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