started implementing some GPU abstractions and moved test to C 0ctri
authorJohn Tsiombikas <nuclear@member.fsf.org>
Mon, 11 Mar 2024 03:36:18 +0000 (05:36 +0200)
committerJohn Tsiombikas <nuclear@member.fsf.org>
Mon, 11 Mar 2024 03:36:18 +0000 (05:36 +0200)
.gitignore
Makefile
src/gpu.c [new file with mode: 0644]
src/gpu.h [new file with mode: 0644]
src/main.c
src/psxregs.h
src/startup.S

index 147abfb..ccff81e 100644 (file)
@@ -5,3 +5,8 @@
 *.psx
 *.map
 *.exe
+*.bin
+*.cue
+license*.dat
+disasm
+*.json
index 9cbaf72..dc59471 100644 (file)
--- 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 (file)
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 (file)
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_ */
index 31dbf45..c247f3c 100644 (file)
@@ -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;
 }
index dc3a7f1..d3042c3 100644 (file)
@@ -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_ */
index a058ea5..27935ef 100644 (file)
@@ -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