|
|
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.