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