cdrom: change pause timing again
[pcsx_rearmed.git] / libpcsxcore / psxevents.c
CommitLineData
6d75addf 1#include <stdio.h>
9a0a61d2 2#include "r3000a.h"
3#include "cdrom.h"
4#include "psxdma.h"
5#include "mdec.h"
6#include "psxevents.h"
6d75addf 7
8extern int pending_exception;
9
10//#define evprintf printf
11#define evprintf(...)
12
13u32 event_cycles[PSXINT_COUNT];
14
de74f599 15u32 schedule_timeslice(void)
6d75addf 16{
17 u32 i, c = psxRegs.cycle;
18 u32 irqs = psxRegs.interrupt;
19 s32 min, dif;
20
21 min = PSXCLK;
22 for (i = 0; irqs != 0; i++, irqs >>= 1) {
23 if (!(irqs & 1))
24 continue;
25 dif = event_cycles[i] - c;
26 //evprintf(" ev %d\n", dif);
27 if (0 < dif && dif < min)
28 min = dif;
29 }
30 next_interupt = c + min;
de74f599 31 return next_interupt;
6d75addf 32}
33
9a0a61d2 34static void irqNoOp() {
35}
36
6d75addf 37typedef void (irq_func)();
38
39static irq_func * const irq_funcs[] = {
40 [PSXINT_SIO] = sioInterrupt,
41 [PSXINT_CDR] = cdrInterrupt,
42 [PSXINT_CDREAD] = cdrPlayReadInterrupt,
43 [PSXINT_GPUDMA] = gpuInterrupt,
44 [PSXINT_MDECOUTDMA] = mdec1Interrupt,
45 [PSXINT_SPUDMA] = spuInterrupt,
46 [PSXINT_MDECINDMA] = mdec0Interrupt,
47 [PSXINT_GPUOTCDMA] = gpuotcInterrupt,
48 [PSXINT_CDRDMA] = cdrDmaInterrupt,
9a0a61d2 49 [PSXINT_NEWDRC_CHECK] = irqNoOp,
6d75addf 50 [PSXINT_CDRLID] = cdrLidSeekInterrupt,
11d23573 51 [PSXINT_IRQ10] = irq10Interrupt,
6d75addf 52 [PSXINT_SPU_UPDATE] = spuUpdate,
c2eee46b 53 [PSXINT_SPU_IRQ] = spuDelayedIrq,
6d75addf 54 [PSXINT_RCNT] = psxRcntUpdate,
55};
56
57/* local dupe of psxBranchTest, using event_cycles */
9a0a61d2 58void irq_test(psxCP0Regs *cp0)
6d75addf 59{
60 u32 cycle = psxRegs.cycle;
61 u32 irq, irq_bits;
62
63 for (irq = 0, irq_bits = psxRegs.interrupt; irq_bits != 0; irq++, irq_bits >>= 1) {
64 if (!(irq_bits & 1))
65 continue;
66 if ((s32)(cycle - event_cycles[irq]) >= 0) {
67 // note: irq_funcs() also modify psxRegs.interrupt
68 psxRegs.interrupt &= ~(1u << irq);
69 irq_funcs[irq]();
70 }
71 }
72
0b1da491 73 cp0->n.Cause &= ~0x400;
74 if (psxHu32(0x1070) & psxHu32(0x1074))
75 cp0->n.Cause |= 0x400;
76 if (((cp0->n.Cause | 1) & cp0->n.SR & 0x401) == 0x401) {
77 psxException(0, 0, cp0);
6d75addf 78 pending_exception = 1;
79 }
80}
81
82void gen_interupt(psxCP0Regs *cp0)
83{
84 evprintf(" +ge %08x, %u->%u (%d)\n", psxRegs.pc, psxRegs.cycle,
85 next_interupt, next_interupt - psxRegs.cycle);
86
87 irq_test(cp0);
88 //pending_exception = 1;
89
90 schedule_timeslice();
91
92 evprintf(" -ge %08x, %u->%u (%d)\n", psxRegs.pc, psxRegs.cycle,
93 next_interupt, next_interupt - psxRegs.cycle);
94}
95
9a0a61d2 96void events_restore(void)
97{
98 int i;
99 for (i = 0; i < PSXINT_COUNT; i++)
100 event_cycles[i] = psxRegs.intCycle[i].sCycle + psxRegs.intCycle[i].cycle;
6d75addf 101
9a0a61d2 102 event_cycles[PSXINT_RCNT] = psxNextsCounter + psxNextCounter;
103 psxRegs.interrupt |= 1 << PSXINT_RCNT;
104 psxRegs.interrupt &= (1 << PSXINT_COUNT) - 1;
105}