Annotation of hatari/src/intercept.c, revision 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.