gbdk-2020 | GameBoy Development Kit |
| download: https://git.y1.nz/archives/gbdk.tar.gz | |
| README | Files | Log | Refs | LICENSE |
commit c023475f7acc50cfb19290b67d30334487b3289f parent 825a20758ac5df0a8651736894c7b3d35d7d33c9 Author: Toxa <56631470+untoxa@users.noreply.github.com> Date: Mon, 17 Jul 2023 23:58:15 +0300 Merge pull request #541 from michel-iwaniec/set_attribute_xy Add support functions for setting an individual map attribute Diffstat:
| M | gbdk-lib/examples/cross-platform/logo/src/main.c | 1 | + |
| M | gbdk-lib/include/gb/gb.h | 17 | +++++++++++++++++ |
| M | gbdk-lib/include/nes/nes.h | 36 | ++++++++++++++++++++++++++++++++++++ |
| M | gbdk-lib/include/sms/sms.h | 11 | +++++++++++ |
| M | gbdk-lib/libc/targets/mos6502/nes/Makefile | 2 | +- |
| M | gbdk-lib/libc/targets/mos6502/nes/crt0.s | 1 | + |
| A | gbdk-lib/libc/targets/mos6502/nes/set_attribute.s | 74 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
| M | gbdk-lib/libc/targets/mos6502/nes/set_bk_attributes.s | 8 | ++++---- |
| M | gbdk-lib/libc/targets/mos6502/nes/set_tile_submap_attributes.s | 4 | ++-- |
| M | gbdk-lib/libc/targets/z80/set_tile.s | 26 | ++++++++++++++++++++++++++ |
10 files changed, 173 insertions(+), 7 deletions(-)
diff --git a/gbdk-lib/examples/cross-platform/logo/src/main.c b/gbdk-lib/examples/cross-platform/logo/src/main.c @@ -25,6 +25,7 @@ void main(void) { GBDK_2020_logo_WIDTH >> 3, GBDK_2020_logo_HEIGHT >> 3, GBDK_2020_logo_map); + wait_vbl_done(); SHOW_BKG; DISPLAY_ON; } diff --git a/gbdk-lib/include/gb/gb.h b/gbdk-lib/include/gb/gb.h @@ -1307,6 +1307,23 @@ uint8_t * set_bkg_tile_xy(uint8_t x, uint8_t y, uint8_t t) OLDCALL PRESERVES_REG #define set_tile_xy set_bkg_tile_xy /** + * Set single attribute data a on background layer at x,y + * @param x X-coordinate + * @param y Y-coordinate + * @param a tile attributes + * @return returns the address of tile attribute, so you may use faster set_vram_byte() later + */ +inline uint8_t * set_bkg_attribute_xy(uint8_t x, uint8_t y, uint8_t a) +{ + uint8_t* addr; + VBK_REG = VBK_ATTRIBUTES; + addr = set_bkg_tile_xy(x, y, a); + VBK_REG = VBK_TILES; + return addr; +} +#define set_attribute_xy set_bkg_attribute_xy + +/** * Get single tile t on background layer at x,y * @param x X-coordinate * @param y Y-coordinate diff --git a/gbdk-lib/include/nes/nes.h b/gbdk-lib/include/nes/nes.h @@ -831,6 +831,33 @@ uint8_t * set_bkg_tile_xy(uint8_t x, uint8_t y, uint8_t t) OLDCALL; #define set_tile_xy set_bkg_tile_xy /** + Set single attribute data a on background layer at x,y + + @param x X-coordinate + @param y Y-coordinate + @param a tile attributes + */ +void set_bkg_attribute_xy_nes16x16(uint8_t x, uint8_t y, uint8_t a); + +/** + Set single attribute data a on background layer at x,y + + Please note that this is just a wrapper function for set_bkg_submap_attributes_nes16x16 + and divides the coordinates and dimensions by 2 to achieve this. + It is intended to make code more portable by using the same coordinate system + that systems with the much more common 8x8 attribute resolution would use. + + @param x X-coordinate + @param y Y-coordinate + @param a tile attributes + */ +inline void set_bkg_attribute_xy(uint8_t x, uint8_t y, uint8_t a) +{ + set_bkg_attribute_xy_nes16x16(x >> 1, y >> 1, a); +} +#define set_attribute_xy set_bkg_attribute_xy + +/** * Get single tile t on background layer at x,y * @param x X-coordinate * @param y Y-coordinate @@ -1153,6 +1180,15 @@ void vmemset (void *s, uint8_t c, size_t n) OLDCALL; void fill_bkg_rect(uint8_t x, uint8_t y, uint8_t w, uint8_t h, uint8_t tile) OLDCALL; #define fill_rect fill_bkg_rect +/** "Flushes" the updates to the shadow attributes so they are written + to the transfer buffer, and then written to PPU memory on next vblank. + + This function must be called to see visible changes to attributes + on the NES target. But it will automatically be called by wait_vbl_done, + so the use-cases for calling it manually are rare in practice. +*/ +void flush_shadow_attributes() OLDCALL; + uint8_t _switch_prg0(uint8_t bank) OLDCALL; #endif /* _NES_H */ diff --git a/gbdk-lib/include/sms/sms.h b/gbdk-lib/include/sms/sms.h @@ -806,6 +806,17 @@ uint8_t * set_tile_xy(uint8_t x, uint8_t y, uint8_t t) Z88DK_CALLEE PRESERVES_RE #define set_win_tile_xy set_tile_xy /** + * Set single attribute data a on background layer at x,y + * @param x X-coordinate + * @param y Y-coordinate + * @param a tile attributes + * @return returns the address of tile attribute, so you may use faster set_vram_byte() later + */ +inline uint8_t * set_attribute_xy(uint8_t x, uint8_t y, uint8_t a) Z88DK_CALLEE PRESERVES_REGS(iyh, iyl); +#define set_bkg_attribute_xy set_attribute_xy +#define set_win_attribute_xy set_attribute_xy + +/** * Get address of X,Y tile of background map */ uint8_t * get_bkg_xy_addr(uint8_t x, uint8_t y) Z88DK_CALLEE PRESERVES_REGS(iyh, iyl); diff --git a/gbdk-lib/libc/targets/mos6502/nes/Makefile b/gbdk-lib/libc/targets/mos6502/nes/Makefile @@ -14,7 +14,7 @@ ASSRC = f_ibm_full.s f_ibm_sh.s f_italic.s f_min.s f_spect.s \ metasprites_hide.s metasprites_hide_spr.s \ vram_transfer_buffer.s \ set_tile.s set_bk_ts.s set_tile_submap.s fill_rect_bk.s \ - set_bk_attributes.s set_tile_submap_attributes.s flush_attributes.s \ + set_attribute.s set_bk_attributes.s set_tile_submap_attributes.s flush_attributes.s \ nes_palettes.s \ pad.s pad_ex.s \ rle_decompress.s \ diff --git a/gbdk-lib/libc/targets/mos6502/nes/crt0.s b/gbdk-lib/libc/targets/mos6502/nes/crt0.s @@ -381,6 +381,7 @@ __crt0_clearVRAM_loop: .wait_vbl_done:: _wait_vbl_done:: _vsync:: + jsr _flush_shadow_attributes jsr .jmp_to_VBL_isr lda *_sys_time _wait_vbl_done_waitForNextFrame_loop: diff --git a/gbdk-lib/libc/targets/mos6502/nes/set_attribute.s b/gbdk-lib/libc/targets/mos6502/nes/set_attribute.s @@ -0,0 +1,74 @@ +.module SetAttributeXY + +.include "global.s" + +.area OSEG (PAG, OVR) +_set_bkg_attribute_xy_nes16x16_PARM_3:: .ds 1 +.x_odd: .ds 1 +.y_odd: .ds 1 +.val: .ds 1 + +.area _HOME + +_set_bkg_attribute_xy_nes16x16:: + lsr + ror *.x_odd + tay + txa + lsr + ror *.y_odd + pha + asl + asl + asl + and #0x38 + ora .identity,y + tay + lda *_set_bkg_attribute_xy_nes16x16_PARM_3 + bit *.y_odd + bpl 1$ + asl + asl + asl + asl +1$: + bit *.x_odd + bpl 2$ + asl + asl +2$: + sta *.val + lda #0 + asl *.y_odd + rol + asl *.x_odd + rol + tax + lda .mask_tab,x + and _attribute_shadow,y + ora *.val + sta _attribute_shadow,y + ; Set dirty bit for row. + ; Assume writing rows, as the potential to optimize column writing is limited anyway. + pla + tay + lda .bitmask_dirty_tab,y + ora *_attribute_row_dirty + sta *_attribute_row_dirty + rts + +.mask_tab: +.db 0b11111100 +.db 0b11110011 +.db 0b11001111 +.db 0b00111111 + +.bitmask_dirty_tab: +.db 0b00000001 +.db 0b00000010 +.db 0b00000100 +.db 0b00001000 +.db 0b00010000 +.db 0b00100000 +.db 0b01000000 +.db 0b10000000 diff --git a/gbdk-lib/libc/targets/mos6502/nes/set_bk_attributes.s b/gbdk-lib/libc/targets/mos6502/nes/set_bk_attributes.s @@ -181,7 +181,7 @@ aligned_xy_column_loop: ; If columns were odd, we have one more byte where only top corner should be modified ALIGNED_XY_RIGHT_EDGE ATTRIBUTE_MASK_TL, ATTRIBUTE_MASK_BL+ATTRIBUTE_MASK_BR+ATTRIBUTE_MASK_TR 1$: - jmp _flush_shadow_attributes + rts ; ; Version for when x is misaligned with attribute byte-grid @@ -268,7 +268,7 @@ unaligned_x_column_loop: ; If columns were odd, we have one more byte where only top-left corner should be modified UNALIGNED_X_RIGHT_EDGE ATTRIBUTE_MASK_TL, ATTRIBUTE_MASK_BL+ATTRIBUTE_MASK_BR+ATTRIBUTE_MASK_TR 5$: - jmp _flush_shadow_attributes + rts ; ; Version for when y is misaligned with attribute byte-grid @@ -366,7 +366,7 @@ unaligned_y_column_loop: ; If columns were odd, we have one more byte where only top-left corner should be modified UNALIGNED_Y_RIGHT_EDGE ATTRIBUTE_MASK_TL, ATTRIBUTE_MASK_BL+ATTRIBUTE_MASK_BR+ATTRIBUTE_MASK_TR 1$: - jmp _flush_shadow_attributes + rts ; ; Version for when x & y are both misaligned with attribute byte-grid @@ -507,7 +507,7 @@ unaligned_xy_column_loop: ; If columns were NOT odd, we have one more byte where only top-left corner should be modified UNALIGNED_XY_RIGHT_EDGE ATTRIBUTE_MASK_TL, ATTRIBUTE_MASK_BL+ATTRIBUTE_MASK_BR+ATTRIBUTE_MASK_TR 1$: - jmp _flush_shadow_attributes + rts .attribute_set_dirty: ; A = min(7, .num_rows + .attribute_num_rows_odd) << 3 diff --git a/gbdk-lib/libc/targets/mos6502/nes/set_tile_submap_attributes.s b/gbdk-lib/libc/targets/mos6502/nes/set_tile_submap_attributes.s @@ -138,7 +138,7 @@ _set_bkg_submap_attributes_horizontalStripes_rowLoop: jsr .inc_row dec *.num_rows bne _set_bkg_submap_attributes_horizontalStripes_rowLoop - jmp _flush_shadow_attributes + rts _set_bkg_submap_attributes_verticalStripes: jsr .inc_height_if_wrap @@ -157,7 +157,7 @@ _set_bkg_submap_attributes_verticalStripes_columnLoop: iny dec *.num_columns bne _set_bkg_submap_attributes_verticalStripes_columnLoop - jmp _flush_shadow_attributes + rts .inc_row: lda *.ypos diff --git a/gbdk-lib/libc/targets/z80/set_tile.s b/gbdk-lib/libc/targets/z80/set_tile.s @@ -68,3 +68,29 @@ _set_tile_xy:: ENABLE_VBLANK_COPY ret + +; uint8_t * set_attribute_xy(uint8_t x, uint8_t y, uint8_t a) __z88dk_callee __preserves_regs(iyh, iyl); +_set_attribute_xy:: + pop hl ; HL = ret + pop de ; DE = YX + dec sp + ex (sp), hl ; HL = data + + ld a, d + + ld bc, #.VDP_TILEMAP + call .coords_to_address + ex de, hl + + ld a, (.vdp_shift) + ADD_A_REG16 h, l + + DISABLE_VBLANK_COPY + WRITE_VDP_CMD_HL + + in a, (.VDP_DATA) ; skip tile index + ld a, d + out (.VDP_DATA), a + + ENABLE_VBLANK_COPY + ret
This webpage is intended to be an accessible preview of this repository. To get a fuller picture, clone it and use the git CLI.