--- /dev/null
+#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++;
+ }
+}
#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,
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_ */
.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