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

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: 
                     56: //-----------------------------------------------------------------------
                     57: /*
                     58:   Reset interrupts, handlers
                     59: */
                     60: void Int_Reset(void)
                     61: {
                     62:   int i;
                     63: 
                     64:   // Reset counts
                     65:   PendingInterruptCount = 0;
                     66:   nCyclesOver = 0;
                     67: 
                     68:   // Reset interrupt table
                     69:   for(i=0; i<MAX_INTERRUPTS; i++) {
                     70:     InterruptHandlers[i].bUsed = FALSE;
                     71:     InterruptHandlers[i].pFunction = pIntHandlerFunctions[i];
                     72:   }
                     73: }
                     74: 
                     75: //-----------------------------------------------------------------------
                     76: /*
                     77:   Save/Restore snapshot of local variables('MemorySnapShot_Store' handles type)
                     78: */
                     79: void Int_MemorySnapShot_Capture(BOOL bSave)
                     80: {
                     81:   int i,ID;
                     82: 
                     83:   // Save/Restore details
                     84:   for(i=0; i<MAX_INTERRUPTS; i++) {
                     85:     MemorySnapShot_Store(&InterruptHandlers[i].bUsed,sizeof(InterruptHandlers[i].bUsed));
                     86:     MemorySnapShot_Store(&InterruptHandlers[i].Cycles,sizeof(InterruptHandlers[i].Cycles));
                     87:     if (bSave) {
                     88:       // Convert function to ID
                     89:       ID = Int_HandlerFunctionToID(InterruptHandlers[i].pFunction);
                     90:       MemorySnapShot_Store(&ID,sizeof(int));
                     91:     }
                     92:     else {
                     93:       // Convert ID to function
                     94:       MemorySnapShot_Store(&ID,sizeof(int));
                     95:       InterruptHandlers[i].pFunction = Int_IDToHandlerFunction(ID);
                     96:     }
                     97:   }
                     98:   MemorySnapShot_Store(&nCyclesOver,sizeof(nCyclesOver));
                     99:   MemorySnapShot_Store(&nFrameCyclesOver,sizeof(nFrameCyclesOver));
                    100: }
                    101: 
                    102: //-----------------------------------------------------------------------
                    103: /*
                    104:   Convert interrupt handler function pointer to ID, used for saving
                    105: */
                    106: int Int_HandlerFunctionToID(void *pHandlerFunction)
                    107: {
                    108:   int i;
                    109: 
                    110:   // Is NULL, return ID 0
                    111:   if (pHandlerFunction==NULL)
                    112:     return(0);
                    113: 
                    114:   // Scan for function match
                    115:   for(i=1; i<MAX_INTERRUPTS; i++) {
                    116:     if (pIntHandlerFunctions[i]==pHandlerFunction)
                    117:       return(i);
                    118:   }
                    119:   
                    120:   // Didn't find one! Oops
                    121:   return(0);
                    122: }
                    123: 
                    124: //-----------------------------------------------------------------------
                    125: /*
                    126:   Convert ID back into interrupt handler function, used for restoring
                    127: */
                    128: void *Int_IDToHandlerFunction(int ID)
                    129: {
                    130:   // Get function pointer
                    131:   return( pIntHandlerFunctions[ID] );
                    132: }
                    133: 
                    134: //-----------------------------------------------------------------------
                    135: /*
                    136:   Return number of clock cycles into retrace
                    137: */
                    138: int Int_FindFrameCycles(void)
                    139: {
                    140:   return( nFrameCyclesOver + (InterruptHandlers[ActiveInterrupt].Cycles-PendingInterruptCount) );
                    141: }
                    142: 
                    143: //-----------------------------------------------------------------------
                    144: /*
                    145:   Find next interrupt to occur, and store to global variables for decrement in instruction decode loop
                    146: */
                    147: void Int_SetNewInterrupt(void)
                    148: {
                    149:   int LowestCycleCount=999999,LowestInterrupt=0;
                    150:   int i;
                    151: 
                    152:   // Find next interrupt to go off
                    153:   for(i=0; i<MAX_INTERRUPTS; i++) {
                    154:     // Is interrupt pending?
                    155:     if (InterruptHandlers[i].bUsed) {
                    156: //fprintf(stderr, "Active Interrupt: %i with cycles: %i\n", i, InterruptHandlers[i].Cycles);
                    157:       if (InterruptHandlers[i].Cycles<LowestCycleCount) {
                    158:         LowestCycleCount = InterruptHandlers[i].Cycles;
                    159:         LowestInterrupt = i;
                    160:       }
                    161:     }
                    162:   }
                    163: //if(LowestCycleCount!=999999) sleep(1);
                    164:   // Set new counts, active interrupt
                    165:   PendingInterruptCount = (short int)InterruptHandlers[LowestInterrupt].Cycles;
                    166:   PendingInterruptFunction = InterruptHandlers[LowestInterrupt].pFunction;
                    167:   ActiveInterrupt = LowestInterrupt;
                    168: 
                    169: }
                    170: 
                    171: //-----------------------------------------------------------------------
                    172: /*
                    173:   Adjust all interrupt timings, MUST call Int_SetNewInterrupt after this
                    174: */
                    175: void Int_UpdateInterrupt(void)
                    176: {
                    177:   int CycleSubtract;
                    178:   int i;
                    179: 
                    180:   // Find out how many cycles we went over (<=0)
                    181:   nCyclesOver = PendingInterruptCount;
                    182:   // Calculate how many cycles have passed, included time we went over
                    183:   CycleSubtract = InterruptHandlers[ActiveInterrupt].Cycles-nCyclesOver;
                    184: 
                    185:   // Adjust table
                    186:   for(i=0; i<MAX_INTERRUPTS; i++) {
                    187:     if (InterruptHandlers[i].bUsed)
                    188:       InterruptHandlers[i].Cycles -= CycleSubtract;
                    189:   }
                    190:   nFrameCyclesOver += CycleSubtract;
                    191: }
                    192: 
                    193: //-----------------------------------------------------------------------
                    194: /*
                    195:   Adjust all interrupt timings as 'ActiveInterrupt' has occured, and remove from active list
                    196: */
                    197: void Int_AcknowledgeInterrupt(void)
                    198: {
                    199:   // Update list cycle counts
                    200:   Int_UpdateInterrupt();
                    201: 
                    202:   // Disable interrupt entry which has just occured
                    203:   InterruptHandlers[ActiveInterrupt].bUsed = FALSE;
                    204: 
                    205:   // Set new
                    206:   Int_SetNewInterrupt();
                    207: }
                    208: 
                    209: //-----------------------------------------------------------------------
                    210: /*
                    211:   Add interrupt from time last one occurred
                    212: */
                    213: void Int_AddAbsoluteInterrupt(int CycleTime, int Handler)
                    214: {
                    215: //fprintf(stderr, "Int_AddAbsoluteInterrupt %i\n", Handler);
                    216:   InterruptHandlers[Handler].bUsed = TRUE;
                    217:   InterruptHandlers[Handler].Cycles = CycleTime + nCyclesOver;
                    218: 
                    219:   // Set new
                    220:   Int_SetNewInterrupt();
                    221: }
                    222: 
                    223: //-----------------------------------------------------------------------
                    224: /*
                    225:   Add interrupt to occur from now
                    226: */
                    227: void Int_AddRelativeInterrupt(int CycleTime, int Handler)
                    228: {
                    229: //fprintf(stderr, "Int_AddRelativeInterrupt %i\n", Handler);
                    230:   InterruptHandlers[Handler].bUsed = TRUE;
                    231:   InterruptHandlers[Handler].Cycles = CycleTime;
                    232: 
                    233:   // Set new
                    234:   Int_SetNewInterrupt();
                    235: }
                    236: 
                    237: //-----------------------------------------------------------------------
                    238: /*
                    239:   Remove a pending interrupt from our table
                    240: */
                    241: void Int_RemovePendingInterrupt(int Handler)
                    242: {
                    243:   // Stop interrupt
                    244:   InterruptHandlers[Handler].bUsed = FALSE;
                    245: 
                    246:   // Update list cycle counts
                    247:   Int_UpdateInterrupt();
                    248:   // Set new
                    249:   Int_SetNewInterrupt();
                    250: }
                    251: 
                    252: //-----------------------------------------------------------------------
                    253: /*
                    254:   Return TRUE if interrupt is active in list
                    255: */
                    256: BOOL Int_InterruptActive(int Handler)
                    257: {
                    258:   // Is timer active?
                    259:   if (InterruptHandlers[Handler].bUsed)
                    260:     return(TRUE);
                    261: 
                    262:   return(FALSE);
                    263: }
                    264: 
                    265: //-----------------------------------------------------------------------
                    266: /*
                    267:   Return cycles passed for an interrupt handler
                    268: */
                    269: int Int_FindCyclesPassed(int Handler)
                    270: {
                    271:   int CyclesPassed, CyclesFromLastInterrupt;
                    272: 
                    273:   CyclesFromLastInterrupt = (int)InterruptHandlers[ActiveInterrupt].Cycles-PendingInterruptCount;
                    274:   CyclesPassed = ((int)InterruptHandlers[Handler].Cycles-CyclesFromLastInterrupt);
                    275: 
                    276:   return(CyclesPassed);
                    277: }

unix.superglobalmegacorp.com

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