ref: df3292dd771872c3f00b3bbaa4c3ae564fc6e5bb
parent: 6ab50aa9b610a087c7b2543571e23a4b3cc389bb
author: allkern <lisandroaalarcon@gmail.com>
date: Sat Jul 15 18:38:28 EDT 2023
Implement timer sync modes
--- a/psx/cpu.c
+++ b/psx/cpu.c
@@ -1386,6 +1386,7 @@
((uint32_t*)(&cpu->cop2_cr))[D] = t;
}
+#define R_IR0 cpu->cop2_dr.ir0
#define R_IR1 cpu->cop2_dr.ir1
#define R_IR2 cpu->cop2_dr.ir2
#define R_IR3 cpu->cop2_dr.ir3
@@ -1427,7 +1428,12 @@
#define R_SZ3 cpu->cop2_dr.sz3
#define R_ZSF3 cpu->cop2_cr.zsf3
#define R_ZSF4 cpu->cop2_cr.zsf4
+#define R_OFX cpu->cop2_cr.ofx
+#define R_OFY cpu->cop2_cr.ofy
#define R_OTZ cpu->cop2_dr.otz
+#define R_H cpu->cop2_cr.h
+#define R_DQA cpu->cop2_cr.dqa
+#define R_DQB cpu->cop2_cr.dqb
#define CLAMPU32(v, min, max) ((uint32_t)v < (uint32_t)min ? min : ((uint32_t)v > (uint32_t)max ? max : (uint32_t)v))
#define CLAMPS32(v, min, max) ((int32_t)v < (int32_t)min ? min : ((int32_t)v > (int32_t)max ? max : (int32_t)v))
@@ -1467,6 +1473,19 @@
R_SZ1 = R_SZ2;
R_SZ2 = R_SZ3;
R_SZ3 = CLAMPU32(R_MAC3 >> (12 * !sf), 0x0000, 0xffff);
+
+ uint32_t f = R_H / R_SZ3;
+
+ R_SX0 = R_SX1;
+ R_SX1 = R_SX2;
+ R_SX2 = R_OFX + R_IR1 * f;
+
+ R_SY0 = R_SY1;
+ R_SY1 = R_SY2;
+ R_SY2 = R_OFY + R_IR2 * f;
+
+ R_IR0 = R_DQB + R_DQA * f;
+ R_MAC0 = R_IR0;
}
void psx_gte_i_nclip(psx_cpu_t* cpu) {@@ -1546,7 +1565,38 @@
}
void psx_gte_i_rtpt(psx_cpu_t* cpu) {- log_fatal("rtpt: Unimplemented GTE instruction"); + int sf = (cpu->opcode >> 19) & 1;
+ int lm = (cpu->opcode >> 9) & 2;
+ int shift = 12 * sf;
+
+ int16_t ir_upper = g_psx_gte_ir_clamp_table[lm];
+ int16_t ir_lower = g_psx_gte_ir_clamp_table[lm + 1];
+
+ R_MAC1 = (R_TRX << 12) + (R_RT11 * R_VX0 + R_RT12 * R_VY0 + R_RT13 * R_VZ0);
+ R_MAC2 = (R_TRY << 12) + (R_RT21 * R_VX0 + R_RT22 * R_VY0 + R_RT23 * R_VZ0);
+ R_MAC3 = (R_TRZ << 12) + (R_RT31 * R_VX0 + R_RT32 * R_VY0 + R_RT33 * R_VZ0);
+
+ R_IR1 = CLAMPS16(R_MAC1 >> shift, ir_lower, ir_upper);
+ R_IR2 = CLAMPS16(R_MAC2 >> shift, ir_lower, ir_upper);
+ R_IR3 = CLAMPS16(R_MAC3 >> shift, ir_lower, ir_upper);
+
+ R_SZ0 = R_SZ1;
+ R_SZ1 = R_SZ2;
+ R_SZ2 = R_SZ3;
+ R_SZ3 = CLAMPU32(R_MAC3 >> (12 * !sf), 0x0000, 0xffff);
+
+ uint32_t f = R_H / R_SZ3;
+
+ R_SX0 = R_SX1;
+ R_SX1 = R_SX2;
+ R_SX2 = R_OFX + R_IR1 * f;
+
+ R_SY0 = R_SY1;
+ R_SY1 = R_SY2;
+ R_SY2 = R_OFY + R_IR2 * f;
+
+ R_IR0 = R_DQB + R_DQA * f;
+ R_MAC0 = R_IR0;
}
void psx_gte_i_gpf(psx_cpu_t* cpu) {--- a/psx/cpu.h
+++ b/psx/cpu.h
@@ -16,24 +16,6 @@
typedef void (*psx_cpu_kcall_hook_t)(psx_cpu_t*);
/*
- Name Alias Common Usage
- R0 zero Constant (always 0)
- R1 at Assembler temporary (destroyed by some assembler pseudoinstructions!)
- R2-R3 v0-v1 Subroutine return values, may be changed by subroutines
- R4-R7 a0-a3 Subroutine arguments, may be changed by subroutines
- R8-R15 t0-t7 Temporaries, may be changed by subroutines
- R16-R23 s0-s7 Static variables, must be saved by subs
- R24-R25 t8-t9 Temporaries, may be changed by subroutines
- R26-R27 k0-k1 Reserved for kernel (destroyed by some IRQ handlers!)
- R28 gp Global pointer (rarely used)
- R29 sp Stack pointer
- R30 fp(s8) Frame Pointer, or 9th Static variable, must be saved
- R31 ra Return address (used so by JAL,BLTZAL,BGEZAL opcodes)
- - pc Program counter
- - hi,lo Multiply/divide results, may be changed by subroutines
-*/
-
-/*
cop0r0 - N/A
cop0r1 - N/A
cop0r2 - N/A
@@ -63,6 +45,24 @@
#define COP0_CAUSE 13
#define COP0_EPC 14
#define COP0_PRID 15
+
+/*
+ Name Alias Common Usage
+ R0 zero Constant (always 0)
+ R1 at Assembler temporary (destroyed by some assembler pseudoinstructions!)
+ R2-R3 v0-v1 Subroutine return values, may be changed by subroutines
+ R4-R7 a0-a3 Subroutine arguments, may be changed by subroutines
+ R8-R15 t0-t7 Temporaries, may be changed by subroutines
+ R16-R23 s0-s7 Static variables, must be saved by subs
+ R24-R25 t8-t9 Temporaries, may be changed by subroutines
+ R26-R27 k0-k1 Reserved for kernel (destroyed by some IRQ handlers!)
+ R28 gp Global pointer (rarely used)
+ R29 sp Stack pointer
+ R30 fp(s8) Frame Pointer, or 9th Static variable, must be saved
+ R31 ra Return address (used so by JAL,BLTZAL,BGEZAL opcodes)
+ - pc Program counter
+ - hi,lo Multiply/divide results, may be changed by subroutines
+*/
struct psx_cpu_t {uint32_t r[32];
--- a/psx/dev/timer.c
+++ b/psx/dev/timer.c
@@ -107,44 +107,12 @@
}
void timer_update_timer0(psx_timer_t* timer, int cyc) {- int src = T0_MODE & 0x100;
- // if (src) {- // log_fatal("Unimplemented T0 clock source: dotclock");-
- // exit(1);
- // }
-
- T0_PREV = T0_COUNTER;
-
- if (!T0_PAUSED)
- T0_COUNTER += cyc;
-
- uint16_t reset = (T0_MODE & MODE_RESETC) ? T0_TARGET : 0xffff;
-
- if ((T0_COUNTER >= reset) && (T0_PREV <= reset)) {- T0_COUNTER -= reset;
- T0_MODE |= 0x800;
-
- if (reset == 0xffff)
- T0_MODE |= 0x1000;
- }
-
- if ((T0_COUNTER >= 0xffff) && (T0_PREV <= 0xffff)) {- T0_COUNTER &= 0xffff;
- T0_MODE |= 0x1000;
- }
}
void timer_update_timer1(psx_timer_t* timer, int cyc) {int src = T1_MODE & 0x100;
- // if (src) {- // log_fatal("Unimplemented T1 clock source: dotclock");-
- // exit(1);
- // }
-
T1_PREV = T1_COUNTER;
if (!T1_PAUSED)
@@ -168,12 +136,6 @@
void timer_update_timer2(psx_timer_t* timer, int cyc) {int src = T2_MODE & 0x100;
- // if (src) {- // log_fatal("Unimplemented T2 clock source: dotclock");-
- // exit(1);
- // }
-
T2_PREV = T2_COUNTER;
if (!T2_PAUSED)
@@ -201,8 +163,47 @@
timer_update_timer2(timer, cyc);
}
-void psxe_gpu_hblank_event_cb(psx_gpu_t* gpu) {}-void psxe_gpu_hblank_end_event_cb(psx_gpu_t* gpu) {}+void psxe_gpu_hblank_event_cb(psx_gpu_t* gpu) {+ psx_timer_t* timer = gpu->udata[1];
+
+ if (T0_MODE & MODE_SYNCEN) {+ switch (T0_MODE & 6) {+ case 0: {+ T0_PAUSED = 1;
+ } break;
+
+ case 2: {+ T0_COUNTER = 0;
+ } break;
+
+ case 4: {+ T0_COUNTER = 0;
+ T0_PAUSED = 0;
+ } break;
+
+ case 6: {+ T0_MODE &= ~MODE_SYNCEN;
+ } break;
+ }
+ }
+}
+
+void psxe_gpu_hblank_end_event_cb(psx_gpu_t* gpu) {+ psx_timer_t* timer = gpu->udata[1];
+
+ if (T0_MODE & MODE_SYNCEN) {+ switch (T0_MODE & 6) {+ case 0: {+ T0_PAUSED = 0;
+ } break;
+
+ case 4: {+ T0_PAUSED = 1;
+ } break;
+ }
+ }
+}
+
void psxe_gpu_vblank_end_event_cb(psx_gpu_t* gpu) {} void psx_timer_destroy(psx_timer_t* timer) {--
⑨