st.cpp
  1  /*
  2  * Castaway
  3  *  (C) 1994 - 2002 Martin Doering, Joachim Hoenig
  4  *
  5  * IO.c - ST hardware emulation
  6  *
  7  * This file is distributed under the GPL, version 2 or at your
  8  * option any later version.  See doc/license.txt for details.
  9  *
 10  * revision history
 11  *  23.05.2002  JH  FAST1.0.1 code import: KR -> ANSI, restructuring
 12  *  09.06.2002  JH  Renamed io.c to st.c again (io.h conflicts with system headers)
 13  *  12.06.2002  JH  Correct bus error/address error exception stack frame
 14  *  14.06.2002  JH  Implemented STOP, shutdown CPU after multiple bus errors.
 15  *                  Removed inst parameter from CPU opcode functions.
 16  *  20.08.2002  JH  Fixed sign bug in DoIORW() and DoIORL()
 17  *  10.09.2002  JH  Bugfix: MOVE.L 0xfffa00,d0 and the like should not raise bus error
 18  *  16.09.2002  JH  Bugfix: Word access on unmapped I/O address stacked
 19  *                  two bus error stack frames. Fault address corrected.
 20  *                  Merged some code from JH_TOS206_patches branch.
 21  *  02.10.2002  JH  Eliminated a lot of silly bugs introduced recently. Shame on me.
 22  No more CPU bus errors from blitter.c::bitblt().
 23  *  10.10.2002  JH  Compatibility improvements.
 24  */
 25  static char     sccsid[] = "$Id: st.c,v 1.14 2002/10/10 19:41:27 jhoenig Exp $";
 26  #include <stdio.h>
 27  #include "dcastaway.h"
 28  #include "st.h"
 29  #include "mem.h"
 30  #include "m68k_intrf.h"
 31  #ifndef NO_SOUND
 32  #include "sound.h"
 33  #endif
 34  #include "emuapi.h"
 35  
 36  
 37  #ifdef DEBUG
 38  #include <assert.h>
 39  #endif
 40  
 41  #include <Arduino.h>
 42  
 43  #define VALUE_OPEN  0xff
 44  /*
 45  * startup display mode
 46  */
 47  int             display_mode = COL4;
 48  
 49  /*
 50  * I/O Registers
 51  */
 52  uint8           memconf;
 53  
 54  //Video shifter
 55  uint32			vid_adr;
 56  uint8           vid_baseh, vid_basem;
 57  uint32			vid_mem=0x10000;
 58  uint8           vid_syncmode=2, vid_shiftmode;
 59  int16           vid_col[16];
 60  int             vid_flag;
 61  
 62  uint16          dma_car, dma_scr, dma_sr, dma_mode;
 63  uint8           dma_adrh, dma_adrm, dma_adrl;
 64  uint8           mfp_gpip, mfp_aer, mfp_ddr, mfp_iera, mfp_ierb, mfp_ipra,
 65  mfp_iprb, mfp_isra, mfp_isrb, mfp_imra, mfp_imrb, mfp_ivr,
 66  mfp_tacr, mfp_tbcr, mfp_tcdcr, mfp_scr, mfp_ucr, mfp_rsr, mfp_tsr, mfp_udr;
 67  
 68  
 69  //Mfp delay timer variables
 70  int32 mfp_reg[12];
 71  #define	mfp_tadr mfp_reg[0]
 72  #define	mfp_tbdr mfp_reg[1]
 73  #define	mfp_tcdr mfp_reg[2]
 74  #define	mfp_tddr mfp_reg[3]
 75  #define	mfp_acount mfp_reg[4]
 76  #define	mfp_bcount mfp_reg[5]
 77  #define	mfp_ccount mfp_reg[6]
 78  #define	mfp_dcount mfp_reg[7]
 79  #define	mfp_ascale mfp_reg[8]
 80  #define	mfp_bscale mfp_reg[9]
 81  #define	mfp_cscale mfp_reg[10]
 82  #define	mfp_dscale mfp_reg[11]
 83  
 84  uint8           acia1_cr, acia1_sr, acia1_dr, acia2_cr, acia2_sr, acia2_dr;
 85  
 86  uint16          blt_halftone[16];
 87  int16           blt_src_x_inc, blt_src_y_inc;
 88  uint32          blt_src_addr;
 89  int16           blt_end_1, blt_end_2, blt_end_3;
 90  int16           blt_dst_x_inc, blt_dst_y_inc;
 91  uint32          blt_dst_addr;
 92  uint16          blt_x_cnt, blt_y_cnt;
 93  int8            blt_hop, blt_op, blt_status, blt_skew;
 94  int8            blt_ready;
 95  
 96  uint32			psg[26];
 97  //unsigned char sample[10000];
 98  #define phase0 psg[16]
 99  #define phase1 psg[17]
100  #define phase2 psg[18]
101  #define phase3 psg[19]
102  #define psg_epos psg[20]
103  #define psgcontrol psg[21]
104  #define phase4 psg[22]
105  #define nrand psg[23]
106  #define sampos psg[24]
107  #define lastpsg psg[25]
108  
109  PROGMEM static const int samvol[16]={0,0,0,1,1,1,2,3,5,7,11,17,25,38,57,85};
110  static int samvol2[4096];
111  
112  const int32 mfpcycletab[16] = {0,80402,32161,20100,6432,5025,3216,1608,1,0,0,0,0,0,0,0};
113  
114  PROGMEM void IOInit(void)
115  {
116  	int n,a,b,c;
117  	//Create sample lookup table (4096 entries)
118  	for (a=0; a<16; a++) {
119  		for (b=0; b<16; b++) {
120  			for (c=0; c<16; c++) {
121  				samvol2[(a<<8)+(b<<4)+c]=samvol[a]+samvol[b]+samvol[c];
122  			}
123  		}
124  	}
125  	//Reset mfp variables
126  	mfp_tadr=256<<20; mfp_tbdr=256<<20; mfp_tcdr=256<<20; mfp_tddr=256<<20;
127  	mfp_tacr=0; mfp_tbcr=0; mfp_tcdcr=0;
128  	mfp_acount=256<<20; mfp_bcount=256<<20; mfp_ccount=256<<20; mfp_dcount=256<<20;
129  	mfp_ascale=0; mfp_bscale=0; mfp_cscale=0; mfp_dscale=0;
130  	for (n=0; n<24; n++) psg[n]=0;
131  	nrand=1;
132  	//Other stuff
133      vid_baseh = 0;
134      vid_basem = 0;
135      vid_shiftmode = display_mode;
136      dma_sr = 1;                 /* DMA status ready */
137      if (display_mode == MONO) {
138          mfp_gpip = 0x39;        /* no lpr, no blt, no interrupt, monochrome */
139      } else {
140          mfp_gpip = 0xb9;        /* no lpr, no blt, no interrupt, color */
141      }
142  #ifdef sun
143      act.sa_handler = Sigbus;
144      (void) sigaction (SIGBUS, &act, &oldsigbus);
145  #endif
146  #ifdef USE_MMAP
147      act.sa_handler = Sigsegv;
148      (void) sigaction (SIGSEGV, &act, &oldsigsegv);
149  #endif
150  }
151  
152  PROGMEM static void update_psg(uint8 value) {
153  #ifndef NO_SOUND
154  	Sound_Update();
155  #endif	
156  	//Update psg register
157  	psg[psgcontrol]=value;
158  	
159  	switch(psgcontrol)
160  	{
161  		case 13:
162  #ifndef NO_SOUND
163  			bEnvelopeFreqFlag = 1;
164  			bWriteEnvelopeFreq = 1;
165  #endif
166  			break;
167  		case 12:
168  			psg_epos=0;
169  			break;
170  		case 8:
171  #ifndef NO_SOUND
172  			bWriteChannelAAmp= 1;
173  #endif
174  			break;
175  		case 9:
176  #ifndef NO_SOUND
177  			bWriteChannelBAmp= 1;
178  #endif
179  			break;
180  		case 10:
181  #ifndef NO_SOUND
182  			bWriteChannelCAmp= 1;
183  #endif
184  			break;
185  	}
186  }
187  
188  PROGMEM void DoIOWB(uint32 address, uint8 value)
189  {
190  	address&=0x7fff;
191  	
192  	//Video and dma emu
193  	if (address<0x800) {
194  		switch (address) {
195  		case MEM_CONF&0x7fff:
196  			memconf = value;
197  			break;
198  		case VID_BASEH&0x7fff:
199  			vid_baseh = value;
200  			vid_mem = (vid_baseh<<16)+(vid_basem<<8);
201  			break;
202  		case VID_BASEM&0x7fff:
203  			vid_basem = value;
204  			vid_mem = (vid_baseh<<16)+(vid_basem<<8);
205  			break;
206  		case VID_SYNCMODE&0x7fff:
207  			vid_syncmode = value;
208  			maybe_border++;
209  			break;
210  		case VID_SHIFTMODE&0x7fff:
211  			vid_shiftmode = value;
212  			vid_flag=1;
213  			break;
214  		case DMA_ADRH&0x7fff:
215  			dma_adrh = value;
216  			break;
217  		case DMA_ADRM&0x7fff:
218  			dma_adrm = value;
219  			break;
220  		case DMA_ADRL&0x7fff:
221  			dma_adrl = value;
222  			break;
223  		}
224  		return;
225  	}
226  	
227  	//Sound emu
228  	if (address<0x900) {
229  #if defined(USE_FAME_CORE) && defined(USE_MOVEM_FAME_PATCH)
230  		static unsigned back_cycles=0;
231  		static unsigned back_value=0;
232  		static unsigned back_ctrl=0;
233  		static unsigned new_value=0;
234  #endif
235  		if (address<0x804)
236  			waitstate+=1;
237  		address&=3;
238  		if (address==0) {
239  			psgcontrol=value; //&15;
240  #if defined(USE_FAME_CORE) && defined(USE_MOVEM_FAME_PATCH)
241  			if ((M68KCONTEXT.cycles_counter+IO_CYCLE)==back_cycles) {
242  				psg[back_ctrl]=back_value;
243  				update_psg(new_value);
244  			}
245  #endif
246  		}else if (address==2 && psgcontrol<16) {
247  #if defined(USE_FAME_CORE) && defined(USE_MOVEM_FAME_PATCH)
248  			back_ctrl=psgcontrol;
249  			back_value=psg[psgcontrol];
250  			new_value=value;
251  #endif
252  			update_psg(value);
253  		}
254  #if defined(USE_FAME_CORE) && defined(USE_MOVEM_FAME_PATCH)
255  		back_cycles=IO_CYCLE+M68KCONTEXT.cycles_counter;
256  #endif
257  		return;
258  	}
259  	
260  	//Bus error?
261  	if (address<0xb00) {
262  		ExceptionGroup0(BUSERR, address|0xff8000, 0);
263  		return;
264  	}
265  	
266  	//MFP emu
267  	if (address<0x7c00) {
268  		waitstate+=4;
269  		switch(address) {
270  		case MFP_AER&0x7fff:
271  			mfp_aer = value;
272  			break;
273  		case MFP_DDR&0x7fff:
274  			mfp_ddr = value;
275  			break;
276  		case MFP_IERA&0x7fff:
277  			mfp_iera = value;
278  			mfp_ipra &= mfp_iera;
279  			break;
280  		case MFP_IERB&0x7fff:
281  			mfp_ierb = value;
282  			mfp_iprb &= mfp_ierb;
283  			break;
284  		case MFP_IPRA&0x7fff:
285  			mfp_ipra &= value;
286  			break;
287  		case MFP_IPRB&0x7fff:
288  			mfp_iprb &= value;
289  			break;
290  		case MFP_ISRA&0x7fff:
291  			mfp_isra &= value;
292  #ifndef USE_FAME_CORE
293  			recalc_int = 1;
294  #endif
295  			break;
296  		case MFP_ISRB&0x7fff:
297  			mfp_isrb &= value;
298  #ifndef USE_FAME_CORE
299  			recalc_int = 1;
300  #endif
301  			break;
302  		case MFP_IMRA&0x7fff:
303  			mfp_imra = value;
304  #ifndef USE_FAME_CORE
305  			recalc_int = 1;
306  #endif
307  			break;
308  		case MFP_IMRB&0x7fff:
309  			mfp_imrb = value;
310  #ifndef USE_FAME_CORE
311  			recalc_int = 1;
312  #endif
313  			break;
314  		case MFP_IVR&0x7fff:
315  			mfp_ivr = value;
316  			break;
317  		case MFP_TACR&0x7fff:
318  			mfp_tacr = value&15;
319  #if defined(USE_FAME_CORE) && defined(USE_SHORT_SLICE)
320  			if (mfp_ascale)
321  				m68k_stop_emulating();
322  #endif
323  			mfp_ascale = mfpcycletab[mfp_tacr];
324  			break;
325  		case MFP_TBCR&0x7fff:
326  			mfp_tbcr = value&15;
327  #if defined(USE_FAME_CORE) && defined(USE_SHORT_SLICE)
328  			if (mfp_bscale)
329  				m68k_stop_emulating();
330  #endif
331  			mfp_bscale = mfpcycletab[mfp_tbcr];
332  			break;
333  		case MFP_TCDCR&0x7fff:
334  			mfp_tcdcr = value&0x77;
335  #if defined(USE_FAME_CORE) && defined(USE_SHORT_SLICE)
336  			if (mfp_cscale || mfp_dscale)
337  				m68k_stop_emulating();
338  #endif
339  			mfp_cscale = mfpcycletab[mfp_tcdcr>>4];
340  			mfp_dscale = mfpcycletab[mfp_tcdcr&7];
341  			break;
342  		case MFP_TADR&0x7fff:
343  			if (value==0) mfp_tadr=256<<20; else mfp_tadr=value<<20;
344  			if (mfp_ascale==0) mfp_acount=mfp_tadr;
345  			break;
346  		case MFP_TBDR&0x7fff:
347  			if (value==0) mfp_tbdr=256<<20; else mfp_tbdr=value<<20;
348  			if (mfp_bscale==0) mfp_bcount=mfp_tbdr;
349  			break;
350  		case MFP_TCDR&0x7fff:
351  			if (value==0) mfp_tcdr=256<<20; else mfp_tcdr=value<<20;
352  			if (mfp_cscale==0) mfp_ccount=mfp_tcdr;
353  			break;
354  		case MFP_TDDR&0x7fff:
355  			if (value==0) mfp_tddr=256<<20; else mfp_tddr=value<<20;
356  			if (mfp_dscale==0) mfp_dcount=mfp_tddr;
357  			break;
358  		case MFP_SCR&0x7fff:
359  			mfp_scr = value;
360  			break;
361  		case MFP_UCR&0x7fff:
362  			mfp_ucr = value;
363  			break;
364  		case MFP_RSR&0x7fff:
365  			mfp_rsr = value;
366  			break;
367  		case MFP_TSR&0x7fff:
368  			mfp_tsr = value;
369  			break;
370  		case MFP_UDR&0x7fff:
371  			mfp_udr = value;
372  			break;
373  		}
374  		return;
375  	}
376  
377  	switch(address) {
378      case ACIA1_SR&0x7fff:
379          //Serial.println(value);    
380  	waitstate+=8;
381          acia1_cr = value;
382          break;
383      case ACIA1_DR&0x7fff:
384          //Serial.println(value);    
385  	waitstate+=8;
386          IkbdRecv (value);
387          break;
388      case ACIA2_SR&0x7fff: 
389  	waitstate+=8;
390          acia2_cr = value;
391          break;
392      case ACIA2_DR&0x7fff:
393          emu_MidiOnDataReceived(value);
394  	waitstate+=8;
395          break;
396  	}
397  	
398  }
399  
400  PROGMEM void DoIOWW(uint32 address, uint16 value)
401  {
402      if (address >= VID_COL0 && address <= VID_COL15) {
403          vid_col[(address & 0x1f) >> 1] = value&0x777;
404          vid_flag = 1;
405  		return;
406  	}
407  	else
408          switch (address) {
409          case DMA_MODE:
410              dma_mode = value;
411              break;
412          case DMA_CAR:
413  	    waitstate+=4;
414              if (dma_mode & 0x10) dma_scr = value;
415  			else if (dma_mode & 0x8) dma_car = value;
416  			else {
417  				switch (dma_mode & 0x6) {
418  				case 0:
419  					fdc_command = value;
420  					FDCCommand ();
421  					break;
422  				case 2:
423  					fdc_track = value;
424  					break;
425  				case 4:
426  					fdc_sector = value;
427  					break;
428  				case 6:
429  					fdc_data = value;
430  					break;
431  				}
432              }
433              break;
434          default:
435              DoIOWB(address, value>>8);
436  	    DoIOWB(address+1, value);
437              break;
438  	}
439  }
440  
441  PROGMEM void DoIOWL(uint32 address, uint32 value)
442  {
443      DoIOWW(address, value>>16);
444  	DoIOWW(address+2, value);
445  }
446  
447  static __inline__ void calculate_vid_adr(void)
448  {
449  	unsigned yet=(vid_cycle[cyclenext-IO_CYCLE]-vid_adr_cycleyet)&(~3);
450  	vid_adr+=yet;
451  	vid_adr_cycleyet+=yet;
452  }
453  
454  PROGMEM uint8 DoIORB(uint32 address)
455  {
456  	address&=0x7fff;
457  	
458      //Video and dma emu
459  	if (address<0x800) {
460  		switch (address) {
461  		case MEM_CONF&0x7fff:
462  			return memconf;
463  		case VID_BASEH&0x7fff:
464  			return vid_baseh;
465  		case VID_BASEM&0x7fff:
466  			return vid_basem;
467  		case VID_ADRH&0x7fff:
468  			calculate_vid_adr();
469  			return (unsigned char)(vid_adr>>16);
470  		case VID_ADRM&0x7fff:
471  			calculate_vid_adr();
472  			return (unsigned char)(vid_adr>>8);
473  		case VID_ADRL&0x7fff:
474  			calculate_vid_adr();
475  			return (unsigned char)(vid_adr);
476  		case VID_SYNCMODE&0x7fff:
477  			return vid_syncmode;
478  		case VID_LINEWIDTH&0x7fff:
479  			return 0xff;
480  		case VID_SHIFTMODE&0x7fff:
481  			return vid_shiftmode;
482  		case DMA_ADRH&0x7fff:
483  			return dma_adrh;
484  		case DMA_ADRM&0x7fff:
485  			return dma_adrm;
486  		case DMA_ADRL&0x7fff:
487  			return dma_adrl;
488  		}
489  		return VALUE_OPEN;
490  	}
491  	
492  	//Sound emu
493  	if (address<0x900) {
494  		address&=3;
495  		if (!address)
496  		{
497  			waitstate+=4;
498  			if (psgcontrol>=16) return 0xff;
499  			return psg[psgcontrol];
500  		}
501  		else if (address<4)
502  			waitstate++;
503  		return VALUE_OPEN;
504  	}
505  	
506  	//Bus error?
507  	if (address<0xb00) {
508  		ExceptionGroup0(BUSERR, address|0xff8000, 0);
509  		return VALUE_OPEN;
510  	}
511  	
512  	//MFP emu
513  	if (address<0x7c00) {
514  		waitstate+=4;
515  		switch(address) {
516  		case MFP_GPIP&0x7fff:
517  			return mfp_gpip;
518  		case MFP_AER&0x7fff:
519  			return mfp_aer;
520  		case MFP_DDR&0x7fff:
521  			return mfp_ddr;
522  		case MFP_IERA&0x7fff:
523  			return mfp_iera;
524  		case MFP_IERB&0x7fff:
525  			return mfp_ierb;
526  		case MFP_IPRA&0x7fff:
527  			return mfp_ipra;
528  		case MFP_IPRB&0x7fff:
529  			return mfp_iprb;
530  		case MFP_ISRA&0x7fff:
531  			return mfp_isra;
532  		case MFP_ISRB&0x7fff:
533  			return mfp_isrb;
534  		case MFP_IMRA&0x7fff:
535  			return mfp_imra;
536  		case MFP_IMRB&0x7fff:
537  			return mfp_imrb;
538  		case MFP_IVR&0x7fff:
539  			return mfp_ivr;
540  		case MFP_TACR&0x7fff:
541  			return mfp_tacr;
542  		case MFP_TBCR&0x7fff:
543  			return mfp_tbcr;
544  		case MFP_TCDCR&0x7fff:
545  			return mfp_tcdcr;
546  		case MFP_TADR&0x7fff:
547  			return (mfp_acount+0xfffff)>>20;
548  		case MFP_TBDR&0x7fff:
549  			return (mfp_bcount+0xfffff)>>20;
550  		case MFP_TCDR&0x7fff:
551  			return (mfp_ccount+0xfffff)>>20;
552  		case MFP_TDDR&0x7fff:
553  			return (mfp_dcount+0xfffff)>>20;
554  		case MFP_SCR&0x7fff:
555  			return mfp_scr;
556  		case MFP_UCR&0x7fff:
557  			return mfp_ucr;
558  		case MFP_RSR&0x7fff:
559  			return mfp_rsr;
560  		case MFP_TSR&0x7fff:
561  			return mfp_tsr;
562  		case MFP_UDR&0x7fff:
563  			return mfp_udr;
564  		}
565  		return VALUE_OPEN;
566  	}
567  	
568  	//Acia emu
569  	switch(address) {
570      case ACIA1_SR&0x7fff:
571  	waitstate+=8;
572          return 2 | acia1_sr;
573      case ACIA1_DR&0x7fff:
574  	waitstate+=8;
575          if (!(acia1_cr & 0x20)) {acia1_sr&=0x7e; mfp_gpip|=0x10;}
576          return acia1_dr;
577      case ACIA2_SR&0x7fff:
578  		waitstate+=8;
579  		return 2;
580      case ACIA2_DR&0x7fff:
581  		waitstate+=8;
582  		return 1;
583  	}
584  	return VALUE_OPEN;
585  	
586  }
587  
588  PROGMEM uint16 DoIORW(uint32 address)
589  {
590      if (address >= VID_COL0 && address <= VID_COL15) {
591          return vid_col[(address & 0x1f) >> 1];
592  	}
593      switch (address) {
594  	case DMA_SR:
595  		return dma_sr;
596  	case DMA_CAR:
597  		waitstate+=4;
598  		if (dma_mode & 0x10) return dma_scr;
599  		else if (dma_mode & 0x8) return dma_car;
600  		else {
601  			switch (dma_mode & 0x6) {
602  			case 0:
603  				if (!fdc_int) mfp_gpip |= 0x20;
604  				return fdc_status;
605  			case 2:
606  				return fdc_track;
607  			case 4:
608  				return fdc_sector;
609  			case 6:
610  				return fdc_data;
611  			}
612              return 0;
613  		}
614  	default:
615  		return (((uint32)DoIORB(address))<<8)+DoIORB(address+1);
616  	}
617  }
618  
619  PROGMEM uint32 DoIORL(uint32 address)
620  {
621  	return (((uint32)DoIORW(address))<<16)+DoIORW(address+2);
622  }