aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMiquel Sabaté Solà <msabate@suse.com>2023-12-03 10:41:39 +0100
committerMiquel Sabaté Solà <msabate@suse.com>2023-12-03 10:41:39 +0100
commitc0d6966592a0aaeda220fff1171f057ef14a7ea6 (patch)
tree195cd2573ee5ce423281385ae92bad1715f0c02f
parent03760c25d6a0609480c0ef5672ba0861f2838153 (diff)
downloadaoc2023.nes-c0d6966592a0aaeda220fff1171f057ef14a7ea6.tar.gz
aoc2023.nes-c0d6966592a0aaeda220fff1171f057ef14a7ea6.zip
Let's print the result to the screen
I have found and vendored a piece of code that allows me to convert a 16-bit number so it can be easily printed on screen. With this, let's be a bit more flashy and print the result to the screen. Signed-off-by: Miquel Sabaté Solà <msabate@suse.com>
-rw-r--r--assets/alphanum.chrbin0 -> 8192 bytes
-rw-r--r--assets/session.nss186
-rw-r--r--src/1.s176
-rw-r--r--vendor/bcd16.s124
4 files changed, 467 insertions, 19 deletions
diff --git a/assets/alphanum.chr b/assets/alphanum.chr
new file mode 100644
index 0000000..622eb8e
--- /dev/null
+++ b/assets/alphanum.chr
Binary files differ
diff --git a/assets/session.nss b/assets/session.nss
new file mode 100644
index 0000000..42f6b13
--- /dev/null
+++ b/assets/session.nss
@@ -0,0 +1,186 @@
+NSTssTXT
+
+BtnTiles=1
+BtnChecker=0
+BtnSelTiles=0
+BtnChrBank1=0
+BtnChrBank2=1
+BtnGridAll=0
+BtnGridTile=0
+BtnGridAtr=1
+BtnGridBlock=0
+BtnGridScr=0
+BtnPal=1
+BtnTypeIn=0
+BtnFrameAll=1
+BtnFrameSelected=0
+BtnFrameNone=0
+BtnSpriteSnap=0
+BtnSprite8x16=0
+BtnForce8x16=1
+MenuBestOffsets=0
+MenuLossy=0
+MenuThreshold=0
+MenuNoColorData=0
+MenuMetaSprAutoInc=0
+MenuMetaSprSkipZero=0
+MenuMetaSprMerge=0
+MenuSaveIncName=1
+MenuSaveIncAttr=1
+MenuSaveRLE=0
+VarTileViewTagBuf=0
+VarBgPalCur=1
+VarPalActive=0
+VarTileActive=54
+VarBankActive=4096
+VarPPUMask=0
+VarPPUMaskSet0=0
+VarPPUMaskSet1=0
+VarPPUMaskSet2=0
+VarPPUMaskSet3=0
+VarPalBank=0
+VarMetaSpriteActive=0
+VarSpriteActive=0
+VarSpriteGridX=64
+VarSpriteGridY=64
+VarNameW=32
+VarNameH=30
+VarNameViewX=0
+VarNameViewY=-1
+VarNameSelectionL=-1
+VarNameSelectionR=0
+VarNameSelectionT=-1
+VarNameSelectionB=0
+VarNameCopyW=-1
+VarNameCopyH=-1
+VarCHRSelectionL=6
+VarCHRSelectionR=7
+VarCHRSelectionT=3
+VarCHRSelectionB=4
+VarCHRCopyW=-1
+VarCHRCopyH=-1
+VarCHRCopyRect=1
+VarCHRSelectRect=1
+VarCHRBanks=4
+VarCHRBanksUndo=4
+VarCheckpoint_CHRBanks=4
+VarCheckpoint_CHRBanksUndo=4
+
+
+VarCHRSelected=00[36]0100[c9]
+
+
+Palette=0f3010000f0121310f0616260f0919290f1121310f1222320f1323330f1424340f1525350f1626360f1727370f1828380f1929390f1a2a3a0f1b2b3b0f1c2c3c
+
+
+PalUndo=0f3010000f0121310f0616260f0919290f1121310f1222320f1323330f1424340f1525350f1626360f1727370f1828380f1929390f1a2a3a0f1b2b3b0f1c2c3c
+
+
+CHRMain=00[1101]3c464a52623c00[a]182808[3]3e00[a]3c42023c407e00[a]3c420c02423c00[a]081828487e0800[a]7e407c02423c00[a]3e407c42[2]3c00[a]3e02040810[2]00[a]3c423c42[2]3c00[a]3c42[2]3e023c00[9]3c4299a1[2]99423c00[9]3c42[2]7e42[2]00[a]7c427c42[2]3c00[a]3c4240[2]423c00[a]7c42[4]7c00[a]7c407040[2]7c00[a]3c40[2]7040[2]00[a]3c42404e423c00[a]42[3]7e42[2]00[a]3e08[4]3e00[a]02[3]42[2]3c00[a]44487048444200[a]40[5]7e00[a]42665a42[3]00[a]4262524a464200[a]3c42[4]3c00[a]7c42[2]7c40[2]00[a]3c42[3]3c0600[a]3c42[2]7c444200[a]3e403c02[2]7c00[a]3e08[5]00[a]42[5]3c00[a]22[4]140800[a]42[3]5a664200[a]422418[2]244200[a]41221408[3]00[a]7e040810207e00[f]102000[e]18[2]00[c98]
+
+
+CHRCopy=00[1000]
+
+
+CHRUndo=00[1101]3c464a52623c00[a]182808[3]3e00[a]3c42023c407e00[a]3c420c02423c00[a]081828487e0800[a]7e407c02423c00[a]3e407c42[2]3c00[a]3e02040810[2]00[a]3c423c42[2]3c00[a]3c42[2]3e023c00[9]3c4299a1[2]99423c00[9]3c42[2]7e42[2]00[a]7c427c42[2]3c00[a]3c4240[2]423c00[a]7c42[4]7c00[a]7c407040[2]7c00[a]3c40[2]7040[2]00[a]3c42404e423c00[a]42[3]7e42[2]00[a]3e08[4]3e00[a]02[3]42[2]3c00[a]44487048444200[a]40[5]7e00[a]42665a42[3]00[a]4262524a464200[a]3c42[4]3c00[a]7c42[2]7c40[2]00[a]3c42[3]3c0600[a]3c42[2]7c444200[a]3e403c02[2]7c00[a]3e08[5]00[a]42[5]3c00[a]22[4]140800[a]42[3]5a664200[a]422418[2]244200[a]41221408[3]00[a]7e040810207e00[f]102000[e]18[2]00[c98]
+
+
+NameTable=00[12a]2a261f1b2d1f00311b232e36[3]00[288]
+
+
+NameCopy=00[3c0]
+
+
+NameUndo=00[12a]2a261f1b2d1f00311b232e36[2]00[289]
+
+
+AttrTable=00[40]
+
+
+AttrCopy=00[40]
+
+
+AttrUndo=00[40]
+
+
+MetaSprites=ff[10000]
+
+
+32_TileCollisionProperties=00000000[200]
+
+
+32_TileCollisionPropertiesUndo=00000000[200]
+
+
+PropertyConditions=1[2]0[2]1[2]0[2]1[2]0[2]1[2]0[2]1[2]0[2]1[2]0[2]1[2]0[2]1[2]0[2]
+
+
+PropertyConditionsUndo=1[2]0[2]1[2]0[2]1[2]0[2]1[2]0[2]1[2]0[2]1[2]0[2]1[2]0[2]1[2]0[2]
+
+
+TilePropConditionType=00[7]02
+
+
+TilePropConditionTypeUndo=00[7]02
+
+
+Checkpoint_Palette=00[40]
+
+
+Checkpoint_PalUndo=00[40]
+
+
+Checkpoint_CHRMain=00[2000]
+
+
+Checkpoint_CHRUndo=00[2000]
+
+
+Checkpoint_NameTable=00[3c0]
+
+
+Checkpoint_NameUndo=00[3c0]
+
+
+Checkpoint_AttrTable=00[40]
+
+
+Checkpoint_AttrUndo=00[40]
+
+
+Checkpoint_MetaSprites=ff[10000]
+
+
+Checkpoint_32_TileCollisionProperties=00000000[200]
+
+
+Checkpoint_32_TileCollisionPropertiesUndo=00000000[200]
+
+
+Checkpoint_PropertyConditions=[20]
+
+
+Checkpoint_PropertyConditionsUndo=[20]
+
+
+Checkpoint_TilePropConditionType=00[7]02
+
+
+Checkpoint_TilePropConditionTypeUndo=00[7]02
+propertyCHRlabel0=solid
+propertyCHRlabel1=dangerous
+propertyCHRlabel2=unlabeled2
+propertyCHRlabel3=unlabeled3
+propertyCHRlabel4=unlabeled4
+propertyCHRlabel5=unlabeled5
+propertyCHRlabel6=escape bit
+propertyCHRlabel7=global condition
+MetaSpriteBankName=session
+
+FilterCHR=1
+FilterName=1
+FileNameCHR=C:\users\mssola\Desktop\src\github.com\mssola\aoc2023.nes\assets\alphanum.chr
+FileNameName=
+FileNamePal=
+FileNameMetaSpriteBank=
+FileNameTileProps=
diff --git a/src/1.s b/src/1.s
index 2980951..202c3ee 100644
--- a/src/1.s
+++ b/src/1.s
@@ -2,13 +2,8 @@
;; Day 1 https://adventofcode.com/2023/day/1
;;
;; This program then iterates over the array on `data` and computes the value on
-;; each row, then accumulating it into a sum variable. This variable is stored
-;; as a 16-bit number on $08-$09. In order to see the actual result, in FCEUX,
-;; for example, you need to go to `Tools -> RAM Watch`, and set a watch on
-;; address $08 which is unsigned and 2-bytes long. This will show you the end
-;; result after a couple of seconds (yes, it's a big ass computation for poor
-;; old NES, and it's quite fast considering that we are not rendering anything
-;; on screen!). The result must be: `54953`.
+;; each row, then accumulating it into a sum variable. The end result will be
+;; printed to the screen, which must be `54953`.
;; Luckily for us, good ol' NROM can fit the data set for this exercise :D
.segment "HEADER"
@@ -24,6 +19,8 @@
.addr nmi, reset, irq
.segment "CHARS"
+ .incbin "../assets/alphanum.chr"
+
.segment "STARTUP"
.segment "CODE"
@@ -32,6 +29,7 @@
.include "../include/ppu.s"
.include "../include/reset.s"
.include "../include/globals.s"
+.include "../vendor/bcd16.s"
;; "Variables" used by this program.
.scope Vars
@@ -80,23 +78,24 @@
;; The main function will be called at the end of the `reset` vector as defined
;; in `include/reset.s`.
.proc main
- cli
-
- lda #%10010000
- sta PPU::CONTROL
- lda #%00011110
- sta PPU::MASK
-
- ;; Initialize variables being used for this program.
+ ;; Initialize palettes and variables being used for this program.
+ jsr init_palettes
jsr Vars::init
;; This program uses two flags:
- ;; - 7 (`render`): whether NMI-code can render stuff on screen. Unused but
- ;; reserved out of habit.
+ ;; - 7 (`render`): whether NMI-code can render stuff on screen.
;; - 6 (`done`): whether the computation has been done.
- lda #0
+ ;; 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:
jsr compute_next
jmp @loop
@@ -187,6 +186,17 @@
lda #%01000000
ora Globals::m_flags
sta Globals::m_flags
+
+ ;; Now that we are done, convert the 16-bit number into separate bytes so it
+ ;; can be rendered on NMI-code.
+ lda Vars::m_sum + 1
+ sta bcdNum
+ lda Vars::m_sum
+ sta bcdNum + 1
+ jsr bcdConvert
+
+ ;; Because of the previous, we can set the `render` flag again.
+ SET_RENDER_FLAG
@end:
rts
.endproc
@@ -221,8 +231,136 @@
rts
.endproc
-;; Unused.
+;; init_palettes copies all the palettes into the proper PPU address.
+.proc init_palettes
+ PPU_ADDR $3F00
+
+ ldx #0
+@load_palettes_loop:
+ lda palettes, x
+ sta PPU::DATA
+ inx
+ cpx #$20
+ bne @load_palettes_loop
+ rts
+palettes:
+ ;; Background (only first one used)
+ .byte $0F, $30, $10, $00
+ .byte $0F, $00, $00, $00
+ .byte $0F, $00, $00, $00
+ .byte $0F, $00, $00, $00
+
+ ;; Foreground (unused)
+ .byte $0F, $00, $00, $00
+ .byte $0F, $00, $00, $00
+ .byte $0F, $00, $00, $00
+ .byte $0F, $00, $00, $00
+.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 the given result.
+ bit Globals::m_flags
+ bvs :+
+ jsr print_message
+ jmp :++
+:
+ jsr print_result
+:
+
+ ;; 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
+
+;; Simply print "Please wait..." to the screen.
+.proc print_message
+ WRITE_PPU_DATA $2129, $2A
+ WRITE_PPU_DATA $212A, $26
+ WRITE_PPU_DATA $212B, $1F
+ WRITE_PPU_DATA $212C, $1B
+ WRITE_PPU_DATA $212D, $2D
+ WRITE_PPU_DATA $212E, $1F
+
+ WRITE_PPU_DATA $2130, $31
+ WRITE_PPU_DATA $2131, $1B
+ WRITE_PPU_DATA $2132, $23
+ WRITE_PPU_DATA $2133, $2E
+ WRITE_PPU_DATA $2134, $36
+ WRITE_PPU_DATA $2135, $36
+ WRITE_PPU_DATA $2136, $36
+
+ rts
+.endproc
+
+;; Print the result on screen. This assumes that `bcdResult` already contains
+;; the proper data.
+.proc print_result
+ ;; Clear tiles that were written by `print_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 $2133, $00
+ WRITE_PPU_DATA $2134, $00
+ WRITE_PPU_DATA $2135, $00
+ WRITE_PPU_DATA $2136, $00
+
+ ;; And loop so PPU::ADDRESS $2E21-$2E32 has the data as stored on bcdResult,
+ ;; which is the binary to decimal conversion result when the final
+ ;; computation was done.
+ ldx #4
+ ldy #$2E
+@loop:
+ ;; PPU address.
+ bit PPU::STATUS
+ lda #$21
+ sta PPU::ADDRESS
+ sty PPU::ADDRESS
+
+ ;; PPU data.
+ lda bcdResult, x
+ clc
+ adc #$10
+ sta PPU::DATA
+ dex
+ iny
+ cpy #$33
+ bne @loop
+
+ rts
+.endproc
+
+;; Unused.
irq:
rti
diff --git a/vendor/bcd16.s b/vendor/bcd16.s
new file mode 100644
index 0000000..452b294
--- /dev/null
+++ b/vendor/bcd16.s
@@ -0,0 +1,124 @@
+; bcd16.s
+; version 20060201
+;
+; Copyright (C) 2006 Damian Yerrick
+;
+; Copying and distribution of this file, with or without
+; modification, are permitted in any medium without royalty provided
+; the copyright notice and this notice are preserved in any source
+; code copies. This file is offered as-is, without any warranty.
+;
+; @mssola: The memory addresses being used here have been modified so they don't
+; clash with my programs (from $0x to $8x).
+
+.p02
+
+.exportzp bcdNum, bcdResult
+.export bcdConvert
+
+; bcdConvert
+;
+; Given a number in bcdNum (16-bit), converts it to 5 decimal digits
+; in bcdResult. Unlike most 6502 binary-to-decimal converters, this
+; subroutine doesn't use the decimal mode that was removed from the
+; 2A03 variant of the 6502 processor.
+;
+; For each value of n from 4 to 1, it compares the number to 8*10^n,
+; then 4*10^n, then 2*10^n, then 1*10^n, each time subtracting if
+; possible. After finishing all the comparisons and subtractions in
+; each decimal place value, it writes the digit to the output array
+; as a byte value in the range [0, 9]. Finally, it writes the
+; remainder to element 0.
+;
+; Extension to 24-bit and larger numbers is straightforward:
+; Add a third bcdTable, increase BCD_BITS, and extend the
+; trial subtraction.
+
+; Constants _________________________________________________________
+; BCD_BITS
+; The highest possible number of bits in the BCD output. Should
+; roughly equal 4 * log10(2) * x, where x is the width in bits
+; of the largest binary number to be put in bcdNum.
+; bcdTableLo[y], bcdTableHi[y]
+; Contains (1 << y) converted from BCD to binary.
+BCD_BITS = 19
+
+; Variables _________________________________________________________
+; bcdNum (input)
+; Number to be converted to decimal (16-bit little endian).
+; Overwritten.
+; bcdResult (output)
+; Decimal digits of result (5-digit little endian).
+; X
+; Offset of current digit being worked on.
+; Y
+; Offset into bcdTable*.
+; curDigit
+; The lower holds the digit being constructed.
+; The upper nibble contains a sentinel value; when a 1 is shifted
+; out, the byte is complete and should be copied to result.
+; (This behavior is called a "ring counter".)
+; Overwritten.
+; b
+; Low byte of the result of trial subtraction.
+; Overwritten.
+bcdNum = $80
+bcdResult = $82
+curDigit = $87
+b = $82
+
+;
+; Completes within 670 cycles.
+;
+
+bcdConvert:
+ lda #$80 >> ((BCD_BITS - 1) & 3)
+ sta curDigit
+ ldx #(BCD_BITS - 1) >> 2
+ ldy #BCD_BITS - 5
+
+@loop:
+ ; Trial subtract this bit to A:b
+ sec
+ lda bcdNum
+ sbc bcdTableLo,y
+ sta b
+ lda bcdNum+1
+ sbc bcdTableHi,y
+
+ ; If A:b > bcdNum then bcdNum = A:b
+ bcc @trial_lower
+ sta bcdNum+1
+ lda b
+ sta bcdNum
+@trial_lower:
+
+ ; Copy bit from carry into digit and pick up
+ ; end-of-digit sentinel into carry
+ rol curDigit
+ dey
+ bcc @loop
+
+ ; Copy digit into result
+ lda curDigit
+ sta bcdResult,x
+ lda #$10 ; Empty digit; sentinel at 4 bits
+ sta curDigit
+ ; If there are digits left, do those
+ dex
+ bne @loop
+ lda bcdNum
+ sta bcdResult
+ rts
+
+bcdTableLo:
+ .byt <10, <20, <40, <80
+ .byt <100, <200, <400, <800
+ .byt <1000, <2000, <4000, <8000
+ .byt <10000, <20000, <40000
+
+bcdTableHi:
+ .byt >10, >20, >40, >80
+ .byt >100, >200, >400, >800
+ .byt >1000, >2000, >4000, >8000
+ .byt >10000, >20000, >40000