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