├── ucode_src ├── src │ ├── hfx_ucode.c │ ├── crt.S │ └── hfx_main.c └── include │ ├── mat_vec.S │ ├── sort.S │ └── tri.S ├── .gitignore ├── libhfx_gl ├── include │ ├── hfx_int.h │ └── hfx_types.h └── src │ └── hfx.c ├── include ├── ucode │ ├── hfx_asm.h │ ├── fixed_vector.h │ └── rsp.h ├── hfx_cmds.h ├── hfx.h └── GL │ └── gl.h ├── tests ├── ucode_sort │ ├── ucode.c │ ├── loader.S │ ├── ucode_asm.S │ └── main.c ├── ucode_tri │ ├── ucode.c │ ├── loader.S │ ├── ucode_asm.S │ └── main.c ├── ucode_mul_mat_vec │ ├── ucode.c │ ├── loader.S │ ├── ucode_asm.S │ └── main.c ├── basic_rdp_test │ └── main.c ├── hfx_persp │ └── main.c ├── hfx_clear │ └── main.c ├── basic_rb_test │ └── main.c ├── rdp_buffer_wrap │ └── main.c ├── hfx_draw_single_tri │ └── main.c ├── hfx_persp_tex │ └── main.c ├── hfx_tex_tri │ └── main.c ├── hfx_cube │ └── main.c └── meson.build ├── libhfx_src ├── include │ ├── hfx_rb.h │ ├── hfx_regs.h │ ├── hfx_int.h │ ├── hfx_types.h │ └── hfx_rdp.h └── src │ ├── linker.S │ ├── hfx_cmd_dma.c │ ├── hfx_math.c │ ├── hfx_cmd.c │ ├── hfx_state.c │ ├── hfx_display.c │ ├── hfx_dispatch.c │ ├── hfx_texture.c │ ├── hfx_rb.c │ ├── hfx_matrix.c │ ├── hfx.c │ ├── hfx_render.c │ └── hfx_render_gl.c ├── ucode.ld ├── gl_test └── cube │ └── main.c └── meson.build /ucode_src/src/hfx_ucode.c: -------------------------------------------------------------------------------- 1 | #include "hfx_main.c" -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | build 2 | builddir 3 | *.o 4 | dev.sh 5 | *.swp 6 | -------------------------------------------------------------------------------- /libhfx_gl/include/hfx_int.h: -------------------------------------------------------------------------------- 1 | #define hfx_fatal_error(state, msg) -------------------------------------------------------------------------------- /libhfx_gl/include/hfx_types.h: -------------------------------------------------------------------------------- 1 | #ifndef HFX_TYPES_H 2 | #define HFX_TYPES_H 3 | #include 4 | 5 | typedef struct hfx_state { 6 | SDL_Window *window; 7 | SDL_GLContext context; 8 | 9 | float model_matrix[16]; 10 | } hfx_state; 11 | 12 | #endif 13 | -------------------------------------------------------------------------------- /include/ucode/hfx_asm.h: -------------------------------------------------------------------------------- 1 | #ifndef HFX_ASM_H 2 | #define HFX_ASM_H 3 | #include 4 | #define REG_RB_END $k0 5 | #define REG_RB_START $k1 6 | #define HFX_RDP_BUFFER_SIZE 1024 7 | 8 | #define HFX_SET_XBUX_DMEM_DMA 0x0002 9 | 10 | .set noreorder 11 | 12 | #endif 13 | -------------------------------------------------------------------------------- /tests/ucode_sort/ucode.c: -------------------------------------------------------------------------------- 1 | extern void draw_tri(void); 2 | extern void setup_data(void); 3 | extern void output_data(void); 4 | 5 | int main() 6 | { 7 | setup_data(); 8 | sort_tri(); 9 | output_data(); 10 | asm volatile ("break"); 11 | return 0; 12 | } 13 | -------------------------------------------------------------------------------- /tests/ucode_tri/ucode.c: -------------------------------------------------------------------------------- 1 | extern void draw_tri(void); 2 | extern void setup_data(void); 3 | extern void output_data(void); 4 | 5 | int main() 6 | { 7 | setup_data(); 8 | draw_tri(); 9 | //output_data(); 10 | asm volatile ("break"); 11 | return 0; 12 | } 13 | -------------------------------------------------------------------------------- /tests/ucode_mul_mat_vec/ucode.c: -------------------------------------------------------------------------------- 1 | extern void mul_mat_vec(void); 2 | extern void setup_data(void); 3 | extern void output_data(void); 4 | 5 | int main() 6 | { 7 | setup_data(); 8 | mul_mat_vec(); 9 | output_data(); 10 | asm volatile ("break"); 11 | return 0; 12 | } 13 | -------------------------------------------------------------------------------- /libhfx_src/include/hfx_rb.h: -------------------------------------------------------------------------------- 1 | #ifndef HFX_RB_H 2 | #define HFX_RB_H 3 | #include 4 | 5 | void hfx_rb_calc_size_mask(hfx_state *state); 6 | void hfx_rb_reserve(hfx_state *state, uint32_t num_cmds); 7 | void hfx_rb_queue(hfx_state *state, uint32_t cmd); 8 | void hfx_rb_submit(hfx_state *state); 9 | 10 | #endif -------------------------------------------------------------------------------- /tests/ucode_tri/loader.S: -------------------------------------------------------------------------------- 1 | .section .data 2 | 3 | .balign 8 4 | .global _ucode_data_start 5 | _ucode_data_start: 6 | 7 | .incbin "ucode_tri_ucode_data.bin" 8 | 9 | .balign 8 10 | .global _ucode_start 11 | _ucode_start: 12 | 13 | .incbin "ucode_tri_ucode_text.bin" 14 | 15 | .balign 8 16 | .global _ucode_end 17 | _ucode_end: 18 | -------------------------------------------------------------------------------- /libhfx_src/src/linker.S: -------------------------------------------------------------------------------- 1 | .section .data 2 | 3 | .balign 8 4 | .global _hfx_ucode_data_start 5 | _hfx_ucode_data_start: 6 | 7 | .incbin DATA_SECTION_BIN 8 | 9 | .balign 8 10 | .global _hfx_ucode_start 11 | _hfx_ucode_start: 12 | 13 | .incbin TEXT_SECTION_BIN 14 | 15 | .balign 8 16 | .global _hfx_ucode_end 17 | _hfx_ucode_end: 18 | -------------------------------------------------------------------------------- /tests/ucode_sort/loader.S: -------------------------------------------------------------------------------- 1 | .section .data 2 | 3 | .balign 8 4 | .global _ucode_data_start 5 | _ucode_data_start: 6 | 7 | .incbin "ucode_sort_ucode_data.bin" 8 | 9 | .balign 8 10 | .global _ucode_start 11 | _ucode_start: 12 | 13 | .incbin "ucode_sort_ucode_text.bin" 14 | 15 | .balign 8 16 | .global _ucode_end 17 | _ucode_end: 18 | -------------------------------------------------------------------------------- /tests/ucode_mul_mat_vec/loader.S: -------------------------------------------------------------------------------- 1 | .section .data 2 | 3 | .balign 8 4 | .global _ucode_data_start 5 | _ucode_data_start: 6 | 7 | .incbin "ucode_mul_mat_vec_ucode_data.bin" 8 | 9 | .balign 8 10 | .global _ucode_start 11 | _ucode_start: 12 | 13 | .incbin "ucode_mul_mat_vec_ucode_text.bin" 14 | 15 | .balign 8 16 | .global _ucode_end 17 | _ucode_end: 18 | -------------------------------------------------------------------------------- /ucode.ld: -------------------------------------------------------------------------------- 1 | SECTIONS 2 | { 3 | .data 0x0000 : AT (0x04000000) 4 | { 5 | "*crt.o"(.data) 6 | *(.*data*) 7 | *(.*bss*) 8 | } 9 | 10 | .text 0x0000 : AT (0x04001000) 11 | { 12 | "*crt.o"(.text) 13 | *(.text*) 14 | } 15 | 16 | /DISCARD/ : 17 | { 18 | *(.MIPS.abiflags) 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /libhfx_src/src/hfx_cmd_dma.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | void hfx_cmd_dma_read_to_rsp( 6 | hfx_state *state, uint32_t dmem_addr, void *addr, uint32_t size) 7 | { 8 | hfx_rb_reserve(state, 4); 9 | hfx_rb_queue(state, HFX_CMD_DMA); 10 | hfx_rb_queue(state, dmem_addr); 11 | hfx_rb_queue(state, (uint32_t)addr); 12 | hfx_rb_queue(state, size-1); 13 | } -------------------------------------------------------------------------------- /libhfx_src/src/hfx_math.c: -------------------------------------------------------------------------------- 1 | #include "hfx.h" 2 | 3 | HFXfixed hfx_addx(HFXfixed a, HFXfixed b) 4 | { 5 | return a + b; 6 | } 7 | 8 | HFXfixed hfx_subx(HFXfixed a, HFXfixed b) 9 | { 10 | return a - b; 11 | } 12 | 13 | HFXfixed hfx_mulx(HFXfixed a, HFXfixed b) 14 | { 15 | return (HFXfixed)(((int64_t)a * (int64_t)b) >> 16); 16 | } 17 | 18 | HFXfixed hfx_divx(HFXfixed a, HFXfixed b) 19 | { 20 | return (HFXfixed)(((int64_t)a << 16) / ((int64_t)b)); 21 | } -------------------------------------------------------------------------------- /tests/ucode_tri/ucode_asm.S: -------------------------------------------------------------------------------- 1 | #include "tri.S" 2 | 3 | .global setup_data 4 | setup_data: 5 | // Initalize $4 to 0 6 | li $4, 0 7 | 8 | // Load test data in vector registers 9 | lqv $v04, 0, 0, $0 10 | lqv $v05, 0, 1, $0 11 | lqv $v06, 0, 2, $0 12 | lqv $v07, 0, 3, $0 13 | lqv $v08, 0, 4, $0 14 | lqv $v09, 0, 5, $0 15 | jr $ra 16 | nop 17 | 18 | .global output_data 19 | output_data: 20 | // output vector registers to memory 21 | sqv $v16, 0, 0, $0 22 | sqv $v17, 0, 1, $0 23 | sqv $v18, 0, 2, $0 24 | sqv $v19, 0, 3, $0 25 | sqv $v20, 0, 4, $0 26 | sqv $v21, 0, 5, $0 27 | sqv $v14, 0, 6, $0 28 | sqv $v15, 0, 7, $0 29 | jr $ra 30 | nop 31 | -------------------------------------------------------------------------------- /libhfx_src/include/hfx_regs.h: -------------------------------------------------------------------------------- 1 | #ifndef HFX_REGS_H 2 | #define HFX_REGS_H 3 | #include "hfx_cmds.h" 4 | 5 | #define HFX_VADDR_RSP_DMEM 0x04000000 6 | #define HFX_VADDR_REG_STATUS (HFX_VADDR_RSP_DMEM|HFX_REG_STATUS) 7 | #define HFX_VADDR_REG_RB_START (HFX_VADDR_RSP_DMEM|HFX_REG_RB_START) 8 | #define HFX_VADDR_REG_RB_END (HFX_VADDR_RSP_DMEM|HFX_REG_RB_END) 9 | #define HFX_VADDR_REG_BAD_OP (HFX_VADDR_RSP_DMEM|HFX_REG_BAD_OP) 10 | 11 | 12 | #define HFX_VADDR_REG_RSP_PC (HFX_VADDR_RSP_DMEM|0x80000) 13 | #define HFX_VADDR_REG_RSP_STATUS (HFX_VADDR_RSP_DMEM|0x40010) 14 | 15 | #define HFX_RSP_CLEAR_HALT 0x00000001 16 | #define HFX_RSP_SET_HALT 0x00000002 17 | #define HFX_RSP_CLEAR_BROKE 0x00000004 18 | 19 | #endif -------------------------------------------------------------------------------- /libhfx_src/src/hfx_cmd.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | void hfx_cmd_nop(hfx_state *state) 7 | { 8 | hfx_rb_reserve(state, 1); 9 | hfx_rb_queue(state, HFX_CMD_NOP); 10 | } 11 | 12 | void hfx_cmd_int(hfx_state *state) 13 | { 14 | hfx_rb_reserve(state, 1); 15 | hfx_rb_queue(state, HFX_CMD_INT); 16 | } 17 | 18 | void hfx_cmd_rdp(hfx_state *state, uint32_t num_cmds, uint64_t *cmds) 19 | { 20 | uint32_t num_words = num_cmds*2; 21 | uint32_t cmd = ((num_words << 8) | HFX_CMD_SEND_RDP); 22 | hfx_rb_reserve(state, 1+num_words); 23 | hfx_rb_queue(state, cmd); 24 | for(int i=0; i < num_cmds; i++) 25 | { 26 | hfx_rb_queue(state, (uint32_t)(cmds[i] >> 32)); 27 | hfx_rb_queue(state, (uint32_t)(cmds[i])); 28 | } 29 | } -------------------------------------------------------------------------------- /tests/ucode_sort/ucode_asm.S: -------------------------------------------------------------------------------- 1 | #include "sort.S" 2 | 3 | .global setup_data 4 | setup_data: 5 | // Initalize $4 to 0 6 | li $4, 0 7 | 8 | // Load test data in vector registers 9 | lqv $v04, 0, 0, $0 10 | lqv $v05, 0, 1, $0 11 | lqv $v06, 0, 2, $0 12 | lqv $v07, 0, 3, $0 13 | lqv $v08, 0, 4, $0 14 | lqv $v09, 0, 5, $0 15 | jr $ra 16 | nop 17 | 18 | .global output_data 19 | output_data: 20 | // output vector registers to memory 21 | ssv $v04, 0, 0, $0 22 | ssv $v05, 0, 1, $0 23 | ssv $v04, 2, 2, $0 24 | ssv $v05, 2, 3, $0 25 | 26 | ssv $v06, 0, 4, $0 27 | ssv $v07, 0, 5, $0 28 | ssv $v06, 2, 6, $0 29 | ssv $v07, 2, 7, $0 30 | 31 | ssv $v08, 0, 8, $0 32 | ssv $v09, 0, 9, $0 33 | ssv $v08, 2, 10, $0 34 | ssv $v09, 2, 11, $0 35 | 36 | jr $ra 37 | nop 38 | -------------------------------------------------------------------------------- /tests/ucode_mul_mat_vec/ucode_asm.S: -------------------------------------------------------------------------------- 1 | #include "mat_vec.S" 2 | 3 | .global setup_data 4 | setup_data: 5 | // Initalize $4 to 0 6 | li $4, 0 7 | 8 | // Load test data in vector registers 9 | lqv $v04, 0, 0, $0 10 | lqv $v05, 0, 1, $0 11 | lqv $v06, 0, 2, $0 12 | lqv $v07, 0, 3, $0 13 | lqv $v08, 0, 4, $0 14 | lqv $v09, 0, 5, $0 15 | lqv $v10, 0, 6, $0 16 | lqv $v11, 0, 7, $0 17 | lqv $v12, 0, 8, $0 18 | lqv $v13, 0, 9, $0 19 | jr $ra 20 | nop 21 | 22 | .global output_data 23 | output_data: 24 | // output vector registers to memory 25 | ssv $v04, 0, 0, $0 26 | ssv $v05, 0, 1, $0 27 | ssv $v04, 2, 2, $0 28 | ssv $v05, 2, 3, $0 29 | ssv $v04, 4, 4, $0 30 | ssv $v05, 4, 5, $0 31 | ssv $v04, 6, 6, $0 32 | ssv $v05, 6, 7, $0 33 | 34 | jr $ra 35 | nop 36 | -------------------------------------------------------------------------------- /ucode_src/src/crt.S: -------------------------------------------------------------------------------- 1 | .set noreorder 2 | 3 | #include 4 | 5 | .text 6 | .global _start 7 | _start: 8 | /* Set stack to end of RAM */ 9 | move $gp, $zero 10 | addi $sp, $0, 0x1000 11 | 12 | /* Initalize vector register */ 13 | mtc2 zero, $v00, 0 14 | mtc2 zero, $v00, 1 15 | mtc2 zero, $v00, 2 16 | mtc2 zero, $v00, 3 17 | mtc2 zero, $v00, 4 18 | mtc2 zero, $v00, 5 19 | mtc2 zero, $v00, 6 20 | mtc2 zero, $v00, 7 21 | 22 | /* Note macros from libdragon for mtc2 use 23 | * named registers for the general purpose 24 | * registers, so in this case v0 == $2 */ 25 | li $v0, 2 26 | mtc2 v0, $v02, 2 27 | li $v0, 4 28 | mtc2 v0, $v02, 4 29 | 30 | /* Jump to main function */ 31 | jal main 32 | nop 33 | 34 | .data 35 | .global hfx_registers 36 | hfx_registers: 37 | .fill 32 38 | -------------------------------------------------------------------------------- /libhfx_src/src/hfx_state.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | void hfx_init_caps(hfx_state *state) 8 | { 9 | state->caps.dirty = true; 10 | 11 | state->caps.depth_test = false; 12 | state->caps.vertex_array = false; 13 | state->caps.color_array = false; 14 | state->caps.texture_2d = false; 15 | } 16 | 17 | void hfx_enable(hfx_state *state, uint32_t cap) 18 | { 19 | bool *value = NULL; 20 | switch(cap) 21 | { 22 | case HFX_DEPTH_TEST: 23 | value = &state->caps.depth_test; 24 | break; 25 | case HFX_VERTEX_ARRAY: 26 | value = &state->caps.vertex_array; 27 | break; 28 | case HFX_COLOR_ARRAY: 29 | value = &state->caps.color_array; 30 | break; 31 | case HFX_TEXTURE_2D: 32 | value = &state->caps.texture_2d; 33 | default: 34 | break; 35 | } 36 | 37 | if(value != NULL && *value != true) 38 | { 39 | *value = true; 40 | state->caps.dirty = true; 41 | } 42 | } -------------------------------------------------------------------------------- /include/ucode/fixed_vector.h: -------------------------------------------------------------------------------- 1 | #ifndef FIXED_VECTOR_H 2 | #define FIXED_VECTOR_H 3 | 4 | #include 5 | 6 | // TODO fill them with element redefine recommendations 7 | // from pg. 58 of the RSP programming guide 8 | // TODO submit pull request to libdragon to include these 9 | .set f, 0b0000 10 | .set q0, 0b0010 11 | .set q1, 0b0011 12 | .set h0, 0b0100 13 | .set h1, 0b0101 14 | .set h2, 0b0110 15 | .set h3, 0b0111 16 | .set w0, 0b1000 17 | .set w1, 0b1001 18 | .set w2, 0b1010 19 | .set w3, 0b1011 20 | .set w4, 0b1100 21 | .set w5, 0b1101 22 | .set w6, 0b1110 23 | .set w7, 0b1111 24 | 25 | .macro add_fixed res_hi, res_lo, a_hi, a_lo, b_hi, b_lo, e=0 26 | vaddc \res_lo, \a_lo, \b_lo, \e 27 | vadd \res_hi, \a_hi, \b_hi, \e 28 | .endm 29 | 30 | .macro sub_fixed res_hi, res_lo, a_hi, a_lo, b_hi, b_lo 31 | vsubc \res_lo, \a_lo, \b_lo, 0 32 | vsub \res_hi, \a_hi, \b_hi, 0 33 | .endm 34 | 35 | .macro mul_fixed res_hi, res_lo, a_hi, a_lo, b_hi, b_lo, e=0 36 | vmudl \res_hi, \a_lo, \b_lo, \e 37 | vmadm \res_hi, \a_hi, \b_lo, \e 38 | vmadn \res_lo, \a_lo, \b_hi, \e 39 | vmadh \res_hi, \a_hi, \b_hi, \e 40 | .endm 41 | 42 | 43 | #endif 44 | -------------------------------------------------------------------------------- /libhfx_src/include/hfx_int.h: -------------------------------------------------------------------------------- 1 | #ifndef HFX_INT_H 2 | #define HFX_INT_H 3 | #include 4 | #include 5 | 6 | #define HFX_UNUSED(x) (void)(x) 7 | 8 | void hfx_write_reg(uint32_t addr, uint32_t data); 9 | uint32_t hfx_read_reg(uint32_t addr); 10 | 11 | /* Internal HFX functions */ 12 | void *hfx_display_get_pointer(hfx_state *state); 13 | void hfx_init_caps(hfx_state *state); 14 | void hfx_set_mode(hfx_state *state); 15 | void hfx_init_textures(hfx_state *state); 16 | 17 | void hfx_wait_us(uint64_t num_us); 18 | void hfx_fatal_error(hfx_state *state, char *msg); 19 | 20 | uint32_t hfx_float_to_fixed(float a); 21 | 22 | /* Internal HFX cmds */ 23 | void hfx_cmd_nop(hfx_state *state); 24 | void hfx_cmd_int(hfx_state *state); 25 | void hfx_cmd_dma_read_to_rsp( 26 | hfx_state *state, uint32_t dmem_addr, void *addr, uint32_t size); 27 | void hfx_cmd_register_display(hfx_state *state); 28 | void hfx_cmd_rdp(hfx_state *state, uint32_t num_cmds, uint64_t *cmds); 29 | 30 | void hfx_matrix_vector_multiply(hfx_state *state, float *mat, float *vec, float *result); 31 | void hfx_render_tri_f(hfx_state *state, float *v1, float *v2, float *v3, float *vc1, float *vc2, float *vc3, float *vt1, float *vt2, float *vt3); 32 | 33 | 34 | #endif 35 | -------------------------------------------------------------------------------- /include/hfx_cmds.h: -------------------------------------------------------------------------------- 1 | #ifndef HFX_CMDS_H 2 | #define HFX_CMDS_H 3 | 4 | #define HFX_REGISTER_SPACE_SIZE 0x0020 5 | 6 | #define HFX_REG_STATUS 0x0000 7 | #define HFX_STATUS_INVALID_OP 0x0001 8 | #define HFX_STATUS_IN_RDP_RESERVE 0x0002 9 | #define HFX_STATUS_FIFO_EMPTY 0x0004 10 | #define HFX_REG_RB_ADDR 0x0004 11 | #define HFX_REG_RB_SIZE 0x0008 12 | #define HFX_REG_BAD_OP 0x000C 13 | // 0x000C Reserved 14 | #define HFX_REG_RB_START 0x0010 15 | #define HFX_REG_RB_END 0x0014 16 | #define HFX_REG_RDP_START 0x0018 17 | #define HFX_REG_RDP_END 0x001C 18 | 19 | #define HFX_CMD_ARG_MASK 0xFF00 20 | #define HFX_CMD_ARG_SHIFT 8 21 | #define HFX_TOTAL_CMDS 0x0020 22 | 23 | #define HFX_CMD_NOP 0x0000 24 | #define HFX_CMD_INT 0x0001 25 | #define HFX_CMD_DMA 0x0002 26 | #define HFX_CMD_DMA_TYPE_READ (0 << HFX_CMD_ARG_SHIFT) 27 | #define HFX_CMD_DMA_TYPE_WRITE (1 << HFX_CMD_ARG_SHIFT) 28 | #define HFX_CMD_BLANK_CMD 0x0003 /* TODO this command is unused and can be replaced */ 29 | #define HFX_CMD_SEND_RDP 0x0004 30 | #define HFX_CMD_TRI 0x0005 31 | #define HFX_CMD_TRI_3D (0 << HFX_CMD_ARG_SHIFT) 32 | #define HFX_CMD_TRI_2D (1 << HFX_CMD_ARG_SHIFT) 33 | 34 | #endif 35 | -------------------------------------------------------------------------------- /tests/basic_rdp_test/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | static resolution_t res = RESOLUTION_320x240; 13 | static bitdepth_t bit = DEPTH_16_BPP; 14 | 15 | static int done = 1; 16 | static hfx_state *state; 17 | 18 | static void hfx_int() 19 | { 20 | done = 0; 21 | } 22 | 23 | static uint64_t cmds[] = 24 | { 25 | 0xED000000005003C0ULL, 26 | 0xEFB000FF00004000ULL, 27 | 0xF7000000FF00FF00ULL, 28 | 0xF619019000000000ULL, 29 | 0xE900000000000000ULL, 30 | }; 31 | 32 | int main(void) 33 | { 34 | /* enable interrupts (on the CPU) */ 35 | init_interrupts(); 36 | 37 | /* Initialize peripherals */ 38 | display_init( res, bit, 2, GAMMA_NONE, ANTIALIAS_RESAMPLE ); 39 | 40 | register_DP_handler(hfx_int); 41 | set_DP_interrupt(1); 42 | 43 | state = hfx_init(); 44 | hfx_register_rsp_int(state, hfx_int); 45 | hfx_cmd_rdp(state, sizeof(cmds)/sizeof(uint64_t), cmds); 46 | hfx_rb_submit(state); 47 | 48 | 49 | while(1) 50 | { 51 | if(done == 0) 52 | { 53 | done = 1; 54 | 55 | hfx_swap_buffers(state); 56 | } 57 | 58 | #if 0 59 | *(uint32_t *)(0xA0000000 | 0x18000004) = 0x2222; 60 | *(uint32_t *)(0xA0000000 | 0x18000004) = hfx_read_reg(HFX_VADDR_REG_RB_START); 61 | *(uint32_t *)(0xA0000000 | 0x18000004) = hfx_read_reg(HFX_VADDR_REG_RB_END); 62 | #endif 63 | } 64 | } -------------------------------------------------------------------------------- /libhfx_src/include/hfx_types.h: -------------------------------------------------------------------------------- 1 | #ifndef HFX_TYPES_H 2 | #define HFX_TYPES_H 3 | #include 4 | #include 5 | #include 6 | 7 | #define HFX_RB_SIZE 1024 8 | 9 | #define HFX_MIN_TEXTURES 16 10 | 11 | typedef struct hfx_color { 12 | uint8_t r; 13 | uint8_t g; 14 | uint8_t b; 15 | uint8_t a; 16 | } hfx_color; 17 | 18 | typedef struct hfx_tex_info { 19 | uint32_t width; 20 | uint32_t height; 21 | uint32_t type; 22 | void *data; 23 | void *unsafe_data; 24 | bool alloced; 25 | } hfx_tex_info; 26 | 27 | struct hfx_state { 28 | uint32_t rb[HFX_RB_SIZE/4] __attribute__((aligned(8))); 29 | uint32_t rb_start; 30 | uint32_t rb_end; 31 | uint32_t rb_size; 32 | uint32_t rb_size_mask; 33 | display_context_t display; 34 | display_context_t last_display; 35 | void *display_ptr; 36 | 37 | struct 38 | { 39 | bool depth_test; 40 | bool vertex_array; 41 | bool color_array; 42 | bool texture_2d; 43 | bool dirty; 44 | } caps; 45 | 46 | struct 47 | { 48 | uint32_t current_tex; 49 | uint32_t num_texs; 50 | hfx_tex_info *tex_list; 51 | bool dirty; 52 | } tex_info; 53 | 54 | hfx_tex_info *cur_tex; 55 | 56 | uint64_t rdp_mode; 57 | 58 | hfx_color clear_color; 59 | hfx_color vertex_color; 60 | 61 | float model_matrix[16]; 62 | 63 | float *vertex_pointer; 64 | uint32_t vertex_size; 65 | 66 | uint8_t *color_pointer; 67 | uint32_t color_size; 68 | 69 | float *tex_coord_pointer; 70 | uint32_t tex_coord_size; 71 | 72 | struct 73 | { 74 | uint32_t width; 75 | uint32_t height; 76 | } display_dim; 77 | }; 78 | 79 | #endif 80 | -------------------------------------------------------------------------------- /tests/hfx_persp/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | static resolution_t res = RESOLUTION_320x240; 13 | static bitdepth_t bit = DEPTH_16_BPP; 14 | 15 | static int done = 1; 16 | static hfx_state *state; 17 | 18 | static char pbuf[256]; 19 | float v1[] = 20 | { 21 | -0.8f, -0.8f, -0.1f, 22 | 0.0f, -0.8f, -0.8f, 23 | 0.0f, 0.8f, -0.8f, 24 | 25 | -0.8f, -0.8f, -0.1f, 26 | 0.0f, 0.8f, -0.8f, 27 | -0.8f, 0.8f, -0.1f, 28 | 29 | }; 30 | 31 | uint8_t vc1[] = 32 | { 33 | 255.0f, 0.0f, 0.0f, 255.0f, 34 | 255.0f, 0.0f, 0.0f, 255.0f, 35 | 255.0f, 0.0f, 0.0f, 255.0f, 36 | 37 | 255.0f, 0.0f, 0.0f, 255.0f, 38 | 255.0f, 0.0f, 0.0f, 255.0f, 39 | 255.0f, 0.0f, 0.0f, 255.0f, 40 | }; 41 | 42 | int main(void) 43 | { 44 | /* enable interrupts (on the CPU) */ 45 | init_interrupts(); 46 | 47 | /* Initialize peripherals */ 48 | display_init( res, bit, 2, GAMMA_NONE, ANTIALIAS_RESAMPLE ); 49 | 50 | state = hfx_init(); 51 | 52 | hfx_vertex_pointer(state, 3, HFX_FLOAT, 0, v1); 53 | hfx_color_pointer(state, 4, HFX_UNSIGNED_BYTE, 0, vc1); 54 | hfx_clear_color_f(state, 0.0f, 0.0f, 0.0f, 1.0f); 55 | 56 | float angle = 10.0f; 57 | 58 | while(1) 59 | { 60 | angle += 1.0f; 61 | // Queue the next frame up 62 | hfx_clear(state, HFX_COLOR_BUFFER_BIT|HFX_DEPTH_BUFFER_BIT); 63 | hfx_load_identity(state); 64 | hfx_persp_f(state, 120.0f, 320.0f/240.0f, 0.1f, 100.0f); 65 | 66 | hfx_rotate_f(state, angle, 0.0f, 1.0f, 0.0f); 67 | 68 | hfx_draw_arrays(state, HFX_TRIANGLES, 0, 6); 69 | 70 | hfx_swap_buffers(state); 71 | } 72 | } -------------------------------------------------------------------------------- /tests/hfx_clear/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | static resolution_t res = RESOLUTION_320x240; 13 | static bitdepth_t bit = DEPTH_16_BPP; 14 | 15 | static int done = 1; 16 | static hfx_state *state; 17 | 18 | /* This command sets the clip area */ 19 | /* Should not be required, internal library code should */ 20 | /* Handle this on init */ 21 | static uint64_t cmds1[] = 22 | { 23 | 0xED000000005003C0ULL, 24 | }; 25 | 26 | /* This triggers a full sync to happen */ 27 | /* eventually this should all be moved into the swap buffers command */ 28 | static uint64_t cmds[] = 29 | { 30 | 0xE900000000000000ULL, 31 | }; 32 | 33 | static void hfx_int() 34 | { 35 | done = 0; 36 | } 37 | 38 | int main(void) 39 | { 40 | /* enable interrupts (on the CPU) */ 41 | init_interrupts(); 42 | 43 | /* Initialize peripherals */ 44 | display_init( res, bit, 2, GAMMA_NONE, ANTIALIAS_RESAMPLE ); 45 | 46 | register_DP_handler(hfx_int); 47 | set_DP_interrupt(1); 48 | 49 | state = hfx_init(); 50 | hfx_register_rsp_int(state, hfx_int); 51 | 52 | // TODO this rdp command is only here to set the default clip 53 | // Should really be part of the hfx library 54 | hfx_cmd_rdp(state, sizeof(cmds1)/sizeof(uint64_t), cmds1); 55 | hfx_clear_color_f(state, 1.0f, 0.0f, 0.0f, 1.0f); 56 | hfx_clear(state, HFX_COLOR_BUFFER_BIT); 57 | hfx_cmd_rdp(state, sizeof(cmds)/sizeof(uint64_t), cmds); 58 | hfx_rb_submit(state); 59 | 60 | 61 | while(1) 62 | { 63 | if(done == 0) 64 | { 65 | done = 1; 66 | 67 | graphics_draw_text(state->display, 0, 100, "Done"); 68 | 69 | hfx_swap_buffers(state); 70 | } 71 | } 72 | } -------------------------------------------------------------------------------- /tests/basic_rb_test/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | static resolution_t res = RESOLUTION_320x240; 12 | static bitdepth_t bit = DEPTH_16_BPP; 13 | 14 | static uint32_t array[4] __attribute__((aligned(8))) = {1,2,3,4}; 15 | static uint32_t array2[4] __attribute__((aligned(8))) = {5,6,7,8}; 16 | static uint32_t buffer[1024] __attribute__((aligned(8))); 17 | 18 | static int done = 1; 19 | 20 | 21 | static display_context_t disp = 0; 22 | 23 | static void hfx_int() 24 | { 25 | done = 0; 26 | } 27 | 28 | int main(void) 29 | { 30 | /* enable interrupts (on the CPU) */ 31 | init_interrupts(); 32 | 33 | /* Initialize peripherals */ 34 | display_init( res, bit, 2, GAMMA_NONE, ANTIALIAS_RESAMPLE ); 35 | 36 | hfx_state *state = hfx_init(); 37 | hfx_register_rsp_int(state, hfx_int); 38 | 39 | hfx_cmd_dma_read_to_rsp(state, 2048, &array, sizeof(array)); 40 | hfx_cmd_int(state); 41 | hfx_cmd_dma_read_to_rsp(state, 2048, &array2, sizeof(array)); 42 | hfx_cmd_int(state); 43 | hfx_rb_submit(state); 44 | 45 | 46 | console_init(); 47 | console_set_render_mode(RENDER_MANUAL); 48 | console_clear(); 49 | 50 | 51 | printf("Running\n"); 52 | console_render(); 53 | 54 | while(1) 55 | { 56 | if(done == 0) 57 | { 58 | done = 1; 59 | read_data(buffer, 4096); 60 | printf("Buffer values %lu %lu %lu %lu\n", buffer[512], buffer[513], buffer[514], buffer[515]); 61 | printf("Pointers are %lu %lu\n", buffer[HFX_REG_RB_END/4], buffer[HFX_REG_RB_START/4]); 62 | printf("PC value 0x%lx\n", *(volatile uint32_t *) 0xA4080000); 63 | console_render(); 64 | 65 | hfx_restart_rsp(state); 66 | } 67 | } 68 | } -------------------------------------------------------------------------------- /libhfx_src/src/hfx_display.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #define DISPLAY_TIMEOUT (1*1000*1000) 11 | #define get_disp_buffer(x) __safe_buffer[(x)-1] 12 | 13 | uint16_t hfx_depth_buffer[320*240] __attribute__((aligned(64))); 14 | 15 | uint16_t *depth_buffer; 16 | 17 | extern void *__safe_buffer[]; 18 | 19 | void *hfx_display_get_pointer(hfx_state *state) 20 | { 21 | return state->display_ptr; 22 | } 23 | 24 | void hfx_get_display(hfx_state *state) 25 | { 26 | display_context_t disp = 0; 27 | state->last_display = state->display; 28 | uint32_t count = 0; 29 | do 30 | { 31 | if(count >= DISPLAY_TIMEOUT) 32 | { 33 | break; 34 | } 35 | 36 | count += 1; 37 | disp = display_lock(); 38 | hfx_wait_us(1); 39 | } while(disp == 0); 40 | 41 | if(count >= DISPLAY_TIMEOUT) 42 | { 43 | hfx_fatal_error(state, "timeout wait for display"); 44 | } 45 | 46 | state->display = disp; 47 | state->display_ptr = (void*)(0x1ffffff & (uintptr_t)get_disp_buffer(state->display)); 48 | } 49 | 50 | void hfx_cmd_register_display(hfx_state *state) 51 | { 52 | depth_buffer = hfx_depth_buffer; 53 | uint64_t buffer_cmds[2]; 54 | /* Get display handle */ 55 | hfx_get_display(state); 56 | 57 | buffer_cmds[0] = HFX_RDP_PKT_SET_COLOR_IMAGE(HFX_RDP_CMD_SET_COLOR_IMAGE_FORMAT_RGBA, HFX_RDP_CMD_SET_COLOR_IMAGE_SIZE_16B, state->display_dim.width, hfx_display_get_pointer(state)); 58 | buffer_cmds[1] = HFX_RDP_PKT_SET_Z_IMAGE(0x1ffffff&(uintptr_t)hfx_depth_buffer); 59 | hfx_cmd_rdp(state, sizeof(buffer_cmds)/sizeof(uint64_t), buffer_cmds); 60 | } 61 | 62 | 63 | void hfx_swap_buffers(hfx_state *state) 64 | { 65 | // TODO if we want to support triple buffering 66 | // we wouldn't wait for idle here 67 | hfx_wait_for_idle(state); 68 | display_show(state->display); 69 | hfx_cmd_register_display(state); 70 | } -------------------------------------------------------------------------------- /ucode_src/include/mat_vec.S: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | // Assume data is in the following format 4 | // v04, v05 vector 5 | // v06, v07 matrix row 1 6 | // v08, v09 matrix row 2 7 | // v10, v11 matrix row 3 8 | // v12, v13 matrix row 4 9 | // Note: Matrix is already transposed so each vector 10 | // register represents one row in the matrix 11 | // Return results transformed vector in v04, v05 12 | .global mul_mat_vec 13 | mul_mat_vec: 14 | // Multiply vector with first row of matrix 15 | mul_fixed $v14, $v15, $v06, $v07, $v04, $v05 16 | // Accumulate the results of the multiply 17 | add_fixed $v16, $v17, $v14, $v15, $v14, $v15, w1 18 | add_fixed $v16, $v17, $v16, $v17, $v14, $v15, w2 19 | add_fixed $v16, $v17, $v16, $v17, $v14, $v15, w3 20 | 21 | // Multiply vector with first second of matrix 22 | mul_fixed $v14, $v15, $v08, $v09, $v04, $v05 23 | // Accumulate the results of the multiply 24 | add_fixed $v18, $v19, $v14, $v15, $v14, $v15, w1 25 | add_fixed $v18, $v19, $v18, $v19, $v14, $v15, w2 26 | add_fixed $v18, $v19, $v18, $v19, $v14, $v15, w3 27 | 28 | // Multiply vector with third row of matrix 29 | mul_fixed $v14, $v15, $v10, $v11, $v04, $v05 30 | // Accumulate the results of the multiply 31 | add_fixed $v20, $v21, $v14, $v15, $v14, $v15, w1 32 | add_fixed $v20, $v21, $v20, $v21, $v14, $v15, w2 33 | add_fixed $v20, $v21, $v20, $v21, $v14, $v15, w3 34 | 35 | // Multiply vector with first row of matrix 36 | mul_fixed $v14, $v15, $v12, $v13, $v04, $v05 37 | // Accumulate the results of the multiply 38 | add_fixed $v22, $v23, $v14, $v15, $v14, $v15, w1 39 | add_fixed $v22, $v23, $v22, $v23, $v14, $v15, w2 40 | add_fixed $v22, $v23, $v22, $v23, $v14, $v15, w3 41 | 42 | // Store results back in v04, v05 43 | vmov $v04, 0, $v16, w0 44 | vmov $v05, 0, $v17, w0 45 | vmov $v04, 1, $v18, w0 46 | vmov $v05, 1, $v19, w0 47 | vmov $v04, 2, $v20, w0 48 | vmov $v05, 2, $v21, w0 49 | vmov $v04, 3, $v22, w0 50 | vmov $v05, 3, $v23, w0 51 | 52 | jr $ra 53 | nop 54 | -------------------------------------------------------------------------------- /libhfx_src/src/hfx_dispatch.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "GL/gl.h" 3 | 4 | hfx_state *g_hfx_state = NULL; 5 | 6 | void libhfx_init(void) 7 | { 8 | g_hfx_state = hfx_init(); 9 | } 10 | 11 | void glEnable (GLenum cap) 12 | { 13 | hfx_enable(g_hfx_state, cap); 14 | } 15 | 16 | void glClearColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha) 17 | { 18 | hfx_clear_color_f(g_hfx_state, red, green, blue, alpha); 19 | } 20 | 21 | void glClear(GLbitfield mask) 22 | { 23 | hfx_clear(g_hfx_state, mask); 24 | } 25 | 26 | void glLoadIdentity(void) 27 | { 28 | hfx_load_identity(g_hfx_state); 29 | } 30 | 31 | void glTranslatef(GLfloat x, GLfloat y, GLfloat z) 32 | { 33 | hfx_translate_f(g_hfx_state, x, y, z); 34 | } 35 | 36 | void glRotatef(GLfloat angle, GLfloat x, GLfloat y, GLfloat z) 37 | { 38 | hfx_rotate_f(g_hfx_state, angle, x, y, z); 39 | } 40 | 41 | void glScalef(GLfloat x, GLfloat y, GLfloat z) 42 | { 43 | hfx_scale_f(g_hfx_state, x, y, z); 44 | } 45 | 46 | void glOrthof(GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat zNear, GLfloat zFar) 47 | { 48 | hfx_ortho_f(g_hfx_state, left, right, bottom, top, zNear, zFar); 49 | } 50 | 51 | void glMultMatrixf(const GLfloat *m) 52 | { 53 | hfx_mult_matrix_f(g_hfx_state, (float*)m); 54 | } 55 | 56 | void glVertexPointer(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer) 57 | { 58 | hfx_vertex_pointer(g_hfx_state, size, type, stride, (void*)pointer); 59 | } 60 | 61 | void glColorPointer(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer) 62 | { 63 | hfx_color_pointer(g_hfx_state, size, type, stride, (void*)pointer); 64 | } 65 | 66 | void glTexCoordPointer(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer) 67 | { 68 | hfx_tex_coord_pointer(g_hfx_state, size, type, stride, (void*)pointer); 69 | } 70 | 71 | void glDrawArrays(GLenum mode, GLint first, GLsizei count) 72 | { 73 | hfx_draw_arrays(g_hfx_state, mode, first, count); 74 | } 75 | 76 | void glGenTextures(GLsizei n, GLuint *textures) 77 | { 78 | hfx_gen_textures(g_hfx_state, n, (uint32_t*)textures); 79 | } 80 | 81 | void glTexImage2D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels) 82 | { 83 | hfx_tex_image_2d(g_hfx_state, target, level, internalformat, width, height, border, format, type, (void*)pixels); 84 | } -------------------------------------------------------------------------------- /libhfx_src/src/hfx_texture.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #define TEXTURE_ALIGN 64 11 | #define ALIGN_64BYTE(x) ((void *)(((uint32_t)(x)+63) & 0xFFFFFFC0)) 12 | 13 | void hfx_init_textures(hfx_state *state) 14 | { 15 | state->tex_info.current_tex = 0; 16 | state->tex_info.num_texs = HFX_MIN_TEXTURES; 17 | state->tex_info.tex_list = (hfx_tex_info*)malloc(state->tex_info.num_texs*sizeof(hfx_tex_info)); 18 | for(int i = 0; i < state->tex_info.num_texs; i++) 19 | { 20 | state->tex_info.tex_list[i].alloced = false; 21 | state->tex_info.tex_list[i].data = NULL; 22 | } 23 | 24 | /* Mark default texture 0 as already allocated */ 25 | /* Required to be conformant with OpenGL */ 26 | state->tex_info.tex_list[0].alloced = true; 27 | } 28 | 29 | void hfx_gen_textures(hfx_state *state, uint32_t n, uint32_t *textures) 30 | { 31 | for(int i = 0; i < n; i++) 32 | { 33 | bool found = false; 34 | for(int j = 0; j < state->tex_info.num_texs; j++) 35 | { 36 | if(state->tex_info.tex_list[j].alloced == false) 37 | { 38 | found = true; 39 | textures[i] = j; 40 | } 41 | 42 | // TODO if found is false realloc array 43 | // Right now only 16 textures can exist 44 | HFX_UNUSED(found); 45 | } 46 | } 47 | } 48 | 49 | void hfx_tex_image_2d(hfx_state *state, uint32_t target, int32_t level, int32_t internalformat, uint32_t width, uint32_t height, int32_t border, uint32_t format, uint32_t type, const void *data) 50 | { 51 | int bpp = 2; // TODO Have function to get proper bit depth 52 | uint32_t size = width * height * bpp; 53 | hfx_tex_info *cur_tex = &state->tex_info.tex_list[state->tex_info.current_tex]; 54 | 55 | cur_tex->unsafe_data = malloc(size + (TEXTURE_ALIGN)); 56 | cur_tex->data = ALIGN_64BYTE(cur_tex->unsafe_data); 57 | 58 | memcpy(cur_tex->data, data, size); 59 | /* Need to flush and invalidate cache so texture memory is commited 60 | * to RAM and visible by the RDP */ 61 | data_cache_hit_writeback_invalidate(cur_tex->data, size); 62 | 63 | cur_tex->width = width; 64 | cur_tex->height = height; 65 | cur_tex->type = HFX_UNSIGNED_SHORT_5_5_5_1; 66 | state->tex_info.dirty = true; 67 | } 68 | -------------------------------------------------------------------------------- /include/ucode/rsp.h: -------------------------------------------------------------------------------- 1 | #ifndef RSP_H 2 | #define RSP_H 3 | 4 | .macro genReg 5 | .equ hex.$0, 0 6 | .equ hex.$5, 1 7 | .equ hex.$2, 2 8 | .equ hex.$3, 3 9 | .equ hex.$4, 4 10 | .equ hex.$5, 5 11 | .equ hex.$6, 6 12 | .equ hex.$7, 7 13 | .equ hex.$8, 8 14 | .equ hex.$9, 9 15 | .equ hex.$10, 10 16 | .equ hex.$11, 11 17 | .equ hex.$12, 12 18 | .equ hex.$13, 13 19 | .equ hex.$14, 14 20 | .equ hex.$15, 15 21 | .equ hex.$16, 16 22 | .equ hex.$17, 17 23 | .equ hex.$18, 18 24 | .equ hex.$19, 19 25 | .equ hex.$20, 20 26 | .equ hex.$21, 21 27 | .equ hex.$22, 22 28 | .equ hex.$23, 23 29 | .equ hex.$24, 24 30 | .equ hex.$25, 25 31 | .equ hex.$26, 26 32 | .equ hex.$27, 27 33 | .equ hex.$28, 28 34 | .equ hex.$29, 29 35 | .equ hex.$30, 30 36 | .equ hex.$31, 31 37 | .endm 38 | 39 | .macro namedReg 40 | .equ hex.$zero, 0 41 | .equ hex.$at, 1 42 | .equ hex.$v0, 2 43 | .equ hex.$v1, 3 44 | .equ hex.$a0, 4 45 | .equ hex.$a1, 5 46 | .equ hex.$a2, 6 47 | .equ hex.$a3, 7 48 | .equ hex.$t0, 8 49 | .equ hex.$t1, 9 50 | .equ hex.$t2, 10 51 | .equ hex.$t3, 11 52 | .equ hex.$t4, 12 53 | .equ hex.$t5, 13 54 | .equ hex.$t6, 14 55 | .equ hex.$t7, 15 56 | .equ hex.$s0, 16 57 | .equ hex.$s1, 17 58 | .equ hex.$s2, 18 59 | .equ hex.$s3, 19 60 | .equ hex.$s4, 20 61 | .equ hex.s5, 21 62 | .equ hex.$s6, 22 63 | .equ hex.$s7, 23 64 | .equ hex.$t8, 24 65 | .equ hex.$t9, 25 66 | .equ hex.$k0, 26 67 | .equ hex.$k1, 27 68 | .equ hex.$gp, 28 69 | .equ hex.$sp, 29 70 | .equ hex.$fp, 30 71 | .equ hex.$ra, 31 72 | .endm 73 | 74 | .macro cReg 75 | .set $c0, 0x0 76 | .set $c1, 0x1 77 | .set $c2, 0x2 78 | .set $c3, 0x3 79 | .set $c4, 0x4 80 | .set $c5, 0x5 81 | .set $c6, 0x6 82 | .set $c7, 0x7 83 | .set $c8, 0x8 84 | .set $c9, 0x9 85 | .set $c10, 0xA 86 | .set $c11, 0xB 87 | .set $c12, 0xC 88 | .set $c13, 0xD 89 | .set $c14, 0xE 90 | .set $c15, 0xF 91 | .endm 92 | 93 | .macro mtc0 reg, creg 94 | namedReg 95 | genReg 96 | cReg 97 | .long (0x40800000 | hex.\reg << 16 | \creg << 11) 98 | .endm 99 | 100 | .macro mfc0 reg, creg 101 | genReg 102 | hexGeneralRegisters 103 | cReg 104 | .long (0x40000000 | hex.\reg << 16 | \creg << 11) 105 | .endm 106 | 107 | #endif 108 | -------------------------------------------------------------------------------- /ucode_src/include/sort.S: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | 4 | // Assume vertex data is the following format 5 | // v04, v05 v1 6 | // v06, v07 v2 7 | // v08, v09 v3 8 | // This function will take vertex data in any order 9 | // and sort them so v04, v05 will be the highest vert, 10 | // v06, v07 will be the middle vert 11 | // and v08,v09 will be the lowest vert 12 | .global sort_tri 13 | sort_tri: 14 | li $t7, 0xFFFF0000 15 | // Grab fixed point y1 and store in a1 16 | mfc2 a1, $v04, 2 17 | mfc2 a2, $v05, 2 18 | sll $a1, $a1, 16 19 | and $a2, $a2, $t7 20 | or $a1, $a1, $a2 21 | 22 | // Grab fixed point y2 and store in a2 23 | mfc2 a2, $v06, 2 24 | mfc2 a3, $v07, 2 25 | sll $a2, $a2, 16 26 | and $a3, $a3, $t7 27 | or $a2, $a2, $a3 28 | 29 | // Grab fixed point y3 and store in a3 30 | mfc2 a3, $v08, 2 31 | mfc2 t0, $v09, 2 32 | sll $a3, $a3, 16 33 | and $t0, $t0, $t7 34 | or $a3, $a3, $t0 35 | 36 | // Check if y1 > y2 37 | slt $t1, $a2, $a1 38 | beq $t1, $zero, second_compare 39 | nop 40 | 41 | // Set temp (v10,v11) to v2 42 | vaddc $v10, $v06, $v00, 0 43 | vaddc $v11, $v07, $v00, 0 44 | 45 | // Set v2 = v1 46 | vaddc $v06, $v04, $v00, 0 47 | vaddc $v07, $v05, $v00, 0 48 | 49 | // Set v1 = temp 50 | vaddc $v04, $v10, $v00, 0 51 | vaddc $v05, $v11, $v00, 0 52 | 53 | // Swap y1 and y2 54 | move $t0, $a1 55 | move $a1, $a2 56 | move $a2, $t0 57 | 58 | // Check if y2 > y3 59 | second_compare: 60 | slt $t1, $a3, $a2 61 | beq $t1, $zero, third_compare 62 | nop 63 | 64 | // Set temp (v10,v11) to v3 65 | vaddc $v10, $v08, $v00, 0 66 | vaddc $v11, $v09, $v00, 0 67 | 68 | // Set v3 to v2 69 | vaddc $v08, $v06, $v00, 0 70 | vaddc $v09, $v07, $v00, 0 71 | 72 | // Set v2 to temp 73 | vaddc $v06, $v10, $v00, 0 74 | vaddc $v07, $v11, $v00, 0 75 | 76 | // Swap y2 and y3 77 | move $t0, $a2 78 | move $a2, $a3 79 | move $a3, $t0 80 | 81 | // Check if y1 > y2 82 | third_compare: 83 | slt $t1, $a2, $a1 84 | beq $t1, $zero, done_compare 85 | nop 86 | 87 | // Set temp (v10,v11) to v2 88 | vaddc $v10, $v06, $v00, 0 89 | vaddc $v11, $v07, $v00, 0 90 | 91 | // Set v2 = v1 92 | vaddc $v06, $v04, $v00, 0 93 | vaddc $v07, $v05, $v00, 0 94 | 95 | // Set v1 = temp 96 | vaddc $v04, $v10, $v00, 0 97 | vaddc $v05, $v11, $v00, 0 98 | 99 | done_compare: 100 | 101 | jr $ra 102 | nop 103 | -------------------------------------------------------------------------------- /tests/rdp_buffer_wrap/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | /* With current implementation RDP buffer is 256 bytes long */ 13 | /* which means only 32 64-bit commands can fit in the buffer */ 14 | /* but during init the hfx library sends a single command to set the */ 15 | /* Framebuffer address. So we will send 30 commands to start before sending */ 16 | /* the commands that we actually want to do work */ 17 | #define WRAP_LIMIT 30 18 | 19 | #define BUFFER_SIZE_BYTES 256 20 | 21 | static resolution_t res = RESOLUTION_320x240; 22 | static bitdepth_t bit = DEPTH_16_BPP; 23 | 24 | static int done = 1; 25 | static hfx_state *state; 26 | 27 | static char print_buf[256]; 28 | 29 | static void hfx_int() 30 | { 31 | done = 0; 32 | } 33 | 34 | static uint64_t null_cmds[WRAP_LIMIT]; 35 | 36 | static uint64_t cmds[] = 37 | { 38 | 0xED000000005003C0ULL, 39 | 0xEFB000FF00004000ULL, 40 | 0xF7000000FF00FF00ULL, 41 | 0xF619019000000000ULL, 42 | 0xE900000000000000ULL, 43 | }; 44 | 45 | int main(void) 46 | { 47 | /* enable interrupts (on the CPU) */ 48 | init_interrupts(); 49 | 50 | /* Initialize peripherals */ 51 | display_init( res, bit, 2, GAMMA_NONE, ANTIALIAS_RESAMPLE ); 52 | 53 | register_DP_handler(hfx_int); 54 | set_DP_interrupt(1); 55 | 56 | for(uint32_t i = 0; i < WRAP_LIMIT; i++) 57 | { 58 | null_cmds[i] = 0xED000000005003C0ULL; 59 | } 60 | 61 | state = hfx_init(); 62 | hfx_register_rsp_int(state, hfx_int); 63 | 64 | 65 | hfx_cmd_rdp(state, sizeof(null_cmds)/sizeof(uint64_t), null_cmds); 66 | hfx_cmd_rdp(state, sizeof(cmds)/sizeof(uint64_t), cmds); 67 | hfx_rb_submit(state); 68 | 69 | 70 | while(1) 71 | { 72 | if(done == 0) 73 | { 74 | //done = 1; 75 | uint32_t rdp_start = hfx_read_reg(0x04100000); 76 | uint32_t rdp_end = hfx_read_reg(0x04100004); 77 | uint32_t rdp_current = hfx_read_reg(0x04100008); 78 | 79 | sprintf(print_buf, "Start 0x%lx, end 0x%lx, current 0x%lx", rdp_start, rdp_end, rdp_current); 80 | graphics_draw_text(state->display, 0, 0, print_buf); 81 | 82 | if(rdp_current >= (rdp_start+BUFFER_SIZE_BYTES)) 83 | { 84 | graphics_draw_text(state->display, 0, 100, "RDP command buffer overflowed!"); 85 | } 86 | 87 | hfx_swap_buffers(state); 88 | } 89 | } 90 | } -------------------------------------------------------------------------------- /tests/hfx_draw_single_tri/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | static resolution_t res = RESOLUTION_320x240; 13 | static bitdepth_t bit = DEPTH_16_BPP; 14 | 15 | static int done = 1; 16 | static hfx_state *state; 17 | 18 | static char pbuf[256]; 19 | float v1[] = 20 | { 21 | 0.0f, 0.0f, 0.0f, 22 | 0.5f, 0.0f, 0.0f, 23 | 0.5f / 2.0f, 0.5f, 0.0f, 24 | }; 25 | 26 | uint8_t vc1[] = 27 | { 28 | 255.0f, 0.0f, 0.0f, 255.0f, 29 | 0.0f, 255.0f, 0.0f, 255.0f, 30 | 0.0f, 0.0f, 255.0f, 255.0f, 31 | }; 32 | 33 | int main(void) 34 | { 35 | /* enable interrupts (on the CPU) */ 36 | init_interrupts(); 37 | 38 | /* Initialize peripherals */ 39 | display_init( res, bit, 2, GAMMA_NONE, ANTIALIAS_RESAMPLE ); 40 | 41 | state = hfx_init(); 42 | 43 | hfx_vertex_pointer(state, 3, HFX_FLOAT, 0, v1); 44 | hfx_color_pointer(state, 4, HFX_UNSIGNED_BYTE, 0, vc1); 45 | 46 | hfx_load_identity(state); 47 | //hfx_rotate_f(state, 50, 0, 0, 1); 48 | hfx_translate_f(state, 50.0f, 50.0f, 0.0f); 49 | 50 | hfx_draw_arrays(state, HFX_TRIANGLES, 0, 3); 51 | 52 | hfx_clear_color_f(state, 0.0f, 0.0f, 0.0f, 1.0f); 53 | 54 | float angle = 0.0; 55 | 56 | while(1) 57 | { 58 | if(angle == 360) 59 | angle = 0; 60 | else 61 | angle += 1.0f; 62 | done = 1; 63 | 64 | // This angle causes graphical glitch 65 | //angle = 240.0f; 66 | 67 | // Queue the next frame up 68 | hfx_clear(state, HFX_COLOR_BUFFER_BIT|HFX_DEPTH_BUFFER_BIT); 69 | hfx_load_identity(state); 70 | //hfx_translate_f(state, 100.0f, 100.0f, 0.0f); 71 | hfx_rotate_f(state, angle, 0, 0, 1); 72 | 73 | hfx_draw_arrays(state, HFX_TRIANGLES, 0, 3); 74 | 75 | hfx_wait_for_idle(state); 76 | 77 | sprintf(pbuf, "Done %f", angle); 78 | graphics_draw_text(state->display, 0, 100, pbuf); 79 | 80 | sprintf(pbuf, "Start 0x%08lx, end 0x%08lx", hfx_read_reg(HFX_VADDR_REG_RB_START), state->rb_end); 81 | graphics_draw_text(state->display, 0, 130, pbuf); 82 | 83 | uint32_t rdp_start = hfx_read_reg(0x04100000); 84 | uint32_t rdp_end = hfx_read_reg(0x04100004); 85 | uint32_t rdp_current = hfx_read_reg(0x04100008); 86 | 87 | sprintf(pbuf, "Start 0x%lx, end 0x%lx, current 0x%lx", rdp_start, rdp_end, rdp_current); 88 | graphics_draw_text(state->display, 0, 160, pbuf); 89 | 90 | hfx_swap_buffers(state); 91 | } 92 | } -------------------------------------------------------------------------------- /libhfx_src/src/hfx_rb.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #define RB_TIMEOUT (1*1000*1000) 11 | 12 | bool hfx_wait_for_rb = false; 13 | 14 | void hfx_rb_calc_size_mask(hfx_state *state) 15 | { 16 | // TODO replace this would properly calculated mask 17 | state->rb_size_mask = 0x3FF; 18 | } 19 | 20 | void hfx_rb_reserve(hfx_state *state, uint32_t num_cmds) 21 | { 22 | uint32_t num_bytes = num_cmds*4; 23 | uint32_t rb_start = hfx_read_reg(HFX_VADDR_REG_RB_START); 24 | uint32_t rb_size = 0; 25 | uint32_t num_bytes_in_buffer = 0; 26 | uint32_t count = 0; 27 | 28 | /* If command buffer is not empty */ 29 | if(state->rb_end != rb_start) 30 | { 31 | num_bytes_in_buffer = (state->rb_end - rb_start + 4) & state->rb_size_mask; 32 | rb_size = state->rb_size - num_bytes_in_buffer; 33 | 34 | if(rb_size < num_bytes) 35 | { 36 | /* If there is not enough space in buffer */ 37 | /* submit commands and wait until there is */ 38 | /* enough space to insert the new commands */ 39 | hfx_rb_submit(state); 40 | 41 | hfx_wait_for_rb = true; 42 | /* While there is not enough space in the command buffer */ 43 | do { 44 | if(count >= RB_TIMEOUT) 45 | { 46 | break; 47 | } 48 | count += 1; 49 | rb_start = hfx_read_reg(HFX_VADDR_REG_RB_START); 50 | num_bytes_in_buffer = (state->rb_end - rb_start + 4) & state->rb_size_mask; 51 | rb_size = state->rb_size - num_bytes_in_buffer; 52 | hfx_wait_us(1); 53 | } while(rb_size < num_bytes); 54 | 55 | if(count >= RB_TIMEOUT) 56 | { 57 | hfx_fatal_error(state, "timeout wait for rb"); 58 | } 59 | else 60 | { 61 | hfx_wait_for_rb = false; 62 | } 63 | } 64 | } 65 | } 66 | 67 | 68 | void hfx_rb_queue(hfx_state *state, uint32_t cmd) 69 | { 70 | state->rb[state->rb_end/4] = cmd; 71 | state->rb_end = (state->rb_end + 4) & state->rb_size_mask; 72 | } 73 | 74 | void hfx_rb_submit(hfx_state *state) 75 | { 76 | // TODO likely need to decrement rb_end by 4 here 77 | /* Flush cache to make sure all commands are written to memory for DMA */ 78 | data_cache_hit_writeback_invalidate(state->rb, state->rb_size); 79 | while(hfx_read_reg(HFX_VADDR_REG_RB_END) != state->rb_end) 80 | { 81 | hfx_write_reg(HFX_VADDR_REG_RB_END, state->rb_end); 82 | } 83 | hfx_write_reg(HFX_VADDR_REG_RB_END, state->rb_end); 84 | } -------------------------------------------------------------------------------- /include/hfx.h: -------------------------------------------------------------------------------- 1 | #ifndef HFX_H 2 | #define HFX_H 3 | #include 4 | #include 5 | 6 | #define HFX_COLOR_BUFFER_BIT 0x00004000 7 | #define HFX_DEPTH_BUFFER_BIT 0x00000100 8 | 9 | #define HFX_BYTE 0x1400 10 | #define HFX_UNSIGNED_BYTE 0x1401 11 | #define HFX_SHORT 0x1402 12 | #define HFX_UNSIGNED_SHORT 0x1403 13 | #define HFX_INT 0x1404 14 | #define HFX_UNSIGNED_INT 0x1405 15 | #define HFX_FLOAT 0x1406 16 | 17 | #define HFX_UNSIGNED_SHORT_5_5_5_1 0x8034 18 | 19 | #define HFX_TEXTURE_2D 0x0de1 20 | 21 | #define HFX_RGBA 0x1908 22 | 23 | #define HFX_TRIANGLES 0x0004 24 | 25 | #define HFX_VERTEX_ARRAY 0x8074 26 | #define HFX_COLOR_ARRAY 0x8076 27 | 28 | #define HFX_DEPTH_TEST 0x0B71 29 | 30 | typedef struct hfx_state hfx_state; 31 | typedef int32_t HFXfixed; 32 | 33 | hfx_state *hfx_init(); 34 | void libhfx_init(void); 35 | void hfx_register_rsp_int(hfx_state *state, void (*func_ptr)()); 36 | void hfx_restart_rsp(hfx_state *state); 37 | void hfx_wait_for_idle(hfx_state *state); 38 | 39 | void hfx_swap_buffers(hfx_state *state); 40 | 41 | HFXfixed hfx_addx(HFXfixed a, HFXfixed b); 42 | HFXfixed hfx_subx(HFXfixed a, HFXfixed b); 43 | HFXfixed hfx_mulx(HFXfixed a, HFXfixed b); 44 | HFXfixed hfx_divx(HFXfixed a, HFXfixed b); 45 | 46 | void hfx_enable(hfx_state *state, uint32_t cap); 47 | 48 | void hfx_set_scissor(hfx_state *state, uint32_t xh, uint32_t yh, uint32_t xl, uint32_t yl); 49 | void hfx_draw_tri_f(hfx_state *state, float *v1, float *v2, float *v3, float *vc1, float *vc2, float *vc3, float *vt1, float *vt2, float *vt3); 50 | void hfx_color_f(hfx_state *state, float r, float g, float b, float a); 51 | void hfx_clear_color_f(hfx_state *state, float r, float g, float b, float a); 52 | void hfx_clear(hfx_state *state, uint32_t bits); 53 | void hfx_load_identity(hfx_state *state); 54 | void hfx_translate_f(hfx_state *state, float x, float y, float z); 55 | void hfx_rotate_f(hfx_state *state, float angle, float x, float y, float z); 56 | void hfx_scale_f(hfx_state *state, float sx, float sy, float sz); 57 | void hfx_ortho_f(hfx_state *state, float left, float right, float top, float bottom, float near, float far); 58 | void hfx_persp_f(hfx_state *state, float fovy, float aspect, float znear, float zfar); 59 | void hfx_mult_matrix_f(hfx_state *state, float *mat); 60 | 61 | void hfx_vertex_pointer(hfx_state *state, uint32_t size, uint32_t type, uint32_t stride, void *data); 62 | void hfx_color_pointer(hfx_state *state, uint32_t size, uint32_t type, uint32_t stride, void *data); 63 | void hfx_tex_coord_pointer(hfx_state *state, uint32_t size, uint32_t type, uint32_t stride, void *data); 64 | void hfx_draw_arrays(hfx_state *state, uint32_t type, uint32_t start, uint32_t count); 65 | 66 | void hfx_gen_textures(hfx_state *state, uint32_t n, uint32_t *textures); 67 | void hfx_tex_image_2d(hfx_state *state, uint32_t target, int32_t level, int32_t internalformat, uint32_t width, uint32_t height, int32_t border, uint32_t format, uint32_t type, const void *data); 68 | 69 | #endif 70 | -------------------------------------------------------------------------------- /libhfx_gl/src/hfx.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #define BITS_PER_PIXEL 8 7 | 8 | static hfx_state prv_state; 9 | 10 | static void checkSDLError() 11 | { 12 | const char *errMsg = SDL_GetError(); 13 | 14 | if(*errMsg != '\0') { 15 | printf("%s\n", errMsg); 16 | } 17 | } 18 | 19 | hfx_state *hfx_init() 20 | { 21 | hfx_state *state = &prv_state; 22 | 23 | if(SDL_Init(SDL_INIT_EVERYTHING) == -1) 24 | { 25 | printf("Failed to init SDL\n"); 26 | } 27 | checkSDLError(); 28 | 29 | SDL_GL_SetAttribute(SDL_GL_RED_SIZE, BITS_PER_PIXEL); 30 | SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, BITS_PER_PIXEL); 31 | SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, BITS_PER_PIXEL); 32 | SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, BITS_PER_PIXEL); 33 | SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24); 34 | SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8); 35 | SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE); 36 | SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 1); 37 | SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3); 38 | 39 | state->window = SDL_CreateWindow("LibHFX", 40 | SDL_WINDOWPOS_CENTERED, 41 | SDL_WINDOWPOS_CENTERED, 42 | 640, 480, 43 | SDL_WINDOW_OPENGL); 44 | checkSDLError(); 45 | state->context = SDL_GL_CreateContext(state->window); 46 | checkSDLError(); 47 | 48 | GLenum err = glewInit(); 49 | if (GLEW_OK != err) 50 | { 51 | printf("Failed to init glew\n"); 52 | } 53 | 54 | return state; 55 | } 56 | 57 | void hfx_swap_buffers(hfx_state *state) 58 | { 59 | SDL_Event e; 60 | while(SDL_PollEvent(&e)) { 61 | if(e.type == SDL_QUIT) { 62 | exit(0); 63 | } 64 | } 65 | 66 | SDL_GL_SwapWindow(state->window); 67 | } 68 | 69 | void hfxEnable(hfx_state *state, uint32_t cap) 70 | { 71 | glEnable(cap); 72 | } 73 | 74 | void hfxClearColor(hfx_state *state, float r, float g, float b, float a) 75 | { 76 | glClearColor(r, g, b, a); 77 | } 78 | 79 | void hfxClear(hfx_state *state, uint32_t bits) 80 | { 81 | glClear(bits); 82 | } 83 | 84 | void hfxVertexPointer(hfx_state *state, int32_t size, uint32_t type, uint32_t stride, void *pointer) 85 | { 86 | glVertexPointer(size, type, stride, pointer); 87 | } 88 | 89 | void hfxColorPointer(hfx_state *state, int32_t size, uint32_t type, uint32_t stride, void *pointer) 90 | { 91 | glColorPointer(size, type, stride, pointer); 92 | } 93 | 94 | void hfxLoadIdentity(hfx_state *state) 95 | { 96 | hfx_load_identity(state); 97 | } 98 | 99 | void hfxTranslatef(hfx_state *state, float x, float y, float z) 100 | { 101 | hfx_translate_f(state, x, y, z); 102 | } 103 | 104 | void hfxRotatef(hfx_state *state, float angle, float x, float y, float z) 105 | { 106 | hfx_rotate_f(state, angle, x, y, z); 107 | } 108 | 109 | void hfxScalef(hfx_state *state, float x, float y, float z) 110 | { 111 | hfx_scale_f(state, x, y, z); 112 | } 113 | 114 | void hfxDrawArrays(hfx_state *state, uint32_t mode, uint32_t first, uint32_t count) 115 | { 116 | glLoadMatrixf(state->model_matrix); 117 | glDrawArrays(mode, first, count); 118 | } -------------------------------------------------------------------------------- /tests/hfx_persp_tex/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #define RGBA8_TO_RGBA5551(r,g,b,a) ((((uint32_t)(r)&0xf8u)<<8u) | (((uint32_t)(g)&0xf8u)<<4u) | (((uint32_t)(b)&0xf8u)>>2u) | ((uint32_t)(a)&0x01u)) 13 | 14 | static resolution_t res = RESOLUTION_320x240; 15 | static bitdepth_t bit = DEPTH_16_BPP; 16 | 17 | static int done = 1; 18 | static hfx_state *state; 19 | 20 | static char pbuf[256]; 21 | float v1[] = 22 | { 23 | -0.8f, -0.8f, -0.1f, 24 | 0.0f, -0.8f, -0.8f, 25 | 0.0f, 0.8f, -0.8f, 26 | 27 | -0.8f, -0.8f, -0.1f, 28 | 0.0f, 0.8f, -0.8f, 29 | -0.8f, 0.8f, -0.1f, 30 | 31 | }; 32 | 33 | float t1[] = 34 | { 35 | 0.0f, 0.0f, 36 | 1.0f, 0.0f, 37 | 1.0f, 1.0f, 38 | 0.0f, 0.0f, 39 | 1.0f, 1.0f, 40 | 0.0f, 1.0f, 41 | }; 42 | 43 | uint8_t vc1[] = 44 | { 45 | 255.0f, 0.0f, 0.0f, 255.0f, 46 | 255.0f, 0.0f, 0.0f, 255.0f, 47 | 255.0f, 0.0f, 0.0f, 255.0f, 48 | 49 | 255.0f, 0.0f, 0.0f, 255.0f, 50 | 255.0f, 0.0f, 0.0f, 255.0f, 51 | 255.0f, 0.0f, 0.0f, 255.0f, 52 | }; 53 | 54 | static uint16_t tex_data[16*16] __attribute__((aligned(64))); 55 | 56 | void load_tex_dat() 57 | { 58 | for(int j=0; j < 16; j++) 59 | { 60 | for(int i=0; i < 16; i++) 61 | { 62 | 63 | if((i+j)%2 == 0) 64 | { 65 | tex_data[j*16 + i] = RGBA8_TO_RGBA5551(0xffu,0xffu,0xffu,0xffu); 66 | } 67 | else 68 | { 69 | if(i%3 == 0) 70 | { 71 | tex_data[j*16 + i] = RGBA8_TO_RGBA5551(0xffu,0x00u,0x00u,0xffu); 72 | } 73 | else if(i%3 == 1) 74 | { 75 | tex_data[j*16 + i] = RGBA8_TO_RGBA5551(0x00u,0xffu,0x00u,0xffu); 76 | } 77 | else 78 | { 79 | tex_data[j*16 + i] = RGBA8_TO_RGBA5551(0x00u,0x00u,0xffu,0xffu); 80 | } 81 | } 82 | 83 | } 84 | } 85 | 86 | data_cache_hit_writeback_invalidate(tex_data, sizeof(tex_data)); 87 | } 88 | 89 | int main(void) 90 | { 91 | /* enable interrupts (on the CPU) */ 92 | init_interrupts(); 93 | 94 | load_tex_dat(); 95 | 96 | /* Initialize peripherals */ 97 | display_init( res, bit, 2, GAMMA_NONE, ANTIALIAS_RESAMPLE ); 98 | 99 | state = hfx_init(); 100 | 101 | hfx_enable(state, HFX_TEXTURE_2D); 102 | 103 | hfx_tex_image_2d(state, 0, 0, HFX_RGBA, 16, 16, 0, HFX_RGBA, HFX_UNSIGNED_SHORT_5_5_5_1, tex_data); 104 | 105 | hfx_vertex_pointer(state, 3, HFX_FLOAT, 0, v1); 106 | hfx_color_pointer(state, 4, HFX_UNSIGNED_BYTE, 0, vc1); 107 | hfx_tex_coord_pointer(state, 2, HFX_FLOAT, 0, t1); 108 | hfx_clear_color_f(state, 0.0f, 0.0f, 0.0f, 1.0f); 109 | 110 | //float angle = -30.0f; 111 | float angle = 0.0f; 112 | while(1) 113 | { 114 | angle += 1.0f; 115 | // Queue the next frame up 116 | hfx_clear(state, HFX_COLOR_BUFFER_BIT|HFX_DEPTH_BUFFER_BIT); 117 | hfx_load_identity(state); 118 | hfx_persp_f(state, 120.0f, 320.0f/240.0f, 0.1f, 100.0f); 119 | 120 | hfx_rotate_f(state, angle, 0.0f, 1.0f, 0.0f); 121 | 122 | hfx_draw_arrays(state, HFX_TRIANGLES, 0, 6); 123 | 124 | hfx_swap_buffers(state); 125 | } 126 | } -------------------------------------------------------------------------------- /tests/hfx_tex_tri/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #define RGBA8_TO_RGBA5551(r,g,b,a) ((((uint32_t)(r)&0xf8u)<<8u) | (((uint32_t)(g)&0xf8u)<<4u) | (((uint32_t)(b)&0xf8u)>>2u) | ((uint32_t)(a)&0x01u)) 13 | 14 | static resolution_t res = RESOLUTION_320x240; 15 | static bitdepth_t bit = DEPTH_16_BPP; 16 | 17 | static int done = 1; 18 | static hfx_state *state; 19 | 20 | float v1[] = 21 | { 22 | 0.0f, 0.0f, 0.0f, 23 | 0.5f, 0.0f, 0.0f, 24 | 0.5f, 0.5f, 0.0f, 25 | 0.0f, 0.0f, 0.0f, 26 | 0.5f, 0.5f, 0.0f, 27 | 0.0f, 0.5f, 0.0f, 28 | }; 29 | 30 | float t1[] = 31 | { 32 | 0.0f, 0.0f, 33 | 1.0f, 0.0f, 34 | 1.0f, 1.0f, 35 | 0.0f, 0.0f, 36 | 1.0f, 1.0f, 37 | 0.0f, 1.0f, 38 | }; 39 | 40 | uint8_t vc1[] = 41 | { 42 | 255.0f, 255.0f, 255.0f, 1.0f, 43 | 255.0f, 255.0f, 255.0f, 1.0f, 44 | 255.0f, 255.0f, 255.0f, 1.0f, 45 | 255.0f, 255.0f, 255.0f, 1.0f, 46 | 255.0f, 255.0f, 255.0f, 1.0f, 47 | 255.0f, 255.0f, 255.0f, 1.0f, 48 | }; 49 | 50 | static uint16_t tex_data[16*16] __attribute__((aligned(64))); 51 | 52 | void load_tex_dat() 53 | { 54 | for(int j=0; j < 16; j++) 55 | { 56 | for(int i=0; i < 16; i++) 57 | { 58 | 59 | if((i+j)%2 == 0) 60 | { 61 | tex_data[j*16 + i] = RGBA8_TO_RGBA5551(0xffu,0xffu,0xffu,0xffu); 62 | } 63 | else 64 | { 65 | if(i%3 == 0) 66 | { 67 | tex_data[j*16 + i] = RGBA8_TO_RGBA5551(0xffu,0x00u,0x00u,0xffu); 68 | } 69 | else if(i%3 == 1) 70 | { 71 | tex_data[j*16 + i] = RGBA8_TO_RGBA5551(0x00u,0xffu,0x00u,0xffu); 72 | } 73 | else 74 | { 75 | tex_data[j*16 + i] = RGBA8_TO_RGBA5551(0x00u,0x00u,0xffu,0xffu); 76 | } 77 | } 78 | } 79 | } 80 | 81 | data_cache_hit_writeback_invalidate(tex_data, sizeof(tex_data)); 82 | } 83 | 84 | void exception(exception_t *data) 85 | { 86 | hfx_fatal_error(state, "exception"); 87 | } 88 | 89 | int main(void) 90 | { 91 | /* enable interrupts (on the CPU) */ 92 | init_interrupts(); 93 | 94 | /* Initialize peripherals */ 95 | display_init( res, bit, 2, GAMMA_NONE, ANTIALIAS_RESAMPLE ); 96 | register_exception_handler(exception); 97 | 98 | load_tex_dat(); 99 | 100 | state = hfx_init(); 101 | 102 | hfx_enable(state, HFX_TEXTURE_2D); 103 | 104 | hfx_tex_image_2d(state, 0, 0, HFX_RGBA, 16, 16, 0, HFX_RGBA, HFX_UNSIGNED_SHORT_5_5_5_1, tex_data); 105 | 106 | hfx_vertex_pointer(state, 3, HFX_FLOAT, 0, v1); 107 | hfx_color_pointer(state, 4, HFX_UNSIGNED_BYTE, 0, vc1); 108 | hfx_tex_coord_pointer(state, 2, HFX_FLOAT, 0, t1); 109 | 110 | hfx_clear_color_f(state, 0.2f, 0.0f, 0.9f, 1.0f); 111 | 112 | float angle = 0.0; 113 | while(1) 114 | { 115 | if(angle == 360) 116 | angle = 0; 117 | else 118 | angle += 1.0f; 119 | done = 1; 120 | 121 | // Queue the next frame up 122 | hfx_clear(state, HFX_COLOR_BUFFER_BIT|HFX_DEPTH_BUFFER_BIT); 123 | hfx_load_identity(state); 124 | hfx_rotate_f(state, angle, 0, 0, 1); 125 | hfx_draw_arrays(state, HFX_TRIANGLES, 0, 6); 126 | 127 | hfx_swap_buffers(state); 128 | } 129 | } 130 | -------------------------------------------------------------------------------- /gl_test/cube/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #ifdef PLATFORM_N64 8 | #include 9 | #endif 10 | 11 | 12 | float cube_verts[] = 13 | { 14 | // Top 15 | -1.0f, 1.0f, -1.0f, 16 | 1.0f, 1.0f, 1.0f, 17 | 1.0f, 1.0f, -1.0f, 18 | 19 | -1.0f, 1.0f, -1.0f, 20 | -1.0f, 1.0f, 1.0f, 21 | 1.0f, 1.0f, 1.0f, 22 | 23 | // Front 24 | -1.0f, -1.0f, -1.0f, 25 | 1.0f, 1.0f, -1.0f, 26 | -1.0f, 1.0f, -1.0f, 27 | 28 | -1.0f, -1.0f, -1.0f, 29 | 1.0f, -1.0f, -1.0f, 30 | 1.0f, 1.0f, -1.0f, 31 | 32 | // Right 33 | 1.0f, -1.0f, -1.0f, 34 | 1.0f, 1.0f, -1.0f, 35 | 1.0f, 1.0f, 1.0f, 36 | 37 | 1.0f, -1.0f, -1.0f, 38 | 1.0f, 1.0f, 1.0f, 39 | 1.0f, -1.0f, 1.0f, 40 | 41 | // Left 42 | -1.0f, -1.0f, -1.0f, 43 | -1.0f, 1.0f, -1.0f, 44 | -1.0f, -1.0f, 1.0f, 45 | 46 | -1.0f, -1.0f, 1.0f, 47 | -1.0f, 1.0f, -1.0f, 48 | -1.0f, 1.0f, 1.0f, 49 | 50 | // Back 51 | -1.0f, -1.0f, 1.0f, 52 | 1.0f, 1.0f, 1.0f, 53 | -1.0f, 1.0f, 1.0f, 54 | 55 | -1.0f, -1.0f, 1.0f, 56 | 1.0f, -1.0f, 1.0f, 57 | 1.0f, 1.0f, 1.0f, 58 | 59 | // Bottom 60 | -1.0f, -1.0f, -1.0f, 61 | 1.0f, -1.0f, 1.0f, 62 | 1.0f, -1.0f, -1.0f, 63 | 64 | -1.0f, -1.0f, -1.0f, 65 | -1.0f, -1.0f, 1.0f, 66 | 1.0f, -1.0f, 1.0f, 67 | 68 | }; 69 | 70 | uint8_t cube_colors[] = 71 | { 72 | // Top 73 | 255, 0, 0, 255, 74 | 255, 0, 0, 255, 75 | 255, 0, 0, 255, 76 | 77 | 255, 0, 0, 255, 78 | 255, 0, 0, 255, 79 | 255, 0, 0, 255, 80 | 81 | // Front 82 | 0, 255, 0, 255, 83 | 0, 255, 0, 255, 84 | 0, 255, 0, 255, 85 | 86 | 0, 255, 0, 255, 87 | 0, 255, 0, 255, 88 | 0, 255, 0, 255, 89 | 90 | // Right 91 | 0, 0, 255, 255, 92 | 0, 0, 255, 255, 93 | 0, 0, 255, 255, 94 | 95 | 0, 0, 255, 255, 96 | 0, 0, 255, 255, 97 | 0, 0, 255, 255, 98 | 99 | // Left 100 | 0, 0, 255, 255, 101 | 0, 0, 255, 255, 102 | 0, 0, 255, 255, 103 | 104 | 0, 0, 255, 255, 105 | 0, 0, 255, 255, 106 | 0, 0, 255, 255, 107 | 108 | // Back 109 | 255, 0, 0, 255, 110 | 255, 0, 0, 255, 111 | 255, 0, 0, 255, 112 | 113 | 255, 0, 0, 255, 114 | 255, 0, 0, 255, 115 | 255, 0, 0, 255, 116 | 117 | // Bottom 118 | 0, 255, 255, 255, 119 | 0, 255, 255, 255, 120 | 0, 255, 255, 255, 121 | 122 | 0, 255, 255, 255, 123 | 0, 255, 255, 255, 124 | 0, 255, 255, 255, 125 | }; 126 | 127 | int main() 128 | { 129 | hfx_state *state; 130 | 131 | #ifdef PLATFORM_N64 132 | /* enable interrupts (on the CPU) */ 133 | init_interrupts(); 134 | 135 | /* Initialize peripherals */ 136 | display_init( res, bit, 2, GAMMA_NONE, ANTIALIAS_RESAMPLE ); 137 | #endif 138 | 139 | 140 | state = hfx_init(); 141 | hfxEnable(state, HFX_DEPTH_TEST); 142 | hfxEnable(state, HFX_VERTEX_ARRAY); 143 | hfxEnable(state, HFX_COLOR_ARRAY); 144 | 145 | hfxClearColor(state, 0.3f, 0.1f, 0.9f, 1.0f); 146 | 147 | hfxVertexPointer(state, 3, HFX_FLOAT, 0, cube_verts); 148 | hfxColorPointer(state, 4, HFX_UNSIGNED_BYTE, 0, cube_colors); 149 | 150 | float angle = 0.0f; 151 | while(1) 152 | { 153 | hfxClear(state, HFX_COLOR_BUFFER_BIT | HFX_DEPTH_BUFFER_BIT); 154 | hfxLoadIdentity(state); 155 | hfxTranslatef(state, 0.0f, 0.0f, -0.5f); 156 | hfxRotatef(state, angle, 0.58f, 0.58f, 0.58f); 157 | hfxScalef(state, 0.2f, 0.2f, 0.2f); 158 | hfxDrawArrays(state, HFX_TRIANGLES, 0, 36); 159 | hfx_swap_buffers(state); 160 | 161 | angle += 1; 162 | } 163 | 164 | return 0; 165 | } -------------------------------------------------------------------------------- /tests/ucode_mul_mat_vec/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | static resolution_t res = RESOLUTION_320x240; 9 | static bitdepth_t bit = DEPTH_16_BPP; 10 | 11 | static volatile int done = 1; 12 | 13 | extern const void _ucode_data_start; 14 | extern const void _ucode_start; 15 | extern const void _ucode_end; 16 | 17 | void sp_handler() 18 | { 19 | done = 0; 20 | } 21 | 22 | void write_dmem(uintptr_t offset, uint16_t value1, uint16_t value2) 23 | { 24 | volatile uint32_t *dmem = (volatile uint32_t*)(0xa4000000); 25 | uint32_t value = (value1<<16) | value2; 26 | dmem[offset] = value; 27 | } 28 | 29 | uint32_t read_dmem(uintptr_t offset) 30 | { 31 | volatile uint32_t *dmem = (volatile uint32_t*)(0xa4000000); 32 | return dmem[offset]; 33 | } 34 | 35 | void read_dmem_two(uintptr_t offset, uint16_t *v1, uint16_t *v2) 36 | { 37 | volatile uint32_t *dmem = (volatile uint32_t*)(0xa4000000); 38 | uint32_t val = dmem[offset]; 39 | *v1 = val >> 16; 40 | *v2 = (uint16_t)val; 41 | } 42 | 43 | int main(void) 44 | { 45 | /* enable interrupts (on the CPU) */ 46 | init_interrupts(); 47 | 48 | /* Initialize peripherals */ 49 | display_init( res, bit, 2, GAMMA_NONE, ANTIALIAS_RESAMPLE ); 50 | console_init(); 51 | console_set_render_mode(RENDER_MANUAL); 52 | rsp_init(); 53 | 54 | /* Attach SP handler and enable interrupt */ 55 | register_SP_handler(&sp_handler); 56 | set_SP_interrupt(1); 57 | 58 | // Size must be multiple of 8 and start & end must be aligned to 8 bytes 59 | unsigned long data_size = (unsigned long) (&_ucode_start - &_ucode_data_start); 60 | unsigned long ucode_size = (unsigned long) (&_ucode_end - &_ucode_start); 61 | load_data((void*)&_ucode_data_start, data_size); 62 | load_ucode((void*)&_ucode_start, ucode_size); 63 | 64 | float vec[4] = {1.0f, 2.0f, 3.0f, 4.0f}; 65 | float mat[16] = {2.0f, 0.0f, 0.0f, 0.0f, 66 | 0.0f, 2.0f, 0.0f, 0.0f, 67 | 2.0f, 0.0f, 1.0f, 0.0f, 68 | 0.0f, 2.0f, 0.0f, 2.0f}; 69 | 70 | for(int i=0; i < 2; i++) 71 | { 72 | uint32_t ivalue1 = hfx_float_to_fixed(vec[i*2 + 0]); 73 | uint32_t ivalue2 = hfx_float_to_fixed(vec[i*2 + 1]); 74 | printf("ivalues 0x%08X 0x%08X\n", (unsigned int)ivalue1, (unsigned int)ivalue2); 75 | write_dmem(0*4 + i, ivalue1>>16, ivalue2>>16); 76 | write_dmem(1*4 + i, ivalue1, ivalue2); 77 | } 78 | 79 | for(int j=0; j < 4; j++) 80 | { 81 | for(int i=0; i < 2; i++) 82 | { 83 | uint32_t ivalue1 = hfx_float_to_fixed(mat[j*4+i*2+0]); 84 | uint32_t ivalue2 = hfx_float_to_fixed(mat[j*4+i*2+1]); 85 | write_dmem((j*2+2+0)*4+i, ivalue1>>16, ivalue2>>16); 86 | write_dmem((j*2+2+1)*4+i, ivalue1, ivalue2); 87 | printf("writing 0x%08X 0x%08X, to %d %d\n", ivalue1, ivalue2, (j*2+2+0)*4+i, (j*2+2+1)*4+i); 88 | } 89 | } 90 | 91 | printf("Running!\n"); 92 | console_render(); 93 | 94 | run_ucode(); 95 | 96 | while(1) 97 | { 98 | if(done == 0) 99 | { 100 | done = 1; 101 | 102 | uint32_t ivalue[4]; 103 | float fvalue[4]; 104 | printf("Results are:\n"); 105 | for(int i=0; i < 4; i++) 106 | { 107 | ivalue[i] = read_dmem(i); 108 | fvalue[i] = ivalue[i] / 65536.0f; 109 | printf("%d: int 0x%08X float %f\n", i, (unsigned int)ivalue[i], fvalue[i]); 110 | } 111 | 112 | console_render(); 113 | } 114 | } 115 | } 116 | -------------------------------------------------------------------------------- /tests/ucode_tri/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | static resolution_t res = RESOLUTION_320x240; 9 | static bitdepth_t bit = DEPTH_16_BPP; 10 | 11 | static volatile int done = 1; 12 | 13 | extern const void _ucode_data_start; 14 | extern const void _ucode_start; 15 | extern const void _ucode_end; 16 | 17 | void sp_handler() 18 | { 19 | done = 0; 20 | } 21 | 22 | void write_dmem(uintptr_t offset, uint16_t value1, uint16_t value2) 23 | { 24 | volatile uint32_t *dmem = (volatile uint32_t*)(0xa4000000); 25 | uint32_t value = (value1<<16) | value2; 26 | dmem[offset] = value; 27 | } 28 | 29 | uint32_t read_dmem(uintptr_t offset) 30 | { 31 | volatile uint32_t *dmem = (volatile uint32_t*)(0xa4000000); 32 | return dmem[offset]; 33 | } 34 | 35 | void read_dmem_two(uintptr_t offset, uint16_t *v1, uint16_t *v2) 36 | { 37 | volatile uint32_t *dmem = (volatile uint32_t*)(0xa4000000); 38 | uint32_t val = dmem[offset]; 39 | *v1 = val >> 16; 40 | *v2 = (uint16_t)val; 41 | } 42 | 43 | int main(void) 44 | { 45 | /* enable interrupts (on the CPU) */ 46 | init_interrupts(); 47 | 48 | /* Initialize peripherals */ 49 | display_init( res, bit, 2, GAMMA_NONE, ANTIALIAS_RESAMPLE ); 50 | console_init(); 51 | console_set_render_mode(RENDER_MANUAL); 52 | rsp_init(); 53 | 54 | /* Attach SP handler and enable interrupt */ 55 | register_SP_handler(&sp_handler); 56 | set_SP_interrupt(1); 57 | 58 | // Size must be multiple of 8 and start & end must be aligned to 8 bytes 59 | unsigned long data_size = (unsigned long) (&_ucode_start - &_ucode_data_start); 60 | unsigned long ucode_size = (unsigned long) (&_ucode_end - &_ucode_start); 61 | load_data((void*)&_ucode_data_start, data_size); 62 | load_ucode((void*)&_ucode_start, ucode_size); 63 | 64 | float x1 = 100.0f, y1 = 30.0f; 65 | float x2 = 120.0f, y2 = 100.0f; 66 | float x3 = 30.0f, y3 = 150.0f; 67 | 68 | uint32_t ix1 = hfx_float_to_fixed(x1), iy1 = hfx_float_to_fixed(y1); 69 | uint32_t ix2 = hfx_float_to_fixed(x2), iy2 = hfx_float_to_fixed(y2); 70 | uint32_t ix3 = hfx_float_to_fixed(x3), iy3 = hfx_float_to_fixed(y3); 71 | 72 | float exp_x1 = (x3-x1)/(y3-y1); 73 | float exp_x2 = (x2-x1)/(y2-y1); 74 | float exp_x3 = (x3-x2)/(y3-y2); 75 | 76 | float winding = (x1*y2 - x2*y1) + (x2*y3 - x3*y2) + (x3*y1 - x1*y3); 77 | 78 | write_dmem(0*4, ix1>>16, iy1>>16); 79 | write_dmem(1*4, ix1, iy1); 80 | 81 | write_dmem(2*4, ix2>>16, iy2>>16); 82 | write_dmem(3*4, ix2, iy2); 83 | 84 | write_dmem(4*4, ix3>>16, iy3>>16); 85 | write_dmem(5*4, ix3, iy3); 86 | 87 | printf("Running!\n"); 88 | console_render(); 89 | 90 | run_ucode(); 91 | 92 | while(1) 93 | { 94 | if(done == 0) 95 | { 96 | done = 1; 97 | 98 | uint32_t dxHDy = read_dmem(5); 99 | uint32_t dxMDy = read_dmem(7); 100 | uint32_t dxLDy = read_dmem(3); 101 | 102 | x1 = ((float)(int)dxHDy) / 65536.0f; 103 | x2 = ((float)(int)dxMDy) / 65536.0f; 104 | x3 = ((float)(int)dxLDy) / 65536.0f; 105 | 106 | printf("Done!\n"); 107 | printf("fixed 0x%X float %f expecting %f\n", (int)dxHDy, x1, exp_x1); 108 | printf("fixed 0x%X float %f expecting %f\n", (int)dxMDy, x2, exp_x2); 109 | printf("fixed 0x%X float %f expecting %f\n\n", (int)dxLDy, x3, exp_x3); 110 | 111 | for(int i=0; i < 4; i++) 112 | { 113 | uint32_t w1, w2; 114 | w1 = read_dmem((i*2 + 0)); 115 | w2 = read_dmem((i*2 + 1)); 116 | printf("0x%08X 0x%08X\n", w1, w2); 117 | } 118 | 119 | console_render(); 120 | } 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /tests/ucode_sort/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | static resolution_t res = RESOLUTION_320x240; 9 | static bitdepth_t bit = DEPTH_16_BPP; 10 | 11 | static volatile int done = 1; 12 | 13 | extern const void _ucode_data_start; 14 | extern const void _ucode_start; 15 | extern const void _ucode_end; 16 | 17 | void sp_handler() 18 | { 19 | done = 0; 20 | } 21 | 22 | void write_dmem(uintptr_t offset, uint16_t value1, uint16_t value2) 23 | { 24 | volatile uint32_t *dmem = (volatile uint32_t*)(0xa4000000); 25 | uint32_t value = (value1<<16) | value2; 26 | dmem[offset] = value; 27 | } 28 | 29 | uint32_t read_dmem(uintptr_t offset) 30 | { 31 | volatile uint32_t *dmem = (volatile uint32_t*)(0xa4000000); 32 | return dmem[offset]; 33 | } 34 | 35 | void read_dmem_two(uintptr_t offset, uint16_t *v1, uint16_t *v2) 36 | { 37 | volatile uint32_t *dmem = (volatile uint32_t*)(0xa4000000); 38 | uint32_t val = dmem[offset]; 39 | *v1 = val >> 16; 40 | *v2 = (uint16_t)val; 41 | } 42 | 43 | int main(void) 44 | { 45 | /* enable interrupts (on the CPU) */ 46 | init_interrupts(); 47 | 48 | /* Initialize peripherals */ 49 | display_init( res, bit, 2, GAMMA_NONE, ANTIALIAS_RESAMPLE ); 50 | console_init(); 51 | console_set_render_mode(RENDER_MANUAL); 52 | rsp_init(); 53 | 54 | /* Attach SP handler and enable interrupt */ 55 | register_SP_handler(&sp_handler); 56 | set_SP_interrupt(1); 57 | 58 | // Size must be multiple of 8 and start & end must be aligned to 8 bytes 59 | unsigned long data_size = (unsigned long) (&_ucode_start - &_ucode_data_start); 60 | unsigned long ucode_size = (unsigned long) (&_ucode_end - &_ucode_start); 61 | load_data((void*)&_ucode_data_start, data_size); 62 | load_ucode((void*)&_ucode_start, ucode_size); 63 | 64 | float x1 = 120.0f, y1 = 100.0f; 65 | float x2 = 100.0f, y2 = 30.0f; 66 | float x3 = 30.0f, y3 = 150.0f; 67 | 68 | uint32_t ix1 = hfx_float_to_fixed(x1), iy1 = hfx_float_to_fixed(y1); 69 | uint32_t ix2 = hfx_float_to_fixed(x2), iy2 = hfx_float_to_fixed(y2); 70 | uint32_t ix3 = hfx_float_to_fixed(x3), iy3 = hfx_float_to_fixed(y3); 71 | 72 | write_dmem(0*4, ix1>>16, iy1>>16); 73 | write_dmem(1*4, ix1, iy1); 74 | 75 | write_dmem(2*4, ix2>>16, iy2>>16); 76 | write_dmem(3*4, ix2, iy2); 77 | 78 | write_dmem(4*4, ix3>>16, iy3>>16); 79 | write_dmem(5*4, ix3, iy3); 80 | 81 | 82 | printf("Verts presorted are:\n"); 83 | printf("hex 0x%08X 0x%08X float %f %f\n", (int)ix1, (int)iy1, x1, y1); 84 | printf("hex 0x%08X 0x%08X float %f %f\n", (int)ix2, (int)iy2, x2, y2); 85 | printf("hex 0x%08X 0x%08X float %f %f\n", (int)ix3, (int)iy3, x3, y3); 86 | 87 | printf("Running!\n"); 88 | console_render(); 89 | 90 | run_ucode(); 91 | 92 | while(1) 93 | { 94 | if(done == 0) 95 | { 96 | done = 1; 97 | 98 | uint32_t x1 = read_dmem(0); 99 | uint32_t y1 = read_dmem(1); 100 | uint32_t x2 = read_dmem(2); 101 | uint32_t y2 = read_dmem(3); 102 | uint32_t x3 = read_dmem(4); 103 | uint32_t y3 = read_dmem(5); 104 | 105 | float xf1 = x1 / 65536.0f; 106 | float yf1 = y1 / 65536.0f; 107 | float xf2 = x2 / 65536.0f; 108 | float yf2 = y2 / 65536.0f; 109 | float xf3 = x3 / 65536.0f; 110 | float yf3 = y3 / 65536.0f; 111 | 112 | printf("Verts sorted are:\n"); 113 | printf("hex 0x%08X 0x%08X float %f %f\n", (int)x1, (int)y1, xf1, yf1); 114 | printf("hex 0x%08X 0x%08X float %f %f\n", (int)x2, (int)y2, xf2, yf2); 115 | printf("hex 0x%08X 0x%08X float %f %f\n", (int)x3, (int)y3, xf3, yf3); 116 | 117 | console_render(); 118 | } 119 | } 120 | } 121 | -------------------------------------------------------------------------------- /tests/hfx_cube/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | static resolution_t res = RESOLUTION_320x240; 14 | static bitdepth_t bit = DEPTH_16_BPP; 15 | 16 | static char pbuf[256]; 17 | 18 | extern hfx_state *g_hfx_state; 19 | 20 | float cube_verts[] = 21 | { 22 | // Top 23 | -1.0f, 1.0f, -1.0f, 24 | 1.0f, 1.0f, 1.0f, 25 | 1.0f, 1.0f, -1.0f, 26 | 27 | -1.0f, 1.0f, -1.0f, 28 | -1.0f, 1.0f, 1.0f, 29 | 1.0f, 1.0f, 1.0f, 30 | 31 | // Front 32 | -1.0f, -1.0f, -1.0f, 33 | 1.0f, 1.0f, -1.0f, 34 | -1.0f, 1.0f, -1.0f, 35 | 36 | -1.0f, -1.0f, -1.0f, 37 | 1.0f, -1.0f, -1.0f, 38 | 1.0f, 1.0f, -1.0f, 39 | 40 | // Right 41 | 1.0f, -1.0f, -1.0f, 42 | 1.0f, 1.0f, -1.0f, 43 | 1.0f, 1.0f, 1.0f, 44 | 45 | 1.0f, -1.0f, -1.0f, 46 | 1.0f, 1.0f, 1.0f, 47 | 1.0f, -1.0f, 1.0f, 48 | 49 | // Left 50 | -1.0f, -1.0f, -1.0f, 51 | -1.0f, 1.0f, -1.0f, 52 | -1.0f, -1.0f, 1.0f, 53 | 54 | -1.0f, -1.0f, 1.0f, 55 | -1.0f, 1.0f, -1.0f, 56 | -1.0f, 1.0f, 1.0f, 57 | 58 | // Back 59 | -1.0f, -1.0f, 1.0f, 60 | 1.0f, 1.0f, 1.0f, 61 | -1.0f, 1.0f, 1.0f, 62 | 63 | -1.0f, -1.0f, 1.0f, 64 | 1.0f, -1.0f, 1.0f, 65 | 1.0f, 1.0f, 1.0f, 66 | 67 | // Bottom 68 | -1.0f, -1.0f, -1.0f, 69 | 1.0f, -1.0f, 1.0f, 70 | 1.0f, -1.0f, -1.0f, 71 | 72 | -1.0f, -1.0f, -1.0f, 73 | -1.0f, -1.0f, 1.0f, 74 | 1.0f, -1.0f, 1.0f, 75 | 76 | }; 77 | 78 | uint8_t cube_colors[] = 79 | { 80 | // Top 81 | 255, 0, 0, 255, 82 | 255, 0, 0, 255, 83 | 255, 0, 0, 255, 84 | 85 | 255, 0, 0, 255, 86 | 255, 0, 0, 255, 87 | 255, 0, 0, 255, 88 | 89 | // Front 90 | 0, 255, 0, 255, 91 | 0, 255, 0, 255, 92 | 0, 255, 0, 255, 93 | 94 | 0, 255, 0, 255, 95 | 0, 255, 0, 255, 96 | 0, 255, 0, 255, 97 | 98 | // Right 99 | 0, 0, 255, 255, 100 | 0, 0, 255, 255, 101 | 0, 0, 255, 255, 102 | 103 | 0, 0, 255, 255, 104 | 0, 0, 255, 255, 105 | 0, 0, 255, 255, 106 | 107 | // Left 108 | 0, 0, 255, 255, 109 | 0, 0, 255, 255, 110 | 0, 0, 255, 255, 111 | 112 | 0, 0, 255, 255, 113 | 0, 0, 255, 255, 114 | 0, 0, 255, 255, 115 | 116 | // Back 117 | 255, 100, 0, 255, 118 | 255, 100, 0, 255, 119 | 255, 100, 0, 255, 120 | 121 | 255, 100, 0, 255, 122 | 255, 100, 0, 255, 123 | 255, 100, 0, 255, 124 | 125 | // Bottom 126 | 0, 255, 255, 255, 127 | 0, 255, 255, 255, 128 | 0, 255, 255, 255, 129 | 130 | 0, 255, 255, 255, 131 | 0, 255, 255, 255, 132 | 0, 255, 255, 255, 133 | }; 134 | 135 | void exception(exception_t *data) 136 | { 137 | hfx_fatal_error(g_hfx_state, "exception"); 138 | } 139 | 140 | int main(void) 141 | { 142 | /* enable interrupts (on the CPU) */ 143 | init_interrupts(); 144 | 145 | /* Initialize peripherals */ 146 | display_init( res, bit, 2, GAMMA_NONE, ANTIALIAS_RESAMPLE ); 147 | register_exception_handler(exception); 148 | 149 | libhfx_init(); 150 | 151 | glClearColor(0.3f, 0.1f, 0.9f, 1.0f); 152 | 153 | glEnable(GL_DEPTH_TEST); 154 | glEnable(GL_VERTEX_ARRAY); 155 | glEnable(GL_COLOR_ARRAY); 156 | 157 | glVertexPointer(3, GL_FLOAT, 0, cube_verts); 158 | glColorPointer(4, GL_UNSIGNED_BYTE, 0, cube_colors); 159 | 160 | float angle = 0; 161 | while(1) 162 | { 163 | if(angle == 360) 164 | { 165 | angle = 0; 166 | } 167 | else 168 | { 169 | angle += 1.0f; 170 | } 171 | 172 | //angle = 285.0f; 173 | 174 | // Queue the next frame up 175 | glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 176 | glLoadIdentity(); 177 | glRotatef(angle, 0.58f, 0.58f, 0.58f); 178 | glScalef(0.5f, 0.5f, 0.5f); 179 | 180 | glDrawArrays(GL_TRIANGLES, 0, 36); 181 | 182 | hfx_wait_for_idle(g_hfx_state); 183 | 184 | sprintf(pbuf, "Done %f", angle); 185 | graphics_draw_text(g_hfx_state->display, 0, 100, pbuf); 186 | 187 | hfx_swap_buffers(g_hfx_state); 188 | } 189 | } -------------------------------------------------------------------------------- /meson.build: -------------------------------------------------------------------------------- 1 | project('libhfx', 'c') 2 | fs = import('fs') 3 | 4 | # Need to get exe extension to properly run on windows 5 | exe_extension = '' 6 | if build_machine.system().contains('mingw') 7 | exe_extension = '.exe' 8 | endif 9 | 10 | mips_compiler = find_program('mips64-elf-gcc' + exe_extension) 11 | mips_linker = find_program('mips64-elf-ld' + exe_extension) 12 | mips_ar = find_program('mips64-elf-ar' + exe_extension) 13 | mips_objcopy = find_program('mips64-elf-objcopy' + exe_extension) 14 | n64tool = find_program('n64tool' + exe_extension) 15 | chksum64 = find_program('chksum64' + exe_extension) 16 | bash = find_program('bash' + exe_extension) 17 | 18 | ##################################### 19 | # Add new files here 20 | src_dir = './libhfx_src/' 21 | src_files = [ 22 | 'src/hfx.c', 23 | 'src/hfx_rb.c', 24 | 'src/hfx_cmd_dma.c', 25 | 'src/hfx_cmd.c', 26 | 'src/hfx_display.c', 27 | 'src/hfx_math.c', 28 | 'src/hfx_render.c', 29 | 'src/hfx_render_gl.c', 30 | 'src/hfx_matrix.c', 31 | 'src/hfx_state.c', 32 | 'src/hfx_texture.c', 33 | 'src/hfx_dispatch.c', 34 | ] 35 | 36 | ucode_src_dir = './ucode_src/src/' 37 | ucode_files = [ 38 | 'crt.S', 39 | 'hfx_ucode.c', 40 | ] 41 | ucode_loader = 'libhfx_src/src/linker.S' 42 | ucode_linker_script = 'ucode.ld' 43 | 44 | # Change compiler flags here 45 | cflags = [ 46 | '-I'+meson.source_root()+'/include', 47 | '-I'+meson.source_root()+'/libhfx_src/include', 48 | '-std=gnu99', 49 | '-march=vr4300', 50 | '-mtune=vr4300', 51 | '-O0', 52 | '-Wall', 53 | '-Wpedantic', 54 | '-MMD', 55 | '-g', 56 | ] 57 | 58 | ucode_cflags = [ 59 | '-I'+meson.source_root()+'/include', 60 | '-std=gnu99', 61 | '-Wall', 62 | '-march=vr4300', 63 | '-mtune=vr4300', 64 | '-Os', 65 | '-mno-branch-likely', 66 | '-mno-llsc', 67 | '-Wall', 68 | '-mabi=eabi', 69 | '-mgp32', 70 | '-flto', 71 | '-MMD', 72 | '-EB', 73 | ] 74 | 75 | ucode_ldflags = [ 76 | '-Wall', 77 | '-march=vr4300', 78 | '-mtune=vr4300', 79 | '-mabi=eabi', 80 | '-mgp32', 81 | '-ffreestanding', 82 | '-nostdlib', 83 | '-Os', 84 | '-mno-branch-likely', 85 | '-mno-llsc', 86 | '-flto', 87 | '-EB', 88 | ] 89 | 90 | ##################################### 91 | 92 | src = [] 93 | foreach source : src_files 94 | src += [src_dir + source] 95 | endforeach 96 | 97 | ucode_src_files = [] 98 | foreach source : ucode_files 99 | src_file = ucode_src_dir + source 100 | ucode_src_files += [src_file] 101 | endforeach 102 | 103 | ucode_define_string = '-DTEXT_SECTION_BIN="@0@" -DDATA_SECTION_BIN="@1@"' 104 | 105 | # Build all ucode object files 106 | ucode_obj_files = [] 107 | foreach source : ucode_src_files 108 | obj = custom_target(fs.name(source), 109 | output : '@BASENAME@.o', 110 | input : source, 111 | command : [mips_compiler] + ucode_cflags + ['-c', '@INPUT@', '-o', '@OUTPUT@'], 112 | depfile : '@BASENAME@.d') 113 | ucode_obj_files += [obj] 114 | endforeach 115 | 116 | # Build ucode into elf file 117 | ucode_elf_file = custom_target('ucode_elf', 118 | output : 'ucode.elf', 119 | input : ucode_obj_files, 120 | depend_files : ucode_linker_script, 121 | command : [mips_compiler] + ucode_ldflags + ['@INPUT@', '-o', '@OUTPUT@', '-T', '../'+ucode_linker_script]) 122 | 123 | # convert ucode elf into bin files 124 | ucode_bin = custom_target('ucode_bin', 125 | output : ['ucode_text.bin', 'ucode_data.bin'], 126 | input : ucode_elf_file, 127 | command : [mips_objcopy, '--dump-section', '.text=ucode_text.bin', 128 | '--dump-section', '.data=ucode_data.bin', '@INPUT@']) 129 | 130 | # Build linker object file 131 | ucode_link = custom_target('ucode_link', 132 | output : '@BASENAME@.o', 133 | input : ucode_loader, 134 | depfile : '@BASENAME@.d', 135 | depends: ucode_bin, 136 | command : [mips_compiler] + cflags + 137 | ucode_define_string.format(ucode_bin[0].full_path(), ucode_bin[1].full_path()).split() + 138 | ['-c', '@INPUT@', '-o', '@OUTPUT@']) 139 | 140 | # Build all c source files 141 | object_generator = generator(mips_compiler, 142 | output : '@BASENAME@.o', 143 | arguments : cflags + ['-c', '@INPUT@', '-o', '@OUTPUT@'], 144 | depfile : '@BASENAME@.d') 145 | object_files = object_generator.process(src) 146 | 147 | # Build library file 148 | libhfx = custom_target('libhfx', 149 | output : 'libhfx.a', 150 | input : [object_files] + [ucode_link], 151 | command : [mips_ar, 'rcs', '@OUTPUT@', '@INPUT@'], 152 | build_by_default:true) 153 | 154 | ############################################################# 155 | 156 | opengl_src = [ 157 | './libhfx_gl/src/hfx.c', 158 | './libhfx_src/src/hfx_matrix.c', 159 | './gl_test/cube/main.c' 160 | ] 161 | 162 | opengl_c_args = [ 163 | '-I'+meson.source_root()+'/libhfx_gl/include', 164 | '-I'+meson.source_root()+'/include' 165 | ] 166 | 167 | 168 | # Build OpenGL example platform 169 | # current disable OpenGL example platform 170 | ''' 171 | executable('cube', opengl_src, 172 | c_args : opengl_c_args, 173 | link_args : ['-lSDL2', '-lGL', '-lGLEW', '-lm']) 174 | ''' 175 | -------------------------------------------------------------------------------- /libhfx_src/src/hfx_matrix.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #define TO_RAD(x) ((x)*(M_PI)/180.0f) 8 | 9 | void hfx_matrix_multiply(hfx_state *state, float *a, float *b, float *result) 10 | { 11 | float temp[16] = {0}; 12 | 13 | for(int i=0; i < 4; i++) 14 | { 15 | for(int j=0; j < 4; j++) 16 | { 17 | for(int k=0; k < 4; k++) 18 | { 19 | temp[i*4 + j] += a[k*4 + j]*b[i*4 + k]; 20 | } 21 | } 22 | } 23 | 24 | memcpy(result, temp, sizeof(temp)); 25 | } 26 | 27 | void hfx_matrix_vector_multiply(hfx_state *state, float *mat, float *vec, float *result) 28 | { 29 | float temp[4] = {0}; 30 | 31 | for(int i=0; i < 4; i++) 32 | { 33 | for(int j=0; j < 4; j++) 34 | { 35 | temp[i] += mat[j*4 + i]*vec[j]; 36 | } 37 | } 38 | 39 | memcpy(result, temp, sizeof(temp)); 40 | } 41 | 42 | void hfx_normalize(hfx_state *state, float *vector, float *result) 43 | { 44 | float temp[4]; 45 | float mag = sqrtf(vector[0]*vector[0] + vector[1]*vector[1] + vector[2]*vector[2] + vector[3]*vector[3]); 46 | 47 | if(mag == 0) 48 | { 49 | hfx_fatal_error(state, "normalize zero vector"); 50 | } 51 | else 52 | { 53 | temp[0] = vector[0]/mag; 54 | temp[1] = vector[1]/mag; 55 | temp[2] = vector[2]/mag; 56 | temp[3] = vector[3]/mag; 57 | } 58 | 59 | memcpy(result, temp, sizeof(temp)); 60 | } 61 | 62 | void hfx_load_identity(hfx_state *state) 63 | { 64 | state->model_matrix[0] = 1.0f; 65 | state->model_matrix[1] = 0.0f; 66 | state->model_matrix[2] = 0.0f; 67 | state->model_matrix[3] = 0.0f; 68 | 69 | state->model_matrix[4] = 0.0f; 70 | state->model_matrix[5] = 1.0f; 71 | state->model_matrix[6] = 0.0f; 72 | state->model_matrix[7] = 0.0f; 73 | 74 | state->model_matrix[8] = 0.0f; 75 | state->model_matrix[9] = 0.0f; 76 | state->model_matrix[10] = 1.0f; 77 | state->model_matrix[11] = 0.0f; 78 | 79 | state->model_matrix[12] = 0.0f; 80 | state->model_matrix[13] = 0.0f; 81 | state->model_matrix[14] = 0.0f; 82 | state->model_matrix[15] = 1.0f; 83 | } 84 | 85 | void hfx_translate_f(hfx_state *state, float x, float y, float z) 86 | { 87 | float result[16] = {0}; 88 | result[0] = 1.0f; 89 | result[5] = 1.0f; 90 | result[10] = 1.0f; 91 | result[12] = x; 92 | result[13] = y; 93 | result[14] = z; 94 | result[15] = 1.0f; 95 | 96 | hfx_matrix_multiply(state, state->model_matrix, result, state->model_matrix); 97 | } 98 | 99 | void hfx_rotate_f(hfx_state *state, float angle, float x, float y, float z) 100 | { 101 | float axis[4] = {0}; 102 | float normalized_axis[4]; 103 | float result[16]; 104 | float angle_rad = TO_RAD(angle); 105 | float c = cos(angle_rad); 106 | float s = sin(angle_rad); 107 | 108 | axis[0] = x; 109 | axis[1] = y; 110 | axis[2] = z; 111 | 112 | hfx_normalize(state, axis, normalized_axis); 113 | 114 | result[0] = c + (1-c)*normalized_axis[0]*normalized_axis[0]; 115 | result[1] = (1-c)*normalized_axis[0]*normalized_axis[1] + s*normalized_axis[2]; 116 | result[2] = (1-c)*normalized_axis[0]*normalized_axis[2] - s*normalized_axis[1]; 117 | result[3] = 0.0f; 118 | 119 | result[4] = (1-c)*normalized_axis[1]*normalized_axis[0] - s*normalized_axis[2]; 120 | result[5] = c + (1-c)*normalized_axis[1]*normalized_axis[1]; 121 | result[6] = (1-c)*normalized_axis[1]*normalized_axis[2] + s*normalized_axis[0]; 122 | result[7] = 0.0f; 123 | 124 | result[8] = (1-c)*normalized_axis[2]*normalized_axis[0] + s*normalized_axis[1]; 125 | result[9] = (1-c)*normalized_axis[2]*normalized_axis[1] - s*normalized_axis[0]; 126 | result[10] = c + (1-c)*normalized_axis[2]*normalized_axis[2]; 127 | result[11] = 0.0f; 128 | 129 | result[12] = 0.0f; 130 | result[13] = 0.0f; 131 | result[14] = 0.0f; 132 | result[15] = 1.0f; 133 | 134 | hfx_matrix_multiply(state, state->model_matrix, result, state->model_matrix); 135 | } 136 | 137 | void hfx_scale_f(hfx_state *state, float sx, float sy, float sz) 138 | { 139 | float result[16] = {0}; 140 | 141 | result[0] = sx; 142 | result[5] = sy; 143 | result[10] = sz; 144 | result[15] = 1.0f; 145 | 146 | hfx_matrix_multiply(state, state->model_matrix, result, state->model_matrix); 147 | } 148 | 149 | void hfx_ortho_f(hfx_state *state, float left, float right, float top, float bottom, float near, float far) 150 | { 151 | float result[16] = {0}; 152 | 153 | result[0] = 2.0f / (right - left); 154 | result[5] = 2.0f / (top - bottom); 155 | result[10] = -2.0f / (far-near); 156 | result[12] = -(right + left) / (right - left); 157 | result[13] = -(top + bottom) / (top - bottom); 158 | result[14] = -(far + near) / (far - near); 159 | result[15] = 1.0f; 160 | 161 | hfx_matrix_multiply(state, state->model_matrix, result, state->model_matrix); 162 | } 163 | 164 | void hfx_persp_f(hfx_state *state, float fovy, float aspect, float znear, float zfar) 165 | { 166 | float result[16] = {0}; 167 | float tan_half_fov = tan(TO_RAD(fovy) / 2.0f); 168 | 169 | result[0] = 1.0f / (aspect * tan_half_fov); 170 | result[5] = 1.0f / tan_half_fov; 171 | result[10] = (zfar + znear) / (zfar - znear); 172 | result[11] = -1.0f; 173 | result[14] = (2.0f * zfar * znear) / (zfar - znear); 174 | 175 | hfx_matrix_multiply(state, state->model_matrix, result, state->model_matrix); 176 | } 177 | 178 | void hfx_mult_matrix_f(hfx_state *state, float *mat) 179 | { 180 | hfx_matrix_multiply(state, state->model_matrix, mat, state->model_matrix); 181 | } -------------------------------------------------------------------------------- /libhfx_src/src/hfx.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include "hfx_rdp.h" 9 | #include "system.h" 10 | 11 | #define RB_SIZE 1024 12 | 13 | #define RDP_TIMEOUT (1*1000*1000) 14 | 15 | #define COUNT_PER_US (TICKS_PER_SECOND / 1000 / 1000) 16 | #define HFX_DEBUG 17 | 18 | extern const void _hfx_ucode_data_start; 19 | extern const void _hfx_ucode_start; 20 | extern const void _hfx_ucode_end; 21 | 22 | static hfx_state state __attribute__((aligned(64))); 23 | 24 | static char pbuf[256]; 25 | 26 | static volatile bool done; 27 | 28 | static int __console_write( char *buf, unsigned int len ) 29 | { 30 | /* Write to special IO register in cen64 EMU */ 31 | for(int x = 0; x < len; x++) 32 | { 33 | hfx_write_reg(0x18000004, (uint32_t)buf[x]); 34 | } 35 | 36 | /* Always write all */ 37 | return len; 38 | } 39 | 40 | static stdio_t console_calls = { 41 | 0, 42 | __console_write, 43 | 0 44 | }; 45 | 46 | void hfx_rdp_int() 47 | { 48 | done = true; 49 | } 50 | 51 | void hfx_rsp_int() 52 | { 53 | hfx_fatal_error(&state, "RSP interrupt"); 54 | } 55 | 56 | hfx_state *hfx_init() 57 | { 58 | state.rb_start = 0; 59 | state.rb_end = 0; 60 | state.rb_size = HFX_RB_SIZE; // TODO probably want to make this programmable 61 | 62 | /* Initalize variables in hfx state */ 63 | hfx_rb_calc_size_mask(&state); 64 | 65 | /* For now hardcode display dimensions to 320x240 */ 66 | state.display_dim.width = 320; 67 | state.display_dim.height = 240; 68 | 69 | /* Initalize textures */ 70 | hfx_init_textures(&state); 71 | 72 | /* Initalize capabilties */ 73 | hfx_init_caps(&state); 74 | hfx_set_mode(&state); 75 | hfx_set_scissor(&state, 0, 0, (state.display_dim.width-1)<<2, (state.display_dim.height-1)<<2); 76 | 77 | /* Initalize RSP */ 78 | rsp_init(); 79 | register_SP_handler(hfx_rsp_int); 80 | set_SP_interrupt(1); 81 | 82 | /* Setup RDP interrupt for library */ 83 | register_DP_handler(hfx_rdp_int); 84 | set_DP_interrupt(1); 85 | 86 | /* Set RB pointer and size in ucode data */ 87 | uint32_t data_size = (uint32_t) ((uint8_t*)&_hfx_ucode_start - (uint8_t*)&_hfx_ucode_data_start); 88 | uint32_t ucode_size = (uint32_t) ((uint8_t*)&_hfx_ucode_end - (uint8_t*)&_hfx_ucode_start); 89 | 90 | uint32_t *data_ptr = (uint32_t*)&_hfx_ucode_data_start; 91 | data_ptr[HFX_REG_RB_ADDR/4] = (uint32_t)&state.rb; 92 | data_ptr[HFX_REG_RB_SIZE/4] = HFX_RB_SIZE; 93 | data_cache_hit_writeback_invalidate(data_ptr, data_size); 94 | 95 | load_data((void*)&_hfx_ucode_data_start, data_size); 96 | load_ucode((void*)&_hfx_ucode_start, ucode_size); 97 | 98 | run_ucode(); 99 | 100 | 101 | hfx_cmd_register_display(&state); 102 | 103 | HFX_UNUSED(console_calls); 104 | 105 | #ifdef HFX_DEBUG 106 | /* Register ourselves with newlib */ 107 | hook_stdio_calls( &console_calls ); 108 | #endif 109 | 110 | return &state; 111 | } 112 | 113 | 114 | void hfx_write_reg(uint32_t addr, uint32_t data) 115 | { 116 | *((volatile uint32_t*)(0xA0000000|addr)) = data; 117 | } 118 | 119 | uint32_t hfx_read_reg(uint32_t addr) 120 | { 121 | return *((volatile uint32_t*)(0xA0000000|addr)); 122 | } 123 | 124 | void hfx_register_rsp_int(hfx_state *state, void (*func_ptr)()) 125 | { 126 | /* Attach the RSP intterupt handler */ 127 | register_SP_handler(func_ptr); 128 | set_SP_interrupt(1); 129 | } 130 | 131 | void hfx_restart_rsp(hfx_state *state) 132 | { 133 | hfx_write_reg(HFX_VADDR_REG_RSP_PC, hfx_read_reg(HFX_VADDR_REG_RSP_PC)); 134 | hfx_write_reg(HFX_VADDR_REG_RSP_STATUS, HFX_RSP_CLEAR_BROKE|HFX_RSP_CLEAR_HALT); 135 | } 136 | 137 | void hfx_wait_us(uint64_t num_us) 138 | { 139 | wait_ticks(num_us*COUNT_PER_US); 140 | } 141 | 142 | void hfx_wait_for_idle(hfx_state *state) 143 | { 144 | uint64_t cmds[1]; 145 | done = false; 146 | cmds[0] = HFX_RDP_PKT_SYNC_FULL; 147 | hfx_cmd_rdp(state, sizeof(cmds)/sizeof(uint64_t), cmds); 148 | hfx_rb_submit(state); 149 | 150 | uint32_t count = 0; 151 | while(done != true) 152 | { 153 | count += 1; 154 | if(count > RDP_TIMEOUT) 155 | { 156 | hfx_fatal_error(state, "timeout wait for idle"); 157 | } 158 | hfx_wait_us(1); 159 | } 160 | } 161 | 162 | void hfx_fatal_error(hfx_state *state, char *msg) 163 | { 164 | // TODO replace this with proper define 165 | uint32_t rdp_status = hfx_read_reg(0x0410000C); 166 | uint32_t rsp_fifo_status = hfx_read_reg(HFX_VADDR_REG_STATUS); 167 | uint32_t rsp_status = hfx_read_reg(0x04040010); 168 | 169 | uint32_t rdp_start = hfx_read_reg(0x04100000); 170 | uint32_t rdp_end = hfx_read_reg(0x04100004); 171 | uint32_t rdp_current = hfx_read_reg(0x04100008); 172 | 173 | /* HALT RSP & RDP */ 174 | // TODO add defines for these registers 175 | hfx_write_reg(0x04040010, 0x00000002); 176 | hfx_write_reg(0x0410000c, 0x0008); 177 | 178 | graphics_fill_screen(state->last_display, 0); 179 | graphics_draw_text(state->last_display, 10, 10, "FATAL ERROR!"); 180 | 181 | sprintf(pbuf, "RSP STATUS: 0x%lx", rsp_status); 182 | graphics_draw_text(state->last_display, 10, 20, pbuf); 183 | 184 | sprintf(pbuf, "RSP FIFO STATUS: 0x%lx", rsp_fifo_status); 185 | graphics_draw_text(state->last_display, 10, 30, pbuf); 186 | 187 | sprintf(pbuf, "RDP STATUS: 0x%lx", rdp_status); 188 | graphics_draw_text(state->last_display, 10, 40, pbuf); 189 | 190 | sprintf(pbuf, "RSP FIFO\nStart 0x%08lx, end 0x%08lx", hfx_read_reg(HFX_VADDR_REG_RB_START), state->rb_end); 191 | graphics_draw_text(state->last_display, 10, 50, pbuf); 192 | 193 | sprintf(pbuf, "RSP CUR END 0x%lx\n", hfx_read_reg(HFX_VADDR_REG_RB_END)); 194 | graphics_draw_text(state->last_display, 10, 70, pbuf); 195 | 196 | sprintf(pbuf, "RDP FIFO\nStart 0x%lx, end 0x%lx, current 0x%lx", rdp_start, rdp_end, rdp_current); 197 | graphics_draw_text(state->last_display, 10, 80, pbuf); 198 | 199 | graphics_draw_text(state->last_display, 10, 100, msg); 200 | 201 | while(1) 202 | { 203 | /* Do nothing */ 204 | } 205 | } 206 | -------------------------------------------------------------------------------- /ucode_src/src/hfx_main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #define HFX_SET_XBUS_DMEM_DMA 0x0002 6 | #define HFX_RDP_BUFFER_SIZE 64 7 | 8 | #define HFX_READ_REG(reg) hfx_registers[(reg)>>2] 9 | #define HFX_WRITE_REG(reg, value) hfx_registers[(reg)>>2] = (value) 10 | // TODO fix masking here 11 | #define HFX_READ_RB(offset) hfx_rb_buffer[((rb_start+((offset)<<2))&0x3FF)>>2] 12 | #define OFFSET_OF(addr, offset) (((uint8_t*)(addr))+(offset)) 13 | 14 | #define hfx_rdp_queue(cmd) { \ 15 | hfx_rdb_buffer[hfx_rdp_end>>2] = cmd; \ 16 | hfx_rdp_end += sizeof(uint32_t); \ 17 | } 18 | 19 | extern uint32_t volatile hfx_registers[HFX_REGISTER_SPACE_SIZE]; 20 | volatile uint32_t hfx_rb_buffer[256] __attribute__((aligned(8))); 21 | volatile uint32_t hfx_rdb_buffer[HFX_RDP_BUFFER_SIZE] __attribute__((aligned(8))); 22 | static uint32_t hfx_rb_end; 23 | static uint32_t hfx_rdp_start, hfx_rdp_end; 24 | 25 | static void hfx_rdp_submit(); 26 | 27 | static void hfx_check_rb_ptr() 28 | { 29 | uint32_t status; 30 | uint32_t rb_end = HFX_READ_REG(HFX_REG_RB_END); 31 | 32 | if(hfx_rb_end != rb_end) 33 | { 34 | /* Setup DMA transfer registers */ 35 | // TODO only copy data we need to 36 | asm volatile ("mtc0 %0, $0\n" 37 | "mtc0 %1, $1\n" 38 | "mtc0 %2, $2" 39 | :: "r"(hfx_rb_buffer), 40 | "r"(HFX_READ_REG(HFX_REG_RB_ADDR)), 41 | "r"(HFX_READ_REG(HFX_REG_RB_SIZE)-1)); 42 | 43 | /* Wait for DMA to finish copying data */ 44 | do 45 | { 46 | asm volatile ("mfc0 %0, $6" : "=r"(status)); 47 | } while(status != 0); 48 | 49 | /* Update cached rb end value with updated value */ 50 | hfx_rb_end = rb_end; 51 | } 52 | 53 | return; 54 | } 55 | 56 | static void hfx_cmd_dma(bool write, uint32_t rb_start) 57 | { 58 | uint32_t dma_dmem_addr = HFX_READ_RB(1); 59 | uint32_t dma_mem_addr = HFX_READ_RB(2); 60 | uint32_t dma_size = HFX_READ_RB(3); 61 | uint32_t status; 62 | 63 | /* Setup DMA transfer registers */ 64 | asm volatile ("mtc0 %0, $0\n" 65 | "mtc0 %1, $1" 66 | :: "r"(dma_dmem_addr), 67 | "r"(dma_mem_addr)); 68 | if(write) 69 | { 70 | asm volatile ("mtc0 %0, $3" :: "r"(dma_size)); 71 | } 72 | else 73 | { 74 | asm volatile ("mtc0 %0, $2" :: "r"(dma_size)); 75 | } 76 | 77 | /* Wait for DMA to finish copying data */ 78 | do 79 | { 80 | asm volatile ("mfc0 %0, $6" : "=r"(status)); 81 | } while(status != 0); 82 | 83 | 84 | return; 85 | } 86 | 87 | static void hfx_rdp_init() 88 | { 89 | hfx_rdp_start = 0; 90 | hfx_rdp_end = 0; 91 | 92 | /* Set RDP to load using XBUS DMA (DMA from DMEM) */ 93 | /* Set RDP start and end pointer to statically allocated buffer */ 94 | asm volatile("mtc0 %0, $11\n" 95 | "mtc0 %1, $8\n" 96 | "mtc0 %2, $9" 97 | :: "r"(HFX_SET_XBUS_DMEM_DMA), 98 | "r"(hfx_rdb_buffer), 99 | "r"(hfx_rdb_buffer)); 100 | } 101 | 102 | static uint32_t hfx_rdp_size() 103 | { 104 | return hfx_rdp_end - hfx_rdp_start; 105 | } 106 | 107 | static void hfx_rdp_reserve(uint32_t num_bytes) 108 | { 109 | uint32_t rdp_size = hfx_rdp_size(); 110 | HFX_WRITE_REG(HFX_REG_STATUS, HFX_READ_REG(HFX_REG_STATUS)|HFX_STATUS_IN_RDP_RESERVE); 111 | if((rdp_size + num_bytes) >= (HFX_RDP_BUFFER_SIZE*sizeof(uint32_t))) 112 | { 113 | /* To deal with buffer wrapping we take the following approach: */ 114 | /* Submit any remaining queued commands, then wait for the RDP */ 115 | /* to complete executing by waiting until the RDP current pointer */ 116 | /* equals the end of the buffer. Once we know that the RDP has executed */ 117 | /* all remaining commands in the buffer we can then reset the buffer by */ 118 | /* setting the begin and end pointer to the same value */ 119 | hfx_rdp_submit(); 120 | 121 | uint32_t rdp_current; 122 | uint32_t offset_end = (uint32_t)OFFSET_OF(hfx_rdb_buffer, hfx_rdp_end); 123 | 124 | do 125 | { 126 | asm volatile("mfc0 %0, $10" 127 | : "=r"(rdp_current)); 128 | } while(rdp_current != offset_end); 129 | 130 | hfx_rdp_init(); 131 | } 132 | 133 | HFX_WRITE_REG(HFX_REG_STATUS, HFX_READ_REG(HFX_REG_STATUS)&(~HFX_STATUS_IN_RDP_RESERVE)); 134 | } 135 | 136 | static void hfx_rdp_submit() 137 | { 138 | asm volatile("mtc0 %0, $9" 139 | :: "r"(OFFSET_OF(hfx_rdb_buffer, hfx_rdp_end))); 140 | } 141 | 142 | static void hfx_cmd_set_rdp(uint32_t rb_start, uint32_t num_cmds) 143 | { 144 | hfx_rdp_reserve(sizeof(uint32_t)*num_cmds); 145 | 146 | for(uint32_t i=0; i < num_cmds; i++) 147 | { 148 | hfx_rdp_queue(HFX_READ_RB(1+i)); 149 | } 150 | 151 | hfx_rdp_submit(); 152 | } 153 | 154 | int main() 155 | { 156 | uint32_t num_rdp_cmds = 0; 157 | /* Set REG RB_END to zero */ 158 | hfx_rb_end = 0; 159 | 160 | /* Set status reg to zero */ 161 | HFX_WRITE_REG(HFX_REG_STATUS, 0); 162 | 163 | hfx_rdp_init(); 164 | 165 | for(;;) 166 | { 167 | hfx_check_rb_ptr(); 168 | uint32_t rb_start = HFX_READ_REG(HFX_REG_RB_START); 169 | if(rb_start == hfx_rb_end) 170 | { 171 | HFX_WRITE_REG(HFX_REG_STATUS, HFX_READ_REG(HFX_REG_STATUS)|HFX_STATUS_FIFO_EMPTY); 172 | continue; 173 | } 174 | HFX_WRITE_REG(HFX_REG_STATUS, HFX_READ_REG(HFX_REG_STATUS)&(~HFX_STATUS_FIFO_EMPTY)); 175 | 176 | 177 | uint32_t cmd = HFX_READ_RB(0); 178 | switch(cmd & 0xFF) 179 | { 180 | case HFX_CMD_NOP: 181 | rb_start += 4; 182 | break; 183 | case HFX_CMD_DMA: 184 | hfx_cmd_dma(cmd>>8, rb_start); 185 | rb_start += 16; 186 | break; 187 | case HFX_CMD_SEND_RDP: 188 | num_rdp_cmds = cmd >> 8; 189 | hfx_cmd_set_rdp(rb_start, num_rdp_cmds); 190 | rb_start += 4 + num_rdp_cmds*4; 191 | break; 192 | default: 193 | HFX_WRITE_REG(HFX_REG_STATUS, HFX_READ_REG(HFX_REG_STATUS)|HFX_STATUS_INVALID_OP); 194 | HFX_WRITE_REG(HFX_REG_BAD_OP, cmd); 195 | case HFX_CMD_INT: 196 | asm volatile ("break"); 197 | rb_start += 4; 198 | break; 199 | } 200 | 201 | HFX_WRITE_REG(HFX_REG_RB_START, rb_start & 0x3FF); 202 | } 203 | 204 | return 0; 205 | } 206 | -------------------------------------------------------------------------------- /ucode_src/include/tri.S: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | 4 | // Assume vertex data is the following format 5 | // v04,v05 v1 6 | // v06,v07 v2 7 | // v08,v09 v3 8 | // Also assume verticies are sorted from highest to lowest, 9 | // with v1 at the top of the display 10 | // Also assume that $4 contains a pointer RDP ring buffer 11 | .global draw_tri 12 | draw_tri: 13 | // Calculate x3-x1, y3-y1 14 | sub_fixed $v10, $v11, $v08, $v09, $v04, $v05 15 | // Calculate x2-x1, y2-y1 16 | sub_fixed $v12, $v13, $v06, $v07, $v04, $v05 17 | // Calculate x3-x2, y3-y2 18 | sub_fixed $v14, $v15, $v08, $v09, $v06, $v07 19 | 20 | // Compute 1/(y3-y1) 21 | // This follows RSP doc pg. 79 for how to compute 22 | // the receipricol and then multiply by 2 23 | vrcph $v16, 1, $v10, 1 24 | vrcpl $v17, 1, $v11, 1 25 | vrcph $v16, 1, $v00, 0 26 | 27 | vmudn $v19, $v17, $v02, w1 // w1 contains constant 2 28 | vmadm $v18, $v16, $v02, w1 29 | vmadn $v19, $v00, $v00, 0 30 | 31 | // Calculate (x3-x1) * (1/(y3-y1)) 32 | // After this block v16,v17 contain DxHDy 33 | vmudl $v17, $v11, $v19, h1 34 | vmadm $v16, $v10, $v19, h1 35 | vmadn $v17, $v00, $v00, 0 36 | 37 | // Compute 1/(y2-y1) 38 | // This follows RSP doc pg. 79 for how to compute 39 | // the receipricol and then multiply by 2 40 | vrcph $v18, 1, $v12, 1 41 | vrcpl $v19, 1, $v13, 1 42 | vrcph $v18, 1, $v00, 0 43 | 44 | vmudn $v21, $v19, $v02, w1 // w1 contains constant 2 45 | vmadm $v20, $v18, $v02, w1 46 | vmadn $v21, $v00, $v00, w1 47 | 48 | // Calculate (x2-x1) * (1/(y2-y1)) 49 | // After this block v18,v19 contain DxMDy 50 | vmudl $v19, $v13, $v21, h1 51 | vmadm $v18, $v12, $v21, h1, 52 | vmadn $v19, $v00, $v00, 0 53 | 54 | // Compute 1/(y3-y2) 55 | // This follows RSP doc pg. 79 for how to compute 56 | // the receipricol and then multiply by 2 57 | vrcph $v20, 1, $v14, 1 58 | vrcpl $v21, 1, $v15, 1 59 | vrcph $v20, 1, $v00, 0 60 | 61 | vmudn $v23, $v21, $v02, w1 // w1 contains constant 2 62 | vmadm $v22, $v20, $v02, w1 63 | vmadn $v23, $v00, $v00, 0 64 | 65 | // Calculate (x3-x2) * (1/(y3-y2)) 66 | // After this block v20,v21 contain DxLDy 67 | vmudl $v21, $v15, $v23, h1 68 | vmadm $v20, $v14, $v23, h1 69 | vmadn $v21, $v00, $v00, 0 70 | 71 | // We have now computed DxHDy(v16,v17) DxMDy(v18,v19), DxLDy(v20,v21) 72 | // We need to calculate the triangle winding order with 73 | // a the calculation of (x1*y2 - x2*y1) + (x2*y3 - x3*y2) + (x3*y1 - x1*y3) 74 | // and we can check if the triangle is flipped based on if the result is positive 75 | 76 | // In order to perform a cross product we need vectors that look like a=(x1, x2, x3) 77 | // and b=(y1,y2,y3), c=(x2,x3,x1), d=(y2,y3,y1) 78 | // Then we can do r=(a*d) - (c*b) and accumlate the results of this vector (r[0]+r[1]+r[2]) 79 | // to obtain the winding value 80 | vmov $v10, 0, $v04, w0 81 | vmov $v10, 1, $v06, w0 82 | vmov $v10, 2, $v08, w0 83 | vmov $v11, 0, $v05, w0 84 | vmov $v11, 1, $v07, w0 85 | vmov $v11, 2, $v09, w0 86 | 87 | vmov $v12, 0, $v04, w1 88 | vmov $v12, 1, $v06, w1 89 | vmov $v12, 2, $v08, w1 90 | vmov $v13, 0, $v05, w1 91 | vmov $v13, 1, $v07, w1 92 | vmov $v13, 2, $v09, w1 93 | 94 | vmov $v14, 0, $v10, w1 95 | vmov $v14, 1, $v10, w2 96 | vmov $v14, 2, $v10, w0 97 | vmov $v15, 0, $v11, w1 98 | vmov $v15, 1, $v11, w2 99 | vmov $v15, 2, $v11, w0 100 | 101 | vmov $v22, 0, $v12, w1 102 | vmov $v22, 1, $v12, w2 103 | vmov $v22, 2, $v12, w0 104 | vmov $v23, 0, $v13, w1 105 | vmov $v23, 1, $v13, w2 106 | vmov $v23, 2, $v13, w0 107 | 108 | mul_fixed $v24, $v25, $v10, $v11, $v22, $v23 109 | mul_fixed $v26, $v27, $v12, $v13, $v14, $v15 110 | sub_fixed $v10, $v11, $v24, $v25, $v26, $v27 111 | 112 | // $v10,$v11 no contains the cross product of the (x1,x2,x3) (y1,y2,y3), we need to accumlate 113 | // the result[0] + result[1] + result[2] 114 | add_fixed $v12, $v13, $v10, $v11, $v10, $v11, w1 115 | add_fixed $v14, $v15, $v12, $v13, $v10, $v11, w2 116 | 117 | // Now store all of these values into the RDP command buffer 118 | add $5, $0, $0 119 | lui $5, 0x0800 120 | mfc2 a2, $v14, 0 121 | slt $6, $0, $6 122 | sll $6, $6, 23 123 | or $5, $5, $6 124 | 125 | // Load YL interger in a2 126 | mfc2 a2, $v08, 1 127 | // Load YL frac in a3 128 | mfc2 a3, $v09, 1 129 | 130 | // Get the upper 2 bits of YL frac and shift them to the start of the register 131 | andi $a3, $a3, 0xC000 132 | srl $a3, $a3, 14 133 | 134 | // Get the lower 11 bits and sign of YL int and sift them over two bits to make room for YL frac 135 | andi $a2, $a2, 0x1FFF 136 | sll $a2, $a2, 2 137 | 138 | // OR YL int and YL frac to combine them 139 | or $a2, $a2, $a3 140 | 141 | // OR YL with the command buffer register 142 | or $5, $5, $a2 143 | 144 | // Store first 32bit word of command in RDP command buffer 145 | sw $5, 0($4) 146 | 147 | // Load YM interger in a2 148 | mfc2 a2, $v06, 1 149 | // Load YM frac in a3 150 | mfc2 a3, $v07, 1 151 | 152 | // Get the upper 2 bits of YM frac and shift them to the start of the register 153 | andi $a3, $a3, 0xC000 154 | srl $a3, $a3, 14 155 | 156 | // Get the lower 11 bits and sign of YM int and sift them over two bits to make room for YM frac 157 | andi $a2, $a2, 0x1FFF 158 | sll $a2, $a2, 2 159 | 160 | // OR YM int and YM frac to combine them 161 | or $a2, $a2, $a3 162 | 163 | // Move YM into upper part of next word 164 | sll $5, $a2, 16 165 | 166 | // Load YH interger in a2 167 | mfc2 a2, $v04, 1 168 | // Load YH frac in a3 169 | mfc2 a3, $v05, 1 170 | 171 | // Get the upper 2 bits of YH frac and shift them to the start of the register 172 | andi $a3, $a3, 0xC000 173 | srl $a3, $a3, 14 174 | 175 | // Get the lower 11 bits and sign of YH int and sift them over two bits to make room for YH frac 176 | andi $a2, $a2, 0x1FFF 177 | sll $a2, $a2, 2 178 | 179 | // OR YH int and YH frac to combine them 180 | or $a2, $a2, $a3 181 | 182 | // OR YM and YH to combine them 183 | or $5, $5, $a2 184 | 185 | // Store second 32bit word of command in RDP buffer 186 | sw $5, 4($4) 187 | 188 | ssv $v08, 0, 4, $4 189 | ssv $v09, 0, 5, $4 190 | ssv $v20, 0, 6, $4 191 | ssv $v21, 0, 7, $4 192 | 193 | ssv $v04, 0, 8, $4 194 | ssv $v05, 0, 9, $4 195 | ssv $v16, 0, 10, $4 196 | ssv $v17, 0, 11, $4 197 | 198 | ssv $v06, 0, 12, $4 199 | ssv $v07, 0, 13, $4 200 | ssv $v18, 0, 14, $4 201 | ssv $v19, 0, 15, $4 202 | 203 | jr $ra 204 | nop 205 | 206 | -------------------------------------------------------------------------------- /tests/meson.build: -------------------------------------------------------------------------------- 1 | project('tests') 2 | fs = import('fs') 3 | 4 | # Need to get exe extension to properly run on windows 5 | exe_extension = '' 6 | if build_machine.system().contains('mingw') 7 | exe_extension = '.exe' 8 | endif 9 | 10 | mips_compiler = find_program('mips64-elf-gcc' + exe_extension) 11 | mips_linker = find_program('mips64-elf-ld' + exe_extension) 12 | mips_objcopy = find_program('mips64-elf-objcopy' + exe_extension) 13 | n64tool = find_program('n64tool' + exe_extension) 14 | chksum64 = find_program('chksum64' + exe_extension) 15 | 16 | prj_root = meson.source_root() + '/..' 17 | 18 | ##################################### 19 | # Add new tests & files here 20 | n64_tool_path = run_command('sh' + exe_extension, '-c', 'echo $N64_INST').stdout().strip() 21 | 22 | test_dict = { 23 | 'basic_rb_test' : { 24 | 'src' : ['main.c'], 25 | 'ucode_src' : [], 26 | }, 27 | 'basic_rdp_test' : { 28 | 'src' : ['main.c'], 29 | 'ucode_src' : [], 30 | }, 31 | 'rdp_buffer_wrap' : { 32 | 'src' : ['main.c'], 33 | 'ucode_src' : [], 34 | }, 35 | 'hfx_clear' : { 36 | 'src' : ['main.c'], 37 | 'ucode_src' : [], 38 | }, 39 | 'hfx_draw_single_tri' : { 40 | 'src' : ['main.c'], 41 | 'ucode_src' : [], 42 | }, 43 | 'hfx_cube' : { 44 | 'src' : ['main.c'], 45 | 'ucode_src' : [], 46 | }, 47 | 'hfx_tex_tri' : { 48 | 'src' : ['main.c'], 49 | 'ucode_src' : [], 50 | }, 51 | 'hfx_persp' : { 52 | 'src' : ['main.c'], 53 | 'ucode_src' : [], 54 | }, 55 | 'hfx_persp_tex' : { 56 | 'src' : ['main.c'], 57 | 'ucode_src' : [], 58 | }, 59 | 'ucode_tri' : { 60 | 'src' : ['main.c'], 61 | 'ucode_src' : ['ucode.c', 'ucode_asm.S'], 62 | }, 63 | 'ucode_sort' : { 64 | 'src' : ['main.c'], 65 | 'ucode_src' : ['ucode.c', 'ucode_asm.S'], 66 | }, 67 | 'ucode_mul_mat_vec' : { 68 | 'src' : ['main.c'], 69 | 'ucode_src' : ['ucode.c', 'ucode_asm.S'], 70 | }, 71 | } 72 | 73 | # Change compiler flags here 74 | cflags = [ 75 | '-I'+prj_root+'/include', 76 | '-I'+prj_root+'/libhfx_src/include', 77 | '-std=gnu99', 78 | '-march=vr4300', 79 | '-mtune=vr4300', 80 | '-O0', 81 | '-Wall', 82 | '-MMD', 83 | '-g', 84 | ] 85 | 86 | hfx_lib_path = prj_root+'/build' 87 | hfx_lib_name = hfx_lib_path + '/libhfx.a' 88 | 89 | ldflags = [ 90 | '-L'+n64_tool_path+'/mips64-elf/lib', 91 | '-L'+hfx_lib_path, 92 | '-L'+meson.source_root()+'/build', 93 | '--start-group', 94 | '-lhfx', 95 | '-ldragon', 96 | '-lc', 97 | '-lm', 98 | '-ldragonsys', 99 | '--end-group', 100 | '-Tn64.ld', 101 | ] 102 | 103 | ucode_cflags = [ 104 | '-I'+prj_root+'/include', 105 | '-I'+prj_root+'/ucode_src/include', 106 | '-std=gnu99', 107 | '-Wall', 108 | '-march=vr4300', 109 | '-mtune=vr4300', 110 | '-Os', 111 | '-mno-branch-likely', 112 | '-mno-llsc', 113 | '-Wall', 114 | '-mabi=eabi', 115 | '-mgp32', 116 | '-flto', 117 | '-MMD', 118 | '-EB', 119 | ] 120 | 121 | ucode_ldflags = [ 122 | '-I'+prj_root+'/include', 123 | '-I'+prj_root+'/ucode_src/include', 124 | '-Wall', 125 | '-march=vr4300', 126 | '-mtune=vr4300', 127 | '-mabi=eabi', 128 | '-mgp32', 129 | '-ffreestanding', 130 | '-nostdlib', 131 | '-Os', 132 | '-mno-branch-likely', 133 | '-mno-llsc', 134 | '-flto', 135 | '-EB', 136 | ] 137 | 138 | ucode_linker_script = prj_root+'/ucode.ld' 139 | ucode_crt = prj_root+'/ucode_src/src/crt.S' 140 | 141 | ##################################### 142 | 143 | # Build all c source files 144 | object_generator = generator(mips_compiler, 145 | output : '@BASENAME@.o', 146 | arguments : cflags + ['-c', '@INPUT@', '-o', '@OUTPUT@'], 147 | depfile : '@BASENAME@.d') 148 | 149 | ucode_object_generator = generator(mips_compiler, 150 | output : '@BASENAME@.o', 151 | arguments : ucode_cflags + ['-c', '@INPUT@', '-o', '@OUTPUT@'], 152 | depfile : '@BASENAME@.d') 153 | 154 | foreach test, test_sources : test_dict 155 | source_files = [] 156 | foreach source : test_sources['src'] 157 | file = meson.source_root() + '/' + test + '/' + source 158 | source_files += [file] 159 | endforeach 160 | 161 | ucode_deps = [] 162 | 163 | if 0 != test_sources['ucode_src'].length() 164 | ucode_source_files = [ucode_crt] 165 | foreach source : test_sources['ucode_src'] 166 | file = meson.source_root() + '/' + test + '/' + source 167 | ucode_source_files += [file] 168 | endforeach 169 | 170 | ucode_object_files = ucode_object_generator.process(ucode_source_files) 171 | 172 | # Build ucode into elf file 173 | ucode_elf_file = custom_target(test+'_ucode_elf', 174 | output : test+'.ucode.elf', 175 | input : ucode_object_files, 176 | depend_files : ucode_linker_script, 177 | command : [mips_compiler] + ucode_ldflags + ['@INPUT@', '-o', '@OUTPUT@', '-T', ucode_linker_script]) 178 | 179 | # convert ucode elf into bin files 180 | ucode_bin = custom_target(test+'_ucode_bin', 181 | output : [test+'_ucode_text.bin', test+'_ucode_data.bin'], 182 | input : ucode_elf_file, 183 | command : [mips_objcopy, '--dump-section', '.text='+test+'_ucode_text.bin', 184 | '--dump-section', '.data='+test+'_ucode_data.bin', '@INPUT@']) 185 | 186 | ucode_loader_file = meson.source_root() + '/' + test + '/loader.S' 187 | ucode_loader = custom_target(test+'_ucode_loader', 188 | output : test+'_@BASENAME@.o', 189 | input : ucode_loader_file, 190 | depfile : '@BASENAME@.d', 191 | depends : ucode_bin, 192 | command : [mips_compiler] + cflags + ['-c', '@INPUT@', '-o', '@OUTPUT@']) 193 | 194 | ucode_deps += [ucode_loader] 195 | endif 196 | 197 | object_files = object_generator.process(source_files) 198 | 199 | # Build final elf file 200 | elf_file = custom_target(test+'_elf', 201 | output : test+'.elf', 202 | input : [object_files] + ucode_deps, 203 | depend_files : hfx_lib_name, 204 | command : [mips_linker, '-o', '@OUTPUT@', '@INPUT@'] + ldflags) 205 | 206 | bin_file = custom_target(test+'_bin', 207 | output : test+'.bin', 208 | input : elf_file, 209 | command : [mips_objcopy, '@INPUT@', '@OUTPUT@', '-O', 'binary']) 210 | 211 | unfixed_binary = custom_target(test+'_unfixed_binary', 212 | output : test+'.z64', 213 | input: bin_file, 214 | command : [n64tool, '-l', '2M', '-h', n64_tool_path+'/mips64-elf/lib/header', '-o', '@OUTPUT@', '@INPUT@']) 215 | 216 | fixed_binary = custom_target(test+'_fixed_binary', 217 | output : test+'2.z64', # TODO find out if this is okay 218 | input : unfixed_binary, 219 | command : [chksum64, '@INPUT@'], build_by_default:true) 220 | endforeach 221 | -------------------------------------------------------------------------------- /include/GL/gl.h: -------------------------------------------------------------------------------- 1 | #ifndef GL_H 2 | #define GL_H 3 | #include 4 | 5 | #ifndef APIENTRY 6 | #define APIENTRY 7 | #endif 8 | #ifndef GLAPI 9 | #define GLAPI extern 10 | #endif 11 | 12 | #define GL_COLOR_BUFFER_BIT HFX_COLOR_BUFFER_BIT 13 | #define GL_DEPTH_BUFFER_BIT HFX_DEPTH_BUFFER_BIT 14 | 15 | #define GL_BYTE HFX_BYTE 16 | #define GL_UNSIGNED_BYTE HFX_UNSIGNED_BYTE 17 | #define GL_SHORT HFX_SHORT 18 | #define GL_UNSIGNED_SHORT HFX_UNSIGNED_SHORT 19 | #define GL_INT HFX_INT 20 | #define GL_UNSIGNED_INT HFX_UNSIGNED_INT 21 | #define GL_FLOAT HFX_FLOAT 22 | 23 | #define GL_UNSIGNED_SHORT_5_5_5_1 HFX_UNSIGNED_SHORT_5_5_5_1 24 | 25 | #define GL_TEXTURE_2D HFX_TEXTURE_2D 26 | 27 | #define GL_RGBA HFX_RGBA 28 | 29 | #define GL_TRIANGLES HFX_TRIANGLES 30 | 31 | #define GL_VERTEX_ARRAY HFX_VERTEX_ARRAY 32 | #define GL_COLOR_ARRAY HFX_COLOR_ARRAY 33 | 34 | #define GL_DEPTH_TEST HFX_DEPTH_TEST 35 | 36 | typedef unsigned int GLenum; 37 | typedef unsigned char GLboolean; 38 | typedef unsigned int GLbitfield; 39 | typedef signed char GLbyte; 40 | typedef short GLshort; 41 | typedef int GLint; 42 | typedef int GLsizei; 43 | typedef unsigned char GLubyte; 44 | typedef unsigned short GLushort; 45 | typedef unsigned int GLuint; 46 | typedef float GLfloat; 47 | typedef float GLclampf; 48 | typedef void GLvoid; 49 | typedef int GLintptrARB; 50 | typedef int GLsizeiptrARB; 51 | typedef int GLfixed; 52 | typedef int GLclampx; 53 | /* Internal convenience typedefs */ 54 | typedef void (*_GLfuncptr)(); 55 | 56 | /*************************************************************/ 57 | 58 | GLAPI void APIENTRY glActiveTexture (GLenum texture); 59 | GLAPI void APIENTRY glAlphaFunc (GLenum func, GLclampf ref); 60 | GLAPI void APIENTRY glAlphaFuncx (GLenum func, GLclampx ref); 61 | GLAPI void APIENTRY glBindTexture (GLenum target, GLuint texture); 62 | GLAPI void APIENTRY glBlendFunc (GLenum sfactor, GLenum dfactor); 63 | GLAPI void APIENTRY glClear (GLbitfield mask); 64 | GLAPI void APIENTRY glClearColor (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha); 65 | GLAPI void APIENTRY glClearColorx (GLclampx red, GLclampx green, GLclampx blue, GLclampx alpha); 66 | GLAPI void APIENTRY glClearDepthf (GLclampf depth); 67 | GLAPI void APIENTRY glClearDepthx (GLclampx depth); 68 | GLAPI void APIENTRY glClearStencil (GLint s); 69 | GLAPI void APIENTRY glClientActiveTexture (GLenum texture); 70 | GLAPI void APIENTRY glColor4f (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha); 71 | GLAPI void APIENTRY glColor4x (GLfixed red, GLfixed green, GLfixed blue, GLfixed alpha); 72 | GLAPI void APIENTRY glColorMask (GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha); 73 | GLAPI void APIENTRY glColorPointer (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer); 74 | GLAPI void APIENTRY glCompressedTexImage2D (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid *data); 75 | GLAPI void APIENTRY glCompressedTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid *data); 76 | GLAPI void APIENTRY glCopyTexImage2D (GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border); 77 | GLAPI void APIENTRY glCopyTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height); 78 | GLAPI void APIENTRY glCullFace (GLenum mode); 79 | GLAPI void APIENTRY glDeleteTextures (GLsizei n, const GLuint *textures); 80 | GLAPI void APIENTRY glDepthFunc (GLenum func); 81 | GLAPI void APIENTRY glDepthMask (GLboolean flag); 82 | GLAPI void APIENTRY glDepthRangef (GLclampf zNear, GLclampf zFar); 83 | GLAPI void APIENTRY glDepthRangex (GLclampx zNear, GLclampx zFar); 84 | GLAPI void APIENTRY glDisable (GLenum cap); 85 | GLAPI void APIENTRY glDisableClientState (GLenum array); 86 | GLAPI void APIENTRY glDrawArrays (GLenum mode, GLint first, GLsizei count); 87 | GLAPI void APIENTRY glDrawElements (GLenum mode, GLsizei count, GLenum type, const GLvoid *indices); 88 | GLAPI void APIENTRY glEnable (GLenum cap); 89 | GLAPI void APIENTRY glEnableClientState (GLenum array); 90 | GLAPI void APIENTRY glFinish (void); 91 | GLAPI void APIENTRY glFlush (void); 92 | GLAPI void APIENTRY glFogf (GLenum pname, GLfloat param); 93 | GLAPI void APIENTRY glFogfv (GLenum pname, const GLfloat *params); 94 | GLAPI void APIENTRY glFogx (GLenum pname, GLfixed param); 95 | GLAPI void APIENTRY glFogxv (GLenum pname, const GLfixed *params); 96 | GLAPI void APIENTRY glFrontFace (GLenum mode); 97 | GLAPI void APIENTRY glFrustumf (GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat zNear, GLfloat zFar); 98 | GLAPI void APIENTRY glFrustumx (GLfixed left, GLfixed right, GLfixed bottom, GLfixed top, GLfixed zNear, GLfixed zFar); 99 | GLAPI void APIENTRY glGenTextures (GLsizei n, GLuint *textures); 100 | GLAPI GLenum APIENTRY glGetError (void); 101 | GLAPI void APIENTRY glGetIntegerv (GLenum pname, GLint *params); 102 | GLAPI const GLubyte * APIENTRY glGetString (GLenum name); 103 | GLAPI void APIENTRY glHint (GLenum target, GLenum mode); 104 | GLAPI void APIENTRY glLightModelf (GLenum pname, GLfloat param); 105 | GLAPI void APIENTRY glLightModelfv (GLenum pname, const GLfloat *params); 106 | GLAPI void APIENTRY glLightModelx (GLenum pname, GLfixed param); 107 | GLAPI void APIENTRY glLightModelxv (GLenum pname, const GLfixed *params); 108 | GLAPI void APIENTRY glLightf (GLenum light, GLenum pname, GLfloat param); 109 | GLAPI void APIENTRY glLightfv (GLenum light, GLenum pname, const GLfloat *params); 110 | GLAPI void APIENTRY glLightx (GLenum light, GLenum pname, GLfixed param); 111 | GLAPI void APIENTRY glLightxv (GLenum light, GLenum pname, const GLfixed *params); 112 | GLAPI void APIENTRY glLineWidth (GLfloat width); 113 | GLAPI void APIENTRY glLineWidthx (GLfixed width); 114 | GLAPI void APIENTRY glLoadIdentity (void); 115 | GLAPI void APIENTRY glLoadMatrixf (const GLfloat *m); 116 | GLAPI void APIENTRY glLoadMatrixx (const GLfixed *m); 117 | GLAPI void APIENTRY glLogicOp (GLenum opcode); 118 | GLAPI void APIENTRY glMaterialf (GLenum face, GLenum pname, GLfloat param); 119 | GLAPI void APIENTRY glMaterialfv (GLenum face, GLenum pname, const GLfloat *params); 120 | GLAPI void APIENTRY glMaterialx (GLenum face, GLenum pname, GLfixed param); 121 | GLAPI void APIENTRY glMaterialxv (GLenum face, GLenum pname, const GLfixed *params); 122 | GLAPI void APIENTRY glMatrixMode (GLenum mode); 123 | GLAPI void APIENTRY glMultMatrixf (const GLfloat *m); 124 | GLAPI void APIENTRY glMultMatrixx (const GLfixed *m); 125 | GLAPI void APIENTRY glMultiTexCoord4f (GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q); 126 | GLAPI void APIENTRY glMultiTexCoord4x (GLenum target, GLfixed s, GLfixed t, GLfixed r, GLfixed q); 127 | GLAPI void APIENTRY glNormal3f (GLfloat nx, GLfloat ny, GLfloat nz); 128 | GLAPI void APIENTRY glNormal3x (GLfixed nx, GLfixed ny, GLfixed nz); 129 | GLAPI void APIENTRY glNormalPointer (GLenum type, GLsizei stride, const GLvoid *pointer); 130 | GLAPI void APIENTRY glOrthof (GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat zNear, GLfloat zFar); 131 | GLAPI void APIENTRY glOrthox (GLfixed left, GLfixed right, GLfixed bottom, GLfixed top, GLfixed zNear, GLfixed zFar); 132 | GLAPI void APIENTRY glPixelStorei (GLenum pname, GLint param); 133 | GLAPI void APIENTRY glPointSize (GLfloat size); 134 | GLAPI void APIENTRY glPointSizex (GLfixed size); 135 | GLAPI void APIENTRY glPolygonOffset (GLfloat factor, GLfloat units); 136 | GLAPI void APIENTRY glPolygonOffsetx (GLfixed factor, GLfixed units); 137 | GLAPI void APIENTRY glPopMatrix (void); 138 | GLAPI void APIENTRY glPushMatrix (void); 139 | GLAPI void APIENTRY glReadPixels (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid *pixels); 140 | GLAPI void APIENTRY glRotatef (GLfloat angle, GLfloat x, GLfloat y, GLfloat z); 141 | GLAPI void APIENTRY glRotatex (GLfixed angle, GLfixed x, GLfixed y, GLfixed z); 142 | GLAPI void APIENTRY glSampleCoverage (GLclampf value, GLboolean invert); 143 | GLAPI void APIENTRY glSampleCoveragex (GLclampx value, GLboolean invert); 144 | GLAPI void APIENTRY glScalef (GLfloat x, GLfloat y, GLfloat z); 145 | GLAPI void APIENTRY glScalex (GLfixed x, GLfixed y, GLfixed z); 146 | GLAPI void APIENTRY glScissor (GLint x, GLint y, GLsizei width, GLsizei height); 147 | GLAPI void APIENTRY glShadeModel (GLenum mode); 148 | GLAPI void APIENTRY glStencilFunc (GLenum func, GLint ref, GLuint mask); 149 | GLAPI void APIENTRY glStencilMask (GLuint mask); 150 | GLAPI void APIENTRY glStencilOp (GLenum fail, GLenum zfail, GLenum zpass); 151 | GLAPI void APIENTRY glTexCoordPointer (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer); 152 | GLAPI void APIENTRY glTexEnvf (GLenum target, GLenum pname, GLfloat param); 153 | GLAPI void APIENTRY glTexEnvfv (GLenum target, GLenum pname, const GLfloat *params); 154 | GLAPI void APIENTRY glTexEnvx (GLenum target, GLenum pname, GLfixed param); 155 | GLAPI void APIENTRY glTexEnvxv (GLenum target, GLenum pname, const GLfixed *params); 156 | GLAPI void APIENTRY glTexImage2D (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels); 157 | GLAPI void APIENTRY glTexParameterf (GLenum target, GLenum pname, GLfloat param); 158 | GLAPI void APIENTRY glTexParameterx (GLenum target, GLenum pname, GLfixed param); 159 | GLAPI void APIENTRY glTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels); 160 | GLAPI void APIENTRY glTranslatef (GLfloat x, GLfloat y, GLfloat z); 161 | GLAPI void APIENTRY glTranslatex (GLfixed x, GLfixed y, GLfixed z); 162 | GLAPI void APIENTRY glVertexPointer (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer); 163 | GLAPI void APIENTRY glViewport (GLint x, GLint y, GLsizei width, GLsizei height); 164 | 165 | #endif -------------------------------------------------------------------------------- /libhfx_src/src/hfx_render.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #define MIN_FLOAT 0.0001f 10 | 11 | void hfx_render_init(hfx_state *state) 12 | { 13 | uint64_t cmds[] = 14 | { 15 | /* Enable primitive fill */ 16 | 0xEF0000FF80000000ull, 17 | }; 18 | 19 | hfx_cmd_rdp(state, sizeof(cmds)/sizeof(uint64_t), cmds); 20 | } 21 | 22 | void hfx_set_primitive_color(hfx_state *state, uint32_t color) 23 | { 24 | uint64_t cmds[] = 25 | { 26 | 0xF900000000000000ull, 27 | }; 28 | cmds[0] = cmds[0] | color; 29 | 30 | hfx_cmd_rdp(state, sizeof(cmds)/sizeof(uint64_t), cmds); 31 | 32 | } 33 | 34 | void hfx_render_tri(hfx_state *state, HFXfixed *v1, HFXfixed *v2, HFXfixed *v3) 35 | { 36 | uint32_t a1 = (v1[0] & 0xFFFF0000) | ((v1[1] & 0xFFFF0000) >> 16); 37 | uint32_t a2 = (v1[2] & 0xFFFF0000) | ((v1[3] & 0xFFFF0000) >> 16); 38 | uint32_t b1 = (v2[0] & 0xFFFF0000) | ((v2[1] & 0xFFFF0000) >> 16); 39 | uint32_t b2 = (v2[2] & 0xFFFF0000) | ((v2[3] & 0xFFFF0000) >> 16); 40 | uint32_t c1 = (v3[0] & 0xFFFF0000) | ((v3[1] & 0xFFFF0000) >> 16); 41 | uint32_t c2 = (v3[2] & 0xFFFF0000) | ((v3[3] & 0xFFFF0000) >> 16); 42 | 43 | uint32_t d1 = ((v1[0] & 0x0000FFFF) << 16) | (v1[1] & 0x0000FFFF); 44 | uint32_t d2 = ((v1[2] & 0x0000FFFF) << 16) | (v1[3] & 0x0000FFFF); 45 | uint32_t e1 = ((v2[0] & 0x0000FFFF) << 16) | (v2[1] & 0x0000FFFF); 46 | uint32_t e2 = ((v2[2] & 0x0000FFFF) << 16) | (v2[3] & 0x0000FFFF); 47 | uint32_t f1 = ((v3[0] & 0x0000FFFF) << 16) | (v3[1] & 0x0000FFFF); 48 | uint32_t f2 = ((v3[2] & 0x0000FFFF) << 16) | (v3[3] & 0x0000FFFF); 49 | 50 | hfx_rb_reserve(state, 13); 51 | hfx_rb_queue(state, HFX_CMD_TRI); 52 | hfx_rb_queue(state, a1); 53 | hfx_rb_queue(state, a2); 54 | hfx_rb_queue(state, b1); 55 | hfx_rb_queue(state, b2); 56 | hfx_rb_queue(state, c1); 57 | hfx_rb_queue(state, c2); 58 | hfx_rb_queue(state, d1); 59 | hfx_rb_queue(state, d2); 60 | hfx_rb_queue(state, e1); 61 | hfx_rb_queue(state, e2); 62 | hfx_rb_queue(state, f1); 63 | hfx_rb_queue(state, f2); 64 | } 65 | 66 | void barycentric(float px, float py, float x1, float y1, float x2, float y2, float x3, float y3, float *u, float *v, float *w) 67 | { 68 | float v0x = x2 - x1, v0y = y2 - y1; 69 | float v1x = x3 - x1, v1y = y3 - y1; 70 | float v2x = px - x1, v2y = py - y1; 71 | float d00 = v0x*v0x + v0y * v0y; 72 | float d01 = v0x*v1x + v0y * v1y; 73 | float d11 = v1x*v1x + v1y * v1y; 74 | float d20 = v2x*v0x + v2y * v0y; 75 | float d21 = v2x*v1x + v2y * v1y; 76 | float denom = d00 * d11 - d01 * d01; 77 | *v = (fabs(denom) < MIN_FLOAT) ? 0.0f : ((d11 * d20 - d01 * d21) / denom); 78 | *w = (fabs(denom) < MIN_FLOAT) ? 0.0f : ((d00 * d21 - d01 * d20) / denom); 79 | *u = 1.0f - *v - *w; 80 | } 81 | 82 | uint32_t hfx_float_to_fixed(float a) 83 | { 84 | if(a > 32767) 85 | return (32767<<16); 86 | else if(a < -32768) 87 | return (-32768<<16); 88 | else 89 | return a * 65536.0; 90 | } 91 | 92 | uint32_t tri_draw_mode(hfx_state *state) 93 | { 94 | /* 95 | TRI: 1000 96 | SHADE: 1100 97 | DEPTH: 1001 98 | TEX: 1010 99 | SHADE_DEPTH: 1101 100 | */ 101 | 102 | uint32_t mode = 0xc; 103 | 104 | if(state->caps.depth_test) 105 | { 106 | mode |= 0x1; 107 | } 108 | 109 | if(state->caps.texture_2d) 110 | { 111 | mode |= 0x2; 112 | } 113 | 114 | return mode; 115 | } 116 | 117 | void hfx_render_tri_f(hfx_state *state, float *v1, float *v2, float *v3, float *vc1, float *vc2, float *vc3, float *vt1, float *vt2, float *vt3) 118 | { 119 | /* Credit to libdragon rdp_draw_filled_triangle for providing the */ 120 | /* conversion algorithm */ 121 | uint64_t edge_coef[4+8+2+8]; 122 | uint32_t buffer_index = 0; 123 | uint32_t tri_mode = 0; 124 | const float to_fixed_11_2 = 4.0f; 125 | float temp_x, temp_y, temp_z, temp_w; 126 | float x1 = v1[0], y1 = v1[1], z1 = v1[2], w1 = v1[3]; 127 | float x2 = v2[0], y2 = v2[1], z2 = v2[2], w2 = v2[3]; 128 | float x3 = v3[0], y3 = v3[1], z3 = v3[2], w3 = v3[3]; 129 | 130 | float *c1 = vc1, *c2 = vc2, *c3 = vc3, *temp_c; 131 | float *t1 = vt1, *t2 = vt2, *t3 = vt3, *temp_t; 132 | 133 | tri_mode = tri_draw_mode(state); 134 | 135 | /* sort vertices by Y ascending to find the major, mid and low edges */ 136 | if( y1 > y2 ) 137 | { 138 | temp_x = x2, temp_y = y2; temp_z = z2 ; temp_c = c2; temp_t = t2; temp_w = w2; 139 | y2 = y1; y1 = temp_y; 140 | x2 = x1; x1 = temp_x; 141 | z2 = z1; z1 = temp_z; 142 | w2 = w1; w1 = temp_w; 143 | c2 = c1; c1 = temp_c; 144 | t2 = t1; t1 = temp_t; 145 | } 146 | if( y2 > y3 ) 147 | { 148 | temp_x = x3, temp_y = y3; temp_z = z3; temp_c = c3; temp_t = t3; temp_w = w3; 149 | y3 = y2; y2 = temp_y; 150 | x3 = x2; x2 = temp_x; 151 | z3 = z2; z2 = temp_z; 152 | w3 = w2; w2 = temp_w; 153 | c3 = c2; c2 = temp_c; 154 | t3 = t2; t2 = temp_t; 155 | } 156 | if( y1 > y2 ) 157 | { 158 | temp_x = x2, temp_y = y2; temp_z = z2; temp_c = c2; temp_t = t2; temp_w = w2; 159 | y2 = y1; y1 = temp_y; 160 | x2 = x1; x1 = temp_x; 161 | z2 = z1; z1 = temp_z; 162 | w2 = w1; w1 = temp_w; 163 | c2 = c1; c1 = temp_c; 164 | t2 = t1; t1 = temp_t; 165 | } 166 | 167 | x1 = floorf(x1) + fmodf(x1, 1.0f/4.0f); 168 | x2 = floorf(x2) + fmodf(x2, 1.0f/4.0f); 169 | x3 = floorf(x3) + fmodf(x3, 1.0f/4.0f); 170 | y1 = floorf(y1) + fmodf(y1, 1.0f/4.0f); 171 | y2 = floorf(y2) + fmodf(y2, 1.0f/4.0f); 172 | y3 = floorf(y3) + fmodf(y3, 1.0f/4.0f); 173 | 174 | /* calculate Y edge coefficients in 11.2 fixed format */ 175 | uint32_t yh = y1 * to_fixed_11_2; 176 | uint32_t ym = y2 * to_fixed_11_2; 177 | uint32_t yl = y3 * to_fixed_11_2; 178 | 179 | float dxhdy_f = ( fabs(y3-y1) < MIN_FLOAT ) ? 0 : ( ( x3 - x1 ) / ( y3 - y1 ) ); 180 | float dxmdy_f = ( fabs(y2-y1) < MIN_FLOAT ) ? 0 : ( ( x2 - x1 ) / ( y2 - y1 ) ); 181 | float dxldy_f = ( fabs(y3-y2) < MIN_FLOAT ) ? 0 : ( ( x3 - x2 ) / ( y3 - y2 ) ); 182 | 183 | /* calculate inverse slopes in 16.16 fixed format */ 184 | uint32_t dxhdy = hfx_float_to_fixed(dxhdy_f); 185 | uint32_t dxmdy = hfx_float_to_fixed(dxmdy_f); 186 | uint32_t dxldy = hfx_float_to_fixed(dxldy_f); 187 | 188 | /* calculate X edge coefficients in 16.16 fixed format */ 189 | uint32_t xh = hfx_float_to_fixed(x1); 190 | uint32_t xm = hfx_float_to_fixed(x1); 191 | uint32_t xl = hfx_float_to_fixed(x2); 192 | 193 | /* determine the winding of the triangle */ 194 | int32_t winding = ( x1 * y2 - x2 * y1 ) + ( x2 * y3 - x3 * y2 ) + ( x3 * y1 - x1 * y3 ); 195 | uint32_t flip = (winding > 0 ? 1 : 0 ); 196 | 197 | uint32_t r = hfx_float_to_fixed(c1[0]); 198 | uint32_t g = hfx_float_to_fixed(c1[1]); 199 | uint32_t b = hfx_float_to_fixed(c1[2]); 200 | uint32_t a = hfx_float_to_fixed(c1[3]); 201 | 202 | uint32_t drde; 203 | uint32_t dgde; 204 | uint32_t dbde; 205 | uint32_t dade; 206 | uint32_t drdx; 207 | uint32_t dgdx; 208 | uint32_t dbdx; 209 | uint32_t dadx; 210 | uint32_t drdy; 211 | uint32_t dgdy; 212 | uint32_t dbdy; 213 | uint32_t dady; 214 | 215 | uint32_t dzde; 216 | uint32_t dzdx; 217 | uint32_t dzdy; 218 | 219 | uint32_t dwde; 220 | uint32_t dwdx; 221 | uint32_t dwdy; 222 | 223 | uint32_t s, t, dsdx, dtdx, dsde, dtde, dsdy, dtdy; 224 | 225 | float inv_z1 = (fabs(z1) < MIN_FLOAT) ? 65532.0f : (1.0f / z1); 226 | float inv_z2 = (fabs(z2) < MIN_FLOAT) ? 65532.0f : (1.0f / z2); 227 | float inv_z3 = (fabs(z3) < MIN_FLOAT) ? 65532.0f : (1.0f / z3); 228 | 229 | float inv_w1 = (fabs(w1) < MIN_FLOAT) ? 65532.0f : (1.0f / w1); 230 | float inv_w2 = (fabs(w2) < MIN_FLOAT) ? 65532.0f : (1.0f / w2); 231 | float inv_w3 = (fabs(w3) < MIN_FLOAT) ? 65532.0f : (1.0f / w3); 232 | 233 | uint32_t iz1 = ((uint32_t)hfx_float_to_fixed(inv_z1)) << 10; 234 | 235 | uint32_t iw1 = ((uint32_t)hfx_float_to_fixed(inv_w1)) << 12; 236 | 237 | { 238 | float u2,v2,w2,u3,v3,w3,u4,v4,w4; 239 | barycentric(x1+1,y1,x1,y1,x2,y2,x3,y3, &u2, &v2, &w2); 240 | barycentric(x1,y1+1,x1,y1,x2,y2,x3,y3, &u3, &v3, &w3); 241 | barycentric(x1+dxhdy_f,y1+1,x1,y1,x2,y2,x3,y3, &u4, &v4, &w4); 242 | 243 | drdx = hfx_float_to_fixed((c1[0]*u2 + c2[0]*v2 + c3[0]*w2) - c1[0]); 244 | dgdx = hfx_float_to_fixed((c1[1]*u2 + c2[1]*v2 + c3[1]*w2) - c1[1]); 245 | dbdx = hfx_float_to_fixed((c1[2]*u2 + c2[2]*v2 + c3[2]*w2) - c1[2]); 246 | dadx = hfx_float_to_fixed((c1[3]*u2 + c2[3]*v2 + c3[3]*w2) - c1[3]); 247 | 248 | drdy = hfx_float_to_fixed((c1[0]*u3 + c2[0]*v3 + c3[0]*w3) - c1[0]); 249 | dgdy = hfx_float_to_fixed((c1[1]*u3 + c2[1]*v3 + c3[1]*w3) - c1[1]); 250 | dbdy = hfx_float_to_fixed((c1[2]*u3 + c2[2]*v3 + c3[2]*w3) - c1[2]); 251 | dady = hfx_float_to_fixed((c1[3]*u3 + c2[3]*v3 + c3[3]*w3) - c1[3]); 252 | 253 | drde = hfx_float_to_fixed((c1[0]*u4 + c2[0]*v4 + c3[0]*w4) - c1[0]); 254 | dgde = hfx_float_to_fixed((c1[1]*u4 + c2[1]*v4 + c3[1]*w4) - c1[1]); 255 | dbde = hfx_float_to_fixed((c1[2]*u4 + c2[2]*v4 + c3[2]*w4) - c1[2]); 256 | dade = hfx_float_to_fixed((c1[3]*u4 + c2[3]*v4 + c3[3]*w4) - c1[3]); 257 | 258 | /* Calculate tex values */ 259 | s = hfx_float_to_fixed(t1[0]); 260 | t = hfx_float_to_fixed(t1[1]); 261 | 262 | dsdx = hfx_float_to_fixed((t1[0]*u2 + t2[0]*v2 + t3[0]*w2) - t1[0]); 263 | dtdx = hfx_float_to_fixed((t1[1]*u2 + t2[1]*v2 + t3[1]*w2) - t1[1]); 264 | 265 | dsdy = hfx_float_to_fixed((t1[0]*u3 + t2[0]*v3 + t3[0]*w3) - t1[0]); 266 | dtdy = hfx_float_to_fixed((t1[1]*u3 + t2[1]*v3 + t3[1]*w3) - t1[1]); 267 | 268 | dsde = hfx_float_to_fixed((t1[0]*u4 + t2[0]*v4 + t3[0]*w4) - t1[0]); 269 | dtde = hfx_float_to_fixed((t1[1]*u4 + t2[1]*v4 + t3[1]*w4) - t1[1]); 270 | 271 | /* Calculate depth values */ 272 | dzdx = ((uint32_t)hfx_float_to_fixed(((inv_z1*u2 + inv_z2*v2 + inv_z3*w2) - inv_z1))) << 10; 273 | dzdy = ((uint32_t)hfx_float_to_fixed(((inv_z1*u3 + inv_z2*v3 + inv_z3*w3) - inv_z1))) << 10; 274 | dzde = ((uint32_t)hfx_float_to_fixed(((inv_z1*u4 + inv_z2*v4 + inv_z3*w4) - inv_z1))) << 10; 275 | 276 | /* Calculate w-depth values */ 277 | dwdx = ((uint32_t)hfx_float_to_fixed(((inv_w1*u2 + inv_w2*v2 + inv_w3*w2) - inv_w1))) << 12; 278 | dwdy = ((uint32_t)hfx_float_to_fixed(((inv_w1*u3 + inv_w2*v3 + inv_w3*w3) - inv_w1))) << 12; 279 | dwde = ((uint32_t)hfx_float_to_fixed(((inv_w1*u4 + inv_w2*v4 + inv_w3*w4) - inv_w1))) << 12; 280 | } 281 | 282 | HFX_RDP_PKT_TRI_NON_SHADE(edge_coef, 283 | tri_mode, 284 | flip, 285 | 0, 286 | 0, 287 | yl, 288 | ym, 289 | yh, 290 | xl, 291 | dxldy, 292 | xh, 293 | dxhdy, 294 | xm, 295 | dxmdy); 296 | HFX_RDP_PKT_TRI_SHADE(edge_coef, r, g, b, a, 297 | drdx, dgdx, dbdx, dadx, 298 | drdy, dgdy, dbdy, dady, 299 | drde, dgde, dbde, dade); 300 | if(state->caps.texture_2d) 301 | { 302 | HFX_RDP_PKT_TRI_TEX(edge_coef, s, t, iw1, dsdx, dtdx, dwdx, dsde, dtde, dwde, dsdy, dtdy, dwdy); 303 | } 304 | 305 | if(state->caps.depth_test) 306 | { 307 | HFX_RDP_PKT_TRI_DEPTH(edge_coef, iz1, dzdx, dzdy, dzde); 308 | } 309 | 310 | hfx_cmd_rdp(state, buffer_index, edge_coef); 311 | } 312 | -------------------------------------------------------------------------------- /libhfx_src/src/hfx_render_gl.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #define RGBA8_TO_RGBA5551(r,g,b,a) ((((r)&0xf8)<<8) | (((g)&0xf8)<<4) | (((b)&0xf8)>>2) | ((a)&0x01)) 10 | #define RGBA8_TO_UINT(r,g,b,a) ((((uint64_t)(r)&0xff)<<24) | (((uint64_t)(g)&0xff)<<16) | (((uint64_t)(b)&0xff)<<8) | ((uint64_t)(a)&0xff)) 11 | #define RGBA8_TO_PACKED(r,g,b,a) ((RGBA8_TO_RGBA5551(r,g,b,a) << 16) | (RGBA8_TO_RGBA5551(r,g,b,a))) 12 | 13 | extern uint16_t hfx_depth_buffer[]; 14 | 15 | void hfx_clear_color_f(hfx_state *state, float r, float g, float b, float a) 16 | { 17 | state->clear_color.r = r*255; 18 | state->clear_color.g = g*255; 19 | state->clear_color.b = b*255; 20 | state->clear_color.a = a*255; 21 | } 22 | 23 | void hfx_color_f(hfx_state *state, float r, float g, float b, float a) 24 | { 25 | state->vertex_color.r = r*255; 26 | state->vertex_color.g = g*255; 27 | state->vertex_color.b = b*255; 28 | state->vertex_color.a = a*255; 29 | } 30 | 31 | void hfx_vertex_pointer(hfx_state *state, uint32_t size, uint32_t type, uint32_t stride, void *data) 32 | { 33 | state->vertex_pointer = (float*)data; 34 | state->vertex_size = size; 35 | } 36 | 37 | void hfx_color_pointer(hfx_state *state, uint32_t size, uint32_t type, uint32_t stride, void *data) 38 | { 39 | state->color_pointer = (uint8_t*)data; 40 | state->color_size = size; 41 | } 42 | 43 | void hfx_tex_coord_pointer(hfx_state *state, uint32_t size, uint32_t type, uint32_t stride, void *data) 44 | { 45 | state->tex_coord_pointer = (float*)data; 46 | state->tex_coord_size = size; 47 | } 48 | 49 | void hfx_set_scissor(hfx_state *state, uint32_t xh, uint32_t yh, uint32_t xl, uint32_t yl) 50 | { 51 | uint64_t cmds[1]; 52 | 53 | cmds[0] = HFX_RDP_PKT_SET_SCISSOR(xh, yh, 0, 0, xl, yl); 54 | hfx_cmd_rdp(state, sizeof(cmds)/sizeof(uint64_t), cmds); 55 | } 56 | 57 | void hfx_set_mode(hfx_state *state) 58 | { 59 | bool is_two_cycle = false; // TODO figure out when we need two cycle 60 | uint64_t mode = 0; 61 | uint64_t combine_mode = 0; 62 | uint64_t cmds[4]; 63 | uint32_t cmd_index = 0; 64 | uint32_t combine_mode_type = HFX_RDP_CMD_SET_COMBINE_MODE_SHADE; 65 | hfx_tex_info *cur_tex = &state->tex_info.tex_list[state->tex_info.current_tex]; 66 | 67 | 68 | /* Only update the mode if we need to */ 69 | if(state->caps.dirty) 70 | { 71 | if(state->caps.depth_test) 72 | { 73 | mode |= HFX_RDP_CMD_SET_MODE_Z_UPDATE_ENABLE | 74 | HFX_RDP_CMD_SET_MODE_Z_COMPARE_ENABLE | 75 | HFX_RDP_CMD_SET_MODE_Z_SOURCE_SEL_PIXEL; 76 | } 77 | 78 | if(is_two_cycle) 79 | { 80 | mode |= HFX_RDP_CMD_SET_MODE_TWO_CYCLE; 81 | } 82 | else 83 | { 84 | mode |= HFX_RDP_CMD_SET_MODE_ONE_CYCLE; 85 | } 86 | 87 | // TODO need to add more specialized logic for handling different combine modes 88 | if(state->caps.texture_2d) 89 | { 90 | combine_mode_type = HFX_RDP_CMD_SET_COMBINE_MODE_TEXEL0; 91 | mode |= HFX_RDP_CMD_SET_MODE_BI_LERP_0 | 92 | HFX_RDP_CMD_SET_MODE_DETAIL_TEX_EN | 93 | HFX_RDP_CMD_SET_MODE_PERSP_TEX_EN; 94 | } 95 | 96 | // TODO set the rest of this state based on the graphics state 97 | mode |= HFX_RDP_CMD_SET_BLEND_MODE(1B_0, 0) | 98 | HFX_RDP_CMD_SET_BLEND_MODE(1A_0, 0) | 99 | HFX_RDP_CMD_SET_BLEND_MODE(2A_0, 0) | 100 | HFX_RDP_CMD_SET_BLEND_MODE(2B_0, 0) | 101 | HFX_RDP_CMD_SET_MODE_RGB_NO_DITHER | 102 | HFX_RDP_CMD_SET_MODE_ALPHA_NO_DITHER | 103 | HFX_RDP_CMD_SET_MODE_DEPTH_MODE_OPAQUE | 104 | HFX_RDP_CMD_SET_MODE_ALPHA_CVG_SELECT | 105 | HFX_RDP_CMD_SET_MODE_CVG_DEST_FULL; 106 | 107 | combine_mode |= (combine_mode_type<caps.dirty = false; 120 | state->rdp_mode = mode; 121 | } 122 | 123 | if(state->tex_info.dirty && cur_tex->data != NULL) 124 | { 125 | uint32_t size_in_bytes = cur_tex->width*2; // TODO This is hardcoded uint16 126 | uint32_t round_amt = (size_in_bytes%8) ? 1 : 0; 127 | uint32_t size_in_words = (size_in_bytes/8) + round_amt; 128 | 129 | // TODO probably need to verify that texture data is 64 byte aligned 130 | cmd_index = 0; 131 | cmds[cmd_index++] = HFX_RDP_PKT_SYNC_LOAD; 132 | cmds[cmd_index++] = HFX_RDP_PKT_SET_TEXTURE_IMAGE(HFX_RDP_CMD_SET_TEXTURE_IMAGE_RGBA, 133 | HFX_RDP_CMD_SET_TEXTURE_IMAGE_16B, 134 | cur_tex->width-1, 135 | (uintptr_t)cur_tex->data); 136 | cmds[cmd_index++] = HFX_RDP_PKT_SET_TILE(HFX_RDP_CMD_SET_TILE_RBGA, 137 | HFX_RDP_CMD_SET_TILE_16B, 138 | size_in_words, 139 | 0, // TODO always loading to start of TMEM 140 | 0, // TODO tile desc is set to 0 141 | 0, // TODO palette is hardcoded to 0 142 | 0, // TODO ct set to zero 143 | 0, // TODO mt set to zero 144 | 5, // TODO mask_t hardcoded to 3 bits 145 | 0, // TODO shift_t set to zero 146 | 0, // TODO cs set to zero 147 | 0, // TODO ms set to zero 148 | 5, // TODO mask_s hardcoded to 3 bits 149 | 0 // TODO set shift to zero 150 | ); 151 | cmds[cmd_index++] = HFX_RDP_PKT_LOAD_TILE(0, // TODO set sl to zero 152 | 0, // TODO set tl to zero 153 | 0, // TODO set tile to zero 154 | (cur_tex->width-1)<<2, 155 | (cur_tex->height-1)<<2); 156 | 157 | hfx_cmd_rdp(state, cmd_index, cmds); 158 | state->tex_info.dirty = false; 159 | } 160 | } 161 | 162 | void hfx_draw_arrays(hfx_state *state, uint32_t type, uint32_t start, uint32_t count) 163 | { 164 | uint32_t num_tri = count / 3; 165 | uint32_t start_tri = start / 3; 166 | hfx_tex_info *cur_tex = &state->tex_info.tex_list[state->tex_info.current_tex]; 167 | float v1[4], v2[4], v3[4], c1[4], c2[4], c3[4], t1[2]={0}, t2[2]={0}, t3[2]={0}; 168 | float tex_width = cur_tex->width*4.0f - 1.0f; 169 | float tex_height= cur_tex->height*4.0f - 1.0f; 170 | uint32_t vs = state->vertex_size; 171 | 172 | hfx_set_mode(state); 173 | 174 | for(int i = start_tri; i < num_tri; i++) 175 | { 176 | v1[0] = state->vertex_pointer[i*vs*state->vertex_size+0]; 177 | v1[1] = state->vertex_pointer[i*vs*state->vertex_size+1]; 178 | v1[2] = vs < 3 ? 0.0f : state->vertex_pointer[i*vs*state->vertex_size+2]; 179 | v1[3] = vs < 4 ? 1.0f : state->vertex_pointer[i*vs*state->vertex_size+3]; 180 | 181 | v2[0] = state->vertex_pointer[i*vs*state->vertex_size+vs+0]; 182 | v2[1] = state->vertex_pointer[i*vs*state->vertex_size+vs+1]; 183 | v2[2] = vs < 3 ? 0.0f : state->vertex_pointer[i*vs*state->vertex_size+vs+2]; 184 | v2[3] = vs < 4 ? 1.0f : state->vertex_pointer[i*vs*state->vertex_size+vs+3]; 185 | 186 | v3[0] = state->vertex_pointer[i*vs*state->vertex_size+vs*2+0]; 187 | v3[1] = state->vertex_pointer[i*vs*state->vertex_size+vs*2+1]; 188 | v3[2] = vs < 3 ? 0.0f : state->vertex_pointer[i*vs*state->vertex_size+vs*2+2]; 189 | v3[3] = vs < 4 ? 1.0f : state->vertex_pointer[i*vs*state->vertex_size+vs*2+3]; 190 | 191 | c1[0] = (float)state->color_pointer[i*3*state->color_size+0]; 192 | c1[1] = (float)state->color_pointer[i*3*state->color_size+1]; 193 | c1[2] = (float)state->color_pointer[i*3*state->color_size+2]; 194 | c1[3] = (float)state->color_pointer[i*3*state->color_size+3]; 195 | 196 | c2[0] = (float)state->color_pointer[i*3*state->color_size+4]; 197 | c2[1] = (float)state->color_pointer[i*3*state->color_size+5]; 198 | c2[2] = (float)state->color_pointer[i*3*state->color_size+6]; 199 | c2[3] = (float)state->color_pointer[i*3*state->color_size+7]; 200 | 201 | c3[0] = (float)state->color_pointer[i*3*state->color_size+8]; 202 | c3[1] = (float)state->color_pointer[i*3*state->color_size+9]; 203 | c3[2] = (float)state->color_pointer[i*3*state->color_size+10]; 204 | c3[3] = (float)state->color_pointer[i*3*state->color_size+11]; 205 | 206 | if(state->caps.texture_2d) 207 | { 208 | printf("TEXTURE WIDTH %f %f\n", tex_width, tex_height); 209 | t1[0] = state->tex_coord_pointer[i*3*state->tex_coord_size+0]*tex_height; 210 | t1[1] = state->tex_coord_pointer[i*3*state->tex_coord_size+1]*tex_width; 211 | 212 | t2[0] = state->tex_coord_pointer[i*3*state->tex_coord_size+2]*tex_width; 213 | t2[1] = state->tex_coord_pointer[i*3*state->tex_coord_size+3]*tex_height; 214 | 215 | t3[0] = state->tex_coord_pointer[i*3*state->tex_coord_size+4]*tex_width; 216 | t3[1] = state->tex_coord_pointer[i*3*state->tex_coord_size+5]*tex_height; 217 | } 218 | 219 | hfx_draw_tri_f(state, v1, v2, v3, c1, c2, c3, t1, t2, t3); 220 | } 221 | } 222 | 223 | void hfx_clear(hfx_state *state, uint32_t bits) 224 | { 225 | uint32_t index = 0; 226 | uint64_t cmds[1+4+2+1]; 227 | 228 | cmds[index++] = HFX_RDP_PKT_SET_MODE(HFX_RDP_CMD_SET_MODE_ATOMIC_PRIM | 229 | HFX_RDP_CMD_SET_MODE_FILL | 230 | HFX_RDP_CMD_SET_MODE_RGB_NO_DITHER | 231 | HFX_RDP_CMD_SET_MODE_ALPHA_NO_DITHER) ; 232 | if(bits & HFX_DEPTH_BUFFER_BIT) 233 | { 234 | uint32_t packed_color = (HFX_PACK_Z_VALUE(HFX_MAX_DEPTH_VALUE,0)<<16 | 235 | HFX_PACK_Z_VALUE(HFX_MAX_DEPTH_VALUE,0)); 236 | cmds[index++] = HFX_RDP_PKT_SET_COLOR_IMAGE(HFX_RDP_CMD_SET_COLOR_IMAGE_FORMAT_RGBA, 237 | HFX_RDP_CMD_SET_COLOR_IMAGE_SIZE_16B, 238 | state->display_dim.width, 239 | 0x1ffffff&(uintptr_t)hfx_depth_buffer); 240 | cmds[index++] = HFX_RDP_PKT_SET_FILL_COLOR(packed_color); 241 | cmds[index++] = HFX_RDP_PKT_FILL_RECT(state->display_dim.width << 2, 242 | state->display_dim.height << 2, 0, 0); 243 | cmds[index++] = HFX_RDP_PKT_SET_COLOR_IMAGE(HFX_RDP_CMD_SET_COLOR_IMAGE_FORMAT_RGBA, 244 | HFX_RDP_CMD_SET_COLOR_IMAGE_SIZE_16B, 245 | state->display_dim.width, 246 | hfx_display_get_pointer(state)); 247 | } 248 | 249 | /* If we are clearing color buffer */ 250 | if(bits & HFX_COLOR_BUFFER_BIT) 251 | { 252 | uint32_t packed_color = RGBA8_TO_PACKED(state->clear_color.r, state->clear_color.g, 253 | state->clear_color.b, state->clear_color.a); 254 | cmds[index++] = HFX_RDP_PKT_SET_FILL_COLOR(packed_color); 255 | cmds[index++] = HFX_RDP_PKT_FILL_RECT(state->display_dim.width << 2, 256 | state->display_dim.height << 2, 0, 0); 257 | } 258 | cmds[index++] = HFX_RDP_PKT_SET_MODE(state->rdp_mode); 259 | 260 | hfx_cmd_rdp(state, index, cmds); 261 | } 262 | 263 | typedef struct hfx_vert 264 | { 265 | float pos[4]; 266 | float col[4]; 267 | float tex[2]; 268 | } hfx_vert; 269 | 270 | float lerp(float a, float b, float t) 271 | { 272 | return a + t*(b - a); 273 | } 274 | 275 | hfx_vert hfx_lerp_vert(hfx_vert *a, hfx_vert *b, float t) 276 | { 277 | hfx_vert out; 278 | out.pos[0] = lerp(a->pos[0], b->pos[0], t); 279 | out.pos[1] = lerp(a->pos[1], b->pos[1], t); 280 | out.pos[2] = lerp(a->pos[2], b->pos[2], t); 281 | out.pos[3] = lerp(a->pos[3], b->pos[3], t); 282 | out.col[0] = lerp(a->col[0], b->col[0], t); 283 | out.col[1] = lerp(a->col[1], b->col[1], t); 284 | out.col[2] = lerp(a->col[2], b->col[2], t); 285 | out.col[3] = lerp(a->col[3], b->col[3], t); 286 | out.tex[0] = lerp(a->tex[0], b->tex[0], t); 287 | out.tex[1] = lerp(a->tex[1], b->tex[1], t); 288 | 289 | return out; 290 | } 291 | 292 | hfx_vert hfx_make_vert(float *pos, float *col, float *tex) 293 | { 294 | hfx_vert output_vert; 295 | output_vert.pos[0] = pos[0]; 296 | output_vert.pos[1] = pos[1]; 297 | output_vert.pos[2] = pos[2]; 298 | output_vert.pos[3] = pos[3]; 299 | output_vert.col[0] = col[0]; 300 | output_vert.col[1] = col[1]; 301 | output_vert.col[2] = col[2]; 302 | output_vert.col[3] = col[3]; 303 | output_vert.tex[0] = tex[0]; 304 | output_vert.tex[1] = tex[1]; 305 | 306 | return output_vert; 307 | } 308 | 309 | void hfx_draw_tri_f(hfx_state *state, float *v1, float *v2, float *v3, float *vc1, float *vc2, float *vc3, float *vt1, float *vt2, float *vt3) 310 | { 311 | float v1_t[4], v2_t[4], v3_t[4]; 312 | hfx_vert verts[3]; 313 | hfx_vert output_verts[5]; 314 | bool good[3]; 315 | 316 | hfx_matrix_vector_multiply(state, state->model_matrix, v1, v1_t); 317 | hfx_matrix_vector_multiply(state, state->model_matrix, v2, v2_t); 318 | hfx_matrix_vector_multiply(state, state->model_matrix, v3, v3_t); 319 | 320 | verts[0] = hfx_make_vert(v1_t, vc1, vt1); 321 | verts[1] = hfx_make_vert(v2_t, vc2, vt2); 322 | verts[2] = hfx_make_vert(v3_t, vc3, vt3); 323 | 324 | for(int i=0; i < 3; i++) 325 | { 326 | float *cur_vert = &verts[i].pos[0]; 327 | good[i] = (cur_vert[2] >= -cur_vert[3]) && (cur_vert[2] <= cur_vert[3]); 328 | } 329 | 330 | int prev_index = 2; 331 | int prev2_index = 1; 332 | hfx_vert *prev_vert = &verts[prev_index]; 333 | hfx_vert *prev2_vert = &verts[prev2_index]; 334 | int index = 0; 335 | for(int i=0; i < 3; i++) 336 | { 337 | hfx_vert *cur_vert = &verts[i]; 338 | if(!good[i]) 339 | { 340 | if(good[prev_index]) 341 | { 342 | float t1 = (prev_vert->pos[3] - prev_vert->pos[2]) / 343 | ((prev_vert->pos[3] - prev_vert->pos[2]) - 344 | (cur_vert->pos[3] - cur_vert->pos[2])); 345 | /* Add t1 interpolated vert */ 346 | output_verts[index++] = hfx_lerp_vert(prev_vert, cur_vert, t1); 347 | } 348 | 349 | if(good[prev2_index]) 350 | { 351 | float t2 = (prev2_vert->pos[3] - prev2_vert->pos[2]) / 352 | ((prev2_vert->pos[3] - prev2_vert->pos[2]) - 353 | (cur_vert->pos[3] - cur_vert->pos[2])); 354 | /* Add t2 interpolated vert */ 355 | output_verts[index++] = hfx_lerp_vert(prev2_vert, cur_vert, t2); 356 | } 357 | } 358 | else 359 | { 360 | output_verts[index++] = *cur_vert; 361 | } 362 | 363 | prev2_vert = prev_vert; 364 | prev_vert = cur_vert; 365 | prev2_index = prev_index; 366 | prev_index = i; 367 | } 368 | 369 | int num_tri = index - 2; 370 | 371 | index = 2; 372 | 373 | if(num_tri > 0) 374 | { 375 | float w_depth; 376 | output_verts[0].pos[0] = ((output_verts[0].pos[0]/ 377 | output_verts[0].pos[3])+1)*(320.0f/2.0f); 378 | output_verts[0].pos[1] = ((output_verts[0].pos[1]/ 379 | output_verts[0].pos[3])-1)*(-240.0f/2.0f); 380 | w_depth = output_verts[0].pos[2]/output_verts[0].pos[3]; 381 | output_verts[0].pos[2] = (w_depth-1)*(-1.0f/2.0f); 382 | 383 | output_verts[0].tex[0] /= output_verts[0].pos[3]; 384 | output_verts[0].tex[1] /= output_verts[0].pos[3]; 385 | 386 | output_verts[index-1].pos[0] = ((output_verts[index-1].pos[0]/ 387 | output_verts[index-1].pos[3])+1)*(320.0f/2.0f); 388 | output_verts[index-1].pos[1] = ((output_verts[index-1].pos[1]/ 389 | output_verts[index-1].pos[3])-1)*(-240.0f/2.0f); 390 | w_depth = output_verts[index-1].pos[2]/output_verts[index-1].pos[3]; 391 | output_verts[index-1].pos[2] = (w_depth-1)*(-1.0f/2.0f); 392 | 393 | output_verts[index-1].tex[0] /= output_verts[index-1].pos[3]; 394 | output_verts[index-1].tex[1] /= output_verts[index-1].pos[3]; 395 | 396 | for(int i=0; i < num_tri; i++) 397 | { 398 | output_verts[index].pos[0] = ((output_verts[index].pos[0]/ 399 | output_verts[index].pos[3])+1)*(320.0f/2.0f); 400 | output_verts[index].pos[1] = ((output_verts[index].pos[1]/ 401 | output_verts[index].pos[3])-1)*(-240.0f/2.0f); 402 | w_depth = output_verts[index].pos[2]/output_verts[index].pos[3]; 403 | output_verts[index].pos[2] = (w_depth-1)*(-1.0f/2.0f); 404 | output_verts[index].tex[0] /= output_verts[index].pos[3]; 405 | output_verts[index].tex[1] /= output_verts[index].pos[3]; 406 | 407 | hfx_render_tri_f(state, output_verts[0].pos, output_verts[index-1].pos, output_verts[index].pos, 408 | output_verts[0].col, output_verts[index-1].col, output_verts[index].col, 409 | output_verts[0].tex, output_verts[index-1].tex, output_verts[index].tex); 410 | index += 1; 411 | } 412 | } 413 | } 414 | -------------------------------------------------------------------------------- /libhfx_src/include/hfx_rdp.h: -------------------------------------------------------------------------------- 1 | #ifndef HFX_RDP_H 2 | #define HFX_RDP_H 3 | 4 | #define HFX_RDP_10_2_MASK 0x1FFFull 5 | 6 | #define HFX_RDP_CMD_SHIFT 56ull 7 | #define HFX_RDP_CMD_MASK (0x3f << HFX_RDP_CMD_SHIFT) 8 | #define HFX_RDP_CMD_SET_COLOR_IMAGE 0x3full 9 | #define HFX_RDP_CMD_SET_COLOR_IMAGE_FORMAT_RGBA 0ull 10 | #define HFX_RDP_CMD_SET_COLOR_IMAGE_FORMAT_YUV 1ull 11 | #define HFX_RDP_CMD_SET_COLOR_IMAGE_FORMAT_INDEX 2ull 12 | #define HFX_RDP_CMD_SET_COLOR_IMAGE_FORMAT_IA 3ull 13 | #define HFX_RDP_CMD_SET_COLOR_IMAGE_FORMAT_I 4ull 14 | #define HFX_RDP_CMD_SET_COLOR_IMAGE_SIZE_4B 0ull 15 | #define HFX_RDP_CMD_SET_COLOR_IMAGE_SIZE_8B 1ull 16 | #define HFX_RDP_CMD_SET_COLOR_IMAGE_SIZE_16B 2ull 17 | #define HFX_RDP_CMD_SET_COLOR_IMAGE_SIZE_32B 3ull 18 | #define HFX_RDP_CMD_SET_Z_IMAGE 0x3eull 19 | #define HFX_RDP_CMD_RESERVE 0xc0ull 20 | #define HFX_RDP_CMD_SET_FILL_COLOR 0x37ull 21 | #define HFX_RDP_CMD_FILL_RECT 0x36ull 22 | #define HFX_RDP_CMD_FILL_RECT_ARG_MASK 0xfffull 23 | #define HFX_RDP_CMD_FILL_RECT_XL_SHIFT 44ull 24 | #define HFX_RDP_CMD_FILL_RECT_YL_SHIFT 32ull 25 | #define HFX_RDP_CMD_FILL_RECT_XH_SHIFT 12ull 26 | #define HFX_RDP_CMD_FILL_RECT_YH_SHIFT 0ull 27 | #define HFX_RDP_CMD_SET_MODE 0x2full 28 | #define HFX_RPD_CMD_SET_MODE_RESERVED 0xf00000000ull 29 | #define HFX_RDP_CMD_SET_MODE_ATOMIC_PRIM (1ull << 55ull) 30 | #define HFX_RDP_CMD_SET_MODE_ONE_CYCLE (0ull << 52ull) 31 | #define HFX_RDP_CMD_SET_MODE_TWO_CYCLE (1ull << 52ull) 32 | #define HFX_RDP_CMD_SET_MODE_COPY (2ull << 52ull) 33 | #define HFX_RDP_CMD_SET_MODE_FILL (3ull << 52ull) 34 | #define HFX_RDP_CMD_SET_MODE_PERSP_TEX_EN (1ull << 51ull) 35 | #define HFX_RDP_CMD_SET_MODE_DETAIL_TEX_EN (1ull << 50ull) 36 | #define HFX_RDP_CMD_SET_MODE_SHARPEN_TEX_EN (1ull << 49ull) 37 | #define HFX_RDP_CMD_SET_MODE_TEX_LOD_EN (1ull << 48ull) 38 | #define HFX_RDP_CMD_SET_MODE_TLUT_EN (1ull << 47ull) 39 | #define HFX_RDP_CMD_SET_MODE_TLUT_RGBA (0ull << 46ull) 40 | #define HFX_RDP_CMD_SET_MODE_TLUT_IA (1ull << 46ull) 41 | #define HFX_RDP_CMD_SET_MODE_SAMPLE_1X1 (0ull << 45ull) 42 | #define HFX_RDP_CMD_SET_MODE_SAMPLE_2X2 (1ull << 45ull) 43 | #define HFX_RDP_CMD_SET_MODE_MID_TEXEL (1ull << 44ull) 44 | #define HFX_RDP_CMD_SET_MODE_BI_LERP_0 (1ull << 43ull) 45 | #define HFX_RDP_CMD_SET_MODE_BI_LERP_1 (1ull << 42ull) 46 | #define HFX_RDP_CMD_SET_MODE_CONVERT_ONE (1ull << 41ull) 47 | #define HFX_RDP_CMD_SET_MODE_KEY_EN (1ull << 40ull) 48 | #define HFX_RDP_CMD_SET_MODE_RGB_MAGIC_SQUARE (0ull << 38ull) 49 | #define HFX_RDP_CMD_SET_MODE_RGB_BAYER_MATRIX (1ull << 38ull) 50 | #define HFX_RDP_CMD_SET_MODE_RGB_NOISE (2ull << 38ull) 51 | #define HFX_RDP_CMD_SET_MODE_RGB_NO_DITHER (3ull << 38ull) 52 | #define HFX_RDP_CMD_SET_MODE_ALPHA_MAGIC_SQUARE (0ull << 36ull) 53 | #define HFX_RDP_CMD_SET_MODE_ALPHA_BAYER_MATRIX (1ull << 36ull) 54 | #define HFX_RDP_CMD_SET_MODE_ALPHA_NOISE (2ull << 36ull) 55 | #define HFX_RDP_CMD_SET_MODE_ALPHA_NO_DITHER (3ull << 36ull) 56 | #define HFX_RDP_CMD_SET_MODE_BLEND_MODE_MASK 3ull 57 | #define HFX_RDP_CMD_SET_MODE_BLEND_MODE_1A_0_SHIFT 30ull 58 | #define HFX_RDP_CMD_SET_MODE_BLEND_MODE_1A_1_SHIFT 28ull 59 | #define HFX_RDP_CMD_SET_MODE_BLEND_MODE_1B_0_SHIFT 26ull 60 | #define HFX_RDP_CMD_SET_MODE_BLEND_MODE_1B_1_SHIFT 24ull 61 | #define HFX_RDP_CMD_SET_MODE_BLEND_MODE_2A_0_SHIFT 22ull 62 | #define HFX_RDP_CMD_SET_MODE_BLEND_MODE_2A_1_SHIFT 20ull 63 | #define HFX_RDP_CMD_SET_MODE_BLEND_MODE_2B_0_SHIFT 18ull 64 | #define HFX_RDP_CMD_SET_MODE_BLEND_MODE_2B_1_SHIFT 16ull 65 | #define HFX_RDP_CMD_SET_MODE_FORCE_BLEND (1ull << 14ull) 66 | #define HFX_RDP_CMD_SET_MODE_ALPHA_CVG_SELECT (1ull << 13ull) 67 | #define HFX_RDP_CMD_SET_MODE_CVG_TIMES_ALPHA (1ull << 12ull) 68 | /* TODO mising cvg and z-buffer operations here */ 69 | #define HFX_RDP_CMD_SET_MODE_DEPTH_MODE_OPAQUE (0ull << 10ull) 70 | #define HFX_RDP_CMD_SET_MODE_DEPTH_MODE_INTERPENETRATING (1ull << 10ull) 71 | #define HFX_RDP_CMD_SET_MODE_DEPTH_MODE_TRANSPARENT (2ull << 10ull) 72 | #define HFX_RDP_CMD_SET_MODE_DEPTH_MODE_DECAL (3ull << 10ull) 73 | #define HFX_RDP_CMD_SET_MODE_CVG_DEST_CLAMP (0ull << 8ull) 74 | #define HFX_RDP_CMD_SET_MODE_CVG_DEST_WARP (1ull << 8ull) 75 | #define HFX_RDP_CMD_SET_MODE_CVG_DEST_FULL (2ull << 8ull) 76 | #define HFX_RDP_CMD_SET_MODE_CVG_DEST_SAVE (3ull << 8ull) 77 | #define HFX_RDP_CMD_SET_MODE_IMAGE_READ (1ull << 6ull) 78 | #define HFX_RDP_CMD_SET_MODE_Z_UPDATE_ENABLE (1ull << 5ull) 79 | #define HFX_RDP_CMD_SET_MODE_Z_COMPARE_ENABLE (1ull << 4ull) 80 | #define HFX_RDP_CMD_SET_MODE_AA_ENABLE (1ull << 3ull) 81 | #define HFX_RDP_CMD_SET_MODE_Z_SOURCE_SEL_PIXEL (0ull << 2ull) 82 | #define HFX_RDP_CMD_SET_MODE_Z_SOURCE_SEL_PRIM (1ull << 2ull) 83 | #define HFX_RDP_CMD_TRI_NON_SHADE 0x08ull 84 | #define HFX_RDP_CMD_TRI_LEFT_MAJOR_FLAG_SHIFT 55ull 85 | #define HFX_RDP_CMD_TRI_LEVEL_MASK 0x7ull 86 | #define HFX_RDP_CMD_TRI_LEVEL_SHIFT 51ull 87 | #define HFX_RDP_CMD_TRI_TILE_MASK 0x7ull 88 | #define HFX_RPD_CMD_TRI_TILE_SHIFT 48ull 89 | #define HFX_RDP_CMD_TRI_YL_MASK 0x7fffull 90 | #define HFX_RDP_CMD_TRI_YL_SHIFT 32ull 91 | #define HFX_RDP_CMD_TRI_YM_MASK 0x7fffull 92 | #define HFX_RDP_CMD_TRI_YM_SHIFT 16ull 93 | #define HFX_RDP_CMD_TRI_YH_MASK 0x7fffull 94 | #define HFX_RDP_CMD_TRI_YH_SHIFT 0ull 95 | #define HFX_RDP_CMD_TRI_SHADE 0x0cull 96 | #define HFX_RDP_CMD_TRI_TEX_DEPTH 0x0bull 97 | #define HFX_RDP_CMD_TRI_SHADE_DEPTH 0x0dull 98 | #define HFX_RDP_CMD_TRI_SHADE_TEX_DEPTH 0x0full 99 | #define HFX_RDP_CMD_SET_BLEND_COLOR 0x39ull 100 | #define HFX_RDP_CMD_SET_COMBINE_MODE 0x3cull 101 | #define HFX_RDP_CMD_SET_COMBINE_MODE_COMBINED 0ull 102 | #define HFX_RDP_CMD_SET_COMBINE_MODE_TEXEL0 1ull 103 | #define HFX_RDP_CMD_SET_COMBINE_MODE_TEXEL1 2ull 104 | #define HFX_RDP_CMD_SET_COMBINE_MODE_PRIM 3ull 105 | #define HFX_RDP_CMD_SET_COMBINE_MODE_SHADE 4ull 106 | #define HFX_RDP_CMD_SET_COMBINE_MODE_ENV 5ull 107 | #define HFX_RDP_CMD_SET_COMBINE_MODE_CEN 6ull 108 | #define HFX_RDP_CMD_SET_COMBINE_MODE_SCALE 6ull 109 | #define HFX_RDP_CMD_SET_COMBINE_MODE_COMBINED_ALPHA 7ull 110 | #define HFX_RDP_CMD_SET_COMBINE_MODE_TEXEL0_ALPHA 8ull 111 | #define HFX_RDP_CMD_SET_COMBINE_MODE_TEXEL1_ALPHA 9ull 112 | #define HFX_RDP_CMD_SET_COMBINE_MODE_PRIM_ALPHA 10ull 113 | #define HFX_RDP_CMD_SET_COMBINE_MODE_SHADE_ALPHA 11ull 114 | #define HFX_RDP_CMD_SET_COMBINE_MODE_ENV_ALPHA 12ull 115 | #define HFX_RDP_CMD_SET_COMBINE_MODE_LOD_FRACATION 13ull 116 | #define HFX_RDP_CMD_SET_COMBINE_MODE_PRIM_LOD_FRAC 14ull 117 | #define HFX_RDP_CMD_SET_COMBINE_MODE_NOISE 7ull 118 | #define HFX_RDP_CMD_SET_COMBINE_MODE_K4 7ull 119 | #define HFX_RDP_CMD_SET_COMBINE_MODE_K5 15ull 120 | #define HFX_RDP_CMD_SET_COMBINE_MODE_1 6ull 121 | #define HFX_RDP_CMD_SET_COMBINE_MODE_0 31ull 122 | #define HFX_RDP_CMD_SET_COMBINE_MODE_ALPHA_COMBINED 0ull 123 | #define HFX_RDP_CMD_SET_COMBINE_MODE_ALPHA_TEXEL0 1ull 124 | #define HFX_RDP_CMD_SET_COMBINE_MODE_ALPHA_TEXEL1 2ull 125 | #define HFX_RDP_CMD_SET_COMBINE_MODE_ALPHA_PRIM 3ull 126 | #define HFX_RDP_CMD_SET_COMBINE_MODE_ALPHA_SHADE 4ull 127 | #define HFX_RDP_CMD_SET_COMBINE_MODE_ALPHA_ENV 5ull 128 | #define HFX_RDP_CMD_SET_COMBINE_MODE_ALPHA_LOD_FRAC 0ull 129 | #define HFX_RDP_CMD_SET_COMBINE_MODE_ALPHA_PRIM_LOD_FRAC 6ull 130 | #define HFX_RDP_CMD_SET_COMBINE_MODE_ALPHA_1 6ull 131 | #define HFX_RDP_CMD_SET_COMBINE_MODE_ALPHA_0 7ull 132 | #define HFX_RDP_CMD_SET_COMBINE_MODE_RGB_A_0_SHIFT 52ull 133 | #define HFX_RDP_CMD_SET_COMBINE_MODE_RGB_C_0_SHIFT 47ull 134 | #define HFX_RDP_CMD_SET_COMBINE_MODE_ALPHA_A_0_SHIFT 44ull 135 | #define HFX_RDP_CMD_SET_COMBINE_MODE_ALPHA_C_0_SHIFT 41ull 136 | #define HFX_RDP_CMD_SET_COMBINE_MODE_RGB_A_1_SHIFT 37ull 137 | #define HFX_RDP_CMD_SET_COMBINE_MODE_RGB_C_1_SHIFT 32ull 138 | #define HFX_RDP_CMD_SET_COMBINE_MODE_RGB_B_0_SHIFT 28ull 139 | #define HFX_RDP_CMD_SET_COMBINE_MODE_RGB_B_1_SHIFT 24ull 140 | #define HFX_RDP_CMD_SET_COMBINE_MODE_ALPHA_A_1_SHIFT 21ull 141 | #define HFX_RDP_CMD_SET_COMBINE_MODE_ALPHA_C_1_SHIFT 18ull 142 | #define HFX_RDP_CMD_SET_COMBINE_MODE_RGB_D_0_SHIFT 15ull 143 | #define HFX_RDP_CMD_SET_COMBINE_MODE_ALPHA_B_0_SHIFT 12ull 144 | #define HFX_RDP_CMD_SET_COMBINE_MODE_ALPHA_D_0_SHIFT 9ull 145 | #define HFX_RDP_CMD_SET_COMBINE_MODE_RGB_D_1_SHIFT 6ull 146 | #define HFX_RDP_CMD_SET_COMBINE_MODE_ALPHA_B_1_SHIFT 3ull 147 | #define HFX_RDP_CMD_SET_COMBINE_MODE_ALPHA_D_1_SHIFT 0ull 148 | #define HFX_RDP_CMD_SET_SCISSOR 0x2dull 149 | #define HFX_RDP_CMD_SET_SCISSOR_XH_SHIFT 44ull 150 | #define HFX_RDP_CMD_SET_SCISSOR_YH_SHIFT 32ull 151 | #define HFX_RDP_CMD_SET_SCISSOR_F_SHIFT 25ull 152 | #define HFX_RDP_CMD_SET_SCISSOR_O_SHIFT 24ull 153 | #define HFX_RDP_CMD_SET_SCISSOR_XL_SHIFT 12ull 154 | #define HFX_RDP_CMD_SET_SCISSOR_YL_SHIFT 0ull 155 | #define HFX_RDP_CMD_SET_TEXTURE_IMAGE 0x3dull 156 | #define HFX_RDP_CMD_SET_TEXTURE_IMAGE_RGBA 0ull 157 | #define HFX_RDP_CMD_SET_TEXTURE_IMAGE_YUV 1ull 158 | #define HFX_RDP_CMD_SET_TEXTURE_IMAGE_IDX 2ull 159 | #define HFX_RDP_CMD_SET_TEXTURE_IMAGE_IA 3ull 160 | #define HFX_RDP_CMD_SET_TEXTURE_IMAGE_I 4ull 161 | #define HFX_RDP_CMD_SET_TEXTURE_IMAGE_FORMAT_SHIFT 53ull 162 | #define HFX_RDP_CMD_SET_TEXTURE_IMAGE_4B 0ull 163 | #define HFX_RDP_CMD_SET_TEXTURE_IMAGE_8B 1ull 164 | #define HFX_RDP_CMD_SET_TEXTURE_IMAGE_16B 2ull 165 | #define HFX_RDP_CMD_SET_TEXTURE_IMAGE_32B 3ull 166 | #define HFX_RDP_CMD_SET_TEXTURE_IMAGE_SIZE_SHIFT 51ull 167 | #define HFX_RDP_CMD_SET_TEXTURE_IMAGE_WIDTH_SHIFT 32ull 168 | #define HFX_RDP_CMD_SET_TILE 0x35ull 169 | #define HFX_RDP_CMD_SET_TILE_RBGA 0ull 170 | #define HFX_RDP_CMD_SET_TILE_YUV 1ull 171 | #define HFX_RDP_CMD_SET_TILE_IDX 2ull 172 | #define HFX_RDP_CMD_SET_TILE_IA 3ull 173 | #define HFX_RDP_CMD_SET_TILE_I 4ull 174 | #define HFX_RDP_CMD_SET_TILE_FORMAT_SHIFT 53ull 175 | #define HFX_RDP_CMD_SET_TILE_4B 0ull 176 | #define HFX_RDP_CMD_SET_TILE_8B 1ull 177 | #define HFX_RDP_CMD_SET_TILE_16B 2ull 178 | #define HFX_RDP_CMD_SET_TILE_32B 3ull 179 | #define HFX_RDP_CMD_SET_TILE_OTHER 4ull 180 | #define HFX_RDP_CMD_SET_TILE_SIZE_SHIFT 51ull 181 | #define HFX_RDP_CMD_SET_TILE_LINE_SHIFT 41ull 182 | #define HFX_RDP_CMD_SET_TILE_TMEM_ADDR_SHIFT 32ull 183 | #define HFX_RDP_CMD_SET_TILE_TILE_SHIFT 24ull 184 | #define HFX_RDP_CMD_SET_TILE_PAL_SHIFT 20ull 185 | #define HFX_RDP_CMD_SET_TILE_CT_SHIFT 19ull 186 | #define HFX_RDP_CMD_SET_TILE_MT_SHIFT 18ull 187 | #define HFX_RDP_CMD_SET_TILE_MASK_T_SHIFT 14ull 188 | #define HFX_RDP_CMD_SET_TILE_SHIFT_T_SHIFT 10ull 189 | #define HFX_RDP_CMD_SET_TILE_CS_SHIFT 9ull 190 | #define HFX_RDP_CMD_SET_TILE_MS_SHIFT 8ull 191 | #define HFX_RDP_CMD_SET_TILE_MASK_S_SHIFT 4ull 192 | #define HFX_RDP_CMD_SET_TILE_SHIFT_S_SHIFT 0ull 193 | #define HFX_RDP_CMD_LOAD_TILE 0x34ull 194 | #define HFX_RDP_CMD_LOAD_TILE_SL_SHIFT 44ull 195 | #define HFX_RDP_CMD_LOAD_TILE_TL_SHIFT 32ull 196 | #define HFX_RDP_CMD_LOAD_TILE_TILE_SHIFT 24ull 197 | #define HFX_RDP_CMD_LOAD_TILE_SH_SHIFT 12ull 198 | #define HFX_RDP_CMD_LOAD_TILE_TH_SHIFT 0ull 199 | #define HFX_RPD_CMD_SYNC_LOAD 0x26ull 200 | #define HFX_RDP_CMD_SYNC_PIPE 0x27ull 201 | #define HFX_RDP_CMD_SYNC_TILE 0x28ull 202 | #define HFX_RDP_CMD_SYNC_FULL 0x29ull 203 | 204 | 205 | #define HFX_RDP_CMD_SET_BLEND_MODE(type, value) (((value)&HFX_RDP_CMD_SET_MODE_BLEND_MODE_MASK)<> 16); \ 274 | (buffer)[buffer_index++] = ((((uint64_t)(drdx))&0xFFFF0000) << 32) | ((((uint64_t)(dgdx))&0xFFFF0000) << 16) | ((((uint64_t)(dbdx))&0xFFFF0000)) | ((((uint64_t)(dadx))&0xFFFF0000) >> 16); \ 275 | (buffer)[buffer_index++] = ((((uint64_t)(r))&0x0000FFFF) << 48) | ((((uint64_t)(g))&0x0000FFFF) << 32) | ((((uint64_t)(b))&0x0000FFFF) << 16) | ((((uint64_t)(a))&0x0000FFFF)); \ 276 | (buffer)[buffer_index++] = ((((uint64_t)(drdx))&0x0000FFFF) << 48) | ((((uint64_t)(dgdx))&0x0000FFFF) << 32) | ((((uint64_t)(dbdx))&0x0000FFFF) << 16) | ((((uint64_t)(dadx))&0x0000FFFF)); \ 277 | (buffer)[buffer_index++] = ((((uint64_t)(drde))&0xFFFF0000) << 32) | ((((uint64_t)(dgde))&0xFFFF0000) << 16) | ((((uint64_t)(dbde))&0xFFFF0000)) | ((((uint64_t)(dade))&0xFFFF0000) >> 16); \ 278 | (buffer)[buffer_index++] = ((((uint64_t)(drdy))&0xFFFF0000) << 32) | ((((uint64_t)(dgdy))&0xFFFF0000) << 16) | ((((uint64_t)(dbdy))&0xFFFF0000)) | ((((uint64_t)(dady))&0xFFFF0000) >> 16); \ 279 | (buffer)[buffer_index++] = ((((uint64_t)(drde))&0x0000FFFF) << 48) | ((((uint64_t)(dgde))&0x0000FFFF) << 32) | ((((uint64_t)(dbde))&0x0000FFFF) << 16) | ((((uint64_t)(dade))&0x0000FFFF)); \ 280 | (buffer)[buffer_index++] = ((((uint64_t)(drdy))&0x0000FFFF) << 48) | ((((uint64_t)(dgdy))&0x0000FFFF) << 32) | ((((uint64_t)(dbdy))&0x0000FFFF) << 16) | ((((uint64_t)(dady))&0x0000FFFF)); 281 | #define HFX_RDP_PKT_TRI_DEPTH(buffer, inv_z, dzdx, dzdy, dzde) \ 282 | (buffer)[buffer_index++] = ((uint64_t)(inv_z) << 32) | ((uint64_t)(dzdx)); \ 283 | (buffer)[buffer_index++] = ((uint64_t)(dzde) << 32) | ((uint64_t)(dzdy)); 284 | #define HFX_RDP_PKT_TRI_TEX(buffer, s, t, w, dsdx, dtdx, dwdx, dsde, dtde, dwde, dsdy, dtdy, dwdy) \ 285 | (buffer)[buffer_index++] = ((((uint64_t)(s))&0xFFFF0000) << 32) | ((((uint64_t)(t))&0xFFFF0000) << 16) | ((((uint64_t)(w))&0xFFFF0000)); \ 286 | (buffer)[buffer_index++] = ((((uint64_t)(dsdx))&0xFFFF0000) << 32) | ((((uint64_t)(dtdx))&0xFFFF0000) << 16) | ((((uint64_t)(dwdx))&0xFFFF0000)); \ 287 | (buffer)[buffer_index++] = ((((uint64_t)(s))&0x0000FFFF) << 48) | ((((uint64_t)(t))&0x0000FFFF) << 32) | ((((uint64_t)(w))&0x0000FFFF) << 16); \ 288 | (buffer)[buffer_index++] = ((((uint64_t)(dsdx))&0x0000FFFF) << 48) | ((((uint64_t)(dtdx))&0x0000FFFF) << 32) | ((((uint64_t)(dwdx))&0x0000FFFF) << 16); \ 289 | (buffer)[buffer_index++] = ((((uint64_t)(dsde))&0xFFFF0000) << 32) | ((((uint64_t)(dtde))&0xFFFF0000) << 16) | ((((uint64_t)(dwde))&0xFFFF0000)); \ 290 | (buffer)[buffer_index++] = ((((uint64_t)(dsdy))&0xFFFF0000) << 32) | ((((uint64_t)(dtdy))&0xFFFF0000) << 16) | ((((uint64_t)(dwdy))&0xFFFF0000)); \ 291 | (buffer)[buffer_index++] = ((((uint64_t)(dsde))&0x0000FFFF) << 48) | ((((uint64_t)(dtde))&0x0000FFFF) << 32) | ((((uint64_t)(dwde))&0x0000FFFF) << 16); \ 292 | (buffer)[buffer_index++] = ((((uint64_t)(dsdy))&0x0000FFFF) << 48) | ((((uint64_t)(dtdy))&0x0000FFFF) << 32) | ((((uint64_t)(dwdy))&0x0000FFFF) << 16); 293 | 294 | 295 | 296 | #define HFX_MAX_DEPTH_VALUE 0x3fff 297 | #define HFX_PACK_Z_VALUE(z, dz) (((z)<<2)|(dz)) 298 | 299 | #endif --------------------------------------------------------------------------------