aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMiquel Sabaté Solà <mssola@mssola.com>2026-03-25 01:03:17 +0100
committerMiquel Sabaté Solà <mssola@mssola.com>2026-03-25 01:03:17 +0100
commitccf320971efe9b11f7b7722b2ee2642a10303203 (patch)
tree9ad50e8ffda2194256a9945de0af44a6fad119a2
parentfcc4a0c30ee01719451596d579abf4cbe1e9b8a1 (diff)
downloadjetpac.nes-ccf320971efe9b11f7b7722b2ee2642a10303203.tar.gz
jetpac.nes-ccf320971efe9b11f7b7722b2ee2642a10303203.zip
Add support for adding scores
Signed-off-by: Miquel Sabaté Solà <mssola@mssola.com>
-rw-r--r--.nasm/memory.txt4
-rw-r--r--.nasm/segments.txt2
-rw-r--r--src/jetpac.s14
-rw-r--r--src/score.s159
4 files changed, 176 insertions, 3 deletions
diff --git a/.nasm/memory.txt b/.nasm/memory.txt
index 397a90b..7a2ccaa 100644
--- a/.nasm/memory.txt
+++ b/.nasm/memory.txt
@@ -68,6 +68,8 @@ $E3: zp_current_bullet_x
$E7-$EF: zp_current_tiles
$F0-$FF: zp_current_tiles
$0200-$02FF: m_sprites
+$0300-$030B: m_players
+$030C-$0311: m_hi
$2000: m_control
$2001: m_mask
$2002: m_status
@@ -81,4 +83,4 @@ $4016: m_joypad
$4017: m_frame_counter
--- Summary (in bytes) ---
-- Internal RAM: 419/2048 (20.46%)
+- Internal RAM: 437/2048 (21.34%)
diff --git a/.nasm/segments.txt b/.nasm/segments.txt
index c2666b1..486c2fa 100644
--- a/.nasm/segments.txt
+++ b/.nasm/segments.txt
@@ -1,4 +1,4 @@
- HEADER: 16/16 (100%)
-- ROM0: 8716/32762 (26.60%)
+- ROM0: 8864/32762 (27.06%)
- ROMV: 6/6 (100%)
- ROM2: 8192/8192 (100%)
diff --git a/src/jetpac.s b/src/jetpac.s
index 3cf8f0a..b356192 100644
--- a/src/jetpac.s
+++ b/src/jetpac.s
@@ -42,6 +42,7 @@
.include "background.s"
.include "prng.s"
.include "explosions.s"
+.include "score.s"
.include "items.s"
.include "player.s"
.include "enemies.s"
@@ -112,7 +113,14 @@
.endproc
.proc main
- ;; TODO: high score initialization has to happen here.
+ ;; Initialize the high score.
+ lda #0
+ sta Score::m_hi
+ sta Score::m_hi + 1
+ sta Score::m_hi + 2
+ sta Score::m_hi + 3
+ sta Score::m_hi + 4
+ sta Score::m_hi + 5
@init:
;; Disable the PPU and zero out variables which shadow PPU registers.
@@ -156,6 +164,10 @@
;; Initialize some variables from the "Game Over" side of the game.
jsr Over::init
+ ;; Initialize the score for both players. Note that initializing the high
+ ;; score is the first thing we do in main().
+ jsr Score::init_players_scores
+
;; Initialize variables from the game's driver that need to be set before
;; NMIs start ticking.
jsr Driver::init_before_nmi
diff --git a/src/score.s b/src/score.s
new file mode 100644
index 0000000..ed36283
--- /dev/null
+++ b/src/score.s
@@ -0,0 +1,159 @@
+;; Clear the carry and add ADDR to the indexed digit on 'Score::m_players'. If
+;; the result is larger or equal than 10, then 0 is stored and the carry flag is
+;; set. Otherwise the carry flag is cleared.
+.macro BCD_ADD ADDR
+ lda Score::m_players, x
+ clc
+ adc ADDR
+ cmp #10
+ bcc :+
+ sec
+ lda #0
+:
+ sta Score::m_players, x
+.endmacro
+
+;; Add ADDR to the indexed digit on 'Score::m_players' _with_ carry. If the
+;; result is larger or equal than 10, then 0 is stored and the carry flag is
+;; set. Otherwise the carry flag is cleared.
+.macro BCD_ADDC ADDR
+ lda Score::m_players, x
+ adc ADDR
+ clc
+ cmp #10
+ bcc :+
+ sec
+ lda #0
+:
+ sta Score::m_players, x
+.endmacro
+
+;; Only add the carry to the indexed digit on 'Score::m_players' _with_
+;; carry. If the result is larger or equal than 10, then 0 is stored and the
+;; carry flag is set. Otherwise the carry flag is cleared.
+.macro BCD_JUST_CARRY
+ lda Score::m_players, x
+ adc #0
+ clc
+ cmp #10
+ bne :+
+ sec
+ lda #0
+:
+ sta Score::m_players, x
+.endmacro
+
+;; A score is a 6-digit number where each digit is stored on a byte of its
+;; own. This makes adding numbers and representing them into the screen dead
+;; easy.
+;;
+;; This is indeed rather wasteful, but we have a lot of RAM to spare and the
+;; ease of use is quite convenient.
+.scope Score
+ ;; Scores for both players are stored in a single buffer. Even indeces
+ ;; contain digits for the first player, and odd indeces contain digits for
+ ;; the second player. Digits are stored in little-endian format.
+ ;;
+ ;; Interweaving digits this way might seem weird, but it actually makes
+ ;; indexing things super easy: the 'active' bit from
+ ;; 'Globals::zp_multiplayer' can be used to index the first item, and then
+ ;; it's a matter of advancing the 'x' register twice in order to get the
+ ;; next digit.
+ PLAYERS_BUFF_SIZE = $0C
+ m_players = $300 ; asan:reserve PLAYERS_BUFF_SIZE
+
+ ;; The high score for this session.
+ m_hi = $30C ; asan:reserve $06
+
+ ;; Initialize the scores for both players.
+ .proc init_players_scores
+ lda #0
+ ldx #0
+
+ @loop:
+ sta m_players, x
+ inx
+ cpx #PLAYERS_BUFF_SIZE
+ bne @loop
+
+ rts
+ .endproc
+
+ ;; Add to the current player's score the number stored in
+ ;; 'Globals::zp_tmp{0,1,2}', where 'Globals::zp_tmp0' has the least
+ ;; significant number.
+ .proc add_to_player
+ ;; See 'Score::m_players' on why this is the way to select the current
+ ;; player's score.
+ lda Globals::zp_multiplayer
+ and #$01
+ tax
+
+ ;;;
+ ;; The first three digits are the product of adding the contents of
+ ;; 'Globals::zp_tmp{0,1,2}'.
+
+ BCD_ADD Globals::zp_tmp0
+ inx
+ inx
+
+ BCD_ADDC Globals::zp_tmp1
+ inx
+ inx
+
+ BCD_ADDC Globals::zp_tmp2
+ inx
+ inx
+
+ ;;;
+ ;; The rest are just a matter of adding the carry.
+
+ BCD_JUST_CARRY
+ inx
+ inx
+
+ BCD_JUST_CARRY
+ inx
+ inx
+
+ BCD_JUST_CARRY
+
+ ;; TODO: set a flag about updating the score on the HUD.
+
+ rts
+ .endproc
+.endscope
+
+;; Add the score for a dead enemy to the current player's score.
+.macro ADD_ENEMY_SCORE
+ lda #5
+ sta Globals::zp_tmp0
+ lda #2
+ sta Globals::zp_tmp1
+ lda #0
+ sta Globals::zp_tmp2
+ jsr Score::add_to_player
+.endmacro
+
+;; Add the score for grabbing a shuttle part / fuel tank to the current player's
+;; score.
+.macro ADD_PART_FUEL_SCORE
+ lda #0
+ sta Globals::zp_tmp0
+ lda #0
+ sta Globals::zp_tmp1
+ lda #1
+ sta Globals::zp_tmp2
+ jsr Score::add_to_player
+.endmacro
+
+;; Add the score for grabbing an item to the current player's score.
+.macro ADD_ITEM_SCORE
+ lda #0
+ sta Globals::zp_tmp0
+ lda #5
+ sta Globals::zp_tmp1
+ lda #2
+ sta Globals::zp_tmp2
+ jsr Score::add_to_player
+.endmacro