diff options
| author | Miquel Sabaté Solà <mssola@mssola.com> | 2026-03-05 18:47:08 +0100 |
|---|---|---|
| committer | Miquel Sabaté Solà <mssola@mssola.com> | 2026-03-05 18:47:08 +0100 |
| commit | 11847f52aed5bda1966b7d28e009430dc58d2561 (patch) | |
| tree | 49012edd92bcf40add6b784c3aa66ac1ae1a9bf3 /src/over.s | |
| parent | dbcbd43287a28bf087e20e660edd5ba40b5c27ec (diff) | |
| download | jetpac.nes-11847f52aed5bda1966b7d28e009430dc58d2561.tar.gz jetpac.nes-11847f52aed5bda1966b7d28e009430dc58d2561.zip | |
Add the Game Over screen
This is still missing the support for player 2, but I've left traces
about it.
Signed-off-by: Miquel Sabaté Solà <mssola@mssola.com>
Diffstat (limited to 'src/over.s')
| -rw-r--r-- | src/over.s | 196 |
1 files changed, 196 insertions, 0 deletions
diff --git a/src/over.s b/src/over.s new file mode 100644 index 0000000..a2a0f9f --- /dev/null +++ b/src/over.s @@ -0,0 +1,196 @@ +.segment "CODE" + +.scope Over + ;; Has the "Game over" screen been displayed yet? + zp_displayed = $10 + + ;; Timer set whenever the "Game over" screen has been displayed. Whenever it + ;; times out, then the player is redirected to the title screen. + zp_timer = $11 + + ;; Amount of time the player has to wait for the title screen to appear + ;; again. + TIMER_VALUE = HZ * 3 + + ;; Initialize all variables for the "Game over" screens. + .proc init + lda #0 + sta Over::zp_displayed + sta Over::zp_timer + + rts + .endproc + + ;; Handle a "Game over" screen. It has two phases: + ;; 1. Render a "Game over" message. + ;; 2. Wait for a timer to time out. + ;; It will set 1 to the 'a' register if the timer has run out, signaling + ;; that the game can start over. Otherwise it sets 0 to the 'a' register. + .proc handle + ldy #0 + + ;; Has the "Game over" screen been displayed? If not do it now. + lda Over::zp_displayed + bne @do_handle + jsr Over::render + jmp @end + + @do_handle: + lda Over::zp_timer + bne @dec_timer + iny + beq @end + @dec_timer: + dec Over::zp_timer + + @end: + tya + rts + .endproc + + ;; Render the "Game over" message to the screen. This is done in two + ;; phases. We first ensure to disable the PPU, and in the second phase we do + ;; the actual writing. + .proc render + ;; Is PPU disabled? If it is then jump into rendering the screen + ;; directly. + lda PPU::zp_mask + beq @do_render + + ;; Nope! Force the PPU to be disabled and quit. + lda Globals::zp_flags + ora #%01000000 + sta Globals::zp_flags + lda #$00 + sta PPU::zp_mask + rts + + @do_render: + jsr Over::clear_out_screen + ;; TODO: coin game over. + jsr Over::render_regular_game_over + + ;; Enable back the PPU (only background). + lda #%00001110 + sta PPU::zp_mask + + ;; Update PPU registers. + lda #%01000000 + ora Globals::zp_flags + sta Globals::zp_flags + + ;; Set the "Game over" message as displayed and fire up the timer. + lda #1 + sta Over::zp_displayed + lda #Over::TIMER_VALUE + sta Over::zp_timer + + rts + .endproc + + ;; Remove all platforms and the ground. + .proc clear_out_screen + ;; Remove left platform. + bit PPU::m_status + ldx #$29 + stx PPU::m_address + ldx #$83 + stx PPU::m_address + lda #$00 + sta PPU::m_data + sta PPU::m_data + sta PPU::m_data + sta PPU::m_data + sta PPU::m_data + sta PPU::m_data + sta PPU::m_data + + ;; Remove center platform. + bit PPU::m_status + ldx #$29 + stx PPU::m_address + ldx #$EF + stx PPU::m_address + sta PPU::m_data + sta PPU::m_data + sta PPU::m_data + sta PPU::m_data + sta PPU::m_data + + ;; Remove right platform. + bit PPU::m_status + ldx #$29 + stx PPU::m_address + ldx #$38 + stx PPU::m_address + sta PPU::m_data + sta PPU::m_data + sta PPU::m_data + sta PPU::m_data + sta PPU::m_data + sta PPU::m_data + sta PPU::m_data + + ;; Ground + bit PPU::m_status + ldx #$2B + stx PPU::m_address + ldx #$20 + stx PPU::m_address + + ldx #$20 + @clear_ground_loop: + sta PPU::m_data + dex + bne @clear_ground_loop + + rts + .endproc + + ;; Render the regular "Game over player X" screen. + ;; + ;; TODO: multiplayer support. + .proc render_regular_game_over + ;; Set the position. + bit PPU::m_status + ldx #$29 + stx PPU::m_address + ldx #$67 + stx PPU::m_address + + ;; And just iterate over the "message" until we reach the end of string + ;; $FF character. + ldx #0 + @message_loop: + lda message, x + cmp #$FF + beq @out + sta PPU::m_data + inx + bne @message_loop + + @out: + ;; Reset attributes for the end of the message. + bit PPU::m_status + ldx #$2B + stx PPU::m_address + ldx #$D5 + stx PPU::m_address + lda #0 + sta PPU::m_data + sta PPU::m_data + sta PPU::m_data + + rts + + message: + ;; "GAME " + .byte $21, $1B, $27, $1F, $00 + ;; "OVER " + .byte $29, $30, $1F, $2C, $00 + ;; "PLAYER " + .byte $2A, $26, $1B, $33, $1F, $2C, $00 + ;; "1" + .byte $11, $FF + .endproc +.endscope |
