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

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

unix.superglobalmegacorp.com

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