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

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 );
1.1.1.3   root      712:    col &= 0x777;                                    /* Mask off to 512 palette */
                    713:    STMemory_WriteWord(addr, col);                   /* (some games write 0xFFFF and read back to see if STe) */
1.1       root      714:    Spec512_StoreCyclePalette( col, addr );          /* Store colour into CyclePalettes[] */
                    715:    pHBLPalettes[(addr-0xff8240)/2]=col;             /* Set colour x */
                    716:    *pHBLPaletteMasks |= 1 << ((addr-0xff8240)/2);   /* And mask */
                    717:   }
                    718: }
                    719: 
1.1.1.2   root      720: /* INTERCEPT_COLOUR0(0xff8240 word) */
1.1       root      721: void Intercept_Colour0_WriteWord(void)
                    722: {
                    723:  Intercept_Colour_WriteWord( 0xff8240 );
                    724: }
                    725: 
1.1.1.2   root      726: /* INTERCEPT_COLOUR1(0xff8242 word) */
1.1       root      727: void Intercept_Colour1_WriteWord(void)
                    728: {
                    729:  Intercept_Colour_WriteWord( 0xff8242 );
                    730: }
                    731: 
1.1.1.2   root      732: /* INTERCEPT_COLOUR2(0xff8244 word) */
1.1       root      733: void Intercept_Colour2_WriteWord(void)
                    734: {
                    735:  Intercept_Colour_WriteWord( 0xff8244 );
                    736: }
                    737: 
1.1.1.2   root      738: /* INTERCEPT_COLOUR3(0xff8246 word) */
1.1       root      739: void Intercept_Colour3_WriteWord(void)
                    740: {
                    741:  Intercept_Colour_WriteWord( 0xff8246 );
                    742: }
                    743: 
1.1.1.2   root      744: /* INTERCEPT_COLOUR4(0xff8248 word) */
1.1       root      745: void Intercept_Colour4_WriteWord(void)
                    746: {
                    747:  Intercept_Colour_WriteWord( 0xff8248 );
                    748: }
                    749: 
1.1.1.2   root      750: /* INTERCEPT_COLOUR5(0xff824a word) */
1.1       root      751: void Intercept_Colour5_WriteWord(void)
                    752: {
                    753:  Intercept_Colour_WriteWord( 0xff824a );
                    754: }
                    755: 
1.1.1.2   root      756: /* INTERCEPT_COLOUR6(0xff824c word) */
1.1       root      757: void Intercept_Colour6_WriteWord(void)
                    758: {
                    759:  Intercept_Colour_WriteWord( 0xff824c );
                    760: }
                    761: 
1.1.1.2   root      762: /* INTERCEPT_COLOUR7(0xff824e word) */
1.1       root      763: void Intercept_Colour7_WriteWord(void)
                    764: {
                    765:  Intercept_Colour_WriteWord( 0xff824e );
                    766: }
                    767: 
1.1.1.2   root      768: /* INTERCEPT_COLOUR8(0xff8250 word) */
1.1       root      769: void Intercept_Colour8_WriteWord(void)
                    770: {
                    771:  Intercept_Colour_WriteWord( 0xff8250 );
                    772: }
                    773: 
1.1.1.2   root      774: /* INTERCEPT_COLOUR9(0xff8252 word) */
1.1       root      775: void Intercept_Colour9_WriteWord(void)
                    776: {
                    777:  Intercept_Colour_WriteWord( 0xff8252 );
                    778: }
                    779: 
1.1.1.2   root      780: /* INTERCEPT_COLOUR10(0xff8254 word) */
1.1       root      781: void Intercept_Colour10_WriteWord(void)
                    782: {
                    783:  Intercept_Colour_WriteWord( 0xff8254 );
                    784: }
                    785: 
1.1.1.2   root      786: /* INTERCEPT_COLOUR11(0xff8256 word) */
1.1       root      787: void Intercept_Colour11_WriteWord(void)
                    788: {
                    789:  Intercept_Colour_WriteWord( 0xff8256 );
                    790: }
                    791: 
1.1.1.2   root      792: /* INTERCEPT_COLOUR12(0xff8258 word) */
1.1       root      793: void Intercept_Colour12_WriteWord(void)
                    794: {
                    795:  Intercept_Colour_WriteWord( 0xff8258 );
                    796: }
                    797: 
1.1.1.2   root      798: /* INTERCEPT_COLOUR13(0xff825a word) */
1.1       root      799: void Intercept_Colour13_WriteWord(void)
                    800: {
                    801:  Intercept_Colour_WriteWord( 0xff825a );
                    802: }
                    803: 
1.1.1.2   root      804: /* INTERCEPT_COLOUR14(0xff825c word) */
1.1       root      805: void Intercept_Colour14_WriteWord(void)
                    806: {
                    807:  Intercept_Colour_WriteWord( 0xff825c );
                    808: }
                    809: 
1.1.1.2   root      810: /* INTERCEPT_COLOUR15(0xff825e word) */
1.1       root      811: void Intercept_Colour15_WriteWord(void)
                    812: {
                    813:  Intercept_Colour_WriteWord( 0xff825e );
                    814: }
                    815: 
1.1.1.2   root      816: /* INTERCEPT_SHIFTERMODE(0xff8260 byte) */
1.1       root      817: void Intercept_ShifterMode_WriteByte(void)
                    818: {
                    819:  if( !bUseHighRes && !bUseVDIRes )                    /* Don't store if hi-res and don't store if VDI resolution */
                    820:   {
                    821:    VideoShifterByte = STRam[0xff8260] & 3;            /* We only care for lower 2-bits */
                    822:    Video_WriteToShifter();
                    823:    Video_SetHBLPaletteMaskPointers();
1.1.1.3   root      824:    *pHBLPaletteMasks &= 0xff00ffff;
                    825:    /* Store resolution after palette mask and set resolution write bit: */
                    826:    *pHBLPaletteMasks |= (((unsigned long)VideoShifterByte|0x04)<<16);
1.1       root      827:   }
                    828: }
                    829: 
1.1.1.2   root      830: /* INTERCEPT_DISKCONTROL(0xff8604 word) */
1.1       root      831: void Intercept_DiskControl_WriteWord(void)
                    832: {
                    833:  FDC_WriteDiscController( STMemory_ReadWord(0xff8604) );
                    834: }
                    835: 
1.1.1.2   root      836: /* INTERCEPT_DMASTATUS(0xff8606 word) */
1.1       root      837: void Intercept_DmaStatus_WriteWord(void)
                    838: {
                    839:  FDC_WriteDMAModeControl( STMemory_ReadWord(0xff8606) );
                    840: }
                    841: 
1.1.1.2   root      842: /* INTERCEPT_PSG_REGISTER(0xff8800 byte) */
1.1       root      843: void Intercept_PSGRegister_WriteByte(void)
                    844: {
                    845:  PSG_WriteSelectRegister( STRam[0xff8800] );
                    846: }
                    847: 
1.1.1.2   root      848: /* INTERCEPT_PSG_DATA(0xff8802 byte) */
1.1       root      849: void Intercept_PSGData_WriteByte(void)
                    850: {
                    851:  PSG_WriteDataRegister( STRam[0xff8802] );
                    852: }
                    853: 
1.1.1.2   root      854: /* INTERCEPT_MICROWIREDATA(0xff8922 word) */
1.1       root      855: void Intercept_MicrowireData_WriteWord(void)
                    856: {
1.1.1.2   root      857:   /* Nothing... */
1.1       root      858: }
                    859: 
1.1.1.2   root      860: /* INTERCEPT_MONITOR(0xfffa01 byte) */
1.1       root      861: void Intercept_Monitor_WriteByte(void)
                    862: {
1.1.1.2   root      863:   /* Nothing... */
1.1       root      864: }
                    865: 
1.1.1.2   root      866: /* INTERCEPT_ACTIVE_EDGE(0xfffa03 byte) */
1.1       root      867: void Intercept_ActiveEdge_WriteByte(void)
                    868: {
                    869:  MFP_AER = STRam[0xfffa03];
                    870: }
                    871: 
1.1.1.2   root      872: /* INTERCEPT_DATA_DIRECTION(0xfffa05 byte) */
1.1       root      873: void Intercept_DataDirection_WriteByte(void)
                    874: {
                    875:  MFP_DDR = STRam[0xfffa05];
                    876: }
                    877: 
                    878: 
1.1.1.2   root      879: /* INTERCEPT_ENABLE_A(0xfffa07 byte) */
1.1       root      880: void Intercept_EnableA_WriteByte(void)
                    881: {
                    882:  MFP_IERA = STRam[0xfffa07];
                    883:  MFP_IPRA &= MFP_IERA;
                    884:  MFP_UpdateFlags();
                    885:  /* We may have enabled Timer A or B, check */
                    886:  MFP_StartTimerA();
                    887:  MFP_StartTimerB();
                    888: }
                    889: 
1.1.1.2   root      890: /* INTERCEPT_ENABLE_B(0xfffa09 byte) */
1.1       root      891: void Intercept_EnableB_WriteByte(void)
                    892: {
                    893:  MFP_IERB = STRam[0xfffa09];
                    894:  MFP_IPRB &= MFP_IERB;
                    895:  MFP_UpdateFlags();
                    896:  /* We may have enabled Timer C or D, check */
                    897:  MFP_StartTimerC();
                    898:  MFP_StartTimerD();
                    899: }
                    900: 
1.1.1.2   root      901: /* INTERCEPT_PENDING_A(0xfffa0b byte) */
1.1       root      902: void Intercept_PendingA_WriteByte(void)
                    903: {
                    904:  MFP_IPRA &= STRam[0xfffa0b];         /* Cannot set pending bits - only clear via software */
                    905:  MFP_UpdateFlags();                   /* Check if any interrupts pending */
                    906: }
                    907: 
1.1.1.2   root      908: /* INTERCEPT_PENDING_B(0xfffa0d byte) */
1.1       root      909: void Intercept_PendingB_WriteByte(void)
                    910: {
                    911:  MFP_IPRB &= STRam[0xfffa0d];
                    912:  MFP_UpdateFlags();                   /* Check if any interrupts pending */
                    913: }
                    914: 
1.1.1.2   root      915: /* INTERCEPT_INSERVICE_A(0xfffa0f byte) */
1.1       root      916: void Intercept_InServiceA_WriteByte(void)
                    917: {
                    918:  MFP_ISRA &= STRam[0xfffa0f];         /* Cannot set in-service bits - only clear via software */
                    919: }
                    920: 
1.1.1.2   root      921: /* INTERCEPT_INSERVICE_B(0xfffa11 byte) */
1.1       root      922: void Intercept_InServiceB_WriteByte(void)
                    923: {
                    924:  MFP_ISRB &= STRam[0xfffa11];         /* Cannot set in-service bits - only clear via software */
                    925: }
                    926: 
1.1.1.2   root      927: /* INTERCEPT_MASK_A(0xfffa13 byte) */
1.1       root      928:  void Intercept_MaskA_WriteByte(void)
                    929: {
                    930:  MFP_IMRA = STRam[0xfffa13];
                    931: }
                    932: 
1.1.1.2   root      933: /* INTERCEPT_MASK_B(0xfffa15 byte) */
1.1       root      934: void Intercept_MaskB_WriteByte(void)
                    935: {
                    936:  MFP_IMRB = STRam[0xfffa15];
                    937: }
                    938: 
1.1.1.2   root      939: /* INTERCEPT_VECTOR_REG(0xfffa17 byte) */
1.1       root      940: void Intercept_VectorReg_WriteByte(void)
                    941: {
                    942:  unsigned short old_vr;
                    943:  old_vr = MFP_VR;                 /* Copy for checking if set mode */
                    944:  MFP_VR = STRam[0xfffa17];
                    945:  if( (MFP_VR^old_vr)&0x08 )       /* Test change in end-of-interrupt mode */
                    946:    if( MFP_VR&0x08 )              /* Mode did change but was it to automatic mode? (ie bit is a zero) */
                    947:      {                            /* We are now in automatic mode, so clear all in-service bits! */
                    948:       MFP_ISRA = 0;
                    949:       MFP_ISRB = 0;
                    950:      }
                    951: }
                    952: 
1.1.1.2   root      953: /* INTERCEPT_TIMERA_CTRL(0xfffa19 byte) */
1.1       root      954: void Intercept_TimerACtrl_WriteByte(void)
                    955: {
                    956:  unsigned short old_tacr;
                    957:  old_tacr = MFP_TACR;               /* Remember old control state */
                    958:  MFP_TACR = STRam[0xfffa19] & 0x0f; /* Mask, Fish(auto160) writes into top nibble! */
                    959:  if( (MFP_TACR^old_tacr)&0x0f )     /* Check if Timer A control changed */
                    960:    MFP_StartTimerA();               /* Reset timers if need to */
                    961: }
                    962: 
1.1.1.2   root      963: /* INTERCEPT_TIMERB_CTRL(0xfffa1b byte) */
1.1       root      964: void Intercept_TimerBCtrl_WriteByte(void)
                    965: {
                    966:  unsigned short old_tbcr;
                    967:  old_tbcr = MFP_TBCR;               /* Remember old control state */
                    968:  MFP_TBCR = STRam[0xfffa1b] & 0x0f; /* Mask, Fish(auto160) writes into top nibble! */
                    969:  if( (MFP_TBCR^old_tbcr)&0x0f )     /* Check if Timer B control changed */
                    970:    MFP_StartTimerB();               /* Reset timers if need to */
                    971: }
                    972: 
1.1.1.2   root      973: /* INTERCEPT_TIMERCD_CTRL(0xfffa1d byte) */
1.1       root      974: void Intercept_TimerCDCtrl_WriteByte(void)
                    975: {
                    976:  unsigned short old_tcdcr;
                    977:  old_tcdcr = MFP_TCDCR;             /* Remember old control state */
                    978:  MFP_TCDCR = STRam[0xfffa1d];       /* Store new one */
                    979:  if( (MFP_TCDCR^old_tcdcr)&0x70 )   /* Check if Timer C control changed */
                    980:    MFP_StartTimerC();               /* Reset timers if need to */
                    981:  if( (MFP_TCDCR^old_tcdcr)&0x07 )   /* Check if Timer D control changed */
                    982:    MFP_StartTimerD();               /* Reset timers if need to */
                    983: }
                    984: 
1.1.1.2   root      985: /* INTERCEPT_TIMERA_DATA(0xfffa1f byte) */
1.1       root      986: void Intercept_TimerAData_WriteByte(void)
                    987: {
                    988:  MFP_TADR = STRam[0xfffa1f];        /* Store into data register */
                    989:  if( MFP_TACR==0 )                  /* Now check if timer is running - if so do not set */
                    990:   {
                    991:    MFP_TA_MAINCOUNTER = MFP_TADR;   /* Timer is off, store to main counter */
                    992:    MFP_StartTimerA();               /* Add our interrupt */
                    993:   }
                    994: }
                    995: 
1.1.1.2   root      996: /* INTERCEPT_TIMERB_DATA(0xfffa21 byte) */
1.1       root      997: void Intercept_TimerBData_WriteByte(void)
                    998: {
                    999:  MFP_TBDR = STRam[0xfffa21];        /* Store into data register */
                   1000:  if( MFP_TBCR==0 )                  /* Now check if timer is running - if so do not set */
                   1001:   {
                   1002:    MFP_TB_MAINCOUNTER = MFP_TBDR;   /* Timer is off, store to main counter */
                   1003:    MFP_StartTimerB();               /* Add our interrupt */
                   1004:   }
                   1005: }
                   1006: 
1.1.1.2   root     1007: /* INTERCEPT_TIMERC_DATA(0xfffa23 byte) */
1.1       root     1008: void Intercept_TimerCData_WriteByte(void)
                   1009: {
                   1010:  MFP_TCDR = STRam[0xfffa23];        /* Store into data register */
                   1011:  if( (MFP_TCDCR&0x70)==0 )          /* Now check if timer is running - if so do not set */
                   1012:   {
                   1013:    MFP_StartTimerC();               /* Add our interrupt */
                   1014:   }
                   1015: }
                   1016: 
1.1.1.2   root     1017: /* INTERCEPT_TIMERD_DATA(0xfffa25 byte) */
1.1       root     1018: void Intercept_TimerDData_WriteByte(void)
                   1019: {
                   1020:  MFP_TDDR = STRam[0xfffa25];        /* Store into data register */
                   1021:  if( (MFP_TCDCR&0x07)==0 )          /* Now check if timer is running - if so do not set */
                   1022:   {
                   1023:    MFP_StartTimerD();               /* Add our interrupt */
                   1024:   }
                   1025: }
                   1026: 
1.1.1.2   root     1027: /* INTERCEPT_KEYBOARDCONTROL(0xfffc00 byte) */
1.1       root     1028: void Intercept_KeyboardControl_WriteByte(void)
                   1029: {
                   1030:   /* Nothing... */
                   1031: }
                   1032: 
1.1.1.2   root     1033: /* INTERCEPT_KEYBOARDDATA(0xfffc02 byte) */
1.1       root     1034: void Intercept_KeyboardData_WriteByte(void)
                   1035: {
                   1036:  IKBD_SendByteToKeyboardProcessor( STRam[0xfffc02] );  /* Pass our byte to the keyboard processor */
                   1037: }
                   1038: 
1.1.1.2   root     1039: /* INTERCEPT_MIDICONTROL(0xfffc04 byte) */
1.1       root     1040: void Intercept_MidiControl_WriteByte(void)
                   1041: {
                   1042:   /* Nothing... */
                   1043: }
                   1044: 
1.1.1.2   root     1045: /* INTERCEPT_MIDIDATA(0xfffc06 byte) */
1.1       root     1046: void Intercept_MidiData_WriteByte(void)
                   1047: {
                   1048:   /* Nothing... */
                   1049: }
                   1050: 
                   1051: 
1.1.1.2   root     1052: 
                   1053: /* Address space for Bus Error in hardware mapping */
1.1       root     1054: INTERCEPT_ADDRESSRANGE InterceptBusErrors[] = {
                   1055:   0xff8a00,0xff8a3e,        /* Blitter */
                   1056:   0xff8900,0xff8960,        /* DMA Sound/MicroWire */
1.1.1.4 ! root     1057:   0xff8400,0xff85fe,        /* TT Palette (EmuTOS depends on this) */
        !          1058:   0xff8280,0xff82c4,        /* Falcon VIDEL (again for EmuTOS) */
1.1       root     1059: 
                   1060:   0,0  /* term */
                   1061: };
                   1062: 
                   1063: 
1.1.1.2   root     1064: /*-------------------------------------------------------------------------*/
                   1065: /*
                   1066:   Jump to the BusError handler with the correct bus address
                   1067: */
                   1068: void Intercept_BusError(void)
                   1069: {
                   1070:   M68000_BusError(BusAddressLocation);
                   1071: }
                   1072: 
1.1       root     1073: 
                   1074: /*-------------------------------------------------------------------------*/
                   1075: /*
                   1076:   Modify 'intercept' tables to cause Bus Errors on addres to un-mapped
                   1077:   hardware space (Wing Of Death addresses Blitter space which causes
                   1078:   BusError on STfm)
                   1079: */
                   1080: void Intercept_ModifyTablesForBusErrors(void)
                   1081: {
                   1082:   unsigned long *pInterceptList;
                   1083:   unsigned int Address;
                   1084:   int i=0;
                   1085: 
1.1.1.2   root     1086:   /* Set routine list */
1.1       root     1087:   pInterceptList = pCurrentInterceptWorkspace;
1.1.1.2   root     1088:   *pCurrentInterceptWorkspace++ = (unsigned long)Intercept_BusError;
1.1       root     1089:   *pCurrentInterceptWorkspace++ = 0L;
                   1090: 
1.1.1.2   root     1091:   /* Set all 'no-mans-land' entries */
1.1       root     1092:   while(InterceptBusErrors[i].Start_Address!=0) {
1.1.1.2   root     1093:     /* Set 'no-mans-land' table */
1.1       root     1094:     for(Address=InterceptBusErrors[i].Start_Address; Address<InterceptBusErrors[i].End_Address; Address++) {
1.1.1.2   root     1095:       /* For 'read' */
1.1       root     1096:       pInterceptReadByteTable[Address-0xff8000] = pInterceptList;
                   1097:       pInterceptReadWordTable[Address-0xff8000] = pInterceptList;
                   1098:       pInterceptReadLongTable[Address-0xff8000] = pInterceptList;
1.1.1.2   root     1099:       /* and 'write' */
1.1       root     1100:       pInterceptWriteByteTable[Address-0xff8000] = pInterceptList;
                   1101:       pInterceptWriteWordTable[Address-0xff8000] = pInterceptList;
                   1102:       pInterceptWriteLongTable[Address-0xff8000] = pInterceptList;
                   1103:     }
                   1104: 
                   1105:     i++;
                   1106:   }
                   1107: }
                   1108: 
1.1.1.2   root     1109: 
                   1110: 
1.1       root     1111: #ifdef CHECK_FOR_NO_MANS_LAND
                   1112: 
1.1.1.2   root     1113: /* List of hardware addresses which are 'no-man's-land', ie not connected on ST */
                   1114: /* NOTE PSG is mirror'd in range 0xff8004 to 0xff8900 */
1.1       root     1115: INTERCEPT_ADDRESSRANGE InterceptNoMansLand[] = {
1.1.1.2   root     1116:   0xff8002,0xff8200,        /* All these are illegal addresses on standard STfm */
1.1       root     1117:   0xff8210,0xff8240,
                   1118:   0xff8262,0xff8600,
                   1119:   0xff860e,0xff8800,
                   1120:   0xff8900,0xfffa00,
                   1121:   0xfffa30,0xfffc00,
                   1122:   0xfffc20,0x1000000,
                   1123: 
1.1.1.2   root     1124:   0,0  /*term*/
1.1       root     1125: };
                   1126: 
1.1.1.2   root     1127: /*-----------------------------------------------------------------------*/
1.1       root     1128: /*
1.1.1.2   root     1129:   Intercept function used on all non-documented hardware registers.
                   1130:   Used to help debugging
1.1       root     1131: */
                   1132: void Intercept_NoMansLand_ReadWrite(void)
                   1133: {
1.1.1.2   root     1134:   fprintf(stderr,"NoMansLand_ReadWrite at address $%lx , PC=$%lx\n",
                   1135:           BusAddressLocation, PC);
1.1       root     1136: }
                   1137: 
1.1.1.2   root     1138: /*----------------------------------------------------------------------- */
1.1       root     1139: /*
                   1140:   Modify 'intercept' tables to check for access into 'no-mans-land', ie unknown hardware locations
                   1141: */
                   1142: void Intercept_ModifyTablesForNoMansLand(void)
                   1143: {
                   1144:   unsigned long *pInterceptList;
                   1145:   unsigned int Address;
                   1146:   int i=0;
                   1147: 
1.1.1.2   root     1148:   /* Set routine list */
1.1       root     1149:   pInterceptList = pCurrentInterceptWorkspace;
                   1150:   *pCurrentInterceptWorkspace++ = (unsigned long)Intercept_NoMansLand_ReadWrite;
                   1151:   *pCurrentInterceptWorkspace++ = NULL;
                   1152: 
1.1.1.2   root     1153:   /* Set all 'no-mans-land' entries */
1.1       root     1154:   while(InterceptNoMansLand[i].Start_Address!=0) {
1.1.1.2   root     1155:     /* Set 'no-mans-land' table */
1.1       root     1156:     for(Address=InterceptNoMansLand[i].Start_Address; Address<InterceptNoMansLand[i].End_Address; Address++) {
1.1.1.2   root     1157:       /* For 'read' */
1.1       root     1158:       pInterceptReadByteTable[Address-0xff8000] = pInterceptList;
                   1159:       pInterceptReadWordTable[Address-0xff8000] = pInterceptList;
                   1160:       pInterceptReadLongTable[Address-0xff8000] = pInterceptList;
1.1.1.2   root     1161:       /* and 'write' */
1.1       root     1162:       pInterceptWriteByteTable[Address-0xff8000] = pInterceptList;
                   1163:       pInterceptWriteWordTable[Address-0xff8000] = pInterceptList;
                   1164:       pInterceptWriteLongTable[Address-0xff8000] = pInterceptList;
                   1165:     }
                   1166: 
                   1167:     i++;
                   1168:   }
                   1169: }
                   1170: 
1.1.1.2   root     1171: #endif  /*CHECK_FOR_NO_MANS_LAND*/
1.1       root     1172: 

unix.superglobalmegacorp.com

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