Welcome.
I don't know if this is a bit premature, but I'd like to nudge you to look into
macros as soon as you're ready. Your first loop there for example,
Code:
SYS_INIT:
LDX #<[CHAR_ROM+$400-8] ; Store Low Byte of Char ROM (Last Character) in ZP 05
STX $40
LDX #>[CHAR_ROM+$400-8] ; Store High Byte of Char ROM (Last Character) in ZP 06
STX $41
LDX #$7F ; Set X counter to 127 (128 total)
.loop
STX $20 ; Set Location of this character
LDA $40 ; Set Address of Char Rom in ZP 40
STA $10
LDA $41
STA $11
JSR DVGA_STORECHAR ; Put Address of Character in ZP 10 and Location you want it stored in ZP 20
LDA #$08 ; Put 8 bytes of dec
STA $10 ; Store it in param (ZP10)
JSR MEM_SAFE_ZP40_DEC
DEX ; deduct 1 from the location
BPL .loop ; loop until we hit go through 0 to FF
JSR DVGA_BLANKSCREEN ; Blank the Screen
RTS
can be shortened to:
Code:
SYS_INIT: PUT2 CHAR_ROM+$400-8, INTO, $40 ; The PUT2 macro uses A instead of X; but you re-init A and X below anyway.
FOR_X $7F, DOWN_TO, NEG_NRs ; Set X counter to 127 (128 total, dropping through when X dec's to $FF)
STX $20 ; Set Location of this character
COPY2 $40, TO, $10 ; Set Address of Char Rom in ZP 40
JSR DVGA_STORECHAR ; Put addr of Char in ZP 10 and Location you want it stored in ZP 20
PUT 8, INTO, $10 ; Put 8 bytes of dec and Store it in param (ZP10)
JSR MEM_SAFE_ZP40_DEC
NEXT_X ; NEXT_X assembles DEX, BPL because that's what FOR_X and its parameters dictated.
JMP DVGA_BLANKSCREEN ; Blank the Screen (Combine JSR, RTS, saving one byte and 9 clocks.
and this last version brings a slight improvement in both performance and memory. The macros offload some of your work to the assembler, work that you were doing by hand before. You're still in total control since you write the macros (or adapt others' macros) and you know what they do; but you don't have to look at the mundane innards every time anymore. You become more productive, and since you can see what you're doing better, you get fewer bugs to fix.
The first small change is that "PUT2" uses LDA# instead of LDX# which I figured is no problem because you re-initialize both A and X right below anyway, without re-using what's in either of them. If you really had to have it use X, you could write another version of PUT2, or re-write the existing one to use a parameter telling which register to use. The other change is that I removed your RTS by replacing your last JSR with JMP, using the RTS at the end of subroutine DVGA_BLANKSCREEN to return to the right place. The only time you can't do that is when passing parameters on the hardware stack, since the routines need a consistent number of return addresses on the stack above the data so they can find the data where it's expected. (Passing parameters on the hardware stack (or even on a virtual stack) can remove the need for a lot of variables though. This is covered in my
stack treatise, especially
section 6.)
If you don't feel ready for the macros yet, no problem. Just keep it in the back of your mind for later.
If you have a 65c02, you can shorten things up further. A couple of key things that pop out at me right away in your code is that LDA#0, STA can be replaced with just STZ (STore Zero) which is shorter and does not disturb any registers; and the 65c02 can push and pull the index registers without going through A. I have a list of the differences between the CMOS and NMOS 6502
here.
If your assembler can handle lots of bytes on each .BYTE line, you can shorten up your source code a lot there, too. The part at the end becomes:
Code:
CHAR_ROM: ; ASCII encoded - 128 Chars
.BYTE @00000000, @00000000, @00000000, @00000000, @00000000, @00000000, @00000000, @00000000
.BYTE @00000000, @00111110, @01000001, @01010101, @01000001, @01010101, @01001001, @00111110
.BYTE @00000000, @00111110, @01111111, @01101011, @01111111, @01101011, @01110111, @00111110
.BYTE @00000000, @00100010, @01110111, @01111111, @01111111, @00111110, @00011100, @00001000
.BYTE @00000000, @00001000, @00011100, @00111110, @01111111, @00111110, @00011100, @00001000
.BYTE @00000000, @00001000, @00011100, @00101010, @01111111, @00101010, @00001000, @00011100
.BYTE @00000000, @00001000, @00011100, @00111110, @01111111, @00111110, @00001000, @00011100
.BYTE @00000000, @00000000, @00011100, @00111110, @00111110, @00111110, @00011100, @00000000
.BYTE @11111111, @11111111, @11100011, @11000001, @11000001, @11000001, @11100011, @11111111
.BYTE @00000000, @00000000, @00011100, @00100010, @00100010, @00100010, @00011100, @00000000
instead of the 90 or so lines you had.