|
|
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:
1.1.1.2 ! root 56:
! 57: /*-----------------------------------------------------------------------*/
1.1 root 58: /*
59: Reset interrupts, handlers
60: */
61: void Int_Reset(void)
62: {
63: int i;
64:
1.1.1.2 ! root 65: /* Reset counts */
1.1 root 66: PendingInterruptCount = 0;
67: nCyclesOver = 0;
68:
1.1.1.2 ! root 69: /* Reset interrupt table */
1.1 root 70: for(i=0; i<MAX_INTERRUPTS; i++) {
71: InterruptHandlers[i].bUsed = FALSE;
72: InterruptHandlers[i].pFunction = pIntHandlerFunctions[i];
73: }
74: }
75:
1.1.1.2 ! root 76:
! 77: /*-----------------------------------------------------------------------*/
1.1 root 78: /*
79: Save/Restore snapshot of local variables('MemorySnapShot_Store' handles type)
80: */
81: void Int_MemorySnapShot_Capture(BOOL bSave)
82: {
83: int i,ID;
84:
1.1.1.2 ! root 85: /* Save/Restore details */
1.1 root 86: for(i=0; i<MAX_INTERRUPTS; i++) {
87: MemorySnapShot_Store(&InterruptHandlers[i].bUsed,sizeof(InterruptHandlers[i].bUsed));
88: MemorySnapShot_Store(&InterruptHandlers[i].Cycles,sizeof(InterruptHandlers[i].Cycles));
89: if (bSave) {
1.1.1.2 ! root 90: /* Convert function to ID */
1.1 root 91: ID = Int_HandlerFunctionToID(InterruptHandlers[i].pFunction);
92: MemorySnapShot_Store(&ID,sizeof(int));
93: }
94: else {
1.1.1.2 ! root 95: /* Convert ID to function */
1.1 root 96: MemorySnapShot_Store(&ID,sizeof(int));
97: InterruptHandlers[i].pFunction = Int_IDToHandlerFunction(ID);
98: }
99: }
100: MemorySnapShot_Store(&nCyclesOver,sizeof(nCyclesOver));
101: MemorySnapShot_Store(&nFrameCyclesOver,sizeof(nFrameCyclesOver));
102: }
103:
1.1.1.2 ! root 104:
! 105: /*-----------------------------------------------------------------------*/
1.1 root 106: /*
107: Convert interrupt handler function pointer to ID, used for saving
108: */
109: int Int_HandlerFunctionToID(void *pHandlerFunction)
110: {
111: int i;
112:
1.1.1.2 ! root 113: /* Is NULL, return ID 0 */
1.1 root 114: if (pHandlerFunction==NULL)
115: return(0);
116:
1.1.1.2 ! root 117: /* Scan for function match */
1.1 root 118: for(i=1; i<MAX_INTERRUPTS; i++) {
119: if (pIntHandlerFunctions[i]==pHandlerFunction)
120: return(i);
121: }
122:
1.1.1.2 ! root 123: /* Didn't find one! Oops */
1.1 root 124: return(0);
125: }
126:
1.1.1.2 ! root 127:
! 128: /*-----------------------------------------------------------------------*/
1.1 root 129: /*
130: Convert ID back into interrupt handler function, used for restoring
131: */
132: void *Int_IDToHandlerFunction(int ID)
133: {
1.1.1.2 ! root 134: /* Get function pointer */
1.1 root 135: return( pIntHandlerFunctions[ID] );
136: }
137:
1.1.1.2 ! root 138:
! 139: /*-----------------------------------------------------------------------*/
1.1 root 140: /*
141: Return number of clock cycles into retrace
142: */
143: int Int_FindFrameCycles(void)
144: {
145: return( nFrameCyclesOver + (InterruptHandlers[ActiveInterrupt].Cycles-PendingInterruptCount) );
146: }
147:
1.1.1.2 ! root 148:
! 149: /*-----------------------------------------------------------------------*/
1.1 root 150: /*
151: Find next interrupt to occur, and store to global variables for decrement in instruction decode loop
152: */
153: void Int_SetNewInterrupt(void)
154: {
155: int LowestCycleCount=999999,LowestInterrupt=0;
156: int i;
157:
1.1.1.2 ! root 158: /* Find next interrupt to go off */
1.1 root 159: for(i=0; i<MAX_INTERRUPTS; i++) {
1.1.1.2 ! root 160: /* Is interrupt pending? */
1.1 root 161: if (InterruptHandlers[i].bUsed) {
162: if (InterruptHandlers[i].Cycles<LowestCycleCount) {
163: LowestCycleCount = InterruptHandlers[i].Cycles;
164: LowestInterrupt = i;
165: }
166: }
167: }
1.1.1.2 ! root 168:
! 169: /* Set new counts, active interrupt */
1.1 root 170: PendingInterruptCount = (short int)InterruptHandlers[LowestInterrupt].Cycles;
171: PendingInterruptFunction = InterruptHandlers[LowestInterrupt].pFunction;
172: ActiveInterrupt = LowestInterrupt;
173:
174: }
175:
1.1.1.2 ! root 176:
! 177: /*-----------------------------------------------------------------------*/
1.1 root 178: /*
179: Adjust all interrupt timings, MUST call Int_SetNewInterrupt after this
180: */
181: void Int_UpdateInterrupt(void)
182: {
183: int CycleSubtract;
184: int i;
185:
1.1.1.2 ! root 186: /* Find out how many cycles we went over (<=0) */
1.1 root 187: nCyclesOver = PendingInterruptCount;
1.1.1.2 ! root 188: /* Calculate how many cycles have passed, included time we went over */
1.1 root 189: CycleSubtract = InterruptHandlers[ActiveInterrupt].Cycles-nCyclesOver;
190:
1.1.1.2 ! root 191: /* Adjust table */
1.1 root 192: for(i=0; i<MAX_INTERRUPTS; i++) {
193: if (InterruptHandlers[i].bUsed)
194: InterruptHandlers[i].Cycles -= CycleSubtract;
195: }
196: nFrameCyclesOver += CycleSubtract;
197: }
198:
1.1.1.2 ! root 199:
! 200: /*-----------------------------------------------------------------------*/
1.1 root 201: /*
202: Adjust all interrupt timings as 'ActiveInterrupt' has occured, and remove from active list
203: */
204: void Int_AcknowledgeInterrupt(void)
205: {
1.1.1.2 ! root 206: /* Update list cycle counts */
1.1 root 207: Int_UpdateInterrupt();
208:
1.1.1.2 ! root 209: /* Disable interrupt entry which has just occured */
1.1 root 210: InterruptHandlers[ActiveInterrupt].bUsed = FALSE;
211:
1.1.1.2 ! root 212: /* Set new */
1.1 root 213: Int_SetNewInterrupt();
214: }
215:
1.1.1.2 ! root 216:
! 217: /*-----------------------------------------------------------------------*/
1.1 root 218: /*
219: Add interrupt from time last one occurred
220: */
221: void Int_AddAbsoluteInterrupt(int CycleTime, int Handler)
222: {
223: InterruptHandlers[Handler].bUsed = TRUE;
224: InterruptHandlers[Handler].Cycles = CycleTime + nCyclesOver;
225:
1.1.1.2 ! root 226: /* Set new */
1.1 root 227: Int_SetNewInterrupt();
228: }
229:
1.1.1.2 ! root 230:
! 231: /*-----------------------------------------------------------------------*/
1.1 root 232: /*
233: Add interrupt to occur from now
234: */
235: void Int_AddRelativeInterrupt(int CycleTime, int Handler)
236: {
237: InterruptHandlers[Handler].bUsed = TRUE;
238: InterruptHandlers[Handler].Cycles = CycleTime;
239:
1.1.1.2 ! root 240: /* Set new */
1.1 root 241: Int_SetNewInterrupt();
242: }
243:
1.1.1.2 ! root 244:
! 245: /*-----------------------------------------------------------------------*/
1.1 root 246: /*
247: Remove a pending interrupt from our table
248: */
249: void Int_RemovePendingInterrupt(int Handler)
250: {
1.1.1.2 ! root 251: /* Stop interrupt */
1.1 root 252: InterruptHandlers[Handler].bUsed = FALSE;
253:
1.1.1.2 ! root 254: /* Update list cycle counts */
1.1 root 255: Int_UpdateInterrupt();
1.1.1.2 ! root 256: /* Set new */
1.1 root 257: Int_SetNewInterrupt();
258: }
259:
1.1.1.2 ! root 260:
! 261: /*-----------------------------------------------------------------------*/
1.1 root 262: /*
263: Return TRUE if interrupt is active in list
264: */
265: BOOL Int_InterruptActive(int Handler)
266: {
1.1.1.2 ! root 267: /* Is timer active? */
1.1 root 268: if (InterruptHandlers[Handler].bUsed)
269: return(TRUE);
270:
271: return(FALSE);
272: }
273:
1.1.1.2 ! root 274:
! 275: /*-----------------------------------------------------------------------*/
1.1 root 276: /*
277: Return cycles passed for an interrupt handler
278: */
279: int Int_FindCyclesPassed(int Handler)
280: {
281: int CyclesPassed, CyclesFromLastInterrupt;
282:
283: CyclesFromLastInterrupt = (int)InterruptHandlers[ActiveInterrupt].Cycles-PendingInterruptCount;
284: CyclesPassed = ((int)InterruptHandlers[Handler].Cycles-CyclesFromLastInterrupt);
285:
286: return(CyclesPassed);
287: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.