Skimming through this, this is the first piece of code that my eyes drilled into more deeply:
LCD__clear_video_ram:
pha ; preserve A via stack
tya ; same for Y
pha
ldy #$20 ; set index to 32
.loop:
lda #$20 ; set character to 'space'
sta VIDEO_RAM,Y ; clean video ram
dey ; decrease index
bne .loop ; are we done? no, repea
sta VIDEO_RAM ; yes, write zero'th location manually
pla ; restore Y
tay
pla ; restore A
rts
Surely we don't need to keep loading the space character into A on every iteration?
Since Y starts at a hard-coded value that is (well) below $80, this could use "bpl .loop" and drop the "sta VIDEO_RAM" special case.
You are more than right. This is just my first assembly project in 20 years, put together from scratch in a couple of days. Therefor I am more than greatful for every constructive hint, that helps me improve. Thanks!
You probably know, but it also would help readability and portability if you created separate constants SPACE and SCREENSIZE (or similar)
Also, if you want to go for idiomatic 6502 code, rather than readability:
- you want to optimize for size and speed by looping down from C to zero (rather than looping up from zero to C) where possible (because you don’t need to do a CMP to compare with zero)
- LCD__print wastes memory and CPU cycles. It can fall-through to LCD__print_with_offset, and that could fall-through to LCD_render,
The 65C02 does (as well as AFAIK the 6510) if one compiles VASM with the according flags. Ben decided not to do so, neither did I for the feeling of good old times. Why make it easy ;)
Since Y starts at a hard-coded value that is (well) below $80, this could use "bpl .loop" and drop the "sta VIDEO_RAM" special case.
In .select_option, I'd looking into doing a jump table. Ideas here: https://wiki.nesdev.com/w/index.php/Jump_table