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

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.6 ! root       19: char Int_rcsid[] = "Hatari $Id: int.c,v 1.9 2005/08/06 12:32:09 thothy Exp $";
1.1       root       20: 
                     21: #include "main.h"
1.1.1.6 ! root       22: #include "dmaSnd.h"
1.1       root       23: #include "ikbd.h"
                     24: #include "int.h"
                     25: #include "m68000.h"
                     26: #include "memorySnapShot.h"
                     27: #include "mfp.h"
                     28: #include "sound.h"
                     29: #include "video.h"
                     30: 
1.1.1.3   root       31: 
1.1       root       32: /* List of possible interrupt handlers to be store in 'PendingInterruptTable', used for 'MemorySnapShot' */
1.1.1.3   root       33: void *pIntHandlerFunctions[] =
                     34: {
1.1       root       35:   NULL,
                     36:   Video_InterruptHandler_VBL,
                     37:   Video_InterruptHandler_HBL,
                     38:   Video_InterruptHandler_EndLine,
                     39:   MFP_InterruptHandler_TimerA,
                     40:   MFP_InterruptHandler_TimerB,
                     41:   MFP_InterruptHandler_TimerC,
                     42:   MFP_InterruptHandler_TimerD,
                     43:   IKBD_InterruptHandler_ResetTimer,
                     44:   IKBD_InterruptHandler_ACIA,
1.1.1.6 ! root       45:   DmaSnd_InterruptHandler,
1.1       root       46:   NULL
                     47: };
                     48: 
                     49: INTERRUPTHANDLER InterruptHandlers[MAX_INTERRUPTS];
                     50: int nCyclesOver=0;
                     51: int nFrameCyclesOver=0;
                     52: int ActiveInterrupt=0;
                     53: 
1.1.1.2   root       54: 
                     55: /*-----------------------------------------------------------------------*/
1.1       root       56: /*
                     57:   Reset interrupts, handlers
                     58: */
                     59: void Int_Reset(void)
                     60: {
                     61:   int i;
                     62: 
1.1.1.2   root       63:   /* Reset counts */
1.1       root       64:   PendingInterruptCount = 0;
                     65:   nCyclesOver = 0;
                     66: 
1.1.1.2   root       67:   /* Reset interrupt table */
1.1       root       68:   for(i=0; i<MAX_INTERRUPTS; i++) {
                     69:     InterruptHandlers[i].bUsed = FALSE;
                     70:     InterruptHandlers[i].pFunction = pIntHandlerFunctions[i];
                     71:   }
                     72: }
                     73: 
1.1.1.2   root       74: 
                     75: /*-----------------------------------------------------------------------*/
1.1       root       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: 
1.1.1.2   root       83:   /* Save/Restore details */
1.1       root       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) {
1.1.1.2   root       88:       /* Convert function to ID */
1.1       root       89:       ID = Int_HandlerFunctionToID(InterruptHandlers[i].pFunction);
                     90:       MemorySnapShot_Store(&ID,sizeof(int));
                     91:     }
                     92:     else {
1.1.1.2   root       93:       /* Convert ID to function */
1.1       root       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: 
1.1.1.2   root      102: 
                    103: /*-----------------------------------------------------------------------*/
1.1       root      104: /*
                    105:   Convert interrupt handler function pointer to ID, used for saving
                    106: */
                    107: int Int_HandlerFunctionToID(void *pHandlerFunction)
                    108: {
                    109:   int i;
                    110: 
1.1.1.2   root      111:   /* Is NULL, return ID 0 */
1.1       root      112:   if (pHandlerFunction==NULL)
                    113:     return(0);
                    114: 
1.1.1.2   root      115:   /* Scan for function match */
1.1       root      116:   for(i=1; i<MAX_INTERRUPTS; i++) {
                    117:     if (pIntHandlerFunctions[i]==pHandlerFunction)
                    118:       return(i);
                    119:   }
                    120:   
1.1.1.2   root      121:   /* Didn't find one! Oops */
1.1       root      122:   return(0);
                    123: }
                    124: 
1.1.1.2   root      125: 
                    126: /*-----------------------------------------------------------------------*/
1.1       root      127: /*
                    128:   Convert ID back into interrupt handler function, used for restoring
                    129: */
                    130: void *Int_IDToHandlerFunction(int ID)
                    131: {
1.1.1.2   root      132:   /* Get function pointer */
1.1       root      133:   return( pIntHandlerFunctions[ID] );
                    134: }
                    135: 
1.1.1.2   root      136: 
                    137: /*-----------------------------------------------------------------------*/
1.1       root      138: /*
                    139:   Return number of clock cycles into retrace
                    140: */
                    141: int Int_FindFrameCycles(void)
                    142: {
                    143:   return( nFrameCyclesOver + (InterruptHandlers[ActiveInterrupt].Cycles-PendingInterruptCount) );
                    144: }
                    145: 
1.1.1.2   root      146: 
                    147: /*-----------------------------------------------------------------------*/
1.1       root      148: /*
                    149:   Find next interrupt to occur, and store to global variables for decrement in instruction decode loop
                    150: */
                    151: void Int_SetNewInterrupt(void)
                    152: {
                    153:   int LowestCycleCount=999999,LowestInterrupt=0;
                    154:   int i;
                    155: 
1.1.1.2   root      156:   /* Find next interrupt to go off */
1.1       root      157:   for(i=0; i<MAX_INTERRUPTS; i++) {
1.1.1.2   root      158:     /* Is interrupt pending? */
1.1       root      159:     if (InterruptHandlers[i].bUsed) {
                    160:       if (InterruptHandlers[i].Cycles<LowestCycleCount) {
                    161:         LowestCycleCount = InterruptHandlers[i].Cycles;
                    162:         LowestInterrupt = i;
                    163:       }
                    164:     }
                    165:   }
1.1.1.2   root      166: 
                    167:   /* Set new counts, active interrupt */
1.1       root      168:   PendingInterruptCount = (short int)InterruptHandlers[LowestInterrupt].Cycles;
                    169:   PendingInterruptFunction = InterruptHandlers[LowestInterrupt].pFunction;
                    170:   ActiveInterrupt = LowestInterrupt;
                    171: 
                    172: }
                    173: 
1.1.1.2   root      174: 
                    175: /*-----------------------------------------------------------------------*/
1.1       root      176: /*
                    177:   Adjust all interrupt timings, MUST call Int_SetNewInterrupt after this
                    178: */
1.1.1.3   root      179: static void Int_UpdateInterrupt(void)
1.1       root      180: {
                    181:   int CycleSubtract;
                    182:   int i;
                    183: 
1.1.1.2   root      184:   /* Find out how many cycles we went over (<=0) */
1.1       root      185:   nCyclesOver = PendingInterruptCount;
1.1.1.2   root      186:   /* Calculate how many cycles have passed, included time we went over */
1.1       root      187:   CycleSubtract = InterruptHandlers[ActiveInterrupt].Cycles-nCyclesOver;
                    188: 
1.1.1.2   root      189:   /* Adjust table */
1.1       root      190:   for(i=0; i<MAX_INTERRUPTS; i++) {
                    191:     if (InterruptHandlers[i].bUsed)
                    192:       InterruptHandlers[i].Cycles -= CycleSubtract;
                    193:   }
                    194:   nFrameCyclesOver += CycleSubtract;
                    195: }
                    196: 
1.1.1.2   root      197: 
                    198: /*-----------------------------------------------------------------------*/
1.1       root      199: /*
                    200:   Adjust all interrupt timings as 'ActiveInterrupt' has occured, and remove from active list
                    201: */
                    202: void Int_AcknowledgeInterrupt(void)
                    203: {
1.1.1.2   root      204:   /* Update list cycle counts */
1.1       root      205:   Int_UpdateInterrupt();
                    206: 
1.1.1.2   root      207:   /* Disable interrupt entry which has just occured */
1.1       root      208:   InterruptHandlers[ActiveInterrupt].bUsed = FALSE;
                    209: 
1.1.1.2   root      210:   /* Set new */
1.1       root      211:   Int_SetNewInterrupt();
                    212: }
                    213: 
1.1.1.2   root      214: 
                    215: /*-----------------------------------------------------------------------*/
1.1       root      216: /*
                    217:   Add interrupt from time last one occurred
                    218: */
                    219: void Int_AddAbsoluteInterrupt(int CycleTime, int Handler)
                    220: {
                    221:   InterruptHandlers[Handler].bUsed = TRUE;
                    222:   InterruptHandlers[Handler].Cycles = CycleTime + nCyclesOver;
                    223: 
1.1.1.2   root      224:   /* Set new */
1.1       root      225:   Int_SetNewInterrupt();
                    226: }
                    227: 
1.1.1.2   root      228: 
                    229: /*-----------------------------------------------------------------------*/
1.1       root      230: /*
                    231:   Add interrupt to occur from now
                    232: */
                    233: void Int_AddRelativeInterrupt(int CycleTime, int Handler)
                    234: {
                    235:   InterruptHandlers[Handler].bUsed = TRUE;
                    236:   InterruptHandlers[Handler].Cycles = CycleTime;
                    237: 
1.1.1.2   root      238:   /* Set new */
1.1       root      239:   Int_SetNewInterrupt();
                    240: }
                    241: 
1.1.1.2   root      242: 
                    243: /*-----------------------------------------------------------------------*/
1.1       root      244: /*
                    245:   Remove a pending interrupt from our table
                    246: */
                    247: void Int_RemovePendingInterrupt(int Handler)
                    248: {
1.1.1.2   root      249:   /* Stop interrupt */
1.1       root      250:   InterruptHandlers[Handler].bUsed = FALSE;
                    251: 
1.1.1.2   root      252:   /* Update list cycle counts */
1.1       root      253:   Int_UpdateInterrupt();
1.1.1.2   root      254:   /* Set new */
1.1       root      255:   Int_SetNewInterrupt();
                    256: }
                    257: 
1.1.1.2   root      258: 
                    259: /*-----------------------------------------------------------------------*/
1.1       root      260: /*
                    261:   Return TRUE if interrupt is active in list
                    262: */
                    263: BOOL Int_InterruptActive(int Handler)
                    264: {
1.1.1.2   root      265:   /* Is timer active? */
1.1       root      266:   if (InterruptHandlers[Handler].bUsed)
                    267:     return(TRUE);
                    268: 
                    269:   return(FALSE);
                    270: }
                    271: 
1.1.1.2   root      272: 
                    273: /*-----------------------------------------------------------------------*/
1.1       root      274: /*
                    275:   Return cycles passed for an interrupt handler
                    276: */
                    277: int Int_FindCyclesPassed(int Handler)
                    278: {
                    279:   int CyclesPassed, CyclesFromLastInterrupt;
                    280: 
                    281:   CyclesFromLastInterrupt = (int)InterruptHandlers[ActiveInterrupt].Cycles-PendingInterruptCount;
                    282:   CyclesPassed = ((int)InterruptHandlers[Handler].Cycles-CyclesFromLastInterrupt);
                    283: 
                    284:   return(CyclesPassed);
                    285: }

unix.superglobalmegacorp.com

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