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

1.1       root        1: /*
                      2:   Hatari
                      3: 
                      4:   This code handles our interrupt table. So we do not need to test for every possible
                      5:   interrupt we add any pending interrupts into a table. We then scan the list if used
                      6:   entries in the table and copy the one with the least cycle count into the global
                      7:   'PendingInterruptCount' variable. This is then decremented by the execution loop -
                      8:   rather than decrement each and every entry (as the others cannot occur before this one)
                      9:   We have two methods of adding interrupts; Absolute and Relative. Absolute will set values
                     10:   from the time of the previous interrupt(eg, add HBL every 512 cycles), and Relative
                     11:   will add from the current cycle time.
                     12:   Note that interrupt may occur 'late'. Ie, if an interrupt is due in 4 cycles time but
                     13:   the current instruction takes 20 cycles we will be 16 cycles late - this is handled in
                     14:   the adjust functions.
                     15: */
                     16: 
                     17: #include "main.h"
                     18: #include "debug.h"
                     19: #include "decode.h"
                     20: #include "ikbd.h"
                     21: #include "int.h"
                     22: #include "m68000.h"
                     23: #include "memAlloc.h"
                     24: #include "memorySnapShot.h"
                     25: #include "misc.h"
                     26: #include "mfp.h"
                     27: #include "sound.h"
                     28: #include "video.h"
                     29: 
                     30: /* List of possible interrupt handlers to be store in 'PendingInterruptTable', used for 'MemorySnapShot' */
                     31: void *pIntHandlerFunctions[] = {
                     32:   NULL,
                     33: 
                     34: #ifdef USE_DEBUGGER
                     35:   InterruptHandler_Debugger,
                     36:   InterruptHandler_SingleStep,
                     37: #endif  /* USE_DEBUGGER */
                     38:   Video_InterruptHandler_VBL,
                     39:   Video_InterruptHandler_VBL_Pending,
                     40:   Video_InterruptHandler_HBL,
                     41:   Video_InterruptHandler_EndLine,
                     42:   MFP_InterruptHandler_TimerA,
                     43:   MFP_InterruptHandler_TimerB,
                     44:   MFP_InterruptHandler_TimerC,
                     45:   MFP_InterruptHandler_TimerD,
                     46:   IKBD_InterruptHandler_ResetTimer,
                     47:   IKBD_InterruptHandler_ACIA,
                     48:   NULL
                     49: };
                     50: 
                     51: INTERRUPTHANDLER InterruptHandlers[MAX_INTERRUPTS];
                     52: int nCyclesOver=0;
                     53: int nFrameCyclesOver=0;
                     54: int ActiveInterrupt=0;
                     55: 
1.1.1.2 ! root       56: 
        !            57: /*-----------------------------------------------------------------------*/
1.1       root       58: /*
                     59:   Reset interrupts, handlers
                     60: */
                     61: void Int_Reset(void)
                     62: {
                     63:   int i;
                     64: 
1.1.1.2 ! root       65:   /* Reset counts */
1.1       root       66:   PendingInterruptCount = 0;
                     67:   nCyclesOver = 0;
                     68: 
1.1.1.2 ! root       69:   /* Reset interrupt table */
1.1       root       70:   for(i=0; i<MAX_INTERRUPTS; i++) {
                     71:     InterruptHandlers[i].bUsed = FALSE;
                     72:     InterruptHandlers[i].pFunction = pIntHandlerFunctions[i];
                     73:   }
                     74: }
                     75: 
1.1.1.2 ! root       76: 
        !            77: /*-----------------------------------------------------------------------*/
1.1       root       78: /*
                     79:   Save/Restore snapshot of local variables('MemorySnapShot_Store' handles type)
                     80: */
                     81: void Int_MemorySnapShot_Capture(BOOL bSave)
                     82: {
                     83:   int i,ID;
                     84: 
1.1.1.2 ! root       85:   /* Save/Restore details */
1.1       root       86:   for(i=0; i<MAX_INTERRUPTS; i++) {
                     87:     MemorySnapShot_Store(&InterruptHandlers[i].bUsed,sizeof(InterruptHandlers[i].bUsed));
                     88:     MemorySnapShot_Store(&InterruptHandlers[i].Cycles,sizeof(InterruptHandlers[i].Cycles));
                     89:     if (bSave) {
1.1.1.2 ! root       90:       /* Convert function to ID */
1.1       root       91:       ID = Int_HandlerFunctionToID(InterruptHandlers[i].pFunction);
                     92:       MemorySnapShot_Store(&ID,sizeof(int));
                     93:     }
                     94:     else {
1.1.1.2 ! root       95:       /* Convert ID to function */
1.1       root       96:       MemorySnapShot_Store(&ID,sizeof(int));
                     97:       InterruptHandlers[i].pFunction = Int_IDToHandlerFunction(ID);
                     98:     }
                     99:   }
                    100:   MemorySnapShot_Store(&nCyclesOver,sizeof(nCyclesOver));
                    101:   MemorySnapShot_Store(&nFrameCyclesOver,sizeof(nFrameCyclesOver));
                    102: }
                    103: 
1.1.1.2 ! root      104: 
        !           105: /*-----------------------------------------------------------------------*/
1.1       root      106: /*
                    107:   Convert interrupt handler function pointer to ID, used for saving
                    108: */
                    109: int Int_HandlerFunctionToID(void *pHandlerFunction)
                    110: {
                    111:   int i;
                    112: 
1.1.1.2 ! root      113:   /* Is NULL, return ID 0 */
1.1       root      114:   if (pHandlerFunction==NULL)
                    115:     return(0);
                    116: 
1.1.1.2 ! root      117:   /* Scan for function match */
1.1       root      118:   for(i=1; i<MAX_INTERRUPTS; i++) {
                    119:     if (pIntHandlerFunctions[i]==pHandlerFunction)
                    120:       return(i);
                    121:   }
                    122:   
1.1.1.2 ! root      123:   /* Didn't find one! Oops */
1.1       root      124:   return(0);
                    125: }
                    126: 
1.1.1.2 ! root      127: 
        !           128: /*-----------------------------------------------------------------------*/
1.1       root      129: /*
                    130:   Convert ID back into interrupt handler function, used for restoring
                    131: */
                    132: void *Int_IDToHandlerFunction(int ID)
                    133: {
1.1.1.2 ! root      134:   /* Get function pointer */
1.1       root      135:   return( pIntHandlerFunctions[ID] );
                    136: }
                    137: 
1.1.1.2 ! root      138: 
        !           139: /*-----------------------------------------------------------------------*/
1.1       root      140: /*
                    141:   Return number of clock cycles into retrace
                    142: */
                    143: int Int_FindFrameCycles(void)
                    144: {
                    145:   return( nFrameCyclesOver + (InterruptHandlers[ActiveInterrupt].Cycles-PendingInterruptCount) );
                    146: }
                    147: 
1.1.1.2 ! root      148: 
        !           149: /*-----------------------------------------------------------------------*/
1.1       root      150: /*
                    151:   Find next interrupt to occur, and store to global variables for decrement in instruction decode loop
                    152: */
                    153: void Int_SetNewInterrupt(void)
                    154: {
                    155:   int LowestCycleCount=999999,LowestInterrupt=0;
                    156:   int i;
                    157: 
1.1.1.2 ! root      158:   /* Find next interrupt to go off */
1.1       root      159:   for(i=0; i<MAX_INTERRUPTS; i++) {
1.1.1.2 ! root      160:     /* Is interrupt pending? */
1.1       root      161:     if (InterruptHandlers[i].bUsed) {
                    162:       if (InterruptHandlers[i].Cycles<LowestCycleCount) {
                    163:         LowestCycleCount = InterruptHandlers[i].Cycles;
                    164:         LowestInterrupt = i;
                    165:       }
                    166:     }
                    167:   }
1.1.1.2 ! root      168: 
        !           169:   /* Set new counts, active interrupt */
1.1       root      170:   PendingInterruptCount = (short int)InterruptHandlers[LowestInterrupt].Cycles;
                    171:   PendingInterruptFunction = InterruptHandlers[LowestInterrupt].pFunction;
                    172:   ActiveInterrupt = LowestInterrupt;
                    173: 
                    174: }
                    175: 
1.1.1.2 ! root      176: 
        !           177: /*-----------------------------------------------------------------------*/
1.1       root      178: /*
                    179:   Adjust all interrupt timings, MUST call Int_SetNewInterrupt after this
                    180: */
                    181: void Int_UpdateInterrupt(void)
                    182: {
                    183:   int CycleSubtract;
                    184:   int i;
                    185: 
1.1.1.2 ! root      186:   /* Find out how many cycles we went over (<=0) */
1.1       root      187:   nCyclesOver = PendingInterruptCount;
1.1.1.2 ! root      188:   /* Calculate how many cycles have passed, included time we went over */
1.1       root      189:   CycleSubtract = InterruptHandlers[ActiveInterrupt].Cycles-nCyclesOver;
                    190: 
1.1.1.2 ! root      191:   /* Adjust table */
1.1       root      192:   for(i=0; i<MAX_INTERRUPTS; i++) {
                    193:     if (InterruptHandlers[i].bUsed)
                    194:       InterruptHandlers[i].Cycles -= CycleSubtract;
                    195:   }
                    196:   nFrameCyclesOver += CycleSubtract;
                    197: }
                    198: 
1.1.1.2 ! root      199: 
        !           200: /*-----------------------------------------------------------------------*/
1.1       root      201: /*
                    202:   Adjust all interrupt timings as 'ActiveInterrupt' has occured, and remove from active list
                    203: */
                    204: void Int_AcknowledgeInterrupt(void)
                    205: {
1.1.1.2 ! root      206:   /* Update list cycle counts */
1.1       root      207:   Int_UpdateInterrupt();
                    208: 
1.1.1.2 ! root      209:   /* Disable interrupt entry which has just occured */
1.1       root      210:   InterruptHandlers[ActiveInterrupt].bUsed = FALSE;
                    211: 
1.1.1.2 ! root      212:   /* Set new */
1.1       root      213:   Int_SetNewInterrupt();
                    214: }
                    215: 
1.1.1.2 ! root      216: 
        !           217: /*-----------------------------------------------------------------------*/
1.1       root      218: /*
                    219:   Add interrupt from time last one occurred
                    220: */
                    221: void Int_AddAbsoluteInterrupt(int CycleTime, int Handler)
                    222: {
                    223:   InterruptHandlers[Handler].bUsed = TRUE;
                    224:   InterruptHandlers[Handler].Cycles = CycleTime + nCyclesOver;
                    225: 
1.1.1.2 ! root      226:   /* Set new */
1.1       root      227:   Int_SetNewInterrupt();
                    228: }
                    229: 
1.1.1.2 ! root      230: 
        !           231: /*-----------------------------------------------------------------------*/
1.1       root      232: /*
                    233:   Add interrupt to occur from now
                    234: */
                    235: void Int_AddRelativeInterrupt(int CycleTime, int Handler)
                    236: {
                    237:   InterruptHandlers[Handler].bUsed = TRUE;
                    238:   InterruptHandlers[Handler].Cycles = CycleTime;
                    239: 
1.1.1.2 ! root      240:   /* Set new */
1.1       root      241:   Int_SetNewInterrupt();
                    242: }
                    243: 
1.1.1.2 ! root      244: 
        !           245: /*-----------------------------------------------------------------------*/
1.1       root      246: /*
                    247:   Remove a pending interrupt from our table
                    248: */
                    249: void Int_RemovePendingInterrupt(int Handler)
                    250: {
1.1.1.2 ! root      251:   /* Stop interrupt */
1.1       root      252:   InterruptHandlers[Handler].bUsed = FALSE;
                    253: 
1.1.1.2 ! root      254:   /* Update list cycle counts */
1.1       root      255:   Int_UpdateInterrupt();
1.1.1.2 ! root      256:   /* Set new */
1.1       root      257:   Int_SetNewInterrupt();
                    258: }
                    259: 
1.1.1.2 ! root      260: 
        !           261: /*-----------------------------------------------------------------------*/
1.1       root      262: /*
                    263:   Return TRUE if interrupt is active in list
                    264: */
                    265: BOOL Int_InterruptActive(int Handler)
                    266: {
1.1.1.2 ! root      267:   /* Is timer active? */
1.1       root      268:   if (InterruptHandlers[Handler].bUsed)
                    269:     return(TRUE);
                    270: 
                    271:   return(FALSE);
                    272: }
                    273: 
1.1.1.2 ! root      274: 
        !           275: /*-----------------------------------------------------------------------*/
1.1       root      276: /*
                    277:   Return cycles passed for an interrupt handler
                    278: */
                    279: int Int_FindCyclesPassed(int Handler)
                    280: {
                    281:   int CyclesPassed, CyclesFromLastInterrupt;
                    282: 
                    283:   CyclesFromLastInterrupt = (int)InterruptHandlers[ActiveInterrupt].Cycles-PendingInterruptCount;
                    284:   CyclesPassed = ((int)InterruptHandlers[Handler].Cycles-CyclesFromLastInterrupt);
                    285: 
                    286:   return(CyclesPassed);
                    287: }

unix.superglobalmegacorp.com

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