From faa08133a892dc96719d6cf27ba2527137b2ab05 Mon Sep 17 00:00:00 2001 From: Irmen de Jong Date: Sat, 13 Jan 2018 22:42:07 +0100 Subject: [PATCH] memset fixed --- il65/compile.py | 3 +- il65/generateasm.py | 11 ++++-- il65/lib/c64lib.ill | 18 +++++---- il65/lib/il65lib.ill | 93 +++++++++++++++++++++++++++++++++++--------- il65/main.py | 3 +- il65/plyparse.py | 17 +++++--- reference.md | 3 ++ 7 files changed, 110 insertions(+), 38 deletions(-) diff --git a/il65/compile.py b/il65/compile.py index ae92ecca1..2d4f6d8b9 100644 --- a/il65/compile.py +++ b/il65/compile.py @@ -86,7 +86,8 @@ class PlyParser: zeropage = Zeropage(module.zp_options) for vardef in zpnode.scope.filter_nodes(VarDef): try: - vardef.zp_address = zeropage.allocate(vardef) + if vardef.vartype == VarType.VAR: + vardef.zp_address = zeropage.allocate(vardef) except CompileError as x: raise ParseError(str(x), vardef.sourceref) diff --git a/il65/generateasm.py b/il65/generateasm.py index 96ed01c27..b8386ac1c 100644 --- a/il65/generateasm.py +++ b/il65/generateasm.py @@ -338,9 +338,14 @@ class AssemblyGenerator: assert len(vardef.size) == 1 self.p("\v{:s} = {:s}\t; array of {:d} words".format(vardef.name, to_hex(vardef.value), vardef.size[0])) elif vardef.datatype == DataType.MATRIX: - assert len(vardef.size) == 2 - self.p("\v{:s} = {:s}\t; matrix of {:d} by {:d} = {:d} bytes" - .format(vardef.name, to_hex(vardef.value), vardef.size[0], vardef.size[1], vardef.size[0]*vardef.size[1])) + assert len(vardef.size) in (2, 3) + if len(vardef.size) == 2: + comment = "matrix of {:d} by {:d} = {:d} bytes".format(vardef.size[0], vardef.size[1], vardef.size[0]*vardef.size[1]) + elif len(vardef.size) == 3: + comment = "matrix of {:d} by {:d}, interleave {:d}".format(vardef.size[0], vardef.size[1], vardef.size[2]) + else: + raise CodeError("matrix size should be 2 or 3 numbers") + self.p("\v{:s} = {:s}\t; {:s}".format(vardef.name, to_hex(vardef.value), comment)) else: raise CodeError("invalid var type") self.p("; normal variables - initial values will be set by init code") diff --git a/il65/lib/c64lib.ill b/il65/lib/c64lib.ill index dd9016ae6..7fea24007 100644 --- a/il65/lib/c64lib.ill +++ b/il65/lib/c64lib.ill @@ -20,6 +20,7 @@ memory .byte SFDX = $cb ; current key pressed (matrix value) (updated by IRQ) memory .byte COLOR = $0286 ; cursor color + memory .byte HIBASE = $0288 ; screen base address / 256 (hi-byte of screen memory address) memory .word CINV = $0314 ; IRQ vector memory .matrix(40, 25) Screen = $0400 ; default character screen matrix memory .matrix(40, 25) Colors = $d800 ; character screen colors @@ -452,6 +453,7 @@ sub float_sub_SW1_from_XY (mflt: XY) -> (?) { sub clear_screen (char:A, color: Y) -> () { ; ---- clear the character screen with the given fill character and character color. ; (assumes screen is at $0400, could be altered in the future with self-modifying code) + ; @todo X = SCREEN ADDR HI BYTE %asm { sta _loop + 1 ; self-modifying @@ -486,7 +488,7 @@ sub scroll_left_full (alsocolors: SC) -> (A?, X?, Y?) { bcs + jmp _scroll_screen -+ ++ ; scroll the color memory ldx #0 ldy #38 - @@ -509,7 +511,7 @@ sub scroll_left_full (alsocolors: SC) -> (A?, X?, Y?) { dey bpl - -_scroll_screen +_scroll_screen ; scroll the screen memory ldx #0 ldy #38 - @@ -545,7 +547,7 @@ sub scroll_right_full (alsocolors: SC) -> (A?, X?) { bcs + jmp _scroll_screen -+ ++ ; scroll the color memory ldx #38 - .for row=0, row<=12, row+=1 @@ -564,7 +566,7 @@ sub scroll_right_full (alsocolors: SC) -> (A?, X?) { dex bpl - -_scroll_screen +_scroll_screen ; scroll the screen memory ldx #38 - .for row=0, row<=12, row+=1 @@ -596,7 +598,7 @@ sub scroll_up_full (alsocolors: SC) -> (A?, X?) { bcs + jmp _scroll_screen -+ ++ ; scroll the color memory ldx #39 - .for row=1, row<=11, row+=1 @@ -615,7 +617,7 @@ sub scroll_up_full (alsocolors: SC) -> (A?, X?) { dex bpl - -_scroll_screen +_scroll_screen ; scroll the screen memory ldx #39 - .for row=1, row<=11, row+=1 @@ -647,7 +649,7 @@ sub scroll_down_full (alsocolors: SC) -> (A?, X?) { bcs + jmp _scroll_screen -+ ++ ; scroll the color memory ldx #39 - .for row=23, row>=12, row-=1 @@ -666,7 +668,7 @@ sub scroll_down_full (alsocolors: SC) -> (A?, X?) { dex bpl - -_scroll_screen +_scroll_screen ; scroll the screen memory ldx #39 - .for row=23, row>=12, row-=1 diff --git a/il65/lib/il65lib.ill b/il65/lib/il65lib.ill index 9da9baed0..186c7f934 100644 --- a/il65/lib/il65lib.ill +++ b/il65/lib/il65lib.ill @@ -88,29 +88,84 @@ memcopy rts -; fill memory from (SCRATCH_ZPWORD1) length X (1-256, 0=256) with value in A. +; fill memory from (SCRATCH_ZPWORD1), length XY, with value in A. ; clobbers X, Y -memset ldy #0 -- sta (SCRATCH_ZPWORD1), y - iny - dex - bne - - rts - -; fill memory from (SCRATCH_ZPWORD1) length X (1-256, 0=256) with word value in AY. -; clobbers A, X, Y -memsetw sty _mod_hi+1 ; self-modify - sta _mod_lo+1 ; self-modify +memset stx SCRATCH_ZP1 + sty SCRATCH_ZP2 ldy #0 -_mod_lo lda #$00 ; self-modified - sta (SCRATCH_ZPWORD1), y - iny -_mod_hi lda #$00 ; self-modified - sta (SCRATCH_ZPWORD1), y + ldx SCRATCH_ZP2 + beq _lastpage + +_fullpage sta (SCRATCH_ZPWORD1),y iny + bne _fullpage + inc SCRATCH_ZPWORD1+1 ; next page dex - bne _mod_lo - rts + bne _fullpage + +_lastpage ldy SCRATCH_ZP1 + beq + +- dey + sta (SCRATCH_ZPWORD1),y + bne - + ++ rts + + + +; fill memory from (SCRATCH_ZPWORD1) number of words in SCRATCH_ZPWORD2, with word value in AY. +; clobbers A, X, Y +memsetw + sta _mod1+1 ; self-modify + sty _mod1b+1 ; self-modify + sta _mod2+1 ; self-modify + sty _mod2b+1 ; self-modify + ldx SCRATCH_ZPWORD1 + stx SCRATCH_ZP1 + ldx SCRATCH_ZPWORD1+1 + inx + stx SCRATCH_ZP2 ; second page + + ldy #0 + ldx SCRATCH_ZPWORD2+1 + beq _lastpage + +_fullpage +_mod1 lda #0 ; self-modified + sta (SCRATCH_ZPWORD1),y ; first page + sta (SCRATCH_ZP1),y ; second page + iny +_mod1b lda #0 ; self-modified + sta (SCRATCH_ZPWORD1),y ; first page + sta (SCRATCH_ZP1),y ; second page + iny + bne _fullpage + inc SCRATCH_ZPWORD1+1 ; next page pair + inc SCRATCH_ZPWORD1+1 ; next page pair + inc SCRATCH_ZP1+1 ; next page pair + inc SCRATCH_ZP1+1 ; next page pair + dex + bne _fullpage + +_lastpage ldx SCRATCH_ZPWORD2 + beq _done + + ldy #0 +- +_mod2 lda #0 ; self-modified + sta (SCRATCH_ZPWORD1), y + inc SCRATCH_ZPWORD1 + bne _mod2b + inc SCRATCH_ZPWORD1+1 +_mod2b lda #0 ; self-modified + sta (SCRATCH_ZPWORD1), y + inc SCRATCH_ZPWORD1 + bne + + inc SCRATCH_ZPWORD1+1 ++ dex + bne - +_done rts + } } diff --git a/il65/main.py b/il65/main.py index 2bf1013ca..1060f464b 100644 --- a/il65/main.py +++ b/il65/main.py @@ -56,7 +56,8 @@ def main() -> None: print() if args.startvice: print("Autostart vice emulator...") - cmdline = ["x64", "-remotemonitor", "-moncommands", mon_command_file, + # "-remotemonitor" + cmdline = ["x64", "-moncommands", mon_command_file, "-autostartprgmode", "1", "-autostart-warp", "-autostart", program_filename] with open(os.devnull, "wb") as shutup: subprocess.call(cmdline, stdout=shutup) diff --git a/il65/plyparse.py b/il65/plyparse.py index 67884bdc8..0abcc577e 100644 --- a/il65/plyparse.py +++ b/il65/plyparse.py @@ -203,12 +203,13 @@ def dimensions_validator(obj: 'DatatypeNode', attrib: attr.Attribute, value: Lis else: raise ParseError("array must have only one dimension", obj.sourceref) if dt == DataType.MATRIX: - if len(value) == 2: - size = value[0] * value[1] - if size <= 0 or size > 0x8000: - raise ParseError("matrix size columns * rows must be 1..32768", obj.sourceref) - else: - raise ParseError("matrix must have two dimensions", obj.sourceref) + if len(value) < 2 or len(value) > 3: + raise ParseError("matrix must have two dimensions, with optional interleave", obj.sourceref) + if len(value) == 3: + if value[2] < 1 or value[2] > 256: + raise ParseError("matrix interleave must be 1..256", obj.sourceref) + if value[0] < 0 or value[0] > 128 or value[1] < 0 or value[1] > 128: + raise ParseError("matrix rows and columns must be 1..128", obj.sourceref) @attr.s(cmp=False, repr=False) @@ -440,6 +441,10 @@ class VarDef(AstNode): self.value.processed_expr_must_be_constant = True elif self.value is None and self.datatype in (DataType.BYTE, DataType.WORD, DataType.FLOAT): self.value = 0 + # if it's a matrix with interleave, it must be memory mapped + if self.datatype == DataType.MATRIX and len(self.size) == 3: + if self.vartype != VarType.MEMORY: + raise ParseError("matrix with interleave can only be a memory-mapped variable", self.sourceref) # note: value coercion is done later, when all expressions are evaluated def process_expressions(self, scope: Scope) -> None: diff --git a/reference.md b/reference.md index 9d960d068..c099b7cc9 100644 --- a/reference.md +++ b/reference.md @@ -594,6 +594,9 @@ Allows us to create pre calculated sine tables and such. Something like: - strings: identical operations as on lists. +- matrix with row-interleave can only be a memory mapped variable and can be used to directly + access a rectangular area within another piece of memory - such as a rectangle on the (character) screen + these should call (or emit inline) optimized pieces of assembly code, so they run as fast as possible