aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile2
-rw-r--r--assets/alphanum.chrbin8192 -> 8192 bytes
-rw-r--r--include/print.s36
-rw-r--r--src/1.s5
-rw-r--r--src/2.s5
-rw-r--r--src/3.s713
-rw-r--r--test/3.lua13
-rw-r--r--test/defines.s10
-rw-r--r--test/run.sh2
-rw-r--r--test/utils.lua3
-rw-r--r--vendor/bcd16.s4
11 files changed, 774 insertions, 19 deletions
diff --git a/Makefile b/Makefile
index 0784337..be38f1a 100644
--- a/Makefile
+++ b/Makefile
@@ -5,7 +5,7 @@ CCOPTS += -g -Ln out/labels.txt
endif
QUIET = @echo ' ' CC65 $@;
-SOURCES = $(shell find src/ -type f -name '*.s' -printf "%f\n")
+SOURCES = $(shell find src/ -type f -name '*.s' -printf "%f\n" | sort)
ROMS = $(SOURCES:%.s=out/%.nes)
.PHONY: all
diff --git a/assets/alphanum.chr b/assets/alphanum.chr
index 622eb8e..8817e9b 100644
--- a/assets/alphanum.chr
+++ b/assets/alphanum.chr
Binary files differ
diff --git a/include/print.s b/include/print.s
index 7a0ac23..15755d5 100644
--- a/include/print.s
+++ b/include/print.s
@@ -22,10 +22,39 @@
rts
.endproc
- ;; TODO
+ ;; Print a "Done!" message to the screen in a similar fashion as `show_wait_message`.
+ .proc show_done_message
+ ;; Clear tiles that were written by `show_wait_message` and that are not
+ ;; re-used here.
+ WRITE_PPU_DATA $2129, $00
+ WRITE_PPU_DATA $212A, $00
+ WRITE_PPU_DATA $212B, $00
+ WRITE_PPU_DATA $212C, $00
+ WRITE_PPU_DATA $212D, $00
+ WRITE_PPU_DATA $2132, $00
+ WRITE_PPU_DATA $2134, $00
+ WRITE_PPU_DATA $2135, $00
+ WRITE_PPU_DATA $2136, $00
+
+ ;; And print the message.
+ WRITE_PPU_DATA $212E, $1E
+ WRITE_PPU_DATA $212F, $29
+ WRITE_PPU_DATA $2130, $28
+ WRITE_PPU_DATA $2131, $1F
+ WRITE_PPU_DATA $2133, $37
+
+ rts
+ .endproc
+
+ ;; Show a 16-bit number on screen.
+ ;;
+ ;; NOTE: This subroutine will do nothing if `vendor/bcd16.s` has not been
+ ;; previously included.
.proc show_bcd_16_number
- ;; Clear tiles that were written by `show_wait_message` and that are not re-used
- ;; here.
+ .ifdef BCD16_SUPPORT
+
+ ;; Clear tiles that were written by `show_wait_message` and that are not
+ ;; re-used here.
WRITE_PPU_DATA $2129, $00
WRITE_PPU_DATA $212A, $00
WRITE_PPU_DATA $212B, $00
@@ -58,6 +87,7 @@
cpy #$33
bne @loop
+ .endif
rts
.endproc
diff --git a/src/1.s b/src/1.s
index 4f4ae38..28cd933 100644
--- a/src/1.s
+++ b/src/1.s
@@ -110,7 +110,10 @@
@end:
;; Run tests now that everything has been done.
- CALL_TESTS_ON_DONE
+.ifdef RUN_TESTS
+ @test:
+ nop
+.endif
@halt:
jmp @halt
.endproc
diff --git a/src/2.s b/src/2.s
index 353cb16..78b068e 100644
--- a/src/2.s
+++ b/src/2.s
@@ -138,7 +138,10 @@
@end:
;; Run tests now that everything has been done.
- CALL_TESTS_ON_DONE
+.ifdef RUN_TESTS
+@test:
+ nop
+.endif
@halt:
jmp @halt
.endproc
diff --git a/src/3.s b/src/3.s
new file mode 100644
index 0000000..962807a
--- /dev/null
+++ b/src/3.s
@@ -0,0 +1,713 @@
+;;;
+;; Day 3 https://adventofcode.com/2023/day/3
+;;
+;; The enunciate has two parts, but I have only implemented the first one
+;; because I didn't have the time, and for it I'd need to build up some memory
+;; management code that gets out of hand fast on the poor NES. Maybe in the
+;; future I'd revisit this, but I was feeling the enjoyment out of the puzzle,
+;; which is kind of the whole point...
+;;
+;; Note also that this will not print the result in a similar fashion as the
+;; second part from day 2, because printing 24-bit numbers needs its own code
+;; which I have not yet implemented. Maybe in the near future. For now just look
+;; at the 32-bit integer at $0C.
+
+.segment "HEADER"
+ .byte 'N', 'E', 'S', $1A
+
+ .byte $02
+ .byte $01
+
+ .byte $00
+ .byte $00
+
+.segment "VECTORS"
+ .addr nmi, reset, irq
+
+.segment "CHARS"
+ .incbin "../assets/alphanum.chr"
+
+.segment "STARTUP"
+.segment "CODE"
+
+.include "../include/apu.s"
+.include "../include/oam.s"
+.include "../include/ppu.s"
+.include "../include/reset.s"
+.include "../include/globals.s"
+.include "../include/print.s"
+
+.include "../test/defines.s"
+
+;; "Variables" used by this program.
+.scope Vars
+ ;; The address pointing to the previous row.
+ ;;
+ ;; NOTE: 16 bit.
+ m_address_prev = $00
+
+ ;; The address pointing to the current row.
+ ;;
+ ;; NOTE: 16 bit.
+ m_address_cur = $02
+
+ ;; The address pointing to the next row.
+ ;;
+ ;; NOTE: 16 bit.
+ m_address_next = $04
+
+ ;; The number of bytes separating the beginning of a row and the other.
+ ;; Used when advancing to the next iteration.
+ m_address_step = $06
+
+ ;; Numeric values being used when parsing numbers, and also sometimes for
+ ;; temporary values when the number represented by these three bytes has
+ ;; already been consumed.
+ m_num_1 = $07
+ m_num_2 = $08
+ m_num_3 = $09
+
+ ;; The last number that has been parsed.
+ ;;
+ ;; NOTE: 16-bit.
+ m_num_16 = $0a
+
+ ;; The number being accumulated over different iterations and giving the end
+ ;; result.
+ ;;
+ ;; NOTE: this could have been just a 24-bit number, but we are reserving to
+ ;; it 32 bits because FCEUX goes from 16 bit to 32 bits.
+ m_num_32 = $0c
+
+ ;; The index pointing to the left edge of the last evaluated number.
+ m_num_left = $10
+
+ ;; The index pointing to the right edge of the last evaluated number.
+ m_num_right = $11
+
+ ;; Address iterator. This is to be set before calling `check_address`,
+ ;; because this subroutine will consume this address.
+ ;;
+ ;; NOTE: 16 bit.
+ m_address_it = $12
+
+ ;; Initialize some of the variables.
+ .proc init
+ lda #0
+ sta Vars::m_address_prev
+ sta Vars::m_address_prev + 1
+
+ sta Vars::m_num_16
+ sta Vars::m_num_16 + 1
+
+ sta Vars::m_num_32
+ sta Vars::m_num_32 + 1
+ sta Vars::m_num_32 + 2
+ sta Vars::m_num_32 + 3
+
+ lda #.LOBYTE(data)
+ sta Vars::m_address_cur
+ lda #.HIBYTE(data)
+ sta Vars::m_address_cur + 1
+
+ jsr set_step
+ lda #.LOBYTE(data)
+ clc
+ adc Vars::m_address_step
+ sta Vars::m_address_next
+ lda #0
+ adc #.HIBYTE(data)
+ sta Vars::m_address_next + 1
+
+ rts
+ .endproc
+.endscope
+
+;; Copy the given pointer to Vars::m_address_it.
+.macro ADDRESS_PTR_TO_IT address
+ lda address
+ sta Vars::m_address_it
+ lda address + 1
+ sta Vars::m_address_it + 1
+.endmacro
+
+;; The main function will be called at the end of the `reset` vector as defined
+;; in `include/reset.s`.
+.proc main
+ ;; Initialize palettes and variables being used for this program.
+ jsr Print::load_basic_palettes
+ jsr Vars::init
+
+ ;; This program uses two flags:
+ ;; - 7 (`render`): whether NMI-code can render stuff on screen.
+ ;; - 6 (`done`): whether the computation has been done.
+ ;;
+ ;; Note that we are setting the render flag so the initial message is
+ ;; shown.
+ lda #%10000000
+ sta Globals::m_flags
+
+ cli
+
+ lda #%10010000
+ sta PPU::CONTROL
+ lda #%00011110
+ sta PPU::MASK
+
+@loop:
+ ;; Skip everything if the `done` flag is set.
+ bit Globals::m_flags
+ bvs @end
+
+ jsr compute_next
+ jmp @loop
+
+@end:
+ ;; Run tests now that everything has been done.
+.ifdef RUN_TESTS
+@test:
+ nop
+.endif
+@halt:
+ jmp @halt
+.endproc
+
+;; Initialize `Vars::m_address_step` with the step as computed by measuring the
+;; length of the first row. That is, we assume that all rows have the same
+;; number of columns, which is cool by the enunciate.
+.proc set_step
+ ldy #0
+@loop:
+ lda (Vars::m_address_cur), y
+ beq @done
+ iny
+ jmp @loop
+@done:
+ iny
+ sty Vars::m_address_step
+ rts
+.endproc
+
+;; Compute the next iteration of the exercise. Note that this subroutine assumes
+;; that we are not done yet. Hence, do not call this subroutine if the `done`
+;; flag has already been set.
+.proc compute_next
+ jsr compute_row
+
+ ;;
+ ;; Ready address pointers for the next iteration.
+
+ ;; current -> previous.
+ lda Vars::m_address_cur
+ sta Vars::m_address_prev
+ lda Vars::m_address_cur + 1
+ sta Vars::m_address_prev + 1
+
+ ;; next -> current
+ lda Vars::m_address_next
+ sta Vars::m_address_cur
+ lda Vars::m_address_next + 1
+ sta Vars::m_address_cur + 1
+
+ ;; Wait, does the first byte on the current address contain the guard value?
+ ;; If so, then we are done.
+ ldy #0
+ lda (Vars::m_address_cur), y
+ cmp #$ED
+ beq @done
+
+ ;; next = next + step.
+ lda Vars::m_address_step
+ clc
+ adc Vars::m_address_next
+ sta Vars::m_address_next
+ lda #0
+ adc Vars::m_address_next + 1
+ sta Vars::m_address_next + 1
+
+ rts
+
+@done:
+ ;; Mark the `done` flag so future iterations don't go through all of this.
+ ;; We are also setting the `render` flag so the last message is also shown.
+ lda #%11000000
+ ora Globals::m_flags
+ sta Globals::m_flags
+ rts
+.endproc
+
+;; Compute a given row of the exercise.
+.proc compute_row
+ ldy #0
+
+ ;; This loop is rather simple:
+ ;;
+ ;; 1. Fetch the current byte. If this is the zero byte, then we are done.
+ ;; If it's not numeric, skip it and go to @next.
+ ;; 2. If this is a numeric value, parse the number.
+ ;; 3. Then check the edges on the prev, cur, and next addresses.
+ ;; 4. If any of them left a `1` on `Vars::m_num_1`, then we have found a
+ ;; symbol between the two edges and we have to add the value of our
+ ;; number on @sum.
+@loop:
+ lda (Vars::m_address_cur), y
+ beq @done
+ sec
+ sbc #48
+ bcc @next
+ cmp #10
+ bcs @next
+
+ lda #0
+ sta Vars::m_num_16
+ sta Vars::m_num_16 + 1
+
+ jsr parse_number
+
+ ADDRESS_PTR_TO_IT Vars::m_address_prev
+ jsr check_address
+ lda Vars::m_num_1
+ bne @sum
+
+ ADDRESS_PTR_TO_IT Vars::m_address_cur
+ jsr check_address
+ lda Vars::m_num_1
+ bne @sum
+
+ ADDRESS_PTR_TO_IT Vars::m_address_next
+ jsr check_address
+ lda Vars::m_num_1
+ bne @sum
+ jmp @loop
+
+@sum:
+ ;; We have to add the number on `Vars::m_num_16` into the accumulator
+ ;; `Vars::m_num_32`. That is, we only need to add the first 16 bits and then
+ ;; carry over the carry bit into the other 16 bits.
+ lda Vars::m_num_16
+ clc
+ adc Vars::m_num_32
+ sta Vars::m_num_32
+ lda Vars::m_num_16 + 1
+ adc Vars::m_num_32 + 1
+ sta Vars::m_num_32 + 1
+ lda #0
+ adc Vars::m_num_32 + 2
+ sta Vars::m_num_32 + 2
+ lda #0
+ adc Vars::m_num_32 + 3
+ sta Vars::m_num_32 + 3
+ jmp @loop
+
+@next:
+ iny
+ jmp @loop
+
+@done:
+ rts
+.endproc
+
+;; Parse the number being pointed by `Vars::m_address_cur` and the `y` register.
+.proc parse_number
+ ;; Initialize with a guard value.
+ lda #$FF
+ sta Vars::m_num_1
+ sta Vars::m_num_2
+ sta Vars::m_num_3
+
+ ;; Now it's a good time to set the left edge. Note that `y` is pointing
+ ;; right at the first numeric value, and the edge is -1 of that. Hence, we
+ ;; have to decrease this value unless we are already at 0.
+ sty Vars::m_num_left
+ cpy #0
+ beq @loop
+ dec Vars::m_num_left
+
+@loop:
+ ;; Load the given byte. If this is not a numerical value, just go to @done.
+ lda (Vars::m_address_cur), y
+ sec
+ sbc #48
+ bcc @done
+ cmp #10
+ bcs @done
+
+ ;; This is a numerical value! At this point we will set the number on
+ ;; `Vars::m_num_{1, 2, 3}` in order.
+ ldx Vars::m_num_1
+ cpx #$FF
+ beq @first
+ ldx Vars::m_num_2
+ cpx #$FF
+ beq @second
+ sta Vars::m_num_3
+ iny
+ jmp @done
+@first:
+ sta Vars::m_num_1
+ iny
+ jmp @loop
+@second:
+ sta Vars::m_num_2
+ iny
+ jmp @loop
+
+ ;; There are no more numerical digits, let's evaluate what we have parsed.
+@done:
+ ;; The `y` register is already pointing at the right edge.
+ sty Vars::m_num_right
+
+ ;;;
+ ;; From here forward the code seems more comboluted that it actually is. We
+ ;; basically track how many `Vars::m_num_{1, 2, 3}` we have set. Depending
+ ;; on that, each variable will contain either a hundredth, a tenth or a
+ ;; unit. Either way, we just multiply at the proper values and add things up
+ ;; to get our numeric value into `Vars::m_num_16`.
+
+ lda Vars::m_num_2
+ cmp #$FF
+ beq @just_unit
+ lda Vars::m_num_3
+ cmp #$FF
+ beq @tenth_and_unit
+
+ ;; This is the case in which we have found three digits. Hence, `m_num_1`
+ ;; contains the hundredth (used by `mul_by_100`), `m_num_2` the tenth and
+ ;; `m_num_3` the unit. See that for simplicity we first go with the
+ ;; hundredth, then we add the unit, and we prepare into the `a` register the
+ ;; digit for the tenth, since `@tenth` will take care of it regardless of
+ ;; the branch of the code.
+
+ jsr mul_by_100
+
+ lda Vars::m_num_3
+ clc
+ adc Vars::m_num_16
+ sta Vars::m_num_16
+ lda #0
+ adc Vars::m_num_16 + 1
+ sta Vars::m_num_16 + 1
+
+ lda Vars::m_num_2
+ jmp @tenth
+@tenth_and_unit:
+ ;; Two digits were found. Here we only need to initialize our number with
+ ;; the unit and then go to `@tenth` to get the tenth which is in `m_num_1`
+ ;; this time around.
+ lda Vars::m_num_2
+ clc
+ adc Vars::m_num_16
+ sta Vars::m_num_16
+ lda #0
+ adc Vars::m_num_16 + 1
+ sta Vars::m_num_16 + 1
+
+ lda Vars::m_num_1
+@tenth:
+ ;; Similarly to day 2, multiplying by 10 is done by n*2 + n*8.
+ asl
+ sta Vars::m_num_3
+ asl
+ asl
+ clc
+ adc Vars::m_num_3
+
+ ;; And add this tenth (regardless if we came from the three or two digits
+ ;; cases) and we have it already.
+ clc
+ adc Vars::m_num_16
+ sta Vars::m_num_16
+ lda #0
+ adc Vars::m_num_16 + 1
+ sta Vars::m_num_16 + 1
+
+ rts
+@just_unit:
+ ;; This is the most simple case: only one digit was found. Then we have it
+ ;; on `m_num_1`, and we can just set it into our number.
+ lda Vars::m_num_1
+ sta Vars::m_num_16
+ lda #0
+ sta Vars::m_num_16 + 1
+ rts
+.endproc
+
+;; Multiply the value on `Vars::m_num_1` by 100 and set it into
+;; `Vars::m_num_16`.
+.proc mul_by_100
+ ;; What's the algorithm on poor 6502 with no decimal mode? Well, you guessed
+ ;; it, just accumulate the value 100 times :D
+ ldx #100
+@loop:
+ lda Vars::m_num_16
+ clc
+ adc Vars::m_num_1
+ sta Vars::m_num_16
+ lda #0
+ adc Vars::m_num_16 + 1
+ sta Vars::m_num_16 + 1
+
+ dex
+ bne @loop
+ rts
+.endproc
+
+;; Sets the `Vars::m_num_1` variable to `1` if there is a symbol between the
+;; left and the right edges as can be seen on the data indexed by
+;; `Vars::m_address_it`. The `y` register is preserved during all of this.
+.proc check_address
+ ;; We set it now, and we will only set it again when we find a symbol.
+ lda #0
+ sta Vars::m_num_1
+
+ ;; If the 16-bit pointer is null, then just leave.
+ lda Vars::m_address_it
+ bne @proceed
+ lda Vars::m_address_it + 1
+ bne @proceed
+ rts
+
+@proceed:
+ ;; Save the `y` register, since the caller is definitely interested on
+ ;; preserving it.
+ tya
+ pha
+
+ ;; The loop is pretty straighforward: we will iterate over
+ ;; `Vars::m_address_it` from the left edge until the right one. On each
+ ;; iteration we will call `is_symbol` and set `Vars::m_num_1` to `1` if this
+ ;; call returns true.
+ ldy Vars::m_num_left
+ dey
+@loop:
+ iny
+ lda (Vars::m_address_it), y
+ beq @done
+ jsr is_symbol
+ beq @next
+ lda #1
+ sta Vars::m_num_1
+ jmp @done
+@next:
+ ;; The register `y` contains the index of the last evaluated position. If
+ ;; this turns out to be either the right edge or, by any bug, greater than
+ ;; that, then we are done. Otherwise, we will loop if `y` is lesser than the
+ ;; right edge.
+ cpy Vars::m_num_right
+ bcc @loop
+@done:
+ ;; And restore the `y` register before leaving.
+ pla
+ tay
+ rts
+.endproc
+
+;; Sets the `a` register to `1` if the current value of `a` corresponds to a
+;; symbol as defined by the enunciate. Otherwise it will set it to 0.
+.proc is_symbol
+ ldx #0
+@loop:
+ cmp symbols, x
+ beq @found
+ inx
+ cpx #$0A
+ bne @loop
+ lda #0
+ rts
+@found:
+ lda #1
+ rts
+symbols:
+ .asciiz "#%&*+-/=@$"
+.endproc
+
+;; Non-Maskable Interrupts handler.
+nmi:
+ bit PPU::STATUS
+
+ ;; Skip rendering if the `render` flag is not set.
+ bit Globals::m_flags
+ bpl @nmi_next
+
+ ;; Backup registers.
+ pha
+ txa
+ pha
+ tya
+ pha
+
+ ;; If the result is not there yet, then we just print an initial message.
+ ;; Otherwise print a done message.
+ bit Globals::m_flags
+ bvs :+
+ jsr Print::show_wait_message
+ jmp :++
+:
+ jsr Print::show_done_message
+:
+
+ ;; Reset the scroll.
+ bit PPU::STATUS
+ lda #$00
+ sta PPU::SCROLL
+ sta PPU::SCROLL
+
+ ;; And unset the render flag so the `main` code is unblocked.
+ UNSET_RENDER_FLAG
+
+ ;; Restore registers.
+ pla
+ tay
+ pla
+ tax
+ pla
+@nmi_next:
+ rti
+
+;; Unused.
+irq:
+ rti
+
+.segment "RODATA"
+data:
+ .asciiz "..............423....688..934............970................................95.728..........896...113..................153..972............."
+ .asciiz "...122..................*.....*..........................919..509*..........&...@.........../...........................+.......*..........."
+ .asciiz "....+..........259....698..373.992.52.674.........................781...22........130.584.....-...%399.......777.................266........"
+ .asciiz "......148..+....*........................*.....357.123.......................812.........*756.143...........*..............................."
+ .asciiz "..691*.....700..708................-...357........*........$177......%..244.............................762.453....477-.707..-168..359*....."
+ .asciiz ".......................394.443....456......750..................71.160.....*..183.........835..74.........*.............../............129.."
+ .asciiz "....578$....................%........................362..1......*.......661....*...........=.....730......744..294..........247............"
+ .asciiz "..............415...306*....../.452.................+.....*......375.............76....186*....../...............*..........@.......-..441.."
+ .asciiz ".....*152......#........75.757.......204%..................605.............................77.......%405.......957..324...........404......."
+ .asciiz "..545.............../...........................................*....618......%...599...............................&....43.............=..."
+ .asciiz "..............902...145............170..............568..741.285.592..........54./.......%.......923......522+..........*..../...128....602."
+ .asciiz ".......697.16*................322...........$............*............+339..........633.56............$..............792..751..............."
+ .asciiz ".......*.........................*..752..826.......*...104..861......................................144.....883...............+..778.892..."
+ .asciiz "......968..690.......#.....769#.718...*.........326..........*..............493..123..........362...........*.........757....570..@....*...."
+ .asciiz "..681.................242............806................509...307..../.....*......./.350..942...*..614@...511........+.................151.."
+ .asciiz "........*....../..256.......................235.....923....*..........28..264........*......&..316..............945....522........*823......"
+ .asciiz ".....961.136.567....................944.......*..........500..-.......................504................765$..........=.......563.........."
+ .asciiz "..................837..823......480.....627....984.#.........136....969..........-289......$757............................107........593..."
+ .asciiz ".74.924....../.............+110....*...............511................+....564......................389%.....989*305....@...*.........*....."
+ .asciiz ".......+......110..735..........647....658.509*378..........-999............*....#225....937.............147.........778...868.....871..611."
+ .asciiz ".........$...........*.....3............*...........................608..842..............*.......589.......*....842...................*...."
+ .asciiz "......$.963.....634.....................569....&..........177................*..........774.........*..132.153..*.............=.......13...."
+ .asciiz "...723.........=.......@..324......455#.......417....849$.*.........*372..747.87............./358...35..*.......974..453...811...990........"
+ .asciiz ".....................174...%............949...............182....684.............414...................201.......................*...../...."
+ .asciiz "........@.......................62.....*.....-.@669.....................487......*................943.........740*...10.......298....384...."
+ .asciiz "....446.711.........20.674...........343..806.....................&.574.*........965..............*......776...........*.867................"
+ .asciiz "......*............&.......705.804.............................374....+.307............&.......683...830...*....625..530....*837...272*....."
+ .asciiz ".......791....................*.......&.................108...........................533..............*...966.*.......................515.."
+ .asciiz "............412...../................764....................658.+292.635.674..337.................98..814......263.......720*..............."
+ .asciiz "..............*...469..162.....23......................*64..*...............*.............+.........*.....*552...............990......942..."
+ .asciiz "790.536.......365.......*..587..=..........................313.....512....983....953.......348.....617.982.................................."
+ .asciiz "........580............227...*....673.808....66......595............./........*............................$..........21..989..............."
+ .asciiz ".....#.....*.781...........688...*..../........=.........865...............316.162.440.............&......482.663....*.............529......"
+ .asciiz "...357...182.@......359=..........553.......#....33....................323.........*............702...........*....200........&.....*......."
+ .asciiz "...............733....................957.22..........815.........................57..657@..................792..........%.....678.305......"
+ .asciiz "..701..246........*238....553..107......*...................301..........649.555..............70....................610.233.&..............."
+ .asciiz "....#...*..&.................$.*....$.......$......438.....*.......943......*.....&675..955*....*..........183...=....%.....595............."
+ .asciiz "......719.857...640*299............202...125...802..#...786...........*.....................277.424..........*.790./...............984......"
+ .asciiz "...@......................368.....................*...............323..587.479....553.272.................843.......518.............*......."
+ .asciiz "...382..........892...46..........359..372+.611..585...............*.......*........*...+........&.............................487...35....."
+ .asciiz "........&692.......*..*..............@.......-.......*697.......656.....155....34..681............64..641......................*............"
+ .asciiz "....495..........885..964................993......685................%........*....................../..........543.........863............."
+ .asciiz "..........*408................&....244.....*..........................893....339........................109.....................777........."
+ .asciiz "...521.985..................677......*......734........18....925#................352...843*74.......&....*.............260.......*.........."
+ .asciiz "...$........445.$..................802...................#..........=........533...@.................228..612......724....*................."
+ .asciiz ".............*..504............=.......*.....177...................502.....+..*.............395......................$.....274.....396......"
+ .asciiz "......................417....274.....61.504..*........36*..................34..801..........%............224......................*........."
+ .asciiz "......789.........139......&.....*............802........674....&..332..............675............819.............814............883..+915."
+ .asciiz "...@.....*.....-..*.....970...279.117...............984@.....878..........231*168.*..................*.........793*........................."
+ .asciiz "..33..875.....483.433....................*.........................................148.675...581*.....544.........................*537......"
+ .asciiz "......................884............671..839.....31..........685..@...899....350*...............621........*509............./.913.........."
+ .asciiz "....947......=742..........*.......................*...............712....*.......722...159............378........438.....300...........381."
+ .asciiz "...*....................548..-................*..638.....................827...........*......714/...../...867....$..................%.-...."
+ .asciiz "998.....966.693..............694...........781...........764......584...............233....58......-......*............67=........161......."
+ .asciiz "...........*.....................509..-851.........&.846..#........../...199.................*.443..658..976.130..489..................594.."
+ .asciiz "243....413.........499-...384.......*............352.+.............................752....298..*...............$..$...............577...*..."
+ .asciiz "......*......................*......378.335.................*.........+...813.120.*....................654..........$........325...*...984.."
+ .asciiz "...847..496....151*...........741.......*............624.116....767.988..&.....*...87............807...*.........127....997+......621......."
+ .asciiz "........*..........227....345......*........@.....................*............699....566..604...*...760....290............................."
+ .asciiz "......526..................*..500..799...761...413*......277....101........$..........*.........342..........*.......589..997......=........"
+ .asciiz ".............+....379....549............................*............*97.647.779....$.655..975......216...............*.......51..307./496.."
+ .asciiz "...........485.......&...............................55...........509............825......+.....43.....*...554......36...678+.$............."
+ .asciiz "..........................73.....419.....314../...........311...........$....946.....272............351...*........................968../..."
+ .asciiz ".....786.................*........-..824.$...478......908....*.....455.254.....*.........615....760.....60...$......&.....*562.........102.."
+ .asciiz ".......*......43.....&...808........*.............267.*...985.....*..........616.........../......*...........189....977........616........."
+ .asciiz "......45.932...*.....502..........805...943.840%...*..270......764......680......................750..415*184......................*606....."
+ .asciiz "..768....*.....941............%.......8.&..................*................248&..105..745...633...........................584..........692."
+ .asciiz ".......684............115....88...396*..................494.354...88...58.....................*.........956......809...53.......615........."
+ .asciiz "................*391.............................................$....%.....&64.............488...........$.........*.....*.......*........."
+ .asciiz "......440.459...........637...*....866...412.519.183..../.......................*82..963.........*307..=......715.408..421.292....626..*...."
+ .asciiz ".........*......$..........#...769............./..*....470.939.+......*.....257.....*.........257.....109.578..*.......................290.."
+ .asciiz "......+.......-..897...............................629.....-...834.254.798..*.......411....................*....411.......309....218........"
+ .asciiz ".......960..744..............384............................................433................$301.....848.................*.......#..144.."
+ .asciiz "..746............$....../...........38$...536.....-....@.............*..................-............................320...471..........*..."
+ .asciiz "....*.............720...59......................260..852...........633.........714...510......256.173.23...850........*........#.....691...."
+ .asciiz "..294..434...264......................422../639..........378.493...........388*................-....*...*..../.141..............539........."
+ .asciiz "........../.&........790..........@....*....................*..........&............$.............16....633.....=.....................458..."
+ .asciiz "..678...............&.......184....186.934..652...741%.........=887...980.425../....485.732...502...........%........745..............*....."
+ .asciiz "...*..........98.......@......*.................+...........................*...989.....$........*......838.9..........-...........464......"
+ .asciiz ".975..768....*.....*..702.....979....511$....161....645..............44.....18............721.695...348.........400......./.543*............"
+ .asciiz "........*.769....320......724......................&.....330&........*...................*...........$...188.....*.....977......618...%....."
+ .asciiz "......879.....79............*....658..............................601................701..490....#......*........478.......166.........892.."
+ .asciiz "..844.............706....472....*...........113.........-765..217........267....../.*..........648....973....285............................"
+ .asciiz ".....*.482..........*...........853....408.....*................&........*.......59.265.........................*.......364....45.......@..."
+ .asciiz "..164..*...........309....472............#..478...40.......356........328....706..............$...............149.526.....%.....*.....27...."
+ .asciiz "...........................*.......&..................612...*..58.64%........*...766.......953......488............=.../.......152.........."
+ .asciiz "...*73....872.............347....27...22......552@.........559.*............435.....*679.............*...13.774......177.#250.......8*......"
+ .asciiz "977......#.........=....................=.......................56...508......................139.747.....*..*................861.....666..."
+ .asciiz "..............703...102....../........&....637..448......%..951........*...175.552*235...@.....*.......486..693............................."
+ .asciiz "........944..*....@...........590..42.738...*..........861.....&....919.....*............108.837................#....963.530...831..&...251."
+ .asciiz "........#.....93.103....708................54.342....+......................496.......................&.........278.....*.....*....162......"
+ .asciiz "..........860............@.......$167..............431.683......=496....858.........422.............662.154.405..............635.%.........."
+ .asciiz ".....882/.*.............................%......611..........766.......-...*.....755..@.....................*..........608.........951......."
+ .asciiz "..........513......................274...226......*........@.......&..556.151....*.............229...681..............*.....911............."
+ .asciiz "..............445....375.....774....*...........348..............643.............302...........*........*.......-...88......*........975...."
+ .asciiz "....*664.........*...&........@.........................893..........523....13...............825.........558...733.....769...991.....*......"
+ .asciiz ".328......821....935...................&.......@...457.....*.....+..*.........=..................341..................#............384......"
+ .asciiz ".........*...........164..........251..756....23...........912.532..879..................459........*...=..................................."
+ .asciiz "219.....71..821..............654.....................684........................@2....................931...........910....................."
+ .asciiz "............&...425+..-.............207........*.....%...360...........190..........69.....................43..........$...................."
+ .asciiz ".....................116....................127.214.........*..181........@..%...49*....444....57.........*.....................715........."
+ .asciiz "............$....*.............-..859.................=..248......*..........82........*.......@.......246..376.........#........*.........."
+ .asciiz "...726...898...-..772...223.712....%........%464.....342.........442..447.........461..102.....................*355...537....313..596...584."
+ .asciiz "....*.........189........@...............................................*187........*...............*....807.............+.....*..........."
+ .asciiz ".....181.+..........197......530.653+.383...293.........461%.22*..............394....769..104...$.818.36.$....=.......&....860...333........"
+ .asciiz "..........827..........*................-....*..................110.883..................%.....56............111......872..................."
+ .asciiz "........................8.321....-............209.....578...583.....$.....948..548#..................868*678......871......................."
+ .asciiz "......658...264...........&....105......132............./...................*..................640..................*...........714........."
+ .asciiz ".........+.*.....................................................................608..............*....963*565.....472.......93...*........."
+ .asciiz "...*717....14.......................702............604.608......................*.....12....689..599.............................423........"
+ .asciiz "999.........................764......*.......$780.....*.......+.......%........406....*...............278*........600*23.....407.....964...."
+ .asciiz "...........%....308................183................../......758..&..360..........127.#696...50........................839*.....&.....$..."
+ .asciiz "......277..449....*............881.......822.....905...205.........345.......572@................../733....=..61...................796......"
+ .asciiz ".......#..........659...*.....=..........................................................................665...................292.........."
+ .asciiz "......................887.711.....560..........................11...213*434...................949....761......*856...233*996......%.965....."
+ .asciiz ".....699..../.............&....%......103...518...............................673......=.........*....@....149.............................."
+ .asciiz "............894......=......292..425.....#........@259....787..995..................927..813..326..............439.....379.547..292........."
+ .asciiz "....901............678.217......*..............................*.......289.346..875.........*.........653+......*......*....=.....$........."
+ .asciiz "......#........................56..887....&540..200...........824............&.....*.414=....629..............893..34.334................731"
+ .asciiz "...............476.......338........@..#............592..573*.....759...........598........$.........692..474.......*................304...."
+ .asciiz "..........................*..263*93...541....138......*..........*.....................260.187.......%...*.........436.................*...."
+ .asciiz ".....#..895............744.....................%.473...92........23..................$..#........853.....443......................12..339..."
+ .asciiz "...284...*...59*...131...............................................=....354.792...679.....649....*.......................994...%.........."
+ .asciiz ".......267............*...............176..............=.............743.........*......631......856................166.......*............."
+ .asciiz ".....................684.................@...........773....108...........617...965....*........................958............777.....767.."
+ .asciiz "..........572................#....&.............................51........@..........190..............694..882.#......511..788.............."
+ .asciiz "...96........%.....119..4.954....81..836....@.....671....161.................*.........................#..*.......730.%...*................."
+ .asciiz "....................@.................*...68..924...........*...644.......654.842..473.....449.............936.....*......305............980"
+ .asciiz "..........188....7..........672......596.........@........473......*..................*418....&.......302.........7...621.....476...938.*..."
+ .asciiz ".......@...*...........#824..*...303...........................%....486..........290..................*.....-907.....*.......*......*...686."
+ .asciiz "....869....976...478*.......56..*...........*..................415......97.@605.....................129............701....626....157........"
+ .asciiz ".....................455.......306.876......829............430..................956.15@.......302..........938.............................."
+ .asciiz "..........................43.......*..............$.......-.....998...106.......=.......486*....&.......+......................982.........."
+ .asciiz ".554......................*.......50.231.........409..............+...$.....*........72.....716.........51..445.....*284........*........350"
+ .asciiz ".........425............*.94..836......&..............#516..............775.701.....*............................744..........541......-...."
+ .asciiz "....*810..............34....................&....297..........#........*....................#.............899=..........972..........27....."
+ .asciiz "960........762.....................*........394........&355.401........347.....+853.....&...967............................*86..663........."
+ .asciiz "............*..........991......686.25.286.......&...................................653...........914........$.....580...........*........."
+ .asciiz "...#.....784......-.......*............*......498......*..........*..316........................&.&..........691.2.....*........91.........."
+ .asciiz "..791..............462....193..........8.............57.685.......90..........201............371.....242............996................579.."
+ .byte $ED
diff --git a/test/3.lua b/test/3.lua
new file mode 100644
index 0000000..6fdbdae
--- /dev/null
+++ b/test/3.lua
@@ -0,0 +1,13 @@
+utils = require "utils"
+
+utils.StartRun("3")
+
+utils.MemTest("@test", {{0x0C, "BE"}, {0x0D, "35"}, {0x0E, "08"}, {0x0F, "00"}})
+
+-- This test is either flaky or it takes a long ass time. Let's wait for a
+-- little while longer than usual.
+for i = 0, 300, 1 do
+ emu.frameadvance();
+end
+
+utils.EndRun()
diff --git a/test/defines.s b/test/defines.s
index 17c0221..cf15595 100644
--- a/test/defines.s
+++ b/test/defines.s
@@ -1,11 +1 @@
RUN_TESTS = 0
-
-.macro CALL_TESTS_ON_DONE
- .ifdef RUN_TESTS
- bit Globals::m_flags
- bvc :+
- @test:
- nop
- :
- .endif
-.endmacro
diff --git a/test/run.sh b/test/run.sh
index 2142ad1..f8eac6c 100644
--- a/test/run.sh
+++ b/test/run.sh
@@ -19,7 +19,7 @@ if [ -n "${GITHUB_ACTION}" ]; then
fi
# Run all the tests that we have on Lua.
-for name in $(seq 2); do
+for name in $(seq 3); do
DEBUG=1 make out/$name.nes
fceux --loadlua "$ROOT/test/$name.lua" "$ROOT/out/$name.nes"
done
diff --git a/test/utils.lua b/test/utils.lua
index c5ecd94..2cd713a 100644
--- a/test/utils.lua
+++ b/test/utils.lua
@@ -48,10 +48,9 @@ function utils.MemTest(label, addresses)
if expected == got then
io.write("OK\n")
else
- io.write("\n-> Test '".. label .."': FAIL\n")
+ io.write("FAIL\n")
io.write("Expected: ".. expected .. "\n")
io.write("Got: ".. got .. "\n")
- io.write("\n")
end
io.close(file)
end)
diff --git a/vendor/bcd16.s b/vendor/bcd16.s
index 452b294..7839eaf 100644
--- a/vendor/bcd16.s
+++ b/vendor/bcd16.s
@@ -13,6 +13,10 @@
.p02
+;; Define so you can better manage code that you want included whenever this
+;; feature has been included.
+BCD16_SUPPORT = 1
+
.exportzp bcdNum, bcdResult
.export bcdConvert