Skip to content

Commit

Permalink
Fix undocumented BXX dupes
Browse files Browse the repository at this point in the history
Fix scaling on 512x240
Improve GPU timings and accuracy
  • Loading branch information
allkern committed Jun 29, 2023
1 parent baa9e6a commit 364d822
Show file tree
Hide file tree
Showing 5 changed files with 112 additions and 32 deletions.
2 changes: 1 addition & 1 deletion build-win64.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,6 @@ gcc -I"`"$($PSX_DIR)`"" `
-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"
4 changes: 3 additions & 1 deletion frontend/screen.c
Original file line number Diff line number Diff line change
Expand Up @@ -93,8 +93,10 @@ void psxe_screen_update(psxe_screen_t* screen) {
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
}

Expand All @@ -119,7 +121,7 @@ void psxe_gpu_dmode_event_cb(psx_gpu_t* gpu) {
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 {
Expand Down
20 changes: 16 additions & 4 deletions psx/cpu.c
Original file line number Diff line number Diff line change
Expand Up @@ -126,10 +126,10 @@ psx_cpu_instruction_t g_psx_cpu_bxx_table[] = {
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)
Expand Down Expand Up @@ -320,6 +320,12 @@ void psx_cpu_cycle(psx_cpu_t* cpu) {

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;
Expand Down Expand Up @@ -731,6 +737,8 @@ void psx_cpu_i_lwr(psx_cpu_t* cpu) {

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;
Expand Down Expand Up @@ -1256,6 +1264,10 @@ void psx_cpu_i_mtc0(psx_cpu_t* cpu) {
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);
}
}

void psx_cpu_i_ctc0(psx_cpu_t* cpu) {
Expand Down
103 changes: 77 additions & 26 deletions psx/dev/gpu.c
Original file line number Diff line number Diff line change
Expand Up @@ -38,15 +38,7 @@ void psx_gpu_init(psx_gpu_t* gpu, psx_ic_t* ic) {
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);
Expand All @@ -56,8 +48,8 @@ uint32_t psx_gpu_read32(psx_gpu_t* gpu, uint32_t offset) {

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);
Expand All @@ -67,8 +59,8 @@ uint16_t psx_gpu_read16(psx_gpu_t* gpu, uint32_t offset) {

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);
Expand Down Expand Up @@ -114,6 +106,24 @@ uint16_t gpu_fetch_texel(psx_gpu_t* gpu, uint16_t tx, uint16_t ty, uint32_t tpx,
}
}

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;

Expand Down Expand Up @@ -571,6 +581,29 @@ void gpu_cmd_64(psx_gpu_t* gpu) {
}
}

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;
Expand All @@ -580,6 +613,7 @@ void psx_gpu_update_cmd(psx_gpu_t* gpu) {
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;
Expand Down Expand Up @@ -698,26 +732,43 @@ void psx_gpu_set_udata(psx_gpu_t* gpu, int index, void* udata) {
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);
}
}

Expand Down
15 changes: 15 additions & 0 deletions psx/dev/timer.c
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,21 @@ uint32_t psx_timer_read32(psx_timer_t* timer, uint32_t offset) {
}

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;
Expand Down

0 comments on commit 364d822

Please sign in to comment.