From b25051a80c464fd86d94418e52b8793c91c2a2d6 Mon Sep 17 00:00:00 2001 From: Sean Maas Date: Fri, 15 Nov 2024 01:05:54 -0500 Subject: [PATCH] Lay the groundwork for PPU window support --- src/defines.h | 41 +++++--- src/memory.S | 9 +- src/ppu.S | 274 +++++++++++++++++++++++++++++++++++++------------ src/rsp_main.S | 193 +++++++++++++++++++++++++++------- 4 files changed, 400 insertions(+), 117 deletions(-) diff --git a/src/defines.h b/src/defines.h index 7e07981..6daab7d 100644 --- a/src/defines.h +++ b/src/defines.h @@ -40,7 +40,7 @@ #define SECTION_INC 1 // The frame section data structure's size in bytes -#define SECTION_SIZE 0x30 +#define SECTION_SIZE 0x40 // Flags for tracking JIT block state #define FLAG_SX (1 << 0) @@ -163,14 +163,25 @@ #define M7D (M7C + 0x2) #define M7X (M7D + 0x2) #define M7Y (M7X + 0x2) -#define FILL_COLOR (M7Y + 0x2) -#define BGXSC (FILL_COLOR + 0x2) -#define OBSEL (BGXSC + 0x4) +#define WBGSEL (M7Y + 0x2) +#define SUB_COLOR (WBGSEL + 0x2) +#define MAIN_COLOR (SUB_COLOR + 0x2) +#define BGXSC (MAIN_COLOR + 0x2) +#define WHX (BGXSC + 0x4) +#define OBSEL (WHX + 0x4) #define M7SEL (OBSEL + 0x1) -#define TS (M7SEL + 0x1) +#define WOBJSEL (M7SEL + 0x1) +#define WBGLOG (WOBJSEL + 0x1) +#define WOBJLOG (WBGLOG + 0x1) +#define CGWSEL (WOBJLOG + 0x1) +#define CGADSUB (CGWSEL + 0x1) +#define TS (CGADSUB + 0x1) #define TM (TS + 0x1) -#define BG_MODE (TM + 0x1) -#define SPLIT_LINE (BG_MODE + 0x1) +#define TSW (TM + 0x1) +#define TMW (TSW + 0x1) +#define BG_MODE (TMW + 0x1) +#define FORCE_BLANK (BG_MODE + 0x1) +#define SPLIT_LINE (FORCE_BLANK + 0x1) // Start of frame values #define MASK_SEL (SPLIT_LINE + 0x1) #define FB_OFFSET (MASK_SEL + 0x8) @@ -184,18 +195,22 @@ // End of frame values #define RDP_INIT (FRAMEBUFFER + 0x8) #define RDP_FRAME (RDP_INIT + 0x40) -#define RDP_SECTION (RDP_FRAME + 0x18) -#define RDP_TILE (RDP_SECTION + 0x30) +#define RDP_FILL (RDP_FRAME + 0x18) +#define RDP_TILE (RDP_FILL + 0x38) #define RDP_TILE7 (RDP_TILE + 0x28) #define TILE_PARAMS (RDP_TILE7 + 0x78) #define LAYER_CHART (TILE_PARAMS + 0x20) #define OBJ_SIZES (LAYER_CHART + 0x90) -#define SCRN_OFSH (OBJ_SIZES + 0x20) -#define SCRN_OFSV (SCRN_OFSH + 0x8) -#define TILE_JUMPS (SCRN_OFSV + 0x8) -#define MAX_OBJECT (TILE_JUMPS + 0xC) +#define SCRN_OFSV (OBJ_SIZES + 0x20) +#define FILL_JUMPS (SCRN_OFSV + 0x8) +#define TILE_JUMPS (FILL_JUMPS + 0x10) +#define TEXREC_OFS (TILE_JUMPS + 0xC) +#define FILLREC_MASK (TEXREC_OFS + 0x4) +#define LDBLK_BITS (FILLREC_MASK + 0x4) +#define MAX_OBJECT (LDBLK_BITS + 0x4) #define WRAP_BOUND (MAX_OBJECT + 0x2) #define PRIO_CHECKS (WRAP_BOUND + 0x2) +#define WIN_BOUNDS (PRIO_CHECKS + 0x8) #define VEC_DATA 0xF70 // Macros that convert addresses between cached and uncached diff --git a/src/memory.S b/src/memory.S index 71743c8..8a21bee 100644 --- a/src/memory.S +++ b/src/memory.S @@ -118,10 +118,11 @@ write_iomap: .word write_bg4vofs, write_vmain, write_vmaddl, write_vmaddh // 0x2114-0x2117 .word write_vmdatal, write_vmdatah, write_m7sel, write_m7a // 0x2118-0x211B .word write_m7b, write_m7c, write_m7d, write_m7x // 0x211C-0x211F - .word write_m7y, write_cgadd, write_cgdata, write_unk // 0x2120-0x2123 - .word write_unk:(0x212B - 0x2123) // 0x2124-0x212B - .word write_tm, write_ts, write_unk, write_unk // 0x212C-0x212F - .word write_unk, write_cgadsub, write_coldata, write_setini // 0x2130-0x2133 + .word write_m7y, write_cgadd, write_cgdata, write_w12sel // 0x2120-0x2123 + .word write_w34sel, write_wobjsel, write_wh0, write_wh1 // 0x2124-0x2127 + .word write_wh2, write_wh3, write_wbglog, write_wobjlog // 0x2128-0x212B + .word write_tm, write_ts, write_tmw, write_tsw // 0x212C-0x212F + .word write_cgwsel, write_cgadsub, write_coldata, write_setini // 0x2130-0x2133 .word write_unk:(0x213F - 0x2133) // 0x2134-0x213F .word write_apuio0, write_apuio1, write_apuio2, write_apuio3 // 0x2140-0x2143 .word write_apuio0, write_apuio1, write_apuio2, write_apuio3 // 0x2144-0x2147 diff --git a/src/ppu.S b/src/ppu.S index be85f22..81208c1 100644 --- a/src/ppu.S +++ b/src/ppu.S @@ -67,8 +67,20 @@ .globl write_m7y .globl write_cgadd .globl write_cgdata +.globl write_w12sel +.globl write_w34sel +.globl write_wobjsel +.globl write_wh0 +.globl write_wh1 +.globl write_wh2 +.globl write_wh3 +.globl write_wbglog +.globl write_wobjlog .globl write_tm .globl write_ts +.globl write_tmw +.globl write_tsw +.globl write_cgwsel .globl write_cgadsub .globl write_coldata .globl write_setini @@ -117,14 +129,13 @@ vmadd: .hword 0 cgadd: .hword 0 vtime: .hword 0 stat78: .byte 0x1 -cgadsub: .byte 0 nmitimen: .byte 0 rdnmi: .byte 0 timeup: .byte 0 hvbjoy: .byte 0 .align 4 -// Values that are saved for each frame section (0x30 bytes) +// Values that are saved for each frame section (0x40 bytes) bghofs: .hword 0:4 bgvofs: .hword 0:4 bgnba: .hword 0 @@ -137,13 +148,24 @@ m7c: .hword 0 m7d: .hword 0 m7x: .hword 0 m7y: .hword 0 -fill_color: .hword 0 +wbgsel: .hword 0 +sub_color: .hword 0 +main_color: .hword 0 bgxsc: .byte 0:4 +whx: .byte 0:4 obsel: .byte 0 m7sel: .byte 0 +wobjsel: .byte 0 +wbglog: .byte 0 +wobjlog: .byte 0 +cgwsel: .byte 0 +cgadsub: .byte 0 ts: .byte 0 tm: .byte 0 +tsw: .byte 0 +tmw: .byte 0 bg_mode: .byte 0 +force_blank: .byte 0 split_line: .byte 0 .align 4 @@ -321,14 +343,10 @@ update_frame: .align 5 update_fill: - // Choose between main or sub backdrop color with some guesswork - lbu t0, cgadsub - lhu t1, cgram - andi t0, t0, 0x20 // Backdrop math - beqz t0, set_fill - lhu t2, coldata - beqz t2, set_fill - move t1, t2 + // Load the first fill color and both destinations + lhu t1, coldata + la t4, sub_color + la t5, main_color set_fill: // Space out the color's components and multiply with current brightness @@ -354,12 +372,20 @@ set_fill: srl t3, t3, 9 or t2, t2, t3 - // Update the fill color and the frame if the color changed - lhu t1, fill_color - andi t3, t1, 0x1 // Force blank - or t2, t2, t3 - sh t2, fill_color - bne t1, t2, update_frame + // Set the fill color and update the frame if changed + lhu t1, (t4) + beq t1, t2, next_fill + sh t2, (t4) + li t1, 0x1 + sb t1, sect_status + +next_fill: + // Move to the next color until both are done + beq t4, t5, end_fill + lhu t1, cgram + move t4, t5 + b set_fill +end_fill: jr ra .align 5 @@ -716,14 +742,11 @@ read_hvbjoy: // v0: value .align 5 write_inidisp: // a1: value - // Set the force blank bit and mark the section as dirty if changed - lhu t1, fill_color + // Set the force blank bit and update the frame if changed + lbu t1, force_blank andi t0, a1, 0x80 - srl t0, t0, 7 - andi t2, t1, 0xFFFE - or t2, t2, t0 - beq t1, t2, set_bright - sh t2, fill_color + beq t1, t0, set_bright + sb t0, force_blank li t1, 0x1 sb t1, sect_status @@ -750,40 +773,44 @@ set_bright: .align 5 write_obsel: // a1: value - // Write to the OBSEL register + // Write to the OBSEL register and update the frame if changed + lbu t0, obsel sb a1, obsel - j update_frame + bne t0, a1, update_frame + jr ra .align 5 write_oamaddl: // a1: value // Set the low byte of the OAM address reload - lhu t0, oamadd + lhu t2, oamadd andi t1, a1, 0xFF - andi t0, t0, 0x8100 - or t0, t0, t1 - sh t0, oamadd + andi t0, t2, 0x8100 + or t1, t1, t0 + sh t1, oamadd - // Reload the OAM address - sll t0, t0, 1 + // Reload the OAM address and update the frame if changed + sll t0, t1, 1 andi t0, t0, 0x3FE sh t0, oam_addr - j update_frame + bne t2, t1, update_frame + jr ra .align 5 write_oamaddh: // a1: value // Set the high bits of the OAM address reload - lhu t0, oamadd + lhu t2, oamadd sll t1, a1, 8 andi t1, t1, 0x8100 - andi t0, t0, 0xFF - or t0, t0, t1 - sh t0, oamadd + andi t0, t2, 0xFF + or t1, t1, t0 + sh t1, oamadd - // Reload the OAM address - sll t0, t0, 1 + // Reload the OAM address and update the frame if changed + sll t0, t1, 1 andi t0, t0, 0x3FE sh t0, oam_addr - j update_frame + bne t2, t1, update_frame + jr ra .align 5 write_oamdata: // a1: value @@ -822,54 +849,70 @@ oam_end: .align 5 write_bgmode: // a1: value // Set the BG screen mode from 0 to 7 + lbu t1, bg_mode andi t0, a1, 0xF beq t0, 0x9, high_prio andi t0, a1, 0xF7 + +set_mode: + // Update the frame if changed sb t0, bg_mode - j update_frame + bne t1, t0, update_frame + jr ra high_prio: // Set a special mode when mode 1 is set with the BG3 priority bit andi t0, a1, 0xF0 ori t0, t0, 8 - sb t0, bg_mode - j update_frame + b set_mode .align 5 write_bg1sc: // a1: value - // Write to the BG1SC register + // Write to the BG1SC register and update the frame if changed + lbu t0, bgxsc + 0 sb a1, bgxsc + 0 - j update_frame + bne t0, a1, update_frame + jr ra .align 5 write_bg2sc: // a1: value - // Write to the BG2SC register + // Write to the BG2SC register and update the frame if changed + lbu t0, bgxsc + 1 sb a1, bgxsc + 1 - j update_frame + bne t0, a1, update_frame + jr ra .align 5 write_bg3sc: // a1: value - // Write to the BG3SC register + // Write to the BG3SC register and update the frame if changed + lbu t0, bgxsc + 2 sb a1, bgxsc + 2 - j update_frame + bne t0, a1, update_frame + jr ra .align 5 write_bg4sc: // a1: value - // Write to the BG4SC register + // Write to the BG4SC register and update the frame if changed + lbu t0, bgxsc + 3 sb a1, bgxsc + 3 - j update_frame + bne t0, a1, update_frame + jr ra .align 5 write_bg12nba: // a1: value - // Set the low byte of the combined BGNBA register + // Set the low byte of the combined BGNBA register and update the frame if changed + lbu t0, bgnba + 1 sb a1, bgnba + 1 - j update_frame + bne t0, a1, update_frame + jr ra .align 5 write_bg34nba: // a1: value - // Set the high byte of the combined BGNBA register + // Set the high byte of the combined BGNBA register and update the frame if changed + lbu t0, bgnba + 0 sb a1, bgnba + 0 - j update_frame + bne t0, a1, update_frame + jr ra .align 5 write_bg1hofs: // a1: value @@ -1094,9 +1137,11 @@ datah_trans: .align 5 write_m7sel: // a1: value - // Write to the M7SEL register + // Write to the M7SEL register and update the frame if changed + lbu t0, m7sel sb a1, m7sel - j update_frame + bne t0, a1, update_frame + jr ra .align 5 write_m7a: // a1: value @@ -1206,24 +1251,125 @@ cg_high: beqz t0, update_fill jr ra +.align 5 +write_w12sel: // a1: value + // Set the low byte of the combined WBGSEL register and update the frame if changed + lbu t0, wbgsel + 1 + sb a1, wbgsel + 1 + bne t0, a1, update_frame + jr ra + +.align 5 +write_w34sel: // a1: value + // Set the high byte of the combined WBGSEL register and update the frame if changed + lbu t0, wbgsel + 0 + sb a1, wbgsel + 0 + bne t0, a1, update_frame + jr ra + +.align 5 +write_wobjsel: // a1: value + // Write to the WOBJSEL register and update the frame if changed + lbu t0, wobjsel + sb a1, wobjsel + bne t0, a1, update_frame + jr ra + +.align 5 +write_wh0: // a1: value + // Write to the WH0 register and update the frame if changed + lbu t0, whx + 0 + sb a1, whx + 0 + bne t0, a1, update_frame + jr ra + +.align 5 +write_wh1: // a1: value + // Write to the WH1 register and update the frame if changed + lbu t0, whx + 1 + sb a1, whx + 1 + bne t0, a1, update_frame + jr ra + +.align 5 +write_wh2: // a1: value + // Write to the WH2 register and update the frame if changed + lbu t0, whx + 2 + sb a1, whx + 2 + bne t0, a1, update_frame + jr ra + +.align 5 +write_wh3: // a1: value + // Write to the WH3 register and update the frame if changed + lbu t0, whx + 3 + sb a1, whx + 3 + bne t0, a1, update_frame + jr ra + +.align 5 +write_wbglog: // a1: value + // Write to the WBGLOG register and update the frame if changed + lbu t0, wbglog + sb a1, wbglog + bne t0, a1, update_frame + jr ra + +.align 5 +write_wobjlog: // a1: value + // Write to the WOBJLOG register and update the frame if changed + lbu t0, wobjlog + sb a1, wobjlog + bne t0, a1, update_frame + jr ra + .align 5 write_tm: // a1: value - // Write to the TM register + // Write to the TM register and update the frame if changed + lbu t0, tm sb a1, tm - j update_frame + bne t0, a1, update_frame + jr ra .align 5 write_ts: // a1: value - // Write to the TS register + // Write to the TS register and update the frame if changed + lbu t0, ts sb a1, ts - j update_frame + bne t0, a1, update_frame + jr ra + +.align 5 +write_tmw: // a1: value + // Write to the TMW register and update the frame if changed + lbu t0, tmw + sb a1, tmw + bne t0, a1, update_frame + jr ra + +.align 5 +write_tsw: // a1: value + // Write to the TSW register and update the frame if changed + lbu t0, tsw + sb a1, tsw + bne t0, a1, update_frame + jr ra + +.align 5 +write_cgwsel: // a1: value + // Write to the CGWSEL register and update the frame if changed + lbu t0, cgwsel + sb a1, cgwsel + bne t0, a1, update_frame + jr ra .align 5 write_cgadsub: // a1: value - // Write to the CGADSUB register - // TODO: use for more than approximations + // Write to the CGADSUB register and update the frame if changed + lbu t0, cgadsub sb a1, cgadsub - j update_fill + bne t0, a1, update_frame + jr ra .align 5 write_coldata: // a1: value diff --git a/src/rsp_main.S b/src/rsp_main.S index 84a8edb..157a7ff 100644 --- a/src/rsp_main.S +++ b/src/rsp_main.S @@ -35,7 +35,7 @@ framebuffer: .word FRAMEBUFFER1, FRAMEBUFFER2 rdp_init: // RDP commands that only need to run once - .dword 0x3C080E10001C8241 // Set Combine + .dword 0x2F0088FF00040001 // Set Other Modes .dword 0x39000000FFFFFFFF // Set Blend Color .dword 0x3510810000000000 // Set Tile (palette) .dword 0x3550000001054150 // Set Tile (block) @@ -50,14 +50,15 @@ rdp_frame: .dword 0x3D10000000000000 // Set Texture Image (palette) .dword 0x3300000000400000 // Load Block (palette) -rdp_section: - // RDP commands that run when changing the frame section +rdp_fill: + // RDP commands that run when filling the backdrop .dword 0x2800000000000000 // Sync Tile .dword 0x2D030020004303A0 // Set Scissor - .dword 0x3700000000000000 // Set Fill Color - .dword 0x2F3088FF00040001 // Set Other Modes (fill) + .dword 0x3A00000000000000 // Set Primitive Color + .dword 0x3C080E10001D86C3 // Set Combine (primitive) .dword 0x3642F3A000030020 // Fill Rectangle - .dword 0x2F0088FF00040001 // Set Other Modes (1-cycle) + .dword 0x2700000000000000 // Sync Pipe + .dword 0x3C080E10001C8241 // Set Combine (texture) rdp_tile: // RDP commands that run when a regular tile is drawn @@ -111,10 +112,15 @@ obj_sizes: .word 0x08081010, 0x08082020, 0x08084040, 0x10102020 .word 0x10104040, 0x20204040, 0x10202040, 0x10202020 -scrn_ofsh: .hword 0x0000, 0x0800, 0x0000, 0x0800 // Horizontal screen address offsets scrn_ofsv: .hword 0x0000, 0x0000, 0x0800, 0x1000 // Vertical screen address offsets +fill_jumps: .word fill_sub, fill_win, fill_notwin, fill_main // Backdrop fill functions tile_jumps: .word decode_tile4, decode_tile16, decode_tile256 // Tile decoding functions +// 32-bit constants +texrec_ofs: .word 0x22020020 +fillrec_mask: .word 0xFF000FFF +ldblk_bits: .word 0x01000200 + // Gap to ensure vector data is aligned .byte 0:(VEC_DATA - MAX_OBJECT) @@ -209,7 +215,7 @@ table_loop: // Run the RDP to start the frame li a0, RDP_FRAME jal rdp_send - li a1, RDP_SECTION + li a1, RDP_FILL // Initialize values for finding the first visible object li t9, 0x200 // Index @@ -296,31 +302,107 @@ next_section: lw t0, FB_OFFSET(sp) add t1, t0, k0 sll t1, t1, 2 - sh t1, RDP_SECTION + 10 - sh t1, RDP_SECTION + 38 + sh t1, RDP_FILL + 10 + sh t1, RDP_FILL + 38 add t2, t0, k1 sll t2, t2, 2 - sh t2, RDP_SECTION + 14 - ori t2, t2, 0xF000 - sh t2, RDP_SECTION + 34 - - // Update the RDP fill color for the section - lhu t0, FILL_COLOR - andi t1, t0, 0x1 - beqz t1, no_blank + sh t2, RDP_FILL + 14 + sh t2, RDP_FILL + 34 + + // Set some values for filling the backdrop + lw t0, FILLREC_MASK + lw t5, RDP_FILL + 36 + lw t6, RDP_FILL + 32 + and t5, t5, t0 + and t6, t6, t0 + li t7, 0 // Left bound + li t8, 255 // Right bound + li t9, 0 // Bound index + + // Clear the backdrop if force blank is enabled + lbu t4, FORCE_BLANK + beqz t4, not_blank + li s0, 0 + b fill_backdrop + +not_blank: + // Check if color math is enabled for backdrop pixels + lbu t0, CGADSUB + andi t0, t0, 0x20 + beqz t0, fill_main + + // Fill the backdrop based the math window, so effects like SMW transitions work + // TODO: implement color math properly if possible + lbu t0, CGWSEL + srl t0, t0, 2 + andi t0, t0, 0xC + lw t0, FILL_JUMPS(t0) + jr t0 nop - li t0, 0 -no_blank: - sh t0, RDP_SECTION + 20 - sh t0, RDP_SECTION + 22 - // Run the RDP to prepare the section - li a0, RDP_SECTION +fill_main: + // Use the main color first, with or without windows + b fill_backdrop +fill_win: + lhu s0, MAIN_COLOR + b use_window + lhu s1, SUB_COLOR + +fill_sub: + // Use the sub color first, with or without windows + b fill_backdrop +fill_notwin: + lhu s0, SUB_COLOR + lhu s1, MAIN_COLOR + +use_window: + // Calculate window bounds and load the first one + lbu a0, WOBJSEL + jal calc_windows + srl a0, a0, 4 + lbu t8, WIN_BOUNDS + +fill_backdrop: + // Update the RDP fill bounds for a window segment + addi t1, t7, 12 + sll t1, t1, 14 + or t0, t5, t1 + sw t0, RDP_FILL + 36 + addi t1, t8, 13 + sll t1, t1, 14 + or t0, t6, t1 + sw t0, RDP_FILL + 32 + + // Update the RDP primitive color for the segment + andi t0, s0, 0x3E // B + sll t0, t0, 10 + andi t1, s0, 0x7C0 // G + sll t1, t1, 13 + or t0, t0, t1 + andi t1, s0, 0xF800 // R + sll t1, t1, 16 + or t0, t0, t1 + ori t0, t0, 0xFF + sw t0, RDP_FILL + 20 + + // Run the RDP to fill the segment + li a0, RDP_FILL jal rdp_send li a1, RDP_TILE - // Don't draw any layers if force blank is set - bnez t1, next_section + // Swap the main and sub colors + move t0, s0 + move s0, s1 + move s1, t0 + + // Move to the next segment until the section is done + addi t9, t9, 1 + move t7, t8 + bne t7, 255, fill_backdrop + lbu t8, WIN_BOUNDS(t9) + + // Don't draw any layers if force blank was set + bnez t4, next_section // Set the initial layer lookup offset lbu s3, BG_MODE @@ -346,6 +428,7 @@ next_layer: // Look up the next layer and check if it's BG or OBJ // Layers are drawn in an order that mimics priority without slow depth testing // This isn't fully accurate; OBJ priority effects like SMB3 pipes won't work + // TODO: implement windows for layers lbu t0, LAYER_CHART(s3) bge t0, 0x80, draw_obj addi s3, s3, 1 @@ -469,9 +552,8 @@ load_screen: // Load a row of BG entries from the second horizontal screen addi a0, a0, 0x40 - andi t0, t2, 0x3 - sll t0, t0, 1 - lhu t0, SCRN_OFSH(t0) + andi t0, t2, 0x1 + sll t0, t0, 11 jal dma_read add a1, a1, t0 @@ -484,8 +566,8 @@ load_screen: addi t2, s0, 12 sll t2, t2, 14 or t1, t1, t2 // Upper X + lw t2, TEXREC_OFS sw t1, RDP_TILE + 28 - li t2, 0x22020020 add t1, t1, t2 // Lower X/Y sw t1, RDP_TILE + 24 @@ -960,8 +1042,8 @@ set_texels: // Update the amount of texels the RDP should load to TMEM sll t1, v1, 7 addi t1, t1, -1 + lw t0, LDBLK_BITS sll t1, t1, 12 - li t0, 0x01000200 or t0, t0, t1 sw t0, RDP_TILE7 + 20 @@ -1266,8 +1348,8 @@ next_objx: andi t7, t7, 0x1FF sll t7, t7, 14 or t0, t6, t7 // Upper X + lw t7, TEXREC_OFS sw t0, RDP_TILE + 28 - li t7, 0x22020020 add t0, t0, t7 // Lower X/Y sw t0, RDP_TILE + 24 @@ -1385,12 +1467,11 @@ skip_wrap: jal dma_write li a2, 0x1FF b next_layer - nop skip_objdecode: // Update the RDP texture address and draw a cached tile - li a1, TILE_CACHE_OBJ sll t0, s5, 6 + li a1, TILE_CACHE_OBJ add a1, a1, t0 b draw_objtile sw a1, RDP_TILE + 4 @@ -1404,6 +1485,48 @@ next_frame: xori sp, sp, 4 +calc_windows: // a0: mask settings + // Load offsets where the window area changes + lbu t0, WHX + 0 + lbu t1, WHX + 1 + li t2, 255 + + // Determine window areas based on the mask settings + // TODO: support window 2 and combine logic + li t3, 2 + beq a0, t3, win_in + li t3, 3 + beq a0, t3, win_out + nop + +win_none: + // Define the entire screen as non-window area + jr ra + sb t2, WIN_BOUNDS + 0 + +win_in: + // Define the space between bounds as window area + bgt t0, t1, win_none + sb t0, WIN_BOUNDS + 0 + sb t1, WIN_BOUNDS + 1 + jr ra + sb t2, WIN_BOUNDS + 2 + +win_all: + // Define the entire screen as window area + jr ra + sb t2, WIN_BOUNDS + 1 + +win_out: + // Define the space between bounds as non-window area + bgt t0, t1, win_all + sb zero, WIN_BOUNDS + 0 + sb t0, WIN_BOUNDS + 1 + sb t1, WIN_BOUNDS + 2 + jr ra + sb t2, WIN_BOUNDS + 3 + + multiply: // a0: multiplicand, a1: multiplier - v0: product // Multiply 2 16-bit values to get a 32-bit value mtc2 a0, $v00, 0 @@ -1448,7 +1571,6 @@ max2: move v1, a2 max3: jr ra - nop dma_write: // a0: RSP address, a1: DRAM address, a2: size @@ -1477,7 +1599,6 @@ rdp_send: // a0: start address, a1: end address mfc0 t0, COP0_DP_STATUS andi t0, t0, 0x40 // Command busy bnez t0, rdp_send - nop mtc0 a0, COP0_DP_START mtc0 a1, COP0_DP_END jr ra