From 74b1003ab8abad2f8220de4f2f18a3b118f23f01 Mon Sep 17 00:00:00 2001 From: Miquel Sabaté Solà Date: Wed, 10 Dec 2025 14:41:35 +0100 Subject: Adapt the code to play well with nasm's asan MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The address sanitizer from nasm provides quite a few goodies, so let's adapt the code more to it to benefit from those. Signed-off-by: Miquel Sabaté Solà --- include/apu.s | 4 ++-- include/globals.s | 10 ++++---- include/joypad.s | 10 ++++---- include/oam.s | 19 ++++++++------- include/ppu.s | 12 +++++----- src/assets.s | 70 +++++++++++++++++++++++++++---------------------------- src/bullets.s | 2 +- src/driver.s | 20 ++++++++-------- src/enemies.s | 2 +- src/jetpac.s | 8 +++---- src/player.s | 68 ++++++++++++++++++++++++++--------------------------- src/title.s | 24 +++++++++---------- src/vectors.s | 40 +++++++++++++++---------------- 13 files changed, 145 insertions(+), 144 deletions(-) diff --git a/include/apu.s b/include/apu.s index 65d9876..bb0319f 100644 --- a/include/apu.s +++ b/include/apu.s @@ -1,4 +1,4 @@ .scope APU - DMC = $4010 - FRAME_COUNTER = $4017 + m_dmc = $4010 + m_frame_counter = $4017 .endscope diff --git a/include/globals.s b/include/globals.s index 842de34..f9777e5 100644 --- a/include/globals.s +++ b/include/globals.s @@ -6,17 +6,17 @@ ;; Argument values reserved passing arguments to functions in memory. zp_arg0 = $00 zp_arg1 = $01 - zp_arg2 = $02 - zp_arg3 = $03 - zp_arg4 = $04 + ;; zp_arg2 = $02 + ;; zp_arg3 = $03 + ;; zp_arg4 = $04 ;;; ;; Random values that can be used inside of functions for temporary values ;; so `zp_argX` variables are not overwritten as often. zp_tmp0 = $05 zp_tmp1 = $06 - zp_tmp2 = $07 - zp_tmp3 = $08 + ;; zp_tmp2 = $07 + ;; zp_tmp3 = $08 ;;; ;; Reserve a byte of memory for preserving indices on memory. This is needed diff --git a/include/joypad.s b/include/joypad.s index 141877f..f7268e8 100644 --- a/include/joypad.s +++ b/include/joypad.s @@ -10,8 +10,8 @@ BUTTON_RIGHT = 1 << 0 ;; Port addresses for controllers. - JOYPAD1 = $4016 - JOYPAD2 = $4017 + m_joypad1 = $4016 + ;; m_joypad2 = $4017 ;; After running a `read_*` function these two variables will contain the ;; given result. @@ -49,14 +49,14 @@ .proc unsafe_read_x ;; Start the latch process. lda #$01 - sta Joypad::JOYPAD1 + sta Joypad::m_joypad1 sta Joypad::zp_buttons1, x ; Bit as a guard for the loop below. lsr - sta Joypad::JOYPAD1 + sta Joypad::m_joypad1 ;; Now the joypad is ready to accept reads. @loop: - lda Joypad::JOYPAD1, x + lda Joypad::m_joypad1, x and #%00000011 ; Ignore bits other than controller. cmp #$01 ; Set carry if and only if nonzero. rol Joypad::zp_buttons1, x ; Carry -> bit 0; bit 7 -> Carry diff --git a/include/oam.s b/include/oam.s index 22935b2..a73494d 100644 --- a/include/oam.s +++ b/include/oam.s @@ -1,11 +1,12 @@ .scope OAM - ADDRESS = $2003 - DMA = $4014 -.endscope + ;; Region in internal RAM where sprites are being allocated for later use in + ;; the DMA process. The entire page is reserved, as there are 64 sprites x 4 + ;; bytes each = 256 bytes in total. + m_sprites = $200 ; asan:reserve $100 + + ;;; + ;; Actual addresses from OAM space. -.macro OAM_WRITE_SPRITES - lda #$00 - sta OAM::ADDR - lda #$02 - sta OAM::DMA -.endmacro + m_address = $2003 + m_dma = $4014 +.endscope diff --git a/include/ppu.s b/include/ppu.s index a9c0ed2..7882809 100644 --- a/include/ppu.s +++ b/include/ppu.s @@ -1,10 +1,10 @@ .scope PPU - CONTROL = $2000 - MASK = $2001 - STATUS = $2002 - SCROLL = $2005 - ADDRESS = $2006 - DATA = $2007 + m_control = $2000 + m_mask = $2001 + m_status = $2002 + m_scroll = $2005 + m_address = $2006 + m_data = $2007 ;; Shadow for the PPU::CONTROL value. Touch this value instead of accessing ;; the PPU register directly. diff --git a/src/assets.s b/src/assets.s index 3d1a6a3..82b6a06 100644 --- a/src/assets.s +++ b/src/assets.s @@ -24,7 +24,7 @@ lda #.hibyte(main_screen) sta Globals::zp_arg1 ldx #$28 - jsr load_screen_x + jsr load_screen_x ;; TODO: jal rts .endproc @@ -33,17 +33,17 @@ ;; Globals::zp_arg{0,1}. Set the `x` register to the high byte of the ;; nametable to be used. .proc load_screen_x - bit PPU::STATUS + bit PPU::m_status - stx PPU::ADDRESS + stx PPU::m_address lda #$00 - sta PPU::ADDRESS + sta PPU::m_address ldy #0 ldx #4 @loop: lda (Globals::zp_arg0), y - sta PPU::DATA + sta PPU::m_data iny bne @loop @@ -60,44 +60,44 @@ ;; Performs all the needed tricks in order to get the first nametable as ;; expected. .proc prepare_for_title_screen - bit PPU::STATUS + bit PPU::m_status lda #$23 - sta $2006 + sta PPU::m_address lda #$C8 - sta $2006 + sta PPU::m_address ldx #$10 @upper_title_bar_loop: lda #%10101010 - sta $2007 + sta PPU::m_data dex bne @upper_title_bar_loop ;; Update 2nd palette for background. This is redundant upon entering ;; the game, but it makes sense after a game over. lda #$3F - sta PPU::ADDRESS + sta PPU::m_address lda #$09 - sta PPU::ADDRESS + sta PPU::m_address lda #$28 - sta PPU::DATA + sta PPU::m_data lda #$2C - sta PPU::DATA + sta PPU::m_data lda #$16 - sta PPU::DATA + sta PPU::m_data ;; Update 1st palette for foreground. lda #$3F - sta PPU::ADDRESS + sta PPU::m_address lda #$11 - sta PPU::ADDRESS + sta PPU::m_address lda #$30 - sta PPU::DATA + sta PPU::m_data lda #$10 - sta PPU::DATA + sta PPU::m_data lda #$30 - sta PPU::DATA + sta PPU::m_data rts .endproc @@ -105,31 +105,31 @@ ;; Performs all the needed tricks in order to get the second nametable as ;; expected. .proc prepare_for_main_screen - bit PPU::STATUS + bit PPU::m_status ;; Update 2nd palette for background. lda #$3F - sta PPU::ADDRESS + sta PPU::m_address lda #$09 - sta PPU::ADDRESS + sta PPU::m_address lda #$14 - sta PPU::DATA + sta PPU::m_data lda #$2C - sta PPU::DATA + sta PPU::m_data lda #$28 - sta PPU::DATA + sta PPU::m_data ;; Update 1st palette for foreground. lda #$3F - sta PPU::ADDRESS + sta PPU::m_address lda #$11 - sta PPU::ADDRESS + sta PPU::m_address lda #$16 - sta PPU::DATA + sta PPU::m_data lda #$10 - sta PPU::DATA + sta PPU::m_data lda #$30 - sta PPU::DATA + sta PPU::m_data rts .endproc @@ -137,14 +137,14 @@ ;; Copies all the palettes for our game into the proper PPU address. .proc init_palettes lda #$3F - sta PPU::ADDRESS + sta PPU::m_address lda #$00 - sta PPU::ADDRESS + sta PPU::m_address ldx #0 @load_palettes_loop: lda palettes, x - sta PPU::DATA + sta PPU::m_data inx cpx #$20 bne @load_palettes_loop @@ -177,9 +177,9 @@ ;; simple game, I have so much space left in the cartridge that I can go ;; bananas with it. This helps out loading the screen as we can go faster ;; and it is less error prone. - title_screen: + title_screen: .incbin "../assets/title.nam" - main_screen: + main_screen: .incbin "../assets/main.nam" .endscope diff --git a/src/bullets.s b/src/bullets.s index db8bfd7..0f31d0c 100644 --- a/src/bullets.s +++ b/src/bullets.s @@ -18,7 +18,7 @@ ;; bullet. ;; 2. Y coordinate. ;; 3. X coordinate. - zp_bullets_pool_base = $A0 + zp_bullets_pool_base = $A0 ; asan:reserve $1E ;; The current amount of bullets on screen. zp_bullets_pool_size = $E0 diff --git a/src/driver.s b/src/driver.s index 3ed0536..149eaa7 100644 --- a/src/driver.s +++ b/src/driver.s @@ -6,7 +6,7 @@ ;; ;; NOTE: this memory address is shared with `zp_title_timer`, as they can ;; never conflict with each other. - zp_player_timer = $30 + zp_player_timer = $30 ; asan:ignore PLAYER_TIMER_VALUE = HZ * 2 .ifdef PAL @@ -165,7 +165,7 @@ ;; It is a valid bullet! Set it now. lda Bullets::zp_bullets_pool_base + 1, x - sta $200, y + sta OAM::m_sprites, y iny ;; The tile selection depends on how many moves the bullet has done. @@ -183,14 +183,14 @@ @last_bullet_tile: lda #$1E @set_bullet_tile: - sta $200, y + sta OAM::m_sprites, y iny lda #0 - sta $200, y + sta OAM::m_sprites, y iny lda Bullets::zp_bullets_pool_base + 2, x - sta $200, y + sta OAM::m_sprites, y iny @after_first_bullet: @@ -238,7 +238,7 @@ beq @next_bullet lda Bullets::zp_bullets_pool_base + 1, x - sta $200, y + sta OAM::m_sprites, y iny ;; The tile selection depends on how many moves the bullet has done. @@ -256,14 +256,14 @@ @other_last_bullet_tile: lda #$1E @other_set_bullet_tile: - sta $200, y + sta OAM::m_sprites, y iny lda #0 - sta $200, y + sta OAM::m_sprites, y iny lda Bullets::zp_bullets_pool_base + 2, x - sta $200, y + sta OAM::m_sprites, y iny @next_bullet: @@ -287,7 +287,7 @@ ;; need for the 'y' register to wrap around in order to quit. lda #$EF @reset_sprite: - sta $200, y + sta OAM::m_sprites, y iny iny iny diff --git a/src/enemies.s b/src/enemies.s index 377a9a5..dbd0e08 100644 --- a/src/enemies.s +++ b/src/enemies.s @@ -10,7 +10,7 @@ ENEMIES_INITIAL_X = $F0 ;; TODO: 3 bytes a la bullets - zp_enemies_pool_base = $60 + zp_enemies_pool_base = $60 ; asan:reserve $09 zp_enemies_timer = $D0 zp_enemies_pool_size = $D1 diff --git a/src/jetpac.s b/src/jetpac.s index 6708ed3..6e74d53 100644 --- a/src/jetpac.s +++ b/src/jetpac.s @@ -50,7 +50,7 @@ .proc main ;; Disable the PPU and zero out variables which shadow PPU registers. lda #0 - sta PPU::MASK + sta PPU::m_mask sta PPU::zp_mask sta PPU::zp_control @@ -89,13 +89,13 @@ jsr Driver::switch lda PPU::zp_control - sta PPU::CONTROL + sta PPU::m_control .else jsr Title::init lda #%10001000 sta PPU::zp_control - sta PPU::CONTROL + sta PPU::m_control .endif cli @@ -103,7 +103,7 @@ ;; Enable back the PPU lda #%00011110 sta PPU::zp_mask - sta PPU::MASK + sta PPU::m_mask @main_game_loop: READ_JOYPAD1 diff --git a/src/player.s b/src/player.s index c7b65af..2a87b85 100644 --- a/src/player.s +++ b/src/player.s @@ -7,9 +7,9 @@ .macro FIXED_POINT_POSITION_TO_SCREEN POS_ADDR ;; We save the high byte into a temporary value, and we load the low byte ;; into the accumulator. - lda POS_ADDR + 1 + lda POS_ADDR + 1 ; asan:ignore sta Globals::zp_tmp0 - lda POS_ADDR + lda POS_ADDR ; asan:ignore ;; And now it's a matter of rotating the high byte into the low one to ;; match a full byte. @@ -73,12 +73,12 @@ .include "../config/values/player.s" zp_screen_y = $40 - zp_position_y = $41 ; NOTE: 16-bit. + zp_position_y = $41 ; asan:reserve $02 zp_target_velocity_y = $43 ; TODO: needed? zp_velocity_y = $44 zp_screen_x = $45 - zp_position_x = $46 ; NOTE: 16-bit. + zp_position_x = $46 ; asan:reserve $02 zp_target_velocity_x = $48 ; TODO: needed? zp_velocity_x = $49 @@ -760,40 +760,40 @@ bvs @right lda #$01 - sta $201 + sta OAM::m_sprites + $01 lda #$00 - sta $205 + sta OAM::m_sprites + $05 lda #$11 - sta $209 + sta OAM::m_sprites + $09 lda #$10 - sta $20D - stx $211 - sty $215 + sta OAM::m_sprites + $0D + stx OAM::m_sprites + $11 + sty OAM::m_sprites + $15 ldx #%01000000 bne @set_attributes @right: lda #$00 - sta $201 + sta OAM::m_sprites + $01 lda #$01 - sta $205 + sta OAM::m_sprites + $05 lda #$10 - sta $209 + sta OAM::m_sprites + $09 lda #$11 - sta $20D - stx $215 - sty $211 + sta OAM::m_sprites + $0D + stx OAM::m_sprites + $15 + sty OAM::m_sprites + $11 ldx #$00 ;; The `x` register contains the tile attributes. @set_attributes: - stx $202 - stx $206 - stx $20A - stx $20E - stx $212 - stx $216 + stx OAM::m_sprites + $02 + stx OAM::m_sprites + $06 + stx OAM::m_sprites + $0A + stx OAM::m_sprites + $0E + stx OAM::m_sprites + $12 + stx OAM::m_sprites + $16 rts .endproc @@ -802,27 +802,27 @@ .proc update_sprites_coordinates ;; Y axis. lda zp_screen_y - sta $0200 - sta $0204 + sta OAM::m_sprites + sta OAM::m_sprites + $04 clc adc #8 - sta $0208 - sta $020C + sta OAM::m_sprites + $08 + sta OAM::m_sprites + $0C clc adc #8 - sta $0210 - sta $0214 + sta OAM::m_sprites + $10 + sta OAM::m_sprites + $14 ;; X axis. lda zp_screen_x - sta $0203 - sta $020B - sta $0213 + sta OAM::m_sprites + $03 + sta OAM::m_sprites + $0B + sta OAM::m_sprites + $13 clc adc #8 - sta $0207 - sta $020F - sta $0217 + sta OAM::m_sprites + $07 + sta OAM::m_sprites + $0F + sta OAM::m_sprites + $17 rts .endproc diff --git a/src/title.s b/src/title.s index 01d58f5..e3a2086 100644 --- a/src/title.s +++ b/src/title.s @@ -18,13 +18,13 @@ ;; Initialize the sprite that guides the player on the menu. lda #SPRITE_Y_POSITION0 - sta $200 + sta OAM::m_sprites lda #$30 - sta $201 + sta OAM::m_sprites + 1 lda #$00 - sta $202 + sta OAM::m_sprites + 2 lda #SPRITE_X_POSITION - sta $203 + sta OAM::m_sprites + 3 rts .endproc @@ -42,9 +42,9 @@ beq @check_down lda #SPRITE_Y_POSITION0 - cmp $200 + cmp OAM::m_sprites beq @end - sta $200 + sta OAM::m_sprites jmp @set_timer_and_end @check_down: @@ -53,9 +53,9 @@ beq @check_select lda #SPRITE_Y_POSITION1 - cmp $200 + cmp OAM::m_sprites beq @end - sta $200 + sta OAM::m_sprites jmp @set_timer_and_end @check_select: @@ -72,14 +72,14 @@ @do_select: lda #SPRITE_Y_POSITION0 - cmp $200 + cmp OAM::m_sprites beq @down - sta $200 + sta OAM::m_sprites bne @set_timer_and_end @down: lda #SPRITE_Y_POSITION1 - sta $200 + sta OAM::m_sprites @set_timer_and_end: lda #TIMER_INIT_VALUE @@ -94,7 +94,7 @@ .proc start ;; Hide the sprite from the menu. lda #$EF - sta $200 + sta OAM::m_sprites lda #1 rts diff --git a/src/vectors.s b/src/vectors.s index af343a7..e5d1a58 100644 --- a/src/vectors.s +++ b/src/vectors.s @@ -5,8 +5,8 @@ ;; Debug utilities. .scope Debug - ;; Counter for frame drops. - zp_frame_drops = $90 + ;; Counter for frame drops. Only touched when PARTIAL is defined. + zp_frame_drops = $90 ; asan:ignore .endscope ;; Pretty standard reset function, nothing crazy. @@ -17,7 +17,7 @@ ;; Disable APU frame counter. ldx #$40 - stx APU::FRAME_COUNTER + stx APU::m_frame_counter ;; Setup the stack. ldx #$FF @@ -25,14 +25,14 @@ ;; Disable NMIs and the APU's DMC. inx - stx PPU::CONTROL - stx PPU::MASK - stx APU::DMC + stx PPU::m_control + stx PPU::m_mask + stx APU::m_dmc ;; First PPU wait. - bit PPU::STATUS + bit PPU::m_status @vblankwait1: - bit PPU::STATUS + bit PPU::m_status bpl @vblankwait1 ;; Initialize the counter for frame drops before any NMIs can come in. @@ -45,7 +45,7 @@ lda #$EF ldx #0 @sprite_reset_loop: - sta $200, x + sta OAM::m_sprites, x inx inx inx @@ -54,13 +54,13 @@ ;; DMA setup for sprite reset. lda #$00 - sta OAM::ADDRESS + sta OAM::m_address lda #$02 - sta OAM::DMA + sta OAM::m_dma ;; Second PPU wait. After that the PPU is stable. @vblankwait2: - bit PPU::STATUS + bit PPU::m_status bpl @vblankwait2 ;; NOTE: palettes are not initialized here as it's going to be one of the @@ -89,9 +89,9 @@ ;; Sprite DMA. lda #$00 - sta OAM::ADDRESS + sta OAM::m_address lda #$02 - sta OAM::DMA + sta OAM::m_dma ;; Are we paused? If so skip timers, PAL handler and the likes. lda #%00001000 @@ -126,20 +126,20 @@ and Globals::zp_flags sta Globals::zp_flags - bit PPU::STATUS + bit PPU::m_status ;; Update the PPU control/mask registers with shadowed values. lda PPU::zp_mask - sta PPU::MASK + sta PPU::m_mask lda PPU::zp_control - sta PPU::CONTROL + sta PPU::m_control @scroll: ;; Always reset the scroll just in case. - bit PPU::STATUS + bit PPU::m_status lda #$00 - sta PPU::SCROLL - sta PPU::SCROLL + sta PPU::m_scroll + sta PPU::m_scroll ;; Unblock the main code. lda #%01111111 -- cgit v1.2.3