From bd3e55548dafd97ce02401010f0308d437889dae Mon Sep 17 00:00:00 2001 From: allkern Date: Thu, 6 Jul 2023 23:56:38 -0300 Subject: [PATCH] Fix GPU commands --- psx/dev/gpu.c | 157 +++++++++++++++++++++++++++++++++++++------------- psx/dev/gpu.h | 4 +- psx/dev/pad.c | 56 +++++++++--------- 3 files changed, 148 insertions(+), 69 deletions(-) diff --git a/psx/dev/gpu.c b/psx/dev/gpu.c index e25c31a..a08ecb8 100644 --- a/psx/dev/gpu.c +++ b/psx/dev/gpu.c @@ -40,16 +40,26 @@ uint32_t psx_gpu_read32(psx_gpu_t* gpu, uint32_t offset) { case 0x00: { uint32_t data = 0x0; - if (gpu->c0_ysiz) { - data = *((uint32_t*)(&gpu->vram[gpu->c0_xpos + (gpu->c0_ypos * 1024)])); + if (gpu->c0_tsiz) { + data |= gpu->vram[gpu->c0_addr + (gpu->c0_xcnt + (gpu->c0_ycnt * 1024))]; - gpu->c0_xsiz -= 2; - gpu->c0_xpos += 2; + gpu->c0_xcnt += 1; - if (gpu->c0_xsiz <= 0) { - gpu->c0_ypos += 1; - gpu->c0_ysiz -= 1; + if (gpu->c0_xcnt == gpu->c0_xsiz) { + gpu->c0_ycnt += 1; + gpu->c0_xcnt = 0; } + + data |= gpu->vram[gpu->c0_addr + (gpu->c0_xcnt + (gpu->c0_ycnt * 1024))] << 16; + + gpu->c0_xcnt += 1; + + if (gpu->c0_xcnt == gpu->c0_xsiz) { + gpu->c0_ycnt += 1; + gpu->c0_xcnt = 0; + } + + gpu->c0_tsiz -= 2; } return data; @@ -94,11 +104,11 @@ int max(int x0, int x1) { #define EDGE(a, b, c) ((b.x - a.x) * (c.y - a.y) - (b.y - a.y) * (c.x - a.x)) -uint16_t gpu_fetch_texel(psx_gpu_t* gpu, uint16_t tx, uint16_t ty, uint32_t tpx, uint32_t tpy) { +uint16_t gpu_fetch_texel(psx_gpu_t* gpu, uint16_t tx, uint16_t ty, uint32_t tpx, uint32_t tpy, int depth) { tx = (tx & ~gpu->texw_mx) | (gpu->texw_ox & gpu->texw_mx); ty = (ty & ~gpu->texw_my) | (gpu->texw_oy & gpu->texw_my); - switch (gpu->texp_d) { + switch (depth) { // 4-bit case 0: { uint16_t texel = gpu->vram[(tpx + (tx >> 2)) + ((tpy + ty) * 1024)]; @@ -124,20 +134,82 @@ uint16_t gpu_fetch_texel(psx_gpu_t* gpu, uint16_t tx, uint16_t ty, uint32_t tpx, } } -void gpu_render_flat_line(psx_gpu_t* gpu, vertex_t v0, vertex_t v1, uint32_t color) { - double l = 640.0; +void plotLineLow(psx_gpu_t* gpu, int x0, int y0, int x1, int y1, uint16_t color) { + int dx = x1 - x0; + int dy = y1 - y0; + int yi = 1; + if (dy < 0) { + yi = -1; + dy = -dy; + } + int d = (2 * dy) - dx; + int y = y0; - for (double p = 0.0; p < 1.0; p += 1.0 / l) { - unsigned int ax = (v0.x * p) + (v1.x * (1.0f - p)); - unsigned int ay = (v0.y * p) + (v1.y * (1.0f - p)); + for (int x = x0; x < x1; x++) { + gpu->vram[x + (y * 1024)] = color; - if ((ax > 1024) || (ay > 512)) - continue; + if (d > 0) { + y += yi; + d += (2 * (dy - dx)); + } else { + d += 2*dy; + } + } +} - gpu->vram[ax + (ay * 1024)] = color; +void plotLineHigh(psx_gpu_t* gpu, int x0, int y0, int x1, int y1, uint16_t color) { + int dx = x1 - x0; + int dy = y1 - y0; + int xi = 1; + if (dx < 0) { + xi = -1; + dx = -dx; + } + int d = (2 * dx) - dy; + int x = x0; + + for (int y = y0; y < y1; y++) { + gpu->vram[x + (y * 1024)] = color; + if (d > 0) { + x = x + xi; + d += (2 * (dx - dy)); + } else { + d += 2*dx; + } } } +void plotLine(psx_gpu_t* gpu, int x0, int y0, int x1, int y1, uint16_t color) { + if (abs(y1 - y0) < abs(x1 - x0)) { + if (x0 > x1) { + plotLineLow(gpu, x1, y1, x0, y0, color); + } else { + plotLineLow(gpu, x0, y0, x1, y1, color); + } + } else { + if (y0 > y1) { + plotLineHigh(gpu, x1, y1, x0, y0, color); + } else { + plotLineHigh(gpu, x0, y0, x1, y1, color); + } + } +} + +void gpu_render_flat_line(psx_gpu_t* gpu, vertex_t v0, vertex_t v1, uint32_t color) { + plotLine(gpu, v0.x, v0.y, v1.x, v1.y, color); + // double l = 640.0; + + // for (double p = 0.0; p < 1.0; p += 1.0 / l) { + // unsigned int ax = (v0.x * p) + (v1.x * (1.0f - p)); + // unsigned int ay = (v0.y * p) + (v1.y * (1.0f - p)); + + // if ((ax > 1024) || (ay > 512)) + // continue; + + // gpu->vram[ax + (ay * 1024)] = color; + // } +} + 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; @@ -171,7 +243,7 @@ void gpu_render_textured_rectangle(psx_gpu_t* gpu, vertex_t v, uint32_t w, uint3 for (int y = ymin; y < ymax; y++) { for (int x = xmin; x < xmax; x++) { - uint16_t color = gpu_fetch_texel(gpu, a.tx + xc, a.ty + yc, tpx, tpy); + uint16_t color = gpu_fetch_texel(gpu, a.tx + xc, a.ty + yc, tpx, tpy, gpu->texp_d); ++xc; @@ -298,7 +370,7 @@ void gpu_render_shaded_triangle(psx_gpu_t* gpu, vertex_t v0, vertex_t v1, vertex } } -void gpu_render_textured_triangle(psx_gpu_t* gpu, vertex_t v0, vertex_t v1, vertex_t v2, uint32_t tpx, uint32_t tpy) { +void gpu_render_textured_triangle(psx_gpu_t* gpu, vertex_t v0, vertex_t v1, vertex_t v2, uint32_t tpx, uint32_t tpy, int depth) { vertex_t a, b, c; a = v0; @@ -341,7 +413,7 @@ void gpu_render_textured_triangle(psx_gpu_t* gpu, vertex_t v0, vertex_t v1, vert uint32_t tx = ((z0 * a.tx) + (z1 * b.tx) + (z2 * c.tx)) / area; uint32_t ty = ((z0 * a.ty) + (z1 * b.ty) + (z2 * c.ty)) / area; - uint16_t color = gpu_fetch_texel(gpu, tx, ty, tpx, tpy); + uint16_t color = gpu_fetch_texel(gpu, tx, ty, tpx, tpy, depth); if (!color) continue; @@ -511,9 +583,9 @@ void gpu_cmd_2c(psx_gpu_t* gpu) { if (!gpu->cmd_args_remaining) { gpu->state = GPU_STATE_RECV_DATA; + uint32_t texp = gpu->buf[4] >> 16; gpu->color = gpu->buf[0] & 0xffffff; gpu->pal = gpu->buf[2] >> 16; - gpu->texp = gpu->buf[4] >> 16; gpu->v0.tx = gpu->buf[2] & 0xff; gpu->v0.ty = (gpu->buf[2] >> 8) & 0xff; gpu->v1.tx = gpu->buf[4] & 0xff; @@ -534,11 +606,12 @@ void gpu_cmd_2c(psx_gpu_t* gpu) { gpu->clut_x = (gpu->pal & 0x3f) << 4; gpu->clut_y = (gpu->pal >> 6) & 0x1ff; - uint32_t tpx = (gpu->texp & 0xf) << 6; - uint32_t tpy = (gpu->texp & 0x10) << 4; + uint32_t tpx = (texp & 0xf) << 6; + uint32_t tpy = (texp & 0x10) << 4; + uint32_t depth = (texp >> 7) & 0x3; - gpu_render_textured_triangle(gpu, gpu->v0, gpu->v1, gpu->v2, tpx, tpy); - gpu_render_textured_triangle(gpu, gpu->v1, gpu->v2, gpu->v3, tpx, tpy); + gpu_render_textured_triangle(gpu, gpu->v0, gpu->v1, gpu->v2, tpx, tpy, depth); + gpu_render_textured_triangle(gpu, gpu->v1, gpu->v2, gpu->v3, tpx, tpy, depth); gpu->state = GPU_STATE_RECV_CMD; } @@ -558,9 +631,9 @@ void gpu_cmd_2d(psx_gpu_t* gpu) { if (!gpu->cmd_args_remaining) { gpu->state = GPU_STATE_RECV_DATA; + uint32_t texp = gpu->buf[4] >> 16; gpu->color = gpu->buf[0] & 0xffffff; gpu->pal = gpu->buf[2] >> 16; - gpu->texp = gpu->buf[4] >> 16; gpu->v0.tx = gpu->buf[2] & 0xff; gpu->v0.ty = (gpu->buf[2] >> 8) & 0xff; gpu->v1.tx = gpu->buf[4] & 0xff; @@ -581,11 +654,12 @@ void gpu_cmd_2d(psx_gpu_t* gpu) { gpu->clut_x = (gpu->pal & 0x3f) << 4; gpu->clut_y = (gpu->pal >> 6) & 0x1ff; - uint32_t tpx = (gpu->texp & 0xf) << 6; - uint32_t tpy = (gpu->texp & 0x10) << 4; + uint32_t tpx = (texp & 0xf) << 6; + uint32_t tpy = (texp & 0x10) << 4; + int depth = (texp >> 7) & 0x3; - gpu_render_textured_triangle(gpu, gpu->v0, gpu->v1, gpu->v2, tpx, tpy); - gpu_render_textured_triangle(gpu, gpu->v1, gpu->v2, gpu->v3, tpx, tpy); + gpu_render_textured_triangle(gpu, gpu->v0, gpu->v1, gpu->v2, tpx, tpy, depth); + gpu_render_textured_triangle(gpu, gpu->v1, gpu->v2, gpu->v3, tpx, tpy, depth); gpu->state = GPU_STATE_RECV_CMD; } @@ -687,10 +761,18 @@ void gpu_cmd_c0(psx_gpu_t* gpu) { case GPU_STATE_RECV_ARGS: { if (!gpu->cmd_args_remaining) { - gpu->c0_xpos = gpu->buf[1] & 0xffff; - gpu->c0_ypos = gpu->buf[1] >> 16; + gpu->c0_xcnt = 0; + gpu->c0_ycnt = 0; + uint32_t c0_xpos = gpu->buf[1] & 0xffff; + uint32_t c0_ypos = gpu->buf[1] >> 16; gpu->c0_xsiz = gpu->buf[2] & 0xffff; gpu->c0_ysiz = gpu->buf[2] >> 16; + c0_xpos = c0_xpos & 0x3ff; + c0_ypos = c0_ypos & 0x1ff; + gpu->c0_xsiz = ((gpu->c0_xsiz - 1) & 0x3ff) + 1; + gpu->c0_ysiz = ((gpu->c0_ysiz - 1) & 0x1ff) + 1; + gpu->c0_tsiz = ((gpu->c0_xsiz * gpu->c0_ysiz) + 1) & 0xfffffffe; + gpu->c0_addr = c0_xpos + (c0_ypos * 1024); gpu->state = GPU_STATE_RECV_CMD; } @@ -720,12 +802,6 @@ void gpu_cmd_02(psx_gpu_t* gpu) { gpu->xsiz = (((gpu->xsiz & 0x3ff) + 0x0f) & 0xfffffff0); gpu->ysiz = gpu->ysiz & 0x1ff; - log_fatal("Render flat rectangle pos=(%u, %u) siz=(%u, %u), color=%02x", - gpu->v0.x, gpu->v0.y, - gpu->xsiz, gpu->ysiz, - gpu->color - ); - gpu->v0.x += gpu->off_x; gpu->v0.y += gpu->off_y; @@ -743,9 +819,12 @@ void psx_gpu_update_cmd(psx_gpu_t* gpu) { case 0x01: /* Cache clear */ break; case 0x02: gpu_cmd_02(gpu); break; case 0x28: gpu_cmd_28(gpu); break; - case 0x2c: gpu_cmd_2c(gpu); break; + case 0x2c: gpu_cmd_2d(gpu); break; case 0x2d: gpu_cmd_2d(gpu); break; + case 0x2e: gpu_cmd_2d(gpu); break; + case 0x2f: gpu_cmd_2d(gpu); break; case 0x30: gpu_cmd_30(gpu); break; + case 0x32: gpu_cmd_30(gpu); break; case 0x38: gpu_cmd_38(gpu); break; case 0x40: gpu_cmd_40(gpu); break; case 0x64: gpu_cmd_64(gpu); break; diff --git a/psx/dev/gpu.h b/psx/dev/gpu.h index 117e8f7..4419314 100644 --- a/psx/dev/gpu.h +++ b/psx/dev/gpu.h @@ -70,8 +70,10 @@ struct psx_gpu_t { uint32_t xcnt, ycnt; vertex_t v0, v1, v2, v3; uint32_t pal, texp; - uint32_t c0_xpos, c0_ypos; + uint32_t c0_xcnt, c0_ycnt; + uint32_t c0_addr; int c0_xsiz, c0_ysiz; + int c0_tsiz; // GPU state uint32_t state; diff --git a/psx/dev/pad.c b/psx/dev/pad.c index ca5b12b..1f14e33 100644 --- a/psx/dev/pad.c +++ b/psx/dev/pad.c @@ -69,11 +69,11 @@ void psx_pad_init(psx_pad_t* pad, psx_ic_t* ic) { uint32_t psx_pad_read32(psx_pad_t* pad, uint32_t offset) { switch (offset) { - case 0: log_fatal("RX read 32"); return pad_read_rx(pad); - case 4: log_fatal("ST read 32"); return pad_handle_stat_read(pad); - case 8: log_fatal("MD read 32"); return pad->mode; - case 10: log_fatal("CT read 32"); return pad->ctrl; - case 14: log_fatal("BD read 32"); return pad->baud; + case 0: return pad_read_rx(pad); + case 4: return pad_handle_stat_read(pad); + case 8: return pad->mode; + case 10: return pad->ctrl; + case 14: return pad->baud; } log_fatal("Unhandled 32-bit PAD read at offset %08x", offset); @@ -83,11 +83,11 @@ uint32_t psx_pad_read32(psx_pad_t* pad, uint32_t offset) { uint16_t psx_pad_read16(psx_pad_t* pad, uint32_t offset) { switch (offset) { - case 0: log_fatal("RX read 16"); return pad_read_rx(pad) & 0xffff; - case 4: log_fatal("ST read 16 %04x", pad_handle_stat_read(pad) & 0xffff); return pad_handle_stat_read(pad) & 0xffff; - case 8: log_fatal("MD read 16"); return pad->mode; - case 10: log_fatal("CT read 16 %04x", pad->ctrl & 0xffff); return pad->ctrl & 0xffff; - case 14: log_fatal("BD read 16"); return pad->baud; + case 0: return pad_read_rx(pad) & 0xffff; + case 4: return pad_handle_stat_read(pad) & 0xffff; + case 8: return pad->mode; + case 10: return pad->ctrl & 0xffff; + case 14: return pad->baud; } log_fatal("Unhandled 16-bit PAD read at offset %08x", offset); @@ -97,11 +97,11 @@ uint16_t psx_pad_read16(psx_pad_t* pad, uint32_t offset) { uint8_t psx_pad_read8(psx_pad_t* pad, uint32_t offset) { switch (offset) { - case 0: log_fatal("RX read 8 %02x", pad_read_rx(pad) & 0xff); return pad_read_rx(pad) & 0xff; - case 4: log_fatal("ST read 8"); return pad_handle_stat_read(pad) & 0xff; - case 8: log_fatal("MD read 8"); return pad->mode & 0xff; - case 10: log_fatal("CT read 8"); return pad->ctrl & 0xff; - case 14: log_fatal("BD read 8"); return pad->baud & 0xff; + case 0: return pad_read_rx(pad) & 0xff; + case 4: return pad_handle_stat_read(pad) & 0xff; + case 8: return pad->mode & 0xff; + case 10: return pad->ctrl & 0xff; + case 14: return pad->baud & 0xff; } log_fatal("Unhandled 8-bit PAD read at offset %08x", offset); @@ -111,10 +111,10 @@ uint8_t psx_pad_read8(psx_pad_t* pad, uint32_t offset) { void psx_pad_write32(psx_pad_t* pad, uint32_t offset, uint32_t value) { switch (offset) { - case 0: log_fatal("TX write 32 %08x", value); pad_write_tx(pad, value); return; - case 8: log_fatal("MD write 32 %08x", value); pad->mode = value & 0xffff; return; - case 10: log_fatal("CT write 32 %08x", value); pad_handle_ctrl_write(pad, value); return; - case 14: log_fatal("BD write 32 %08x", value); pad->baud = value & 0xffff; return; + case 0: pad_write_tx(pad, value); return; + case 8: pad->mode = value & 0xffff; return; + case 10: pad_handle_ctrl_write(pad, value); return; + case 14: pad->baud = value & 0xffff; return; } log_fatal("Unhandled 32-bit PAD write at offset %08x (%08x)", offset, value); @@ -122,10 +122,10 @@ void psx_pad_write32(psx_pad_t* pad, uint32_t offset, uint32_t value) { void psx_pad_write16(psx_pad_t* pad, uint32_t offset, uint16_t value) { switch (offset) { - case 0: log_fatal("TX write 16 %04x", value); pad_write_tx(pad, value); return; - case 8: log_fatal("MD write 16 %04x", value); pad->mode = value; return; - case 10: log_fatal("CT write 16 %04x", value); pad_handle_ctrl_write(pad, value); return; - case 14: log_fatal("BD write 16 %04x", value); pad->baud = value; return; + case 0: pad_write_tx(pad, value); return; + case 8: pad->mode = value; return; + case 10: pad_handle_ctrl_write(pad, value); return; + case 14: pad->baud = value; return; } log_fatal("Unhandled 16-bit PAD write at offset %08x (%04x)", offset, value); @@ -133,10 +133,10 @@ void psx_pad_write16(psx_pad_t* pad, uint32_t offset, uint16_t value) { void psx_pad_write8(psx_pad_t* pad, uint32_t offset, uint8_t value) { switch (offset) { - case 0: log_fatal("TX write 8 %02x", value); pad_write_tx(pad, value); return; - case 8: log_fatal("MD write 8 %02x", value); pad->mode = value; return; - case 10: log_fatal("CT write 8 %02x", value); pad_handle_ctrl_write(pad, value); return; - case 14: log_fatal("BD write 8 %02x", value); pad->baud = value; return; + case 0: pad_write_tx(pad, value); return; + case 8: pad->mode = value; return; + case 10: pad_handle_ctrl_write(pad, value); return; + case 14: pad->baud = value; return; } log_fatal("Unhandled 8-bit PAD write at offset %08x (%02x)", offset, value); @@ -167,8 +167,6 @@ void psx_pad_update(psx_pad_t* pad, int cyc) { if (pad->cycles_until_irq <= 0) { psx_ic_irq(pad->ic, IC_JOY); - log_fatal("PAD IRQ"); - pad->cycles_until_irq = 0; } }