mirror of
https://github.com/irmen/prog8.git
synced 2024-12-23 09:32:43 +00:00
if statement
This commit is contained in:
parent
9e87001ddb
commit
a3faf07c8c
@ -100,6 +100,16 @@ def parse_arguments(text: str, sourceref: SourceRef) -> List[Tuple[str, Primitiv
|
||||
raise TypeError("ast.Expression expected")
|
||||
|
||||
|
||||
def parse_expr_as_comparison(text: str, context: Optional[SymbolTable], ppcontext: Optional[SymbolTable], sourceref: SourceRef) -> None:
|
||||
src = SourceLine(text, sourceref)
|
||||
text = src.preprocess()
|
||||
try:
|
||||
node = ast.parse(text, sourceref.file, mode="eval")
|
||||
except SyntaxError as x:
|
||||
raise src.to_error(str(x))
|
||||
print("AST NODE", node)
|
||||
|
||||
|
||||
def parse_expr_as_int(text: str, context: Optional[SymbolTable], ppcontext: Optional[SymbolTable], sourceref: SourceRef, *,
|
||||
minimum: int=0, maximum: int=0xffff) -> int:
|
||||
result = parse_expr_as_primitive(text, context, ppcontext, sourceref, minimum=minimum, maximum=maximum)
|
||||
|
@ -944,25 +944,25 @@ class Parser:
|
||||
raise self.PError(str(x)) from x
|
||||
|
||||
def parse_subroutine_def(self, line: str) -> None:
|
||||
match = re.match(r"^sub\s+(?P<name>\w+)\s+"
|
||||
r"\((?P<parameters>[\w\s:,]*)\)"
|
||||
r"\s*->\s*"
|
||||
r"\((?P<results>[\w\s?,]*)\)\s*"
|
||||
r"(?P<decltype>\s+=\s+(?P<address>\S*)|{)\s*$", line)
|
||||
match = re.fullmatch(r"sub\s+(?P<name>\w+)\s+"
|
||||
r"\((?P<parameters>[\w\s:,]*)\)"
|
||||
r"\s*->\s*"
|
||||
r"\((?P<results>[\w\s?,]*)\)\s*"
|
||||
r"(?P<decltype>\s+=\s+(?P<address>\S*)|{)\s*", line)
|
||||
if not match:
|
||||
raise self.PError("invalid sub declaration")
|
||||
code_decl = match.group("decltype") == "{"
|
||||
name, parameterlist, resultlist, address_str = \
|
||||
match.group("name"), match.group("parameters"), match.group("results"), match.group("address")
|
||||
parameters = [(match.group("name"), match.group("target"))
|
||||
for match in re.finditer(r"(?:(?:(?P<name>[\w]+)\s*:\s*)?(?P<target>[\w]+))(?:,|$)", parameterlist)]
|
||||
groups = match.groupdict()
|
||||
code_decl = groups["decltype"] == "{"
|
||||
name, parameterlist, resultlist, address_str = groups["name"], groups["parameters"], groups["results"], groups["address"]
|
||||
parameters = [(m.group("name"), m.group("target"))
|
||||
for m in re.finditer(r"(?:(?:(?P<name>[\w]+)\s*:\s*)?(?P<target>[\w]+))(?:,|$)", parameterlist)]
|
||||
for _, regs in parameters:
|
||||
if regs not in REGISTER_SYMBOLS:
|
||||
raise self.PError("invalid register(s) in parameter or return values")
|
||||
all_paramnames = [p[0] for p in parameters if p[0]]
|
||||
if len(all_paramnames) != len(set(all_paramnames)):
|
||||
raise self.PError("duplicates in parameter names")
|
||||
results = [match.group("name") for match in re.finditer(r"\s*(?P<name>(?:\w+)\??)\s*(?:,|$)", resultlist)]
|
||||
results = [m.group("name") for m in re.finditer(r"\s*(?P<name>(?:\w+)\??)\s*(?:,|$)", resultlist)]
|
||||
subroutine_block = None
|
||||
if code_decl:
|
||||
address = None
|
||||
@ -1040,31 +1040,29 @@ class Parser:
|
||||
return varname, datatype, length, matrix_dimensions, valuetext
|
||||
|
||||
def parse_statement(self, line: str) -> ParseResult._AstNode:
|
||||
match = re.match(r"(?P<outputs>.*\s*=)\s*(?P<subname>[\S]+?)\s*(?P<fcall>[!]?)\s*(\((?P<arguments>.*)\))?\s*$", line)
|
||||
match = re.fullmatch(r"goto\s+(?P<subname>[\S]+?)\s*(\((?P<arguments>.*)\))?\s*", line)
|
||||
if match:
|
||||
# subroutine call (not a goto) with output param assignment
|
||||
preserve = not bool(match.group("fcall"))
|
||||
subname = match.group("subname")
|
||||
arguments = match.group("arguments")
|
||||
outputs = match.group("outputs")
|
||||
# goto
|
||||
groups = match.groupdict()
|
||||
subname = groups["subname"]
|
||||
if '!' in subname:
|
||||
raise self.PError("goto is always without register preservation, should not have exclamation mark")
|
||||
arguments = groups["arguments"]
|
||||
return self.parse_call_or_goto(subname, arguments, None, False, True)
|
||||
match = re.fullmatch(r"(?P<outputs>[^\(]*\s*=)?\s*(?P<subname>[\S]+?)\s*(?P<fcall>[!]?)\s*(\((?P<arguments>.*)\))?\s*", line)
|
||||
if match:
|
||||
# subroutine call (not a goto) with possible output param assignment
|
||||
groups = match.groupdict()
|
||||
preserve = not bool(groups["fcall"])
|
||||
subname = groups["subname"]
|
||||
arguments = groups["arguments"]
|
||||
outputs = groups["outputs"] or ""
|
||||
if outputs.strip() == "=":
|
||||
raise self.PError("missing assignment target variables")
|
||||
outputs = outputs.rstrip("=")
|
||||
if arguments or match.group(4):
|
||||
if arguments or match.group(4): # group 4 = (possibly empty) parenthesis
|
||||
return self.parse_call_or_goto(subname, arguments, outputs, preserve, False)
|
||||
# apparently it is not a call (no arguments), fall through
|
||||
match = re.match(r"(?P<goto>goto\s+)?(?P<subname>[\S]+?)\s*(?P<fcall>[!]?)\s*(\((?P<arguments>.*)\))?\s*$", line)
|
||||
if match:
|
||||
# subroutine or goto call, without output param assignment
|
||||
is_goto = bool(match.group("goto"))
|
||||
preserve = not bool(match.group("fcall"))
|
||||
subname = match.group("subname")
|
||||
arguments = match.group("arguments")
|
||||
if is_goto:
|
||||
return self.parse_call_or_goto(subname, arguments, None, preserve, True)
|
||||
elif arguments or match.group(4):
|
||||
return self.parse_call_or_goto(subname, arguments, None, preserve, False)
|
||||
# apparently it is not a call (no arguments), fall through
|
||||
if line == "return" or line.startswith(("return ", "return\t")):
|
||||
return self.parse_return(line)
|
||||
elif line.endswith(("++", "--")):
|
||||
|
@ -10,7 +10,7 @@
|
||||
output raw
|
||||
|
||||
~ c64 {
|
||||
memory SCRATCH_ZP1 = $02 ; scratch register #1 in ZP
|
||||
memory SCRATCH_ZP1 = $02 ; scratch register #1 in ZP
|
||||
memory SCRATCH_ZP2 = $03 ; scratch register #2 in ZP
|
||||
|
||||
memory .byte COLOR = $0286 ; cursor color
|
||||
@ -92,7 +92,6 @@ output raw
|
||||
memory .float FL_FR4 = $e2ea ; .25
|
||||
|
||||
|
||||
; @todo verify clobbered registers?
|
||||
; note: fac1/2 might get clobbered even if not mentioned in the function's name.
|
||||
; note: for subtraction and division, the left operand is in fac2, the right operand in fac1.
|
||||
|
||||
@ -132,7 +131,7 @@ sub FADDT () -> (A?, X?, Y?) = $b86a ; fac1 += fac2
|
||||
sub FADD (mflpt: AY) -> (A?, X?, Y?) = $b867 ; fac1 += mflpt value from A/Y
|
||||
sub FSUBT () -> (A?, X?, Y?) = $b853 ; fac1 = fac2-fac1 mind the order of the operands
|
||||
sub FSUB (mflpt: AY) -> (A?, X?, Y?) = $b850 ; fac1 = mflpt from A/Y - fac1
|
||||
sub FMULTT () -> (A?, X?, Y?) = $ba2b ; fac1 *= fac2
|
||||
sub FMULTT () -> (A?, X?, Y?) = $ba2b ; fac1 *= fac2
|
||||
sub FMULT (mflpt: AY) -> (A?, X?, Y?) = $ba28 ; fac1 *= mflpt value from A/Y
|
||||
sub FDIVT () -> (A?, X?, Y?) = $bb12 ; fac1 = fac2/fac1 mind the order of the operands
|
||||
sub FDIV (mflpt: AY) -> (A?, X?, Y?) = $bb0f ; fac1 = mflpt in A/Y / fac1
|
||||
@ -230,7 +229,7 @@ sub FREADS32 () -> (A?, X?, Y?) {
|
||||
ldx #$a0
|
||||
jmp $bc4f ; internal BASIC routine
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sub FREADUS32 () -> (A?, X?, Y?) {
|
||||
; ---- fac1 = uint32 from $62-$65 big endian (MSB FIRST)
|
||||
@ -244,7 +243,7 @@ sub FREADUS32 () -> (A?, X?, Y?) {
|
||||
|
||||
sub FREADS24AXY (lo: A, mid: X, hi: Y) -> (A?, X?, Y?) {
|
||||
; ---- fac1 = signed int24 (A/X/Y contain lo/mid/hi bytes)
|
||||
; note: there is no FREADU24AXY (unsigned), use FREADUS32 instead.
|
||||
; note: there is no FREADU24AXY (unsigned), use FREADUS32 instead.
|
||||
asm {
|
||||
sty $62
|
||||
stx $63
|
||||
@ -258,7 +257,7 @@ sub FREADS24AXY (lo: A, mid: X, hi: Y) -> (A?, X?, Y?) {
|
||||
jmp $bc4f ; internal BASIC routine
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
sub GIVUAYF (uword: AY) -> (A?, X?, Y?) {
|
||||
; ---- unsigned 16 bit word in A/Y (lo/hi) to fac1
|
||||
asm {
|
||||
@ -589,4 +588,48 @@ sub input_chars (buffer: AX) -> (A?, Y) {
|
||||
}
|
||||
}
|
||||
|
||||
sub memcopy_basic () -> (A?, X?, Y?) {
|
||||
; ---- copy a memory block by using a BASIC ROM routine @todo fix code
|
||||
; it calls a function from the basic interpreter, so:
|
||||
; - BASIC ROM must be banked in
|
||||
; - the source block must be readable (so no RAM hidden under BASIC, Kernal, or I/O)
|
||||
; - the target block must be writable (so no RAM hidden under I/O)
|
||||
; higher addresses are copied first, so:
|
||||
; - moving data to higher addresses works even if areas overlap
|
||||
; - moving data to lower addresses only works if areas do not overlap
|
||||
asm {
|
||||
lda #<src_start
|
||||
ldx #>src_start
|
||||
sta $5f
|
||||
stx $60
|
||||
lda #<src_end
|
||||
ldx #>src_end
|
||||
sta $5a
|
||||
stx $5b
|
||||
lda #<(target_start + src_end - src_start)
|
||||
ldx #>(target_start + src_end - src_start)
|
||||
sta $58
|
||||
stx $59
|
||||
jmp $a3bf
|
||||
}
|
||||
}
|
||||
|
||||
; macro version of the above memcopy_basic routine: @todo macro support?
|
||||
; MACRO PARAMS src_start, src_end, target_start
|
||||
; lda #<src_start
|
||||
; ldx #>src_start
|
||||
; sta $5f
|
||||
; stx $60
|
||||
; lda #<src_end
|
||||
; ldx #>src_end
|
||||
; sta $5a
|
||||
; stx $5b
|
||||
; lda #<(target_start + src_end - src_start)
|
||||
; ldx #>(target_start + src_end - src_start)
|
||||
; sta $58
|
||||
; stx $59
|
||||
; jsr $a3bf
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
72
reference.md
72
reference.md
@ -18,7 +18,7 @@ which aims to provide many conveniences over raw assembly code (even when using
|
||||
- various data types other than just bytes
|
||||
- automatic type conversions
|
||||
- floating point operations
|
||||
- automatically preserving and restoring CPU registers state, when calling routines that otherwise would clobber these
|
||||
- automatically preserving and restoring CPU registers state, when calling routines that otherwise would clobber these
|
||||
- abstracting away low level aspects such as zero page handling, program startup, explicit memory addresses
|
||||
- @todo: conditionals and loops
|
||||
- @todo: memory block operations
|
||||
@ -28,7 +28,7 @@ to write performance critical pieces of code, but otherwise compiles fairly stra
|
||||
into 6502 assembly code. This resulting code is assembled into a binary program by using
|
||||
an external macro assembler, [64tass](https://sourceforge.net/projects/tass64/).
|
||||
It can be compiled pretty easily for various platforms (Linux, Mac OS, Windows) or just ask me
|
||||
to provide a small precompiled executable if you need that.
|
||||
to provide a small precompiled executable if you need that.
|
||||
You need [Python 3.5](https://www.python.org/downloads/) or newer to run IL65 itself.
|
||||
|
||||
IL65 is mainly targeted at the Commodore-64 machine, but should be mostly system independent.
|
||||
@ -42,7 +42,7 @@ Most of the 64 kilobyte address space can be accessed by your program.
|
||||
| type | memory area | note |
|
||||
|-----------------|-------------------------|-----------------------------------------------------------------|
|
||||
| Zero page | ``$00`` - ``$ff`` | contains many sensitive system variables |
|
||||
| Hardware stack | ``$100`` - ``$1ff`` | is used by the CPU and should normally not be accessed directly |
|
||||
| Hardware stack | ``$100`` - ``$1ff`` | is used by the CPU and should normally not be accessed directly |
|
||||
| Free RAM or ROM | ``$0200`` - ``$ffff`` | free to use memory area, often a mix of RAM and ROM |
|
||||
|
||||
|
||||
@ -92,7 +92,7 @@ For the Commodore-64 here is a list of free-to-use zero page locations even when
|
||||
|
||||
``$02`` - ``$03`` (but see remark above); ``$04`` - ``$05``; ``$06``;
|
||||
``$0a``; ``$2a``; ``$52``; ``$93``;
|
||||
``$f7`` - ``$f8``; ``$f9`` - ``$fa``; ``$fb`` - ``$fc``; ``$fd`` - ``$fe``
|
||||
``$f7`` - ``$f8``; ``$f9`` - ``$fa``; ``$fb`` - ``$fc``; ``$fd`` - ``$fe``
|
||||
|
||||
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
|
||||
@ -118,7 +118,7 @@ IL65 supports the following data types:
|
||||
| address-of | 16 bits | | ``#variable`` |
|
||||
| indirect | variable | | ``[ address ]`` |
|
||||
|
||||
Strings can be writen in your code as CBM PETSCII or as C-64 screencode variants,
|
||||
Strings can be writen in your code as CBM PETSCII or as C-64 screencode variants,
|
||||
these will be translated by the compiler. PETSCII is the default, if you need screencodes you
|
||||
have to use the ``s`` variants of the type identifier.
|
||||
|
||||
@ -134,7 +134,7 @@ treats those as a value that you manipulate via its address, so the ``#`` is ign
|
||||
For most other types this prefix is not supported.
|
||||
|
||||
**Indirect addressing:** The ``[address]`` syntax means: the contents of the memory at address, or "indirect addressing".
|
||||
By default, if not otherwise known, a single byte is assumed. You can add the ``.byte`` or ``.word`` or ``.float``
|
||||
By default, if not otherwise known, a single byte is assumed. You can add the ``.byte`` or ``.word`` or ``.float``
|
||||
type identifier suffix to make it clear what data type the address points to.
|
||||
This addressing mode is only supported for constant (integer) addresses and not for variable types,
|
||||
unless it is part of a subroutine call statement. For an indirect goto call, the 6502 CPU has a special opcode
|
||||
@ -146,7 +146,7 @@ PROGRAM STRUCTURE
|
||||
|
||||
In IL65 every line in the source file can only contain *one* statement or declaration.
|
||||
Compilation is done on *one* main source code file, but other files can be imported.
|
||||
|
||||
|
||||
### Comments
|
||||
|
||||
Everything after a semicolon '``;``' is a comment and is ignored.
|
||||
@ -171,11 +171,11 @@ at the beginning of your program:
|
||||
|
||||
### Program Entry Point
|
||||
|
||||
Every program has to have one entry point where code execution begins.
|
||||
Every program has to have one entry point where code execution begins.
|
||||
The compiler looks for the ``start`` label in the ``main`` block for this.
|
||||
For proper program termination, this block has to end with a ``return`` statement (or a ``goto`` call).
|
||||
Blocks and other details are described below.
|
||||
|
||||
|
||||
|
||||
### Blocks
|
||||
|
||||
@ -241,7 +241,7 @@ if this makes sense.
|
||||
|
||||
Subroutines are parts of the code that can be repeatedly invoked using a subroutine call from elsewhere.
|
||||
Their definition, using the sub statement, includes the specification of the required input- and output parameters.
|
||||
For now, only register based parameters are supported (A, X, Y and paired registers,
|
||||
For now, only register based parameters are supported (A, X, Y and paired registers,
|
||||
the carry status bit SC and the interrupt disable bit SI as specials).
|
||||
For subroutine return values, the special SZ register is also available, it means the zero status bit.
|
||||
|
||||
@ -280,11 +280,11 @@ You call a subroutine like this:
|
||||
If the subroutine returns one or more values as results, you must use an assignment statement
|
||||
to store those values somewhere:
|
||||
outputvar1, outputvar2 = subroutine ( arg1, arg2, arg3 )
|
||||
|
||||
|
||||
The output variables must occur in the correct sequence of return registers as specified
|
||||
in the subroutine's definiton. It is possible to not specify any of them but the compiler
|
||||
will issue a warning then if the result values of a subroutine call are discarded.
|
||||
Even if the subroutine returns something in a register that already is the correct one
|
||||
Even if the subroutine returns something in a register that already is the correct one
|
||||
you want to keep, you'll have to explicitly assign the return value to that register.
|
||||
If you omit it, no return value is stored at all (well, unless you call the subroutine without
|
||||
register preserving, see the next paragraph.)
|
||||
@ -314,15 +314,15 @@ TODOS
|
||||
Required building blocks: additional forms of 'go' statement: including an if clause, comparison statement.
|
||||
|
||||
- a primitive conditional branch instruction (special case of 'go'): directly translates to a branch instruction:
|
||||
if[_XX] go <label>
|
||||
if[_XX] goto <label>
|
||||
XX is one of: (cc, cs, vc, vs, eq, ne, pos, min,
|
||||
lt==cc, lts==min, gt==eq+cs, gts==eq+pos, le==cc+eq, les==neg+eq, ge==cs, ges==pos)
|
||||
and when left out, defaults to ne (not-zero, i.e. true)
|
||||
NOTE: some combination branches such as cc+eq an be peephole optimized see http://www.6502.org/tutorials/compare_beyond.html#2.2
|
||||
|
||||
- conditional go with expression: where the if[_XX] is followed by a <expression>
|
||||
- conditional goto with expression: where the if[_XX] is followed by a <expression>
|
||||
in that case, evaluate the <expression> first (whatever it is) and then emit the primitive if[_XX] go
|
||||
if[_XX] <expression> go <label>
|
||||
if[_XX] <expression> goto <label>
|
||||
eventually translates to:
|
||||
<expression-code>
|
||||
bXX <label>
|
||||
@ -347,15 +347,15 @@ if[_XX] [<expression>] {
|
||||
|
||||
(no else:)
|
||||
|
||||
if[_!XX] [<expression>] go il65_if_999_end ; !XX being the conditional inverse of XX
|
||||
if[_!XX] [<expression>] goto il65_if_999_end ; !XX being the conditional inverse of XX
|
||||
.... (true part)
|
||||
il65_if_999_end ; code continues after this
|
||||
|
||||
|
||||
(with else):
|
||||
if[_XX] [<expression>] go il65_if_999
|
||||
if[_XX] [<expression>] goto il65_if_999
|
||||
... (else part)
|
||||
go il65_if_999_end
|
||||
goto il65_if_999_end
|
||||
il65_if_999 ... (true part)
|
||||
il65_if_999_end ; code continues after this
|
||||
|
||||
@ -364,7 +364,7 @@ il65_if_999_end ; code continues after this
|
||||
|
||||
==> DESUGARING ==>
|
||||
compare X, Y
|
||||
if_XX go ....
|
||||
if_XX goto ....
|
||||
XX based on <COMPARISON>.
|
||||
|
||||
|
||||
@ -381,13 +381,13 @@ while[_XX] <expression> {
|
||||
|
||||
==> DESUGARING ==>
|
||||
|
||||
go il65_while_999_check ; jump to the check
|
||||
goto il65_while_999_check ; jump to the check
|
||||
il65_while_999
|
||||
... (code)
|
||||
go il65_while_999 ;continue
|
||||
go il65_while_999_end ;break
|
||||
goto il65_while_999 ;continue
|
||||
goto il65_while_999_end ;break
|
||||
il65_while_999_check
|
||||
if[_XX] <expression> go il65_while_999 ; loop condition
|
||||
if[_XX] <expression> goto il65_while_999 ; loop condition
|
||||
il65_while_999_end ; code continues after this
|
||||
|
||||
|
||||
@ -403,9 +403,9 @@ repeat {
|
||||
|
||||
il65_repeat_999
|
||||
... (code)
|
||||
go il65_repeat_999 ;continue
|
||||
go il65_repeat_999_end ;break
|
||||
if[_!XX] <expression> go il65_repeat_999 ; loop condition via conditional inverse of XX
|
||||
goto il65_repeat_999 ;continue
|
||||
goto il65_repeat_999_end ;break
|
||||
if[_!XX] <expression> goto il65_repeat_999 ; loop condition via conditional inverse of XX
|
||||
il65_repeat_999_end ; code continues after this
|
||||
|
||||
|
||||
@ -425,17 +425,17 @@ for <loopvar> = <from_expression> to <to_expression> [step <step_expression>] {
|
||||
|
||||
loopvar = <from_expression>
|
||||
compare loopvar, <to_expression>
|
||||
if_ge go il65_for_999_end ; loop condition
|
||||
if_ge goto il65_for_999_end ; loop condition
|
||||
step = <step_expression> ; (store only if step < -1 or step > 1)
|
||||
il65_for_999
|
||||
go il65_for_999_end ;break
|
||||
go il65_for_999_loop ;continue
|
||||
goto il65_for_999_end ;break
|
||||
goto il65_for_999_loop ;continue
|
||||
.... (code)
|
||||
il65_for_999_loop
|
||||
loopvar += step ; (if step > 1 or step < -1)
|
||||
loopvar++ ; (if step == 1)
|
||||
loopvar-- ; (if step == -1)
|
||||
go il65_for_999 ; continue the loop
|
||||
goto il65_for_999 ; continue the loop
|
||||
il65_for_999_end ; code continues after this
|
||||
|
||||
|
||||
@ -484,6 +484,16 @@ and SPRITES (24x21 monochrome or 12x21 multicolor = 63 bytes)
|
||||
--> PLACE in memory on correct address (base+sprite pointer, 64-byte aligned)
|
||||
|
||||
|
||||
### More Datatypes
|
||||
### More Datatypes
|
||||
|
||||
@todo 24 and 32 bits integers, unsigned and signed?
|
||||
|
||||
### Some support for simple arithmetic
|
||||
|
||||
A *= Y
|
||||
A = X * Y
|
||||
A /= Y
|
||||
A = Y / Y
|
||||
|
||||
@todo multiplication routines (8*8 -> 16, 8*16 -> 16, 16*16->16 (or 32?))
|
||||
@todo division routines
|
||||
|
@ -45,10 +45,10 @@ start
|
||||
|
||||
sub printflt (float: AY) -> (A?, X?, Y?) {
|
||||
c64.MOVFM!(AY)
|
||||
goto c64.FPRINTLN!()
|
||||
goto c64.FPRINTLN
|
||||
; c64.FOUT!()
|
||||
; c64util.print_string!(AY)
|
||||
;goto c64.CHROUT!('\n')
|
||||
;goto c64.CHROUT('\n')
|
||||
}
|
||||
|
||||
|
||||
|
@ -18,6 +18,15 @@ start
|
||||
c64util.print_string(name)
|
||||
c64.CHROUT('\n')
|
||||
|
||||
;if_cc goto label
|
||||
;if_cc label
|
||||
;if_cc dsdaf + 33 < 22 label
|
||||
;if_cc dsdaf + 33 < 22 goto label!
|
||||
goto label
|
||||
goto label()
|
||||
|
||||
label
|
||||
|
||||
SI = 1
|
||||
c64.CINV = XY
|
||||
SI = 0
|
||||
|
Loading…
Reference in New Issue
Block a user