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