2016-02-17 12:35:00 -08:00
|
|
|
; ca65
|
|
|
|
.feature c_comments
|
2016-02-18 12:34:00 -08:00
|
|
|
|
2016-02-18 12:48:00 -08:00
|
|
|
/* Version 13
|
|
|
|
printm - a printf replacement for 6502
|
|
|
|
Michael Pohroeski
|
|
|
|
|
2016-02-18 12:34:00 -08:00
|
|
|
|
|
|
|
Problem:
|
|
|
|
We want to print this:
|
|
|
|
|
|
|
|
.byte "X=## Y=### $=####:@@ %%%%%%%%~????????"
|
|
|
|
|
|
|
|
without having to waste marking up literals with an escape character
|
|
|
|
|
|
|
|
Why printf() on the 6502 sucks:
|
|
|
|
|
|
|
|
- is bloated by using a meta-character '%' instead of the high bit
|
|
|
|
- doesn't provide a standard way to print binary *facepalm*
|
|
|
|
- doesn't provide a standard way to print a deferenced pointer
|
|
|
|
- 2 digit, 3 digit and 5 digit decimals requiring wasting "width" characters
|
|
|
|
e.g. %2d, %3d, %5d
|
|
|
|
When a single character would work instead.
|
|
|
|
|
|
|
|
Solution:
|
|
|
|
|
|
|
|
Here is a micro replacement, printm()
|
|
|
|
|
|
|
|
* Literals have the high byte set (APPLE text)
|
|
|
|
* Meta characters have the high bit cleared (ASCII)
|
|
|
|
|
|
|
|
x Hex - print 2 Byte
|
|
|
|
$ Hex - print 4 Byte
|
|
|
|
|
|
|
|
@ Ptr - print hex byte at 16-bit pointer
|
|
|
|
& Ptr - print hex word at 16-bit pointer
|
|
|
|
|
|
|
|
# Dec - Print 1 Byte in decimal (max 2 digits)
|
|
|
|
d Dec - Print 2 Byte in decimal (max 3 digits)
|
|
|
|
u Dec - Print 2 Byte in decimal (max 5 digits)
|
|
|
|
b Dec - Print signed byte
|
|
|
|
|
|
|
|
% Bin 1 Byte
|
|
|
|
? Bin 1 Byte but 1's are printed in inverse
|
|
|
|
|
|
|
|
a Str - APPLE text (high bit set), last char is ASCII
|
|
|
|
s Str - C string, zero terminated
|
|
|
|
p Str - Pascal string, first character is string length
|
|
|
|
|
|
|
|
Note: The dummy address $C0DE is to force the assembler
|
|
|
|
to generate a 16-bit address instead of optimizing a ZP operand
|
|
|
|
|
|
|
|
To toggle features on / off:
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
ENABLE_BIN = 0
|
|
|
|
ENABLE_DEC = 0
|
|
|
|
ENABLE_BYTE = 0 ; requires ENABLE_DEC
|
|
|
|
ENABLE_HEX = 0
|
|
|
|
ENABLE_PTR = 1 ; requires ENABLE_HEX
|
|
|
|
ENABLE_STR = 1
|
|
|
|
|
|
|
|
|
2016-02-17 12:35:00 -08:00
|
|
|
.feature labels_without_colons
|
|
|
|
.feature leading_dot_in_identifiers
|
|
|
|
; 65C02
|
|
|
|
.PC02
|
|
|
|
|
|
|
|
; Force APPLE 'text' to have high bit on
|
|
|
|
; Will display as NORMAL characters
|
|
|
|
.macro APPLE text
|
|
|
|
.repeat .strlen(text), I
|
|
|
|
.byte .strat(text, I) | $80
|
|
|
|
.endrep
|
|
|
|
.endmacro
|
|
|
|
|
2016-02-18 12:19:00 -08:00
|
|
|
; Force APPLE 'text' with high bit on but last character has high bit off
|
|
|
|
; Will display as NORMAL characters (last character will appear FLASHING)
|
|
|
|
; Merlin: Macro Assembler -- Dextral Character Inverted
|
|
|
|
.macro DCI text
|
|
|
|
.repeat .strlen(text)-1, I
|
|
|
|
.byte .strat(text, I) | $80
|
|
|
|
.endrep
|
|
|
|
.byte .strat(text, .strlen(text)-1) & $7F
|
|
|
|
.endmacro
|
|
|
|
|
2016-02-17 12:35:00 -08:00
|
|
|
; Force ASCII 'text' to be control chars: $00..$1F
|
|
|
|
; Will display as INVERSE characters
|
|
|
|
.macro CTRL text
|
|
|
|
.repeat .strlen(text), I
|
|
|
|
.byte .strat(text, I) & $1F
|
|
|
|
.endrep
|
|
|
|
.endmacro
|
|
|
|
|
|
|
|
; Force ASCII 'text' to be control chars: $00..$3F
|
|
|
|
; Will display as INVERSE characters
|
|
|
|
.macro INV text
|
|
|
|
.repeat .strlen(text), I
|
|
|
|
.byte .strat(text, I) & $3F
|
|
|
|
.endrep
|
|
|
|
.endmacro
|
|
|
|
|
2016-02-18 12:19:00 -08:00
|
|
|
.macro PASCAL text
|
|
|
|
.byte .strlen(text)
|
|
|
|
APPLE text
|
|
|
|
.endmacro
|
|
|
|
|
2016-02-17 12:35:00 -08:00
|
|
|
.macro db val
|
|
|
|
.byte val
|
|
|
|
.endmacro
|
|
|
|
|
|
|
|
.macro dw val
|
|
|
|
.word val
|
|
|
|
.endmacro
|
|
|
|
|
|
|
|
.macro ds bytes
|
|
|
|
.res bytes
|
|
|
|
.endmacro
|
|
|
|
|
2016-02-18 12:19:00 -08:00
|
|
|
HOME = $FC58
|
|
|
|
TABV = $FB5B
|
2016-02-17 12:35:00 -08:00
|
|
|
|
2016-02-18 12:19:00 -08:00
|
|
|
; printm pointer for PrintPtr2, PrintPtr4, PrintStrA, PrintStrC, PrintStrP
|
|
|
|
_temp = $FE
|
|
|
|
|
|
|
|
__MAIN = $4000
|
2016-02-18 07:48:00 -08:00
|
|
|
; DOS3.3 meta -- remove these 2 if running under ProDOS
|
|
|
|
.word __MAIN ; 2 byte BLOAD address
|
|
|
|
.word __END - __MAIN ; 2 byte BLOAD size
|
2016-02-17 12:35:00 -08:00
|
|
|
|
2016-02-18 12:19:00 -08:00
|
|
|
/*
|
|
|
|
|
|
|
|
Output:
|
|
|
|
|
|
|
|
X=39 Y=191 $=2345:D5 11010101~10101011
|
|
|
|
|
|
|
|
Byte=-128 -001 000 001 127
|
2016-02-17 12:35:00 -08:00
|
|
|
|
2016-02-18 12:19:00 -08:00
|
|
|
Strings: 'HELLO','WORLD'
|
2016-02-17 12:35:00 -08:00
|
|
|
|
2016-02-18 12:19:00 -08:00
|
|
|
Apple: 'HOME' Pascal: 'String Len 13'
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
.org __MAIN ; .org must come after header else offsets are wrong
|
|
|
|
; Demo printm
|
2016-02-17 15:02:00 -08:00
|
|
|
JSR HOME
|
|
|
|
|
|
|
|
LDA #$D5
|
2016-02-18 12:19:00 -08:00
|
|
|
|
|
|
|
LDX #$45
|
|
|
|
LDY #$23
|
|
|
|
STX DATA+6
|
|
|
|
STY DATA+7
|
|
|
|
STX DATA+8
|
|
|
|
STY DATA+9
|
|
|
|
|
|
|
|
STX _HgrAddr+1
|
|
|
|
STY _HgrAddr+2
|
|
|
|
_HgrAddr
|
|
|
|
STA $C0DE
|
|
|
|
|
|
|
|
STA DATA+10
|
2016-02-17 15:02:00 -08:00
|
|
|
JSR ReverseByte
|
2016-02-18 12:19:00 -08:00
|
|
|
STA DATA+12
|
2016-02-17 15:02:00 -08:00
|
|
|
|
2016-02-18 12:48:00 -08:00
|
|
|
.if ENABLE_BIN || ENABLE_DEC || ENABLE_HEX
|
2016-02-18 12:19:00 -08:00
|
|
|
LDY #0
|
|
|
|
JSR VTABY
|
2016-02-17 15:02:00 -08:00
|
|
|
LDX #<DATA ; Low Byte of Address
|
|
|
|
LDY #>DATA ; High Byte of Address
|
|
|
|
JSR PrintM
|
2016-02-18 12:48:00 -08:00
|
|
|
.endif
|
2016-02-18 09:56:00 -08:00
|
|
|
|
2016-02-18 12:48:00 -08:00
|
|
|
.if ENABLE_BYTE
|
2016-02-18 12:19:00 -08:00
|
|
|
LDY #2
|
|
|
|
JSR VTABY
|
2016-02-18 09:56:00 -08:00
|
|
|
LDX #<DATA2
|
|
|
|
LDY #>DATA2
|
|
|
|
JSR PrintM
|
2016-02-18 12:48:00 -08:00
|
|
|
.endif ; ENABLE_BYTE
|
2016-02-18 09:56:00 -08:00
|
|
|
|
2016-02-18 12:48:00 -08:00
|
|
|
.if ENABLE_STR
|
2016-02-18 12:19:00 -08:00
|
|
|
LDY #4
|
|
|
|
JSR VTABY
|
|
|
|
LDX #<DATA3
|
|
|
|
LDY #>DATA3
|
|
|
|
JSR PrintM
|
|
|
|
|
|
|
|
LDY #6
|
|
|
|
JSR VTABY
|
|
|
|
LDX #<DATA4
|
|
|
|
LDY #>DATA4
|
|
|
|
JSR PrintM
|
2016-02-18 12:48:00 -08:00
|
|
|
.endif ; ENABLE_STR
|
2016-02-18 12:19:00 -08:00
|
|
|
|
|
|
|
LDA #8
|
|
|
|
JMP TABV
|
2016-02-17 15:02:00 -08:00
|
|
|
|
|
|
|
ReverseByte
|
|
|
|
LDX #8
|
2016-02-18 12:19:00 -08:00
|
|
|
STA $FF ; temp working byte
|
2016-02-17 15:02:00 -08:00
|
|
|
ReverseBit
|
2016-02-18 12:19:00 -08:00
|
|
|
ASL $FF ; temp working byte
|
2016-02-17 15:02:00 -08:00
|
|
|
ROR
|
|
|
|
DEX
|
|
|
|
BNE ReverseBit
|
|
|
|
RTS
|
2016-02-17 12:35:00 -08:00
|
|
|
|
2016-02-18 12:19:00 -08:00
|
|
|
VTABY
|
|
|
|
LDA SCREEN_LO,Y
|
|
|
|
STA PutChar+1
|
|
|
|
LDA SCREEN_HI,Y
|
|
|
|
ORA #$04 ; TXT page 1
|
|
|
|
STA PutChar+2
|
|
|
|
RTS
|
|
|
|
|
|
|
|
; Y Lookup Table for 40x24 Text Screen
|
|
|
|
SCREEN_LO
|
|
|
|
.byte $00, $80, $00, $80
|
|
|
|
.byte $00, $80, $00, $80
|
|
|
|
|
|
|
|
.byte $28, $A8, $28, $A8
|
|
|
|
.byte $28, $A8, $28, $A8
|
|
|
|
|
|
|
|
.byte $50, $D0, $50, $D0
|
|
|
|
.byte $50, $D0, $50, $D0
|
|
|
|
SCREEN_HI
|
|
|
|
.byte $00, $00, $01, $01
|
|
|
|
.byte $02, $02, $03, $03
|
|
|
|
|
|
|
|
.byte $00, $00, $01, $01
|
|
|
|
.byte $02, $02, $03, $03
|
|
|
|
|
|
|
|
.byte $00, $00, $01, $01
|
|
|
|
.byte $02, $02, $03, $03
|
|
|
|
|
2016-02-17 12:35:00 -08:00
|
|
|
TEXT
|
2016-02-18 09:56:00 -08:00
|
|
|
;byte "X=## Y=ddd $=xxxx:@@ %%%%%%%%~????????"
|
2016-02-17 12:35:00 -08:00
|
|
|
APPLE "X="
|
2016-02-17 15:02:00 -08:00
|
|
|
.byte "#"
|
|
|
|
APPLE " Y="
|
2016-02-17 15:42:00 -08:00
|
|
|
.byte "d"
|
2016-02-17 15:02:00 -08:00
|
|
|
APPLE " $="
|
|
|
|
.byte "x"
|
|
|
|
APPLE ":"
|
|
|
|
.byte "@"
|
|
|
|
APPLE " "
|
|
|
|
.byte "%"
|
2016-02-18 12:48:00 -08:00
|
|
|
APPLE "~"
|
2016-02-17 15:02:00 -08:00
|
|
|
.byte "?"
|
2016-02-17 12:35:00 -08:00
|
|
|
.byte 0
|
|
|
|
|
|
|
|
DATA
|
|
|
|
dw TEXT ; aArg[ 0] text
|
2016-02-17 15:02:00 -08:00
|
|
|
dw 39 ; aArg[ 1] x
|
|
|
|
dw 191 ; aArg[ 2] y
|
2016-02-18 12:19:00 -08:00
|
|
|
dw $C0DE ; aArg[ 3] addr ScreenAddr
|
|
|
|
dw $C0DE ; aArg[ 4] byte ScreenAddr pointer
|
|
|
|
dw $DA1A ; aArg[ 5] bits ScreenByte
|
|
|
|
dw $DA1A ; aArg[ 6] bits ScreenByte reversed
|
2016-02-17 12:35:00 -08:00
|
|
|
|
2016-02-18 09:56:00 -08:00
|
|
|
TEXT2
|
|
|
|
;byte "Byte=b b b b Str=s,s"
|
|
|
|
APPLE "Byte="
|
|
|
|
.byte "b"
|
|
|
|
APPLE " "
|
|
|
|
.byte "b"
|
|
|
|
APPLE " "
|
|
|
|
.byte "b"
|
|
|
|
APPLE " "
|
|
|
|
.byte "b"
|
2016-02-18 12:19:00 -08:00
|
|
|
APPLE " "
|
|
|
|
.byte "b"
|
2016-02-18 09:56:00 -08:00
|
|
|
db 0
|
|
|
|
|
|
|
|
TEXT_HELLO
|
2016-02-18 12:19:00 -08:00
|
|
|
APPLE "HELLO"
|
2016-02-18 09:56:00 -08:00
|
|
|
db 0
|
|
|
|
|
|
|
|
TEXT_WORLD
|
2016-02-18 12:19:00 -08:00
|
|
|
APPLE "WORLD"
|
2016-02-18 09:56:00 -08:00
|
|
|
db 0
|
2016-02-18 12:19:00 -08:00
|
|
|
|
2016-02-18 09:56:00 -08:00
|
|
|
DATA2
|
|
|
|
dw TEXT2
|
|
|
|
dw $80 ; -128
|
|
|
|
dw $FF ; -1
|
|
|
|
dw $00 ; 0
|
2016-02-18 12:19:00 -08:00
|
|
|
dw $01 ; +1
|
2016-02-18 09:56:00 -08:00
|
|
|
dw $7F ; +127
|
2016-02-18 12:19:00 -08:00
|
|
|
|
|
|
|
TEXT3
|
|
|
|
APPLE "Strings: '"
|
|
|
|
.byte "s"
|
|
|
|
APPLE "','"
|
|
|
|
.byte "s"
|
|
|
|
APPLE "'"
|
|
|
|
db 0
|
|
|
|
|
|
|
|
DATA3
|
|
|
|
dw TEXT3
|
2016-02-18 09:56:00 -08:00
|
|
|
dw TEXT_HELLO
|
|
|
|
dw TEXT_WORLD
|
|
|
|
|
2016-02-18 12:19:00 -08:00
|
|
|
TEXT_DCI
|
|
|
|
DCI "HOME"
|
2016-02-17 12:35:00 -08:00
|
|
|
|
2016-02-18 12:19:00 -08:00
|
|
|
TEXT_PASCAL
|
|
|
|
PASCAL "String Len 13"
|
2016-02-18 09:56:00 -08:00
|
|
|
|
2016-02-18 12:19:00 -08:00
|
|
|
TEXT4
|
|
|
|
APPLE "Apple: '"
|
|
|
|
.byte "a"
|
|
|
|
APPLE "' Pascal: '"
|
|
|
|
.byte "p"
|
|
|
|
APPLE "'"
|
|
|
|
db 0
|
|
|
|
|
|
|
|
DATA4
|
|
|
|
dw TEXT4
|
|
|
|
dw TEXT_DCI
|
|
|
|
dw TEXT_PASCAL
|
|
|
|
|
|
|
|
; Pad until end of page so PrintM starts on new page
|
|
|
|
ds 256 - <*
|
2016-02-18 07:48:00 -08:00
|
|
|
|
2016-02-17 12:35:00 -08:00
|
|
|
|
2016-02-18 12:48:00 -08:00
|
|
|
; self-modifying variable aliases
|
2016-02-17 12:35:00 -08:00
|
|
|
|
|
|
|
_pScreen = PutChar +1
|
|
|
|
_pFormat = GetFormat +1
|
|
|
|
_iArg = NxtArgByte+1
|
|
|
|
_pArg = IncArg +1
|
2016-02-18 12:34:00 -08:00
|
|
|
.if ENABLE_HEX
|
2016-02-17 16:47:00 -08:00
|
|
|
_nHexWidth = HexWidth +1
|
2016-02-18 12:34:00 -08:00
|
|
|
.endif
|
|
|
|
.if ENABLE_DEC
|
2016-02-17 16:47:00 -08:00
|
|
|
_nDecWidth = DecWidth +1
|
2016-02-18 12:34:00 -08:00
|
|
|
.endif ; ENABLE_DEC
|
2016-02-17 12:35:00 -08:00
|
|
|
|
|
|
|
; printm( format, args, ... )
|
2016-02-17 16:47:00 -08:00
|
|
|
; ======================================================================
|
2016-02-17 12:35:00 -08:00
|
|
|
PrintM
|
|
|
|
STX _pArg+0
|
|
|
|
STY _pArg+1
|
2016-02-18 12:48:00 -08:00
|
|
|
STZ _iArg
|
2016-02-17 12:35:00 -08:00
|
|
|
|
|
|
|
NextArg
|
2016-02-18 09:56:00 -08:00
|
|
|
JSR NxtArgYX
|
2016-02-17 12:35:00 -08:00
|
|
|
STX _pFormat+0 ; lo
|
|
|
|
STY _pFormat+1 ; hi
|
|
|
|
BRA GetFormat ; always
|
2016-02-17 15:02:00 -08:00
|
|
|
|
2016-02-18 12:34:00 -08:00
|
|
|
.if ENABLE_HEX
|
|
|
|
|
2016-02-17 15:02:00 -08:00
|
|
|
; x Hex 2 Byte
|
|
|
|
; $ Hex 4 Byte
|
2016-02-17 16:47:00 -08:00
|
|
|
; ======================================================================
|
2016-02-17 15:02:00 -08:00
|
|
|
PrintHex4
|
|
|
|
LDA #4
|
|
|
|
BNE _PrintHex
|
|
|
|
PrintHex2
|
|
|
|
LDA #2
|
|
|
|
_PrintHex
|
2016-02-17 16:47:00 -08:00
|
|
|
STA _nHexWidth
|
2016-02-18 09:56:00 -08:00
|
|
|
JSR NxtArgYX
|
2016-02-18 07:48:00 -08:00
|
|
|
|
|
|
|
; Print 16-bit Y,X in hex
|
|
|
|
; Uses _nHexWidth to limit output width
|
2016-02-18 12:19:00 -08:00
|
|
|
PrintHexYX
|
|
|
|
STX _val+0 ; may be tempting to move this to NxtArgYX
|
|
|
|
STY _val+1 ; as XYtoVal but others call us
|
|
|
|
|
2016-02-17 15:17:00 -08:00
|
|
|
LDX #0
|
|
|
|
_HexDigit
|
|
|
|
LDA _val+0
|
|
|
|
AND #$F
|
|
|
|
CMP #$A ; n < 10 ?
|
|
|
|
BCC _Hex2Asc
|
|
|
|
ADC #6 ; n += 6 $A -> +6 + (C=1) = $11
|
|
|
|
_Hex2Asc
|
|
|
|
ADC #'0' + $80 ; inverse=remove #$80
|
|
|
|
STA _bcd, X ; NOTE: Digits are reversed!
|
|
|
|
|
|
|
|
LSR _val+1 ; 16-bit SHR nibble
|
|
|
|
ROR _val+0
|
|
|
|
|
|
|
|
LSR _val+1
|
|
|
|
ROR _val+0
|
|
|
|
|
|
|
|
LSR _val+1
|
|
|
|
ROR _val+0
|
|
|
|
|
|
|
|
LSR _val+1
|
|
|
|
ROR _val+0
|
|
|
|
|
|
|
|
INX
|
2016-02-17 16:47:00 -08:00
|
|
|
HexWidth
|
|
|
|
CPX #0 ; _nHexWidth NOTE: self-modifying!
|
2016-02-17 15:17:00 -08:00
|
|
|
BNE _HexDigit
|
2016-02-17 15:54:00 -08:00
|
|
|
; Intentional fall into reverse BCD
|
2016-02-17 15:17:00 -08:00
|
|
|
|
2016-02-17 16:47:00 -08:00
|
|
|
; On Entry: X number of chars to print in buffer _bcd
|
|
|
|
; ======================================================================
|
2016-02-17 15:42:00 -08:00
|
|
|
PrintReverseBCD
|
2016-02-17 15:17:00 -08:00
|
|
|
DEX
|
|
|
|
BMI NextFormat
|
|
|
|
LDA _bcd, X
|
|
|
|
JSR PutChar
|
2016-02-17 15:42:00 -08:00
|
|
|
BRA PrintReverseBCD
|
2016-02-17 15:02:00 -08:00
|
|
|
|
2016-02-17 16:47:00 -08:00
|
|
|
|
2016-02-18 12:34:00 -08:00
|
|
|
.if ENABLE_PTR
|
2016-02-17 15:02:00 -08:00
|
|
|
; @ Ptr 2 Byte
|
|
|
|
; & Ptr 4 Byte
|
2016-02-17 16:47:00 -08:00
|
|
|
; ======================================================================
|
2016-02-17 15:02:00 -08:00
|
|
|
PrintPtr4
|
|
|
|
LDA #4
|
|
|
|
BNE _PrintPtr
|
|
|
|
PrintPtr2
|
|
|
|
LDA #2
|
|
|
|
_PrintPtr
|
2016-02-17 16:47:00 -08:00
|
|
|
STA _nHexWidth
|
2016-02-18 12:19:00 -08:00
|
|
|
JSR NxtArgToTemp
|
2016-02-17 15:02:00 -08:00
|
|
|
|
2016-02-18 12:19:00 -08:00
|
|
|
; JSR NxtArgYX
|
2016-02-18 12:48:00 -08:00
|
|
|
; 13 bytes: zero page version
|
2016-02-18 12:19:00 -08:00
|
|
|
; STX _temp+0 ; zero-page for (ZP),Y
|
|
|
|
; STY _temp+1
|
2016-02-17 15:02:00 -08:00
|
|
|
LDY #$0
|
2016-02-18 12:19:00 -08:00
|
|
|
LDA (_temp),Y
|
2016-02-17 15:02:00 -08:00
|
|
|
TAX
|
|
|
|
INY
|
2016-02-18 12:19:00 -08:00
|
|
|
LDA (_temp),Y
|
2016-02-17 15:02:00 -08:00
|
|
|
TAY
|
2016-02-17 16:47:00 -08:00
|
|
|
|
2016-02-18 12:48:00 -08:00
|
|
|
; 20 bytes: self-modifying code version if zero-page not available
|
2016-02-17 16:47:00 -08:00
|
|
|
; STX PtrVal+1
|
|
|
|
; STY PtrVal+2
|
|
|
|
; LDY #0 ; 0: A->X
|
|
|
|
;PrtVal
|
|
|
|
; TAX ; 1: A->Y
|
|
|
|
; LDA $C0DE, Y
|
|
|
|
; INY
|
|
|
|
; CPY #2
|
|
|
|
; BEQ _JumpPrintHexXY
|
|
|
|
; BNE _PtrVal
|
|
|
|
;_JumpPrintHexXY
|
|
|
|
; TAY
|
|
|
|
|
2016-02-18 12:19:00 -08:00
|
|
|
BRA PrintHexYX ; needs XYtoVal setup
|
2016-02-18 12:34:00 -08:00
|
|
|
.endif ; ENABLE_PTR
|
|
|
|
.endif ; ENABLE_HEX
|
|
|
|
|
2016-02-17 15:02:00 -08:00
|
|
|
|
2016-02-17 16:47:00 -08:00
|
|
|
; ======================================================================
|
2016-02-17 12:35:00 -08:00
|
|
|
Print
|
|
|
|
JSR PutChar
|
2016-02-17 15:42:00 -08:00
|
|
|
|
|
|
|
; Adjust pointer to next char in format
|
2016-02-17 12:35:00 -08:00
|
|
|
NextFormat
|
2016-02-17 15:42:00 -08:00
|
|
|
INC _pFormat+0
|
|
|
|
BNE GetFormat
|
|
|
|
INC _pFormat+1
|
2016-02-17 12:35:00 -08:00
|
|
|
GetFormat
|
|
|
|
LDA $C0DE ; _pFormat NOTE: self-modifying!
|
|
|
|
BEQ _Done
|
|
|
|
BMI Print ; neg = literal
|
2016-02-18 12:48:00 -08:00
|
|
|
; NOTE: If all features are turned off, will get a ca65 Range Error
|
2016-02-17 12:35:00 -08:00
|
|
|
LDX #NumMeta-1 ; pos = meta
|
|
|
|
FindMeta
|
|
|
|
CMP MetaChar,X
|
|
|
|
BEQ CallMeta
|
|
|
|
DEX
|
|
|
|
BPL FindMeta
|
|
|
|
BMI NextFormat ; always = invalid meta; ignore
|
|
|
|
CallMeta
|
|
|
|
TXA
|
|
|
|
ASL
|
|
|
|
TAX
|
|
|
|
JMP (MetaFunc,X)
|
|
|
|
_Done
|
|
|
|
RTS
|
|
|
|
|
|
|
|
; === Meta Ops ===
|
|
|
|
|
2016-02-18 12:34:00 -08:00
|
|
|
.if ENABLE_DEC
|
2016-02-17 15:42:00 -08:00
|
|
|
; # Dec 1 Byte (max 2 digits)
|
|
|
|
; d Dec 2 Byte (max 3 digits)
|
|
|
|
; u Dec 2 Byte (max 5 digits)
|
2016-02-17 16:47:00 -08:00
|
|
|
; ======================================================================
|
2016-02-17 15:54:00 -08:00
|
|
|
PrintDec5
|
|
|
|
LDA #5
|
|
|
|
BNE _PrintDec ; always
|
|
|
|
PrintDec3
|
|
|
|
LDA #3
|
|
|
|
BNE _PrintDec ; always
|
2016-02-17 15:02:00 -08:00
|
|
|
PrintDec2
|
2016-02-17 15:54:00 -08:00
|
|
|
LDA #2 ; 2 digits
|
2016-02-17 15:02:00 -08:00
|
|
|
_PrintDec
|
2016-02-17 16:47:00 -08:00
|
|
|
STA _nDecWidth
|
2016-02-18 09:56:00 -08:00
|
|
|
JSR NxtArgYX
|
2016-02-18 07:48:00 -08:00
|
|
|
|
|
|
|
PrintDecYX
|
2016-02-18 12:19:00 -08:00
|
|
|
STX _val+0 ; may be tempting to move this to NxtArgYX
|
|
|
|
STY _val+1 ; as XYtoVal but others call us
|
2016-02-17 12:35:00 -08:00
|
|
|
|
2016-02-17 15:02:00 -08:00
|
|
|
STZ _bcd+0
|
|
|
|
STZ _bcd+1
|
|
|
|
STZ _bcd+2
|
2016-02-17 12:35:00 -08:00
|
|
|
|
2016-02-17 15:17:00 -08:00
|
|
|
Dec2BCD
|
2016-02-17 15:02:00 -08:00
|
|
|
LDX #16
|
|
|
|
SED
|
2016-02-17 15:17:00 -08:00
|
|
|
_Dec2BCD
|
2016-02-17 15:02:00 -08:00
|
|
|
ASL _val+0
|
|
|
|
ROl _val+1
|
|
|
|
|
|
|
|
LDA _bcd+0
|
|
|
|
ADC _bcd+0
|
|
|
|
STA _bcd+0
|
|
|
|
|
|
|
|
LDA _bcd+1
|
|
|
|
ADC _bcd+1
|
|
|
|
STA _bcd+1
|
|
|
|
|
|
|
|
LDA _bcd+2
|
|
|
|
ADC _bcd+2
|
|
|
|
STA _bcd+2
|
|
|
|
|
|
|
|
DEX
|
2016-02-17 15:17:00 -08:00
|
|
|
BNE _Dec2BCD
|
2016-02-17 15:02:00 -08:00
|
|
|
CLD
|
|
|
|
|
2016-02-17 15:17:00 -08:00
|
|
|
BCD2Char
|
2016-02-17 15:02:00 -08:00
|
|
|
LDX #2
|
|
|
|
LDY #5
|
2016-02-17 15:17:00 -08:00
|
|
|
_BCD2Char
|
2016-02-18 09:56:00 -08:00
|
|
|
LDA _bcd,X ; __c??? _b_?XX a_YYXX
|
2016-02-17 15:02:00 -08:00
|
|
|
LSR
|
|
|
|
LSR
|
|
|
|
LSR
|
|
|
|
LSR
|
|
|
|
CLC
|
2016-02-18 09:56:00 -08:00
|
|
|
ADC #'0'+$80
|
|
|
|
STA _bcd,Y ; __c??X _b_YXX aZYYXX
|
2016-02-17 15:02:00 -08:00
|
|
|
DEY
|
|
|
|
|
2016-02-18 09:56:00 -08:00
|
|
|
LDA _bcd,X ; __c??X _b_YXX aZYYXX
|
2016-02-17 15:02:00 -08:00
|
|
|
AND #$F
|
|
|
|
CLC
|
2016-02-18 09:56:00 -08:00
|
|
|
ADC #'0'+$80
|
|
|
|
STA _bcd,Y ; __c?XX _bYYXX ZZYYXX
|
2016-02-17 15:02:00 -08:00
|
|
|
DEY
|
|
|
|
DEX
|
2016-02-17 15:17:00 -08:00
|
|
|
BPL _BCD2Char
|
|
|
|
|
2016-02-17 16:47:00 -08:00
|
|
|
DecWidth
|
2016-02-18 12:48:00 -08:00
|
|
|
LDX #0 ; _nDecDigits NOTE: self-modifying!
|
2016-02-17 15:42:00 -08:00
|
|
|
JMP PrintReverseBCD
|
2016-02-18 12:34:00 -08:00
|
|
|
.endif ; ENABLE_DEC
|
2016-02-17 15:02:00 -08:00
|
|
|
|
|
|
|
|
2016-02-18 12:19:00 -08:00
|
|
|
.if ENABLE_BIN
|
2016-02-18 07:48:00 -08:00
|
|
|
; % Bin 1 Byte normal one's and zeros
|
|
|
|
; ? Bin 1 Byte inverse one's, normal zeroes
|
2016-02-17 16:47:00 -08:00
|
|
|
; ======================================================================
|
2016-02-17 15:02:00 -08:00
|
|
|
PrintBinInv
|
|
|
|
LDA #$81
|
|
|
|
BNE _PrintBin
|
2016-02-17 12:35:00 -08:00
|
|
|
PrintBinAsc
|
2016-02-17 15:02:00 -08:00
|
|
|
LDA #$01
|
|
|
|
_PrintBin
|
|
|
|
STA _PrintBit+1
|
2016-02-18 09:56:00 -08:00
|
|
|
JSR NxtArgYX ; X = low byte
|
2016-02-17 15:02:00 -08:00
|
|
|
|
|
|
|
LDY #8 ; print 8 bits
|
|
|
|
_Bit2Asc
|
2016-02-17 16:47:00 -08:00
|
|
|
TXA
|
|
|
|
CMP #$80 ; C= A>=$80
|
|
|
|
ROL ; C<-76543210<-C
|
|
|
|
TAX
|
2016-02-18 12:48:00 -08:00
|
|
|
AND #$01 ; 0 -> B0
|
2016-02-17 15:02:00 -08:00
|
|
|
BEQ _FlipBit
|
|
|
|
_PrintBit
|
2016-02-18 12:48:00 -08:00
|
|
|
LDA #$81 ; 1 -> 31 NOTE: self-modifying!
|
2016-02-17 15:02:00 -08:00
|
|
|
_FlipBit
|
|
|
|
EOR #$B0
|
|
|
|
JSR PutChar
|
|
|
|
DEY
|
|
|
|
BNE _Bit2Asc
|
2016-02-18 12:34:00 -08:00
|
|
|
.endif ; ENABLE_BIN
|
|
|
|
|
2016-02-17 15:42:00 -08:00
|
|
|
_JumpNextFormat
|
|
|
|
; BRA NextFormat ; always
|
|
|
|
JMP NextFormat ; JMP :-(
|
2016-02-17 15:54:00 -08:00
|
|
|
|
2016-02-18 12:19:00 -08:00
|
|
|
; b Print a signed byte in decimal
|
2016-02-18 09:56:00 -08:00
|
|
|
; ======================================================================
|
2016-02-18 12:34:00 -08:00
|
|
|
.if ENABLE_DEC
|
|
|
|
.if ENABLE_BYTE
|
2016-02-18 09:56:00 -08:00
|
|
|
PrintByte
|
|
|
|
JSR NxtArgYX ; X = low byte
|
|
|
|
TXA
|
|
|
|
BPL PrintBytePos
|
|
|
|
LDA #'-' + $80 ; X >= $80 --> $80 (-128) .. $FF (-1)
|
|
|
|
JSR PutChar
|
|
|
|
TXA
|
|
|
|
EOR #$FF ; 2's complement
|
|
|
|
AND #$7F
|
|
|
|
CLC
|
|
|
|
ADC #$01
|
|
|
|
PrintBytePos
|
|
|
|
TAX
|
|
|
|
|
|
|
|
LDY #00 ; 00XX
|
|
|
|
LDA #3 ; 3 digits max
|
|
|
|
STA _nDecWidth
|
2016-02-18 12:19:00 -08:00
|
|
|
JMP PrintDecYX ; needs XYtoVal setup
|
2016-02-18 12:34:00 -08:00
|
|
|
.endif ; ENABLE_BYTE
|
|
|
|
.endif ; ENABLE_DEC
|
2016-02-18 12:19:00 -08:00
|
|
|
|
2016-02-18 09:56:00 -08:00
|
|
|
|
2016-02-18 12:34:00 -08:00
|
|
|
.if ENABLE_STR
|
2016-02-18 12:19:00 -08:00
|
|
|
; a String (APPLE text, last byte ASCII)
|
|
|
|
; See: DCI
|
|
|
|
; ======================================================================
|
|
|
|
PrintStrA
|
|
|
|
JSR NxtArgToTemp
|
|
|
|
|
|
|
|
LDY #$0
|
|
|
|
_PrintStrA
|
|
|
|
LDA (_temp),Y
|
|
|
|
BPL @_LastChar
|
|
|
|
JSR PutChar
|
|
|
|
INY
|
|
|
|
BNE _PrintStrA
|
|
|
|
INC _temp+1
|
|
|
|
BRA _PrintStrA
|
|
|
|
@_LastChar
|
|
|
|
LDX #1
|
|
|
|
ORA #$80
|
|
|
|
BRA _PrintCharA
|
|
|
|
|
|
|
|
; s String (C,ASCIIZ)
|
|
|
|
; ======================================================================
|
|
|
|
PrintStrC
|
|
|
|
JSR NxtArgToTemp
|
|
|
|
|
|
|
|
LDY #$0
|
|
|
|
@_NextByte
|
|
|
|
LDA (_temp),Y
|
|
|
|
BEQ _JumpNextFormat
|
|
|
|
JSR PutChar
|
|
|
|
INY
|
|
|
|
BNE @_NextByte
|
|
|
|
INC _temp+1
|
|
|
|
BRA @_NextByte
|
|
|
|
|
|
|
|
; p String (Pascal)
|
2016-02-18 09:56:00 -08:00
|
|
|
; ======================================================================
|
|
|
|
PrintStrP
|
2016-02-18 12:19:00 -08:00
|
|
|
JSR NxtArgToTemp
|
2016-02-18 09:56:00 -08:00
|
|
|
|
|
|
|
LDY #$0
|
2016-02-18 12:19:00 -08:00
|
|
|
LDA (_temp),Y
|
|
|
|
BEQ _JumpNextFormat
|
2016-02-18 09:56:00 -08:00
|
|
|
TAX
|
|
|
|
_PrintStrP
|
2016-02-17 12:35:00 -08:00
|
|
|
INY
|
2016-02-18 12:19:00 -08:00
|
|
|
LDA (_temp),Y
|
|
|
|
_PrintCharA
|
2016-02-18 09:56:00 -08:00
|
|
|
JSR PutChar
|
|
|
|
DEX
|
|
|
|
BNE _PrintStrP
|
|
|
|
BEQ _JumpNextFormat ; always
|
2016-02-18 12:34:00 -08:00
|
|
|
.endif ; ENABLE_STR
|
2016-02-18 09:56:00 -08:00
|
|
|
|
|
|
|
; __________ Utility __________
|
2016-02-17 12:35:00 -08:00
|
|
|
|
2016-02-17 16:47:00 -08:00
|
|
|
; ======================================================================
|
2016-02-17 12:35:00 -08:00
|
|
|
PutChar
|
2016-02-18 12:48:00 -08:00
|
|
|
STA $C0DE ; _pScreen NOTE: self-modifying!
|
2016-02-17 12:35:00 -08:00
|
|
|
INC PutChar+1 ; inc lo
|
|
|
|
RTS
|
|
|
|
|
2016-02-17 16:47:00 -08:00
|
|
|
; ======================================================================
|
2016-02-18 09:56:00 -08:00
|
|
|
; @return next arg as 16-bit arg value in Y,X
|
2016-02-18 12:19:00 -08:00
|
|
|
NxtArgToTemp
|
2016-02-18 09:56:00 -08:00
|
|
|
NxtArgYX
|
|
|
|
JSR NxtArgByte
|
|
|
|
TAX
|
2016-02-17 12:35:00 -08:00
|
|
|
|
|
|
|
; @return _Arg[ _Num ]
|
|
|
|
NxtArgByte
|
2016-02-18 12:48:00 -08:00
|
|
|
LDY #00 ; _iArg NOTE: self-modifying!
|
2016-02-17 12:35:00 -08:00
|
|
|
IncArg
|
|
|
|
LDA $C0DE,Y ; _pArg NOTE: self-modifying!
|
2016-02-18 12:48:00 -08:00
|
|
|
INC _iArg ;
|
2016-02-17 12:35:00 -08:00
|
|
|
BNE @_SamePage
|
|
|
|
INC _pArg+1 ;
|
|
|
|
@_SamePage
|
|
|
|
TAY
|
2016-02-18 12:19:00 -08:00
|
|
|
|
|
|
|
; Callers of NxtToArgYX don't use _temp
|
|
|
|
_NxtArgToTemp
|
|
|
|
STX _temp+0 ; zero-page for (ZP),Y
|
|
|
|
STY _temp+1
|
|
|
|
|
|
|
|
;XYtoVal
|
|
|
|
; STX _val+0 ; may be tempting to move this to NxtArgYX
|
|
|
|
; STY _val+1 ;
|
|
|
|
|
2016-02-17 12:35:00 -08:00
|
|
|
RTS
|
|
|
|
|
2016-02-18 12:48:00 -08:00
|
|
|
;
|
2016-02-18 12:19:00 -08:00
|
|
|
; ======================================================================
|
|
|
|
|
2016-02-17 15:02:00 -08:00
|
|
|
_bcd ds 6 ; 6 chars for printing dec
|
2016-02-18 12:34:00 -08:00
|
|
|
_val dw 0 ; PrintHex2 PrintHex4 temp
|
2016-02-17 12:35:00 -08:00
|
|
|
|
|
|
|
MetaChar
|
2016-02-18 12:19:00 -08:00
|
|
|
|
|
|
|
.if ENABLE_BIN
|
|
|
|
db '?' ; PrintBinInv NOTE: 1's printed in inverse
|
2016-02-17 12:35:00 -08:00
|
|
|
db '%' ; PrintBinAsc
|
2016-02-18 12:19:00 -08:00
|
|
|
.endif
|
|
|
|
.if ENABLE_DEC
|
|
|
|
.if ENABLE_BYTE
|
|
|
|
db 'b' ; PrintByte NOTE: Signed -128 .. +127
|
|
|
|
.endif
|
2016-02-17 15:54:00 -08:00
|
|
|
db 'u' ; PrintDec5
|
|
|
|
db 'd' ; PrintDec3
|
2016-02-17 12:35:00 -08:00
|
|
|
db '#' ; PrintDec2
|
2016-02-18 12:19:00 -08:00
|
|
|
.endif
|
|
|
|
.if ENABLE_HEX
|
2016-02-17 15:02:00 -08:00
|
|
|
db 'x' ; PrintHex4
|
2016-02-18 12:19:00 -08:00
|
|
|
db '$' ; PrintHex2
|
|
|
|
.endif
|
|
|
|
.if ENABLE_PTR
|
|
|
|
db '&' ; PrintPtr4
|
|
|
|
db '@' ; PrintPtr2
|
|
|
|
.endif
|
|
|
|
.if ENABLE_STR
|
|
|
|
db 'p' ; PrintStrP NOTE: Pascal string; C printf 'p' is pointer!
|
|
|
|
db 's' ; PrintStrC NOTE: C string, zero terminated
|
|
|
|
db 'a' ; PrintStrA NOTE: Last byte is ASCII
|
|
|
|
.endif
|
2016-02-17 12:35:00 -08:00
|
|
|
|
|
|
|
_MetaCharEnd
|
|
|
|
NumMeta = _MetaCharEnd - MetaChar
|
|
|
|
|
|
|
|
MetaFunc
|
2016-02-18 12:19:00 -08:00
|
|
|
|
|
|
|
.if ENABLE_BIN
|
2016-02-17 12:35:00 -08:00
|
|
|
dw PrintBinInv
|
|
|
|
dw PrintBinAsc
|
2016-02-18 12:19:00 -08:00
|
|
|
.endif
|
|
|
|
.if ENABLE_DEC
|
|
|
|
.if ENABLE_BYTE
|
2016-02-18 09:56:00 -08:00
|
|
|
dw PrintByte
|
2016-02-18 12:19:00 -08:00
|
|
|
.endif
|
2016-02-17 15:54:00 -08:00
|
|
|
dw PrintDec5
|
|
|
|
dw PrintDec3
|
2016-02-17 12:35:00 -08:00
|
|
|
dw PrintDec2
|
2016-02-18 12:19:00 -08:00
|
|
|
.endif
|
|
|
|
.if ENABLE_HEX
|
2016-02-17 12:35:00 -08:00
|
|
|
dw PrintHex4
|
2016-02-18 12:19:00 -08:00
|
|
|
dw PrintHex2
|
2016-02-18 12:34:00 -08:00
|
|
|
.if ENABLE_PTR
|
2016-02-18 12:19:00 -08:00
|
|
|
dw PrintPtr4
|
|
|
|
dw PrintPtr2
|
2016-02-18 12:34:00 -08:00
|
|
|
.endif
|
2016-02-18 12:19:00 -08:00
|
|
|
.endif
|
|
|
|
.if ENABLE_STR
|
|
|
|
dw PrintStrP
|
|
|
|
dw PrintStrC
|
|
|
|
dw PrintStrA
|
|
|
|
.endif
|
|
|
|
|
2016-02-17 12:35:00 -08:00
|
|
|
__END
|
|
|
|
|