diff --git a/.vscode/launch.json b/.vscode/launch.json index 15f80a9..92c6b1f 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -51,6 +51,30 @@ "tbreak main", "continue" ] + }, + { + "name": "Debug: Hello GTE 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_gte.elf", + "autorun": [ + "monitor reset shellhalt", + "load hello_gte.elf", + "tbreak main", + "continue" + ] } ] } diff --git a/code/gte_hello/hello_gte.c b/code/gte_hello/hello_gte.c new file mode 100644 index 0000000..2a854f8 --- /dev/null +++ b/code/gte_hello/hello_gte.c @@ -0,0 +1,287 @@ +#include "stdio.h" +#include +#include "assert.h" +// #include "libgpu.h" +// #include "libetc.h" +// #include "libgte.h" + +#include "duffle/dsl.h" +#include "duffle/memory.h" +#include "duffle/math.h" +#include "duffle/gp.h" +#include "hello_gte.h" + +enum { + PrimitiveBuff_Len = 4096, + OrderingTbl_Len = 2048 +}; + +typedef U4 OrderingTable_Buffer[OrderingTbl_Len]; +typedef def_farray(OrderingTable_Buffer, 2); + +typedef B1 PrimitiveBuffer[PrimitiveBuff_Len]; +typedef def_farray(PrimitiveBuffer, 2); +typedef def_struct(PrimitiveArena) { + A2_PrimitiveBuffer buf; + U4 used; +}; + +#define Cube_num_verts 8 +typedef def_farray(V3_S2, Cube_num_verts); +#define Cube_num_faces 6 +typedef def_farray(V4_S2, Cube_num_faces); +void ent_cube128_init(A8_V3_S2* verts, A6_V4_S2* faces) { + memory_copy(verts, & (A8_V3_S2) { + { -128, -128, -128 }, + { 128, -128, -128 }, + { 128, -128, 128 }, + { -128, -128, 128 }, + { -128, 128, -128 }, + { 128, 128, -128 }, + { 128, 128, 128 }, + { -128, 128, 128 } + }, size_of(A8_V3_S2) ); + memory_copy(faces, & (A6_V4_S2) { + { 3, 2, 0, 1 }, + { 0, 1, 4, 5 }, + { 4, 5, 7, 6 }, + { 1, 2, 5, 6 }, + { 2, 3, 6, 7 }, + { 3, 0, 7, 4 }, + }, size_of(A6_V4_S2) ); + return; +} +typedef def_struct(Ent_Cube) { + V3_S4 accel; + V3_S4 vel; + V3_S4 pos; + V3_S4 scale; + V3_S2 rot; + A8_V3_S2 verts; + A6_V4_S2 faces; +}; + +#define Floor_num_verts 4 +typedef def_farray(V3_S2, Floor_num_verts); +#define Floor_num_faces 2 +typedef def_farray(V3_S2, Floor_num_faces); +void ent_floor_init(A4_V3_S2* verts, A2_V3_S2* faces) { + memory_copy(verts, &(A4_V3_S2) { + { -900, 0, -900 }, + { -900, 0, 900 }, + { 900, 0, -900 }, + { 900, 0, 900 }, + }, size_of(A8_V3_S2)); + memory_copy(faces, & (A2_V3_S2) { + { 0, 1, 2 }, + { 1, 3, 2 }, + }, size_of(A2_V3_S2)); +}; +typedef def_struct(Ent_Floor) { + V3_S4 accel; + V3_S4 pos; + V3_S4 scale; + V3_S2 rot; + A4_V3_S2 verts; + A2_V3_S2 faces; +}; + +typedef def_struct(SMemory) { + DoubleBuffer screen_buf; + A2_OrderingTable_Buffer ordering_tbl; + PrimitiveArena primitives; + S2 active_buf_id; + + M3_S2 tform_world; + + Ent_Cube cube; + Ent_Floor floor; +}; +global SMemory static_mem; +extern SMemory static_mem; + +B1* prim__alloc(U4 type_width, Str8 type_name) { + gknown PrimitiveArena* pa = & static_mem.primitives; + gknown B1* buf = (B1*) r_(static_mem.primitives.buf)[static_mem.active_buf_id]; + assert(pa->used + type_width < PrimitiveBuff_Len); + B1* next = buf + pa->used; + pa->used += type_width; + return next; +} +#define prim_alloc(type) (type*)prim__alloc(size_of(type), txt( stringify(type))) + +void gp_screen_init_c11(DoubleBuffer* screen_buf, S2* active_buf_id) +{ + reset_graph(0); + + // Set the current initial buffer + active_buf_id[0] = 0; + + // Just setting env data, not interacting with console hw. + // First buffer area + displayenv_init(& r_(screen_buf->display)[0], 0, 0, ScreenRes_X, ScreenRes_Y); + drawenv_init (& r_(screen_buf->draw )[0], 0, ScreenRes_Y, ScreenRes_X, ScreenRes_Y); + // Second buffer area + displayenv_init(& r_(screen_buf->display)[1], 0, ScreenRes_Y, ScreenRes_X, ScreenRes_Y); + drawenv_init (& r_(screen_buf->draw )[1], 0, 0, ScreenRes_X, ScreenRes_Y); + // Set the back/drawing buffer + screen_buf->draw[0].enable_auto_clear = true; + screen_buf->draw[1].enable_auto_clear = true; + // Set the background clear color + screen_buf->draw[0].initial_bg_color = rgb8( .r = 7, .g = 7, .b = 7 ); + screen_buf->draw[1].initial_bg_color = rgb8( .r = 7, .g = 7, .b = 7 ); + // screen_buf->draw[1].initial_bg_color = rgb8( .r = 47, .g = 13, .b = 0 ); + displayenv_put(& r_(screen_buf->display)[ active_buf_id[0] ]); + drawenv_put (& r_(screen_buf->draw )[ active_buf_id[0] ]); + + // Initialize and setup the GTE geometry offsets + geom_init(); + geom_set_offset(ScreenRes_CenterX, ScreenRes_CenterY); + geom_set_screen(ScreenZ); + + set_display_enabled(1); // gp_DisplayEnabled +} + +void gp_display_frame(DoubleBuffer* screen_buf, S2* active_buf_id, U4* ordering_buf, PrimitiveArena* pa) { + draw_sync(0); + vsync(0); + displayenv_put(& r_(screen_buf->display)[active_buf_id[0] ]); + drawenv_put (& r_(screen_buf->draw) [active_buf_id[0] ]); + { + draw_orderingtbl(ordering_buf + OrderingTbl_Len - 1); + pa->used = 0; + } + active_buf_id[0] = ! active_buf_id[0]; // Swap current buffer +} + +void render(void) { +} + +void update(PrimitiveArena* pa, U4* ordering_buf) +{ + orderingtbl_clear_reverse(ordering_buf, OrderingTbl_Len); + + // Update the position based on acceleration and velocity + gknown V3_S4_R pos = & static_mem.cube.pos; + gknown V3_S4_R vel = & static_mem.cube.vel; + gknown V3_S4_R acc = & static_mem.cube.accel; + add_v3s4(vel, acc[0]); + add_v3s4_fp(pos, vel[0]); + // vel->x += acc->x; + // vel->y += acc->y; + // vel->z += acc->z; + // pos->x += vel->x; + // pos->y += vel->y; + // pos->z += vel->z; + + if (pos->y + 150 > static_mem.floor.pos.y) vel->y *= -1; + + // Prep + S4 nclip = 0; + S4 orderingtbl_z = 0; + A2_S2 p; //??? + S4 flag; //???? + + // Draw Cube + { + m3s2_rotation (& static_mem.cube.rot, & static_mem.tform_world); + m3s2_translation(& static_mem.tform_world, & static_mem.cube.pos); + m3s2_scale (& static_mem.tform_world, & static_mem.cube.scale); + gte_matrix_set_rotation (& static_mem.tform_world); + gte_matrix_set_translation(& static_mem.tform_world); + for (U4 face_id = 0; face_id < Cube_num_faces; face_id += 1) + { + Poly_G4* quad = prim_alloc(Poly_G4); set_poly_g4(quad); + quad->c0 = rgb8(255, 0, 255); + quad->c1 = rgb8(255, 255, 0); + quad->c2 = rgb8( 0, 255, 255); + quad->c3 = rgb8( 0, 255, 0); + + V4_S2* face = & static_mem.cube.faces[face_id]; + V3_S2* p0 = & static_mem.cube.verts[face->x]; + V3_S2* p1 = & static_mem.cube.verts[face->y]; + V3_S2* p2 = & static_mem.cube.verts[face->z]; + V3_S2* p3 = & static_mem.cube.verts[face->w]; + + nclip = rtp_avg_nclip_a4_v3s2( + p0, p1, p2, p3, + & quad->p0, & quad->p1, & quad->p2, & quad->p3, + & p, & orderingtbl_z, & flag + ); + if (nclip <= 0) { + continue; + } + + if ((orderingtbl_z > 0) && (orderingtbl_z < OrderingTbl_Len)) { + orderingtbl_add_primitive(ordering_buf[orderingtbl_z], quad); + } + } + // static_mem.cube.rot.x += 6; + // static_mem.cube.rot.y += 8; + // static_mem.cube.rot.z += 12; + static_mem.cube.rot.y += 20; + } + // Draw Floor + { + m3s2_rotation (& static_mem.floor.rot, & static_mem.tform_world); + m3s2_translation(& static_mem.tform_world, & static_mem.floor.pos); + m3s2_scale (& static_mem.tform_world, & static_mem.floor.scale); + gte_matrix_set_rotation (& static_mem.tform_world); + gte_matrix_set_translation(& static_mem.tform_world); + for (U4 face_id = 0; face_id < Floor_num_faces; face_id += 1) + { + Poly_F3* tri = prim_alloc(Poly_F3); set_poly_f3(tri); + tri->color = rgb8(255, 255, 255); + + V3_S2* face = & static_mem.floor.faces[face_id]; + V3_S2* p0 = & static_mem.floor.verts[face->x]; + V3_S2* p1 = & static_mem.floor.verts[face->y]; + V3_S2* p2 = & static_mem.floor.verts[face->z]; + + nclip = rtp_avg_nclip_a3_v3s2(p0, p1, p2 + , & tri->p0, & tri->p1, & tri->p2 + , & p, & orderingtbl_z, & flag + ); + if (nclip <= 0) { + continue; + } + + if ((orderingtbl_z > 0) && (orderingtbl_z < OrderingTbl_Len)) { + orderingtbl_add_primitive(ordering_buf[orderingtbl_z], tri); + } + } + static_mem.floor.rot.y += 5; + } +} + +int main(void) +{ + static_mem = (SMemory){0}; + static_mem.primitives.used = 0; + ent_cube128_init(& static_mem.cube.verts, & static_mem.cube.faces); { + Ent_Cube* cube = & static_mem.cube; + cube->rot = v3s2(0, 0, 0); + // cube->pos = v3s4(0, 0, 900); + cube->scale = v3s4_fp_one(); + cube->accel = v3s4(0, 1, 0); + cube->pos = v3s4(0, -400, 1800); + } + ent_floor_init(& static_mem.floor.verts, & static_mem.floor.faces); { + Ent_Floor* floor = & static_mem.floor; + floor->rot = v3s2(0, 0, 0); + floor->pos = v3s4(0, 450, 1800); + floor->scale = v3s4_fp_one(); + } + // gknown gp_screen_init(); + gp_screen_init_c11(& static_mem.screen_buf, & static_mem.active_buf_id); + while (1) + { + gknown S2* active_buf_id = & static_mem.active_buf_id; + gknown U4* ordering_buf = r_(static_mem.ordering_tbl)[active_buf_id[0]]; + gknown PrimitiveArena* pa = & static_mem.primitives; + update(pa, ordering_buf); + render(); + gp_display_frame(& static_mem.screen_buf, active_buf_id, ordering_buf, pa); + }; + return 0; +} diff --git a/code/gte_hello/hello_gte.h b/code/gte_hello/hello_gte.h new file mode 100644 index 0000000..4ab9b25 --- /dev/null +++ b/code/gte_hello/hello_gte.h @@ -0,0 +1,207 @@ +#ifdef INTELLISENSE_DIRECTIVES +# pragma once +# include "duffle/dsl.h" +# include "duffle/math.h" +# include "duffle/gp.h" +#endif + +typedef def_struct(DrawEnv_Packed) { U4 tag; U4 code[15]; }; +typedef def_struct(DrawEnv) { + Rect_S2 clip_area; + A2_S2 drawing_offset; + Rect_S2 texture_window; + S2 texture_page; + B1 flag_dither; + B1 flag_draw_on_display; + B1 enable_auto_clear; + RGB8 initial_bg_color; + DrawEnv_Packed dr_env; // reserved +}; +typedef def_struct(DisplayEnv) { + Rect_S2 display_area; + Rect_S2 screen; + B1 vinterlace; + B1 color24; + B1 pad0; + B1 pad1; +}; +typedef def_farray(DrawEnv, 2); +typedef def_farray(DisplayEnv, 2); +typedef def_struct(DoubleBuffer) { + A2_DrawEnv draw; + A2_DisplayEnv display; +}; + +#define ScreenRes_X 320 +#define ScreenRes_Y 240 +#define ScreenZ 320 +#define ScreenRes_CenterX (ScreenRes_X >> 1) +#define ScreenRes_CenterY (ScreenRes_Y >> 1) + +DisplayEnv* displayenv_init(DisplayEnv* env, S4 x, S4 y, S4 w, S4 h) __asm__("SetDefDispEnv"); +DrawEnv* drawenv_init (DrawEnv* env, S4 x, S4 y, S4 w, S4 h) __asm__("SetDefDrawEnv"); + +DisplayEnv* displayenv_put(DisplayEnv* env) __asm__("PutDispEnv"); +DrawEnv* drawenv_put (DrawEnv* env) __asm__("PutDrawEnv"); + +U4 geom_init(void) __asm__("InitGeom"); +void geom_set_offset(U4 x, U4 y) __asm__("SetGeomOffset"); +void geom_set_screen(U4 h) __asm__("SetGeomScreen"); + +U4* orderingtbl_clear_reverse(U4* ot, U4 len) __asm__("ClearOTagR"); + +U4 reset_graph(U4 mode) __asm__("ResetGraph"); +void set_display_enabled(U4 mask) __asm__("SetDispMask"); + +U4 draw_sync(U4 mode) __asm__("DrawSync"); +U4 vsync(U4 mode) __asm__("VSync"); + +void draw_orderingtbl(U4* buf) __asm__("DrawOTag"); + +typedef def_struct(PolyTag) { + U4 addr: 24; + U4 len: 8; + RGB8 color; + B1 code; +}; + +/* + * Primitive Handling Macros + */ + +#define set_len( p, _len) (((PolyTag*R_)(p))->len = (B1)(_len)) +#define set_addr(p, _addr) (((PolyTag*R_)(p))->addr = (U4)(_addr)) +#define set_code(p, _code) (((PolyTag*R_)(p))->code = (B1)(_code)) + +#define get_len(p) (B1)(((PolyTag*R_)(p))->len) +#define get_code(p) (B1)(((PolyTag*R_)(p))->code) +#define get_addr(p) (U4)(((PolyTag*R_)(p))->addr) + +#define orderingtbl_add_primitive(ot, p) set_addr(p, get_addr(ot)), set_addr(ot, p) +#define orderingtbl_add_primitives(ot, p0, p1) set_addr(p1, get_addr(ot)), set_addr(ot, p0) + +/* Primitive Length Code */ + +#define set_poly_f3(p) set_len(p, 4), set_code(p, 0x20) +#define set_poly_ft3(p) set_len(p, 7), set_code(p, 0x24) +#define set_poly_g3(p) set_len(p, 6), set_code(p, 0x30) +#define set_poly_gt3(p) set_len(p, 9), set_code(p, 0x34) +#define set_poly_f4(p) set_len(p, 5), set_code(p, 0x28) +#define set_poly_ft4(p) set_len(p, 9), set_code(p, 0x2c) +#define set_poly_g4(p) set_len(p, 8), set_code(p, 0x38) +#define set_poly_gt4(p) set_len(p, 12), set_code(p, 0x3c) + +// #define setSprt8(p) setlen(p, 3), setcode(p, 0x74) +// #define setSprt16(p) setlen(p, 3), setcode(p, 0x7c) +// #define setSprt(p) setlen(p, 4), setcode(p, 0x64) + +// #define setTile1(p) set_len(p, 2), set_code(p, 0x68) +// #define setTile8(p) set_len(p, 2), set_code(p, 0x70) +// #define setTile16(p) set_len(p, 2), set_code(p, 0x78) +#define set_tile(p) set_len(p, 3), set_code(p, 0x60) +// #define setLineF2(p) set_len(p, 3), set_code(p, 0x40) +// #define setLineG2(p) set_len(p, 4), set_code(p, 0x50) +// #define setLineF3(p) set_len(p, 5), set_code(p, 0x48),(p)->pad = 0x55555555 +// #define setLineG3(p) set_len(p, 7), set_code(p, 0x58),(p)->pad = 0x55555555, (p)->p2 = 0 +// #define setLineF4(p) set_len(p, 6), set_code(p, 0x4c),(p)->pad = 0x55555555 +// #define setLineG4(p) set_len(p, 9), set_code(p, 0x5c),(p)->pad = 0x55555555, (p)->p2 = 0, (p)->p3 = 0 + +typedef def_struct(Poly_F3) { + U4 tag; + RGB8 color; + B1 code; + union { + struct { + V2_S2 p0; + V2_S2 p1; + V2_S2 p2; + }; + A3_V2_S2 points; + }; +}; + +typedef def_struct(Poly_G3) { + U4 tag; RGB8 c0; B1 code; + V2_S2 p0; RGB8 c1; B1 pad1; + V2_S2 p1; RGB8 c2; B1 pad2; + V2_S2 p2; +}; + +typedef def_struct(Poly_F4) { + U4 tag; + RGB8 color; + B1 code; + union { + struct { + V2_S2 p0; + V2_S2 p1; + V2_S2 p2; + V2_S2 p3; + }; + A4_V2_S2 points; + }; +}; + +typedef def_struct(Poly_G4) { + U4 tag; RGB8 c0; B1 code; + V2_S2 p0; RGB8 c1; B1 pad1; + V2_S2 p1; RGB8 c2; B1 pad2; + V2_S2 p2; RGB8 c3; B1 pad3; + V2_S2 p3; +}; + +typedef def_struct(Tile) { + U4 tag; + RGB8 color; + B1 code; + Rect_S2 rect; +}; + + +/* + Linear Algebra +*/ + +M3_S2* m3s2_rotation (V3_S2* vec, M3_S2* mat) __asm__("RotMatrix"); +M3_S2* m3s2_translation(M3_S2* mat, V3_S4* vec) __asm__("TransMatrix"); +M3_S2* m3s2_scale (M3_S2* mat, V3_S4* vec) __asm__("ScaleMatrix"); + +// Rotation, Translation, Perspective + +S4 rtp_v3s2_raw(V3_S2* vec, S4* xy, S4* pp, S4* flag) __asm__("RotTransPers"); +FI_ S4 rtp_v3s2(V3_S2* vec, V2_S2* xy, A2_S2* pp, S4* flag) { return rtp_v3s2_raw(vec, cast(S4*R_, & xy->x), cast(S4*R_, pp), r_(flag)); } + +S4 rtp_avg_nclip_a3_v3s2_raw(V3_S2* v0, V3_S2* v1, V3_S2* v2, S4* xy1, S4* xy2, S4* xy3, S4* pp, S4* otz, S4* flag) __asm__("RotAverageNclip3"); +FI_ S4 rtp_avg_nclip_a3_v3s2( + V3_S2* v0, V3_S2* v1, V3_S2* v2, + V2_S2* xy0, V2_S2* xy1, V2_S2* xy2, + A2_S2* pp, S4* otz, S4* flag +){ + return rtp_avg_nclip_a3_v3s2_raw( + v0, v1, v2, + cast(S4*R_, xy0), cast(S4*R_, xy1), cast(S4*R_, xy2), + cast(S4*R_, pp), cast(S4*R_, otz), cast(S4*R_, flag) + ); +} + +S4 rtp_avg_nclip_a4_v3s2_raw(V3_S2* v0, V3_S2* v1, V3_S2* v2, V3_S2* v3, S4* xy1, S4* xy2, S4* xy3, S4* xy4, S4* pp, S4* otz, S4* flag) __asm__("RotAverageNclip4"); +FI_ S4 rtp_avg_nclip_a4_v3s2( + V3_S2* v0, V3_S2* v1, V3_S2* v2, V3_S2* v3, + V2_S2* xy0, V2_S2* xy1, V2_S2* xy2, V2_S2* xy3, + A2_S2* pp, S4* otz, S4* flag +){ + return rtp_avg_nclip_a4_v3s2_raw( + v0, v1, v2, v3, + cast(S4*R_, xy0), cast(S4*R_, xy1), cast(S4*R_, xy2), cast(S4*R_, xy3), + cast(S4*R_, pp), cast(S4*R_, otz), cast(S4*R_, flag) + ); +} + +void gte_matrix_set_rotation (M3_S2* mat) __asm__("SetRotMatrix"); +void gte_matrix_set_translation(M3_S2* mat) __asm__("SetTransMatrix"); + +enum { + fp_one = (1 << 12), +}; + +#define v3s4_fp_one() v3s4(fp_one, fp_one, fp_one) diff --git a/code/gte_hello/hello_gte.s b/code/gte_hello/hello_gte.s new file mode 100644 index 0000000..1712b3a --- /dev/null +++ b/code/gte_hello/hello_gte.s @@ -0,0 +1,170 @@ +// .include "./toolchain/pcsx-redux/src/mips/common/crt0/crt0.s" + +.include "./asmdd/dsl.s" +.include "./asmdd/math.s" +.include "./asmdd/io.s" +.include "./asmdd/gp.s" + +# DrawEnv_Packed { U4 tag; U4 code[15]; } +.equ DrawEnv_Packed_tag, 0 +.equ DrawEnv_Packed_code, DrawEnv_Packed_tag + U4 +.equ DrawEnv_Packed, 64 +# DrawEnv { Rect_S2 clip; V2_S2 ofs; Rect_S2 tw; U2 tpage; U8 dtd; U8 dfe; U8 tme; U8 r0,g0,b0; DR_ENV dr_env; } +.equ DrawEnv_clip_area, /* 0 */ Rect_S2 * 0 +.equ DrawEnv_drawing_offset, /* 8 */ V2_S2 * 0 + Rect_S2 +.equ DrawEnv_texture_window, /* 12 */ Rect_S2 * 0 + A2_S2 + DrawEnv_drawing_offset +.equ DrawEnv_texture_page, /* 20 */ S1 * 0 + Rect_S2 + DrawEnv_texture_window +.equ DrawEnv_flag_dither, /* 22 */ B1 * 0 + S2 + DrawEnv_texture_page +.equ DrawEnv_flag_draw_on_display, /* 23 */ B1 * 0 + B1 + DrawEnv_flag_dither +.equ DrawEnv_enable_auto_clear, /* 24 */ B1 * 0 + B1 + DrawEnv_flag_draw_on_display +.equ DrawEnv_initial_bg_color, /* 25 */ RGB8 * 0 + B1 + DrawEnv_enable_auto_clear +.equ DrawEnv_dr_env, /* 28 */ DrawEnv_Packed * 0 + RGB8 + DrawEnv_initial_bg_color +.equ DrawEnv, /* 92 */ DrawEnv_dr_env + DrawEnv_Packed +# DisplayEnv { Rect_S16 disp; Rect_S16 screen; U8 isinter; U8 isrgb24; U8 pad[2]; } +.equ DisplayEnv_display_area, Rect_S2 * 0 +.equ DisplayEnv_screen, Rect_S2 * 0 + Rect_S2 + DisplayEnv_display_area +.equ DisplayEnv_vinterlace, B1 * 0 + Rect_S2 + DisplayEnv_screen +.equ DisplayEnv_color24, B1 * 0 + B1 + DisplayEnv_vinterlace +.equ DisplayEnv_pad0, B1 * 0 + B1 + DisplayEnv_color24 +.equ DisplayEnv_pad1, B1 * 0 + B1 + DisplayEnv_pad0 +.equ DisplayEnv, DisplayEnv_pad1 + B1 +# DoubleBuffer { DrawEnv draw[2]; DisplayEnv display[2]; } +.equ DoubleBuffer_draw, 0 +.equ DoubleBuffer_draw_0, (DrawEnv * 0) +.equ DoubleBuffer_draw_1, (DrawEnv * 1) +.equ DoubleBuffer_display, (DrawEnv * 2) +.equ DoubleBuffer_display_0, (DisplayEnv * 0) + DoubleBuffer_display +.equ DoubleBuffer_display_1, (DisplayEnv * 1) + DoubleBuffer_display +.equ DoubleBuffer, (DisplayEnv * 2) + DoubleBuffer_display +# Screen Constants +.equ ScreenRes_X, 320 +.equ ScreenRes_Y, 240 +.equ ScreenRes_CenterX, (ScreenRes_X >> 1) +.equ ScreenRes_CenterY, (ScreenRes_Y >> 1) + +.equ SMemory_screen_buf, DoubleBuffer * 0 +.equ SMemory_active_screen_buf, S2 * 0 + DoubleBuffer + +.equ CF_Shadow, 16 + +.extern ResetGraph +.equ ResetGraph_mode, rarg_0 + +.extern SetDispMask +.equ SetDispMask_mask, rarg_0 + +.extern PutDispEnv +.extern PutDrawEnv +.equ PutDispEnv_env, rarg_0 +.equ PutDrawEnv_env, rarg_0 + +.extern SetDefDispEnv +.equ SetDefDispEnv_env, rarg_0 +.equ SetDefDispEnv_x, rarg_1 +.equ SetDefDispEnv_y, rarg_2 +.equ SetDefDispEnv_w, rarg_3 +.equ SetDefDispEnv_h, CF_Shadow +.set SetDefDispEnv_sp_size, CF_Shadow + S4 + +.extern SetDefDrawEnv +.equ SetDefDrawEnv_env, rarg_0 +.equ SetDefDrawEnv_x, rarg_1 +.equ SetDefDrawEnv_y, rarg_2 +.equ SetDefDrawEnv_w, rarg_3 +.equ SetDefDrawEnv_h, CF_Shadow +.set SetDefDrawEnv_sp_size, CF_Shadow + S4 + +.extern SetGeomOffset +.equ SetGeomOffset_x, rarg_0 +.equ SetGeomOffset_y, rarg_1 + +.extern SetGeomScreen +.equ SetGeomScreen_h, rarg_0 + +.global gp_screen_init_asm +.type gp_screen_init_asm, @function +gp_screen_init_asm: + .equiv rio_offset, rtmp_0 + load_imm rtmp_0, IO_BASE_ADDR + #define gp0 gpio_port0(rio_offset) + #define gp1 gpio_port1(rio_offset) + + def_cf_sp_size 0x18; // Should be enough for all calls within this proc, for some reason SetDefDispEnv needs the offset to be CF_Shadow.. + stack_alloc cf_ssize + store_word rret_addr, 0($sp) + + // Note(Ed): Cannot be used psyq manages things related to vblank and other things so the api must be called instead + // gcmd_push gp1, rtmp_1, gp_Reset // ResetGraph(0) + // gcmd_push gp1, rtmp_1, gp_DisplayEnabled // SetDispMask(1) + load_imm ResetGraph_mode, gp_Reset; jump_nlink ResetGraph + load_imm SetDispMask_mask, 1; jump_nlink SetDispMask + + // First buffer area + load_addr rtmp_0, static_mem; add_ui SetDefDispEnv_env, rtmp_0, SMemory_screen_buf + DoubleBuffer_display_0 + move SetDefDispEnv_x, $zero + move SetDefDispEnv_y, $zero + load_imm SetDefDispEnv_w, ScreenRes_X + load_imm rtmp_0, ScreenRes_Y; store_word rtmp_0, SetDefDispEnv_h($sp) + jump_nlink SetDefDispEnv + load_addr rtmp_0, static_mem; add_ui SetDefDrawEnv_env, rtmp_0, SMemory_screen_buf + DoubleBuffer_draw_0 + move SetDefDrawEnv_x, $zero + load_imm SetDefDrawEnv_y, ScreenRes_Y + load_imm SetDefDrawEnv_w, ScreenRes_X + load_imm rtmp_0, ScreenRes_Y; store_word rtmp_0, SetDefDrawEnv_h($sp) + jump_nlink SetDefDrawEnv + // Second buffer area + load_addr rtmp_0, static_mem; add_ui SetDefDispEnv_env, rtmp_0, SMemory_screen_buf + DoubleBuffer_display_1 + move SetDefDispEnv_x, $zero + load_imm SetDefDispEnv_y, ScreenRes_Y + load_imm SetDefDispEnv_w, ScreenRes_X + load_imm rtmp_0, ScreenRes_Y; store_word rtmp_0, SetDefDispEnv_h($sp) + jump_nlink SetDefDispEnv + load_addr rtmp_0, static_mem; add_ui SetDefDrawEnv_env, rtmp_0, SMemory_screen_buf + DoubleBuffer_draw_1 + move SetDefDrawEnv_x, $zero + move SetDefDrawEnv_y, $zero + load_imm SetDefDrawEnv_w, ScreenRes_X + load_imm rtmp_0, ScreenRes_Y; store_word rtmp_0, SetDefDrawEnv_h($sp) + jump_nlink SetDefDrawEnv + + // Set the back/drawing buffer + load_imm rtmp_1, true + load_addr rtmp_0, static_mem; // At SMemory_screen_buf + store_word rtmp_1, DoubleBuffer_draw_0 + DrawEnv_enable_auto_clear(rtmp_0) + store_word rtmp_1, DoubleBuffer_draw_1 + DrawEnv_enable_auto_clear(rtmp_0) + + // Set background clear color + load_imm rtmp_1, 28; load_imm rtmp_2, 22; load_imm rtmp_3, 25 + // 63, 0, 127 + store_byte rtmp_2, DoubleBuffer_draw_0 + DrawEnv_initial_bg_color + RGB8_r(rtmp_0) + store_byte rtmp_1, DoubleBuffer_draw_0 + DrawEnv_initial_bg_color + RGB8_g(rtmp_0) + store_byte rtmp_3, DoubleBuffer_draw_0 + DrawEnv_initial_bg_color + RGB8_b(rtmp_0) + // 127, 63, 0 + store_byte rtmp_3, DoubleBuffer_draw_1 + DrawEnv_initial_bg_color + RGB8_r(rtmp_0) + store_byte rtmp_2, DoubleBuffer_draw_1 + DrawEnv_initial_bg_color + RGB8_g(rtmp_0) + store_byte rtmp_1, DoubleBuffer_draw_1 + DrawEnv_initial_bg_color + RGB8_b(rtmp_0) + load_addr rtmp_0, static_mem; store_word rtmp_1, SMemory_active_screen_buf(rtmp_0) + + load_addr rtmp_1, static_mem; load_half rtmp_1, SMemory_active_screen_buf(rtmp_1); // rtmp_1 = active_screen_buffer + load_imm rtmp_2, DisplayEnv; mult_u rtmp_1, rtmp_2; mov_from_low rtmp_2 // rtmp_2 = DisplayEnv.type_size * active_screen_Buffer (rtmp_1) + add_ui rtmp_2, rtmp_2, DoubleBuffer_display // rtmp_2 += DoubleBuffer.display + load_addr rtmp_0, static_mem; add_u PutDispEnv_env, rtmp_0, rtmp_2 // rarg_0 = rtmp_0 (screen_buffer) + rtmp_2 (.display[active_screen-buffer]) + jump_nlink PutDispEnv + load_addr rtmp_1, static_mem; load_half rtmp_1, SMemory_active_screen_buf(rtmp_1); + load_imm rtmp_2, DrawEnv; mult_u rtmp_1, rtmp_2; mov_from_low rtmp_2; + add_ui rtmp_2, rtmp_2, DoubleBuffer_draw + load_addr rtmp_0, static_mem; add_u PutDrawEnv_env, rtmp_0, rtmp_2 + jump_nlink PutDrawEnv + + // Initialize and setup the GTE geometry offsets + jump_nlink InitGeom + load_imm SetGeomOffset_x, ScreenRes_CenterX + load_imm SetGeomOffset_y, ScreenRes_CenterY + jump_nlink SetGeomOffset + load_imm SetGeomScreen_h, ScreenRes_CenterX + jump_nlink SetGeomScreen + + load_word rret_addr, 0($sp) + stack_release cf_ssize + jump_reg rret_addr; +.Lgp_screen_init_end: +.size gp_screen_init_asm, . - gp_screen_init_asm diff --git a/scripts/build_psyq.ps1 b/scripts/build_psyq.ps1 index efd3ba7..996ff05 100644 --- a/scripts/build_psyq.ps1 +++ b/scripts/build_psyq.ps1 @@ -307,4 +307,46 @@ function build-graphis_hello { link-modules @($module_asm_crt, $module_asm, $module_c) $elf $link_args make-binary $elf $exe } -build-graphis_hello +# build-graphis_hello + +function build-gte_hello { + $includes += @() + + $path_module = join-path $path_code 'gte_hello' + + $assemble_args = @() + $assemble_args += $f_debug + $assemble_args += $f_optimize_none + $assemble_args += ($f_include + $path_code) + + $src_asm_crt = join-path $path_nugget_common 'crt0/crt0.s' + $module_asm_crt = join-path $path_build 'crt0.o' + # assemble-unit $src_asm_crt $module_asm_crt $includes $assemble_args + + $src_asm = join-path $path_module 'hello_gte.s' + $module_asm = join-path $path_build 'hello_gte.o' + + assemble-unit $src_asm $module_asm $includes $assemble_args + + $src_c = join-path $path_module 'hello_gte.c' + $module_c = join-path $path_build 'hello_gte_c.o' + + $compile_args = @() + $compile_args += $f_debug + # $compile_args += $f_optimize_none + # $compile_args += $f_optimize_intrinsics + $compile_args += $f_optimize_size + # $compile_args += $f_optimize_debug + $compile_args += ($f_include + $path_code) + compile-unit $src_c $module_c $includes $compile_args + + $elf = join-path $path_build 'hello_gte.elf' + $exe = join-path $path_build 'hello_gte.ps-exe' + + $link_args = @() + $link_args += $f_debug + # $link_args += $f_optimize_size + link-modules @($module_asm_crt, $module_asm, $module_c) $elf $link_args + make-binary $elf $exe +} +build-gte_hello \ No newline at end of file