|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.