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

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

unix.superglobalmegacorp.com

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