From a87340cddb40eab47956081c648adc0dfcd6d38d Mon Sep 17 00:00:00 2001 From: John Tsiombikas Date: Mon, 11 Mar 2024 05:36:18 +0200 Subject: [PATCH] started implementing some GPU abstractions and moved test to C --- .gitignore | 5 ++ Makefile | 6 ++- src/gpu.c | 93 +++++++++++++++++++++++++++++++++++ src/gpu.h | 30 ++++++++++++ src/main.c | 23 +++++++++ src/psxregs.h | 151 ++++++++++++++++++++++++++++++++++++++++++++++++++++----- src/startup.S | 64 ++++++++---------------- 7 files changed, 312 insertions(+), 60 deletions(-) create mode 100644 src/gpu.c create mode 100644 src/gpu.h diff --git a/.gitignore b/.gitignore index 147abfb..ccff81e 100644 --- a/.gitignore +++ b/.gitignore @@ -5,3 +5,8 @@ *.psx *.map *.exe +*.bin +*.cue +license*.dat +disasm +*.json diff --git a/Makefile b/Makefile index 9cbaf72..dc59471 100644 --- a/Makefile +++ b/Makefile @@ -14,7 +14,6 @@ TCPREFIX = mipsel-linux-gnu- CC = $(TCPREFIX)gcc AS = $(TCPREFIX)as LD = $(TCPREFIX)ld -OBJCOPY = $(TCPREFIX)objcopy arch = -march=r3000 -msoft-float -mno-abicalls -mno-shared -fno-pic @@ -23,7 +22,7 @@ ASFLAGS = $(arch) LDFLAGS = -T psx.ld -print-gc-sections $(bin): $(elf) - $(OBJCOPY) -O binary $< $@ + $(TCPREFIX)objcopy -O binary $< $@ $(elf): $(obj) $(LD) -o $@ $(obj) -Map link.map $(LDFLAGS) @@ -36,6 +35,9 @@ $(iso): cd/cd.xml cd/system.cnf $(bin) %.s: %.c $(CC) $(CFLAGS) -S -o $@ $< +disasm: $(elf) + $(TCPREFIX)objdump -D $< >$@ + .PHONY: iso iso: $(iso) diff --git a/src/gpu.c b/src/gpu.c new file mode 100644 index 0000000..bc2f1a4 --- /dev/null +++ b/src/gpu.c @@ -0,0 +1,93 @@ +#include "gpu.h" +#include "psxregs.h" + +void gpu_reset(void) +{ + REG_GP1 = 0; /* GPCMD(GP1_RESET) */ +} + +void gpu_setmode(int xsz, int ysz, int bpp, int rate) +{ + unsigned int x1, y0, y1; + unsigned int mode = (ysz >= 480) ? DISP_V480 | DISP_ILACE : 0; + + switch(xsz) { + case 320: + mode |= DISP_H320; + break; + case 368: + mode |= DISP_H368; + break; + case 512: + mode |= DISP_H512; + break; + case 640: + mode |= DISP_H640; + break; + default: + break; + } + + if(bpp >= 24) mode |= DISP_24BPP; + if(rate == 50) mode |= DISP_PAL; + + REG_GP1 = GPCMD(GP1_DISPMODE) | mode; + + /* also set display ranges */ + x1 = 0x260 + 320 * 8; + REG_GP1 = GPCMD(GP1_HDISP) | 0x260 | (x1 << 12); + if(mode & DISP_PAL) { + y0 = 0xa3 - 264 / 2; + y1 = 0xa3 + 264 / 2; + } else { + y0 = 0x88 - 224 / 2; + y1 = 0x88 + 224 / 2; + } + REG_GP1 = GPCMD(GP1_VDISP) | y0 | (y1 << 10); +} + +void gpu_display(int en) +{ + REG_GP1 = GPCMD(GP1_DISPEN) | (en ? 0 : 1); +} + +void gpu_cliprect(int x, int y, int w, int h) +{ + REG_GP0 = GPCMD(GP0_CLIP_TL) | x | (y << 10); + REG_GP0 = GPCMD(GP0_CLIP_BR) | (w - 1) | ((h - 1) << 10); +} + +void gpu_origin(int x, int y) +{ + REG_GP0 = GPCMD(GP0_ORIGIN) | x | (y << 11); +} + +/* ---- drawing ---- */ + +void gpu_fillrect(int x, int y, int w, int h, unsigned int col) +{ + REG_GP0 = GPCMD(GP0_FILLRECT) | col; + REG_GP0 = x | (y << 16); + REG_GP0 = w | (h << 16); +} + +void gpu_draw_flat(int cmd, uint32_t color, struct gpu_vert *data, int vcount) +{ + REG_GP0 = GPCMD(cmd) | color; + while(vcount-- > 0) { + REG_GP0 = *(uint32_t*)data++; + } +} + +void gpu_draw_gouraud(int cmd, struct gpu_gvert *data, int vcount) +{ + REG_GP0 = GPCMD(cmd) | data->color; + REG_GP0 = *(uint32_t*)&data->x; + data++; + + while(--vcount > 0) { + REG_GP0 = data->color; + REG_GP0 = *(uint32_t*)&data->x; + data++; + } +} diff --git a/src/gpu.h b/src/gpu.h new file mode 100644 index 0000000..81d341f --- /dev/null +++ b/src/gpu.h @@ -0,0 +1,30 @@ +#ifndef GPU_H_ +#define GPU_H_ + +typedef short int16_t; +typedef unsigned long uint32_t; + +/* flat vertex */ +struct gpu_vert { + int16_t x, y; +}; + +/* gouraud vertex */ +struct gpu_gvert { + uint32_t color; + int16_t x, y; +}; + + +void gpu_reset(void); +void gpu_setmode(int xsz, int ysz, int bpp, int rate); +void gpu_display(int en); +void gpu_cliprect(int x, int y, int w, int h); +void gpu_origin(int x, int y); + +void gpu_fillrect(int x, int y, int w, int h, unsigned int col); + +void gpu_draw_flat(int cmd, uint32_t color, struct gpu_vert *data, int vcount); +void gpu_draw_gouraud(int cmd, struct gpu_gvert *data, int vcount); + +#endif /* GPU_H_ */ diff --git a/src/main.c b/src/main.c index 31dbf45..c247f3c 100644 --- a/src/main.c +++ b/src/main.c @@ -1,4 +1,27 @@ +#include "gpu.h" +#include "psxregs.h" + +static struct gpu_gvert triangle[] = { + {0xff0000, 160, 16}, {0x00ff00, 32, 180}, {0x0000ff, 280, 220} +}; + +int dbg; + int main(void) { + gpu_reset(); + gpu_setmode(320, 264, 15, 50); + gpu_display(1); + + REG_GP0 = GPCMD(GP0_TEXPG) | TEXPG_DRAWDISP | TEXPG_DITHER; + + gpu_cliprect(0, 0, 320, 264); + gpu_origin(0, 0); + + gpu_fillrect(0, 0, 320, 264, 0x003f00); + + gpu_draw_gouraud(GP0_GTRI, triangle, 3); + + for(;;); return 0; } diff --git a/src/psxregs.h b/src/psxregs.h index dc3a7f1..d3042c3 100644 --- a/src/psxregs.h +++ b/src/psxregs.h @@ -1,27 +1,27 @@ #ifndef PSXREGS_H_ #define PSXREGS_H_ -#define REG_BASE 0x1f800000 -#define REGPTR32(x) (*(volatile unsigned long*)(REG_BASE | (x))) -#define REGPTR16(x) (*(volatile unsigned short*)(REG_BASE | (x))) +#define REG_BASE 0x1f800000 +#define REGPTR32(x) (*(volatile unsigned long*)(REG_BASE | (x))) +#define REGPTR16(x) (*(volatile unsigned short*)(REG_BASE | (x))) /* --- GPU --- */ -#define REGN_GP0 0x1810 -#define REGN_GP1 0x1814 +#define REGN_GP0 0x1810 +#define REGN_GP1 0x1814 #define REGN_GPUREAD REGN_GP0 #define REGN_GPUSTAT REGN_GP1 -#define REG_GP0 REGPTR32(REGN_GP0) -#define REG_GP1 REGPTR32(REGN_GP1) -#define REG_GPUREAD REGPTR32(REGN_GPUREAD) -#define REG_GPUSTAT REGPTR32(REGN_GPUSTAT) +#define REG_GP0 REGPTR32(REGN_GP0) +#define REG_GP1 REGPTR32(REGN_GP1) +#define REG_GPUREAD REGPTR32(REGN_GPUREAD) +#define REG_GPUSTAT REGPTR32(REGN_GPUSTAT) /* --- interrupts --- */ -#define REGN_ISTAT 1070h -#define REGN_IMASK 1074h +#define REGN_ISTAT 1070h +#define REGN_IMASK 1074h -#define REG_ISTAT REGPTR32(REGN_ISTAT) -#define REG_IMASK REGPTR32(REGN_IMASK) +#define REG_ISTAT REGPTR32(REGN_ISTAT) +#define REG_IMASK REGPTR32(REGN_IMASK) enum { IRQ_VBLANK = 0x0001, @@ -37,4 +37,129 @@ enum { IRQ_LPEN = 0x0400 }; +#define GPCMD(cmd) ((cmd) << 24) + +enum { + GP1_RESET = 0, + GP1_RESET_CMDBUF = 0x01, + GP1_IACK = 0x02, + GP1_DISPEN = 0x03, /* 0:on, 1:off */ + GP1_DMADIR = 0x04, /* 0:off, 1:fifo, 2:cpu->gpu, 3:gpu->cpu */ + GP1_START = 0x05, /* bits [0,9]: X, [10,18]: Y */ + GP1_HDISP = 0x06, /* (pix*8) bits [0,11]: left, [12,23]: right */ + GP1_VDISP = 0x07, /* bits [0,9]: top, [10,19]: bottom */ + GP1_DISPMODE = 0x08, /* see DISP_* flags */ +}; + +#define DISP_H256 0 +#define DISP_H320 0x01 +#define DISP_H512 0x02 +#define DISP_H640 0x03 +#define DISP_V240 0 +#define DISP_V480 0x04 +#define DISP_NTSC 0 +#define DISP_PAL 0x08 +#define DISP_15BPP 0 +#define DISP_24BPP 0x10 +#define DISP_ILACE 0x20 +#define DISP_H368 0x40 + + +/* primitive bits for GP0 drawing commands */ +enum { + PRIM_TRI = 0x20, + PRIM_QUAD = 0x28, + PRIM_LINE = 0x40, + PRIM_PLINE = 0x48, + PRIM_RECT = 0x60, + PRIM_POINT = 0x6a, /* rect 1x1 */ + PRIM_RECT8 = 0x70, + PRIM_RECT16 = 0x78, + + PRIM_NOMOD = 0x01, /* no-modulate tex/color bit */ + PRIM_ST = 0x02, /* semi-transparent bit */ + PRIM_TEX = 0x04, /* textured bit */ + PRIM_GOURAUD = 0x10 /* gouraud bit */ +}; + +enum { + GP0_CLEAR_CACHE = 0, + GP0_FILLRECT = 0x02, /* color24+cmd/topleft/size */ + GP0_BLT_VIDVID = 0x80, /* cmd/src/dst/size */ + GP0_BLT_CPUVID = 0xa0, /* cmd/dst/size/data(dma?) */ + GP0_BLT_VIDCPU = 0xc0, /* cmd/src/size/data(GPUREAD|dma) */ + GP0_TEXPG = 0xe1, + GP0_TEXWIN = 0xe2, + GP0_CLIP_TL = 0xe3, + GP0_CLIP_BR = 0xe4, + GP0_ORIGIN = 0xe5, + + /* flat tri/quad: cmd+color/v0/.../vN (16+16 YYYYXXXX) */ + GP0_TRI = PRIM_TRI, + GP0_TRI_ST = PRIM_TRI | PRIM_ST, + GP0_QUAD = PRIM_QUAD, + GP0_QUAD_ST = PRIM_QUAD | PRIM_ST, + /* textured tri/quad: cmd+color/v0/uv0+pal/v1/uv1+texpage/v2/uv2/.. */ + GP0_TRI_TEXMOD = PRIM_TRI | PRIM_TEX, + GP0_TRI_TEX = PRIM_TRI | PRIM_TEX | PRIM_NOMOD, + GP0_TRI_ST_TEXMOD = PRIM_TRI | PRIM_ST | PRIM_TEX, + GP0_TRI_ST_TEX = PRIM_TRI | PRIM_ST | PRIM_TEX | PRIM_NOMOD, + GP0_QUAD_TEXMOD = PRIM_QUAD | PRIM_TEX, + GP0_QUAD_TEX = PRIM_QUAD | PRIM_TEX | PRIM_NOMOD, + GP0_QUAD_ST_TEXMOD = PRIM_QUAD | PRIM_ST | PRIM_TEX, + GP0_QUAD_ST_TEX = PRIM_QUAD | PRIM_ST | PRIM_TEX | PRIM_NOMOD, + /* gouraud tri/quad: cmd+color0/v0/c1/v1/.../cN/vN */ + GP0_GTRI = PRIM_TRI | PRIM_GOURAUD, + GP0_GTRI_ST = PRIM_TRI | PRIM_GOURAUD | PRIM_ST, + GP0_GQUAD = PRIM_QUAD | PRIM_GOURAUD, + GP0_GQUAD_ST = PRIM_QUAD | PRIM_GOURAUD | PRIM_ST, + /* gouraud tex tri/quad: cmd+color0/v0/uv0+pal/c1/v1/uv1+texpage/c2/v2/uv2/... */ + GP0_GTRI_TEXMOD = PRIM_TRI | PRIM_GOURAUD | PRIM_TEX, + GP0_GTRI_ST_TEXMOD = PRIM_TRI | PRIM_GOURAUD | PRIM_ST | PRIM_TEX, + GP0_GQUAD_TEXMOD = PRIM_QUAD | PRIM_GOURAUD | PRIM_TEX, + GP0_GQUAD_ST_TEXMOD = PRIM_QUAD | PRIM_GOURAUD | PRIM_ST | PRIM_TEX, + + /* line/poly-line: cmd+color/v0/.../vN/PLINE_END(55555555h) */ + GP0_LINE = PRIM_LINE, + GP0_LINE_ST = PRIM_LINE | PRIM_ST, + GP0_PLINE = PRIM_PLINE, + GP0_PLINE_ST = PRIM_PLINE | PRIM_ST, + /* line/poly-line: cmd+color0/v0/c1/v1/.../cN/vN/PLINE_END */ + GP0_GLINE = PRIM_LINE | PRIM_GOURAUD, + GP0_GLINE_ST = PRIM_LINE | PRIM_GOURAUD | PRIM_ST, + GP0_GPLINE = PRIM_PLINE | PRIM_GOURAUD, + GP0_GPLINE_ST = PRIM_PLINE | PRIM_GOURAUD | PRIM_ST, + + /* rect: cmd+col/pos/size(for variable rect) */ + GP0_RECT = PRIM_RECT, + GP0_RECT_ST = PRIM_RECT | PRIM_ST, + GP0_POINT = PRIM_POINT, + GP0_POINT_ST = PRIM_POINT | PRIM_ST, + GP0_RECT8 = PRIM_RECT8, + GP0_RECT8_ST = PRIM_RECT8 | PRIM_ST, + GP0_RECT16 = PRIM_RECT16, + GP0_RECT16_ST = PRIM_RECT16 | PRIM_ST, + /* rect: cmd+col/pos/uv0+pal/size(for var rect), texpage in GP0(e1h) */ + GP0_RECT_TEXMOD = PRIM_RECT | PRIM_TEX, + GP0_RECT_TEX = PRIM_RECT | PRIM_TEX | PRIM_NOMOD, + GP0_RECT_ST_TEXMOD = PRIM_RECT | PRIM_ST | PRIM_TEX, + GP0_RECT_ST_TEX = PRIM_RECT | PRIM_ST | PRIM_TEX | PRIM_NOMOD, + /* ... TODO and the rest ... */ +}; + + +enum { + TEXPG_BLEND_HALF = 0, + TEXPG_BLEND_ADD = 0x0020, + TEXPG_BLEND_SUB = 0x0040, + TEXPG_BLEND_QUART = 0x0060, + TEXPG_8BPP = 0x0080, + TEXPG_15BPP = 0x0100, + TEXPG_DRAWDISP = 0x0200, + TEXPG_DITHER = 0x0400, + TEXPG_NOTEX = 0x0800, + TEXPG_XFLIP = 0x1000, + TEXPG_YFLIP = 0x2000 +}; + #endif /* PSXREGS_H_ */ diff --git a/src/startup.S b/src/startup.S index a058ea5..27935ef 100644 --- a/src/startup.S +++ b/src/startup.S @@ -8,56 +8,30 @@ .section .startup .extern main + .extern _stacktop + .extern _gp + .extern _bss_start + .extern _bss_end .globl _start _start: - lui a0, REG_BASE + la sp, _stacktop + la gp, _gp - # setup screen mode - sw zero, REG_GP1(a0) # GP1 0: reset - - li t0, 0x03000000 # GP1 3: display enable - sw t0, REG_GP1(a0) - li t0, 0x08000009 # GP1 8: display mode (320x240 15bpp PAL) - sw t0, REG_GP1(a0) - li t0, 0x06c60260 # GP1 6: horiz. display range (608-3168) - sw t0, REG_GP1(a0) - li t0, 0x07049c1f # GP1 7: vert. display range (31-295) - sw t0, REG_GP1(a0) - - li t0, 0xe1000600 # GP0 e1: draw mode (draw allowed & dither enable) - sw t0, REG_GP0(a0) - li t0, 0xe3000000 # draw area top left (0, 0) - sw t0, REG_GP0(a0) - li t0, 0xe4041d3f # draw area bottom right (319,263) - sw t0, REG_GP0(a0) - li t0, 0xe5000000 # draw offset (0, 0) - sw t0, REG_GP0(a0) - - # clear screen - li t0, 0x02302010 # cmd 2: fill area (BBGGRR) - sw t0, REG_GP0(a0) - sw zero, REG_GP0(a0) # ... top left 0,0 (YYYYXXXX) - li t0, 0x0108013f # ... size 319x239 (HHHHWWWW) - sw t0, REG_GP0(a0) - - # draw gouraud triangle - li t0, 0x30ff0000 # cmd 30: draw gouraud triangle (+BBGGRR vert0) - sw t0, REG_GP0(a0) - li t0, 160 | (16 << 16) # ... vertex(160, 16) - sw t0, REG_GP0(a0) - - li t0, 0x0000ff00 # ... color vert1 - sw t0, REG_GP0(a0) - li t0, 32 | (180 << 16) # ... vertex(32, 180) - sw t0, REG_GP0(a0) - - li t0, 0x000000ff # ... color vert2 - sw t0, REG_GP0(a0) - li t0, 280 | (220 << 16) # ... vertex(220, 280) - sw t0, REG_GP0(a0) + la t0, _bss_start + la t1, _bss_end + nop + beq t0, t1, donebss + nop +zerobss: + sw zero, (t0) + addi t0, t0, 4 + nop + bne t0, t1, zerobss + nop +donebss: - #jal main + jal main nop 0: b 0b -- 1.7.10.4