diff options
| -rw-r--r-- | .nasm/segments.txt | 2 | ||||
| -rw-r--r-- | src/driver.s | 28 | ||||
| -rw-r--r-- | src/items.s | 207 | ||||
| -rw-r--r-- | src/jetpac.s | 2 | ||||
| -rw-r--r-- | src/player.s | 5 |
5 files changed, 138 insertions, 106 deletions
diff --git a/.nasm/segments.txt b/.nasm/segments.txt index bfc83f3..7d74792 100644 --- a/.nasm/segments.txt +++ b/.nasm/segments.txt @@ -1,4 +1,4 @@ - HEADER: 16/16 (100%) -- ROM0: 8003/32762 (24.43%) +- ROM0: 8030/32762 (24.51%) - ROMV: 6/6 (100%) - ROM2: 8192/8192 (100%) diff --git a/src/driver.s b/src/driver.s index 448efa2..f747c4b 100644 --- a/src/driver.s +++ b/src/driver.s @@ -161,15 +161,6 @@ dey bne @bullets_reset_loop - ;; Invalidate all items. - ldx #0 - ldy #Items::POOL_CAPACITY - @items_reset_loop: - sta Items::zp_pool_base, x - NEXT_ITEM_INDEX_X - dey - bne @items_reset_loop - ;; Set that we have done this operation so it's not done in future ;; cycles. lda Driver::zp_flags @@ -324,7 +315,12 @@ lda Explosions::zp_active bne @sprite_cycling - ;; After all the explosions have been done, is any player alive? + ;; Are there still falling items? + lda Items::zp_state + and #$03 + bne @sprite_cycling + + ;; After all the explosions/items have been done, is any player alive? lda Globals::zp_multiplayer and #%00000110 bne @reset_timer @@ -335,6 +331,18 @@ ora #%00000010 sta Globals::zp_flags + ;; Invalidate items, which were skipped on move_sprites_out() on purpose + ;; to keep them after each death. But since we are about to go to the + ;; title screen, now they are no longer useful. + lda #$FF + ldx #0 + ldy #Items::POOL_CAPACITY + @items_reset_loop: + sta Items::zp_pool_base, x + NEXT_ITEM_INDEX_X + dey + bne @items_reset_loop + @reset_timer: ;; Reset the player's timer to enter the game screen again. lda #PLAYER_TIMER_VALUE diff --git a/src/items.s b/src/items.s index 756da2b..e1ebed6 100644 --- a/src/items.s +++ b/src/items.s @@ -10,6 +10,13 @@ .endmacro .scope Items + ;;; + ;; Shadowed variables from the Player scope. This is mainly to be + ;; compatible with cl65. + zp_player_screen_y = $40 ; asan:ignore + zp_player_screen_x = $45 ; asan:ignore + PLAYER_WAIST = $0C + ;; Maximum amount of items allowed on screen at the same time. POOL_CAPACITY = 3 @@ -43,13 +50,12 @@ ;; ;; TODO: stabilize and document. ;; - ;; |GNS- FFAA| + ;; |GNS- --FF| ;; | ;; |- G: the player is grabbing an item ;; |- N: a fuel tank is needed. ;; |- S: there is a fuel tank on screen. (TODO: needed?) ;; |- F: number of falling items. - ;; |- A: number of active items. zp_state = $CA ;; Number of shuttle parts (or fuel tanks) that have been collected so far. @@ -85,11 +91,12 @@ ;; deaths. Hence, they will only be re-initialized on either after a game ;; over, or switching to a new level. .proc init_level + ldx #0 + lda Globals::zp_level_kind bne @other_screens - ;; We are going to allocate two shuttle parts, and hence two items. - lda #2 + lda #0 sta Items::zp_state ;; We haven't collected anything yet, but it's convenient for us to mock @@ -98,51 +105,10 @@ lda #1 sta Items::zp_collected - rts - - @other_screens: - ;; Fuel tanks are needed, that's all. - lda #%01000000 - sta Items::zp_state - - ;; Shuttle parts are counted as "collected". This makes the - ;; implementation on other parts easier. - lda #3 - sta Items::zp_collected - - rts - .endproc - - ;; Initialize which sprites are to appear when initializing the screen. - ;; - ;; NOTE: this should _only_ be called whenever we initialize the - ;; screen. This happens either when switching to it for the first time, but - ;; also after a death. That is, unlike Items::init_level() things here are - ;; reset for good. - .proc init - ;; Initialize the timer. - lda #ITEM_TIMER_LO - sta Items::zp_timer - lda #ITEM_TIMER_HI - sta Items::zp_timer + 1 - - ;; State of the top part of the shuttle. - ldx #0 - ldy #0 - sty Items::zp_pool_base, x - - ;; Has the top shuttle part been collected yet? If not we will allocate - ;; the first slot for it. - lda Items::zp_collected - cmp #3 - bcc @set_top_shuttle - - ;; Invalidate the first slot, as it should not be allocated yet. - lda #$FF + ;; State for the top part of the shuttle. + lda #0 sta Items::zp_pool_base, x - bne @mid_shuttle - @set_top_shuttle: ;; Screen and tile coordinates for the top part of the shuttle. lda #$4F sta Items::zp_pool_base + 1, x @@ -161,19 +127,6 @@ lda #0 sta Items::zp_current_tiles + 2, x - @mid_shuttle: - ;; Has the mid shuttle part been collected yet? If not we will allocate - ;; the second slot for it. - lda Items::zp_collected - cmp #2 - bcc @set_mid_shuttle - - ;; Invalidate the second slot, as it should not be allocated yet. - lda #$FF - sta Items::zp_pool_base + 3, x - bne @invalidate_third - - @set_mid_shuttle: ;; State of the middle part of the shuttle. lda #1 sta Items::zp_pool_base + 3, x @@ -196,10 +149,43 @@ lda #0 sta Items::zp_current_tiles + 6, x + beq @invalidate_third + + @other_screens: + ;; Fuel tanks are needed, that's all. + lda #%01000000 + sta Items::zp_state + + ;; Shuttle parts are counted as "collected". This makes the + ;; implementation on other parts easier. + lda #3 + sta Items::zp_collected + + ;; Invalidate the first and the second slots. + lda #$FF + sta Items::zp_pool_base, x + sta Items::zp_pool_base + 3, x + @invalidate_third: - ;; Always invalidte the third item. - ldy #$FF - sty Items::zp_pool_base + 6, x + ;; Always invalidate the third item. + lda #$FF + sta Items::zp_pool_base + 6, x + + rts + .endproc + + ;; Initialize a fresh screen. + ;; + ;; NOTE: this should _only_ be called whenever we initialize the + ;; screen. This happens either when switching to it for the first time, but + ;; also after a death. That is, unlike Items::init_level() things here are + ;; reset for good. + .proc init + ;; Initialize the timer. + lda #ITEM_TIMER_LO + sta Items::zp_timer + lda #ITEM_TIMER_HI + sta Items::zp_timer + 1 rts .endproc @@ -353,14 +339,14 @@ ;; can be used for collision checking. Note that we are targetting for ;; the center of the player, which feels at a fair point for item ;; interactions. - lda Player::zp_screen_y + lda zp_player_screen_y clc - adc #Player::PLAYER_WAIST + adc #PLAYER_WAIST lsr lsr lsr sta Globals::zp_arg0 - lda Player::zp_screen_x + lda zp_player_screen_x lsr lsr lsr @@ -396,11 +382,11 @@ ;; Follow the player. ;; Neither of the above. Then, just follow the player. - lda Player::zp_screen_y + lda zp_player_screen_y clc adc #8 sta Items::zp_pool_base + 1, x - lda Player::zp_screen_x + lda zp_player_screen_x sta Items::zp_pool_base + 2, x ;; Are we at the zone where we must drop items? @@ -421,9 +407,8 @@ ;; Unset the 'grabbing' bit and increase the number of falling items. lda Items::zp_state and #$7F - clc - adc #$04 sta Items::zp_state + inc Items::zp_state ;; And we force the item to be on the exact X screen position so to ;; adjust from the player's subpixel movement. @@ -485,9 +470,7 @@ ;; Now we unset the 'S' bit, which is unconditionally true regardless of ;; the collection state. That being said, if we still need to collect ;; more fuel tanks (the rocket has all its parts and we have not filled - ;; it with all tanks), then we set the 'N' bit. As a cherry on top, we - ;; take advantge of these operations to also decrease the number of - ;; falling/active items. + ;; it with all tanks), then we set the 'N' bit. lda Items::zp_state ldy Items::zp_collected cpy #3 @@ -497,10 +480,11 @@ ora #$40 @set_new_state: and #%11011111 - sec - sbc #$05 ; NOTE: $04 (falling) + $01 (active) sta Items::zp_state + ;; Decrease the number of falling items. + dec Items::zp_state + ;; Save the index of this free slot. stx Globals::zp_arg3 @@ -516,8 +500,11 @@ ;; Collision checks. @check_collision: - ;; Check collision with the player. Otherwise let's check for background - ;; collision. + ;; Check collision with the player if it's alive. Otherwise let's check + ;; for background collision. + lda Globals::zp_flags + and #$10 + bne @background jsr Items::collides_with_player beq @background @@ -560,12 +547,7 @@ bit Globals::zp_tmp0 bvc @set_modes and #%10111111 - tay - lda Items::zp_state - sec - sbc #$04 - sta Items::zp_state - tya + dec Items::zp_state @set_modes: sta Items::zp_pool_base, x @@ -608,10 +590,7 @@ sta Items::zp_pool_base, x ;; And we need to decrease the number of falling items. - lda Items::zp_state - sec - sbc #$04 - sta Items::zp_state + dec Items::zp_state @preserve_and_next: ldx Items::zp_pool_index @@ -721,11 +700,8 @@ ldx Items::zp_pool_index sta Items::zp_current_tiles + 2, x - ;; Update the state to reflect a new active & falling item. - lda Items::zp_state - clc - adc #5 ; NOTE: #4: falling; #1: active - sta Items::zp_state + ;; Update the state to reflect a new falling item. + inc Items::zp_state rts @@ -773,12 +749,59 @@ rts .endproc + ;; Let go the item from the player if there is one being grabbed. + .proc let_go_on_death + ;; First of all, we need do check if the player was actually holding an + ;; item. + ldx #0 + ldy #Items::POOL_CAPACITY + + @loop: + lda Items::zp_pool_base, x + cmp #$FF + beq @next + and #$80 + bne @found + + @next: + NEXT_ITEM_INDEX_X + dey + bne @loop + rts + + @found: + ;; The player was indeed grabbing an item. Then unset the P flag and set + ;; the F one. + lda Items::zp_pool_base, x + and #$7F + ora #$40 + sta Items::zp_pool_base, x + ;; TODO: what if it died while on the ground + + ;; Unset the 'grabbing' bit, and increase the number of falling items. + lda Items::zp_state + and #$7F + sta Items::zp_state + inc Items::zp_state + + rts + .endproc + ;; Collect an item as indexed by 'zp_pool_index'. This function assumes that ;; the item is already valid. ;; ;; NOTE: the 'y' register is preserved. .proc collect ldx Items::zp_pool_index + + ;; If the collected item was actually falling down, decrease the number + ;; of falling items. + lda Items::zp_pool_base, x + and #$40 + beq @invalidate + dec Items::zp_state + + @invalidate: lda #$FF sta Items::zp_pool_base, x diff --git a/src/jetpac.s b/src/jetpac.s index d2ed90b..2d397ac 100644 --- a/src/jetpac.s +++ b/src/jetpac.s @@ -42,10 +42,10 @@ .include "background.s" .include "prng.s" .include "explosions.s" +.include "items.s" .include "player.s" .include "enemies.s" .include "bullets.s" -.include "items.s" .include "title.s" .include "over.s" .include "driver.s" diff --git a/src/player.s b/src/player.s index 48b0bb0..fa649c6 100644 --- a/src/player.s +++ b/src/player.s @@ -834,6 +834,9 @@ ;; That's just german for "the Bart, the". .proc die_bart_die + ;; If the player was grabbing an item when it happened, let go of it. + jsr Items::let_go_on_death + ;; Decrement the life. lda Globals::zp_multiplayer and #$01 @@ -841,8 +844,6 @@ dec Player::zp_lifes, x bne @nmi_update - ;; TODO: if it was grabbing an item, turn it into 'falling' state. - ;; If this poor guy is over, then mark it in the multiplayer bitmap. cpx #0 bne @player_2_over |
