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