diff options
| -rw-r--r-- | assets/alphanum.chr | bin | 0 -> 8192 bytes | |||
| -rw-r--r-- | assets/session.nss | 186 | ||||
| -rw-r--r-- | src/1.s | 176 | ||||
| -rw-r--r-- | vendor/bcd16.s | 124 |
4 files changed, 467 insertions, 19 deletions
diff --git a/assets/alphanum.chr b/assets/alphanum.chr Binary files differnew file mode 100644 index 0000000..622eb8e --- /dev/null +++ b/assets/alphanum.chr 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=
@@ -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 |
