136 lines
3.8 KiB
NASM
136 lines
3.8 KiB
NASM
; Subroutines
|
|
; ----------------------------------------------------------------------
|
|
; Do some math to calculate tile address in video memory
|
|
; using x,y coordinates
|
|
; Formula: addr = $400 + y * SCREEN_W + x
|
|
calcTileMem:
|
|
; Save registers
|
|
pha
|
|
txa
|
|
pha
|
|
tya
|
|
pha
|
|
|
|
; Set tileMem to $400
|
|
lda #$00
|
|
sta tileMem
|
|
lda #$04
|
|
sta tileMem + 1
|
|
|
|
ldy calcTileY ; Get head Y coordinate
|
|
calcTileMult:
|
|
tya
|
|
beq calcTileEnd ; if Y is equal to zero, nothing to do, just skip moltiplication, else...
|
|
dey ; decrement Y
|
|
clc
|
|
lda #SCREEN_W ; A = screen width = 40
|
|
adc tileMem ; A = screen width + tileMem (low)
|
|
sta tileMem ; update tileMem (low)
|
|
lda #0 ; do the same with higher byte: A = 0
|
|
adc tileMem + 1 ; add (eventual) carry
|
|
sta tileMem + 1 ; update tileMem (high)
|
|
jmp calcTileMult ; do again until Y == 0
|
|
calcTileEnd: ; now multiplication is ended, so add X
|
|
lda calcTileX
|
|
adc tileMem
|
|
sta tileMem
|
|
lda #0
|
|
adc tileMem + 1
|
|
sta tileMem + 1
|
|
|
|
; Restore old registers
|
|
pla
|
|
tay
|
|
pla
|
|
tax
|
|
pla
|
|
|
|
rts
|
|
|
|
; Print a byte in hexadecimal
|
|
; A input register for byte to print
|
|
; Y input register for printing colum (on first line)
|
|
printByte:
|
|
; Copy parameter also in X
|
|
tax
|
|
|
|
lsr ; Take most significant nibble
|
|
lsr
|
|
lsr
|
|
lsr
|
|
jsr printDigit
|
|
sta $400,y ; print msb char
|
|
|
|
txa ; Take least significant nibble (use previous copy)
|
|
and #$0f
|
|
jsr printDigit
|
|
sta $401,y ; print lsb char
|
|
|
|
rts
|
|
|
|
; Transform a base-36 digit into a Commodore screen code
|
|
; Leave input digit in accumulator; returns output screen code in accumulator
|
|
printDigit:
|
|
cmp #10
|
|
bcs printDigitL ; if it is not a decimal digit, then go to printDigitL
|
|
clc ; it is a decimal digit! Just add `0` (48)
|
|
adc #48
|
|
ora #$80 ; reverse color
|
|
rts
|
|
printDigitL: ; it is not a decimal digit, then...
|
|
sec
|
|
sbc #10 ; take away 10
|
|
clc
|
|
adc #1 ; add 1, so you obtain something in [A-F]
|
|
ora #$80 ; reverse color
|
|
rts
|
|
|
|
; Print null-terminated string on status bar
|
|
; address of string is given in input using memory location printStatusString
|
|
printStatus:
|
|
ldy #0
|
|
printStatusLoop:
|
|
lda (printStatusString),y
|
|
beq printStatusEnd
|
|
cmp #$20
|
|
bne printStatusSkipSpace
|
|
lda #$60
|
|
printStatusSkipSpace:
|
|
sec
|
|
sbc #$40 ; convert from standard ASCII to Commodore screen code
|
|
ora #$80 ; reverse color
|
|
sta $413,y
|
|
iny
|
|
jmp printStatusLoop
|
|
printStatusEnd:
|
|
rts
|
|
|
|
; Print string for intro
|
|
; Input parameters:
|
|
; printIntroString pointer to string to be printed (source)
|
|
; introScreenStart pointer to text video memory on screen where to print (dest)
|
|
printIntro:
|
|
ldy #0
|
|
printIntroLoop:
|
|
lda (printIntroString),y ; get char from string
|
|
beq printIntroEnd ; if zero, then end (string must be null-terminated)
|
|
cmp #$40 ; is char greater or equal to #$40 = #64 = `@' ?
|
|
bcc printIntroEndCheck ; if not, it is less, thus it must be
|
|
; a full stop, comma, colon or something
|
|
; that actually has the same value in both
|
|
; true ASCII and in PET screen codes
|
|
; otherwise, it is greater than `@`, so must
|
|
; subtract 64 because CBM and its encodings
|
|
; are simply a big shit
|
|
sec
|
|
sbc #$40
|
|
|
|
printIntroEndCheck:
|
|
sta (introScreenStart),y ; put screen code to screen
|
|
iny ; next char in string
|
|
jmp printIntroLoop
|
|
printIntroEnd:
|
|
rts
|
|
|
|
|