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 }