ref: 364d8222cea403a2a6109640e26cc7131bcb465f
parent: baa9e6a32f5eb94d1c0d2314fa3ad69ad6567945
author: allkern <lisandroaalarcon@gmail.com>
date: Wed Jun 28 19:35:54 EDT 2023
Fix undocumented BXX dupes Fix scaling on 512x240 Improve GPU timings and accuracy
--- a/build-win64.ps1
+++ b/build-win64.ps1
@@ -22,6 +22,6 @@
-L"`"$($SDL2_DIR)\lib`"" `
-m64 -lSDL2main -lSDL2 -Wno-overflow `
-Wall -pedantic -DLOG_USE_COLOR `
- -ffast-math -Ofast
+ -ffast-math -Ofast -g
Copy-Item -Path "sdl2-win64/SDL2.dll" -Destination "bin"
\ No newline at end of file
--- a/frontend/screen.c
+++ b/frontend/screen.c
@@ -93,8 +93,10 @@
void psxe_screen_set_scale(psxe_screen_t* screen, unsigned int scale) {#ifdef PSXE_SCREEN_DEBUG
screen->scale = 1;
+ screen->saved_scale = 1;
#else
screen->scale = scale;
+ screen->saved_scale = scale;
#endif
}
@@ -119,7 +121,7 @@
screen->height = psx_get_display_height(screen->psx);
#endif
- if (screen->width >= 512) {+ if (screen->width > 512) {screen->saved_scale = screen->scale;
screen->scale = 1;
} else {--- a/psx/cpu.c
+++ b/psx/cpu.c
@@ -126,10 +126,10 @@
psx_cpu_i_bltz , psx_cpu_i_bgez , psx_cpu_i_bltz , psx_cpu_i_bgez ,
psx_cpu_i_bltz , psx_cpu_i_bgez , psx_cpu_i_bltz , psx_cpu_i_bgez ,
psx_cpu_i_bltz , psx_cpu_i_bgez , psx_cpu_i_bltz , psx_cpu_i_bgez ,
- psx_cpu_i_bltzal , psx_cpu_i_bgezal , psx_cpu_i_bltzal , psx_cpu_i_bgezal ,
- psx_cpu_i_bltzal , psx_cpu_i_bgezal , psx_cpu_i_bltzal , psx_cpu_i_bgezal ,
- psx_cpu_i_bltzal , psx_cpu_i_bgezal , psx_cpu_i_bltzal , psx_cpu_i_bgezal ,
- psx_cpu_i_bltzal , psx_cpu_i_bgezal , psx_cpu_i_bltzal , psx_cpu_i_bgezal
+ psx_cpu_i_bltzal , psx_cpu_i_bgezal , psx_cpu_i_bltz , psx_cpu_i_bgez ,
+ psx_cpu_i_bltz , psx_cpu_i_bgez , psx_cpu_i_bltz , psx_cpu_i_bgez ,
+ psx_cpu_i_bltz , psx_cpu_i_bgez , psx_cpu_i_bltz , psx_cpu_i_bgez ,
+ psx_cpu_i_bltz , psx_cpu_i_bgez , psx_cpu_i_bltz , psx_cpu_i_bgez
};
#define OP ((cpu->buf[1] >> 26) & 0x3f)
@@ -320,6 +320,12 @@
cpu->buf[1] = cpu->buf[0];
+ if (cpu->pc & 0x3) {+ psx_cpu_exception(cpu, CAUSE_ADEL);
+
+ return;
+ }
+
psx_cpu_fetch(cpu);
cpu->delay_slot = cpu->branch;
@@ -731,6 +737,8 @@
uint32_t aligned = psx_bus_read32(cpu->bus, addr & ~0x3);
+ cpu->load_v = cpu->r[T];
+
switch (addr & 0x3) {case 0: cpu->load_v = aligned ; break;
case 1: cpu->load_v = (cpu->load_v & 0xff000000) | (aligned >> 8 ); break;
@@ -1255,6 +1263,10 @@
case 9: cpu->cop0_bdam = t; break;
case 11: cpu->cop0_bpcm = t; break;
case 12: cpu->cop0_sr = t; break;
+ }
+
+ if ((cpu->cop0_sr & SR_IEC) && (cpu->cop0_cause & cpu->cop0_sr & SR_IM2)) {+ psx_cpu_exception(cpu, CAUSE_INT);
}
}
--- a/psx/dev/gpu.c
+++ b/psx/dev/gpu.c
@@ -38,15 +38,7 @@
uint32_t psx_gpu_read32(psx_gpu_t* gpu, uint32_t offset) { switch (offset) {case 0x00: return gpu->gpuread; // GPUREAD
- case 0x04: {- if (gpu->gpustat & 0x80000000) {- gpu->gpustat &= ~0x80000000;
- } else {- gpu->gpustat |= 0x80000000;
- }
-
- return (gpu->gpustat & ~0x00080000) | 0x1c000000; // GPUSTAT
- }
+ case 0x04: return gpu->gpustat | 0x1c000000;
}
log_warn("Unhandled 32-bit GPU read at offset %08x", offset);@@ -56,8 +48,8 @@
uint16_t psx_gpu_read16(psx_gpu_t* gpu, uint32_t offset) { switch (offset) {- case 0x00: return 0x00000000; // GPUREAD
- case 0x04: return 0x1c000000; // GPUSTAT
+ case 0x00: return gpu->gpuread;
+ case 0x04: return gpu->gpustat;
}
log_warn("Unhandled 16-bit GPU read at offset %08x", offset);@@ -67,8 +59,8 @@
uint8_t psx_gpu_read8(psx_gpu_t* gpu, uint32_t offset) { switch (offset) {- case 0x00: return 0x00000000; // GPUREAD
- case 0x04: return 0x1c000000; // GPUSTAT
+ case 0x00: return gpu->gpuread;
+ case 0x04: return gpu->gpustat;
}
log_warn("Unhandled 8-bit GPU read at offset %08x", offset);@@ -114,6 +106,24 @@
}
}
+void gpu_render_flat_rectangle(psx_gpu_t* gpu, vertex_t v, uint32_t w, uint32_t h, uint32_t color) {+ /* Offset coordinates */
+ v.x += gpu->off_x;
+ v.y += gpu->off_y;
+
+ /* Calculate bounding box */
+ int xmin = max(v.x, gpu->draw_x1);
+ int ymin = max(v.y, gpu->draw_y1);
+ int xmax = min(xmin + w, gpu->draw_x2);
+ int ymax = min(ymin + h, gpu->draw_y2);
+
+ for (uint32_t y = ymin; y < ymax; y++) {+ for (uint32_t x = xmin; x < xmax; x++) {+ gpu->vram[x + (y * 1024)] = gpu_to_bgr555(color);
+ }
+ }
+}
+
void gpu_render_textured_rectangle(psx_gpu_t* gpu, vertex_t v, uint32_t w, uint32_t h, uint32_t tpx, uint32_t tpy) {vertex_t a = v;
@@ -571,6 +581,29 @@
}
}
+void gpu_cmd_68(psx_gpu_t* gpu) {+ switch (gpu->state) {+ case GPU_STATE_RECV_CMD: {+ gpu->state = GPU_STATE_RECV_ARGS;
+ gpu->cmd_args_remaining = 1;
+ } break;
+
+ case GPU_STATE_RECV_ARGS: {+ if (!gpu->cmd_args_remaining) {+ gpu->state = GPU_STATE_RECV_DATA;
+
+ gpu->color = gpu->buf[0] & 0xffffff;
+ gpu->v0.x = gpu->buf[1] & 0xffff;
+ gpu->v0.y = gpu->buf[1] >> 16;
+
+ gpu_render_flat_rectangle(gpu, gpu->v0, 1, 1, gpu->color);
+
+ gpu->state = GPU_STATE_RECV_CMD;
+ }
+ } break;
+ }
+}
+
void psx_gpu_update_cmd(psx_gpu_t* gpu) { switch (gpu->buf[0] >> 24) {case 0x00: /* nop */ break;
@@ -580,6 +613,7 @@
case 0x30: gpu_cmd_30(gpu); break;
case 0x38: gpu_cmd_38(gpu); break;
case 0x64: gpu_cmd_64(gpu); break;
+ case 0x68: gpu_cmd_68(gpu); break;
case 0xa0: gpu_cmd_a0(gpu); break;
case 0xe1: {gpu->gpustat &= 0x7ff;
@@ -698,26 +732,43 @@
gpu->udata[index] = udata;
}
-#define GPU_CYCLES_PER_SCAN_NTSC 3413
+#define GPU_CYCLES_PER_HDRAW_NTSC 2560
+#define GPU_CYCLES_PER_SCANL_NTSC 3413
+#define GPU_SCANS_PER_VDRAW_NTSC 240
#define GPU_SCANS_PER_FRAME_NTSC 263
-#define GPU_CYCLES_PER_SCAN_PAL 3406
-#define GPU_SCANS_PER_FRAME_PAL 314
+void gpu_scanline_event(psx_gpu_t* gpu) {+ gpu->line++;
+
+ if (gpu->line < GPU_SCANS_PER_VDRAW_NTSC) {+ if (gpu->line & 1) {+ gpu->gpustat |= 1 << 31;
+ } else {+ gpu->gpustat &= ~(1 << 31);
+ }
+ } else {+ gpu->gpustat &= ~(1 << 31);
+ }
+
+ if (gpu->line == GPU_SCANS_PER_VDRAW_NTSC) {+ // Disable Vblank for now
+ // psx_ic_irq(gpu->ic, IC_VBLANK);
+ } else if (gpu->line == GPU_SCANS_PER_FRAME_NTSC) {+ gpu->line = 0;
+ }
+}
+
void psx_gpu_update(psx_gpu_t* gpu, int cyc) {// Convert CPU (~33.8 MHz) cycles to GPU (~53.7 MHz) cycles
- gpu->cycles += (float)cyc * (PSX_GPU_CLOCK_FREQ_NTSC / PSX_CPU_CLOCK_FREQ);
+ gpu->cycles += ((float)cyc) * (PSX_GPU_CLOCK_FREQ_PAL / PSX_CPU_CLOCK_FREQ);
- if (gpu->cycles >= (float)GPU_CYCLES_PER_SCAN_NTSC) {- gpu->cycles -= (float)GPU_CYCLES_PER_SCAN_NTSC;
- gpu->line++;
+ //if (gpu->cycles >= (float)GPU_CYCLES_PER_HDRAW_NTSC) {+ // Tick Hblank timer
- if (gpu->line == GPU_SCANS_PER_FRAME_NTSC) {- // psx_ic_irq(gpu->ic, IC_VBLANK);
+ if (gpu->cycles >= (float)GPU_CYCLES_PER_SCANL_NTSC) {+ gpu->cycles -= (float)GPU_CYCLES_PER_SCANL_NTSC;
- gpu->line = 0;
- } else {- psx_ic_irq(gpu->ic, IC_GPU);
- }
+ gpu_scanline_event(gpu);
}
}
--- a/psx/dev/timer.c
+++ b/psx/dev/timer.c
@@ -34,6 +34,21 @@
}
uint16_t psx_timer_read16(psx_timer_t* timer, uint32_t offset) {+ if (offset == 0x20) {+ return 0x000016b0;
+ }
+
+ int t = (offset >> 4) & 0x3;
+ int r = offset & 0xf;
+
+ if (r == 0) {+ switch (t) {+ case 0: return timer->t0_stub++;
+ case 1: return timer->t1_stub++;
+ case 2: return timer->t2_stub++;
+ }
+ }
+
log_fatal("Unhandled 16-bit TIMER read at offset %08x", offset);return 0x0;
--
⑨