|
|
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 "decode.h" ! 19: #include "int.h" ! 20: #include "m68000.h" ! 21: #include "memAlloc.h" ! 22: #include "misc.h" ! 23: #include "video.h" ! 24: ! 25: /* List of possible interrupt handlers to be store in 'PendingInterruptTable', used for 'MemorySnapShot' */ ! 26: void *pIntHandlerFunctions[] = { ! 27: NULL, ! 28: Video_InterruptHandler_VBL_Pending, ! 29: NULL, ! 30: NULL, ! 31: NULL ! 32: }; ! 33: ! 34: INTERRUPTHANDLER InterruptHandlers[MAX_INTERRUPTS]; ! 35: int nCyclesOver=0; ! 36: int ActiveInterrupt=0; ! 37: ! 38: ! 39: /*-----------------------------------------------------------------------*/ ! 40: /* ! 41: Reset interrupts, handlers ! 42: */ ! 43: void Int_Reset(void) ! 44: { ! 45: int i; ! 46: ! 47: /* Reset counts */ ! 48: PendingInterruptCount = 0; ! 49: nCyclesOver = 0; ! 50: ! 51: /* Reset interrupt table */ ! 52: for(i=0; i<MAX_INTERRUPTS; i++) { ! 53: InterruptHandlers[i].bUsed = FALSE; ! 54: InterruptHandlers[i].pFunction = pIntHandlerFunctions[i]; ! 55: } ! 56: } ! 57: ! 58: ! 59: /*-----------------------------------------------------------------------*/ ! 60: /* ! 61: Convert interrupt handler function pointer to ID, used for saving ! 62: */ ! 63: int Int_HandlerFunctionToID(void *pHandlerFunction) ! 64: { ! 65: int i; ! 66: ! 67: /* Is NULL, return ID 0 */ ! 68: if (pHandlerFunction==NULL) ! 69: return(0); ! 70: ! 71: /* Scan for function match */ ! 72: for(i=1; i<MAX_INTERRUPTS; i++) { ! 73: if (pIntHandlerFunctions[i]==pHandlerFunction) ! 74: return(i); ! 75: } ! 76: ! 77: /* Didn't find one! Oops */ ! 78: return(0); ! 79: } ! 80: ! 81: ! 82: /*-----------------------------------------------------------------------*/ ! 83: /* ! 84: Convert ID back into interrupt handler function, used for restoring ! 85: */ ! 86: void *Int_IDToHandlerFunction(int ID) ! 87: { ! 88: /* Get function pointer */ ! 89: return( pIntHandlerFunctions[ID] ); ! 90: } ! 91: ! 92: ! 93: /*-----------------------------------------------------------------------*/ ! 94: /* ! 95: Find next interrupt to occur, and store to global variables for decrement in instruction decode loop ! 96: */ ! 97: void Int_SetNewInterrupt(void) ! 98: { ! 99: int LowestCycleCount=999999,LowestInterrupt=0; ! 100: int i; ! 101: ! 102: /* Find next interrupt to go off */ ! 103: for(i=0; i<MAX_INTERRUPTS; i++) { ! 104: /* Is interrupt pending? */ ! 105: if (InterruptHandlers[i].bUsed) { ! 106: if (InterruptHandlers[i].Cycles<LowestCycleCount) { ! 107: LowestCycleCount = InterruptHandlers[i].Cycles; ! 108: LowestInterrupt = i; ! 109: } ! 110: } ! 111: } ! 112: ! 113: /* Set new counts, active interrupt */ ! 114: PendingInterruptCount = (short int)InterruptHandlers[LowestInterrupt].Cycles; ! 115: PendingInterruptFunction = InterruptHandlers[LowestInterrupt].pFunction; ! 116: ActiveInterrupt = LowestInterrupt; ! 117: ! 118: } ! 119: ! 120: ! 121: /*-----------------------------------------------------------------------*/ ! 122: /* ! 123: Adjust all interrupt timings, MUST call Int_SetNewInterrupt after this ! 124: */ ! 125: void Int_UpdateInterrupt(void) ! 126: { ! 127: int CycleSubtract; ! 128: int i; ! 129: ! 130: /* Find out how many cycles we went over (<=0) */ ! 131: nCyclesOver = PendingInterruptCount; ! 132: /* Calculate how many cycles have passed, included time we went over */ ! 133: CycleSubtract = InterruptHandlers[ActiveInterrupt].Cycles-nCyclesOver; ! 134: ! 135: /* Adjust table */ ! 136: for(i=0; i<MAX_INTERRUPTS; i++) { ! 137: if (InterruptHandlers[i].bUsed) ! 138: InterruptHandlers[i].Cycles -= CycleSubtract; ! 139: } ! 140: } ! 141: ! 142: ! 143: /*-----------------------------------------------------------------------*/ ! 144: /* ! 145: Adjust all interrupt timings as 'ActiveInterrupt' has occured, and remove from active list ! 146: */ ! 147: void Int_AcknowledgeInterrupt(void) ! 148: { ! 149: /* Update list cycle counts */ ! 150: Int_UpdateInterrupt(); ! 151: ! 152: /* Disable interrupt entry which has just occured */ ! 153: InterruptHandlers[ActiveInterrupt].bUsed = FALSE; ! 154: ! 155: /* Set new */ ! 156: Int_SetNewInterrupt(); ! 157: } ! 158: ! 159: ! 160: /*-----------------------------------------------------------------------*/ ! 161: /* ! 162: Add interrupt from time last one occurred ! 163: */ ! 164: void Int_AddAbsoluteInterrupt(int CycleTime, int Handler) ! 165: { ! 166: InterruptHandlers[Handler].bUsed = TRUE; ! 167: InterruptHandlers[Handler].Cycles = CycleTime + nCyclesOver; ! 168: ! 169: /* Set new */ ! 170: Int_SetNewInterrupt(); ! 171: } ! 172: ! 173: ! 174: /*-----------------------------------------------------------------------*/ ! 175: /* ! 176: Add interrupt to occur from now ! 177: */ ! 178: void Int_AddRelativeInterrupt(int CycleTime, int Handler) ! 179: { ! 180: InterruptHandlers[Handler].bUsed = TRUE; ! 181: InterruptHandlers[Handler].Cycles = CycleTime; ! 182: ! 183: /* Set new */ ! 184: Int_SetNewInterrupt(); ! 185: } ! 186: ! 187: ! 188: /*-----------------------------------------------------------------------*/ ! 189: /* ! 190: Remove a pending interrupt from our table ! 191: */ ! 192: void Int_RemovePendingInterrupt(int Handler) ! 193: { ! 194: /* Stop interrupt */ ! 195: InterruptHandlers[Handler].bUsed = FALSE; ! 196: ! 197: /* Update list cycle counts */ ! 198: Int_UpdateInterrupt(); ! 199: /* Set new */ ! 200: Int_SetNewInterrupt(); ! 201: } ! 202: ! 203: ! 204: /*-----------------------------------------------------------------------*/ ! 205: /* ! 206: Return TRUE if interrupt is active in list ! 207: */ ! 208: BOOL Int_InterruptActive(int Handler) ! 209: { ! 210: /* Is timer active? */ ! 211: if (InterruptHandlers[Handler].bUsed) ! 212: return(TRUE); ! 213: ! 214: return(FALSE); ! 215: } ! 216: ! 217: ! 218: /*-----------------------------------------------------------------------*/ ! 219: /* ! 220: Return cycles passed for an interrupt handler ! 221: */ ! 222: int Int_FindCyclesPassed(int Handler) ! 223: { ! 224: int CyclesPassed, CyclesFromLastInterrupt; ! 225: ! 226: CyclesFromLastInterrupt = (int)InterruptHandlers[ActiveInterrupt].Cycles-PendingInterruptCount; ! 227: CyclesPassed = ((int)InterruptHandlers[Handler].Cycles-CyclesFromLastInterrupt); ! 228: ! 229: return(CyclesPassed); ! 230: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.