This commit is contained in:
Irmen de Jong 2017-12-31 03:19:06 +01:00
parent a5283bfc7b
commit 2f6ef28c80
15 changed files with 284 additions and 218 deletions

View File

@ -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

View File

@ -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)]

View File

@ -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)

View File

@ -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
}
}

View File

@ -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
}
}

View File

@ -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

View File

@ -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)
---------------------

View File

@ -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)

View File

@ -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

View File

@ -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')
}

View File

@ -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

View File

@ -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
}

View File

@ -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('!')

View File

@ -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

View File

@ -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