diff options
| author | Miquel Sabaté Solà <mssola@mssola.com> | 2026-09-06 22:55:50 +0200 |
|---|---|---|
| committer | Miquel Sabaté Solà <mssola@mssola.com> | 2026-09-06 22:55:50 +0200 |
| commit | 2d61e42fab657d61212a7aff1ecacbd674be8cda (patch) | |
| tree | f8064b630e1caa4b6e329ab1dcc72b14f0f5c8d5 | |
| parent | 076b1b31f37b37560382545d424ee063903b6b31 (diff) | |
| download | tools.nes-2d61e42fab657d61212a7aff1ecacbd674be8cda.tar.gz tools.nes-2d61e42fab657d61212a7aff1ecacbd674be8cda.zip | |
tests: add a test on branching instructions
Signed-off-by: Miquel Sabaté Solà <mssola@mssola.com>
| -rwxr-xr-x | scripts/test-e2e.sh | 6 | ||||
| -rw-r--r-- | tests/expected/runrom/branching.txt | 71 | ||||
| -rw-r--r-- | tests/runrom/branching.s | 128 |
3 files changed, 205 insertions, 0 deletions
diff --git a/scripts/test-e2e.sh b/scripts/test-e2e.sh index be43685..573a729 100755 --- a/scripts/test-e2e.sh +++ b/scripts/test-e2e.sh @@ -294,6 +294,12 @@ echo "test: runrom => cmp.nes" diff tests/out/cmp.txt tests/expected/runrom/cmp.txt exit_code=$((exit_code + $?)) +echo "test: runrom => branching.nes" +./target/debug/nasm -Werror --asan -o tests/out/branching.nes tests/runrom/branching.s +./target/debug/runrom --function --dump-memory tests/out/branching.nes > tests/out/branching.txt +diff tests/out/branching.txt tests/expected/runrom/branching.txt +exit_code=$((exit_code + $?)) + echo "test: runrom => misc.nes" ./target/debug/nasm -Werror --asan --write-info --allow-unused --out tests/out/misc.nes tests/runrom/misc.s ./target/debug/runrom --nasm .nasm --dump-memory --function tests/out/misc.nes > tests/out/misc-all.txt diff --git a/tests/expected/runrom/branching.txt b/tests/expected/runrom/branching.txt new file mode 100644 index 0000000..8c2eb7f --- /dev/null +++ b/tests/expected/runrom/branching.txt @@ -0,0 +1,71 @@ +<start> PC: $8000, cycles: 7, registers: [a: $00, x: $00, y: $00, sp: $FD], status: ----I-- +ldx #$0A PC: $8002, cycles: 9, registers: [a: $00, x: $0A, y: $00, sp: $FD], status: ----I-- +ldy #$05 PC: $8004, cycles: 11, registers: [a: $00, x: $0A, y: $05, sp: $FD], status: ----I-- +lda $030C, y PC: $8007, cycles: 15, registers: [a: $00, x: $0A, y: $05, sp: $FD], status: ----IZ- +cmp $0300, x PC: $800A, cycles: 19, registers: [a: $00, x: $0A, y: $05, sp: $FD], status: ----IZC +bcc $1F PC: $800C, cycles: 21, registers: [a: $00, x: $0A, y: $05, sp: $FD], status: ----IZC +dex PC: $800D, cycles: 23, registers: [a: $00, x: $09, y: $05, sp: $FD], status: ----I-C +dex PC: $800E, cycles: 25, registers: [a: $00, x: $08, y: $05, sp: $FD], status: ----I-C +dey PC: $800F, cycles: 27, registers: [a: $00, x: $08, y: $04, sp: $FD], status: ----I-C +cpy #$FF PC: $8011, cycles: 29, registers: [a: $00, x: $08, y: $04, sp: $FD], status: ----I-- +bne $F1 PC: $8004, cycles: 32, registers: [a: $00, x: $08, y: $04, sp: $FD], status: ----I-- +lda $030C, y PC: $8007, cycles: 36, registers: [a: $00, x: $08, y: $04, sp: $FD], status: ----IZ- +cmp $0300, x PC: $800A, cycles: 40, registers: [a: $00, x: $08, y: $04, sp: $FD], status: ----IZC +bcc $1F PC: $800C, cycles: 42, registers: [a: $00, x: $08, y: $04, sp: $FD], status: ----IZC +dex PC: $800D, cycles: 44, registers: [a: $00, x: $07, y: $04, sp: $FD], status: ----I-C +dex PC: $800E, cycles: 46, registers: [a: $00, x: $06, y: $04, sp: $FD], status: ----I-C +dey PC: $800F, cycles: 48, registers: [a: $00, x: $06, y: $03, sp: $FD], status: ----I-C +cpy #$FF PC: $8011, cycles: 50, registers: [a: $00, x: $06, y: $03, sp: $FD], status: ----I-- +bne $F1 PC: $8004, cycles: 53, registers: [a: $00, x: $06, y: $03, sp: $FD], status: ----I-- +lda $030C, y PC: $8007, cycles: 57, registers: [a: $00, x: $06, y: $03, sp: $FD], status: ----IZ- +cmp $0300, x PC: $800A, cycles: 61, registers: [a: $00, x: $06, y: $03, sp: $FD], status: ----IZC +bcc $1F PC: $800C, cycles: 63, registers: [a: $00, x: $06, y: $03, sp: $FD], status: ----IZC +dex PC: $800D, cycles: 65, registers: [a: $00, x: $05, y: $03, sp: $FD], status: ----I-C +dex PC: $800E, cycles: 67, registers: [a: $00, x: $04, y: $03, sp: $FD], status: ----I-C +dey PC: $800F, cycles: 69, registers: [a: $00, x: $04, y: $02, sp: $FD], status: ----I-C +cpy #$FF PC: $8011, cycles: 71, registers: [a: $00, x: $04, y: $02, sp: $FD], status: ----I-- +bne $F1 PC: $8004, cycles: 74, registers: [a: $00, x: $04, y: $02, sp: $FD], status: ----I-- +lda $030C, y PC: $8007, cycles: 78, registers: [a: $00, x: $04, y: $02, sp: $FD], status: ----IZ- +cmp $0300, x PC: $800A, cycles: 82, registers: [a: $00, x: $04, y: $02, sp: $FD], status: ----IZC +bcc $1F PC: $800C, cycles: 84, registers: [a: $00, x: $04, y: $02, sp: $FD], status: ----IZC +dex PC: $800D, cycles: 86, registers: [a: $00, x: $03, y: $02, sp: $FD], status: ----I-C +dex PC: $800E, cycles: 88, registers: [a: $00, x: $02, y: $02, sp: $FD], status: ----I-C +dey PC: $800F, cycles: 90, registers: [a: $00, x: $02, y: $01, sp: $FD], status: ----I-C +cpy #$FF PC: $8011, cycles: 92, registers: [a: $00, x: $02, y: $01, sp: $FD], status: ----I-- +bne $F1 PC: $8004, cycles: 95, registers: [a: $00, x: $02, y: $01, sp: $FD], status: ----I-- +lda $030C, y PC: $8007, cycles: 99, registers: [a: $00, x: $02, y: $01, sp: $FD], status: ----IZ- +cmp $0300, x PC: $800A, cycles: 103, registers: [a: $00, x: $02, y: $01, sp: $FD], status: ----IZC +bcc $1F PC: $800C, cycles: 105, registers: [a: $00, x: $02, y: $01, sp: $FD], status: ----IZC +dex PC: $800D, cycles: 107, registers: [a: $00, x: $01, y: $01, sp: $FD], status: ----I-C +dex PC: $800E, cycles: 109, registers: [a: $00, x: $00, y: $01, sp: $FD], status: ----IZC +dey PC: $800F, cycles: 111, registers: [a: $00, x: $00, y: $00, sp: $FD], status: ----IZC +cpy #$FF PC: $8011, cycles: 113, registers: [a: $00, x: $00, y: $00, sp: $FD], status: ----I-- +bne $F1 PC: $8004, cycles: 116, registers: [a: $00, x: $00, y: $00, sp: $FD], status: ----I-- +lda $030C, y PC: $8007, cycles: 120, registers: [a: $00, x: $00, y: $00, sp: $FD], status: ----IZ- +cmp $0300, x PC: $800A, cycles: 124, registers: [a: $00, x: $00, y: $00, sp: $FD], status: ----IZC +bcc $1F PC: $800C, cycles: 126, registers: [a: $00, x: $00, y: $00, sp: $FD], status: ----IZC +dex PC: $800D, cycles: 128, registers: [a: $00, x: $FF, y: $00, sp: $FD], status: ----I-C +dex PC: $800E, cycles: 130, registers: [a: $00, x: $FE, y: $00, sp: $FD], status: N---I-C +dey PC: $800F, cycles: 132, registers: [a: $00, x: $FE, y: $FF, sp: $FD], status: ----I-C +cpy #$FF PC: $8011, cycles: 134, registers: [a: $00, x: $FE, y: $FF, sp: $FD], status: ----IZC +bne $F1 PC: $8013, cycles: 136, registers: [a: $00, x: $FE, y: $FF, sp: $FD], status: ----IZC +bit $27 PC: $8015, cycles: 139, registers: [a: $00, x: $FE, y: $FF, sp: $FD], status: ----IZC +bpl $2F PC: $8046, cycles: 142, registers: [a: $00, x: $FE, y: $FF, sp: $FD], status: ----IZC +rts PC: $8047, cycles: 148, registers: [a: $00, x: $FE, y: $FF, sp: $FD], status: ----IZC +<end> + +== Memory dump == + +[$27] = $00 [reads=1, writes=0] +[$300] = $00 [reads=1, writes=0] +[$302] = $00 [reads=1, writes=0] +[$304] = $00 [reads=1, writes=0] +[$306] = $00 [reads=1, writes=0] +[$308] = $00 [reads=1, writes=0] +[$30A] = $00 [reads=1, writes=0] +[$30C] = $00 [reads=1, writes=0] +[$30D] = $00 [reads=1, writes=0] +[$30E] = $00 [reads=1, writes=0] +[$30F] = $00 [reads=1, writes=0] +[$310] = $00 [reads=1, writes=0] +[$311] = $00 [reads=1, writes=0] diff --git a/tests/runrom/branching.s b/tests/runrom/branching.s new file mode 100644 index 0000000..a96888c --- /dev/null +++ b/tests/runrom/branching.s @@ -0,0 +1,128 @@ +.segment "HEADER" + .byte 'N', 'E', 'S', $1A + .byte $02, $01 + .byte $00 + .byte $00 + +.segment "CHARS" +.byte 0 + +.segment "VECTORS" + .addr reset, reset, reset + +.segment "CODE" +;; asan:stack full + +;; From: https://git.mssola.com/nes/jetpac.nes/. +.scope Globals + ;; | Bit | Short name | Meaning | + ;; |-----+------------------+--------------------------| + ;; | 7 | enabled | Multiplayer enabled. | + ;; | 6-3 | - | Unused. | + ;; | 2 | player's 2 state | 0: over; 1: alive | + ;; | 1 | player's 1 state | 0: over; 1: alive | + ;; | 0 | active | 0: player 1; 1: player 2 | + zp_multiplayer = $27 + + ;; Extra bitmap that was needed beyond the ones that we already have. Yeah, + ;; I know, bad planning from my side, but now it's a bit complex to untangle + ;; variables like 'Globals::zp_flags'. + ;; + ;; | Bit | Short name | Meaning | + ;; |-----+------------------+----------------------------------| + ;; | 7 | score | The score has been updated. | + ;; | 6 | high | The high score has been updated. | + ;; | 5-0 | - | Unused. | + zp_extra_flags = $28 +.endscope + +;; From: https://git.mssola.com/nes/jetpac.nes/. +.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 +.endscope + +;; This is basically Score::save_hi_score() from +;; https://git.mssola.com/nes/jetpac.nes/. +.proc reset + ;;; + ;; Check player 1. + + ldx #(Score::PLAYERS_BUFF_SIZE - 2) + ldy #5 + +@player1_loop: + lda Score::m_hi, y + cmp Score::m_players, x + bcc @save_player1 + dex + dex + dey + cpy #$FF + bne @player1_loop + + ;; No dice! If we are in multiplayer mode, then check player 2, + ;; otherwise just quit. + bit Globals::zp_multiplayer + bpl @end + + ;;; + ;; Check player 2. + + ldx #(Score::PLAYERS_BUFF_SIZE - 1) + ldy #5 + +@player2_loop: + lda Score::m_hi, y + cmp Score::m_players, x + bcc @save_player2 + dex + dex + dey + cpy #$FF + bne @player2_loop + + ;; Not player 2 either. Just quit. + rts + + ;;; + ;; One of the players actually achieved a high score. Let's save it. + +@save_player1: + ldx #0 + beq @save +@save_player2: + ldx #1 + +@save: + ldy #0 +@save_loop: + lda Score::m_players, x + sta Score::m_hi, y + + inx + inx + iny + cpy #6 + bne @save_loop + + ;; And set the 'high' bit so this change is reflected on screen. + lda Globals::zp_extra_flags + ora #$40 + sta Globals::zp_extra_flags + +@end: + rts +.endproc |
