|
|
1.1 ! root 1: /* ! 2: Hatari ! 3: ! 4: This is where we intercept read/writes to/from the hardware. The ST's memory is nicely split into ! 5: four main parts - the bottom area of RAM is for user programs. This is followed by a large area which ! 6: causes a Bus Error. After this is the ROM addresses for TOS and finally an area for hardware mapping. ! 7: To gain speed any address in the user area can simply read/write, but anything above this range needs ! 8: to be checked for validity and sent to the various handlers. ! 9: A big problem for ST emulation is the use of the hardware registers. These often consist of an 'odd' byte ! 10: in memory and is usually addressed as a single byte. A number of applications, however, write to the address ! 11: using a word or even long word - which may span over two hardware registers! Rather than check for any and ! 12: all combinations we use a tables for byte/word/long and for read/write. These are lists of functions which ! 13: access the ST Ram area any bytes which maybe affected by the operation. Eg, a long write to a PSG register ! 14: (which access two registers) will write the long into ST Ram and then call the two handlers which read off ! 15: the bytes for each register. This means that any access to any hardware register in such a way will work ! 16: correctly - it certainly fixes a lot of bugs and means writing just one routine for each hardware register ! 17: we mean to intercept! Phew! ! 18: Note the 'mirror'(or shadow) registers of the PSG - this is used by most games. We also have a means of ! 19: testing for addressing into 'no-mans-land' which are parts of the hardware map which are not valid on a ! 20: standard STfm. ! 21: */ ! 22: ! 23: #include "main.h" ! 24: #include "debug.h" ! 25: #include "decode.h" ! 26: #include "dialog.h" ! 27: #include "fdc.h" ! 28: #include "int.h" ! 29: #include "intercept.h" ! 30: #include "ikbd.h" ! 31: #include "m68000.h" ! 32: #include "memAlloc.h" ! 33: #include "mfp.h" ! 34: #include "psg.h" ! 35: #include "screen.h" ! 36: #include "spec512.h" ! 37: #include "vdi.h" ! 38: #include "video.h" ! 39: #include "uae-cpu/sysdeps.h" ! 40: ! 41: //#define CHECK_FOR_NO_MANS_LAND /* Check for read/write from unknown hardware addresses */ ! 42: ! 43: //----------------------------------------------------------------------- ! 44: // List of functions to handle read/write hardware intercepts. MUST match INTERCEPT_xxx enum ! 45: INTERCEPT_ACCESS_FUNC InterceptAccessFuncs[INTERCEPT_COUNT] = { ! 46: 0x0,SIZE_BYTE,NULL,NULL, ! 47: 0xff8205,SIZE_BYTE,Intercept_VideoHigh_ReadByte,Intercept_VideoHigh_WriteByte, // INTERCEPT_VIDEOHIGH ! 48: 0xff8207,SIZE_BYTE,Intercept_VideoMed_ReadByte,Intercept_VideoMed_WriteByte, // INTERCEPT_VIDEOMED ! 49: 0xff8209,SIZE_BYTE,Intercept_VideoLow_ReadByte,Intercept_VideoLow_WriteByte, // INTERCEPT_VIDEOLOW ! 50: 0xff820a,SIZE_BYTE,Intercept_VideoSync_ReadByte,Intercept_VideoSync_WriteByte, // INTERCEPT_VIDEOSYNC ! 51: 0xff820d,SIZE_BYTE,Intercept_VideoBaseLow_ReadByte,Intercept_VideoBaseLow_WriteByte, // INTERCEPT_VIDEOBASELOW ! 52: 0xff820f,SIZE_BYTE,Intercept_LineWidth_ReadByte,Intercept_LineWidth_WriteByte, // INTERCEPT_LINEWIDTH ! 53: 0xff8240,SIZE_WORD,Intercept_Colour0_ReadWord,Intercept_Colour0_WriteWord, // INTERCEPT_COLOUR0 ! 54: 0xff8242,SIZE_WORD,Intercept_Colour1_ReadWord,Intercept_Colour1_WriteWord, // INTERCEPT_COLOUR1 ! 55: 0xff8244,SIZE_WORD,Intercept_Colour2_ReadWord,Intercept_Colour2_WriteWord, // INTERCEPT_COLOUR2 ! 56: 0xff8246,SIZE_WORD,Intercept_Colour3_ReadWord,Intercept_Colour3_WriteWord, // INTERCEPT_COLOUR3 ! 57: 0xff8248,SIZE_WORD,Intercept_Colour4_ReadWord,Intercept_Colour4_WriteWord, // INTERCEPT_COLOUR4 ! 58: 0xff824a,SIZE_WORD,Intercept_Colour5_ReadWord,Intercept_Colour5_WriteWord, // INTERCEPT_COLOUR5 ! 59: 0xff824c,SIZE_WORD,Intercept_Colour6_ReadWord,Intercept_Colour6_WriteWord, // INTERCEPT_COLOUR6 ! 60: 0xff824e,SIZE_WORD,Intercept_Colour7_ReadWord,Intercept_Colour7_WriteWord, // INTERCEPT_COLOUR7 ! 61: 0xff8250,SIZE_WORD,Intercept_Colour8_ReadWord,Intercept_Colour8_WriteWord, // INTERCEPT_COLOUR8 ! 62: 0xff8252,SIZE_WORD,Intercept_Colour9_ReadWord,Intercept_Colour9_WriteWord, // INTERCEPT_COLOUR9 ! 63: 0xff8254,SIZE_WORD,Intercept_Colour10_ReadWord,Intercept_Colour10_WriteWord, // INTERCEPT_COLOUR10 ! 64: 0xff8256,SIZE_WORD,Intercept_Colour11_ReadWord,Intercept_Colour11_WriteWord, // INTERCEPT_COLOUR11 ! 65: 0xff8258,SIZE_WORD,Intercept_Colour12_ReadWord,Intercept_Colour12_WriteWord, // INTERCEPT_COLOUR12 ! 66: 0xff825a,SIZE_WORD,Intercept_Colour13_ReadWord,Intercept_Colour13_WriteWord, // INTERCEPT_COLOUR13 ! 67: 0xff825c,SIZE_WORD,Intercept_Colour14_ReadWord,Intercept_Colour14_WriteWord, // INTERCEPT_COLOUR14 ! 68: 0xff825e,SIZE_WORD,Intercept_Colour15_ReadWord,Intercept_Colour15_WriteWord, // INTERCEPT_COLOUR15 ! 69: 0xff8260,SIZE_BYTE,Intercept_ShifterMode_ReadByte,Intercept_ShifterMode_WriteByte, // INTERCEPT_SHIFTERMODE ! 70: 0xff8604,SIZE_WORD,Intercept_DiskControl_ReadWord,Intercept_DiskControl_WriteWord, // INTERCEPT_DISKCONTROL ! 71: 0xff8606,SIZE_WORD,Intercept_DmaStatus_ReadWord,Intercept_DmaStatus_WriteWord, // INTERCEPT_DMASTATUS ! 72: 0xff8800,SIZE_BYTE,Intercept_PSGRegister_ReadByte,Intercept_PSGRegister_WriteByte, // INTERCEPT_PSG_REGISTER ! 73: 0xff8802,SIZE_BYTE,Intercept_PSGData_ReadByte,Intercept_PSGData_WriteByte, // INTERCEPT_PSG_DATA ! 74: 0xff8922,SIZE_WORD,Intercept_MicrowireData_ReadWord,Intercept_MicrowireData_WriteWord, // INTERCEPT_MICROWIREDATA ! 75: 0xfffa01,SIZE_BYTE,Intercept_Monitor_ReadByte,Intercept_Monitor_WriteByte, // INTERCEPT_MONITOR ! 76: 0xfffa03,SIZE_BYTE,Intercept_ActiveEdge_ReadByte,Intercept_ActiveEdge_WriteByte, // INTERCEPT_ACTIVE_EDGE ! 77: 0xfffa05,SIZE_BYTE,Intercept_DataDirection_ReadByte,Intercept_DataDirection_WriteByte, // INTERCEPT_DATA_DIRECTION ! 78: 0xfffa07,SIZE_BYTE,Intercept_EnableA_ReadByte,Intercept_EnableA_WriteByte, // INTERCEPT_ENABLE_A ! 79: 0xfffa09,SIZE_BYTE,Intercept_EnableB_ReadByte,Intercept_EnableB_WriteByte, // INTERCEPT_ENABLE_B ! 80: 0xfffa0b,SIZE_BYTE,Intercept_PendingA_ReadByte,Intercept_PendingA_WriteByte, // INTERCEPT_PENDING_A ! 81: 0xfffa0d,SIZE_BYTE,Intercept_PendingB_ReadByte,Intercept_PendingB_WriteByte, // INTERCEPT_PENDING_B ! 82: 0xfffa0f,SIZE_BYTE,Intercept_InServiceA_ReadByte,Intercept_InServiceA_WriteByte, // INTERCEPT_INSERVICE_A ! 83: 0xfffa11,SIZE_BYTE,Intercept_InServiceB_ReadByte,Intercept_InServiceB_WriteByte, // INTERCEPT_INSERVICE_B ! 84: 0xfffa13,SIZE_BYTE,Intercept_MaskA_ReadByte,Intercept_MaskA_WriteByte, // INTERCEPT_MASK_A ! 85: 0xfffa15,SIZE_BYTE,Intercept_MaskB_ReadByte,Intercept_MaskB_WriteByte, // INTERCEPT_MASK_B ! 86: 0xfffa17,SIZE_BYTE,Intercept_VectorReg_ReadByte,Intercept_VectorReg_WriteByte, // INTERCEPT_VECTOR_REG ! 87: 0xfffa19,SIZE_BYTE,Intercept_TimerACtrl_ReadByte,Intercept_TimerACtrl_WriteByte, // INTERCEPT_TIMERA_CTRL ! 88: 0xfffa1b,SIZE_BYTE,Intercept_TimerBCtrl_ReadByte,Intercept_TimerBCtrl_WriteByte, // INTERCEPT_TIMERB_CTRL ! 89: 0xfffa1d,SIZE_BYTE,Intercept_TimerCDCtrl_ReadByte,Intercept_TimerCDCtrl_WriteByte, // INTERCEPT_TIMERCD_CTRL ! 90: 0xfffa1f,SIZE_BYTE,Intercept_TimerAData_ReadByte,Intercept_TimerAData_WriteByte, // INTERCEPT_TIMERA_DATA ! 91: 0xfffa21,SIZE_BYTE,Intercept_TimerBData_ReadByte,Intercept_TimerBData_WriteByte, // INTERCEPT_TIMERB_DATA ! 92: 0xfffa23,SIZE_BYTE,Intercept_TimerCData_ReadByte,Intercept_TimerCData_WriteByte, // INTERCEPT_TIMERC_DATA ! 93: 0xfffa25,SIZE_BYTE,Intercept_TimerDData_ReadByte,Intercept_TimerDData_WriteByte, // INTERCEPT_TIMERD_DATA ! 94: 0xfffc00,SIZE_BYTE,Intercept_KeyboardControl_ReadByte,Intercept_KeyboardControl_WriteByte, // INTERCEPT_KEYBOARDCONTROL ! 95: 0xfffc02,SIZE_BYTE,Intercept_KeyboardData_ReadByte,Intercept_KeyboardData_WriteByte, // INTERCEPT_KEYBOARDDATA ! 96: 0xfffc04,SIZE_BYTE,Intercept_MidiControl_ReadByte,Intercept_MidiControl_WriteByte, // INTERCEPT_MIDICONTROL ! 97: 0xfffc06,SIZE_BYTE,Intercept_MidiData_ReadByte,Intercept_MidiData_WriteByte, // INTERCEPT_MIDIDATA ! 98: }; ! 99: ! 100: unsigned long *pInterceptWorkspace; // Memory used to store all read/write NULL terminated function call tables ! 101: unsigned long *pCurrentInterceptWorkspace; // Index into above ! 102: unsigned long *pInterceptReadByteTable[0x8000],*pInterceptReadWordTable[0x8000],*pInterceptReadLongTable[0x8000]; ! 103: unsigned long *pInterceptWriteByteTable[0x8000],*pInterceptWriteWordTable[0x8000],*pInterceptWriteLongTable[0x8000]; ! 104: ! 105: //----------------------------------------------------------------------- ! 106: /* ! 107: Create 'intercept' tables for hardware address access ! 108: */ ! 109: void Intercept_Init(void) ! 110: { ! 111: // Allocate memory for intercept tables ! 112: pCurrentInterceptWorkspace = pInterceptWorkspace = (unsigned long *)Memory_Alloc(INTERCEPT_WORKSPACE_SIZE); ! 113: ! 114: // Clear intercept tables(NULL signifies no entries for that location) ! 115: Memory_Clear(pInterceptReadByteTable,sizeof(unsigned long *)*0x8000); ! 116: Memory_Clear(pInterceptReadWordTable,sizeof(unsigned long *)*0x8000); ! 117: Memory_Clear(pInterceptReadLongTable,sizeof(unsigned long *)*0x8000); ! 118: Memory_Clear(pInterceptWriteByteTable,sizeof(unsigned long *)*0x8000); ! 119: Memory_Clear(pInterceptWriteWordTable,sizeof(unsigned long *)*0x8000); ! 120: Memory_Clear(pInterceptWriteLongTable,sizeof(unsigned long *)*0x8000); ! 121: ! 122: // Create 'read' tables ! 123: Intercept_CreateTable(pInterceptReadByteTable,SIZE_BYTE,0); ! 124: Intercept_CreateTable(pInterceptReadWordTable,SIZE_WORD,0); ! 125: Intercept_CreateTable(pInterceptReadLongTable,SIZE_LONG,0); ! 126: // And 'write' tables ! 127: Intercept_CreateTable(pInterceptWriteByteTable,SIZE_BYTE,1); ! 128: Intercept_CreateTable(pInterceptWriteWordTable,SIZE_WORD,1); ! 129: Intercept_CreateTable(pInterceptWriteLongTable,SIZE_LONG,1); ! 130: ! 131: #ifdef CHECK_FOR_NO_MANS_LAND ! 132: // This causes a error when an application tries to access illegal hardware registers(maybe mirror'd) ! 133: Intercept_ModifyTablesForNoMansLand(); ! 134: #endif //CHECK_FOR_NO_MANS_LAND ! 135: ! 136: // And modify for bus-error in hardware space ! 137: Intercept_ModifyTablesForBusErrors(); ! 138: } ! 139: ! 140: //----------------------------------------------------------------------- ! 141: /* ! 142: Free 'intercept' hardware lists ! 143: */ ! 144: void Intercept_UnInit(void) ! 145: { ! 146: Memory_Free(pInterceptWorkspace); ! 147: } ! 148: ! 149: //----------------------------------------------------------------------- ! 150: /* ! 151: Set Intercept hardware address table index's ! 152: ! 153: Each 'intercept table' is a list of 0x8000 pointers to a list of functions to call when that ! 154: location in the ST's memory is accessed. Each entry is terminated by a NULL ! 155: Eg, if we write a long word to address '0xff8800', we ! 156: need to call the functions 'InterceptPSGRegister_WriteByte' and then 'InterceptPSGData_WriteByte'. ! 157: */ ! 158: ! 159: void Intercept_CreateTable(unsigned long *pInterceptTable[],int Span,int ReadWrite) ! 160: { ! 161: unsigned int Address, LowAddress, HiAddress; ! 162: int i; ! 163: ! 164: // Scan each hardware address ! 165: for(Address=0xff8000; Address<=0xffffff; Address++) { ! 166: // Does this hardware location/span appear in our list of possible intercepted functions? ! 167: for (i=0; i<INTERCEPT_COUNT; i++) { ! 168: LowAddress = InterceptAccessFuncs[i].Address; ! 169: HiAddress = InterceptAccessFuncs[i].Address+InterceptAccessFuncs[i].SpanInBytes; ! 170: ! 171: if ( (Address+Span) <= LowAddress ) ! 172: continue; ! 173: if ( Address >= HiAddress ) ! 174: continue; ! 175: ! 176: // This location needs to be intercepted, so add entry to list ! 177: if (pInterceptTable[Address-0xff8000]==NULL) ! 178: pInterceptTable[Address-0xff8000] = pCurrentInterceptWorkspace; ! 179: *pCurrentInterceptWorkspace++ = (unsigned long)InterceptAccessFuncs[i].ReadWriteFunc[ReadWrite]; ! 180: } ! 181: // Terminate table? ! 182: if (pInterceptTable[Address-0xff8000]) ! 183: *pCurrentInterceptWorkspace++ = 0L; ! 184: } ! 185: } ! 186: ! 187: //----------------------------------------------------------------------- ! 188: /* ! 189: Check list of handlers to see if address needs to be intercepted and call routines ! 190: 'ecx' is pointer to function list (or NULL) ! 191: */ ! 192: void Intercept_ScanHandlers(unsigned long *the_func) ! 193: { ! 194: if( the_func ) ! 195: while( *the_func ) /* Do we have any routines to run for this address? */ ! 196: { ! 197: CALL_VAR(*the_func); /* Call routine */ ! 198: the_func+=1; ! 199: } ! 200: } ! 201: ! 202: //----------------------------------------------------------------------- ! 203: /* ! 204: Check if need to change our address 'ebp' as maybe a mirror register ! 205: Currently we only have a PSG mirror area ! 206: */ ! 207: unsigned long Intercept_CheckMirrorAddresses(unsigned long addr) ! 208: { ! 209: if( addr>=0xff8800 && addr<=0xff8900 ) /* Is a PSG mirror registers? */ ! 210: addr = ( addr & 3) + 0xff8800; /* Bring into 0xff8800-0xff8804 range */ ! 211: return addr; ! 212: } ! 213: ! 214: //----------------------------------------------------------------------- ! 215: uae_u32 Intercept_ReadByte(uaecptr addr) ! 216: { ! 217: //fprintf(stderr,"byte hardware read access: $%lx\n", addr); ! 218: addr &= 0x00ffffff; /* Use a 24 bit address */ ! 219: if(addr >= 0x00ff8000) /* Is hardware address? */ ! 220: { ! 221: BusAddressLocation=addr; /* Store for exception frame, just in case */ ! 222: addr = Intercept_CheckMirrorAddresses(addr); ! 223: Intercept_ScanHandlers( pInterceptReadByteTable[ addr-0x00ff8000 ] ); ! 224: } ! 225: else ! 226: { ! 227: if(addr < STRamEnd_BusErr) return 0; /* Blank area between RAM and bus error */ ! 228: if(addr < BUS_ERROR_ADDR) { M68000_BusError(addr); return 0; } /* Is a bus error? (invalid memory addressing) */ ! 229: } ! 230: return( STRam[addr] ); ! 231: } ! 232: ! 233: ! 234: uae_u32 Intercept_ReadWord(uaecptr addr) ! 235: { ! 236: //fprintf(stderr,"Word hardware read access: $%lx\n", addr); ! 237: addr &= 0x00ffffff; /* Use a 24 bit address */ ! 238: if( addr&1 ) ! 239: { M68000_AddressError(addr); return 0; } /* Is address error? (not correct alignment) */ ! 240: if(addr >= 0x00ff8000) /* Is hardware address? */ ! 241: { ! 242: BusAddressLocation=addr; /* Store for exception frame, just in case */ ! 243: addr = Intercept_CheckMirrorAddresses(addr); ! 244: Intercept_ScanHandlers( pInterceptReadWordTable[ addr-0x00ff8000 ] ); ! 245: } ! 246: else ! 247: { ! 248: if(addr < STRamEnd_BusErr) return 0; /* Blank area between RAM and bus error */ ! 249: if(addr < BUS_ERROR_ADDR) { M68000_BusError(addr); return 0; } /* Is a bus error? (invalid memory addressing) */ ! 250: } ! 251: return STMemory_ReadWord( addr ); ! 252: } ! 253: ! 254: ! 255: uae_u32 Intercept_ReadLong(uaecptr addr) ! 256: { ! 257: //fprintf(stderr,"Long hardware read access: $%lx\n", addr); ! 258: addr &= 0x00ffffff; /* Use a 24 bit address */ ! 259: if( addr&1 ) ! 260: { M68000_AddressError(addr); return 0; } /* Is address error? (not correct alignment) */ ! 261: if(addr >= 0x00ff8000) /* Is hardware address? */ ! 262: { ! 263: BusAddressLocation=addr; /* Store for exception frame, just in case */ ! 264: addr = Intercept_CheckMirrorAddresses(addr); ! 265: Intercept_ScanHandlers( pInterceptReadLongTable[ addr-0x00ff8000 ] ); ! 266: } ! 267: else ! 268: { ! 269: if(addr < STRamEnd_BusErr) return 0; /* Blank area between RAM and bus error */ ! 270: if(addr < BUS_ERROR_ADDR) { M68000_BusError(addr); return 0; } /* Is a bus error? (invalid memory addressing) */ ! 271: } ! 272: return STMemory_ReadLong( addr ); ! 273: } ! 274: ! 275: //----------------------------------------------------------------------- ! 276: void Intercept_WriteByte(uaecptr addr, uae_u32 val) ! 277: { ! 278: //fprintf(stderr,"Byte hardware write access: $%lx\n", addr); ! 279: addr &= 0x00ffffff; /* Use a 24 bit address */ ! 280: if( addr>=0x00ff8000 ) /* Is hardware address? */ ! 281: { ! 282: BusAddressLocation=addr; /* Store for exception frame, just in case */ ! 283: addr = Intercept_CheckMirrorAddresses(addr); ! 284: STRam[addr]=val; ! 285: Intercept_ScanHandlers( pInterceptWriteByteTable[ addr-0x00ff8000 ] ); ! 286: } ! 287: else ! 288: { ! 289: if( addr < STRamEnd_BusErr ) return; /* Allow writes to no-mans-land(just return) */ ! 290: if( addr < BUS_ERROR_ADDR ) { M68000_BusError(addr); return; } /* Is a bus error? (invalid memory addressing) */ ! 291: STRam[addr]=val; ! 292: } ! 293: } ! 294: ! 295: void Intercept_WriteWord(uaecptr addr, uae_u32 val) ! 296: { ! 297: //fprintf(stderr,"Word hardware write access: $%lx\n", addr); ! 298: addr &= 0x00ffffff; /* Use a 24 bit address */ ! 299: if( addr&1 ) ! 300: { M68000_AddressError(addr); return; } /* Is address error? (not correct alignment) */ ! 301: if( addr>=0x00ff8000 ) /* Is hardware address? */ ! 302: { ! 303: BusAddressLocation=addr; /* Store for exception frame, just in case */ ! 304: addr = Intercept_CheckMirrorAddresses(addr); ! 305: STMemory_WriteWord( addr, val); ! 306: Intercept_ScanHandlers( pInterceptWriteWordTable[ addr-0x00ff8000 ] ); ! 307: } ! 308: else ! 309: { ! 310: if( addr < STRamEnd_BusErr ) return; /* Allow writes to no-mans-land(just return) */ ! 311: if( addr < BUS_ERROR_ADDR ) { M68000_BusError(addr); return; } /* Is a bus error? (invalid memory addressing) */ ! 312: STMemory_WriteWord( addr, val); ! 313: } ! 314: } ! 315: ! 316: void Intercept_WriteLong(uaecptr addr, uae_u32 val) ! 317: { ! 318: //fprintf(stderr,"Long hardware write access: $%lx\n", addr); ! 319: addr &= 0x00ffffff; /* Use a 24 bit address */ ! 320: if( addr&1 ) ! 321: { M68000_AddressError(addr); return; } /* Is address error? (not correct alignment) */ ! 322: if( addr>=0x00ff8000 ) /* Is hardware address? */ ! 323: { ! 324: BusAddressLocation=addr; /* Store for exception frame, just in case */ ! 325: addr = Intercept_CheckMirrorAddresses(addr); ! 326: STMemory_WriteLong( addr, val); ! 327: Intercept_ScanHandlers( pInterceptWriteLongTable[ addr-0x00ff8000 ] ); ! 328: } ! 329: else ! 330: { ! 331: if( addr < STRamEnd_BusErr ) return; /* Allow writes to no-mans-land(just return) */ ! 332: if( addr < BUS_ERROR_ADDR ) { M68000_BusError(addr); return; } /* Is a bus error? (invalid memory addressing) */ ! 333: STMemory_WriteLong( addr, val); ! 334: } ! 335: } ! 336: ! 337: ! 338: //----------------------------------------------------------------------- ! 339: // Read from Hardware(0x00ff8000 to 0xffffff) ! 340: ! 341: // INTERCEPT_VIDEOHIGH(0xff8205 byte) ! 342: void Intercept_VideoHigh_ReadByte(void) ! 343: { ! 344: STRam[0xff8205] = Video_ReadAddress() >> 16; /* Get video address high byte */ ! 345: } ! 346: ! 347: // INTERCEPT_VIDEOMED(0xff8207 byte) ! 348: void Intercept_VideoMed_ReadByte(void) ! 349: { ! 350: STRam[0xff8207] = Video_ReadAddress() >> 8; /* Get video address med byte */ ! 351: } ! 352: ! 353: // INTERCEPT_VIDEOLOW(0xff8209 byte) ! 354: void Intercept_VideoLow_ReadByte(void) ! 355: { ! 356: STRam[0xff8209] = Video_ReadAddress(); /* Get video address med byte */ ! 357: } ! 358: ! 359: // INTERCEPT_VIDEOSYNC(0xff820a byte) ! 360: void Intercept_VideoSync_ReadByte(void) ! 361: { ! 362: /* Nothing... */ ! 363: } ! 364: ! 365: // INTERCEPT_VIDEOBASELOW(0xff820d byte) ! 366: void Intercept_VideoBaseLow_ReadByte(void) ! 367: { ! 368: STRam[0xff820d] = 0; /* ST can only store screen address to 256 bytes(ie no lower byte) */ ! 369: } ! 370: ! 371: // INTERCEPT_LINEWIDTH(0xff820f byte) ! 372: void Intercept_LineWidth_ReadByte(void) ! 373: { ! 374: STRam[0xff820f]=0; /* On ST this is always 0 */ ! 375: } ! 376: ! 377: // INTERCEPT_COLOUR0(0xff8240 word) ! 378: void Intercept_Colour0_ReadWord(void) ! 379: { ! 380: // Nothing... ! 381: } ! 382: ! 383: // INTERCEPT_COLOUR1(0xff8242 word) ! 384: void Intercept_Colour1_ReadWord(void) ! 385: { ! 386: // Nothing... ! 387: } ! 388: ! 389: // INTERCEPT_COLOUR2(0xff8244 word) ! 390: void Intercept_Colour2_ReadWord(void) ! 391: { ! 392: // Nothing... ! 393: } ! 394: ! 395: // INTERCEPT_COLOUR3(0xff8246 word) ! 396: void Intercept_Colour3_ReadWord(void) ! 397: { ! 398: // Nothing... ! 399: } ! 400: ! 401: // INTERCEPT_COLOUR4(0xff8248 word) ! 402: void Intercept_Colour4_ReadWord(void) ! 403: { ! 404: // Nothing... ! 405: } ! 406: ! 407: // INTERCEPT_COLOUR5(0xff824a word) ! 408: void Intercept_Colour5_ReadWord(void) ! 409: { ! 410: // Nothing... ! 411: } ! 412: ! 413: // INTERCEPT_COLOUR6(0xff824c word) ! 414: void Intercept_Colour6_ReadWord(void) ! 415: { ! 416: // Nothing... ! 417: } ! 418: ! 419: // INTERCEPT_COLOUR7(0xff824e word) ! 420: void Intercept_Colour7_ReadWord(void) ! 421: { ! 422: // Nothing... ! 423: } ! 424: ! 425: // INTERCEPT_COLOUR8(0xff8250 word) ! 426: void Intercept_Colour8_ReadWord(void) ! 427: { ! 428: // Nothing... ! 429: } ! 430: ! 431: // INTERCEPT_COLOUR9(0xff8252 word) ! 432: void Intercept_Colour9_ReadWord(void) ! 433: { ! 434: // Nothing... ! 435: } ! 436: ! 437: // INTERCEPT_COLOUR10(0xff8254 word) ! 438: void Intercept_Colour10_ReadWord(void) ! 439: { ! 440: // Nothing... ! 441: } ! 442: ! 443: // INTERCEPT_COLOUR11(0xff8256 word) ! 444: void Intercept_Colour11_ReadWord(void) ! 445: { ! 446: // Nothing... ! 447: } ! 448: ! 449: // INTERCEPT_COLOUR12(0xff8258 word) ! 450: void Intercept_Colour12_ReadWord(void) ! 451: { ! 452: // Nothing... ! 453: } ! 454: ! 455: // INTERCEPT_COLOUR13(0xff825a word) ! 456: void Intercept_Colour13_ReadWord(void) ! 457: { ! 458: // Nothing... ! 459: } ! 460: ! 461: // INTERCEPT_COLOUR14(0xff825c word) ! 462: void Intercept_Colour14_ReadWord(void) ! 463: { ! 464: // Nothing... ! 465: } ! 466: ! 467: // INTERCEPT_COLOUR15(0xff825e word) ! 468: void Intercept_Colour15_ReadWord(void) ! 469: { ! 470: // Nothing... ! 471: } ! 472: ! 473: // INTERCEPT_SHIFTERMODE(0xff8260 byte) ! 474: void Intercept_ShifterMode_ReadByte(void) ! 475: { ! 476: if(bUseHighRes) ! 477: STRam[0xff8260]=2; /* If mono monitor, force to high resolution */ ! 478: else ! 479: STRam[0xff8260]=VideoShifterByte; /* Read shifter register */ ! 480: } ! 481: ! 482: // INTERCEPT_DISKCONTROL(0xff8604 word) ! 483: void Intercept_DiskControl_ReadWord(void) ! 484: { ! 485: STMemory_WriteWord( 0xff8604, FDC_ReadDiscControllerStatus() ); ! 486: } ! 487: ! 488: // INTERCEPT_DMASTATUS(0xff8606 word) ! 489: void Intercept_DmaStatus_ReadWord(void) ! 490: { ! 491: STMemory_WriteWord( 0xff8606, FDC_ReadDMAStatus() ); ! 492: } ! 493: ! 494: // INTERCEPT_PSG_REGISTER(0xff8800 byte) ! 495: void Intercept_PSGRegister_ReadByte(void) ! 496: { ! 497: STRam[0xff8800] = PSG_ReadSelectRegister(); ! 498: } ! 499: ! 500: // INTERCEPT_PSG_DATA(0xff8802 byte) ! 501: void Intercept_PSGData_ReadByte(void) ! 502: { ! 503: STRam[0xff8802] = PSG_ReadDataRegister(); ! 504: } ! 505: ! 506: // INTERCEPT_MICROWIREDATA(0xff8922 word) ! 507: void Intercept_MicrowireData_ReadWord(void) ! 508: { ! 509: STRam[0xff8922]=0; ! 510: } ! 511: ! 512: // INTERCEPT_MONITOR(0xfffa01 byte) ! 513: void Intercept_Monitor_ReadByte(void) ! 514: { ! 515: unsigned short v; ! 516: v=MFP_GPIP & 0x7f; /* Lower 7-bits are GPIP(Top bit is monitor type) */ ! 517: if( !bUseHighRes ) v|=0x80; /* Colour monitor */ ! 518: STRam[0xfffa01]=v; ! 519: } ! 520: ! 521: // INTERCEPT_ACTIVE_EDGE(0xfffa03 byte) ! 522: void Intercept_ActiveEdge_ReadByte(void) ! 523: { ! 524: STRam[0xfffa03] = MFP_AER; ! 525: } ! 526: ! 527: // INTERCEPT_DATA_DIRECTION(0xfffa05 byte) ! 528: void Intercept_DataDirection_ReadByte(void) ! 529: { ! 530: STRam[0xfffa05] = MFP_DDR; ! 531: } ! 532: ! 533: // INTERCEPT_ENABLE_A(0xfffa07 byte) ! 534: void Intercept_EnableA_ReadByte(void) ! 535: { ! 536: STRam[0xfffa07] = MFP_IERA; ! 537: } ! 538: ! 539: // INTERCEPT_ENABLE_B(0xfffa09 byte) ! 540: void Intercept_EnableB_ReadByte(void) ! 541: { ! 542: STRam[0xfffa09] = MFP_IERB; ! 543: } ! 544: ! 545: // INTERCEPT_PENDING_A(0xfffa0b byte) ! 546: void Intercept_PendingA_ReadByte(void) ! 547: { ! 548: STRam[0xfffa0b] = MFP_IPRA; ! 549: } ! 550: ! 551: // INTERCEPT_PENDING_B(0xfffa0d byte) ! 552: void Intercept_PendingB_ReadByte(void) ! 553: { ! 554: STRam[0xfffa0d] = MFP_IPRB; ! 555: } ! 556: ! 557: // INTERCEPT_INSERVICE_A(0xfffa0f byte) ! 558: void Intercept_InServiceA_ReadByte(void) ! 559: { ! 560: STRam[0xfffa0f] = MFP_ISRA; ! 561: } ! 562: ! 563: // INTERCEPT_INSERVICE_B(0xfffa11 byte) ! 564: void Intercept_InServiceB_ReadByte(void) ! 565: { ! 566: STRam[0xfffa11] = MFP_ISRB; ! 567: } ! 568: ! 569: // INTERCEPT_MASK_A(0xfffa13 byte) ! 570: void Intercept_MaskA_ReadByte(void) ! 571: { ! 572: STRam[0xfffa13] = MFP_IMRA; ! 573: } ! 574: ! 575: // INTERCEPT_MASK_B(0xfffa15 byte) ! 576: void Intercept_MaskB_ReadByte(void) ! 577: { ! 578: STRam[0xfffa15] = MFP_IMRB; ! 579: } ! 580: ! 581: // INTERCEPT_VECTOR_REG(0xfffa17 byte) ! 582: void Intercept_VectorReg_ReadByte(void) ! 583: { ! 584: STRam[0xfffa17] = MFP_VR; ! 585: } ! 586: ! 587: // INTERCEPT_TIMERA_CTRL(0xfffa19 byte) ! 588: void Intercept_TimerACtrl_ReadByte(void) ! 589: { ! 590: STRam[0xfffa19] = MFP_TACR; ! 591: } ! 592: ! 593: // INTERCEPT_TIMERB_CTRL(0xfffa1b byte) ! 594: void Intercept_TimerBCtrl_ReadByte(void) ! 595: { ! 596: STRam[0xfffa1b] = MFP_TBCR; ! 597: } ! 598: ! 599: // INTERCEPT_TIMERCD_CTRL(0xfffa1d byte) ! 600: void Intercept_TimerCDCtrl_ReadByte(void) ! 601: { ! 602: STRam[0xfffa1d] = MFP_TCDCR; ! 603: } ! 604: ! 605: // INTERCEPT_TIMERA_DATA(0xfffa1f byte) ! 606: void Intercept_TimerAData_ReadByte(void) ! 607: { ! 608: if( MFP_TACR != 8 ) /* Is event count? Need to re-calculate counter */ ! 609: MFP_ReadTimerA(); /* Stores result in 'MFP_TA_MAINCOUNTER' */ ! 610: STRam[0xfffa1f] = MFP_TA_MAINCOUNTER; ! 611: } ! 612: ! 613: // INTERCEPT_TIMERB_DATA(0xfffa21 byte) ! 614: void Intercept_TimerBData_ReadByte(void) ! 615: { ! 616: if(MFP_TBCR != 8) /* Is event count? Need to re-calculate counter */ ! 617: MFP_ReadTimerB(); /* Stores result in 'MFP_TB_MAINCOUNTER' */ ! 618: STRam[0xfffa21] = MFP_TB_MAINCOUNTER; ! 619: } ! 620: ! 621: // INTERCEPT_TIMERC_DATA(0xfffa23 byte) ! 622: void Intercept_TimerCData_ReadByte(void) ! 623: { ! 624: MFP_ReadTimerC(); /* Stores result in 'MFP_TC_MAINCOUNTER' */ ! 625: STRam[0xfffa23] = MFP_TC_MAINCOUNTER; ! 626: } ! 627: ! 628: // INTERCEPT_TIMERD_DATA(0xfffa25 byte) ! 629: void Intercept_TimerDData_ReadByte(void) ! 630: { ! 631: MFP_ReadTimerD(); /* Stores result in 'MFP_TD_MAINCOUNTER' */ ! 632: STRam[0xfffa25] = MFP_TD_MAINCOUNTER; ! 633: } ! 634: ! 635: // INTERCEPT_KEYBOARDCONTROL(0xfffc00 byte) ! 636: void Intercept_KeyboardControl_ReadByte(void) ! 637: { ! 638: /* For our emulation send is immediate so acknowledge buffer is empty */ ! 639: STRam[0xfffc00] = ACIAStatusRegister | ACIA_STATUS_REGISTER__TX_BUFFER_EMPTY; ! 640: } ! 641: ! 642: // INTERCEPT_KEYBOARDDATA(0xfffc02 byte) ! 643: void Intercept_KeyboardData_ReadByte(void) ! 644: { ! 645: STRam[0xfffc02] = IKBD_GetByteFromACIA(); /* Return our byte from keyboard processor */ ! 646: } ! 647: ! 648: // INTERCEPT_MIDICONTROL(0xfffc04 byte) ! 649: void Intercept_MidiControl_ReadByte(void) ! 650: { ! 651: STRam[0xfffc04] = 2; /* Should be this? */ ! 652: } ! 653: ! 654: // INTERCEPT_MIDIDATA(0xfffc06 byte) ! 655: void Intercept_MidiData_ReadByte(void) ! 656: { ! 657: STRam[0xfffc06] = 1; /* Should be this? */ ! 658: } ! 659: ! 660: ! 661: ! 662: ! 663: //----------------------------------------------------------------------- ! 664: // Write to Hardware(0x00ff8000 to 0xffffff) ! 665: ! 666: // INTERCEPT_VIDEOHIGH(0xff8205 byte) ! 667: void Intercept_VideoHigh_WriteByte(void) ! 668: { ! 669: // Nothing... ! 670: } ! 671: ! 672: // INTERCEPT_VIDEOMED(0xff8207 byte) ! 673: void Intercept_VideoMed_WriteByte(void) ! 674: { ! 675: // Nothing... ! 676: } ! 677: ! 678: // INTERCEPT_VIDEOLOW(0xff8209 byte) ! 679: void Intercept_VideoLow_WriteByte(void) ! 680: { ! 681: // Nothing... ! 682: } ! 683: ! 684: // INTERCEPT_VIDEOSYNC(0xff820a byte) ! 685: void Intercept_VideoSync_WriteByte(void) ! 686: { ! 687: VideoSyncByte = STRam[0xff820a] & 3; /* We're only interested in lower 2 bits(50/60Hz) */ ! 688: Video_WriteToSync(); ! 689: } ! 690: ! 691: // INTERCEPT_VIDEOBASELOW(0xff820d byte) ! 692: void Intercept_VideoBaseLow_WriteByte(void) ! 693: { ! 694: // Nothing... ! 695: } ! 696: ! 697: // INTERCEPT_LINEWIDTH(0xff820f byte) ! 698: void Intercept_LineWidth_WriteByte(void) ! 699: { ! 700: // Nothing... ! 701: } ! 702: ! 703: void Intercept_Colour_WriteWord(unsigned long addr) ! 704: { ! 705: if( !bUseHighRes ) /* Don't store if hi-res */ ! 706: { ! 707: unsigned short col; ! 708: Video_SetHBLPaletteMaskPointers(); /* Set 'pHBLPalettes' etc.. according cycles into frame */ ! 709: col = STMemory_ReadWord( addr ); ! 710: col &= 0x777; /* Mask off to 512 palette(some games write 0xFFFF and read back to see if STe) */ ! 711: Spec512_StoreCyclePalette( col, addr ); /* Store colour into CyclePalettes[] */ ! 712: pHBLPalettes[(addr-0xff8240)/2]=col; /* Set colour x */ ! 713: *pHBLPaletteMasks |= 1 << ((addr-0xff8240)/2); /* And mask */ ! 714: } ! 715: } ! 716: ! 717: // INTERCEPT_COLOUR0(0xff8240 word) ! 718: void Intercept_Colour0_WriteWord(void) ! 719: { ! 720: Intercept_Colour_WriteWord( 0xff8240 ); ! 721: } ! 722: ! 723: // INTERCEPT_COLOUR1(0xff8242 word) ! 724: void Intercept_Colour1_WriteWord(void) ! 725: { ! 726: Intercept_Colour_WriteWord( 0xff8242 ); ! 727: } ! 728: ! 729: // INTERCEPT_COLOUR2(0xff8244 word) ! 730: void Intercept_Colour2_WriteWord(void) ! 731: { ! 732: Intercept_Colour_WriteWord( 0xff8244 ); ! 733: } ! 734: ! 735: // INTERCEPT_COLOUR3(0xff8246 word) ! 736: void Intercept_Colour3_WriteWord(void) ! 737: { ! 738: Intercept_Colour_WriteWord( 0xff8246 ); ! 739: } ! 740: ! 741: // INTERCEPT_COLOUR4(0xff8248 word) ! 742: void Intercept_Colour4_WriteWord(void) ! 743: { ! 744: Intercept_Colour_WriteWord( 0xff8248 ); ! 745: } ! 746: ! 747: // INTERCEPT_COLOUR5(0xff824a word) ! 748: void Intercept_Colour5_WriteWord(void) ! 749: { ! 750: Intercept_Colour_WriteWord( 0xff824a ); ! 751: } ! 752: ! 753: // INTERCEPT_COLOUR6(0xff824c word) ! 754: void Intercept_Colour6_WriteWord(void) ! 755: { ! 756: Intercept_Colour_WriteWord( 0xff824c ); ! 757: } ! 758: ! 759: // INTERCEPT_COLOUR7(0xff824e word) ! 760: void Intercept_Colour7_WriteWord(void) ! 761: { ! 762: Intercept_Colour_WriteWord( 0xff824e ); ! 763: } ! 764: ! 765: // INTERCEPT_COLOUR8(0xff8250 word) ! 766: void Intercept_Colour8_WriteWord(void) ! 767: { ! 768: Intercept_Colour_WriteWord( 0xff8250 ); ! 769: } ! 770: ! 771: // INTERCEPT_COLOUR9(0xff8252 word) ! 772: void Intercept_Colour9_WriteWord(void) ! 773: { ! 774: Intercept_Colour_WriteWord( 0xff8252 ); ! 775: } ! 776: ! 777: // INTERCEPT_COLOUR10(0xff8254 word) ! 778: void Intercept_Colour10_WriteWord(void) ! 779: { ! 780: Intercept_Colour_WriteWord( 0xff8254 ); ! 781: } ! 782: ! 783: // INTERCEPT_COLOUR11(0xff8256 word) ! 784: void Intercept_Colour11_WriteWord(void) ! 785: { ! 786: Intercept_Colour_WriteWord( 0xff8256 ); ! 787: } ! 788: ! 789: // INTERCEPT_COLOUR12(0xff8258 word) ! 790: void Intercept_Colour12_WriteWord(void) ! 791: { ! 792: Intercept_Colour_WriteWord( 0xff8258 ); ! 793: } ! 794: ! 795: // INTERCEPT_COLOUR13(0xff825a word) ! 796: void Intercept_Colour13_WriteWord(void) ! 797: { ! 798: Intercept_Colour_WriteWord( 0xff825a ); ! 799: } ! 800: ! 801: // INTERCEPT_COLOUR14(0xff825c word) ! 802: void Intercept_Colour14_WriteWord(void) ! 803: { ! 804: Intercept_Colour_WriteWord( 0xff825c ); ! 805: } ! 806: ! 807: // INTERCEPT_COLOUR15(0xff825e word) ! 808: void Intercept_Colour15_WriteWord(void) ! 809: { ! 810: Intercept_Colour_WriteWord( 0xff825e ); ! 811: } ! 812: ! 813: // INTERCEPT_SHIFTERMODE(0xff8260 byte) ! 814: void Intercept_ShifterMode_WriteByte(void) ! 815: { ! 816: if( !bUseHighRes && !bUseVDIRes ) /* Don't store if hi-res and don't store if VDI resolution */ ! 817: { ! 818: VideoShifterByte = STRam[0xff8260] & 3; /* We only care for lower 2-bits */ ! 819: Video_WriteToShifter(); ! 820: Video_SetHBLPaletteMaskPointers(); ! 821: *pHBLPaletteMasks &= 0xffff00ff; ! 822: *pHBLPaletteMasks |= (VideoShifterByte|0x04)<<8; /* Store resolution after palette mask and set resolution write bit */ ! 823: } ! 824: /* FIXME: Is the pHBLPaletteMasks stuff okay? In the original source, it was: */ ! 825: /* ! 826: mov ebp,[pHBLPaletteMasks] // Store resolution ! 827: mov bl,[VideoShifterByte] ! 828: mov BYTE PTR [ebp+2],bl // after palette mask ! 829: or BYTE PTR [ebp+2],0x04 // and set resolution write bit ! 830: */ ! 831: } ! 832: ! 833: // INTERCEPT_DISKCONTROL(0xff8604 word) ! 834: void Intercept_DiskControl_WriteWord(void) ! 835: { ! 836: FDC_WriteDiscController( STMemory_ReadWord(0xff8604) ); ! 837: } ! 838: ! 839: // INTERCEPT_DMASTATUS(0xff8606 word) ! 840: void Intercept_DmaStatus_WriteWord(void) ! 841: { ! 842: FDC_WriteDMAModeControl( STMemory_ReadWord(0xff8606) ); ! 843: } ! 844: ! 845: // INTERCEPT_PSG_REGISTER(0xff8800 byte) ! 846: void Intercept_PSGRegister_WriteByte(void) ! 847: { ! 848: PSG_WriteSelectRegister( STRam[0xff8800] ); ! 849: } ! 850: ! 851: // INTERCEPT_PSG_DATA(0xff8802 byte) ! 852: void Intercept_PSGData_WriteByte(void) ! 853: { ! 854: PSG_WriteDataRegister( STRam[0xff8802] ); ! 855: } ! 856: ! 857: // INTERCEPT_MICROWIREDATA(0xff8922 word) ! 858: void Intercept_MicrowireData_WriteWord(void) ! 859: { ! 860: // Nothing... ! 861: } ! 862: ! 863: // INTERCEPT_MONITOR(0xfffa01 byte) ! 864: void Intercept_Monitor_WriteByte(void) ! 865: { ! 866: // Nothing... ! 867: } ! 868: ! 869: // INTERCEPT_ACTIVE_EDGE(0xfffa03 byte) ! 870: void Intercept_ActiveEdge_WriteByte(void) ! 871: { ! 872: MFP_AER = STRam[0xfffa03]; ! 873: } ! 874: ! 875: // INTERCEPT_DATA_DIRECTION(0xfffa05 byte) ! 876: void Intercept_DataDirection_WriteByte(void) ! 877: { ! 878: MFP_DDR = STRam[0xfffa05]; ! 879: } ! 880: ! 881: ! 882: // INTERCEPT_ENABLE_A(0xfffa07 byte) ! 883: void Intercept_EnableA_WriteByte(void) ! 884: { ! 885: MFP_IERA = STRam[0xfffa07]; ! 886: MFP_IPRA &= MFP_IERA; ! 887: MFP_UpdateFlags(); ! 888: /* We may have enabled Timer A or B, check */ ! 889: MFP_StartTimerA(); ! 890: MFP_StartTimerB(); ! 891: } ! 892: ! 893: // INTERCEPT_ENABLE_B(0xfffa09 byte) ! 894: void Intercept_EnableB_WriteByte(void) ! 895: { ! 896: MFP_IERB = STRam[0xfffa09]; ! 897: MFP_IPRB &= MFP_IERB; ! 898: MFP_UpdateFlags(); ! 899: /* We may have enabled Timer C or D, check */ ! 900: MFP_StartTimerC(); ! 901: MFP_StartTimerD(); ! 902: } ! 903: ! 904: // INTERCEPT_PENDING_A(0xfffa0b byte) ! 905: void Intercept_PendingA_WriteByte(void) ! 906: { ! 907: MFP_IPRA &= STRam[0xfffa0b]; /* Cannot set pending bits - only clear via software */ ! 908: MFP_UpdateFlags(); /* Check if any interrupts pending */ ! 909: } ! 910: ! 911: // INTERCEPT_PENDING_B(0xfffa0d byte) ! 912: void Intercept_PendingB_WriteByte(void) ! 913: { ! 914: MFP_IPRB &= STRam[0xfffa0d]; ! 915: MFP_UpdateFlags(); /* Check if any interrupts pending */ ! 916: } ! 917: ! 918: // INTERCEPT_INSERVICE_A(0xfffa0f byte) ! 919: void Intercept_InServiceA_WriteByte(void) ! 920: { ! 921: MFP_ISRA &= STRam[0xfffa0f]; /* Cannot set in-service bits - only clear via software */ ! 922: } ! 923: ! 924: // INTERCEPT_INSERVICE_B(0xfffa11 byte) ! 925: void Intercept_InServiceB_WriteByte(void) ! 926: { ! 927: MFP_ISRB &= STRam[0xfffa11]; /* Cannot set in-service bits - only clear via software */ ! 928: } ! 929: ! 930: // INTERCEPT_MASK_A(0xfffa13 byte) ! 931: void Intercept_MaskA_WriteByte(void) ! 932: { ! 933: MFP_IMRA = STRam[0xfffa13]; ! 934: } ! 935: ! 936: // INTERCEPT_MASK_B(0xfffa15 byte) ! 937: void Intercept_MaskB_WriteByte(void) ! 938: { ! 939: MFP_IMRB = STRam[0xfffa15]; ! 940: } ! 941: ! 942: // INTERCEPT_VECTOR_REG(0xfffa17 byte) ! 943: void Intercept_VectorReg_WriteByte(void) ! 944: { ! 945: unsigned short old_vr; ! 946: old_vr = MFP_VR; /* Copy for checking if set mode */ ! 947: MFP_VR = STRam[0xfffa17]; ! 948: if( (MFP_VR^old_vr)&0x08 ) /* Test change in end-of-interrupt mode */ ! 949: if( MFP_VR&0x08 ) /* Mode did change but was it to automatic mode? (ie bit is a zero) */ ! 950: { /* We are now in automatic mode, so clear all in-service bits! */ ! 951: MFP_ISRA = 0; ! 952: MFP_ISRB = 0; ! 953: } ! 954: } ! 955: ! 956: // INTERCEPT_TIMERA_CTRL(0xfffa19 byte) ! 957: void Intercept_TimerACtrl_WriteByte(void) ! 958: { ! 959: unsigned short old_tacr; ! 960: old_tacr = MFP_TACR; /* Remember old control state */ ! 961: MFP_TACR = STRam[0xfffa19] & 0x0f; /* Mask, Fish(auto160) writes into top nibble! */ ! 962: if( (MFP_TACR^old_tacr)&0x0f ) /* Check if Timer A control changed */ ! 963: MFP_StartTimerA(); /* Reset timers if need to */ ! 964: } ! 965: ! 966: // INTERCEPT_TIMERB_CTRL(0xfffa1b byte) ! 967: void Intercept_TimerBCtrl_WriteByte(void) ! 968: { ! 969: unsigned short old_tbcr; ! 970: old_tbcr = MFP_TBCR; /* Remember old control state */ ! 971: MFP_TBCR = STRam[0xfffa1b] & 0x0f; /* Mask, Fish(auto160) writes into top nibble! */ ! 972: if( (MFP_TBCR^old_tbcr)&0x0f ) /* Check if Timer B control changed */ ! 973: MFP_StartTimerB(); /* Reset timers if need to */ ! 974: } ! 975: ! 976: // INTERCEPT_TIMERCD_CTRL(0xfffa1d byte) ! 977: void Intercept_TimerCDCtrl_WriteByte(void) ! 978: { ! 979: unsigned short old_tcdcr; ! 980: old_tcdcr = MFP_TCDCR; /* Remember old control state */ ! 981: MFP_TCDCR = STRam[0xfffa1d]; /* Store new one */ ! 982: if( (MFP_TCDCR^old_tcdcr)&0x70 ) /* Check if Timer C control changed */ ! 983: MFP_StartTimerC(); /* Reset timers if need to */ ! 984: if( (MFP_TCDCR^old_tcdcr)&0x07 ) /* Check if Timer D control changed */ ! 985: MFP_StartTimerD(); /* Reset timers if need to */ ! 986: } ! 987: ! 988: // INTERCEPT_TIMERA_DATA(0xfffa1f byte) ! 989: void Intercept_TimerAData_WriteByte(void) ! 990: { ! 991: MFP_TADR = STRam[0xfffa1f]; /* Store into data register */ ! 992: if( MFP_TACR==0 ) /* Now check if timer is running - if so do not set */ ! 993: { ! 994: MFP_TA_MAINCOUNTER = MFP_TADR; /* Timer is off, store to main counter */ ! 995: MFP_StartTimerA(); /* Add our interrupt */ ! 996: } ! 997: } ! 998: ! 999: // INTERCEPT_TIMERB_DATA(0xfffa21 byte) ! 1000: void Intercept_TimerBData_WriteByte(void) ! 1001: { ! 1002: MFP_TBDR = STRam[0xfffa21]; /* Store into data register */ ! 1003: if( MFP_TBCR==0 ) /* Now check if timer is running - if so do not set */ ! 1004: { ! 1005: MFP_TB_MAINCOUNTER = MFP_TBDR; /* Timer is off, store to main counter */ ! 1006: MFP_StartTimerB(); /* Add our interrupt */ ! 1007: } ! 1008: } ! 1009: ! 1010: // INTERCEPT_TIMERC_DATA(0xfffa23 byte) ! 1011: void Intercept_TimerCData_WriteByte(void) ! 1012: { ! 1013: MFP_TCDR = STRam[0xfffa23]; /* Store into data register */ ! 1014: if( (MFP_TCDCR&0x70)==0 ) /* Now check if timer is running - if so do not set */ ! 1015: { ! 1016: MFP_StartTimerC(); /* Add our interrupt */ ! 1017: } ! 1018: } ! 1019: ! 1020: // INTERCEPT_TIMERD_DATA(0xfffa25 byte) ! 1021: void Intercept_TimerDData_WriteByte(void) ! 1022: { ! 1023: MFP_TDDR = STRam[0xfffa25]; /* Store into data register */ ! 1024: if( (MFP_TCDCR&0x07)==0 ) /* Now check if timer is running - if so do not set */ ! 1025: { ! 1026: MFP_StartTimerD(); /* Add our interrupt */ ! 1027: } ! 1028: } ! 1029: ! 1030: // INTERCEPT_KEYBOARDCONTROL(0xfffc00 byte) ! 1031: void Intercept_KeyboardControl_WriteByte(void) ! 1032: { ! 1033: /* Nothing... */ ! 1034: } ! 1035: ! 1036: // INTERCEPT_KEYBOARDDATA(0xfffc02 byte) ! 1037: void Intercept_KeyboardData_WriteByte(void) ! 1038: { ! 1039: IKBD_SendByteToKeyboardProcessor( STRam[0xfffc02] ); /* Pass our byte to the keyboard processor */ ! 1040: } ! 1041: ! 1042: // INTERCEPT_MIDICONTROL(0xfffc04 byte) ! 1043: void Intercept_MidiControl_WriteByte(void) ! 1044: { ! 1045: /* Nothing... */ ! 1046: } ! 1047: ! 1048: // INTERCEPT_MIDIDATA(0xfffc06 byte) ! 1049: void Intercept_MidiData_WriteByte(void) ! 1050: { ! 1051: /* Nothing... */ ! 1052: } ! 1053: ! 1054: ! 1055: // Address space for Bus Error in hardware mapping ! 1056: INTERCEPT_ADDRESSRANGE InterceptBusErrors[] = { ! 1057: 0xff8a00,0xff8a3e, /* Blitter */ ! 1058: 0xff8900,0xff8960, /* DMA Sound/MicroWire */ ! 1059: ! 1060: 0,0 /* term */ ! 1061: }; ! 1062: ! 1063: ! 1064: ! 1065: /*-------------------------------------------------------------------------*/ ! 1066: /* ! 1067: Modify 'intercept' tables to cause Bus Errors on addres to un-mapped ! 1068: hardware space (Wing Of Death addresses Blitter space which causes ! 1069: BusError on STfm) ! 1070: */ ! 1071: void Intercept_ModifyTablesForBusErrors(void) ! 1072: { ! 1073: unsigned long *pInterceptList; ! 1074: unsigned int Address; ! 1075: int i=0; ! 1076: ! 1077: // Set routine list ! 1078: pInterceptList = pCurrentInterceptWorkspace; ! 1079: *pCurrentInterceptWorkspace++ = (unsigned long)M68000_BusError; ! 1080: *pCurrentInterceptWorkspace++ = 0L; ! 1081: ! 1082: // Set all 'no-mans-land' entries ! 1083: while(InterceptBusErrors[i].Start_Address!=0) { ! 1084: // Set 'no-mans-land' table ! 1085: for(Address=InterceptBusErrors[i].Start_Address; Address<InterceptBusErrors[i].End_Address; Address++) { ! 1086: // For 'read' ! 1087: pInterceptReadByteTable[Address-0xff8000] = pInterceptList; ! 1088: pInterceptReadWordTable[Address-0xff8000] = pInterceptList; ! 1089: pInterceptReadLongTable[Address-0xff8000] = pInterceptList; ! 1090: // and 'write' ! 1091: pInterceptWriteByteTable[Address-0xff8000] = pInterceptList; ! 1092: pInterceptWriteWordTable[Address-0xff8000] = pInterceptList; ! 1093: pInterceptWriteLongTable[Address-0xff8000] = pInterceptList; ! 1094: } ! 1095: ! 1096: i++; ! 1097: } ! 1098: } ! 1099: ! 1100: #ifdef CHECK_FOR_NO_MANS_LAND ! 1101: ! 1102: // List of hardware addresses which are 'no-man's-land', ie not connected on ST ! 1103: // NOTE PSG is mirror'd in range 0xff8004 to 0xff8900 ! 1104: INTERCEPT_ADDRESSRANGE InterceptNoMansLand[] = { ! 1105: 0xff8002,0xff8200, // All these are illegal addresses on standard STfm ! 1106: 0xff8210,0xff8240, ! 1107: 0xff8262,0xff8600, ! 1108: 0xff860e,0xff8800, ! 1109: 0xff8900,0xfffa00, ! 1110: 0xfffa30,0xfffc00, ! 1111: 0xfffc20,0x1000000, ! 1112: ! 1113: 0,0 //term ! 1114: }; ! 1115: ! 1116: //----------------------------------------------------------------------- ! 1117: /* ! 1118: Intercept function used on all non-documented hardware registers. Used to help debugging ! 1119: */ ! 1120: void Intercept_NoMansLand_ReadWrite(void) ! 1121: { ! 1122: /* ! 1123: SAVE_ASSEM_REGS ! 1124: __asm { ! 1125: // 'ebp' will hold address we tried to access! ! 1126: // 'esi' is ST program counter! ! 1127: int 3 // Cause Windows GPF, so can see register list ! 1128: } ! 1129: */ ! 1130: } ! 1131: ! 1132: //----------------------------------------------------------------------- ! 1133: /* ! 1134: Modify 'intercept' tables to check for access into 'no-mans-land', ie unknown hardware locations ! 1135: */ ! 1136: void Intercept_ModifyTablesForNoMansLand(void) ! 1137: { ! 1138: unsigned long *pInterceptList; ! 1139: unsigned int Address; ! 1140: int i=0; ! 1141: ! 1142: // Set routine list ! 1143: pInterceptList = pCurrentInterceptWorkspace; ! 1144: *pCurrentInterceptWorkspace++ = (unsigned long)Intercept_NoMansLand_ReadWrite; ! 1145: *pCurrentInterceptWorkspace++ = NULL; ! 1146: ! 1147: // Set all 'no-mans-land' entries ! 1148: while(InterceptNoMansLand[i].Start_Address!=0) { ! 1149: // Set 'no-mans-land' table ! 1150: for(Address=InterceptNoMansLand[i].Start_Address; Address<InterceptNoMansLand[i].End_Address; Address++) { ! 1151: // For 'read' ! 1152: pInterceptReadByteTable[Address-0xff8000] = pInterceptList; ! 1153: pInterceptReadWordTable[Address-0xff8000] = pInterceptList; ! 1154: pInterceptReadLongTable[Address-0xff8000] = pInterceptList; ! 1155: // and 'write' ! 1156: pInterceptWriteByteTable[Address-0xff8000] = pInterceptList; ! 1157: pInterceptWriteWordTable[Address-0xff8000] = pInterceptList; ! 1158: pInterceptWriteLongTable[Address-0xff8000] = pInterceptList; ! 1159: } ! 1160: ! 1161: i++; ! 1162: } ! 1163: } ! 1164: ! 1165: #endif //CHECK_FOR_NO_MANS_LAND ! 1166:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.