mirror of
https://github.com/irmen/prog8.git
synced 2024-12-27 05:29:38 +00:00
rename
This commit is contained in:
parent
a5283bfc7b
commit
2f6ef28c80
@ -1514,7 +1514,7 @@ class CodeGenerator:
|
||||
# assigning a register to a float requires c64 ROM routines
|
||||
if r_register in REGISTER_WORDS:
|
||||
def do_rom_calls():
|
||||
self.p("\t\tjsr c64util.GIVUAYF") # uword AY -> fac1
|
||||
self.p("\t\tjsr c64.GIVUAYF") # uword AY -> fac1
|
||||
self.p("\t\tldx #<" + lv_string)
|
||||
self.p("\t\tldy #>" + lv_string)
|
||||
self.p("\t\tjsr c64.FTOMEMXY") # fac1 -> memory XY
|
||||
@ -1750,7 +1750,7 @@ class CodeGenerator:
|
||||
self.p("\t\tsta c64.SCRATCH_ZPWORD1+1")
|
||||
self.p("\t\tldx #<" + l_str)
|
||||
self.p("\t\tldy #>" + l_str)
|
||||
self.p("\t\tjsr c64_lib.copy_mflt")
|
||||
self.p("\t\tjsr il65_lib.copy_mflt")
|
||||
elif rvalue.datatype == DataType.BYTE:
|
||||
with self.preserving_registers({'A', 'X', 'Y'}):
|
||||
self.p("\t\tldy " + r_str)
|
||||
@ -1762,7 +1762,7 @@ class CodeGenerator:
|
||||
with self.preserving_registers({'A', 'X', 'Y'}, loads_a_within=True):
|
||||
self.p("\t\tlda " + r_str)
|
||||
self.p("\t\tldy {:s}+1".format(r_str))
|
||||
self.p("\t\tjsr c64util.GIVUAYF") # uword AY -> fac1
|
||||
self.p("\t\tjsr c64.GIVUAYF") # uword AY -> fac1
|
||||
self.p("\t\tldx #<" + l_str)
|
||||
self.p("\t\tldy #>" + l_str)
|
||||
self.p("\t\tjsr c64.FTOMEMXY") # fac1 -> memory XY
|
||||
|
@ -1308,7 +1308,7 @@ class Parser:
|
||||
raise self.PError("all call arguments should have a name or be matched on a named parameter")
|
||||
if isinstance(target, (type(None), ParseResult.Value)):
|
||||
# special case for the C-64 lib's print function, to be able to use it with a single character argument
|
||||
if target.name == "c64util.print_string" and len(arguments) == 1 and isinstance(arguments[0], str):
|
||||
if target.name == "c64scr.print_string" and len(arguments) == 1 and isinstance(arguments[0], str):
|
||||
if arguments[0][1].startswith("'") and arguments[0][1].endswith("'"):
|
||||
target = self.parse_expression("c64.CHROUT")
|
||||
address = target.address
|
||||
@ -1797,7 +1797,7 @@ class Optimizer:
|
||||
def remove_unused_subroutines(self, block: ParseResult.Block) -> None:
|
||||
# some symbols are used by the emitted assembly code from the code generator,
|
||||
# and should never be removed or the assembler will fail
|
||||
never_remove = {"c64util.GIVUAYF", "c64.FREADUY", "c64.FTOMEMXY"}
|
||||
never_remove = {"c64.GIVUAYF", "c64.FREADUY", "c64.FTOMEMXY"}
|
||||
discarded = []
|
||||
for sub in list(block.symbols.iter_subroutines()):
|
||||
usages = self.parsed.subroutine_usage[(sub.blockname, sub.name)]
|
||||
|
@ -221,6 +221,8 @@ class Zeropage:
|
||||
raise SymbolError("cannot configure the ZP multiple times")
|
||||
if clobber_zp:
|
||||
self.free = list(range(0x04, 0xfb)) + [0xff]
|
||||
for updated_by_irq in [0xa0, 0xa1, 0xa2, 0x91, 0xc0, 0xc5, 0xcb, 0xf5, 0xf6]:
|
||||
self.free.remove(updated_by_irq)
|
||||
else:
|
||||
# these are valid for the C-64 (when no RS232 I/O is performed):
|
||||
# ($02, $03, $fb-$fc, $fd-$fe are reserved as scratch addresses for various routines)
|
||||
|
253
lib/c64lib.ill
253
lib/c64lib.ill
@ -7,16 +7,21 @@
|
||||
; indent format: TABS, size=8
|
||||
|
||||
|
||||
output raw
|
||||
|
||||
~ c64 {
|
||||
memory .byte SCRATCH_ZP1 = $02 ; scratch register #1 in ZP
|
||||
memory .byte SCRATCH_ZP2 = $03 ; scratch register #2 in ZP
|
||||
memory .word SCRATCH_ZPWORD1 = $fb ; scratch word in ZP ($fb/$fc)
|
||||
memory .word SCRATCH_ZPWORD2 = $fd ; scratch word in ZP ($fd/$fe)
|
||||
|
||||
memory .byte COLOR = $0286 ; cursor color
|
||||
memory .word CINV = $0314 ; IRQ vector
|
||||
|
||||
memory .byte TIME_HI = $a0 ; software jiffy clock, hi byte
|
||||
memory .byte TIME_MID = $a1 ; .. mid byte
|
||||
memory .byte TIME_LO = $a2 ; .. lo byte. Updated by IRQ every 1/60 sec
|
||||
memory .byte STKEY = $91 ; various keyboard statuses (updated by IRQ)
|
||||
memory .byte SFDX = $cb ; current key pressed (matrix value) (updated by IRQ)
|
||||
|
||||
memory .byte COLOR = $0286 ; cursor color
|
||||
memory .word CINV = $0314 ; IRQ vector
|
||||
|
||||
; ---- VIC-II registers ----
|
||||
|
||||
@ -107,17 +112,17 @@ sub MOVAF () -> (A?, X?) = $bc0c ; copy fac1 to fac2 (rounded)
|
||||
sub MOVEF () -> (A?, X?) = $bc0f ; copy fac1 to fac2
|
||||
sub FTOMEMXY (mflpt: XY) -> (A?, Y?) = $bbd4 ; store fac1 to memory X/Y as 5-byte mflpt
|
||||
sub FTOSWORDYA () -> (Y, A, X?) = $b1aa ; fac1-> signed word in Y/A (might throw ILLEGAL QUANTITY)
|
||||
; use c64util.FTOSWRDAY to get A/Y output (lo/hi switched to normal order)
|
||||
; use c64.FTOSWRDAY to get A/Y output (lo/hi switched to normal order)
|
||||
sub GETADR () -> (Y, A, X?) = $b7f7 ; fac1 -> unsigned word in Y/A (might throw ILLEGAL QUANTITY)
|
||||
; (result also in $14/15) use c64util.GETADRAY to get A/Y output (lo/hi switched to normal order)
|
||||
; (result also in $14/15) use c64.GETADRAY to get A/Y output (lo/hi switched to normal order)
|
||||
sub QINT () -> (?) = $bc9b ; fac1 -> 4-byte signed integer in 98-101 ($62-$65), with the MSB FIRST.
|
||||
sub AYINT () -> (?) = $b1bf ; fac1-> signed word in 100-101 ($64-$65) MSB FIRST. (might throw ILLEGAL QUANTITY)
|
||||
sub GIVAYF (lo: Y, hi: A) -> (?) = $b391 ; signed word in Y/A -> float in fac1
|
||||
; use c64util.GIVAYFAY to use A/Y input (lo/hi switched to normal order)
|
||||
; there is also c64util.GIVUAYF - unsigned word in A/Y (lo/hi) to fac1
|
||||
; there is also c64util.FREADS32 that reads from 98-101 ($62-$65) MSB FIRST
|
||||
; there is also c64util.FREADUS32 that reads from 98-101 ($62-$65) MSB FIRST
|
||||
; there is also c64util.FREADS24AXY that reads signed int24 into fac1 from A/X/Y (lo/mid/hi bytes)
|
||||
; use c64.GIVAYFAY to use A/Y input (lo/hi switched to normal order)
|
||||
; there is also c64.GIVUAYF - unsigned word in A/Y (lo/hi) to fac1
|
||||
; there is also c64.FREADS32 that reads from 98-101 ($62-$65) MSB FIRST
|
||||
; there is also c64.FREADUS32 that reads from 98-101 ($62-$65) MSB FIRST
|
||||
; there is also c64.FREADS24AXY that reads signed int24 into fac1 from A/X/Y (lo/mid/hi bytes)
|
||||
sub FREADUY (ubyte: Y) -> (?) = $b3a2 ; 8 bit unsigned Y -> float in fac1
|
||||
sub FREADSA (sbyte: A) -> (?) = $bc3c ; 8 bit signed A -> float in fac1
|
||||
sub FREADSTR (len: A) -> (?) = $b7b5 ; str -> fac1, $22/23 must point to string, A=string length
|
||||
@ -217,10 +222,9 @@ sub IOBASE () -> (X, Y) = $FFF3 ; read base address of I/O devices
|
||||
memory .word RESET_VEC = $FFFC ; reset vector, set by the kernal if banked in
|
||||
memory .word IRQ_VEC = $FFFE ; interrupt vector, set by the kernal if banked in
|
||||
|
||||
}
|
||||
|
||||
|
||||
~ c64util {
|
||||
; ----- utility functions ----
|
||||
|
||||
sub init_system () -> (?) {
|
||||
; ---- initializes the machine to a sane starting state
|
||||
@ -252,7 +256,6 @@ sub init_system () -> (?) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
sub FREADS32 () -> (?) {
|
||||
; ---- fac1 = signed int32 from $62-$65 big endian (MSB FIRST)
|
||||
asm {
|
||||
@ -335,70 +338,55 @@ sub GETADRAY () -> (AY, X?) {
|
||||
}
|
||||
}
|
||||
|
||||
sub print_string (address: XY) -> (A?, Y?) {
|
||||
; ---- print null terminated string from X/Y
|
||||
; note: the IL65 compiler contains an optimization that will replace
|
||||
; a call to this subroutine with a string argument of just one char,
|
||||
; by just one call to c64.CHROUT of that single char.
|
||||
asm {
|
||||
stx c64.SCRATCH_ZP1
|
||||
sty c64.SCRATCH_ZP2
|
||||
ldy #0
|
||||
- lda (c64.SCRATCH_ZP1),y
|
||||
beq +
|
||||
jsr c64.CHROUT
|
||||
iny
|
||||
bne -
|
||||
+ rts
|
||||
}
|
||||
}
|
||||
|
||||
sub print_pstring (address: XY) -> (A?, X?, Y) {
|
||||
; ---- print pstring (length as first byte) from X/Y, returns str len in Y
|
||||
asm {
|
||||
stx c64.SCRATCH_ZP1
|
||||
sty c64.SCRATCH_ZP2
|
||||
ldy #0
|
||||
lda (c64.SCRATCH_ZP1),y
|
||||
beq +
|
||||
tax
|
||||
- iny
|
||||
lda (c64.SCRATCH_ZP1),y
|
||||
jsr c64.CHROUT
|
||||
dex
|
||||
bne -
|
||||
+ rts ; output string length is in Y
|
||||
}
|
||||
}
|
||||
} ; ------ end of block c64
|
||||
|
||||
|
||||
|
||||
~ c64scr {
|
||||
; ---- this block contains (character) Screen and text I/O related functions ----
|
||||
|
||||
|
||||
sub clear_screen (char:A, color: Y, screenaddr_hi: X) -> () {
|
||||
; ---- clear the character screen with the given fill character and character color.
|
||||
; X must be set to the high byte of the current screen display memory address (usually $04, for $0400).
|
||||
|
||||
sub print_pimmediate () -> () {
|
||||
; ---- print pstring in memory immediately following the subroutine fast call instruction
|
||||
; note that the clobbered registers (A,X,Y) are not listed ON PURPOSE
|
||||
asm {
|
||||
tsx
|
||||
lda $102,x
|
||||
tay ; put high byte in y
|
||||
lda $101,x
|
||||
tax ; and low byte in x.
|
||||
;ldx #$04 ; high byte of screen addres
|
||||
;lda #1 ; fill char
|
||||
;ldy #3 ; fill color
|
||||
sta _loop +1 ; self-modify
|
||||
sty _mod_col +1 ; self-modify
|
||||
stx _loop + 4 ; self-modify
|
||||
inx
|
||||
bne +
|
||||
iny
|
||||
+ jsr print_pstring ; print string in XY, returns string length in y.
|
||||
tya
|
||||
tsx
|
||||
clc
|
||||
adc $101,x ; add content of 1st (length) byte to return addr.
|
||||
bcc + ; if that made the low byte roll over to 00,
|
||||
inc $102,x ; then increment the high byte too.
|
||||
+ clc
|
||||
adc #1 ; now add 1 for the length byte itself.
|
||||
sta $101,x
|
||||
bne + ; if that made it (the low byte) roll over to 00,
|
||||
inc $102,x ; increment the high byte of the return addr too.
|
||||
+ rts
|
||||
}
|
||||
stx _loop + 7 ; self-modify
|
||||
inx
|
||||
stx _loop + 10 ; self-modify
|
||||
stx _loop + 13 ; self-modify
|
||||
|
||||
|
||||
ldx #0
|
||||
_loop lda #0
|
||||
sta $8400,x ; screen address will be modified
|
||||
sta $8500,x
|
||||
sta $8600,x
|
||||
sta $86e8,x
|
||||
_mod_col lda #0
|
||||
sta $d800,x ; color address is fixed
|
||||
sta $d900,x
|
||||
sta $da00,x
|
||||
sta $dae8,x
|
||||
inx
|
||||
bne _loop
|
||||
|
||||
lda _loop+1 ; restore A and X
|
||||
ldx _loop+4
|
||||
rts
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
sub byte2decimal (ubyte: A) -> (Y, X, A) {
|
||||
; ---- A to decimal string in Y/X/A (100s in Y, 10s in X, 1s in A)
|
||||
asm {
|
||||
@ -437,10 +425,10 @@ hex_digits .text "0123456789abcdef" ; can probably be reused for other stuff as
|
||||
}
|
||||
}
|
||||
|
||||
; var .array(4) word2hex_output_array @todo support to use array/matrix type by address
|
||||
var .text word2hex_output = "123" ; 0-terminated, 4 bytes total @todo remove once array works
|
||||
|
||||
var .text word2hex_output = "1234" ; 0-terminated, to make printing easier
|
||||
sub word2hex (word: XY) -> (?) {
|
||||
; ---- convert 16 bit word in X/Y into hexadecimal string into memory 'word2hex_output'
|
||||
; ---- convert 16 bit word in X/Y into 4-character hexadecimal string into memory 'word2hex_output'
|
||||
asm {
|
||||
stx c64.SCRATCH_ZP2
|
||||
tya
|
||||
@ -526,6 +514,77 @@ sub word2decimal (word: XY) -> (?) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
; @todo string to 32 bit unsigned integer http://www.6502.org/source/strings/ascii-to-32bit.html
|
||||
|
||||
|
||||
sub print_string (address: XY) -> (A?, Y?) {
|
||||
; ---- print null terminated string from X/Y
|
||||
; note: the IL65 compiler contains an optimization that will replace
|
||||
; a call to this subroutine with a string argument of just one char,
|
||||
; by just one call to c64.CHROUT of that single char.
|
||||
asm {
|
||||
stx c64.SCRATCH_ZP1
|
||||
sty c64.SCRATCH_ZP2
|
||||
ldy #0
|
||||
- lda (c64.SCRATCH_ZP1),y
|
||||
beq +
|
||||
jsr c64.CHROUT
|
||||
iny
|
||||
bne -
|
||||
+ rts
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
sub print_pstring (address: XY) -> (A?, X?, Y) {
|
||||
; ---- print pstring (length as first byte) from X/Y, returns str len in Y
|
||||
asm {
|
||||
stx c64.SCRATCH_ZP1
|
||||
sty c64.SCRATCH_ZP2
|
||||
ldy #0
|
||||
lda (c64.SCRATCH_ZP1),y
|
||||
beq +
|
||||
tax
|
||||
- iny
|
||||
lda (c64.SCRATCH_ZP1),y
|
||||
jsr c64.CHROUT
|
||||
dex
|
||||
bne -
|
||||
+ rts ; output string length is in Y
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
sub print_pimmediate () -> () {
|
||||
; ---- print pstring in memory immediately following the subroutine fast call instruction
|
||||
; note that the clobbered registers (A,X,Y) are not listed ON PURPOSE
|
||||
asm {
|
||||
tsx
|
||||
lda $102,x
|
||||
tay ; put high byte in y
|
||||
lda $101,x
|
||||
tax ; and low byte in x.
|
||||
inx
|
||||
bne +
|
||||
iny
|
||||
+ jsr print_pstring ; print string in XY, returns string length in y.
|
||||
tya
|
||||
tsx
|
||||
clc
|
||||
adc $101,x ; add content of 1st (length) byte to return addr.
|
||||
bcc + ; if that made the low byte roll over to 00,
|
||||
inc $102,x ; then increment the high byte too.
|
||||
+ clc
|
||||
adc #1 ; now add 1 for the length byte itself.
|
||||
sta $101,x
|
||||
bne + ; if that made it (the low byte) roll over to 00,
|
||||
inc $102,x ; increment the high byte of the return addr too.
|
||||
+ rts
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
sub print_byte_decimal0 (ubyte: A) -> (?) {
|
||||
; ---- print the byte in A in decimal form, with left padding 0s (3 positions total)
|
||||
asm {
|
||||
@ -540,6 +599,7 @@ sub print_byte_decimal0 (ubyte: A) -> (?) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
sub print_byte_decimal (ubyte: A) -> (?) {
|
||||
; ---- print the byte in A in decimal form, without left padding 0s
|
||||
asm {
|
||||
@ -560,6 +620,7 @@ _print_tens txa
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
sub print_byte_hex (prefix: SC, ubyte: A) -> (?) {
|
||||
; ---- print the byte in A in hex form (if Carry is set, a radix prefix '$' is printed as well)
|
||||
asm {
|
||||
@ -576,6 +637,7 @@ sub print_byte_hex (prefix: SC, ubyte: A) -> (?) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
sub print_word_hex (prefix: SC, word: XY) -> (?) {
|
||||
; ---- print the (unsigned) word in X/Y in hexadecimal form (4 digits)
|
||||
; (if Carry is set, a radix prefix '$' is printed as well)
|
||||
@ -641,9 +703,6 @@ _pr_decimal
|
||||
}
|
||||
|
||||
|
||||
; @todo string to 32 bit unsigned integer http://www.6502.org/source/strings/ascii-to-32bit.html
|
||||
|
||||
|
||||
sub input_chars (buffer: AX) -> (A?, Y) {
|
||||
; ---- Input a string (max. 80 chars) from the keyboard.
|
||||
; It assumes the keyboard is selected as I/O channel!!
|
||||
@ -665,6 +724,11 @@ sub input_chars (buffer: AX) -> (A?, Y) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} ; ---- end block c64scr
|
||||
|
||||
|
||||
|
||||
;sub memcopy_basic () -> (?) {
|
||||
; ; ---- copy a memory block by using a BASIC ROM routine @todo fix code
|
||||
; ; it calls a function from the basic interpreter, so:
|
||||
@ -708,36 +772,3 @@ sub input_chars (buffer: AX) -> (A?, Y) {
|
||||
; stx $59
|
||||
; jsr $a3bf
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
~ c64_lib {
|
||||
|
||||
asm {
|
||||
|
||||
; ---- copy a 5 byte MFLT floating point variable to another place
|
||||
; input: X/Y = source address, SCRATCH_ZPWORD1 = destination address
|
||||
copy_mflt stx c64.SCRATCH_ZP1
|
||||
sty c64.SCRATCH_ZPWORD1+1
|
||||
ldy #0
|
||||
lda (c64.SCRATCH_ZP1),y
|
||||
sta (c64.SCRATCH_ZPWORD1),y
|
||||
iny
|
||||
lda (c64.SCRATCH_ZP1),y
|
||||
sta (c64.SCRATCH_ZPWORD1),y
|
||||
iny
|
||||
lda (c64.SCRATCH_ZP1),y
|
||||
sta (c64.SCRATCH_ZPWORD1),y
|
||||
iny
|
||||
lda (c64.SCRATCH_ZP1),y
|
||||
sta (c64.SCRATCH_ZPWORD1),y
|
||||
iny
|
||||
lda (c64.SCRATCH_ZP1),y
|
||||
sta (c64.SCRATCH_ZPWORD1),y
|
||||
ldy c64.SCRATCH_ZPWORD1+1
|
||||
rts
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -5,7 +5,6 @@
|
||||
;
|
||||
; indent format: TABS, size=8
|
||||
|
||||
output raw
|
||||
|
||||
~ il65_lib_zp {
|
||||
; note: separate block so the 64tass assembler can remove this when no zp restore is required
|
||||
@ -17,9 +16,10 @@ save_zeropage
|
||||
sei
|
||||
ldx #2
|
||||
- lda $00,x
|
||||
sta zp_backup-2,x
|
||||
sta zp_backup,x
|
||||
inx
|
||||
bne -
|
||||
cli
|
||||
rts
|
||||
|
||||
restore_zeropage
|
||||
@ -28,6 +28,14 @@ restore_zeropage
|
||||
txa
|
||||
pha
|
||||
sei
|
||||
|
||||
lda $a0 ; save the current jiffy clock
|
||||
sta zp_backup+$a0
|
||||
lda $a1
|
||||
sta zp_backup+$a1
|
||||
lda $a2
|
||||
sta zp_backup+$a2
|
||||
|
||||
ldx #2
|
||||
- lda zp_backup-2,x
|
||||
sta $00,x
|
||||
@ -40,7 +48,7 @@ restore_zeropage
|
||||
plp
|
||||
rts
|
||||
|
||||
zp_backup .fill 254, 0
|
||||
zp_backup .fill 256, 0
|
||||
|
||||
}
|
||||
}
|
||||
@ -87,4 +95,30 @@ jsr_indirect_XY
|
||||
jmp (SCRATCH_ZP1)
|
||||
|
||||
}
|
||||
|
||||
|
||||
asm {
|
||||
|
||||
; ---- copy a 5 byte MFLT floating point variable to another place
|
||||
; input: X/Y = source address, SCRATCH_ZPWORD1 = destination address
|
||||
copy_mflt stx SCRATCH_ZP1
|
||||
sty SCRATCH_ZPWORD1+1
|
||||
ldy #0
|
||||
lda (SCRATCH_ZP1),y
|
||||
sta (SCRATCH_ZPWORD1),y
|
||||
iny
|
||||
lda (SCRATCH_ZP1),y
|
||||
sta (SCRATCH_ZPWORD1),y
|
||||
iny
|
||||
lda (SCRATCH_ZP1),y
|
||||
sta (SCRATCH_ZPWORD1),y
|
||||
iny
|
||||
lda (SCRATCH_ZP1),y
|
||||
sta (SCRATCH_ZPWORD1),y
|
||||
iny
|
||||
lda (SCRATCH_ZP1),y
|
||||
sta (SCRATCH_ZPWORD1),y
|
||||
ldy SCRATCH_ZPWORD1+1
|
||||
rts
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,9 @@
|
||||
; IL65 integer math library for 6502
|
||||
; (floating point math is done via the C-64's BASIC ROM routines)
|
||||
;
|
||||
; some more interesting routines can be found here http://6502org.wikidot.com/software-math
|
||||
; some more interesting routines can be found here:
|
||||
; http://6502org.wikidot.com/software-math
|
||||
; http://codebase64.org/doku.php?id=base:6502_6510_maths
|
||||
;
|
||||
; Written by Irmen de Jong (irmen@razorvine.net)
|
||||
; License: GNU GPL 3.0, see LICENSE
|
||||
@ -9,8 +11,6 @@
|
||||
; indent format: TABS, size=8
|
||||
|
||||
|
||||
output raw
|
||||
|
||||
~ math {
|
||||
; note: the following ZP scratch registers must be the same as in c64lib
|
||||
memory .byte SCRATCH_ZP1 = $02 ; scratch register #1 in ZP
|
||||
|
36
reference.md
36
reference.md
@ -102,11 +102,22 @@ The four reserved locations mentioned above are subtracted from this set, leavin
|
||||
five 1-byte and two 2-byte usable zero page registers.
|
||||
IL65 knows about all this: it will use the above zero page locations to place its ZP variables in,
|
||||
until they're all used up. You can instruct it to treat your program as taking over the entire
|
||||
machine, in which case all of the zero page locations are suddenly available for variables.
|
||||
machine, in which case (almost) all of the zero page locations are suddenly available for variables.
|
||||
IL65 can generate a special routine that saves and restores the zero page to let your program run
|
||||
and return safely back to the system afterwards - you don't have to take care of that yourself.
|
||||
|
||||
@todo some global way (in ZP block) to promote certian other blocks/variables from that block or even
|
||||
**IRQ and the Zero page:**
|
||||
|
||||
The normal IRQ routine in the C-64's kernal will read and write several locations in the zero page:
|
||||
|
||||
``$a0 - $a2``; ``$91``; ``$c0``; ``$c5``; ``$cb``; ``$f5 - $f6``
|
||||
|
||||
These locations will not be used by the compiler for zero page variables, so your variables will
|
||||
not interfere with the IRQ routine and vice versa. This is true for the normal zp mode but also
|
||||
for the mode where the whole zp has been taken over.
|
||||
|
||||
|
||||
@todo: some global way (in ZP block) to promote certian other blocks/variables from that block or even
|
||||
subroutine to the zeropage. Don't do this in the block itself because it's a global optimization
|
||||
and if blocks require it themselves you can't combine various modules anymore once ZP runs out.
|
||||
|
||||
@ -198,18 +209,15 @@ However you can specify some options globally in your program to change this beh
|
||||
be stored in the ZP, which is more efficient.
|
||||
- ``zp clobber, restore``
|
||||
Use the whole zeropage, but make a backup copy of the original values at program start.
|
||||
When your program exits, the original ZP is restored and you drop back to the BASIC prompt.
|
||||
Not that the interrupts are *disabled* when your program is entered!
|
||||
(you want/have to set your own IRQ routine because the default one will write to
|
||||
various locations in the zeropage)
|
||||
When your program exits, the original ZP is restored (except for the software jiffy clock
|
||||
in ``$a0 - $a2``) and you drop back to the BASIC prompt.
|
||||
Not that the default IRQ routine is *still enabled* when your program is entered!
|
||||
See the paragraph on the zero page for more info about this.
|
||||
|
||||
If you use ``zp clobber``, you can no longer use BASIC or KERNAL routines,
|
||||
because these depend on most of the locations in the ZP. This includes most of the floating-point
|
||||
If you use ``zp clobber``, you can no longer use most BASIC or KERNAL routines,
|
||||
because these depend on most of the locations in the ZP. This includes the floating-point
|
||||
logic and several utility routines that do I/O, such as ``print_string``.
|
||||
|
||||
@todo default IRQ handling will still change certain values in ZP...
|
||||
|
||||
|
||||
|
||||
### Program Entry Point
|
||||
|
||||
@ -376,6 +384,12 @@ if-statuses can be used when such a *comparison expression* is used. An example
|
||||
``if_not A > 55 goto more_iterations``
|
||||
|
||||
|
||||
Conditional jumps are compiled into 6502's branching instructions (such as ``bne`` and ``bcc``) so
|
||||
the rather strict limit on how *far* it can jump applies. The compiler itself can't figure this
|
||||
out unfortunately, so it is entirely possible to create code that cannot be assembled successfully.
|
||||
You'll have to restructure your gotos in the code (place target labels closer to the branch)
|
||||
if you run into this type of assembler error.
|
||||
|
||||
|
||||
Debugging (with Vice)
|
||||
---------------------
|
||||
|
@ -38,14 +38,20 @@ def test_zp_noclobber_allocation():
|
||||
def test_zp_clobber_allocation():
|
||||
zp = Zeropage()
|
||||
zp.configure(True)
|
||||
assert zp.available() == 248
|
||||
assert zp.available() == 239
|
||||
loc = zp.allocate("", DataType.FLOAT)
|
||||
assert loc > 3 and loc not in zp.free
|
||||
num, rest = divmod(zp.available(), 5)
|
||||
for _ in range(num):
|
||||
for _ in range(num-3):
|
||||
zp.allocate("", DataType.FLOAT)
|
||||
assert zp.available() == rest
|
||||
for _ in range(rest // 2):
|
||||
assert zp.available() == 19
|
||||
with pytest.raises(LookupError):
|
||||
zp.allocate("", DataType.FLOAT) # can't allocate because no more sequential bytes, only fragmented
|
||||
for _ in range(14):
|
||||
zp.allocate("", DataType.BYTE)
|
||||
zp.allocate("", DataType.WORD)
|
||||
zp.allocate("", DataType.WORD)
|
||||
with pytest.raises(LookupError):
|
||||
zp.allocate("", DataType.WORD)
|
||||
assert zp.available() == 1
|
||||
zp.allocate("last", DataType.BYTE)
|
||||
|
@ -88,11 +88,11 @@ label4
|
||||
|
||||
|
||||
start
|
||||
c64util.init_system()
|
||||
c64.init_system()
|
||||
|
||||
A = 0
|
||||
printloop
|
||||
c64util.print_byte_decimal(A)
|
||||
c64scr.print_byte_decimal(A)
|
||||
c64.CHROUT('\n')
|
||||
A++
|
||||
if A <20 goto printloop
|
||||
|
@ -47,7 +47,7 @@ sub printflt (float: AY) -> (?) {
|
||||
c64.MOVFM!(AY)
|
||||
goto c64.FPRINTLN
|
||||
; c64.FOUT!()
|
||||
; c64util.print_string!(AY)
|
||||
; c64scr.print_string!(AY)
|
||||
;goto c64.CHROUT('\n')
|
||||
}
|
||||
|
||||
|
@ -6,7 +6,7 @@ import "c64lib"
|
||||
var .text name = "?"*80
|
||||
|
||||
start
|
||||
c64util.init_system()
|
||||
c64.init_system()
|
||||
|
||||
XY = c64.CINV
|
||||
SI = 1
|
||||
@ -14,15 +14,15 @@ start
|
||||
SI = 0
|
||||
|
||||
|
||||
c64util.print_string("enter your name: ")
|
||||
c64util.input_chars(name)
|
||||
c64scr.print_string("enter your name: ")
|
||||
c64scr.input_chars(name)
|
||||
c64.CHROUT('\n')
|
||||
|
||||
blop
|
||||
breakpoint ; yeah!
|
||||
|
||||
c64util.print_string("thank you, mr or mrs: ")
|
||||
c64util.print_string(name)
|
||||
c64scr.print_string("thank you, mr or mrs: ")
|
||||
c64scr.print_string(name)
|
||||
c64.CHROUT('\n')
|
||||
|
||||
SI = 1
|
||||
|
@ -13,19 +13,19 @@ import "c64lib"
|
||||
|
||||
|
||||
start
|
||||
c64util.init_system()
|
||||
c64.init_system()
|
||||
|
||||
A = c64.VMCSB
|
||||
A |= 2 ; @todo c64.VMCSB |= 2
|
||||
c64.VMCSB = A
|
||||
|
||||
; greeting
|
||||
c64util.print_string("Enter your name: ")
|
||||
Y = c64util.input_chars(name)
|
||||
c64scr.print_string("Enter your name: ")
|
||||
Y = c64scr.input_chars(name)
|
||||
c64.CHROUT('\n')
|
||||
c64.CHROUT('\n')
|
||||
c64util.print_string("Hello, ")
|
||||
c64util.print_string(name)
|
||||
c64scr.print_string("Hello, ")
|
||||
c64scr.print_string(name)
|
||||
c64.CHROUT('.')
|
||||
c64.CHROUT('\n')
|
||||
|
||||
@ -35,43 +35,43 @@ start
|
||||
c64.MUL10()
|
||||
c64.FADDH()
|
||||
c64.FADDH()
|
||||
AY = c64util.GETADRAY()
|
||||
AY = c64.GETADRAY()
|
||||
secretnumber = A
|
||||
|
||||
c64util.print_string("I am thinking of a number from 1 to 100!You'll have to guess it!\n")
|
||||
c64scr.print_string("I am thinking of a number from 1 to 100!You'll have to guess it!\n")
|
||||
|
||||
printloop
|
||||
c64util.print_string("\nYou have ")
|
||||
c64util.print_byte_decimal(attempts_left)
|
||||
c64util.print_string(" guess")
|
||||
c64scr.print_string("\nYou have ")
|
||||
c64scr.print_byte_decimal(attempts_left)
|
||||
c64scr.print_string(" guess")
|
||||
|
||||
; @todo comparison expression so we can do if attempts_left>0 ...
|
||||
A = attempts_left
|
||||
A--
|
||||
if_zero A goto ask_guess
|
||||
c64util.print_string("es")
|
||||
c64scr.print_string("es")
|
||||
ask_guess
|
||||
c64util.print_string(" left.\nWhat is your next guess? ")
|
||||
Y = c64util.input_chars(guess)
|
||||
c64scr.print_string(" left.\nWhat is your next guess? ")
|
||||
Y = c64scr.input_chars(guess)
|
||||
c64.CHROUT('\n')
|
||||
[$22.word] = guess
|
||||
c64.FREADSTR(A)
|
||||
AY = c64util.GETADRAY()
|
||||
AY = c64.GETADRAY()
|
||||
A -= secretnumber ; @todo condition so we can do if guess > secretnumber....
|
||||
if_zero goto correct_guess
|
||||
if_gt goto too_high
|
||||
c64util.print_string("That is too ")
|
||||
c64util.print_string("low!\n")
|
||||
c64scr.print_string("That is too ")
|
||||
c64scr.print_string("low!\n")
|
||||
goto continue
|
||||
|
||||
correct_guess
|
||||
c64util.print_string("\nThat's my number, impressive!\n")
|
||||
c64scr.print_string("\nThat's my number, impressive!\n")
|
||||
goodbye()
|
||||
return
|
||||
|
||||
too_high
|
||||
c64util.print_string("That is too ")
|
||||
c64util.print_string("high!\n")
|
||||
c64scr.print_string("That is too ")
|
||||
c64scr.print_string("high!\n")
|
||||
|
||||
continue
|
||||
attempts_left--
|
||||
@ -79,8 +79,8 @@ continue
|
||||
goto printloop
|
||||
|
||||
game_over
|
||||
c64util.print_string("\nToo bad! It was: ")
|
||||
c64util.print_byte_decimal(secretnumber)
|
||||
c64scr.print_string("\nToo bad! It was: ")
|
||||
c64scr.print_byte_decimal(secretnumber)
|
||||
c64.CHROUT('\n')
|
||||
goodbye()
|
||||
return
|
||||
@ -90,7 +90,7 @@ sub goodbye ()->() {
|
||||
;memory y = $c000 ; @todo vars in sub
|
||||
;const q = 22 ; @todo const in sub
|
||||
|
||||
c64util.print_string("\nThanks for playing. Bye!\n")
|
||||
c64scr.print_string("\nThanks for playing. Bye!\n")
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -57,7 +57,7 @@ start
|
||||
c64.CHROUT('0')
|
||||
c64.CHROUT('1')
|
||||
c64.CHROUT('2')
|
||||
c64util.print_string(hello)
|
||||
c64scr.print_string(hello)
|
||||
goto c64.CHROUT('!')
|
||||
|
||||
|
||||
|
@ -9,41 +9,41 @@ output prg,basic ; create a c-64 program with basic SYS to() launch it
|
||||
const .word BORDER = $d020
|
||||
|
||||
start
|
||||
c64util.print_pimmediate ! () ; this prints the pstring immediately following it
|
||||
c64scr.print_pimmediate ! () ; this prints the pstring immediately following it
|
||||
asm {
|
||||
.ptext "hello-pimmediate!{cr}"
|
||||
}
|
||||
|
||||
c64util.print_byte_decimal0 ! (19)
|
||||
c64scr.print_byte_decimal0 ! (19)
|
||||
c64.CHROUT ! (13)
|
||||
c64util.print_byte_decimal ! (19)
|
||||
c64scr.print_byte_decimal ! (19)
|
||||
c64.CHROUT ! (13)
|
||||
|
||||
|
||||
c64util.print_word_decimal0 ! ($0102)
|
||||
c64scr.print_word_decimal0 ! ($0102)
|
||||
c64.CHROUT ! (13)
|
||||
c64util.print_word_decimal ! ($0102)
|
||||
c64scr.print_word_decimal ! ($0102)
|
||||
c64.CHROUT ! (13)
|
||||
return
|
||||
|
||||
start2
|
||||
global2.make_screen_black()
|
||||
c64.CLEARSCR()
|
||||
c64util.print_string(greeting)
|
||||
c64util.print_pstring(p_greeting)
|
||||
c64util.print_byte_decimal(0)
|
||||
c64util.print_byte_hex(0, 0)
|
||||
c64scr.print_string(greeting)
|
||||
c64scr.print_pstring(p_greeting)
|
||||
c64scr.print_byte_decimal(0)
|
||||
c64scr.print_byte_hex(0, 0)
|
||||
c64.CHROUT(13)
|
||||
c64util.print_byte_decimal(13)
|
||||
c64util.print_byte_hex(0, 13)
|
||||
c64scr.print_byte_decimal(13)
|
||||
c64scr.print_byte_hex(0, 13)
|
||||
c64.CHROUT(13)
|
||||
c64util.print_byte_decimal(255)
|
||||
c64util.print_byte_hex(0, 254)
|
||||
c64util.print_byte_hex(0, 129)
|
||||
c64scr.print_byte_decimal(255)
|
||||
c64scr.print_byte_hex(0, 254)
|
||||
c64scr.print_byte_hex(0, 129)
|
||||
c64.CHROUT(13)
|
||||
|
||||
c64.CHROUT(13)
|
||||
c64util.print_word_decimal($0100)
|
||||
c64scr.print_word_decimal($0100)
|
||||
c64.CHROUT(13)
|
||||
return
|
||||
|
||||
|
49
todo.ill
49
todo.ill
@ -1,48 +1,27 @@
|
||||
output prg,basic
|
||||
zp clobber, restore
|
||||
|
||||
;reg_preserve off ; @todo global option off/on default off?
|
||||
|
||||
import "c64lib"
|
||||
|
||||
~ ZP {
|
||||
var .float fl1 = 3.1415927
|
||||
var .float fl2 = 99.999999
|
||||
var .float fl3 = 100000
|
||||
}
|
||||
|
||||
|
||||
~ main {
|
||||
var .float fl1 = 3.1415927
|
||||
var .float fl2 = 99.999999
|
||||
var .float fl3 = 10
|
||||
|
||||
start
|
||||
fl1 = 111111.22222
|
||||
fl2 = 0
|
||||
fl3 = 1
|
||||
fl3 = -1
|
||||
fl3 = 0.5
|
||||
fl3 = -0.5
|
||||
A = $11
|
||||
X = $22
|
||||
Y = $33
|
||||
|
||||
X=6
|
||||
loop1
|
||||
A=X
|
||||
c64util.print_byte_hex(0, A)
|
||||
c64.CHROUT!(" ")
|
||||
X--
|
||||
if_pos goto loop1
|
||||
c64scr.clear_screen !(81, 5, $04)
|
||||
;c64scr.clear_screen !A (81, 5, $04)
|
||||
;c64scr.clear_screen !AX (81, 5, $04)
|
||||
;c64scr.clear_screen !AXY (81, 5, $04)
|
||||
|
||||
Y=6
|
||||
loop2
|
||||
A=Y
|
||||
c64util.print_byte_hex(0, A)
|
||||
c64.CHROUT!(" ")
|
||||
Y--
|
||||
if_neg goto stop
|
||||
goto loop2
|
||||
|
||||
stop
|
||||
c64scr.print_byte_hex(1,A)
|
||||
c64.CHROUT(' ')
|
||||
c64scr.print_byte_hex(1,X)
|
||||
c64.CHROUT(' ')
|
||||
c64scr.print_byte_hex(1,Y)
|
||||
c64scr.print_word_decimal(1222)
|
||||
c64.CHROUT('\n')
|
||||
|
||||
return
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user