diff --git a/.vscode/c_cpp_properties.json b/.vscode/c_cpp_properties.json index 165c800..99c5ca1 100644 --- a/.vscode/c_cpp_properties.json +++ b/.vscode/c_cpp_properties.json @@ -4,17 +4,14 @@ "name": "The Usual", "includePath": [ "${env:AppData}/mips/mips/include", + "${workspaceFolder}/code", "${workspaceFolder}/toolchain/pcsx-redux/src/mips", "${workspaceFolder}/toolchain/psyq-4_7/include" ], "cStandard": "c17", "defines": [ - "__STDC_HOSTED__ = 0" - ], - "defines": [ - "_DEBUG", - "UNICODE", - "_UNICODE" + "__STDC_HOSTED__ = 0", + "INTELLISENSE_DIRECTIVES=1" ], "intelliSenseMode": "gcc-x86" } diff --git a/.vscode/launch.json b/.vscode/launch.json index cd83f89..15f80a9 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -27,6 +27,30 @@ "tbreak main", "continue" ] + }, + { + "name": "Debug: Hello GPU Psy-Q!", + "type": "gdb", + "request": "attach", + "target": "localhost:3333", + "remote": true, + "cwd": "${workspaceRoot}/build", + "valuesFormatting": "parseText", + "stopAtConnect": true, + "gdbpath": "gdb-multiarch", + "windows": { + "gdbpath": "gdb-multiarch.exe" + }, + "osx": { + "gdbpath": "gdb" + }, + "executable": "${workspaceRoot}/build/hello_gpu.elf", + "autorun": [ + "monitor reset shellhalt", + "load hello_gpu.elf", + "tbreak main", + "continue" + ] } ] } diff --git a/.vscode/settings.json b/.vscode/settings.json index b89b2d3..d72c5fa 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,9 +1,21 @@ { "files.associations": { "*.rmd": "markdown", - "*.s": "armips", + "*.s": "gas", + "*.asm": "gas", "stdlib.h": "c", "libetc.h": "c", - "libgpu.h": "c" + "libgpu.h": "c", + "stddef.h": "c", + "abs.h": "c", + "qsort.h": "c", + "malloc.h": "c", + "convert.h": "c", + "type_traits": "c", + "xlocmon": "c", + "iterator": "c", + "regex": "c", + "dsl.h": "c", + "xlocale": "c" } } \ No newline at end of file diff --git a/code/asmdd/dsl.asm b/code/asmdd/dsl.asm new file mode 100644 index 0000000..c41e36d --- /dev/null +++ b/code/asmdd/dsl.asm @@ -0,0 +1,135 @@ +# Symbol Alias Table + +# Instructions +# Load +.macro load_addr p1, p2 + la \p1, \p2 +.endm +.macro load_imm p1, p2 + li \p1, \p2 +.endm +.macro load_uimm p1, p2 + lui \p1, \p2 +.endm +.macro load_word p1, p2 + lw \p1, \p2 +.endm +# Store +.macro store_word p1, p2 + sw \p1, \p2 +.endm +# Shift +.macro shift_ll p1, p2, p3 + sll \p1, \p2, \p3 +.endm +.macro shift_rl p1, p2, p3 + srl \p1, \p2, \p3 +.endm +.macro shift_ra p1, p2, p3 + sra \p1, \p2, \p3 +.endm +# Addition +.macro add_s p1, p2, p3 + add \p1, \p2, \p3 +.endm +.macro add_u p1, p2, p3 + add \p1, \p2, \p3 +.endm +.macro add_si p1, p2, p3 + addi \p1, \p2, \p3 +.endm +.macro add_ui p1, p2, p3 + addiu \p1, \p2, \p3 +.endm +# Subtraction +.macro sub_s p1, p2, p3 + sub \p1, \p2, \p3 +.endm +.macro sub_u p1, p2, p3 + subu \p1, \p2, \p3 +.endm +# Multiplication + +# Division +.macro div_s p1, p2 + div \p1, \p2 +.endm +.macro div_u p1, p2 + divu \p1, \p2 +.endm +.macro mov_from_high p1 + mfhi \p1 +.endm +.macro mov_from_low p1 + mflo \p1 +.endm +# Branch +.macro branch_ne_zero p1, p2 + bnez \p1, \p2 +.endm +.macro branch_equal p1, p2, p3 + beq \p1, \p2, \p3 +.endm +.macro branch_gt_equal p1, p2, p3 + bge \p1, \p2, \p3 +.endm +.macro branch_gt p1, p2, p3 + bgt \p1, \p2, \p3 +.endm +.macro branch_lt p1, p2, p3 + blt \p1, \p2, \p3 +.endm +# Jump +.macro jump p1 + j \p1 +.endm +.macro jump_nlink p1 + jal \p1 +.endm +.macro jump_reg p1 + jr \p1 +.endm +.macro jump_nreg p1 + jalr \p1 +.endm + +# Registers +# Stack +.equiv rstack_ptr, $sp # I have this but won't really use the alias.. +# Temporaries, may be changed by subroutines +.set rtmp_0, $t0 +.set rtmp_1, $t1 +.set rtmp_2, $t2 +.set rtmp_3, $t3 +.set rtmp_4, $t4 +# Static Variables +.set rstatic_0, $s0 +.set rstatic_1, $s1 +.set rstatic_2, $s2 +.set rstatic_3, $s3 +.set rstatic_4, $s4 +.set rstatic_5, $s5 +.set rstatic_6, $s6 +.set rstatic_7, $s7 +# Subroutine arguments +.set rarg_0, $a0 +.set rarg_1, $a1 +.set rarg_2, $a2 +.set rarg_3, $a3 +# Subroutine return values +.set rret_0, $v0 +.set rret_1, $v1 +# Subroutine return address when doing a sub +.set rret_addr, $ra + +# Data Widths +.set byte, 1 +.set word, 4 + +.macro stack_alloc amount + add_ui $sp, - \amount +.endm + +.macro stack_release amount + add_ui $sp, \amount +.endm diff --git a/code/asmdd/gp.asm b/code/asmdd/gp.asm new file mode 100644 index 0000000..01d385a --- /dev/null +++ b/code/asmdd/gp.asm @@ -0,0 +1,191 @@ +# GPU Registers +.equiv gpio_port0, 0x1810 # 1F801810h-Write GP0: Send GP0 Commands/Packets (Rendering and VRAM Access) +.equiv gpio_port1, 0x1814 # 1F801814h-Write GP1: Send GP1 Commands (Display Control) (and DMA Control) + +# GPU Command Format: [7:8] Command (8-bit), [0:6] Paraemter (24-bit) + +.equiv gcmd_offset, 24 + +.equiv gcmd_Reset, 0b000 +.equiv gcmd_Polygon, 0b001 +.equiv gcmd_Line, 0b010 +.equiv gcmd_Rect, 0b011 +.equiv gcmd_VM_to_VM, 0b100 +.equiv gcmd_CPU_to_VM, 0b101 +.equiv gcmd_VM_to_CPU, 0b110 +.equiv gcmd_Environment, 0b111 + +.equiv gcmd_SetDrawMode, 0xE1 +.equiv gcmd_SetTextureWindow, 0xE2 +.equiv gcmd_SetDrawArea_TopLeft, 0xE3 +.equiv gcmd_SetDrawArea_BotRight, 0xE4 +.equiv gcmd_SetDrawOffset, 0xE5 +.equiv gcmd_SetMaskBit, 0xE6 + +.equiv gcmd_ResetCommandBuffer, 0x01 +.equiv gcmd_AcknowledgeGPUInterrupt, 0x02 +.equiv gcmd_DisplayEnable, 0x03 +.equiv gcmd_DMA_Request, 0x04 +.equiv gcmd_DispArea_Start, 0x05 +.equiv gcmd_HorizontalDisplayRange, 0x06 +.equiv gcmd_VerticalDisplayRange, 0x07 +.equiv gcmd_DisplayMode, 0x08 + +.equiv gcmd_SetVramSize, 0x09 + +.equiv gp_Reset, gcmd_Reset << gcmd_offset + +# GP1(03h) - Display Enable +# On: 0x0 +# Off: 0x1 +.equiv gp_DisplayEnabled, gcmd_DisplayEnable << gcmd_offset | 0x0 +.equiv gp_DisplayDisabled, gcmd_DisplayEnable << gcmd_offset | 0x1 + +# GP1(04h) - DMA Direction / Data Request +# 0-1 DMA Direction (0=Off, 1=FIFO, 2=CPUtoGP0, 3=GPUREADtoCPU) ;GPUSTAT.29-30 +# 2-23 Not used (zero) +.equiv gp_DMA_FIFO, 1 +.equiv gp_DMA_CPU_to_GPU, 2 +.equiv gp_DMA_GPU_to_CPU, 3 +.equiv gp_DMA_Request, gcmd_DMA_Request << gcmd_offset + +# GP1(06h) - Horizontal Display range (on Screen) +# X2 = X1 + pixels * cycles_per_pix +# 0 - 11 X1 (260h + 0) ; 12bit ; \ counted in video clock units, +# 12 - 23 X2 (260h + 320 * 8) ; 12bit ; / relative to HSYNC +.equiv gp_HorizontalDisplayRange_3168_608, gcmd_HorizontalDisplayRange << gcmd_offset | 0xC60 << 12 | 0x260 + +# GP1(07h) - Vertical Display range (on Screen) +# 0 - 9 Y1 (NTSC = 88h - (240 / 2), (PAL = A3h - (288 / 2)) ; \ scanline numbers on screen, +# 10 - 19 Y2 (NTSC = 88h + (240 / 2), (PAL = A3h + (288 / 2)) ; / relative to VSYNC +# 20 - 23 Not used (zero) +.equiv gp_VerticalDiplayRange, gcmd_VerticalDisplayRange << gcmd_offset +.equiv gp_VerticalDisplayRange_264_24, gp_VerticalDiplayRange | 264 << 10 | 24 +.equiv gp_VerticalDisplayRange_504_24, gp_VerticalDiplayRange | 504 << 10 | 24 + +# GP1(08h) - Display mode +# 0-1 Horizontal Resolution 1 (0=256, 1=320, 2=512, 3=640) ;GPUSTAT.17-18 +# 2 Vertical Resolution (0=240, 1=480, when Bit5=1) ;GPUSTAT.19 +# 3 Video Mode (0=NTSC/60Hz, 1=PAL/50Hz) ;GPUSTAT.20 +# 4 Display Area Color Depth (0=15bit, 1=24bit) ;GPUSTAT.21 +# 5 Vertical Interlace (0=Off, 1=On) ;GPUSTAT.22 +# 6 Horizontal Resolution 2 (0=256/320/512/640, 1=368) ;GPUSTAT.16 +# 7 Flip screen horizontally (0=Off, 1=On, v1 only) ;GPUSTAT.14 +# 8-23 Not used (zero) +.equiv gp_DisplayMode, 0x8 << gcmd_offset +.equiv gp_Disp_HRes_256, 0x0 +.equiv gp_Disp_HRes_320, 0x1 +.equiv gp_Disp_HRes_512, 0x2 +.equiv gp_Disp_HRes_640, 0x3 +.equiv gp_Disp_VRes_240, 0x0 << 2 +.equiv gp_Disp_VRes_480, 0x1 << 2 +.equiv gp_Disp_Color15, 0x0 << 4 +.equiv gp_Disp_Color24, 0x1 << 4 +.equiv gp_Disp_VInterlace, 0x1 << 5 +.equiv gp_DisplayMode_320x240_15bit_NTSC, gp_DisplayMode | gp_Disp_HRes_320 | gp_Disp_VRes_240 | gp_Disp_Color15 +.equiv gp_DisplayMOde_640x480_24bbp_NTSC, gp_DisplayMode | gp_Disp_HRes_640 | gp_Disp_VRes_480 | gp_Disp_Color24 | gp_Disp_VInterlace + +# GP0(E1h) - Draw Mode setting (aka "Texpage") +# 0 - 3 Texture page X Base (N * 64) (ie. in 64-halfword steps) ; GPUSTAT.0-3 +# 4 Texture page Y Base 1 (N * 256) (ie. 0, 256, 512 or 768) ; GPUSTAT.4 +# 5 - 6 Semi-transparency (0 = B / 2 + F / 2, 1 = B + F, 2 = B - F, 3 = B + F / 4) ; GPUSTAT.5-6 +# 7 - 8 Texture page colors (0 = 4 bit, 1 = 8bit, 2 = 15bit, 3 = Reserved) ; GPUSTAT.7-8 +# 9 Dither 24bit to 15bit (0=Off / strip LSBs, 1 = Dither Enabled) ; GPUSTAT.9 +# 10 Drawing to display area (0=Prohibited, 1=Allowed) ; GPUSTAT.10 +# 11 Texture page Y Base 2 (N * 512) (only for 2 MB VRAM) ; GPUSTAT.15 +# 12 Textured Rectangle X-Flip (BIOS does set this bit on power-up...?) +# 13 Textured Rectangle Y-Flip (BIOS does set it equal to GPUSTAT.13...?) +# 14 - 23 Not used (should be 0) +# 24 - 31 Command (E1h) +.equiv gp_SetDisplayMode_DrawAllowed, 10 +.equiv gp_SetDisplayMode_DipArea, gcmd_SetDrawMode << gcmd_offset | 0x1 << gp_SetDisplayMode_DrawAllowed + +# GP0(E3h) - Set Drawing Area top left (X1,Y1) +# GP0(E4h) - Set Drawing Area bottom right (X2,Y2) +# Sets the drawing area corners. The Render commands GP0(20h..7Fh) +# are automatically clipping any pixels that are outside of this region. +# 0 - 9 X-coordinate (0..1023) +# 10 - 18 Y-coordinate (0..511) ; \ on v0 GPU (max 1 MB VRAM) +# 19 - 23 Not used (zero) ; / +# 10 - 19 Y-coordinate (0..1023) ; \ on v2 GPU (max 2 MB VRAM) +# 20 - 23 Not used (zero) ; / +# 24 - 31 Command (Exh) +.equiv gp_SetArea_TopLeft, gcmd_SetDrawArea_TopLeft << gcmd_offset +.equiv gp_SetArea_BottomRight, gcmd_SetDrawArea_BotRight << gcmd_offset + +# GP0(E5h) - Set Drawing Offset (X,Y) +# 0-9 X-coordinate (0..1023) +# 10-18 Y-coordinate (0..511) ;\on v0 GPU (max 1 MB VRAM) +# 19-23 Not used (zero) ;/ +# 10-19 Y-coordinate (0..1023) ;\on v2 GPU (max 2 MB VRAM) +# 20-23 Not used (zero) ;/ +# 24-31 Command (Exh) +.equiv gp_SetOffset, gcmd_SetDrawOffset << gcmd_offset + +# GPU Memory Transfer Commands + +# GP0(02h) Fill Vram +# GP0(02h) - Fill Rectangle in VRAM +# 1st Color+Command (CcBbGgRrh) ;24bit RGB value (see note) +# 2nd Top Left Corner (YyyyXxxxh) ;Xpos counted in halfwords, steps of 10h +# 3rd Width+Height (YsizXsizh) ;Xsiz counted in halfwords, steps of 10h +# Fills the area in the frame buffer with the value in RGB. +# Horizontally the filling is done in 16-pixel (32-bytes) units (see below masking/rounding). +# The "Color" parameter is a 24bit RGB value, however, the actual fill data is 16bit: +# The hardware automatically converts the 24bit RGB value to 15bit RGB (with bit15=0). +# Fill is NOT affected by the Mask settings (acts as if Mask.Bit0,1 are both zero). +.equiv gp_RectFillVM, 0x02 << gcmd_offset + +# GP0(A0h) - Copy Rectangle (CPU to VRAM) +# Transfers data from CPU to frame buffer. +# If the number of halfwords to be sent is odd, an extra halfword should be sent, +# as packets consist of 32bits words. The transfer is affected by Mask setting. +# 1st Command (Cc000000h) +# 2nd Destination Coord (YyyyXxxxh) ;Xpos counted in halfwords +# 3rd Width+Height (YsizXsizh) ;Xsiz counted in halfwords +# ... Data (...) <--- usually transferred via DMA +.equiv gp_Blit_VM_VM, gcmd_VM_to_VM << gcmd_offset +.equiv gp_Blit_CPU_VM, gcmd_CPU_to_VM << gcmd_offset +.equiv gp_Blit_VM_CPU, gcmd_VM_to_CPU << gcmd_offset + +# GPU Render Polygon Commands + +# When the upper 3 bits of the first GP0 command are set to 1 (001), +# then the command can be decoded using the following bitfield: +# bit number value meaning +# 31-29 001 polygon render +# 28 1/0 gouraud / flat shading +# 27 1/0 4 / 3 vertices +# 26 1/0 textured / untextured +# 25 1/0 semi-transparent / opaque +# 24 1/0 raw texture / modulation +# 23-0 rgb first color value. +.equiv gp_Poly_FirstColor, 0 +.equiv gp_Poly_RawTexture, 1 << 24 +.equiv gp_Poly_SemiTrans, 1 << 25 +.equiv gp_Poly_Textured, 1 << 26 +.equiv gp_Poly_Quad, 1 << 27 +.equiv gp_Poly_Tri, 0 << 27 +.equiv gp_Poly_ShadeFlat, 0 << 28 +.equiv gp_Poly_ShadeGourand, 1 << 28 +.equiv gp_Polygon, 1 << 29 + +.equiv gp_Quad, gp_Polygon | gp_Poly_Quad + +.equiv gp_b10_X, 0 +.equiv gp_b10_Y, 10 +.equiv gp_b16_X, 0 +.equiv gp_b16_Y, 16 + +.equiv gp_pixel16, (2 * byte) +.equiv gp_pixel24, (3 * byte) +.equiv gp_vec2, word + +.macro gp_push_pak port, reg_scratch, packet + load_imm \reg_scratch, \packet + store_word \reg_scratch, \port +.endm +.macro gcmd_push port, reg_scratch, cmd + load_imm \reg_scratch, \cmd + store_word \reg_scratch, \port +.endm diff --git a/code/asmdd/io.asm b/code/asmdd/io.asm new file mode 100644 index 0000000..1d9e479 --- /dev/null +++ b/code/asmdd/io.asm @@ -0,0 +1 @@ +.equiv IO_BASE_ADDR, 0x1F80 diff --git a/code/duffle/dsl.h b/code/duffle/dsl.h new file mode 100644 index 0000000..8bd1b4d --- /dev/null +++ b/code/duffle/dsl.h @@ -0,0 +1,72 @@ +#ifdef INTELLISENSE_DIRECTIVES +# pragma once +#endif + +typedef unsigned char U8; +typedef signed char S8; +typedef unsigned short U16; +typedef signed short S16; +typedef unsigned int U32; +typedef signed int S32; +typedef unsigned char BYTE; +typedef unsigned int USIZE; +typedef signed int SSIZE; +typedef S8 B8; +typedef S16 B16; +typedef S32 B32; +enum { + false = 0, + true = 1, + true_overflow, +}; +#define glue_impl(A, B) A ## B +#define glue(A, B) glue_impl(A, B) +#define stringify_impl(S) #S +#define stringify(S) stringify_impl(S) +#define tmpl(prefix, type) prefix ## _ ## type + +#define alignas _Alignas +#define alignof _Alignof +#define byte_pad(amount, ...) Byte glue(_PAD_, __VA_ARGS__) [amount] +#define farray_len(array) (SSIZE)sizeof(array) / size_of( typeof((array)[0])) +#define farray_init(type, ...) (type[]){__VA_ARGS__} +#define def_farray(type, len) type A ## len ## _ ## type[len] +#define def_enum(underlying_type, symbol) underlying_type symbol; enum symbol +#define def_struct(symbol) struct symbol symbol; struct symbol +#define def_union(symbol) union symbol symbol; union symbol +#define fn(symbol) symbol +#define opt_args(symbol, ...) &(symbol){__VA_ARGS__} +#define ret_type(type) type +#define local_persist static +#define global static +#define offset_of(type, member) cast(SSIZE, & (((type*) 0)->member)) +#define static_assert _Static_assert +#define typeof __typeof__ +#define typeof_ptr(ptr) typeof(ptr[0]) +#define typeof_same(a, b) _Generic((a), typeof((b)): 1, default: 0) + +#define cast(type, data) ((type)(data)) +#define pcast(type, data) * cast(type*, & (data)) +#define nullptr cast(void*, 0) +#define size_of(data) cast(SSIZE, sizeof(data)) +#define kilo(n) (cast(SSIZE, n) << 10) +#define mega(n) (cast(SSIZE, n) << 20) +#define giga(n) (cast(SSIZE, n) << 30) +#define tera(n) (cast(SSIZE, n) << 40) + +#define range_iter(type, iter, m_begin, op, m_end) \ + tmpl(Iter_Range,type) iter = { \ + .r = {(m_begin), (m_end)}, \ + .cursor = (m_begin) }; \ + iter.cursor op iter.r.end; \ + ++ iter.cursor + +#define def_range(type) \ + def_struct(tmpl( Range,type)) { type begin; type end; }; \ + typedef def_struct(tmpl(Iter_Range,type)) { tmpl(Range,type) r; type cursor; } + +typedef def_range(S32); +typedef def_range(U32); +typedef def_range(SSIZE); + +typedef void fn(VoidFn) (void); diff --git a/code/duffle/gp.h b/code/duffle/gp.h new file mode 100644 index 0000000..3a714bf --- /dev/null +++ b/code/duffle/gp.h @@ -0,0 +1,88 @@ +#ifdef INTELLISENSE_DIRECTIVES +# pragma once +# include "dsl.h" +#endif + +typedef def_enum(U32, gp_Commands) { + gcmd_Reset = 0b000, + gcmd_Polygon = 0b001, + gcmd_Line = 0b010, + gcmd_Rect = 0b011, + gcmd_VM_to_VM = 0b100, + gcmd_CPU_to_VM = 0b101, + gcmd_VM_to_CPU = 0b110, + gcmd_Environment = 0b111, + + gcmd_SetDrawMode = 0xE1, + gcmd_SetTextureWindow = 0xE2, + gcmd_SetDrawArea_TopLeft = 0xE3, + gcmd_SetDrawArea_BotRight = 0xE4, + gcmd_SetDrawOffset = 0xE5, + gcmd_SetMaskBit = 0xE6, + + gcmd_ResetCommandBuffer = 0x01, + gcmd_AcknowledgeGPUInterrupt = 0x02, + gcmd_DisplayEnable = 0x03, + gcmd_DMA_Request = 0x04, + gcmd_DispArea_Start = 0x05, + gcmd_HorizontalDisplayRange = 0x06, + gcmd_VerticalDisplayRange = 0x07, + gcmd_DisplayMode = 0x08, + + gcmd_SetVramSize = 0x09, +}; + +#define gpio_port0 0x1810 +#define gpio_port1 0x1814 + +#define gcmd_offset 24 + +#define gp_Reset (gcmd_Reset << gcmd_offset) + +#define gp_DisplayEnabled (gcmd_DisplayEnable << gcmd_offset | 0x0) +#define gp_DisplayDisabled (gcmd_DisplayEnable << gcmd_offset | 0x1) + +#define gp_DMA_FIFO 1 +#define gp_DMA_CPU_to_GPU 2 +#define gp_DMA_GPU_to_CPU 3 +#define gp_DMA_Request (gcmd_DMA_Request << gcmd_offset) + +#define gp_HorizontalDisplayRange_3168_608 (gcmd_HorizontalDisplayRange << gcmd_offset | 0xC60 << 12 | 0x260) + +#define gp_VerticalDiplayRange (gcmd_VerticalDisplayRange << gcmd_offset) +#define gp_VerticalDisplayRange_264_24 (gp_VerticalDiplayRange | 264 << 10 | 24) +#define gp_VerticalDisplayRange_504_24 (gp_VerticalDiplayRange | 504 << 10 | 24) + +#define gp_DisplayMode (gcmd_DisplayMode << gcmd_offset) +#define gp_Disp_HRes_256 (0x0) +#define gp_Disp_HRes_320 (0x1) +#define gp_Disp_HRes_512 (0x2) +#define gp_Disp_HRes_640 (0x3) +#define gp_Disp_VRes_240 (0x0 << 2) +#define gp_Disp_VRes_480 (0x1 << 2) +#define gp_Disp_Color15 (0x0 << 4) +#define gp_Disp_Color24 (0x1 << 4) +#define gp_Disp_VInterlace (0x1 << 5) +#define gp_DisplayMode_320x240_15bit_NTSC (gp_DisplayMode | gp_Disp_HRes_320 | gp_Disp_VRes_240 | gp_Disp_Color15) +#define gp_DisplayMOde_640x480_24bbp_NTSC (gp_DisplayMode | gp_Disp_HRes_640 | gp_Disp_VRes_480 | gp_Disp_Color24 | gp_Disp_VInterlace) + +#define gp_DrawMode_DrawAllowed 10 +#define gp_SetDrawMode_DrawAllowed (gcmd_SetDrawMode << gcmd_offset | 0x1 << gp_DrawMode_DrawAllowed) + +#define gp_SetArea_TopLeft (gcmd_SetDrawArea_TopLeft << gcmd_offset) +#define gp_SetArea_BottomRight (gcmd_SetDrawArea_BotRight << gcmd_offset) + +typedef BYTE gp_Pixel16[1]; +typedef BYTE gp_Pixel24[3]; + +#define gp_b10_X 0 +#define gp_b10_Y 10 +#define gp_b16_X 0 +#define gp_b16_Y 16 + +typedef def_struct(gp_Vec2) { + U16 x; + U16 y; +}; + +extern void gp_screen_init(); diff --git a/code/graphics_hello_psyq/hello_gpu.asm b/code/graphics_hello_psyq/hello_gpu.asm new file mode 100644 index 0000000..2cbc8bf --- /dev/null +++ b/code/graphics_hello_psyq/hello_gpu.asm @@ -0,0 +1,23 @@ +.include "./toolchain/pcsx-redux/src/mips/common/crt0/crt0.s" + +.include "./asmdd/dsl.asm" +.include "./asmdd/io.asm" +.include "./asmdd/gp.asm" + +#.section .text.gp, "ax, @progbits" +#.align 2 +.global gp_screen_init +.type gp_screen_init, @function +gp_screen_init: + .equiv rio_offset, rtmp_0 + load_imm rtmp_0, IO_BASE_ADDR + #define gp0 gpio_port0(rio_offset) + #define gp1 gpio_port1(rio_offset) + + gcmd_push gp1, rtmp_1, gp_Reset + nop; nop; + gcmd_push gp1, rtmp_1, gp_DisplayEnabled + jump_reg rret_addr; nop + +.Lgp_screen_init_end: +.size gp_screen_init, . - gp_screen_init diff --git a/code/graphics_hello_psyq/hello_gpu.c b/code/graphics_hello_psyq/hello_gpu.c index 430ddd9..d0f90ba 100644 --- a/code/graphics_hello_psyq/hello_gpu.c +++ b/code/graphics_hello_psyq/hello_gpu.c @@ -1,6 +1,20 @@ -#include +// #include +#include "duffle/dsl.h" +#include "duffle/gp.h" + +#define ScreenRes_X 320 +#define ScreenRes_Y 240 +#define ScreenRes_CenterX (ScreenRes_X >> 1) +#define ScreenRes_CenterY (ScreenRes_Y >> 1) int main(void) { + gp_screen_init(); + + while (1) + { + + }; + return 0; } diff --git a/code/graphics_hello_psyq/hello_gpu.s b/code/hello_psyq/hello_psyq.asm similarity index 100% rename from code/graphics_hello_psyq/hello_gpu.s rename to code/hello_psyq/hello_psyq.asm diff --git a/code/hello_psyq/hello_psyq.s b/code/hello_psyq/hello_psyq.s deleted file mode 100644 index b39d3d8..0000000 --- a/code/hello_psyq/hello_psyq.s +++ /dev/null @@ -1,3 +0,0 @@ -.include "./toolchain/pcsx-redux/src/mips/common/crt0/crt0.s" - - diff --git a/docs/assets/pcsx-redux_2025-08-05_23-01-19.png b/docs/assets/pcsx-redux_2025-08-05_23-01-19.png new file mode 100644 index 0000000..736377b Binary files /dev/null and b/docs/assets/pcsx-redux_2025-08-05_23-01-19.png differ diff --git a/readme.md b/readme.md index 0141cb1..517d773 100644 --- a/readme.md +++ b/readme.md @@ -55,3 +55,4 @@ scoop install lua ![clear!](./docs/assets/pcsx-redux.main_2025-08-03_18-02-08.png) ![traingles!](./docs/assets/pcsx-redux.main_2025-08-03_19-28-22.png) ![polys!](./docs/assets/pcsx-redux.main_2025-08-03_20-45-35.png) +![hello_psyq!](./docs/assets/pcsx-redux_2025-08-05_23-01-19.png) diff --git a/scripts/build_psyq.ps1 b/scripts/build_psyq.ps1 index 7250dc6..a180db1 100644 --- a/scripts/build_psyq.ps1 +++ b/scripts/build_psyq.ps1 @@ -106,6 +106,7 @@ function assemble-unit { param( $assemble_args += $user_assemble_args + $assemble_args += '-x', 'assembler-with-cpp' $assemble_args += $f_compile, $unit, ($f_output + $link_module) write-host "Assembling '$unit' -> '$link_module'" -ForegroundColor Cyan @@ -264,17 +265,18 @@ function build-hello_psyqo { } # build-hello_psyqo -function build-double_buffer { +function build-graphis_hello { $includes += @() $path_module = join-path $path_code 'graphics_hello_psyq' - $src_asm = join-path $path_module 'hello_gpu.s' + $src_asm = join-path $path_module 'hello_gpu.asm' $module_asm = join-path $path_build 'hello_gpu.o' $assemble_args = @() $assemble_args += $f_debug $assemble_args += $f_optimize_none + $assemble_args += ($f_include + $path_code) assemble-unit $src_asm $module_asm $includes $assemble_args $src_c = join-path $path_module 'hello_gpu.c' @@ -284,14 +286,16 @@ function build-double_buffer { $compile_args += $f_debug $compile_args += $f_optimize_none # $compile_args += $f_optimize_size + $compile_args += ($f_include + $path_code) compile-unit $src_c $module_c $includes $compile_args $elf = join-path $path_build 'hello_gpu.elf' $exe = join-path $path_build 'hello_gpu.ps-exe' + $link_args = @() $link_args += $f_debug # $link_args += $f_optimize_size link-modules @($module_asm, $module_c) $elf $link_args make-binary $elf $exe } -build-double_buffer +build-graphis_hello