Annotation of hatari/src/intercept.c, revision 1.1.1.1

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: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.