From: Lukas Krickl Date: Tue, 15 Jul 2025 19:17:39 +0000 (+0200) Subject: video: added new system to redraw UI X-Git-Url: https://git.krickl.dev/?a=commitdiff_plain;h=683c9225af6219cf27db1f2d21d696c0d99e6c7f;p=gbrg%2F.git video: added new system to redraw UI The new system redraws the UI with a request system. The entire UI tilemap is mirrored in wram where it can be updated outside of blanks. --- diff --git a/src/defs.s b/src/defs.s index ae5bf9e..dbbf2c4 100644 --- a/src/defs.s +++ b/src/defs.s @@ -32,6 +32,9 @@ #define WINDOW_Y 112 #define WINDOW_X 1 +#define UI_TILE_WIDTH 20 +#define UI_TILE_HEIGHT 4 + ; defines end of scroll location #define CURSOR_MIN_X 0 #define CURSOR_MAX_X 0xF8 @@ -227,26 +230,6 @@ .de act_dialog_opts, 2 .de act_size, 0 - ; max bge queue size -#define BGE_MAX 4 - - ; max bg updates per frame -#define BG_UPDATE_MAX 8 - - ; bg update flags -.se 1 - ; sets a tile -.de BGEF_TILE, 1 - ; sets BGE address -.de BGEF_ADDR, 2 - - ; bg update entry -.se 0 - ; if flags is 00 the entry is skipped -.de bge_flags, 1 -.de bge_new_tile, 1 -.de bge_addr, 2 -.de bge_size, 0 #define MAP_BG_TILE_OFFSET 0 #define MAP_BG_FLAGS_OFFSET 1 diff --git a/src/map.s b/src/map.s index 4f7c949..6ada788 100644 --- a/src/map.s +++ b/src/map.s @@ -51,7 +51,7 @@ map_load: ret - ; draws map title to UI (SCRN1) + ; draws map title to UI ; inputs: ; hl: map_ptr map_draw_area_title: @@ -59,7 +59,7 @@ map_draw_area_title: add hl, de ; hl = map_name ptr ld b, MAP_NAME_LEN - ld de, SCRN1+1 + ld de, shadow_ui+1 @loop: ld a, [hl+] add a, FONT_OFFSET @@ -68,6 +68,8 @@ map_draw_area_title: dec b jr nz, @loop REL + call ui_request_redraw + ret ; gets the tile at a y/x position diff --git a/src/strings.s b/src/strings.s index 18f8297..24b7c1a 100644 --- a/src/strings.s +++ b/src/strings.s @@ -67,44 +67,3 @@ puts: @done: ret - ; prints a 0-terminated string to the update buffer - ; can be called outside of blank - ; inputs: - ; hl: the string - ; de: tile location -bputs: - ; the first char is special - ld a, [hl+] - cp a, 0 - jr z, @done REL ; if its 0 already skip - - ; if its not 0 write the address to the - ; bg update queue - add a, FONT_OFFSET - ld b, a ; b = tile data for text - ld a, BGEF_TILE | BGEF_ADDR - ; de = tile address already - push hl - call bg_update_queue_push - pop hl - -@loop: - - ; now we just push tiles - ; with BGEF_TILE - ld a, [hl+] - cp a, 0 ; terminator? - jr z, @done REL - - push hl - add a, FONT_OFFSET - ld b, a ; b = tile - ld a, BGEF_TILE ; tile only mode - ; no need to set location - call bg_update_queue_push - pop hl - - jr @loop REL -@done: - ret - diff --git a/src/ui.s b/src/ui.s index 029505a..0fca356 100644 --- a/src/ui.s +++ b/src/ui.s @@ -8,14 +8,104 @@ ; inits UI ui_init: + ; fill shadow UI with default tile + ld hl, shadow_ui + ld bc, UI_TILE_WIDTH * UI_TILE_HEIGHT + ld d, UI_WINDOW_BACKGROUND + call memset + call ui_redraw_hp + + call ui_request_redraw ret ; updates HP UI ui_redraw_hp: ld hl, STR_TEST - ld de, SCRN1 + 34 - call bputs + ld de, shadow_ui + 34 + call puts + + ret + + ; requests a redraw + ; this will set up redraw_bg + ; redraw_shadow and redraw_steps +ui_request_redraw: + ld hl, SCRN1 + ld a, h + ld [ui_redraw_bg], a + ld a, l + ld [ui_redraw_bg+1], a + + ld de, shadow_ui + ld a, d + ld [ui_redraw_shadow], a + ld a, e + ld [ui_redraw_shadow+1], a + + ; steps of 5 * 16 + ld a, 16 + ld [ui_redraw_steps], a + ret + +#macro ui_redraw_vblank_write + ld a, [de] + inc de + ld [hl+], a +#endmacro + + ; redraws a UI step in vblank +ui_redraw_vblank: + ld a, [ui_redraw_steps] + ; no more steps we bail + cp a, 0 + ret z + + ; steps-- + dec a + ld [ui_redraw_steps], a + + ; load bg ptr + ld a, [ui_redraw_bg] + ld h, a + ld a, [ui_redraw_bg+1] + ld l, a + + ; load source address + ld a, [ui_redraw_shadow] + ld d, a + ld a, [ui_redraw_shadow+1] + ld e, a + + ; write data + ; in an unrolled loop + ui_redraw_vblank_write + ui_redraw_vblank_write + ui_redraw_vblank_write + ui_redraw_vblank_write + ui_redraw_vblank_write + + ; lastly store current ptr state again + + + ld a, d + ld [ui_redraw_shadow], a + ld a, e + ld [ui_redraw_shadow+1], a + + ; skip 12 tiles ahead in BG + ; every other step + ld a, [ui_redraw_steps] + and a, 3 + jr nz, @no_jump REL + ld de, 12 + add hl, de +@no_jump: + ld a, h + ld [ui_redraw_bg], a + ld a, l + ld [ui_redraw_bg+1], a ret +#undefine ui_redraw_vblank_write diff --git a/src/update.s b/src/update.s index 4a83536..8d0b92b 100644 --- a/src/update.s +++ b/src/update.s @@ -41,9 +41,11 @@ update: ; loads default map new_game_init: call video_fade_out - + call shadow_oam_clear + call ui_init + call unit_load_default_player ; init initial map @@ -66,8 +68,6 @@ game_init: ld a, WINDOW_X ld [RWX], a - call ui_init - ; set up palettes for ; gameplay ld a, BGP diff --git a/src/video.s b/src/video.s index 5488045..3228ec5 100644 --- a/src/video.s +++ b/src/video.s @@ -10,12 +10,13 @@ vblank: ld a, [RLCD] or a, LCDCF_OBJON ld [RLCD], a + + ; check ui update + call ui_redraw_vblank ; dma previous frame's oam call OAMDMAFN - call bg_update_queue_process - call scroll_write ; get inputs @@ -248,129 +249,3 @@ tiles_load_bank9000: jp memcpy - - ; bg update queue - ; loads update_start tile address - ; and updates tiles until the STOP flag is read - ; of the loop countr is BGE_MAX -bg_update_queue_process: - ld de, bg_update_queue ; load initial entry - - ld b, BGE_MAX ; b == loop counter - ; hl = target address - -@loop: - ld a, [de] ; load flags - ; thest big 1 (STOP) - cp a, 0 - jr z, @skip REL ; skip this entry - - ; first test address set mode - bit 1, a - jr z, @no_addr_set REL - - push de - push af - - ; load addr from entry - inc de - inc de - ; get to addr - ld a, [de] - ld l, a - inc de - ld a, [de] - ld h, a - ; hl = new target address - - pop af - pop de -@no_addr_set: - ; test tile set bit - bit 0, a - jr z, @no_tile_wirte REL - - inc de - - ; write new tile and inc hl - ld a, [de] - ld [hl+], a - - dec de - -@no_tile_wirte: -@skip: - ; advance to next entry - inc de - inc de - inc de - inc de - dec b ; b-- - jr nz, @loop REL - - - ; advance to queue clear - - ; clears the bg update queue - ; sets update index to 0 -bg_update_queue_clear: - xor a, a - ld [bg_update_index], a - - ; clear all entries - ld hl, bg_update_queue - ld bc, bge_size * BGE_MAX - ld d, a ; d = 0 - jp memset - - ; pushes a new bg update to the queue - ; inputs: - ; b: tile data - ; a: entry flags - ; de: address (unused unless in BGEF_ADDR mode) - ; returns: - ; a == 1: if update was queued - ; a == 0: if queue is full -bg_update_queue_push: - push af - push bc - - ; first calculate address in queue - ld a, [bg_update_index] - cp a, BGE_MAX - jp z, @full - - add a, a - add a, a - ; a * 4 - ld b, 0 - ld c, a ; de = index offset - - ld hl, bg_update_queue - add hl, bc - - pop bc - pop af - - ; write flags - ld [hl+], a - ld a, b - ; write tile data - ld [hl+], a - - ; write address - ld a, e - ld [hl+], a - ld a, d - ld [hl], a - - ; index++ - ld a, [bg_update_index] - inc a - ld [bg_update_index], a - - ld a, 1 - ret -@full: - xor a, a ; queue was full - ret diff --git a/src/wram.s b/src/wram.s index 606445a..16e50f2 100644 --- a/src/wram.s +++ b/src/wram.s @@ -44,12 +44,19 @@ demo_inputs: .adv 2 ; menu cursor can be used by any in-game menu menu_cursor_index: .adv 1 - ; offset into bg_update_queue -bg_update_index: .adv 1 ; current entry -bg_update_queue: .adv bge_size * BGE_MAX - draw_flags: .adv 1 gameplay_flags: .adv 1 + + ; shadow UI is a buffer for drawing the UI + ; this UI is then re-drawn on request in vblank +shadow_ui: .adv UI_TILE_WIDTH * UI_TILE_HEIGHT + +; UI redraw BG address +ui_redraw_bg: .adv 2 +; UI redraw shadow address +ui_redraw_shadow: .adv 2 +; remaining UI redraw steps +ui_redraw_steps: .adv 1 ; dummy oam ; same memory as empty_unit