From c78cbc4a33982337d599fe6e24ff1fd948c94ea8 Mon Sep 17 00:00:00 2001 From: Irmen de Jong Date: Mon, 25 Dec 2017 21:43:06 +0100 Subject: [PATCH] add SI register --- il65/astparse.py | 2 +- il65/codegen.py | 6 ++++++ il65/parse.py | 4 ++-- il65/symbols.py | 4 ++-- lib/c64lib.ill | 35 ++++++++++++++++++++++++++++++----- reference.md | 6 +++++- testsource/dtypes.ill | 3 +++ testsource/input.ill | 34 ++++++++++++++++++++++++++++++++++ 8 files changed, 83 insertions(+), 11 deletions(-) create mode 100644 testsource/input.ill diff --git a/il65/astparse.py b/il65/astparse.py index ce2b44194..8928d6b77 100644 --- a/il65/astparse.py +++ b/il65/astparse.py @@ -135,7 +135,7 @@ class EvaluatingTransformer(ast.NodeTransformer): globals = {"__builtins__": {}} locals = None try: - result = eval(code, globals, locals) + result = eval(code, globals, locals) # XXX unsafe... except Exception as x: raise self.src.to_error(str(x)) from x else: diff --git a/il65/codegen.py b/il65/codegen.py index 6569af80a..6a58dd14b 100644 --- a/il65/codegen.py +++ b/il65/codegen.py @@ -928,6 +928,12 @@ class CodeGenerator: self.p("\t\tsec") else: self.p("\t\tclc") + elif l_register == "SI": + # interrupt disable bit + if rvalue.value: + self.p("\t\tsei") + else: + self.p("\t\tcli") else: raise CodeError("invalid register in immediate integer assignment", l_register, rvalue.value) diff --git a/il65/parse.py b/il65/parse.py index 418ecde70..f7e506b87 100644 --- a/il65/parse.py +++ b/il65/parse.py @@ -245,10 +245,10 @@ class ParseResult: return True, "" return False, "(unsigned) byte required" return False, "incompatible indirect value for register assignment" - if self.register == "SC": + if self.register in ("SC", "SI"): if isinstance(other, ParseResult.IntegerValue) and other.value in (0, 1): return True, "" - return False, "can only assign an integer constant value of 0 or 1 to SC" + return False, "can only assign an integer constant value of 0 or 1 to SC and SI" if self.constant: return False, "cannot assign to a constant" if isinstance(other, ParseResult.RegisterValue) and len(self.register) < len(other.register): diff --git a/il65/symbols.py b/il65/symbols.py index 0d927d3d9..83bd97380 100644 --- a/il65/symbols.py +++ b/il65/symbols.py @@ -16,9 +16,9 @@ from typing import Optional, Set, Union, Tuple, Dict, Iterable, Sequence, Any, L PrimitiveType = Union[int, float, str] -REGISTER_SYMBOLS = {"A", "X", "Y", "AX", "AY", "XY", "SC"} +REGISTER_SYMBOLS = {"A", "X", "Y", "AX", "AY", "XY", "SC", "SI"} REGISTER_SYMBOLS_RETURNVALUES = REGISTER_SYMBOLS | {"SZ"} -REGISTER_BYTES = {"A", "X", "Y", "SC"} +REGISTER_BYTES = {"A", "X", "Y", "SC", "SI"} REGISTER_WORDS = {"AX", "AY", "XY"} # 5-byte cbm MFLPT format limitations: diff --git a/lib/c64lib.ill b/lib/c64lib.ill index 9fb6b5305..4a596305c 100644 --- a/lib/c64lib.ill +++ b/lib/c64lib.ill @@ -10,7 +10,8 @@ output raw memory SCRATCH_ZP1 = $02 ; scratch register #1 in ZP memory SCRATCH_ZP2 = $03 ; scratch register #2 in ZP - memory COLOR = $286 ; cursor color + memory COLOR = $0286 ; cursor color + memory CINV = $0314 ; IRQ vector ; ---- VIC-II registers ---- @@ -163,6 +164,8 @@ sub HOMECRSR () -> (A?, X?, Y?) = $E566 ; cursor to top left of screen ; ---- C64 kernal routines ---- +sub IRQDFRT () -> (A?, X?, Y?) = $EA31 ; default IRQ routine +sub IRQDFEND () -> (A?, X?, Y?) = $EA81 ; default IRQ end/cleanup sub CINT () -> (A?, X?, Y?) = $FF81 ; (alias: SCINIT) initialize screen editor and video chip sub IOINIT () -> (A?, X?) = $FF84 ; initialize I/O devices sub RAMTAS () -> (A?, X?, Y?) = $FF87 ; initialize RAM, tape buffer, screen @@ -189,7 +192,7 @@ sub CLOSE (logical: A) -> (A?, X?, Y?) = $FFC3 ; (via 796 ($31C)) sub CHKIN (logical: X) -> (A?, X?) = $FFC6 ; (via 798 ($31E)) define an input channel sub CHKOUT (logical: X) -> (A?, X?) = $FFC9 ; (via 800 ($320)) define an output channel sub CLRCHN () -> (A?, X?) = $FFCC ; (via 802 ($322)) restore default devices -sub CHRIN () -> (A, Y?) = $FFCF ; (via 804 ($324)) input a character +sub CHRIN () -> (A, Y?) = $FFCF ; (via 804 ($324)) input a character (for keyboard, read a whole line from the screen) A=byte read. sub CHROUT (char: A) -> () = $FFD2 ; (via 806 ($326)) output a character sub LOAD (verify: A, address: XY) -> (SC, A, X, Y) = $FFD5 ; (via 816 ($330)) load from device sub SAVE (zp_startaddr: A, endaddr: XY) -> (SC, A) = $FFD8 ; (via 818 ($332)) save to a device @@ -205,9 +208,9 @@ sub IOBASE () -> (X, Y) = $FFF3 ; read base address ; ---- end of C64 kernal routines ---- - memory .word NMI_VEC = $FFFA - memory .word RESET_VEC = $FFFC - memory .word IRQ_VEC = $FFFE + memory .word NMI_VEC = $FFFA ; nmi vector, set by the kernal if banked in + 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 } @@ -561,4 +564,26 @@ _pr_decimal } } + +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!! + + asm { + sta c64.SCRATCH_ZP1 + stx c64.SCRATCH_ZP2 + ldy #0 ; char counter = 0 +- jsr c64.CHRIN + cmp #$0d ; return (ascii 13) pressed? + beq + ; yes, end. + sta (c64.SCRATCH_ZP1),y ; else store char in buffer + iny + bne - ++ lda #0 + sta (c64.SCRATCH_ZP1),y ; finish string with 0 byte + rts + + } +} + } diff --git a/reference.md b/reference.md index bf9ade286..38f9fbb20 100644 --- a/reference.md +++ b/reference.md @@ -73,6 +73,7 @@ The following 6502 hardware registers are directly accessible in your code (and - ``A``, ``X``, ``Y`` - ``AX``, ``AY``, ``XY`` (surrogate registers: 16-bit combined register pairs in LSB byte order lo/hi) - ``SC`` (status register's Carry flag) +- ``SI`` (status register's Interrupt Disable flag) ### Zero Page ("ZP") @@ -240,7 +241,10 @@ 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, and the carry status bit SC as a special). +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. + The syntax is: sub ([proc_parameters]) -> ([proc_results]) { diff --git a/testsource/dtypes.ill b/testsource/dtypes.ill index 1e8495e00..57eb47634 100644 --- a/testsource/dtypes.ill +++ b/testsource/dtypes.ill @@ -223,6 +223,9 @@ start SC = 0 SC = 1 SC = false + SI = 1 + SI = 0 + SI = false uninitbyte1 = 99 uninitbyte1 = 1.234 diff --git a/testsource/input.ill b/testsource/input.ill new file mode 100644 index 000000000..aa1374668 --- /dev/null +++ b/testsource/input.ill @@ -0,0 +1,34 @@ +output prg,sys + +import "c64lib" + +~ main { + + var .text name = "?"*80 + +start + SI = 1 + [$0314.word] = #irq_handler + SI = 0 + + c64util.print_string("enter your name: ") + c64util.input_chars(name) + c64.CHROUT('\n') + ; c64util.print_string("thank you, ") ; @todo fix param parsing /splitting + c64util.print_string("thank you ") + c64util.print_string(name) + c64.CHROUT('\n') + + return + +irq_handler + asm { + lda $cb + cmp #$40 + beq + + inc c64.EXTCOL ++ jmp c64.IRQDFRT + } + + +} \ No newline at end of file