Annotation of hatari/src/int.c, revision 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.