diff --git a/src/arch/z80/translator.py b/src/arch/z80/translator.py index 71504b915..bfe09a2ce 100644 --- a/src/arch/z80/translator.py +++ b/src/arch/z80/translator.py @@ -700,6 +700,7 @@ def visit_WHILE_DO(self, node): # Drawing Primitives PLOT, DRAW, DRAW3, CIRCLE # ----------------------------------------------------------------------------------------------------- def visit_PLOT(self, node): + self.norm_attr() TMP_HAS_ATTR = self.check_attr(node, 2) yield TMP_HAS_ATTR yield node.children[0] @@ -708,9 +709,9 @@ def visit_PLOT(self, node): self.ic_fparam(node.children[1].type_, node.children[1].t) self.runtime_call(RuntimeLabel.PLOT, 0) self.HAS_ATTR = TMP_HAS_ATTR is not None - self.norm_attr() def visit_DRAW(self, node): + self.norm_attr() TMP_HAS_ATTR = self.check_attr(node, 2) yield TMP_HAS_ATTR yield node.children[0] @@ -719,9 +720,9 @@ def visit_DRAW(self, node): self.ic_fparam(node.children[1].type_, node.children[1].t) self.runtime_call(RuntimeLabel.DRAW, 0) self.HAS_ATTR = TMP_HAS_ATTR is not None - self.norm_attr() def visit_DRAW3(self, node): + self.norm_attr() TMP_HAS_ATTR = self.check_attr(node, 3) yield TMP_HAS_ATTR yield node.children[0] @@ -732,9 +733,9 @@ def visit_DRAW3(self, node): self.ic_fparam(node.children[2].type_, node.children[2].t) self.runtime_call(RuntimeLabel.DRAW3, 0) self.HAS_ATTR = TMP_HAS_ATTR is not None - self.norm_attr() def visit_CIRCLE(self, node): + self.norm_attr() TMP_HAS_ATTR = self.check_attr(node, 3) yield TMP_HAS_ATTR yield node.children[0] @@ -745,7 +746,6 @@ def visit_CIRCLE(self, node): self.ic_fparam(node.children[2].type_, node.children[2].t) self.runtime_call(RuntimeLabel.CIRCLE, 0) self.HAS_ATTR = TMP_HAS_ATTR is not None - self.norm_attr() # endregion @@ -759,6 +759,7 @@ def visit_OUT(self, node): self.ic_out(node.children[0].t, node.children[1].t) def visit_PRINT(self, node): + self.norm_attr() for i in node.children: yield i @@ -788,19 +789,8 @@ def visit_PRINT(self, node): }[self.TSUFFIX(i.type_)] self.runtime_call(label, 0) - for i in node.children: - if i.token in self.ATTR_TMP or self.has_control_chars(i): - self.HAS_ATTR = True - break - if node.eol: - if self.HAS_ATTR: - self.runtime_call(RuntimeLabel.PRINT_EOL_ATTR, 0) - self.HAS_ATTR = False - else: - self.runtime_call(RuntimeLabel.PRINT_EOL, 0) - else: - self.norm_attr() + self.runtime_call(RuntimeLabel.PRINT_EOL, 0) def visit_PRINT_AT(self, node): yield node.children[0] @@ -1463,7 +1453,6 @@ def visit_FUNCTION(self, node): for i in node.body: yield i - self.norm_attr() self.ic_label("%s__leave" % node.mangled) # Now free any local string from memory. diff --git a/src/arch/z80/translatorvisitor.py b/src/arch/z80/translatorvisitor.py index e08c028b7..dbbbd873d 100644 --- a/src/arch/z80/translatorvisitor.py +++ b/src/arch/z80/translatorvisitor.py @@ -181,17 +181,10 @@ def _visit(self, node): if node.token in self.ATTR_TMP: return self.visit_ATTR_TMP(node) - if node.token not in self.ATTR and isinstance(node, symbols.SENTENCE): - self.norm_attr() - return TranslatorInstVisitor._visit(self, node) def norm_attr(self): """Normalize attr state""" - if not self.HAS_ATTR: - return - - self.HAS_ATTR = False self.runtime_call(RuntimeLabel.COPY_ATTR, 0) @staticmethod diff --git a/src/arch/zx48k/library-asm/print.asm b/src/arch/zx48k/library-asm/print.asm index e1e121c14..5f6daf9da 100644 --- a/src/arch/zx48k/library-asm/print.asm +++ b/src/arch/zx48k/library-asm/print.asm @@ -176,11 +176,10 @@ INVERSE_MODE: ; 00 -> NOP -> INVERSE 0 ld (DFCC), hl ld hl, (DFCCL) ; current ATTR Pos - push hl - call __SET_ATTR - pop hl inc hl - ld (DFCCL),hl + ld (DFCCL), hl + dec hl + call __SET_ATTR exx ret diff --git a/src/arch/zxnext/library-asm/print.asm b/src/arch/zxnext/library-asm/print.asm index e1e121c14..5f6daf9da 100644 --- a/src/arch/zxnext/library-asm/print.asm +++ b/src/arch/zxnext/library-asm/print.asm @@ -176,11 +176,10 @@ INVERSE_MODE: ; 00 -> NOP -> INVERSE 0 ld (DFCC), hl ld hl, (DFCCL) ; current ATTR Pos - push hl - call __SET_ATTR - pop hl inc hl - ld (DFCCL),hl + ld (DFCCL), hl + dec hl + call __SET_ATTR exx ret diff --git a/tests/functional/zx48k/astore16.asm b/tests/functional/zx48k/astore16.asm index b6d25bafe..f2ff44f32 100644 --- a/tests/functional/zx48k/astore16.asm +++ b/tests/functional/zx48k/astore16.asm @@ -76,6 +76,7 @@ _obj.__DATA__: ld (hl), 15 inc hl ld (hl), 39 + call .core.COPY_ATTR ld a, (_i) ld l, a ld h, 0 @@ -244,7 +245,8 @@ TMP_ARR_PTR: DW 0 ; temporary storage for pointer to tables ENDP pop namespace -#line 51 "zx48k/astore16.bas" +#line 52 "zx48k/astore16.bas" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" #line 1 "/zxbasic/src/arch/zx48k/library-asm/print.asm" ; vim:ts=4:sw=4:et: ; PRINT command routine @@ -594,60 +596,6 @@ BRIGHT_TMP: #line 1 "/zxbasic/src/arch/zx48k/library-asm/over.asm" ; Sets OVER flag in P_FLAG permanently ; Parameter: OVER flag in bit 0 of A register -#line 1 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" -#line 4 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" - push namespace core -COPY_ATTR: - ; Just copies current permanent attribs into temporal attribs - ; and sets print mode - PROC - LOCAL INVERSE1 - LOCAL __REFRESH_TMP - INVERSE1 EQU 02Fh - ld hl, (ATTR_P) - ld (ATTR_T), hl - ld hl, FLAGS2 - call __REFRESH_TMP - ld hl, P_FLAG - call __REFRESH_TMP -__SET_ATTR_MODE: ; Another entry to set print modes. A contains (P_FLAG) - LOCAL TABLE - LOCAL CONT2 - rra ; Over bit to carry - ld a, (FLAGS2) - rla ; Over bit in bit 1, Over2 bit in bit 2 - and 3 ; Only bit 0 and 1 (OVER flag) - ld c, a - ld b, 0 - ld hl, TABLE - add hl, bc - ld a, (hl) - ld (PRINT_MODE), a - ld hl, (P_FLAG) - xor a ; NOP -> INVERSE0 - bit 2, l - jr z, CONT2 - ld a, INVERSE1 ; CPL -> INVERSE1 -CONT2: - ld (INVERSE_MODE), a - ret -TABLE: - nop ; NORMAL MODE - xor (hl) ; OVER 1 MODE - and (hl) ; OVER 2 MODE - or (hl) ; OVER 3 MODE -#line 67 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" -__REFRESH_TMP: - ld a, (hl) - and 0b10101010 - ld c, a - rra - or c - ld (hl), a - ret - ENDP - pop namespace -#line 4 "/zxbasic/src/arch/zx48k/library-asm/over.asm" push namespace core OVER: PROC @@ -889,11 +837,10 @@ INVERSE_MODE: ; 00 -> NOP -> INVERSE 0 inc hl ld (DFCC), hl ld hl, (DFCCL) ; current ATTR Pos - push hl - call __SET_ATTR - pop hl inc hl - ld (DFCCL),hl + ld (DFCCL), hl + dec hl + call __SET_ATTR exx ret ; ------------- SPECIAL CHARS (< 32) ----------------- @@ -912,7 +859,7 @@ __PRINT_0Dh: ; Called WHEN printing CHR$(13) push hl call __SCROLL_SCR pop hl -#line 210 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 209 "/zxbasic/src/arch/zx48k/library-asm/print.asm" 1: ld l, 1 __PRINT_EOL_END: @@ -1029,14 +976,14 @@ __PRINT_BOLD: __PRINT_BOLD2: call BOLD_TMP jp __PRINT_RESTART -#line 354 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 353 "/zxbasic/src/arch/zx48k/library-asm/print.asm" __PRINT_ITA: ld hl, __PRINT_ITA2 jp __PRINT_SET_STATE __PRINT_ITA2: call ITALIC_TMP jp __PRINT_RESTART -#line 364 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 363 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __BOLD __BOLD: push hl @@ -1054,7 +1001,7 @@ __BOLD: pop hl ld de, MEM0 ret -#line 385 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 384 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __ITALIC __ITALIC: push hl @@ -1079,12 +1026,12 @@ __ITALIC: pop hl ld de, MEM0 ret -#line 413 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 412 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __SCROLL_SCR -#line 487 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 486 "/zxbasic/src/arch/zx48k/library-asm/print.asm" __SCROLL_SCR EQU 0DFEh ; Use ROM SCROLL +#line 488 "/zxbasic/src/arch/zx48k/library-asm/print.asm" #line 489 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -#line 490 "/zxbasic/src/arch/zx48k/library-asm/print.asm" PRINT_COMMA: call __LOAD_S_POSN ld a, e @@ -1127,9 +1074,9 @@ PRINT_AT: ; Changes cursor to ROW, COL LOCAL __PRINT_TABLE LOCAL __PRINT_TAB, __PRINT_TAB1, __PRINT_TAB2 LOCAL __PRINT_ITA2 -#line 546 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 545 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __PRINT_BOLD2 -#line 552 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 551 "/zxbasic/src/arch/zx48k/library-asm/print.asm" __PRINT_TABLE: ; Jump table for 0 .. 22 codes DW __PRINT_NOP ; 0 DW __PRINT_NOP ; 1 @@ -1157,7 +1104,60 @@ __PRINT_TABLE: ; Jump table for 0 .. 22 codes DW __PRINT_TAB ; 23 TAB ENDP pop namespace -#line 52 "zx48k/astore16.bas" +#line 3 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" +#line 4 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" + push namespace core +COPY_ATTR: + ; Just copies current permanent attribs into temporal attribs + ; and sets print mode + PROC + LOCAL INVERSE1 + LOCAL __REFRESH_TMP + INVERSE1 EQU 02Fh + ld hl, (ATTR_P) + ld (ATTR_T), hl + ld hl, FLAGS2 + call __REFRESH_TMP + ld hl, P_FLAG + call __REFRESH_TMP +__SET_ATTR_MODE: ; Another entry to set print modes. A contains (P_FLAG) + LOCAL TABLE + LOCAL CONT2 + rra ; Over bit to carry + ld a, (FLAGS2) + rla ; Over bit in bit 1, Over2 bit in bit 2 + and 3 ; Only bit 0 and 1 (OVER flag) + ld c, a + ld b, 0 + ld hl, TABLE + add hl, bc + ld a, (hl) + ld (PRINT_MODE), a + ld hl, (P_FLAG) + xor a ; NOP -> INVERSE0 + bit 2, l + jr z, CONT2 + ld a, INVERSE1 ; CPL -> INVERSE1 +CONT2: + ld (INVERSE_MODE), a + ret +TABLE: + nop ; NORMAL MODE + xor (hl) ; OVER 1 MODE + and (hl) ; OVER 2 MODE + or (hl) ; OVER 3 MODE +#line 67 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" +__REFRESH_TMP: + ld a, (hl) + and 0b10101010 + ld c, a + rra + or c + ld (hl), a + ret + ENDP + pop namespace +#line 53 "zx48k/astore16.bas" #line 1 "/zxbasic/src/arch/zx48k/library-asm/printu16.asm" #line 1 "/zxbasic/src/arch/zx48k/library-asm/printi16.asm" #line 1 "/zxbasic/src/arch/zx48k/library-asm/printnum.asm" @@ -1305,5 +1305,5 @@ __PRINTU_LOOP: ENDP pop namespace #line 2 "/zxbasic/src/arch/zx48k/library-asm/printu16.asm" -#line 53 "zx48k/astore16.bas" +#line 55 "zx48k/astore16.bas" END diff --git a/tests/functional/zx48k/attr.asm b/tests/functional/zx48k/attr.asm index 94d48caf4..53dcb1ed1 100644 --- a/tests/functional/zx48k/attr.asm +++ b/tests/functional/zx48k/attr.asm @@ -30,7 +30,6 @@ call .core.OVER ld a, 1 call .core.BOLD - call .core.COPY_ATTR ld hl, 0 ld b, h ld c, l @@ -131,7 +130,7 @@ BOLD_TMP: ret ENDP pop namespace -#line 28 "zx48k/attr.bas" +#line 27 "zx48k/attr.bas" #line 1 "/zxbasic/src/arch/zx48k/library-asm/flash.asm" ; Sets flash flag in ATTR_P permanently ; Parameter: Paper color in A register @@ -168,7 +167,7 @@ FLASH_TMP: jr __SET_FLASH ENDP pop namespace -#line 30 "zx48k/attr.bas" +#line 28 "zx48k/attr.bas" #line 1 "/zxbasic/src/arch/zx48k/library-asm/ink.asm" ; Sets ink color in ATTR_P permanently ; Parameter: Paper color in A register @@ -205,7 +204,7 @@ INK_TMP: jp __SET_INK ENDP pop namespace -#line 31 "zx48k/attr.bas" +#line 29 "zx48k/attr.bas" #line 1 "/zxbasic/src/arch/zx48k/library-asm/over.asm" ; Sets OVER flag in P_FLAG permanently ; Parameter: OVER flag in bit 0 of A register @@ -244,7 +243,7 @@ OVER_TMP: jp __SET_ATTR_MODE ENDP pop namespace -#line 32 "zx48k/attr.bas" +#line 30 "zx48k/attr.bas" #line 1 "/zxbasic/src/arch/zx48k/library-asm/paper.asm" ; Sets paper color in ATTR_P permanently ; Parameter: Paper color in A register @@ -284,5 +283,5 @@ PAPER_TMP: jp __SET_PAPER ENDP pop namespace -#line 33 "zx48k/attr.bas" +#line 31 "zx48k/attr.bas" END diff --git a/tests/functional/zx48k/attr_in_subs.asm b/tests/functional/zx48k/attr_in_subs.asm index f62cb71b4..12b92a861 100644 --- a/tests/functional/zx48k/attr_in_subs.asm +++ b/tests/functional/zx48k/attr_in_subs.asm @@ -46,7 +46,6 @@ _screenAttributes2: call .core.BRIGHT ld a, 2 call .core.INK - call .core.COPY_ATTR _screenAttributes2__leave: ld sp, ix pop ix @@ -115,7 +114,7 @@ BRIGHT_TMP: jr __SET_BRIGHT ENDP pop namespace -#line 34 "zx48k/attr_in_subs.bas" +#line 33 "zx48k/attr_in_subs.bas" #line 1 "/zxbasic/src/arch/zx48k/library-asm/cls.asm" ;; Clears the user screen (24 rows) push namespace core @@ -146,38 +145,7 @@ CLS: ret ENDP pop namespace -#line 35 "zx48k/attr_in_subs.bas" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" -#line 4 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" - push namespace core -COPY_ATTR: - ; Just copies current permanent attribs into temporal attribs - ; and sets print mode - PROC - LOCAL INVERSE1 - LOCAL __REFRESH_TMP - INVERSE1 EQU 02Fh - ld hl, (ATTR_P) - ld (ATTR_T), hl - ld hl, FLAGS2 - call __REFRESH_TMP - ld hl, P_FLAG - call __REFRESH_TMP -__SET_ATTR_MODE: ; Another entry to set print modes. A contains (P_FLAG) -#line 65 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" - ret -#line 67 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" -__REFRESH_TMP: - ld a, (hl) - and 0b10101010 - ld c, a - rra - or c - ld (hl), a - ret - ENDP - pop namespace -#line 36 "zx48k/attr_in_subs.bas" +#line 34 "zx48k/attr_in_subs.bas" #line 1 "/zxbasic/src/arch/zx48k/library-asm/ink.asm" ; Sets ink color in ATTR_P permanently ; Parameter: Paper color in A register @@ -214,7 +182,7 @@ INK_TMP: jp __SET_INK ENDP pop namespace -#line 37 "zx48k/attr_in_subs.bas" +#line 35 "zx48k/attr_in_subs.bas" #line 1 "/zxbasic/src/arch/zx48k/library-asm/paper.asm" ; Sets paper color in ATTR_P permanently ; Parameter: Paper color in A register @@ -254,5 +222,5 @@ PAPER_TMP: jp __SET_PAPER ENDP pop namespace -#line 38 "zx48k/attr_in_subs.bas" +#line 36 "zx48k/attr_in_subs.bas" END diff --git a/tests/functional/zx48k/circle.asm b/tests/functional/zx48k/circle.asm index 7e81f7328..7ab026e2c 100644 --- a/tests/functional/zx48k/circle.asm +++ b/tests/functional/zx48k/circle.asm @@ -26,12 +26,14 @@ _c: DEFB 00, 00, 00, 00, 00 .core.ZXBASIC_USER_DATA_END: .core.__MAIN_PROGRAM__: + call .core.COPY_ATTR ld a, 11 push af ld a, 22 push af ld a, 33 call .core.CIRCLE + call .core.COPY_ATTR ld a, (_a) ld de, (_a + 1) ld bc, (_a + 3) @@ -42,6 +44,7 @@ _c: push af ld a, 33 call .core.CIRCLE + call .core.COPY_ATTR ld a, 11 push af ld a, (_a) @@ -52,6 +55,7 @@ _c: push af ld a, 33 call .core.CIRCLE + call .core.COPY_ATTR ld a, (_a) ld de, (_a + 1) ld bc, (_a + 3) @@ -66,6 +70,7 @@ _c: push af ld a, 33 call .core.CIRCLE + call .core.COPY_ATTR ld a, (_a) ld de, (_a + 1) ld bc, (_a + 3) @@ -527,7 +532,38 @@ __CIRCLE_PLOT: ret ENDP pop namespace -#line 75 "zx48k/circle.bas" +#line 80 "zx48k/circle.bas" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" +#line 4 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" + push namespace core +COPY_ATTR: + ; Just copies current permanent attribs into temporal attribs + ; and sets print mode + PROC + LOCAL INVERSE1 + LOCAL __REFRESH_TMP + INVERSE1 EQU 02Fh + ld hl, (ATTR_P) + ld (ATTR_T), hl + ld hl, FLAGS2 + call __REFRESH_TMP + ld hl, P_FLAG + call __REFRESH_TMP +__SET_ATTR_MODE: ; Another entry to set print modes. A contains (P_FLAG) +#line 65 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" + ret +#line 67 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" +__REFRESH_TMP: + ld a, (hl) + and 0b10101010 + ld c, a + rra + or c + ld (hl), a + ret + ENDP + pop namespace +#line 81 "zx48k/circle.bas" #line 1 "/zxbasic/src/arch/zx48k/library-asm/ftou32reg.asm" #line 1 "/zxbasic/src/arch/zx48k/library-asm/neg32.asm" push namespace core @@ -626,5 +662,5 @@ __FTOU8: ; Converts float in C ED LH to Unsigned byte in A ld a, l ret pop namespace -#line 76 "zx48k/circle.bas" +#line 82 "zx48k/circle.bas" END diff --git a/tests/functional/zx48k/code00.asm b/tests/functional/zx48k/code00.asm index 67f705c3a..59508f65c 100644 --- a/tests/functional/zx48k/code00.asm +++ b/tests/functional/zx48k/code00.asm @@ -942,11 +942,10 @@ INVERSE_MODE: ; 00 -> NOP -> INVERSE 0 inc hl ld (DFCC), hl ld hl, (DFCCL) ; current ATTR Pos - push hl - call __SET_ATTR - pop hl inc hl - ld (DFCCL),hl + ld (DFCCL), hl + dec hl + call __SET_ATTR exx ret ; ------------- SPECIAL CHARS (< 32) ----------------- @@ -965,7 +964,7 @@ __PRINT_0Dh: ; Called WHEN printing CHR$(13) push hl call __SCROLL_SCR pop hl -#line 210 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 209 "/zxbasic/src/arch/zx48k/library-asm/print.asm" 1: ld l, 1 __PRINT_EOL_END: @@ -1082,14 +1081,14 @@ __PRINT_BOLD: __PRINT_BOLD2: call BOLD_TMP jp __PRINT_RESTART -#line 354 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 353 "/zxbasic/src/arch/zx48k/library-asm/print.asm" __PRINT_ITA: ld hl, __PRINT_ITA2 jp __PRINT_SET_STATE __PRINT_ITA2: call ITALIC_TMP jp __PRINT_RESTART -#line 364 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 363 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __BOLD __BOLD: push hl @@ -1107,7 +1106,7 @@ __BOLD: pop hl ld de, MEM0 ret -#line 385 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 384 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __ITALIC __ITALIC: push hl @@ -1132,12 +1131,12 @@ __ITALIC: pop hl ld de, MEM0 ret -#line 413 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 412 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __SCROLL_SCR -#line 487 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 486 "/zxbasic/src/arch/zx48k/library-asm/print.asm" __SCROLL_SCR EQU 0DFEh ; Use ROM SCROLL +#line 488 "/zxbasic/src/arch/zx48k/library-asm/print.asm" #line 489 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -#line 490 "/zxbasic/src/arch/zx48k/library-asm/print.asm" PRINT_COMMA: call __LOAD_S_POSN ld a, e @@ -1180,9 +1179,9 @@ PRINT_AT: ; Changes cursor to ROW, COL LOCAL __PRINT_TABLE LOCAL __PRINT_TAB, __PRINT_TAB1, __PRINT_TAB2 LOCAL __PRINT_ITA2 -#line 546 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 545 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __PRINT_BOLD2 -#line 552 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 551 "/zxbasic/src/arch/zx48k/library-asm/print.asm" __PRINT_TABLE: ; Jump table for 0 .. 22 codes DW __PRINT_NOP ; 0 DW __PRINT_NOP ; 1 diff --git a/tests/functional/zx48k/code01.asm b/tests/functional/zx48k/code01.asm index 40b5c22cf..1baaaedcb 100644 --- a/tests/functional/zx48k/code01.asm +++ b/tests/functional/zx48k/code01.asm @@ -942,11 +942,10 @@ INVERSE_MODE: ; 00 -> NOP -> INVERSE 0 inc hl ld (DFCC), hl ld hl, (DFCCL) ; current ATTR Pos - push hl - call __SET_ATTR - pop hl inc hl - ld (DFCCL),hl + ld (DFCCL), hl + dec hl + call __SET_ATTR exx ret ; ------------- SPECIAL CHARS (< 32) ----------------- @@ -965,7 +964,7 @@ __PRINT_0Dh: ; Called WHEN printing CHR$(13) push hl call __SCROLL_SCR pop hl -#line 210 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 209 "/zxbasic/src/arch/zx48k/library-asm/print.asm" 1: ld l, 1 __PRINT_EOL_END: @@ -1082,14 +1081,14 @@ __PRINT_BOLD: __PRINT_BOLD2: call BOLD_TMP jp __PRINT_RESTART -#line 354 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 353 "/zxbasic/src/arch/zx48k/library-asm/print.asm" __PRINT_ITA: ld hl, __PRINT_ITA2 jp __PRINT_SET_STATE __PRINT_ITA2: call ITALIC_TMP jp __PRINT_RESTART -#line 364 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 363 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __BOLD __BOLD: push hl @@ -1107,7 +1106,7 @@ __BOLD: pop hl ld de, MEM0 ret -#line 385 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 384 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __ITALIC __ITALIC: push hl @@ -1132,12 +1131,12 @@ __ITALIC: pop hl ld de, MEM0 ret -#line 413 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 412 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __SCROLL_SCR -#line 487 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 486 "/zxbasic/src/arch/zx48k/library-asm/print.asm" __SCROLL_SCR EQU 0DFEh ; Use ROM SCROLL +#line 488 "/zxbasic/src/arch/zx48k/library-asm/print.asm" #line 489 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -#line 490 "/zxbasic/src/arch/zx48k/library-asm/print.asm" PRINT_COMMA: call __LOAD_S_POSN ld a, e @@ -1180,9 +1179,9 @@ PRINT_AT: ; Changes cursor to ROW, COL LOCAL __PRINT_TABLE LOCAL __PRINT_TAB, __PRINT_TAB1, __PRINT_TAB2 LOCAL __PRINT_ITA2 -#line 546 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 545 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __PRINT_BOLD2 -#line 552 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 551 "/zxbasic/src/arch/zx48k/library-asm/print.asm" __PRINT_TABLE: ; Jump table for 0 .. 22 codes DW __PRINT_NOP ; 0 DW __PRINT_NOP ; 1 diff --git a/tests/functional/zx48k/code02.asm b/tests/functional/zx48k/code02.asm index 7ad27b404..dda033c55 100644 --- a/tests/functional/zx48k/code02.asm +++ b/tests/functional/zx48k/code02.asm @@ -942,11 +942,10 @@ INVERSE_MODE: ; 00 -> NOP -> INVERSE 0 inc hl ld (DFCC), hl ld hl, (DFCCL) ; current ATTR Pos - push hl - call __SET_ATTR - pop hl inc hl - ld (DFCCL),hl + ld (DFCCL), hl + dec hl + call __SET_ATTR exx ret ; ------------- SPECIAL CHARS (< 32) ----------------- @@ -965,7 +964,7 @@ __PRINT_0Dh: ; Called WHEN printing CHR$(13) push hl call __SCROLL_SCR pop hl -#line 210 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 209 "/zxbasic/src/arch/zx48k/library-asm/print.asm" 1: ld l, 1 __PRINT_EOL_END: @@ -1082,14 +1081,14 @@ __PRINT_BOLD: __PRINT_BOLD2: call BOLD_TMP jp __PRINT_RESTART -#line 354 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 353 "/zxbasic/src/arch/zx48k/library-asm/print.asm" __PRINT_ITA: ld hl, __PRINT_ITA2 jp __PRINT_SET_STATE __PRINT_ITA2: call ITALIC_TMP jp __PRINT_RESTART -#line 364 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 363 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __BOLD __BOLD: push hl @@ -1107,7 +1106,7 @@ __BOLD: pop hl ld de, MEM0 ret -#line 385 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 384 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __ITALIC __ITALIC: push hl @@ -1132,12 +1131,12 @@ __ITALIC: pop hl ld de, MEM0 ret -#line 413 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 412 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __SCROLL_SCR -#line 487 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 486 "/zxbasic/src/arch/zx48k/library-asm/print.asm" __SCROLL_SCR EQU 0DFEh ; Use ROM SCROLL +#line 488 "/zxbasic/src/arch/zx48k/library-asm/print.asm" #line 489 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -#line 490 "/zxbasic/src/arch/zx48k/library-asm/print.asm" PRINT_COMMA: call __LOAD_S_POSN ld a, e @@ -1180,9 +1179,9 @@ PRINT_AT: ; Changes cursor to ROW, COL LOCAL __PRINT_TABLE LOCAL __PRINT_TAB, __PRINT_TAB1, __PRINT_TAB2 LOCAL __PRINT_ITA2 -#line 546 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 545 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __PRINT_BOLD2 -#line 552 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 551 "/zxbasic/src/arch/zx48k/library-asm/print.asm" __PRINT_TABLE: ; Jump table for 0 .. 22 codes DW __PRINT_NOP ; 0 DW __PRINT_NOP ; 1 diff --git a/tests/functional/zx48k/coercion3.asm b/tests/functional/zx48k/coercion3.asm index fd722061e..5366b1ae6 100644 --- a/tests/functional/zx48k/coercion3.asm +++ b/tests/functional/zx48k/coercion3.asm @@ -32,7 +32,6 @@ _c: add hl, hl ld a, l call .core.PAPER - call .core.COPY_ATTR ld hl, 0 ld b, h ld c, l @@ -48,8 +47,9 @@ _c: ei ret ;; --- end of user code --- -#line 1 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" -#line 4 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/paper.asm" + ; Sets paper color in ATTR_P permanently +; Parameter: Paper color in A register #line 1 "/zxbasic/src/arch/zx48k/library-asm/sysvars.asm" ;; ----------------------------------------------------------------------- ;; ZX Basic System Vars @@ -76,39 +76,7 @@ SCREEN_ATTR_ADDR: DW 22528 ; Screen attribute address (ditto.) SCR_ROWS EQU 24 ; Screen height in rows SCR_SIZE EQU (SCR_ROWS << 8) + SCR_COLS pop namespace -#line 6 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" - push namespace core -COPY_ATTR: - ; Just copies current permanent attribs into temporal attribs - ; and sets print mode - PROC - LOCAL INVERSE1 - LOCAL __REFRESH_TMP - INVERSE1 EQU 02Fh - ld hl, (ATTR_P) - ld (ATTR_T), hl - ld hl, FLAGS2 - call __REFRESH_TMP - ld hl, P_FLAG - call __REFRESH_TMP -__SET_ATTR_MODE: ; Another entry to set print modes. A contains (P_FLAG) -#line 65 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" - ret -#line 67 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" -__REFRESH_TMP: - ld a, (hl) - and 0b10101010 - ld c, a - rra - or c - ld (hl), a - ret - ENDP - pop namespace -#line 28 "zx48k/coercion3.bas" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/paper.asm" - ; Sets paper color in ATTR_P permanently -; Parameter: Paper color in A register +#line 5 "/zxbasic/src/arch/zx48k/library-asm/paper.asm" push namespace core PAPER: PROC @@ -145,5 +113,5 @@ PAPER_TMP: jp __SET_PAPER ENDP pop namespace -#line 29 "zx48k/coercion3.bas" +#line 27 "zx48k/coercion3.bas" END diff --git a/tests/functional/zx48k/draw.asm b/tests/functional/zx48k/draw.asm index fbb11ee81..70c5724c2 100644 --- a/tests/functional/zx48k/draw.asm +++ b/tests/functional/zx48k/draw.asm @@ -24,10 +24,12 @@ _b: DEFB 00, 00, 00, 00, 00 .core.ZXBASIC_USER_DATA_END: .core.__MAIN_PROGRAM__: + call .core.COPY_ATTR ld hl, 11 push hl ld hl, 22 call .core.DRAW + call .core.COPY_ATTR ld a, (_a) ld de, (_a + 1) ld bc, (_a + 3) @@ -35,6 +37,7 @@ _b: push hl ld hl, 22 call .core.DRAW + call .core.COPY_ATTR ld hl, 11 push hl ld a, (_a) @@ -42,6 +45,7 @@ _b: ld bc, (_a + 3) call .core.__FTOU32REG call .core.DRAW + call .core.COPY_ATTR ld a, (_a) ld de, (_a + 1) ld bc, (_a + 3) @@ -67,6 +71,64 @@ _b: ei ret ;; --- end of user code --- +#line 1 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" +#line 4 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/sysvars.asm" + ;; ----------------------------------------------------------------------- + ;; ZX Basic System Vars + ;; Some of them will be mapped over Sinclair ROM ones for compatibility + ;; ----------------------------------------------------------------------- + push namespace core +SCREEN_ADDR: DW 16384 ; Screen address (can be pointed to other place to use a screen buffer) +SCREEN_ATTR_ADDR: DW 22528 ; Screen attribute address (ditto.) + ; These are mapped onto ZX Spectrum ROM VARS + CHARS EQU 23606 ; Pointer to ROM/RAM Charset + TVFLAGS EQU 23612 ; TV Flags + UDG EQU 23675 ; Pointer to UDG Charset + COORDS EQU 23677 ; Last PLOT coordinates + FLAGS2 EQU 23681 ; + ECHO_E EQU 23682 ; + DFCC EQU 23684 ; Next screen addr for PRINT + DFCCL EQU 23686 ; Next screen attr for PRINT + S_POSN EQU 23688 + ATTR_P EQU 23693 ; Current Permanent ATTRS set with INK, PAPER, etc commands + ATTR_T EQU 23695 ; temporary ATTRIBUTES + P_FLAG EQU 23697 ; + MEM0 EQU 23698 ; Temporary memory buffer used by ROM chars + SCR_COLS EQU 33 ; Screen with in columns + 1 + SCR_ROWS EQU 24 ; Screen height in rows + SCR_SIZE EQU (SCR_ROWS << 8) + SCR_COLS + pop namespace +#line 6 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" + push namespace core +COPY_ATTR: + ; Just copies current permanent attribs into temporal attribs + ; and sets print mode + PROC + LOCAL INVERSE1 + LOCAL __REFRESH_TMP + INVERSE1 EQU 02Fh + ld hl, (ATTR_P) + ld (ATTR_T), hl + ld hl, FLAGS2 + call __REFRESH_TMP + ld hl, P_FLAG + call __REFRESH_TMP +__SET_ATTR_MODE: ; Another entry to set print modes. A contains (P_FLAG) +#line 65 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" + ret +#line 67 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" +__REFRESH_TMP: + ld a, (hl) + and 0b10101010 + ld c, a + rra + or c + ld (hl), a + ret + ENDP + pop namespace +#line 49 "zx48k/draw.bas" #line 1 "/zxbasic/src/arch/zx48k/library-asm/draw.asm" ; DRAW using bresenhams algorithm and screen positioning ; Copyleft (k) 2010 by J. Rodriguez (a.k.a. Boriel) http://www.boriel.com @@ -110,33 +172,6 @@ __STOP: #line 9 "/zxbasic/src/arch/zx48k/library-asm/draw.asm" #line 1 "/zxbasic/src/arch/zx48k/library-asm/in_screen.asm" #line 1 "/zxbasic/src/arch/zx48k/library-asm/sposn.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/sysvars.asm" - ;; ----------------------------------------------------------------------- - ;; ZX Basic System Vars - ;; Some of them will be mapped over Sinclair ROM ones for compatibility - ;; ----------------------------------------------------------------------- - push namespace core -SCREEN_ADDR: DW 16384 ; Screen address (can be pointed to other place to use a screen buffer) -SCREEN_ATTR_ADDR: DW 22528 ; Screen attribute address (ditto.) - ; These are mapped onto ZX Spectrum ROM VARS - CHARS EQU 23606 ; Pointer to ROM/RAM Charset - TVFLAGS EQU 23612 ; TV Flags - UDG EQU 23675 ; Pointer to UDG Charset - COORDS EQU 23677 ; Last PLOT coordinates - FLAGS2 EQU 23681 ; - ECHO_E EQU 23682 ; - DFCC EQU 23684 ; Next screen addr for PRINT - DFCCL EQU 23686 ; Next screen attr for PRINT - S_POSN EQU 23688 - ATTR_P EQU 23693 ; Current Permanent ATTRS set with INK, PAPER, etc commands - ATTR_T EQU 23695 ; temporary ATTRIBUTES - P_FLAG EQU 23697 ; - MEM0 EQU 23698 ; Temporary memory buffer used by ROM chars - SCR_COLS EQU 33 ; Screen with in columns + 1 - SCR_ROWS EQU 24 ; Screen height in rows - SCR_SIZE EQU (SCR_ROWS << 8) + SCR_COLS - pop namespace -#line 2 "/zxbasic/src/arch/zx48k/library-asm/sposn.asm" #line 1 "/zxbasic/src/arch/zx48k/library-asm/attr.asm" ; Attribute routines ; vim:ts=4:et:sw: @@ -671,7 +706,7 @@ __FASTPLOTEND: ret ENDP pop namespace -#line 45 "zx48k/draw.bas" +#line 50 "zx48k/draw.bas" #line 1 "/zxbasic/src/arch/zx48k/library-asm/ftou32reg.asm" #line 1 "/zxbasic/src/arch/zx48k/library-asm/neg32.asm" push namespace core @@ -770,5 +805,5 @@ __FTOU8: ; Converts float in C ED LH to Unsigned byte in A ld a, l ret pop namespace -#line 46 "zx48k/draw.bas" +#line 51 "zx48k/draw.bas" END diff --git a/tests/functional/zx48k/draw3.asm b/tests/functional/zx48k/draw3.asm index 6b84c8c91..0226d2e1c 100644 --- a/tests/functional/zx48k/draw3.asm +++ b/tests/functional/zx48k/draw3.asm @@ -26,6 +26,7 @@ _c: DEFB 00, 00, 00, 00, 00 .core.ZXBASIC_USER_DATA_END: .core.__MAIN_PROGRAM__: + call .core.COPY_ATTR ld hl, 11 push hl ld hl, 22 @@ -34,6 +35,7 @@ _c: ld de, 00004h ld bc, 00000h call .core.DRAW3 + call .core.COPY_ATTR ld a, (_a) ld de, (_a + 1) ld bc, (_a + 3) @@ -45,6 +47,7 @@ _c: ld de, 00004h ld bc, 00000h call .core.DRAW3 + call .core.COPY_ATTR ld hl, 11 push hl ld a, (_a) @@ -56,6 +59,7 @@ _c: ld de, 00004h ld bc, 00000h call .core.DRAW3 + call .core.COPY_ATTR ld a, (_a) ld de, (_a + 1) ld bc, (_a + 3) @@ -70,6 +74,7 @@ _c: ld de, 00004h ld bc, 00000h call .core.DRAW3 + call .core.COPY_ATTR ld a, (_a) ld de, (_a + 1) ld bc, (_a + 3) @@ -99,6 +104,64 @@ _c: ei ret ;; --- end of user code --- +#line 1 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" +#line 4 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/sysvars.asm" + ;; ----------------------------------------------------------------------- + ;; ZX Basic System Vars + ;; Some of them will be mapped over Sinclair ROM ones for compatibility + ;; ----------------------------------------------------------------------- + push namespace core +SCREEN_ADDR: DW 16384 ; Screen address (can be pointed to other place to use a screen buffer) +SCREEN_ATTR_ADDR: DW 22528 ; Screen attribute address (ditto.) + ; These are mapped onto ZX Spectrum ROM VARS + CHARS EQU 23606 ; Pointer to ROM/RAM Charset + TVFLAGS EQU 23612 ; TV Flags + UDG EQU 23675 ; Pointer to UDG Charset + COORDS EQU 23677 ; Last PLOT coordinates + FLAGS2 EQU 23681 ; + ECHO_E EQU 23682 ; + DFCC EQU 23684 ; Next screen addr for PRINT + DFCCL EQU 23686 ; Next screen attr for PRINT + S_POSN EQU 23688 + ATTR_P EQU 23693 ; Current Permanent ATTRS set with INK, PAPER, etc commands + ATTR_T EQU 23695 ; temporary ATTRIBUTES + P_FLAG EQU 23697 ; + MEM0 EQU 23698 ; Temporary memory buffer used by ROM chars + SCR_COLS EQU 33 ; Screen with in columns + 1 + SCR_ROWS EQU 24 ; Screen height in rows + SCR_SIZE EQU (SCR_ROWS << 8) + SCR_COLS + pop namespace +#line 6 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" + push namespace core +COPY_ATTR: + ; Just copies current permanent attribs into temporal attribs + ; and sets print mode + PROC + LOCAL INVERSE1 + LOCAL __REFRESH_TMP + INVERSE1 EQU 02Fh + ld hl, (ATTR_P) + ld (ATTR_T), hl + ld hl, FLAGS2 + call __REFRESH_TMP + ld hl, P_FLAG + call __REFRESH_TMP +__SET_ATTR_MODE: ; Another entry to set print modes. A contains (P_FLAG) +#line 65 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" + ret +#line 67 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" +__REFRESH_TMP: + ld a, (hl) + and 0b10101010 + ld c, a + rra + or c + ld (hl), a + ret + ENDP + pop namespace +#line 80 "zx48k/draw3.bas" #line 1 "/zxbasic/src/arch/zx48k/library-asm/draw3.asm" ; ----------------------------------------------------------- ; vim: et:ts=4:sw=4:ruler: @@ -149,33 +212,6 @@ __STOP: ; X in top of the stack #line 1 "/zxbasic/src/arch/zx48k/library-asm/in_screen.asm" #line 1 "/zxbasic/src/arch/zx48k/library-asm/sposn.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/sysvars.asm" - ;; ----------------------------------------------------------------------- - ;; ZX Basic System Vars - ;; Some of them will be mapped over Sinclair ROM ones for compatibility - ;; ----------------------------------------------------------------------- - push namespace core -SCREEN_ADDR: DW 16384 ; Screen address (can be pointed to other place to use a screen buffer) -SCREEN_ATTR_ADDR: DW 22528 ; Screen attribute address (ditto.) - ; These are mapped onto ZX Spectrum ROM VARS - CHARS EQU 23606 ; Pointer to ROM/RAM Charset - TVFLAGS EQU 23612 ; TV Flags - UDG EQU 23675 ; Pointer to UDG Charset - COORDS EQU 23677 ; Last PLOT coordinates - FLAGS2 EQU 23681 ; - ECHO_E EQU 23682 ; - DFCC EQU 23684 ; Next screen addr for PRINT - DFCCL EQU 23686 ; Next screen attr for PRINT - S_POSN EQU 23688 - ATTR_P EQU 23693 ; Current Permanent ATTRS set with INK, PAPER, etc commands - ATTR_T EQU 23695 ; temporary ATTRIBUTES - P_FLAG EQU 23697 ; - MEM0 EQU 23698 ; Temporary memory buffer used by ROM chars - SCR_COLS EQU 33 ; Screen with in columns + 1 - SCR_ROWS EQU 24 ; Screen height in rows - SCR_SIZE EQU (SCR_ROWS << 8) + SCR_COLS - pop namespace -#line 2 "/zxbasic/src/arch/zx48k/library-asm/sposn.asm" #line 1 "/zxbasic/src/arch/zx48k/library-asm/attr.asm" ; Attribute routines ; vim:ts=4:et:sw: @@ -1198,7 +1234,7 @@ SUM_B: jp __DRAW ;;forward to LINE-DRAW (Fastcalled) ENDP pop namespace -#line 75 "zx48k/draw3.bas" +#line 81 "zx48k/draw3.bas" #line 1 "/zxbasic/src/arch/zx48k/library-asm/ftou32reg.asm" #line 1 "/zxbasic/src/arch/zx48k/library-asm/neg32.asm" push namespace core @@ -1297,5 +1333,5 @@ __FTOU8: ; Converts float in C ED LH to Unsigned byte in A ld a, l ret pop namespace -#line 76 "zx48k/draw3.bas" +#line 82 "zx48k/draw3.bas" END diff --git a/tests/functional/zx48k/einarattr.asm b/tests/functional/zx48k/einarattr.asm index ffd61b635..c5da2df58 100644 --- a/tests/functional/zx48k/einarattr.asm +++ b/tests/functional/zx48k/einarattr.asm @@ -27,6 +27,7 @@ .core.ZXBASIC_USER_DATA_END: .core.__MAIN_PROGRAM__: call _printA + call .core.COPY_ATTR ld hl, .LABEL.__LABEL0 xor a call .core.__PRINTSTR @@ -48,6 +49,7 @@ _printA: push ix ld ix, 0 add ix, sp + call .core.COPY_ATTR xor a call .core.PAPER_TMP ld a, 7 @@ -55,7 +57,6 @@ _printA: ld hl, .LABEL.__LABEL1 xor a call .core.__PRINTSTR - call .core.COPY_ATTR _printA__leave: ld sp, ix pop ix @@ -658,11 +659,10 @@ INVERSE_MODE: ; 00 -> NOP -> INVERSE 0 inc hl ld (DFCC), hl ld hl, (DFCCL) ; current ATTR Pos - push hl - call __SET_ATTR - pop hl inc hl - ld (DFCCL),hl + ld (DFCCL), hl + dec hl + call __SET_ATTR exx ret ; ------------- SPECIAL CHARS (< 32) ----------------- @@ -681,7 +681,7 @@ __PRINT_0Dh: ; Called WHEN printing CHR$(13) push hl call __SCROLL_SCR pop hl -#line 210 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 209 "/zxbasic/src/arch/zx48k/library-asm/print.asm" 1: ld l, 1 __PRINT_EOL_END: @@ -798,14 +798,14 @@ __PRINT_BOLD: __PRINT_BOLD2: call BOLD_TMP jp __PRINT_RESTART -#line 354 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 353 "/zxbasic/src/arch/zx48k/library-asm/print.asm" __PRINT_ITA: ld hl, __PRINT_ITA2 jp __PRINT_SET_STATE __PRINT_ITA2: call ITALIC_TMP jp __PRINT_RESTART -#line 364 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 363 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __BOLD __BOLD: push hl @@ -823,7 +823,7 @@ __BOLD: pop hl ld de, MEM0 ret -#line 385 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 384 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __ITALIC __ITALIC: push hl @@ -848,12 +848,12 @@ __ITALIC: pop hl ld de, MEM0 ret -#line 413 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 412 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __SCROLL_SCR -#line 487 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 486 "/zxbasic/src/arch/zx48k/library-asm/print.asm" __SCROLL_SCR EQU 0DFEh ; Use ROM SCROLL +#line 488 "/zxbasic/src/arch/zx48k/library-asm/print.asm" #line 489 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -#line 490 "/zxbasic/src/arch/zx48k/library-asm/print.asm" PRINT_COMMA: call __LOAD_S_POSN ld a, e @@ -896,9 +896,9 @@ PRINT_AT: ; Changes cursor to ROW, COL LOCAL __PRINT_TABLE LOCAL __PRINT_TAB, __PRINT_TAB1, __PRINT_TAB2 LOCAL __PRINT_ITA2 -#line 546 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 545 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __PRINT_BOLD2 -#line 552 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 551 "/zxbasic/src/arch/zx48k/library-asm/print.asm" __PRINT_TABLE: ; Jump table for 0 .. 22 codes DW __PRINT_NOP ; 0 DW __PRINT_NOP ; 1 @@ -979,7 +979,7 @@ __REFRESH_TMP: ret ENDP pop namespace -#line 43 "zx48k/einarattr.bas" +#line 44 "zx48k/einarattr.bas" #line 1 "/zxbasic/src/arch/zx48k/library-asm/printstr.asm" #line 1 "/zxbasic/src/arch/zx48k/library-asm/free.asm" ; vim: ts=4:et:sw=4: @@ -1290,5 +1290,5 @@ __PRINT_STR: jp __PRINT_STR_LOOP ENDP pop namespace -#line 46 "zx48k/einarattr.bas" +#line 47 "zx48k/einarattr.bas" END diff --git a/tests/functional/zx48k/einarshift.asm b/tests/functional/zx48k/einarshift.asm index 89bb3e55c..39a8c7e7f 100644 --- a/tests/functional/zx48k/einarshift.asm +++ b/tests/functional/zx48k/einarshift.asm @@ -25,6 +25,7 @@ _b: DEFB 02h .core.ZXBASIC_USER_DATA_END: .core.__MAIN_PROGRAM__: + call .core.COPY_ATTR ld a, 3 ld hl, (_b - 1) sub h @@ -54,6 +55,7 @@ _b: ei ret ;; --- end of user code --- +#line 1 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" #line 1 "/zxbasic/src/arch/zx48k/library-asm/print.asm" ; vim:ts=4:sw=4:et: ; PRINT command routine @@ -403,60 +405,6 @@ BRIGHT_TMP: #line 1 "/zxbasic/src/arch/zx48k/library-asm/over.asm" ; Sets OVER flag in P_FLAG permanently ; Parameter: OVER flag in bit 0 of A register -#line 1 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" -#line 4 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" - push namespace core -COPY_ATTR: - ; Just copies current permanent attribs into temporal attribs - ; and sets print mode - PROC - LOCAL INVERSE1 - LOCAL __REFRESH_TMP - INVERSE1 EQU 02Fh - ld hl, (ATTR_P) - ld (ATTR_T), hl - ld hl, FLAGS2 - call __REFRESH_TMP - ld hl, P_FLAG - call __REFRESH_TMP -__SET_ATTR_MODE: ; Another entry to set print modes. A contains (P_FLAG) - LOCAL TABLE - LOCAL CONT2 - rra ; Over bit to carry - ld a, (FLAGS2) - rla ; Over bit in bit 1, Over2 bit in bit 2 - and 3 ; Only bit 0 and 1 (OVER flag) - ld c, a - ld b, 0 - ld hl, TABLE - add hl, bc - ld a, (hl) - ld (PRINT_MODE), a - ld hl, (P_FLAG) - xor a ; NOP -> INVERSE0 - bit 2, l - jr z, CONT2 - ld a, INVERSE1 ; CPL -> INVERSE1 -CONT2: - ld (INVERSE_MODE), a - ret -TABLE: - nop ; NORMAL MODE - xor (hl) ; OVER 1 MODE - and (hl) ; OVER 2 MODE - or (hl) ; OVER 3 MODE -#line 67 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" -__REFRESH_TMP: - ld a, (hl) - and 0b10101010 - ld c, a - rra - or c - ld (hl), a - ret - ENDP - pop namespace -#line 4 "/zxbasic/src/arch/zx48k/library-asm/over.asm" push namespace core OVER: PROC @@ -698,11 +646,10 @@ INVERSE_MODE: ; 00 -> NOP -> INVERSE 0 inc hl ld (DFCC), hl ld hl, (DFCCL) ; current ATTR Pos - push hl - call __SET_ATTR - pop hl inc hl - ld (DFCCL),hl + ld (DFCCL), hl + dec hl + call __SET_ATTR exx ret ; ------------- SPECIAL CHARS (< 32) ----------------- @@ -721,7 +668,7 @@ __PRINT_0Dh: ; Called WHEN printing CHR$(13) push hl call __SCROLL_SCR pop hl -#line 210 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 209 "/zxbasic/src/arch/zx48k/library-asm/print.asm" 1: ld l, 1 __PRINT_EOL_END: @@ -838,14 +785,14 @@ __PRINT_BOLD: __PRINT_BOLD2: call BOLD_TMP jp __PRINT_RESTART -#line 354 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 353 "/zxbasic/src/arch/zx48k/library-asm/print.asm" __PRINT_ITA: ld hl, __PRINT_ITA2 jp __PRINT_SET_STATE __PRINT_ITA2: call ITALIC_TMP jp __PRINT_RESTART -#line 364 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 363 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __BOLD __BOLD: push hl @@ -863,7 +810,7 @@ __BOLD: pop hl ld de, MEM0 ret -#line 385 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 384 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __ITALIC __ITALIC: push hl @@ -888,12 +835,12 @@ __ITALIC: pop hl ld de, MEM0 ret -#line 413 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 412 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __SCROLL_SCR -#line 487 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 486 "/zxbasic/src/arch/zx48k/library-asm/print.asm" __SCROLL_SCR EQU 0DFEh ; Use ROM SCROLL +#line 488 "/zxbasic/src/arch/zx48k/library-asm/print.asm" #line 489 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -#line 490 "/zxbasic/src/arch/zx48k/library-asm/print.asm" PRINT_COMMA: call __LOAD_S_POSN ld a, e @@ -936,9 +883,9 @@ PRINT_AT: ; Changes cursor to ROW, COL LOCAL __PRINT_TABLE LOCAL __PRINT_TAB, __PRINT_TAB1, __PRINT_TAB2 LOCAL __PRINT_ITA2 -#line 546 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 545 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __PRINT_BOLD2 -#line 552 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 551 "/zxbasic/src/arch/zx48k/library-asm/print.asm" __PRINT_TABLE: ; Jump table for 0 .. 22 codes DW __PRINT_NOP ; 0 DW __PRINT_NOP ; 1 @@ -966,7 +913,60 @@ __PRINT_TABLE: ; Jump table for 0 .. 22 codes DW __PRINT_TAB ; 23 TAB ENDP pop namespace -#line 31 "zx48k/einarshift.bas" +#line 3 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" +#line 4 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" + push namespace core +COPY_ATTR: + ; Just copies current permanent attribs into temporal attribs + ; and sets print mode + PROC + LOCAL INVERSE1 + LOCAL __REFRESH_TMP + INVERSE1 EQU 02Fh + ld hl, (ATTR_P) + ld (ATTR_T), hl + ld hl, FLAGS2 + call __REFRESH_TMP + ld hl, P_FLAG + call __REFRESH_TMP +__SET_ATTR_MODE: ; Another entry to set print modes. A contains (P_FLAG) + LOCAL TABLE + LOCAL CONT2 + rra ; Over bit to carry + ld a, (FLAGS2) + rla ; Over bit in bit 1, Over2 bit in bit 2 + and 3 ; Only bit 0 and 1 (OVER flag) + ld c, a + ld b, 0 + ld hl, TABLE + add hl, bc + ld a, (hl) + ld (PRINT_MODE), a + ld hl, (P_FLAG) + xor a ; NOP -> INVERSE0 + bit 2, l + jr z, CONT2 + ld a, INVERSE1 ; CPL -> INVERSE1 +CONT2: + ld (INVERSE_MODE), a + ret +TABLE: + nop ; NORMAL MODE + xor (hl) ; OVER 1 MODE + and (hl) ; OVER 2 MODE + or (hl) ; OVER 3 MODE +#line 67 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" +__REFRESH_TMP: + ld a, (hl) + and 0b10101010 + ld c, a + rra + or c + ld (hl), a + ret + ENDP + pop namespace +#line 32 "zx48k/einarshift.bas" #line 1 "/zxbasic/src/arch/zx48k/library-asm/printu8.asm" #line 1 "/zxbasic/src/arch/zx48k/library-asm/printi8.asm" #line 1 "/zxbasic/src/arch/zx48k/library-asm/printnum.asm" @@ -1088,5 +1088,5 @@ __PRINTU_LOOP: ENDP pop namespace #line 2 "/zxbasic/src/arch/zx48k/library-asm/printu8.asm" -#line 32 "zx48k/einarshift.bas" +#line 34 "zx48k/einarshift.bas" END diff --git a/tests/functional/zx48k/fact.asm b/tests/functional/zx48k/fact.asm index 27579f499..76622d4a3 100644 --- a/tests/functional/zx48k/fact.asm +++ b/tests/functional/zx48k/fact.asm @@ -33,6 +33,7 @@ _x: ld (_x), a jp .LABEL.__LABEL0 .LABEL.__LABEL3: + call .core.COPY_ATTR ld hl, .LABEL.__LABEL5 xor a call .core.__PRINTSTR @@ -192,90 +193,8 @@ CLS: ret ENDP pop namespace -#line 109 "zx48k/fact.bas" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/mul32.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/_mul32.asm" -; Ripped from: http://www.andreadrian.de/oldcpu/z80_number_cruncher.html#moztocid784223 - ; Used with permission. - ; Multiplies 32x32 bit integer (DEHL x D'E'H'L') - ; 64bit result is returned in H'L'H L B'C'A C - push namespace core -__MUL32_64START: - push hl - exx - ld b, h - ld c, l ; BC = Low Part (A) - pop hl ; HL = Load Part (B) - ex de, hl ; DE = Low Part (B), HL = HightPart(A) (must be in B'C') - push hl - exx - pop bc ; B'C' = HightPart(A) - exx ; A = B'C'BC , B = D'E'DE - ; multiply routine 32 * 32bit = 64bit - ; h'l'hlb'c'ac = b'c'bc * d'e'de - ; needs register a, changes flags - ; - ; this routine was with tiny differences in the - ; sinclair zx81 rom for the mantissa multiply -__LMUL: - xor a ; reset carry flag - ld h, a ; result bits 32..47 = 0 - ld l, a - exx - ld h, a ; result bits 48..63 = 0 - ld l, a - exx - ld a,b ; mpr is b'c'ac - ld b,33 ; initialize loop counter - jp __LMULSTART -__LMULLOOP: - jr nc,__LMULNOADD ; JP is 2 cycles faster than JR. Since it's inside a LOOP - ; it can save up to 33 * 2 = 66 cycles - ; But JR if 3 cycles faster if JUMP not taken! - add hl,de ; result += mpd - exx - adc hl,de - exx -__LMULNOADD: - exx - rr h ; right shift upper - rr l ; 32bit of result - exx - rr h - rr l -__LMULSTART: - exx - rr b ; right shift mpr/ - rr c ; lower 32bit of result - exx - rra ; equivalent to rr a - rr c - djnz __LMULLOOP - ret ; result in h'l'hlb'c'ac - pop namespace -#line 2 "/zxbasic/src/arch/zx48k/library-asm/mul32.asm" - push namespace core -__MUL32: - ; multiplies 32 bit un/signed integer. - ; First operand stored in DEHL, and 2nd onto stack - ; Lowest part of 2nd operand on top of the stack - ; returns the result in DE.HL - exx - pop hl ; Return ADDRESS - pop de ; Low part - ex (sp), hl ; CALLEE -> HL = High part - ex de, hl - call __MUL32_64START -__TO32BIT: ; Converts H'L'HLB'C'AC to DEHL (Discards H'L'HL) - exx - push bc - exx - pop de - ld h, a - ld l, c - ret - pop namespace #line 110 "zx48k/fact.bas" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" #line 1 "/zxbasic/src/arch/zx48k/library-asm/print.asm" ; vim:ts=4:sw=4:et: ; PRINT command routine @@ -598,60 +517,6 @@ BRIGHT_TMP: #line 1 "/zxbasic/src/arch/zx48k/library-asm/over.asm" ; Sets OVER flag in P_FLAG permanently ; Parameter: OVER flag in bit 0 of A register -#line 1 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" -#line 4 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" - push namespace core -COPY_ATTR: - ; Just copies current permanent attribs into temporal attribs - ; and sets print mode - PROC - LOCAL INVERSE1 - LOCAL __REFRESH_TMP - INVERSE1 EQU 02Fh - ld hl, (ATTR_P) - ld (ATTR_T), hl - ld hl, FLAGS2 - call __REFRESH_TMP - ld hl, P_FLAG - call __REFRESH_TMP -__SET_ATTR_MODE: ; Another entry to set print modes. A contains (P_FLAG) - LOCAL TABLE - LOCAL CONT2 - rra ; Over bit to carry - ld a, (FLAGS2) - rla ; Over bit in bit 1, Over2 bit in bit 2 - and 3 ; Only bit 0 and 1 (OVER flag) - ld c, a - ld b, 0 - ld hl, TABLE - add hl, bc - ld a, (hl) - ld (PRINT_MODE), a - ld hl, (P_FLAG) - xor a ; NOP -> INVERSE0 - bit 2, l - jr z, CONT2 - ld a, INVERSE1 ; CPL -> INVERSE1 -CONT2: - ld (INVERSE_MODE), a - ret -TABLE: - nop ; NORMAL MODE - xor (hl) ; OVER 1 MODE - and (hl) ; OVER 2 MODE - or (hl) ; OVER 3 MODE -#line 67 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" -__REFRESH_TMP: - ld a, (hl) - and 0b10101010 - ld c, a - rra - or c - ld (hl), a - ret - ENDP - pop namespace -#line 4 "/zxbasic/src/arch/zx48k/library-asm/over.asm" push namespace core OVER: PROC @@ -893,11 +758,10 @@ INVERSE_MODE: ; 00 -> NOP -> INVERSE 0 inc hl ld (DFCC), hl ld hl, (DFCCL) ; current ATTR Pos - push hl - call __SET_ATTR - pop hl inc hl - ld (DFCCL),hl + ld (DFCCL), hl + dec hl + call __SET_ATTR exx ret ; ------------- SPECIAL CHARS (< 32) ----------------- @@ -916,7 +780,7 @@ __PRINT_0Dh: ; Called WHEN printing CHR$(13) push hl call __SCROLL_SCR pop hl -#line 210 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 209 "/zxbasic/src/arch/zx48k/library-asm/print.asm" 1: ld l, 1 __PRINT_EOL_END: @@ -1033,14 +897,14 @@ __PRINT_BOLD: __PRINT_BOLD2: call BOLD_TMP jp __PRINT_RESTART -#line 354 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 353 "/zxbasic/src/arch/zx48k/library-asm/print.asm" __PRINT_ITA: ld hl, __PRINT_ITA2 jp __PRINT_SET_STATE __PRINT_ITA2: call ITALIC_TMP jp __PRINT_RESTART -#line 364 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 363 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __BOLD __BOLD: push hl @@ -1058,7 +922,7 @@ __BOLD: pop hl ld de, MEM0 ret -#line 385 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 384 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __ITALIC __ITALIC: push hl @@ -1083,12 +947,12 @@ __ITALIC: pop hl ld de, MEM0 ret -#line 413 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 412 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __SCROLL_SCR -#line 487 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 486 "/zxbasic/src/arch/zx48k/library-asm/print.asm" __SCROLL_SCR EQU 0DFEh ; Use ROM SCROLL +#line 488 "/zxbasic/src/arch/zx48k/library-asm/print.asm" #line 489 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -#line 490 "/zxbasic/src/arch/zx48k/library-asm/print.asm" PRINT_COMMA: call __LOAD_S_POSN ld a, e @@ -1131,9 +995,9 @@ PRINT_AT: ; Changes cursor to ROW, COL LOCAL __PRINT_TABLE LOCAL __PRINT_TAB, __PRINT_TAB1, __PRINT_TAB2 LOCAL __PRINT_ITA2 -#line 546 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 545 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __PRINT_BOLD2 -#line 552 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 551 "/zxbasic/src/arch/zx48k/library-asm/print.asm" __PRINT_TABLE: ; Jump table for 0 .. 22 codes DW __PRINT_NOP ; 0 DW __PRINT_NOP ; 1 @@ -1161,7 +1025,143 @@ __PRINT_TABLE: ; Jump table for 0 .. 22 codes DW __PRINT_TAB ; 23 TAB ENDP pop namespace +#line 3 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" +#line 4 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" + push namespace core +COPY_ATTR: + ; Just copies current permanent attribs into temporal attribs + ; and sets print mode + PROC + LOCAL INVERSE1 + LOCAL __REFRESH_TMP + INVERSE1 EQU 02Fh + ld hl, (ATTR_P) + ld (ATTR_T), hl + ld hl, FLAGS2 + call __REFRESH_TMP + ld hl, P_FLAG + call __REFRESH_TMP +__SET_ATTR_MODE: ; Another entry to set print modes. A contains (P_FLAG) + LOCAL TABLE + LOCAL CONT2 + rra ; Over bit to carry + ld a, (FLAGS2) + rla ; Over bit in bit 1, Over2 bit in bit 2 + and 3 ; Only bit 0 and 1 (OVER flag) + ld c, a + ld b, 0 + ld hl, TABLE + add hl, bc + ld a, (hl) + ld (PRINT_MODE), a + ld hl, (P_FLAG) + xor a ; NOP -> INVERSE0 + bit 2, l + jr z, CONT2 + ld a, INVERSE1 ; CPL -> INVERSE1 +CONT2: + ld (INVERSE_MODE), a + ret +TABLE: + nop ; NORMAL MODE + xor (hl) ; OVER 1 MODE + and (hl) ; OVER 2 MODE + or (hl) ; OVER 3 MODE +#line 67 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" +__REFRESH_TMP: + ld a, (hl) + and 0b10101010 + ld c, a + rra + or c + ld (hl), a + ret + ENDP + pop namespace #line 111 "zx48k/fact.bas" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/mul32.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/_mul32.asm" +; Ripped from: http://www.andreadrian.de/oldcpu/z80_number_cruncher.html#moztocid784223 + ; Used with permission. + ; Multiplies 32x32 bit integer (DEHL x D'E'H'L') + ; 64bit result is returned in H'L'H L B'C'A C + push namespace core +__MUL32_64START: + push hl + exx + ld b, h + ld c, l ; BC = Low Part (A) + pop hl ; HL = Load Part (B) + ex de, hl ; DE = Low Part (B), HL = HightPart(A) (must be in B'C') + push hl + exx + pop bc ; B'C' = HightPart(A) + exx ; A = B'C'BC , B = D'E'DE + ; multiply routine 32 * 32bit = 64bit + ; h'l'hlb'c'ac = b'c'bc * d'e'de + ; needs register a, changes flags + ; + ; this routine was with tiny differences in the + ; sinclair zx81 rom for the mantissa multiply +__LMUL: + xor a ; reset carry flag + ld h, a ; result bits 32..47 = 0 + ld l, a + exx + ld h, a ; result bits 48..63 = 0 + ld l, a + exx + ld a,b ; mpr is b'c'ac + ld b,33 ; initialize loop counter + jp __LMULSTART +__LMULLOOP: + jr nc,__LMULNOADD ; JP is 2 cycles faster than JR. Since it's inside a LOOP + ; it can save up to 33 * 2 = 66 cycles + ; But JR if 3 cycles faster if JUMP not taken! + add hl,de ; result += mpd + exx + adc hl,de + exx +__LMULNOADD: + exx + rr h ; right shift upper + rr l ; 32bit of result + exx + rr h + rr l +__LMULSTART: + exx + rr b ; right shift mpr/ + rr c ; lower 32bit of result + exx + rra ; equivalent to rr a + rr c + djnz __LMULLOOP + ret ; result in h'l'hlb'c'ac + pop namespace +#line 2 "/zxbasic/src/arch/zx48k/library-asm/mul32.asm" + push namespace core +__MUL32: + ; multiplies 32 bit un/signed integer. + ; First operand stored in DEHL, and 2nd onto stack + ; Lowest part of 2nd operand on top of the stack + ; returns the result in DE.HL + exx + pop hl ; Return ADDRESS + pop de ; Low part + ex (sp), hl ; CALLEE -> HL = High part + ex de, hl + call __MUL32_64START +__TO32BIT: ; Converts H'L'HLB'C'AC to DEHL (Discards H'L'HL) + exx + push bc + exx + pop de + ld h, a + ld l, c + ret + pop namespace +#line 112 "zx48k/fact.bas" #line 1 "/zxbasic/src/arch/zx48k/library-asm/printstr.asm" #line 1 "/zxbasic/src/arch/zx48k/library-asm/free.asm" ; vim: ts=4:et:sw=4: @@ -1472,7 +1472,7 @@ __PRINT_STR: jp __PRINT_STR_LOOP ENDP pop namespace -#line 112 "zx48k/fact.bas" +#line 114 "zx48k/fact.bas" #line 1 "/zxbasic/src/arch/zx48k/library-asm/printu32.asm" #line 1 "/zxbasic/src/arch/zx48k/library-asm/printi32.asm" #line 1 "/zxbasic/src/arch/zx48k/library-asm/printnum.asm" @@ -1673,7 +1673,7 @@ __PRINTU_LOOP: ENDP pop namespace #line 2 "/zxbasic/src/arch/zx48k/library-asm/printu32.asm" -#line 113 "zx48k/fact.bas" +#line 115 "zx48k/fact.bas" #line 1 "/zxbasic/src/arch/zx48k/library-asm/printu8.asm" #line 1 "/zxbasic/src/arch/zx48k/library-asm/printi8.asm" #line 1 "/zxbasic/src/arch/zx48k/library-asm/div8.asm" @@ -1771,7 +1771,7 @@ __PRINTU_LOOP: ENDP pop namespace #line 2 "/zxbasic/src/arch/zx48k/library-asm/printu8.asm" -#line 114 "zx48k/fact.bas" +#line 116 "zx48k/fact.bas" #line 1 "/zxbasic/src/arch/zx48k/library-asm/sub32.asm" ; SUB32 ; Perform TOP of the stack - DEHL @@ -1798,5 +1798,5 @@ __SUB32: exx ret pop namespace -#line 115 "zx48k/fact.bas" +#line 117 "zx48k/fact.bas" END diff --git a/tests/functional/zx48k/for0.asm b/tests/functional/zx48k/for0.asm index a1a350b21..ebced93bb 100644 --- a/tests/functional/zx48k/for0.asm +++ b/tests/functional/zx48k/for0.asm @@ -33,6 +33,7 @@ _x: ld (_x), a jp .LABEL.__LABEL0 .LABEL.__LABEL3: + call .core.COPY_ATTR ld a, (_x) call .core.__PRINTI8 ld hl, .LABEL.__LABEL5 @@ -123,34 +124,8 @@ CLS: ret ENDP pop namespace -#line 40 "zx48k/for0.bas" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/lti8.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/lei8.asm" - push namespace core -__LEI8: ; Signed <= comparison for 8bit int - ; A <= H (registers) - PROC - LOCAL checkParity - sub h - jr nz, __LTI - inc a - ret -__LTI8: ; Test 8 bit values A < H - sub h -__LTI: ; Generic signed comparison - jp po, checkParity - xor 0x80 -checkParity: - ld a, 0 ; False - ret p - inc a ; True - ret - ENDP - pop namespace -#line 2 "/zxbasic/src/arch/zx48k/library-asm/lti8.asm" #line 41 "zx48k/for0.bas" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/printi8.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/printnum.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" #line 1 "/zxbasic/src/arch/zx48k/library-asm/print.asm" ; vim:ts=4:sw=4:et: ; PRINT command routine @@ -473,60 +448,6 @@ BRIGHT_TMP: #line 1 "/zxbasic/src/arch/zx48k/library-asm/over.asm" ; Sets OVER flag in P_FLAG permanently ; Parameter: OVER flag in bit 0 of A register -#line 1 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" -#line 4 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" - push namespace core -COPY_ATTR: - ; Just copies current permanent attribs into temporal attribs - ; and sets print mode - PROC - LOCAL INVERSE1 - LOCAL __REFRESH_TMP - INVERSE1 EQU 02Fh - ld hl, (ATTR_P) - ld (ATTR_T), hl - ld hl, FLAGS2 - call __REFRESH_TMP - ld hl, P_FLAG - call __REFRESH_TMP -__SET_ATTR_MODE: ; Another entry to set print modes. A contains (P_FLAG) - LOCAL TABLE - LOCAL CONT2 - rra ; Over bit to carry - ld a, (FLAGS2) - rla ; Over bit in bit 1, Over2 bit in bit 2 - and 3 ; Only bit 0 and 1 (OVER flag) - ld c, a - ld b, 0 - ld hl, TABLE - add hl, bc - ld a, (hl) - ld (PRINT_MODE), a - ld hl, (P_FLAG) - xor a ; NOP -> INVERSE0 - bit 2, l - jr z, CONT2 - ld a, INVERSE1 ; CPL -> INVERSE1 -CONT2: - ld (INVERSE_MODE), a - ret -TABLE: - nop ; NORMAL MODE - xor (hl) ; OVER 1 MODE - and (hl) ; OVER 2 MODE - or (hl) ; OVER 3 MODE -#line 67 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" -__REFRESH_TMP: - ld a, (hl) - and 0b10101010 - ld c, a - rra - or c - ld (hl), a - ret - ENDP - pop namespace -#line 4 "/zxbasic/src/arch/zx48k/library-asm/over.asm" push namespace core OVER: PROC @@ -768,11 +689,10 @@ INVERSE_MODE: ; 00 -> NOP -> INVERSE 0 inc hl ld (DFCC), hl ld hl, (DFCCL) ; current ATTR Pos - push hl - call __SET_ATTR - pop hl inc hl - ld (DFCCL),hl + ld (DFCCL), hl + dec hl + call __SET_ATTR exx ret ; ------------- SPECIAL CHARS (< 32) ----------------- @@ -791,7 +711,7 @@ __PRINT_0Dh: ; Called WHEN printing CHR$(13) push hl call __SCROLL_SCR pop hl -#line 210 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 209 "/zxbasic/src/arch/zx48k/library-asm/print.asm" 1: ld l, 1 __PRINT_EOL_END: @@ -908,14 +828,14 @@ __PRINT_BOLD: __PRINT_BOLD2: call BOLD_TMP jp __PRINT_RESTART -#line 354 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 353 "/zxbasic/src/arch/zx48k/library-asm/print.asm" __PRINT_ITA: ld hl, __PRINT_ITA2 jp __PRINT_SET_STATE __PRINT_ITA2: call ITALIC_TMP jp __PRINT_RESTART -#line 364 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 363 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __BOLD __BOLD: push hl @@ -933,7 +853,7 @@ __BOLD: pop hl ld de, MEM0 ret -#line 385 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 384 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __ITALIC __ITALIC: push hl @@ -958,12 +878,12 @@ __ITALIC: pop hl ld de, MEM0 ret -#line 413 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 412 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __SCROLL_SCR -#line 487 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 486 "/zxbasic/src/arch/zx48k/library-asm/print.asm" __SCROLL_SCR EQU 0DFEh ; Use ROM SCROLL +#line 488 "/zxbasic/src/arch/zx48k/library-asm/print.asm" #line 489 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -#line 490 "/zxbasic/src/arch/zx48k/library-asm/print.asm" PRINT_COMMA: call __LOAD_S_POSN ld a, e @@ -1006,9 +926,9 @@ PRINT_AT: ; Changes cursor to ROW, COL LOCAL __PRINT_TABLE LOCAL __PRINT_TAB, __PRINT_TAB1, __PRINT_TAB2 LOCAL __PRINT_ITA2 -#line 546 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 545 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __PRINT_BOLD2 -#line 552 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 551 "/zxbasic/src/arch/zx48k/library-asm/print.asm" __PRINT_TABLE: ; Jump table for 0 .. 22 codes DW __PRINT_NOP ; 0 DW __PRINT_NOP ; 1 @@ -1036,7 +956,87 @@ __PRINT_TABLE: ; Jump table for 0 .. 22 codes DW __PRINT_TAB ; 23 TAB ENDP pop namespace -#line 2 "/zxbasic/src/arch/zx48k/library-asm/printnum.asm" +#line 3 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" +#line 4 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" + push namespace core +COPY_ATTR: + ; Just copies current permanent attribs into temporal attribs + ; and sets print mode + PROC + LOCAL INVERSE1 + LOCAL __REFRESH_TMP + INVERSE1 EQU 02Fh + ld hl, (ATTR_P) + ld (ATTR_T), hl + ld hl, FLAGS2 + call __REFRESH_TMP + ld hl, P_FLAG + call __REFRESH_TMP +__SET_ATTR_MODE: ; Another entry to set print modes. A contains (P_FLAG) + LOCAL TABLE + LOCAL CONT2 + rra ; Over bit to carry + ld a, (FLAGS2) + rla ; Over bit in bit 1, Over2 bit in bit 2 + and 3 ; Only bit 0 and 1 (OVER flag) + ld c, a + ld b, 0 + ld hl, TABLE + add hl, bc + ld a, (hl) + ld (PRINT_MODE), a + ld hl, (P_FLAG) + xor a ; NOP -> INVERSE0 + bit 2, l + jr z, CONT2 + ld a, INVERSE1 ; CPL -> INVERSE1 +CONT2: + ld (INVERSE_MODE), a + ret +TABLE: + nop ; NORMAL MODE + xor (hl) ; OVER 1 MODE + and (hl) ; OVER 2 MODE + or (hl) ; OVER 3 MODE +#line 67 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" +__REFRESH_TMP: + ld a, (hl) + and 0b10101010 + ld c, a + rra + or c + ld (hl), a + ret + ENDP + pop namespace +#line 42 "zx48k/for0.bas" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/lti8.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/lei8.asm" + push namespace core +__LEI8: ; Signed <= comparison for 8bit int + ; A <= H (registers) + PROC + LOCAL checkParity + sub h + jr nz, __LTI + inc a + ret +__LTI8: ; Test 8 bit values A < H + sub h +__LTI: ; Generic signed comparison + jp po, checkParity + xor 0x80 +checkParity: + ld a, 0 ; False + ret p + inc a ; True + ret + ENDP + pop namespace +#line 2 "/zxbasic/src/arch/zx48k/library-asm/lti8.asm" +#line 43 "zx48k/for0.bas" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/printi8.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/printnum.asm" push namespace core __PRINTU_START: PROC @@ -1154,7 +1154,7 @@ __PRINTU_LOOP: jp __PRINTU_LOOP ; Uses JP in loops ENDP pop namespace -#line 42 "zx48k/for0.bas" +#line 44 "zx48k/for0.bas" #line 1 "/zxbasic/src/arch/zx48k/library-asm/printstr.asm" #line 1 "/zxbasic/src/arch/zx48k/library-asm/free.asm" ; vim: ts=4:et:sw=4: @@ -1465,5 +1465,5 @@ __PRINT_STR: jp __PRINT_STR_LOOP ENDP pop namespace -#line 43 "zx48k/for0.bas" +#line 45 "zx48k/for0.bas" END diff --git a/tests/functional/zx48k/ifelse1.asm b/tests/functional/zx48k/ifelse1.asm index d27f70878..a05154c2b 100644 --- a/tests/functional/zx48k/ifelse1.asm +++ b/tests/functional/zx48k/ifelse1.asm @@ -32,6 +32,7 @@ _a: sub 2 jp z, .LABEL.__LABEL1 .LABEL.__LABEL0: + call .core.COPY_ATTR ld hl, .LABEL.__LABEL2 xor a call .core.__PRINTSTR @@ -67,6 +68,7 @@ _a: DEFB 6Eh DEFB 21h ;; --- end of user code --- +#line 1 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" #line 1 "/zxbasic/src/arch/zx48k/library-asm/print.asm" ; vim:ts=4:sw=4:et: ; PRINT command routine @@ -416,60 +418,6 @@ BRIGHT_TMP: #line 1 "/zxbasic/src/arch/zx48k/library-asm/over.asm" ; Sets OVER flag in P_FLAG permanently ; Parameter: OVER flag in bit 0 of A register -#line 1 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" -#line 4 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" - push namespace core -COPY_ATTR: - ; Just copies current permanent attribs into temporal attribs - ; and sets print mode - PROC - LOCAL INVERSE1 - LOCAL __REFRESH_TMP - INVERSE1 EQU 02Fh - ld hl, (ATTR_P) - ld (ATTR_T), hl - ld hl, FLAGS2 - call __REFRESH_TMP - ld hl, P_FLAG - call __REFRESH_TMP -__SET_ATTR_MODE: ; Another entry to set print modes. A contains (P_FLAG) - LOCAL TABLE - LOCAL CONT2 - rra ; Over bit to carry - ld a, (FLAGS2) - rla ; Over bit in bit 1, Over2 bit in bit 2 - and 3 ; Only bit 0 and 1 (OVER flag) - ld c, a - ld b, 0 - ld hl, TABLE - add hl, bc - ld a, (hl) - ld (PRINT_MODE), a - ld hl, (P_FLAG) - xor a ; NOP -> INVERSE0 - bit 2, l - jr z, CONT2 - ld a, INVERSE1 ; CPL -> INVERSE1 -CONT2: - ld (INVERSE_MODE), a - ret -TABLE: - nop ; NORMAL MODE - xor (hl) ; OVER 1 MODE - and (hl) ; OVER 2 MODE - or (hl) ; OVER 3 MODE -#line 67 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" -__REFRESH_TMP: - ld a, (hl) - and 0b10101010 - ld c, a - rra - or c - ld (hl), a - ret - ENDP - pop namespace -#line 4 "/zxbasic/src/arch/zx48k/library-asm/over.asm" push namespace core OVER: PROC @@ -711,11 +659,10 @@ INVERSE_MODE: ; 00 -> NOP -> INVERSE 0 inc hl ld (DFCC), hl ld hl, (DFCCL) ; current ATTR Pos - push hl - call __SET_ATTR - pop hl inc hl - ld (DFCCL),hl + ld (DFCCL), hl + dec hl + call __SET_ATTR exx ret ; ------------- SPECIAL CHARS (< 32) ----------------- @@ -734,7 +681,7 @@ __PRINT_0Dh: ; Called WHEN printing CHR$(13) push hl call __SCROLL_SCR pop hl -#line 210 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 209 "/zxbasic/src/arch/zx48k/library-asm/print.asm" 1: ld l, 1 __PRINT_EOL_END: @@ -851,14 +798,14 @@ __PRINT_BOLD: __PRINT_BOLD2: call BOLD_TMP jp __PRINT_RESTART -#line 354 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 353 "/zxbasic/src/arch/zx48k/library-asm/print.asm" __PRINT_ITA: ld hl, __PRINT_ITA2 jp __PRINT_SET_STATE __PRINT_ITA2: call ITALIC_TMP jp __PRINT_RESTART -#line 364 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 363 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __BOLD __BOLD: push hl @@ -876,7 +823,7 @@ __BOLD: pop hl ld de, MEM0 ret -#line 385 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 384 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __ITALIC __ITALIC: push hl @@ -901,12 +848,12 @@ __ITALIC: pop hl ld de, MEM0 ret -#line 413 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 412 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __SCROLL_SCR -#line 487 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 486 "/zxbasic/src/arch/zx48k/library-asm/print.asm" __SCROLL_SCR EQU 0DFEh ; Use ROM SCROLL +#line 488 "/zxbasic/src/arch/zx48k/library-asm/print.asm" #line 489 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -#line 490 "/zxbasic/src/arch/zx48k/library-asm/print.asm" PRINT_COMMA: call __LOAD_S_POSN ld a, e @@ -949,9 +896,9 @@ PRINT_AT: ; Changes cursor to ROW, COL LOCAL __PRINT_TABLE LOCAL __PRINT_TAB, __PRINT_TAB1, __PRINT_TAB2 LOCAL __PRINT_ITA2 -#line 546 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 545 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __PRINT_BOLD2 -#line 552 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 551 "/zxbasic/src/arch/zx48k/library-asm/print.asm" __PRINT_TABLE: ; Jump table for 0 .. 22 codes DW __PRINT_NOP ; 0 DW __PRINT_NOP ; 1 @@ -979,7 +926,60 @@ __PRINT_TABLE: ; Jump table for 0 .. 22 codes DW __PRINT_TAB ; 23 TAB ENDP pop namespace -#line 41 "zx48k/ifelse1.bas" +#line 3 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" +#line 4 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" + push namespace core +COPY_ATTR: + ; Just copies current permanent attribs into temporal attribs + ; and sets print mode + PROC + LOCAL INVERSE1 + LOCAL __REFRESH_TMP + INVERSE1 EQU 02Fh + ld hl, (ATTR_P) + ld (ATTR_T), hl + ld hl, FLAGS2 + call __REFRESH_TMP + ld hl, P_FLAG + call __REFRESH_TMP +__SET_ATTR_MODE: ; Another entry to set print modes. A contains (P_FLAG) + LOCAL TABLE + LOCAL CONT2 + rra ; Over bit to carry + ld a, (FLAGS2) + rla ; Over bit in bit 1, Over2 bit in bit 2 + and 3 ; Only bit 0 and 1 (OVER flag) + ld c, a + ld b, 0 + ld hl, TABLE + add hl, bc + ld a, (hl) + ld (PRINT_MODE), a + ld hl, (P_FLAG) + xor a ; NOP -> INVERSE0 + bit 2, l + jr z, CONT2 + ld a, INVERSE1 ; CPL -> INVERSE1 +CONT2: + ld (INVERSE_MODE), a + ret +TABLE: + nop ; NORMAL MODE + xor (hl) ; OVER 1 MODE + and (hl) ; OVER 2 MODE + or (hl) ; OVER 3 MODE +#line 67 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" +__REFRESH_TMP: + ld a, (hl) + and 0b10101010 + ld c, a + rra + or c + ld (hl), a + ret + ENDP + pop namespace +#line 42 "zx48k/ifelse1.bas" #line 1 "/zxbasic/src/arch/zx48k/library-asm/printstr.asm" #line 1 "/zxbasic/src/arch/zx48k/library-asm/free.asm" ; vim: ts=4:et:sw=4: @@ -1290,5 +1290,5 @@ __PRINT_STR: jp __PRINT_STR_LOOP ENDP pop namespace -#line 42 "zx48k/ifelse1.bas" +#line 44 "zx48k/ifelse1.bas" END diff --git a/tests/functional/zx48k/ifwhilex.asm b/tests/functional/zx48k/ifwhilex.asm index cade42f11..37f141bbd 100644 --- a/tests/functional/zx48k/ifwhilex.asm +++ b/tests/functional/zx48k/ifwhilex.asm @@ -38,6 +38,7 @@ _i: inc (hl) jp .LABEL.__LABEL2 .LABEL.__LABEL3: + call .core.COPY_ATTR ld a, (_i) call .core.__PRINTI8 call .core.PRINT_EOL @@ -57,31 +58,7 @@ _i: ei ret ;; --- end of user code --- -#line 1 "/zxbasic/src/arch/zx48k/library-asm/lti8.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/lei8.asm" - push namespace core -__LEI8: ; Signed <= comparison for 8bit int - ; A <= H (registers) - PROC - LOCAL checkParity - sub h - jr nz, __LTI - inc a - ret -__LTI8: ; Test 8 bit values A < H - sub h -__LTI: ; Generic signed comparison - jp po, checkParity - xor 0x80 -checkParity: - ld a, 0 ; False - ret p - inc a ; True - ret - ENDP - pop namespace -#line 2 "/zxbasic/src/arch/zx48k/library-asm/lti8.asm" -#line 36 "zx48k/ifwhilex.bas" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" #line 1 "/zxbasic/src/arch/zx48k/library-asm/print.asm" ; vim:ts=4:sw=4:et: ; PRINT command routine @@ -431,60 +408,6 @@ BRIGHT_TMP: #line 1 "/zxbasic/src/arch/zx48k/library-asm/over.asm" ; Sets OVER flag in P_FLAG permanently ; Parameter: OVER flag in bit 0 of A register -#line 1 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" -#line 4 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" - push namespace core -COPY_ATTR: - ; Just copies current permanent attribs into temporal attribs - ; and sets print mode - PROC - LOCAL INVERSE1 - LOCAL __REFRESH_TMP - INVERSE1 EQU 02Fh - ld hl, (ATTR_P) - ld (ATTR_T), hl - ld hl, FLAGS2 - call __REFRESH_TMP - ld hl, P_FLAG - call __REFRESH_TMP -__SET_ATTR_MODE: ; Another entry to set print modes. A contains (P_FLAG) - LOCAL TABLE - LOCAL CONT2 - rra ; Over bit to carry - ld a, (FLAGS2) - rla ; Over bit in bit 1, Over2 bit in bit 2 - and 3 ; Only bit 0 and 1 (OVER flag) - ld c, a - ld b, 0 - ld hl, TABLE - add hl, bc - ld a, (hl) - ld (PRINT_MODE), a - ld hl, (P_FLAG) - xor a ; NOP -> INVERSE0 - bit 2, l - jr z, CONT2 - ld a, INVERSE1 ; CPL -> INVERSE1 -CONT2: - ld (INVERSE_MODE), a - ret -TABLE: - nop ; NORMAL MODE - xor (hl) ; OVER 1 MODE - and (hl) ; OVER 2 MODE - or (hl) ; OVER 3 MODE -#line 67 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" -__REFRESH_TMP: - ld a, (hl) - and 0b10101010 - ld c, a - rra - or c - ld (hl), a - ret - ENDP - pop namespace -#line 4 "/zxbasic/src/arch/zx48k/library-asm/over.asm" push namespace core OVER: PROC @@ -726,11 +649,10 @@ INVERSE_MODE: ; 00 -> NOP -> INVERSE 0 inc hl ld (DFCC), hl ld hl, (DFCCL) ; current ATTR Pos - push hl - call __SET_ATTR - pop hl inc hl - ld (DFCCL),hl + ld (DFCCL), hl + dec hl + call __SET_ATTR exx ret ; ------------- SPECIAL CHARS (< 32) ----------------- @@ -749,7 +671,7 @@ __PRINT_0Dh: ; Called WHEN printing CHR$(13) push hl call __SCROLL_SCR pop hl -#line 210 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 209 "/zxbasic/src/arch/zx48k/library-asm/print.asm" 1: ld l, 1 __PRINT_EOL_END: @@ -866,14 +788,14 @@ __PRINT_BOLD: __PRINT_BOLD2: call BOLD_TMP jp __PRINT_RESTART -#line 354 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 353 "/zxbasic/src/arch/zx48k/library-asm/print.asm" __PRINT_ITA: ld hl, __PRINT_ITA2 jp __PRINT_SET_STATE __PRINT_ITA2: call ITALIC_TMP jp __PRINT_RESTART -#line 364 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 363 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __BOLD __BOLD: push hl @@ -891,7 +813,7 @@ __BOLD: pop hl ld de, MEM0 ret -#line 385 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 384 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __ITALIC __ITALIC: push hl @@ -916,12 +838,12 @@ __ITALIC: pop hl ld de, MEM0 ret -#line 413 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 412 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __SCROLL_SCR -#line 487 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 486 "/zxbasic/src/arch/zx48k/library-asm/print.asm" __SCROLL_SCR EQU 0DFEh ; Use ROM SCROLL +#line 488 "/zxbasic/src/arch/zx48k/library-asm/print.asm" #line 489 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -#line 490 "/zxbasic/src/arch/zx48k/library-asm/print.asm" PRINT_COMMA: call __LOAD_S_POSN ld a, e @@ -964,9 +886,9 @@ PRINT_AT: ; Changes cursor to ROW, COL LOCAL __PRINT_TABLE LOCAL __PRINT_TAB, __PRINT_TAB1, __PRINT_TAB2 LOCAL __PRINT_ITA2 -#line 546 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 545 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __PRINT_BOLD2 -#line 552 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 551 "/zxbasic/src/arch/zx48k/library-asm/print.asm" __PRINT_TABLE: ; Jump table for 0 .. 22 codes DW __PRINT_NOP ; 0 DW __PRINT_NOP ; 1 @@ -994,7 +916,85 @@ __PRINT_TABLE: ; Jump table for 0 .. 22 codes DW __PRINT_TAB ; 23 TAB ENDP pop namespace +#line 3 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" +#line 4 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" + push namespace core +COPY_ATTR: + ; Just copies current permanent attribs into temporal attribs + ; and sets print mode + PROC + LOCAL INVERSE1 + LOCAL __REFRESH_TMP + INVERSE1 EQU 02Fh + ld hl, (ATTR_P) + ld (ATTR_T), hl + ld hl, FLAGS2 + call __REFRESH_TMP + ld hl, P_FLAG + call __REFRESH_TMP +__SET_ATTR_MODE: ; Another entry to set print modes. A contains (P_FLAG) + LOCAL TABLE + LOCAL CONT2 + rra ; Over bit to carry + ld a, (FLAGS2) + rla ; Over bit in bit 1, Over2 bit in bit 2 + and 3 ; Only bit 0 and 1 (OVER flag) + ld c, a + ld b, 0 + ld hl, TABLE + add hl, bc + ld a, (hl) + ld (PRINT_MODE), a + ld hl, (P_FLAG) + xor a ; NOP -> INVERSE0 + bit 2, l + jr z, CONT2 + ld a, INVERSE1 ; CPL -> INVERSE1 +CONT2: + ld (INVERSE_MODE), a + ret +TABLE: + nop ; NORMAL MODE + xor (hl) ; OVER 1 MODE + and (hl) ; OVER 2 MODE + or (hl) ; OVER 3 MODE +#line 67 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" +__REFRESH_TMP: + ld a, (hl) + and 0b10101010 + ld c, a + rra + or c + ld (hl), a + ret + ENDP + pop namespace #line 37 "zx48k/ifwhilex.bas" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/lti8.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/lei8.asm" + push namespace core +__LEI8: ; Signed <= comparison for 8bit int + ; A <= H (registers) + PROC + LOCAL checkParity + sub h + jr nz, __LTI + inc a + ret +__LTI8: ; Test 8 bit values A < H + sub h +__LTI: ; Generic signed comparison + jp po, checkParity + xor 0x80 +checkParity: + ld a, 0 ; False + ret p + inc a ; True + ret + ENDP + pop namespace +#line 2 "/zxbasic/src/arch/zx48k/library-asm/lti8.asm" +#line 38 "zx48k/ifwhilex.bas" #line 1 "/zxbasic/src/arch/zx48k/library-asm/printi8.asm" #line 1 "/zxbasic/src/arch/zx48k/library-asm/printnum.asm" push namespace core @@ -1114,5 +1114,5 @@ __PRINTU_LOOP: jp __PRINTU_LOOP ; Uses JP in loops ENDP pop namespace -#line 38 "zx48k/ifwhilex.bas" +#line 40 "zx48k/ifwhilex.bas" END diff --git a/tests/functional/zx48k/inkey.asm b/tests/functional/zx48k/inkey.asm index 1d6cae8c0..5bc75584a 100644 --- a/tests/functional/zx48k/inkey.asm +++ b/tests/functional/zx48k/inkey.asm @@ -32,10 +32,12 @@ _a: ex de, hl ld hl, _a call .core.__STORE_STR2 + call .core.COPY_ATTR ld hl, (_a) xor a call .core.__PRINTSTR - call .core.PRINT_EOL_ATTR + call .core.PRINT_EOL + call .core.COPY_ATTR call .core.INKEY ld a, 1 call .core.__PRINTSTR @@ -55,71 +57,42 @@ _a: ei ret ;; --- end of user code --- -#line 1 "/zxbasic/src/arch/zx48k/library-asm/inkey.asm" - ; INKEY Function - ; Returns a string allocated in dynamic memory - ; containing the string. - ; An empty string otherwise. -#line 1 "/zxbasic/src/arch/zx48k/library-asm/alloc.asm" -; vim: ts=4:et:sw=4: - ; Copyleft (K) by Jose M. Rodriguez de la Rosa - ; (a.k.a. Boriel) -; http://www.boriel.com - ; - ; This ASM library is licensed under the MIT license - ; you can use it for any purpose (even for commercial - ; closed source programs). - ; - ; Please read the MIT license on the internet - ; ----- IMPLEMENTATION NOTES ------ - ; The heap is implemented as a linked list of free blocks. -; Each free block contains this info: - ; - ; +----------------+ <-- HEAP START - ; | Size (2 bytes) | - ; | 0 | <-- Size = 0 => DUMMY HEADER BLOCK - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ <-+ - ; | Size (2 bytes) | - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ | - ; | | | <-- If Size > 4, then this contains (size - 4) bytes - ; | (0 if Size = 4)| | - ; +----------------+ <-+ - ; | Size (2 bytes) | - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ | - ; | | | - ; | (0 if Size = 4)| | - ; +----------------+ | - ; | <-- This zone is in use (Already allocated) - ; +----------------+ <-+ - ; | Size (2 bytes) | - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ | - ; | | | - ; | (0 if Size = 4)| | - ; +----------------+ <-+ - ; | Next (2 bytes) |--> NULL => END OF LIST - ; | 0 = NULL | - ; +----------------+ - ; | | - ; | (0 if Size = 4)| - ; +----------------+ - ; When a block is FREED, the previous and next pointers are examined to see - ; if we can defragment the heap. If the block to be freed is just next to the - ; previous, or to the next (or both) they will be converted into a single - ; block (so defragmented). - ; MEMORY MANAGER - ; - ; This library must be initialized calling __MEM_INIT with - ; HL = BLOCK Start & DE = Length. - ; An init directive is useful for initialization routines. - ; They will be added automatically if needed. +#line 1 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +; vim:ts=4:sw=4:et: + ; PRINT command routine + ; Does not print attribute. Use PRINT_STR or PRINT_NUM for that +#line 1 "/zxbasic/src/arch/zx48k/library-asm/sposn.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/sysvars.asm" + ;; ----------------------------------------------------------------------- + ;; ZX Basic System Vars + ;; Some of them will be mapped over Sinclair ROM ones for compatibility + ;; ----------------------------------------------------------------------- + push namespace core +SCREEN_ADDR: DW 16384 ; Screen address (can be pointed to other place to use a screen buffer) +SCREEN_ATTR_ADDR: DW 22528 ; Screen attribute address (ditto.) + ; These are mapped onto ZX Spectrum ROM VARS + CHARS EQU 23606 ; Pointer to ROM/RAM Charset + TVFLAGS EQU 23612 ; TV Flags + UDG EQU 23675 ; Pointer to UDG Charset + COORDS EQU 23677 ; Last PLOT coordinates + FLAGS2 EQU 23681 ; + ECHO_E EQU 23682 ; + DFCC EQU 23684 ; Next screen addr for PRINT + DFCCL EQU 23686 ; Next screen attr for PRINT + S_POSN EQU 23688 + ATTR_P EQU 23693 ; Current Permanent ATTRS set with INK, PAPER, etc commands + ATTR_T EQU 23695 ; temporary ATTRIBUTES + P_FLAG EQU 23697 ; + MEM0 EQU 23698 ; Temporary memory buffer used by ROM chars + SCR_COLS EQU 33 ; Screen with in columns + 1 + SCR_ROWS EQU 24 ; Screen height in rows + SCR_SIZE EQU (SCR_ROWS << 8) + SCR_COLS + pop namespace +#line 2 "/zxbasic/src/arch/zx48k/library-asm/sposn.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/attr.asm" + ; Attribute routines +; vim:ts=4:et:sw: #line 1 "/zxbasic/src/arch/zx48k/library-asm/error.asm" ; Simple error control routines ; vim:ts=4:et: @@ -154,315 +127,29 @@ __STOP: ld (ERR_NR), a ret pop namespace -#line 69 "/zxbasic/src/arch/zx48k/library-asm/alloc.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/heapinit.asm" -; vim: ts=4:et:sw=4: - ; Copyleft (K) by Jose M. Rodriguez de la Rosa - ; (a.k.a. Boriel) -; http://www.boriel.com - ; - ; This ASM library is licensed under the BSD license - ; you can use it for any purpose (even for commercial - ; closed source programs). - ; - ; Please read the BSD license on the internet - ; ----- IMPLEMENTATION NOTES ------ - ; The heap is implemented as a linked list of free blocks. -; Each free block contains this info: - ; - ; +----------------+ <-- HEAP START - ; | Size (2 bytes) | - ; | 0 | <-- Size = 0 => DUMMY HEADER BLOCK - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ <-+ - ; | Size (2 bytes) | - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ | - ; | | | <-- If Size > 4, then this contains (size - 4) bytes - ; | (0 if Size = 4)| | - ; +----------------+ <-+ - ; | Size (2 bytes) | - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ | - ; | | | - ; | (0 if Size = 4)| | - ; +----------------+ | - ; | <-- This zone is in use (Already allocated) - ; +----------------+ <-+ - ; | Size (2 bytes) | - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ | - ; | | | - ; | (0 if Size = 4)| | - ; +----------------+ <-+ - ; | Next (2 bytes) |--> NULL => END OF LIST - ; | 0 = NULL | - ; +----------------+ - ; | | - ; | (0 if Size = 4)| - ; +----------------+ - ; When a block is FREED, the previous and next pointers are examined to see - ; if we can defragment the heap. If the block to be breed is just next to the - ; previous, or to the next (or both) they will be converted into a single - ; block (so defragmented). - ; MEMORY MANAGER - ; - ; This library must be initialized calling __MEM_INIT with - ; HL = BLOCK Start & DE = Length. - ; An init directive is useful for initialization routines. - ; They will be added automatically if needed. - ; --------------------------------------------------------------------- - ; __MEM_INIT must be called to initalize this library with the - ; standard parameters - ; --------------------------------------------------------------------- +#line 6 "/zxbasic/src/arch/zx48k/library-asm/attr.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/in_screen.asm" push namespace core -__MEM_INIT: ; Initializes the library using (RAMTOP) as start, and - ld hl, ZXBASIC_MEM_HEAP ; Change this with other address of heap start - ld de, ZXBASIC_HEAP_SIZE ; Change this with your size - ; --------------------------------------------------------------------- - ; __MEM_INIT2 initalizes this library -; Parameters: -; HL : Memory address of 1st byte of the memory heap -; DE : Length in bytes of the Memory Heap - ; --------------------------------------------------------------------- -__MEM_INIT2: - ; HL as TOP +__IN_SCREEN: + ; Returns NO carry if current coords (D, E) + ; are OUT of the screen limits PROC - dec de - dec de - dec de - dec de ; DE = length - 4; HL = start - ; This is done, because we require 4 bytes for the empty dummy-header block - xor a - ld (hl), a - inc hl - ld (hl), a ; First "free" block is a header: size=0, Pointer=&(Block) + 4 - inc hl - ld b, h - ld c, l - inc bc - inc bc ; BC = starts of next block - ld (hl), c - inc hl - ld (hl), b - inc hl ; Pointer to next block - ld (hl), e - inc hl - ld (hl), d - inc hl ; Block size (should be length - 4 at start); This block contains all the available memory - ld (hl), a ; NULL (0000h) ; No more blocks (a list with a single block) - inc hl - ld (hl), a - ld a, 201 - ld (__MEM_INIT), a; "Pokes" with a RET so ensure this routine is not called again - ret + LOCAL __IN_SCREEN_ERR + ld hl, SCR_SIZE + ld a, e + cp l + jr nc, __IN_SCREEN_ERR ; Do nothing and return if out of range + ld a, d + cp h + ret c ; Return if carry (OK) +__IN_SCREEN_ERR: +__OUT_OF_SCREEN_ERR: + ; Jumps here if out of screen + ld a, ERROR_OutOfScreen + jp __STOP ; Saves error code and exits ENDP pop namespace -#line 70 "/zxbasic/src/arch/zx48k/library-asm/alloc.asm" - ; --------------------------------------------------------------------- - ; MEM_ALLOC - ; Allocates a block of memory in the heap. - ; - ; Parameters - ; BC = Length of requested memory block - ; -; Returns: - ; HL = Pointer to the allocated block in memory. Returns 0 (NULL) - ; if the block could not be allocated (out of memory) - ; --------------------------------------------------------------------- - push namespace core -MEM_ALLOC: -__MEM_ALLOC: ; Returns the 1st free block found of the given length (in BC) - PROC - LOCAL __MEM_LOOP - LOCAL __MEM_DONE - LOCAL __MEM_SUBTRACT - LOCAL __MEM_START - LOCAL TEMP, TEMP0 - TEMP EQU TEMP0 + 1 - ld hl, 0 - ld (TEMP), hl -__MEM_START: - ld hl, ZXBASIC_MEM_HEAP ; This label point to the heap start - inc bc - inc bc ; BC = BC + 2 ; block size needs 2 extra bytes for hidden pointer -__MEM_LOOP: ; Loads lengh at (HL, HL+). If Lenght >= BC, jump to __MEM_DONE - ld a, h ; HL = NULL (No memory available?) - or l -#line 113 "/zxbasic/src/arch/zx48k/library-asm/alloc.asm" - ret z ; NULL -#line 115 "/zxbasic/src/arch/zx48k/library-asm/alloc.asm" - ; HL = Pointer to Free block - ld e, (hl) - inc hl - ld d, (hl) - inc hl ; DE = Block Length - push hl ; HL = *pointer to -> next block - ex de, hl - or a ; CF = 0 - sbc hl, bc ; FREE >= BC (Length) (HL = BlockLength - Length) - jp nc, __MEM_DONE - pop hl - ld (TEMP), hl - ex de, hl - ld e, (hl) - inc hl - ld d, (hl) - ex de, hl - jp __MEM_LOOP -__MEM_DONE: ; A free block has been found. - ; Check if at least 4 bytes remains free (HL >= 4) - push hl - exx ; exx to preserve bc - pop hl - ld bc, 4 - or a - sbc hl, bc - exx - jp nc, __MEM_SUBTRACT - ; At this point... - ; less than 4 bytes remains free. So we return this block entirely - ; We must link the previous block with the next to this one - ; (DE) => Pointer to next block - ; (TEMP) => &(previous->next) - pop hl ; Discard current block pointer - push de - ex de, hl ; DE = Previous block pointer; (HL) = Next block pointer - ld a, (hl) - inc hl - ld h, (hl) - ld l, a ; HL = (HL) - ex de, hl ; HL = Previous block pointer; DE = Next block pointer -TEMP0: - ld hl, 0 ; Pre-previous block pointer - ld (hl), e - inc hl - ld (hl), d ; LINKED - pop hl ; Returning block. - ret -__MEM_SUBTRACT: - ; At this point we have to store HL value (Length - BC) into (DE - 2) - ex de, hl - dec hl - ld (hl), d - dec hl - ld (hl), e ; Store new block length - add hl, de ; New length + DE => free-block start - pop de ; Remove previous HL off the stack - ld (hl), c ; Store length on its 1st word - inc hl - ld (hl), b - inc hl ; Return hl - ret - ENDP - pop namespace -#line 7 "/zxbasic/src/arch/zx48k/library-asm/inkey.asm" - push namespace core -INKEY: - PROC - LOCAL __EMPTY_INKEY - LOCAL KEY_SCAN - LOCAL KEY_TEST - LOCAL KEY_CODE - ld bc, 3 ; 1 char length string - call __MEM_ALLOC - ld a, h - or l - ret z ; Return if NULL (No memory) - push hl ; Saves memory pointer - call KEY_SCAN - jp nz, __EMPTY_INKEY - call KEY_TEST - jp nc, __EMPTY_INKEY - dec d ; D is expected to be FLAGS so set bit 3 $FF - ; 'L' Mode so no keywords. - ld e, a ; main key to A - ; C is MODE 0 'KLC' from above still. - call KEY_CODE ; routine K-DECODE - pop hl - ld (hl), 1 - inc hl - ld (hl), 0 - inc hl - ld (hl), a - dec hl - dec hl ; HL Points to string result - ret -__EMPTY_INKEY: - pop hl - xor a - ld (hl), a - inc hl - ld (hl), a - dec hl - ret - KEY_SCAN EQU 028Eh - KEY_TEST EQU 031Eh - KEY_CODE EQU 0333h - ENDP - pop namespace -#line 29 "zx48k/inkey.bas" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -; vim:ts=4:sw=4:et: - ; PRINT command routine - ; Does not print attribute. Use PRINT_STR or PRINT_NUM for that -#line 1 "/zxbasic/src/arch/zx48k/library-asm/sposn.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/sysvars.asm" - ;; ----------------------------------------------------------------------- - ;; ZX Basic System Vars - ;; Some of them will be mapped over Sinclair ROM ones for compatibility - ;; ----------------------------------------------------------------------- - push namespace core -SCREEN_ADDR: DW 16384 ; Screen address (can be pointed to other place to use a screen buffer) -SCREEN_ATTR_ADDR: DW 22528 ; Screen attribute address (ditto.) - ; These are mapped onto ZX Spectrum ROM VARS - CHARS EQU 23606 ; Pointer to ROM/RAM Charset - TVFLAGS EQU 23612 ; TV Flags - UDG EQU 23675 ; Pointer to UDG Charset - COORDS EQU 23677 ; Last PLOT coordinates - FLAGS2 EQU 23681 ; - ECHO_E EQU 23682 ; - DFCC EQU 23684 ; Next screen addr for PRINT - DFCCL EQU 23686 ; Next screen attr for PRINT - S_POSN EQU 23688 - ATTR_P EQU 23693 ; Current Permanent ATTRS set with INK, PAPER, etc commands - ATTR_T EQU 23695 ; temporary ATTRIBUTES - P_FLAG EQU 23697 ; - MEM0 EQU 23698 ; Temporary memory buffer used by ROM chars - SCR_COLS EQU 33 ; Screen with in columns + 1 - SCR_ROWS EQU 24 ; Screen height in rows - SCR_SIZE EQU (SCR_ROWS << 8) + SCR_COLS - pop namespace -#line 2 "/zxbasic/src/arch/zx48k/library-asm/sposn.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/attr.asm" - ; Attribute routines -; vim:ts=4:et:sw: -#line 1 "/zxbasic/src/arch/zx48k/library-asm/in_screen.asm" - push namespace core -__IN_SCREEN: - ; Returns NO carry if current coords (D, E) - ; are OUT of the screen limits - PROC - LOCAL __IN_SCREEN_ERR - ld hl, SCR_SIZE - ld a, e - cp l - jr nc, __IN_SCREEN_ERR ; Do nothing and return if out of range - ld a, d - cp h - ret c ; Return if carry (OK) -__IN_SCREEN_ERR: -__OUT_OF_SCREEN_ERR: - ; Jumps here if out of screen - ld a, ERROR_OutOfScreen - jp __STOP ; Saves error code and exits - ENDP - pop namespace -#line 7 "/zxbasic/src/arch/zx48k/library-asm/attr.asm" +#line 7 "/zxbasic/src/arch/zx48k/library-asm/attr.asm" push namespace core __ATTR_ADDR: ; calc start address in DE (as (32 * d) + e) @@ -720,60 +407,6 @@ BRIGHT_TMP: #line 1 "/zxbasic/src/arch/zx48k/library-asm/over.asm" ; Sets OVER flag in P_FLAG permanently ; Parameter: OVER flag in bit 0 of A register -#line 1 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" -#line 4 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" - push namespace core -COPY_ATTR: - ; Just copies current permanent attribs into temporal attribs - ; and sets print mode - PROC - LOCAL INVERSE1 - LOCAL __REFRESH_TMP - INVERSE1 EQU 02Fh - ld hl, (ATTR_P) - ld (ATTR_T), hl - ld hl, FLAGS2 - call __REFRESH_TMP - ld hl, P_FLAG - call __REFRESH_TMP -__SET_ATTR_MODE: ; Another entry to set print modes. A contains (P_FLAG) - LOCAL TABLE - LOCAL CONT2 - rra ; Over bit to carry - ld a, (FLAGS2) - rla ; Over bit in bit 1, Over2 bit in bit 2 - and 3 ; Only bit 0 and 1 (OVER flag) - ld c, a - ld b, 0 - ld hl, TABLE - add hl, bc - ld a, (hl) - ld (PRINT_MODE), a - ld hl, (P_FLAG) - xor a ; NOP -> INVERSE0 - bit 2, l - jr z, CONT2 - ld a, INVERSE1 ; CPL -> INVERSE1 -CONT2: - ld (INVERSE_MODE), a - ret -TABLE: - nop ; NORMAL MODE - xor (hl) ; OVER 1 MODE - and (hl) ; OVER 2 MODE - or (hl) ; OVER 3 MODE -#line 67 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" -__REFRESH_TMP: - ld a, (hl) - and 0b10101010 - ld c, a - rra - or c - ld (hl), a - ret - ENDP - pop namespace -#line 4 "/zxbasic/src/arch/zx48k/library-asm/over.asm" push namespace core OVER: PROC @@ -1015,11 +648,10 @@ INVERSE_MODE: ; 00 -> NOP -> INVERSE 0 inc hl ld (DFCC), hl ld hl, (DFCCL) ; current ATTR Pos - push hl - call __SET_ATTR - pop hl inc hl - ld (DFCCL),hl + ld (DFCCL), hl + dec hl + call __SET_ATTR exx ret ; ------------- SPECIAL CHARS (< 32) ----------------- @@ -1038,7 +670,7 @@ __PRINT_0Dh: ; Called WHEN printing CHR$(13) push hl call __SCROLL_SCR pop hl -#line 210 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 209 "/zxbasic/src/arch/zx48k/library-asm/print.asm" 1: ld l, 1 __PRINT_EOL_END: @@ -1155,14 +787,14 @@ __PRINT_BOLD: __PRINT_BOLD2: call BOLD_TMP jp __PRINT_RESTART -#line 354 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 353 "/zxbasic/src/arch/zx48k/library-asm/print.asm" __PRINT_ITA: ld hl, __PRINT_ITA2 jp __PRINT_SET_STATE __PRINT_ITA2: call ITALIC_TMP jp __PRINT_RESTART -#line 364 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 363 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __BOLD __BOLD: push hl @@ -1175,124 +807,484 @@ __BOLD: or c ld (hl), a inc hl - inc de - djnz 1b - pop hl - ld de, MEM0 - ret -#line 385 "/zxbasic/src/arch/zx48k/library-asm/print.asm" - LOCAL __ITALIC -__ITALIC: - push hl - ld hl, MEM0 - ex de, hl - ld bc, 8 - ldir - ld hl, MEM0 - srl (hl) - inc hl - srl (hl) + inc de + djnz 1b + pop hl + ld de, MEM0 + ret +#line 384 "/zxbasic/src/arch/zx48k/library-asm/print.asm" + LOCAL __ITALIC +__ITALIC: + push hl + ld hl, MEM0 + ex de, hl + ld bc, 8 + ldir + ld hl, MEM0 + srl (hl) + inc hl + srl (hl) + inc hl + srl (hl) + inc hl + inc hl + inc hl + sla (hl) + inc hl + sla (hl) + inc hl + sla (hl) + pop hl + ld de, MEM0 + ret +#line 412 "/zxbasic/src/arch/zx48k/library-asm/print.asm" + LOCAL __SCROLL_SCR +#line 486 "/zxbasic/src/arch/zx48k/library-asm/print.asm" + __SCROLL_SCR EQU 0DFEh ; Use ROM SCROLL +#line 488 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 489 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +PRINT_COMMA: + call __LOAD_S_POSN + ld a, e + and 16 + add a, 16 +PRINT_TAB: + ; Tabulates the number of spaces in A register + ; If the current cursor position is already A, does nothing + PROC + LOCAL LOOP + call __LOAD_S_POSN ; e = current row + sub e + and 31 + ret z + ld b, a +LOOP: + ld a, ' ' + call __PRINTCHAR + djnz LOOP + ret + ENDP +PRINT_AT: ; Changes cursor to ROW, COL + ; COL in A register + ; ROW in stack + pop hl ; Ret address + ex (sp), hl ; callee H = ROW + ld l, a + ex de, hl + call __IN_SCREEN + ret nc ; Return if out of screen + jp __SAVE_S_POSN + LOCAL __PRINT_COM + LOCAL __PRINT_AT1 + LOCAL __PRINT_AT2 + LOCAL __PRINT_BOLD + LOCAL __PRINT_ITA + LOCAL __PRINT_INK + LOCAL __PRINT_PAP + LOCAL __PRINT_SET_STATE + LOCAL __PRINT_TABLE + LOCAL __PRINT_TAB, __PRINT_TAB1, __PRINT_TAB2 + LOCAL __PRINT_ITA2 +#line 545 "/zxbasic/src/arch/zx48k/library-asm/print.asm" + LOCAL __PRINT_BOLD2 +#line 551 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +__PRINT_TABLE: ; Jump table for 0 .. 22 codes + DW __PRINT_NOP ; 0 + DW __PRINT_NOP ; 1 + DW __PRINT_NOP ; 2 + DW __PRINT_NOP ; 3 + DW __PRINT_NOP ; 4 + DW __PRINT_NOP ; 5 + DW __PRINT_COM ; 6 COMMA + DW __PRINT_NOP ; 7 + DW __PRINT_DEL ; 8 DEL + DW __PRINT_NOP ; 9 + DW __PRINT_NOP ; 10 + DW __PRINT_NOP ; 11 + DW __PRINT_NOP ; 12 + DW __PRINT_0Dh ; 13 + DW __PRINT_BOLD ; 14 + DW __PRINT_ITA ; 15 + DW __PRINT_INK ; 16 + DW __PRINT_PAP ; 17 + DW __PRINT_FLA ; 18 + DW __PRINT_BRI ; 19 + DW __PRINT_INV ; 20 + DW __PRINT_OVR ; 21 + DW __PRINT_AT ; 22 AT + DW __PRINT_TAB ; 23 TAB + ENDP + pop namespace +#line 3 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" +#line 4 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" + push namespace core +COPY_ATTR: + ; Just copies current permanent attribs into temporal attribs + ; and sets print mode + PROC + LOCAL INVERSE1 + LOCAL __REFRESH_TMP + INVERSE1 EQU 02Fh + ld hl, (ATTR_P) + ld (ATTR_T), hl + ld hl, FLAGS2 + call __REFRESH_TMP + ld hl, P_FLAG + call __REFRESH_TMP +__SET_ATTR_MODE: ; Another entry to set print modes. A contains (P_FLAG) + LOCAL TABLE + LOCAL CONT2 + rra ; Over bit to carry + ld a, (FLAGS2) + rla ; Over bit in bit 1, Over2 bit in bit 2 + and 3 ; Only bit 0 and 1 (OVER flag) + ld c, a + ld b, 0 + ld hl, TABLE + add hl, bc + ld a, (hl) + ld (PRINT_MODE), a + ld hl, (P_FLAG) + xor a ; NOP -> INVERSE0 + bit 2, l + jr z, CONT2 + ld a, INVERSE1 ; CPL -> INVERSE1 +CONT2: + ld (INVERSE_MODE), a + ret +TABLE: + nop ; NORMAL MODE + xor (hl) ; OVER 1 MODE + and (hl) ; OVER 2 MODE + or (hl) ; OVER 3 MODE +#line 67 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" +__REFRESH_TMP: + ld a, (hl) + and 0b10101010 + ld c, a + rra + or c + ld (hl), a + ret + ENDP + pop namespace +#line 31 "zx48k/inkey.bas" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/inkey.asm" + ; INKEY Function + ; Returns a string allocated in dynamic memory + ; containing the string. + ; An empty string otherwise. +#line 1 "/zxbasic/src/arch/zx48k/library-asm/alloc.asm" +; vim: ts=4:et:sw=4: + ; Copyleft (K) by Jose M. Rodriguez de la Rosa + ; (a.k.a. Boriel) +; http://www.boriel.com + ; + ; This ASM library is licensed under the MIT license + ; you can use it for any purpose (even for commercial + ; closed source programs). + ; + ; Please read the MIT license on the internet + ; ----- IMPLEMENTATION NOTES ------ + ; The heap is implemented as a linked list of free blocks. +; Each free block contains this info: + ; + ; +----------------+ <-- HEAP START + ; | Size (2 bytes) | + ; | 0 | <-- Size = 0 => DUMMY HEADER BLOCK + ; +----------------+ + ; | Next (2 bytes) |---+ + ; +----------------+ <-+ + ; | Size (2 bytes) | + ; +----------------+ + ; | Next (2 bytes) |---+ + ; +----------------+ | + ; | | | <-- If Size > 4, then this contains (size - 4) bytes + ; | (0 if Size = 4)| | + ; +----------------+ <-+ + ; | Size (2 bytes) | + ; +----------------+ + ; | Next (2 bytes) |---+ + ; +----------------+ | + ; | | | + ; | (0 if Size = 4)| | + ; +----------------+ | + ; | <-- This zone is in use (Already allocated) + ; +----------------+ <-+ + ; | Size (2 bytes) | + ; +----------------+ + ; | Next (2 bytes) |---+ + ; +----------------+ | + ; | | | + ; | (0 if Size = 4)| | + ; +----------------+ <-+ + ; | Next (2 bytes) |--> NULL => END OF LIST + ; | 0 = NULL | + ; +----------------+ + ; | | + ; | (0 if Size = 4)| + ; +----------------+ + ; When a block is FREED, the previous and next pointers are examined to see + ; if we can defragment the heap. If the block to be freed is just next to the + ; previous, or to the next (or both) they will be converted into a single + ; block (so defragmented). + ; MEMORY MANAGER + ; + ; This library must be initialized calling __MEM_INIT with + ; HL = BLOCK Start & DE = Length. + ; An init directive is useful for initialization routines. + ; They will be added automatically if needed. +#line 1 "/zxbasic/src/arch/zx48k/library-asm/heapinit.asm" +; vim: ts=4:et:sw=4: + ; Copyleft (K) by Jose M. Rodriguez de la Rosa + ; (a.k.a. Boriel) +; http://www.boriel.com + ; + ; This ASM library is licensed under the BSD license + ; you can use it for any purpose (even for commercial + ; closed source programs). + ; + ; Please read the BSD license on the internet + ; ----- IMPLEMENTATION NOTES ------ + ; The heap is implemented as a linked list of free blocks. +; Each free block contains this info: + ; + ; +----------------+ <-- HEAP START + ; | Size (2 bytes) | + ; | 0 | <-- Size = 0 => DUMMY HEADER BLOCK + ; +----------------+ + ; | Next (2 bytes) |---+ + ; +----------------+ <-+ + ; | Size (2 bytes) | + ; +----------------+ + ; | Next (2 bytes) |---+ + ; +----------------+ | + ; | | | <-- If Size > 4, then this contains (size - 4) bytes + ; | (0 if Size = 4)| | + ; +----------------+ <-+ + ; | Size (2 bytes) | + ; +----------------+ + ; | Next (2 bytes) |---+ + ; +----------------+ | + ; | | | + ; | (0 if Size = 4)| | + ; +----------------+ | + ; | <-- This zone is in use (Already allocated) + ; +----------------+ <-+ + ; | Size (2 bytes) | + ; +----------------+ + ; | Next (2 bytes) |---+ + ; +----------------+ | + ; | | | + ; | (0 if Size = 4)| | + ; +----------------+ <-+ + ; | Next (2 bytes) |--> NULL => END OF LIST + ; | 0 = NULL | + ; +----------------+ + ; | | + ; | (0 if Size = 4)| + ; +----------------+ + ; When a block is FREED, the previous and next pointers are examined to see + ; if we can defragment the heap. If the block to be breed is just next to the + ; previous, or to the next (or both) they will be converted into a single + ; block (so defragmented). + ; MEMORY MANAGER + ; + ; This library must be initialized calling __MEM_INIT with + ; HL = BLOCK Start & DE = Length. + ; An init directive is useful for initialization routines. + ; They will be added automatically if needed. + ; --------------------------------------------------------------------- + ; __MEM_INIT must be called to initalize this library with the + ; standard parameters + ; --------------------------------------------------------------------- + push namespace core +__MEM_INIT: ; Initializes the library using (RAMTOP) as start, and + ld hl, ZXBASIC_MEM_HEAP ; Change this with other address of heap start + ld de, ZXBASIC_HEAP_SIZE ; Change this with your size + ; --------------------------------------------------------------------- + ; __MEM_INIT2 initalizes this library +; Parameters: +; HL : Memory address of 1st byte of the memory heap +; DE : Length in bytes of the Memory Heap + ; --------------------------------------------------------------------- +__MEM_INIT2: + ; HL as TOP + PROC + dec de + dec de + dec de + dec de ; DE = length - 4; HL = start + ; This is done, because we require 4 bytes for the empty dummy-header block + xor a + ld (hl), a + inc hl + ld (hl), a ; First "free" block is a header: size=0, Pointer=&(Block) + 4 inc hl - srl (hl) + ld b, h + ld c, l + inc bc + inc bc ; BC = starts of next block + ld (hl), c inc hl + ld (hl), b + inc hl ; Pointer to next block + ld (hl), e inc hl + ld (hl), d + inc hl ; Block size (should be length - 4 at start); This block contains all the available memory + ld (hl), a ; NULL (0000h) ; No more blocks (a list with a single block) inc hl - sla (hl) + ld (hl), a + ld a, 201 + ld (__MEM_INIT), a; "Pokes" with a RET so ensure this routine is not called again + ret + ENDP + pop namespace +#line 70 "/zxbasic/src/arch/zx48k/library-asm/alloc.asm" + ; --------------------------------------------------------------------- + ; MEM_ALLOC + ; Allocates a block of memory in the heap. + ; + ; Parameters + ; BC = Length of requested memory block + ; +; Returns: + ; HL = Pointer to the allocated block in memory. Returns 0 (NULL) + ; if the block could not be allocated (out of memory) + ; --------------------------------------------------------------------- + push namespace core +MEM_ALLOC: +__MEM_ALLOC: ; Returns the 1st free block found of the given length (in BC) + PROC + LOCAL __MEM_LOOP + LOCAL __MEM_DONE + LOCAL __MEM_SUBTRACT + LOCAL __MEM_START + LOCAL TEMP, TEMP0 + TEMP EQU TEMP0 + 1 + ld hl, 0 + ld (TEMP), hl +__MEM_START: + ld hl, ZXBASIC_MEM_HEAP ; This label point to the heap start + inc bc + inc bc ; BC = BC + 2 ; block size needs 2 extra bytes for hidden pointer +__MEM_LOOP: ; Loads lengh at (HL, HL+). If Lenght >= BC, jump to __MEM_DONE + ld a, h ; HL = NULL (No memory available?) + or l +#line 113 "/zxbasic/src/arch/zx48k/library-asm/alloc.asm" + ret z ; NULL +#line 115 "/zxbasic/src/arch/zx48k/library-asm/alloc.asm" + ; HL = Pointer to Free block + ld e, (hl) inc hl - sla (hl) + ld d, (hl) + inc hl ; DE = Block Length + push hl ; HL = *pointer to -> next block + ex de, hl + or a ; CF = 0 + sbc hl, bc ; FREE >= BC (Length) (HL = BlockLength - Length) + jp nc, __MEM_DONE + pop hl + ld (TEMP), hl + ex de, hl + ld e, (hl) inc hl - sla (hl) + ld d, (hl) + ex de, hl + jp __MEM_LOOP +__MEM_DONE: ; A free block has been found. + ; Check if at least 4 bytes remains free (HL >= 4) + push hl + exx ; exx to preserve bc pop hl - ld de, MEM0 - ret -#line 413 "/zxbasic/src/arch/zx48k/library-asm/print.asm" - LOCAL __SCROLL_SCR -#line 487 "/zxbasic/src/arch/zx48k/library-asm/print.asm" - __SCROLL_SCR EQU 0DFEh ; Use ROM SCROLL -#line 489 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -#line 490 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -PRINT_COMMA: - call __LOAD_S_POSN - ld a, e - and 16 - add a, 16 -PRINT_TAB: - ; Tabulates the number of spaces in A register - ; If the current cursor position is already A, does nothing - PROC - LOCAL LOOP - call __LOAD_S_POSN ; e = current row - sub e - and 31 - ret z - ld b, a -LOOP: - ld a, ' ' - call __PRINTCHAR - djnz LOOP + ld bc, 4 + or a + sbc hl, bc + exx + jp nc, __MEM_SUBTRACT + ; At this point... + ; less than 4 bytes remains free. So we return this block entirely + ; We must link the previous block with the next to this one + ; (DE) => Pointer to next block + ; (TEMP) => &(previous->next) + pop hl ; Discard current block pointer + push de + ex de, hl ; DE = Previous block pointer; (HL) = Next block pointer + ld a, (hl) + inc hl + ld h, (hl) + ld l, a ; HL = (HL) + ex de, hl ; HL = Previous block pointer; DE = Next block pointer +TEMP0: + ld hl, 0 ; Pre-previous block pointer + ld (hl), e + inc hl + ld (hl), d ; LINKED + pop hl ; Returning block. ret - ENDP -PRINT_AT: ; Changes cursor to ROW, COL - ; COL in A register - ; ROW in stack - pop hl ; Ret address - ex (sp), hl ; callee H = ROW - ld l, a +__MEM_SUBTRACT: + ; At this point we have to store HL value (Length - BC) into (DE - 2) ex de, hl - call __IN_SCREEN - ret nc ; Return if out of screen - jp __SAVE_S_POSN - LOCAL __PRINT_COM - LOCAL __PRINT_AT1 - LOCAL __PRINT_AT2 - LOCAL __PRINT_BOLD - LOCAL __PRINT_ITA - LOCAL __PRINT_INK - LOCAL __PRINT_PAP - LOCAL __PRINT_SET_STATE - LOCAL __PRINT_TABLE - LOCAL __PRINT_TAB, __PRINT_TAB1, __PRINT_TAB2 - LOCAL __PRINT_ITA2 -#line 546 "/zxbasic/src/arch/zx48k/library-asm/print.asm" - LOCAL __PRINT_BOLD2 -#line 552 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -__PRINT_TABLE: ; Jump table for 0 .. 22 codes - DW __PRINT_NOP ; 0 - DW __PRINT_NOP ; 1 - DW __PRINT_NOP ; 2 - DW __PRINT_NOP ; 3 - DW __PRINT_NOP ; 4 - DW __PRINT_NOP ; 5 - DW __PRINT_COM ; 6 COMMA - DW __PRINT_NOP ; 7 - DW __PRINT_DEL ; 8 DEL - DW __PRINT_NOP ; 9 - DW __PRINT_NOP ; 10 - DW __PRINT_NOP ; 11 - DW __PRINT_NOP ; 12 - DW __PRINT_0Dh ; 13 - DW __PRINT_BOLD ; 14 - DW __PRINT_ITA ; 15 - DW __PRINT_INK ; 16 - DW __PRINT_PAP ; 17 - DW __PRINT_FLA ; 18 - DW __PRINT_BRI ; 19 - DW __PRINT_INV ; 20 - DW __PRINT_OVR ; 21 - DW __PRINT_AT ; 22 AT - DW __PRINT_TAB ; 23 TAB + dec hl + ld (hl), d + dec hl + ld (hl), e ; Store new block length + add hl, de ; New length + DE => free-block start + pop de ; Remove previous HL off the stack + ld (hl), c ; Store length on its 1st word + inc hl + ld (hl), b + inc hl ; Return hl + ret ENDP pop namespace -#line 30 "zx48k/inkey.bas" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/print_eol_attr.asm" - ; Calls PRINT_EOL and then COPY_ATTR, so saves - ; 3 bytes +#line 7 "/zxbasic/src/arch/zx48k/library-asm/inkey.asm" push namespace core -PRINT_EOL_ATTR: - call PRINT_EOL - jp COPY_ATTR +INKEY: + PROC + LOCAL __EMPTY_INKEY + LOCAL KEY_SCAN + LOCAL KEY_TEST + LOCAL KEY_CODE + ld bc, 3 ; 1 char length string + call __MEM_ALLOC + ld a, h + or l + ret z ; Return if NULL (No memory) + push hl ; Saves memory pointer + call KEY_SCAN + jp nz, __EMPTY_INKEY + call KEY_TEST + jp nc, __EMPTY_INKEY + dec d ; D is expected to be FLAGS so set bit 3 $FF + ; 'L' Mode so no keywords. + ld e, a ; main key to A + ; C is MODE 0 'KLC' from above still. + call KEY_CODE ; routine K-DECODE + pop hl + ld (hl), 1 + inc hl + ld (hl), 0 + inc hl + ld (hl), a + dec hl + dec hl ; HL Points to string result + ret +__EMPTY_INKEY: + pop hl + xor a + ld (hl), a + inc hl + ld (hl), a + dec hl + ret + KEY_SCAN EQU 028Eh + KEY_TEST EQU 031Eh + KEY_CODE EQU 0333h + ENDP pop namespace -#line 31 "zx48k/inkey.bas" +#line 32 "zx48k/inkey.bas" #line 1 "/zxbasic/src/arch/zx48k/library-asm/printstr.asm" #line 1 "/zxbasic/src/arch/zx48k/library-asm/free.asm" ; vim: ts=4:et:sw=4: @@ -1495,7 +1487,7 @@ __PRINT_STR: jp __PRINT_STR_LOOP ENDP pop namespace -#line 32 "zx48k/inkey.bas" +#line 34 "zx48k/inkey.bas" #line 1 "/zxbasic/src/arch/zx48k/library-asm/storestr2.asm" ; Similar to __STORE_STR, but this one is called when ; the value of B$ if already duplicated onto the stack. @@ -1529,5 +1521,5 @@ __STORE_STR2: dec hl ; HL points to mem address variable. This might be useful in the future. ret pop namespace -#line 33 "zx48k/inkey.bas" +#line 35 "zx48k/inkey.bas" END diff --git a/tests/functional/zx48k/inktemp.asm b/tests/functional/zx48k/inktemp.asm index 24977a51f..98e8b78a1 100644 --- a/tests/functional/zx48k/inktemp.asm +++ b/tests/functional/zx48k/inktemp.asm @@ -20,6 +20,7 @@ .core.__LABEL__.ZXBASIC_USER_DATA EQU .core.ZXBASIC_USER_DATA .core.ZXBASIC_USER_DATA_END: .core.__MAIN_PROGRAM__: + call .core.COPY_ATTR ld a, 2 call .core.INK_TMP ld hl, 255 @@ -44,7 +45,6 @@ push af ld a, 60 call .core.CIRCLE - call .core.COPY_ATTR ld hl, 0 ld b, h ld c, l diff --git a/tests/functional/zx48k/label_sent2.asm b/tests/functional/zx48k/label_sent2.asm index 2ceec750f..e8545b0c4 100644 --- a/tests/functional/zx48k/label_sent2.asm +++ b/tests/functional/zx48k/label_sent2.asm @@ -26,7 +26,6 @@ call .core.BORDER ld a, 1 call .core.PAPER - call .core.COPY_ATTR ld hl, 0 ld b, h ld c, l @@ -49,9 +48,10 @@ BORDER EQU 229Bh pop namespace ; Nothing to do! (Directly from the ZX Spectrum ROM) -#line 24 "zx48k/label_sent2.bas" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" -#line 4 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" +#line 23 "zx48k/label_sent2.bas" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/paper.asm" + ; Sets paper color in ATTR_P permanently +; Parameter: Paper color in A register #line 1 "/zxbasic/src/arch/zx48k/library-asm/sysvars.asm" ;; ----------------------------------------------------------------------- ;; ZX Basic System Vars @@ -78,39 +78,7 @@ SCREEN_ATTR_ADDR: DW 22528 ; Screen attribute address (ditto.) SCR_ROWS EQU 24 ; Screen height in rows SCR_SIZE EQU (SCR_ROWS << 8) + SCR_COLS pop namespace -#line 6 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" - push namespace core -COPY_ATTR: - ; Just copies current permanent attribs into temporal attribs - ; and sets print mode - PROC - LOCAL INVERSE1 - LOCAL __REFRESH_TMP - INVERSE1 EQU 02Fh - ld hl, (ATTR_P) - ld (ATTR_T), hl - ld hl, FLAGS2 - call __REFRESH_TMP - ld hl, P_FLAG - call __REFRESH_TMP -__SET_ATTR_MODE: ; Another entry to set print modes. A contains (P_FLAG) -#line 65 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" - ret -#line 67 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" -__REFRESH_TMP: - ld a, (hl) - and 0b10101010 - ld c, a - rra - or c - ld (hl), a - ret - ENDP - pop namespace -#line 25 "zx48k/label_sent2.bas" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/paper.asm" - ; Sets paper color in ATTR_P permanently -; Parameter: Paper color in A register +#line 5 "/zxbasic/src/arch/zx48k/library-asm/paper.asm" push namespace core PAPER: PROC @@ -147,5 +115,5 @@ PAPER_TMP: jp __SET_PAPER ENDP pop namespace -#line 26 "zx48k/label_sent2.bas" +#line 24 "zx48k/label_sent2.bas" END diff --git a/tests/functional/zx48k/label_sent3.asm b/tests/functional/zx48k/label_sent3.asm index 8f77de7af..8e578f24e 100644 --- a/tests/functional/zx48k/label_sent3.asm +++ b/tests/functional/zx48k/label_sent3.asm @@ -26,7 +26,6 @@ call .core.BORDER ld a, 1 call .core.PAPER - call .core.COPY_ATTR ld hl, 0 ld b, h ld c, l @@ -49,9 +48,10 @@ BORDER EQU 229Bh pop namespace ; Nothing to do! (Directly from the ZX Spectrum ROM) -#line 24 "zx48k/label_sent3.bas" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" -#line 4 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" +#line 23 "zx48k/label_sent3.bas" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/paper.asm" + ; Sets paper color in ATTR_P permanently +; Parameter: Paper color in A register #line 1 "/zxbasic/src/arch/zx48k/library-asm/sysvars.asm" ;; ----------------------------------------------------------------------- ;; ZX Basic System Vars @@ -78,39 +78,7 @@ SCREEN_ATTR_ADDR: DW 22528 ; Screen attribute address (ditto.) SCR_ROWS EQU 24 ; Screen height in rows SCR_SIZE EQU (SCR_ROWS << 8) + SCR_COLS pop namespace -#line 6 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" - push namespace core -COPY_ATTR: - ; Just copies current permanent attribs into temporal attribs - ; and sets print mode - PROC - LOCAL INVERSE1 - LOCAL __REFRESH_TMP - INVERSE1 EQU 02Fh - ld hl, (ATTR_P) - ld (ATTR_T), hl - ld hl, FLAGS2 - call __REFRESH_TMP - ld hl, P_FLAG - call __REFRESH_TMP -__SET_ATTR_MODE: ; Another entry to set print modes. A contains (P_FLAG) -#line 65 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" - ret -#line 67 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" -__REFRESH_TMP: - ld a, (hl) - and 0b10101010 - ld c, a - rra - or c - ld (hl), a - ret - ENDP - pop namespace -#line 25 "zx48k/label_sent3.bas" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/paper.asm" - ; Sets paper color in ATTR_P permanently -; Parameter: Paper color in A register +#line 5 "/zxbasic/src/arch/zx48k/library-asm/paper.asm" push namespace core PAPER: PROC @@ -147,5 +115,5 @@ PAPER_TMP: jp __SET_PAPER ENDP pop namespace -#line 26 "zx48k/label_sent3.bas" +#line 24 "zx48k/label_sent3.bas" END diff --git a/tests/functional/zx48k/label_sent4.asm b/tests/functional/zx48k/label_sent4.asm index dc84d4e84..744feb4fa 100644 --- a/tests/functional/zx48k/label_sent4.asm +++ b/tests/functional/zx48k/label_sent4.asm @@ -26,7 +26,6 @@ call .core.BORDER ld a, 1 call .core.PAPER - call .core.COPY_ATTR ld hl, 0 ld b, h ld c, l @@ -49,9 +48,10 @@ BORDER EQU 229Bh pop namespace ; Nothing to do! (Directly from the ZX Spectrum ROM) -#line 24 "zx48k/label_sent4.bas" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" -#line 4 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" +#line 23 "zx48k/label_sent4.bas" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/paper.asm" + ; Sets paper color in ATTR_P permanently +; Parameter: Paper color in A register #line 1 "/zxbasic/src/arch/zx48k/library-asm/sysvars.asm" ;; ----------------------------------------------------------------------- ;; ZX Basic System Vars @@ -78,39 +78,7 @@ SCREEN_ATTR_ADDR: DW 22528 ; Screen attribute address (ditto.) SCR_ROWS EQU 24 ; Screen height in rows SCR_SIZE EQU (SCR_ROWS << 8) + SCR_COLS pop namespace -#line 6 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" - push namespace core -COPY_ATTR: - ; Just copies current permanent attribs into temporal attribs - ; and sets print mode - PROC - LOCAL INVERSE1 - LOCAL __REFRESH_TMP - INVERSE1 EQU 02Fh - ld hl, (ATTR_P) - ld (ATTR_T), hl - ld hl, FLAGS2 - call __REFRESH_TMP - ld hl, P_FLAG - call __REFRESH_TMP -__SET_ATTR_MODE: ; Another entry to set print modes. A contains (P_FLAG) -#line 65 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" - ret -#line 67 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" -__REFRESH_TMP: - ld a, (hl) - and 0b10101010 - ld c, a - rra - or c - ld (hl), a - ret - ENDP - pop namespace -#line 25 "zx48k/label_sent4.bas" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/paper.asm" - ; Sets paper color in ATTR_P permanently -; Parameter: Paper color in A register +#line 5 "/zxbasic/src/arch/zx48k/library-asm/paper.asm" push namespace core PAPER: PROC @@ -147,5 +115,5 @@ PAPER_TMP: jp __SET_PAPER ENDP pop namespace -#line 26 "zx48k/label_sent4.bas" +#line 24 "zx48k/label_sent4.bas" END diff --git a/tests/functional/zx48k/label_sent5.asm b/tests/functional/zx48k/label_sent5.asm index 6c478fdb2..4b9f54d0d 100644 --- a/tests/functional/zx48k/label_sent5.asm +++ b/tests/functional/zx48k/label_sent5.asm @@ -26,7 +26,6 @@ call .core.BORDER ld a, 1 call .core.PAPER - call .core.COPY_ATTR ld hl, 0 ld b, h ld c, l @@ -49,9 +48,10 @@ BORDER EQU 229Bh pop namespace ; Nothing to do! (Directly from the ZX Spectrum ROM) -#line 24 "zx48k/label_sent5.bas" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" -#line 4 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" +#line 23 "zx48k/label_sent5.bas" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/paper.asm" + ; Sets paper color in ATTR_P permanently +; Parameter: Paper color in A register #line 1 "/zxbasic/src/arch/zx48k/library-asm/sysvars.asm" ;; ----------------------------------------------------------------------- ;; ZX Basic System Vars @@ -78,39 +78,7 @@ SCREEN_ATTR_ADDR: DW 22528 ; Screen attribute address (ditto.) SCR_ROWS EQU 24 ; Screen height in rows SCR_SIZE EQU (SCR_ROWS << 8) + SCR_COLS pop namespace -#line 6 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" - push namespace core -COPY_ATTR: - ; Just copies current permanent attribs into temporal attribs - ; and sets print mode - PROC - LOCAL INVERSE1 - LOCAL __REFRESH_TMP - INVERSE1 EQU 02Fh - ld hl, (ATTR_P) - ld (ATTR_T), hl - ld hl, FLAGS2 - call __REFRESH_TMP - ld hl, P_FLAG - call __REFRESH_TMP -__SET_ATTR_MODE: ; Another entry to set print modes. A contains (P_FLAG) -#line 65 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" - ret -#line 67 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" -__REFRESH_TMP: - ld a, (hl) - and 0b10101010 - ld c, a - rra - or c - ld (hl), a - ret - ENDP - pop namespace -#line 25 "zx48k/label_sent5.bas" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/paper.asm" - ; Sets paper color in ATTR_P permanently -; Parameter: Paper color in A register +#line 5 "/zxbasic/src/arch/zx48k/library-asm/paper.asm" push namespace core PAPER: PROC @@ -147,5 +115,5 @@ PAPER_TMP: jp __SET_PAPER ENDP pop namespace -#line 26 "zx48k/label_sent5.bas" +#line 24 "zx48k/label_sent5.bas" END diff --git a/tests/functional/zx48k/lcd3.asm b/tests/functional/zx48k/lcd3.asm index c6ee7cc82..e63b06599 100644 --- a/tests/functional/zx48k/lcd3.asm +++ b/tests/functional/zx48k/lcd3.asm @@ -28,6 +28,7 @@ _adr: DEFB 00, 00, 00, 00, 00 .core.ZXBASIC_USER_DATA_END: .core.__MAIN_PROGRAM__: + call .core.COPY_ATTR xor a push af ld a, 30 @@ -224,434 +225,43 @@ __ADDF: ; Addition defb 38h; ; END CALC jp __FPSTACK_POP pop namespace -#line 140 "zx48k/lcd3.bas" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/free.asm" -; vim: ts=4:et:sw=4: - ; Copyleft (K) by Jose M. Rodriguez de la Rosa - ; (a.k.a. Boriel) -; http://www.boriel.com - ; - ; This ASM library is licensed under the BSD license - ; you can use it for any purpose (even for commercial - ; closed source programs). - ; - ; Please read the BSD license on the internet - ; ----- IMPLEMENTATION NOTES ------ - ; The heap is implemented as a linked list of free blocks. -; Each free block contains this info: - ; - ; +----------------+ <-- HEAP START - ; | Size (2 bytes) | - ; | 0 | <-- Size = 0 => DUMMY HEADER BLOCK - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ <-+ - ; | Size (2 bytes) | - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ | - ; | | | <-- If Size > 4, then this contains (size - 4) bytes - ; | (0 if Size = 4)| | - ; +----------------+ <-+ - ; | Size (2 bytes) | - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ | - ; | | | - ; | (0 if Size = 4)| | - ; +----------------+ | - ; | <-- This zone is in use (Already allocated) - ; +----------------+ <-+ - ; | Size (2 bytes) | - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ | - ; | | | - ; | (0 if Size = 4)| | - ; +----------------+ <-+ - ; | Next (2 bytes) |--> NULL => END OF LIST - ; | 0 = NULL | - ; +----------------+ - ; | | - ; | (0 if Size = 4)| - ; +----------------+ - ; When a block is FREED, the previous and next pointers are examined to see - ; if we can defragment the heap. If the block to be breed is just next to the - ; previous, or to the next (or both) they will be converted into a single - ; block (so defragmented). - ; MEMORY MANAGER - ; - ; This library must be initialized calling __MEM_INIT with - ; HL = BLOCK Start & DE = Length. - ; An init directive is useful for initialization routines. - ; They will be added automatically if needed. -#line 1 "/zxbasic/src/arch/zx48k/library-asm/heapinit.asm" -; vim: ts=4:et:sw=4: - ; Copyleft (K) by Jose M. Rodriguez de la Rosa - ; (a.k.a. Boriel) -; http://www.boriel.com - ; - ; This ASM library is licensed under the BSD license - ; you can use it for any purpose (even for commercial - ; closed source programs). - ; - ; Please read the BSD license on the internet - ; ----- IMPLEMENTATION NOTES ------ - ; The heap is implemented as a linked list of free blocks. -; Each free block contains this info: - ; - ; +----------------+ <-- HEAP START - ; | Size (2 bytes) | - ; | 0 | <-- Size = 0 => DUMMY HEADER BLOCK - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ <-+ - ; | Size (2 bytes) | - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ | - ; | | | <-- If Size > 4, then this contains (size - 4) bytes - ; | (0 if Size = 4)| | - ; +----------------+ <-+ - ; | Size (2 bytes) | - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ | - ; | | | - ; | (0 if Size = 4)| | - ; +----------------+ | - ; | <-- This zone is in use (Already allocated) - ; +----------------+ <-+ - ; | Size (2 bytes) | - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ | - ; | | | - ; | (0 if Size = 4)| | - ; +----------------+ <-+ - ; | Next (2 bytes) |--> NULL => END OF LIST - ; | 0 = NULL | - ; +----------------+ - ; | | - ; | (0 if Size = 4)| - ; +----------------+ - ; When a block is FREED, the previous and next pointers are examined to see - ; if we can defragment the heap. If the block to be breed is just next to the - ; previous, or to the next (or both) they will be converted into a single - ; block (so defragmented). - ; MEMORY MANAGER - ; - ; This library must be initialized calling __MEM_INIT with - ; HL = BLOCK Start & DE = Length. - ; An init directive is useful for initialization routines. - ; They will be added automatically if needed. - ; --------------------------------------------------------------------- - ; __MEM_INIT must be called to initalize this library with the - ; standard parameters - ; --------------------------------------------------------------------- - push namespace core -__MEM_INIT: ; Initializes the library using (RAMTOP) as start, and - ld hl, ZXBASIC_MEM_HEAP ; Change this with other address of heap start - ld de, ZXBASIC_HEAP_SIZE ; Change this with your size - ; --------------------------------------------------------------------- - ; __MEM_INIT2 initalizes this library -; Parameters: -; HL : Memory address of 1st byte of the memory heap -; DE : Length in bytes of the Memory Heap - ; --------------------------------------------------------------------- -__MEM_INIT2: - ; HL as TOP - PROC - dec de - dec de - dec de - dec de ; DE = length - 4; HL = start - ; This is done, because we require 4 bytes for the empty dummy-header block - xor a - ld (hl), a - inc hl - ld (hl), a ; First "free" block is a header: size=0, Pointer=&(Block) + 4 - inc hl - ld b, h - ld c, l - inc bc - inc bc ; BC = starts of next block - ld (hl), c - inc hl - ld (hl), b - inc hl ; Pointer to next block - ld (hl), e - inc hl - ld (hl), d - inc hl ; Block size (should be length - 4 at start); This block contains all the available memory - ld (hl), a ; NULL (0000h) ; No more blocks (a list with a single block) - inc hl - ld (hl), a - ld a, 201 - ld (__MEM_INIT), a; "Pokes" with a RET so ensure this routine is not called again - ret - ENDP - pop namespace -#line 69 "/zxbasic/src/arch/zx48k/library-asm/free.asm" - ; --------------------------------------------------------------------- - ; MEM_FREE - ; Frees a block of memory - ; -; Parameters: - ; HL = Pointer to the block to be freed. If HL is NULL (0) nothing - ; is done - ; --------------------------------------------------------------------- - push namespace core -MEM_FREE: -__MEM_FREE: ; Frees the block pointed by HL - ; HL DE BC & AF modified - PROC - LOCAL __MEM_LOOP2 - LOCAL __MEM_LINK_PREV - LOCAL __MEM_JOIN_TEST - LOCAL __MEM_BLOCK_JOIN - ld a, h - or l - ret z ; Return if NULL pointer - dec hl - dec hl - ld b, h - ld c, l ; BC = Block pointer - ld hl, ZXBASIC_MEM_HEAP ; This label point to the heap start -__MEM_LOOP2: - inc hl - inc hl ; Next block ptr - ld e, (hl) - inc hl - ld d, (hl) ; Block next ptr - ex de, hl ; DE = &(block->next); HL = block->next - ld a, h ; HL == NULL? - or l - jp z, __MEM_LINK_PREV; if so, link with previous - or a ; Clear carry flag - sbc hl, bc ; Carry if BC > HL => This block if before - add hl, bc ; Restores HL, preserving Carry flag - jp c, __MEM_LOOP2 ; This block is before. Keep searching PASS the block - ;------ At this point current HL is PAST BC, so we must link (DE) with BC, and HL in BC->next -__MEM_LINK_PREV: ; Link (DE) with BC, and BC->next with HL - ex de, hl - push hl - dec hl - ld (hl), c - inc hl - ld (hl), b ; (DE) <- BC - ld h, b ; HL <- BC (Free block ptr) - ld l, c - inc hl ; Skip block length (2 bytes) - inc hl - ld (hl), e ; Block->next = DE - inc hl - ld (hl), d - ; --- LINKED ; HL = &(BC->next) + 2 - call __MEM_JOIN_TEST - pop hl -__MEM_JOIN_TEST: ; Checks for fragmented contiguous blocks and joins them - ; hl = Ptr to current block + 2 - ld d, (hl) - dec hl - ld e, (hl) - dec hl - ld b, (hl) ; Loads block length into BC - dec hl - ld c, (hl) ; - push hl ; Saves it for later - add hl, bc ; Adds its length. If HL == DE now, it must be joined - or a - sbc hl, de ; If Z, then HL == DE => We must join - pop hl - ret nz -__MEM_BLOCK_JOIN: ; Joins current block (pointed by HL) with next one (pointed by DE). HL->length already in BC - push hl ; Saves it for later - ex de, hl - ld e, (hl) ; DE -> block->next->length - inc hl - ld d, (hl) - inc hl - ex de, hl ; DE = &(block->next) - add hl, bc ; HL = Total Length - ld b, h - ld c, l ; BC = Total Length - ex de, hl - ld e, (hl) - inc hl - ld d, (hl) ; DE = block->next - pop hl ; Recovers Pointer to block - ld (hl), c - inc hl - ld (hl), b ; Length Saved - inc hl - ld (hl), e - inc hl - ld (hl), d ; Next saved - ret - ENDP - pop namespace -#line 141 "zx48k/lcd3.bas" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/ftou32reg.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/neg32.asm" - push namespace core -__ABS32: - bit 7, d - ret z -__NEG32: ; Negates DEHL (Two's complement) - ld a, l - cpl - ld l, a - ld a, h - cpl - ld h, a - ld a, e - cpl - ld e, a - ld a, d - cpl - ld d, a - inc l - ret nz - inc h - ret nz - inc de - ret - pop namespace -#line 2 "/zxbasic/src/arch/zx48k/library-asm/ftou32reg.asm" - push namespace core -__FTOU32REG: ; Converts a Float to (un)signed 32 bit integer (NOTE: It's ALWAYS 32 bit signed) - ; Input FP number in A EDCB (A exponent, EDCB mantissa) - ; Output: DEHL 32 bit number (signed) - PROC - LOCAL __IS_FLOAT - LOCAL __NEGATE - or a - jr nz, __IS_FLOAT - ; Here if it is a ZX ROM Integer - ld h, c - ld l, d - ld d, e - ret -__IS_FLOAT: ; Jumps here if it is a true floating point number - ld h, e - push hl ; Stores it for later (Contains Sign in H) - push de - push bc - exx - pop de ; Loads mantissa into C'B' E'D' - pop bc ; - set 7, c ; Highest mantissa bit is always 1 - exx - ld hl, 0 ; DEHL = 0 - ld d, h - ld e, l - ;ld a, c ; Get exponent - sub 128 ; Exponent -= 128 - jr z, __FTOU32REG_END ; If it was <= 128, we are done (Integers must be > 128) - jr c, __FTOU32REG_END ; It was decimal (0.xxx). We are done (return 0) - ld b, a ; Loop counter = exponent - 128 -__FTOU32REG_LOOP: - exx ; Shift C'B' E'D' << 1, output bit stays in Carry - sla d - rl e - rl b - rl c - exx ; Shift DEHL << 1, inserting the carry on the right - rl l - rl h - rl e - rl d - djnz __FTOU32REG_LOOP -__FTOU32REG_END: - pop af ; Take the sign bit - or a ; Sets SGN bit to 1 if negative - jp m, __NEGATE ; Negates DEHL - ret -__NEGATE: - exx - ld a, d - or e - or b - or c - exx - jr z, __END - inc l - jr nz, __END - inc h - jr nz, __END - inc de - LOCAL __END -__END: - jp __NEG32 - ENDP -__FTOU8: ; Converts float in C ED LH to Unsigned byte in A - call __FTOU32REG - ld a, l - ret - pop namespace -#line 142 "zx48k/lcd3.bas" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/loadstr.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/alloc.asm" -; vim: ts=4:et:sw=4: - ; Copyleft (K) by Jose M. Rodriguez de la Rosa - ; (a.k.a. Boriel) -; http://www.boriel.com - ; - ; This ASM library is licensed under the MIT license - ; you can use it for any purpose (even for commercial - ; closed source programs). - ; - ; Please read the MIT license on the internet - ; ----- IMPLEMENTATION NOTES ------ - ; The heap is implemented as a linked list of free blocks. -; Each free block contains this info: - ; - ; +----------------+ <-- HEAP START - ; | Size (2 bytes) | - ; | 0 | <-- Size = 0 => DUMMY HEADER BLOCK - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ <-+ - ; | Size (2 bytes) | - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ | - ; | | | <-- If Size > 4, then this contains (size - 4) bytes - ; | (0 if Size = 4)| | - ; +----------------+ <-+ - ; | Size (2 bytes) | - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ | - ; | | | - ; | (0 if Size = 4)| | - ; +----------------+ | - ; | <-- This zone is in use (Already allocated) - ; +----------------+ <-+ - ; | Size (2 bytes) | - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ | - ; | | | - ; | (0 if Size = 4)| | - ; +----------------+ <-+ - ; | Next (2 bytes) |--> NULL => END OF LIST - ; | 0 = NULL | - ; +----------------+ - ; | | - ; | (0 if Size = 4)| - ; +----------------+ - ; When a block is FREED, the previous and next pointers are examined to see - ; if we can defragment the heap. If the block to be freed is just next to the - ; previous, or to the next (or both) they will be converted into a single - ; block (so defragmented). - ; MEMORY MANAGER - ; - ; This library must be initialized calling __MEM_INIT with - ; HL = BLOCK Start & DE = Length. - ; An init directive is useful for initialization routines. - ; They will be added automatically if needed. +#line 141 "zx48k/lcd3.bas" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +; vim:ts=4:sw=4:et: + ; PRINT command routine + ; Does not print attribute. Use PRINT_STR or PRINT_NUM for that +#line 1 "/zxbasic/src/arch/zx48k/library-asm/sposn.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/sysvars.asm" + ;; ----------------------------------------------------------------------- + ;; ZX Basic System Vars + ;; Some of them will be mapped over Sinclair ROM ones for compatibility + ;; ----------------------------------------------------------------------- + push namespace core +SCREEN_ADDR: DW 16384 ; Screen address (can be pointed to other place to use a screen buffer) +SCREEN_ATTR_ADDR: DW 22528 ; Screen attribute address (ditto.) + ; These are mapped onto ZX Spectrum ROM VARS + CHARS EQU 23606 ; Pointer to ROM/RAM Charset + TVFLAGS EQU 23612 ; TV Flags + UDG EQU 23675 ; Pointer to UDG Charset + COORDS EQU 23677 ; Last PLOT coordinates + FLAGS2 EQU 23681 ; + ECHO_E EQU 23682 ; + DFCC EQU 23684 ; Next screen addr for PRINT + DFCCL EQU 23686 ; Next screen attr for PRINT + S_POSN EQU 23688 + ATTR_P EQU 23693 ; Current Permanent ATTRS set with INK, PAPER, etc commands + ATTR_T EQU 23695 ; temporary ATTRIBUTES + P_FLAG EQU 23697 ; + MEM0 EQU 23698 ; Temporary memory buffer used by ROM chars + SCR_COLS EQU 33 ; Screen with in columns + 1 + SCR_ROWS EQU 24 ; Screen height in rows + SCR_SIZE EQU (SCR_ROWS << 8) + SCR_COLS + pop namespace +#line 2 "/zxbasic/src/arch/zx48k/library-asm/sposn.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/attr.asm" + ; Attribute routines +; vim:ts=4:et:sw: #line 1 "/zxbasic/src/arch/zx48k/library-asm/error.asm" ; Simple error control routines ; vim:ts=4:et: @@ -686,457 +296,795 @@ __STOP: ld (ERR_NR), a ret pop namespace -#line 69 "/zxbasic/src/arch/zx48k/library-asm/alloc.asm" - ; --------------------------------------------------------------------- - ; MEM_ALLOC - ; Allocates a block of memory in the heap. - ; - ; Parameters - ; BC = Length of requested memory block - ; -; Returns: - ; HL = Pointer to the allocated block in memory. Returns 0 (NULL) - ; if the block could not be allocated (out of memory) - ; --------------------------------------------------------------------- +#line 6 "/zxbasic/src/arch/zx48k/library-asm/attr.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/in_screen.asm" + push namespace core +__IN_SCREEN: + ; Returns NO carry if current coords (D, E) + ; are OUT of the screen limits + PROC + LOCAL __IN_SCREEN_ERR + ld hl, SCR_SIZE + ld a, e + cp l + jr nc, __IN_SCREEN_ERR ; Do nothing and return if out of range + ld a, d + cp h + ret c ; Return if carry (OK) +__IN_SCREEN_ERR: +__OUT_OF_SCREEN_ERR: + ; Jumps here if out of screen + ld a, ERROR_OutOfScreen + jp __STOP ; Saves error code and exits + ENDP + pop namespace +#line 7 "/zxbasic/src/arch/zx48k/library-asm/attr.asm" + push namespace core +__ATTR_ADDR: + ; calc start address in DE (as (32 * d) + e) + ; Contributed by Santiago Romero at http://www.speccy.org + ld h, 0 ; 7 T-States + ld a, d ; 4 T-States + ld d, h + add a, a ; a * 2 ; 4 T-States + add a, a ; a * 4 ; 4 T-States + ld l, a ; HL = A * 4 ; 4 T-States + add hl, hl ; HL = A * 8 ; 15 T-States + add hl, hl ; HL = A * 16 ; 15 T-States + add hl, hl ; HL = A * 32 ; 15 T-States + add hl, de + ld de, (SCREEN_ATTR_ADDR) ; Adds the screen address + add hl, de + ; Return current screen address in HL + ret + ; Sets the attribute at a given screen coordinate (D, E). + ; The attribute is taken from the ATTR_T memory variable + ; Used by PRINT routines +SET_ATTR: + ; Checks for valid coords + call __IN_SCREEN + ret nc + call __ATTR_ADDR +__SET_ATTR: + ; Internal __FASTCALL__ Entry used by printing routines + ; HL contains the address of the ATTR cell to set + PROC +__SET_ATTR2: ; Sets attr from ATTR_T to (HL) which points to the scr address + ld de, (ATTR_T) ; E = ATTR_T, D = MASK_T + ld a, d + and (hl) + ld c, a ; C = current screen color, masked + ld a, d + cpl ; Negate mask + and e ; Mask current attributes + or c ; Mix them + ld (hl), a ; Store result in screen + ret + ENDP + pop namespace +#line 3 "/zxbasic/src/arch/zx48k/library-asm/sposn.asm" + ; Printing positioning library. + push namespace core + ; Loads into DE current ROW, COL print position from S_POSN mem var. +__LOAD_S_POSN: + PROC + ld de, (S_POSN) + ld hl, SCR_SIZE + or a + sbc hl, de + ex de, hl + ret + ENDP + ; Saves ROW, COL from DE into S_POSN mem var. +__SAVE_S_POSN: + PROC + ld hl, SCR_SIZE + or a + sbc hl, de + ld (S_POSN), hl ; saves it again +__SET_SCR_PTR: ;; Fast + push de + call __ATTR_ADDR + ld (DFCCL), hl + pop de + ld a, d + ld c, a ; Saves it for later + and 0F8h ; Masks 3 lower bit ; zy + ld d, a + ld a, c ; Recovers it + and 07h ; MOD 7 ; y1 + rrca + rrca + rrca + or e + ld e, a + ld hl, (SCREEN_ADDR) + add hl, de ; HL = Screen address + DE + ld (DFCC), hl + ret + ENDP + pop namespace +#line 6 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/table_jump.asm" push namespace core -MEM_ALLOC: -__MEM_ALLOC: ; Returns the 1st free block found of the given length (in BC) - PROC - LOCAL __MEM_LOOP - LOCAL __MEM_DONE - LOCAL __MEM_SUBTRACT - LOCAL __MEM_START - LOCAL TEMP, TEMP0 - TEMP EQU TEMP0 + 1 - ld hl, 0 - ld (TEMP), hl -__MEM_START: - ld hl, ZXBASIC_MEM_HEAP ; This label point to the heap start - inc bc - inc bc ; BC = BC + 2 ; block size needs 2 extra bytes for hidden pointer -__MEM_LOOP: ; Loads lengh at (HL, HL+). If Lenght >= BC, jump to __MEM_DONE - ld a, h ; HL = NULL (No memory available?) - or l -#line 113 "/zxbasic/src/arch/zx48k/library-asm/alloc.asm" - ret z ; NULL -#line 115 "/zxbasic/src/arch/zx48k/library-asm/alloc.asm" - ; HL = Pointer to Free block - ld e, (hl) - inc hl - ld d, (hl) - inc hl ; DE = Block Length - push hl ; HL = *pointer to -> next block - ex de, hl - or a ; CF = 0 - sbc hl, bc ; FREE >= BC (Length) (HL = BlockLength - Length) - jp nc, __MEM_DONE - pop hl - ld (TEMP), hl - ex de, hl +JUMP_HL_PLUS_2A: ; Does JP (HL + A*2) Modifies DE. Modifies A + add a, a +JUMP_HL_PLUS_A: ; Does JP (HL + A) Modifies DE + ld e, a + ld d, 0 +JUMP_HL_PLUS_DE: ; Does JP (HL + DE) + add hl, de ld e, (hl) inc hl ld d, (hl) ex de, hl - jp __MEM_LOOP -__MEM_DONE: ; A free block has been found. - ; Check if at least 4 bytes remains free (HL >= 4) - push hl - exx ; exx to preserve bc - pop hl - ld bc, 4 +CALL_HL: + jp (hl) + pop namespace +#line 8 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/ink.asm" + ; Sets ink color in ATTR_P permanently +; Parameter: Paper color in A register + push namespace core +INK: + PROC + LOCAL __SET_INK + LOCAL __SET_INK2 + ld de, ATTR_P +__SET_INK: + cp 8 + jr nz, __SET_INK2 + inc de ; Points DE to MASK_T or MASK_P + ld a, (de) + or 7 ; Set bits 0,1,2 to enable transparency + ld (de), a + ret +__SET_INK2: + ; Another entry. This will set the ink color at location pointer by DE + and 7 ; # Gets color mod 8 + ld b, a ; Saves the color + ld a, (de) + and 0F8h ; Clears previous value + or b + ld (de), a + inc de ; Points DE to MASK_T or MASK_P + ld a, (de) + and 0F8h ; Reset bits 0,1,2 sign to disable transparency + ld (de), a ; Store new attr + ret + ; Sets the INK color passed in A register in the ATTR_T variable +INK_TMP: + ld de, ATTR_T + jp __SET_INK + ENDP + pop namespace +#line 9 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/paper.asm" + ; Sets paper color in ATTR_P permanently +; Parameter: Paper color in A register + push namespace core +PAPER: + PROC + LOCAL __SET_PAPER + LOCAL __SET_PAPER2 + ld de, ATTR_P +__SET_PAPER: + cp 8 + jr nz, __SET_PAPER2 + inc de + ld a, (de) + or 038h + ld (de), a + ret + ; Another entry. This will set the paper color at location pointer by DE +__SET_PAPER2: + and 7 ; # Remove + rlca + rlca + rlca ; a *= 8 + ld b, a ; Saves the color + ld a, (de) + and 0C7h ; Clears previous value + or b + ld (de), a + inc de ; Points to MASK_T or MASK_P accordingly + ld a, (de) + and 0C7h ; Resets bits 3,4,5 + ld (de), a + ret + ; Sets the PAPER color passed in A register in the ATTR_T variable +PAPER_TMP: + ld de, ATTR_T + jp __SET_PAPER + ENDP + pop namespace +#line 10 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/flash.asm" + ; Sets flash flag in ATTR_P permanently +; Parameter: Paper color in A register + push namespace core +FLASH: + ld hl, ATTR_P + PROC + LOCAL IS_TR + LOCAL IS_ZERO +__SET_FLASH: + ; Another entry. This will set the flash flag at location pointer by DE + cp 8 + jr z, IS_TR + ; # Convert to 0/1 or a - sbc hl, bc - exx - jp nc, __MEM_SUBTRACT - ; At this point... - ; less than 4 bytes remains free. So we return this block entirely - ; We must link the previous block with the next to this one - ; (DE) => Pointer to next block - ; (TEMP) => &(previous->next) - pop hl ; Discard current block pointer - push de - ex de, hl ; DE = Previous block pointer; (HL) = Next block pointer + jr z, IS_ZERO + ld a, 0x80 +IS_ZERO: + ld b, a ; Saves the color ld a, (hl) + and 07Fh ; Clears previous value + or b + ld (hl), a inc hl - ld h, (hl) - ld l, a ; HL = (HL) - ex de, hl ; HL = Previous block pointer; DE = Next block pointer -TEMP0: - ld hl, 0 ; Pre-previous block pointer - ld (hl), e - inc hl - ld (hl), d ; LINKED - pop hl ; Returning block. + res 7, (hl) ;Reset bit 7 to disable transparency ret -__MEM_SUBTRACT: - ; At this point we have to store HL value (Length - BC) into (DE - 2) - ex de, hl - dec hl - ld (hl), d - dec hl - ld (hl), e ; Store new block length - add hl, de ; New length + DE => free-block start - pop de ; Remove previous HL off the stack - ld (hl), c ; Store length on its 1st word +IS_TR: ; transparent + inc hl ; Points DE to MASK_T or MASK_P + set 7, (hl) ;Set bit 7 to enable transparency + ret + ; Sets the FLASH flag passed in A register in the ATTR_T variable +FLASH_TMP: + ld hl, ATTR_T + jr __SET_FLASH + ENDP + pop namespace +#line 11 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/bright.asm" + ; Sets bright flag in ATTR_P permanently +; Parameter: Paper color in A register + push namespace core +BRIGHT: + ld hl, ATTR_P + PROC + LOCAL IS_TR + LOCAL IS_ZERO +__SET_BRIGHT: + ; Another entry. This will set the bright flag at location pointer by DE + cp 8 + jr z, IS_TR + ; # Convert to 0/1 + or a + jr z, IS_ZERO + ld a, 0x40 +IS_ZERO: + ld b, a ; Saves the color + ld a, (hl) + and 0BFh ; Clears previous value + or b + ld (hl), a inc hl - ld (hl), b - inc hl ; Return hl + res 6, (hl) ;Reset bit 6 to disable transparency ret +IS_TR: ; transparent + inc hl ; Points DE to MASK_T or MASK_P + set 6, (hl) ;Set bit 6 to enable transparency + ret + ; Sets the BRIGHT flag passed in A register in the ATTR_T variable +BRIGHT_TMP: + ld hl, ATTR_T + jr __SET_BRIGHT ENDP pop namespace -#line 2 "/zxbasic/src/arch/zx48k/library-asm/loadstr.asm" - ; Loads a string (ptr) from HL - ; and duplicates it on dynamic memory again - ; Finally, it returns result pointer in HL +#line 12 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/over.asm" + ; Sets OVER flag in P_FLAG permanently +; Parameter: OVER flag in bit 0 of A register push namespace core -__ILOADSTR: ; This is the indirect pointer entry HL = (HL) - ld a, h - or l - ret z - ld a, (hl) - inc hl - ld h, (hl) - ld l, a -__LOADSTR: ; __FASTCALL__ entry - ld a, h - or l - ret z ; Return if NULL - ld c, (hl) - inc hl - ld b, (hl) - dec hl ; BC = LEN(a$) - inc bc - inc bc ; BC = LEN(a$) + 2 (two bytes for length) - push hl - push bc - call __MEM_ALLOC - pop bc ; Recover length - pop de ; Recover origin - ld a, h - or l - ret z ; Return if NULL (No memory) - ex de, hl ; ldir takes HL as source, DE as destiny, so SWAP HL,DE - push de ; Saves destiny start - ldir ; Copies string (length number included) - pop hl ; Recovers destiny in hl as result +OVER: + PROC + ld c, a ; saves it for later + and 2 + ld hl, FLAGS2 + res 1, (HL) + or (hl) + ld (hl), a + ld a, c ; Recovers previous value + and 1 ; # Convert to 0/1 + add a, a; # Shift left 1 bit for permanent + ld hl, P_FLAG + res 1, (hl) + or (hl) + ld (hl), a ret + ; Sets OVER flag in P_FLAG temporarily +OVER_TMP: + ld c, a ; saves it for later + and 2 ; gets bit 1; clears carry + rra + ld hl, FLAGS2 + res 0, (hl) + or (hl) + ld (hl), a + ld a, c ; Recovers previous value + and 1 + ld hl, P_FLAG + res 0, (hl) + or (hl) + ld (hl), a + jp __SET_ATTR_MODE + ENDP pop namespace -#line 143 "zx48k/lcd3.bas" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -; vim:ts=4:sw=4:et: - ; PRINT command routine - ; Does not print attribute. Use PRINT_STR or PRINT_NUM for that -#line 1 "/zxbasic/src/arch/zx48k/library-asm/sposn.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/sysvars.asm" - ;; ----------------------------------------------------------------------- - ;; ZX Basic System Vars - ;; Some of them will be mapped over Sinclair ROM ones for compatibility - ;; ----------------------------------------------------------------------- - push namespace core -SCREEN_ADDR: DW 16384 ; Screen address (can be pointed to other place to use a screen buffer) -SCREEN_ATTR_ADDR: DW 22528 ; Screen attribute address (ditto.) - ; These are mapped onto ZX Spectrum ROM VARS - CHARS EQU 23606 ; Pointer to ROM/RAM Charset - TVFLAGS EQU 23612 ; TV Flags - UDG EQU 23675 ; Pointer to UDG Charset - COORDS EQU 23677 ; Last PLOT coordinates - FLAGS2 EQU 23681 ; - ECHO_E EQU 23682 ; - DFCC EQU 23684 ; Next screen addr for PRINT - DFCCL EQU 23686 ; Next screen attr for PRINT - S_POSN EQU 23688 - ATTR_P EQU 23693 ; Current Permanent ATTRS set with INK, PAPER, etc commands - ATTR_T EQU 23695 ; temporary ATTRIBUTES - P_FLAG EQU 23697 ; - MEM0 EQU 23698 ; Temporary memory buffer used by ROM chars - SCR_COLS EQU 33 ; Screen with in columns + 1 - SCR_ROWS EQU 24 ; Screen height in rows - SCR_SIZE EQU (SCR_ROWS << 8) + SCR_COLS - pop namespace -#line 2 "/zxbasic/src/arch/zx48k/library-asm/sposn.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/attr.asm" - ; Attribute routines -; vim:ts=4:et:sw: -#line 1 "/zxbasic/src/arch/zx48k/library-asm/in_screen.asm" +#line 13 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/inverse.asm" + ; Sets INVERSE flag in P_FLAG permanently +; Parameter: INVERSE flag in bit 0 of A register push namespace core -__IN_SCREEN: - ; Returns NO carry if current coords (D, E) - ; are OUT of the screen limits +INVERSE: PROC - LOCAL __IN_SCREEN_ERR - ld hl, SCR_SIZE - ld a, e - cp l - jr nc, __IN_SCREEN_ERR ; Do nothing and return if out of range - ld a, d - cp h - ret c ; Return if carry (OK) -__IN_SCREEN_ERR: -__OUT_OF_SCREEN_ERR: - ; Jumps here if out of screen - ld a, ERROR_OutOfScreen - jp __STOP ; Saves error code and exits + and 1 ; # Convert to 0/1 + add a, a; # Shift left 3 bits for permanent + add a, a + add a, a + ld hl, P_FLAG + res 3, (hl) + or (hl) + ld (hl), a + ret + ; Sets INVERSE flag in P_FLAG temporarily +INVERSE_TMP: + and 1 + add a, a + add a, a; # Shift left 2 bits for temporary + ld hl, P_FLAG + res 2, (hl) + or (hl) + ld (hl), a + jp __SET_ATTR_MODE ENDP pop namespace -#line 7 "/zxbasic/src/arch/zx48k/library-asm/attr.asm" +#line 14 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/bold.asm" + ; Sets BOLD flag in P_FLAG permanently +; Parameter: BOLD flag in bit 0 of A register push namespace core -__ATTR_ADDR: - ; calc start address in DE (as (32 * d) + e) - ; Contributed by Santiago Romero at http://www.speccy.org - ld h, 0 ; 7 T-States - ld a, d ; 4 T-States - ld d, h - add a, a ; a * 2 ; 4 T-States - add a, a ; a * 4 ; 4 T-States - ld l, a ; HL = A * 4 ; 4 T-States - add hl, hl ; HL = A * 8 ; 15 T-States - add hl, hl ; HL = A * 16 ; 15 T-States - add hl, hl ; HL = A * 32 ; 15 T-States - add hl, de - ld de, (SCREEN_ATTR_ADDR) ; Adds the screen address - add hl, de - ; Return current screen address in HL +BOLD: + PROC + and 1 + rlca + rlca + rlca + ld hl, FLAGS2 + res 3, (HL) + or (hl) + ld (hl), a ret - ; Sets the attribute at a given screen coordinate (D, E). - ; The attribute is taken from the ATTR_T memory variable - ; Used by PRINT routines -SET_ATTR: - ; Checks for valid coords - call __IN_SCREEN - ret nc - call __ATTR_ADDR -__SET_ATTR: - ; Internal __FASTCALL__ Entry used by printing routines - ; HL contains the address of the ATTR cell to set + ; Sets BOLD flag in P_FLAG temporarily +BOLD_TMP: + and 1 + rlca + rlca + ld hl, FLAGS2 + res 2, (hl) + or (hl) + ld (hl), a + ret + ENDP + pop namespace +#line 15 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/italic.asm" + ; Sets ITALIC flag in P_FLAG permanently +; Parameter: ITALIC flag in bit 0 of A register + push namespace core +ITALIC: PROC -__SET_ATTR2: ; Sets attr from ATTR_T to (HL) which points to the scr address - ld de, (ATTR_T) ; E = ATTR_T, D = MASK_T - ld a, d - and (hl) - ld c, a ; C = current screen color, masked - ld a, d - cpl ; Negate mask - and e ; Mask current attributes - or c ; Mix them - ld (hl), a ; Store result in screen + and 1 + rrca + rrca + rrca + ld hl, FLAGS2 + res 5, (HL) + or (hl) + ld (hl), a + ret + ; Sets ITALIC flag in P_FLAG temporarily +ITALIC_TMP: + and 1 + rrca + rrca + rrca + rrca + ld hl, FLAGS2 + res 4, (hl) + or (hl) + ld (hl), a ret ENDP pop namespace -#line 3 "/zxbasic/src/arch/zx48k/library-asm/sposn.asm" - ; Printing positioning library. +#line 16 "/zxbasic/src/arch/zx48k/library-asm/print.asm" + ; Putting a comment starting with @INIT
+ ; will make the compiler to add a CALL to
+ ; It is useful for initialization routines. push namespace core - ; Loads into DE current ROW, COL print position from S_POSN mem var. -__LOAD_S_POSN: +__PRINT_INIT: ; To be called before program starts (initializes library) PROC - ld de, (S_POSN) + ld hl, __PRINT_START + ld (PRINT_JUMP_STATE), hl + ;; Clears ATTR2 flags (OVER 2, etc) + xor a + ld (FLAGS2), a + LOCAL SET_SCR_ADDR + call __LOAD_S_POSN + jp __SET_SCR_PTR + ;; Receives HL = future value of S_POSN + ;; Stores it at (S_POSN) and refresh screen pointers (ATTR, SCR) +SET_SCR_ADDR: + ld (S_POSN), hl + ex de, hl ld hl, SCR_SIZE or a sbc hl, de ex de, hl + dec e + jp __SET_SCR_PTR +__PRINTCHAR: ; Print character store in accumulator (A register) + ; Modifies H'L', B'C', A'F', D'E', A + LOCAL PO_GR_1 + LOCAL __PRCHAR + LOCAL __PRINT_JUMP + LOCAL __SRCADDR + LOCAL __PRINT_UDG + LOCAL __PRGRAPH + LOCAL __PRINT_START + PRINT_JUMP_STATE EQU __PRINT_JUMP + 2 +__PRINT_JUMP: + exx ; Switch to alternative registers + jp __PRINT_START ; Where to jump. If we print 22 (AT), next two calls jumps to AT1 and AT2 respectively +__PRINT_START: +__PRINT_CHR: + cp ' ' + jr c, __PRINT_SPECIAL ; Characters below ' ' are special ones + ex af, af' ; Saves a value (char to print) for later + ld hl, (S_POSN) + dec l + jr nz, 1f + ld l, SCR_COLS - 1 + dec h + jr nz, 2f + inc h + push hl + call __SCROLL_SCR + pop hl +#line 92 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +2: + call SET_SCR_ADDR + jr 4f +1: + ld (S_POSN), hl +4: + ex af, af' + cp 80h ; Is it a "normal" (printable) char + jr c, __SRCADDR + cp 90h ; Is it an UDG? + jr nc, __PRINT_UDG + ; Print an 8 bit pattern (80h to 8Fh) + ld b, a + call PO_GR_1 ; This ROM routine will generate the bit pattern at MEM0 + ld hl, MEM0 + jp __PRGRAPH + PO_GR_1 EQU 0B38h +__PRINT_UDG: + sub 90h ; Sub ASC code + ld bc, (UDG) + jr __PRGRAPH0 + __SOURCEADDR EQU (__SRCADDR + 1) ; Address of the pointer to chars source +__SRCADDR: + ld bc, (CHARS) +__PRGRAPH0: + add a, a ; A = a * 2 (since a < 80h) ; Thanks to Metalbrain at http://foro.speccy.org + ld l, a + ld h, 0 ; HL = a * 2 (accumulator) + add hl, hl + add hl, hl ; HL = a * 8 + add hl, bc ; HL = CHARS address +__PRGRAPH: + ex de, hl ; HL = Write Address, DE = CHARS address + bit 2, (iy + $47) + call nz, __BOLD +#line 139 "/zxbasic/src/arch/zx48k/library-asm/print.asm" + bit 4, (iy + $47) + call nz, __ITALIC +#line 144 "/zxbasic/src/arch/zx48k/library-asm/print.asm" + ld hl, (DFCC) + push hl + ld b, 8 ; 8 bytes per char +__PRCHAR: + ld a, (de) ; DE *must* be source, and HL destiny +PRINT_MODE: ; Which operation is used to write on the screen + ; Set it with: + ; LD A, + ; LD (PRINT_MODE), A + ; + ; Available operations: + ; NORMAL : 0h --> NOP ; OVER 0 + ; XOR : AEh --> XOR (HL) ; OVER 1 + ; OR : B6h --> OR (HL) ; PUTSPRITE + ; AND : A6h --> AND (HL) ; PUTMASK + nop ; Set to one of the values above +INVERSE_MODE: ; 00 -> NOP -> INVERSE 0 + nop ; 2F -> CPL -> INVERSE 1 + ld (hl), a + inc de + inc h ; Next line + djnz __PRCHAR + pop hl + inc hl + ld (DFCC), hl + ld hl, (DFCCL) ; current ATTR Pos + inc hl + ld (DFCCL), hl + dec hl + call __SET_ATTR + exx ret - ENDP - ; Saves ROW, COL from DE into S_POSN mem var. -__SAVE_S_POSN: - PROC - ld hl, SCR_SIZE - or a - sbc hl, de - ld (S_POSN), hl ; saves it again -__SET_SCR_PTR: ;; Fast + ; ------------- SPECIAL CHARS (< 32) ----------------- +__PRINT_SPECIAL: ; Jumps here if it is a special char + ld hl, __PRINT_TABLE + jp JUMP_HL_PLUS_2A +PRINT_EOL: ; Called WHENEVER there is no ";" at end of PRINT sentence + exx +__PRINT_0Dh: ; Called WHEN printing CHR$(13) + ld hl, (S_POSN) + dec l + jr nz, 1f + dec h + jr nz, 1f + inc h + push hl + call __SCROLL_SCR + pop hl +#line 209 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +1: + ld l, 1 +__PRINT_EOL_END: + call SET_SCR_ADDR + exx + ret +__PRINT_COM: + exx + push hl push de - call __ATTR_ADDR - ld (DFCCL), hl + push bc + call PRINT_COMMA + pop bc pop de - ld a, d - ld c, a ; Saves it for later - and 0F8h ; Masks 3 lower bit ; zy - ld d, a - ld a, c ; Recovers it - and 07h ; MOD 7 ; y1 - rrca - rrca - rrca - or e - ld e, a - ld hl, (SCREEN_ADDR) - add hl, de ; HL = Screen address + DE - ld (DFCC), hl + pop hl ret - ENDP - pop namespace -#line 6 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/table_jump.asm" - push namespace core -JUMP_HL_PLUS_2A: ; Does JP (HL + A*2) Modifies DE. Modifies A - add a, a -JUMP_HL_PLUS_A: ; Does JP (HL + A) Modifies DE - ld e, a - ld d, 0 -JUMP_HL_PLUS_DE: ; Does JP (HL + DE) - add hl, de - ld e, (hl) - inc hl - ld d, (hl) - ex de, hl -CALL_HL: - jp (hl) - pop namespace -#line 8 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/ink.asm" - ; Sets ink color in ATTR_P permanently -; Parameter: Paper color in A register - push namespace core -INK: - PROC - LOCAL __SET_INK - LOCAL __SET_INK2 - ld de, ATTR_P -__SET_INK: - cp 8 - jr nz, __SET_INK2 - inc de ; Points DE to MASK_T or MASK_P - ld a, (de) - or 7 ; Set bits 0,1,2 to enable transparency - ld (de), a +__PRINT_TAB: + ld hl, __PRINT_TAB1 + jr __PRINT_SET_STATE +__PRINT_TAB1: + ld (MEM0), a + ld hl, __PRINT_TAB2 + jr __PRINT_SET_STATE +__PRINT_TAB2: + ld a, (MEM0) ; Load tab code (ignore the current one) + ld hl, __PRINT_START + ld (PRINT_JUMP_STATE), hl + exx + push hl + push bc + push de + call PRINT_TAB + pop de + pop bc + pop hl ret -__SET_INK2: - ; Another entry. This will set the ink color at location pointer by DE - and 7 ; # Gets color mod 8 - ld b, a ; Saves the color - ld a, (de) - and 0F8h ; Clears previous value - or b - ld (de), a - inc de ; Points DE to MASK_T or MASK_P - ld a, (de) - and 0F8h ; Reset bits 0,1,2 sign to disable transparency - ld (de), a ; Store new attr +__PRINT_AT: + ld hl, __PRINT_AT1 + jr __PRINT_SET_STATE +__PRINT_NOP: +__PRINT_RESTART: + ld hl, __PRINT_START +__PRINT_SET_STATE: + ld (PRINT_JUMP_STATE), hl ; Saves next entry call + exx + ret +__PRINT_AT1: ; Jumps here if waiting for 1st parameter + ld hl, (S_POSN) + ld h, a + ld a, SCR_ROWS + sub h + ld (S_POSN + 1), a + ld hl, __PRINT_AT2 + jr __PRINT_SET_STATE +__PRINT_AT2: + call __LOAD_S_POSN + ld e, a + call __SAVE_S_POSN + jr __PRINT_RESTART +__PRINT_DEL: + call __LOAD_S_POSN ; Gets current screen position + dec e + ld a, -1 + cp e + jr nz, 3f + ld e, SCR_COLS - 2 + dec d + cp d + jr nz, 3f + ld d, SCR_ROWS - 1 +3: + call __SAVE_S_POSN + exx ret - ; Sets the INK color passed in A register in the ATTR_T variable -INK_TMP: - ld de, ATTR_T - jp __SET_INK - ENDP - pop namespace -#line 9 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/paper.asm" - ; Sets paper color in ATTR_P permanently -; Parameter: Paper color in A register - push namespace core -PAPER: - PROC - LOCAL __SET_PAPER - LOCAL __SET_PAPER2 - ld de, ATTR_P -__SET_PAPER: - cp 8 - jr nz, __SET_PAPER2 - inc de +__PRINT_INK: + ld hl, __PRINT_INK2 + jr __PRINT_SET_STATE +__PRINT_INK2: + call INK_TMP + jr __PRINT_RESTART +__PRINT_PAP: + ld hl, __PRINT_PAP2 + jr __PRINT_SET_STATE +__PRINT_PAP2: + call PAPER_TMP + jr __PRINT_RESTART +__PRINT_FLA: + ld hl, __PRINT_FLA2 + jr __PRINT_SET_STATE +__PRINT_FLA2: + call FLASH_TMP + jr __PRINT_RESTART +__PRINT_BRI: + ld hl, __PRINT_BRI2 + jr __PRINT_SET_STATE +__PRINT_BRI2: + call BRIGHT_TMP + jr __PRINT_RESTART +__PRINT_INV: + ld hl, __PRINT_INV2 + jr __PRINT_SET_STATE +__PRINT_INV2: + call INVERSE_TMP + jr __PRINT_RESTART +__PRINT_OVR: + ld hl, __PRINT_OVR2 + jr __PRINT_SET_STATE +__PRINT_OVR2: + call OVER_TMP + jr __PRINT_RESTART +__PRINT_BOLD: + ld hl, __PRINT_BOLD2 + jp __PRINT_SET_STATE +__PRINT_BOLD2: + call BOLD_TMP + jp __PRINT_RESTART +#line 353 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +__PRINT_ITA: + ld hl, __PRINT_ITA2 + jp __PRINT_SET_STATE +__PRINT_ITA2: + call ITALIC_TMP + jp __PRINT_RESTART +#line 363 "/zxbasic/src/arch/zx48k/library-asm/print.asm" + LOCAL __BOLD +__BOLD: + push hl + ld hl, MEM0 + ld b, 8 +1: ld a, (de) - or 038h - ld (de), a - ret - ; Another entry. This will set the paper color at location pointer by DE -__SET_PAPER2: - and 7 ; # Remove - rlca + ld c, a rlca - rlca ; a *= 8 - ld b, a ; Saves the color - ld a, (de) - and 0C7h ; Clears previous value - or b - ld (de), a - inc de ; Points to MASK_T or MASK_P accordingly - ld a, (de) - and 0C7h ; Resets bits 3,4,5 - ld (de), a - ret - ; Sets the PAPER color passed in A register in the ATTR_T variable -PAPER_TMP: - ld de, ATTR_T - jp __SET_PAPER - ENDP - pop namespace -#line 10 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/flash.asm" - ; Sets flash flag in ATTR_P permanently -; Parameter: Paper color in A register - push namespace core -FLASH: - ld hl, ATTR_P - PROC - LOCAL IS_TR - LOCAL IS_ZERO -__SET_FLASH: - ; Another entry. This will set the flash flag at location pointer by DE - cp 8 - jr z, IS_TR - ; # Convert to 0/1 - or a - jr z, IS_ZERO - ld a, 0x80 -IS_ZERO: - ld b, a ; Saves the color - ld a, (hl) - and 07Fh ; Clears previous value - or b + or c ld (hl), a inc hl - res 7, (hl) ;Reset bit 7 to disable transparency - ret -IS_TR: ; transparent - inc hl ; Points DE to MASK_T or MASK_P - set 7, (hl) ;Set bit 7 to enable transparency + inc de + djnz 1b + pop hl + ld de, MEM0 ret - ; Sets the FLASH flag passed in A register in the ATTR_T variable -FLASH_TMP: - ld hl, ATTR_T - jr __SET_FLASH - ENDP - pop namespace -#line 11 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/bright.asm" - ; Sets bright flag in ATTR_P permanently -; Parameter: Paper color in A register - push namespace core -BRIGHT: - ld hl, ATTR_P - PROC - LOCAL IS_TR - LOCAL IS_ZERO -__SET_BRIGHT: - ; Another entry. This will set the bright flag at location pointer by DE - cp 8 - jr z, IS_TR - ; # Convert to 0/1 - or a - jr z, IS_ZERO - ld a, 0x40 -IS_ZERO: - ld b, a ; Saves the color - ld a, (hl) - and 0BFh ; Clears previous value - or b - ld (hl), a +#line 384 "/zxbasic/src/arch/zx48k/library-asm/print.asm" + LOCAL __ITALIC +__ITALIC: + push hl + ld hl, MEM0 + ex de, hl + ld bc, 8 + ldir + ld hl, MEM0 + srl (hl) inc hl - res 6, (hl) ;Reset bit 6 to disable transparency + srl (hl) + inc hl + srl (hl) + inc hl + inc hl + inc hl + sla (hl) + inc hl + sla (hl) + inc hl + sla (hl) + pop hl + ld de, MEM0 ret -IS_TR: ; transparent - inc hl ; Points DE to MASK_T or MASK_P - set 6, (hl) ;Set bit 6 to enable transparency +#line 412 "/zxbasic/src/arch/zx48k/library-asm/print.asm" + LOCAL __SCROLL_SCR +#line 486 "/zxbasic/src/arch/zx48k/library-asm/print.asm" + __SCROLL_SCR EQU 0DFEh ; Use ROM SCROLL +#line 488 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 489 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +PRINT_COMMA: + call __LOAD_S_POSN + ld a, e + and 16 + add a, 16 +PRINT_TAB: + ; Tabulates the number of spaces in A register + ; If the current cursor position is already A, does nothing + PROC + LOCAL LOOP + call __LOAD_S_POSN ; e = current row + sub e + and 31 + ret z + ld b, a +LOOP: + ld a, ' ' + call __PRINTCHAR + djnz LOOP ret - ; Sets the BRIGHT flag passed in A register in the ATTR_T variable -BRIGHT_TMP: - ld hl, ATTR_T - jr __SET_BRIGHT + ENDP +PRINT_AT: ; Changes cursor to ROW, COL + ; COL in A register + ; ROW in stack + pop hl ; Ret address + ex (sp), hl ; callee H = ROW + ld l, a + ex de, hl + call __IN_SCREEN + ret nc ; Return if out of screen + jp __SAVE_S_POSN + LOCAL __PRINT_COM + LOCAL __PRINT_AT1 + LOCAL __PRINT_AT2 + LOCAL __PRINT_BOLD + LOCAL __PRINT_ITA + LOCAL __PRINT_INK + LOCAL __PRINT_PAP + LOCAL __PRINT_SET_STATE + LOCAL __PRINT_TABLE + LOCAL __PRINT_TAB, __PRINT_TAB1, __PRINT_TAB2 + LOCAL __PRINT_ITA2 +#line 545 "/zxbasic/src/arch/zx48k/library-asm/print.asm" + LOCAL __PRINT_BOLD2 +#line 551 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +__PRINT_TABLE: ; Jump table for 0 .. 22 codes + DW __PRINT_NOP ; 0 + DW __PRINT_NOP ; 1 + DW __PRINT_NOP ; 2 + DW __PRINT_NOP ; 3 + DW __PRINT_NOP ; 4 + DW __PRINT_NOP ; 5 + DW __PRINT_COM ; 6 COMMA + DW __PRINT_NOP ; 7 + DW __PRINT_DEL ; 8 DEL + DW __PRINT_NOP ; 9 + DW __PRINT_NOP ; 10 + DW __PRINT_NOP ; 11 + DW __PRINT_NOP ; 12 + DW __PRINT_0Dh ; 13 + DW __PRINT_BOLD ; 14 + DW __PRINT_ITA ; 15 + DW __PRINT_INK ; 16 + DW __PRINT_PAP ; 17 + DW __PRINT_FLA ; 18 + DW __PRINT_BRI ; 19 + DW __PRINT_INV ; 20 + DW __PRINT_OVR ; 21 + DW __PRINT_AT ; 22 AT + DW __PRINT_TAB ; 23 TAB ENDP pop namespace -#line 12 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/over.asm" - ; Sets OVER flag in P_FLAG permanently -; Parameter: OVER flag in bit 0 of A register -#line 1 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" +#line 3 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" #line 4 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" push namespace core COPY_ATTR: @@ -1189,517 +1137,569 @@ __REFRESH_TMP: ret ENDP pop namespace -#line 4 "/zxbasic/src/arch/zx48k/library-asm/over.asm" - push namespace core -OVER: - PROC - ld c, a ; saves it for later - and 2 - ld hl, FLAGS2 - res 1, (HL) - or (hl) - ld (hl), a - ld a, c ; Recovers previous value - and 1 ; # Convert to 0/1 - add a, a; # Shift left 1 bit for permanent - ld hl, P_FLAG - res 1, (hl) - or (hl) - ld (hl), a - ret - ; Sets OVER flag in P_FLAG temporarily -OVER_TMP: - ld c, a ; saves it for later - and 2 ; gets bit 1; clears carry - rra - ld hl, FLAGS2 - res 0, (hl) - or (hl) - ld (hl), a - ld a, c ; Recovers previous value - and 1 - ld hl, P_FLAG - res 0, (hl) - or (hl) - ld (hl), a - jp __SET_ATTR_MODE - ENDP - pop namespace -#line 13 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/inverse.asm" - ; Sets INVERSE flag in P_FLAG permanently -; Parameter: INVERSE flag in bit 0 of A register - push namespace core -INVERSE: - PROC - and 1 ; # Convert to 0/1 - add a, a; # Shift left 3 bits for permanent - add a, a - add a, a - ld hl, P_FLAG - res 3, (hl) - or (hl) - ld (hl), a - ret - ; Sets INVERSE flag in P_FLAG temporarily -INVERSE_TMP: - and 1 - add a, a - add a, a; # Shift left 2 bits for temporary - ld hl, P_FLAG - res 2, (hl) - or (hl) - ld (hl), a - jp __SET_ATTR_MODE - ENDP - pop namespace -#line 14 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/bold.asm" - ; Sets BOLD flag in P_FLAG permanently -; Parameter: BOLD flag in bit 0 of A register - push namespace core -BOLD: - PROC - and 1 - rlca - rlca - rlca - ld hl, FLAGS2 - res 3, (HL) - or (hl) - ld (hl), a - ret - ; Sets BOLD flag in P_FLAG temporarily -BOLD_TMP: - and 1 - rlca - rlca - ld hl, FLAGS2 - res 2, (hl) - or (hl) - ld (hl), a - ret - ENDP - pop namespace -#line 15 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/italic.asm" - ; Sets ITALIC flag in P_FLAG permanently -; Parameter: ITALIC flag in bit 0 of A register +#line 142 "zx48k/lcd3.bas" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/free.asm" +; vim: ts=4:et:sw=4: + ; Copyleft (K) by Jose M. Rodriguez de la Rosa + ; (a.k.a. Boriel) +; http://www.boriel.com + ; + ; This ASM library is licensed under the BSD license + ; you can use it for any purpose (even for commercial + ; closed source programs). + ; + ; Please read the BSD license on the internet + ; ----- IMPLEMENTATION NOTES ------ + ; The heap is implemented as a linked list of free blocks. +; Each free block contains this info: + ; + ; +----------------+ <-- HEAP START + ; | Size (2 bytes) | + ; | 0 | <-- Size = 0 => DUMMY HEADER BLOCK + ; +----------------+ + ; | Next (2 bytes) |---+ + ; +----------------+ <-+ + ; | Size (2 bytes) | + ; +----------------+ + ; | Next (2 bytes) |---+ + ; +----------------+ | + ; | | | <-- If Size > 4, then this contains (size - 4) bytes + ; | (0 if Size = 4)| | + ; +----------------+ <-+ + ; | Size (2 bytes) | + ; +----------------+ + ; | Next (2 bytes) |---+ + ; +----------------+ | + ; | | | + ; | (0 if Size = 4)| | + ; +----------------+ | + ; | <-- This zone is in use (Already allocated) + ; +----------------+ <-+ + ; | Size (2 bytes) | + ; +----------------+ + ; | Next (2 bytes) |---+ + ; +----------------+ | + ; | | | + ; | (0 if Size = 4)| | + ; +----------------+ <-+ + ; | Next (2 bytes) |--> NULL => END OF LIST + ; | 0 = NULL | + ; +----------------+ + ; | | + ; | (0 if Size = 4)| + ; +----------------+ + ; When a block is FREED, the previous and next pointers are examined to see + ; if we can defragment the heap. If the block to be breed is just next to the + ; previous, or to the next (or both) they will be converted into a single + ; block (so defragmented). + ; MEMORY MANAGER + ; + ; This library must be initialized calling __MEM_INIT with + ; HL = BLOCK Start & DE = Length. + ; An init directive is useful for initialization routines. + ; They will be added automatically if needed. +#line 1 "/zxbasic/src/arch/zx48k/library-asm/heapinit.asm" +; vim: ts=4:et:sw=4: + ; Copyleft (K) by Jose M. Rodriguez de la Rosa + ; (a.k.a. Boriel) +; http://www.boriel.com + ; + ; This ASM library is licensed under the BSD license + ; you can use it for any purpose (even for commercial + ; closed source programs). + ; + ; Please read the BSD license on the internet + ; ----- IMPLEMENTATION NOTES ------ + ; The heap is implemented as a linked list of free blocks. +; Each free block contains this info: + ; + ; +----------------+ <-- HEAP START + ; | Size (2 bytes) | + ; | 0 | <-- Size = 0 => DUMMY HEADER BLOCK + ; +----------------+ + ; | Next (2 bytes) |---+ + ; +----------------+ <-+ + ; | Size (2 bytes) | + ; +----------------+ + ; | Next (2 bytes) |---+ + ; +----------------+ | + ; | | | <-- If Size > 4, then this contains (size - 4) bytes + ; | (0 if Size = 4)| | + ; +----------------+ <-+ + ; | Size (2 bytes) | + ; +----------------+ + ; | Next (2 bytes) |---+ + ; +----------------+ | + ; | | | + ; | (0 if Size = 4)| | + ; +----------------+ | + ; | <-- This zone is in use (Already allocated) + ; +----------------+ <-+ + ; | Size (2 bytes) | + ; +----------------+ + ; | Next (2 bytes) |---+ + ; +----------------+ | + ; | | | + ; | (0 if Size = 4)| | + ; +----------------+ <-+ + ; | Next (2 bytes) |--> NULL => END OF LIST + ; | 0 = NULL | + ; +----------------+ + ; | | + ; | (0 if Size = 4)| + ; +----------------+ + ; When a block is FREED, the previous and next pointers are examined to see + ; if we can defragment the heap. If the block to be breed is just next to the + ; previous, or to the next (or both) they will be converted into a single + ; block (so defragmented). + ; MEMORY MANAGER + ; + ; This library must be initialized calling __MEM_INIT with + ; HL = BLOCK Start & DE = Length. + ; An init directive is useful for initialization routines. + ; They will be added automatically if needed. + ; --------------------------------------------------------------------- + ; __MEM_INIT must be called to initalize this library with the + ; standard parameters + ; --------------------------------------------------------------------- push namespace core -ITALIC: - PROC - and 1 - rrca - rrca - rrca - ld hl, FLAGS2 - res 5, (HL) - or (hl) +__MEM_INIT: ; Initializes the library using (RAMTOP) as start, and + ld hl, ZXBASIC_MEM_HEAP ; Change this with other address of heap start + ld de, ZXBASIC_HEAP_SIZE ; Change this with your size + ; --------------------------------------------------------------------- + ; __MEM_INIT2 initalizes this library +; Parameters: +; HL : Memory address of 1st byte of the memory heap +; DE : Length in bytes of the Memory Heap + ; --------------------------------------------------------------------- +__MEM_INIT2: + ; HL as TOP + PROC + dec de + dec de + dec de + dec de ; DE = length - 4; HL = start + ; This is done, because we require 4 bytes for the empty dummy-header block + xor a ld (hl), a - ret - ; Sets ITALIC flag in P_FLAG temporarily -ITALIC_TMP: - and 1 - rrca - rrca - rrca - rrca - ld hl, FLAGS2 - res 4, (hl) - or (hl) + inc hl + ld (hl), a ; First "free" block is a header: size=0, Pointer=&(Block) + 4 + inc hl + ld b, h + ld c, l + inc bc + inc bc ; BC = starts of next block + ld (hl), c + inc hl + ld (hl), b + inc hl ; Pointer to next block + ld (hl), e + inc hl + ld (hl), d + inc hl ; Block size (should be length - 4 at start); This block contains all the available memory + ld (hl), a ; NULL (0000h) ; No more blocks (a list with a single block) + inc hl ld (hl), a + ld a, 201 + ld (__MEM_INIT), a; "Pokes" with a RET so ensure this routine is not called again ret ENDP pop namespace -#line 16 "/zxbasic/src/arch/zx48k/library-asm/print.asm" - ; Putting a comment starting with @INIT
- ; will make the compiler to add a CALL to
- ; It is useful for initialization routines. +#line 69 "/zxbasic/src/arch/zx48k/library-asm/free.asm" + ; --------------------------------------------------------------------- + ; MEM_FREE + ; Frees a block of memory + ; +; Parameters: + ; HL = Pointer to the block to be freed. If HL is NULL (0) nothing + ; is done + ; --------------------------------------------------------------------- push namespace core -__PRINT_INIT: ; To be called before program starts (initializes library) +MEM_FREE: +__MEM_FREE: ; Frees the block pointed by HL + ; HL DE BC & AF modified PROC - ld hl, __PRINT_START - ld (PRINT_JUMP_STATE), hl - ;; Clears ATTR2 flags (OVER 2, etc) - xor a - ld (FLAGS2), a - LOCAL SET_SCR_ADDR - call __LOAD_S_POSN - jp __SET_SCR_PTR - ;; Receives HL = future value of S_POSN - ;; Stores it at (S_POSN) and refresh screen pointers (ATTR, SCR) -SET_SCR_ADDR: - ld (S_POSN), hl - ex de, hl - ld hl, SCR_SIZE - or a - sbc hl, de + LOCAL __MEM_LOOP2 + LOCAL __MEM_LINK_PREV + LOCAL __MEM_JOIN_TEST + LOCAL __MEM_BLOCK_JOIN + ld a, h + or l + ret z ; Return if NULL pointer + dec hl + dec hl + ld b, h + ld c, l ; BC = Block pointer + ld hl, ZXBASIC_MEM_HEAP ; This label point to the heap start +__MEM_LOOP2: + inc hl + inc hl ; Next block ptr + ld e, (hl) + inc hl + ld d, (hl) ; Block next ptr + ex de, hl ; DE = &(block->next); HL = block->next + ld a, h ; HL == NULL? + or l + jp z, __MEM_LINK_PREV; if so, link with previous + or a ; Clear carry flag + sbc hl, bc ; Carry if BC > HL => This block if before + add hl, bc ; Restores HL, preserving Carry flag + jp c, __MEM_LOOP2 ; This block is before. Keep searching PASS the block + ;------ At this point current HL is PAST BC, so we must link (DE) with BC, and HL in BC->next +__MEM_LINK_PREV: ; Link (DE) with BC, and BC->next with HL ex de, hl - dec e - jp __SET_SCR_PTR -__PRINTCHAR: ; Print character store in accumulator (A register) - ; Modifies H'L', B'C', A'F', D'E', A - LOCAL PO_GR_1 - LOCAL __PRCHAR - LOCAL __PRINT_JUMP - LOCAL __SRCADDR - LOCAL __PRINT_UDG - LOCAL __PRGRAPH - LOCAL __PRINT_START - PRINT_JUMP_STATE EQU __PRINT_JUMP + 2 -__PRINT_JUMP: - exx ; Switch to alternative registers - jp __PRINT_START ; Where to jump. If we print 22 (AT), next two calls jumps to AT1 and AT2 respectively -__PRINT_START: -__PRINT_CHR: - cp ' ' - jr c, __PRINT_SPECIAL ; Characters below ' ' are special ones - ex af, af' ; Saves a value (char to print) for later - ld hl, (S_POSN) - dec l - jr nz, 1f - ld l, SCR_COLS - 1 - dec h - jr nz, 2f - inc h push hl - call __SCROLL_SCR + dec hl + ld (hl), c + inc hl + ld (hl), b ; (DE) <- BC + ld h, b ; HL <- BC (Free block ptr) + ld l, c + inc hl ; Skip block length (2 bytes) + inc hl + ld (hl), e ; Block->next = DE + inc hl + ld (hl), d + ; --- LINKED ; HL = &(BC->next) + 2 + call __MEM_JOIN_TEST pop hl -#line 92 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -2: - call SET_SCR_ADDR - jr 4f -1: - ld (S_POSN), hl -4: - ex af, af' - cp 80h ; Is it a "normal" (printable) char - jr c, __SRCADDR - cp 90h ; Is it an UDG? - jr nc, __PRINT_UDG - ; Print an 8 bit pattern (80h to 8Fh) - ld b, a - call PO_GR_1 ; This ROM routine will generate the bit pattern at MEM0 - ld hl, MEM0 - jp __PRGRAPH - PO_GR_1 EQU 0B38h -__PRINT_UDG: - sub 90h ; Sub ASC code - ld bc, (UDG) - jr __PRGRAPH0 - __SOURCEADDR EQU (__SRCADDR + 1) ; Address of the pointer to chars source -__SRCADDR: - ld bc, (CHARS) -__PRGRAPH0: - add a, a ; A = a * 2 (since a < 80h) ; Thanks to Metalbrain at http://foro.speccy.org +__MEM_JOIN_TEST: ; Checks for fragmented contiguous blocks and joins them + ; hl = Ptr to current block + 2 + ld d, (hl) + dec hl + ld e, (hl) + dec hl + ld b, (hl) ; Loads block length into BC + dec hl + ld c, (hl) ; + push hl ; Saves it for later + add hl, bc ; Adds its length. If HL == DE now, it must be joined + or a + sbc hl, de ; If Z, then HL == DE => We must join + pop hl + ret nz +__MEM_BLOCK_JOIN: ; Joins current block (pointed by HL) with next one (pointed by DE). HL->length already in BC + push hl ; Saves it for later + ex de, hl + ld e, (hl) ; DE -> block->next->length + inc hl + ld d, (hl) + inc hl + ex de, hl ; DE = &(block->next) + add hl, bc ; HL = Total Length + ld b, h + ld c, l ; BC = Total Length + ex de, hl + ld e, (hl) + inc hl + ld d, (hl) ; DE = block->next + pop hl ; Recovers Pointer to block + ld (hl), c + inc hl + ld (hl), b ; Length Saved + inc hl + ld (hl), e + inc hl + ld (hl), d ; Next saved + ret + ENDP + pop namespace +#line 143 "zx48k/lcd3.bas" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/ftou32reg.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/neg32.asm" + push namespace core +__ABS32: + bit 7, d + ret z +__NEG32: ; Negates DEHL (Two's complement) + ld a, l + cpl ld l, a - ld h, 0 ; HL = a * 2 (accumulator) - add hl, hl - add hl, hl ; HL = a * 8 - add hl, bc ; HL = CHARS address -__PRGRAPH: - ex de, hl ; HL = Write Address, DE = CHARS address - bit 2, (iy + $47) - call nz, __BOLD -#line 139 "/zxbasic/src/arch/zx48k/library-asm/print.asm" - bit 4, (iy + $47) - call nz, __ITALIC -#line 144 "/zxbasic/src/arch/zx48k/library-asm/print.asm" - ld hl, (DFCC) - push hl - ld b, 8 ; 8 bytes per char -__PRCHAR: - ld a, (de) ; DE *must* be source, and HL destiny -PRINT_MODE: ; Which operation is used to write on the screen - ; Set it with: - ; LD A, - ; LD (PRINT_MODE), A - ; - ; Available operations: - ; NORMAL : 0h --> NOP ; OVER 0 - ; XOR : AEh --> XOR (HL) ; OVER 1 - ; OR : B6h --> OR (HL) ; PUTSPRITE - ; AND : A6h --> AND (HL) ; PUTMASK - nop ; Set to one of the values above -INVERSE_MODE: ; 00 -> NOP -> INVERSE 0 - nop ; 2F -> CPL -> INVERSE 1 - ld (hl), a + ld a, h + cpl + ld h, a + ld a, e + cpl + ld e, a + ld a, d + cpl + ld d, a + inc l + ret nz + inc h + ret nz inc de - inc h ; Next line - djnz __PRCHAR - pop hl - inc hl - ld (DFCC), hl - ld hl, (DFCCL) ; current ATTR Pos - push hl - call __SET_ATTR - pop hl - inc hl - ld (DFCCL),hl - exx ret - ; ------------- SPECIAL CHARS (< 32) ----------------- -__PRINT_SPECIAL: ; Jumps here if it is a special char - ld hl, __PRINT_TABLE - jp JUMP_HL_PLUS_2A -PRINT_EOL: ; Called WHENEVER there is no ";" at end of PRINT sentence - exx -__PRINT_0Dh: ; Called WHEN printing CHR$(13) - ld hl, (S_POSN) - dec l - jr nz, 1f - dec h - jr nz, 1f - inc h - push hl - call __SCROLL_SCR - pop hl -#line 210 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -1: - ld l, 1 -__PRINT_EOL_END: - call SET_SCR_ADDR - exx + pop namespace +#line 2 "/zxbasic/src/arch/zx48k/library-asm/ftou32reg.asm" + push namespace core +__FTOU32REG: ; Converts a Float to (un)signed 32 bit integer (NOTE: It's ALWAYS 32 bit signed) + ; Input FP number in A EDCB (A exponent, EDCB mantissa) + ; Output: DEHL 32 bit number (signed) + PROC + LOCAL __IS_FLOAT + LOCAL __NEGATE + or a + jr nz, __IS_FLOAT + ; Here if it is a ZX ROM Integer + ld h, c + ld l, d + ld d, e ret -__PRINT_COM: - exx - push hl +__IS_FLOAT: ; Jumps here if it is a true floating point number + ld h, e + push hl ; Stores it for later (Contains Sign in H) push de push bc - call PRINT_COMMA - pop bc - pop de - pop hl - ret -__PRINT_TAB: - ld hl, __PRINT_TAB1 - jr __PRINT_SET_STATE -__PRINT_TAB1: - ld (MEM0), a - ld hl, __PRINT_TAB2 - jr __PRINT_SET_STATE -__PRINT_TAB2: - ld a, (MEM0) ; Load tab code (ignore the current one) - ld hl, __PRINT_START - ld (PRINT_JUMP_STATE), hl exx - push hl - push bc - push de - call PRINT_TAB - pop de - pop bc - pop hl - ret -__PRINT_AT: - ld hl, __PRINT_AT1 - jr __PRINT_SET_STATE -__PRINT_NOP: -__PRINT_RESTART: - ld hl, __PRINT_START -__PRINT_SET_STATE: - ld (PRINT_JUMP_STATE), hl ; Saves next entry call + pop de ; Loads mantissa into C'B' E'D' + pop bc ; + set 7, c ; Highest mantissa bit is always 1 exx + ld hl, 0 ; DEHL = 0 + ld d, h + ld e, l + ;ld a, c ; Get exponent + sub 128 ; Exponent -= 128 + jr z, __FTOU32REG_END ; If it was <= 128, we are done (Integers must be > 128) + jr c, __FTOU32REG_END ; It was decimal (0.xxx). We are done (return 0) + ld b, a ; Loop counter = exponent - 128 +__FTOU32REG_LOOP: + exx ; Shift C'B' E'D' << 1, output bit stays in Carry + sla d + rl e + rl b + rl c + exx ; Shift DEHL << 1, inserting the carry on the right + rl l + rl h + rl e + rl d + djnz __FTOU32REG_LOOP +__FTOU32REG_END: + pop af ; Take the sign bit + or a ; Sets SGN bit to 1 if negative + jp m, __NEGATE ; Negates DEHL ret -__PRINT_AT1: ; Jumps here if waiting for 1st parameter - ld hl, (S_POSN) - ld h, a - ld a, SCR_ROWS - sub h - ld (S_POSN + 1), a - ld hl, __PRINT_AT2 - jr __PRINT_SET_STATE -__PRINT_AT2: - call __LOAD_S_POSN - ld e, a - call __SAVE_S_POSN - jr __PRINT_RESTART -__PRINT_DEL: - call __LOAD_S_POSN ; Gets current screen position - dec e - ld a, -1 - cp e - jr nz, 3f - ld e, SCR_COLS - 2 - dec d - cp d - jr nz, 3f - ld d, SCR_ROWS - 1 -3: - call __SAVE_S_POSN +__NEGATE: exx - ret -__PRINT_INK: - ld hl, __PRINT_INK2 - jr __PRINT_SET_STATE -__PRINT_INK2: - call INK_TMP - jr __PRINT_RESTART -__PRINT_PAP: - ld hl, __PRINT_PAP2 - jr __PRINT_SET_STATE -__PRINT_PAP2: - call PAPER_TMP - jr __PRINT_RESTART -__PRINT_FLA: - ld hl, __PRINT_FLA2 - jr __PRINT_SET_STATE -__PRINT_FLA2: - call FLASH_TMP - jr __PRINT_RESTART -__PRINT_BRI: - ld hl, __PRINT_BRI2 - jr __PRINT_SET_STATE -__PRINT_BRI2: - call BRIGHT_TMP - jr __PRINT_RESTART -__PRINT_INV: - ld hl, __PRINT_INV2 - jr __PRINT_SET_STATE -__PRINT_INV2: - call INVERSE_TMP - jr __PRINT_RESTART -__PRINT_OVR: - ld hl, __PRINT_OVR2 - jr __PRINT_SET_STATE -__PRINT_OVR2: - call OVER_TMP - jr __PRINT_RESTART -__PRINT_BOLD: - ld hl, __PRINT_BOLD2 - jp __PRINT_SET_STATE -__PRINT_BOLD2: - call BOLD_TMP - jp __PRINT_RESTART -#line 354 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -__PRINT_ITA: - ld hl, __PRINT_ITA2 - jp __PRINT_SET_STATE -__PRINT_ITA2: - call ITALIC_TMP - jp __PRINT_RESTART -#line 364 "/zxbasic/src/arch/zx48k/library-asm/print.asm" - LOCAL __BOLD -__BOLD: - push hl - ld hl, MEM0 - ld b, 8 -1: - ld a, (de) - ld c, a - rlca + ld a, d + or e + or b or c - ld (hl), a + exx + jr z, __END + inc l + jr nz, __END + inc h + jr nz, __END + inc de + LOCAL __END +__END: + jp __NEG32 + ENDP +__FTOU8: ; Converts float in C ED LH to Unsigned byte in A + call __FTOU32REG + ld a, l + ret + pop namespace +#line 144 "zx48k/lcd3.bas" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/loadstr.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/alloc.asm" +; vim: ts=4:et:sw=4: + ; Copyleft (K) by Jose M. Rodriguez de la Rosa + ; (a.k.a. Boriel) +; http://www.boriel.com + ; + ; This ASM library is licensed under the MIT license + ; you can use it for any purpose (even for commercial + ; closed source programs). + ; + ; Please read the MIT license on the internet + ; ----- IMPLEMENTATION NOTES ------ + ; The heap is implemented as a linked list of free blocks. +; Each free block contains this info: + ; + ; +----------------+ <-- HEAP START + ; | Size (2 bytes) | + ; | 0 | <-- Size = 0 => DUMMY HEADER BLOCK + ; +----------------+ + ; | Next (2 bytes) |---+ + ; +----------------+ <-+ + ; | Size (2 bytes) | + ; +----------------+ + ; | Next (2 bytes) |---+ + ; +----------------+ | + ; | | | <-- If Size > 4, then this contains (size - 4) bytes + ; | (0 if Size = 4)| | + ; +----------------+ <-+ + ; | Size (2 bytes) | + ; +----------------+ + ; | Next (2 bytes) |---+ + ; +----------------+ | + ; | | | + ; | (0 if Size = 4)| | + ; +----------------+ | + ; | <-- This zone is in use (Already allocated) + ; +----------------+ <-+ + ; | Size (2 bytes) | + ; +----------------+ + ; | Next (2 bytes) |---+ + ; +----------------+ | + ; | | | + ; | (0 if Size = 4)| | + ; +----------------+ <-+ + ; | Next (2 bytes) |--> NULL => END OF LIST + ; | 0 = NULL | + ; +----------------+ + ; | | + ; | (0 if Size = 4)| + ; +----------------+ + ; When a block is FREED, the previous and next pointers are examined to see + ; if we can defragment the heap. If the block to be freed is just next to the + ; previous, or to the next (or both) they will be converted into a single + ; block (so defragmented). + ; MEMORY MANAGER + ; + ; This library must be initialized calling __MEM_INIT with + ; HL = BLOCK Start & DE = Length. + ; An init directive is useful for initialization routines. + ; They will be added automatically if needed. + ; --------------------------------------------------------------------- + ; MEM_ALLOC + ; Allocates a block of memory in the heap. + ; + ; Parameters + ; BC = Length of requested memory block + ; +; Returns: + ; HL = Pointer to the allocated block in memory. Returns 0 (NULL) + ; if the block could not be allocated (out of memory) + ; --------------------------------------------------------------------- + push namespace core +MEM_ALLOC: +__MEM_ALLOC: ; Returns the 1st free block found of the given length (in BC) + PROC + LOCAL __MEM_LOOP + LOCAL __MEM_DONE + LOCAL __MEM_SUBTRACT + LOCAL __MEM_START + LOCAL TEMP, TEMP0 + TEMP EQU TEMP0 + 1 + ld hl, 0 + ld (TEMP), hl +__MEM_START: + ld hl, ZXBASIC_MEM_HEAP ; This label point to the heap start + inc bc + inc bc ; BC = BC + 2 ; block size needs 2 extra bytes for hidden pointer +__MEM_LOOP: ; Loads lengh at (HL, HL+). If Lenght >= BC, jump to __MEM_DONE + ld a, h ; HL = NULL (No memory available?) + or l +#line 113 "/zxbasic/src/arch/zx48k/library-asm/alloc.asm" + ret z ; NULL +#line 115 "/zxbasic/src/arch/zx48k/library-asm/alloc.asm" + ; HL = Pointer to Free block + ld e, (hl) inc hl - inc de - djnz 1b + ld d, (hl) + inc hl ; DE = Block Length + push hl ; HL = *pointer to -> next block + ex de, hl + or a ; CF = 0 + sbc hl, bc ; FREE >= BC (Length) (HL = BlockLength - Length) + jp nc, __MEM_DONE pop hl - ld de, MEM0 - ret -#line 385 "/zxbasic/src/arch/zx48k/library-asm/print.asm" - LOCAL __ITALIC -__ITALIC: - push hl - ld hl, MEM0 + ld (TEMP), hl ex de, hl - ld bc, 8 - ldir - ld hl, MEM0 - srl (hl) - inc hl - srl (hl) - inc hl - srl (hl) - inc hl - inc hl + ld e, (hl) inc hl - sla (hl) + ld d, (hl) + ex de, hl + jp __MEM_LOOP +__MEM_DONE: ; A free block has been found. + ; Check if at least 4 bytes remains free (HL >= 4) + push hl + exx ; exx to preserve bc + pop hl + ld bc, 4 + or a + sbc hl, bc + exx + jp nc, __MEM_SUBTRACT + ; At this point... + ; less than 4 bytes remains free. So we return this block entirely + ; We must link the previous block with the next to this one + ; (DE) => Pointer to next block + ; (TEMP) => &(previous->next) + pop hl ; Discard current block pointer + push de + ex de, hl ; DE = Previous block pointer; (HL) = Next block pointer + ld a, (hl) inc hl - sla (hl) + ld h, (hl) + ld l, a ; HL = (HL) + ex de, hl ; HL = Previous block pointer; DE = Next block pointer +TEMP0: + ld hl, 0 ; Pre-previous block pointer + ld (hl), e inc hl - sla (hl) - pop hl - ld de, MEM0 + ld (hl), d ; LINKED + pop hl ; Returning block. ret -#line 413 "/zxbasic/src/arch/zx48k/library-asm/print.asm" - LOCAL __SCROLL_SCR -#line 487 "/zxbasic/src/arch/zx48k/library-asm/print.asm" - __SCROLL_SCR EQU 0DFEh ; Use ROM SCROLL -#line 489 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -#line 490 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -PRINT_COMMA: - call __LOAD_S_POSN - ld a, e - and 16 - add a, 16 -PRINT_TAB: - ; Tabulates the number of spaces in A register - ; If the current cursor position is already A, does nothing - PROC - LOCAL LOOP - call __LOAD_S_POSN ; e = current row - sub e - and 31 - ret z - ld b, a -LOOP: - ld a, ' ' - call __PRINTCHAR - djnz LOOP +__MEM_SUBTRACT: + ; At this point we have to store HL value (Length - BC) into (DE - 2) + ex de, hl + dec hl + ld (hl), d + dec hl + ld (hl), e ; Store new block length + add hl, de ; New length + DE => free-block start + pop de ; Remove previous HL off the stack + ld (hl), c ; Store length on its 1st word + inc hl + ld (hl), b + inc hl ; Return hl ret ENDP -PRINT_AT: ; Changes cursor to ROW, COL - ; COL in A register - ; ROW in stack - pop hl ; Ret address - ex (sp), hl ; callee H = ROW + pop namespace +#line 2 "/zxbasic/src/arch/zx48k/library-asm/loadstr.asm" + ; Loads a string (ptr) from HL + ; and duplicates it on dynamic memory again + ; Finally, it returns result pointer in HL + push namespace core +__ILOADSTR: ; This is the indirect pointer entry HL = (HL) + ld a, h + or l + ret z + ld a, (hl) + inc hl + ld h, (hl) ld l, a - ex de, hl - call __IN_SCREEN - ret nc ; Return if out of screen - jp __SAVE_S_POSN - LOCAL __PRINT_COM - LOCAL __PRINT_AT1 - LOCAL __PRINT_AT2 - LOCAL __PRINT_BOLD - LOCAL __PRINT_ITA - LOCAL __PRINT_INK - LOCAL __PRINT_PAP - LOCAL __PRINT_SET_STATE - LOCAL __PRINT_TABLE - LOCAL __PRINT_TAB, __PRINT_TAB1, __PRINT_TAB2 - LOCAL __PRINT_ITA2 -#line 546 "/zxbasic/src/arch/zx48k/library-asm/print.asm" - LOCAL __PRINT_BOLD2 -#line 552 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -__PRINT_TABLE: ; Jump table for 0 .. 22 codes - DW __PRINT_NOP ; 0 - DW __PRINT_NOP ; 1 - DW __PRINT_NOP ; 2 - DW __PRINT_NOP ; 3 - DW __PRINT_NOP ; 4 - DW __PRINT_NOP ; 5 - DW __PRINT_COM ; 6 COMMA - DW __PRINT_NOP ; 7 - DW __PRINT_DEL ; 8 DEL - DW __PRINT_NOP ; 9 - DW __PRINT_NOP ; 10 - DW __PRINT_NOP ; 11 - DW __PRINT_NOP ; 12 - DW __PRINT_0Dh ; 13 - DW __PRINT_BOLD ; 14 - DW __PRINT_ITA ; 15 - DW __PRINT_INK ; 16 - DW __PRINT_PAP ; 17 - DW __PRINT_FLA ; 18 - DW __PRINT_BRI ; 19 - DW __PRINT_INV ; 20 - DW __PRINT_OVR ; 21 - DW __PRINT_AT ; 22 AT - DW __PRINT_TAB ; 23 TAB - ENDP +__LOADSTR: ; __FASTCALL__ entry + ld a, h + or l + ret z ; Return if NULL + ld c, (hl) + inc hl + ld b, (hl) + dec hl ; BC = LEN(a$) + inc bc + inc bc ; BC = LEN(a$) + 2 (two bytes for length) + push hl + push bc + call __MEM_ALLOC + pop bc ; Recover length + pop de ; Recover origin + ld a, h + or l + ret z ; Return if NULL (No memory) + ex de, hl ; ldir takes HL as source, DE as destiny, so SWAP HL,DE + push de ; Saves destiny start + ldir ; Copies string (length number included) + pop hl ; Recovers destiny in hl as result + ret pop namespace -#line 144 "zx48k/lcd3.bas" +#line 145 "zx48k/lcd3.bas" #line 1 "/zxbasic/src/arch/zx48k/library-asm/printstr.asm" ; PRINT command routine ; Prints string pointed by HL @@ -1743,7 +1743,7 @@ __PRINT_STR: jp __PRINT_STR_LOOP ENDP pop namespace -#line 145 "zx48k/lcd3.bas" +#line 147 "zx48k/lcd3.bas" #line 1 "/zxbasic/src/arch/zx48k/library-asm/pstorestr2.asm" ; vim:ts=4:et:sw=4 ; @@ -1792,7 +1792,7 @@ __PSTORE_STR2: add hl, bc jp __STORE_STR2 pop namespace -#line 146 "zx48k/lcd3.bas" +#line 148 "zx48k/lcd3.bas" #line 1 "/zxbasic/src/arch/zx48k/library-asm/pushf.asm" ; Routine to push Float pointed by HL ; Into the stack. Notice that the hl points to the last @@ -1820,7 +1820,7 @@ __FP_PUSH_REV: exx ret pop namespace -#line 147 "zx48k/lcd3.bas" +#line 149 "zx48k/lcd3.bas" #line 1 "/zxbasic/src/arch/zx48k/library-asm/str.asm" ; The STR$( ) BASIC function implementation ; Given a FP number in C ED LH @@ -1877,7 +1877,7 @@ __STR_END: STK_END EQU 5C65h ENDP pop namespace -#line 148 "zx48k/lcd3.bas" +#line 150 "zx48k/lcd3.bas" #line 1 "/zxbasic/src/arch/zx48k/library-asm/strcat.asm" #line 1 "/zxbasic/src/arch/zx48k/library-asm/strlen.asm" ; Returns len if a string @@ -1990,7 +1990,7 @@ __STRCATEND: ret ENDP pop namespace -#line 149 "zx48k/lcd3.bas" +#line 151 "zx48k/lcd3.bas" #line 1 "/zxbasic/src/arch/zx48k/library-asm/u32tofreg.asm" push namespace core __I8TOFREG: @@ -2061,5 +2061,5 @@ __U32TOFREG_END: ret ENDP pop namespace -#line 151 "zx48k/lcd3.bas" +#line 153 "zx48k/lcd3.bas" END diff --git a/tests/functional/zx48k/lcd7.asm b/tests/functional/zx48k/lcd7.asm index 46b9f7aad..454cc11e8 100644 --- a/tests/functional/zx48k/lcd7.asm +++ b/tests/functional/zx48k/lcd7.asm @@ -45,11 +45,12 @@ _printerPutString: push ix ld ix, 0 add ix, sp + call .core.COPY_ATTR ld l, (ix+4) ld h, (ix+5) xor a call .core.__PRINTSTR - call .core.PRINT_EOL_ATTR + call .core.PRINT_EOL _printerPutString__leave: ex af, af' exx @@ -95,334 +96,42 @@ _Frame__leave: DEFB 4Fh DEFB 4Bh ;; --- end of user code --- -#line 1 "/zxbasic/src/arch/zx48k/library-asm/free.asm" -; vim: ts=4:et:sw=4: - ; Copyleft (K) by Jose M. Rodriguez de la Rosa - ; (a.k.a. Boriel) -; http://www.boriel.com - ; - ; This ASM library is licensed under the BSD license - ; you can use it for any purpose (even for commercial - ; closed source programs). - ; - ; Please read the BSD license on the internet - ; ----- IMPLEMENTATION NOTES ------ - ; The heap is implemented as a linked list of free blocks. -; Each free block contains this info: - ; - ; +----------------+ <-- HEAP START - ; | Size (2 bytes) | - ; | 0 | <-- Size = 0 => DUMMY HEADER BLOCK - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ <-+ - ; | Size (2 bytes) | - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ | - ; | | | <-- If Size > 4, then this contains (size - 4) bytes - ; | (0 if Size = 4)| | - ; +----------------+ <-+ - ; | Size (2 bytes) | - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ | - ; | | | - ; | (0 if Size = 4)| | - ; +----------------+ | - ; | <-- This zone is in use (Already allocated) - ; +----------------+ <-+ - ; | Size (2 bytes) | - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ | - ; | | | - ; | (0 if Size = 4)| | - ; +----------------+ <-+ - ; | Next (2 bytes) |--> NULL => END OF LIST - ; | 0 = NULL | - ; +----------------+ - ; | | - ; | (0 if Size = 4)| - ; +----------------+ - ; When a block is FREED, the previous and next pointers are examined to see - ; if we can defragment the heap. If the block to be breed is just next to the - ; previous, or to the next (or both) they will be converted into a single - ; block (so defragmented). - ; MEMORY MANAGER - ; - ; This library must be initialized calling __MEM_INIT with - ; HL = BLOCK Start & DE = Length. - ; An init directive is useful for initialization routines. - ; They will be added automatically if needed. -#line 1 "/zxbasic/src/arch/zx48k/library-asm/heapinit.asm" -; vim: ts=4:et:sw=4: - ; Copyleft (K) by Jose M. Rodriguez de la Rosa - ; (a.k.a. Boriel) -; http://www.boriel.com - ; - ; This ASM library is licensed under the BSD license - ; you can use it for any purpose (even for commercial - ; closed source programs). - ; - ; Please read the BSD license on the internet - ; ----- IMPLEMENTATION NOTES ------ - ; The heap is implemented as a linked list of free blocks. -; Each free block contains this info: - ; - ; +----------------+ <-- HEAP START - ; | Size (2 bytes) | - ; | 0 | <-- Size = 0 => DUMMY HEADER BLOCK - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ <-+ - ; | Size (2 bytes) | - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ | - ; | | | <-- If Size > 4, then this contains (size - 4) bytes - ; | (0 if Size = 4)| | - ; +----------------+ <-+ - ; | Size (2 bytes) | - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ | - ; | | | - ; | (0 if Size = 4)| | - ; +----------------+ | - ; | <-- This zone is in use (Already allocated) - ; +----------------+ <-+ - ; | Size (2 bytes) | - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ | - ; | | | - ; | (0 if Size = 4)| | - ; +----------------+ <-+ - ; | Next (2 bytes) |--> NULL => END OF LIST - ; | 0 = NULL | - ; +----------------+ - ; | | - ; | (0 if Size = 4)| - ; +----------------+ - ; When a block is FREED, the previous and next pointers are examined to see - ; if we can defragment the heap. If the block to be breed is just next to the - ; previous, or to the next (or both) they will be converted into a single - ; block (so defragmented). - ; MEMORY MANAGER - ; - ; This library must be initialized calling __MEM_INIT with - ; HL = BLOCK Start & DE = Length. - ; An init directive is useful for initialization routines. - ; They will be added automatically if needed. - ; --------------------------------------------------------------------- - ; __MEM_INIT must be called to initalize this library with the - ; standard parameters - ; --------------------------------------------------------------------- - push namespace core -__MEM_INIT: ; Initializes the library using (RAMTOP) as start, and - ld hl, ZXBASIC_MEM_HEAP ; Change this with other address of heap start - ld de, ZXBASIC_HEAP_SIZE ; Change this with your size - ; --------------------------------------------------------------------- - ; __MEM_INIT2 initalizes this library -; Parameters: -; HL : Memory address of 1st byte of the memory heap -; DE : Length in bytes of the Memory Heap - ; --------------------------------------------------------------------- -__MEM_INIT2: - ; HL as TOP - PROC - dec de - dec de - dec de - dec de ; DE = length - 4; HL = start - ; This is done, because we require 4 bytes for the empty dummy-header block - xor a - ld (hl), a - inc hl - ld (hl), a ; First "free" block is a header: size=0, Pointer=&(Block) + 4 - inc hl - ld b, h - ld c, l - inc bc - inc bc ; BC = starts of next block - ld (hl), c - inc hl - ld (hl), b - inc hl ; Pointer to next block - ld (hl), e - inc hl - ld (hl), d - inc hl ; Block size (should be length - 4 at start); This block contains all the available memory - ld (hl), a ; NULL (0000h) ; No more blocks (a list with a single block) - inc hl - ld (hl), a - ld a, 201 - ld (__MEM_INIT), a; "Pokes" with a RET so ensure this routine is not called again - ret - ENDP - pop namespace -#line 69 "/zxbasic/src/arch/zx48k/library-asm/free.asm" - ; --------------------------------------------------------------------- - ; MEM_FREE - ; Frees a block of memory - ; -; Parameters: - ; HL = Pointer to the block to be freed. If HL is NULL (0) nothing - ; is done - ; --------------------------------------------------------------------- - push namespace core -MEM_FREE: -__MEM_FREE: ; Frees the block pointed by HL - ; HL DE BC & AF modified - PROC - LOCAL __MEM_LOOP2 - LOCAL __MEM_LINK_PREV - LOCAL __MEM_JOIN_TEST - LOCAL __MEM_BLOCK_JOIN - ld a, h - or l - ret z ; Return if NULL pointer - dec hl - dec hl - ld b, h - ld c, l ; BC = Block pointer - ld hl, ZXBASIC_MEM_HEAP ; This label point to the heap start -__MEM_LOOP2: - inc hl - inc hl ; Next block ptr - ld e, (hl) - inc hl - ld d, (hl) ; Block next ptr - ex de, hl ; DE = &(block->next); HL = block->next - ld a, h ; HL == NULL? - or l - jp z, __MEM_LINK_PREV; if so, link with previous - or a ; Clear carry flag - sbc hl, bc ; Carry if BC > HL => This block if before - add hl, bc ; Restores HL, preserving Carry flag - jp c, __MEM_LOOP2 ; This block is before. Keep searching PASS the block - ;------ At this point current HL is PAST BC, so we must link (DE) with BC, and HL in BC->next -__MEM_LINK_PREV: ; Link (DE) with BC, and BC->next with HL - ex de, hl - push hl - dec hl - ld (hl), c - inc hl - ld (hl), b ; (DE) <- BC - ld h, b ; HL <- BC (Free block ptr) - ld l, c - inc hl ; Skip block length (2 bytes) - inc hl - ld (hl), e ; Block->next = DE - inc hl - ld (hl), d - ; --- LINKED ; HL = &(BC->next) + 2 - call __MEM_JOIN_TEST - pop hl -__MEM_JOIN_TEST: ; Checks for fragmented contiguous blocks and joins them - ; hl = Ptr to current block + 2 - ld d, (hl) - dec hl - ld e, (hl) - dec hl - ld b, (hl) ; Loads block length into BC - dec hl - ld c, (hl) ; - push hl ; Saves it for later - add hl, bc ; Adds its length. If HL == DE now, it must be joined - or a - sbc hl, de ; If Z, then HL == DE => We must join - pop hl - ret nz -__MEM_BLOCK_JOIN: ; Joins current block (pointed by HL) with next one (pointed by DE). HL->length already in BC - push hl ; Saves it for later - ex de, hl - ld e, (hl) ; DE -> block->next->length - inc hl - ld d, (hl) - inc hl - ex de, hl ; DE = &(block->next) - add hl, bc ; HL = Total Length - ld b, h - ld c, l ; BC = Total Length - ex de, hl - ld e, (hl) - inc hl - ld d, (hl) ; DE = block->next - pop hl ; Recovers Pointer to block - ld (hl), c - inc hl - ld (hl), b ; Length Saved - inc hl - ld (hl), e - inc hl - ld (hl), d ; Next saved - ret - ENDP - pop namespace -#line 71 "zx48k/lcd7.bas" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/loadstr.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/alloc.asm" -; vim: ts=4:et:sw=4: - ; Copyleft (K) by Jose M. Rodriguez de la Rosa - ; (a.k.a. Boriel) -; http://www.boriel.com - ; - ; This ASM library is licensed under the MIT license - ; you can use it for any purpose (even for commercial - ; closed source programs). - ; - ; Please read the MIT license on the internet - ; ----- IMPLEMENTATION NOTES ------ - ; The heap is implemented as a linked list of free blocks. -; Each free block contains this info: - ; - ; +----------------+ <-- HEAP START - ; | Size (2 bytes) | - ; | 0 | <-- Size = 0 => DUMMY HEADER BLOCK - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ <-+ - ; | Size (2 bytes) | - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ | - ; | | | <-- If Size > 4, then this contains (size - 4) bytes - ; | (0 if Size = 4)| | - ; +----------------+ <-+ - ; | Size (2 bytes) | - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ | - ; | | | - ; | (0 if Size = 4)| | - ; +----------------+ | - ; | <-- This zone is in use (Already allocated) - ; +----------------+ <-+ - ; | Size (2 bytes) | - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ | - ; | | | - ; | (0 if Size = 4)| | - ; +----------------+ <-+ - ; | Next (2 bytes) |--> NULL => END OF LIST - ; | 0 = NULL | - ; +----------------+ - ; | | - ; | (0 if Size = 4)| - ; +----------------+ - ; When a block is FREED, the previous and next pointers are examined to see - ; if we can defragment the heap. If the block to be freed is just next to the - ; previous, or to the next (or both) they will be converted into a single - ; block (so defragmented). - ; MEMORY MANAGER - ; - ; This library must be initialized calling __MEM_INIT with - ; HL = BLOCK Start & DE = Length. - ; An init directive is useful for initialization routines. - ; They will be added automatically if needed. +#line 1 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +; vim:ts=4:sw=4:et: + ; PRINT command routine + ; Does not print attribute. Use PRINT_STR or PRINT_NUM for that +#line 1 "/zxbasic/src/arch/zx48k/library-asm/sposn.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/sysvars.asm" + ;; ----------------------------------------------------------------------- + ;; ZX Basic System Vars + ;; Some of them will be mapped over Sinclair ROM ones for compatibility + ;; ----------------------------------------------------------------------- + push namespace core +SCREEN_ADDR: DW 16384 ; Screen address (can be pointed to other place to use a screen buffer) +SCREEN_ATTR_ADDR: DW 22528 ; Screen attribute address (ditto.) + ; These are mapped onto ZX Spectrum ROM VARS + CHARS EQU 23606 ; Pointer to ROM/RAM Charset + TVFLAGS EQU 23612 ; TV Flags + UDG EQU 23675 ; Pointer to UDG Charset + COORDS EQU 23677 ; Last PLOT coordinates + FLAGS2 EQU 23681 ; + ECHO_E EQU 23682 ; + DFCC EQU 23684 ; Next screen addr for PRINT + DFCCL EQU 23686 ; Next screen attr for PRINT + S_POSN EQU 23688 + ATTR_P EQU 23693 ; Current Permanent ATTRS set with INK, PAPER, etc commands + ATTR_T EQU 23695 ; temporary ATTRIBUTES + P_FLAG EQU 23697 ; + MEM0 EQU 23698 ; Temporary memory buffer used by ROM chars + SCR_COLS EQU 33 ; Screen with in columns + 1 + SCR_ROWS EQU 24 ; Screen height in rows + SCR_SIZE EQU (SCR_ROWS << 8) + SCR_COLS + pop namespace +#line 2 "/zxbasic/src/arch/zx48k/library-asm/sposn.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/attr.asm" + ; Attribute routines +; vim:ts=4:et:sw: #line 1 "/zxbasic/src/arch/zx48k/library-asm/error.asm" ; Simple error control routines ; vim:ts=4:et: @@ -457,460 +166,795 @@ __STOP: ld (ERR_NR), a ret pop namespace -#line 69 "/zxbasic/src/arch/zx48k/library-asm/alloc.asm" - ; --------------------------------------------------------------------- - ; MEM_ALLOC - ; Allocates a block of memory in the heap. - ; - ; Parameters - ; BC = Length of requested memory block - ; -; Returns: - ; HL = Pointer to the allocated block in memory. Returns 0 (NULL) - ; if the block could not be allocated (out of memory) - ; --------------------------------------------------------------------- +#line 6 "/zxbasic/src/arch/zx48k/library-asm/attr.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/in_screen.asm" push namespace core -MEM_ALLOC: -__MEM_ALLOC: ; Returns the 1st free block found of the given length (in BC) +__IN_SCREEN: + ; Returns NO carry if current coords (D, E) + ; are OUT of the screen limits PROC - LOCAL __MEM_LOOP - LOCAL __MEM_DONE - LOCAL __MEM_SUBTRACT - LOCAL __MEM_START - LOCAL TEMP, TEMP0 - TEMP EQU TEMP0 + 1 - ld hl, 0 - ld (TEMP), hl -__MEM_START: - ld hl, ZXBASIC_MEM_HEAP ; This label point to the heap start - inc bc - inc bc ; BC = BC + 2 ; block size needs 2 extra bytes for hidden pointer -__MEM_LOOP: ; Loads lengh at (HL, HL+). If Lenght >= BC, jump to __MEM_DONE - ld a, h ; HL = NULL (No memory available?) - or l -#line 113 "/zxbasic/src/arch/zx48k/library-asm/alloc.asm" - ret z ; NULL -#line 115 "/zxbasic/src/arch/zx48k/library-asm/alloc.asm" - ; HL = Pointer to Free block - ld e, (hl) - inc hl - ld d, (hl) - inc hl ; DE = Block Length - push hl ; HL = *pointer to -> next block - ex de, hl - or a ; CF = 0 - sbc hl, bc ; FREE >= BC (Length) (HL = BlockLength - Length) - jp nc, __MEM_DONE - pop hl - ld (TEMP), hl + LOCAL __IN_SCREEN_ERR + ld hl, SCR_SIZE + ld a, e + cp l + jr nc, __IN_SCREEN_ERR ; Do nothing and return if out of range + ld a, d + cp h + ret c ; Return if carry (OK) +__IN_SCREEN_ERR: +__OUT_OF_SCREEN_ERR: + ; Jumps here if out of screen + ld a, ERROR_OutOfScreen + jp __STOP ; Saves error code and exits + ENDP + pop namespace +#line 7 "/zxbasic/src/arch/zx48k/library-asm/attr.asm" + push namespace core +__ATTR_ADDR: + ; calc start address in DE (as (32 * d) + e) + ; Contributed by Santiago Romero at http://www.speccy.org + ld h, 0 ; 7 T-States + ld a, d ; 4 T-States + ld d, h + add a, a ; a * 2 ; 4 T-States + add a, a ; a * 4 ; 4 T-States + ld l, a ; HL = A * 4 ; 4 T-States + add hl, hl ; HL = A * 8 ; 15 T-States + add hl, hl ; HL = A * 16 ; 15 T-States + add hl, hl ; HL = A * 32 ; 15 T-States + add hl, de + ld de, (SCREEN_ATTR_ADDR) ; Adds the screen address + add hl, de + ; Return current screen address in HL + ret + ; Sets the attribute at a given screen coordinate (D, E). + ; The attribute is taken from the ATTR_T memory variable + ; Used by PRINT routines +SET_ATTR: + ; Checks for valid coords + call __IN_SCREEN + ret nc + call __ATTR_ADDR +__SET_ATTR: + ; Internal __FASTCALL__ Entry used by printing routines + ; HL contains the address of the ATTR cell to set + PROC +__SET_ATTR2: ; Sets attr from ATTR_T to (HL) which points to the scr address + ld de, (ATTR_T) ; E = ATTR_T, D = MASK_T + ld a, d + and (hl) + ld c, a ; C = current screen color, masked + ld a, d + cpl ; Negate mask + and e ; Mask current attributes + or c ; Mix them + ld (hl), a ; Store result in screen + ret + ENDP + pop namespace +#line 3 "/zxbasic/src/arch/zx48k/library-asm/sposn.asm" + ; Printing positioning library. + push namespace core + ; Loads into DE current ROW, COL print position from S_POSN mem var. +__LOAD_S_POSN: + PROC + ld de, (S_POSN) + ld hl, SCR_SIZE + or a + sbc hl, de ex de, hl + ret + ENDP + ; Saves ROW, COL from DE into S_POSN mem var. +__SAVE_S_POSN: + PROC + ld hl, SCR_SIZE + or a + sbc hl, de + ld (S_POSN), hl ; saves it again +__SET_SCR_PTR: ;; Fast + push de + call __ATTR_ADDR + ld (DFCCL), hl + pop de + ld a, d + ld c, a ; Saves it for later + and 0F8h ; Masks 3 lower bit ; zy + ld d, a + ld a, c ; Recovers it + and 07h ; MOD 7 ; y1 + rrca + rrca + rrca + or e + ld e, a + ld hl, (SCREEN_ADDR) + add hl, de ; HL = Screen address + DE + ld (DFCC), hl + ret + ENDP + pop namespace +#line 6 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/table_jump.asm" + push namespace core +JUMP_HL_PLUS_2A: ; Does JP (HL + A*2) Modifies DE. Modifies A + add a, a +JUMP_HL_PLUS_A: ; Does JP (HL + A) Modifies DE + ld e, a + ld d, 0 +JUMP_HL_PLUS_DE: ; Does JP (HL + DE) + add hl, de ld e, (hl) inc hl ld d, (hl) ex de, hl - jp __MEM_LOOP -__MEM_DONE: ; A free block has been found. - ; Check if at least 4 bytes remains free (HL >= 4) - push hl - exx ; exx to preserve bc - pop hl - ld bc, 4 +CALL_HL: + jp (hl) + pop namespace +#line 8 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/ink.asm" + ; Sets ink color in ATTR_P permanently +; Parameter: Paper color in A register + push namespace core +INK: + PROC + LOCAL __SET_INK + LOCAL __SET_INK2 + ld de, ATTR_P +__SET_INK: + cp 8 + jr nz, __SET_INK2 + inc de ; Points DE to MASK_T or MASK_P + ld a, (de) + or 7 ; Set bits 0,1,2 to enable transparency + ld (de), a + ret +__SET_INK2: + ; Another entry. This will set the ink color at location pointer by DE + and 7 ; # Gets color mod 8 + ld b, a ; Saves the color + ld a, (de) + and 0F8h ; Clears previous value + or b + ld (de), a + inc de ; Points DE to MASK_T or MASK_P + ld a, (de) + and 0F8h ; Reset bits 0,1,2 sign to disable transparency + ld (de), a ; Store new attr + ret + ; Sets the INK color passed in A register in the ATTR_T variable +INK_TMP: + ld de, ATTR_T + jp __SET_INK + ENDP + pop namespace +#line 9 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/paper.asm" + ; Sets paper color in ATTR_P permanently +; Parameter: Paper color in A register + push namespace core +PAPER: + PROC + LOCAL __SET_PAPER + LOCAL __SET_PAPER2 + ld de, ATTR_P +__SET_PAPER: + cp 8 + jr nz, __SET_PAPER2 + inc de + ld a, (de) + or 038h + ld (de), a + ret + ; Another entry. This will set the paper color at location pointer by DE +__SET_PAPER2: + and 7 ; # Remove + rlca + rlca + rlca ; a *= 8 + ld b, a ; Saves the color + ld a, (de) + and 0C7h ; Clears previous value + or b + ld (de), a + inc de ; Points to MASK_T or MASK_P accordingly + ld a, (de) + and 0C7h ; Resets bits 3,4,5 + ld (de), a + ret + ; Sets the PAPER color passed in A register in the ATTR_T variable +PAPER_TMP: + ld de, ATTR_T + jp __SET_PAPER + ENDP + pop namespace +#line 10 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/flash.asm" + ; Sets flash flag in ATTR_P permanently +; Parameter: Paper color in A register + push namespace core +FLASH: + ld hl, ATTR_P + PROC + LOCAL IS_TR + LOCAL IS_ZERO +__SET_FLASH: + ; Another entry. This will set the flash flag at location pointer by DE + cp 8 + jr z, IS_TR + ; # Convert to 0/1 or a - sbc hl, bc - exx - jp nc, __MEM_SUBTRACT - ; At this point... - ; less than 4 bytes remains free. So we return this block entirely - ; We must link the previous block with the next to this one - ; (DE) => Pointer to next block - ; (TEMP) => &(previous->next) - pop hl ; Discard current block pointer - push de - ex de, hl ; DE = Previous block pointer; (HL) = Next block pointer + jr z, IS_ZERO + ld a, 0x80 +IS_ZERO: + ld b, a ; Saves the color ld a, (hl) + and 07Fh ; Clears previous value + or b + ld (hl), a inc hl - ld h, (hl) - ld l, a ; HL = (HL) - ex de, hl ; HL = Previous block pointer; DE = Next block pointer -TEMP0: - ld hl, 0 ; Pre-previous block pointer - ld (hl), e - inc hl - ld (hl), d ; LINKED - pop hl ; Returning block. + res 7, (hl) ;Reset bit 7 to disable transparency ret -__MEM_SUBTRACT: - ; At this point we have to store HL value (Length - BC) into (DE - 2) - ex de, hl - dec hl - ld (hl), d - dec hl - ld (hl), e ; Store new block length - add hl, de ; New length + DE => free-block start - pop de ; Remove previous HL off the stack - ld (hl), c ; Store length on its 1st word - inc hl - ld (hl), b - inc hl ; Return hl +IS_TR: ; transparent + inc hl ; Points DE to MASK_T or MASK_P + set 7, (hl) ;Set bit 7 to enable transparency ret + ; Sets the FLASH flag passed in A register in the ATTR_T variable +FLASH_TMP: + ld hl, ATTR_T + jr __SET_FLASH ENDP pop namespace -#line 2 "/zxbasic/src/arch/zx48k/library-asm/loadstr.asm" - ; Loads a string (ptr) from HL - ; and duplicates it on dynamic memory again - ; Finally, it returns result pointer in HL +#line 11 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/bright.asm" + ; Sets bright flag in ATTR_P permanently +; Parameter: Paper color in A register push namespace core -__ILOADSTR: ; This is the indirect pointer entry HL = (HL) - ld a, h - or l - ret z +BRIGHT: + ld hl, ATTR_P + PROC + LOCAL IS_TR + LOCAL IS_ZERO +__SET_BRIGHT: + ; Another entry. This will set the bright flag at location pointer by DE + cp 8 + jr z, IS_TR + ; # Convert to 0/1 + or a + jr z, IS_ZERO + ld a, 0x40 +IS_ZERO: + ld b, a ; Saves the color ld a, (hl) + and 0BFh ; Clears previous value + or b + ld (hl), a inc hl - ld h, (hl) - ld l, a -__LOADSTR: ; __FASTCALL__ entry - ld a, h - or l - ret z ; Return if NULL - ld c, (hl) - inc hl - ld b, (hl) - dec hl ; BC = LEN(a$) - inc bc - inc bc ; BC = LEN(a$) + 2 (two bytes for length) - push hl - push bc - call __MEM_ALLOC - pop bc ; Recover length - pop de ; Recover origin - ld a, h - or l - ret z ; Return if NULL (No memory) - ex de, hl ; ldir takes HL as source, DE as destiny, so SWAP HL,DE - push de ; Saves destiny start - ldir ; Copies string (length number included) - pop hl ; Recovers destiny in hl as result + res 6, (hl) ;Reset bit 6 to disable transparency + ret +IS_TR: ; transparent + inc hl ; Points DE to MASK_T or MASK_P + set 6, (hl) ;Set bit 6 to enable transparency ret + ; Sets the BRIGHT flag passed in A register in the ATTR_T variable +BRIGHT_TMP: + ld hl, ATTR_T + jr __SET_BRIGHT + ENDP pop namespace -#line 72 "zx48k/lcd7.bas" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/print_eol_attr.asm" - ; Calls PRINT_EOL and then COPY_ATTR, so saves - ; 3 bytes -#line 1 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -; vim:ts=4:sw=4:et: - ; PRINT command routine - ; Does not print attribute. Use PRINT_STR or PRINT_NUM for that -#line 1 "/zxbasic/src/arch/zx48k/library-asm/sposn.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/sysvars.asm" - ;; ----------------------------------------------------------------------- - ;; ZX Basic System Vars - ;; Some of them will be mapped over Sinclair ROM ones for compatibility - ;; ----------------------------------------------------------------------- - push namespace core -SCREEN_ADDR: DW 16384 ; Screen address (can be pointed to other place to use a screen buffer) -SCREEN_ATTR_ADDR: DW 22528 ; Screen attribute address (ditto.) - ; These are mapped onto ZX Spectrum ROM VARS - CHARS EQU 23606 ; Pointer to ROM/RAM Charset - TVFLAGS EQU 23612 ; TV Flags - UDG EQU 23675 ; Pointer to UDG Charset - COORDS EQU 23677 ; Last PLOT coordinates - FLAGS2 EQU 23681 ; - ECHO_E EQU 23682 ; - DFCC EQU 23684 ; Next screen addr for PRINT - DFCCL EQU 23686 ; Next screen attr for PRINT - S_POSN EQU 23688 - ATTR_P EQU 23693 ; Current Permanent ATTRS set with INK, PAPER, etc commands - ATTR_T EQU 23695 ; temporary ATTRIBUTES - P_FLAG EQU 23697 ; - MEM0 EQU 23698 ; Temporary memory buffer used by ROM chars - SCR_COLS EQU 33 ; Screen with in columns + 1 - SCR_ROWS EQU 24 ; Screen height in rows - SCR_SIZE EQU (SCR_ROWS << 8) + SCR_COLS - pop namespace -#line 2 "/zxbasic/src/arch/zx48k/library-asm/sposn.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/attr.asm" - ; Attribute routines -; vim:ts=4:et:sw: -#line 1 "/zxbasic/src/arch/zx48k/library-asm/in_screen.asm" +#line 12 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/over.asm" + ; Sets OVER flag in P_FLAG permanently +; Parameter: OVER flag in bit 0 of A register push namespace core -__IN_SCREEN: - ; Returns NO carry if current coords (D, E) - ; are OUT of the screen limits +OVER: PROC - LOCAL __IN_SCREEN_ERR - ld hl, SCR_SIZE - ld a, e - cp l - jr nc, __IN_SCREEN_ERR ; Do nothing and return if out of range - ld a, d - cp h - ret c ; Return if carry (OK) -__IN_SCREEN_ERR: -__OUT_OF_SCREEN_ERR: - ; Jumps here if out of screen - ld a, ERROR_OutOfScreen - jp __STOP ; Saves error code and exits + ld c, a ; saves it for later + and 2 + ld hl, FLAGS2 + res 1, (HL) + or (hl) + ld (hl), a + ld a, c ; Recovers previous value + and 1 ; # Convert to 0/1 + add a, a; # Shift left 1 bit for permanent + ld hl, P_FLAG + res 1, (hl) + or (hl) + ld (hl), a + ret + ; Sets OVER flag in P_FLAG temporarily +OVER_TMP: + ld c, a ; saves it for later + and 2 ; gets bit 1; clears carry + rra + ld hl, FLAGS2 + res 0, (hl) + or (hl) + ld (hl), a + ld a, c ; Recovers previous value + and 1 + ld hl, P_FLAG + res 0, (hl) + or (hl) + ld (hl), a + jp __SET_ATTR_MODE + ENDP + pop namespace +#line 13 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/inverse.asm" + ; Sets INVERSE flag in P_FLAG permanently +; Parameter: INVERSE flag in bit 0 of A register + push namespace core +INVERSE: + PROC + and 1 ; # Convert to 0/1 + add a, a; # Shift left 3 bits for permanent + add a, a + add a, a + ld hl, P_FLAG + res 3, (hl) + or (hl) + ld (hl), a + ret + ; Sets INVERSE flag in P_FLAG temporarily +INVERSE_TMP: + and 1 + add a, a + add a, a; # Shift left 2 bits for temporary + ld hl, P_FLAG + res 2, (hl) + or (hl) + ld (hl), a + jp __SET_ATTR_MODE + ENDP + pop namespace +#line 14 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/bold.asm" + ; Sets BOLD flag in P_FLAG permanently +; Parameter: BOLD flag in bit 0 of A register + push namespace core +BOLD: + PROC + and 1 + rlca + rlca + rlca + ld hl, FLAGS2 + res 3, (HL) + or (hl) + ld (hl), a + ret + ; Sets BOLD flag in P_FLAG temporarily +BOLD_TMP: + and 1 + rlca + rlca + ld hl, FLAGS2 + res 2, (hl) + or (hl) + ld (hl), a + ret ENDP pop namespace -#line 7 "/zxbasic/src/arch/zx48k/library-asm/attr.asm" +#line 15 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/italic.asm" + ; Sets ITALIC flag in P_FLAG permanently +; Parameter: ITALIC flag in bit 0 of A register push namespace core -__ATTR_ADDR: - ; calc start address in DE (as (32 * d) + e) - ; Contributed by Santiago Romero at http://www.speccy.org - ld h, 0 ; 7 T-States - ld a, d ; 4 T-States - ld d, h - add a, a ; a * 2 ; 4 T-States - add a, a ; a * 4 ; 4 T-States - ld l, a ; HL = A * 4 ; 4 T-States - add hl, hl ; HL = A * 8 ; 15 T-States - add hl, hl ; HL = A * 16 ; 15 T-States - add hl, hl ; HL = A * 32 ; 15 T-States - add hl, de - ld de, (SCREEN_ATTR_ADDR) ; Adds the screen address - add hl, de - ; Return current screen address in HL - ret - ; Sets the attribute at a given screen coordinate (D, E). - ; The attribute is taken from the ATTR_T memory variable - ; Used by PRINT routines -SET_ATTR: - ; Checks for valid coords - call __IN_SCREEN - ret nc - call __ATTR_ADDR -__SET_ATTR: - ; Internal __FASTCALL__ Entry used by printing routines - ; HL contains the address of the ATTR cell to set +ITALIC: PROC -__SET_ATTR2: ; Sets attr from ATTR_T to (HL) which points to the scr address - ld de, (ATTR_T) ; E = ATTR_T, D = MASK_T - ld a, d - and (hl) - ld c, a ; C = current screen color, masked - ld a, d - cpl ; Negate mask - and e ; Mask current attributes - or c ; Mix them - ld (hl), a ; Store result in screen + and 1 + rrca + rrca + rrca + ld hl, FLAGS2 + res 5, (HL) + or (hl) + ld (hl), a + ret + ; Sets ITALIC flag in P_FLAG temporarily +ITALIC_TMP: + and 1 + rrca + rrca + rrca + rrca + ld hl, FLAGS2 + res 4, (hl) + or (hl) + ld (hl), a ret ENDP pop namespace -#line 3 "/zxbasic/src/arch/zx48k/library-asm/sposn.asm" - ; Printing positioning library. +#line 16 "/zxbasic/src/arch/zx48k/library-asm/print.asm" + ; Putting a comment starting with @INIT
+ ; will make the compiler to add a CALL to
+ ; It is useful for initialization routines. push namespace core - ; Loads into DE current ROW, COL print position from S_POSN mem var. -__LOAD_S_POSN: +__PRINT_INIT: ; To be called before program starts (initializes library) PROC - ld de, (S_POSN) + ld hl, __PRINT_START + ld (PRINT_JUMP_STATE), hl + ;; Clears ATTR2 flags (OVER 2, etc) + xor a + ld (FLAGS2), a + LOCAL SET_SCR_ADDR + call __LOAD_S_POSN + jp __SET_SCR_PTR + ;; Receives HL = future value of S_POSN + ;; Stores it at (S_POSN) and refresh screen pointers (ATTR, SCR) +SET_SCR_ADDR: + ld (S_POSN), hl + ex de, hl ld hl, SCR_SIZE or a sbc hl, de ex de, hl + dec e + jp __SET_SCR_PTR +__PRINTCHAR: ; Print character store in accumulator (A register) + ; Modifies H'L', B'C', A'F', D'E', A + LOCAL PO_GR_1 + LOCAL __PRCHAR + LOCAL __PRINT_JUMP + LOCAL __SRCADDR + LOCAL __PRINT_UDG + LOCAL __PRGRAPH + LOCAL __PRINT_START + PRINT_JUMP_STATE EQU __PRINT_JUMP + 2 +__PRINT_JUMP: + exx ; Switch to alternative registers + jp __PRINT_START ; Where to jump. If we print 22 (AT), next two calls jumps to AT1 and AT2 respectively +__PRINT_START: +__PRINT_CHR: + cp ' ' + jr c, __PRINT_SPECIAL ; Characters below ' ' are special ones + ex af, af' ; Saves a value (char to print) for later + ld hl, (S_POSN) + dec l + jr nz, 1f + ld l, SCR_COLS - 1 + dec h + jr nz, 2f + inc h + push hl + call __SCROLL_SCR + pop hl +#line 92 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +2: + call SET_SCR_ADDR + jr 4f +1: + ld (S_POSN), hl +4: + ex af, af' + cp 80h ; Is it a "normal" (printable) char + jr c, __SRCADDR + cp 90h ; Is it an UDG? + jr nc, __PRINT_UDG + ; Print an 8 bit pattern (80h to 8Fh) + ld b, a + call PO_GR_1 ; This ROM routine will generate the bit pattern at MEM0 + ld hl, MEM0 + jp __PRGRAPH + PO_GR_1 EQU 0B38h +__PRINT_UDG: + sub 90h ; Sub ASC code + ld bc, (UDG) + jr __PRGRAPH0 + __SOURCEADDR EQU (__SRCADDR + 1) ; Address of the pointer to chars source +__SRCADDR: + ld bc, (CHARS) +__PRGRAPH0: + add a, a ; A = a * 2 (since a < 80h) ; Thanks to Metalbrain at http://foro.speccy.org + ld l, a + ld h, 0 ; HL = a * 2 (accumulator) + add hl, hl + add hl, hl ; HL = a * 8 + add hl, bc ; HL = CHARS address +__PRGRAPH: + ex de, hl ; HL = Write Address, DE = CHARS address + bit 2, (iy + $47) + call nz, __BOLD +#line 139 "/zxbasic/src/arch/zx48k/library-asm/print.asm" + bit 4, (iy + $47) + call nz, __ITALIC +#line 144 "/zxbasic/src/arch/zx48k/library-asm/print.asm" + ld hl, (DFCC) + push hl + ld b, 8 ; 8 bytes per char +__PRCHAR: + ld a, (de) ; DE *must* be source, and HL destiny +PRINT_MODE: ; Which operation is used to write on the screen + ; Set it with: + ; LD A, + ; LD (PRINT_MODE), A + ; + ; Available operations: + ; NORMAL : 0h --> NOP ; OVER 0 + ; XOR : AEh --> XOR (HL) ; OVER 1 + ; OR : B6h --> OR (HL) ; PUTSPRITE + ; AND : A6h --> AND (HL) ; PUTMASK + nop ; Set to one of the values above +INVERSE_MODE: ; 00 -> NOP -> INVERSE 0 + nop ; 2F -> CPL -> INVERSE 1 + ld (hl), a + inc de + inc h ; Next line + djnz __PRCHAR + pop hl + inc hl + ld (DFCC), hl + ld hl, (DFCCL) ; current ATTR Pos + inc hl + ld (DFCCL), hl + dec hl + call __SET_ATTR + exx ret - ENDP - ; Saves ROW, COL from DE into S_POSN mem var. -__SAVE_S_POSN: - PROC - ld hl, SCR_SIZE - or a - sbc hl, de - ld (S_POSN), hl ; saves it again -__SET_SCR_PTR: ;; Fast + ; ------------- SPECIAL CHARS (< 32) ----------------- +__PRINT_SPECIAL: ; Jumps here if it is a special char + ld hl, __PRINT_TABLE + jp JUMP_HL_PLUS_2A +PRINT_EOL: ; Called WHENEVER there is no ";" at end of PRINT sentence + exx +__PRINT_0Dh: ; Called WHEN printing CHR$(13) + ld hl, (S_POSN) + dec l + jr nz, 1f + dec h + jr nz, 1f + inc h + push hl + call __SCROLL_SCR + pop hl +#line 209 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +1: + ld l, 1 +__PRINT_EOL_END: + call SET_SCR_ADDR + exx + ret +__PRINT_COM: + exx + push hl push de - call __ATTR_ADDR - ld (DFCCL), hl + push bc + call PRINT_COMMA + pop bc pop de - ld a, d - ld c, a ; Saves it for later - and 0F8h ; Masks 3 lower bit ; zy - ld d, a - ld a, c ; Recovers it - and 07h ; MOD 7 ; y1 - rrca - rrca - rrca - or e - ld e, a - ld hl, (SCREEN_ADDR) - add hl, de ; HL = Screen address + DE - ld (DFCC), hl + pop hl + ret +__PRINT_TAB: + ld hl, __PRINT_TAB1 + jr __PRINT_SET_STATE +__PRINT_TAB1: + ld (MEM0), a + ld hl, __PRINT_TAB2 + jr __PRINT_SET_STATE +__PRINT_TAB2: + ld a, (MEM0) ; Load tab code (ignore the current one) + ld hl, __PRINT_START + ld (PRINT_JUMP_STATE), hl + exx + push hl + push bc + push de + call PRINT_TAB + pop de + pop bc + pop hl ret - ENDP - pop namespace -#line 6 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/table_jump.asm" - push namespace core -JUMP_HL_PLUS_2A: ; Does JP (HL + A*2) Modifies DE. Modifies A - add a, a -JUMP_HL_PLUS_A: ; Does JP (HL + A) Modifies DE - ld e, a - ld d, 0 -JUMP_HL_PLUS_DE: ; Does JP (HL + DE) - add hl, de - ld e, (hl) - inc hl - ld d, (hl) - ex de, hl -CALL_HL: - jp (hl) - pop namespace -#line 8 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/ink.asm" - ; Sets ink color in ATTR_P permanently -; Parameter: Paper color in A register - push namespace core -INK: - PROC - LOCAL __SET_INK - LOCAL __SET_INK2 - ld de, ATTR_P -__SET_INK: - cp 8 - jr nz, __SET_INK2 - inc de ; Points DE to MASK_T or MASK_P - ld a, (de) - or 7 ; Set bits 0,1,2 to enable transparency - ld (de), a +__PRINT_AT: + ld hl, __PRINT_AT1 + jr __PRINT_SET_STATE +__PRINT_NOP: +__PRINT_RESTART: + ld hl, __PRINT_START +__PRINT_SET_STATE: + ld (PRINT_JUMP_STATE), hl ; Saves next entry call + exx ret -__SET_INK2: - ; Another entry. This will set the ink color at location pointer by DE - and 7 ; # Gets color mod 8 - ld b, a ; Saves the color - ld a, (de) - and 0F8h ; Clears previous value - or b - ld (de), a - inc de ; Points DE to MASK_T or MASK_P - ld a, (de) - and 0F8h ; Reset bits 0,1,2 sign to disable transparency - ld (de), a ; Store new attr +__PRINT_AT1: ; Jumps here if waiting for 1st parameter + ld hl, (S_POSN) + ld h, a + ld a, SCR_ROWS + sub h + ld (S_POSN + 1), a + ld hl, __PRINT_AT2 + jr __PRINT_SET_STATE +__PRINT_AT2: + call __LOAD_S_POSN + ld e, a + call __SAVE_S_POSN + jr __PRINT_RESTART +__PRINT_DEL: + call __LOAD_S_POSN ; Gets current screen position + dec e + ld a, -1 + cp e + jr nz, 3f + ld e, SCR_COLS - 2 + dec d + cp d + jr nz, 3f + ld d, SCR_ROWS - 1 +3: + call __SAVE_S_POSN + exx ret - ; Sets the INK color passed in A register in the ATTR_T variable -INK_TMP: - ld de, ATTR_T - jp __SET_INK - ENDP - pop namespace -#line 9 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/paper.asm" - ; Sets paper color in ATTR_P permanently -; Parameter: Paper color in A register - push namespace core -PAPER: - PROC - LOCAL __SET_PAPER - LOCAL __SET_PAPER2 - ld de, ATTR_P -__SET_PAPER: - cp 8 - jr nz, __SET_PAPER2 - inc de +__PRINT_INK: + ld hl, __PRINT_INK2 + jr __PRINT_SET_STATE +__PRINT_INK2: + call INK_TMP + jr __PRINT_RESTART +__PRINT_PAP: + ld hl, __PRINT_PAP2 + jr __PRINT_SET_STATE +__PRINT_PAP2: + call PAPER_TMP + jr __PRINT_RESTART +__PRINT_FLA: + ld hl, __PRINT_FLA2 + jr __PRINT_SET_STATE +__PRINT_FLA2: + call FLASH_TMP + jr __PRINT_RESTART +__PRINT_BRI: + ld hl, __PRINT_BRI2 + jr __PRINT_SET_STATE +__PRINT_BRI2: + call BRIGHT_TMP + jr __PRINT_RESTART +__PRINT_INV: + ld hl, __PRINT_INV2 + jr __PRINT_SET_STATE +__PRINT_INV2: + call INVERSE_TMP + jr __PRINT_RESTART +__PRINT_OVR: + ld hl, __PRINT_OVR2 + jr __PRINT_SET_STATE +__PRINT_OVR2: + call OVER_TMP + jr __PRINT_RESTART +__PRINT_BOLD: + ld hl, __PRINT_BOLD2 + jp __PRINT_SET_STATE +__PRINT_BOLD2: + call BOLD_TMP + jp __PRINT_RESTART +#line 353 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +__PRINT_ITA: + ld hl, __PRINT_ITA2 + jp __PRINT_SET_STATE +__PRINT_ITA2: + call ITALIC_TMP + jp __PRINT_RESTART +#line 363 "/zxbasic/src/arch/zx48k/library-asm/print.asm" + LOCAL __BOLD +__BOLD: + push hl + ld hl, MEM0 + ld b, 8 +1: ld a, (de) - or 038h - ld (de), a - ret - ; Another entry. This will set the paper color at location pointer by DE -__SET_PAPER2: - and 7 ; # Remove - rlca + ld c, a rlca - rlca ; a *= 8 - ld b, a ; Saves the color - ld a, (de) - and 0C7h ; Clears previous value - or b - ld (de), a - inc de ; Points to MASK_T or MASK_P accordingly - ld a, (de) - and 0C7h ; Resets bits 3,4,5 - ld (de), a - ret - ; Sets the PAPER color passed in A register in the ATTR_T variable -PAPER_TMP: - ld de, ATTR_T - jp __SET_PAPER - ENDP - pop namespace -#line 10 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/flash.asm" - ; Sets flash flag in ATTR_P permanently -; Parameter: Paper color in A register - push namespace core -FLASH: - ld hl, ATTR_P - PROC - LOCAL IS_TR - LOCAL IS_ZERO -__SET_FLASH: - ; Another entry. This will set the flash flag at location pointer by DE - cp 8 - jr z, IS_TR - ; # Convert to 0/1 - or a - jr z, IS_ZERO - ld a, 0x80 -IS_ZERO: - ld b, a ; Saves the color - ld a, (hl) - and 07Fh ; Clears previous value - or b + or c ld (hl), a inc hl - res 7, (hl) ;Reset bit 7 to disable transparency - ret -IS_TR: ; transparent - inc hl ; Points DE to MASK_T or MASK_P - set 7, (hl) ;Set bit 7 to enable transparency - ret - ; Sets the FLASH flag passed in A register in the ATTR_T variable -FLASH_TMP: - ld hl, ATTR_T - jr __SET_FLASH - ENDP - pop namespace -#line 11 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/bright.asm" - ; Sets bright flag in ATTR_P permanently -; Parameter: Paper color in A register - push namespace core -BRIGHT: - ld hl, ATTR_P - PROC - LOCAL IS_TR - LOCAL IS_ZERO -__SET_BRIGHT: - ; Another entry. This will set the bright flag at location pointer by DE - cp 8 - jr z, IS_TR - ; # Convert to 0/1 - or a - jr z, IS_ZERO - ld a, 0x40 -IS_ZERO: - ld b, a ; Saves the color - ld a, (hl) - and 0BFh ; Clears previous value - or b - ld (hl), a + inc de + djnz 1b + pop hl + ld de, MEM0 + ret +#line 384 "/zxbasic/src/arch/zx48k/library-asm/print.asm" + LOCAL __ITALIC +__ITALIC: + push hl + ld hl, MEM0 + ex de, hl + ld bc, 8 + ldir + ld hl, MEM0 + srl (hl) inc hl - res 6, (hl) ;Reset bit 6 to disable transparency + srl (hl) + inc hl + srl (hl) + inc hl + inc hl + inc hl + sla (hl) + inc hl + sla (hl) + inc hl + sla (hl) + pop hl + ld de, MEM0 ret -IS_TR: ; transparent - inc hl ; Points DE to MASK_T or MASK_P - set 6, (hl) ;Set bit 6 to enable transparency +#line 412 "/zxbasic/src/arch/zx48k/library-asm/print.asm" + LOCAL __SCROLL_SCR +#line 486 "/zxbasic/src/arch/zx48k/library-asm/print.asm" + __SCROLL_SCR EQU 0DFEh ; Use ROM SCROLL +#line 488 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 489 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +PRINT_COMMA: + call __LOAD_S_POSN + ld a, e + and 16 + add a, 16 +PRINT_TAB: + ; Tabulates the number of spaces in A register + ; If the current cursor position is already A, does nothing + PROC + LOCAL LOOP + call __LOAD_S_POSN ; e = current row + sub e + and 31 + ret z + ld b, a +LOOP: + ld a, ' ' + call __PRINTCHAR + djnz LOOP ret - ; Sets the BRIGHT flag passed in A register in the ATTR_T variable -BRIGHT_TMP: - ld hl, ATTR_T - jr __SET_BRIGHT + ENDP +PRINT_AT: ; Changes cursor to ROW, COL + ; COL in A register + ; ROW in stack + pop hl ; Ret address + ex (sp), hl ; callee H = ROW + ld l, a + ex de, hl + call __IN_SCREEN + ret nc ; Return if out of screen + jp __SAVE_S_POSN + LOCAL __PRINT_COM + LOCAL __PRINT_AT1 + LOCAL __PRINT_AT2 + LOCAL __PRINT_BOLD + LOCAL __PRINT_ITA + LOCAL __PRINT_INK + LOCAL __PRINT_PAP + LOCAL __PRINT_SET_STATE + LOCAL __PRINT_TABLE + LOCAL __PRINT_TAB, __PRINT_TAB1, __PRINT_TAB2 + LOCAL __PRINT_ITA2 +#line 545 "/zxbasic/src/arch/zx48k/library-asm/print.asm" + LOCAL __PRINT_BOLD2 +#line 551 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +__PRINT_TABLE: ; Jump table for 0 .. 22 codes + DW __PRINT_NOP ; 0 + DW __PRINT_NOP ; 1 + DW __PRINT_NOP ; 2 + DW __PRINT_NOP ; 3 + DW __PRINT_NOP ; 4 + DW __PRINT_NOP ; 5 + DW __PRINT_COM ; 6 COMMA + DW __PRINT_NOP ; 7 + DW __PRINT_DEL ; 8 DEL + DW __PRINT_NOP ; 9 + DW __PRINT_NOP ; 10 + DW __PRINT_NOP ; 11 + DW __PRINT_NOP ; 12 + DW __PRINT_0Dh ; 13 + DW __PRINT_BOLD ; 14 + DW __PRINT_ITA ; 15 + DW __PRINT_INK ; 16 + DW __PRINT_PAP ; 17 + DW __PRINT_FLA ; 18 + DW __PRINT_BRI ; 19 + DW __PRINT_INV ; 20 + DW __PRINT_OVR ; 21 + DW __PRINT_AT ; 22 AT + DW __PRINT_TAB ; 23 TAB ENDP pop namespace -#line 12 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/over.asm" - ; Sets OVER flag in P_FLAG permanently -; Parameter: OVER flag in bit 0 of A register -#line 1 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" +#line 3 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" #line 4 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" push namespace core COPY_ATTR: @@ -963,523 +1007,470 @@ __REFRESH_TMP: ret ENDP pop namespace -#line 4 "/zxbasic/src/arch/zx48k/library-asm/over.asm" - push namespace core -OVER: - PROC - ld c, a ; saves it for later - and 2 - ld hl, FLAGS2 - res 1, (HL) - or (hl) - ld (hl), a - ld a, c ; Recovers previous value - and 1 ; # Convert to 0/1 - add a, a; # Shift left 1 bit for permanent - ld hl, P_FLAG - res 1, (hl) - or (hl) - ld (hl), a - ret - ; Sets OVER flag in P_FLAG temporarily -OVER_TMP: - ld c, a ; saves it for later - and 2 ; gets bit 1; clears carry - rra - ld hl, FLAGS2 - res 0, (hl) - or (hl) - ld (hl), a - ld a, c ; Recovers previous value - and 1 - ld hl, P_FLAG - res 0, (hl) - or (hl) - ld (hl), a - jp __SET_ATTR_MODE - ENDP - pop namespace -#line 13 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/inverse.asm" - ; Sets INVERSE flag in P_FLAG permanently -; Parameter: INVERSE flag in bit 0 of A register - push namespace core -INVERSE: - PROC - and 1 ; # Convert to 0/1 - add a, a; # Shift left 3 bits for permanent - add a, a - add a, a - ld hl, P_FLAG - res 3, (hl) - or (hl) - ld (hl), a - ret - ; Sets INVERSE flag in P_FLAG temporarily -INVERSE_TMP: - and 1 - add a, a - add a, a; # Shift left 2 bits for temporary - ld hl, P_FLAG - res 2, (hl) - or (hl) - ld (hl), a - jp __SET_ATTR_MODE - ENDP - pop namespace -#line 14 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/bold.asm" - ; Sets BOLD flag in P_FLAG permanently -; Parameter: BOLD flag in bit 0 of A register - push namespace core -BOLD: - PROC - and 1 - rlca - rlca - rlca - ld hl, FLAGS2 - res 3, (HL) - or (hl) - ld (hl), a - ret - ; Sets BOLD flag in P_FLAG temporarily -BOLD_TMP: - and 1 - rlca - rlca - ld hl, FLAGS2 - res 2, (hl) - or (hl) - ld (hl), a - ret - ENDP - pop namespace -#line 15 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/italic.asm" - ; Sets ITALIC flag in P_FLAG permanently -; Parameter: ITALIC flag in bit 0 of A register +#line 72 "zx48k/lcd7.bas" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/free.asm" +; vim: ts=4:et:sw=4: + ; Copyleft (K) by Jose M. Rodriguez de la Rosa + ; (a.k.a. Boriel) +; http://www.boriel.com + ; + ; This ASM library is licensed under the BSD license + ; you can use it for any purpose (even for commercial + ; closed source programs). + ; + ; Please read the BSD license on the internet + ; ----- IMPLEMENTATION NOTES ------ + ; The heap is implemented as a linked list of free blocks. +; Each free block contains this info: + ; + ; +----------------+ <-- HEAP START + ; | Size (2 bytes) | + ; | 0 | <-- Size = 0 => DUMMY HEADER BLOCK + ; +----------------+ + ; | Next (2 bytes) |---+ + ; +----------------+ <-+ + ; | Size (2 bytes) | + ; +----------------+ + ; | Next (2 bytes) |---+ + ; +----------------+ | + ; | | | <-- If Size > 4, then this contains (size - 4) bytes + ; | (0 if Size = 4)| | + ; +----------------+ <-+ + ; | Size (2 bytes) | + ; +----------------+ + ; | Next (2 bytes) |---+ + ; +----------------+ | + ; | | | + ; | (0 if Size = 4)| | + ; +----------------+ | + ; | <-- This zone is in use (Already allocated) + ; +----------------+ <-+ + ; | Size (2 bytes) | + ; +----------------+ + ; | Next (2 bytes) |---+ + ; +----------------+ | + ; | | | + ; | (0 if Size = 4)| | + ; +----------------+ <-+ + ; | Next (2 bytes) |--> NULL => END OF LIST + ; | 0 = NULL | + ; +----------------+ + ; | | + ; | (0 if Size = 4)| + ; +----------------+ + ; When a block is FREED, the previous and next pointers are examined to see + ; if we can defragment the heap. If the block to be breed is just next to the + ; previous, or to the next (or both) they will be converted into a single + ; block (so defragmented). + ; MEMORY MANAGER + ; + ; This library must be initialized calling __MEM_INIT with + ; HL = BLOCK Start & DE = Length. + ; An init directive is useful for initialization routines. + ; They will be added automatically if needed. +#line 1 "/zxbasic/src/arch/zx48k/library-asm/heapinit.asm" +; vim: ts=4:et:sw=4: + ; Copyleft (K) by Jose M. Rodriguez de la Rosa + ; (a.k.a. Boriel) +; http://www.boriel.com + ; + ; This ASM library is licensed under the BSD license + ; you can use it for any purpose (even for commercial + ; closed source programs). + ; + ; Please read the BSD license on the internet + ; ----- IMPLEMENTATION NOTES ------ + ; The heap is implemented as a linked list of free blocks. +; Each free block contains this info: + ; + ; +----------------+ <-- HEAP START + ; | Size (2 bytes) | + ; | 0 | <-- Size = 0 => DUMMY HEADER BLOCK + ; +----------------+ + ; | Next (2 bytes) |---+ + ; +----------------+ <-+ + ; | Size (2 bytes) | + ; +----------------+ + ; | Next (2 bytes) |---+ + ; +----------------+ | + ; | | | <-- If Size > 4, then this contains (size - 4) bytes + ; | (0 if Size = 4)| | + ; +----------------+ <-+ + ; | Size (2 bytes) | + ; +----------------+ + ; | Next (2 bytes) |---+ + ; +----------------+ | + ; | | | + ; | (0 if Size = 4)| | + ; +----------------+ | + ; | <-- This zone is in use (Already allocated) + ; +----------------+ <-+ + ; | Size (2 bytes) | + ; +----------------+ + ; | Next (2 bytes) |---+ + ; +----------------+ | + ; | | | + ; | (0 if Size = 4)| | + ; +----------------+ <-+ + ; | Next (2 bytes) |--> NULL => END OF LIST + ; | 0 = NULL | + ; +----------------+ + ; | | + ; | (0 if Size = 4)| + ; +----------------+ + ; When a block is FREED, the previous and next pointers are examined to see + ; if we can defragment the heap. If the block to be breed is just next to the + ; previous, or to the next (or both) they will be converted into a single + ; block (so defragmented). + ; MEMORY MANAGER + ; + ; This library must be initialized calling __MEM_INIT with + ; HL = BLOCK Start & DE = Length. + ; An init directive is useful for initialization routines. + ; They will be added automatically if needed. + ; --------------------------------------------------------------------- + ; __MEM_INIT must be called to initalize this library with the + ; standard parameters + ; --------------------------------------------------------------------- push namespace core -ITALIC: +__MEM_INIT: ; Initializes the library using (RAMTOP) as start, and + ld hl, ZXBASIC_MEM_HEAP ; Change this with other address of heap start + ld de, ZXBASIC_HEAP_SIZE ; Change this with your size + ; --------------------------------------------------------------------- + ; __MEM_INIT2 initalizes this library +; Parameters: +; HL : Memory address of 1st byte of the memory heap +; DE : Length in bytes of the Memory Heap + ; --------------------------------------------------------------------- +__MEM_INIT2: + ; HL as TOP PROC - and 1 - rrca - rrca - rrca - ld hl, FLAGS2 - res 5, (HL) - or (hl) + dec de + dec de + dec de + dec de ; DE = length - 4; HL = start + ; This is done, because we require 4 bytes for the empty dummy-header block + xor a ld (hl), a - ret - ; Sets ITALIC flag in P_FLAG temporarily -ITALIC_TMP: - and 1 - rrca - rrca - rrca - rrca - ld hl, FLAGS2 - res 4, (hl) - or (hl) + inc hl + ld (hl), a ; First "free" block is a header: size=0, Pointer=&(Block) + 4 + inc hl + ld b, h + ld c, l + inc bc + inc bc ; BC = starts of next block + ld (hl), c + inc hl + ld (hl), b + inc hl ; Pointer to next block + ld (hl), e + inc hl + ld (hl), d + inc hl ; Block size (should be length - 4 at start); This block contains all the available memory + ld (hl), a ; NULL (0000h) ; No more blocks (a list with a single block) + inc hl ld (hl), a + ld a, 201 + ld (__MEM_INIT), a; "Pokes" with a RET so ensure this routine is not called again ret ENDP pop namespace -#line 16 "/zxbasic/src/arch/zx48k/library-asm/print.asm" - ; Putting a comment starting with @INIT
- ; will make the compiler to add a CALL to
- ; It is useful for initialization routines. +#line 69 "/zxbasic/src/arch/zx48k/library-asm/free.asm" + ; --------------------------------------------------------------------- + ; MEM_FREE + ; Frees a block of memory + ; +; Parameters: + ; HL = Pointer to the block to be freed. If HL is NULL (0) nothing + ; is done + ; --------------------------------------------------------------------- push namespace core -__PRINT_INIT: ; To be called before program starts (initializes library) - PROC - ld hl, __PRINT_START - ld (PRINT_JUMP_STATE), hl - ;; Clears ATTR2 flags (OVER 2, etc) - xor a - ld (FLAGS2), a - LOCAL SET_SCR_ADDR - call __LOAD_S_POSN - jp __SET_SCR_PTR - ;; Receives HL = future value of S_POSN - ;; Stores it at (S_POSN) and refresh screen pointers (ATTR, SCR) -SET_SCR_ADDR: - ld (S_POSN), hl - ex de, hl - ld hl, SCR_SIZE - or a - sbc hl, de - ex de, hl - dec e - jp __SET_SCR_PTR -__PRINTCHAR: ; Print character store in accumulator (A register) - ; Modifies H'L', B'C', A'F', D'E', A - LOCAL PO_GR_1 - LOCAL __PRCHAR - LOCAL __PRINT_JUMP - LOCAL __SRCADDR - LOCAL __PRINT_UDG - LOCAL __PRGRAPH - LOCAL __PRINT_START - PRINT_JUMP_STATE EQU __PRINT_JUMP + 2 -__PRINT_JUMP: - exx ; Switch to alternative registers - jp __PRINT_START ; Where to jump. If we print 22 (AT), next two calls jumps to AT1 and AT2 respectively -__PRINT_START: -__PRINT_CHR: - cp ' ' - jr c, __PRINT_SPECIAL ; Characters below ' ' are special ones - ex af, af' ; Saves a value (char to print) for later - ld hl, (S_POSN) - dec l - jr nz, 1f - ld l, SCR_COLS - 1 - dec h - jr nz, 2f - inc h - push hl - call __SCROLL_SCR - pop hl -#line 92 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -2: - call SET_SCR_ADDR - jr 4f -1: - ld (S_POSN), hl -4: - ex af, af' - cp 80h ; Is it a "normal" (printable) char - jr c, __SRCADDR - cp 90h ; Is it an UDG? - jr nc, __PRINT_UDG - ; Print an 8 bit pattern (80h to 8Fh) - ld b, a - call PO_GR_1 ; This ROM routine will generate the bit pattern at MEM0 - ld hl, MEM0 - jp __PRGRAPH - PO_GR_1 EQU 0B38h -__PRINT_UDG: - sub 90h ; Sub ASC code - ld bc, (UDG) - jr __PRGRAPH0 - __SOURCEADDR EQU (__SRCADDR + 1) ; Address of the pointer to chars source -__SRCADDR: - ld bc, (CHARS) -__PRGRAPH0: - add a, a ; A = a * 2 (since a < 80h) ; Thanks to Metalbrain at http://foro.speccy.org - ld l, a - ld h, 0 ; HL = a * 2 (accumulator) - add hl, hl - add hl, hl ; HL = a * 8 - add hl, bc ; HL = CHARS address -__PRGRAPH: - ex de, hl ; HL = Write Address, DE = CHARS address - bit 2, (iy + $47) - call nz, __BOLD -#line 139 "/zxbasic/src/arch/zx48k/library-asm/print.asm" - bit 4, (iy + $47) - call nz, __ITALIC -#line 144 "/zxbasic/src/arch/zx48k/library-asm/print.asm" - ld hl, (DFCC) - push hl - ld b, 8 ; 8 bytes per char -__PRCHAR: - ld a, (de) ; DE *must* be source, and HL destiny -PRINT_MODE: ; Which operation is used to write on the screen - ; Set it with: - ; LD A, - ; LD (PRINT_MODE), A - ; - ; Available operations: - ; NORMAL : 0h --> NOP ; OVER 0 - ; XOR : AEh --> XOR (HL) ; OVER 1 - ; OR : B6h --> OR (HL) ; PUTSPRITE - ; AND : A6h --> AND (HL) ; PUTMASK - nop ; Set to one of the values above -INVERSE_MODE: ; 00 -> NOP -> INVERSE 0 - nop ; 2F -> CPL -> INVERSE 1 - ld (hl), a - inc de - inc h ; Next line - djnz __PRCHAR - pop hl +MEM_FREE: +__MEM_FREE: ; Frees the block pointed by HL + ; HL DE BC & AF modified + PROC + LOCAL __MEM_LOOP2 + LOCAL __MEM_LINK_PREV + LOCAL __MEM_JOIN_TEST + LOCAL __MEM_BLOCK_JOIN + ld a, h + or l + ret z ; Return if NULL pointer + dec hl + dec hl + ld b, h + ld c, l ; BC = Block pointer + ld hl, ZXBASIC_MEM_HEAP ; This label point to the heap start +__MEM_LOOP2: inc hl - ld (DFCC), hl - ld hl, (DFCCL) ; current ATTR Pos - push hl - call __SET_ATTR - pop hl + inc hl ; Next block ptr + ld e, (hl) inc hl - ld (DFCCL),hl - exx - ret - ; ------------- SPECIAL CHARS (< 32) ----------------- -__PRINT_SPECIAL: ; Jumps here if it is a special char - ld hl, __PRINT_TABLE - jp JUMP_HL_PLUS_2A -PRINT_EOL: ; Called WHENEVER there is no ";" at end of PRINT sentence - exx -__PRINT_0Dh: ; Called WHEN printing CHR$(13) - ld hl, (S_POSN) - dec l - jr nz, 1f - dec h - jr nz, 1f - inc h - push hl - call __SCROLL_SCR - pop hl -#line 210 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -1: - ld l, 1 -__PRINT_EOL_END: - call SET_SCR_ADDR - exx - ret -__PRINT_COM: - exx + ld d, (hl) ; Block next ptr + ex de, hl ; DE = &(block->next); HL = block->next + ld a, h ; HL == NULL? + or l + jp z, __MEM_LINK_PREV; if so, link with previous + or a ; Clear carry flag + sbc hl, bc ; Carry if BC > HL => This block if before + add hl, bc ; Restores HL, preserving Carry flag + jp c, __MEM_LOOP2 ; This block is before. Keep searching PASS the block + ;------ At this point current HL is PAST BC, so we must link (DE) with BC, and HL in BC->next +__MEM_LINK_PREV: ; Link (DE) with BC, and BC->next with HL + ex de, hl push hl - push de - push bc - call PRINT_COMMA - pop bc - pop de + dec hl + ld (hl), c + inc hl + ld (hl), b ; (DE) <- BC + ld h, b ; HL <- BC (Free block ptr) + ld l, c + inc hl ; Skip block length (2 bytes) + inc hl + ld (hl), e ; Block->next = DE + inc hl + ld (hl), d + ; --- LINKED ; HL = &(BC->next) + 2 + call __MEM_JOIN_TEST pop hl - ret -__PRINT_TAB: - ld hl, __PRINT_TAB1 - jr __PRINT_SET_STATE -__PRINT_TAB1: - ld (MEM0), a - ld hl, __PRINT_TAB2 - jr __PRINT_SET_STATE -__PRINT_TAB2: - ld a, (MEM0) ; Load tab code (ignore the current one) - ld hl, __PRINT_START - ld (PRINT_JUMP_STATE), hl - exx - push hl - push bc - push de - call PRINT_TAB - pop de - pop bc +__MEM_JOIN_TEST: ; Checks for fragmented contiguous blocks and joins them + ; hl = Ptr to current block + 2 + ld d, (hl) + dec hl + ld e, (hl) + dec hl + ld b, (hl) ; Loads block length into BC + dec hl + ld c, (hl) ; + push hl ; Saves it for later + add hl, bc ; Adds its length. If HL == DE now, it must be joined + or a + sbc hl, de ; If Z, then HL == DE => We must join pop hl + ret nz +__MEM_BLOCK_JOIN: ; Joins current block (pointed by HL) with next one (pointed by DE). HL->length already in BC + push hl ; Saves it for later + ex de, hl + ld e, (hl) ; DE -> block->next->length + inc hl + ld d, (hl) + inc hl + ex de, hl ; DE = &(block->next) + add hl, bc ; HL = Total Length + ld b, h + ld c, l ; BC = Total Length + ex de, hl + ld e, (hl) + inc hl + ld d, (hl) ; DE = block->next + pop hl ; Recovers Pointer to block + ld (hl), c + inc hl + ld (hl), b ; Length Saved + inc hl + ld (hl), e + inc hl + ld (hl), d ; Next saved ret -__PRINT_AT: - ld hl, __PRINT_AT1 - jr __PRINT_SET_STATE -__PRINT_NOP: -__PRINT_RESTART: - ld hl, __PRINT_START -__PRINT_SET_STATE: - ld (PRINT_JUMP_STATE), hl ; Saves next entry call - exx - ret -__PRINT_AT1: ; Jumps here if waiting for 1st parameter - ld hl, (S_POSN) - ld h, a - ld a, SCR_ROWS - sub h - ld (S_POSN + 1), a - ld hl, __PRINT_AT2 - jr __PRINT_SET_STATE -__PRINT_AT2: - call __LOAD_S_POSN - ld e, a - call __SAVE_S_POSN - jr __PRINT_RESTART -__PRINT_DEL: - call __LOAD_S_POSN ; Gets current screen position - dec e - ld a, -1 - cp e - jr nz, 3f - ld e, SCR_COLS - 2 - dec d - cp d - jr nz, 3f - ld d, SCR_ROWS - 1 -3: - call __SAVE_S_POSN - exx - ret -__PRINT_INK: - ld hl, __PRINT_INK2 - jr __PRINT_SET_STATE -__PRINT_INK2: - call INK_TMP - jr __PRINT_RESTART -__PRINT_PAP: - ld hl, __PRINT_PAP2 - jr __PRINT_SET_STATE -__PRINT_PAP2: - call PAPER_TMP - jr __PRINT_RESTART -__PRINT_FLA: - ld hl, __PRINT_FLA2 - jr __PRINT_SET_STATE -__PRINT_FLA2: - call FLASH_TMP - jr __PRINT_RESTART -__PRINT_BRI: - ld hl, __PRINT_BRI2 - jr __PRINT_SET_STATE -__PRINT_BRI2: - call BRIGHT_TMP - jr __PRINT_RESTART -__PRINT_INV: - ld hl, __PRINT_INV2 - jr __PRINT_SET_STATE -__PRINT_INV2: - call INVERSE_TMP - jr __PRINT_RESTART -__PRINT_OVR: - ld hl, __PRINT_OVR2 - jr __PRINT_SET_STATE -__PRINT_OVR2: - call OVER_TMP - jr __PRINT_RESTART -__PRINT_BOLD: - ld hl, __PRINT_BOLD2 - jp __PRINT_SET_STATE -__PRINT_BOLD2: - call BOLD_TMP - jp __PRINT_RESTART -#line 354 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -__PRINT_ITA: - ld hl, __PRINT_ITA2 - jp __PRINT_SET_STATE -__PRINT_ITA2: - call ITALIC_TMP - jp __PRINT_RESTART -#line 364 "/zxbasic/src/arch/zx48k/library-asm/print.asm" - LOCAL __BOLD -__BOLD: - push hl - ld hl, MEM0 - ld b, 8 -1: - ld a, (de) - ld c, a - rlca - or c - ld (hl), a + ENDP + pop namespace +#line 73 "zx48k/lcd7.bas" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/loadstr.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/alloc.asm" +; vim: ts=4:et:sw=4: + ; Copyleft (K) by Jose M. Rodriguez de la Rosa + ; (a.k.a. Boriel) +; http://www.boriel.com + ; + ; This ASM library is licensed under the MIT license + ; you can use it for any purpose (even for commercial + ; closed source programs). + ; + ; Please read the MIT license on the internet + ; ----- IMPLEMENTATION NOTES ------ + ; The heap is implemented as a linked list of free blocks. +; Each free block contains this info: + ; + ; +----------------+ <-- HEAP START + ; | Size (2 bytes) | + ; | 0 | <-- Size = 0 => DUMMY HEADER BLOCK + ; +----------------+ + ; | Next (2 bytes) |---+ + ; +----------------+ <-+ + ; | Size (2 bytes) | + ; +----------------+ + ; | Next (2 bytes) |---+ + ; +----------------+ | + ; | | | <-- If Size > 4, then this contains (size - 4) bytes + ; | (0 if Size = 4)| | + ; +----------------+ <-+ + ; | Size (2 bytes) | + ; +----------------+ + ; | Next (2 bytes) |---+ + ; +----------------+ | + ; | | | + ; | (0 if Size = 4)| | + ; +----------------+ | + ; | <-- This zone is in use (Already allocated) + ; +----------------+ <-+ + ; | Size (2 bytes) | + ; +----------------+ + ; | Next (2 bytes) |---+ + ; +----------------+ | + ; | | | + ; | (0 if Size = 4)| | + ; +----------------+ <-+ + ; | Next (2 bytes) |--> NULL => END OF LIST + ; | 0 = NULL | + ; +----------------+ + ; | | + ; | (0 if Size = 4)| + ; +----------------+ + ; When a block is FREED, the previous and next pointers are examined to see + ; if we can defragment the heap. If the block to be freed is just next to the + ; previous, or to the next (or both) they will be converted into a single + ; block (so defragmented). + ; MEMORY MANAGER + ; + ; This library must be initialized calling __MEM_INIT with + ; HL = BLOCK Start & DE = Length. + ; An init directive is useful for initialization routines. + ; They will be added automatically if needed. + ; --------------------------------------------------------------------- + ; MEM_ALLOC + ; Allocates a block of memory in the heap. + ; + ; Parameters + ; BC = Length of requested memory block + ; +; Returns: + ; HL = Pointer to the allocated block in memory. Returns 0 (NULL) + ; if the block could not be allocated (out of memory) + ; --------------------------------------------------------------------- + push namespace core +MEM_ALLOC: +__MEM_ALLOC: ; Returns the 1st free block found of the given length (in BC) + PROC + LOCAL __MEM_LOOP + LOCAL __MEM_DONE + LOCAL __MEM_SUBTRACT + LOCAL __MEM_START + LOCAL TEMP, TEMP0 + TEMP EQU TEMP0 + 1 + ld hl, 0 + ld (TEMP), hl +__MEM_START: + ld hl, ZXBASIC_MEM_HEAP ; This label point to the heap start + inc bc + inc bc ; BC = BC + 2 ; block size needs 2 extra bytes for hidden pointer +__MEM_LOOP: ; Loads lengh at (HL, HL+). If Lenght >= BC, jump to __MEM_DONE + ld a, h ; HL = NULL (No memory available?) + or l +#line 113 "/zxbasic/src/arch/zx48k/library-asm/alloc.asm" + ret z ; NULL +#line 115 "/zxbasic/src/arch/zx48k/library-asm/alloc.asm" + ; HL = Pointer to Free block + ld e, (hl) inc hl - inc de - djnz 1b + ld d, (hl) + inc hl ; DE = Block Length + push hl ; HL = *pointer to -> next block + ex de, hl + or a ; CF = 0 + sbc hl, bc ; FREE >= BC (Length) (HL = BlockLength - Length) + jp nc, __MEM_DONE pop hl - ld de, MEM0 - ret -#line 385 "/zxbasic/src/arch/zx48k/library-asm/print.asm" - LOCAL __ITALIC -__ITALIC: - push hl - ld hl, MEM0 + ld (TEMP), hl ex de, hl - ld bc, 8 - ldir - ld hl, MEM0 - srl (hl) - inc hl - srl (hl) - inc hl - srl (hl) - inc hl - inc hl + ld e, (hl) inc hl - sla (hl) + ld d, (hl) + ex de, hl + jp __MEM_LOOP +__MEM_DONE: ; A free block has been found. + ; Check if at least 4 bytes remains free (HL >= 4) + push hl + exx ; exx to preserve bc + pop hl + ld bc, 4 + or a + sbc hl, bc + exx + jp nc, __MEM_SUBTRACT + ; At this point... + ; less than 4 bytes remains free. So we return this block entirely + ; We must link the previous block with the next to this one + ; (DE) => Pointer to next block + ; (TEMP) => &(previous->next) + pop hl ; Discard current block pointer + push de + ex de, hl ; DE = Previous block pointer; (HL) = Next block pointer + ld a, (hl) inc hl - sla (hl) + ld h, (hl) + ld l, a ; HL = (HL) + ex de, hl ; HL = Previous block pointer; DE = Next block pointer +TEMP0: + ld hl, 0 ; Pre-previous block pointer + ld (hl), e inc hl - sla (hl) - pop hl - ld de, MEM0 - ret -#line 413 "/zxbasic/src/arch/zx48k/library-asm/print.asm" - LOCAL __SCROLL_SCR -#line 487 "/zxbasic/src/arch/zx48k/library-asm/print.asm" - __SCROLL_SCR EQU 0DFEh ; Use ROM SCROLL -#line 489 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -#line 490 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -PRINT_COMMA: - call __LOAD_S_POSN - ld a, e - and 16 - add a, 16 -PRINT_TAB: - ; Tabulates the number of spaces in A register - ; If the current cursor position is already A, does nothing - PROC - LOCAL LOOP - call __LOAD_S_POSN ; e = current row - sub e - and 31 - ret z - ld b, a -LOOP: - ld a, ' ' - call __PRINTCHAR - djnz LOOP + ld (hl), d ; LINKED + pop hl ; Returning block. ret - ENDP -PRINT_AT: ; Changes cursor to ROW, COL - ; COL in A register - ; ROW in stack - pop hl ; Ret address - ex (sp), hl ; callee H = ROW - ld l, a +__MEM_SUBTRACT: + ; At this point we have to store HL value (Length - BC) into (DE - 2) ex de, hl - call __IN_SCREEN - ret nc ; Return if out of screen - jp __SAVE_S_POSN - LOCAL __PRINT_COM - LOCAL __PRINT_AT1 - LOCAL __PRINT_AT2 - LOCAL __PRINT_BOLD - LOCAL __PRINT_ITA - LOCAL __PRINT_INK - LOCAL __PRINT_PAP - LOCAL __PRINT_SET_STATE - LOCAL __PRINT_TABLE - LOCAL __PRINT_TAB, __PRINT_TAB1, __PRINT_TAB2 - LOCAL __PRINT_ITA2 -#line 546 "/zxbasic/src/arch/zx48k/library-asm/print.asm" - LOCAL __PRINT_BOLD2 -#line 552 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -__PRINT_TABLE: ; Jump table for 0 .. 22 codes - DW __PRINT_NOP ; 0 - DW __PRINT_NOP ; 1 - DW __PRINT_NOP ; 2 - DW __PRINT_NOP ; 3 - DW __PRINT_NOP ; 4 - DW __PRINT_NOP ; 5 - DW __PRINT_COM ; 6 COMMA - DW __PRINT_NOP ; 7 - DW __PRINT_DEL ; 8 DEL - DW __PRINT_NOP ; 9 - DW __PRINT_NOP ; 10 - DW __PRINT_NOP ; 11 - DW __PRINT_NOP ; 12 - DW __PRINT_0Dh ; 13 - DW __PRINT_BOLD ; 14 - DW __PRINT_ITA ; 15 - DW __PRINT_INK ; 16 - DW __PRINT_PAP ; 17 - DW __PRINT_FLA ; 18 - DW __PRINT_BRI ; 19 - DW __PRINT_INV ; 20 - DW __PRINT_OVR ; 21 - DW __PRINT_AT ; 22 AT - DW __PRINT_TAB ; 23 TAB + dec hl + ld (hl), d + dec hl + ld (hl), e ; Store new block length + add hl, de ; New length + DE => free-block start + pop de ; Remove previous HL off the stack + ld (hl), c ; Store length on its 1st word + inc hl + ld (hl), b + inc hl ; Return hl + ret ENDP pop namespace -#line 5 "/zxbasic/src/arch/zx48k/library-asm/print_eol_attr.asm" +#line 2 "/zxbasic/src/arch/zx48k/library-asm/loadstr.asm" + ; Loads a string (ptr) from HL + ; and duplicates it on dynamic memory again + ; Finally, it returns result pointer in HL push namespace core -PRINT_EOL_ATTR: - call PRINT_EOL - jp COPY_ATTR +__ILOADSTR: ; This is the indirect pointer entry HL = (HL) + ld a, h + or l + ret z + ld a, (hl) + inc hl + ld h, (hl) + ld l, a +__LOADSTR: ; __FASTCALL__ entry + ld a, h + or l + ret z ; Return if NULL + ld c, (hl) + inc hl + ld b, (hl) + dec hl ; BC = LEN(a$) + inc bc + inc bc ; BC = LEN(a$) + 2 (two bytes for length) + push hl + push bc + call __MEM_ALLOC + pop bc ; Recover length + pop de ; Recover origin + ld a, h + or l + ret z ; Return if NULL (No memory) + ex de, hl ; ldir takes HL as source, DE as destiny, so SWAP HL,DE + push de ; Saves destiny start + ldir ; Copies string (length number included) + pop hl ; Recovers destiny in hl as result + ret pop namespace -#line 73 "zx48k/lcd7.bas" +#line 74 "zx48k/lcd7.bas" #line 1 "/zxbasic/src/arch/zx48k/library-asm/printstr.asm" ; PRINT command routine ; Prints string pointed by HL @@ -1523,7 +1514,7 @@ __PRINT_STR: jp __PRINT_STR_LOOP ENDP pop namespace -#line 74 "zx48k/lcd7.bas" +#line 76 "zx48k/lcd7.bas" #line 1 "/zxbasic/src/arch/zx48k/library-asm/pstorestr.asm" ; vim:ts=4:et:sw=4 ; @@ -1786,5 +1777,5 @@ __PSTORE_STR: add hl, bc jp __STORE_STR pop namespace -#line 75 "zx48k/lcd7.bas" +#line 77 "zx48k/lcd7.bas" END diff --git a/tests/functional/zx48k/lcd8.asm b/tests/functional/zx48k/lcd8.asm index c6f26db27..02087c7c4 100644 --- a/tests/functional/zx48k/lcd8.asm +++ b/tests/functional/zx48k/lcd8.asm @@ -48,11 +48,12 @@ _printerPutString: push ix ld ix, 0 add ix, sp + call .core.COPY_ATTR ld l, (ix+4) ld h, (ix+5) xor a call .core.__PRINTSTR - call .core.PRINT_EOL_ATTR + call .core.PRINT_EOL _printerPutString__leave: ex af, af' exx @@ -97,334 +98,42 @@ _Frame__leave: DEFB 4Fh DEFB 4Bh ;; --- end of user code --- -#line 1 "/zxbasic/src/arch/zx48k/library-asm/free.asm" -; vim: ts=4:et:sw=4: - ; Copyleft (K) by Jose M. Rodriguez de la Rosa - ; (a.k.a. Boriel) -; http://www.boriel.com - ; - ; This ASM library is licensed under the BSD license - ; you can use it for any purpose (even for commercial - ; closed source programs). - ; - ; Please read the BSD license on the internet - ; ----- IMPLEMENTATION NOTES ------ - ; The heap is implemented as a linked list of free blocks. -; Each free block contains this info: - ; - ; +----------------+ <-- HEAP START - ; | Size (2 bytes) | - ; | 0 | <-- Size = 0 => DUMMY HEADER BLOCK - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ <-+ - ; | Size (2 bytes) | - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ | - ; | | | <-- If Size > 4, then this contains (size - 4) bytes - ; | (0 if Size = 4)| | - ; +----------------+ <-+ - ; | Size (2 bytes) | - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ | - ; | | | - ; | (0 if Size = 4)| | - ; +----------------+ | - ; | <-- This zone is in use (Already allocated) - ; +----------------+ <-+ - ; | Size (2 bytes) | - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ | - ; | | | - ; | (0 if Size = 4)| | - ; +----------------+ <-+ - ; | Next (2 bytes) |--> NULL => END OF LIST - ; | 0 = NULL | - ; +----------------+ - ; | | - ; | (0 if Size = 4)| - ; +----------------+ - ; When a block is FREED, the previous and next pointers are examined to see - ; if we can defragment the heap. If the block to be breed is just next to the - ; previous, or to the next (or both) they will be converted into a single - ; block (so defragmented). - ; MEMORY MANAGER - ; - ; This library must be initialized calling __MEM_INIT with - ; HL = BLOCK Start & DE = Length. - ; An init directive is useful for initialization routines. - ; They will be added automatically if needed. -#line 1 "/zxbasic/src/arch/zx48k/library-asm/heapinit.asm" -; vim: ts=4:et:sw=4: - ; Copyleft (K) by Jose M. Rodriguez de la Rosa - ; (a.k.a. Boriel) -; http://www.boriel.com - ; - ; This ASM library is licensed under the BSD license - ; you can use it for any purpose (even for commercial - ; closed source programs). - ; - ; Please read the BSD license on the internet - ; ----- IMPLEMENTATION NOTES ------ - ; The heap is implemented as a linked list of free blocks. -; Each free block contains this info: - ; - ; +----------------+ <-- HEAP START - ; | Size (2 bytes) | - ; | 0 | <-- Size = 0 => DUMMY HEADER BLOCK - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ <-+ - ; | Size (2 bytes) | - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ | - ; | | | <-- If Size > 4, then this contains (size - 4) bytes - ; | (0 if Size = 4)| | - ; +----------------+ <-+ - ; | Size (2 bytes) | - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ | - ; | | | - ; | (0 if Size = 4)| | - ; +----------------+ | - ; | <-- This zone is in use (Already allocated) - ; +----------------+ <-+ - ; | Size (2 bytes) | - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ | - ; | | | - ; | (0 if Size = 4)| | - ; +----------------+ <-+ - ; | Next (2 bytes) |--> NULL => END OF LIST - ; | 0 = NULL | - ; +----------------+ - ; | | - ; | (0 if Size = 4)| - ; +----------------+ - ; When a block is FREED, the previous and next pointers are examined to see - ; if we can defragment the heap. If the block to be breed is just next to the - ; previous, or to the next (or both) they will be converted into a single - ; block (so defragmented). - ; MEMORY MANAGER - ; - ; This library must be initialized calling __MEM_INIT with - ; HL = BLOCK Start & DE = Length. - ; An init directive is useful for initialization routines. - ; They will be added automatically if needed. - ; --------------------------------------------------------------------- - ; __MEM_INIT must be called to initalize this library with the - ; standard parameters - ; --------------------------------------------------------------------- - push namespace core -__MEM_INIT: ; Initializes the library using (RAMTOP) as start, and - ld hl, ZXBASIC_MEM_HEAP ; Change this with other address of heap start - ld de, ZXBASIC_HEAP_SIZE ; Change this with your size - ; --------------------------------------------------------------------- - ; __MEM_INIT2 initalizes this library -; Parameters: -; HL : Memory address of 1st byte of the memory heap -; DE : Length in bytes of the Memory Heap - ; --------------------------------------------------------------------- -__MEM_INIT2: - ; HL as TOP - PROC - dec de - dec de - dec de - dec de ; DE = length - 4; HL = start - ; This is done, because we require 4 bytes for the empty dummy-header block - xor a - ld (hl), a - inc hl - ld (hl), a ; First "free" block is a header: size=0, Pointer=&(Block) + 4 - inc hl - ld b, h - ld c, l - inc bc - inc bc ; BC = starts of next block - ld (hl), c - inc hl - ld (hl), b - inc hl ; Pointer to next block - ld (hl), e - inc hl - ld (hl), d - inc hl ; Block size (should be length - 4 at start); This block contains all the available memory - ld (hl), a ; NULL (0000h) ; No more blocks (a list with a single block) - inc hl - ld (hl), a - ld a, 201 - ld (__MEM_INIT), a; "Pokes" with a RET so ensure this routine is not called again - ret - ENDP - pop namespace -#line 69 "/zxbasic/src/arch/zx48k/library-asm/free.asm" - ; --------------------------------------------------------------------- - ; MEM_FREE - ; Frees a block of memory - ; -; Parameters: - ; HL = Pointer to the block to be freed. If HL is NULL (0) nothing - ; is done - ; --------------------------------------------------------------------- - push namespace core -MEM_FREE: -__MEM_FREE: ; Frees the block pointed by HL - ; HL DE BC & AF modified - PROC - LOCAL __MEM_LOOP2 - LOCAL __MEM_LINK_PREV - LOCAL __MEM_JOIN_TEST - LOCAL __MEM_BLOCK_JOIN - ld a, h - or l - ret z ; Return if NULL pointer - dec hl - dec hl - ld b, h - ld c, l ; BC = Block pointer - ld hl, ZXBASIC_MEM_HEAP ; This label point to the heap start -__MEM_LOOP2: - inc hl - inc hl ; Next block ptr - ld e, (hl) - inc hl - ld d, (hl) ; Block next ptr - ex de, hl ; DE = &(block->next); HL = block->next - ld a, h ; HL == NULL? - or l - jp z, __MEM_LINK_PREV; if so, link with previous - or a ; Clear carry flag - sbc hl, bc ; Carry if BC > HL => This block if before - add hl, bc ; Restores HL, preserving Carry flag - jp c, __MEM_LOOP2 ; This block is before. Keep searching PASS the block - ;------ At this point current HL is PAST BC, so we must link (DE) with BC, and HL in BC->next -__MEM_LINK_PREV: ; Link (DE) with BC, and BC->next with HL - ex de, hl - push hl - dec hl - ld (hl), c - inc hl - ld (hl), b ; (DE) <- BC - ld h, b ; HL <- BC (Free block ptr) - ld l, c - inc hl ; Skip block length (2 bytes) - inc hl - ld (hl), e ; Block->next = DE - inc hl - ld (hl), d - ; --- LINKED ; HL = &(BC->next) + 2 - call __MEM_JOIN_TEST - pop hl -__MEM_JOIN_TEST: ; Checks for fragmented contiguous blocks and joins them - ; hl = Ptr to current block + 2 - ld d, (hl) - dec hl - ld e, (hl) - dec hl - ld b, (hl) ; Loads block length into BC - dec hl - ld c, (hl) ; - push hl ; Saves it for later - add hl, bc ; Adds its length. If HL == DE now, it must be joined - or a - sbc hl, de ; If Z, then HL == DE => We must join - pop hl - ret nz -__MEM_BLOCK_JOIN: ; Joins current block (pointed by HL) with next one (pointed by DE). HL->length already in BC - push hl ; Saves it for later - ex de, hl - ld e, (hl) ; DE -> block->next->length - inc hl - ld d, (hl) - inc hl - ex de, hl ; DE = &(block->next) - add hl, bc ; HL = Total Length - ld b, h - ld c, l ; BC = Total Length - ex de, hl - ld e, (hl) - inc hl - ld d, (hl) ; DE = block->next - pop hl ; Recovers Pointer to block - ld (hl), c - inc hl - ld (hl), b ; Length Saved - inc hl - ld (hl), e - inc hl - ld (hl), d ; Next saved - ret - ENDP - pop namespace -#line 73 "zx48k/lcd8.bas" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/loadstr.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/alloc.asm" -; vim: ts=4:et:sw=4: - ; Copyleft (K) by Jose M. Rodriguez de la Rosa - ; (a.k.a. Boriel) -; http://www.boriel.com - ; - ; This ASM library is licensed under the MIT license - ; you can use it for any purpose (even for commercial - ; closed source programs). - ; - ; Please read the MIT license on the internet - ; ----- IMPLEMENTATION NOTES ------ - ; The heap is implemented as a linked list of free blocks. -; Each free block contains this info: - ; - ; +----------------+ <-- HEAP START - ; | Size (2 bytes) | - ; | 0 | <-- Size = 0 => DUMMY HEADER BLOCK - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ <-+ - ; | Size (2 bytes) | - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ | - ; | | | <-- If Size > 4, then this contains (size - 4) bytes - ; | (0 if Size = 4)| | - ; +----------------+ <-+ - ; | Size (2 bytes) | - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ | - ; | | | - ; | (0 if Size = 4)| | - ; +----------------+ | - ; | <-- This zone is in use (Already allocated) - ; +----------------+ <-+ - ; | Size (2 bytes) | - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ | - ; | | | - ; | (0 if Size = 4)| | - ; +----------------+ <-+ - ; | Next (2 bytes) |--> NULL => END OF LIST - ; | 0 = NULL | - ; +----------------+ - ; | | - ; | (0 if Size = 4)| - ; +----------------+ - ; When a block is FREED, the previous and next pointers are examined to see - ; if we can defragment the heap. If the block to be freed is just next to the - ; previous, or to the next (or both) they will be converted into a single - ; block (so defragmented). - ; MEMORY MANAGER - ; - ; This library must be initialized calling __MEM_INIT with - ; HL = BLOCK Start & DE = Length. - ; An init directive is useful for initialization routines. - ; They will be added automatically if needed. +#line 1 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +; vim:ts=4:sw=4:et: + ; PRINT command routine + ; Does not print attribute. Use PRINT_STR or PRINT_NUM for that +#line 1 "/zxbasic/src/arch/zx48k/library-asm/sposn.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/sysvars.asm" + ;; ----------------------------------------------------------------------- + ;; ZX Basic System Vars + ;; Some of them will be mapped over Sinclair ROM ones for compatibility + ;; ----------------------------------------------------------------------- + push namespace core +SCREEN_ADDR: DW 16384 ; Screen address (can be pointed to other place to use a screen buffer) +SCREEN_ATTR_ADDR: DW 22528 ; Screen attribute address (ditto.) + ; These are mapped onto ZX Spectrum ROM VARS + CHARS EQU 23606 ; Pointer to ROM/RAM Charset + TVFLAGS EQU 23612 ; TV Flags + UDG EQU 23675 ; Pointer to UDG Charset + COORDS EQU 23677 ; Last PLOT coordinates + FLAGS2 EQU 23681 ; + ECHO_E EQU 23682 ; + DFCC EQU 23684 ; Next screen addr for PRINT + DFCCL EQU 23686 ; Next screen attr for PRINT + S_POSN EQU 23688 + ATTR_P EQU 23693 ; Current Permanent ATTRS set with INK, PAPER, etc commands + ATTR_T EQU 23695 ; temporary ATTRIBUTES + P_FLAG EQU 23697 ; + MEM0 EQU 23698 ; Temporary memory buffer used by ROM chars + SCR_COLS EQU 33 ; Screen with in columns + 1 + SCR_ROWS EQU 24 ; Screen height in rows + SCR_SIZE EQU (SCR_ROWS << 8) + SCR_COLS + pop namespace +#line 2 "/zxbasic/src/arch/zx48k/library-asm/sposn.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/attr.asm" + ; Attribute routines +; vim:ts=4:et:sw: #line 1 "/zxbasic/src/arch/zx48k/library-asm/error.asm" ; Simple error control routines ; vim:ts=4:et: @@ -459,460 +168,795 @@ __STOP: ld (ERR_NR), a ret pop namespace -#line 69 "/zxbasic/src/arch/zx48k/library-asm/alloc.asm" - ; --------------------------------------------------------------------- - ; MEM_ALLOC - ; Allocates a block of memory in the heap. - ; - ; Parameters - ; BC = Length of requested memory block - ; -; Returns: - ; HL = Pointer to the allocated block in memory. Returns 0 (NULL) - ; if the block could not be allocated (out of memory) - ; --------------------------------------------------------------------- +#line 6 "/zxbasic/src/arch/zx48k/library-asm/attr.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/in_screen.asm" push namespace core -MEM_ALLOC: -__MEM_ALLOC: ; Returns the 1st free block found of the given length (in BC) +__IN_SCREEN: + ; Returns NO carry if current coords (D, E) + ; are OUT of the screen limits PROC - LOCAL __MEM_LOOP - LOCAL __MEM_DONE - LOCAL __MEM_SUBTRACT - LOCAL __MEM_START - LOCAL TEMP, TEMP0 - TEMP EQU TEMP0 + 1 - ld hl, 0 - ld (TEMP), hl -__MEM_START: - ld hl, ZXBASIC_MEM_HEAP ; This label point to the heap start - inc bc - inc bc ; BC = BC + 2 ; block size needs 2 extra bytes for hidden pointer -__MEM_LOOP: ; Loads lengh at (HL, HL+). If Lenght >= BC, jump to __MEM_DONE - ld a, h ; HL = NULL (No memory available?) - or l -#line 113 "/zxbasic/src/arch/zx48k/library-asm/alloc.asm" - ret z ; NULL -#line 115 "/zxbasic/src/arch/zx48k/library-asm/alloc.asm" - ; HL = Pointer to Free block - ld e, (hl) - inc hl - ld d, (hl) - inc hl ; DE = Block Length - push hl ; HL = *pointer to -> next block - ex de, hl - or a ; CF = 0 - sbc hl, bc ; FREE >= BC (Length) (HL = BlockLength - Length) - jp nc, __MEM_DONE - pop hl - ld (TEMP), hl + LOCAL __IN_SCREEN_ERR + ld hl, SCR_SIZE + ld a, e + cp l + jr nc, __IN_SCREEN_ERR ; Do nothing and return if out of range + ld a, d + cp h + ret c ; Return if carry (OK) +__IN_SCREEN_ERR: +__OUT_OF_SCREEN_ERR: + ; Jumps here if out of screen + ld a, ERROR_OutOfScreen + jp __STOP ; Saves error code and exits + ENDP + pop namespace +#line 7 "/zxbasic/src/arch/zx48k/library-asm/attr.asm" + push namespace core +__ATTR_ADDR: + ; calc start address in DE (as (32 * d) + e) + ; Contributed by Santiago Romero at http://www.speccy.org + ld h, 0 ; 7 T-States + ld a, d ; 4 T-States + ld d, h + add a, a ; a * 2 ; 4 T-States + add a, a ; a * 4 ; 4 T-States + ld l, a ; HL = A * 4 ; 4 T-States + add hl, hl ; HL = A * 8 ; 15 T-States + add hl, hl ; HL = A * 16 ; 15 T-States + add hl, hl ; HL = A * 32 ; 15 T-States + add hl, de + ld de, (SCREEN_ATTR_ADDR) ; Adds the screen address + add hl, de + ; Return current screen address in HL + ret + ; Sets the attribute at a given screen coordinate (D, E). + ; The attribute is taken from the ATTR_T memory variable + ; Used by PRINT routines +SET_ATTR: + ; Checks for valid coords + call __IN_SCREEN + ret nc + call __ATTR_ADDR +__SET_ATTR: + ; Internal __FASTCALL__ Entry used by printing routines + ; HL contains the address of the ATTR cell to set + PROC +__SET_ATTR2: ; Sets attr from ATTR_T to (HL) which points to the scr address + ld de, (ATTR_T) ; E = ATTR_T, D = MASK_T + ld a, d + and (hl) + ld c, a ; C = current screen color, masked + ld a, d + cpl ; Negate mask + and e ; Mask current attributes + or c ; Mix them + ld (hl), a ; Store result in screen + ret + ENDP + pop namespace +#line 3 "/zxbasic/src/arch/zx48k/library-asm/sposn.asm" + ; Printing positioning library. + push namespace core + ; Loads into DE current ROW, COL print position from S_POSN mem var. +__LOAD_S_POSN: + PROC + ld de, (S_POSN) + ld hl, SCR_SIZE + or a + sbc hl, de ex de, hl + ret + ENDP + ; Saves ROW, COL from DE into S_POSN mem var. +__SAVE_S_POSN: + PROC + ld hl, SCR_SIZE + or a + sbc hl, de + ld (S_POSN), hl ; saves it again +__SET_SCR_PTR: ;; Fast + push de + call __ATTR_ADDR + ld (DFCCL), hl + pop de + ld a, d + ld c, a ; Saves it for later + and 0F8h ; Masks 3 lower bit ; zy + ld d, a + ld a, c ; Recovers it + and 07h ; MOD 7 ; y1 + rrca + rrca + rrca + or e + ld e, a + ld hl, (SCREEN_ADDR) + add hl, de ; HL = Screen address + DE + ld (DFCC), hl + ret + ENDP + pop namespace +#line 6 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/table_jump.asm" + push namespace core +JUMP_HL_PLUS_2A: ; Does JP (HL + A*2) Modifies DE. Modifies A + add a, a +JUMP_HL_PLUS_A: ; Does JP (HL + A) Modifies DE + ld e, a + ld d, 0 +JUMP_HL_PLUS_DE: ; Does JP (HL + DE) + add hl, de ld e, (hl) inc hl ld d, (hl) ex de, hl - jp __MEM_LOOP -__MEM_DONE: ; A free block has been found. - ; Check if at least 4 bytes remains free (HL >= 4) - push hl - exx ; exx to preserve bc - pop hl - ld bc, 4 +CALL_HL: + jp (hl) + pop namespace +#line 8 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/ink.asm" + ; Sets ink color in ATTR_P permanently +; Parameter: Paper color in A register + push namespace core +INK: + PROC + LOCAL __SET_INK + LOCAL __SET_INK2 + ld de, ATTR_P +__SET_INK: + cp 8 + jr nz, __SET_INK2 + inc de ; Points DE to MASK_T or MASK_P + ld a, (de) + or 7 ; Set bits 0,1,2 to enable transparency + ld (de), a + ret +__SET_INK2: + ; Another entry. This will set the ink color at location pointer by DE + and 7 ; # Gets color mod 8 + ld b, a ; Saves the color + ld a, (de) + and 0F8h ; Clears previous value + or b + ld (de), a + inc de ; Points DE to MASK_T or MASK_P + ld a, (de) + and 0F8h ; Reset bits 0,1,2 sign to disable transparency + ld (de), a ; Store new attr + ret + ; Sets the INK color passed in A register in the ATTR_T variable +INK_TMP: + ld de, ATTR_T + jp __SET_INK + ENDP + pop namespace +#line 9 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/paper.asm" + ; Sets paper color in ATTR_P permanently +; Parameter: Paper color in A register + push namespace core +PAPER: + PROC + LOCAL __SET_PAPER + LOCAL __SET_PAPER2 + ld de, ATTR_P +__SET_PAPER: + cp 8 + jr nz, __SET_PAPER2 + inc de + ld a, (de) + or 038h + ld (de), a + ret + ; Another entry. This will set the paper color at location pointer by DE +__SET_PAPER2: + and 7 ; # Remove + rlca + rlca + rlca ; a *= 8 + ld b, a ; Saves the color + ld a, (de) + and 0C7h ; Clears previous value + or b + ld (de), a + inc de ; Points to MASK_T or MASK_P accordingly + ld a, (de) + and 0C7h ; Resets bits 3,4,5 + ld (de), a + ret + ; Sets the PAPER color passed in A register in the ATTR_T variable +PAPER_TMP: + ld de, ATTR_T + jp __SET_PAPER + ENDP + pop namespace +#line 10 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/flash.asm" + ; Sets flash flag in ATTR_P permanently +; Parameter: Paper color in A register + push namespace core +FLASH: + ld hl, ATTR_P + PROC + LOCAL IS_TR + LOCAL IS_ZERO +__SET_FLASH: + ; Another entry. This will set the flash flag at location pointer by DE + cp 8 + jr z, IS_TR + ; # Convert to 0/1 or a - sbc hl, bc - exx - jp nc, __MEM_SUBTRACT - ; At this point... - ; less than 4 bytes remains free. So we return this block entirely - ; We must link the previous block with the next to this one - ; (DE) => Pointer to next block - ; (TEMP) => &(previous->next) - pop hl ; Discard current block pointer - push de - ex de, hl ; DE = Previous block pointer; (HL) = Next block pointer + jr z, IS_ZERO + ld a, 0x80 +IS_ZERO: + ld b, a ; Saves the color ld a, (hl) + and 07Fh ; Clears previous value + or b + ld (hl), a inc hl - ld h, (hl) - ld l, a ; HL = (HL) - ex de, hl ; HL = Previous block pointer; DE = Next block pointer -TEMP0: - ld hl, 0 ; Pre-previous block pointer - ld (hl), e - inc hl - ld (hl), d ; LINKED - pop hl ; Returning block. + res 7, (hl) ;Reset bit 7 to disable transparency ret -__MEM_SUBTRACT: - ; At this point we have to store HL value (Length - BC) into (DE - 2) - ex de, hl - dec hl - ld (hl), d - dec hl - ld (hl), e ; Store new block length - add hl, de ; New length + DE => free-block start - pop de ; Remove previous HL off the stack - ld (hl), c ; Store length on its 1st word - inc hl - ld (hl), b - inc hl ; Return hl +IS_TR: ; transparent + inc hl ; Points DE to MASK_T or MASK_P + set 7, (hl) ;Set bit 7 to enable transparency ret + ; Sets the FLASH flag passed in A register in the ATTR_T variable +FLASH_TMP: + ld hl, ATTR_T + jr __SET_FLASH ENDP pop namespace -#line 2 "/zxbasic/src/arch/zx48k/library-asm/loadstr.asm" - ; Loads a string (ptr) from HL - ; and duplicates it on dynamic memory again - ; Finally, it returns result pointer in HL +#line 11 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/bright.asm" + ; Sets bright flag in ATTR_P permanently +; Parameter: Paper color in A register push namespace core -__ILOADSTR: ; This is the indirect pointer entry HL = (HL) - ld a, h - or l - ret z +BRIGHT: + ld hl, ATTR_P + PROC + LOCAL IS_TR + LOCAL IS_ZERO +__SET_BRIGHT: + ; Another entry. This will set the bright flag at location pointer by DE + cp 8 + jr z, IS_TR + ; # Convert to 0/1 + or a + jr z, IS_ZERO + ld a, 0x40 +IS_ZERO: + ld b, a ; Saves the color ld a, (hl) + and 0BFh ; Clears previous value + or b + ld (hl), a inc hl - ld h, (hl) - ld l, a -__LOADSTR: ; __FASTCALL__ entry - ld a, h - or l - ret z ; Return if NULL - ld c, (hl) - inc hl - ld b, (hl) - dec hl ; BC = LEN(a$) - inc bc - inc bc ; BC = LEN(a$) + 2 (two bytes for length) - push hl - push bc - call __MEM_ALLOC - pop bc ; Recover length - pop de ; Recover origin - ld a, h - or l - ret z ; Return if NULL (No memory) - ex de, hl ; ldir takes HL as source, DE as destiny, so SWAP HL,DE - push de ; Saves destiny start - ldir ; Copies string (length number included) - pop hl ; Recovers destiny in hl as result + res 6, (hl) ;Reset bit 6 to disable transparency + ret +IS_TR: ; transparent + inc hl ; Points DE to MASK_T or MASK_P + set 6, (hl) ;Set bit 6 to enable transparency ret + ; Sets the BRIGHT flag passed in A register in the ATTR_T variable +BRIGHT_TMP: + ld hl, ATTR_T + jr __SET_BRIGHT + ENDP pop namespace -#line 74 "zx48k/lcd8.bas" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/print_eol_attr.asm" - ; Calls PRINT_EOL and then COPY_ATTR, so saves - ; 3 bytes -#line 1 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -; vim:ts=4:sw=4:et: - ; PRINT command routine - ; Does not print attribute. Use PRINT_STR or PRINT_NUM for that -#line 1 "/zxbasic/src/arch/zx48k/library-asm/sposn.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/sysvars.asm" - ;; ----------------------------------------------------------------------- - ;; ZX Basic System Vars - ;; Some of them will be mapped over Sinclair ROM ones for compatibility - ;; ----------------------------------------------------------------------- - push namespace core -SCREEN_ADDR: DW 16384 ; Screen address (can be pointed to other place to use a screen buffer) -SCREEN_ATTR_ADDR: DW 22528 ; Screen attribute address (ditto.) - ; These are mapped onto ZX Spectrum ROM VARS - CHARS EQU 23606 ; Pointer to ROM/RAM Charset - TVFLAGS EQU 23612 ; TV Flags - UDG EQU 23675 ; Pointer to UDG Charset - COORDS EQU 23677 ; Last PLOT coordinates - FLAGS2 EQU 23681 ; - ECHO_E EQU 23682 ; - DFCC EQU 23684 ; Next screen addr for PRINT - DFCCL EQU 23686 ; Next screen attr for PRINT - S_POSN EQU 23688 - ATTR_P EQU 23693 ; Current Permanent ATTRS set with INK, PAPER, etc commands - ATTR_T EQU 23695 ; temporary ATTRIBUTES - P_FLAG EQU 23697 ; - MEM0 EQU 23698 ; Temporary memory buffer used by ROM chars - SCR_COLS EQU 33 ; Screen with in columns + 1 - SCR_ROWS EQU 24 ; Screen height in rows - SCR_SIZE EQU (SCR_ROWS << 8) + SCR_COLS - pop namespace -#line 2 "/zxbasic/src/arch/zx48k/library-asm/sposn.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/attr.asm" - ; Attribute routines -; vim:ts=4:et:sw: -#line 1 "/zxbasic/src/arch/zx48k/library-asm/in_screen.asm" +#line 12 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/over.asm" + ; Sets OVER flag in P_FLAG permanently +; Parameter: OVER flag in bit 0 of A register push namespace core -__IN_SCREEN: - ; Returns NO carry if current coords (D, E) - ; are OUT of the screen limits +OVER: PROC - LOCAL __IN_SCREEN_ERR - ld hl, SCR_SIZE - ld a, e - cp l - jr nc, __IN_SCREEN_ERR ; Do nothing and return if out of range - ld a, d - cp h - ret c ; Return if carry (OK) -__IN_SCREEN_ERR: -__OUT_OF_SCREEN_ERR: - ; Jumps here if out of screen - ld a, ERROR_OutOfScreen - jp __STOP ; Saves error code and exits + ld c, a ; saves it for later + and 2 + ld hl, FLAGS2 + res 1, (HL) + or (hl) + ld (hl), a + ld a, c ; Recovers previous value + and 1 ; # Convert to 0/1 + add a, a; # Shift left 1 bit for permanent + ld hl, P_FLAG + res 1, (hl) + or (hl) + ld (hl), a + ret + ; Sets OVER flag in P_FLAG temporarily +OVER_TMP: + ld c, a ; saves it for later + and 2 ; gets bit 1; clears carry + rra + ld hl, FLAGS2 + res 0, (hl) + or (hl) + ld (hl), a + ld a, c ; Recovers previous value + and 1 + ld hl, P_FLAG + res 0, (hl) + or (hl) + ld (hl), a + jp __SET_ATTR_MODE + ENDP + pop namespace +#line 13 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/inverse.asm" + ; Sets INVERSE flag in P_FLAG permanently +; Parameter: INVERSE flag in bit 0 of A register + push namespace core +INVERSE: + PROC + and 1 ; # Convert to 0/1 + add a, a; # Shift left 3 bits for permanent + add a, a + add a, a + ld hl, P_FLAG + res 3, (hl) + or (hl) + ld (hl), a + ret + ; Sets INVERSE flag in P_FLAG temporarily +INVERSE_TMP: + and 1 + add a, a + add a, a; # Shift left 2 bits for temporary + ld hl, P_FLAG + res 2, (hl) + or (hl) + ld (hl), a + jp __SET_ATTR_MODE + ENDP + pop namespace +#line 14 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/bold.asm" + ; Sets BOLD flag in P_FLAG permanently +; Parameter: BOLD flag in bit 0 of A register + push namespace core +BOLD: + PROC + and 1 + rlca + rlca + rlca + ld hl, FLAGS2 + res 3, (HL) + or (hl) + ld (hl), a + ret + ; Sets BOLD flag in P_FLAG temporarily +BOLD_TMP: + and 1 + rlca + rlca + ld hl, FLAGS2 + res 2, (hl) + or (hl) + ld (hl), a + ret ENDP pop namespace -#line 7 "/zxbasic/src/arch/zx48k/library-asm/attr.asm" +#line 15 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/italic.asm" + ; Sets ITALIC flag in P_FLAG permanently +; Parameter: ITALIC flag in bit 0 of A register push namespace core -__ATTR_ADDR: - ; calc start address in DE (as (32 * d) + e) - ; Contributed by Santiago Romero at http://www.speccy.org - ld h, 0 ; 7 T-States - ld a, d ; 4 T-States - ld d, h - add a, a ; a * 2 ; 4 T-States - add a, a ; a * 4 ; 4 T-States - ld l, a ; HL = A * 4 ; 4 T-States - add hl, hl ; HL = A * 8 ; 15 T-States - add hl, hl ; HL = A * 16 ; 15 T-States - add hl, hl ; HL = A * 32 ; 15 T-States - add hl, de - ld de, (SCREEN_ATTR_ADDR) ; Adds the screen address - add hl, de - ; Return current screen address in HL - ret - ; Sets the attribute at a given screen coordinate (D, E). - ; The attribute is taken from the ATTR_T memory variable - ; Used by PRINT routines -SET_ATTR: - ; Checks for valid coords - call __IN_SCREEN - ret nc - call __ATTR_ADDR -__SET_ATTR: - ; Internal __FASTCALL__ Entry used by printing routines - ; HL contains the address of the ATTR cell to set +ITALIC: PROC -__SET_ATTR2: ; Sets attr from ATTR_T to (HL) which points to the scr address - ld de, (ATTR_T) ; E = ATTR_T, D = MASK_T - ld a, d - and (hl) - ld c, a ; C = current screen color, masked - ld a, d - cpl ; Negate mask - and e ; Mask current attributes - or c ; Mix them - ld (hl), a ; Store result in screen + and 1 + rrca + rrca + rrca + ld hl, FLAGS2 + res 5, (HL) + or (hl) + ld (hl), a + ret + ; Sets ITALIC flag in P_FLAG temporarily +ITALIC_TMP: + and 1 + rrca + rrca + rrca + rrca + ld hl, FLAGS2 + res 4, (hl) + or (hl) + ld (hl), a ret ENDP pop namespace -#line 3 "/zxbasic/src/arch/zx48k/library-asm/sposn.asm" - ; Printing positioning library. +#line 16 "/zxbasic/src/arch/zx48k/library-asm/print.asm" + ; Putting a comment starting with @INIT
+ ; will make the compiler to add a CALL to
+ ; It is useful for initialization routines. push namespace core - ; Loads into DE current ROW, COL print position from S_POSN mem var. -__LOAD_S_POSN: +__PRINT_INIT: ; To be called before program starts (initializes library) PROC - ld de, (S_POSN) + ld hl, __PRINT_START + ld (PRINT_JUMP_STATE), hl + ;; Clears ATTR2 flags (OVER 2, etc) + xor a + ld (FLAGS2), a + LOCAL SET_SCR_ADDR + call __LOAD_S_POSN + jp __SET_SCR_PTR + ;; Receives HL = future value of S_POSN + ;; Stores it at (S_POSN) and refresh screen pointers (ATTR, SCR) +SET_SCR_ADDR: + ld (S_POSN), hl + ex de, hl ld hl, SCR_SIZE or a sbc hl, de ex de, hl + dec e + jp __SET_SCR_PTR +__PRINTCHAR: ; Print character store in accumulator (A register) + ; Modifies H'L', B'C', A'F', D'E', A + LOCAL PO_GR_1 + LOCAL __PRCHAR + LOCAL __PRINT_JUMP + LOCAL __SRCADDR + LOCAL __PRINT_UDG + LOCAL __PRGRAPH + LOCAL __PRINT_START + PRINT_JUMP_STATE EQU __PRINT_JUMP + 2 +__PRINT_JUMP: + exx ; Switch to alternative registers + jp __PRINT_START ; Where to jump. If we print 22 (AT), next two calls jumps to AT1 and AT2 respectively +__PRINT_START: +__PRINT_CHR: + cp ' ' + jr c, __PRINT_SPECIAL ; Characters below ' ' are special ones + ex af, af' ; Saves a value (char to print) for later + ld hl, (S_POSN) + dec l + jr nz, 1f + ld l, SCR_COLS - 1 + dec h + jr nz, 2f + inc h + push hl + call __SCROLL_SCR + pop hl +#line 92 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +2: + call SET_SCR_ADDR + jr 4f +1: + ld (S_POSN), hl +4: + ex af, af' + cp 80h ; Is it a "normal" (printable) char + jr c, __SRCADDR + cp 90h ; Is it an UDG? + jr nc, __PRINT_UDG + ; Print an 8 bit pattern (80h to 8Fh) + ld b, a + call PO_GR_1 ; This ROM routine will generate the bit pattern at MEM0 + ld hl, MEM0 + jp __PRGRAPH + PO_GR_1 EQU 0B38h +__PRINT_UDG: + sub 90h ; Sub ASC code + ld bc, (UDG) + jr __PRGRAPH0 + __SOURCEADDR EQU (__SRCADDR + 1) ; Address of the pointer to chars source +__SRCADDR: + ld bc, (CHARS) +__PRGRAPH0: + add a, a ; A = a * 2 (since a < 80h) ; Thanks to Metalbrain at http://foro.speccy.org + ld l, a + ld h, 0 ; HL = a * 2 (accumulator) + add hl, hl + add hl, hl ; HL = a * 8 + add hl, bc ; HL = CHARS address +__PRGRAPH: + ex de, hl ; HL = Write Address, DE = CHARS address + bit 2, (iy + $47) + call nz, __BOLD +#line 139 "/zxbasic/src/arch/zx48k/library-asm/print.asm" + bit 4, (iy + $47) + call nz, __ITALIC +#line 144 "/zxbasic/src/arch/zx48k/library-asm/print.asm" + ld hl, (DFCC) + push hl + ld b, 8 ; 8 bytes per char +__PRCHAR: + ld a, (de) ; DE *must* be source, and HL destiny +PRINT_MODE: ; Which operation is used to write on the screen + ; Set it with: + ; LD A, + ; LD (PRINT_MODE), A + ; + ; Available operations: + ; NORMAL : 0h --> NOP ; OVER 0 + ; XOR : AEh --> XOR (HL) ; OVER 1 + ; OR : B6h --> OR (HL) ; PUTSPRITE + ; AND : A6h --> AND (HL) ; PUTMASK + nop ; Set to one of the values above +INVERSE_MODE: ; 00 -> NOP -> INVERSE 0 + nop ; 2F -> CPL -> INVERSE 1 + ld (hl), a + inc de + inc h ; Next line + djnz __PRCHAR + pop hl + inc hl + ld (DFCC), hl + ld hl, (DFCCL) ; current ATTR Pos + inc hl + ld (DFCCL), hl + dec hl + call __SET_ATTR + exx ret - ENDP - ; Saves ROW, COL from DE into S_POSN mem var. -__SAVE_S_POSN: - PROC - ld hl, SCR_SIZE - or a - sbc hl, de - ld (S_POSN), hl ; saves it again -__SET_SCR_PTR: ;; Fast + ; ------------- SPECIAL CHARS (< 32) ----------------- +__PRINT_SPECIAL: ; Jumps here if it is a special char + ld hl, __PRINT_TABLE + jp JUMP_HL_PLUS_2A +PRINT_EOL: ; Called WHENEVER there is no ";" at end of PRINT sentence + exx +__PRINT_0Dh: ; Called WHEN printing CHR$(13) + ld hl, (S_POSN) + dec l + jr nz, 1f + dec h + jr nz, 1f + inc h + push hl + call __SCROLL_SCR + pop hl +#line 209 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +1: + ld l, 1 +__PRINT_EOL_END: + call SET_SCR_ADDR + exx + ret +__PRINT_COM: + exx + push hl push de - call __ATTR_ADDR - ld (DFCCL), hl + push bc + call PRINT_COMMA + pop bc pop de - ld a, d - ld c, a ; Saves it for later - and 0F8h ; Masks 3 lower bit ; zy - ld d, a - ld a, c ; Recovers it - and 07h ; MOD 7 ; y1 - rrca - rrca - rrca - or e - ld e, a - ld hl, (SCREEN_ADDR) - add hl, de ; HL = Screen address + DE - ld (DFCC), hl + pop hl + ret +__PRINT_TAB: + ld hl, __PRINT_TAB1 + jr __PRINT_SET_STATE +__PRINT_TAB1: + ld (MEM0), a + ld hl, __PRINT_TAB2 + jr __PRINT_SET_STATE +__PRINT_TAB2: + ld a, (MEM0) ; Load tab code (ignore the current one) + ld hl, __PRINT_START + ld (PRINT_JUMP_STATE), hl + exx + push hl + push bc + push de + call PRINT_TAB + pop de + pop bc + pop hl ret - ENDP - pop namespace -#line 6 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/table_jump.asm" - push namespace core -JUMP_HL_PLUS_2A: ; Does JP (HL + A*2) Modifies DE. Modifies A - add a, a -JUMP_HL_PLUS_A: ; Does JP (HL + A) Modifies DE - ld e, a - ld d, 0 -JUMP_HL_PLUS_DE: ; Does JP (HL + DE) - add hl, de - ld e, (hl) - inc hl - ld d, (hl) - ex de, hl -CALL_HL: - jp (hl) - pop namespace -#line 8 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/ink.asm" - ; Sets ink color in ATTR_P permanently -; Parameter: Paper color in A register - push namespace core -INK: - PROC - LOCAL __SET_INK - LOCAL __SET_INK2 - ld de, ATTR_P -__SET_INK: - cp 8 - jr nz, __SET_INK2 - inc de ; Points DE to MASK_T or MASK_P - ld a, (de) - or 7 ; Set bits 0,1,2 to enable transparency - ld (de), a +__PRINT_AT: + ld hl, __PRINT_AT1 + jr __PRINT_SET_STATE +__PRINT_NOP: +__PRINT_RESTART: + ld hl, __PRINT_START +__PRINT_SET_STATE: + ld (PRINT_JUMP_STATE), hl ; Saves next entry call + exx ret -__SET_INK2: - ; Another entry. This will set the ink color at location pointer by DE - and 7 ; # Gets color mod 8 - ld b, a ; Saves the color - ld a, (de) - and 0F8h ; Clears previous value - or b - ld (de), a - inc de ; Points DE to MASK_T or MASK_P - ld a, (de) - and 0F8h ; Reset bits 0,1,2 sign to disable transparency - ld (de), a ; Store new attr +__PRINT_AT1: ; Jumps here if waiting for 1st parameter + ld hl, (S_POSN) + ld h, a + ld a, SCR_ROWS + sub h + ld (S_POSN + 1), a + ld hl, __PRINT_AT2 + jr __PRINT_SET_STATE +__PRINT_AT2: + call __LOAD_S_POSN + ld e, a + call __SAVE_S_POSN + jr __PRINT_RESTART +__PRINT_DEL: + call __LOAD_S_POSN ; Gets current screen position + dec e + ld a, -1 + cp e + jr nz, 3f + ld e, SCR_COLS - 2 + dec d + cp d + jr nz, 3f + ld d, SCR_ROWS - 1 +3: + call __SAVE_S_POSN + exx ret - ; Sets the INK color passed in A register in the ATTR_T variable -INK_TMP: - ld de, ATTR_T - jp __SET_INK - ENDP - pop namespace -#line 9 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/paper.asm" - ; Sets paper color in ATTR_P permanently -; Parameter: Paper color in A register - push namespace core -PAPER: - PROC - LOCAL __SET_PAPER - LOCAL __SET_PAPER2 - ld de, ATTR_P -__SET_PAPER: - cp 8 - jr nz, __SET_PAPER2 - inc de +__PRINT_INK: + ld hl, __PRINT_INK2 + jr __PRINT_SET_STATE +__PRINT_INK2: + call INK_TMP + jr __PRINT_RESTART +__PRINT_PAP: + ld hl, __PRINT_PAP2 + jr __PRINT_SET_STATE +__PRINT_PAP2: + call PAPER_TMP + jr __PRINT_RESTART +__PRINT_FLA: + ld hl, __PRINT_FLA2 + jr __PRINT_SET_STATE +__PRINT_FLA2: + call FLASH_TMP + jr __PRINT_RESTART +__PRINT_BRI: + ld hl, __PRINT_BRI2 + jr __PRINT_SET_STATE +__PRINT_BRI2: + call BRIGHT_TMP + jr __PRINT_RESTART +__PRINT_INV: + ld hl, __PRINT_INV2 + jr __PRINT_SET_STATE +__PRINT_INV2: + call INVERSE_TMP + jr __PRINT_RESTART +__PRINT_OVR: + ld hl, __PRINT_OVR2 + jr __PRINT_SET_STATE +__PRINT_OVR2: + call OVER_TMP + jr __PRINT_RESTART +__PRINT_BOLD: + ld hl, __PRINT_BOLD2 + jp __PRINT_SET_STATE +__PRINT_BOLD2: + call BOLD_TMP + jp __PRINT_RESTART +#line 353 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +__PRINT_ITA: + ld hl, __PRINT_ITA2 + jp __PRINT_SET_STATE +__PRINT_ITA2: + call ITALIC_TMP + jp __PRINT_RESTART +#line 363 "/zxbasic/src/arch/zx48k/library-asm/print.asm" + LOCAL __BOLD +__BOLD: + push hl + ld hl, MEM0 + ld b, 8 +1: ld a, (de) - or 038h - ld (de), a - ret - ; Another entry. This will set the paper color at location pointer by DE -__SET_PAPER2: - and 7 ; # Remove - rlca + ld c, a rlca - rlca ; a *= 8 - ld b, a ; Saves the color - ld a, (de) - and 0C7h ; Clears previous value - or b - ld (de), a - inc de ; Points to MASK_T or MASK_P accordingly - ld a, (de) - and 0C7h ; Resets bits 3,4,5 - ld (de), a - ret - ; Sets the PAPER color passed in A register in the ATTR_T variable -PAPER_TMP: - ld de, ATTR_T - jp __SET_PAPER - ENDP - pop namespace -#line 10 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/flash.asm" - ; Sets flash flag in ATTR_P permanently -; Parameter: Paper color in A register - push namespace core -FLASH: - ld hl, ATTR_P - PROC - LOCAL IS_TR - LOCAL IS_ZERO -__SET_FLASH: - ; Another entry. This will set the flash flag at location pointer by DE - cp 8 - jr z, IS_TR - ; # Convert to 0/1 - or a - jr z, IS_ZERO - ld a, 0x80 -IS_ZERO: - ld b, a ; Saves the color - ld a, (hl) - and 07Fh ; Clears previous value - or b + or c ld (hl), a inc hl - res 7, (hl) ;Reset bit 7 to disable transparency - ret -IS_TR: ; transparent - inc hl ; Points DE to MASK_T or MASK_P - set 7, (hl) ;Set bit 7 to enable transparency - ret - ; Sets the FLASH flag passed in A register in the ATTR_T variable -FLASH_TMP: - ld hl, ATTR_T - jr __SET_FLASH - ENDP - pop namespace -#line 11 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/bright.asm" - ; Sets bright flag in ATTR_P permanently -; Parameter: Paper color in A register - push namespace core -BRIGHT: - ld hl, ATTR_P - PROC - LOCAL IS_TR - LOCAL IS_ZERO -__SET_BRIGHT: - ; Another entry. This will set the bright flag at location pointer by DE - cp 8 - jr z, IS_TR - ; # Convert to 0/1 - or a - jr z, IS_ZERO - ld a, 0x40 -IS_ZERO: - ld b, a ; Saves the color - ld a, (hl) - and 0BFh ; Clears previous value - or b - ld (hl), a + inc de + djnz 1b + pop hl + ld de, MEM0 + ret +#line 384 "/zxbasic/src/arch/zx48k/library-asm/print.asm" + LOCAL __ITALIC +__ITALIC: + push hl + ld hl, MEM0 + ex de, hl + ld bc, 8 + ldir + ld hl, MEM0 + srl (hl) inc hl - res 6, (hl) ;Reset bit 6 to disable transparency + srl (hl) + inc hl + srl (hl) + inc hl + inc hl + inc hl + sla (hl) + inc hl + sla (hl) + inc hl + sla (hl) + pop hl + ld de, MEM0 ret -IS_TR: ; transparent - inc hl ; Points DE to MASK_T or MASK_P - set 6, (hl) ;Set bit 6 to enable transparency +#line 412 "/zxbasic/src/arch/zx48k/library-asm/print.asm" + LOCAL __SCROLL_SCR +#line 486 "/zxbasic/src/arch/zx48k/library-asm/print.asm" + __SCROLL_SCR EQU 0DFEh ; Use ROM SCROLL +#line 488 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 489 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +PRINT_COMMA: + call __LOAD_S_POSN + ld a, e + and 16 + add a, 16 +PRINT_TAB: + ; Tabulates the number of spaces in A register + ; If the current cursor position is already A, does nothing + PROC + LOCAL LOOP + call __LOAD_S_POSN ; e = current row + sub e + and 31 + ret z + ld b, a +LOOP: + ld a, ' ' + call __PRINTCHAR + djnz LOOP ret - ; Sets the BRIGHT flag passed in A register in the ATTR_T variable -BRIGHT_TMP: - ld hl, ATTR_T - jr __SET_BRIGHT + ENDP +PRINT_AT: ; Changes cursor to ROW, COL + ; COL in A register + ; ROW in stack + pop hl ; Ret address + ex (sp), hl ; callee H = ROW + ld l, a + ex de, hl + call __IN_SCREEN + ret nc ; Return if out of screen + jp __SAVE_S_POSN + LOCAL __PRINT_COM + LOCAL __PRINT_AT1 + LOCAL __PRINT_AT2 + LOCAL __PRINT_BOLD + LOCAL __PRINT_ITA + LOCAL __PRINT_INK + LOCAL __PRINT_PAP + LOCAL __PRINT_SET_STATE + LOCAL __PRINT_TABLE + LOCAL __PRINT_TAB, __PRINT_TAB1, __PRINT_TAB2 + LOCAL __PRINT_ITA2 +#line 545 "/zxbasic/src/arch/zx48k/library-asm/print.asm" + LOCAL __PRINT_BOLD2 +#line 551 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +__PRINT_TABLE: ; Jump table for 0 .. 22 codes + DW __PRINT_NOP ; 0 + DW __PRINT_NOP ; 1 + DW __PRINT_NOP ; 2 + DW __PRINT_NOP ; 3 + DW __PRINT_NOP ; 4 + DW __PRINT_NOP ; 5 + DW __PRINT_COM ; 6 COMMA + DW __PRINT_NOP ; 7 + DW __PRINT_DEL ; 8 DEL + DW __PRINT_NOP ; 9 + DW __PRINT_NOP ; 10 + DW __PRINT_NOP ; 11 + DW __PRINT_NOP ; 12 + DW __PRINT_0Dh ; 13 + DW __PRINT_BOLD ; 14 + DW __PRINT_ITA ; 15 + DW __PRINT_INK ; 16 + DW __PRINT_PAP ; 17 + DW __PRINT_FLA ; 18 + DW __PRINT_BRI ; 19 + DW __PRINT_INV ; 20 + DW __PRINT_OVR ; 21 + DW __PRINT_AT ; 22 AT + DW __PRINT_TAB ; 23 TAB ENDP pop namespace -#line 12 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/over.asm" - ; Sets OVER flag in P_FLAG permanently -; Parameter: OVER flag in bit 0 of A register -#line 1 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" +#line 3 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" #line 4 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" push namespace core COPY_ATTR: @@ -965,523 +1009,470 @@ __REFRESH_TMP: ret ENDP pop namespace -#line 4 "/zxbasic/src/arch/zx48k/library-asm/over.asm" - push namespace core -OVER: - PROC - ld c, a ; saves it for later - and 2 - ld hl, FLAGS2 - res 1, (HL) - or (hl) - ld (hl), a - ld a, c ; Recovers previous value - and 1 ; # Convert to 0/1 - add a, a; # Shift left 1 bit for permanent - ld hl, P_FLAG - res 1, (hl) - or (hl) - ld (hl), a - ret - ; Sets OVER flag in P_FLAG temporarily -OVER_TMP: - ld c, a ; saves it for later - and 2 ; gets bit 1; clears carry - rra - ld hl, FLAGS2 - res 0, (hl) - or (hl) - ld (hl), a - ld a, c ; Recovers previous value - and 1 - ld hl, P_FLAG - res 0, (hl) - or (hl) - ld (hl), a - jp __SET_ATTR_MODE - ENDP - pop namespace -#line 13 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/inverse.asm" - ; Sets INVERSE flag in P_FLAG permanently -; Parameter: INVERSE flag in bit 0 of A register - push namespace core -INVERSE: - PROC - and 1 ; # Convert to 0/1 - add a, a; # Shift left 3 bits for permanent - add a, a - add a, a - ld hl, P_FLAG - res 3, (hl) - or (hl) - ld (hl), a - ret - ; Sets INVERSE flag in P_FLAG temporarily -INVERSE_TMP: - and 1 - add a, a - add a, a; # Shift left 2 bits for temporary - ld hl, P_FLAG - res 2, (hl) - or (hl) - ld (hl), a - jp __SET_ATTR_MODE - ENDP - pop namespace -#line 14 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/bold.asm" - ; Sets BOLD flag in P_FLAG permanently -; Parameter: BOLD flag in bit 0 of A register - push namespace core -BOLD: - PROC - and 1 - rlca - rlca - rlca - ld hl, FLAGS2 - res 3, (HL) - or (hl) - ld (hl), a - ret - ; Sets BOLD flag in P_FLAG temporarily -BOLD_TMP: - and 1 - rlca - rlca - ld hl, FLAGS2 - res 2, (hl) - or (hl) - ld (hl), a - ret - ENDP - pop namespace -#line 15 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/italic.asm" - ; Sets ITALIC flag in P_FLAG permanently -; Parameter: ITALIC flag in bit 0 of A register +#line 74 "zx48k/lcd8.bas" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/free.asm" +; vim: ts=4:et:sw=4: + ; Copyleft (K) by Jose M. Rodriguez de la Rosa + ; (a.k.a. Boriel) +; http://www.boriel.com + ; + ; This ASM library is licensed under the BSD license + ; you can use it for any purpose (even for commercial + ; closed source programs). + ; + ; Please read the BSD license on the internet + ; ----- IMPLEMENTATION NOTES ------ + ; The heap is implemented as a linked list of free blocks. +; Each free block contains this info: + ; + ; +----------------+ <-- HEAP START + ; | Size (2 bytes) | + ; | 0 | <-- Size = 0 => DUMMY HEADER BLOCK + ; +----------------+ + ; | Next (2 bytes) |---+ + ; +----------------+ <-+ + ; | Size (2 bytes) | + ; +----------------+ + ; | Next (2 bytes) |---+ + ; +----------------+ | + ; | | | <-- If Size > 4, then this contains (size - 4) bytes + ; | (0 if Size = 4)| | + ; +----------------+ <-+ + ; | Size (2 bytes) | + ; +----------------+ + ; | Next (2 bytes) |---+ + ; +----------------+ | + ; | | | + ; | (0 if Size = 4)| | + ; +----------------+ | + ; | <-- This zone is in use (Already allocated) + ; +----------------+ <-+ + ; | Size (2 bytes) | + ; +----------------+ + ; | Next (2 bytes) |---+ + ; +----------------+ | + ; | | | + ; | (0 if Size = 4)| | + ; +----------------+ <-+ + ; | Next (2 bytes) |--> NULL => END OF LIST + ; | 0 = NULL | + ; +----------------+ + ; | | + ; | (0 if Size = 4)| + ; +----------------+ + ; When a block is FREED, the previous and next pointers are examined to see + ; if we can defragment the heap. If the block to be breed is just next to the + ; previous, or to the next (or both) they will be converted into a single + ; block (so defragmented). + ; MEMORY MANAGER + ; + ; This library must be initialized calling __MEM_INIT with + ; HL = BLOCK Start & DE = Length. + ; An init directive is useful for initialization routines. + ; They will be added automatically if needed. +#line 1 "/zxbasic/src/arch/zx48k/library-asm/heapinit.asm" +; vim: ts=4:et:sw=4: + ; Copyleft (K) by Jose M. Rodriguez de la Rosa + ; (a.k.a. Boriel) +; http://www.boriel.com + ; + ; This ASM library is licensed under the BSD license + ; you can use it for any purpose (even for commercial + ; closed source programs). + ; + ; Please read the BSD license on the internet + ; ----- IMPLEMENTATION NOTES ------ + ; The heap is implemented as a linked list of free blocks. +; Each free block contains this info: + ; + ; +----------------+ <-- HEAP START + ; | Size (2 bytes) | + ; | 0 | <-- Size = 0 => DUMMY HEADER BLOCK + ; +----------------+ + ; | Next (2 bytes) |---+ + ; +----------------+ <-+ + ; | Size (2 bytes) | + ; +----------------+ + ; | Next (2 bytes) |---+ + ; +----------------+ | + ; | | | <-- If Size > 4, then this contains (size - 4) bytes + ; | (0 if Size = 4)| | + ; +----------------+ <-+ + ; | Size (2 bytes) | + ; +----------------+ + ; | Next (2 bytes) |---+ + ; +----------------+ | + ; | | | + ; | (0 if Size = 4)| | + ; +----------------+ | + ; | <-- This zone is in use (Already allocated) + ; +----------------+ <-+ + ; | Size (2 bytes) | + ; +----------------+ + ; | Next (2 bytes) |---+ + ; +----------------+ | + ; | | | + ; | (0 if Size = 4)| | + ; +----------------+ <-+ + ; | Next (2 bytes) |--> NULL => END OF LIST + ; | 0 = NULL | + ; +----------------+ + ; | | + ; | (0 if Size = 4)| + ; +----------------+ + ; When a block is FREED, the previous and next pointers are examined to see + ; if we can defragment the heap. If the block to be breed is just next to the + ; previous, or to the next (or both) they will be converted into a single + ; block (so defragmented). + ; MEMORY MANAGER + ; + ; This library must be initialized calling __MEM_INIT with + ; HL = BLOCK Start & DE = Length. + ; An init directive is useful for initialization routines. + ; They will be added automatically if needed. + ; --------------------------------------------------------------------- + ; __MEM_INIT must be called to initalize this library with the + ; standard parameters + ; --------------------------------------------------------------------- push namespace core -ITALIC: +__MEM_INIT: ; Initializes the library using (RAMTOP) as start, and + ld hl, ZXBASIC_MEM_HEAP ; Change this with other address of heap start + ld de, ZXBASIC_HEAP_SIZE ; Change this with your size + ; --------------------------------------------------------------------- + ; __MEM_INIT2 initalizes this library +; Parameters: +; HL : Memory address of 1st byte of the memory heap +; DE : Length in bytes of the Memory Heap + ; --------------------------------------------------------------------- +__MEM_INIT2: + ; HL as TOP PROC - and 1 - rrca - rrca - rrca - ld hl, FLAGS2 - res 5, (HL) - or (hl) + dec de + dec de + dec de + dec de ; DE = length - 4; HL = start + ; This is done, because we require 4 bytes for the empty dummy-header block + xor a ld (hl), a - ret - ; Sets ITALIC flag in P_FLAG temporarily -ITALIC_TMP: - and 1 - rrca - rrca - rrca - rrca - ld hl, FLAGS2 - res 4, (hl) - or (hl) + inc hl + ld (hl), a ; First "free" block is a header: size=0, Pointer=&(Block) + 4 + inc hl + ld b, h + ld c, l + inc bc + inc bc ; BC = starts of next block + ld (hl), c + inc hl + ld (hl), b + inc hl ; Pointer to next block + ld (hl), e + inc hl + ld (hl), d + inc hl ; Block size (should be length - 4 at start); This block contains all the available memory + ld (hl), a ; NULL (0000h) ; No more blocks (a list with a single block) + inc hl ld (hl), a + ld a, 201 + ld (__MEM_INIT), a; "Pokes" with a RET so ensure this routine is not called again ret ENDP pop namespace -#line 16 "/zxbasic/src/arch/zx48k/library-asm/print.asm" - ; Putting a comment starting with @INIT
- ; will make the compiler to add a CALL to
- ; It is useful for initialization routines. +#line 69 "/zxbasic/src/arch/zx48k/library-asm/free.asm" + ; --------------------------------------------------------------------- + ; MEM_FREE + ; Frees a block of memory + ; +; Parameters: + ; HL = Pointer to the block to be freed. If HL is NULL (0) nothing + ; is done + ; --------------------------------------------------------------------- push namespace core -__PRINT_INIT: ; To be called before program starts (initializes library) - PROC - ld hl, __PRINT_START - ld (PRINT_JUMP_STATE), hl - ;; Clears ATTR2 flags (OVER 2, etc) - xor a - ld (FLAGS2), a - LOCAL SET_SCR_ADDR - call __LOAD_S_POSN - jp __SET_SCR_PTR - ;; Receives HL = future value of S_POSN - ;; Stores it at (S_POSN) and refresh screen pointers (ATTR, SCR) -SET_SCR_ADDR: - ld (S_POSN), hl - ex de, hl - ld hl, SCR_SIZE - or a - sbc hl, de - ex de, hl - dec e - jp __SET_SCR_PTR -__PRINTCHAR: ; Print character store in accumulator (A register) - ; Modifies H'L', B'C', A'F', D'E', A - LOCAL PO_GR_1 - LOCAL __PRCHAR - LOCAL __PRINT_JUMP - LOCAL __SRCADDR - LOCAL __PRINT_UDG - LOCAL __PRGRAPH - LOCAL __PRINT_START - PRINT_JUMP_STATE EQU __PRINT_JUMP + 2 -__PRINT_JUMP: - exx ; Switch to alternative registers - jp __PRINT_START ; Where to jump. If we print 22 (AT), next two calls jumps to AT1 and AT2 respectively -__PRINT_START: -__PRINT_CHR: - cp ' ' - jr c, __PRINT_SPECIAL ; Characters below ' ' are special ones - ex af, af' ; Saves a value (char to print) for later - ld hl, (S_POSN) - dec l - jr nz, 1f - ld l, SCR_COLS - 1 - dec h - jr nz, 2f - inc h - push hl - call __SCROLL_SCR - pop hl -#line 92 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -2: - call SET_SCR_ADDR - jr 4f -1: - ld (S_POSN), hl -4: - ex af, af' - cp 80h ; Is it a "normal" (printable) char - jr c, __SRCADDR - cp 90h ; Is it an UDG? - jr nc, __PRINT_UDG - ; Print an 8 bit pattern (80h to 8Fh) - ld b, a - call PO_GR_1 ; This ROM routine will generate the bit pattern at MEM0 - ld hl, MEM0 - jp __PRGRAPH - PO_GR_1 EQU 0B38h -__PRINT_UDG: - sub 90h ; Sub ASC code - ld bc, (UDG) - jr __PRGRAPH0 - __SOURCEADDR EQU (__SRCADDR + 1) ; Address of the pointer to chars source -__SRCADDR: - ld bc, (CHARS) -__PRGRAPH0: - add a, a ; A = a * 2 (since a < 80h) ; Thanks to Metalbrain at http://foro.speccy.org - ld l, a - ld h, 0 ; HL = a * 2 (accumulator) - add hl, hl - add hl, hl ; HL = a * 8 - add hl, bc ; HL = CHARS address -__PRGRAPH: - ex de, hl ; HL = Write Address, DE = CHARS address - bit 2, (iy + $47) - call nz, __BOLD -#line 139 "/zxbasic/src/arch/zx48k/library-asm/print.asm" - bit 4, (iy + $47) - call nz, __ITALIC -#line 144 "/zxbasic/src/arch/zx48k/library-asm/print.asm" - ld hl, (DFCC) - push hl - ld b, 8 ; 8 bytes per char -__PRCHAR: - ld a, (de) ; DE *must* be source, and HL destiny -PRINT_MODE: ; Which operation is used to write on the screen - ; Set it with: - ; LD A, - ; LD (PRINT_MODE), A - ; - ; Available operations: - ; NORMAL : 0h --> NOP ; OVER 0 - ; XOR : AEh --> XOR (HL) ; OVER 1 - ; OR : B6h --> OR (HL) ; PUTSPRITE - ; AND : A6h --> AND (HL) ; PUTMASK - nop ; Set to one of the values above -INVERSE_MODE: ; 00 -> NOP -> INVERSE 0 - nop ; 2F -> CPL -> INVERSE 1 - ld (hl), a - inc de - inc h ; Next line - djnz __PRCHAR - pop hl +MEM_FREE: +__MEM_FREE: ; Frees the block pointed by HL + ; HL DE BC & AF modified + PROC + LOCAL __MEM_LOOP2 + LOCAL __MEM_LINK_PREV + LOCAL __MEM_JOIN_TEST + LOCAL __MEM_BLOCK_JOIN + ld a, h + or l + ret z ; Return if NULL pointer + dec hl + dec hl + ld b, h + ld c, l ; BC = Block pointer + ld hl, ZXBASIC_MEM_HEAP ; This label point to the heap start +__MEM_LOOP2: inc hl - ld (DFCC), hl - ld hl, (DFCCL) ; current ATTR Pos - push hl - call __SET_ATTR - pop hl + inc hl ; Next block ptr + ld e, (hl) inc hl - ld (DFCCL),hl - exx - ret - ; ------------- SPECIAL CHARS (< 32) ----------------- -__PRINT_SPECIAL: ; Jumps here if it is a special char - ld hl, __PRINT_TABLE - jp JUMP_HL_PLUS_2A -PRINT_EOL: ; Called WHENEVER there is no ";" at end of PRINT sentence - exx -__PRINT_0Dh: ; Called WHEN printing CHR$(13) - ld hl, (S_POSN) - dec l - jr nz, 1f - dec h - jr nz, 1f - inc h - push hl - call __SCROLL_SCR - pop hl -#line 210 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -1: - ld l, 1 -__PRINT_EOL_END: - call SET_SCR_ADDR - exx - ret -__PRINT_COM: - exx + ld d, (hl) ; Block next ptr + ex de, hl ; DE = &(block->next); HL = block->next + ld a, h ; HL == NULL? + or l + jp z, __MEM_LINK_PREV; if so, link with previous + or a ; Clear carry flag + sbc hl, bc ; Carry if BC > HL => This block if before + add hl, bc ; Restores HL, preserving Carry flag + jp c, __MEM_LOOP2 ; This block is before. Keep searching PASS the block + ;------ At this point current HL is PAST BC, so we must link (DE) with BC, and HL in BC->next +__MEM_LINK_PREV: ; Link (DE) with BC, and BC->next with HL + ex de, hl push hl - push de - push bc - call PRINT_COMMA - pop bc - pop de + dec hl + ld (hl), c + inc hl + ld (hl), b ; (DE) <- BC + ld h, b ; HL <- BC (Free block ptr) + ld l, c + inc hl ; Skip block length (2 bytes) + inc hl + ld (hl), e ; Block->next = DE + inc hl + ld (hl), d + ; --- LINKED ; HL = &(BC->next) + 2 + call __MEM_JOIN_TEST pop hl - ret -__PRINT_TAB: - ld hl, __PRINT_TAB1 - jr __PRINT_SET_STATE -__PRINT_TAB1: - ld (MEM0), a - ld hl, __PRINT_TAB2 - jr __PRINT_SET_STATE -__PRINT_TAB2: - ld a, (MEM0) ; Load tab code (ignore the current one) - ld hl, __PRINT_START - ld (PRINT_JUMP_STATE), hl - exx - push hl - push bc - push de - call PRINT_TAB - pop de - pop bc +__MEM_JOIN_TEST: ; Checks for fragmented contiguous blocks and joins them + ; hl = Ptr to current block + 2 + ld d, (hl) + dec hl + ld e, (hl) + dec hl + ld b, (hl) ; Loads block length into BC + dec hl + ld c, (hl) ; + push hl ; Saves it for later + add hl, bc ; Adds its length. If HL == DE now, it must be joined + or a + sbc hl, de ; If Z, then HL == DE => We must join pop hl + ret nz +__MEM_BLOCK_JOIN: ; Joins current block (pointed by HL) with next one (pointed by DE). HL->length already in BC + push hl ; Saves it for later + ex de, hl + ld e, (hl) ; DE -> block->next->length + inc hl + ld d, (hl) + inc hl + ex de, hl ; DE = &(block->next) + add hl, bc ; HL = Total Length + ld b, h + ld c, l ; BC = Total Length + ex de, hl + ld e, (hl) + inc hl + ld d, (hl) ; DE = block->next + pop hl ; Recovers Pointer to block + ld (hl), c + inc hl + ld (hl), b ; Length Saved + inc hl + ld (hl), e + inc hl + ld (hl), d ; Next saved ret -__PRINT_AT: - ld hl, __PRINT_AT1 - jr __PRINT_SET_STATE -__PRINT_NOP: -__PRINT_RESTART: - ld hl, __PRINT_START -__PRINT_SET_STATE: - ld (PRINT_JUMP_STATE), hl ; Saves next entry call - exx - ret -__PRINT_AT1: ; Jumps here if waiting for 1st parameter - ld hl, (S_POSN) - ld h, a - ld a, SCR_ROWS - sub h - ld (S_POSN + 1), a - ld hl, __PRINT_AT2 - jr __PRINT_SET_STATE -__PRINT_AT2: - call __LOAD_S_POSN - ld e, a - call __SAVE_S_POSN - jr __PRINT_RESTART -__PRINT_DEL: - call __LOAD_S_POSN ; Gets current screen position - dec e - ld a, -1 - cp e - jr nz, 3f - ld e, SCR_COLS - 2 - dec d - cp d - jr nz, 3f - ld d, SCR_ROWS - 1 -3: - call __SAVE_S_POSN - exx - ret -__PRINT_INK: - ld hl, __PRINT_INK2 - jr __PRINT_SET_STATE -__PRINT_INK2: - call INK_TMP - jr __PRINT_RESTART -__PRINT_PAP: - ld hl, __PRINT_PAP2 - jr __PRINT_SET_STATE -__PRINT_PAP2: - call PAPER_TMP - jr __PRINT_RESTART -__PRINT_FLA: - ld hl, __PRINT_FLA2 - jr __PRINT_SET_STATE -__PRINT_FLA2: - call FLASH_TMP - jr __PRINT_RESTART -__PRINT_BRI: - ld hl, __PRINT_BRI2 - jr __PRINT_SET_STATE -__PRINT_BRI2: - call BRIGHT_TMP - jr __PRINT_RESTART -__PRINT_INV: - ld hl, __PRINT_INV2 - jr __PRINT_SET_STATE -__PRINT_INV2: - call INVERSE_TMP - jr __PRINT_RESTART -__PRINT_OVR: - ld hl, __PRINT_OVR2 - jr __PRINT_SET_STATE -__PRINT_OVR2: - call OVER_TMP - jr __PRINT_RESTART -__PRINT_BOLD: - ld hl, __PRINT_BOLD2 - jp __PRINT_SET_STATE -__PRINT_BOLD2: - call BOLD_TMP - jp __PRINT_RESTART -#line 354 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -__PRINT_ITA: - ld hl, __PRINT_ITA2 - jp __PRINT_SET_STATE -__PRINT_ITA2: - call ITALIC_TMP - jp __PRINT_RESTART -#line 364 "/zxbasic/src/arch/zx48k/library-asm/print.asm" - LOCAL __BOLD -__BOLD: - push hl - ld hl, MEM0 - ld b, 8 -1: - ld a, (de) - ld c, a - rlca - or c - ld (hl), a + ENDP + pop namespace +#line 75 "zx48k/lcd8.bas" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/loadstr.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/alloc.asm" +; vim: ts=4:et:sw=4: + ; Copyleft (K) by Jose M. Rodriguez de la Rosa + ; (a.k.a. Boriel) +; http://www.boriel.com + ; + ; This ASM library is licensed under the MIT license + ; you can use it for any purpose (even for commercial + ; closed source programs). + ; + ; Please read the MIT license on the internet + ; ----- IMPLEMENTATION NOTES ------ + ; The heap is implemented as a linked list of free blocks. +; Each free block contains this info: + ; + ; +----------------+ <-- HEAP START + ; | Size (2 bytes) | + ; | 0 | <-- Size = 0 => DUMMY HEADER BLOCK + ; +----------------+ + ; | Next (2 bytes) |---+ + ; +----------------+ <-+ + ; | Size (2 bytes) | + ; +----------------+ + ; | Next (2 bytes) |---+ + ; +----------------+ | + ; | | | <-- If Size > 4, then this contains (size - 4) bytes + ; | (0 if Size = 4)| | + ; +----------------+ <-+ + ; | Size (2 bytes) | + ; +----------------+ + ; | Next (2 bytes) |---+ + ; +----------------+ | + ; | | | + ; | (0 if Size = 4)| | + ; +----------------+ | + ; | <-- This zone is in use (Already allocated) + ; +----------------+ <-+ + ; | Size (2 bytes) | + ; +----------------+ + ; | Next (2 bytes) |---+ + ; +----------------+ | + ; | | | + ; | (0 if Size = 4)| | + ; +----------------+ <-+ + ; | Next (2 bytes) |--> NULL => END OF LIST + ; | 0 = NULL | + ; +----------------+ + ; | | + ; | (0 if Size = 4)| + ; +----------------+ + ; When a block is FREED, the previous and next pointers are examined to see + ; if we can defragment the heap. If the block to be freed is just next to the + ; previous, or to the next (or both) they will be converted into a single + ; block (so defragmented). + ; MEMORY MANAGER + ; + ; This library must be initialized calling __MEM_INIT with + ; HL = BLOCK Start & DE = Length. + ; An init directive is useful for initialization routines. + ; They will be added automatically if needed. + ; --------------------------------------------------------------------- + ; MEM_ALLOC + ; Allocates a block of memory in the heap. + ; + ; Parameters + ; BC = Length of requested memory block + ; +; Returns: + ; HL = Pointer to the allocated block in memory. Returns 0 (NULL) + ; if the block could not be allocated (out of memory) + ; --------------------------------------------------------------------- + push namespace core +MEM_ALLOC: +__MEM_ALLOC: ; Returns the 1st free block found of the given length (in BC) + PROC + LOCAL __MEM_LOOP + LOCAL __MEM_DONE + LOCAL __MEM_SUBTRACT + LOCAL __MEM_START + LOCAL TEMP, TEMP0 + TEMP EQU TEMP0 + 1 + ld hl, 0 + ld (TEMP), hl +__MEM_START: + ld hl, ZXBASIC_MEM_HEAP ; This label point to the heap start + inc bc + inc bc ; BC = BC + 2 ; block size needs 2 extra bytes for hidden pointer +__MEM_LOOP: ; Loads lengh at (HL, HL+). If Lenght >= BC, jump to __MEM_DONE + ld a, h ; HL = NULL (No memory available?) + or l +#line 113 "/zxbasic/src/arch/zx48k/library-asm/alloc.asm" + ret z ; NULL +#line 115 "/zxbasic/src/arch/zx48k/library-asm/alloc.asm" + ; HL = Pointer to Free block + ld e, (hl) inc hl - inc de - djnz 1b + ld d, (hl) + inc hl ; DE = Block Length + push hl ; HL = *pointer to -> next block + ex de, hl + or a ; CF = 0 + sbc hl, bc ; FREE >= BC (Length) (HL = BlockLength - Length) + jp nc, __MEM_DONE pop hl - ld de, MEM0 - ret -#line 385 "/zxbasic/src/arch/zx48k/library-asm/print.asm" - LOCAL __ITALIC -__ITALIC: - push hl - ld hl, MEM0 + ld (TEMP), hl ex de, hl - ld bc, 8 - ldir - ld hl, MEM0 - srl (hl) - inc hl - srl (hl) - inc hl - srl (hl) - inc hl - inc hl + ld e, (hl) inc hl - sla (hl) + ld d, (hl) + ex de, hl + jp __MEM_LOOP +__MEM_DONE: ; A free block has been found. + ; Check if at least 4 bytes remains free (HL >= 4) + push hl + exx ; exx to preserve bc + pop hl + ld bc, 4 + or a + sbc hl, bc + exx + jp nc, __MEM_SUBTRACT + ; At this point... + ; less than 4 bytes remains free. So we return this block entirely + ; We must link the previous block with the next to this one + ; (DE) => Pointer to next block + ; (TEMP) => &(previous->next) + pop hl ; Discard current block pointer + push de + ex de, hl ; DE = Previous block pointer; (HL) = Next block pointer + ld a, (hl) inc hl - sla (hl) + ld h, (hl) + ld l, a ; HL = (HL) + ex de, hl ; HL = Previous block pointer; DE = Next block pointer +TEMP0: + ld hl, 0 ; Pre-previous block pointer + ld (hl), e inc hl - sla (hl) - pop hl - ld de, MEM0 - ret -#line 413 "/zxbasic/src/arch/zx48k/library-asm/print.asm" - LOCAL __SCROLL_SCR -#line 487 "/zxbasic/src/arch/zx48k/library-asm/print.asm" - __SCROLL_SCR EQU 0DFEh ; Use ROM SCROLL -#line 489 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -#line 490 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -PRINT_COMMA: - call __LOAD_S_POSN - ld a, e - and 16 - add a, 16 -PRINT_TAB: - ; Tabulates the number of spaces in A register - ; If the current cursor position is already A, does nothing - PROC - LOCAL LOOP - call __LOAD_S_POSN ; e = current row - sub e - and 31 - ret z - ld b, a -LOOP: - ld a, ' ' - call __PRINTCHAR - djnz LOOP + ld (hl), d ; LINKED + pop hl ; Returning block. ret - ENDP -PRINT_AT: ; Changes cursor to ROW, COL - ; COL in A register - ; ROW in stack - pop hl ; Ret address - ex (sp), hl ; callee H = ROW - ld l, a +__MEM_SUBTRACT: + ; At this point we have to store HL value (Length - BC) into (DE - 2) ex de, hl - call __IN_SCREEN - ret nc ; Return if out of screen - jp __SAVE_S_POSN - LOCAL __PRINT_COM - LOCAL __PRINT_AT1 - LOCAL __PRINT_AT2 - LOCAL __PRINT_BOLD - LOCAL __PRINT_ITA - LOCAL __PRINT_INK - LOCAL __PRINT_PAP - LOCAL __PRINT_SET_STATE - LOCAL __PRINT_TABLE - LOCAL __PRINT_TAB, __PRINT_TAB1, __PRINT_TAB2 - LOCAL __PRINT_ITA2 -#line 546 "/zxbasic/src/arch/zx48k/library-asm/print.asm" - LOCAL __PRINT_BOLD2 -#line 552 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -__PRINT_TABLE: ; Jump table for 0 .. 22 codes - DW __PRINT_NOP ; 0 - DW __PRINT_NOP ; 1 - DW __PRINT_NOP ; 2 - DW __PRINT_NOP ; 3 - DW __PRINT_NOP ; 4 - DW __PRINT_NOP ; 5 - DW __PRINT_COM ; 6 COMMA - DW __PRINT_NOP ; 7 - DW __PRINT_DEL ; 8 DEL - DW __PRINT_NOP ; 9 - DW __PRINT_NOP ; 10 - DW __PRINT_NOP ; 11 - DW __PRINT_NOP ; 12 - DW __PRINT_0Dh ; 13 - DW __PRINT_BOLD ; 14 - DW __PRINT_ITA ; 15 - DW __PRINT_INK ; 16 - DW __PRINT_PAP ; 17 - DW __PRINT_FLA ; 18 - DW __PRINT_BRI ; 19 - DW __PRINT_INV ; 20 - DW __PRINT_OVR ; 21 - DW __PRINT_AT ; 22 AT - DW __PRINT_TAB ; 23 TAB + dec hl + ld (hl), d + dec hl + ld (hl), e ; Store new block length + add hl, de ; New length + DE => free-block start + pop de ; Remove previous HL off the stack + ld (hl), c ; Store length on its 1st word + inc hl + ld (hl), b + inc hl ; Return hl + ret ENDP pop namespace -#line 5 "/zxbasic/src/arch/zx48k/library-asm/print_eol_attr.asm" +#line 2 "/zxbasic/src/arch/zx48k/library-asm/loadstr.asm" + ; Loads a string (ptr) from HL + ; and duplicates it on dynamic memory again + ; Finally, it returns result pointer in HL push namespace core -PRINT_EOL_ATTR: - call PRINT_EOL - jp COPY_ATTR +__ILOADSTR: ; This is the indirect pointer entry HL = (HL) + ld a, h + or l + ret z + ld a, (hl) + inc hl + ld h, (hl) + ld l, a +__LOADSTR: ; __FASTCALL__ entry + ld a, h + or l + ret z ; Return if NULL + ld c, (hl) + inc hl + ld b, (hl) + dec hl ; BC = LEN(a$) + inc bc + inc bc ; BC = LEN(a$) + 2 (two bytes for length) + push hl + push bc + call __MEM_ALLOC + pop bc ; Recover length + pop de ; Recover origin + ld a, h + or l + ret z ; Return if NULL (No memory) + ex de, hl ; ldir takes HL as source, DE as destiny, so SWAP HL,DE + push de ; Saves destiny start + ldir ; Copies string (length number included) + pop hl ; Recovers destiny in hl as result + ret pop namespace -#line 75 "zx48k/lcd8.bas" +#line 76 "zx48k/lcd8.bas" #line 1 "/zxbasic/src/arch/zx48k/library-asm/printstr.asm" ; PRINT command routine ; Prints string pointed by HL @@ -1525,5 +1516,5 @@ __PRINT_STR: jp __PRINT_STR_LOOP ENDP pop namespace -#line 76 "zx48k/lcd8.bas" +#line 78 "zx48k/lcd8.bas" END diff --git a/tests/functional/zx48k/lcd9.asm b/tests/functional/zx48k/lcd9.asm index dd1e54f2d..c21c3a876 100644 --- a/tests/functional/zx48k/lcd9.asm +++ b/tests/functional/zx48k/lcd9.asm @@ -50,11 +50,12 @@ _printerPutString: push ix ld ix, 0 add ix, sp + call .core.COPY_ATTR ld l, (ix+4) ld h, (ix+5) xor a call .core.__PRINTSTR - call .core.PRINT_EOL_ATTR + call .core.PRINT_EOL _printerPutString__leave: ex af, af' exx @@ -87,334 +88,42 @@ _Frame__leave: DEFB 4Fh DEFB 4Bh ;; --- end of user code --- -#line 1 "/zxbasic/src/arch/zx48k/library-asm/free.asm" -; vim: ts=4:et:sw=4: - ; Copyleft (K) by Jose M. Rodriguez de la Rosa - ; (a.k.a. Boriel) -; http://www.boriel.com - ; - ; This ASM library is licensed under the BSD license - ; you can use it for any purpose (even for commercial - ; closed source programs). - ; - ; Please read the BSD license on the internet - ; ----- IMPLEMENTATION NOTES ------ - ; The heap is implemented as a linked list of free blocks. -; Each free block contains this info: - ; - ; +----------------+ <-- HEAP START - ; | Size (2 bytes) | - ; | 0 | <-- Size = 0 => DUMMY HEADER BLOCK - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ <-+ - ; | Size (2 bytes) | - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ | - ; | | | <-- If Size > 4, then this contains (size - 4) bytes - ; | (0 if Size = 4)| | - ; +----------------+ <-+ - ; | Size (2 bytes) | - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ | - ; | | | - ; | (0 if Size = 4)| | - ; +----------------+ | - ; | <-- This zone is in use (Already allocated) - ; +----------------+ <-+ - ; | Size (2 bytes) | - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ | - ; | | | - ; | (0 if Size = 4)| | - ; +----------------+ <-+ - ; | Next (2 bytes) |--> NULL => END OF LIST - ; | 0 = NULL | - ; +----------------+ - ; | | - ; | (0 if Size = 4)| - ; +----------------+ - ; When a block is FREED, the previous and next pointers are examined to see - ; if we can defragment the heap. If the block to be breed is just next to the - ; previous, or to the next (or both) they will be converted into a single - ; block (so defragmented). - ; MEMORY MANAGER - ; - ; This library must be initialized calling __MEM_INIT with - ; HL = BLOCK Start & DE = Length. - ; An init directive is useful for initialization routines. - ; They will be added automatically if needed. -#line 1 "/zxbasic/src/arch/zx48k/library-asm/heapinit.asm" -; vim: ts=4:et:sw=4: - ; Copyleft (K) by Jose M. Rodriguez de la Rosa - ; (a.k.a. Boriel) -; http://www.boriel.com - ; - ; This ASM library is licensed under the BSD license - ; you can use it for any purpose (even for commercial - ; closed source programs). - ; - ; Please read the BSD license on the internet - ; ----- IMPLEMENTATION NOTES ------ - ; The heap is implemented as a linked list of free blocks. -; Each free block contains this info: - ; - ; +----------------+ <-- HEAP START - ; | Size (2 bytes) | - ; | 0 | <-- Size = 0 => DUMMY HEADER BLOCK - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ <-+ - ; | Size (2 bytes) | - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ | - ; | | | <-- If Size > 4, then this contains (size - 4) bytes - ; | (0 if Size = 4)| | - ; +----------------+ <-+ - ; | Size (2 bytes) | - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ | - ; | | | - ; | (0 if Size = 4)| | - ; +----------------+ | - ; | <-- This zone is in use (Already allocated) - ; +----------------+ <-+ - ; | Size (2 bytes) | - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ | - ; | | | - ; | (0 if Size = 4)| | - ; +----------------+ <-+ - ; | Next (2 bytes) |--> NULL => END OF LIST - ; | 0 = NULL | - ; +----------------+ - ; | | - ; | (0 if Size = 4)| - ; +----------------+ - ; When a block is FREED, the previous and next pointers are examined to see - ; if we can defragment the heap. If the block to be breed is just next to the - ; previous, or to the next (or both) they will be converted into a single - ; block (so defragmented). - ; MEMORY MANAGER - ; - ; This library must be initialized calling __MEM_INIT with - ; HL = BLOCK Start & DE = Length. - ; An init directive is useful for initialization routines. - ; They will be added automatically if needed. - ; --------------------------------------------------------------------- - ; __MEM_INIT must be called to initalize this library with the - ; standard parameters - ; --------------------------------------------------------------------- - push namespace core -__MEM_INIT: ; Initializes the library using (RAMTOP) as start, and - ld hl, ZXBASIC_MEM_HEAP ; Change this with other address of heap start - ld de, ZXBASIC_HEAP_SIZE ; Change this with your size - ; --------------------------------------------------------------------- - ; __MEM_INIT2 initalizes this library -; Parameters: -; HL : Memory address of 1st byte of the memory heap -; DE : Length in bytes of the Memory Heap - ; --------------------------------------------------------------------- -__MEM_INIT2: - ; HL as TOP - PROC - dec de - dec de - dec de - dec de ; DE = length - 4; HL = start - ; This is done, because we require 4 bytes for the empty dummy-header block - xor a - ld (hl), a - inc hl - ld (hl), a ; First "free" block is a header: size=0, Pointer=&(Block) + 4 - inc hl - ld b, h - ld c, l - inc bc - inc bc ; BC = starts of next block - ld (hl), c - inc hl - ld (hl), b - inc hl ; Pointer to next block - ld (hl), e - inc hl - ld (hl), d - inc hl ; Block size (should be length - 4 at start); This block contains all the available memory - ld (hl), a ; NULL (0000h) ; No more blocks (a list with a single block) - inc hl - ld (hl), a - ld a, 201 - ld (__MEM_INIT), a; "Pokes" with a RET so ensure this routine is not called again - ret - ENDP - pop namespace -#line 69 "/zxbasic/src/arch/zx48k/library-asm/free.asm" - ; --------------------------------------------------------------------- - ; MEM_FREE - ; Frees a block of memory - ; -; Parameters: - ; HL = Pointer to the block to be freed. If HL is NULL (0) nothing - ; is done - ; --------------------------------------------------------------------- - push namespace core -MEM_FREE: -__MEM_FREE: ; Frees the block pointed by HL - ; HL DE BC & AF modified - PROC - LOCAL __MEM_LOOP2 - LOCAL __MEM_LINK_PREV - LOCAL __MEM_JOIN_TEST - LOCAL __MEM_BLOCK_JOIN - ld a, h - or l - ret z ; Return if NULL pointer - dec hl - dec hl - ld b, h - ld c, l ; BC = Block pointer - ld hl, ZXBASIC_MEM_HEAP ; This label point to the heap start -__MEM_LOOP2: - inc hl - inc hl ; Next block ptr - ld e, (hl) - inc hl - ld d, (hl) ; Block next ptr - ex de, hl ; DE = &(block->next); HL = block->next - ld a, h ; HL == NULL? - or l - jp z, __MEM_LINK_PREV; if so, link with previous - or a ; Clear carry flag - sbc hl, bc ; Carry if BC > HL => This block if before - add hl, bc ; Restores HL, preserving Carry flag - jp c, __MEM_LOOP2 ; This block is before. Keep searching PASS the block - ;------ At this point current HL is PAST BC, so we must link (DE) with BC, and HL in BC->next -__MEM_LINK_PREV: ; Link (DE) with BC, and BC->next with HL - ex de, hl - push hl - dec hl - ld (hl), c - inc hl - ld (hl), b ; (DE) <- BC - ld h, b ; HL <- BC (Free block ptr) - ld l, c - inc hl ; Skip block length (2 bytes) - inc hl - ld (hl), e ; Block->next = DE - inc hl - ld (hl), d - ; --- LINKED ; HL = &(BC->next) + 2 - call __MEM_JOIN_TEST - pop hl -__MEM_JOIN_TEST: ; Checks for fragmented contiguous blocks and joins them - ; hl = Ptr to current block + 2 - ld d, (hl) - dec hl - ld e, (hl) - dec hl - ld b, (hl) ; Loads block length into BC - dec hl - ld c, (hl) ; - push hl ; Saves it for later - add hl, bc ; Adds its length. If HL == DE now, it must be joined - or a - sbc hl, de ; If Z, then HL == DE => We must join - pop hl - ret nz -__MEM_BLOCK_JOIN: ; Joins current block (pointed by HL) with next one (pointed by DE). HL->length already in BC - push hl ; Saves it for later - ex de, hl - ld e, (hl) ; DE -> block->next->length - inc hl - ld d, (hl) - inc hl - ex de, hl ; DE = &(block->next) - add hl, bc ; HL = Total Length - ld b, h - ld c, l ; BC = Total Length - ex de, hl - ld e, (hl) - inc hl - ld d, (hl) ; DE = block->next - pop hl ; Recovers Pointer to block - ld (hl), c - inc hl - ld (hl), b ; Length Saved - inc hl - ld (hl), e - inc hl - ld (hl), d ; Next saved - ret - ENDP - pop namespace -#line 61 "zx48k/lcd9.bas" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/loadstr.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/alloc.asm" -; vim: ts=4:et:sw=4: - ; Copyleft (K) by Jose M. Rodriguez de la Rosa - ; (a.k.a. Boriel) -; http://www.boriel.com - ; - ; This ASM library is licensed under the MIT license - ; you can use it for any purpose (even for commercial - ; closed source programs). - ; - ; Please read the MIT license on the internet - ; ----- IMPLEMENTATION NOTES ------ - ; The heap is implemented as a linked list of free blocks. -; Each free block contains this info: - ; - ; +----------------+ <-- HEAP START - ; | Size (2 bytes) | - ; | 0 | <-- Size = 0 => DUMMY HEADER BLOCK - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ <-+ - ; | Size (2 bytes) | - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ | - ; | | | <-- If Size > 4, then this contains (size - 4) bytes - ; | (0 if Size = 4)| | - ; +----------------+ <-+ - ; | Size (2 bytes) | - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ | - ; | | | - ; | (0 if Size = 4)| | - ; +----------------+ | - ; | <-- This zone is in use (Already allocated) - ; +----------------+ <-+ - ; | Size (2 bytes) | - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ | - ; | | | - ; | (0 if Size = 4)| | - ; +----------------+ <-+ - ; | Next (2 bytes) |--> NULL => END OF LIST - ; | 0 = NULL | - ; +----------------+ - ; | | - ; | (0 if Size = 4)| - ; +----------------+ - ; When a block is FREED, the previous and next pointers are examined to see - ; if we can defragment the heap. If the block to be freed is just next to the - ; previous, or to the next (or both) they will be converted into a single - ; block (so defragmented). - ; MEMORY MANAGER - ; - ; This library must be initialized calling __MEM_INIT with - ; HL = BLOCK Start & DE = Length. - ; An init directive is useful for initialization routines. - ; They will be added automatically if needed. +#line 1 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +; vim:ts=4:sw=4:et: + ; PRINT command routine + ; Does not print attribute. Use PRINT_STR or PRINT_NUM for that +#line 1 "/zxbasic/src/arch/zx48k/library-asm/sposn.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/sysvars.asm" + ;; ----------------------------------------------------------------------- + ;; ZX Basic System Vars + ;; Some of them will be mapped over Sinclair ROM ones for compatibility + ;; ----------------------------------------------------------------------- + push namespace core +SCREEN_ADDR: DW 16384 ; Screen address (can be pointed to other place to use a screen buffer) +SCREEN_ATTR_ADDR: DW 22528 ; Screen attribute address (ditto.) + ; These are mapped onto ZX Spectrum ROM VARS + CHARS EQU 23606 ; Pointer to ROM/RAM Charset + TVFLAGS EQU 23612 ; TV Flags + UDG EQU 23675 ; Pointer to UDG Charset + COORDS EQU 23677 ; Last PLOT coordinates + FLAGS2 EQU 23681 ; + ECHO_E EQU 23682 ; + DFCC EQU 23684 ; Next screen addr for PRINT + DFCCL EQU 23686 ; Next screen attr for PRINT + S_POSN EQU 23688 + ATTR_P EQU 23693 ; Current Permanent ATTRS set with INK, PAPER, etc commands + ATTR_T EQU 23695 ; temporary ATTRIBUTES + P_FLAG EQU 23697 ; + MEM0 EQU 23698 ; Temporary memory buffer used by ROM chars + SCR_COLS EQU 33 ; Screen with in columns + 1 + SCR_ROWS EQU 24 ; Screen height in rows + SCR_SIZE EQU (SCR_ROWS << 8) + SCR_COLS + pop namespace +#line 2 "/zxbasic/src/arch/zx48k/library-asm/sposn.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/attr.asm" + ; Attribute routines +; vim:ts=4:et:sw: #line 1 "/zxbasic/src/arch/zx48k/library-asm/error.asm" ; Simple error control routines ; vim:ts=4:et: @@ -449,460 +158,795 @@ __STOP: ld (ERR_NR), a ret pop namespace -#line 69 "/zxbasic/src/arch/zx48k/library-asm/alloc.asm" - ; --------------------------------------------------------------------- - ; MEM_ALLOC - ; Allocates a block of memory in the heap. - ; - ; Parameters - ; BC = Length of requested memory block - ; -; Returns: - ; HL = Pointer to the allocated block in memory. Returns 0 (NULL) - ; if the block could not be allocated (out of memory) - ; --------------------------------------------------------------------- +#line 6 "/zxbasic/src/arch/zx48k/library-asm/attr.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/in_screen.asm" push namespace core -MEM_ALLOC: -__MEM_ALLOC: ; Returns the 1st free block found of the given length (in BC) +__IN_SCREEN: + ; Returns NO carry if current coords (D, E) + ; are OUT of the screen limits PROC - LOCAL __MEM_LOOP - LOCAL __MEM_DONE - LOCAL __MEM_SUBTRACT - LOCAL __MEM_START - LOCAL TEMP, TEMP0 - TEMP EQU TEMP0 + 1 - ld hl, 0 - ld (TEMP), hl -__MEM_START: - ld hl, ZXBASIC_MEM_HEAP ; This label point to the heap start - inc bc - inc bc ; BC = BC + 2 ; block size needs 2 extra bytes for hidden pointer -__MEM_LOOP: ; Loads lengh at (HL, HL+). If Lenght >= BC, jump to __MEM_DONE - ld a, h ; HL = NULL (No memory available?) - or l -#line 113 "/zxbasic/src/arch/zx48k/library-asm/alloc.asm" - ret z ; NULL -#line 115 "/zxbasic/src/arch/zx48k/library-asm/alloc.asm" - ; HL = Pointer to Free block - ld e, (hl) - inc hl - ld d, (hl) - inc hl ; DE = Block Length - push hl ; HL = *pointer to -> next block - ex de, hl - or a ; CF = 0 - sbc hl, bc ; FREE >= BC (Length) (HL = BlockLength - Length) - jp nc, __MEM_DONE - pop hl - ld (TEMP), hl + LOCAL __IN_SCREEN_ERR + ld hl, SCR_SIZE + ld a, e + cp l + jr nc, __IN_SCREEN_ERR ; Do nothing and return if out of range + ld a, d + cp h + ret c ; Return if carry (OK) +__IN_SCREEN_ERR: +__OUT_OF_SCREEN_ERR: + ; Jumps here if out of screen + ld a, ERROR_OutOfScreen + jp __STOP ; Saves error code and exits + ENDP + pop namespace +#line 7 "/zxbasic/src/arch/zx48k/library-asm/attr.asm" + push namespace core +__ATTR_ADDR: + ; calc start address in DE (as (32 * d) + e) + ; Contributed by Santiago Romero at http://www.speccy.org + ld h, 0 ; 7 T-States + ld a, d ; 4 T-States + ld d, h + add a, a ; a * 2 ; 4 T-States + add a, a ; a * 4 ; 4 T-States + ld l, a ; HL = A * 4 ; 4 T-States + add hl, hl ; HL = A * 8 ; 15 T-States + add hl, hl ; HL = A * 16 ; 15 T-States + add hl, hl ; HL = A * 32 ; 15 T-States + add hl, de + ld de, (SCREEN_ATTR_ADDR) ; Adds the screen address + add hl, de + ; Return current screen address in HL + ret + ; Sets the attribute at a given screen coordinate (D, E). + ; The attribute is taken from the ATTR_T memory variable + ; Used by PRINT routines +SET_ATTR: + ; Checks for valid coords + call __IN_SCREEN + ret nc + call __ATTR_ADDR +__SET_ATTR: + ; Internal __FASTCALL__ Entry used by printing routines + ; HL contains the address of the ATTR cell to set + PROC +__SET_ATTR2: ; Sets attr from ATTR_T to (HL) which points to the scr address + ld de, (ATTR_T) ; E = ATTR_T, D = MASK_T + ld a, d + and (hl) + ld c, a ; C = current screen color, masked + ld a, d + cpl ; Negate mask + and e ; Mask current attributes + or c ; Mix them + ld (hl), a ; Store result in screen + ret + ENDP + pop namespace +#line 3 "/zxbasic/src/arch/zx48k/library-asm/sposn.asm" + ; Printing positioning library. + push namespace core + ; Loads into DE current ROW, COL print position from S_POSN mem var. +__LOAD_S_POSN: + PROC + ld de, (S_POSN) + ld hl, SCR_SIZE + or a + sbc hl, de ex de, hl + ret + ENDP + ; Saves ROW, COL from DE into S_POSN mem var. +__SAVE_S_POSN: + PROC + ld hl, SCR_SIZE + or a + sbc hl, de + ld (S_POSN), hl ; saves it again +__SET_SCR_PTR: ;; Fast + push de + call __ATTR_ADDR + ld (DFCCL), hl + pop de + ld a, d + ld c, a ; Saves it for later + and 0F8h ; Masks 3 lower bit ; zy + ld d, a + ld a, c ; Recovers it + and 07h ; MOD 7 ; y1 + rrca + rrca + rrca + or e + ld e, a + ld hl, (SCREEN_ADDR) + add hl, de ; HL = Screen address + DE + ld (DFCC), hl + ret + ENDP + pop namespace +#line 6 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/table_jump.asm" + push namespace core +JUMP_HL_PLUS_2A: ; Does JP (HL + A*2) Modifies DE. Modifies A + add a, a +JUMP_HL_PLUS_A: ; Does JP (HL + A) Modifies DE + ld e, a + ld d, 0 +JUMP_HL_PLUS_DE: ; Does JP (HL + DE) + add hl, de ld e, (hl) inc hl ld d, (hl) ex de, hl - jp __MEM_LOOP -__MEM_DONE: ; A free block has been found. - ; Check if at least 4 bytes remains free (HL >= 4) - push hl - exx ; exx to preserve bc - pop hl - ld bc, 4 +CALL_HL: + jp (hl) + pop namespace +#line 8 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/ink.asm" + ; Sets ink color in ATTR_P permanently +; Parameter: Paper color in A register + push namespace core +INK: + PROC + LOCAL __SET_INK + LOCAL __SET_INK2 + ld de, ATTR_P +__SET_INK: + cp 8 + jr nz, __SET_INK2 + inc de ; Points DE to MASK_T or MASK_P + ld a, (de) + or 7 ; Set bits 0,1,2 to enable transparency + ld (de), a + ret +__SET_INK2: + ; Another entry. This will set the ink color at location pointer by DE + and 7 ; # Gets color mod 8 + ld b, a ; Saves the color + ld a, (de) + and 0F8h ; Clears previous value + or b + ld (de), a + inc de ; Points DE to MASK_T or MASK_P + ld a, (de) + and 0F8h ; Reset bits 0,1,2 sign to disable transparency + ld (de), a ; Store new attr + ret + ; Sets the INK color passed in A register in the ATTR_T variable +INK_TMP: + ld de, ATTR_T + jp __SET_INK + ENDP + pop namespace +#line 9 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/paper.asm" + ; Sets paper color in ATTR_P permanently +; Parameter: Paper color in A register + push namespace core +PAPER: + PROC + LOCAL __SET_PAPER + LOCAL __SET_PAPER2 + ld de, ATTR_P +__SET_PAPER: + cp 8 + jr nz, __SET_PAPER2 + inc de + ld a, (de) + or 038h + ld (de), a + ret + ; Another entry. This will set the paper color at location pointer by DE +__SET_PAPER2: + and 7 ; # Remove + rlca + rlca + rlca ; a *= 8 + ld b, a ; Saves the color + ld a, (de) + and 0C7h ; Clears previous value + or b + ld (de), a + inc de ; Points to MASK_T or MASK_P accordingly + ld a, (de) + and 0C7h ; Resets bits 3,4,5 + ld (de), a + ret + ; Sets the PAPER color passed in A register in the ATTR_T variable +PAPER_TMP: + ld de, ATTR_T + jp __SET_PAPER + ENDP + pop namespace +#line 10 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/flash.asm" + ; Sets flash flag in ATTR_P permanently +; Parameter: Paper color in A register + push namespace core +FLASH: + ld hl, ATTR_P + PROC + LOCAL IS_TR + LOCAL IS_ZERO +__SET_FLASH: + ; Another entry. This will set the flash flag at location pointer by DE + cp 8 + jr z, IS_TR + ; # Convert to 0/1 or a - sbc hl, bc - exx - jp nc, __MEM_SUBTRACT - ; At this point... - ; less than 4 bytes remains free. So we return this block entirely - ; We must link the previous block with the next to this one - ; (DE) => Pointer to next block - ; (TEMP) => &(previous->next) - pop hl ; Discard current block pointer - push de - ex de, hl ; DE = Previous block pointer; (HL) = Next block pointer + jr z, IS_ZERO + ld a, 0x80 +IS_ZERO: + ld b, a ; Saves the color ld a, (hl) + and 07Fh ; Clears previous value + or b + ld (hl), a inc hl - ld h, (hl) - ld l, a ; HL = (HL) - ex de, hl ; HL = Previous block pointer; DE = Next block pointer -TEMP0: - ld hl, 0 ; Pre-previous block pointer - ld (hl), e - inc hl - ld (hl), d ; LINKED - pop hl ; Returning block. + res 7, (hl) ;Reset bit 7 to disable transparency ret -__MEM_SUBTRACT: - ; At this point we have to store HL value (Length - BC) into (DE - 2) - ex de, hl - dec hl - ld (hl), d - dec hl - ld (hl), e ; Store new block length - add hl, de ; New length + DE => free-block start - pop de ; Remove previous HL off the stack - ld (hl), c ; Store length on its 1st word - inc hl - ld (hl), b - inc hl ; Return hl +IS_TR: ; transparent + inc hl ; Points DE to MASK_T or MASK_P + set 7, (hl) ;Set bit 7 to enable transparency ret + ; Sets the FLASH flag passed in A register in the ATTR_T variable +FLASH_TMP: + ld hl, ATTR_T + jr __SET_FLASH ENDP pop namespace -#line 2 "/zxbasic/src/arch/zx48k/library-asm/loadstr.asm" - ; Loads a string (ptr) from HL - ; and duplicates it on dynamic memory again - ; Finally, it returns result pointer in HL +#line 11 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/bright.asm" + ; Sets bright flag in ATTR_P permanently +; Parameter: Paper color in A register push namespace core -__ILOADSTR: ; This is the indirect pointer entry HL = (HL) - ld a, h - or l - ret z +BRIGHT: + ld hl, ATTR_P + PROC + LOCAL IS_TR + LOCAL IS_ZERO +__SET_BRIGHT: + ; Another entry. This will set the bright flag at location pointer by DE + cp 8 + jr z, IS_TR + ; # Convert to 0/1 + or a + jr z, IS_ZERO + ld a, 0x40 +IS_ZERO: + ld b, a ; Saves the color ld a, (hl) + and 0BFh ; Clears previous value + or b + ld (hl), a inc hl - ld h, (hl) - ld l, a -__LOADSTR: ; __FASTCALL__ entry - ld a, h - or l - ret z ; Return if NULL - ld c, (hl) - inc hl - ld b, (hl) - dec hl ; BC = LEN(a$) - inc bc - inc bc ; BC = LEN(a$) + 2 (two bytes for length) - push hl - push bc - call __MEM_ALLOC - pop bc ; Recover length - pop de ; Recover origin - ld a, h - or l - ret z ; Return if NULL (No memory) - ex de, hl ; ldir takes HL as source, DE as destiny, so SWAP HL,DE - push de ; Saves destiny start - ldir ; Copies string (length number included) - pop hl ; Recovers destiny in hl as result + res 6, (hl) ;Reset bit 6 to disable transparency + ret +IS_TR: ; transparent + inc hl ; Points DE to MASK_T or MASK_P + set 6, (hl) ;Set bit 6 to enable transparency ret + ; Sets the BRIGHT flag passed in A register in the ATTR_T variable +BRIGHT_TMP: + ld hl, ATTR_T + jr __SET_BRIGHT + ENDP pop namespace -#line 62 "zx48k/lcd9.bas" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/print_eol_attr.asm" - ; Calls PRINT_EOL and then COPY_ATTR, so saves - ; 3 bytes -#line 1 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -; vim:ts=4:sw=4:et: - ; PRINT command routine - ; Does not print attribute. Use PRINT_STR or PRINT_NUM for that -#line 1 "/zxbasic/src/arch/zx48k/library-asm/sposn.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/sysvars.asm" - ;; ----------------------------------------------------------------------- - ;; ZX Basic System Vars - ;; Some of them will be mapped over Sinclair ROM ones for compatibility - ;; ----------------------------------------------------------------------- - push namespace core -SCREEN_ADDR: DW 16384 ; Screen address (can be pointed to other place to use a screen buffer) -SCREEN_ATTR_ADDR: DW 22528 ; Screen attribute address (ditto.) - ; These are mapped onto ZX Spectrum ROM VARS - CHARS EQU 23606 ; Pointer to ROM/RAM Charset - TVFLAGS EQU 23612 ; TV Flags - UDG EQU 23675 ; Pointer to UDG Charset - COORDS EQU 23677 ; Last PLOT coordinates - FLAGS2 EQU 23681 ; - ECHO_E EQU 23682 ; - DFCC EQU 23684 ; Next screen addr for PRINT - DFCCL EQU 23686 ; Next screen attr for PRINT - S_POSN EQU 23688 - ATTR_P EQU 23693 ; Current Permanent ATTRS set with INK, PAPER, etc commands - ATTR_T EQU 23695 ; temporary ATTRIBUTES - P_FLAG EQU 23697 ; - MEM0 EQU 23698 ; Temporary memory buffer used by ROM chars - SCR_COLS EQU 33 ; Screen with in columns + 1 - SCR_ROWS EQU 24 ; Screen height in rows - SCR_SIZE EQU (SCR_ROWS << 8) + SCR_COLS - pop namespace -#line 2 "/zxbasic/src/arch/zx48k/library-asm/sposn.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/attr.asm" - ; Attribute routines -; vim:ts=4:et:sw: -#line 1 "/zxbasic/src/arch/zx48k/library-asm/in_screen.asm" +#line 12 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/over.asm" + ; Sets OVER flag in P_FLAG permanently +; Parameter: OVER flag in bit 0 of A register push namespace core -__IN_SCREEN: - ; Returns NO carry if current coords (D, E) - ; are OUT of the screen limits +OVER: PROC - LOCAL __IN_SCREEN_ERR - ld hl, SCR_SIZE - ld a, e - cp l - jr nc, __IN_SCREEN_ERR ; Do nothing and return if out of range - ld a, d - cp h - ret c ; Return if carry (OK) -__IN_SCREEN_ERR: -__OUT_OF_SCREEN_ERR: - ; Jumps here if out of screen - ld a, ERROR_OutOfScreen - jp __STOP ; Saves error code and exits + ld c, a ; saves it for later + and 2 + ld hl, FLAGS2 + res 1, (HL) + or (hl) + ld (hl), a + ld a, c ; Recovers previous value + and 1 ; # Convert to 0/1 + add a, a; # Shift left 1 bit for permanent + ld hl, P_FLAG + res 1, (hl) + or (hl) + ld (hl), a + ret + ; Sets OVER flag in P_FLAG temporarily +OVER_TMP: + ld c, a ; saves it for later + and 2 ; gets bit 1; clears carry + rra + ld hl, FLAGS2 + res 0, (hl) + or (hl) + ld (hl), a + ld a, c ; Recovers previous value + and 1 + ld hl, P_FLAG + res 0, (hl) + or (hl) + ld (hl), a + jp __SET_ATTR_MODE + ENDP + pop namespace +#line 13 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/inverse.asm" + ; Sets INVERSE flag in P_FLAG permanently +; Parameter: INVERSE flag in bit 0 of A register + push namespace core +INVERSE: + PROC + and 1 ; # Convert to 0/1 + add a, a; # Shift left 3 bits for permanent + add a, a + add a, a + ld hl, P_FLAG + res 3, (hl) + or (hl) + ld (hl), a + ret + ; Sets INVERSE flag in P_FLAG temporarily +INVERSE_TMP: + and 1 + add a, a + add a, a; # Shift left 2 bits for temporary + ld hl, P_FLAG + res 2, (hl) + or (hl) + ld (hl), a + jp __SET_ATTR_MODE + ENDP + pop namespace +#line 14 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/bold.asm" + ; Sets BOLD flag in P_FLAG permanently +; Parameter: BOLD flag in bit 0 of A register + push namespace core +BOLD: + PROC + and 1 + rlca + rlca + rlca + ld hl, FLAGS2 + res 3, (HL) + or (hl) + ld (hl), a + ret + ; Sets BOLD flag in P_FLAG temporarily +BOLD_TMP: + and 1 + rlca + rlca + ld hl, FLAGS2 + res 2, (hl) + or (hl) + ld (hl), a + ret ENDP pop namespace -#line 7 "/zxbasic/src/arch/zx48k/library-asm/attr.asm" +#line 15 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/italic.asm" + ; Sets ITALIC flag in P_FLAG permanently +; Parameter: ITALIC flag in bit 0 of A register push namespace core -__ATTR_ADDR: - ; calc start address in DE (as (32 * d) + e) - ; Contributed by Santiago Romero at http://www.speccy.org - ld h, 0 ; 7 T-States - ld a, d ; 4 T-States - ld d, h - add a, a ; a * 2 ; 4 T-States - add a, a ; a * 4 ; 4 T-States - ld l, a ; HL = A * 4 ; 4 T-States - add hl, hl ; HL = A * 8 ; 15 T-States - add hl, hl ; HL = A * 16 ; 15 T-States - add hl, hl ; HL = A * 32 ; 15 T-States - add hl, de - ld de, (SCREEN_ATTR_ADDR) ; Adds the screen address - add hl, de - ; Return current screen address in HL - ret - ; Sets the attribute at a given screen coordinate (D, E). - ; The attribute is taken from the ATTR_T memory variable - ; Used by PRINT routines -SET_ATTR: - ; Checks for valid coords - call __IN_SCREEN - ret nc - call __ATTR_ADDR -__SET_ATTR: - ; Internal __FASTCALL__ Entry used by printing routines - ; HL contains the address of the ATTR cell to set +ITALIC: PROC -__SET_ATTR2: ; Sets attr from ATTR_T to (HL) which points to the scr address - ld de, (ATTR_T) ; E = ATTR_T, D = MASK_T - ld a, d - and (hl) - ld c, a ; C = current screen color, masked - ld a, d - cpl ; Negate mask - and e ; Mask current attributes - or c ; Mix them - ld (hl), a ; Store result in screen + and 1 + rrca + rrca + rrca + ld hl, FLAGS2 + res 5, (HL) + or (hl) + ld (hl), a + ret + ; Sets ITALIC flag in P_FLAG temporarily +ITALIC_TMP: + and 1 + rrca + rrca + rrca + rrca + ld hl, FLAGS2 + res 4, (hl) + or (hl) + ld (hl), a ret ENDP pop namespace -#line 3 "/zxbasic/src/arch/zx48k/library-asm/sposn.asm" - ; Printing positioning library. +#line 16 "/zxbasic/src/arch/zx48k/library-asm/print.asm" + ; Putting a comment starting with @INIT
+ ; will make the compiler to add a CALL to
+ ; It is useful for initialization routines. push namespace core - ; Loads into DE current ROW, COL print position from S_POSN mem var. -__LOAD_S_POSN: +__PRINT_INIT: ; To be called before program starts (initializes library) PROC - ld de, (S_POSN) + ld hl, __PRINT_START + ld (PRINT_JUMP_STATE), hl + ;; Clears ATTR2 flags (OVER 2, etc) + xor a + ld (FLAGS2), a + LOCAL SET_SCR_ADDR + call __LOAD_S_POSN + jp __SET_SCR_PTR + ;; Receives HL = future value of S_POSN + ;; Stores it at (S_POSN) and refresh screen pointers (ATTR, SCR) +SET_SCR_ADDR: + ld (S_POSN), hl + ex de, hl ld hl, SCR_SIZE or a sbc hl, de ex de, hl + dec e + jp __SET_SCR_PTR +__PRINTCHAR: ; Print character store in accumulator (A register) + ; Modifies H'L', B'C', A'F', D'E', A + LOCAL PO_GR_1 + LOCAL __PRCHAR + LOCAL __PRINT_JUMP + LOCAL __SRCADDR + LOCAL __PRINT_UDG + LOCAL __PRGRAPH + LOCAL __PRINT_START + PRINT_JUMP_STATE EQU __PRINT_JUMP + 2 +__PRINT_JUMP: + exx ; Switch to alternative registers + jp __PRINT_START ; Where to jump. If we print 22 (AT), next two calls jumps to AT1 and AT2 respectively +__PRINT_START: +__PRINT_CHR: + cp ' ' + jr c, __PRINT_SPECIAL ; Characters below ' ' are special ones + ex af, af' ; Saves a value (char to print) for later + ld hl, (S_POSN) + dec l + jr nz, 1f + ld l, SCR_COLS - 1 + dec h + jr nz, 2f + inc h + push hl + call __SCROLL_SCR + pop hl +#line 92 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +2: + call SET_SCR_ADDR + jr 4f +1: + ld (S_POSN), hl +4: + ex af, af' + cp 80h ; Is it a "normal" (printable) char + jr c, __SRCADDR + cp 90h ; Is it an UDG? + jr nc, __PRINT_UDG + ; Print an 8 bit pattern (80h to 8Fh) + ld b, a + call PO_GR_1 ; This ROM routine will generate the bit pattern at MEM0 + ld hl, MEM0 + jp __PRGRAPH + PO_GR_1 EQU 0B38h +__PRINT_UDG: + sub 90h ; Sub ASC code + ld bc, (UDG) + jr __PRGRAPH0 + __SOURCEADDR EQU (__SRCADDR + 1) ; Address of the pointer to chars source +__SRCADDR: + ld bc, (CHARS) +__PRGRAPH0: + add a, a ; A = a * 2 (since a < 80h) ; Thanks to Metalbrain at http://foro.speccy.org + ld l, a + ld h, 0 ; HL = a * 2 (accumulator) + add hl, hl + add hl, hl ; HL = a * 8 + add hl, bc ; HL = CHARS address +__PRGRAPH: + ex de, hl ; HL = Write Address, DE = CHARS address + bit 2, (iy + $47) + call nz, __BOLD +#line 139 "/zxbasic/src/arch/zx48k/library-asm/print.asm" + bit 4, (iy + $47) + call nz, __ITALIC +#line 144 "/zxbasic/src/arch/zx48k/library-asm/print.asm" + ld hl, (DFCC) + push hl + ld b, 8 ; 8 bytes per char +__PRCHAR: + ld a, (de) ; DE *must* be source, and HL destiny +PRINT_MODE: ; Which operation is used to write on the screen + ; Set it with: + ; LD A, + ; LD (PRINT_MODE), A + ; + ; Available operations: + ; NORMAL : 0h --> NOP ; OVER 0 + ; XOR : AEh --> XOR (HL) ; OVER 1 + ; OR : B6h --> OR (HL) ; PUTSPRITE + ; AND : A6h --> AND (HL) ; PUTMASK + nop ; Set to one of the values above +INVERSE_MODE: ; 00 -> NOP -> INVERSE 0 + nop ; 2F -> CPL -> INVERSE 1 + ld (hl), a + inc de + inc h ; Next line + djnz __PRCHAR + pop hl + inc hl + ld (DFCC), hl + ld hl, (DFCCL) ; current ATTR Pos + inc hl + ld (DFCCL), hl + dec hl + call __SET_ATTR + exx ret - ENDP - ; Saves ROW, COL from DE into S_POSN mem var. -__SAVE_S_POSN: - PROC - ld hl, SCR_SIZE - or a - sbc hl, de - ld (S_POSN), hl ; saves it again -__SET_SCR_PTR: ;; Fast + ; ------------- SPECIAL CHARS (< 32) ----------------- +__PRINT_SPECIAL: ; Jumps here if it is a special char + ld hl, __PRINT_TABLE + jp JUMP_HL_PLUS_2A +PRINT_EOL: ; Called WHENEVER there is no ";" at end of PRINT sentence + exx +__PRINT_0Dh: ; Called WHEN printing CHR$(13) + ld hl, (S_POSN) + dec l + jr nz, 1f + dec h + jr nz, 1f + inc h + push hl + call __SCROLL_SCR + pop hl +#line 209 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +1: + ld l, 1 +__PRINT_EOL_END: + call SET_SCR_ADDR + exx + ret +__PRINT_COM: + exx + push hl push de - call __ATTR_ADDR - ld (DFCCL), hl + push bc + call PRINT_COMMA + pop bc pop de - ld a, d - ld c, a ; Saves it for later - and 0F8h ; Masks 3 lower bit ; zy - ld d, a - ld a, c ; Recovers it - and 07h ; MOD 7 ; y1 - rrca - rrca - rrca - or e - ld e, a - ld hl, (SCREEN_ADDR) - add hl, de ; HL = Screen address + DE - ld (DFCC), hl + pop hl + ret +__PRINT_TAB: + ld hl, __PRINT_TAB1 + jr __PRINT_SET_STATE +__PRINT_TAB1: + ld (MEM0), a + ld hl, __PRINT_TAB2 + jr __PRINT_SET_STATE +__PRINT_TAB2: + ld a, (MEM0) ; Load tab code (ignore the current one) + ld hl, __PRINT_START + ld (PRINT_JUMP_STATE), hl + exx + push hl + push bc + push de + call PRINT_TAB + pop de + pop bc + pop hl ret - ENDP - pop namespace -#line 6 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/table_jump.asm" - push namespace core -JUMP_HL_PLUS_2A: ; Does JP (HL + A*2) Modifies DE. Modifies A - add a, a -JUMP_HL_PLUS_A: ; Does JP (HL + A) Modifies DE - ld e, a - ld d, 0 -JUMP_HL_PLUS_DE: ; Does JP (HL + DE) - add hl, de - ld e, (hl) - inc hl - ld d, (hl) - ex de, hl -CALL_HL: - jp (hl) - pop namespace -#line 8 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/ink.asm" - ; Sets ink color in ATTR_P permanently -; Parameter: Paper color in A register - push namespace core -INK: - PROC - LOCAL __SET_INK - LOCAL __SET_INK2 - ld de, ATTR_P -__SET_INK: - cp 8 - jr nz, __SET_INK2 - inc de ; Points DE to MASK_T or MASK_P - ld a, (de) - or 7 ; Set bits 0,1,2 to enable transparency - ld (de), a +__PRINT_AT: + ld hl, __PRINT_AT1 + jr __PRINT_SET_STATE +__PRINT_NOP: +__PRINT_RESTART: + ld hl, __PRINT_START +__PRINT_SET_STATE: + ld (PRINT_JUMP_STATE), hl ; Saves next entry call + exx ret -__SET_INK2: - ; Another entry. This will set the ink color at location pointer by DE - and 7 ; # Gets color mod 8 - ld b, a ; Saves the color - ld a, (de) - and 0F8h ; Clears previous value - or b - ld (de), a - inc de ; Points DE to MASK_T or MASK_P - ld a, (de) - and 0F8h ; Reset bits 0,1,2 sign to disable transparency - ld (de), a ; Store new attr +__PRINT_AT1: ; Jumps here if waiting for 1st parameter + ld hl, (S_POSN) + ld h, a + ld a, SCR_ROWS + sub h + ld (S_POSN + 1), a + ld hl, __PRINT_AT2 + jr __PRINT_SET_STATE +__PRINT_AT2: + call __LOAD_S_POSN + ld e, a + call __SAVE_S_POSN + jr __PRINT_RESTART +__PRINT_DEL: + call __LOAD_S_POSN ; Gets current screen position + dec e + ld a, -1 + cp e + jr nz, 3f + ld e, SCR_COLS - 2 + dec d + cp d + jr nz, 3f + ld d, SCR_ROWS - 1 +3: + call __SAVE_S_POSN + exx ret - ; Sets the INK color passed in A register in the ATTR_T variable -INK_TMP: - ld de, ATTR_T - jp __SET_INK - ENDP - pop namespace -#line 9 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/paper.asm" - ; Sets paper color in ATTR_P permanently -; Parameter: Paper color in A register - push namespace core -PAPER: - PROC - LOCAL __SET_PAPER - LOCAL __SET_PAPER2 - ld de, ATTR_P -__SET_PAPER: - cp 8 - jr nz, __SET_PAPER2 - inc de +__PRINT_INK: + ld hl, __PRINT_INK2 + jr __PRINT_SET_STATE +__PRINT_INK2: + call INK_TMP + jr __PRINT_RESTART +__PRINT_PAP: + ld hl, __PRINT_PAP2 + jr __PRINT_SET_STATE +__PRINT_PAP2: + call PAPER_TMP + jr __PRINT_RESTART +__PRINT_FLA: + ld hl, __PRINT_FLA2 + jr __PRINT_SET_STATE +__PRINT_FLA2: + call FLASH_TMP + jr __PRINT_RESTART +__PRINT_BRI: + ld hl, __PRINT_BRI2 + jr __PRINT_SET_STATE +__PRINT_BRI2: + call BRIGHT_TMP + jr __PRINT_RESTART +__PRINT_INV: + ld hl, __PRINT_INV2 + jr __PRINT_SET_STATE +__PRINT_INV2: + call INVERSE_TMP + jr __PRINT_RESTART +__PRINT_OVR: + ld hl, __PRINT_OVR2 + jr __PRINT_SET_STATE +__PRINT_OVR2: + call OVER_TMP + jr __PRINT_RESTART +__PRINT_BOLD: + ld hl, __PRINT_BOLD2 + jp __PRINT_SET_STATE +__PRINT_BOLD2: + call BOLD_TMP + jp __PRINT_RESTART +#line 353 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +__PRINT_ITA: + ld hl, __PRINT_ITA2 + jp __PRINT_SET_STATE +__PRINT_ITA2: + call ITALIC_TMP + jp __PRINT_RESTART +#line 363 "/zxbasic/src/arch/zx48k/library-asm/print.asm" + LOCAL __BOLD +__BOLD: + push hl + ld hl, MEM0 + ld b, 8 +1: ld a, (de) - or 038h - ld (de), a - ret - ; Another entry. This will set the paper color at location pointer by DE -__SET_PAPER2: - and 7 ; # Remove - rlca + ld c, a rlca - rlca ; a *= 8 - ld b, a ; Saves the color - ld a, (de) - and 0C7h ; Clears previous value - or b - ld (de), a - inc de ; Points to MASK_T or MASK_P accordingly - ld a, (de) - and 0C7h ; Resets bits 3,4,5 - ld (de), a - ret - ; Sets the PAPER color passed in A register in the ATTR_T variable -PAPER_TMP: - ld de, ATTR_T - jp __SET_PAPER - ENDP - pop namespace -#line 10 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/flash.asm" - ; Sets flash flag in ATTR_P permanently -; Parameter: Paper color in A register - push namespace core -FLASH: - ld hl, ATTR_P - PROC - LOCAL IS_TR - LOCAL IS_ZERO -__SET_FLASH: - ; Another entry. This will set the flash flag at location pointer by DE - cp 8 - jr z, IS_TR - ; # Convert to 0/1 - or a - jr z, IS_ZERO - ld a, 0x80 -IS_ZERO: - ld b, a ; Saves the color - ld a, (hl) - and 07Fh ; Clears previous value - or b + or c ld (hl), a inc hl - res 7, (hl) ;Reset bit 7 to disable transparency - ret -IS_TR: ; transparent - inc hl ; Points DE to MASK_T or MASK_P - set 7, (hl) ;Set bit 7 to enable transparency - ret - ; Sets the FLASH flag passed in A register in the ATTR_T variable -FLASH_TMP: - ld hl, ATTR_T - jr __SET_FLASH - ENDP - pop namespace -#line 11 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/bright.asm" - ; Sets bright flag in ATTR_P permanently -; Parameter: Paper color in A register - push namespace core -BRIGHT: - ld hl, ATTR_P - PROC - LOCAL IS_TR - LOCAL IS_ZERO -__SET_BRIGHT: - ; Another entry. This will set the bright flag at location pointer by DE - cp 8 - jr z, IS_TR - ; # Convert to 0/1 - or a - jr z, IS_ZERO - ld a, 0x40 -IS_ZERO: - ld b, a ; Saves the color - ld a, (hl) - and 0BFh ; Clears previous value - or b - ld (hl), a + inc de + djnz 1b + pop hl + ld de, MEM0 + ret +#line 384 "/zxbasic/src/arch/zx48k/library-asm/print.asm" + LOCAL __ITALIC +__ITALIC: + push hl + ld hl, MEM0 + ex de, hl + ld bc, 8 + ldir + ld hl, MEM0 + srl (hl) inc hl - res 6, (hl) ;Reset bit 6 to disable transparency + srl (hl) + inc hl + srl (hl) + inc hl + inc hl + inc hl + sla (hl) + inc hl + sla (hl) + inc hl + sla (hl) + pop hl + ld de, MEM0 ret -IS_TR: ; transparent - inc hl ; Points DE to MASK_T or MASK_P - set 6, (hl) ;Set bit 6 to enable transparency +#line 412 "/zxbasic/src/arch/zx48k/library-asm/print.asm" + LOCAL __SCROLL_SCR +#line 486 "/zxbasic/src/arch/zx48k/library-asm/print.asm" + __SCROLL_SCR EQU 0DFEh ; Use ROM SCROLL +#line 488 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 489 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +PRINT_COMMA: + call __LOAD_S_POSN + ld a, e + and 16 + add a, 16 +PRINT_TAB: + ; Tabulates the number of spaces in A register + ; If the current cursor position is already A, does nothing + PROC + LOCAL LOOP + call __LOAD_S_POSN ; e = current row + sub e + and 31 + ret z + ld b, a +LOOP: + ld a, ' ' + call __PRINTCHAR + djnz LOOP ret - ; Sets the BRIGHT flag passed in A register in the ATTR_T variable -BRIGHT_TMP: - ld hl, ATTR_T - jr __SET_BRIGHT + ENDP +PRINT_AT: ; Changes cursor to ROW, COL + ; COL in A register + ; ROW in stack + pop hl ; Ret address + ex (sp), hl ; callee H = ROW + ld l, a + ex de, hl + call __IN_SCREEN + ret nc ; Return if out of screen + jp __SAVE_S_POSN + LOCAL __PRINT_COM + LOCAL __PRINT_AT1 + LOCAL __PRINT_AT2 + LOCAL __PRINT_BOLD + LOCAL __PRINT_ITA + LOCAL __PRINT_INK + LOCAL __PRINT_PAP + LOCAL __PRINT_SET_STATE + LOCAL __PRINT_TABLE + LOCAL __PRINT_TAB, __PRINT_TAB1, __PRINT_TAB2 + LOCAL __PRINT_ITA2 +#line 545 "/zxbasic/src/arch/zx48k/library-asm/print.asm" + LOCAL __PRINT_BOLD2 +#line 551 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +__PRINT_TABLE: ; Jump table for 0 .. 22 codes + DW __PRINT_NOP ; 0 + DW __PRINT_NOP ; 1 + DW __PRINT_NOP ; 2 + DW __PRINT_NOP ; 3 + DW __PRINT_NOP ; 4 + DW __PRINT_NOP ; 5 + DW __PRINT_COM ; 6 COMMA + DW __PRINT_NOP ; 7 + DW __PRINT_DEL ; 8 DEL + DW __PRINT_NOP ; 9 + DW __PRINT_NOP ; 10 + DW __PRINT_NOP ; 11 + DW __PRINT_NOP ; 12 + DW __PRINT_0Dh ; 13 + DW __PRINT_BOLD ; 14 + DW __PRINT_ITA ; 15 + DW __PRINT_INK ; 16 + DW __PRINT_PAP ; 17 + DW __PRINT_FLA ; 18 + DW __PRINT_BRI ; 19 + DW __PRINT_INV ; 20 + DW __PRINT_OVR ; 21 + DW __PRINT_AT ; 22 AT + DW __PRINT_TAB ; 23 TAB ENDP pop namespace -#line 12 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/over.asm" - ; Sets OVER flag in P_FLAG permanently -; Parameter: OVER flag in bit 0 of A register -#line 1 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" +#line 3 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" #line 4 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" push namespace core COPY_ATTR: @@ -955,523 +999,470 @@ __REFRESH_TMP: ret ENDP pop namespace -#line 4 "/zxbasic/src/arch/zx48k/library-asm/over.asm" - push namespace core -OVER: - PROC - ld c, a ; saves it for later - and 2 - ld hl, FLAGS2 - res 1, (HL) - or (hl) - ld (hl), a - ld a, c ; Recovers previous value - and 1 ; # Convert to 0/1 - add a, a; # Shift left 1 bit for permanent - ld hl, P_FLAG - res 1, (hl) - or (hl) - ld (hl), a - ret - ; Sets OVER flag in P_FLAG temporarily -OVER_TMP: - ld c, a ; saves it for later - and 2 ; gets bit 1; clears carry - rra - ld hl, FLAGS2 - res 0, (hl) - or (hl) - ld (hl), a - ld a, c ; Recovers previous value - and 1 - ld hl, P_FLAG - res 0, (hl) - or (hl) - ld (hl), a - jp __SET_ATTR_MODE - ENDP - pop namespace -#line 13 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/inverse.asm" - ; Sets INVERSE flag in P_FLAG permanently -; Parameter: INVERSE flag in bit 0 of A register - push namespace core -INVERSE: - PROC - and 1 ; # Convert to 0/1 - add a, a; # Shift left 3 bits for permanent - add a, a - add a, a - ld hl, P_FLAG - res 3, (hl) - or (hl) - ld (hl), a - ret - ; Sets INVERSE flag in P_FLAG temporarily -INVERSE_TMP: - and 1 - add a, a - add a, a; # Shift left 2 bits for temporary - ld hl, P_FLAG - res 2, (hl) - or (hl) - ld (hl), a - jp __SET_ATTR_MODE - ENDP - pop namespace -#line 14 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/bold.asm" - ; Sets BOLD flag in P_FLAG permanently -; Parameter: BOLD flag in bit 0 of A register - push namespace core -BOLD: - PROC - and 1 - rlca - rlca - rlca - ld hl, FLAGS2 - res 3, (HL) - or (hl) - ld (hl), a - ret - ; Sets BOLD flag in P_FLAG temporarily -BOLD_TMP: - and 1 - rlca - rlca - ld hl, FLAGS2 - res 2, (hl) - or (hl) - ld (hl), a - ret - ENDP - pop namespace -#line 15 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/italic.asm" - ; Sets ITALIC flag in P_FLAG permanently -; Parameter: ITALIC flag in bit 0 of A register +#line 62 "zx48k/lcd9.bas" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/free.asm" +; vim: ts=4:et:sw=4: + ; Copyleft (K) by Jose M. Rodriguez de la Rosa + ; (a.k.a. Boriel) +; http://www.boriel.com + ; + ; This ASM library is licensed under the BSD license + ; you can use it for any purpose (even for commercial + ; closed source programs). + ; + ; Please read the BSD license on the internet + ; ----- IMPLEMENTATION NOTES ------ + ; The heap is implemented as a linked list of free blocks. +; Each free block contains this info: + ; + ; +----------------+ <-- HEAP START + ; | Size (2 bytes) | + ; | 0 | <-- Size = 0 => DUMMY HEADER BLOCK + ; +----------------+ + ; | Next (2 bytes) |---+ + ; +----------------+ <-+ + ; | Size (2 bytes) | + ; +----------------+ + ; | Next (2 bytes) |---+ + ; +----------------+ | + ; | | | <-- If Size > 4, then this contains (size - 4) bytes + ; | (0 if Size = 4)| | + ; +----------------+ <-+ + ; | Size (2 bytes) | + ; +----------------+ + ; | Next (2 bytes) |---+ + ; +----------------+ | + ; | | | + ; | (0 if Size = 4)| | + ; +----------------+ | + ; | <-- This zone is in use (Already allocated) + ; +----------------+ <-+ + ; | Size (2 bytes) | + ; +----------------+ + ; | Next (2 bytes) |---+ + ; +----------------+ | + ; | | | + ; | (0 if Size = 4)| | + ; +----------------+ <-+ + ; | Next (2 bytes) |--> NULL => END OF LIST + ; | 0 = NULL | + ; +----------------+ + ; | | + ; | (0 if Size = 4)| + ; +----------------+ + ; When a block is FREED, the previous and next pointers are examined to see + ; if we can defragment the heap. If the block to be breed is just next to the + ; previous, or to the next (or both) they will be converted into a single + ; block (so defragmented). + ; MEMORY MANAGER + ; + ; This library must be initialized calling __MEM_INIT with + ; HL = BLOCK Start & DE = Length. + ; An init directive is useful for initialization routines. + ; They will be added automatically if needed. +#line 1 "/zxbasic/src/arch/zx48k/library-asm/heapinit.asm" +; vim: ts=4:et:sw=4: + ; Copyleft (K) by Jose M. Rodriguez de la Rosa + ; (a.k.a. Boriel) +; http://www.boriel.com + ; + ; This ASM library is licensed under the BSD license + ; you can use it for any purpose (even for commercial + ; closed source programs). + ; + ; Please read the BSD license on the internet + ; ----- IMPLEMENTATION NOTES ------ + ; The heap is implemented as a linked list of free blocks. +; Each free block contains this info: + ; + ; +----------------+ <-- HEAP START + ; | Size (2 bytes) | + ; | 0 | <-- Size = 0 => DUMMY HEADER BLOCK + ; +----------------+ + ; | Next (2 bytes) |---+ + ; +----------------+ <-+ + ; | Size (2 bytes) | + ; +----------------+ + ; | Next (2 bytes) |---+ + ; +----------------+ | + ; | | | <-- If Size > 4, then this contains (size - 4) bytes + ; | (0 if Size = 4)| | + ; +----------------+ <-+ + ; | Size (2 bytes) | + ; +----------------+ + ; | Next (2 bytes) |---+ + ; +----------------+ | + ; | | | + ; | (0 if Size = 4)| | + ; +----------------+ | + ; | <-- This zone is in use (Already allocated) + ; +----------------+ <-+ + ; | Size (2 bytes) | + ; +----------------+ + ; | Next (2 bytes) |---+ + ; +----------------+ | + ; | | | + ; | (0 if Size = 4)| | + ; +----------------+ <-+ + ; | Next (2 bytes) |--> NULL => END OF LIST + ; | 0 = NULL | + ; +----------------+ + ; | | + ; | (0 if Size = 4)| + ; +----------------+ + ; When a block is FREED, the previous and next pointers are examined to see + ; if we can defragment the heap. If the block to be breed is just next to the + ; previous, or to the next (or both) they will be converted into a single + ; block (so defragmented). + ; MEMORY MANAGER + ; + ; This library must be initialized calling __MEM_INIT with + ; HL = BLOCK Start & DE = Length. + ; An init directive is useful for initialization routines. + ; They will be added automatically if needed. + ; --------------------------------------------------------------------- + ; __MEM_INIT must be called to initalize this library with the + ; standard parameters + ; --------------------------------------------------------------------- push namespace core -ITALIC: +__MEM_INIT: ; Initializes the library using (RAMTOP) as start, and + ld hl, ZXBASIC_MEM_HEAP ; Change this with other address of heap start + ld de, ZXBASIC_HEAP_SIZE ; Change this with your size + ; --------------------------------------------------------------------- + ; __MEM_INIT2 initalizes this library +; Parameters: +; HL : Memory address of 1st byte of the memory heap +; DE : Length in bytes of the Memory Heap + ; --------------------------------------------------------------------- +__MEM_INIT2: + ; HL as TOP PROC - and 1 - rrca - rrca - rrca - ld hl, FLAGS2 - res 5, (HL) - or (hl) + dec de + dec de + dec de + dec de ; DE = length - 4; HL = start + ; This is done, because we require 4 bytes for the empty dummy-header block + xor a ld (hl), a - ret - ; Sets ITALIC flag in P_FLAG temporarily -ITALIC_TMP: - and 1 - rrca - rrca - rrca - rrca - ld hl, FLAGS2 - res 4, (hl) - or (hl) + inc hl + ld (hl), a ; First "free" block is a header: size=0, Pointer=&(Block) + 4 + inc hl + ld b, h + ld c, l + inc bc + inc bc ; BC = starts of next block + ld (hl), c + inc hl + ld (hl), b + inc hl ; Pointer to next block + ld (hl), e + inc hl + ld (hl), d + inc hl ; Block size (should be length - 4 at start); This block contains all the available memory + ld (hl), a ; NULL (0000h) ; No more blocks (a list with a single block) + inc hl ld (hl), a + ld a, 201 + ld (__MEM_INIT), a; "Pokes" with a RET so ensure this routine is not called again ret ENDP pop namespace -#line 16 "/zxbasic/src/arch/zx48k/library-asm/print.asm" - ; Putting a comment starting with @INIT
- ; will make the compiler to add a CALL to
- ; It is useful for initialization routines. +#line 69 "/zxbasic/src/arch/zx48k/library-asm/free.asm" + ; --------------------------------------------------------------------- + ; MEM_FREE + ; Frees a block of memory + ; +; Parameters: + ; HL = Pointer to the block to be freed. If HL is NULL (0) nothing + ; is done + ; --------------------------------------------------------------------- push namespace core -__PRINT_INIT: ; To be called before program starts (initializes library) - PROC - ld hl, __PRINT_START - ld (PRINT_JUMP_STATE), hl - ;; Clears ATTR2 flags (OVER 2, etc) - xor a - ld (FLAGS2), a - LOCAL SET_SCR_ADDR - call __LOAD_S_POSN - jp __SET_SCR_PTR - ;; Receives HL = future value of S_POSN - ;; Stores it at (S_POSN) and refresh screen pointers (ATTR, SCR) -SET_SCR_ADDR: - ld (S_POSN), hl - ex de, hl - ld hl, SCR_SIZE - or a - sbc hl, de - ex de, hl - dec e - jp __SET_SCR_PTR -__PRINTCHAR: ; Print character store in accumulator (A register) - ; Modifies H'L', B'C', A'F', D'E', A - LOCAL PO_GR_1 - LOCAL __PRCHAR - LOCAL __PRINT_JUMP - LOCAL __SRCADDR - LOCAL __PRINT_UDG - LOCAL __PRGRAPH - LOCAL __PRINT_START - PRINT_JUMP_STATE EQU __PRINT_JUMP + 2 -__PRINT_JUMP: - exx ; Switch to alternative registers - jp __PRINT_START ; Where to jump. If we print 22 (AT), next two calls jumps to AT1 and AT2 respectively -__PRINT_START: -__PRINT_CHR: - cp ' ' - jr c, __PRINT_SPECIAL ; Characters below ' ' are special ones - ex af, af' ; Saves a value (char to print) for later - ld hl, (S_POSN) - dec l - jr nz, 1f - ld l, SCR_COLS - 1 - dec h - jr nz, 2f - inc h - push hl - call __SCROLL_SCR - pop hl -#line 92 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -2: - call SET_SCR_ADDR - jr 4f -1: - ld (S_POSN), hl -4: - ex af, af' - cp 80h ; Is it a "normal" (printable) char - jr c, __SRCADDR - cp 90h ; Is it an UDG? - jr nc, __PRINT_UDG - ; Print an 8 bit pattern (80h to 8Fh) - ld b, a - call PO_GR_1 ; This ROM routine will generate the bit pattern at MEM0 - ld hl, MEM0 - jp __PRGRAPH - PO_GR_1 EQU 0B38h -__PRINT_UDG: - sub 90h ; Sub ASC code - ld bc, (UDG) - jr __PRGRAPH0 - __SOURCEADDR EQU (__SRCADDR + 1) ; Address of the pointer to chars source -__SRCADDR: - ld bc, (CHARS) -__PRGRAPH0: - add a, a ; A = a * 2 (since a < 80h) ; Thanks to Metalbrain at http://foro.speccy.org - ld l, a - ld h, 0 ; HL = a * 2 (accumulator) - add hl, hl - add hl, hl ; HL = a * 8 - add hl, bc ; HL = CHARS address -__PRGRAPH: - ex de, hl ; HL = Write Address, DE = CHARS address - bit 2, (iy + $47) - call nz, __BOLD -#line 139 "/zxbasic/src/arch/zx48k/library-asm/print.asm" - bit 4, (iy + $47) - call nz, __ITALIC -#line 144 "/zxbasic/src/arch/zx48k/library-asm/print.asm" - ld hl, (DFCC) - push hl - ld b, 8 ; 8 bytes per char -__PRCHAR: - ld a, (de) ; DE *must* be source, and HL destiny -PRINT_MODE: ; Which operation is used to write on the screen - ; Set it with: - ; LD A, - ; LD (PRINT_MODE), A - ; - ; Available operations: - ; NORMAL : 0h --> NOP ; OVER 0 - ; XOR : AEh --> XOR (HL) ; OVER 1 - ; OR : B6h --> OR (HL) ; PUTSPRITE - ; AND : A6h --> AND (HL) ; PUTMASK - nop ; Set to one of the values above -INVERSE_MODE: ; 00 -> NOP -> INVERSE 0 - nop ; 2F -> CPL -> INVERSE 1 - ld (hl), a - inc de - inc h ; Next line - djnz __PRCHAR - pop hl +MEM_FREE: +__MEM_FREE: ; Frees the block pointed by HL + ; HL DE BC & AF modified + PROC + LOCAL __MEM_LOOP2 + LOCAL __MEM_LINK_PREV + LOCAL __MEM_JOIN_TEST + LOCAL __MEM_BLOCK_JOIN + ld a, h + or l + ret z ; Return if NULL pointer + dec hl + dec hl + ld b, h + ld c, l ; BC = Block pointer + ld hl, ZXBASIC_MEM_HEAP ; This label point to the heap start +__MEM_LOOP2: inc hl - ld (DFCC), hl - ld hl, (DFCCL) ; current ATTR Pos - push hl - call __SET_ATTR - pop hl + inc hl ; Next block ptr + ld e, (hl) inc hl - ld (DFCCL),hl - exx - ret - ; ------------- SPECIAL CHARS (< 32) ----------------- -__PRINT_SPECIAL: ; Jumps here if it is a special char - ld hl, __PRINT_TABLE - jp JUMP_HL_PLUS_2A -PRINT_EOL: ; Called WHENEVER there is no ";" at end of PRINT sentence - exx -__PRINT_0Dh: ; Called WHEN printing CHR$(13) - ld hl, (S_POSN) - dec l - jr nz, 1f - dec h - jr nz, 1f - inc h - push hl - call __SCROLL_SCR - pop hl -#line 210 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -1: - ld l, 1 -__PRINT_EOL_END: - call SET_SCR_ADDR - exx - ret -__PRINT_COM: - exx + ld d, (hl) ; Block next ptr + ex de, hl ; DE = &(block->next); HL = block->next + ld a, h ; HL == NULL? + or l + jp z, __MEM_LINK_PREV; if so, link with previous + or a ; Clear carry flag + sbc hl, bc ; Carry if BC > HL => This block if before + add hl, bc ; Restores HL, preserving Carry flag + jp c, __MEM_LOOP2 ; This block is before. Keep searching PASS the block + ;------ At this point current HL is PAST BC, so we must link (DE) with BC, and HL in BC->next +__MEM_LINK_PREV: ; Link (DE) with BC, and BC->next with HL + ex de, hl push hl - push de - push bc - call PRINT_COMMA - pop bc - pop de + dec hl + ld (hl), c + inc hl + ld (hl), b ; (DE) <- BC + ld h, b ; HL <- BC (Free block ptr) + ld l, c + inc hl ; Skip block length (2 bytes) + inc hl + ld (hl), e ; Block->next = DE + inc hl + ld (hl), d + ; --- LINKED ; HL = &(BC->next) + 2 + call __MEM_JOIN_TEST pop hl - ret -__PRINT_TAB: - ld hl, __PRINT_TAB1 - jr __PRINT_SET_STATE -__PRINT_TAB1: - ld (MEM0), a - ld hl, __PRINT_TAB2 - jr __PRINT_SET_STATE -__PRINT_TAB2: - ld a, (MEM0) ; Load tab code (ignore the current one) - ld hl, __PRINT_START - ld (PRINT_JUMP_STATE), hl - exx - push hl - push bc - push de - call PRINT_TAB - pop de - pop bc +__MEM_JOIN_TEST: ; Checks for fragmented contiguous blocks and joins them + ; hl = Ptr to current block + 2 + ld d, (hl) + dec hl + ld e, (hl) + dec hl + ld b, (hl) ; Loads block length into BC + dec hl + ld c, (hl) ; + push hl ; Saves it for later + add hl, bc ; Adds its length. If HL == DE now, it must be joined + or a + sbc hl, de ; If Z, then HL == DE => We must join pop hl + ret nz +__MEM_BLOCK_JOIN: ; Joins current block (pointed by HL) with next one (pointed by DE). HL->length already in BC + push hl ; Saves it for later + ex de, hl + ld e, (hl) ; DE -> block->next->length + inc hl + ld d, (hl) + inc hl + ex de, hl ; DE = &(block->next) + add hl, bc ; HL = Total Length + ld b, h + ld c, l ; BC = Total Length + ex de, hl + ld e, (hl) + inc hl + ld d, (hl) ; DE = block->next + pop hl ; Recovers Pointer to block + ld (hl), c + inc hl + ld (hl), b ; Length Saved + inc hl + ld (hl), e + inc hl + ld (hl), d ; Next saved ret -__PRINT_AT: - ld hl, __PRINT_AT1 - jr __PRINT_SET_STATE -__PRINT_NOP: -__PRINT_RESTART: - ld hl, __PRINT_START -__PRINT_SET_STATE: - ld (PRINT_JUMP_STATE), hl ; Saves next entry call - exx - ret -__PRINT_AT1: ; Jumps here if waiting for 1st parameter - ld hl, (S_POSN) - ld h, a - ld a, SCR_ROWS - sub h - ld (S_POSN + 1), a - ld hl, __PRINT_AT2 - jr __PRINT_SET_STATE -__PRINT_AT2: - call __LOAD_S_POSN - ld e, a - call __SAVE_S_POSN - jr __PRINT_RESTART -__PRINT_DEL: - call __LOAD_S_POSN ; Gets current screen position - dec e - ld a, -1 - cp e - jr nz, 3f - ld e, SCR_COLS - 2 - dec d - cp d - jr nz, 3f - ld d, SCR_ROWS - 1 -3: - call __SAVE_S_POSN - exx - ret -__PRINT_INK: - ld hl, __PRINT_INK2 - jr __PRINT_SET_STATE -__PRINT_INK2: - call INK_TMP - jr __PRINT_RESTART -__PRINT_PAP: - ld hl, __PRINT_PAP2 - jr __PRINT_SET_STATE -__PRINT_PAP2: - call PAPER_TMP - jr __PRINT_RESTART -__PRINT_FLA: - ld hl, __PRINT_FLA2 - jr __PRINT_SET_STATE -__PRINT_FLA2: - call FLASH_TMP - jr __PRINT_RESTART -__PRINT_BRI: - ld hl, __PRINT_BRI2 - jr __PRINT_SET_STATE -__PRINT_BRI2: - call BRIGHT_TMP - jr __PRINT_RESTART -__PRINT_INV: - ld hl, __PRINT_INV2 - jr __PRINT_SET_STATE -__PRINT_INV2: - call INVERSE_TMP - jr __PRINT_RESTART -__PRINT_OVR: - ld hl, __PRINT_OVR2 - jr __PRINT_SET_STATE -__PRINT_OVR2: - call OVER_TMP - jr __PRINT_RESTART -__PRINT_BOLD: - ld hl, __PRINT_BOLD2 - jp __PRINT_SET_STATE -__PRINT_BOLD2: - call BOLD_TMP - jp __PRINT_RESTART -#line 354 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -__PRINT_ITA: - ld hl, __PRINT_ITA2 - jp __PRINT_SET_STATE -__PRINT_ITA2: - call ITALIC_TMP - jp __PRINT_RESTART -#line 364 "/zxbasic/src/arch/zx48k/library-asm/print.asm" - LOCAL __BOLD -__BOLD: - push hl - ld hl, MEM0 - ld b, 8 -1: - ld a, (de) - ld c, a - rlca - or c - ld (hl), a + ENDP + pop namespace +#line 63 "zx48k/lcd9.bas" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/loadstr.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/alloc.asm" +; vim: ts=4:et:sw=4: + ; Copyleft (K) by Jose M. Rodriguez de la Rosa + ; (a.k.a. Boriel) +; http://www.boriel.com + ; + ; This ASM library is licensed under the MIT license + ; you can use it for any purpose (even for commercial + ; closed source programs). + ; + ; Please read the MIT license on the internet + ; ----- IMPLEMENTATION NOTES ------ + ; The heap is implemented as a linked list of free blocks. +; Each free block contains this info: + ; + ; +----------------+ <-- HEAP START + ; | Size (2 bytes) | + ; | 0 | <-- Size = 0 => DUMMY HEADER BLOCK + ; +----------------+ + ; | Next (2 bytes) |---+ + ; +----------------+ <-+ + ; | Size (2 bytes) | + ; +----------------+ + ; | Next (2 bytes) |---+ + ; +----------------+ | + ; | | | <-- If Size > 4, then this contains (size - 4) bytes + ; | (0 if Size = 4)| | + ; +----------------+ <-+ + ; | Size (2 bytes) | + ; +----------------+ + ; | Next (2 bytes) |---+ + ; +----------------+ | + ; | | | + ; | (0 if Size = 4)| | + ; +----------------+ | + ; | <-- This zone is in use (Already allocated) + ; +----------------+ <-+ + ; | Size (2 bytes) | + ; +----------------+ + ; | Next (2 bytes) |---+ + ; +----------------+ | + ; | | | + ; | (0 if Size = 4)| | + ; +----------------+ <-+ + ; | Next (2 bytes) |--> NULL => END OF LIST + ; | 0 = NULL | + ; +----------------+ + ; | | + ; | (0 if Size = 4)| + ; +----------------+ + ; When a block is FREED, the previous and next pointers are examined to see + ; if we can defragment the heap. If the block to be freed is just next to the + ; previous, or to the next (or both) they will be converted into a single + ; block (so defragmented). + ; MEMORY MANAGER + ; + ; This library must be initialized calling __MEM_INIT with + ; HL = BLOCK Start & DE = Length. + ; An init directive is useful for initialization routines. + ; They will be added automatically if needed. + ; --------------------------------------------------------------------- + ; MEM_ALLOC + ; Allocates a block of memory in the heap. + ; + ; Parameters + ; BC = Length of requested memory block + ; +; Returns: + ; HL = Pointer to the allocated block in memory. Returns 0 (NULL) + ; if the block could not be allocated (out of memory) + ; --------------------------------------------------------------------- + push namespace core +MEM_ALLOC: +__MEM_ALLOC: ; Returns the 1st free block found of the given length (in BC) + PROC + LOCAL __MEM_LOOP + LOCAL __MEM_DONE + LOCAL __MEM_SUBTRACT + LOCAL __MEM_START + LOCAL TEMP, TEMP0 + TEMP EQU TEMP0 + 1 + ld hl, 0 + ld (TEMP), hl +__MEM_START: + ld hl, ZXBASIC_MEM_HEAP ; This label point to the heap start + inc bc + inc bc ; BC = BC + 2 ; block size needs 2 extra bytes for hidden pointer +__MEM_LOOP: ; Loads lengh at (HL, HL+). If Lenght >= BC, jump to __MEM_DONE + ld a, h ; HL = NULL (No memory available?) + or l +#line 113 "/zxbasic/src/arch/zx48k/library-asm/alloc.asm" + ret z ; NULL +#line 115 "/zxbasic/src/arch/zx48k/library-asm/alloc.asm" + ; HL = Pointer to Free block + ld e, (hl) inc hl - inc de - djnz 1b + ld d, (hl) + inc hl ; DE = Block Length + push hl ; HL = *pointer to -> next block + ex de, hl + or a ; CF = 0 + sbc hl, bc ; FREE >= BC (Length) (HL = BlockLength - Length) + jp nc, __MEM_DONE pop hl - ld de, MEM0 - ret -#line 385 "/zxbasic/src/arch/zx48k/library-asm/print.asm" - LOCAL __ITALIC -__ITALIC: - push hl - ld hl, MEM0 + ld (TEMP), hl ex de, hl - ld bc, 8 - ldir - ld hl, MEM0 - srl (hl) - inc hl - srl (hl) - inc hl - srl (hl) - inc hl - inc hl + ld e, (hl) inc hl - sla (hl) + ld d, (hl) + ex de, hl + jp __MEM_LOOP +__MEM_DONE: ; A free block has been found. + ; Check if at least 4 bytes remains free (HL >= 4) + push hl + exx ; exx to preserve bc + pop hl + ld bc, 4 + or a + sbc hl, bc + exx + jp nc, __MEM_SUBTRACT + ; At this point... + ; less than 4 bytes remains free. So we return this block entirely + ; We must link the previous block with the next to this one + ; (DE) => Pointer to next block + ; (TEMP) => &(previous->next) + pop hl ; Discard current block pointer + push de + ex de, hl ; DE = Previous block pointer; (HL) = Next block pointer + ld a, (hl) inc hl - sla (hl) + ld h, (hl) + ld l, a ; HL = (HL) + ex de, hl ; HL = Previous block pointer; DE = Next block pointer +TEMP0: + ld hl, 0 ; Pre-previous block pointer + ld (hl), e inc hl - sla (hl) - pop hl - ld de, MEM0 - ret -#line 413 "/zxbasic/src/arch/zx48k/library-asm/print.asm" - LOCAL __SCROLL_SCR -#line 487 "/zxbasic/src/arch/zx48k/library-asm/print.asm" - __SCROLL_SCR EQU 0DFEh ; Use ROM SCROLL -#line 489 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -#line 490 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -PRINT_COMMA: - call __LOAD_S_POSN - ld a, e - and 16 - add a, 16 -PRINT_TAB: - ; Tabulates the number of spaces in A register - ; If the current cursor position is already A, does nothing - PROC - LOCAL LOOP - call __LOAD_S_POSN ; e = current row - sub e - and 31 - ret z - ld b, a -LOOP: - ld a, ' ' - call __PRINTCHAR - djnz LOOP + ld (hl), d ; LINKED + pop hl ; Returning block. ret - ENDP -PRINT_AT: ; Changes cursor to ROW, COL - ; COL in A register - ; ROW in stack - pop hl ; Ret address - ex (sp), hl ; callee H = ROW - ld l, a +__MEM_SUBTRACT: + ; At this point we have to store HL value (Length - BC) into (DE - 2) ex de, hl - call __IN_SCREEN - ret nc ; Return if out of screen - jp __SAVE_S_POSN - LOCAL __PRINT_COM - LOCAL __PRINT_AT1 - LOCAL __PRINT_AT2 - LOCAL __PRINT_BOLD - LOCAL __PRINT_ITA - LOCAL __PRINT_INK - LOCAL __PRINT_PAP - LOCAL __PRINT_SET_STATE - LOCAL __PRINT_TABLE - LOCAL __PRINT_TAB, __PRINT_TAB1, __PRINT_TAB2 - LOCAL __PRINT_ITA2 -#line 546 "/zxbasic/src/arch/zx48k/library-asm/print.asm" - LOCAL __PRINT_BOLD2 -#line 552 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -__PRINT_TABLE: ; Jump table for 0 .. 22 codes - DW __PRINT_NOP ; 0 - DW __PRINT_NOP ; 1 - DW __PRINT_NOP ; 2 - DW __PRINT_NOP ; 3 - DW __PRINT_NOP ; 4 - DW __PRINT_NOP ; 5 - DW __PRINT_COM ; 6 COMMA - DW __PRINT_NOP ; 7 - DW __PRINT_DEL ; 8 DEL - DW __PRINT_NOP ; 9 - DW __PRINT_NOP ; 10 - DW __PRINT_NOP ; 11 - DW __PRINT_NOP ; 12 - DW __PRINT_0Dh ; 13 - DW __PRINT_BOLD ; 14 - DW __PRINT_ITA ; 15 - DW __PRINT_INK ; 16 - DW __PRINT_PAP ; 17 - DW __PRINT_FLA ; 18 - DW __PRINT_BRI ; 19 - DW __PRINT_INV ; 20 - DW __PRINT_OVR ; 21 - DW __PRINT_AT ; 22 AT - DW __PRINT_TAB ; 23 TAB + dec hl + ld (hl), d + dec hl + ld (hl), e ; Store new block length + add hl, de ; New length + DE => free-block start + pop de ; Remove previous HL off the stack + ld (hl), c ; Store length on its 1st word + inc hl + ld (hl), b + inc hl ; Return hl + ret ENDP pop namespace -#line 5 "/zxbasic/src/arch/zx48k/library-asm/print_eol_attr.asm" +#line 2 "/zxbasic/src/arch/zx48k/library-asm/loadstr.asm" + ; Loads a string (ptr) from HL + ; and duplicates it on dynamic memory again + ; Finally, it returns result pointer in HL push namespace core -PRINT_EOL_ATTR: - call PRINT_EOL - jp COPY_ATTR +__ILOADSTR: ; This is the indirect pointer entry HL = (HL) + ld a, h + or l + ret z + ld a, (hl) + inc hl + ld h, (hl) + ld l, a +__LOADSTR: ; __FASTCALL__ entry + ld a, h + or l + ret z ; Return if NULL + ld c, (hl) + inc hl + ld b, (hl) + dec hl ; BC = LEN(a$) + inc bc + inc bc ; BC = LEN(a$) + 2 (two bytes for length) + push hl + push bc + call __MEM_ALLOC + pop bc ; Recover length + pop de ; Recover origin + ld a, h + or l + ret z ; Return if NULL (No memory) + ex de, hl ; ldir takes HL as source, DE as destiny, so SWAP HL,DE + push de ; Saves destiny start + ldir ; Copies string (length number included) + pop hl ; Recovers destiny in hl as result + ret pop namespace -#line 63 "zx48k/lcd9.bas" +#line 64 "zx48k/lcd9.bas" #line 1 "/zxbasic/src/arch/zx48k/library-asm/printstr.asm" ; PRINT command routine ; Prints string pointed by HL @@ -1515,7 +1506,7 @@ __PRINT_STR: jp __PRINT_STR_LOOP ENDP pop namespace -#line 64 "zx48k/lcd9.bas" +#line 66 "zx48k/lcd9.bas" #line 1 "/zxbasic/src/arch/zx48k/library-asm/storestr.asm" ; vim:ts=4:et:sw=4 ; Stores value of current string pointed by DE register into address pointed by HL @@ -1764,5 +1755,5 @@ __STORE_STR: pop hl ; Returns ptr to b$ in HL (Caller might needed to free it from memory) ret pop namespace -#line 65 "zx48k/lcd9.bas" +#line 67 "zx48k/lcd9.bas" END diff --git a/tests/functional/zx48k/let_array_local_const0.asm b/tests/functional/zx48k/let_array_local_const0.asm index ecdbc2cc0..b91d4687a 100644 --- a/tests/functional/zx48k/let_array_local_const0.asm +++ b/tests/functional/zx48k/let_array_local_const0.asm @@ -92,6 +92,7 @@ _test: ld (_i), hl jp .LABEL.__LABEL0 .LABEL.__LABEL3: + call .core.COPY_ATTR ld hl, (_i) push hl push ix @@ -266,7 +267,7 @@ TMP_ARR_PTR: DW 0 ; temporary storage for pointer to tables ENDP pop namespace -#line 99 "zx48k/let_array_local_const0.bas" +#line 100 "zx48k/let_array_local_const0.bas" #line 1 "/zxbasic/src/arch/zx48k/library-asm/arrayalloc.asm" #line 1 "/zxbasic/src/arch/zx48k/library-asm/calloc.asm" ; vim: ts=4:et:sw=4: @@ -679,168 +680,8 @@ __ALLOC_INITIALIZED_LOCAL_ARRAY: ret #line 139 "/zxbasic/src/arch/zx48k/library-asm/arrayalloc.asm" pop namespace -#line 100 "zx48k/let_array_local_const0.bas" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/free.asm" -; vim: ts=4:et:sw=4: - ; Copyleft (K) by Jose M. Rodriguez de la Rosa - ; (a.k.a. Boriel) -; http://www.boriel.com - ; - ; This ASM library is licensed under the BSD license - ; you can use it for any purpose (even for commercial - ; closed source programs). - ; - ; Please read the BSD license on the internet - ; ----- IMPLEMENTATION NOTES ------ - ; The heap is implemented as a linked list of free blocks. -; Each free block contains this info: - ; - ; +----------------+ <-- HEAP START - ; | Size (2 bytes) | - ; | 0 | <-- Size = 0 => DUMMY HEADER BLOCK - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ <-+ - ; | Size (2 bytes) | - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ | - ; | | | <-- If Size > 4, then this contains (size - 4) bytes - ; | (0 if Size = 4)| | - ; +----------------+ <-+ - ; | Size (2 bytes) | - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ | - ; | | | - ; | (0 if Size = 4)| | - ; +----------------+ | - ; | <-- This zone is in use (Already allocated) - ; +----------------+ <-+ - ; | Size (2 bytes) | - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ | - ; | | | - ; | (0 if Size = 4)| | - ; +----------------+ <-+ - ; | Next (2 bytes) |--> NULL => END OF LIST - ; | 0 = NULL | - ; +----------------+ - ; | | - ; | (0 if Size = 4)| - ; +----------------+ - ; When a block is FREED, the previous and next pointers are examined to see - ; if we can defragment the heap. If the block to be breed is just next to the - ; previous, or to the next (or both) they will be converted into a single - ; block (so defragmented). - ; MEMORY MANAGER - ; - ; This library must be initialized calling __MEM_INIT with - ; HL = BLOCK Start & DE = Length. - ; An init directive is useful for initialization routines. - ; They will be added automatically if needed. - ; --------------------------------------------------------------------- - ; MEM_FREE - ; Frees a block of memory - ; -; Parameters: - ; HL = Pointer to the block to be freed. If HL is NULL (0) nothing - ; is done - ; --------------------------------------------------------------------- - push namespace core -MEM_FREE: -__MEM_FREE: ; Frees the block pointed by HL - ; HL DE BC & AF modified - PROC - LOCAL __MEM_LOOP2 - LOCAL __MEM_LINK_PREV - LOCAL __MEM_JOIN_TEST - LOCAL __MEM_BLOCK_JOIN - ld a, h - or l - ret z ; Return if NULL pointer - dec hl - dec hl - ld b, h - ld c, l ; BC = Block pointer - ld hl, ZXBASIC_MEM_HEAP ; This label point to the heap start -__MEM_LOOP2: - inc hl - inc hl ; Next block ptr - ld e, (hl) - inc hl - ld d, (hl) ; Block next ptr - ex de, hl ; DE = &(block->next); HL = block->next - ld a, h ; HL == NULL? - or l - jp z, __MEM_LINK_PREV; if so, link with previous - or a ; Clear carry flag - sbc hl, bc ; Carry if BC > HL => This block if before - add hl, bc ; Restores HL, preserving Carry flag - jp c, __MEM_LOOP2 ; This block is before. Keep searching PASS the block - ;------ At this point current HL is PAST BC, so we must link (DE) with BC, and HL in BC->next -__MEM_LINK_PREV: ; Link (DE) with BC, and BC->next with HL - ex de, hl - push hl - dec hl - ld (hl), c - inc hl - ld (hl), b ; (DE) <- BC - ld h, b ; HL <- BC (Free block ptr) - ld l, c - inc hl ; Skip block length (2 bytes) - inc hl - ld (hl), e ; Block->next = DE - inc hl - ld (hl), d - ; --- LINKED ; HL = &(BC->next) + 2 - call __MEM_JOIN_TEST - pop hl -__MEM_JOIN_TEST: ; Checks for fragmented contiguous blocks and joins them - ; hl = Ptr to current block + 2 - ld d, (hl) - dec hl - ld e, (hl) - dec hl - ld b, (hl) ; Loads block length into BC - dec hl - ld c, (hl) ; - push hl ; Saves it for later - add hl, bc ; Adds its length. If HL == DE now, it must be joined - or a - sbc hl, de ; If Z, then HL == DE => We must join - pop hl - ret nz -__MEM_BLOCK_JOIN: ; Joins current block (pointed by HL) with next one (pointed by DE). HL->length already in BC - push hl ; Saves it for later - ex de, hl - ld e, (hl) ; DE -> block->next->length - inc hl - ld d, (hl) - inc hl - ex de, hl ; DE = &(block->next) - add hl, bc ; HL = Total Length - ld b, h - ld c, l ; BC = Total Length - ex de, hl - ld e, (hl) - inc hl - ld d, (hl) ; DE = block->next - pop hl ; Recovers Pointer to block - ld (hl), c - inc hl - ld (hl), b ; Length Saved - inc hl - ld (hl), e - inc hl - ld (hl), d ; Next saved - ret - ENDP - pop namespace #line 101 "zx48k/let_array_local_const0.bas" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/printi8.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/printnum.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" #line 1 "/zxbasic/src/arch/zx48k/library-asm/print.asm" ; vim:ts=4:sw=4:et: ; PRINT command routine @@ -1155,60 +996,6 @@ BRIGHT_TMP: #line 1 "/zxbasic/src/arch/zx48k/library-asm/over.asm" ; Sets OVER flag in P_FLAG permanently ; Parameter: OVER flag in bit 0 of A register -#line 1 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" -#line 4 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" - push namespace core -COPY_ATTR: - ; Just copies current permanent attribs into temporal attribs - ; and sets print mode - PROC - LOCAL INVERSE1 - LOCAL __REFRESH_TMP - INVERSE1 EQU 02Fh - ld hl, (ATTR_P) - ld (ATTR_T), hl - ld hl, FLAGS2 - call __REFRESH_TMP - ld hl, P_FLAG - call __REFRESH_TMP -__SET_ATTR_MODE: ; Another entry to set print modes. A contains (P_FLAG) - LOCAL TABLE - LOCAL CONT2 - rra ; Over bit to carry - ld a, (FLAGS2) - rla ; Over bit in bit 1, Over2 bit in bit 2 - and 3 ; Only bit 0 and 1 (OVER flag) - ld c, a - ld b, 0 - ld hl, TABLE - add hl, bc - ld a, (hl) - ld (PRINT_MODE), a - ld hl, (P_FLAG) - xor a ; NOP -> INVERSE0 - bit 2, l - jr z, CONT2 - ld a, INVERSE1 ; CPL -> INVERSE1 -CONT2: - ld (INVERSE_MODE), a - ret -TABLE: - nop ; NORMAL MODE - xor (hl) ; OVER 1 MODE - and (hl) ; OVER 2 MODE - or (hl) ; OVER 3 MODE -#line 67 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" -__REFRESH_TMP: - ld a, (hl) - and 0b10101010 - ld c, a - rra - or c - ld (hl), a - ret - ENDP - pop namespace -#line 4 "/zxbasic/src/arch/zx48k/library-asm/over.asm" push namespace core OVER: PROC @@ -1450,11 +1237,10 @@ INVERSE_MODE: ; 00 -> NOP -> INVERSE 0 inc hl ld (DFCC), hl ld hl, (DFCCL) ; current ATTR Pos - push hl - call __SET_ATTR - pop hl inc hl - ld (DFCCL),hl + ld (DFCCL), hl + dec hl + call __SET_ATTR exx ret ; ------------- SPECIAL CHARS (< 32) ----------------- @@ -1473,7 +1259,7 @@ __PRINT_0Dh: ; Called WHEN printing CHR$(13) push hl call __SCROLL_SCR pop hl -#line 210 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 209 "/zxbasic/src/arch/zx48k/library-asm/print.asm" 1: ld l, 1 __PRINT_EOL_END: @@ -1590,14 +1376,14 @@ __PRINT_BOLD: __PRINT_BOLD2: call BOLD_TMP jp __PRINT_RESTART -#line 354 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 353 "/zxbasic/src/arch/zx48k/library-asm/print.asm" __PRINT_ITA: ld hl, __PRINT_ITA2 jp __PRINT_SET_STATE __PRINT_ITA2: call ITALIC_TMP jp __PRINT_RESTART -#line 364 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 363 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __BOLD __BOLD: push hl @@ -1615,7 +1401,7 @@ __BOLD: pop hl ld de, MEM0 ret -#line 385 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 384 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __ITALIC __ITALIC: push hl @@ -1640,12 +1426,12 @@ __ITALIC: pop hl ld de, MEM0 ret -#line 413 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 412 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __SCROLL_SCR -#line 487 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 486 "/zxbasic/src/arch/zx48k/library-asm/print.asm" __SCROLL_SCR EQU 0DFEh ; Use ROM SCROLL +#line 488 "/zxbasic/src/arch/zx48k/library-asm/print.asm" #line 489 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -#line 490 "/zxbasic/src/arch/zx48k/library-asm/print.asm" PRINT_COMMA: call __LOAD_S_POSN ld a, e @@ -1688,9 +1474,9 @@ PRINT_AT: ; Changes cursor to ROW, COL LOCAL __PRINT_TABLE LOCAL __PRINT_TAB, __PRINT_TAB1, __PRINT_TAB2 LOCAL __PRINT_ITA2 -#line 546 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 545 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __PRINT_BOLD2 -#line 552 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 551 "/zxbasic/src/arch/zx48k/library-asm/print.asm" __PRINT_TABLE: ; Jump table for 0 .. 22 codes DW __PRINT_NOP ; 0 DW __PRINT_NOP ; 1 @@ -1718,7 +1504,221 @@ __PRINT_TABLE: ; Jump table for 0 .. 22 codes DW __PRINT_TAB ; 23 TAB ENDP pop namespace -#line 2 "/zxbasic/src/arch/zx48k/library-asm/printnum.asm" +#line 3 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" +#line 4 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" + push namespace core +COPY_ATTR: + ; Just copies current permanent attribs into temporal attribs + ; and sets print mode + PROC + LOCAL INVERSE1 + LOCAL __REFRESH_TMP + INVERSE1 EQU 02Fh + ld hl, (ATTR_P) + ld (ATTR_T), hl + ld hl, FLAGS2 + call __REFRESH_TMP + ld hl, P_FLAG + call __REFRESH_TMP +__SET_ATTR_MODE: ; Another entry to set print modes. A contains (P_FLAG) + LOCAL TABLE + LOCAL CONT2 + rra ; Over bit to carry + ld a, (FLAGS2) + rla ; Over bit in bit 1, Over2 bit in bit 2 + and 3 ; Only bit 0 and 1 (OVER flag) + ld c, a + ld b, 0 + ld hl, TABLE + add hl, bc + ld a, (hl) + ld (PRINT_MODE), a + ld hl, (P_FLAG) + xor a ; NOP -> INVERSE0 + bit 2, l + jr z, CONT2 + ld a, INVERSE1 ; CPL -> INVERSE1 +CONT2: + ld (INVERSE_MODE), a + ret +TABLE: + nop ; NORMAL MODE + xor (hl) ; OVER 1 MODE + and (hl) ; OVER 2 MODE + or (hl) ; OVER 3 MODE +#line 67 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" +__REFRESH_TMP: + ld a, (hl) + and 0b10101010 + ld c, a + rra + or c + ld (hl), a + ret + ENDP + pop namespace +#line 102 "zx48k/let_array_local_const0.bas" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/free.asm" +; vim: ts=4:et:sw=4: + ; Copyleft (K) by Jose M. Rodriguez de la Rosa + ; (a.k.a. Boriel) +; http://www.boriel.com + ; + ; This ASM library is licensed under the BSD license + ; you can use it for any purpose (even for commercial + ; closed source programs). + ; + ; Please read the BSD license on the internet + ; ----- IMPLEMENTATION NOTES ------ + ; The heap is implemented as a linked list of free blocks. +; Each free block contains this info: + ; + ; +----------------+ <-- HEAP START + ; | Size (2 bytes) | + ; | 0 | <-- Size = 0 => DUMMY HEADER BLOCK + ; +----------------+ + ; | Next (2 bytes) |---+ + ; +----------------+ <-+ + ; | Size (2 bytes) | + ; +----------------+ + ; | Next (2 bytes) |---+ + ; +----------------+ | + ; | | | <-- If Size > 4, then this contains (size - 4) bytes + ; | (0 if Size = 4)| | + ; +----------------+ <-+ + ; | Size (2 bytes) | + ; +----------------+ + ; | Next (2 bytes) |---+ + ; +----------------+ | + ; | | | + ; | (0 if Size = 4)| | + ; +----------------+ | + ; | <-- This zone is in use (Already allocated) + ; +----------------+ <-+ + ; | Size (2 bytes) | + ; +----------------+ + ; | Next (2 bytes) |---+ + ; +----------------+ | + ; | | | + ; | (0 if Size = 4)| | + ; +----------------+ <-+ + ; | Next (2 bytes) |--> NULL => END OF LIST + ; | 0 = NULL | + ; +----------------+ + ; | | + ; | (0 if Size = 4)| + ; +----------------+ + ; When a block is FREED, the previous and next pointers are examined to see + ; if we can defragment the heap. If the block to be breed is just next to the + ; previous, or to the next (or both) they will be converted into a single + ; block (so defragmented). + ; MEMORY MANAGER + ; + ; This library must be initialized calling __MEM_INIT with + ; HL = BLOCK Start & DE = Length. + ; An init directive is useful for initialization routines. + ; They will be added automatically if needed. + ; --------------------------------------------------------------------- + ; MEM_FREE + ; Frees a block of memory + ; +; Parameters: + ; HL = Pointer to the block to be freed. If HL is NULL (0) nothing + ; is done + ; --------------------------------------------------------------------- + push namespace core +MEM_FREE: +__MEM_FREE: ; Frees the block pointed by HL + ; HL DE BC & AF modified + PROC + LOCAL __MEM_LOOP2 + LOCAL __MEM_LINK_PREV + LOCAL __MEM_JOIN_TEST + LOCAL __MEM_BLOCK_JOIN + ld a, h + or l + ret z ; Return if NULL pointer + dec hl + dec hl + ld b, h + ld c, l ; BC = Block pointer + ld hl, ZXBASIC_MEM_HEAP ; This label point to the heap start +__MEM_LOOP2: + inc hl + inc hl ; Next block ptr + ld e, (hl) + inc hl + ld d, (hl) ; Block next ptr + ex de, hl ; DE = &(block->next); HL = block->next + ld a, h ; HL == NULL? + or l + jp z, __MEM_LINK_PREV; if so, link with previous + or a ; Clear carry flag + sbc hl, bc ; Carry if BC > HL => This block if before + add hl, bc ; Restores HL, preserving Carry flag + jp c, __MEM_LOOP2 ; This block is before. Keep searching PASS the block + ;------ At this point current HL is PAST BC, so we must link (DE) with BC, and HL in BC->next +__MEM_LINK_PREV: ; Link (DE) with BC, and BC->next with HL + ex de, hl + push hl + dec hl + ld (hl), c + inc hl + ld (hl), b ; (DE) <- BC + ld h, b ; HL <- BC (Free block ptr) + ld l, c + inc hl ; Skip block length (2 bytes) + inc hl + ld (hl), e ; Block->next = DE + inc hl + ld (hl), d + ; --- LINKED ; HL = &(BC->next) + 2 + call __MEM_JOIN_TEST + pop hl +__MEM_JOIN_TEST: ; Checks for fragmented contiguous blocks and joins them + ; hl = Ptr to current block + 2 + ld d, (hl) + dec hl + ld e, (hl) + dec hl + ld b, (hl) ; Loads block length into BC + dec hl + ld c, (hl) ; + push hl ; Saves it for later + add hl, bc ; Adds its length. If HL == DE now, it must be joined + or a + sbc hl, de ; If Z, then HL == DE => We must join + pop hl + ret nz +__MEM_BLOCK_JOIN: ; Joins current block (pointed by HL) with next one (pointed by DE). HL->length already in BC + push hl ; Saves it for later + ex de, hl + ld e, (hl) ; DE -> block->next->length + inc hl + ld d, (hl) + inc hl + ex de, hl ; DE = &(block->next) + add hl, bc ; HL = Total Length + ld b, h + ld c, l ; BC = Total Length + ex de, hl + ld e, (hl) + inc hl + ld d, (hl) ; DE = block->next + pop hl ; Recovers Pointer to block + ld (hl), c + inc hl + ld (hl), b ; Length Saved + inc hl + ld (hl), e + inc hl + ld (hl), d ; Next saved + ret + ENDP + pop namespace +#line 103 "zx48k/let_array_local_const0.bas" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/printi8.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/printnum.asm" push namespace core __PRINTU_START: PROC @@ -1836,7 +1836,7 @@ __PRINTU_LOOP: jp __PRINTU_LOOP ; Uses JP in loops ENDP pop namespace -#line 102 "zx48k/let_array_local_const0.bas" +#line 104 "zx48k/let_array_local_const0.bas" #line 1 "/zxbasic/src/arch/zx48k/library-asm/printstr.asm" ; PRINT command routine ; Prints string pointed by HL @@ -1880,7 +1880,7 @@ __PRINT_STR: jp __PRINT_STR_LOOP ENDP pop namespace -#line 103 "zx48k/let_array_local_const0.bas" +#line 105 "zx48k/let_array_local_const0.bas" .LABEL.__LABEL6: DEFB 00h DEFB 00h diff --git a/tests/functional/zx48k/load02.asm b/tests/functional/zx48k/load02.asm index 2d8bbecb8..991339296 100644 --- a/tests/functional/zx48k/load02.asm +++ b/tests/functional/zx48k/load02.asm @@ -949,11 +949,10 @@ INVERSE_MODE: ; 00 -> NOP -> INVERSE 0 inc hl ld (DFCC), hl ld hl, (DFCCL) ; current ATTR Pos - push hl - call __SET_ATTR - pop hl inc hl - ld (DFCCL),hl + ld (DFCCL), hl + dec hl + call __SET_ATTR exx ret ; ------------- SPECIAL CHARS (< 32) ----------------- @@ -972,7 +971,7 @@ __PRINT_0Dh: ; Called WHEN printing CHR$(13) push hl call __SCROLL_SCR pop hl -#line 210 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 209 "/zxbasic/src/arch/zx48k/library-asm/print.asm" 1: ld l, 1 __PRINT_EOL_END: @@ -1089,14 +1088,14 @@ __PRINT_BOLD: __PRINT_BOLD2: call BOLD_TMP jp __PRINT_RESTART -#line 354 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 353 "/zxbasic/src/arch/zx48k/library-asm/print.asm" __PRINT_ITA: ld hl, __PRINT_ITA2 jp __PRINT_SET_STATE __PRINT_ITA2: call ITALIC_TMP jp __PRINT_RESTART -#line 364 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 363 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __BOLD __BOLD: push hl @@ -1114,7 +1113,7 @@ __BOLD: pop hl ld de, MEM0 ret -#line 385 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 384 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __ITALIC __ITALIC: push hl @@ -1139,12 +1138,12 @@ __ITALIC: pop hl ld de, MEM0 ret -#line 413 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 412 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __SCROLL_SCR -#line 487 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 486 "/zxbasic/src/arch/zx48k/library-asm/print.asm" __SCROLL_SCR EQU 0DFEh ; Use ROM SCROLL +#line 488 "/zxbasic/src/arch/zx48k/library-asm/print.asm" #line 489 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -#line 490 "/zxbasic/src/arch/zx48k/library-asm/print.asm" PRINT_COMMA: call __LOAD_S_POSN ld a, e @@ -1187,9 +1186,9 @@ PRINT_AT: ; Changes cursor to ROW, COL LOCAL __PRINT_TABLE LOCAL __PRINT_TAB, __PRINT_TAB1, __PRINT_TAB2 LOCAL __PRINT_ITA2 -#line 546 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 545 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __PRINT_BOLD2 -#line 552 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 551 "/zxbasic/src/arch/zx48k/library-asm/print.asm" __PRINT_TABLE: ; Jump table for 0 .. 22 codes DW __PRINT_NOP ; 0 DW __PRINT_NOP ; 1 diff --git a/tests/functional/zx48k/load03.asm b/tests/functional/zx48k/load03.asm index 39781a265..52847e6a8 100644 --- a/tests/functional/zx48k/load03.asm +++ b/tests/functional/zx48k/load03.asm @@ -946,11 +946,10 @@ INVERSE_MODE: ; 00 -> NOP -> INVERSE 0 inc hl ld (DFCC), hl ld hl, (DFCCL) ; current ATTR Pos - push hl - call __SET_ATTR - pop hl inc hl - ld (DFCCL),hl + ld (DFCCL), hl + dec hl + call __SET_ATTR exx ret ; ------------- SPECIAL CHARS (< 32) ----------------- @@ -969,7 +968,7 @@ __PRINT_0Dh: ; Called WHEN printing CHR$(13) push hl call __SCROLL_SCR pop hl -#line 210 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 209 "/zxbasic/src/arch/zx48k/library-asm/print.asm" 1: ld l, 1 __PRINT_EOL_END: @@ -1086,14 +1085,14 @@ __PRINT_BOLD: __PRINT_BOLD2: call BOLD_TMP jp __PRINT_RESTART -#line 354 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 353 "/zxbasic/src/arch/zx48k/library-asm/print.asm" __PRINT_ITA: ld hl, __PRINT_ITA2 jp __PRINT_SET_STATE __PRINT_ITA2: call ITALIC_TMP jp __PRINT_RESTART -#line 364 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 363 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __BOLD __BOLD: push hl @@ -1111,7 +1110,7 @@ __BOLD: pop hl ld de, MEM0 ret -#line 385 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 384 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __ITALIC __ITALIC: push hl @@ -1136,12 +1135,12 @@ __ITALIC: pop hl ld de, MEM0 ret -#line 413 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 412 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __SCROLL_SCR -#line 487 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 486 "/zxbasic/src/arch/zx48k/library-asm/print.asm" __SCROLL_SCR EQU 0DFEh ; Use ROM SCROLL +#line 488 "/zxbasic/src/arch/zx48k/library-asm/print.asm" #line 489 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -#line 490 "/zxbasic/src/arch/zx48k/library-asm/print.asm" PRINT_COMMA: call __LOAD_S_POSN ld a, e @@ -1184,9 +1183,9 @@ PRINT_AT: ; Changes cursor to ROW, COL LOCAL __PRINT_TABLE LOCAL __PRINT_TAB, __PRINT_TAB1, __PRINT_TAB2 LOCAL __PRINT_ITA2 -#line 546 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 545 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __PRINT_BOLD2 -#line 552 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 551 "/zxbasic/src/arch/zx48k/library-asm/print.asm" __PRINT_TABLE: ; Jump table for 0 .. 22 codes DW __PRINT_NOP ; 0 DW __PRINT_NOP ; 1 diff --git a/tests/functional/zx48k/loadu16ii.asm b/tests/functional/zx48k/loadu16ii.asm index e59585037..efbc7b4b1 100644 --- a/tests/functional/zx48k/loadu16ii.asm +++ b/tests/functional/zx48k/loadu16ii.asm @@ -21,9 +21,11 @@ .core.__LABEL__.ZXBASIC_USER_DATA EQU .core.ZXBASIC_USER_DATA .core.ZXBASIC_USER_DATA_END: .core.__MAIN_PROGRAM__: + call .core.COPY_ATTR ld hl, (.LABEL._test) call .core.__PRINTU16 call .core.PRINT_EOL + call .core.COPY_ATTR ld a, (.LABEL._test) ld l, a ld h, 0 @@ -61,33 +63,7 @@ ld c, l jp .core.__END_PROGRAM ;; --- end of user code --- -#line 1 "/zxbasic/src/arch/zx48k/library-asm/mul16.asm" - push namespace core -__MUL16: ; Mutiplies HL with the last value stored into de stack - ; Works for both signed and unsigned - PROC - LOCAL __MUL16LOOP - LOCAL __MUL16NOADD - ex de, hl - pop hl ; Return address - ex (sp), hl ; CALLEE caller convention -__MUL16_FAST: - ld b, 16 - ld a, h - ld c, l - ld hl, 0 -__MUL16LOOP: - add hl, hl ; hl << 1 - sla c - rla ; a,c << 1 - jp nc, __MUL16NOADD - add hl, de -__MUL16NOADD: - djnz __MUL16LOOP - ret ; Result in hl (16 lower bits) - ENDP - pop namespace -#line 15 "zx48k/loadu16ii.bas" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" #line 1 "/zxbasic/src/arch/zx48k/library-asm/print.asm" ; vim:ts=4:sw=4:et: ; PRINT command routine @@ -437,60 +413,6 @@ BRIGHT_TMP: #line 1 "/zxbasic/src/arch/zx48k/library-asm/over.asm" ; Sets OVER flag in P_FLAG permanently ; Parameter: OVER flag in bit 0 of A register -#line 1 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" -#line 4 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" - push namespace core -COPY_ATTR: - ; Just copies current permanent attribs into temporal attribs - ; and sets print mode - PROC - LOCAL INVERSE1 - LOCAL __REFRESH_TMP - INVERSE1 EQU 02Fh - ld hl, (ATTR_P) - ld (ATTR_T), hl - ld hl, FLAGS2 - call __REFRESH_TMP - ld hl, P_FLAG - call __REFRESH_TMP -__SET_ATTR_MODE: ; Another entry to set print modes. A contains (P_FLAG) - LOCAL TABLE - LOCAL CONT2 - rra ; Over bit to carry - ld a, (FLAGS2) - rla ; Over bit in bit 1, Over2 bit in bit 2 - and 3 ; Only bit 0 and 1 (OVER flag) - ld c, a - ld b, 0 - ld hl, TABLE - add hl, bc - ld a, (hl) - ld (PRINT_MODE), a - ld hl, (P_FLAG) - xor a ; NOP -> INVERSE0 - bit 2, l - jr z, CONT2 - ld a, INVERSE1 ; CPL -> INVERSE1 -CONT2: - ld (INVERSE_MODE), a - ret -TABLE: - nop ; NORMAL MODE - xor (hl) ; OVER 1 MODE - and (hl) ; OVER 2 MODE - or (hl) ; OVER 3 MODE -#line 67 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" -__REFRESH_TMP: - ld a, (hl) - and 0b10101010 - ld c, a - rra - or c - ld (hl), a - ret - ENDP - pop namespace -#line 4 "/zxbasic/src/arch/zx48k/library-asm/over.asm" push namespace core OVER: PROC @@ -732,11 +654,10 @@ INVERSE_MODE: ; 00 -> NOP -> INVERSE 0 inc hl ld (DFCC), hl ld hl, (DFCCL) ; current ATTR Pos - push hl - call __SET_ATTR - pop hl inc hl - ld (DFCCL),hl + ld (DFCCL), hl + dec hl + call __SET_ATTR exx ret ; ------------- SPECIAL CHARS (< 32) ----------------- @@ -755,7 +676,7 @@ __PRINT_0Dh: ; Called WHEN printing CHR$(13) push hl call __SCROLL_SCR pop hl -#line 210 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 209 "/zxbasic/src/arch/zx48k/library-asm/print.asm" 1: ld l, 1 __PRINT_EOL_END: @@ -872,14 +793,14 @@ __PRINT_BOLD: __PRINT_BOLD2: call BOLD_TMP jp __PRINT_RESTART -#line 354 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 353 "/zxbasic/src/arch/zx48k/library-asm/print.asm" __PRINT_ITA: ld hl, __PRINT_ITA2 jp __PRINT_SET_STATE __PRINT_ITA2: call ITALIC_TMP jp __PRINT_RESTART -#line 364 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 363 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __BOLD __BOLD: push hl @@ -897,7 +818,7 @@ __BOLD: pop hl ld de, MEM0 ret -#line 385 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 384 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __ITALIC __ITALIC: push hl @@ -922,12 +843,12 @@ __ITALIC: pop hl ld de, MEM0 ret -#line 413 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 412 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __SCROLL_SCR -#line 487 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 486 "/zxbasic/src/arch/zx48k/library-asm/print.asm" __SCROLL_SCR EQU 0DFEh ; Use ROM SCROLL +#line 488 "/zxbasic/src/arch/zx48k/library-asm/print.asm" #line 489 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -#line 490 "/zxbasic/src/arch/zx48k/library-asm/print.asm" PRINT_COMMA: call __LOAD_S_POSN ld a, e @@ -970,9 +891,9 @@ PRINT_AT: ; Changes cursor to ROW, COL LOCAL __PRINT_TABLE LOCAL __PRINT_TAB, __PRINT_TAB1, __PRINT_TAB2 LOCAL __PRINT_ITA2 -#line 546 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 545 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __PRINT_BOLD2 -#line 552 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 551 "/zxbasic/src/arch/zx48k/library-asm/print.asm" __PRINT_TABLE: ; Jump table for 0 .. 22 codes DW __PRINT_NOP ; 0 DW __PRINT_NOP ; 1 @@ -1000,6 +921,86 @@ __PRINT_TABLE: ; Jump table for 0 .. 22 codes DW __PRINT_TAB ; 23 TAB ENDP pop namespace +#line 3 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" +#line 4 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" + push namespace core +COPY_ATTR: + ; Just copies current permanent attribs into temporal attribs + ; and sets print mode + PROC + LOCAL INVERSE1 + LOCAL __REFRESH_TMP + INVERSE1 EQU 02Fh + ld hl, (ATTR_P) + ld (ATTR_T), hl + ld hl, FLAGS2 + call __REFRESH_TMP + ld hl, P_FLAG + call __REFRESH_TMP +__SET_ATTR_MODE: ; Another entry to set print modes. A contains (P_FLAG) + LOCAL TABLE + LOCAL CONT2 + rra ; Over bit to carry + ld a, (FLAGS2) + rla ; Over bit in bit 1, Over2 bit in bit 2 + and 3 ; Only bit 0 and 1 (OVER flag) + ld c, a + ld b, 0 + ld hl, TABLE + add hl, bc + ld a, (hl) + ld (PRINT_MODE), a + ld hl, (P_FLAG) + xor a ; NOP -> INVERSE0 + bit 2, l + jr z, CONT2 + ld a, INVERSE1 ; CPL -> INVERSE1 +CONT2: + ld (INVERSE_MODE), a + ret +TABLE: + nop ; NORMAL MODE + xor (hl) ; OVER 1 MODE + and (hl) ; OVER 2 MODE + or (hl) ; OVER 3 MODE +#line 67 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" +__REFRESH_TMP: + ld a, (hl) + and 0b10101010 + ld c, a + rra + or c + ld (hl), a + ret + ENDP + pop namespace +#line 15 "zx48k/loadu16ii.bas" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/mul16.asm" + push namespace core +__MUL16: ; Mutiplies HL with the last value stored into de stack + ; Works for both signed and unsigned + PROC + LOCAL __MUL16LOOP + LOCAL __MUL16NOADD + ex de, hl + pop hl ; Return address + ex (sp), hl ; CALLEE caller convention +__MUL16_FAST: + ld b, 16 + ld a, h + ld c, l + ld hl, 0 +__MUL16LOOP: + add hl, hl ; hl << 1 + sla c + rla ; a,c << 1 + jp nc, __MUL16NOADD + add hl, de +__MUL16NOADD: + djnz __MUL16LOOP + ret ; Result in hl (16 lower bits) + ENDP + pop namespace #line 16 "zx48k/loadu16ii.bas" #line 1 "/zxbasic/src/arch/zx48k/library-asm/printu16.asm" #line 1 "/zxbasic/src/arch/zx48k/library-asm/printi16.asm" @@ -1148,5 +1149,5 @@ __PRINTU_LOOP: ENDP pop namespace #line 2 "/zxbasic/src/arch/zx48k/library-asm/printu16.asm" -#line 17 "zx48k/loadu16ii.bas" +#line 18 "zx48k/loadu16ii.bas" END diff --git a/tests/functional/zx48k/ltee1.asm b/tests/functional/zx48k/ltee1.asm index cdcbc94cc..e70a9d921 100644 --- a/tests/functional/zx48k/ltee1.asm +++ b/tests/functional/zx48k/ltee1.asm @@ -35,10 +35,11 @@ _newMsg: ex de, hl ld hl, _newMsg call .core.__STORE_STR2 + call .core.COPY_ATTR ld hl, (_newMsg) xor a call .core.__PRINTSTR - call .core.PRINT_EOL_ATTR + call .core.PRINT_EOL ld hl, 0 ld b, h ld c, l @@ -112,334 +113,42 @@ _addWibble__leave: DEFB 6Ch DEFB 65h ;; --- end of user code --- -#line 1 "/zxbasic/src/arch/zx48k/library-asm/free.asm" -; vim: ts=4:et:sw=4: - ; Copyleft (K) by Jose M. Rodriguez de la Rosa - ; (a.k.a. Boriel) -; http://www.boriel.com - ; - ; This ASM library is licensed under the BSD license - ; you can use it for any purpose (even for commercial - ; closed source programs). - ; - ; Please read the BSD license on the internet - ; ----- IMPLEMENTATION NOTES ------ - ; The heap is implemented as a linked list of free blocks. -; Each free block contains this info: - ; - ; +----------------+ <-- HEAP START - ; | Size (2 bytes) | - ; | 0 | <-- Size = 0 => DUMMY HEADER BLOCK - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ <-+ - ; | Size (2 bytes) | - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ | - ; | | | <-- If Size > 4, then this contains (size - 4) bytes - ; | (0 if Size = 4)| | - ; +----------------+ <-+ - ; | Size (2 bytes) | - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ | - ; | | | - ; | (0 if Size = 4)| | - ; +----------------+ | - ; | <-- This zone is in use (Already allocated) - ; +----------------+ <-+ - ; | Size (2 bytes) | - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ | - ; | | | - ; | (0 if Size = 4)| | - ; +----------------+ <-+ - ; | Next (2 bytes) |--> NULL => END OF LIST - ; | 0 = NULL | - ; +----------------+ - ; | | - ; | (0 if Size = 4)| - ; +----------------+ - ; When a block is FREED, the previous and next pointers are examined to see - ; if we can defragment the heap. If the block to be breed is just next to the - ; previous, or to the next (or both) they will be converted into a single - ; block (so defragmented). - ; MEMORY MANAGER - ; - ; This library must be initialized calling __MEM_INIT with - ; HL = BLOCK Start & DE = Length. - ; An init directive is useful for initialization routines. - ; They will be added automatically if needed. -#line 1 "/zxbasic/src/arch/zx48k/library-asm/heapinit.asm" -; vim: ts=4:et:sw=4: - ; Copyleft (K) by Jose M. Rodriguez de la Rosa - ; (a.k.a. Boriel) -; http://www.boriel.com - ; - ; This ASM library is licensed under the BSD license - ; you can use it for any purpose (even for commercial - ; closed source programs). - ; - ; Please read the BSD license on the internet - ; ----- IMPLEMENTATION NOTES ------ - ; The heap is implemented as a linked list of free blocks. -; Each free block contains this info: - ; - ; +----------------+ <-- HEAP START - ; | Size (2 bytes) | - ; | 0 | <-- Size = 0 => DUMMY HEADER BLOCK - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ <-+ - ; | Size (2 bytes) | - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ | - ; | | | <-- If Size > 4, then this contains (size - 4) bytes - ; | (0 if Size = 4)| | - ; +----------------+ <-+ - ; | Size (2 bytes) | - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ | - ; | | | - ; | (0 if Size = 4)| | - ; +----------------+ | - ; | <-- This zone is in use (Already allocated) - ; +----------------+ <-+ - ; | Size (2 bytes) | - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ | - ; | | | - ; | (0 if Size = 4)| | - ; +----------------+ <-+ - ; | Next (2 bytes) |--> NULL => END OF LIST - ; | 0 = NULL | - ; +----------------+ - ; | | - ; | (0 if Size = 4)| - ; +----------------+ - ; When a block is FREED, the previous and next pointers are examined to see - ; if we can defragment the heap. If the block to be breed is just next to the - ; previous, or to the next (or both) they will be converted into a single - ; block (so defragmented). - ; MEMORY MANAGER - ; - ; This library must be initialized calling __MEM_INIT with - ; HL = BLOCK Start & DE = Length. - ; An init directive is useful for initialization routines. - ; They will be added automatically if needed. - ; --------------------------------------------------------------------- - ; __MEM_INIT must be called to initalize this library with the - ; standard parameters - ; --------------------------------------------------------------------- - push namespace core -__MEM_INIT: ; Initializes the library using (RAMTOP) as start, and - ld hl, ZXBASIC_MEM_HEAP ; Change this with other address of heap start - ld de, ZXBASIC_HEAP_SIZE ; Change this with your size - ; --------------------------------------------------------------------- - ; __MEM_INIT2 initalizes this library -; Parameters: -; HL : Memory address of 1st byte of the memory heap -; DE : Length in bytes of the Memory Heap - ; --------------------------------------------------------------------- -__MEM_INIT2: - ; HL as TOP - PROC - dec de - dec de - dec de - dec de ; DE = length - 4; HL = start - ; This is done, because we require 4 bytes for the empty dummy-header block - xor a - ld (hl), a - inc hl - ld (hl), a ; First "free" block is a header: size=0, Pointer=&(Block) + 4 - inc hl - ld b, h - ld c, l - inc bc - inc bc ; BC = starts of next block - ld (hl), c - inc hl - ld (hl), b - inc hl ; Pointer to next block - ld (hl), e - inc hl - ld (hl), d - inc hl ; Block size (should be length - 4 at start); This block contains all the available memory - ld (hl), a ; NULL (0000h) ; No more blocks (a list with a single block) - inc hl - ld (hl), a - ld a, 201 - ld (__MEM_INIT), a; "Pokes" with a RET so ensure this routine is not called again - ret - ENDP - pop namespace -#line 69 "/zxbasic/src/arch/zx48k/library-asm/free.asm" - ; --------------------------------------------------------------------- - ; MEM_FREE - ; Frees a block of memory - ; -; Parameters: - ; HL = Pointer to the block to be freed. If HL is NULL (0) nothing - ; is done - ; --------------------------------------------------------------------- - push namespace core -MEM_FREE: -__MEM_FREE: ; Frees the block pointed by HL - ; HL DE BC & AF modified - PROC - LOCAL __MEM_LOOP2 - LOCAL __MEM_LINK_PREV - LOCAL __MEM_JOIN_TEST - LOCAL __MEM_BLOCK_JOIN - ld a, h - or l - ret z ; Return if NULL pointer - dec hl - dec hl - ld b, h - ld c, l ; BC = Block pointer - ld hl, ZXBASIC_MEM_HEAP ; This label point to the heap start -__MEM_LOOP2: - inc hl - inc hl ; Next block ptr - ld e, (hl) - inc hl - ld d, (hl) ; Block next ptr - ex de, hl ; DE = &(block->next); HL = block->next - ld a, h ; HL == NULL? - or l - jp z, __MEM_LINK_PREV; if so, link with previous - or a ; Clear carry flag - sbc hl, bc ; Carry if BC > HL => This block if before - add hl, bc ; Restores HL, preserving Carry flag - jp c, __MEM_LOOP2 ; This block is before. Keep searching PASS the block - ;------ At this point current HL is PAST BC, so we must link (DE) with BC, and HL in BC->next -__MEM_LINK_PREV: ; Link (DE) with BC, and BC->next with HL - ex de, hl - push hl - dec hl - ld (hl), c - inc hl - ld (hl), b ; (DE) <- BC - ld h, b ; HL <- BC (Free block ptr) - ld l, c - inc hl ; Skip block length (2 bytes) - inc hl - ld (hl), e ; Block->next = DE - inc hl - ld (hl), d - ; --- LINKED ; HL = &(BC->next) + 2 - call __MEM_JOIN_TEST - pop hl -__MEM_JOIN_TEST: ; Checks for fragmented contiguous blocks and joins them - ; hl = Ptr to current block + 2 - ld d, (hl) - dec hl - ld e, (hl) - dec hl - ld b, (hl) ; Loads block length into BC - dec hl - ld c, (hl) ; - push hl ; Saves it for later - add hl, bc ; Adds its length. If HL == DE now, it must be joined - or a - sbc hl, de ; If Z, then HL == DE => We must join - pop hl - ret nz -__MEM_BLOCK_JOIN: ; Joins current block (pointed by HL) with next one (pointed by DE). HL->length already in BC - push hl ; Saves it for later - ex de, hl - ld e, (hl) ; DE -> block->next->length - inc hl - ld d, (hl) - inc hl - ex de, hl ; DE = &(block->next) - add hl, bc ; HL = Total Length - ld b, h - ld c, l ; BC = Total Length - ex de, hl - ld e, (hl) - inc hl - ld d, (hl) ; DE = block->next - pop hl ; Recovers Pointer to block - ld (hl), c - inc hl - ld (hl), b ; Length Saved - inc hl - ld (hl), e - inc hl - ld (hl), d ; Next saved - ret - ENDP - pop namespace -#line 86 "zx48k/ltee1.bas" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/loadstr.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/alloc.asm" -; vim: ts=4:et:sw=4: - ; Copyleft (K) by Jose M. Rodriguez de la Rosa - ; (a.k.a. Boriel) -; http://www.boriel.com - ; - ; This ASM library is licensed under the MIT license - ; you can use it for any purpose (even for commercial - ; closed source programs). - ; - ; Please read the MIT license on the internet - ; ----- IMPLEMENTATION NOTES ------ - ; The heap is implemented as a linked list of free blocks. -; Each free block contains this info: - ; - ; +----------------+ <-- HEAP START - ; | Size (2 bytes) | - ; | 0 | <-- Size = 0 => DUMMY HEADER BLOCK - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ <-+ - ; | Size (2 bytes) | - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ | - ; | | | <-- If Size > 4, then this contains (size - 4) bytes - ; | (0 if Size = 4)| | - ; +----------------+ <-+ - ; | Size (2 bytes) | - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ | - ; | | | - ; | (0 if Size = 4)| | - ; +----------------+ | - ; | <-- This zone is in use (Already allocated) - ; +----------------+ <-+ - ; | Size (2 bytes) | - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ | - ; | | | - ; | (0 if Size = 4)| | - ; +----------------+ <-+ - ; | Next (2 bytes) |--> NULL => END OF LIST - ; | 0 = NULL | - ; +----------------+ - ; | | - ; | (0 if Size = 4)| - ; +----------------+ - ; When a block is FREED, the previous and next pointers are examined to see - ; if we can defragment the heap. If the block to be freed is just next to the - ; previous, or to the next (or both) they will be converted into a single - ; block (so defragmented). - ; MEMORY MANAGER - ; - ; This library must be initialized calling __MEM_INIT with - ; HL = BLOCK Start & DE = Length. - ; An init directive is useful for initialization routines. - ; They will be added automatically if needed. +#line 1 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +; vim:ts=4:sw=4:et: + ; PRINT command routine + ; Does not print attribute. Use PRINT_STR or PRINT_NUM for that +#line 1 "/zxbasic/src/arch/zx48k/library-asm/sposn.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/sysvars.asm" + ;; ----------------------------------------------------------------------- + ;; ZX Basic System Vars + ;; Some of them will be mapped over Sinclair ROM ones for compatibility + ;; ----------------------------------------------------------------------- + push namespace core +SCREEN_ADDR: DW 16384 ; Screen address (can be pointed to other place to use a screen buffer) +SCREEN_ATTR_ADDR: DW 22528 ; Screen attribute address (ditto.) + ; These are mapped onto ZX Spectrum ROM VARS + CHARS EQU 23606 ; Pointer to ROM/RAM Charset + TVFLAGS EQU 23612 ; TV Flags + UDG EQU 23675 ; Pointer to UDG Charset + COORDS EQU 23677 ; Last PLOT coordinates + FLAGS2 EQU 23681 ; + ECHO_E EQU 23682 ; + DFCC EQU 23684 ; Next screen addr for PRINT + DFCCL EQU 23686 ; Next screen attr for PRINT + S_POSN EQU 23688 + ATTR_P EQU 23693 ; Current Permanent ATTRS set with INK, PAPER, etc commands + ATTR_T EQU 23695 ; temporary ATTRIBUTES + P_FLAG EQU 23697 ; + MEM0 EQU 23698 ; Temporary memory buffer used by ROM chars + SCR_COLS EQU 33 ; Screen with in columns + 1 + SCR_ROWS EQU 24 ; Screen height in rows + SCR_SIZE EQU (SCR_ROWS << 8) + SCR_COLS + pop namespace +#line 2 "/zxbasic/src/arch/zx48k/library-asm/sposn.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/attr.asm" + ; Attribute routines +; vim:ts=4:et:sw: #line 1 "/zxbasic/src/arch/zx48k/library-asm/error.asm" ; Simple error control routines ; vim:ts=4:et: @@ -474,460 +183,795 @@ __STOP: ld (ERR_NR), a ret pop namespace -#line 69 "/zxbasic/src/arch/zx48k/library-asm/alloc.asm" - ; --------------------------------------------------------------------- - ; MEM_ALLOC - ; Allocates a block of memory in the heap. - ; - ; Parameters - ; BC = Length of requested memory block - ; -; Returns: - ; HL = Pointer to the allocated block in memory. Returns 0 (NULL) - ; if the block could not be allocated (out of memory) - ; --------------------------------------------------------------------- +#line 6 "/zxbasic/src/arch/zx48k/library-asm/attr.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/in_screen.asm" push namespace core -MEM_ALLOC: -__MEM_ALLOC: ; Returns the 1st free block found of the given length (in BC) +__IN_SCREEN: + ; Returns NO carry if current coords (D, E) + ; are OUT of the screen limits PROC - LOCAL __MEM_LOOP - LOCAL __MEM_DONE - LOCAL __MEM_SUBTRACT - LOCAL __MEM_START - LOCAL TEMP, TEMP0 - TEMP EQU TEMP0 + 1 - ld hl, 0 - ld (TEMP), hl -__MEM_START: - ld hl, ZXBASIC_MEM_HEAP ; This label point to the heap start - inc bc - inc bc ; BC = BC + 2 ; block size needs 2 extra bytes for hidden pointer -__MEM_LOOP: ; Loads lengh at (HL, HL+). If Lenght >= BC, jump to __MEM_DONE - ld a, h ; HL = NULL (No memory available?) - or l -#line 113 "/zxbasic/src/arch/zx48k/library-asm/alloc.asm" - ret z ; NULL -#line 115 "/zxbasic/src/arch/zx48k/library-asm/alloc.asm" - ; HL = Pointer to Free block - ld e, (hl) - inc hl - ld d, (hl) - inc hl ; DE = Block Length - push hl ; HL = *pointer to -> next block - ex de, hl - or a ; CF = 0 - sbc hl, bc ; FREE >= BC (Length) (HL = BlockLength - Length) - jp nc, __MEM_DONE - pop hl - ld (TEMP), hl + LOCAL __IN_SCREEN_ERR + ld hl, SCR_SIZE + ld a, e + cp l + jr nc, __IN_SCREEN_ERR ; Do nothing and return if out of range + ld a, d + cp h + ret c ; Return if carry (OK) +__IN_SCREEN_ERR: +__OUT_OF_SCREEN_ERR: + ; Jumps here if out of screen + ld a, ERROR_OutOfScreen + jp __STOP ; Saves error code and exits + ENDP + pop namespace +#line 7 "/zxbasic/src/arch/zx48k/library-asm/attr.asm" + push namespace core +__ATTR_ADDR: + ; calc start address in DE (as (32 * d) + e) + ; Contributed by Santiago Romero at http://www.speccy.org + ld h, 0 ; 7 T-States + ld a, d ; 4 T-States + ld d, h + add a, a ; a * 2 ; 4 T-States + add a, a ; a * 4 ; 4 T-States + ld l, a ; HL = A * 4 ; 4 T-States + add hl, hl ; HL = A * 8 ; 15 T-States + add hl, hl ; HL = A * 16 ; 15 T-States + add hl, hl ; HL = A * 32 ; 15 T-States + add hl, de + ld de, (SCREEN_ATTR_ADDR) ; Adds the screen address + add hl, de + ; Return current screen address in HL + ret + ; Sets the attribute at a given screen coordinate (D, E). + ; The attribute is taken from the ATTR_T memory variable + ; Used by PRINT routines +SET_ATTR: + ; Checks for valid coords + call __IN_SCREEN + ret nc + call __ATTR_ADDR +__SET_ATTR: + ; Internal __FASTCALL__ Entry used by printing routines + ; HL contains the address of the ATTR cell to set + PROC +__SET_ATTR2: ; Sets attr from ATTR_T to (HL) which points to the scr address + ld de, (ATTR_T) ; E = ATTR_T, D = MASK_T + ld a, d + and (hl) + ld c, a ; C = current screen color, masked + ld a, d + cpl ; Negate mask + and e ; Mask current attributes + or c ; Mix them + ld (hl), a ; Store result in screen + ret + ENDP + pop namespace +#line 3 "/zxbasic/src/arch/zx48k/library-asm/sposn.asm" + ; Printing positioning library. + push namespace core + ; Loads into DE current ROW, COL print position from S_POSN mem var. +__LOAD_S_POSN: + PROC + ld de, (S_POSN) + ld hl, SCR_SIZE + or a + sbc hl, de ex de, hl + ret + ENDP + ; Saves ROW, COL from DE into S_POSN mem var. +__SAVE_S_POSN: + PROC + ld hl, SCR_SIZE + or a + sbc hl, de + ld (S_POSN), hl ; saves it again +__SET_SCR_PTR: ;; Fast + push de + call __ATTR_ADDR + ld (DFCCL), hl + pop de + ld a, d + ld c, a ; Saves it for later + and 0F8h ; Masks 3 lower bit ; zy + ld d, a + ld a, c ; Recovers it + and 07h ; MOD 7 ; y1 + rrca + rrca + rrca + or e + ld e, a + ld hl, (SCREEN_ADDR) + add hl, de ; HL = Screen address + DE + ld (DFCC), hl + ret + ENDP + pop namespace +#line 6 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/table_jump.asm" + push namespace core +JUMP_HL_PLUS_2A: ; Does JP (HL + A*2) Modifies DE. Modifies A + add a, a +JUMP_HL_PLUS_A: ; Does JP (HL + A) Modifies DE + ld e, a + ld d, 0 +JUMP_HL_PLUS_DE: ; Does JP (HL + DE) + add hl, de ld e, (hl) inc hl ld d, (hl) ex de, hl - jp __MEM_LOOP -__MEM_DONE: ; A free block has been found. - ; Check if at least 4 bytes remains free (HL >= 4) - push hl - exx ; exx to preserve bc - pop hl - ld bc, 4 +CALL_HL: + jp (hl) + pop namespace +#line 8 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/ink.asm" + ; Sets ink color in ATTR_P permanently +; Parameter: Paper color in A register + push namespace core +INK: + PROC + LOCAL __SET_INK + LOCAL __SET_INK2 + ld de, ATTR_P +__SET_INK: + cp 8 + jr nz, __SET_INK2 + inc de ; Points DE to MASK_T or MASK_P + ld a, (de) + or 7 ; Set bits 0,1,2 to enable transparency + ld (de), a + ret +__SET_INK2: + ; Another entry. This will set the ink color at location pointer by DE + and 7 ; # Gets color mod 8 + ld b, a ; Saves the color + ld a, (de) + and 0F8h ; Clears previous value + or b + ld (de), a + inc de ; Points DE to MASK_T or MASK_P + ld a, (de) + and 0F8h ; Reset bits 0,1,2 sign to disable transparency + ld (de), a ; Store new attr + ret + ; Sets the INK color passed in A register in the ATTR_T variable +INK_TMP: + ld de, ATTR_T + jp __SET_INK + ENDP + pop namespace +#line 9 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/paper.asm" + ; Sets paper color in ATTR_P permanently +; Parameter: Paper color in A register + push namespace core +PAPER: + PROC + LOCAL __SET_PAPER + LOCAL __SET_PAPER2 + ld de, ATTR_P +__SET_PAPER: + cp 8 + jr nz, __SET_PAPER2 + inc de + ld a, (de) + or 038h + ld (de), a + ret + ; Another entry. This will set the paper color at location pointer by DE +__SET_PAPER2: + and 7 ; # Remove + rlca + rlca + rlca ; a *= 8 + ld b, a ; Saves the color + ld a, (de) + and 0C7h ; Clears previous value + or b + ld (de), a + inc de ; Points to MASK_T or MASK_P accordingly + ld a, (de) + and 0C7h ; Resets bits 3,4,5 + ld (de), a + ret + ; Sets the PAPER color passed in A register in the ATTR_T variable +PAPER_TMP: + ld de, ATTR_T + jp __SET_PAPER + ENDP + pop namespace +#line 10 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/flash.asm" + ; Sets flash flag in ATTR_P permanently +; Parameter: Paper color in A register + push namespace core +FLASH: + ld hl, ATTR_P + PROC + LOCAL IS_TR + LOCAL IS_ZERO +__SET_FLASH: + ; Another entry. This will set the flash flag at location pointer by DE + cp 8 + jr z, IS_TR + ; # Convert to 0/1 or a - sbc hl, bc - exx - jp nc, __MEM_SUBTRACT - ; At this point... - ; less than 4 bytes remains free. So we return this block entirely - ; We must link the previous block with the next to this one - ; (DE) => Pointer to next block - ; (TEMP) => &(previous->next) - pop hl ; Discard current block pointer - push de - ex de, hl ; DE = Previous block pointer; (HL) = Next block pointer + jr z, IS_ZERO + ld a, 0x80 +IS_ZERO: + ld b, a ; Saves the color ld a, (hl) + and 07Fh ; Clears previous value + or b + ld (hl), a inc hl - ld h, (hl) - ld l, a ; HL = (HL) - ex de, hl ; HL = Previous block pointer; DE = Next block pointer -TEMP0: - ld hl, 0 ; Pre-previous block pointer - ld (hl), e - inc hl - ld (hl), d ; LINKED - pop hl ; Returning block. + res 7, (hl) ;Reset bit 7 to disable transparency ret -__MEM_SUBTRACT: - ; At this point we have to store HL value (Length - BC) into (DE - 2) - ex de, hl - dec hl - ld (hl), d - dec hl - ld (hl), e ; Store new block length - add hl, de ; New length + DE => free-block start - pop de ; Remove previous HL off the stack - ld (hl), c ; Store length on its 1st word - inc hl - ld (hl), b - inc hl ; Return hl +IS_TR: ; transparent + inc hl ; Points DE to MASK_T or MASK_P + set 7, (hl) ;Set bit 7 to enable transparency ret + ; Sets the FLASH flag passed in A register in the ATTR_T variable +FLASH_TMP: + ld hl, ATTR_T + jr __SET_FLASH ENDP pop namespace -#line 2 "/zxbasic/src/arch/zx48k/library-asm/loadstr.asm" - ; Loads a string (ptr) from HL - ; and duplicates it on dynamic memory again - ; Finally, it returns result pointer in HL +#line 11 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/bright.asm" + ; Sets bright flag in ATTR_P permanently +; Parameter: Paper color in A register push namespace core -__ILOADSTR: ; This is the indirect pointer entry HL = (HL) - ld a, h - or l - ret z +BRIGHT: + ld hl, ATTR_P + PROC + LOCAL IS_TR + LOCAL IS_ZERO +__SET_BRIGHT: + ; Another entry. This will set the bright flag at location pointer by DE + cp 8 + jr z, IS_TR + ; # Convert to 0/1 + or a + jr z, IS_ZERO + ld a, 0x40 +IS_ZERO: + ld b, a ; Saves the color ld a, (hl) + and 0BFh ; Clears previous value + or b + ld (hl), a inc hl - ld h, (hl) - ld l, a -__LOADSTR: ; __FASTCALL__ entry - ld a, h - or l - ret z ; Return if NULL - ld c, (hl) - inc hl - ld b, (hl) - dec hl ; BC = LEN(a$) - inc bc - inc bc ; BC = LEN(a$) + 2 (two bytes for length) - push hl - push bc - call __MEM_ALLOC - pop bc ; Recover length - pop de ; Recover origin - ld a, h - or l - ret z ; Return if NULL (No memory) - ex de, hl ; ldir takes HL as source, DE as destiny, so SWAP HL,DE - push de ; Saves destiny start - ldir ; Copies string (length number included) - pop hl ; Recovers destiny in hl as result + res 6, (hl) ;Reset bit 6 to disable transparency + ret +IS_TR: ; transparent + inc hl ; Points DE to MASK_T or MASK_P + set 6, (hl) ;Set bit 6 to enable transparency ret + ; Sets the BRIGHT flag passed in A register in the ATTR_T variable +BRIGHT_TMP: + ld hl, ATTR_T + jr __SET_BRIGHT + ENDP pop namespace -#line 87 "zx48k/ltee1.bas" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/print_eol_attr.asm" - ; Calls PRINT_EOL and then COPY_ATTR, so saves - ; 3 bytes -#line 1 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -; vim:ts=4:sw=4:et: - ; PRINT command routine - ; Does not print attribute. Use PRINT_STR or PRINT_NUM for that -#line 1 "/zxbasic/src/arch/zx48k/library-asm/sposn.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/sysvars.asm" - ;; ----------------------------------------------------------------------- - ;; ZX Basic System Vars - ;; Some of them will be mapped over Sinclair ROM ones for compatibility - ;; ----------------------------------------------------------------------- - push namespace core -SCREEN_ADDR: DW 16384 ; Screen address (can be pointed to other place to use a screen buffer) -SCREEN_ATTR_ADDR: DW 22528 ; Screen attribute address (ditto.) - ; These are mapped onto ZX Spectrum ROM VARS - CHARS EQU 23606 ; Pointer to ROM/RAM Charset - TVFLAGS EQU 23612 ; TV Flags - UDG EQU 23675 ; Pointer to UDG Charset - COORDS EQU 23677 ; Last PLOT coordinates - FLAGS2 EQU 23681 ; - ECHO_E EQU 23682 ; - DFCC EQU 23684 ; Next screen addr for PRINT - DFCCL EQU 23686 ; Next screen attr for PRINT - S_POSN EQU 23688 - ATTR_P EQU 23693 ; Current Permanent ATTRS set with INK, PAPER, etc commands - ATTR_T EQU 23695 ; temporary ATTRIBUTES - P_FLAG EQU 23697 ; - MEM0 EQU 23698 ; Temporary memory buffer used by ROM chars - SCR_COLS EQU 33 ; Screen with in columns + 1 - SCR_ROWS EQU 24 ; Screen height in rows - SCR_SIZE EQU (SCR_ROWS << 8) + SCR_COLS - pop namespace -#line 2 "/zxbasic/src/arch/zx48k/library-asm/sposn.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/attr.asm" - ; Attribute routines -; vim:ts=4:et:sw: -#line 1 "/zxbasic/src/arch/zx48k/library-asm/in_screen.asm" +#line 12 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/over.asm" + ; Sets OVER flag in P_FLAG permanently +; Parameter: OVER flag in bit 0 of A register push namespace core -__IN_SCREEN: - ; Returns NO carry if current coords (D, E) - ; are OUT of the screen limits +OVER: PROC - LOCAL __IN_SCREEN_ERR - ld hl, SCR_SIZE - ld a, e - cp l - jr nc, __IN_SCREEN_ERR ; Do nothing and return if out of range - ld a, d - cp h - ret c ; Return if carry (OK) -__IN_SCREEN_ERR: -__OUT_OF_SCREEN_ERR: - ; Jumps here if out of screen - ld a, ERROR_OutOfScreen - jp __STOP ; Saves error code and exits + ld c, a ; saves it for later + and 2 + ld hl, FLAGS2 + res 1, (HL) + or (hl) + ld (hl), a + ld a, c ; Recovers previous value + and 1 ; # Convert to 0/1 + add a, a; # Shift left 1 bit for permanent + ld hl, P_FLAG + res 1, (hl) + or (hl) + ld (hl), a + ret + ; Sets OVER flag in P_FLAG temporarily +OVER_TMP: + ld c, a ; saves it for later + and 2 ; gets bit 1; clears carry + rra + ld hl, FLAGS2 + res 0, (hl) + or (hl) + ld (hl), a + ld a, c ; Recovers previous value + and 1 + ld hl, P_FLAG + res 0, (hl) + or (hl) + ld (hl), a + jp __SET_ATTR_MODE + ENDP + pop namespace +#line 13 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/inverse.asm" + ; Sets INVERSE flag in P_FLAG permanently +; Parameter: INVERSE flag in bit 0 of A register + push namespace core +INVERSE: + PROC + and 1 ; # Convert to 0/1 + add a, a; # Shift left 3 bits for permanent + add a, a + add a, a + ld hl, P_FLAG + res 3, (hl) + or (hl) + ld (hl), a + ret + ; Sets INVERSE flag in P_FLAG temporarily +INVERSE_TMP: + and 1 + add a, a + add a, a; # Shift left 2 bits for temporary + ld hl, P_FLAG + res 2, (hl) + or (hl) + ld (hl), a + jp __SET_ATTR_MODE + ENDP + pop namespace +#line 14 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/bold.asm" + ; Sets BOLD flag in P_FLAG permanently +; Parameter: BOLD flag in bit 0 of A register + push namespace core +BOLD: + PROC + and 1 + rlca + rlca + rlca + ld hl, FLAGS2 + res 3, (HL) + or (hl) + ld (hl), a + ret + ; Sets BOLD flag in P_FLAG temporarily +BOLD_TMP: + and 1 + rlca + rlca + ld hl, FLAGS2 + res 2, (hl) + or (hl) + ld (hl), a + ret ENDP pop namespace -#line 7 "/zxbasic/src/arch/zx48k/library-asm/attr.asm" +#line 15 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/italic.asm" + ; Sets ITALIC flag in P_FLAG permanently +; Parameter: ITALIC flag in bit 0 of A register push namespace core -__ATTR_ADDR: - ; calc start address in DE (as (32 * d) + e) - ; Contributed by Santiago Romero at http://www.speccy.org - ld h, 0 ; 7 T-States - ld a, d ; 4 T-States - ld d, h - add a, a ; a * 2 ; 4 T-States - add a, a ; a * 4 ; 4 T-States - ld l, a ; HL = A * 4 ; 4 T-States - add hl, hl ; HL = A * 8 ; 15 T-States - add hl, hl ; HL = A * 16 ; 15 T-States - add hl, hl ; HL = A * 32 ; 15 T-States - add hl, de - ld de, (SCREEN_ATTR_ADDR) ; Adds the screen address - add hl, de - ; Return current screen address in HL - ret - ; Sets the attribute at a given screen coordinate (D, E). - ; The attribute is taken from the ATTR_T memory variable - ; Used by PRINT routines -SET_ATTR: - ; Checks for valid coords - call __IN_SCREEN - ret nc - call __ATTR_ADDR -__SET_ATTR: - ; Internal __FASTCALL__ Entry used by printing routines - ; HL contains the address of the ATTR cell to set +ITALIC: PROC -__SET_ATTR2: ; Sets attr from ATTR_T to (HL) which points to the scr address - ld de, (ATTR_T) ; E = ATTR_T, D = MASK_T - ld a, d - and (hl) - ld c, a ; C = current screen color, masked - ld a, d - cpl ; Negate mask - and e ; Mask current attributes - or c ; Mix them - ld (hl), a ; Store result in screen + and 1 + rrca + rrca + rrca + ld hl, FLAGS2 + res 5, (HL) + or (hl) + ld (hl), a + ret + ; Sets ITALIC flag in P_FLAG temporarily +ITALIC_TMP: + and 1 + rrca + rrca + rrca + rrca + ld hl, FLAGS2 + res 4, (hl) + or (hl) + ld (hl), a ret ENDP pop namespace -#line 3 "/zxbasic/src/arch/zx48k/library-asm/sposn.asm" - ; Printing positioning library. +#line 16 "/zxbasic/src/arch/zx48k/library-asm/print.asm" + ; Putting a comment starting with @INIT
+ ; will make the compiler to add a CALL to
+ ; It is useful for initialization routines. push namespace core - ; Loads into DE current ROW, COL print position from S_POSN mem var. -__LOAD_S_POSN: +__PRINT_INIT: ; To be called before program starts (initializes library) PROC - ld de, (S_POSN) + ld hl, __PRINT_START + ld (PRINT_JUMP_STATE), hl + ;; Clears ATTR2 flags (OVER 2, etc) + xor a + ld (FLAGS2), a + LOCAL SET_SCR_ADDR + call __LOAD_S_POSN + jp __SET_SCR_PTR + ;; Receives HL = future value of S_POSN + ;; Stores it at (S_POSN) and refresh screen pointers (ATTR, SCR) +SET_SCR_ADDR: + ld (S_POSN), hl + ex de, hl ld hl, SCR_SIZE or a sbc hl, de ex de, hl + dec e + jp __SET_SCR_PTR +__PRINTCHAR: ; Print character store in accumulator (A register) + ; Modifies H'L', B'C', A'F', D'E', A + LOCAL PO_GR_1 + LOCAL __PRCHAR + LOCAL __PRINT_JUMP + LOCAL __SRCADDR + LOCAL __PRINT_UDG + LOCAL __PRGRAPH + LOCAL __PRINT_START + PRINT_JUMP_STATE EQU __PRINT_JUMP + 2 +__PRINT_JUMP: + exx ; Switch to alternative registers + jp __PRINT_START ; Where to jump. If we print 22 (AT), next two calls jumps to AT1 and AT2 respectively +__PRINT_START: +__PRINT_CHR: + cp ' ' + jr c, __PRINT_SPECIAL ; Characters below ' ' are special ones + ex af, af' ; Saves a value (char to print) for later + ld hl, (S_POSN) + dec l + jr nz, 1f + ld l, SCR_COLS - 1 + dec h + jr nz, 2f + inc h + push hl + call __SCROLL_SCR + pop hl +#line 92 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +2: + call SET_SCR_ADDR + jr 4f +1: + ld (S_POSN), hl +4: + ex af, af' + cp 80h ; Is it a "normal" (printable) char + jr c, __SRCADDR + cp 90h ; Is it an UDG? + jr nc, __PRINT_UDG + ; Print an 8 bit pattern (80h to 8Fh) + ld b, a + call PO_GR_1 ; This ROM routine will generate the bit pattern at MEM0 + ld hl, MEM0 + jp __PRGRAPH + PO_GR_1 EQU 0B38h +__PRINT_UDG: + sub 90h ; Sub ASC code + ld bc, (UDG) + jr __PRGRAPH0 + __SOURCEADDR EQU (__SRCADDR + 1) ; Address of the pointer to chars source +__SRCADDR: + ld bc, (CHARS) +__PRGRAPH0: + add a, a ; A = a * 2 (since a < 80h) ; Thanks to Metalbrain at http://foro.speccy.org + ld l, a + ld h, 0 ; HL = a * 2 (accumulator) + add hl, hl + add hl, hl ; HL = a * 8 + add hl, bc ; HL = CHARS address +__PRGRAPH: + ex de, hl ; HL = Write Address, DE = CHARS address + bit 2, (iy + $47) + call nz, __BOLD +#line 139 "/zxbasic/src/arch/zx48k/library-asm/print.asm" + bit 4, (iy + $47) + call nz, __ITALIC +#line 144 "/zxbasic/src/arch/zx48k/library-asm/print.asm" + ld hl, (DFCC) + push hl + ld b, 8 ; 8 bytes per char +__PRCHAR: + ld a, (de) ; DE *must* be source, and HL destiny +PRINT_MODE: ; Which operation is used to write on the screen + ; Set it with: + ; LD A, + ; LD (PRINT_MODE), A + ; + ; Available operations: + ; NORMAL : 0h --> NOP ; OVER 0 + ; XOR : AEh --> XOR (HL) ; OVER 1 + ; OR : B6h --> OR (HL) ; PUTSPRITE + ; AND : A6h --> AND (HL) ; PUTMASK + nop ; Set to one of the values above +INVERSE_MODE: ; 00 -> NOP -> INVERSE 0 + nop ; 2F -> CPL -> INVERSE 1 + ld (hl), a + inc de + inc h ; Next line + djnz __PRCHAR + pop hl + inc hl + ld (DFCC), hl + ld hl, (DFCCL) ; current ATTR Pos + inc hl + ld (DFCCL), hl + dec hl + call __SET_ATTR + exx ret - ENDP - ; Saves ROW, COL from DE into S_POSN mem var. -__SAVE_S_POSN: - PROC - ld hl, SCR_SIZE - or a - sbc hl, de - ld (S_POSN), hl ; saves it again -__SET_SCR_PTR: ;; Fast + ; ------------- SPECIAL CHARS (< 32) ----------------- +__PRINT_SPECIAL: ; Jumps here if it is a special char + ld hl, __PRINT_TABLE + jp JUMP_HL_PLUS_2A +PRINT_EOL: ; Called WHENEVER there is no ";" at end of PRINT sentence + exx +__PRINT_0Dh: ; Called WHEN printing CHR$(13) + ld hl, (S_POSN) + dec l + jr nz, 1f + dec h + jr nz, 1f + inc h + push hl + call __SCROLL_SCR + pop hl +#line 209 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +1: + ld l, 1 +__PRINT_EOL_END: + call SET_SCR_ADDR + exx + ret +__PRINT_COM: + exx + push hl push de - call __ATTR_ADDR - ld (DFCCL), hl + push bc + call PRINT_COMMA + pop bc pop de - ld a, d - ld c, a ; Saves it for later - and 0F8h ; Masks 3 lower bit ; zy - ld d, a - ld a, c ; Recovers it - and 07h ; MOD 7 ; y1 - rrca - rrca - rrca - or e - ld e, a - ld hl, (SCREEN_ADDR) - add hl, de ; HL = Screen address + DE - ld (DFCC), hl + pop hl + ret +__PRINT_TAB: + ld hl, __PRINT_TAB1 + jr __PRINT_SET_STATE +__PRINT_TAB1: + ld (MEM0), a + ld hl, __PRINT_TAB2 + jr __PRINT_SET_STATE +__PRINT_TAB2: + ld a, (MEM0) ; Load tab code (ignore the current one) + ld hl, __PRINT_START + ld (PRINT_JUMP_STATE), hl + exx + push hl + push bc + push de + call PRINT_TAB + pop de + pop bc + pop hl ret - ENDP - pop namespace -#line 6 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/table_jump.asm" - push namespace core -JUMP_HL_PLUS_2A: ; Does JP (HL + A*2) Modifies DE. Modifies A - add a, a -JUMP_HL_PLUS_A: ; Does JP (HL + A) Modifies DE - ld e, a - ld d, 0 -JUMP_HL_PLUS_DE: ; Does JP (HL + DE) - add hl, de - ld e, (hl) - inc hl - ld d, (hl) - ex de, hl -CALL_HL: - jp (hl) - pop namespace -#line 8 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/ink.asm" - ; Sets ink color in ATTR_P permanently -; Parameter: Paper color in A register - push namespace core -INK: - PROC - LOCAL __SET_INK - LOCAL __SET_INK2 - ld de, ATTR_P -__SET_INK: - cp 8 - jr nz, __SET_INK2 - inc de ; Points DE to MASK_T or MASK_P - ld a, (de) - or 7 ; Set bits 0,1,2 to enable transparency - ld (de), a +__PRINT_AT: + ld hl, __PRINT_AT1 + jr __PRINT_SET_STATE +__PRINT_NOP: +__PRINT_RESTART: + ld hl, __PRINT_START +__PRINT_SET_STATE: + ld (PRINT_JUMP_STATE), hl ; Saves next entry call + exx ret -__SET_INK2: - ; Another entry. This will set the ink color at location pointer by DE - and 7 ; # Gets color mod 8 - ld b, a ; Saves the color - ld a, (de) - and 0F8h ; Clears previous value - or b - ld (de), a - inc de ; Points DE to MASK_T or MASK_P - ld a, (de) - and 0F8h ; Reset bits 0,1,2 sign to disable transparency - ld (de), a ; Store new attr +__PRINT_AT1: ; Jumps here if waiting for 1st parameter + ld hl, (S_POSN) + ld h, a + ld a, SCR_ROWS + sub h + ld (S_POSN + 1), a + ld hl, __PRINT_AT2 + jr __PRINT_SET_STATE +__PRINT_AT2: + call __LOAD_S_POSN + ld e, a + call __SAVE_S_POSN + jr __PRINT_RESTART +__PRINT_DEL: + call __LOAD_S_POSN ; Gets current screen position + dec e + ld a, -1 + cp e + jr nz, 3f + ld e, SCR_COLS - 2 + dec d + cp d + jr nz, 3f + ld d, SCR_ROWS - 1 +3: + call __SAVE_S_POSN + exx ret - ; Sets the INK color passed in A register in the ATTR_T variable -INK_TMP: - ld de, ATTR_T - jp __SET_INK - ENDP - pop namespace -#line 9 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/paper.asm" - ; Sets paper color in ATTR_P permanently -; Parameter: Paper color in A register - push namespace core -PAPER: - PROC - LOCAL __SET_PAPER - LOCAL __SET_PAPER2 - ld de, ATTR_P -__SET_PAPER: - cp 8 - jr nz, __SET_PAPER2 - inc de +__PRINT_INK: + ld hl, __PRINT_INK2 + jr __PRINT_SET_STATE +__PRINT_INK2: + call INK_TMP + jr __PRINT_RESTART +__PRINT_PAP: + ld hl, __PRINT_PAP2 + jr __PRINT_SET_STATE +__PRINT_PAP2: + call PAPER_TMP + jr __PRINT_RESTART +__PRINT_FLA: + ld hl, __PRINT_FLA2 + jr __PRINT_SET_STATE +__PRINT_FLA2: + call FLASH_TMP + jr __PRINT_RESTART +__PRINT_BRI: + ld hl, __PRINT_BRI2 + jr __PRINT_SET_STATE +__PRINT_BRI2: + call BRIGHT_TMP + jr __PRINT_RESTART +__PRINT_INV: + ld hl, __PRINT_INV2 + jr __PRINT_SET_STATE +__PRINT_INV2: + call INVERSE_TMP + jr __PRINT_RESTART +__PRINT_OVR: + ld hl, __PRINT_OVR2 + jr __PRINT_SET_STATE +__PRINT_OVR2: + call OVER_TMP + jr __PRINT_RESTART +__PRINT_BOLD: + ld hl, __PRINT_BOLD2 + jp __PRINT_SET_STATE +__PRINT_BOLD2: + call BOLD_TMP + jp __PRINT_RESTART +#line 353 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +__PRINT_ITA: + ld hl, __PRINT_ITA2 + jp __PRINT_SET_STATE +__PRINT_ITA2: + call ITALIC_TMP + jp __PRINT_RESTART +#line 363 "/zxbasic/src/arch/zx48k/library-asm/print.asm" + LOCAL __BOLD +__BOLD: + push hl + ld hl, MEM0 + ld b, 8 +1: ld a, (de) - or 038h - ld (de), a - ret - ; Another entry. This will set the paper color at location pointer by DE -__SET_PAPER2: - and 7 ; # Remove - rlca + ld c, a rlca - rlca ; a *= 8 - ld b, a ; Saves the color - ld a, (de) - and 0C7h ; Clears previous value - or b - ld (de), a - inc de ; Points to MASK_T or MASK_P accordingly - ld a, (de) - and 0C7h ; Resets bits 3,4,5 - ld (de), a - ret - ; Sets the PAPER color passed in A register in the ATTR_T variable -PAPER_TMP: - ld de, ATTR_T - jp __SET_PAPER - ENDP - pop namespace -#line 10 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/flash.asm" - ; Sets flash flag in ATTR_P permanently -; Parameter: Paper color in A register - push namespace core -FLASH: - ld hl, ATTR_P - PROC - LOCAL IS_TR - LOCAL IS_ZERO -__SET_FLASH: - ; Another entry. This will set the flash flag at location pointer by DE - cp 8 - jr z, IS_TR - ; # Convert to 0/1 - or a - jr z, IS_ZERO - ld a, 0x80 -IS_ZERO: - ld b, a ; Saves the color - ld a, (hl) - and 07Fh ; Clears previous value - or b + or c ld (hl), a inc hl - res 7, (hl) ;Reset bit 7 to disable transparency - ret -IS_TR: ; transparent - inc hl ; Points DE to MASK_T or MASK_P - set 7, (hl) ;Set bit 7 to enable transparency - ret - ; Sets the FLASH flag passed in A register in the ATTR_T variable -FLASH_TMP: - ld hl, ATTR_T - jr __SET_FLASH - ENDP - pop namespace -#line 11 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/bright.asm" - ; Sets bright flag in ATTR_P permanently -; Parameter: Paper color in A register - push namespace core -BRIGHT: - ld hl, ATTR_P - PROC - LOCAL IS_TR - LOCAL IS_ZERO -__SET_BRIGHT: - ; Another entry. This will set the bright flag at location pointer by DE - cp 8 - jr z, IS_TR - ; # Convert to 0/1 - or a - jr z, IS_ZERO - ld a, 0x40 -IS_ZERO: - ld b, a ; Saves the color - ld a, (hl) - and 0BFh ; Clears previous value - or b - ld (hl), a + inc de + djnz 1b + pop hl + ld de, MEM0 + ret +#line 384 "/zxbasic/src/arch/zx48k/library-asm/print.asm" + LOCAL __ITALIC +__ITALIC: + push hl + ld hl, MEM0 + ex de, hl + ld bc, 8 + ldir + ld hl, MEM0 + srl (hl) inc hl - res 6, (hl) ;Reset bit 6 to disable transparency + srl (hl) + inc hl + srl (hl) + inc hl + inc hl + inc hl + sla (hl) + inc hl + sla (hl) + inc hl + sla (hl) + pop hl + ld de, MEM0 ret -IS_TR: ; transparent - inc hl ; Points DE to MASK_T or MASK_P - set 6, (hl) ;Set bit 6 to enable transparency +#line 412 "/zxbasic/src/arch/zx48k/library-asm/print.asm" + LOCAL __SCROLL_SCR +#line 486 "/zxbasic/src/arch/zx48k/library-asm/print.asm" + __SCROLL_SCR EQU 0DFEh ; Use ROM SCROLL +#line 488 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 489 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +PRINT_COMMA: + call __LOAD_S_POSN + ld a, e + and 16 + add a, 16 +PRINT_TAB: + ; Tabulates the number of spaces in A register + ; If the current cursor position is already A, does nothing + PROC + LOCAL LOOP + call __LOAD_S_POSN ; e = current row + sub e + and 31 + ret z + ld b, a +LOOP: + ld a, ' ' + call __PRINTCHAR + djnz LOOP ret - ; Sets the BRIGHT flag passed in A register in the ATTR_T variable -BRIGHT_TMP: - ld hl, ATTR_T - jr __SET_BRIGHT + ENDP +PRINT_AT: ; Changes cursor to ROW, COL + ; COL in A register + ; ROW in stack + pop hl ; Ret address + ex (sp), hl ; callee H = ROW + ld l, a + ex de, hl + call __IN_SCREEN + ret nc ; Return if out of screen + jp __SAVE_S_POSN + LOCAL __PRINT_COM + LOCAL __PRINT_AT1 + LOCAL __PRINT_AT2 + LOCAL __PRINT_BOLD + LOCAL __PRINT_ITA + LOCAL __PRINT_INK + LOCAL __PRINT_PAP + LOCAL __PRINT_SET_STATE + LOCAL __PRINT_TABLE + LOCAL __PRINT_TAB, __PRINT_TAB1, __PRINT_TAB2 + LOCAL __PRINT_ITA2 +#line 545 "/zxbasic/src/arch/zx48k/library-asm/print.asm" + LOCAL __PRINT_BOLD2 +#line 551 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +__PRINT_TABLE: ; Jump table for 0 .. 22 codes + DW __PRINT_NOP ; 0 + DW __PRINT_NOP ; 1 + DW __PRINT_NOP ; 2 + DW __PRINT_NOP ; 3 + DW __PRINT_NOP ; 4 + DW __PRINT_NOP ; 5 + DW __PRINT_COM ; 6 COMMA + DW __PRINT_NOP ; 7 + DW __PRINT_DEL ; 8 DEL + DW __PRINT_NOP ; 9 + DW __PRINT_NOP ; 10 + DW __PRINT_NOP ; 11 + DW __PRINT_NOP ; 12 + DW __PRINT_0Dh ; 13 + DW __PRINT_BOLD ; 14 + DW __PRINT_ITA ; 15 + DW __PRINT_INK ; 16 + DW __PRINT_PAP ; 17 + DW __PRINT_FLA ; 18 + DW __PRINT_BRI ; 19 + DW __PRINT_INV ; 20 + DW __PRINT_OVR ; 21 + DW __PRINT_AT ; 22 AT + DW __PRINT_TAB ; 23 TAB ENDP pop namespace -#line 12 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/over.asm" - ; Sets OVER flag in P_FLAG permanently -; Parameter: OVER flag in bit 0 of A register -#line 1 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" +#line 3 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" #line 4 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" push namespace core COPY_ATTR: @@ -980,523 +1024,470 @@ __REFRESH_TMP: ret ENDP pop namespace -#line 4 "/zxbasic/src/arch/zx48k/library-asm/over.asm" - push namespace core -OVER: - PROC - ld c, a ; saves it for later - and 2 - ld hl, FLAGS2 - res 1, (HL) - or (hl) - ld (hl), a - ld a, c ; Recovers previous value - and 1 ; # Convert to 0/1 - add a, a; # Shift left 1 bit for permanent - ld hl, P_FLAG - res 1, (hl) - or (hl) - ld (hl), a - ret - ; Sets OVER flag in P_FLAG temporarily -OVER_TMP: - ld c, a ; saves it for later - and 2 ; gets bit 1; clears carry - rra - ld hl, FLAGS2 - res 0, (hl) - or (hl) - ld (hl), a - ld a, c ; Recovers previous value - and 1 - ld hl, P_FLAG - res 0, (hl) - or (hl) - ld (hl), a - jp __SET_ATTR_MODE - ENDP - pop namespace -#line 13 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/inverse.asm" - ; Sets INVERSE flag in P_FLAG permanently -; Parameter: INVERSE flag in bit 0 of A register - push namespace core -INVERSE: - PROC - and 1 ; # Convert to 0/1 - add a, a; # Shift left 3 bits for permanent - add a, a - add a, a - ld hl, P_FLAG - res 3, (hl) - or (hl) - ld (hl), a - ret - ; Sets INVERSE flag in P_FLAG temporarily -INVERSE_TMP: - and 1 - add a, a - add a, a; # Shift left 2 bits for temporary - ld hl, P_FLAG - res 2, (hl) - or (hl) - ld (hl), a - jp __SET_ATTR_MODE - ENDP - pop namespace -#line 14 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/bold.asm" - ; Sets BOLD flag in P_FLAG permanently -; Parameter: BOLD flag in bit 0 of A register - push namespace core -BOLD: - PROC - and 1 - rlca - rlca - rlca - ld hl, FLAGS2 - res 3, (HL) - or (hl) - ld (hl), a - ret - ; Sets BOLD flag in P_FLAG temporarily -BOLD_TMP: - and 1 - rlca - rlca - ld hl, FLAGS2 - res 2, (hl) - or (hl) - ld (hl), a - ret - ENDP - pop namespace -#line 15 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/italic.asm" - ; Sets ITALIC flag in P_FLAG permanently -; Parameter: ITALIC flag in bit 0 of A register +#line 87 "zx48k/ltee1.bas" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/free.asm" +; vim: ts=4:et:sw=4: + ; Copyleft (K) by Jose M. Rodriguez de la Rosa + ; (a.k.a. Boriel) +; http://www.boriel.com + ; + ; This ASM library is licensed under the BSD license + ; you can use it for any purpose (even for commercial + ; closed source programs). + ; + ; Please read the BSD license on the internet + ; ----- IMPLEMENTATION NOTES ------ + ; The heap is implemented as a linked list of free blocks. +; Each free block contains this info: + ; + ; +----------------+ <-- HEAP START + ; | Size (2 bytes) | + ; | 0 | <-- Size = 0 => DUMMY HEADER BLOCK + ; +----------------+ + ; | Next (2 bytes) |---+ + ; +----------------+ <-+ + ; | Size (2 bytes) | + ; +----------------+ + ; | Next (2 bytes) |---+ + ; +----------------+ | + ; | | | <-- If Size > 4, then this contains (size - 4) bytes + ; | (0 if Size = 4)| | + ; +----------------+ <-+ + ; | Size (2 bytes) | + ; +----------------+ + ; | Next (2 bytes) |---+ + ; +----------------+ | + ; | | | + ; | (0 if Size = 4)| | + ; +----------------+ | + ; | <-- This zone is in use (Already allocated) + ; +----------------+ <-+ + ; | Size (2 bytes) | + ; +----------------+ + ; | Next (2 bytes) |---+ + ; +----------------+ | + ; | | | + ; | (0 if Size = 4)| | + ; +----------------+ <-+ + ; | Next (2 bytes) |--> NULL => END OF LIST + ; | 0 = NULL | + ; +----------------+ + ; | | + ; | (0 if Size = 4)| + ; +----------------+ + ; When a block is FREED, the previous and next pointers are examined to see + ; if we can defragment the heap. If the block to be breed is just next to the + ; previous, or to the next (or both) they will be converted into a single + ; block (so defragmented). + ; MEMORY MANAGER + ; + ; This library must be initialized calling __MEM_INIT with + ; HL = BLOCK Start & DE = Length. + ; An init directive is useful for initialization routines. + ; They will be added automatically if needed. +#line 1 "/zxbasic/src/arch/zx48k/library-asm/heapinit.asm" +; vim: ts=4:et:sw=4: + ; Copyleft (K) by Jose M. Rodriguez de la Rosa + ; (a.k.a. Boriel) +; http://www.boriel.com + ; + ; This ASM library is licensed under the BSD license + ; you can use it for any purpose (even for commercial + ; closed source programs). + ; + ; Please read the BSD license on the internet + ; ----- IMPLEMENTATION NOTES ------ + ; The heap is implemented as a linked list of free blocks. +; Each free block contains this info: + ; + ; +----------------+ <-- HEAP START + ; | Size (2 bytes) | + ; | 0 | <-- Size = 0 => DUMMY HEADER BLOCK + ; +----------------+ + ; | Next (2 bytes) |---+ + ; +----------------+ <-+ + ; | Size (2 bytes) | + ; +----------------+ + ; | Next (2 bytes) |---+ + ; +----------------+ | + ; | | | <-- If Size > 4, then this contains (size - 4) bytes + ; | (0 if Size = 4)| | + ; +----------------+ <-+ + ; | Size (2 bytes) | + ; +----------------+ + ; | Next (2 bytes) |---+ + ; +----------------+ | + ; | | | + ; | (0 if Size = 4)| | + ; +----------------+ | + ; | <-- This zone is in use (Already allocated) + ; +----------------+ <-+ + ; | Size (2 bytes) | + ; +----------------+ + ; | Next (2 bytes) |---+ + ; +----------------+ | + ; | | | + ; | (0 if Size = 4)| | + ; +----------------+ <-+ + ; | Next (2 bytes) |--> NULL => END OF LIST + ; | 0 = NULL | + ; +----------------+ + ; | | + ; | (0 if Size = 4)| + ; +----------------+ + ; When a block is FREED, the previous and next pointers are examined to see + ; if we can defragment the heap. If the block to be breed is just next to the + ; previous, or to the next (or both) they will be converted into a single + ; block (so defragmented). + ; MEMORY MANAGER + ; + ; This library must be initialized calling __MEM_INIT with + ; HL = BLOCK Start & DE = Length. + ; An init directive is useful for initialization routines. + ; They will be added automatically if needed. + ; --------------------------------------------------------------------- + ; __MEM_INIT must be called to initalize this library with the + ; standard parameters + ; --------------------------------------------------------------------- push namespace core -ITALIC: +__MEM_INIT: ; Initializes the library using (RAMTOP) as start, and + ld hl, ZXBASIC_MEM_HEAP ; Change this with other address of heap start + ld de, ZXBASIC_HEAP_SIZE ; Change this with your size + ; --------------------------------------------------------------------- + ; __MEM_INIT2 initalizes this library +; Parameters: +; HL : Memory address of 1st byte of the memory heap +; DE : Length in bytes of the Memory Heap + ; --------------------------------------------------------------------- +__MEM_INIT2: + ; HL as TOP PROC - and 1 - rrca - rrca - rrca - ld hl, FLAGS2 - res 5, (HL) - or (hl) + dec de + dec de + dec de + dec de ; DE = length - 4; HL = start + ; This is done, because we require 4 bytes for the empty dummy-header block + xor a ld (hl), a - ret - ; Sets ITALIC flag in P_FLAG temporarily -ITALIC_TMP: - and 1 - rrca - rrca - rrca - rrca - ld hl, FLAGS2 - res 4, (hl) - or (hl) + inc hl + ld (hl), a ; First "free" block is a header: size=0, Pointer=&(Block) + 4 + inc hl + ld b, h + ld c, l + inc bc + inc bc ; BC = starts of next block + ld (hl), c + inc hl + ld (hl), b + inc hl ; Pointer to next block + ld (hl), e + inc hl + ld (hl), d + inc hl ; Block size (should be length - 4 at start); This block contains all the available memory + ld (hl), a ; NULL (0000h) ; No more blocks (a list with a single block) + inc hl ld (hl), a + ld a, 201 + ld (__MEM_INIT), a; "Pokes" with a RET so ensure this routine is not called again ret ENDP pop namespace -#line 16 "/zxbasic/src/arch/zx48k/library-asm/print.asm" - ; Putting a comment starting with @INIT
- ; will make the compiler to add a CALL to
- ; It is useful for initialization routines. +#line 69 "/zxbasic/src/arch/zx48k/library-asm/free.asm" + ; --------------------------------------------------------------------- + ; MEM_FREE + ; Frees a block of memory + ; +; Parameters: + ; HL = Pointer to the block to be freed. If HL is NULL (0) nothing + ; is done + ; --------------------------------------------------------------------- push namespace core -__PRINT_INIT: ; To be called before program starts (initializes library) +MEM_FREE: +__MEM_FREE: ; Frees the block pointed by HL + ; HL DE BC & AF modified PROC - ld hl, __PRINT_START - ld (PRINT_JUMP_STATE), hl - ;; Clears ATTR2 flags (OVER 2, etc) - xor a - ld (FLAGS2), a - LOCAL SET_SCR_ADDR - call __LOAD_S_POSN - jp __SET_SCR_PTR - ;; Receives HL = future value of S_POSN - ;; Stores it at (S_POSN) and refresh screen pointers (ATTR, SCR) -SET_SCR_ADDR: - ld (S_POSN), hl - ex de, hl - ld hl, SCR_SIZE - or a - sbc hl, de - ex de, hl - dec e - jp __SET_SCR_PTR -__PRINTCHAR: ; Print character store in accumulator (A register) - ; Modifies H'L', B'C', A'F', D'E', A - LOCAL PO_GR_1 - LOCAL __PRCHAR - LOCAL __PRINT_JUMP - LOCAL __SRCADDR - LOCAL __PRINT_UDG - LOCAL __PRGRAPH - LOCAL __PRINT_START - PRINT_JUMP_STATE EQU __PRINT_JUMP + 2 -__PRINT_JUMP: - exx ; Switch to alternative registers - jp __PRINT_START ; Where to jump. If we print 22 (AT), next two calls jumps to AT1 and AT2 respectively -__PRINT_START: -__PRINT_CHR: - cp ' ' - jr c, __PRINT_SPECIAL ; Characters below ' ' are special ones - ex af, af' ; Saves a value (char to print) for later - ld hl, (S_POSN) - dec l - jr nz, 1f - ld l, SCR_COLS - 1 - dec h - jr nz, 2f - inc h - push hl - call __SCROLL_SCR - pop hl -#line 92 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -2: - call SET_SCR_ADDR - jr 4f -1: - ld (S_POSN), hl -4: - ex af, af' - cp 80h ; Is it a "normal" (printable) char - jr c, __SRCADDR - cp 90h ; Is it an UDG? - jr nc, __PRINT_UDG - ; Print an 8 bit pattern (80h to 8Fh) - ld b, a - call PO_GR_1 ; This ROM routine will generate the bit pattern at MEM0 - ld hl, MEM0 - jp __PRGRAPH - PO_GR_1 EQU 0B38h -__PRINT_UDG: - sub 90h ; Sub ASC code - ld bc, (UDG) - jr __PRGRAPH0 - __SOURCEADDR EQU (__SRCADDR + 1) ; Address of the pointer to chars source -__SRCADDR: - ld bc, (CHARS) -__PRGRAPH0: - add a, a ; A = a * 2 (since a < 80h) ; Thanks to Metalbrain at http://foro.speccy.org - ld l, a - ld h, 0 ; HL = a * 2 (accumulator) - add hl, hl - add hl, hl ; HL = a * 8 - add hl, bc ; HL = CHARS address -__PRGRAPH: - ex de, hl ; HL = Write Address, DE = CHARS address - bit 2, (iy + $47) - call nz, __BOLD -#line 139 "/zxbasic/src/arch/zx48k/library-asm/print.asm" - bit 4, (iy + $47) - call nz, __ITALIC -#line 144 "/zxbasic/src/arch/zx48k/library-asm/print.asm" - ld hl, (DFCC) - push hl - ld b, 8 ; 8 bytes per char -__PRCHAR: - ld a, (de) ; DE *must* be source, and HL destiny -PRINT_MODE: ; Which operation is used to write on the screen - ; Set it with: - ; LD A, - ; LD (PRINT_MODE), A - ; - ; Available operations: - ; NORMAL : 0h --> NOP ; OVER 0 - ; XOR : AEh --> XOR (HL) ; OVER 1 - ; OR : B6h --> OR (HL) ; PUTSPRITE - ; AND : A6h --> AND (HL) ; PUTMASK - nop ; Set to one of the values above -INVERSE_MODE: ; 00 -> NOP -> INVERSE 0 - nop ; 2F -> CPL -> INVERSE 1 - ld (hl), a - inc de - inc h ; Next line - djnz __PRCHAR - pop hl + LOCAL __MEM_LOOP2 + LOCAL __MEM_LINK_PREV + LOCAL __MEM_JOIN_TEST + LOCAL __MEM_BLOCK_JOIN + ld a, h + or l + ret z ; Return if NULL pointer + dec hl + dec hl + ld b, h + ld c, l ; BC = Block pointer + ld hl, ZXBASIC_MEM_HEAP ; This label point to the heap start +__MEM_LOOP2: inc hl - ld (DFCC), hl - ld hl, (DFCCL) ; current ATTR Pos - push hl - call __SET_ATTR - pop hl + inc hl ; Next block ptr + ld e, (hl) inc hl - ld (DFCCL),hl - exx - ret - ; ------------- SPECIAL CHARS (< 32) ----------------- -__PRINT_SPECIAL: ; Jumps here if it is a special char - ld hl, __PRINT_TABLE - jp JUMP_HL_PLUS_2A -PRINT_EOL: ; Called WHENEVER there is no ";" at end of PRINT sentence - exx -__PRINT_0Dh: ; Called WHEN printing CHR$(13) - ld hl, (S_POSN) - dec l - jr nz, 1f - dec h - jr nz, 1f - inc h - push hl - call __SCROLL_SCR - pop hl -#line 210 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -1: - ld l, 1 -__PRINT_EOL_END: - call SET_SCR_ADDR - exx - ret -__PRINT_COM: - exx + ld d, (hl) ; Block next ptr + ex de, hl ; DE = &(block->next); HL = block->next + ld a, h ; HL == NULL? + or l + jp z, __MEM_LINK_PREV; if so, link with previous + or a ; Clear carry flag + sbc hl, bc ; Carry if BC > HL => This block if before + add hl, bc ; Restores HL, preserving Carry flag + jp c, __MEM_LOOP2 ; This block is before. Keep searching PASS the block + ;------ At this point current HL is PAST BC, so we must link (DE) with BC, and HL in BC->next +__MEM_LINK_PREV: ; Link (DE) with BC, and BC->next with HL + ex de, hl push hl - push de - push bc - call PRINT_COMMA - pop bc - pop de + dec hl + ld (hl), c + inc hl + ld (hl), b ; (DE) <- BC + ld h, b ; HL <- BC (Free block ptr) + ld l, c + inc hl ; Skip block length (2 bytes) + inc hl + ld (hl), e ; Block->next = DE + inc hl + ld (hl), d + ; --- LINKED ; HL = &(BC->next) + 2 + call __MEM_JOIN_TEST pop hl - ret -__PRINT_TAB: - ld hl, __PRINT_TAB1 - jr __PRINT_SET_STATE -__PRINT_TAB1: - ld (MEM0), a - ld hl, __PRINT_TAB2 - jr __PRINT_SET_STATE -__PRINT_TAB2: - ld a, (MEM0) ; Load tab code (ignore the current one) - ld hl, __PRINT_START - ld (PRINT_JUMP_STATE), hl - exx - push hl - push bc - push de - call PRINT_TAB - pop de - pop bc +__MEM_JOIN_TEST: ; Checks for fragmented contiguous blocks and joins them + ; hl = Ptr to current block + 2 + ld d, (hl) + dec hl + ld e, (hl) + dec hl + ld b, (hl) ; Loads block length into BC + dec hl + ld c, (hl) ; + push hl ; Saves it for later + add hl, bc ; Adds its length. If HL == DE now, it must be joined + or a + sbc hl, de ; If Z, then HL == DE => We must join pop hl + ret nz +__MEM_BLOCK_JOIN: ; Joins current block (pointed by HL) with next one (pointed by DE). HL->length already in BC + push hl ; Saves it for later + ex de, hl + ld e, (hl) ; DE -> block->next->length + inc hl + ld d, (hl) + inc hl + ex de, hl ; DE = &(block->next) + add hl, bc ; HL = Total Length + ld b, h + ld c, l ; BC = Total Length + ex de, hl + ld e, (hl) + inc hl + ld d, (hl) ; DE = block->next + pop hl ; Recovers Pointer to block + ld (hl), c + inc hl + ld (hl), b ; Length Saved + inc hl + ld (hl), e + inc hl + ld (hl), d ; Next saved ret -__PRINT_AT: - ld hl, __PRINT_AT1 - jr __PRINT_SET_STATE -__PRINT_NOP: -__PRINT_RESTART: - ld hl, __PRINT_START -__PRINT_SET_STATE: - ld (PRINT_JUMP_STATE), hl ; Saves next entry call - exx - ret -__PRINT_AT1: ; Jumps here if waiting for 1st parameter - ld hl, (S_POSN) - ld h, a - ld a, SCR_ROWS - sub h - ld (S_POSN + 1), a - ld hl, __PRINT_AT2 - jr __PRINT_SET_STATE -__PRINT_AT2: - call __LOAD_S_POSN - ld e, a - call __SAVE_S_POSN - jr __PRINT_RESTART -__PRINT_DEL: - call __LOAD_S_POSN ; Gets current screen position - dec e - ld a, -1 - cp e - jr nz, 3f - ld e, SCR_COLS - 2 - dec d - cp d - jr nz, 3f - ld d, SCR_ROWS - 1 -3: - call __SAVE_S_POSN - exx - ret -__PRINT_INK: - ld hl, __PRINT_INK2 - jr __PRINT_SET_STATE -__PRINT_INK2: - call INK_TMP - jr __PRINT_RESTART -__PRINT_PAP: - ld hl, __PRINT_PAP2 - jr __PRINT_SET_STATE -__PRINT_PAP2: - call PAPER_TMP - jr __PRINT_RESTART -__PRINT_FLA: - ld hl, __PRINT_FLA2 - jr __PRINT_SET_STATE -__PRINT_FLA2: - call FLASH_TMP - jr __PRINT_RESTART -__PRINT_BRI: - ld hl, __PRINT_BRI2 - jr __PRINT_SET_STATE -__PRINT_BRI2: - call BRIGHT_TMP - jr __PRINT_RESTART -__PRINT_INV: - ld hl, __PRINT_INV2 - jr __PRINT_SET_STATE -__PRINT_INV2: - call INVERSE_TMP - jr __PRINT_RESTART -__PRINT_OVR: - ld hl, __PRINT_OVR2 - jr __PRINT_SET_STATE -__PRINT_OVR2: - call OVER_TMP - jr __PRINT_RESTART -__PRINT_BOLD: - ld hl, __PRINT_BOLD2 - jp __PRINT_SET_STATE -__PRINT_BOLD2: - call BOLD_TMP - jp __PRINT_RESTART -#line 354 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -__PRINT_ITA: - ld hl, __PRINT_ITA2 - jp __PRINT_SET_STATE -__PRINT_ITA2: - call ITALIC_TMP - jp __PRINT_RESTART -#line 364 "/zxbasic/src/arch/zx48k/library-asm/print.asm" - LOCAL __BOLD -__BOLD: - push hl - ld hl, MEM0 - ld b, 8 -1: - ld a, (de) - ld c, a - rlca - or c - ld (hl), a + ENDP + pop namespace +#line 88 "zx48k/ltee1.bas" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/loadstr.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/alloc.asm" +; vim: ts=4:et:sw=4: + ; Copyleft (K) by Jose M. Rodriguez de la Rosa + ; (a.k.a. Boriel) +; http://www.boriel.com + ; + ; This ASM library is licensed under the MIT license + ; you can use it for any purpose (even for commercial + ; closed source programs). + ; + ; Please read the MIT license on the internet + ; ----- IMPLEMENTATION NOTES ------ + ; The heap is implemented as a linked list of free blocks. +; Each free block contains this info: + ; + ; +----------------+ <-- HEAP START + ; | Size (2 bytes) | + ; | 0 | <-- Size = 0 => DUMMY HEADER BLOCK + ; +----------------+ + ; | Next (2 bytes) |---+ + ; +----------------+ <-+ + ; | Size (2 bytes) | + ; +----------------+ + ; | Next (2 bytes) |---+ + ; +----------------+ | + ; | | | <-- If Size > 4, then this contains (size - 4) bytes + ; | (0 if Size = 4)| | + ; +----------------+ <-+ + ; | Size (2 bytes) | + ; +----------------+ + ; | Next (2 bytes) |---+ + ; +----------------+ | + ; | | | + ; | (0 if Size = 4)| | + ; +----------------+ | + ; | <-- This zone is in use (Already allocated) + ; +----------------+ <-+ + ; | Size (2 bytes) | + ; +----------------+ + ; | Next (2 bytes) |---+ + ; +----------------+ | + ; | | | + ; | (0 if Size = 4)| | + ; +----------------+ <-+ + ; | Next (2 bytes) |--> NULL => END OF LIST + ; | 0 = NULL | + ; +----------------+ + ; | | + ; | (0 if Size = 4)| + ; +----------------+ + ; When a block is FREED, the previous and next pointers are examined to see + ; if we can defragment the heap. If the block to be freed is just next to the + ; previous, or to the next (or both) they will be converted into a single + ; block (so defragmented). + ; MEMORY MANAGER + ; + ; This library must be initialized calling __MEM_INIT with + ; HL = BLOCK Start & DE = Length. + ; An init directive is useful for initialization routines. + ; They will be added automatically if needed. + ; --------------------------------------------------------------------- + ; MEM_ALLOC + ; Allocates a block of memory in the heap. + ; + ; Parameters + ; BC = Length of requested memory block + ; +; Returns: + ; HL = Pointer to the allocated block in memory. Returns 0 (NULL) + ; if the block could not be allocated (out of memory) + ; --------------------------------------------------------------------- + push namespace core +MEM_ALLOC: +__MEM_ALLOC: ; Returns the 1st free block found of the given length (in BC) + PROC + LOCAL __MEM_LOOP + LOCAL __MEM_DONE + LOCAL __MEM_SUBTRACT + LOCAL __MEM_START + LOCAL TEMP, TEMP0 + TEMP EQU TEMP0 + 1 + ld hl, 0 + ld (TEMP), hl +__MEM_START: + ld hl, ZXBASIC_MEM_HEAP ; This label point to the heap start + inc bc + inc bc ; BC = BC + 2 ; block size needs 2 extra bytes for hidden pointer +__MEM_LOOP: ; Loads lengh at (HL, HL+). If Lenght >= BC, jump to __MEM_DONE + ld a, h ; HL = NULL (No memory available?) + or l +#line 113 "/zxbasic/src/arch/zx48k/library-asm/alloc.asm" + ret z ; NULL +#line 115 "/zxbasic/src/arch/zx48k/library-asm/alloc.asm" + ; HL = Pointer to Free block + ld e, (hl) inc hl - inc de - djnz 1b + ld d, (hl) + inc hl ; DE = Block Length + push hl ; HL = *pointer to -> next block + ex de, hl + or a ; CF = 0 + sbc hl, bc ; FREE >= BC (Length) (HL = BlockLength - Length) + jp nc, __MEM_DONE pop hl - ld de, MEM0 - ret -#line 385 "/zxbasic/src/arch/zx48k/library-asm/print.asm" - LOCAL __ITALIC -__ITALIC: - push hl - ld hl, MEM0 + ld (TEMP), hl ex de, hl - ld bc, 8 - ldir - ld hl, MEM0 - srl (hl) - inc hl - srl (hl) - inc hl - srl (hl) - inc hl - inc hl + ld e, (hl) inc hl - sla (hl) + ld d, (hl) + ex de, hl + jp __MEM_LOOP +__MEM_DONE: ; A free block has been found. + ; Check if at least 4 bytes remains free (HL >= 4) + push hl + exx ; exx to preserve bc + pop hl + ld bc, 4 + or a + sbc hl, bc + exx + jp nc, __MEM_SUBTRACT + ; At this point... + ; less than 4 bytes remains free. So we return this block entirely + ; We must link the previous block with the next to this one + ; (DE) => Pointer to next block + ; (TEMP) => &(previous->next) + pop hl ; Discard current block pointer + push de + ex de, hl ; DE = Previous block pointer; (HL) = Next block pointer + ld a, (hl) inc hl - sla (hl) + ld h, (hl) + ld l, a ; HL = (HL) + ex de, hl ; HL = Previous block pointer; DE = Next block pointer +TEMP0: + ld hl, 0 ; Pre-previous block pointer + ld (hl), e inc hl - sla (hl) - pop hl - ld de, MEM0 - ret -#line 413 "/zxbasic/src/arch/zx48k/library-asm/print.asm" - LOCAL __SCROLL_SCR -#line 487 "/zxbasic/src/arch/zx48k/library-asm/print.asm" - __SCROLL_SCR EQU 0DFEh ; Use ROM SCROLL -#line 489 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -#line 490 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -PRINT_COMMA: - call __LOAD_S_POSN - ld a, e - and 16 - add a, 16 -PRINT_TAB: - ; Tabulates the number of spaces in A register - ; If the current cursor position is already A, does nothing - PROC - LOCAL LOOP - call __LOAD_S_POSN ; e = current row - sub e - and 31 - ret z - ld b, a -LOOP: - ld a, ' ' - call __PRINTCHAR - djnz LOOP + ld (hl), d ; LINKED + pop hl ; Returning block. ret - ENDP -PRINT_AT: ; Changes cursor to ROW, COL - ; COL in A register - ; ROW in stack - pop hl ; Ret address - ex (sp), hl ; callee H = ROW - ld l, a +__MEM_SUBTRACT: + ; At this point we have to store HL value (Length - BC) into (DE - 2) ex de, hl - call __IN_SCREEN - ret nc ; Return if out of screen - jp __SAVE_S_POSN - LOCAL __PRINT_COM - LOCAL __PRINT_AT1 - LOCAL __PRINT_AT2 - LOCAL __PRINT_BOLD - LOCAL __PRINT_ITA - LOCAL __PRINT_INK - LOCAL __PRINT_PAP - LOCAL __PRINT_SET_STATE - LOCAL __PRINT_TABLE - LOCAL __PRINT_TAB, __PRINT_TAB1, __PRINT_TAB2 - LOCAL __PRINT_ITA2 -#line 546 "/zxbasic/src/arch/zx48k/library-asm/print.asm" - LOCAL __PRINT_BOLD2 -#line 552 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -__PRINT_TABLE: ; Jump table for 0 .. 22 codes - DW __PRINT_NOP ; 0 - DW __PRINT_NOP ; 1 - DW __PRINT_NOP ; 2 - DW __PRINT_NOP ; 3 - DW __PRINT_NOP ; 4 - DW __PRINT_NOP ; 5 - DW __PRINT_COM ; 6 COMMA - DW __PRINT_NOP ; 7 - DW __PRINT_DEL ; 8 DEL - DW __PRINT_NOP ; 9 - DW __PRINT_NOP ; 10 - DW __PRINT_NOP ; 11 - DW __PRINT_NOP ; 12 - DW __PRINT_0Dh ; 13 - DW __PRINT_BOLD ; 14 - DW __PRINT_ITA ; 15 - DW __PRINT_INK ; 16 - DW __PRINT_PAP ; 17 - DW __PRINT_FLA ; 18 - DW __PRINT_BRI ; 19 - DW __PRINT_INV ; 20 - DW __PRINT_OVR ; 21 - DW __PRINT_AT ; 22 AT - DW __PRINT_TAB ; 23 TAB + dec hl + ld (hl), d + dec hl + ld (hl), e ; Store new block length + add hl, de ; New length + DE => free-block start + pop de ; Remove previous HL off the stack + ld (hl), c ; Store length on its 1st word + inc hl + ld (hl), b + inc hl ; Return hl + ret ENDP pop namespace -#line 5 "/zxbasic/src/arch/zx48k/library-asm/print_eol_attr.asm" +#line 2 "/zxbasic/src/arch/zx48k/library-asm/loadstr.asm" + ; Loads a string (ptr) from HL + ; and duplicates it on dynamic memory again + ; Finally, it returns result pointer in HL push namespace core -PRINT_EOL_ATTR: - call PRINT_EOL - jp COPY_ATTR +__ILOADSTR: ; This is the indirect pointer entry HL = (HL) + ld a, h + or l + ret z + ld a, (hl) + inc hl + ld h, (hl) + ld l, a +__LOADSTR: ; __FASTCALL__ entry + ld a, h + or l + ret z ; Return if NULL + ld c, (hl) + inc hl + ld b, (hl) + dec hl ; BC = LEN(a$) + inc bc + inc bc ; BC = LEN(a$) + 2 (two bytes for length) + push hl + push bc + call __MEM_ALLOC + pop bc ; Recover length + pop de ; Recover origin + ld a, h + or l + ret z ; Return if NULL (No memory) + ex de, hl ; ldir takes HL as source, DE as destiny, so SWAP HL,DE + push de ; Saves destiny start + ldir ; Copies string (length number included) + pop hl ; Recovers destiny in hl as result + ret pop namespace -#line 88 "zx48k/ltee1.bas" +#line 89 "zx48k/ltee1.bas" #line 1 "/zxbasic/src/arch/zx48k/library-asm/printstr.asm" ; PRINT command routine ; Prints string pointed by HL @@ -1540,7 +1531,7 @@ __PRINT_STR: jp __PRINT_STR_LOOP ENDP pop namespace -#line 89 "zx48k/ltee1.bas" +#line 91 "zx48k/ltee1.bas" #line 1 "/zxbasic/src/arch/zx48k/library-asm/pstorestr.asm" ; vim:ts=4:et:sw=4 ; @@ -1803,7 +1794,7 @@ __PSTORE_STR: add hl, bc jp __STORE_STR pop namespace -#line 90 "zx48k/ltee1.bas" +#line 92 "zx48k/ltee1.bas" #line 1 "/zxbasic/src/arch/zx48k/library-asm/pstorestr2.asm" ; vim:ts=4:et:sw=4 ; @@ -1852,7 +1843,7 @@ __PSTORE_STR2: add hl, bc jp __STORE_STR2 pop namespace -#line 91 "zx48k/ltee1.bas" +#line 93 "zx48k/ltee1.bas" #line 1 "/zxbasic/src/arch/zx48k/library-asm/strcat.asm" #line 1 "/zxbasic/src/arch/zx48k/library-asm/strlen.asm" ; Returns len if a string @@ -1965,5 +1956,5 @@ __STRCATEND: ret ENDP pop namespace -#line 93 "zx48k/ltee1.bas" +#line 95 "zx48k/ltee1.bas" END diff --git a/tests/functional/zx48k/memcpytest.asm b/tests/functional/zx48k/memcpytest.asm index 8cc391cc5..dc50e991d 100644 --- a/tests/functional/zx48k/memcpytest.asm +++ b/tests/functional/zx48k/memcpytest.asm @@ -33,6 +33,7 @@ _i: ld (_i), a jp .LABEL.__LABEL0 .LABEL.__LABEL3: + call .core.COPY_ATTR ld hl, .LABEL.__LABEL5 xor a call .core.__PRINTSTR @@ -192,58 +193,7 @@ CLS: ENDP pop namespace #line 134 "/zxbasic/src/arch/zx48k/library/memcopy.bas" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/memcopy.asm" - ; ---------------------------------------------------------------- - ; This file is released under the MIT License - ; - ; Copyleft (k) 2008 -; by Jose Rodriguez-Rosa (a.k.a. Boriel) - ; - ; Use this file as a template to develop your own library file - ; ---------------------------------------------------------------- - ; Emulates both memmove and memcpy C routines - ; Block will be safely copied if they overlap - ; HL => Start of source block - ; DE => Start of destiny block - ; BC => Block length - push namespace core -__MEMCPY: - PROC - LOCAL __MEMCPY2 - push hl - add hl, bc ; addr of last source block byte + 1 - or a - sbc hl, de ; checks if DE > HL + BC - pop hl ; recovers HL. If carry => DE > HL + BC (no overlap) - jr c, __MEMCPY2 - ; Now checks if DE <= HL - sbc hl, de ; Even if overlap, if DE < HL then we can LDIR safely - add hl, de - jr nc, __MEMCPY2 - dec bc - add hl, bc - ex de, hl - add hl, bc - ex de, hl - inc bc ; HL and DE point to the last byte position - lddr ; Copies from end to beginning - ret -__MEMCPY2: - ldir - ret - ENDP - pop namespace -#line 135 "/zxbasic/src/arch/zx48k/library/memcopy.bas" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/pause.asm" - ; The PAUSE statement (Calling the ROM) - push namespace core -__PAUSE: - ld b, h - ld c, l - jp 1F3Dh ; PAUSE_1 - pop namespace -#line 136 "/zxbasic/src/arch/zx48k/library/memcopy.bas" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/printstr.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" #line 1 "/zxbasic/src/arch/zx48k/library-asm/print.asm" ; vim:ts=4:sw=4:et: ; PRINT command routine @@ -566,60 +516,6 @@ BRIGHT_TMP: #line 1 "/zxbasic/src/arch/zx48k/library-asm/over.asm" ; Sets OVER flag in P_FLAG permanently ; Parameter: OVER flag in bit 0 of A register -#line 1 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" -#line 4 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" - push namespace core -COPY_ATTR: - ; Just copies current permanent attribs into temporal attribs - ; and sets print mode - PROC - LOCAL INVERSE1 - LOCAL __REFRESH_TMP - INVERSE1 EQU 02Fh - ld hl, (ATTR_P) - ld (ATTR_T), hl - ld hl, FLAGS2 - call __REFRESH_TMP - ld hl, P_FLAG - call __REFRESH_TMP -__SET_ATTR_MODE: ; Another entry to set print modes. A contains (P_FLAG) - LOCAL TABLE - LOCAL CONT2 - rra ; Over bit to carry - ld a, (FLAGS2) - rla ; Over bit in bit 1, Over2 bit in bit 2 - and 3 ; Only bit 0 and 1 (OVER flag) - ld c, a - ld b, 0 - ld hl, TABLE - add hl, bc - ld a, (hl) - ld (PRINT_MODE), a - ld hl, (P_FLAG) - xor a ; NOP -> INVERSE0 - bit 2, l - jr z, CONT2 - ld a, INVERSE1 ; CPL -> INVERSE1 -CONT2: - ld (INVERSE_MODE), a - ret -TABLE: - nop ; NORMAL MODE - xor (hl) ; OVER 1 MODE - and (hl) ; OVER 2 MODE - or (hl) ; OVER 3 MODE -#line 67 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" -__REFRESH_TMP: - ld a, (hl) - and 0b10101010 - ld c, a - rra - or c - ld (hl), a - ret - ENDP - pop namespace -#line 4 "/zxbasic/src/arch/zx48k/library-asm/over.asm" push namespace core OVER: PROC @@ -861,11 +757,10 @@ INVERSE_MODE: ; 00 -> NOP -> INVERSE 0 inc hl ld (DFCC), hl ld hl, (DFCCL) ; current ATTR Pos - push hl - call __SET_ATTR - pop hl inc hl - ld (DFCCL),hl + ld (DFCCL), hl + dec hl + call __SET_ATTR exx ret ; ------------- SPECIAL CHARS (< 32) ----------------- @@ -884,7 +779,7 @@ __PRINT_0Dh: ; Called WHEN printing CHR$(13) push hl call __SCROLL_SCR pop hl -#line 210 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 209 "/zxbasic/src/arch/zx48k/library-asm/print.asm" 1: ld l, 1 __PRINT_EOL_END: @@ -1001,14 +896,14 @@ __PRINT_BOLD: __PRINT_BOLD2: call BOLD_TMP jp __PRINT_RESTART -#line 354 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 353 "/zxbasic/src/arch/zx48k/library-asm/print.asm" __PRINT_ITA: ld hl, __PRINT_ITA2 jp __PRINT_SET_STATE __PRINT_ITA2: call ITALIC_TMP jp __PRINT_RESTART -#line 364 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 363 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __BOLD __BOLD: push hl @@ -1026,7 +921,7 @@ __BOLD: pop hl ld de, MEM0 ret -#line 385 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 384 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __ITALIC __ITALIC: push hl @@ -1051,12 +946,12 @@ __ITALIC: pop hl ld de, MEM0 ret -#line 413 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 412 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __SCROLL_SCR -#line 487 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 486 "/zxbasic/src/arch/zx48k/library-asm/print.asm" __SCROLL_SCR EQU 0DFEh ; Use ROM SCROLL +#line 488 "/zxbasic/src/arch/zx48k/library-asm/print.asm" #line 489 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -#line 490 "/zxbasic/src/arch/zx48k/library-asm/print.asm" PRINT_COMMA: call __LOAD_S_POSN ld a, e @@ -1099,9 +994,9 @@ PRINT_AT: ; Changes cursor to ROW, COL LOCAL __PRINT_TABLE LOCAL __PRINT_TAB, __PRINT_TAB1, __PRINT_TAB2 LOCAL __PRINT_ITA2 -#line 546 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 545 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __PRINT_BOLD2 -#line 552 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 551 "/zxbasic/src/arch/zx48k/library-asm/print.asm" __PRINT_TABLE: ; Jump table for 0 .. 22 codes DW __PRINT_NOP ; 0 DW __PRINT_NOP ; 1 @@ -1129,7 +1024,112 @@ __PRINT_TABLE: ; Jump table for 0 .. 22 codes DW __PRINT_TAB ; 23 TAB ENDP pop namespace -#line 2 "/zxbasic/src/arch/zx48k/library-asm/printstr.asm" +#line 3 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" +#line 4 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" + push namespace core +COPY_ATTR: + ; Just copies current permanent attribs into temporal attribs + ; and sets print mode + PROC + LOCAL INVERSE1 + LOCAL __REFRESH_TMP + INVERSE1 EQU 02Fh + ld hl, (ATTR_P) + ld (ATTR_T), hl + ld hl, FLAGS2 + call __REFRESH_TMP + ld hl, P_FLAG + call __REFRESH_TMP +__SET_ATTR_MODE: ; Another entry to set print modes. A contains (P_FLAG) + LOCAL TABLE + LOCAL CONT2 + rra ; Over bit to carry + ld a, (FLAGS2) + rla ; Over bit in bit 1, Over2 bit in bit 2 + and 3 ; Only bit 0 and 1 (OVER flag) + ld c, a + ld b, 0 + ld hl, TABLE + add hl, bc + ld a, (hl) + ld (PRINT_MODE), a + ld hl, (P_FLAG) + xor a ; NOP -> INVERSE0 + bit 2, l + jr z, CONT2 + ld a, INVERSE1 ; CPL -> INVERSE1 +CONT2: + ld (INVERSE_MODE), a + ret +TABLE: + nop ; NORMAL MODE + xor (hl) ; OVER 1 MODE + and (hl) ; OVER 2 MODE + or (hl) ; OVER 3 MODE +#line 67 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" +__REFRESH_TMP: + ld a, (hl) + and 0b10101010 + ld c, a + rra + or c + ld (hl), a + ret + ENDP + pop namespace +#line 135 "/zxbasic/src/arch/zx48k/library/memcopy.bas" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/memcopy.asm" + ; ---------------------------------------------------------------- + ; This file is released under the MIT License + ; + ; Copyleft (k) 2008 +; by Jose Rodriguez-Rosa (a.k.a. Boriel) + ; + ; Use this file as a template to develop your own library file + ; ---------------------------------------------------------------- + ; Emulates both memmove and memcpy C routines + ; Block will be safely copied if they overlap + ; HL => Start of source block + ; DE => Start of destiny block + ; BC => Block length + push namespace core +__MEMCPY: + PROC + LOCAL __MEMCPY2 + push hl + add hl, bc ; addr of last source block byte + 1 + or a + sbc hl, de ; checks if DE > HL + BC + pop hl ; recovers HL. If carry => DE > HL + BC (no overlap) + jr c, __MEMCPY2 + ; Now checks if DE <= HL + sbc hl, de ; Even if overlap, if DE < HL then we can LDIR safely + add hl, de + jr nc, __MEMCPY2 + dec bc + add hl, bc + ex de, hl + add hl, bc + ex de, hl + inc bc ; HL and DE point to the last byte position + lddr ; Copies from end to beginning + ret +__MEMCPY2: + ldir + ret + ENDP + pop namespace +#line 136 "/zxbasic/src/arch/zx48k/library/memcopy.bas" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/pause.asm" + ; The PAUSE statement (Calling the ROM) + push namespace core +__PAUSE: + ld b, h + ld c, l + jp 1F3Dh ; PAUSE_1 + pop namespace +#line 137 "/zxbasic/src/arch/zx48k/library/memcopy.bas" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/printstr.asm" #line 1 "/zxbasic/src/arch/zx48k/library-asm/free.asm" ; vim: ts=4:et:sw=4: ; Copyleft (K) by Jose M. Rodriguez de la Rosa @@ -1439,5 +1439,5 @@ __PRINT_STR: jp __PRINT_STR_LOOP ENDP pop namespace -#line 137 "/zxbasic/src/arch/zx48k/library/memcopy.bas" +#line 138 "/zxbasic/src/arch/zx48k/library/memcopy.bas" END diff --git a/tests/functional/zx48k/noheap.asm b/tests/functional/zx48k/noheap.asm index db9891779..e1e68c3f5 100644 --- a/tests/functional/zx48k/noheap.asm +++ b/tests/functional/zx48k/noheap.asm @@ -21,6 +21,7 @@ .core.__LABEL__.ZXBASIC_USER_DATA EQU .core.ZXBASIC_USER_DATA .core.ZXBASIC_USER_DATA_END: .core.__MAIN_PROGRAM__: + call .core.COPY_ATTR ld hl, 12345 call .core.__PRINTU16 call .core.PRINT_EOL @@ -39,6 +40,7 @@ ei ret ;; --- end of user code --- +#line 1 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" #line 1 "/zxbasic/src/arch/zx48k/library-asm/print.asm" ; vim:ts=4:sw=4:et: ; PRINT command routine @@ -388,60 +390,6 @@ BRIGHT_TMP: #line 1 "/zxbasic/src/arch/zx48k/library-asm/over.asm" ; Sets OVER flag in P_FLAG permanently ; Parameter: OVER flag in bit 0 of A register -#line 1 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" -#line 4 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" - push namespace core -COPY_ATTR: - ; Just copies current permanent attribs into temporal attribs - ; and sets print mode - PROC - LOCAL INVERSE1 - LOCAL __REFRESH_TMP - INVERSE1 EQU 02Fh - ld hl, (ATTR_P) - ld (ATTR_T), hl - ld hl, FLAGS2 - call __REFRESH_TMP - ld hl, P_FLAG - call __REFRESH_TMP -__SET_ATTR_MODE: ; Another entry to set print modes. A contains (P_FLAG) - LOCAL TABLE - LOCAL CONT2 - rra ; Over bit to carry - ld a, (FLAGS2) - rla ; Over bit in bit 1, Over2 bit in bit 2 - and 3 ; Only bit 0 and 1 (OVER flag) - ld c, a - ld b, 0 - ld hl, TABLE - add hl, bc - ld a, (hl) - ld (PRINT_MODE), a - ld hl, (P_FLAG) - xor a ; NOP -> INVERSE0 - bit 2, l - jr z, CONT2 - ld a, INVERSE1 ; CPL -> INVERSE1 -CONT2: - ld (INVERSE_MODE), a - ret -TABLE: - nop ; NORMAL MODE - xor (hl) ; OVER 1 MODE - and (hl) ; OVER 2 MODE - or (hl) ; OVER 3 MODE -#line 67 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" -__REFRESH_TMP: - ld a, (hl) - and 0b10101010 - ld c, a - rra - or c - ld (hl), a - ret - ENDP - pop namespace -#line 4 "/zxbasic/src/arch/zx48k/library-asm/over.asm" push namespace core OVER: PROC @@ -683,11 +631,10 @@ INVERSE_MODE: ; 00 -> NOP -> INVERSE 0 inc hl ld (DFCC), hl ld hl, (DFCCL) ; current ATTR Pos - push hl - call __SET_ATTR - pop hl inc hl - ld (DFCCL),hl + ld (DFCCL), hl + dec hl + call __SET_ATTR exx ret ; ------------- SPECIAL CHARS (< 32) ----------------- @@ -706,7 +653,7 @@ __PRINT_0Dh: ; Called WHEN printing CHR$(13) push hl call __SCROLL_SCR pop hl -#line 210 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 209 "/zxbasic/src/arch/zx48k/library-asm/print.asm" 1: ld l, 1 __PRINT_EOL_END: @@ -823,14 +770,14 @@ __PRINT_BOLD: __PRINT_BOLD2: call BOLD_TMP jp __PRINT_RESTART -#line 354 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 353 "/zxbasic/src/arch/zx48k/library-asm/print.asm" __PRINT_ITA: ld hl, __PRINT_ITA2 jp __PRINT_SET_STATE __PRINT_ITA2: call ITALIC_TMP jp __PRINT_RESTART -#line 364 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 363 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __BOLD __BOLD: push hl @@ -848,7 +795,7 @@ __BOLD: pop hl ld de, MEM0 ret -#line 385 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 384 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __ITALIC __ITALIC: push hl @@ -873,12 +820,12 @@ __ITALIC: pop hl ld de, MEM0 ret -#line 413 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 412 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __SCROLL_SCR -#line 487 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 486 "/zxbasic/src/arch/zx48k/library-asm/print.asm" __SCROLL_SCR EQU 0DFEh ; Use ROM SCROLL +#line 488 "/zxbasic/src/arch/zx48k/library-asm/print.asm" #line 489 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -#line 490 "/zxbasic/src/arch/zx48k/library-asm/print.asm" PRINT_COMMA: call __LOAD_S_POSN ld a, e @@ -921,9 +868,9 @@ PRINT_AT: ; Changes cursor to ROW, COL LOCAL __PRINT_TABLE LOCAL __PRINT_TAB, __PRINT_TAB1, __PRINT_TAB2 LOCAL __PRINT_ITA2 -#line 546 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 545 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __PRINT_BOLD2 -#line 552 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 551 "/zxbasic/src/arch/zx48k/library-asm/print.asm" __PRINT_TABLE: ; Jump table for 0 .. 22 codes DW __PRINT_NOP ; 0 DW __PRINT_NOP ; 1 @@ -951,7 +898,60 @@ __PRINT_TABLE: ; Jump table for 0 .. 22 codes DW __PRINT_TAB ; 23 TAB ENDP pop namespace -#line 20 "zx48k/noheap.bas" +#line 3 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" +#line 4 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" + push namespace core +COPY_ATTR: + ; Just copies current permanent attribs into temporal attribs + ; and sets print mode + PROC + LOCAL INVERSE1 + LOCAL __REFRESH_TMP + INVERSE1 EQU 02Fh + ld hl, (ATTR_P) + ld (ATTR_T), hl + ld hl, FLAGS2 + call __REFRESH_TMP + ld hl, P_FLAG + call __REFRESH_TMP +__SET_ATTR_MODE: ; Another entry to set print modes. A contains (P_FLAG) + LOCAL TABLE + LOCAL CONT2 + rra ; Over bit to carry + ld a, (FLAGS2) + rla ; Over bit in bit 1, Over2 bit in bit 2 + and 3 ; Only bit 0 and 1 (OVER flag) + ld c, a + ld b, 0 + ld hl, TABLE + add hl, bc + ld a, (hl) + ld (PRINT_MODE), a + ld hl, (P_FLAG) + xor a ; NOP -> INVERSE0 + bit 2, l + jr z, CONT2 + ld a, INVERSE1 ; CPL -> INVERSE1 +CONT2: + ld (INVERSE_MODE), a + ret +TABLE: + nop ; NORMAL MODE + xor (hl) ; OVER 1 MODE + and (hl) ; OVER 2 MODE + or (hl) ; OVER 3 MODE +#line 67 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" +__REFRESH_TMP: + ld a, (hl) + and 0b10101010 + ld c, a + rra + or c + ld (hl), a + ret + ENDP + pop namespace +#line 21 "zx48k/noheap.bas" #line 1 "/zxbasic/src/arch/zx48k/library-asm/printu16.asm" #line 1 "/zxbasic/src/arch/zx48k/library-asm/printi16.asm" #line 1 "/zxbasic/src/arch/zx48k/library-asm/printnum.asm" @@ -1099,5 +1099,5 @@ __PRINTU_LOOP: ENDP pop namespace #line 2 "/zxbasic/src/arch/zx48k/library-asm/printu16.asm" -#line 21 "zx48k/noheap.bas" +#line 23 "zx48k/noheap.bas" END diff --git a/tests/functional/zx48k/ongosub.asm b/tests/functional/zx48k/ongosub.asm index 34b066936..74e6277cc 100644 --- a/tests/functional/zx48k/ongosub.asm +++ b/tests/functional/zx48k/ongosub.asm @@ -37,6 +37,7 @@ _a: push hl ld a, 1 call .core.__ON_GOSUB + call .core.COPY_ATTR ld hl, .LABEL.__LABEL2 xor a call .core.__PRINTSTR @@ -56,24 +57,28 @@ _a: ei ret .LABEL._40: + call .core.COPY_ATTR ld hl, .LABEL.__LABEL3 xor a call .core.__PRINTSTR call .core.PRINT_EOL ret .LABEL._50: + call .core.COPY_ATTR ld hl, .LABEL.__LABEL4 xor a call .core.__PRINTSTR call .core.PRINT_EOL ret .LABEL._60: + call .core.COPY_ATTR ld hl, .LABEL.__LABEL5 xor a call .core.__PRINTSTR call .core.PRINT_EOL ret .LABEL._70: + call .core.COPY_ATTR ld hl, .LABEL.__LABEL6 xor a call .core.__PRINTSTR @@ -111,38 +116,7 @@ _a: DEFW .LABEL._50 DEFW .LABEL._60 ;; --- end of user code --- -#line 1 "/zxbasic/src/arch/zx48k/library-asm/ongoto.asm" - ; ------------------------------------------------------ - ; Implements ON .. GOTO - ; ------------------------------------------------------ - push namespace core -__ON_GOSUB: - pop hl - ex (sp), hl ; hl = beginning of table - call __ON_GOTO_START - ret -__ON_GOTO: - pop hl - ex (sp), hl ; hl = beginning of table -__ON_GOTO_START: - ; hl = address of jump table - ; a = index (0..255) - cp (hl) ; length of last post - ret nc ; a >= length of last position (out of range) - inc hl - pop de ; removes ret addr from the stack - ld d, 0 - add a, a - ld e, a - rl d - add hl, de - ld a, (hl) - inc hl - ld h, (hl) - ld l, a - jp (hl) - pop namespace -#line 85 "zx48k/ongosub.bas" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" #line 1 "/zxbasic/src/arch/zx48k/library-asm/print.asm" ; vim:ts=4:sw=4:et: ; PRINT command routine @@ -492,60 +466,6 @@ BRIGHT_TMP: #line 1 "/zxbasic/src/arch/zx48k/library-asm/over.asm" ; Sets OVER flag in P_FLAG permanently ; Parameter: OVER flag in bit 0 of A register -#line 1 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" -#line 4 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" - push namespace core -COPY_ATTR: - ; Just copies current permanent attribs into temporal attribs - ; and sets print mode - PROC - LOCAL INVERSE1 - LOCAL __REFRESH_TMP - INVERSE1 EQU 02Fh - ld hl, (ATTR_P) - ld (ATTR_T), hl - ld hl, FLAGS2 - call __REFRESH_TMP - ld hl, P_FLAG - call __REFRESH_TMP -__SET_ATTR_MODE: ; Another entry to set print modes. A contains (P_FLAG) - LOCAL TABLE - LOCAL CONT2 - rra ; Over bit to carry - ld a, (FLAGS2) - rla ; Over bit in bit 1, Over2 bit in bit 2 - and 3 ; Only bit 0 and 1 (OVER flag) - ld c, a - ld b, 0 - ld hl, TABLE - add hl, bc - ld a, (hl) - ld (PRINT_MODE), a - ld hl, (P_FLAG) - xor a ; NOP -> INVERSE0 - bit 2, l - jr z, CONT2 - ld a, INVERSE1 ; CPL -> INVERSE1 -CONT2: - ld (INVERSE_MODE), a - ret -TABLE: - nop ; NORMAL MODE - xor (hl) ; OVER 1 MODE - and (hl) ; OVER 2 MODE - or (hl) ; OVER 3 MODE -#line 67 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" -__REFRESH_TMP: - ld a, (hl) - and 0b10101010 - ld c, a - rra - or c - ld (hl), a - ret - ENDP - pop namespace -#line 4 "/zxbasic/src/arch/zx48k/library-asm/over.asm" push namespace core OVER: PROC @@ -787,11 +707,10 @@ INVERSE_MODE: ; 00 -> NOP -> INVERSE 0 inc hl ld (DFCC), hl ld hl, (DFCCL) ; current ATTR Pos - push hl - call __SET_ATTR - pop hl inc hl - ld (DFCCL),hl + ld (DFCCL), hl + dec hl + call __SET_ATTR exx ret ; ------------- SPECIAL CHARS (< 32) ----------------- @@ -810,7 +729,7 @@ __PRINT_0Dh: ; Called WHEN printing CHR$(13) push hl call __SCROLL_SCR pop hl -#line 210 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 209 "/zxbasic/src/arch/zx48k/library-asm/print.asm" 1: ld l, 1 __PRINT_EOL_END: @@ -927,14 +846,14 @@ __PRINT_BOLD: __PRINT_BOLD2: call BOLD_TMP jp __PRINT_RESTART -#line 354 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 353 "/zxbasic/src/arch/zx48k/library-asm/print.asm" __PRINT_ITA: ld hl, __PRINT_ITA2 jp __PRINT_SET_STATE __PRINT_ITA2: call ITALIC_TMP jp __PRINT_RESTART -#line 364 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 363 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __BOLD __BOLD: push hl @@ -952,7 +871,7 @@ __BOLD: pop hl ld de, MEM0 ret -#line 385 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 384 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __ITALIC __ITALIC: push hl @@ -977,12 +896,12 @@ __ITALIC: pop hl ld de, MEM0 ret -#line 413 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 412 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __SCROLL_SCR -#line 487 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 486 "/zxbasic/src/arch/zx48k/library-asm/print.asm" __SCROLL_SCR EQU 0DFEh ; Use ROM SCROLL +#line 488 "/zxbasic/src/arch/zx48k/library-asm/print.asm" #line 489 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -#line 490 "/zxbasic/src/arch/zx48k/library-asm/print.asm" PRINT_COMMA: call __LOAD_S_POSN ld a, e @@ -1025,9 +944,9 @@ PRINT_AT: ; Changes cursor to ROW, COL LOCAL __PRINT_TABLE LOCAL __PRINT_TAB, __PRINT_TAB1, __PRINT_TAB2 LOCAL __PRINT_ITA2 -#line 546 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 545 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __PRINT_BOLD2 -#line 552 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 551 "/zxbasic/src/arch/zx48k/library-asm/print.asm" __PRINT_TABLE: ; Jump table for 0 .. 22 codes DW __PRINT_NOP ; 0 DW __PRINT_NOP ; 1 @@ -1055,7 +974,92 @@ __PRINT_TABLE: ; Jump table for 0 .. 22 codes DW __PRINT_TAB ; 23 TAB ENDP pop namespace -#line 86 "zx48k/ongosub.bas" +#line 3 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" +#line 4 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" + push namespace core +COPY_ATTR: + ; Just copies current permanent attribs into temporal attribs + ; and sets print mode + PROC + LOCAL INVERSE1 + LOCAL __REFRESH_TMP + INVERSE1 EQU 02Fh + ld hl, (ATTR_P) + ld (ATTR_T), hl + ld hl, FLAGS2 + call __REFRESH_TMP + ld hl, P_FLAG + call __REFRESH_TMP +__SET_ATTR_MODE: ; Another entry to set print modes. A contains (P_FLAG) + LOCAL TABLE + LOCAL CONT2 + rra ; Over bit to carry + ld a, (FLAGS2) + rla ; Over bit in bit 1, Over2 bit in bit 2 + and 3 ; Only bit 0 and 1 (OVER flag) + ld c, a + ld b, 0 + ld hl, TABLE + add hl, bc + ld a, (hl) + ld (PRINT_MODE), a + ld hl, (P_FLAG) + xor a ; NOP -> INVERSE0 + bit 2, l + jr z, CONT2 + ld a, INVERSE1 ; CPL -> INVERSE1 +CONT2: + ld (INVERSE_MODE), a + ret +TABLE: + nop ; NORMAL MODE + xor (hl) ; OVER 1 MODE + and (hl) ; OVER 2 MODE + or (hl) ; OVER 3 MODE +#line 67 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" +__REFRESH_TMP: + ld a, (hl) + and 0b10101010 + ld c, a + rra + or c + ld (hl), a + ret + ENDP + pop namespace +#line 90 "zx48k/ongosub.bas" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/ongoto.asm" + ; ------------------------------------------------------ + ; Implements ON .. GOTO + ; ------------------------------------------------------ + push namespace core +__ON_GOSUB: + pop hl + ex (sp), hl ; hl = beginning of table + call __ON_GOTO_START + ret +__ON_GOTO: + pop hl + ex (sp), hl ; hl = beginning of table +__ON_GOTO_START: + ; hl = address of jump table + ; a = index (0..255) + cp (hl) ; length of last post + ret nc ; a >= length of last position (out of range) + inc hl + pop de ; removes ret addr from the stack + ld d, 0 + add a, a + ld e, a + rl d + add hl, de + ld a, (hl) + inc hl + ld h, (hl) + ld l, a + jp (hl) + pop namespace +#line 91 "zx48k/ongosub.bas" #line 1 "/zxbasic/src/arch/zx48k/library-asm/printstr.asm" #line 1 "/zxbasic/src/arch/zx48k/library-asm/free.asm" ; vim: ts=4:et:sw=4: @@ -1366,5 +1370,5 @@ __PRINT_STR: jp __PRINT_STR_LOOP ENDP pop namespace -#line 87 "zx48k/ongosub.bas" +#line 93 "zx48k/ongosub.bas" END diff --git a/tests/functional/zx48k/ongoto.asm b/tests/functional/zx48k/ongoto.asm index 2f56b3c0e..e61fccc53 100644 --- a/tests/functional/zx48k/ongoto.asm +++ b/tests/functional/zx48k/ongoto.asm @@ -34,20 +34,24 @@ _a: inc a call .core.__ON_GOTO .LABEL._10: + call .core.COPY_ATTR ld hl, .LABEL.__LABEL1 xor a call .core.__PRINTSTR call .core.PRINT_EOL .LABEL._20: + call .core.COPY_ATTR ld hl, .LABEL.__LABEL2 xor a call .core.__PRINTSTR call .core.PRINT_EOL .LABEL._30: + call .core.COPY_ATTR ld hl, .LABEL.__LABEL3 xor a call .core.__PRINTSTR call .core.PRINT_EOL + call .core.COPY_ATTR ld hl, .LABEL.__LABEL4 xor a call .core.__PRINTSTR @@ -89,38 +93,7 @@ _a: DEFW .LABEL._20 DEFW .LABEL._30 ;; --- end of user code --- -#line 1 "/zxbasic/src/arch/zx48k/library-asm/ongoto.asm" - ; ------------------------------------------------------ - ; Implements ON .. GOTO - ; ------------------------------------------------------ - push namespace core -__ON_GOSUB: - pop hl - ex (sp), hl ; hl = beginning of table - call __ON_GOTO_START - ret -__ON_GOTO: - pop hl - ex (sp), hl ; hl = beginning of table -__ON_GOTO_START: - ; hl = address of jump table - ; a = index (0..255) - cp (hl) ; length of last post - ret nc ; a >= length of last position (out of range) - inc hl - pop de ; removes ret addr from the stack - ld d, 0 - add a, a - ld e, a - rl d - add hl, de - ld a, (hl) - inc hl - ld h, (hl) - ld l, a - jp (hl) - pop namespace -#line 63 "zx48k/ongoto.bas" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" #line 1 "/zxbasic/src/arch/zx48k/library-asm/print.asm" ; vim:ts=4:sw=4:et: ; PRINT command routine @@ -470,60 +443,6 @@ BRIGHT_TMP: #line 1 "/zxbasic/src/arch/zx48k/library-asm/over.asm" ; Sets OVER flag in P_FLAG permanently ; Parameter: OVER flag in bit 0 of A register -#line 1 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" -#line 4 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" - push namespace core -COPY_ATTR: - ; Just copies current permanent attribs into temporal attribs - ; and sets print mode - PROC - LOCAL INVERSE1 - LOCAL __REFRESH_TMP - INVERSE1 EQU 02Fh - ld hl, (ATTR_P) - ld (ATTR_T), hl - ld hl, FLAGS2 - call __REFRESH_TMP - ld hl, P_FLAG - call __REFRESH_TMP -__SET_ATTR_MODE: ; Another entry to set print modes. A contains (P_FLAG) - LOCAL TABLE - LOCAL CONT2 - rra ; Over bit to carry - ld a, (FLAGS2) - rla ; Over bit in bit 1, Over2 bit in bit 2 - and 3 ; Only bit 0 and 1 (OVER flag) - ld c, a - ld b, 0 - ld hl, TABLE - add hl, bc - ld a, (hl) - ld (PRINT_MODE), a - ld hl, (P_FLAG) - xor a ; NOP -> INVERSE0 - bit 2, l - jr z, CONT2 - ld a, INVERSE1 ; CPL -> INVERSE1 -CONT2: - ld (INVERSE_MODE), a - ret -TABLE: - nop ; NORMAL MODE - xor (hl) ; OVER 1 MODE - and (hl) ; OVER 2 MODE - or (hl) ; OVER 3 MODE -#line 67 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" -__REFRESH_TMP: - ld a, (hl) - and 0b10101010 - ld c, a - rra - or c - ld (hl), a - ret - ENDP - pop namespace -#line 4 "/zxbasic/src/arch/zx48k/library-asm/over.asm" push namespace core OVER: PROC @@ -765,11 +684,10 @@ INVERSE_MODE: ; 00 -> NOP -> INVERSE 0 inc hl ld (DFCC), hl ld hl, (DFCCL) ; current ATTR Pos - push hl - call __SET_ATTR - pop hl inc hl - ld (DFCCL),hl + ld (DFCCL), hl + dec hl + call __SET_ATTR exx ret ; ------------- SPECIAL CHARS (< 32) ----------------- @@ -788,7 +706,7 @@ __PRINT_0Dh: ; Called WHEN printing CHR$(13) push hl call __SCROLL_SCR pop hl -#line 210 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 209 "/zxbasic/src/arch/zx48k/library-asm/print.asm" 1: ld l, 1 __PRINT_EOL_END: @@ -905,14 +823,14 @@ __PRINT_BOLD: __PRINT_BOLD2: call BOLD_TMP jp __PRINT_RESTART -#line 354 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 353 "/zxbasic/src/arch/zx48k/library-asm/print.asm" __PRINT_ITA: ld hl, __PRINT_ITA2 jp __PRINT_SET_STATE __PRINT_ITA2: call ITALIC_TMP jp __PRINT_RESTART -#line 364 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 363 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __BOLD __BOLD: push hl @@ -930,7 +848,7 @@ __BOLD: pop hl ld de, MEM0 ret -#line 385 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 384 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __ITALIC __ITALIC: push hl @@ -955,12 +873,12 @@ __ITALIC: pop hl ld de, MEM0 ret -#line 413 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 412 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __SCROLL_SCR -#line 487 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 486 "/zxbasic/src/arch/zx48k/library-asm/print.asm" __SCROLL_SCR EQU 0DFEh ; Use ROM SCROLL +#line 488 "/zxbasic/src/arch/zx48k/library-asm/print.asm" #line 489 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -#line 490 "/zxbasic/src/arch/zx48k/library-asm/print.asm" PRINT_COMMA: call __LOAD_S_POSN ld a, e @@ -1003,9 +921,9 @@ PRINT_AT: ; Changes cursor to ROW, COL LOCAL __PRINT_TABLE LOCAL __PRINT_TAB, __PRINT_TAB1, __PRINT_TAB2 LOCAL __PRINT_ITA2 -#line 546 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 545 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __PRINT_BOLD2 -#line 552 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 551 "/zxbasic/src/arch/zx48k/library-asm/print.asm" __PRINT_TABLE: ; Jump table for 0 .. 22 codes DW __PRINT_NOP ; 0 DW __PRINT_NOP ; 1 @@ -1033,7 +951,92 @@ __PRINT_TABLE: ; Jump table for 0 .. 22 codes DW __PRINT_TAB ; 23 TAB ENDP pop namespace -#line 64 "zx48k/ongoto.bas" +#line 3 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" +#line 4 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" + push namespace core +COPY_ATTR: + ; Just copies current permanent attribs into temporal attribs + ; and sets print mode + PROC + LOCAL INVERSE1 + LOCAL __REFRESH_TMP + INVERSE1 EQU 02Fh + ld hl, (ATTR_P) + ld (ATTR_T), hl + ld hl, FLAGS2 + call __REFRESH_TMP + ld hl, P_FLAG + call __REFRESH_TMP +__SET_ATTR_MODE: ; Another entry to set print modes. A contains (P_FLAG) + LOCAL TABLE + LOCAL CONT2 + rra ; Over bit to carry + ld a, (FLAGS2) + rla ; Over bit in bit 1, Over2 bit in bit 2 + and 3 ; Only bit 0 and 1 (OVER flag) + ld c, a + ld b, 0 + ld hl, TABLE + add hl, bc + ld a, (hl) + ld (PRINT_MODE), a + ld hl, (P_FLAG) + xor a ; NOP -> INVERSE0 + bit 2, l + jr z, CONT2 + ld a, INVERSE1 ; CPL -> INVERSE1 +CONT2: + ld (INVERSE_MODE), a + ret +TABLE: + nop ; NORMAL MODE + xor (hl) ; OVER 1 MODE + and (hl) ; OVER 2 MODE + or (hl) ; OVER 3 MODE +#line 67 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" +__REFRESH_TMP: + ld a, (hl) + and 0b10101010 + ld c, a + rra + or c + ld (hl), a + ret + ENDP + pop namespace +#line 67 "zx48k/ongoto.bas" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/ongoto.asm" + ; ------------------------------------------------------ + ; Implements ON .. GOTO + ; ------------------------------------------------------ + push namespace core +__ON_GOSUB: + pop hl + ex (sp), hl ; hl = beginning of table + call __ON_GOTO_START + ret +__ON_GOTO: + pop hl + ex (sp), hl ; hl = beginning of table +__ON_GOTO_START: + ; hl = address of jump table + ; a = index (0..255) + cp (hl) ; length of last post + ret nc ; a >= length of last position (out of range) + inc hl + pop de ; removes ret addr from the stack + ld d, 0 + add a, a + ld e, a + rl d + add hl, de + ld a, (hl) + inc hl + ld h, (hl) + ld l, a + jp (hl) + pop namespace +#line 68 "zx48k/ongoto.bas" #line 1 "/zxbasic/src/arch/zx48k/library-asm/printstr.asm" #line 1 "/zxbasic/src/arch/zx48k/library-asm/free.asm" ; vim: ts=4:et:sw=4: @@ -1344,5 +1347,5 @@ __PRINT_STR: jp __PRINT_STR_LOOP ENDP pop namespace -#line 65 "zx48k/ongoto.bas" +#line 70 "zx48k/ongoto.bas" END diff --git a/tests/functional/zx48k/opt1_dim_arr_global.asm b/tests/functional/zx48k/opt1_dim_arr_global.asm index 7532d3e72..2890fe0f9 100644 --- a/tests/functional/zx48k/opt1_dim_arr_global.asm +++ b/tests/functional/zx48k/opt1_dim_arr_global.asm @@ -39,6 +39,8 @@ _a.__DATA__: .core.__MAIN_PROGRAM__: ld hl, 3 ld (_i), hl + call .core.COPY_ATTR + ld hl, (_i) push hl ld hl, _a call .core.__ARRAY @@ -192,7 +194,8 @@ TMP_ARR_PTR: DW 0 ; temporary storage for pointer to tables ENDP pop namespace -#line 25 "zx48k/opt1_dim_arr_global.bas" +#line 27 "zx48k/opt1_dim_arr_global.bas" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" #line 1 "/zxbasic/src/arch/zx48k/library-asm/print.asm" ; vim:ts=4:sw=4:et: ; PRINT command routine @@ -542,60 +545,6 @@ BRIGHT_TMP: #line 1 "/zxbasic/src/arch/zx48k/library-asm/over.asm" ; Sets OVER flag in P_FLAG permanently ; Parameter: OVER flag in bit 0 of A register -#line 1 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" -#line 4 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" - push namespace core -COPY_ATTR: - ; Just copies current permanent attribs into temporal attribs - ; and sets print mode - PROC - LOCAL INVERSE1 - LOCAL __REFRESH_TMP - INVERSE1 EQU 02Fh - ld hl, (ATTR_P) - ld (ATTR_T), hl - ld hl, FLAGS2 - call __REFRESH_TMP - ld hl, P_FLAG - call __REFRESH_TMP -__SET_ATTR_MODE: ; Another entry to set print modes. A contains (P_FLAG) - LOCAL TABLE - LOCAL CONT2 - rra ; Over bit to carry - ld a, (FLAGS2) - rla ; Over bit in bit 1, Over2 bit in bit 2 - and 3 ; Only bit 0 and 1 (OVER flag) - ld c, a - ld b, 0 - ld hl, TABLE - add hl, bc - ld a, (hl) - ld (PRINT_MODE), a - ld hl, (P_FLAG) - xor a ; NOP -> INVERSE0 - bit 2, l - jr z, CONT2 - ld a, INVERSE1 ; CPL -> INVERSE1 -CONT2: - ld (INVERSE_MODE), a - ret -TABLE: - nop ; NORMAL MODE - xor (hl) ; OVER 1 MODE - and (hl) ; OVER 2 MODE - or (hl) ; OVER 3 MODE -#line 67 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" -__REFRESH_TMP: - ld a, (hl) - and 0b10101010 - ld c, a - rra - or c - ld (hl), a - ret - ENDP - pop namespace -#line 4 "/zxbasic/src/arch/zx48k/library-asm/over.asm" push namespace core OVER: PROC @@ -837,11 +786,10 @@ INVERSE_MODE: ; 00 -> NOP -> INVERSE 0 inc hl ld (DFCC), hl ld hl, (DFCCL) ; current ATTR Pos - push hl - call __SET_ATTR - pop hl inc hl - ld (DFCCL),hl + ld (DFCCL), hl + dec hl + call __SET_ATTR exx ret ; ------------- SPECIAL CHARS (< 32) ----------------- @@ -860,7 +808,7 @@ __PRINT_0Dh: ; Called WHEN printing CHR$(13) push hl call __SCROLL_SCR pop hl -#line 210 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 209 "/zxbasic/src/arch/zx48k/library-asm/print.asm" 1: ld l, 1 __PRINT_EOL_END: @@ -977,14 +925,14 @@ __PRINT_BOLD: __PRINT_BOLD2: call BOLD_TMP jp __PRINT_RESTART -#line 354 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 353 "/zxbasic/src/arch/zx48k/library-asm/print.asm" __PRINT_ITA: ld hl, __PRINT_ITA2 jp __PRINT_SET_STATE __PRINT_ITA2: call ITALIC_TMP jp __PRINT_RESTART -#line 364 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 363 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __BOLD __BOLD: push hl @@ -1002,7 +950,7 @@ __BOLD: pop hl ld de, MEM0 ret -#line 385 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 384 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __ITALIC __ITALIC: push hl @@ -1027,12 +975,12 @@ __ITALIC: pop hl ld de, MEM0 ret -#line 413 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 412 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __SCROLL_SCR -#line 487 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 486 "/zxbasic/src/arch/zx48k/library-asm/print.asm" __SCROLL_SCR EQU 0DFEh ; Use ROM SCROLL +#line 488 "/zxbasic/src/arch/zx48k/library-asm/print.asm" #line 489 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -#line 490 "/zxbasic/src/arch/zx48k/library-asm/print.asm" PRINT_COMMA: call __LOAD_S_POSN ld a, e @@ -1075,9 +1023,9 @@ PRINT_AT: ; Changes cursor to ROW, COL LOCAL __PRINT_TABLE LOCAL __PRINT_TAB, __PRINT_TAB1, __PRINT_TAB2 LOCAL __PRINT_ITA2 -#line 546 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 545 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __PRINT_BOLD2 -#line 552 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 551 "/zxbasic/src/arch/zx48k/library-asm/print.asm" __PRINT_TABLE: ; Jump table for 0 .. 22 codes DW __PRINT_NOP ; 0 DW __PRINT_NOP ; 1 @@ -1105,7 +1053,60 @@ __PRINT_TABLE: ; Jump table for 0 .. 22 codes DW __PRINT_TAB ; 23 TAB ENDP pop namespace -#line 26 "zx48k/opt1_dim_arr_global.bas" +#line 3 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" +#line 4 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" + push namespace core +COPY_ATTR: + ; Just copies current permanent attribs into temporal attribs + ; and sets print mode + PROC + LOCAL INVERSE1 + LOCAL __REFRESH_TMP + INVERSE1 EQU 02Fh + ld hl, (ATTR_P) + ld (ATTR_T), hl + ld hl, FLAGS2 + call __REFRESH_TMP + ld hl, P_FLAG + call __REFRESH_TMP +__SET_ATTR_MODE: ; Another entry to set print modes. A contains (P_FLAG) + LOCAL TABLE + LOCAL CONT2 + rra ; Over bit to carry + ld a, (FLAGS2) + rla ; Over bit in bit 1, Over2 bit in bit 2 + and 3 ; Only bit 0 and 1 (OVER flag) + ld c, a + ld b, 0 + ld hl, TABLE + add hl, bc + ld a, (hl) + ld (PRINT_MODE), a + ld hl, (P_FLAG) + xor a ; NOP -> INVERSE0 + bit 2, l + jr z, CONT2 + ld a, INVERSE1 ; CPL -> INVERSE1 +CONT2: + ld (INVERSE_MODE), a + ret +TABLE: + nop ; NORMAL MODE + xor (hl) ; OVER 1 MODE + and (hl) ; OVER 2 MODE + or (hl) ; OVER 3 MODE +#line 67 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" +__REFRESH_TMP: + ld a, (hl) + and 0b10101010 + ld c, a + rra + or c + ld (hl), a + ret + ENDP + pop namespace +#line 28 "zx48k/opt1_dim_arr_global.bas" #line 1 "/zxbasic/src/arch/zx48k/library-asm/printu8.asm" #line 1 "/zxbasic/src/arch/zx48k/library-asm/printi8.asm" #line 1 "/zxbasic/src/arch/zx48k/library-asm/printnum.asm" @@ -1227,5 +1228,5 @@ __PRINTU_LOOP: ENDP pop namespace #line 2 "/zxbasic/src/arch/zx48k/library-asm/printu8.asm" -#line 27 "zx48k/opt1_dim_arr_global.bas" +#line 30 "zx48k/opt1_dim_arr_global.bas" END diff --git a/tests/functional/zx48k/opt1_dim_arr_global2.asm b/tests/functional/zx48k/opt1_dim_arr_global2.asm index 79e555f6e..c1a75c045 100644 --- a/tests/functional/zx48k/opt1_dim_arr_global2.asm +++ b/tests/functional/zx48k/opt1_dim_arr_global2.asm @@ -35,6 +35,7 @@ _a.__DATA__: DEFB 01h .core.ZXBASIC_USER_DATA_END: .core.__MAIN_PROGRAM__: + call .core.COPY_ATTR ld a, (_a.__DATA__ + 2) call .core.__PRINTU8 call .core.PRINT_EOL @@ -53,6 +54,7 @@ _a.__DATA__: ei ret ;; --- end of user code --- +#line 1 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" #line 1 "/zxbasic/src/arch/zx48k/library-asm/print.asm" ; vim:ts=4:sw=4:et: ; PRINT command routine @@ -402,60 +404,6 @@ BRIGHT_TMP: #line 1 "/zxbasic/src/arch/zx48k/library-asm/over.asm" ; Sets OVER flag in P_FLAG permanently ; Parameter: OVER flag in bit 0 of A register -#line 1 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" -#line 4 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" - push namespace core -COPY_ATTR: - ; Just copies current permanent attribs into temporal attribs - ; and sets print mode - PROC - LOCAL INVERSE1 - LOCAL __REFRESH_TMP - INVERSE1 EQU 02Fh - ld hl, (ATTR_P) - ld (ATTR_T), hl - ld hl, FLAGS2 - call __REFRESH_TMP - ld hl, P_FLAG - call __REFRESH_TMP -__SET_ATTR_MODE: ; Another entry to set print modes. A contains (P_FLAG) - LOCAL TABLE - LOCAL CONT2 - rra ; Over bit to carry - ld a, (FLAGS2) - rla ; Over bit in bit 1, Over2 bit in bit 2 - and 3 ; Only bit 0 and 1 (OVER flag) - ld c, a - ld b, 0 - ld hl, TABLE - add hl, bc - ld a, (hl) - ld (PRINT_MODE), a - ld hl, (P_FLAG) - xor a ; NOP -> INVERSE0 - bit 2, l - jr z, CONT2 - ld a, INVERSE1 ; CPL -> INVERSE1 -CONT2: - ld (INVERSE_MODE), a - ret -TABLE: - nop ; NORMAL MODE - xor (hl) ; OVER 1 MODE - and (hl) ; OVER 2 MODE - or (hl) ; OVER 3 MODE -#line 67 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" -__REFRESH_TMP: - ld a, (hl) - and 0b10101010 - ld c, a - rra - or c - ld (hl), a - ret - ENDP - pop namespace -#line 4 "/zxbasic/src/arch/zx48k/library-asm/over.asm" push namespace core OVER: PROC @@ -697,11 +645,10 @@ INVERSE_MODE: ; 00 -> NOP -> INVERSE 0 inc hl ld (DFCC), hl ld hl, (DFCCL) ; current ATTR Pos - push hl - call __SET_ATTR - pop hl inc hl - ld (DFCCL),hl + ld (DFCCL), hl + dec hl + call __SET_ATTR exx ret ; ------------- SPECIAL CHARS (< 32) ----------------- @@ -720,7 +667,7 @@ __PRINT_0Dh: ; Called WHEN printing CHR$(13) push hl call __SCROLL_SCR pop hl -#line 210 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 209 "/zxbasic/src/arch/zx48k/library-asm/print.asm" 1: ld l, 1 __PRINT_EOL_END: @@ -837,14 +784,14 @@ __PRINT_BOLD: __PRINT_BOLD2: call BOLD_TMP jp __PRINT_RESTART -#line 354 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 353 "/zxbasic/src/arch/zx48k/library-asm/print.asm" __PRINT_ITA: ld hl, __PRINT_ITA2 jp __PRINT_SET_STATE __PRINT_ITA2: call ITALIC_TMP jp __PRINT_RESTART -#line 364 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 363 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __BOLD __BOLD: push hl @@ -862,7 +809,7 @@ __BOLD: pop hl ld de, MEM0 ret -#line 385 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 384 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __ITALIC __ITALIC: push hl @@ -887,12 +834,12 @@ __ITALIC: pop hl ld de, MEM0 ret -#line 413 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 412 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __SCROLL_SCR -#line 487 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 486 "/zxbasic/src/arch/zx48k/library-asm/print.asm" __SCROLL_SCR EQU 0DFEh ; Use ROM SCROLL +#line 488 "/zxbasic/src/arch/zx48k/library-asm/print.asm" #line 489 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -#line 490 "/zxbasic/src/arch/zx48k/library-asm/print.asm" PRINT_COMMA: call __LOAD_S_POSN ld a, e @@ -935,9 +882,9 @@ PRINT_AT: ; Changes cursor to ROW, COL LOCAL __PRINT_TABLE LOCAL __PRINT_TAB, __PRINT_TAB1, __PRINT_TAB2 LOCAL __PRINT_ITA2 -#line 546 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 545 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __PRINT_BOLD2 -#line 552 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 551 "/zxbasic/src/arch/zx48k/library-asm/print.asm" __PRINT_TABLE: ; Jump table for 0 .. 22 codes DW __PRINT_NOP ; 0 DW __PRINT_NOP ; 1 @@ -965,7 +912,60 @@ __PRINT_TABLE: ; Jump table for 0 .. 22 codes DW __PRINT_TAB ; 23 TAB ENDP pop namespace -#line 20 "zx48k/opt1_dim_arr_global2.bas" +#line 3 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" +#line 4 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" + push namespace core +COPY_ATTR: + ; Just copies current permanent attribs into temporal attribs + ; and sets print mode + PROC + LOCAL INVERSE1 + LOCAL __REFRESH_TMP + INVERSE1 EQU 02Fh + ld hl, (ATTR_P) + ld (ATTR_T), hl + ld hl, FLAGS2 + call __REFRESH_TMP + ld hl, P_FLAG + call __REFRESH_TMP +__SET_ATTR_MODE: ; Another entry to set print modes. A contains (P_FLAG) + LOCAL TABLE + LOCAL CONT2 + rra ; Over bit to carry + ld a, (FLAGS2) + rla ; Over bit in bit 1, Over2 bit in bit 2 + and 3 ; Only bit 0 and 1 (OVER flag) + ld c, a + ld b, 0 + ld hl, TABLE + add hl, bc + ld a, (hl) + ld (PRINT_MODE), a + ld hl, (P_FLAG) + xor a ; NOP -> INVERSE0 + bit 2, l + jr z, CONT2 + ld a, INVERSE1 ; CPL -> INVERSE1 +CONT2: + ld (INVERSE_MODE), a + ret +TABLE: + nop ; NORMAL MODE + xor (hl) ; OVER 1 MODE + and (hl) ; OVER 2 MODE + or (hl) ; OVER 3 MODE +#line 67 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" +__REFRESH_TMP: + ld a, (hl) + and 0b10101010 + ld c, a + rra + or c + ld (hl), a + ret + ENDP + pop namespace +#line 21 "zx48k/opt1_dim_arr_global2.bas" #line 1 "/zxbasic/src/arch/zx48k/library-asm/printu8.asm" #line 1 "/zxbasic/src/arch/zx48k/library-asm/printi8.asm" #line 1 "/zxbasic/src/arch/zx48k/library-asm/printnum.asm" @@ -1087,5 +1087,5 @@ __PRINTU_LOOP: ENDP pop namespace #line 2 "/zxbasic/src/arch/zx48k/library-asm/printu8.asm" -#line 21 "zx48k/opt1_dim_arr_global2.bas" +#line 23 "zx48k/opt1_dim_arr_global2.bas" END diff --git a/tests/functional/zx48k/opt1_dim_arr_global3.asm b/tests/functional/zx48k/opt1_dim_arr_global3.asm index 3fcb795fc..014998b42 100644 --- a/tests/functional/zx48k/opt1_dim_arr_global3.asm +++ b/tests/functional/zx48k/opt1_dim_arr_global3.asm @@ -37,6 +37,8 @@ _a.__DATA__: .core.__MAIN_PROGRAM__: ld a, 7 ld (_a.__DATA__ + 2), a + call .core.COPY_ATTR + ld a, (_a.__DATA__ + 2) call .core.__PRINTU8 call .core.PRINT_EOL ld hl, 0 @@ -54,6 +56,7 @@ _a.__DATA__: ei ret ;; --- end of user code --- +#line 1 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" #line 1 "/zxbasic/src/arch/zx48k/library-asm/print.asm" ; vim:ts=4:sw=4:et: ; PRINT command routine @@ -403,60 +406,6 @@ BRIGHT_TMP: #line 1 "/zxbasic/src/arch/zx48k/library-asm/over.asm" ; Sets OVER flag in P_FLAG permanently ; Parameter: OVER flag in bit 0 of A register -#line 1 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" -#line 4 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" - push namespace core -COPY_ATTR: - ; Just copies current permanent attribs into temporal attribs - ; and sets print mode - PROC - LOCAL INVERSE1 - LOCAL __REFRESH_TMP - INVERSE1 EQU 02Fh - ld hl, (ATTR_P) - ld (ATTR_T), hl - ld hl, FLAGS2 - call __REFRESH_TMP - ld hl, P_FLAG - call __REFRESH_TMP -__SET_ATTR_MODE: ; Another entry to set print modes. A contains (P_FLAG) - LOCAL TABLE - LOCAL CONT2 - rra ; Over bit to carry - ld a, (FLAGS2) - rla ; Over bit in bit 1, Over2 bit in bit 2 - and 3 ; Only bit 0 and 1 (OVER flag) - ld c, a - ld b, 0 - ld hl, TABLE - add hl, bc - ld a, (hl) - ld (PRINT_MODE), a - ld hl, (P_FLAG) - xor a ; NOP -> INVERSE0 - bit 2, l - jr z, CONT2 - ld a, INVERSE1 ; CPL -> INVERSE1 -CONT2: - ld (INVERSE_MODE), a - ret -TABLE: - nop ; NORMAL MODE - xor (hl) ; OVER 1 MODE - and (hl) ; OVER 2 MODE - or (hl) ; OVER 3 MODE -#line 67 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" -__REFRESH_TMP: - ld a, (hl) - and 0b10101010 - ld c, a - rra - or c - ld (hl), a - ret - ENDP - pop namespace -#line 4 "/zxbasic/src/arch/zx48k/library-asm/over.asm" push namespace core OVER: PROC @@ -698,11 +647,10 @@ INVERSE_MODE: ; 00 -> NOP -> INVERSE 0 inc hl ld (DFCC), hl ld hl, (DFCCL) ; current ATTR Pos - push hl - call __SET_ATTR - pop hl inc hl - ld (DFCCL),hl + ld (DFCCL), hl + dec hl + call __SET_ATTR exx ret ; ------------- SPECIAL CHARS (< 32) ----------------- @@ -721,7 +669,7 @@ __PRINT_0Dh: ; Called WHEN printing CHR$(13) push hl call __SCROLL_SCR pop hl -#line 210 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 209 "/zxbasic/src/arch/zx48k/library-asm/print.asm" 1: ld l, 1 __PRINT_EOL_END: @@ -838,14 +786,14 @@ __PRINT_BOLD: __PRINT_BOLD2: call BOLD_TMP jp __PRINT_RESTART -#line 354 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 353 "/zxbasic/src/arch/zx48k/library-asm/print.asm" __PRINT_ITA: ld hl, __PRINT_ITA2 jp __PRINT_SET_STATE __PRINT_ITA2: call ITALIC_TMP jp __PRINT_RESTART -#line 364 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 363 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __BOLD __BOLD: push hl @@ -863,7 +811,7 @@ __BOLD: pop hl ld de, MEM0 ret -#line 385 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 384 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __ITALIC __ITALIC: push hl @@ -888,12 +836,12 @@ __ITALIC: pop hl ld de, MEM0 ret -#line 413 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 412 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __SCROLL_SCR -#line 487 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 486 "/zxbasic/src/arch/zx48k/library-asm/print.asm" __SCROLL_SCR EQU 0DFEh ; Use ROM SCROLL +#line 488 "/zxbasic/src/arch/zx48k/library-asm/print.asm" #line 489 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -#line 490 "/zxbasic/src/arch/zx48k/library-asm/print.asm" PRINT_COMMA: call __LOAD_S_POSN ld a, e @@ -936,9 +884,9 @@ PRINT_AT: ; Changes cursor to ROW, COL LOCAL __PRINT_TABLE LOCAL __PRINT_TAB, __PRINT_TAB1, __PRINT_TAB2 LOCAL __PRINT_ITA2 -#line 546 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 545 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __PRINT_BOLD2 -#line 552 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 551 "/zxbasic/src/arch/zx48k/library-asm/print.asm" __PRINT_TABLE: ; Jump table for 0 .. 22 codes DW __PRINT_NOP ; 0 DW __PRINT_NOP ; 1 @@ -966,7 +914,60 @@ __PRINT_TABLE: ; Jump table for 0 .. 22 codes DW __PRINT_TAB ; 23 TAB ENDP pop namespace -#line 21 "zx48k/opt1_dim_arr_global3.bas" +#line 3 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" +#line 4 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" + push namespace core +COPY_ATTR: + ; Just copies current permanent attribs into temporal attribs + ; and sets print mode + PROC + LOCAL INVERSE1 + LOCAL __REFRESH_TMP + INVERSE1 EQU 02Fh + ld hl, (ATTR_P) + ld (ATTR_T), hl + ld hl, FLAGS2 + call __REFRESH_TMP + ld hl, P_FLAG + call __REFRESH_TMP +__SET_ATTR_MODE: ; Another entry to set print modes. A contains (P_FLAG) + LOCAL TABLE + LOCAL CONT2 + rra ; Over bit to carry + ld a, (FLAGS2) + rla ; Over bit in bit 1, Over2 bit in bit 2 + and 3 ; Only bit 0 and 1 (OVER flag) + ld c, a + ld b, 0 + ld hl, TABLE + add hl, bc + ld a, (hl) + ld (PRINT_MODE), a + ld hl, (P_FLAG) + xor a ; NOP -> INVERSE0 + bit 2, l + jr z, CONT2 + ld a, INVERSE1 ; CPL -> INVERSE1 +CONT2: + ld (INVERSE_MODE), a + ret +TABLE: + nop ; NORMAL MODE + xor (hl) ; OVER 1 MODE + and (hl) ; OVER 2 MODE + or (hl) ; OVER 3 MODE +#line 67 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" +__REFRESH_TMP: + ld a, (hl) + and 0b10101010 + ld c, a + rra + or c + ld (hl), a + ret + ENDP + pop namespace +#line 23 "zx48k/opt1_dim_arr_global3.bas" #line 1 "/zxbasic/src/arch/zx48k/library-asm/printu8.asm" #line 1 "/zxbasic/src/arch/zx48k/library-asm/printi8.asm" #line 1 "/zxbasic/src/arch/zx48k/library-asm/printnum.asm" @@ -1088,5 +1089,5 @@ __PRINTU_LOOP: ENDP pop namespace #line 2 "/zxbasic/src/arch/zx48k/library-asm/printu8.asm" -#line 22 "zx48k/opt1_dim_arr_global3.bas" +#line 25 "zx48k/opt1_dim_arr_global3.bas" END diff --git a/tests/functional/zx48k/opt1_dim_arr_global4.asm b/tests/functional/zx48k/opt1_dim_arr_global4.asm index a08076634..799615625 100644 --- a/tests/functional/zx48k/opt1_dim_arr_global4.asm +++ b/tests/functional/zx48k/opt1_dim_arr_global4.asm @@ -43,6 +43,7 @@ _a.__DATA__: ld hl, _a call .core.__ARRAY ld (hl), 7 + call .core.COPY_ATTR ld hl, (_i) push hl ld hl, _a @@ -197,7 +198,8 @@ TMP_ARR_PTR: DW 0 ; temporary storage for pointer to tables ENDP pop namespace -#line 30 "zx48k/opt1_dim_arr_global4.bas" +#line 31 "zx48k/opt1_dim_arr_global4.bas" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" #line 1 "/zxbasic/src/arch/zx48k/library-asm/print.asm" ; vim:ts=4:sw=4:et: ; PRINT command routine @@ -547,60 +549,6 @@ BRIGHT_TMP: #line 1 "/zxbasic/src/arch/zx48k/library-asm/over.asm" ; Sets OVER flag in P_FLAG permanently ; Parameter: OVER flag in bit 0 of A register -#line 1 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" -#line 4 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" - push namespace core -COPY_ATTR: - ; Just copies current permanent attribs into temporal attribs - ; and sets print mode - PROC - LOCAL INVERSE1 - LOCAL __REFRESH_TMP - INVERSE1 EQU 02Fh - ld hl, (ATTR_P) - ld (ATTR_T), hl - ld hl, FLAGS2 - call __REFRESH_TMP - ld hl, P_FLAG - call __REFRESH_TMP -__SET_ATTR_MODE: ; Another entry to set print modes. A contains (P_FLAG) - LOCAL TABLE - LOCAL CONT2 - rra ; Over bit to carry - ld a, (FLAGS2) - rla ; Over bit in bit 1, Over2 bit in bit 2 - and 3 ; Only bit 0 and 1 (OVER flag) - ld c, a - ld b, 0 - ld hl, TABLE - add hl, bc - ld a, (hl) - ld (PRINT_MODE), a - ld hl, (P_FLAG) - xor a ; NOP -> INVERSE0 - bit 2, l - jr z, CONT2 - ld a, INVERSE1 ; CPL -> INVERSE1 -CONT2: - ld (INVERSE_MODE), a - ret -TABLE: - nop ; NORMAL MODE - xor (hl) ; OVER 1 MODE - and (hl) ; OVER 2 MODE - or (hl) ; OVER 3 MODE -#line 67 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" -__REFRESH_TMP: - ld a, (hl) - and 0b10101010 - ld c, a - rra - or c - ld (hl), a - ret - ENDP - pop namespace -#line 4 "/zxbasic/src/arch/zx48k/library-asm/over.asm" push namespace core OVER: PROC @@ -842,11 +790,10 @@ INVERSE_MODE: ; 00 -> NOP -> INVERSE 0 inc hl ld (DFCC), hl ld hl, (DFCCL) ; current ATTR Pos - push hl - call __SET_ATTR - pop hl inc hl - ld (DFCCL),hl + ld (DFCCL), hl + dec hl + call __SET_ATTR exx ret ; ------------- SPECIAL CHARS (< 32) ----------------- @@ -865,7 +812,7 @@ __PRINT_0Dh: ; Called WHEN printing CHR$(13) push hl call __SCROLL_SCR pop hl -#line 210 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 209 "/zxbasic/src/arch/zx48k/library-asm/print.asm" 1: ld l, 1 __PRINT_EOL_END: @@ -982,14 +929,14 @@ __PRINT_BOLD: __PRINT_BOLD2: call BOLD_TMP jp __PRINT_RESTART -#line 354 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 353 "/zxbasic/src/arch/zx48k/library-asm/print.asm" __PRINT_ITA: ld hl, __PRINT_ITA2 jp __PRINT_SET_STATE __PRINT_ITA2: call ITALIC_TMP jp __PRINT_RESTART -#line 364 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 363 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __BOLD __BOLD: push hl @@ -1007,7 +954,7 @@ __BOLD: pop hl ld de, MEM0 ret -#line 385 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 384 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __ITALIC __ITALIC: push hl @@ -1032,12 +979,12 @@ __ITALIC: pop hl ld de, MEM0 ret -#line 413 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 412 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __SCROLL_SCR -#line 487 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 486 "/zxbasic/src/arch/zx48k/library-asm/print.asm" __SCROLL_SCR EQU 0DFEh ; Use ROM SCROLL +#line 488 "/zxbasic/src/arch/zx48k/library-asm/print.asm" #line 489 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -#line 490 "/zxbasic/src/arch/zx48k/library-asm/print.asm" PRINT_COMMA: call __LOAD_S_POSN ld a, e @@ -1080,9 +1027,9 @@ PRINT_AT: ; Changes cursor to ROW, COL LOCAL __PRINT_TABLE LOCAL __PRINT_TAB, __PRINT_TAB1, __PRINT_TAB2 LOCAL __PRINT_ITA2 -#line 546 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 545 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __PRINT_BOLD2 -#line 552 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 551 "/zxbasic/src/arch/zx48k/library-asm/print.asm" __PRINT_TABLE: ; Jump table for 0 .. 22 codes DW __PRINT_NOP ; 0 DW __PRINT_NOP ; 1 @@ -1110,7 +1057,60 @@ __PRINT_TABLE: ; Jump table for 0 .. 22 codes DW __PRINT_TAB ; 23 TAB ENDP pop namespace -#line 31 "zx48k/opt1_dim_arr_global4.bas" +#line 3 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" +#line 4 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" + push namespace core +COPY_ATTR: + ; Just copies current permanent attribs into temporal attribs + ; and sets print mode + PROC + LOCAL INVERSE1 + LOCAL __REFRESH_TMP + INVERSE1 EQU 02Fh + ld hl, (ATTR_P) + ld (ATTR_T), hl + ld hl, FLAGS2 + call __REFRESH_TMP + ld hl, P_FLAG + call __REFRESH_TMP +__SET_ATTR_MODE: ; Another entry to set print modes. A contains (P_FLAG) + LOCAL TABLE + LOCAL CONT2 + rra ; Over bit to carry + ld a, (FLAGS2) + rla ; Over bit in bit 1, Over2 bit in bit 2 + and 3 ; Only bit 0 and 1 (OVER flag) + ld c, a + ld b, 0 + ld hl, TABLE + add hl, bc + ld a, (hl) + ld (PRINT_MODE), a + ld hl, (P_FLAG) + xor a ; NOP -> INVERSE0 + bit 2, l + jr z, CONT2 + ld a, INVERSE1 ; CPL -> INVERSE1 +CONT2: + ld (INVERSE_MODE), a + ret +TABLE: + nop ; NORMAL MODE + xor (hl) ; OVER 1 MODE + and (hl) ; OVER 2 MODE + or (hl) ; OVER 3 MODE +#line 67 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" +__REFRESH_TMP: + ld a, (hl) + and 0b10101010 + ld c, a + rra + or c + ld (hl), a + ret + ENDP + pop namespace +#line 32 "zx48k/opt1_dim_arr_global4.bas" #line 1 "/zxbasic/src/arch/zx48k/library-asm/printu8.asm" #line 1 "/zxbasic/src/arch/zx48k/library-asm/printi8.asm" #line 1 "/zxbasic/src/arch/zx48k/library-asm/printnum.asm" @@ -1232,5 +1232,5 @@ __PRINTU_LOOP: ENDP pop namespace #line 2 "/zxbasic/src/arch/zx48k/library-asm/printu8.asm" -#line 32 "zx48k/opt1_dim_arr_global4.bas" +#line 34 "zx48k/opt1_dim_arr_global4.bas" END diff --git a/tests/functional/zx48k/opt1_dim_arr_local2.asm b/tests/functional/zx48k/opt1_dim_arr_local2.asm index 9e0ba4a97..899791491 100644 --- a/tests/functional/zx48k/opt1_dim_arr_local2.asm +++ b/tests/functional/zx48k/opt1_dim_arr_local2.asm @@ -54,6 +54,7 @@ _test: ld de, .LABEL.__LABEL0 ld bc, 6 call .core.__ALLOC_INITIALIZED_LOCAL_ARRAY + call .core.COPY_ATTR ld l, (ix-2) ld h, (ix-1) inc hl @@ -486,166 +487,8 @@ __ALLOC_INITIALIZED_LOCAL_ARRAY: ret #line 139 "/zxbasic/src/arch/zx48k/library-asm/arrayalloc.asm" pop namespace -#line 50 "zx48k/opt1_dim_arr_local2.bas" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/free.asm" -; vim: ts=4:et:sw=4: - ; Copyleft (K) by Jose M. Rodriguez de la Rosa - ; (a.k.a. Boriel) -; http://www.boriel.com - ; - ; This ASM library is licensed under the BSD license - ; you can use it for any purpose (even for commercial - ; closed source programs). - ; - ; Please read the BSD license on the internet - ; ----- IMPLEMENTATION NOTES ------ - ; The heap is implemented as a linked list of free blocks. -; Each free block contains this info: - ; - ; +----------------+ <-- HEAP START - ; | Size (2 bytes) | - ; | 0 | <-- Size = 0 => DUMMY HEADER BLOCK - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ <-+ - ; | Size (2 bytes) | - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ | - ; | | | <-- If Size > 4, then this contains (size - 4) bytes - ; | (0 if Size = 4)| | - ; +----------------+ <-+ - ; | Size (2 bytes) | - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ | - ; | | | - ; | (0 if Size = 4)| | - ; +----------------+ | - ; | <-- This zone is in use (Already allocated) - ; +----------------+ <-+ - ; | Size (2 bytes) | - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ | - ; | | | - ; | (0 if Size = 4)| | - ; +----------------+ <-+ - ; | Next (2 bytes) |--> NULL => END OF LIST - ; | 0 = NULL | - ; +----------------+ - ; | | - ; | (0 if Size = 4)| - ; +----------------+ - ; When a block is FREED, the previous and next pointers are examined to see - ; if we can defragment the heap. If the block to be breed is just next to the - ; previous, or to the next (or both) they will be converted into a single - ; block (so defragmented). - ; MEMORY MANAGER - ; - ; This library must be initialized calling __MEM_INIT with - ; HL = BLOCK Start & DE = Length. - ; An init directive is useful for initialization routines. - ; They will be added automatically if needed. - ; --------------------------------------------------------------------- - ; MEM_FREE - ; Frees a block of memory - ; -; Parameters: - ; HL = Pointer to the block to be freed. If HL is NULL (0) nothing - ; is done - ; --------------------------------------------------------------------- - push namespace core -MEM_FREE: -__MEM_FREE: ; Frees the block pointed by HL - ; HL DE BC & AF modified - PROC - LOCAL __MEM_LOOP2 - LOCAL __MEM_LINK_PREV - LOCAL __MEM_JOIN_TEST - LOCAL __MEM_BLOCK_JOIN - ld a, h - or l - ret z ; Return if NULL pointer - dec hl - dec hl - ld b, h - ld c, l ; BC = Block pointer - ld hl, ZXBASIC_MEM_HEAP ; This label point to the heap start -__MEM_LOOP2: - inc hl - inc hl ; Next block ptr - ld e, (hl) - inc hl - ld d, (hl) ; Block next ptr - ex de, hl ; DE = &(block->next); HL = block->next - ld a, h ; HL == NULL? - or l - jp z, __MEM_LINK_PREV; if so, link with previous - or a ; Clear carry flag - sbc hl, bc ; Carry if BC > HL => This block if before - add hl, bc ; Restores HL, preserving Carry flag - jp c, __MEM_LOOP2 ; This block is before. Keep searching PASS the block - ;------ At this point current HL is PAST BC, so we must link (DE) with BC, and HL in BC->next -__MEM_LINK_PREV: ; Link (DE) with BC, and BC->next with HL - ex de, hl - push hl - dec hl - ld (hl), c - inc hl - ld (hl), b ; (DE) <- BC - ld h, b ; HL <- BC (Free block ptr) - ld l, c - inc hl ; Skip block length (2 bytes) - inc hl - ld (hl), e ; Block->next = DE - inc hl - ld (hl), d - ; --- LINKED ; HL = &(BC->next) + 2 - call __MEM_JOIN_TEST - pop hl -__MEM_JOIN_TEST: ; Checks for fragmented contiguous blocks and joins them - ; hl = Ptr to current block + 2 - ld d, (hl) - dec hl - ld e, (hl) - dec hl - ld b, (hl) ; Loads block length into BC - dec hl - ld c, (hl) ; - push hl ; Saves it for later - add hl, bc ; Adds its length. If HL == DE now, it must be joined - or a - sbc hl, de ; If Z, then HL == DE => We must join - pop hl - ret nz -__MEM_BLOCK_JOIN: ; Joins current block (pointed by HL) with next one (pointed by DE). HL->length already in BC - push hl ; Saves it for later - ex de, hl - ld e, (hl) ; DE -> block->next->length - inc hl - ld d, (hl) - inc hl - ex de, hl ; DE = &(block->next) - add hl, bc ; HL = Total Length - ld b, h - ld c, l ; BC = Total Length - ex de, hl - ld e, (hl) - inc hl - ld d, (hl) ; DE = block->next - pop hl ; Recovers Pointer to block - ld (hl), c - inc hl - ld (hl), b ; Length Saved - inc hl - ld (hl), e - inc hl - ld (hl), d ; Next saved - ret - ENDP - pop namespace #line 51 "zx48k/opt1_dim_arr_local2.bas" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" #line 1 "/zxbasic/src/arch/zx48k/library-asm/print.asm" ; vim:ts=4:sw=4:et: ; PRINT command routine @@ -960,60 +803,6 @@ BRIGHT_TMP: #line 1 "/zxbasic/src/arch/zx48k/library-asm/over.asm" ; Sets OVER flag in P_FLAG permanently ; Parameter: OVER flag in bit 0 of A register -#line 1 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" -#line 4 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" - push namespace core -COPY_ATTR: - ; Just copies current permanent attribs into temporal attribs - ; and sets print mode - PROC - LOCAL INVERSE1 - LOCAL __REFRESH_TMP - INVERSE1 EQU 02Fh - ld hl, (ATTR_P) - ld (ATTR_T), hl - ld hl, FLAGS2 - call __REFRESH_TMP - ld hl, P_FLAG - call __REFRESH_TMP -__SET_ATTR_MODE: ; Another entry to set print modes. A contains (P_FLAG) - LOCAL TABLE - LOCAL CONT2 - rra ; Over bit to carry - ld a, (FLAGS2) - rla ; Over bit in bit 1, Over2 bit in bit 2 - and 3 ; Only bit 0 and 1 (OVER flag) - ld c, a - ld b, 0 - ld hl, TABLE - add hl, bc - ld a, (hl) - ld (PRINT_MODE), a - ld hl, (P_FLAG) - xor a ; NOP -> INVERSE0 - bit 2, l - jr z, CONT2 - ld a, INVERSE1 ; CPL -> INVERSE1 -CONT2: - ld (INVERSE_MODE), a - ret -TABLE: - nop ; NORMAL MODE - xor (hl) ; OVER 1 MODE - and (hl) ; OVER 2 MODE - or (hl) ; OVER 3 MODE -#line 67 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" -__REFRESH_TMP: - ld a, (hl) - and 0b10101010 - ld c, a - rra - or c - ld (hl), a - ret - ENDP - pop namespace -#line 4 "/zxbasic/src/arch/zx48k/library-asm/over.asm" push namespace core OVER: PROC @@ -1255,11 +1044,10 @@ INVERSE_MODE: ; 00 -> NOP -> INVERSE 0 inc hl ld (DFCC), hl ld hl, (DFCCL) ; current ATTR Pos - push hl - call __SET_ATTR - pop hl inc hl - ld (DFCCL),hl + ld (DFCCL), hl + dec hl + call __SET_ATTR exx ret ; ------------- SPECIAL CHARS (< 32) ----------------- @@ -1278,7 +1066,7 @@ __PRINT_0Dh: ; Called WHEN printing CHR$(13) push hl call __SCROLL_SCR pop hl -#line 210 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 209 "/zxbasic/src/arch/zx48k/library-asm/print.asm" 1: ld l, 1 __PRINT_EOL_END: @@ -1395,14 +1183,14 @@ __PRINT_BOLD: __PRINT_BOLD2: call BOLD_TMP jp __PRINT_RESTART -#line 354 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 353 "/zxbasic/src/arch/zx48k/library-asm/print.asm" __PRINT_ITA: ld hl, __PRINT_ITA2 jp __PRINT_SET_STATE __PRINT_ITA2: call ITALIC_TMP jp __PRINT_RESTART -#line 364 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 363 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __BOLD __BOLD: push hl @@ -1420,7 +1208,7 @@ __BOLD: pop hl ld de, MEM0 ret -#line 385 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 384 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __ITALIC __ITALIC: push hl @@ -1445,12 +1233,12 @@ __ITALIC: pop hl ld de, MEM0 ret -#line 413 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 412 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __SCROLL_SCR -#line 487 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 486 "/zxbasic/src/arch/zx48k/library-asm/print.asm" __SCROLL_SCR EQU 0DFEh ; Use ROM SCROLL +#line 488 "/zxbasic/src/arch/zx48k/library-asm/print.asm" #line 489 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -#line 490 "/zxbasic/src/arch/zx48k/library-asm/print.asm" PRINT_COMMA: call __LOAD_S_POSN ld a, e @@ -1493,9 +1281,9 @@ PRINT_AT: ; Changes cursor to ROW, COL LOCAL __PRINT_TABLE LOCAL __PRINT_TAB, __PRINT_TAB1, __PRINT_TAB2 LOCAL __PRINT_ITA2 -#line 546 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 545 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __PRINT_BOLD2 -#line 552 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 551 "/zxbasic/src/arch/zx48k/library-asm/print.asm" __PRINT_TABLE: ; Jump table for 0 .. 22 codes DW __PRINT_NOP ; 0 DW __PRINT_NOP ; 1 @@ -1523,7 +1311,219 @@ __PRINT_TABLE: ; Jump table for 0 .. 22 codes DW __PRINT_TAB ; 23 TAB ENDP pop namespace +#line 3 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" +#line 4 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" + push namespace core +COPY_ATTR: + ; Just copies current permanent attribs into temporal attribs + ; and sets print mode + PROC + LOCAL INVERSE1 + LOCAL __REFRESH_TMP + INVERSE1 EQU 02Fh + ld hl, (ATTR_P) + ld (ATTR_T), hl + ld hl, FLAGS2 + call __REFRESH_TMP + ld hl, P_FLAG + call __REFRESH_TMP +__SET_ATTR_MODE: ; Another entry to set print modes. A contains (P_FLAG) + LOCAL TABLE + LOCAL CONT2 + rra ; Over bit to carry + ld a, (FLAGS2) + rla ; Over bit in bit 1, Over2 bit in bit 2 + and 3 ; Only bit 0 and 1 (OVER flag) + ld c, a + ld b, 0 + ld hl, TABLE + add hl, bc + ld a, (hl) + ld (PRINT_MODE), a + ld hl, (P_FLAG) + xor a ; NOP -> INVERSE0 + bit 2, l + jr z, CONT2 + ld a, INVERSE1 ; CPL -> INVERSE1 +CONT2: + ld (INVERSE_MODE), a + ret +TABLE: + nop ; NORMAL MODE + xor (hl) ; OVER 1 MODE + and (hl) ; OVER 2 MODE + or (hl) ; OVER 3 MODE +#line 67 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" +__REFRESH_TMP: + ld a, (hl) + and 0b10101010 + ld c, a + rra + or c + ld (hl), a + ret + ENDP + pop namespace #line 52 "zx48k/opt1_dim_arr_local2.bas" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/free.asm" +; vim: ts=4:et:sw=4: + ; Copyleft (K) by Jose M. Rodriguez de la Rosa + ; (a.k.a. Boriel) +; http://www.boriel.com + ; + ; This ASM library is licensed under the BSD license + ; you can use it for any purpose (even for commercial + ; closed source programs). + ; + ; Please read the BSD license on the internet + ; ----- IMPLEMENTATION NOTES ------ + ; The heap is implemented as a linked list of free blocks. +; Each free block contains this info: + ; + ; +----------------+ <-- HEAP START + ; | Size (2 bytes) | + ; | 0 | <-- Size = 0 => DUMMY HEADER BLOCK + ; +----------------+ + ; | Next (2 bytes) |---+ + ; +----------------+ <-+ + ; | Size (2 bytes) | + ; +----------------+ + ; | Next (2 bytes) |---+ + ; +----------------+ | + ; | | | <-- If Size > 4, then this contains (size - 4) bytes + ; | (0 if Size = 4)| | + ; +----------------+ <-+ + ; | Size (2 bytes) | + ; +----------------+ + ; | Next (2 bytes) |---+ + ; +----------------+ | + ; | | | + ; | (0 if Size = 4)| | + ; +----------------+ | + ; | <-- This zone is in use (Already allocated) + ; +----------------+ <-+ + ; | Size (2 bytes) | + ; +----------------+ + ; | Next (2 bytes) |---+ + ; +----------------+ | + ; | | | + ; | (0 if Size = 4)| | + ; +----------------+ <-+ + ; | Next (2 bytes) |--> NULL => END OF LIST + ; | 0 = NULL | + ; +----------------+ + ; | | + ; | (0 if Size = 4)| + ; +----------------+ + ; When a block is FREED, the previous and next pointers are examined to see + ; if we can defragment the heap. If the block to be breed is just next to the + ; previous, or to the next (or both) they will be converted into a single + ; block (so defragmented). + ; MEMORY MANAGER + ; + ; This library must be initialized calling __MEM_INIT with + ; HL = BLOCK Start & DE = Length. + ; An init directive is useful for initialization routines. + ; They will be added automatically if needed. + ; --------------------------------------------------------------------- + ; MEM_FREE + ; Frees a block of memory + ; +; Parameters: + ; HL = Pointer to the block to be freed. If HL is NULL (0) nothing + ; is done + ; --------------------------------------------------------------------- + push namespace core +MEM_FREE: +__MEM_FREE: ; Frees the block pointed by HL + ; HL DE BC & AF modified + PROC + LOCAL __MEM_LOOP2 + LOCAL __MEM_LINK_PREV + LOCAL __MEM_JOIN_TEST + LOCAL __MEM_BLOCK_JOIN + ld a, h + or l + ret z ; Return if NULL pointer + dec hl + dec hl + ld b, h + ld c, l ; BC = Block pointer + ld hl, ZXBASIC_MEM_HEAP ; This label point to the heap start +__MEM_LOOP2: + inc hl + inc hl ; Next block ptr + ld e, (hl) + inc hl + ld d, (hl) ; Block next ptr + ex de, hl ; DE = &(block->next); HL = block->next + ld a, h ; HL == NULL? + or l + jp z, __MEM_LINK_PREV; if so, link with previous + or a ; Clear carry flag + sbc hl, bc ; Carry if BC > HL => This block if before + add hl, bc ; Restores HL, preserving Carry flag + jp c, __MEM_LOOP2 ; This block is before. Keep searching PASS the block + ;------ At this point current HL is PAST BC, so we must link (DE) with BC, and HL in BC->next +__MEM_LINK_PREV: ; Link (DE) with BC, and BC->next with HL + ex de, hl + push hl + dec hl + ld (hl), c + inc hl + ld (hl), b ; (DE) <- BC + ld h, b ; HL <- BC (Free block ptr) + ld l, c + inc hl ; Skip block length (2 bytes) + inc hl + ld (hl), e ; Block->next = DE + inc hl + ld (hl), d + ; --- LINKED ; HL = &(BC->next) + 2 + call __MEM_JOIN_TEST + pop hl +__MEM_JOIN_TEST: ; Checks for fragmented contiguous blocks and joins them + ; hl = Ptr to current block + 2 + ld d, (hl) + dec hl + ld e, (hl) + dec hl + ld b, (hl) ; Loads block length into BC + dec hl + ld c, (hl) ; + push hl ; Saves it for later + add hl, bc ; Adds its length. If HL == DE now, it must be joined + or a + sbc hl, de ; If Z, then HL == DE => We must join + pop hl + ret nz +__MEM_BLOCK_JOIN: ; Joins current block (pointed by HL) with next one (pointed by DE). HL->length already in BC + push hl ; Saves it for later + ex de, hl + ld e, (hl) ; DE -> block->next->length + inc hl + ld d, (hl) + inc hl + ex de, hl ; DE = &(block->next) + add hl, bc ; HL = Total Length + ld b, h + ld c, l ; BC = Total Length + ex de, hl + ld e, (hl) + inc hl + ld d, (hl) ; DE = block->next + pop hl ; Recovers Pointer to block + ld (hl), c + inc hl + ld (hl), b ; Length Saved + inc hl + ld (hl), e + inc hl + ld (hl), d ; Next saved + ret + ENDP + pop namespace +#line 53 "zx48k/opt1_dim_arr_local2.bas" #line 1 "/zxbasic/src/arch/zx48k/library-asm/printu8.asm" #line 1 "/zxbasic/src/arch/zx48k/library-asm/printi8.asm" #line 1 "/zxbasic/src/arch/zx48k/library-asm/printnum.asm" @@ -1645,7 +1645,7 @@ __PRINTU_LOOP: ENDP pop namespace #line 2 "/zxbasic/src/arch/zx48k/library-asm/printu8.asm" -#line 53 "zx48k/opt1_dim_arr_local2.bas" +#line 55 "zx48k/opt1_dim_arr_local2.bas" .LABEL.__LABEL0: DEFB 00h DEFB 00h diff --git a/tests/functional/zx48k/opt2_fastcall_func.asm b/tests/functional/zx48k/opt2_fastcall_func.asm index bb20da574..218102e43 100644 --- a/tests/functional/zx48k/opt2_fastcall_func.asm +++ b/tests/functional/zx48k/opt2_fastcall_func.asm @@ -43,6 +43,7 @@ _test: push ix ld ix, 0 add ix, sp + call .core.COPY_ATTR ld a, (ix+5) call .core.__PRINTU8 call .core.PRINT_EOL @@ -83,6 +84,7 @@ _c2: _c2__leave: ret ;; --- end of user code --- +#line 1 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" #line 1 "/zxbasic/src/arch/zx48k/library-asm/print.asm" ; vim:ts=4:sw=4:et: ; PRINT command routine @@ -432,60 +434,6 @@ BRIGHT_TMP: #line 1 "/zxbasic/src/arch/zx48k/library-asm/over.asm" ; Sets OVER flag in P_FLAG permanently ; Parameter: OVER flag in bit 0 of A register -#line 1 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" -#line 4 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" - push namespace core -COPY_ATTR: - ; Just copies current permanent attribs into temporal attribs - ; and sets print mode - PROC - LOCAL INVERSE1 - LOCAL __REFRESH_TMP - INVERSE1 EQU 02Fh - ld hl, (ATTR_P) - ld (ATTR_T), hl - ld hl, FLAGS2 - call __REFRESH_TMP - ld hl, P_FLAG - call __REFRESH_TMP -__SET_ATTR_MODE: ; Another entry to set print modes. A contains (P_FLAG) - LOCAL TABLE - LOCAL CONT2 - rra ; Over bit to carry - ld a, (FLAGS2) - rla ; Over bit in bit 1, Over2 bit in bit 2 - and 3 ; Only bit 0 and 1 (OVER flag) - ld c, a - ld b, 0 - ld hl, TABLE - add hl, bc - ld a, (hl) - ld (PRINT_MODE), a - ld hl, (P_FLAG) - xor a ; NOP -> INVERSE0 - bit 2, l - jr z, CONT2 - ld a, INVERSE1 ; CPL -> INVERSE1 -CONT2: - ld (INVERSE_MODE), a - ret -TABLE: - nop ; NORMAL MODE - xor (hl) ; OVER 1 MODE - and (hl) ; OVER 2 MODE - or (hl) ; OVER 3 MODE -#line 67 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" -__REFRESH_TMP: - ld a, (hl) - and 0b10101010 - ld c, a - rra - or c - ld (hl), a - ret - ENDP - pop namespace -#line 4 "/zxbasic/src/arch/zx48k/library-asm/over.asm" push namespace core OVER: PROC @@ -727,11 +675,10 @@ INVERSE_MODE: ; 00 -> NOP -> INVERSE 0 inc hl ld (DFCC), hl ld hl, (DFCCL) ; current ATTR Pos - push hl - call __SET_ATTR - pop hl inc hl - ld (DFCCL),hl + ld (DFCCL), hl + dec hl + call __SET_ATTR exx ret ; ------------- SPECIAL CHARS (< 32) ----------------- @@ -750,7 +697,7 @@ __PRINT_0Dh: ; Called WHEN printing CHR$(13) push hl call __SCROLL_SCR pop hl -#line 210 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 209 "/zxbasic/src/arch/zx48k/library-asm/print.asm" 1: ld l, 1 __PRINT_EOL_END: @@ -867,14 +814,14 @@ __PRINT_BOLD: __PRINT_BOLD2: call BOLD_TMP jp __PRINT_RESTART -#line 354 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 353 "/zxbasic/src/arch/zx48k/library-asm/print.asm" __PRINT_ITA: ld hl, __PRINT_ITA2 jp __PRINT_SET_STATE __PRINT_ITA2: call ITALIC_TMP jp __PRINT_RESTART -#line 364 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 363 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __BOLD __BOLD: push hl @@ -892,7 +839,7 @@ __BOLD: pop hl ld de, MEM0 ret -#line 385 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 384 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __ITALIC __ITALIC: push hl @@ -917,12 +864,12 @@ __ITALIC: pop hl ld de, MEM0 ret -#line 413 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 412 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __SCROLL_SCR -#line 487 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 486 "/zxbasic/src/arch/zx48k/library-asm/print.asm" __SCROLL_SCR EQU 0DFEh ; Use ROM SCROLL +#line 488 "/zxbasic/src/arch/zx48k/library-asm/print.asm" #line 489 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -#line 490 "/zxbasic/src/arch/zx48k/library-asm/print.asm" PRINT_COMMA: call __LOAD_S_POSN ld a, e @@ -965,9 +912,9 @@ PRINT_AT: ; Changes cursor to ROW, COL LOCAL __PRINT_TABLE LOCAL __PRINT_TAB, __PRINT_TAB1, __PRINT_TAB2 LOCAL __PRINT_ITA2 -#line 546 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 545 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __PRINT_BOLD2 -#line 552 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 551 "/zxbasic/src/arch/zx48k/library-asm/print.asm" __PRINT_TABLE: ; Jump table for 0 .. 22 codes DW __PRINT_NOP ; 0 DW __PRINT_NOP ; 1 @@ -995,7 +942,60 @@ __PRINT_TABLE: ; Jump table for 0 .. 22 codes DW __PRINT_TAB ; 23 TAB ENDP pop namespace -#line 64 "zx48k/opt2_fastcall_func.bas" +#line 3 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" +#line 4 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" + push namespace core +COPY_ATTR: + ; Just copies current permanent attribs into temporal attribs + ; and sets print mode + PROC + LOCAL INVERSE1 + LOCAL __REFRESH_TMP + INVERSE1 EQU 02Fh + ld hl, (ATTR_P) + ld (ATTR_T), hl + ld hl, FLAGS2 + call __REFRESH_TMP + ld hl, P_FLAG + call __REFRESH_TMP +__SET_ATTR_MODE: ; Another entry to set print modes. A contains (P_FLAG) + LOCAL TABLE + LOCAL CONT2 + rra ; Over bit to carry + ld a, (FLAGS2) + rla ; Over bit in bit 1, Over2 bit in bit 2 + and 3 ; Only bit 0 and 1 (OVER flag) + ld c, a + ld b, 0 + ld hl, TABLE + add hl, bc + ld a, (hl) + ld (PRINT_MODE), a + ld hl, (P_FLAG) + xor a ; NOP -> INVERSE0 + bit 2, l + jr z, CONT2 + ld a, INVERSE1 ; CPL -> INVERSE1 +CONT2: + ld (INVERSE_MODE), a + ret +TABLE: + nop ; NORMAL MODE + xor (hl) ; OVER 1 MODE + and (hl) ; OVER 2 MODE + or (hl) ; OVER 3 MODE +#line 67 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" +__REFRESH_TMP: + ld a, (hl) + and 0b10101010 + ld c, a + rra + or c + ld (hl), a + ret + ENDP + pop namespace +#line 65 "zx48k/opt2_fastcall_func.bas" #line 1 "/zxbasic/src/arch/zx48k/library-asm/printu8.asm" #line 1 "/zxbasic/src/arch/zx48k/library-asm/printi8.asm" #line 1 "/zxbasic/src/arch/zx48k/library-asm/printnum.asm" @@ -1117,5 +1117,5 @@ __PRINTU_LOOP: ENDP pop namespace #line 2 "/zxbasic/src/arch/zx48k/library-asm/printu8.asm" -#line 65 "zx48k/opt2_fastcall_func.bas" +#line 67 "zx48k/opt2_fastcall_func.bas" END diff --git a/tests/functional/zx48k/opt2_func_call.asm b/tests/functional/zx48k/opt2_func_call.asm index 8fe8fa4f4..f15117b03 100644 --- a/tests/functional/zx48k/opt2_func_call.asm +++ b/tests/functional/zx48k/opt2_func_call.asm @@ -41,6 +41,7 @@ _test: push ix ld ix, 0 add ix, sp + call .core.COPY_ATTR ld a, (ix+5) call .core.__PRINTU8 call .core.PRINT_EOL @@ -61,6 +62,7 @@ _c1: _c1__leave: ret ;; --- end of user code --- +#line 1 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" #line 1 "/zxbasic/src/arch/zx48k/library-asm/print.asm" ; vim:ts=4:sw=4:et: ; PRINT command routine @@ -410,60 +412,6 @@ BRIGHT_TMP: #line 1 "/zxbasic/src/arch/zx48k/library-asm/over.asm" ; Sets OVER flag in P_FLAG permanently ; Parameter: OVER flag in bit 0 of A register -#line 1 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" -#line 4 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" - push namespace core -COPY_ATTR: - ; Just copies current permanent attribs into temporal attribs - ; and sets print mode - PROC - LOCAL INVERSE1 - LOCAL __REFRESH_TMP - INVERSE1 EQU 02Fh - ld hl, (ATTR_P) - ld (ATTR_T), hl - ld hl, FLAGS2 - call __REFRESH_TMP - ld hl, P_FLAG - call __REFRESH_TMP -__SET_ATTR_MODE: ; Another entry to set print modes. A contains (P_FLAG) - LOCAL TABLE - LOCAL CONT2 - rra ; Over bit to carry - ld a, (FLAGS2) - rla ; Over bit in bit 1, Over2 bit in bit 2 - and 3 ; Only bit 0 and 1 (OVER flag) - ld c, a - ld b, 0 - ld hl, TABLE - add hl, bc - ld a, (hl) - ld (PRINT_MODE), a - ld hl, (P_FLAG) - xor a ; NOP -> INVERSE0 - bit 2, l - jr z, CONT2 - ld a, INVERSE1 ; CPL -> INVERSE1 -CONT2: - ld (INVERSE_MODE), a - ret -TABLE: - nop ; NORMAL MODE - xor (hl) ; OVER 1 MODE - and (hl) ; OVER 2 MODE - or (hl) ; OVER 3 MODE -#line 67 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" -__REFRESH_TMP: - ld a, (hl) - and 0b10101010 - ld c, a - rra - or c - ld (hl), a - ret - ENDP - pop namespace -#line 4 "/zxbasic/src/arch/zx48k/library-asm/over.asm" push namespace core OVER: PROC @@ -705,11 +653,10 @@ INVERSE_MODE: ; 00 -> NOP -> INVERSE 0 inc hl ld (DFCC), hl ld hl, (DFCCL) ; current ATTR Pos - push hl - call __SET_ATTR - pop hl inc hl - ld (DFCCL),hl + ld (DFCCL), hl + dec hl + call __SET_ATTR exx ret ; ------------- SPECIAL CHARS (< 32) ----------------- @@ -728,7 +675,7 @@ __PRINT_0Dh: ; Called WHEN printing CHR$(13) push hl call __SCROLL_SCR pop hl -#line 210 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 209 "/zxbasic/src/arch/zx48k/library-asm/print.asm" 1: ld l, 1 __PRINT_EOL_END: @@ -845,14 +792,14 @@ __PRINT_BOLD: __PRINT_BOLD2: call BOLD_TMP jp __PRINT_RESTART -#line 354 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 353 "/zxbasic/src/arch/zx48k/library-asm/print.asm" __PRINT_ITA: ld hl, __PRINT_ITA2 jp __PRINT_SET_STATE __PRINT_ITA2: call ITALIC_TMP jp __PRINT_RESTART -#line 364 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 363 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __BOLD __BOLD: push hl @@ -870,7 +817,7 @@ __BOLD: pop hl ld de, MEM0 ret -#line 385 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 384 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __ITALIC __ITALIC: push hl @@ -895,12 +842,12 @@ __ITALIC: pop hl ld de, MEM0 ret -#line 413 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 412 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __SCROLL_SCR -#line 487 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 486 "/zxbasic/src/arch/zx48k/library-asm/print.asm" __SCROLL_SCR EQU 0DFEh ; Use ROM SCROLL +#line 488 "/zxbasic/src/arch/zx48k/library-asm/print.asm" #line 489 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -#line 490 "/zxbasic/src/arch/zx48k/library-asm/print.asm" PRINT_COMMA: call __LOAD_S_POSN ld a, e @@ -943,9 +890,9 @@ PRINT_AT: ; Changes cursor to ROW, COL LOCAL __PRINT_TABLE LOCAL __PRINT_TAB, __PRINT_TAB1, __PRINT_TAB2 LOCAL __PRINT_ITA2 -#line 546 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 545 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __PRINT_BOLD2 -#line 552 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 551 "/zxbasic/src/arch/zx48k/library-asm/print.asm" __PRINT_TABLE: ; Jump table for 0 .. 22 codes DW __PRINT_NOP ; 0 DW __PRINT_NOP ; 1 @@ -973,7 +920,60 @@ __PRINT_TABLE: ; Jump table for 0 .. 22 codes DW __PRINT_TAB ; 23 TAB ENDP pop namespace -#line 42 "zx48k/opt2_func_call.bas" +#line 3 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" +#line 4 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" + push namespace core +COPY_ATTR: + ; Just copies current permanent attribs into temporal attribs + ; and sets print mode + PROC + LOCAL INVERSE1 + LOCAL __REFRESH_TMP + INVERSE1 EQU 02Fh + ld hl, (ATTR_P) + ld (ATTR_T), hl + ld hl, FLAGS2 + call __REFRESH_TMP + ld hl, P_FLAG + call __REFRESH_TMP +__SET_ATTR_MODE: ; Another entry to set print modes. A contains (P_FLAG) + LOCAL TABLE + LOCAL CONT2 + rra ; Over bit to carry + ld a, (FLAGS2) + rla ; Over bit in bit 1, Over2 bit in bit 2 + and 3 ; Only bit 0 and 1 (OVER flag) + ld c, a + ld b, 0 + ld hl, TABLE + add hl, bc + ld a, (hl) + ld (PRINT_MODE), a + ld hl, (P_FLAG) + xor a ; NOP -> INVERSE0 + bit 2, l + jr z, CONT2 + ld a, INVERSE1 ; CPL -> INVERSE1 +CONT2: + ld (INVERSE_MODE), a + ret +TABLE: + nop ; NORMAL MODE + xor (hl) ; OVER 1 MODE + and (hl) ; OVER 2 MODE + or (hl) ; OVER 3 MODE +#line 67 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" +__REFRESH_TMP: + ld a, (hl) + and 0b10101010 + ld c, a + rra + or c + ld (hl), a + ret + ENDP + pop namespace +#line 43 "zx48k/opt2_func_call.bas" #line 1 "/zxbasic/src/arch/zx48k/library-asm/printu8.asm" #line 1 "/zxbasic/src/arch/zx48k/library-asm/printi8.asm" #line 1 "/zxbasic/src/arch/zx48k/library-asm/printnum.asm" @@ -1095,5 +1095,5 @@ __PRINTU_LOOP: ENDP pop namespace #line 2 "/zxbasic/src/arch/zx48k/library-asm/printu8.asm" -#line 43 "zx48k/opt2_func_call.bas" +#line 45 "zx48k/opt2_func_call.bas" END diff --git a/tests/functional/zx48k/opt3_data2.asm b/tests/functional/zx48k/opt3_data2.asm index 57bcb6228..3c1f00e59 100644 --- a/tests/functional/zx48k/opt3_data2.asm +++ b/tests/functional/zx48k/opt3_data2.asm @@ -61,6 +61,7 @@ _a.__DATA__: call .core.__ARRAY pop af ld (hl), a + call .core.COPY_ATTR ld a, (_i) ld l, a ld h, 0 @@ -272,54 +273,8 @@ TMP_ARR_PTR: DW 0 ; temporary storage for pointer to tables ENDP pop namespace -#line 96 "zx48k/opt3_data2.bas" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/mul8.asm" - push namespace core -__MUL8: ; Performs 8bit x 8bit multiplication - PROC - ;LOCAL __MUL8A - LOCAL __MUL8LOOP - LOCAL __MUL8B - ; 1st operand (byte) in A, 2nd operand into the stack (AF) - pop hl ; return address - ex (sp), hl ; CALLE convention -;;__MUL8_FAST: ; __FASTCALL__ entry - ;; ld e, a - ;; ld d, 0 - ;; ld l, d - ;; - ;; sla h - ;; jr nc, __MUL8A - ;; ld l, e - ;; -;;__MUL8A: - ;; - ;; ld b, 7 -;;__MUL8LOOP: - ;; add hl, hl - ;; jr nc, __MUL8B - ;; - ;; add hl, de - ;; -;;__MUL8B: - ;; djnz __MUL8LOOP - ;; - ;; ld a, l ; result = A and HL (Truncate to lower 8 bits) -__MUL8_FAST: ; __FASTCALL__ entry, a = a * h (8 bit mul) and Carry - ld b, 8 - ld l, a - xor a -__MUL8LOOP: - add a, a ; a *= 2 - sla l - jp nc, __MUL8B - add a, h -__MUL8B: - djnz __MUL8LOOP - ret ; result = HL - ENDP - pop namespace #line 97 "zx48k/opt3_data2.bas" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" #line 1 "/zxbasic/src/arch/zx48k/library-asm/print.asm" ; vim:ts=4:sw=4:et: ; PRINT command routine @@ -669,60 +624,6 @@ BRIGHT_TMP: #line 1 "/zxbasic/src/arch/zx48k/library-asm/over.asm" ; Sets OVER flag in P_FLAG permanently ; Parameter: OVER flag in bit 0 of A register -#line 1 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" -#line 4 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" - push namespace core -COPY_ATTR: - ; Just copies current permanent attribs into temporal attribs - ; and sets print mode - PROC - LOCAL INVERSE1 - LOCAL __REFRESH_TMP - INVERSE1 EQU 02Fh - ld hl, (ATTR_P) - ld (ATTR_T), hl - ld hl, FLAGS2 - call __REFRESH_TMP - ld hl, P_FLAG - call __REFRESH_TMP -__SET_ATTR_MODE: ; Another entry to set print modes. A contains (P_FLAG) - LOCAL TABLE - LOCAL CONT2 - rra ; Over bit to carry - ld a, (FLAGS2) - rla ; Over bit in bit 1, Over2 bit in bit 2 - and 3 ; Only bit 0 and 1 (OVER flag) - ld c, a - ld b, 0 - ld hl, TABLE - add hl, bc - ld a, (hl) - ld (PRINT_MODE), a - ld hl, (P_FLAG) - xor a ; NOP -> INVERSE0 - bit 2, l - jr z, CONT2 - ld a, INVERSE1 ; CPL -> INVERSE1 -CONT2: - ld (INVERSE_MODE), a - ret -TABLE: - nop ; NORMAL MODE - xor (hl) ; OVER 1 MODE - and (hl) ; OVER 2 MODE - or (hl) ; OVER 3 MODE -#line 67 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" -__REFRESH_TMP: - ld a, (hl) - and 0b10101010 - ld c, a - rra - or c - ld (hl), a - ret - ENDP - pop namespace -#line 4 "/zxbasic/src/arch/zx48k/library-asm/over.asm" push namespace core OVER: PROC @@ -964,11 +865,10 @@ INVERSE_MODE: ; 00 -> NOP -> INVERSE 0 inc hl ld (DFCC), hl ld hl, (DFCCL) ; current ATTR Pos - push hl - call __SET_ATTR - pop hl inc hl - ld (DFCCL),hl + ld (DFCCL), hl + dec hl + call __SET_ATTR exx ret ; ------------- SPECIAL CHARS (< 32) ----------------- @@ -987,7 +887,7 @@ __PRINT_0Dh: ; Called WHEN printing CHR$(13) push hl call __SCROLL_SCR pop hl -#line 210 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 209 "/zxbasic/src/arch/zx48k/library-asm/print.asm" 1: ld l, 1 __PRINT_EOL_END: @@ -1104,14 +1004,14 @@ __PRINT_BOLD: __PRINT_BOLD2: call BOLD_TMP jp __PRINT_RESTART -#line 354 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 353 "/zxbasic/src/arch/zx48k/library-asm/print.asm" __PRINT_ITA: ld hl, __PRINT_ITA2 jp __PRINT_SET_STATE __PRINT_ITA2: call ITALIC_TMP jp __PRINT_RESTART -#line 364 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 363 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __BOLD __BOLD: push hl @@ -1129,7 +1029,7 @@ __BOLD: pop hl ld de, MEM0 ret -#line 385 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 384 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __ITALIC __ITALIC: push hl @@ -1154,12 +1054,12 @@ __ITALIC: pop hl ld de, MEM0 ret -#line 413 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 412 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __SCROLL_SCR -#line 487 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 486 "/zxbasic/src/arch/zx48k/library-asm/print.asm" __SCROLL_SCR EQU 0DFEh ; Use ROM SCROLL +#line 488 "/zxbasic/src/arch/zx48k/library-asm/print.asm" #line 489 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -#line 490 "/zxbasic/src/arch/zx48k/library-asm/print.asm" PRINT_COMMA: call __LOAD_S_POSN ld a, e @@ -1202,9 +1102,9 @@ PRINT_AT: ; Changes cursor to ROW, COL LOCAL __PRINT_TABLE LOCAL __PRINT_TAB, __PRINT_TAB1, __PRINT_TAB2 LOCAL __PRINT_ITA2 -#line 546 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 545 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __PRINT_BOLD2 -#line 552 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 551 "/zxbasic/src/arch/zx48k/library-asm/print.asm" __PRINT_TABLE: ; Jump table for 0 .. 22 codes DW __PRINT_NOP ; 0 DW __PRINT_NOP ; 1 @@ -1232,7 +1132,107 @@ __PRINT_TABLE: ; Jump table for 0 .. 22 codes DW __PRINT_TAB ; 23 TAB ENDP pop namespace +#line 3 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" +#line 4 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" + push namespace core +COPY_ATTR: + ; Just copies current permanent attribs into temporal attribs + ; and sets print mode + PROC + LOCAL INVERSE1 + LOCAL __REFRESH_TMP + INVERSE1 EQU 02Fh + ld hl, (ATTR_P) + ld (ATTR_T), hl + ld hl, FLAGS2 + call __REFRESH_TMP + ld hl, P_FLAG + call __REFRESH_TMP +__SET_ATTR_MODE: ; Another entry to set print modes. A contains (P_FLAG) + LOCAL TABLE + LOCAL CONT2 + rra ; Over bit to carry + ld a, (FLAGS2) + rla ; Over bit in bit 1, Over2 bit in bit 2 + and 3 ; Only bit 0 and 1 (OVER flag) + ld c, a + ld b, 0 + ld hl, TABLE + add hl, bc + ld a, (hl) + ld (PRINT_MODE), a + ld hl, (P_FLAG) + xor a ; NOP -> INVERSE0 + bit 2, l + jr z, CONT2 + ld a, INVERSE1 ; CPL -> INVERSE1 +CONT2: + ld (INVERSE_MODE), a + ret +TABLE: + nop ; NORMAL MODE + xor (hl) ; OVER 1 MODE + and (hl) ; OVER 2 MODE + or (hl) ; OVER 3 MODE +#line 67 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" +__REFRESH_TMP: + ld a, (hl) + and 0b10101010 + ld c, a + rra + or c + ld (hl), a + ret + ENDP + pop namespace #line 98 "zx48k/opt3_data2.bas" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/mul8.asm" + push namespace core +__MUL8: ; Performs 8bit x 8bit multiplication + PROC + ;LOCAL __MUL8A + LOCAL __MUL8LOOP + LOCAL __MUL8B + ; 1st operand (byte) in A, 2nd operand into the stack (AF) + pop hl ; return address + ex (sp), hl ; CALLE convention +;;__MUL8_FAST: ; __FASTCALL__ entry + ;; ld e, a + ;; ld d, 0 + ;; ld l, d + ;; + ;; sla h + ;; jr nc, __MUL8A + ;; ld l, e + ;; +;;__MUL8A: + ;; + ;; ld b, 7 +;;__MUL8LOOP: + ;; add hl, hl + ;; jr nc, __MUL8B + ;; + ;; add hl, de + ;; +;;__MUL8B: + ;; djnz __MUL8LOOP + ;; + ;; ld a, l ; result = A and HL (Truncate to lower 8 bits) +__MUL8_FAST: ; __FASTCALL__ entry, a = a * h (8 bit mul) and Carry + ld b, 8 + ld l, a + xor a +__MUL8LOOP: + add a, a ; a *= 2 + sla l + jp nc, __MUL8B + add a, h +__MUL8B: + djnz __MUL8LOOP + ret ; result = HL + ENDP + pop namespace +#line 99 "zx48k/opt3_data2.bas" #line 1 "/zxbasic/src/arch/zx48k/library-asm/printu8.asm" #line 1 "/zxbasic/src/arch/zx48k/library-asm/printi8.asm" #line 1 "/zxbasic/src/arch/zx48k/library-asm/printnum.asm" @@ -1354,7 +1354,7 @@ __PRINTU_LOOP: ENDP pop namespace #line 2 "/zxbasic/src/arch/zx48k/library-asm/printu8.asm" -#line 99 "zx48k/opt3_data2.bas" +#line 101 "zx48k/opt3_data2.bas" #line 1 "/zxbasic/src/arch/zx48k/library-asm/read_restore.asm" ;; This implements READ & RESTORE functions ;; Reads a new element from the DATA Address code @@ -2409,5 +2409,5 @@ __DATA_ADDR: ;; Stores current DATA ptr dw .DATA.__DATA__0 ENDP pop namespace -#line 100 "zx48k/opt3_data2.bas" +#line 102 "zx48k/opt3_data2.bas" END diff --git a/tests/functional/zx48k/opt3_einar.asm b/tests/functional/zx48k/opt3_einar.asm index f29b4f13c..5faa92c9f 100644 --- a/tests/functional/zx48k/opt3_einar.asm +++ b/tests/functional/zx48k/opt3_einar.asm @@ -51,12 +51,14 @@ _x2: sub (ix-1) ccf jp nc, .LABEL.__LABEL0 + call .core.COPY_ATTR ld hl, .LABEL.__LABEL2 xor a call .core.__PRINTSTR call .core.PRINT_EOL jp _x2__leave .LABEL.__LABEL0: + call .core.COPY_ATTR ld hl, .LABEL.__LABEL3 xor a call .core.__PRINTSTR @@ -75,6 +77,7 @@ _x2__leave: DEFB 4Fh DEFB 4Bh ;; --- end of user code --- +#line 1 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" #line 1 "/zxbasic/src/arch/zx48k/library-asm/print.asm" ; vim:ts=4:sw=4:et: ; PRINT command routine @@ -424,60 +427,6 @@ BRIGHT_TMP: #line 1 "/zxbasic/src/arch/zx48k/library-asm/over.asm" ; Sets OVER flag in P_FLAG permanently ; Parameter: OVER flag in bit 0 of A register -#line 1 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" -#line 4 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" - push namespace core -COPY_ATTR: - ; Just copies current permanent attribs into temporal attribs - ; and sets print mode - PROC - LOCAL INVERSE1 - LOCAL __REFRESH_TMP - INVERSE1 EQU 02Fh - ld hl, (ATTR_P) - ld (ATTR_T), hl - ld hl, FLAGS2 - call __REFRESH_TMP - ld hl, P_FLAG - call __REFRESH_TMP -__SET_ATTR_MODE: ; Another entry to set print modes. A contains (P_FLAG) - LOCAL TABLE - LOCAL CONT2 - rra ; Over bit to carry - ld a, (FLAGS2) - rla ; Over bit in bit 1, Over2 bit in bit 2 - and 3 ; Only bit 0 and 1 (OVER flag) - ld c, a - ld b, 0 - ld hl, TABLE - add hl, bc - ld a, (hl) - ld (PRINT_MODE), a - ld hl, (P_FLAG) - xor a ; NOP -> INVERSE0 - bit 2, l - jr z, CONT2 - ld a, INVERSE1 ; CPL -> INVERSE1 -CONT2: - ld (INVERSE_MODE), a - ret -TABLE: - nop ; NORMAL MODE - xor (hl) ; OVER 1 MODE - and (hl) ; OVER 2 MODE - or (hl) ; OVER 3 MODE -#line 67 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" -__REFRESH_TMP: - ld a, (hl) - and 0b10101010 - ld c, a - rra - or c - ld (hl), a - ret - ENDP - pop namespace -#line 4 "/zxbasic/src/arch/zx48k/library-asm/over.asm" push namespace core OVER: PROC @@ -719,11 +668,10 @@ INVERSE_MODE: ; 00 -> NOP -> INVERSE 0 inc hl ld (DFCC), hl ld hl, (DFCCL) ; current ATTR Pos - push hl - call __SET_ATTR - pop hl inc hl - ld (DFCCL),hl + ld (DFCCL), hl + dec hl + call __SET_ATTR exx ret ; ------------- SPECIAL CHARS (< 32) ----------------- @@ -742,7 +690,7 @@ __PRINT_0Dh: ; Called WHEN printing CHR$(13) push hl call __SCROLL_SCR pop hl -#line 210 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 209 "/zxbasic/src/arch/zx48k/library-asm/print.asm" 1: ld l, 1 __PRINT_EOL_END: @@ -859,14 +807,14 @@ __PRINT_BOLD: __PRINT_BOLD2: call BOLD_TMP jp __PRINT_RESTART -#line 354 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 353 "/zxbasic/src/arch/zx48k/library-asm/print.asm" __PRINT_ITA: ld hl, __PRINT_ITA2 jp __PRINT_SET_STATE __PRINT_ITA2: call ITALIC_TMP jp __PRINT_RESTART -#line 364 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 363 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __BOLD __BOLD: push hl @@ -884,7 +832,7 @@ __BOLD: pop hl ld de, MEM0 ret -#line 385 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 384 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __ITALIC __ITALIC: push hl @@ -909,12 +857,12 @@ __ITALIC: pop hl ld de, MEM0 ret -#line 413 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 412 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __SCROLL_SCR -#line 487 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 486 "/zxbasic/src/arch/zx48k/library-asm/print.asm" __SCROLL_SCR EQU 0DFEh ; Use ROM SCROLL +#line 488 "/zxbasic/src/arch/zx48k/library-asm/print.asm" #line 489 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -#line 490 "/zxbasic/src/arch/zx48k/library-asm/print.asm" PRINT_COMMA: call __LOAD_S_POSN ld a, e @@ -957,9 +905,9 @@ PRINT_AT: ; Changes cursor to ROW, COL LOCAL __PRINT_TABLE LOCAL __PRINT_TAB, __PRINT_TAB1, __PRINT_TAB2 LOCAL __PRINT_ITA2 -#line 546 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 545 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __PRINT_BOLD2 -#line 552 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 551 "/zxbasic/src/arch/zx48k/library-asm/print.asm" __PRINT_TABLE: ; Jump table for 0 .. 22 codes DW __PRINT_NOP ; 0 DW __PRINT_NOP ; 1 @@ -987,7 +935,60 @@ __PRINT_TABLE: ; Jump table for 0 .. 22 codes DW __PRINT_TAB ; 23 TAB ENDP pop namespace -#line 51 "zx48k/opt3_einar.bas" +#line 3 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" +#line 4 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" + push namespace core +COPY_ATTR: + ; Just copies current permanent attribs into temporal attribs + ; and sets print mode + PROC + LOCAL INVERSE1 + LOCAL __REFRESH_TMP + INVERSE1 EQU 02Fh + ld hl, (ATTR_P) + ld (ATTR_T), hl + ld hl, FLAGS2 + call __REFRESH_TMP + ld hl, P_FLAG + call __REFRESH_TMP +__SET_ATTR_MODE: ; Another entry to set print modes. A contains (P_FLAG) + LOCAL TABLE + LOCAL CONT2 + rra ; Over bit to carry + ld a, (FLAGS2) + rla ; Over bit in bit 1, Over2 bit in bit 2 + and 3 ; Only bit 0 and 1 (OVER flag) + ld c, a + ld b, 0 + ld hl, TABLE + add hl, bc + ld a, (hl) + ld (PRINT_MODE), a + ld hl, (P_FLAG) + xor a ; NOP -> INVERSE0 + bit 2, l + jr z, CONT2 + ld a, INVERSE1 ; CPL -> INVERSE1 +CONT2: + ld (INVERSE_MODE), a + ret +TABLE: + nop ; NORMAL MODE + xor (hl) ; OVER 1 MODE + and (hl) ; OVER 2 MODE + or (hl) ; OVER 3 MODE +#line 67 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" +__REFRESH_TMP: + ld a, (hl) + and 0b10101010 + ld c, a + rra + or c + ld (hl), a + ret + ENDP + pop namespace +#line 53 "zx48k/opt3_einar.bas" #line 1 "/zxbasic/src/arch/zx48k/library-asm/printstr.asm" #line 1 "/zxbasic/src/arch/zx48k/library-asm/free.asm" ; vim: ts=4:et:sw=4: @@ -1298,5 +1299,5 @@ __PRINT_STR: jp __PRINT_STR_LOOP ENDP pop namespace -#line 52 "zx48k/opt3_einar.bas" +#line 55 "zx48k/opt3_einar.bas" END diff --git a/tests/functional/zx48k/optconst.asm b/tests/functional/zx48k/optconst.asm index 5285b46bd..3bb90b4bf 100644 --- a/tests/functional/zx48k/optconst.asm +++ b/tests/functional/zx48k/optconst.asm @@ -55,6 +55,7 @@ _a: pop ix ei ret + call .core.COPY_ATTR ld hl, (_a) ld de, (_a + 2) call .core.__PRINTU32 @@ -66,6 +67,7 @@ _a: ld c, l jp .core.__END_PROGRAM ;; --- end of user code --- +#line 1 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" #line 1 "/zxbasic/src/arch/zx48k/library-asm/print.asm" ; vim:ts=4:sw=4:et: ; PRINT command routine @@ -415,60 +417,6 @@ BRIGHT_TMP: #line 1 "/zxbasic/src/arch/zx48k/library-asm/over.asm" ; Sets OVER flag in P_FLAG permanently ; Parameter: OVER flag in bit 0 of A register -#line 1 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" -#line 4 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" - push namespace core -COPY_ATTR: - ; Just copies current permanent attribs into temporal attribs - ; and sets print mode - PROC - LOCAL INVERSE1 - LOCAL __REFRESH_TMP - INVERSE1 EQU 02Fh - ld hl, (ATTR_P) - ld (ATTR_T), hl - ld hl, FLAGS2 - call __REFRESH_TMP - ld hl, P_FLAG - call __REFRESH_TMP -__SET_ATTR_MODE: ; Another entry to set print modes. A contains (P_FLAG) - LOCAL TABLE - LOCAL CONT2 - rra ; Over bit to carry - ld a, (FLAGS2) - rla ; Over bit in bit 1, Over2 bit in bit 2 - and 3 ; Only bit 0 and 1 (OVER flag) - ld c, a - ld b, 0 - ld hl, TABLE - add hl, bc - ld a, (hl) - ld (PRINT_MODE), a - ld hl, (P_FLAG) - xor a ; NOP -> INVERSE0 - bit 2, l - jr z, CONT2 - ld a, INVERSE1 ; CPL -> INVERSE1 -CONT2: - ld (INVERSE_MODE), a - ret -TABLE: - nop ; NORMAL MODE - xor (hl) ; OVER 1 MODE - and (hl) ; OVER 2 MODE - or (hl) ; OVER 3 MODE -#line 67 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" -__REFRESH_TMP: - ld a, (hl) - and 0b10101010 - ld c, a - rra - or c - ld (hl), a - ret - ENDP - pop namespace -#line 4 "/zxbasic/src/arch/zx48k/library-asm/over.asm" push namespace core OVER: PROC @@ -710,11 +658,10 @@ INVERSE_MODE: ; 00 -> NOP -> INVERSE 0 inc hl ld (DFCC), hl ld hl, (DFCCL) ; current ATTR Pos - push hl - call __SET_ATTR - pop hl inc hl - ld (DFCCL),hl + ld (DFCCL), hl + dec hl + call __SET_ATTR exx ret ; ------------- SPECIAL CHARS (< 32) ----------------- @@ -733,7 +680,7 @@ __PRINT_0Dh: ; Called WHEN printing CHR$(13) push hl call __SCROLL_SCR pop hl -#line 210 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 209 "/zxbasic/src/arch/zx48k/library-asm/print.asm" 1: ld l, 1 __PRINT_EOL_END: @@ -850,14 +797,14 @@ __PRINT_BOLD: __PRINT_BOLD2: call BOLD_TMP jp __PRINT_RESTART -#line 354 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 353 "/zxbasic/src/arch/zx48k/library-asm/print.asm" __PRINT_ITA: ld hl, __PRINT_ITA2 jp __PRINT_SET_STATE __PRINT_ITA2: call ITALIC_TMP jp __PRINT_RESTART -#line 364 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 363 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __BOLD __BOLD: push hl @@ -875,7 +822,7 @@ __BOLD: pop hl ld de, MEM0 ret -#line 385 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 384 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __ITALIC __ITALIC: push hl @@ -900,12 +847,12 @@ __ITALIC: pop hl ld de, MEM0 ret -#line 413 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 412 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __SCROLL_SCR -#line 487 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 486 "/zxbasic/src/arch/zx48k/library-asm/print.asm" __SCROLL_SCR EQU 0DFEh ; Use ROM SCROLL +#line 488 "/zxbasic/src/arch/zx48k/library-asm/print.asm" #line 489 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -#line 490 "/zxbasic/src/arch/zx48k/library-asm/print.asm" PRINT_COMMA: call __LOAD_S_POSN ld a, e @@ -948,9 +895,9 @@ PRINT_AT: ; Changes cursor to ROW, COL LOCAL __PRINT_TABLE LOCAL __PRINT_TAB, __PRINT_TAB1, __PRINT_TAB2 LOCAL __PRINT_ITA2 -#line 546 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 545 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __PRINT_BOLD2 -#line 552 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 551 "/zxbasic/src/arch/zx48k/library-asm/print.asm" __PRINT_TABLE: ; Jump table for 0 .. 22 codes DW __PRINT_NOP ; 0 DW __PRINT_NOP ; 1 @@ -978,7 +925,60 @@ __PRINT_TABLE: ; Jump table for 0 .. 22 codes DW __PRINT_TAB ; 23 TAB ENDP pop namespace -#line 45 "zx48k/optconst.bas" +#line 3 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" +#line 4 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" + push namespace core +COPY_ATTR: + ; Just copies current permanent attribs into temporal attribs + ; and sets print mode + PROC + LOCAL INVERSE1 + LOCAL __REFRESH_TMP + INVERSE1 EQU 02Fh + ld hl, (ATTR_P) + ld (ATTR_T), hl + ld hl, FLAGS2 + call __REFRESH_TMP + ld hl, P_FLAG + call __REFRESH_TMP +__SET_ATTR_MODE: ; Another entry to set print modes. A contains (P_FLAG) + LOCAL TABLE + LOCAL CONT2 + rra ; Over bit to carry + ld a, (FLAGS2) + rla ; Over bit in bit 1, Over2 bit in bit 2 + and 3 ; Only bit 0 and 1 (OVER flag) + ld c, a + ld b, 0 + ld hl, TABLE + add hl, bc + ld a, (hl) + ld (PRINT_MODE), a + ld hl, (P_FLAG) + xor a ; NOP -> INVERSE0 + bit 2, l + jr z, CONT2 + ld a, INVERSE1 ; CPL -> INVERSE1 +CONT2: + ld (INVERSE_MODE), a + ret +TABLE: + nop ; NORMAL MODE + xor (hl) ; OVER 1 MODE + and (hl) ; OVER 2 MODE + or (hl) ; OVER 3 MODE +#line 67 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" +__REFRESH_TMP: + ld a, (hl) + and 0b10101010 + ld c, a + rra + or c + ld (hl), a + ret + ENDP + pop namespace +#line 46 "zx48k/optconst.bas" #line 1 "/zxbasic/src/arch/zx48k/library-asm/printu32.asm" #line 1 "/zxbasic/src/arch/zx48k/library-asm/printi32.asm" #line 1 "/zxbasic/src/arch/zx48k/library-asm/printnum.asm" @@ -1179,5 +1179,5 @@ __PRINTU_LOOP: ENDP pop namespace #line 2 "/zxbasic/src/arch/zx48k/library-asm/printu32.asm" -#line 46 "zx48k/optconst.bas" +#line 48 "zx48k/optconst.bas" END diff --git a/tests/functional/zx48k/param0.asm b/tests/functional/zx48k/param0.asm index b41101cc2..f9747f8b2 100644 --- a/tests/functional/zx48k/param0.asm +++ b/tests/functional/zx48k/param0.asm @@ -26,6 +26,7 @@ .core.__LABEL__.ZXBASIC_USER_DATA EQU .core.ZXBASIC_USER_DATA .core.ZXBASIC_USER_DATA_END: .core.__MAIN_PROGRAM__: + call .core.COPY_ATTR ld hl, .LABEL.__LABEL0 call .core.__LOADSTR push hl @@ -79,334 +80,42 @@ _test__leave: DEFW 0001h DEFB 41h ;; --- end of user code --- -#line 1 "/zxbasic/src/arch/zx48k/library-asm/free.asm" -; vim: ts=4:et:sw=4: - ; Copyleft (K) by Jose M. Rodriguez de la Rosa - ; (a.k.a. Boriel) -; http://www.boriel.com - ; - ; This ASM library is licensed under the BSD license - ; you can use it for any purpose (even for commercial - ; closed source programs). - ; - ; Please read the BSD license on the internet - ; ----- IMPLEMENTATION NOTES ------ - ; The heap is implemented as a linked list of free blocks. -; Each free block contains this info: - ; - ; +----------------+ <-- HEAP START - ; | Size (2 bytes) | - ; | 0 | <-- Size = 0 => DUMMY HEADER BLOCK - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ <-+ - ; | Size (2 bytes) | - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ | - ; | | | <-- If Size > 4, then this contains (size - 4) bytes - ; | (0 if Size = 4)| | - ; +----------------+ <-+ - ; | Size (2 bytes) | - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ | - ; | | | - ; | (0 if Size = 4)| | - ; +----------------+ | - ; | <-- This zone is in use (Already allocated) - ; +----------------+ <-+ - ; | Size (2 bytes) | - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ | - ; | | | - ; | (0 if Size = 4)| | - ; +----------------+ <-+ - ; | Next (2 bytes) |--> NULL => END OF LIST - ; | 0 = NULL | - ; +----------------+ - ; | | - ; | (0 if Size = 4)| - ; +----------------+ - ; When a block is FREED, the previous and next pointers are examined to see - ; if we can defragment the heap. If the block to be breed is just next to the - ; previous, or to the next (or both) they will be converted into a single - ; block (so defragmented). - ; MEMORY MANAGER - ; - ; This library must be initialized calling __MEM_INIT with - ; HL = BLOCK Start & DE = Length. - ; An init directive is useful for initialization routines. - ; They will be added automatically if needed. -#line 1 "/zxbasic/src/arch/zx48k/library-asm/heapinit.asm" -; vim: ts=4:et:sw=4: - ; Copyleft (K) by Jose M. Rodriguez de la Rosa - ; (a.k.a. Boriel) -; http://www.boriel.com - ; - ; This ASM library is licensed under the BSD license - ; you can use it for any purpose (even for commercial - ; closed source programs). - ; - ; Please read the BSD license on the internet - ; ----- IMPLEMENTATION NOTES ------ - ; The heap is implemented as a linked list of free blocks. -; Each free block contains this info: - ; - ; +----------------+ <-- HEAP START - ; | Size (2 bytes) | - ; | 0 | <-- Size = 0 => DUMMY HEADER BLOCK - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ <-+ - ; | Size (2 bytes) | - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ | - ; | | | <-- If Size > 4, then this contains (size - 4) bytes - ; | (0 if Size = 4)| | - ; +----------------+ <-+ - ; | Size (2 bytes) | - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ | - ; | | | - ; | (0 if Size = 4)| | - ; +----------------+ | - ; | <-- This zone is in use (Already allocated) - ; +----------------+ <-+ - ; | Size (2 bytes) | - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ | - ; | | | - ; | (0 if Size = 4)| | - ; +----------------+ <-+ - ; | Next (2 bytes) |--> NULL => END OF LIST - ; | 0 = NULL | - ; +----------------+ - ; | | - ; | (0 if Size = 4)| - ; +----------------+ - ; When a block is FREED, the previous and next pointers are examined to see - ; if we can defragment the heap. If the block to be breed is just next to the - ; previous, or to the next (or both) they will be converted into a single - ; block (so defragmented). - ; MEMORY MANAGER - ; - ; This library must be initialized calling __MEM_INIT with - ; HL = BLOCK Start & DE = Length. - ; An init directive is useful for initialization routines. - ; They will be added automatically if needed. - ; --------------------------------------------------------------------- - ; __MEM_INIT must be called to initalize this library with the - ; standard parameters - ; --------------------------------------------------------------------- - push namespace core -__MEM_INIT: ; Initializes the library using (RAMTOP) as start, and - ld hl, ZXBASIC_MEM_HEAP ; Change this with other address of heap start - ld de, ZXBASIC_HEAP_SIZE ; Change this with your size - ; --------------------------------------------------------------------- - ; __MEM_INIT2 initalizes this library -; Parameters: -; HL : Memory address of 1st byte of the memory heap -; DE : Length in bytes of the Memory Heap - ; --------------------------------------------------------------------- -__MEM_INIT2: - ; HL as TOP - PROC - dec de - dec de - dec de - dec de ; DE = length - 4; HL = start - ; This is done, because we require 4 bytes for the empty dummy-header block - xor a - ld (hl), a - inc hl - ld (hl), a ; First "free" block is a header: size=0, Pointer=&(Block) + 4 - inc hl - ld b, h - ld c, l - inc bc - inc bc ; BC = starts of next block - ld (hl), c - inc hl - ld (hl), b - inc hl ; Pointer to next block - ld (hl), e - inc hl - ld (hl), d - inc hl ; Block size (should be length - 4 at start); This block contains all the available memory - ld (hl), a ; NULL (0000h) ; No more blocks (a list with a single block) - inc hl - ld (hl), a - ld a, 201 - ld (__MEM_INIT), a; "Pokes" with a RET so ensure this routine is not called again - ret - ENDP - pop namespace -#line 69 "/zxbasic/src/arch/zx48k/library-asm/free.asm" - ; --------------------------------------------------------------------- - ; MEM_FREE - ; Frees a block of memory - ; -; Parameters: - ; HL = Pointer to the block to be freed. If HL is NULL (0) nothing - ; is done - ; --------------------------------------------------------------------- - push namespace core -MEM_FREE: -__MEM_FREE: ; Frees the block pointed by HL - ; HL DE BC & AF modified - PROC - LOCAL __MEM_LOOP2 - LOCAL __MEM_LINK_PREV - LOCAL __MEM_JOIN_TEST - LOCAL __MEM_BLOCK_JOIN - ld a, h - or l - ret z ; Return if NULL pointer - dec hl - dec hl - ld b, h - ld c, l ; BC = Block pointer - ld hl, ZXBASIC_MEM_HEAP ; This label point to the heap start -__MEM_LOOP2: - inc hl - inc hl ; Next block ptr - ld e, (hl) - inc hl - ld d, (hl) ; Block next ptr - ex de, hl ; DE = &(block->next); HL = block->next - ld a, h ; HL == NULL? - or l - jp z, __MEM_LINK_PREV; if so, link with previous - or a ; Clear carry flag - sbc hl, bc ; Carry if BC > HL => This block if before - add hl, bc ; Restores HL, preserving Carry flag - jp c, __MEM_LOOP2 ; This block is before. Keep searching PASS the block - ;------ At this point current HL is PAST BC, so we must link (DE) with BC, and HL in BC->next -__MEM_LINK_PREV: ; Link (DE) with BC, and BC->next with HL - ex de, hl - push hl - dec hl - ld (hl), c - inc hl - ld (hl), b ; (DE) <- BC - ld h, b ; HL <- BC (Free block ptr) - ld l, c - inc hl ; Skip block length (2 bytes) - inc hl - ld (hl), e ; Block->next = DE - inc hl - ld (hl), d - ; --- LINKED ; HL = &(BC->next) + 2 - call __MEM_JOIN_TEST - pop hl -__MEM_JOIN_TEST: ; Checks for fragmented contiguous blocks and joins them - ; hl = Ptr to current block + 2 - ld d, (hl) - dec hl - ld e, (hl) - dec hl - ld b, (hl) ; Loads block length into BC - dec hl - ld c, (hl) ; - push hl ; Saves it for later - add hl, bc ; Adds its length. If HL == DE now, it must be joined - or a - sbc hl, de ; If Z, then HL == DE => We must join - pop hl - ret nz -__MEM_BLOCK_JOIN: ; Joins current block (pointed by HL) with next one (pointed by DE). HL->length already in BC - push hl ; Saves it for later - ex de, hl - ld e, (hl) ; DE -> block->next->length - inc hl - ld d, (hl) - inc hl - ex de, hl ; DE = &(block->next) - add hl, bc ; HL = Total Length - ld b, h - ld c, l ; BC = Total Length - ex de, hl - ld e, (hl) - inc hl - ld d, (hl) ; DE = block->next - pop hl ; Recovers Pointer to block - ld (hl), c - inc hl - ld (hl), b ; Length Saved - inc hl - ld (hl), e - inc hl - ld (hl), d ; Next saved - ret - ENDP - pop namespace -#line 55 "zx48k/param0.bas" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/loadstr.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/alloc.asm" -; vim: ts=4:et:sw=4: - ; Copyleft (K) by Jose M. Rodriguez de la Rosa - ; (a.k.a. Boriel) -; http://www.boriel.com - ; - ; This ASM library is licensed under the MIT license - ; you can use it for any purpose (even for commercial - ; closed source programs). - ; - ; Please read the MIT license on the internet - ; ----- IMPLEMENTATION NOTES ------ - ; The heap is implemented as a linked list of free blocks. -; Each free block contains this info: - ; - ; +----------------+ <-- HEAP START - ; | Size (2 bytes) | - ; | 0 | <-- Size = 0 => DUMMY HEADER BLOCK - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ <-+ - ; | Size (2 bytes) | - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ | - ; | | | <-- If Size > 4, then this contains (size - 4) bytes - ; | (0 if Size = 4)| | - ; +----------------+ <-+ - ; | Size (2 bytes) | - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ | - ; | | | - ; | (0 if Size = 4)| | - ; +----------------+ | - ; | <-- This zone is in use (Already allocated) - ; +----------------+ <-+ - ; | Size (2 bytes) | - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ | - ; | | | - ; | (0 if Size = 4)| | - ; +----------------+ <-+ - ; | Next (2 bytes) |--> NULL => END OF LIST - ; | 0 = NULL | - ; +----------------+ - ; | | - ; | (0 if Size = 4)| - ; +----------------+ - ; When a block is FREED, the previous and next pointers are examined to see - ; if we can defragment the heap. If the block to be freed is just next to the - ; previous, or to the next (or both) they will be converted into a single - ; block (so defragmented). - ; MEMORY MANAGER - ; - ; This library must be initialized calling __MEM_INIT with - ; HL = BLOCK Start & DE = Length. - ; An init directive is useful for initialization routines. - ; They will be added automatically if needed. +#line 1 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +; vim:ts=4:sw=4:et: + ; PRINT command routine + ; Does not print attribute. Use PRINT_STR or PRINT_NUM for that +#line 1 "/zxbasic/src/arch/zx48k/library-asm/sposn.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/sysvars.asm" + ;; ----------------------------------------------------------------------- + ;; ZX Basic System Vars + ;; Some of them will be mapped over Sinclair ROM ones for compatibility + ;; ----------------------------------------------------------------------- + push namespace core +SCREEN_ADDR: DW 16384 ; Screen address (can be pointed to other place to use a screen buffer) +SCREEN_ATTR_ADDR: DW 22528 ; Screen attribute address (ditto.) + ; These are mapped onto ZX Spectrum ROM VARS + CHARS EQU 23606 ; Pointer to ROM/RAM Charset + TVFLAGS EQU 23612 ; TV Flags + UDG EQU 23675 ; Pointer to UDG Charset + COORDS EQU 23677 ; Last PLOT coordinates + FLAGS2 EQU 23681 ; + ECHO_E EQU 23682 ; + DFCC EQU 23684 ; Next screen addr for PRINT + DFCCL EQU 23686 ; Next screen attr for PRINT + S_POSN EQU 23688 + ATTR_P EQU 23693 ; Current Permanent ATTRS set with INK, PAPER, etc commands + ATTR_T EQU 23695 ; temporary ATTRIBUTES + P_FLAG EQU 23697 ; + MEM0 EQU 23698 ; Temporary memory buffer used by ROM chars + SCR_COLS EQU 33 ; Screen with in columns + 1 + SCR_ROWS EQU 24 ; Screen height in rows + SCR_SIZE EQU (SCR_ROWS << 8) + SCR_COLS + pop namespace +#line 2 "/zxbasic/src/arch/zx48k/library-asm/sposn.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/attr.asm" + ; Attribute routines +; vim:ts=4:et:sw: #line 1 "/zxbasic/src/arch/zx48k/library-asm/error.asm" ; Simple error control routines ; vim:ts=4:et: @@ -441,457 +150,795 @@ __STOP: ld (ERR_NR), a ret pop namespace -#line 69 "/zxbasic/src/arch/zx48k/library-asm/alloc.asm" - ; --------------------------------------------------------------------- - ; MEM_ALLOC - ; Allocates a block of memory in the heap. - ; - ; Parameters - ; BC = Length of requested memory block - ; -; Returns: - ; HL = Pointer to the allocated block in memory. Returns 0 (NULL) - ; if the block could not be allocated (out of memory) - ; --------------------------------------------------------------------- +#line 6 "/zxbasic/src/arch/zx48k/library-asm/attr.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/in_screen.asm" push namespace core -MEM_ALLOC: -__MEM_ALLOC: ; Returns the 1st free block found of the given length (in BC) +__IN_SCREEN: + ; Returns NO carry if current coords (D, E) + ; are OUT of the screen limits PROC - LOCAL __MEM_LOOP - LOCAL __MEM_DONE - LOCAL __MEM_SUBTRACT - LOCAL __MEM_START - LOCAL TEMP, TEMP0 - TEMP EQU TEMP0 + 1 - ld hl, 0 - ld (TEMP), hl -__MEM_START: - ld hl, ZXBASIC_MEM_HEAP ; This label point to the heap start - inc bc - inc bc ; BC = BC + 2 ; block size needs 2 extra bytes for hidden pointer -__MEM_LOOP: ; Loads lengh at (HL, HL+). If Lenght >= BC, jump to __MEM_DONE - ld a, h ; HL = NULL (No memory available?) - or l -#line 113 "/zxbasic/src/arch/zx48k/library-asm/alloc.asm" - ret z ; NULL -#line 115 "/zxbasic/src/arch/zx48k/library-asm/alloc.asm" - ; HL = Pointer to Free block - ld e, (hl) - inc hl - ld d, (hl) - inc hl ; DE = Block Length - push hl ; HL = *pointer to -> next block - ex de, hl - or a ; CF = 0 - sbc hl, bc ; FREE >= BC (Length) (HL = BlockLength - Length) - jp nc, __MEM_DONE - pop hl - ld (TEMP), hl + LOCAL __IN_SCREEN_ERR + ld hl, SCR_SIZE + ld a, e + cp l + jr nc, __IN_SCREEN_ERR ; Do nothing and return if out of range + ld a, d + cp h + ret c ; Return if carry (OK) +__IN_SCREEN_ERR: +__OUT_OF_SCREEN_ERR: + ; Jumps here if out of screen + ld a, ERROR_OutOfScreen + jp __STOP ; Saves error code and exits + ENDP + pop namespace +#line 7 "/zxbasic/src/arch/zx48k/library-asm/attr.asm" + push namespace core +__ATTR_ADDR: + ; calc start address in DE (as (32 * d) + e) + ; Contributed by Santiago Romero at http://www.speccy.org + ld h, 0 ; 7 T-States + ld a, d ; 4 T-States + ld d, h + add a, a ; a * 2 ; 4 T-States + add a, a ; a * 4 ; 4 T-States + ld l, a ; HL = A * 4 ; 4 T-States + add hl, hl ; HL = A * 8 ; 15 T-States + add hl, hl ; HL = A * 16 ; 15 T-States + add hl, hl ; HL = A * 32 ; 15 T-States + add hl, de + ld de, (SCREEN_ATTR_ADDR) ; Adds the screen address + add hl, de + ; Return current screen address in HL + ret + ; Sets the attribute at a given screen coordinate (D, E). + ; The attribute is taken from the ATTR_T memory variable + ; Used by PRINT routines +SET_ATTR: + ; Checks for valid coords + call __IN_SCREEN + ret nc + call __ATTR_ADDR +__SET_ATTR: + ; Internal __FASTCALL__ Entry used by printing routines + ; HL contains the address of the ATTR cell to set + PROC +__SET_ATTR2: ; Sets attr from ATTR_T to (HL) which points to the scr address + ld de, (ATTR_T) ; E = ATTR_T, D = MASK_T + ld a, d + and (hl) + ld c, a ; C = current screen color, masked + ld a, d + cpl ; Negate mask + and e ; Mask current attributes + or c ; Mix them + ld (hl), a ; Store result in screen + ret + ENDP + pop namespace +#line 3 "/zxbasic/src/arch/zx48k/library-asm/sposn.asm" + ; Printing positioning library. + push namespace core + ; Loads into DE current ROW, COL print position from S_POSN mem var. +__LOAD_S_POSN: + PROC + ld de, (S_POSN) + ld hl, SCR_SIZE + or a + sbc hl, de ex de, hl + ret + ENDP + ; Saves ROW, COL from DE into S_POSN mem var. +__SAVE_S_POSN: + PROC + ld hl, SCR_SIZE + or a + sbc hl, de + ld (S_POSN), hl ; saves it again +__SET_SCR_PTR: ;; Fast + push de + call __ATTR_ADDR + ld (DFCCL), hl + pop de + ld a, d + ld c, a ; Saves it for later + and 0F8h ; Masks 3 lower bit ; zy + ld d, a + ld a, c ; Recovers it + and 07h ; MOD 7 ; y1 + rrca + rrca + rrca + or e + ld e, a + ld hl, (SCREEN_ADDR) + add hl, de ; HL = Screen address + DE + ld (DFCC), hl + ret + ENDP + pop namespace +#line 6 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/table_jump.asm" + push namespace core +JUMP_HL_PLUS_2A: ; Does JP (HL + A*2) Modifies DE. Modifies A + add a, a +JUMP_HL_PLUS_A: ; Does JP (HL + A) Modifies DE + ld e, a + ld d, 0 +JUMP_HL_PLUS_DE: ; Does JP (HL + DE) + add hl, de ld e, (hl) inc hl ld d, (hl) ex de, hl - jp __MEM_LOOP -__MEM_DONE: ; A free block has been found. - ; Check if at least 4 bytes remains free (HL >= 4) - push hl - exx ; exx to preserve bc - pop hl - ld bc, 4 +CALL_HL: + jp (hl) + pop namespace +#line 8 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/ink.asm" + ; Sets ink color in ATTR_P permanently +; Parameter: Paper color in A register + push namespace core +INK: + PROC + LOCAL __SET_INK + LOCAL __SET_INK2 + ld de, ATTR_P +__SET_INK: + cp 8 + jr nz, __SET_INK2 + inc de ; Points DE to MASK_T or MASK_P + ld a, (de) + or 7 ; Set bits 0,1,2 to enable transparency + ld (de), a + ret +__SET_INK2: + ; Another entry. This will set the ink color at location pointer by DE + and 7 ; # Gets color mod 8 + ld b, a ; Saves the color + ld a, (de) + and 0F8h ; Clears previous value + or b + ld (de), a + inc de ; Points DE to MASK_T or MASK_P + ld a, (de) + and 0F8h ; Reset bits 0,1,2 sign to disable transparency + ld (de), a ; Store new attr + ret + ; Sets the INK color passed in A register in the ATTR_T variable +INK_TMP: + ld de, ATTR_T + jp __SET_INK + ENDP + pop namespace +#line 9 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/paper.asm" + ; Sets paper color in ATTR_P permanently +; Parameter: Paper color in A register + push namespace core +PAPER: + PROC + LOCAL __SET_PAPER + LOCAL __SET_PAPER2 + ld de, ATTR_P +__SET_PAPER: + cp 8 + jr nz, __SET_PAPER2 + inc de + ld a, (de) + or 038h + ld (de), a + ret + ; Another entry. This will set the paper color at location pointer by DE +__SET_PAPER2: + and 7 ; # Remove + rlca + rlca + rlca ; a *= 8 + ld b, a ; Saves the color + ld a, (de) + and 0C7h ; Clears previous value + or b + ld (de), a + inc de ; Points to MASK_T or MASK_P accordingly + ld a, (de) + and 0C7h ; Resets bits 3,4,5 + ld (de), a + ret + ; Sets the PAPER color passed in A register in the ATTR_T variable +PAPER_TMP: + ld de, ATTR_T + jp __SET_PAPER + ENDP + pop namespace +#line 10 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/flash.asm" + ; Sets flash flag in ATTR_P permanently +; Parameter: Paper color in A register + push namespace core +FLASH: + ld hl, ATTR_P + PROC + LOCAL IS_TR + LOCAL IS_ZERO +__SET_FLASH: + ; Another entry. This will set the flash flag at location pointer by DE + cp 8 + jr z, IS_TR + ; # Convert to 0/1 or a - sbc hl, bc - exx - jp nc, __MEM_SUBTRACT - ; At this point... - ; less than 4 bytes remains free. So we return this block entirely - ; We must link the previous block with the next to this one - ; (DE) => Pointer to next block - ; (TEMP) => &(previous->next) - pop hl ; Discard current block pointer - push de - ex de, hl ; DE = Previous block pointer; (HL) = Next block pointer + jr z, IS_ZERO + ld a, 0x80 +IS_ZERO: + ld b, a ; Saves the color ld a, (hl) + and 07Fh ; Clears previous value + or b + ld (hl), a inc hl - ld h, (hl) - ld l, a ; HL = (HL) - ex de, hl ; HL = Previous block pointer; DE = Next block pointer -TEMP0: - ld hl, 0 ; Pre-previous block pointer - ld (hl), e - inc hl - ld (hl), d ; LINKED - pop hl ; Returning block. + res 7, (hl) ;Reset bit 7 to disable transparency ret -__MEM_SUBTRACT: - ; At this point we have to store HL value (Length - BC) into (DE - 2) - ex de, hl - dec hl - ld (hl), d - dec hl - ld (hl), e ; Store new block length - add hl, de ; New length + DE => free-block start - pop de ; Remove previous HL off the stack - ld (hl), c ; Store length on its 1st word - inc hl - ld (hl), b - inc hl ; Return hl +IS_TR: ; transparent + inc hl ; Points DE to MASK_T or MASK_P + set 7, (hl) ;Set bit 7 to enable transparency ret + ; Sets the FLASH flag passed in A register in the ATTR_T variable +FLASH_TMP: + ld hl, ATTR_T + jr __SET_FLASH ENDP pop namespace -#line 2 "/zxbasic/src/arch/zx48k/library-asm/loadstr.asm" - ; Loads a string (ptr) from HL - ; and duplicates it on dynamic memory again - ; Finally, it returns result pointer in HL +#line 11 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/bright.asm" + ; Sets bright flag in ATTR_P permanently +; Parameter: Paper color in A register push namespace core -__ILOADSTR: ; This is the indirect pointer entry HL = (HL) - ld a, h - or l - ret z +BRIGHT: + ld hl, ATTR_P + PROC + LOCAL IS_TR + LOCAL IS_ZERO +__SET_BRIGHT: + ; Another entry. This will set the bright flag at location pointer by DE + cp 8 + jr z, IS_TR + ; # Convert to 0/1 + or a + jr z, IS_ZERO + ld a, 0x40 +IS_ZERO: + ld b, a ; Saves the color ld a, (hl) + and 0BFh ; Clears previous value + or b + ld (hl), a inc hl - ld h, (hl) - ld l, a -__LOADSTR: ; __FASTCALL__ entry - ld a, h - or l - ret z ; Return if NULL - ld c, (hl) - inc hl - ld b, (hl) - dec hl ; BC = LEN(a$) - inc bc - inc bc ; BC = LEN(a$) + 2 (two bytes for length) - push hl - push bc - call __MEM_ALLOC - pop bc ; Recover length - pop de ; Recover origin - ld a, h - or l - ret z ; Return if NULL (No memory) - ex de, hl ; ldir takes HL as source, DE as destiny, so SWAP HL,DE - push de ; Saves destiny start - ldir ; Copies string (length number included) - pop hl ; Recovers destiny in hl as result + res 6, (hl) ;Reset bit 6 to disable transparency + ret +IS_TR: ; transparent + inc hl ; Points DE to MASK_T or MASK_P + set 6, (hl) ;Set bit 6 to enable transparency ret + ; Sets the BRIGHT flag passed in A register in the ATTR_T variable +BRIGHT_TMP: + ld hl, ATTR_T + jr __SET_BRIGHT + ENDP pop namespace -#line 56 "zx48k/param0.bas" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -; vim:ts=4:sw=4:et: - ; PRINT command routine - ; Does not print attribute. Use PRINT_STR or PRINT_NUM for that -#line 1 "/zxbasic/src/arch/zx48k/library-asm/sposn.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/sysvars.asm" - ;; ----------------------------------------------------------------------- - ;; ZX Basic System Vars - ;; Some of them will be mapped over Sinclair ROM ones for compatibility - ;; ----------------------------------------------------------------------- - push namespace core -SCREEN_ADDR: DW 16384 ; Screen address (can be pointed to other place to use a screen buffer) -SCREEN_ATTR_ADDR: DW 22528 ; Screen attribute address (ditto.) - ; These are mapped onto ZX Spectrum ROM VARS - CHARS EQU 23606 ; Pointer to ROM/RAM Charset - TVFLAGS EQU 23612 ; TV Flags - UDG EQU 23675 ; Pointer to UDG Charset - COORDS EQU 23677 ; Last PLOT coordinates - FLAGS2 EQU 23681 ; - ECHO_E EQU 23682 ; - DFCC EQU 23684 ; Next screen addr for PRINT - DFCCL EQU 23686 ; Next screen attr for PRINT - S_POSN EQU 23688 - ATTR_P EQU 23693 ; Current Permanent ATTRS set with INK, PAPER, etc commands - ATTR_T EQU 23695 ; temporary ATTRIBUTES - P_FLAG EQU 23697 ; - MEM0 EQU 23698 ; Temporary memory buffer used by ROM chars - SCR_COLS EQU 33 ; Screen with in columns + 1 - SCR_ROWS EQU 24 ; Screen height in rows - SCR_SIZE EQU (SCR_ROWS << 8) + SCR_COLS - pop namespace -#line 2 "/zxbasic/src/arch/zx48k/library-asm/sposn.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/attr.asm" - ; Attribute routines -; vim:ts=4:et:sw: -#line 1 "/zxbasic/src/arch/zx48k/library-asm/in_screen.asm" +#line 12 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/over.asm" + ; Sets OVER flag in P_FLAG permanently +; Parameter: OVER flag in bit 0 of A register push namespace core -__IN_SCREEN: - ; Returns NO carry if current coords (D, E) - ; are OUT of the screen limits +OVER: PROC - LOCAL __IN_SCREEN_ERR - ld hl, SCR_SIZE - ld a, e - cp l - jr nc, __IN_SCREEN_ERR ; Do nothing and return if out of range - ld a, d - cp h - ret c ; Return if carry (OK) -__IN_SCREEN_ERR: -__OUT_OF_SCREEN_ERR: - ; Jumps here if out of screen - ld a, ERROR_OutOfScreen - jp __STOP ; Saves error code and exits + ld c, a ; saves it for later + and 2 + ld hl, FLAGS2 + res 1, (HL) + or (hl) + ld (hl), a + ld a, c ; Recovers previous value + and 1 ; # Convert to 0/1 + add a, a; # Shift left 1 bit for permanent + ld hl, P_FLAG + res 1, (hl) + or (hl) + ld (hl), a + ret + ; Sets OVER flag in P_FLAG temporarily +OVER_TMP: + ld c, a ; saves it for later + and 2 ; gets bit 1; clears carry + rra + ld hl, FLAGS2 + res 0, (hl) + or (hl) + ld (hl), a + ld a, c ; Recovers previous value + and 1 + ld hl, P_FLAG + res 0, (hl) + or (hl) + ld (hl), a + jp __SET_ATTR_MODE + ENDP + pop namespace +#line 13 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/inverse.asm" + ; Sets INVERSE flag in P_FLAG permanently +; Parameter: INVERSE flag in bit 0 of A register + push namespace core +INVERSE: + PROC + and 1 ; # Convert to 0/1 + add a, a; # Shift left 3 bits for permanent + add a, a + add a, a + ld hl, P_FLAG + res 3, (hl) + or (hl) + ld (hl), a + ret + ; Sets INVERSE flag in P_FLAG temporarily +INVERSE_TMP: + and 1 + add a, a + add a, a; # Shift left 2 bits for temporary + ld hl, P_FLAG + res 2, (hl) + or (hl) + ld (hl), a + jp __SET_ATTR_MODE + ENDP + pop namespace +#line 14 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/bold.asm" + ; Sets BOLD flag in P_FLAG permanently +; Parameter: BOLD flag in bit 0 of A register + push namespace core +BOLD: + PROC + and 1 + rlca + rlca + rlca + ld hl, FLAGS2 + res 3, (HL) + or (hl) + ld (hl), a + ret + ; Sets BOLD flag in P_FLAG temporarily +BOLD_TMP: + and 1 + rlca + rlca + ld hl, FLAGS2 + res 2, (hl) + or (hl) + ld (hl), a + ret ENDP pop namespace -#line 7 "/zxbasic/src/arch/zx48k/library-asm/attr.asm" +#line 15 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/italic.asm" + ; Sets ITALIC flag in P_FLAG permanently +; Parameter: ITALIC flag in bit 0 of A register push namespace core -__ATTR_ADDR: - ; calc start address in DE (as (32 * d) + e) - ; Contributed by Santiago Romero at http://www.speccy.org - ld h, 0 ; 7 T-States - ld a, d ; 4 T-States - ld d, h - add a, a ; a * 2 ; 4 T-States - add a, a ; a * 4 ; 4 T-States - ld l, a ; HL = A * 4 ; 4 T-States - add hl, hl ; HL = A * 8 ; 15 T-States - add hl, hl ; HL = A * 16 ; 15 T-States - add hl, hl ; HL = A * 32 ; 15 T-States - add hl, de - ld de, (SCREEN_ATTR_ADDR) ; Adds the screen address - add hl, de - ; Return current screen address in HL - ret - ; Sets the attribute at a given screen coordinate (D, E). - ; The attribute is taken from the ATTR_T memory variable - ; Used by PRINT routines -SET_ATTR: - ; Checks for valid coords - call __IN_SCREEN - ret nc - call __ATTR_ADDR -__SET_ATTR: - ; Internal __FASTCALL__ Entry used by printing routines - ; HL contains the address of the ATTR cell to set +ITALIC: PROC -__SET_ATTR2: ; Sets attr from ATTR_T to (HL) which points to the scr address - ld de, (ATTR_T) ; E = ATTR_T, D = MASK_T - ld a, d - and (hl) - ld c, a ; C = current screen color, masked - ld a, d - cpl ; Negate mask - and e ; Mask current attributes - or c ; Mix them - ld (hl), a ; Store result in screen + and 1 + rrca + rrca + rrca + ld hl, FLAGS2 + res 5, (HL) + or (hl) + ld (hl), a + ret + ; Sets ITALIC flag in P_FLAG temporarily +ITALIC_TMP: + and 1 + rrca + rrca + rrca + rrca + ld hl, FLAGS2 + res 4, (hl) + or (hl) + ld (hl), a ret ENDP pop namespace -#line 3 "/zxbasic/src/arch/zx48k/library-asm/sposn.asm" - ; Printing positioning library. +#line 16 "/zxbasic/src/arch/zx48k/library-asm/print.asm" + ; Putting a comment starting with @INIT
+ ; will make the compiler to add a CALL to
+ ; It is useful for initialization routines. push namespace core - ; Loads into DE current ROW, COL print position from S_POSN mem var. -__LOAD_S_POSN: +__PRINT_INIT: ; To be called before program starts (initializes library) PROC - ld de, (S_POSN) + ld hl, __PRINT_START + ld (PRINT_JUMP_STATE), hl + ;; Clears ATTR2 flags (OVER 2, etc) + xor a + ld (FLAGS2), a + LOCAL SET_SCR_ADDR + call __LOAD_S_POSN + jp __SET_SCR_PTR + ;; Receives HL = future value of S_POSN + ;; Stores it at (S_POSN) and refresh screen pointers (ATTR, SCR) +SET_SCR_ADDR: + ld (S_POSN), hl + ex de, hl ld hl, SCR_SIZE or a sbc hl, de ex de, hl + dec e + jp __SET_SCR_PTR +__PRINTCHAR: ; Print character store in accumulator (A register) + ; Modifies H'L', B'C', A'F', D'E', A + LOCAL PO_GR_1 + LOCAL __PRCHAR + LOCAL __PRINT_JUMP + LOCAL __SRCADDR + LOCAL __PRINT_UDG + LOCAL __PRGRAPH + LOCAL __PRINT_START + PRINT_JUMP_STATE EQU __PRINT_JUMP + 2 +__PRINT_JUMP: + exx ; Switch to alternative registers + jp __PRINT_START ; Where to jump. If we print 22 (AT), next two calls jumps to AT1 and AT2 respectively +__PRINT_START: +__PRINT_CHR: + cp ' ' + jr c, __PRINT_SPECIAL ; Characters below ' ' are special ones + ex af, af' ; Saves a value (char to print) for later + ld hl, (S_POSN) + dec l + jr nz, 1f + ld l, SCR_COLS - 1 + dec h + jr nz, 2f + inc h + push hl + call __SCROLL_SCR + pop hl +#line 92 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +2: + call SET_SCR_ADDR + jr 4f +1: + ld (S_POSN), hl +4: + ex af, af' + cp 80h ; Is it a "normal" (printable) char + jr c, __SRCADDR + cp 90h ; Is it an UDG? + jr nc, __PRINT_UDG + ; Print an 8 bit pattern (80h to 8Fh) + ld b, a + call PO_GR_1 ; This ROM routine will generate the bit pattern at MEM0 + ld hl, MEM0 + jp __PRGRAPH + PO_GR_1 EQU 0B38h +__PRINT_UDG: + sub 90h ; Sub ASC code + ld bc, (UDG) + jr __PRGRAPH0 + __SOURCEADDR EQU (__SRCADDR + 1) ; Address of the pointer to chars source +__SRCADDR: + ld bc, (CHARS) +__PRGRAPH0: + add a, a ; A = a * 2 (since a < 80h) ; Thanks to Metalbrain at http://foro.speccy.org + ld l, a + ld h, 0 ; HL = a * 2 (accumulator) + add hl, hl + add hl, hl ; HL = a * 8 + add hl, bc ; HL = CHARS address +__PRGRAPH: + ex de, hl ; HL = Write Address, DE = CHARS address + bit 2, (iy + $47) + call nz, __BOLD +#line 139 "/zxbasic/src/arch/zx48k/library-asm/print.asm" + bit 4, (iy + $47) + call nz, __ITALIC +#line 144 "/zxbasic/src/arch/zx48k/library-asm/print.asm" + ld hl, (DFCC) + push hl + ld b, 8 ; 8 bytes per char +__PRCHAR: + ld a, (de) ; DE *must* be source, and HL destiny +PRINT_MODE: ; Which operation is used to write on the screen + ; Set it with: + ; LD A, + ; LD (PRINT_MODE), A + ; + ; Available operations: + ; NORMAL : 0h --> NOP ; OVER 0 + ; XOR : AEh --> XOR (HL) ; OVER 1 + ; OR : B6h --> OR (HL) ; PUTSPRITE + ; AND : A6h --> AND (HL) ; PUTMASK + nop ; Set to one of the values above +INVERSE_MODE: ; 00 -> NOP -> INVERSE 0 + nop ; 2F -> CPL -> INVERSE 1 + ld (hl), a + inc de + inc h ; Next line + djnz __PRCHAR + pop hl + inc hl + ld (DFCC), hl + ld hl, (DFCCL) ; current ATTR Pos + inc hl + ld (DFCCL), hl + dec hl + call __SET_ATTR + exx ret - ENDP - ; Saves ROW, COL from DE into S_POSN mem var. -__SAVE_S_POSN: - PROC - ld hl, SCR_SIZE - or a - sbc hl, de - ld (S_POSN), hl ; saves it again -__SET_SCR_PTR: ;; Fast + ; ------------- SPECIAL CHARS (< 32) ----------------- +__PRINT_SPECIAL: ; Jumps here if it is a special char + ld hl, __PRINT_TABLE + jp JUMP_HL_PLUS_2A +PRINT_EOL: ; Called WHENEVER there is no ";" at end of PRINT sentence + exx +__PRINT_0Dh: ; Called WHEN printing CHR$(13) + ld hl, (S_POSN) + dec l + jr nz, 1f + dec h + jr nz, 1f + inc h + push hl + call __SCROLL_SCR + pop hl +#line 209 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +1: + ld l, 1 +__PRINT_EOL_END: + call SET_SCR_ADDR + exx + ret +__PRINT_COM: + exx + push hl push de - call __ATTR_ADDR - ld (DFCCL), hl + push bc + call PRINT_COMMA + pop bc pop de - ld a, d - ld c, a ; Saves it for later - and 0F8h ; Masks 3 lower bit ; zy - ld d, a - ld a, c ; Recovers it - and 07h ; MOD 7 ; y1 - rrca - rrca - rrca - or e - ld e, a - ld hl, (SCREEN_ADDR) - add hl, de ; HL = Screen address + DE - ld (DFCC), hl + pop hl + ret +__PRINT_TAB: + ld hl, __PRINT_TAB1 + jr __PRINT_SET_STATE +__PRINT_TAB1: + ld (MEM0), a + ld hl, __PRINT_TAB2 + jr __PRINT_SET_STATE +__PRINT_TAB2: + ld a, (MEM0) ; Load tab code (ignore the current one) + ld hl, __PRINT_START + ld (PRINT_JUMP_STATE), hl + exx + push hl + push bc + push de + call PRINT_TAB + pop de + pop bc + pop hl ret - ENDP - pop namespace -#line 6 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/table_jump.asm" - push namespace core -JUMP_HL_PLUS_2A: ; Does JP (HL + A*2) Modifies DE. Modifies A - add a, a -JUMP_HL_PLUS_A: ; Does JP (HL + A) Modifies DE - ld e, a - ld d, 0 -JUMP_HL_PLUS_DE: ; Does JP (HL + DE) - add hl, de - ld e, (hl) - inc hl - ld d, (hl) - ex de, hl -CALL_HL: - jp (hl) - pop namespace -#line 8 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/ink.asm" - ; Sets ink color in ATTR_P permanently -; Parameter: Paper color in A register - push namespace core -INK: - PROC - LOCAL __SET_INK - LOCAL __SET_INK2 - ld de, ATTR_P -__SET_INK: - cp 8 - jr nz, __SET_INK2 - inc de ; Points DE to MASK_T or MASK_P - ld a, (de) - or 7 ; Set bits 0,1,2 to enable transparency - ld (de), a +__PRINT_AT: + ld hl, __PRINT_AT1 + jr __PRINT_SET_STATE +__PRINT_NOP: +__PRINT_RESTART: + ld hl, __PRINT_START +__PRINT_SET_STATE: + ld (PRINT_JUMP_STATE), hl ; Saves next entry call + exx ret -__SET_INK2: - ; Another entry. This will set the ink color at location pointer by DE - and 7 ; # Gets color mod 8 - ld b, a ; Saves the color - ld a, (de) - and 0F8h ; Clears previous value - or b - ld (de), a - inc de ; Points DE to MASK_T or MASK_P - ld a, (de) - and 0F8h ; Reset bits 0,1,2 sign to disable transparency - ld (de), a ; Store new attr +__PRINT_AT1: ; Jumps here if waiting for 1st parameter + ld hl, (S_POSN) + ld h, a + ld a, SCR_ROWS + sub h + ld (S_POSN + 1), a + ld hl, __PRINT_AT2 + jr __PRINT_SET_STATE +__PRINT_AT2: + call __LOAD_S_POSN + ld e, a + call __SAVE_S_POSN + jr __PRINT_RESTART +__PRINT_DEL: + call __LOAD_S_POSN ; Gets current screen position + dec e + ld a, -1 + cp e + jr nz, 3f + ld e, SCR_COLS - 2 + dec d + cp d + jr nz, 3f + ld d, SCR_ROWS - 1 +3: + call __SAVE_S_POSN + exx ret - ; Sets the INK color passed in A register in the ATTR_T variable -INK_TMP: - ld de, ATTR_T - jp __SET_INK - ENDP - pop namespace -#line 9 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/paper.asm" - ; Sets paper color in ATTR_P permanently -; Parameter: Paper color in A register - push namespace core -PAPER: - PROC - LOCAL __SET_PAPER - LOCAL __SET_PAPER2 - ld de, ATTR_P -__SET_PAPER: - cp 8 - jr nz, __SET_PAPER2 - inc de +__PRINT_INK: + ld hl, __PRINT_INK2 + jr __PRINT_SET_STATE +__PRINT_INK2: + call INK_TMP + jr __PRINT_RESTART +__PRINT_PAP: + ld hl, __PRINT_PAP2 + jr __PRINT_SET_STATE +__PRINT_PAP2: + call PAPER_TMP + jr __PRINT_RESTART +__PRINT_FLA: + ld hl, __PRINT_FLA2 + jr __PRINT_SET_STATE +__PRINT_FLA2: + call FLASH_TMP + jr __PRINT_RESTART +__PRINT_BRI: + ld hl, __PRINT_BRI2 + jr __PRINT_SET_STATE +__PRINT_BRI2: + call BRIGHT_TMP + jr __PRINT_RESTART +__PRINT_INV: + ld hl, __PRINT_INV2 + jr __PRINT_SET_STATE +__PRINT_INV2: + call INVERSE_TMP + jr __PRINT_RESTART +__PRINT_OVR: + ld hl, __PRINT_OVR2 + jr __PRINT_SET_STATE +__PRINT_OVR2: + call OVER_TMP + jr __PRINT_RESTART +__PRINT_BOLD: + ld hl, __PRINT_BOLD2 + jp __PRINT_SET_STATE +__PRINT_BOLD2: + call BOLD_TMP + jp __PRINT_RESTART +#line 353 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +__PRINT_ITA: + ld hl, __PRINT_ITA2 + jp __PRINT_SET_STATE +__PRINT_ITA2: + call ITALIC_TMP + jp __PRINT_RESTART +#line 363 "/zxbasic/src/arch/zx48k/library-asm/print.asm" + LOCAL __BOLD +__BOLD: + push hl + ld hl, MEM0 + ld b, 8 +1: ld a, (de) - or 038h - ld (de), a - ret - ; Another entry. This will set the paper color at location pointer by DE -__SET_PAPER2: - and 7 ; # Remove - rlca + ld c, a rlca - rlca ; a *= 8 - ld b, a ; Saves the color - ld a, (de) - and 0C7h ; Clears previous value - or b - ld (de), a - inc de ; Points to MASK_T or MASK_P accordingly - ld a, (de) - and 0C7h ; Resets bits 3,4,5 - ld (de), a - ret - ; Sets the PAPER color passed in A register in the ATTR_T variable -PAPER_TMP: - ld de, ATTR_T - jp __SET_PAPER - ENDP - pop namespace -#line 10 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/flash.asm" - ; Sets flash flag in ATTR_P permanently -; Parameter: Paper color in A register - push namespace core -FLASH: - ld hl, ATTR_P - PROC - LOCAL IS_TR - LOCAL IS_ZERO -__SET_FLASH: - ; Another entry. This will set the flash flag at location pointer by DE - cp 8 - jr z, IS_TR - ; # Convert to 0/1 - or a - jr z, IS_ZERO - ld a, 0x80 -IS_ZERO: - ld b, a ; Saves the color - ld a, (hl) - and 07Fh ; Clears previous value - or b + or c ld (hl), a inc hl - res 7, (hl) ;Reset bit 7 to disable transparency - ret -IS_TR: ; transparent - inc hl ; Points DE to MASK_T or MASK_P - set 7, (hl) ;Set bit 7 to enable transparency - ret - ; Sets the FLASH flag passed in A register in the ATTR_T variable -FLASH_TMP: - ld hl, ATTR_T - jr __SET_FLASH - ENDP - pop namespace -#line 11 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/bright.asm" - ; Sets bright flag in ATTR_P permanently -; Parameter: Paper color in A register - push namespace core -BRIGHT: - ld hl, ATTR_P - PROC - LOCAL IS_TR - LOCAL IS_ZERO -__SET_BRIGHT: - ; Another entry. This will set the bright flag at location pointer by DE - cp 8 - jr z, IS_TR - ; # Convert to 0/1 - or a - jr z, IS_ZERO - ld a, 0x40 -IS_ZERO: - ld b, a ; Saves the color - ld a, (hl) - and 0BFh ; Clears previous value - or b - ld (hl), a + inc de + djnz 1b + pop hl + ld de, MEM0 + ret +#line 384 "/zxbasic/src/arch/zx48k/library-asm/print.asm" + LOCAL __ITALIC +__ITALIC: + push hl + ld hl, MEM0 + ex de, hl + ld bc, 8 + ldir + ld hl, MEM0 + srl (hl) inc hl - res 6, (hl) ;Reset bit 6 to disable transparency + srl (hl) + inc hl + srl (hl) + inc hl + inc hl + inc hl + sla (hl) + inc hl + sla (hl) + inc hl + sla (hl) + pop hl + ld de, MEM0 ret -IS_TR: ; transparent - inc hl ; Points DE to MASK_T or MASK_P - set 6, (hl) ;Set bit 6 to enable transparency +#line 412 "/zxbasic/src/arch/zx48k/library-asm/print.asm" + LOCAL __SCROLL_SCR +#line 486 "/zxbasic/src/arch/zx48k/library-asm/print.asm" + __SCROLL_SCR EQU 0DFEh ; Use ROM SCROLL +#line 488 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 489 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +PRINT_COMMA: + call __LOAD_S_POSN + ld a, e + and 16 + add a, 16 +PRINT_TAB: + ; Tabulates the number of spaces in A register + ; If the current cursor position is already A, does nothing + PROC + LOCAL LOOP + call __LOAD_S_POSN ; e = current row + sub e + and 31 + ret z + ld b, a +LOOP: + ld a, ' ' + call __PRINTCHAR + djnz LOOP ret - ; Sets the BRIGHT flag passed in A register in the ATTR_T variable -BRIGHT_TMP: - ld hl, ATTR_T - jr __SET_BRIGHT + ENDP +PRINT_AT: ; Changes cursor to ROW, COL + ; COL in A register + ; ROW in stack + pop hl ; Ret address + ex (sp), hl ; callee H = ROW + ld l, a + ex de, hl + call __IN_SCREEN + ret nc ; Return if out of screen + jp __SAVE_S_POSN + LOCAL __PRINT_COM + LOCAL __PRINT_AT1 + LOCAL __PRINT_AT2 + LOCAL __PRINT_BOLD + LOCAL __PRINT_ITA + LOCAL __PRINT_INK + LOCAL __PRINT_PAP + LOCAL __PRINT_SET_STATE + LOCAL __PRINT_TABLE + LOCAL __PRINT_TAB, __PRINT_TAB1, __PRINT_TAB2 + LOCAL __PRINT_ITA2 +#line 545 "/zxbasic/src/arch/zx48k/library-asm/print.asm" + LOCAL __PRINT_BOLD2 +#line 551 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +__PRINT_TABLE: ; Jump table for 0 .. 22 codes + DW __PRINT_NOP ; 0 + DW __PRINT_NOP ; 1 + DW __PRINT_NOP ; 2 + DW __PRINT_NOP ; 3 + DW __PRINT_NOP ; 4 + DW __PRINT_NOP ; 5 + DW __PRINT_COM ; 6 COMMA + DW __PRINT_NOP ; 7 + DW __PRINT_DEL ; 8 DEL + DW __PRINT_NOP ; 9 + DW __PRINT_NOP ; 10 + DW __PRINT_NOP ; 11 + DW __PRINT_NOP ; 12 + DW __PRINT_0Dh ; 13 + DW __PRINT_BOLD ; 14 + DW __PRINT_ITA ; 15 + DW __PRINT_INK ; 16 + DW __PRINT_PAP ; 17 + DW __PRINT_FLA ; 18 + DW __PRINT_BRI ; 19 + DW __PRINT_INV ; 20 + DW __PRINT_OVR ; 21 + DW __PRINT_AT ; 22 AT + DW __PRINT_TAB ; 23 TAB ENDP pop namespace -#line 12 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/over.asm" - ; Sets OVER flag in P_FLAG permanently -; Parameter: OVER flag in bit 0 of A register -#line 1 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" +#line 3 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" #line 4 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" push namespace core COPY_ATTR: @@ -944,517 +991,470 @@ __REFRESH_TMP: ret ENDP pop namespace -#line 4 "/zxbasic/src/arch/zx48k/library-asm/over.asm" - push namespace core -OVER: - PROC - ld c, a ; saves it for later - and 2 - ld hl, FLAGS2 - res 1, (HL) - or (hl) - ld (hl), a - ld a, c ; Recovers previous value - and 1 ; # Convert to 0/1 - add a, a; # Shift left 1 bit for permanent - ld hl, P_FLAG - res 1, (hl) - or (hl) - ld (hl), a - ret - ; Sets OVER flag in P_FLAG temporarily -OVER_TMP: - ld c, a ; saves it for later - and 2 ; gets bit 1; clears carry - rra - ld hl, FLAGS2 - res 0, (hl) - or (hl) - ld (hl), a - ld a, c ; Recovers previous value - and 1 - ld hl, P_FLAG - res 0, (hl) - or (hl) - ld (hl), a - jp __SET_ATTR_MODE - ENDP - pop namespace -#line 13 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/inverse.asm" - ; Sets INVERSE flag in P_FLAG permanently -; Parameter: INVERSE flag in bit 0 of A register - push namespace core -INVERSE: - PROC - and 1 ; # Convert to 0/1 - add a, a; # Shift left 3 bits for permanent - add a, a - add a, a - ld hl, P_FLAG - res 3, (hl) - or (hl) - ld (hl), a - ret - ; Sets INVERSE flag in P_FLAG temporarily -INVERSE_TMP: - and 1 - add a, a - add a, a; # Shift left 2 bits for temporary - ld hl, P_FLAG - res 2, (hl) - or (hl) - ld (hl), a - jp __SET_ATTR_MODE - ENDP - pop namespace -#line 14 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/bold.asm" - ; Sets BOLD flag in P_FLAG permanently -; Parameter: BOLD flag in bit 0 of A register - push namespace core -BOLD: - PROC - and 1 - rlca - rlca - rlca - ld hl, FLAGS2 - res 3, (HL) - or (hl) - ld (hl), a - ret - ; Sets BOLD flag in P_FLAG temporarily -BOLD_TMP: - and 1 - rlca - rlca - ld hl, FLAGS2 - res 2, (hl) - or (hl) - ld (hl), a - ret - ENDP - pop namespace -#line 15 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/italic.asm" - ; Sets ITALIC flag in P_FLAG permanently -; Parameter: ITALIC flag in bit 0 of A register +#line 56 "zx48k/param0.bas" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/free.asm" +; vim: ts=4:et:sw=4: + ; Copyleft (K) by Jose M. Rodriguez de la Rosa + ; (a.k.a. Boriel) +; http://www.boriel.com + ; + ; This ASM library is licensed under the BSD license + ; you can use it for any purpose (even for commercial + ; closed source programs). + ; + ; Please read the BSD license on the internet + ; ----- IMPLEMENTATION NOTES ------ + ; The heap is implemented as a linked list of free blocks. +; Each free block contains this info: + ; + ; +----------------+ <-- HEAP START + ; | Size (2 bytes) | + ; | 0 | <-- Size = 0 => DUMMY HEADER BLOCK + ; +----------------+ + ; | Next (2 bytes) |---+ + ; +----------------+ <-+ + ; | Size (2 bytes) | + ; +----------------+ + ; | Next (2 bytes) |---+ + ; +----------------+ | + ; | | | <-- If Size > 4, then this contains (size - 4) bytes + ; | (0 if Size = 4)| | + ; +----------------+ <-+ + ; | Size (2 bytes) | + ; +----------------+ + ; | Next (2 bytes) |---+ + ; +----------------+ | + ; | | | + ; | (0 if Size = 4)| | + ; +----------------+ | + ; | <-- This zone is in use (Already allocated) + ; +----------------+ <-+ + ; | Size (2 bytes) | + ; +----------------+ + ; | Next (2 bytes) |---+ + ; +----------------+ | + ; | | | + ; | (0 if Size = 4)| | + ; +----------------+ <-+ + ; | Next (2 bytes) |--> NULL => END OF LIST + ; | 0 = NULL | + ; +----------------+ + ; | | + ; | (0 if Size = 4)| + ; +----------------+ + ; When a block is FREED, the previous and next pointers are examined to see + ; if we can defragment the heap. If the block to be breed is just next to the + ; previous, or to the next (or both) they will be converted into a single + ; block (so defragmented). + ; MEMORY MANAGER + ; + ; This library must be initialized calling __MEM_INIT with + ; HL = BLOCK Start & DE = Length. + ; An init directive is useful for initialization routines. + ; They will be added automatically if needed. +#line 1 "/zxbasic/src/arch/zx48k/library-asm/heapinit.asm" +; vim: ts=4:et:sw=4: + ; Copyleft (K) by Jose M. Rodriguez de la Rosa + ; (a.k.a. Boriel) +; http://www.boriel.com + ; + ; This ASM library is licensed under the BSD license + ; you can use it for any purpose (even for commercial + ; closed source programs). + ; + ; Please read the BSD license on the internet + ; ----- IMPLEMENTATION NOTES ------ + ; The heap is implemented as a linked list of free blocks. +; Each free block contains this info: + ; + ; +----------------+ <-- HEAP START + ; | Size (2 bytes) | + ; | 0 | <-- Size = 0 => DUMMY HEADER BLOCK + ; +----------------+ + ; | Next (2 bytes) |---+ + ; +----------------+ <-+ + ; | Size (2 bytes) | + ; +----------------+ + ; | Next (2 bytes) |---+ + ; +----------------+ | + ; | | | <-- If Size > 4, then this contains (size - 4) bytes + ; | (0 if Size = 4)| | + ; +----------------+ <-+ + ; | Size (2 bytes) | + ; +----------------+ + ; | Next (2 bytes) |---+ + ; +----------------+ | + ; | | | + ; | (0 if Size = 4)| | + ; +----------------+ | + ; | <-- This zone is in use (Already allocated) + ; +----------------+ <-+ + ; | Size (2 bytes) | + ; +----------------+ + ; | Next (2 bytes) |---+ + ; +----------------+ | + ; | | | + ; | (0 if Size = 4)| | + ; +----------------+ <-+ + ; | Next (2 bytes) |--> NULL => END OF LIST + ; | 0 = NULL | + ; +----------------+ + ; | | + ; | (0 if Size = 4)| + ; +----------------+ + ; When a block is FREED, the previous and next pointers are examined to see + ; if we can defragment the heap. If the block to be breed is just next to the + ; previous, or to the next (or both) they will be converted into a single + ; block (so defragmented). + ; MEMORY MANAGER + ; + ; This library must be initialized calling __MEM_INIT with + ; HL = BLOCK Start & DE = Length. + ; An init directive is useful for initialization routines. + ; They will be added automatically if needed. + ; --------------------------------------------------------------------- + ; __MEM_INIT must be called to initalize this library with the + ; standard parameters + ; --------------------------------------------------------------------- push namespace core -ITALIC: +__MEM_INIT: ; Initializes the library using (RAMTOP) as start, and + ld hl, ZXBASIC_MEM_HEAP ; Change this with other address of heap start + ld de, ZXBASIC_HEAP_SIZE ; Change this with your size + ; --------------------------------------------------------------------- + ; __MEM_INIT2 initalizes this library +; Parameters: +; HL : Memory address of 1st byte of the memory heap +; DE : Length in bytes of the Memory Heap + ; --------------------------------------------------------------------- +__MEM_INIT2: + ; HL as TOP PROC - and 1 - rrca - rrca - rrca - ld hl, FLAGS2 - res 5, (HL) - or (hl) + dec de + dec de + dec de + dec de ; DE = length - 4; HL = start + ; This is done, because we require 4 bytes for the empty dummy-header block + xor a ld (hl), a - ret - ; Sets ITALIC flag in P_FLAG temporarily -ITALIC_TMP: - and 1 - rrca - rrca - rrca - rrca - ld hl, FLAGS2 - res 4, (hl) - or (hl) + inc hl + ld (hl), a ; First "free" block is a header: size=0, Pointer=&(Block) + 4 + inc hl + ld b, h + ld c, l + inc bc + inc bc ; BC = starts of next block + ld (hl), c + inc hl + ld (hl), b + inc hl ; Pointer to next block + ld (hl), e + inc hl + ld (hl), d + inc hl ; Block size (should be length - 4 at start); This block contains all the available memory + ld (hl), a ; NULL (0000h) ; No more blocks (a list with a single block) + inc hl ld (hl), a + ld a, 201 + ld (__MEM_INIT), a; "Pokes" with a RET so ensure this routine is not called again ret ENDP pop namespace -#line 16 "/zxbasic/src/arch/zx48k/library-asm/print.asm" - ; Putting a comment starting with @INIT
- ; will make the compiler to add a CALL to
- ; It is useful for initialization routines. +#line 69 "/zxbasic/src/arch/zx48k/library-asm/free.asm" + ; --------------------------------------------------------------------- + ; MEM_FREE + ; Frees a block of memory + ; +; Parameters: + ; HL = Pointer to the block to be freed. If HL is NULL (0) nothing + ; is done + ; --------------------------------------------------------------------- push namespace core -__PRINT_INIT: ; To be called before program starts (initializes library) - PROC - ld hl, __PRINT_START - ld (PRINT_JUMP_STATE), hl - ;; Clears ATTR2 flags (OVER 2, etc) - xor a - ld (FLAGS2), a - LOCAL SET_SCR_ADDR - call __LOAD_S_POSN - jp __SET_SCR_PTR - ;; Receives HL = future value of S_POSN - ;; Stores it at (S_POSN) and refresh screen pointers (ATTR, SCR) -SET_SCR_ADDR: - ld (S_POSN), hl - ex de, hl - ld hl, SCR_SIZE - or a - sbc hl, de - ex de, hl - dec e - jp __SET_SCR_PTR -__PRINTCHAR: ; Print character store in accumulator (A register) - ; Modifies H'L', B'C', A'F', D'E', A - LOCAL PO_GR_1 - LOCAL __PRCHAR - LOCAL __PRINT_JUMP - LOCAL __SRCADDR - LOCAL __PRINT_UDG - LOCAL __PRGRAPH - LOCAL __PRINT_START - PRINT_JUMP_STATE EQU __PRINT_JUMP + 2 -__PRINT_JUMP: - exx ; Switch to alternative registers - jp __PRINT_START ; Where to jump. If we print 22 (AT), next two calls jumps to AT1 and AT2 respectively -__PRINT_START: -__PRINT_CHR: - cp ' ' - jr c, __PRINT_SPECIAL ; Characters below ' ' are special ones - ex af, af' ; Saves a value (char to print) for later - ld hl, (S_POSN) - dec l - jr nz, 1f - ld l, SCR_COLS - 1 - dec h - jr nz, 2f - inc h - push hl - call __SCROLL_SCR - pop hl -#line 92 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -2: - call SET_SCR_ADDR - jr 4f -1: - ld (S_POSN), hl -4: - ex af, af' - cp 80h ; Is it a "normal" (printable) char - jr c, __SRCADDR - cp 90h ; Is it an UDG? - jr nc, __PRINT_UDG - ; Print an 8 bit pattern (80h to 8Fh) - ld b, a - call PO_GR_1 ; This ROM routine will generate the bit pattern at MEM0 - ld hl, MEM0 - jp __PRGRAPH - PO_GR_1 EQU 0B38h -__PRINT_UDG: - sub 90h ; Sub ASC code - ld bc, (UDG) - jr __PRGRAPH0 - __SOURCEADDR EQU (__SRCADDR + 1) ; Address of the pointer to chars source -__SRCADDR: - ld bc, (CHARS) -__PRGRAPH0: - add a, a ; A = a * 2 (since a < 80h) ; Thanks to Metalbrain at http://foro.speccy.org - ld l, a - ld h, 0 ; HL = a * 2 (accumulator) - add hl, hl - add hl, hl ; HL = a * 8 - add hl, bc ; HL = CHARS address -__PRGRAPH: - ex de, hl ; HL = Write Address, DE = CHARS address - bit 2, (iy + $47) - call nz, __BOLD -#line 139 "/zxbasic/src/arch/zx48k/library-asm/print.asm" - bit 4, (iy + $47) - call nz, __ITALIC -#line 144 "/zxbasic/src/arch/zx48k/library-asm/print.asm" - ld hl, (DFCC) - push hl - ld b, 8 ; 8 bytes per char -__PRCHAR: - ld a, (de) ; DE *must* be source, and HL destiny -PRINT_MODE: ; Which operation is used to write on the screen - ; Set it with: - ; LD A, - ; LD (PRINT_MODE), A - ; - ; Available operations: - ; NORMAL : 0h --> NOP ; OVER 0 - ; XOR : AEh --> XOR (HL) ; OVER 1 - ; OR : B6h --> OR (HL) ; PUTSPRITE - ; AND : A6h --> AND (HL) ; PUTMASK - nop ; Set to one of the values above -INVERSE_MODE: ; 00 -> NOP -> INVERSE 0 - nop ; 2F -> CPL -> INVERSE 1 - ld (hl), a - inc de - inc h ; Next line - djnz __PRCHAR - pop hl +MEM_FREE: +__MEM_FREE: ; Frees the block pointed by HL + ; HL DE BC & AF modified + PROC + LOCAL __MEM_LOOP2 + LOCAL __MEM_LINK_PREV + LOCAL __MEM_JOIN_TEST + LOCAL __MEM_BLOCK_JOIN + ld a, h + or l + ret z ; Return if NULL pointer + dec hl + dec hl + ld b, h + ld c, l ; BC = Block pointer + ld hl, ZXBASIC_MEM_HEAP ; This label point to the heap start +__MEM_LOOP2: inc hl - ld (DFCC), hl - ld hl, (DFCCL) ; current ATTR Pos - push hl - call __SET_ATTR - pop hl + inc hl ; Next block ptr + ld e, (hl) inc hl - ld (DFCCL),hl - exx - ret - ; ------------- SPECIAL CHARS (< 32) ----------------- -__PRINT_SPECIAL: ; Jumps here if it is a special char - ld hl, __PRINT_TABLE - jp JUMP_HL_PLUS_2A -PRINT_EOL: ; Called WHENEVER there is no ";" at end of PRINT sentence - exx -__PRINT_0Dh: ; Called WHEN printing CHR$(13) - ld hl, (S_POSN) - dec l - jr nz, 1f - dec h - jr nz, 1f - inc h - push hl - call __SCROLL_SCR - pop hl -#line 210 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -1: - ld l, 1 -__PRINT_EOL_END: - call SET_SCR_ADDR - exx - ret -__PRINT_COM: - exx + ld d, (hl) ; Block next ptr + ex de, hl ; DE = &(block->next); HL = block->next + ld a, h ; HL == NULL? + or l + jp z, __MEM_LINK_PREV; if so, link with previous + or a ; Clear carry flag + sbc hl, bc ; Carry if BC > HL => This block if before + add hl, bc ; Restores HL, preserving Carry flag + jp c, __MEM_LOOP2 ; This block is before. Keep searching PASS the block + ;------ At this point current HL is PAST BC, so we must link (DE) with BC, and HL in BC->next +__MEM_LINK_PREV: ; Link (DE) with BC, and BC->next with HL + ex de, hl push hl - push de - push bc - call PRINT_COMMA - pop bc - pop de + dec hl + ld (hl), c + inc hl + ld (hl), b ; (DE) <- BC + ld h, b ; HL <- BC (Free block ptr) + ld l, c + inc hl ; Skip block length (2 bytes) + inc hl + ld (hl), e ; Block->next = DE + inc hl + ld (hl), d + ; --- LINKED ; HL = &(BC->next) + 2 + call __MEM_JOIN_TEST pop hl - ret -__PRINT_TAB: - ld hl, __PRINT_TAB1 - jr __PRINT_SET_STATE -__PRINT_TAB1: - ld (MEM0), a - ld hl, __PRINT_TAB2 - jr __PRINT_SET_STATE -__PRINT_TAB2: - ld a, (MEM0) ; Load tab code (ignore the current one) - ld hl, __PRINT_START - ld (PRINT_JUMP_STATE), hl - exx - push hl - push bc - push de - call PRINT_TAB - pop de - pop bc +__MEM_JOIN_TEST: ; Checks for fragmented contiguous blocks and joins them + ; hl = Ptr to current block + 2 + ld d, (hl) + dec hl + ld e, (hl) + dec hl + ld b, (hl) ; Loads block length into BC + dec hl + ld c, (hl) ; + push hl ; Saves it for later + add hl, bc ; Adds its length. If HL == DE now, it must be joined + or a + sbc hl, de ; If Z, then HL == DE => We must join pop hl + ret nz +__MEM_BLOCK_JOIN: ; Joins current block (pointed by HL) with next one (pointed by DE). HL->length already in BC + push hl ; Saves it for later + ex de, hl + ld e, (hl) ; DE -> block->next->length + inc hl + ld d, (hl) + inc hl + ex de, hl ; DE = &(block->next) + add hl, bc ; HL = Total Length + ld b, h + ld c, l ; BC = Total Length + ex de, hl + ld e, (hl) + inc hl + ld d, (hl) ; DE = block->next + pop hl ; Recovers Pointer to block + ld (hl), c + inc hl + ld (hl), b ; Length Saved + inc hl + ld (hl), e + inc hl + ld (hl), d ; Next saved ret -__PRINT_AT: - ld hl, __PRINT_AT1 - jr __PRINT_SET_STATE -__PRINT_NOP: -__PRINT_RESTART: - ld hl, __PRINT_START -__PRINT_SET_STATE: - ld (PRINT_JUMP_STATE), hl ; Saves next entry call - exx - ret -__PRINT_AT1: ; Jumps here if waiting for 1st parameter - ld hl, (S_POSN) - ld h, a - ld a, SCR_ROWS - sub h - ld (S_POSN + 1), a - ld hl, __PRINT_AT2 - jr __PRINT_SET_STATE -__PRINT_AT2: - call __LOAD_S_POSN - ld e, a - call __SAVE_S_POSN - jr __PRINT_RESTART -__PRINT_DEL: - call __LOAD_S_POSN ; Gets current screen position - dec e - ld a, -1 - cp e - jr nz, 3f - ld e, SCR_COLS - 2 - dec d - cp d - jr nz, 3f - ld d, SCR_ROWS - 1 -3: - call __SAVE_S_POSN - exx - ret -__PRINT_INK: - ld hl, __PRINT_INK2 - jr __PRINT_SET_STATE -__PRINT_INK2: - call INK_TMP - jr __PRINT_RESTART -__PRINT_PAP: - ld hl, __PRINT_PAP2 - jr __PRINT_SET_STATE -__PRINT_PAP2: - call PAPER_TMP - jr __PRINT_RESTART -__PRINT_FLA: - ld hl, __PRINT_FLA2 - jr __PRINT_SET_STATE -__PRINT_FLA2: - call FLASH_TMP - jr __PRINT_RESTART -__PRINT_BRI: - ld hl, __PRINT_BRI2 - jr __PRINT_SET_STATE -__PRINT_BRI2: - call BRIGHT_TMP - jr __PRINT_RESTART -__PRINT_INV: - ld hl, __PRINT_INV2 - jr __PRINT_SET_STATE -__PRINT_INV2: - call INVERSE_TMP - jr __PRINT_RESTART -__PRINT_OVR: - ld hl, __PRINT_OVR2 - jr __PRINT_SET_STATE -__PRINT_OVR2: - call OVER_TMP - jr __PRINT_RESTART -__PRINT_BOLD: - ld hl, __PRINT_BOLD2 - jp __PRINT_SET_STATE -__PRINT_BOLD2: - call BOLD_TMP - jp __PRINT_RESTART -#line 354 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -__PRINT_ITA: - ld hl, __PRINT_ITA2 - jp __PRINT_SET_STATE -__PRINT_ITA2: - call ITALIC_TMP - jp __PRINT_RESTART -#line 364 "/zxbasic/src/arch/zx48k/library-asm/print.asm" - LOCAL __BOLD -__BOLD: - push hl - ld hl, MEM0 - ld b, 8 -1: - ld a, (de) - ld c, a - rlca - or c - ld (hl), a + ENDP + pop namespace +#line 57 "zx48k/param0.bas" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/loadstr.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/alloc.asm" +; vim: ts=4:et:sw=4: + ; Copyleft (K) by Jose M. Rodriguez de la Rosa + ; (a.k.a. Boriel) +; http://www.boriel.com + ; + ; This ASM library is licensed under the MIT license + ; you can use it for any purpose (even for commercial + ; closed source programs). + ; + ; Please read the MIT license on the internet + ; ----- IMPLEMENTATION NOTES ------ + ; The heap is implemented as a linked list of free blocks. +; Each free block contains this info: + ; + ; +----------------+ <-- HEAP START + ; | Size (2 bytes) | + ; | 0 | <-- Size = 0 => DUMMY HEADER BLOCK + ; +----------------+ + ; | Next (2 bytes) |---+ + ; +----------------+ <-+ + ; | Size (2 bytes) | + ; +----------------+ + ; | Next (2 bytes) |---+ + ; +----------------+ | + ; | | | <-- If Size > 4, then this contains (size - 4) bytes + ; | (0 if Size = 4)| | + ; +----------------+ <-+ + ; | Size (2 bytes) | + ; +----------------+ + ; | Next (2 bytes) |---+ + ; +----------------+ | + ; | | | + ; | (0 if Size = 4)| | + ; +----------------+ | + ; | <-- This zone is in use (Already allocated) + ; +----------------+ <-+ + ; | Size (2 bytes) | + ; +----------------+ + ; | Next (2 bytes) |---+ + ; +----------------+ | + ; | | | + ; | (0 if Size = 4)| | + ; +----------------+ <-+ + ; | Next (2 bytes) |--> NULL => END OF LIST + ; | 0 = NULL | + ; +----------------+ + ; | | + ; | (0 if Size = 4)| + ; +----------------+ + ; When a block is FREED, the previous and next pointers are examined to see + ; if we can defragment the heap. If the block to be freed is just next to the + ; previous, or to the next (or both) they will be converted into a single + ; block (so defragmented). + ; MEMORY MANAGER + ; + ; This library must be initialized calling __MEM_INIT with + ; HL = BLOCK Start & DE = Length. + ; An init directive is useful for initialization routines. + ; They will be added automatically if needed. + ; --------------------------------------------------------------------- + ; MEM_ALLOC + ; Allocates a block of memory in the heap. + ; + ; Parameters + ; BC = Length of requested memory block + ; +; Returns: + ; HL = Pointer to the allocated block in memory. Returns 0 (NULL) + ; if the block could not be allocated (out of memory) + ; --------------------------------------------------------------------- + push namespace core +MEM_ALLOC: +__MEM_ALLOC: ; Returns the 1st free block found of the given length (in BC) + PROC + LOCAL __MEM_LOOP + LOCAL __MEM_DONE + LOCAL __MEM_SUBTRACT + LOCAL __MEM_START + LOCAL TEMP, TEMP0 + TEMP EQU TEMP0 + 1 + ld hl, 0 + ld (TEMP), hl +__MEM_START: + ld hl, ZXBASIC_MEM_HEAP ; This label point to the heap start + inc bc + inc bc ; BC = BC + 2 ; block size needs 2 extra bytes for hidden pointer +__MEM_LOOP: ; Loads lengh at (HL, HL+). If Lenght >= BC, jump to __MEM_DONE + ld a, h ; HL = NULL (No memory available?) + or l +#line 113 "/zxbasic/src/arch/zx48k/library-asm/alloc.asm" + ret z ; NULL +#line 115 "/zxbasic/src/arch/zx48k/library-asm/alloc.asm" + ; HL = Pointer to Free block + ld e, (hl) inc hl - inc de - djnz 1b + ld d, (hl) + inc hl ; DE = Block Length + push hl ; HL = *pointer to -> next block + ex de, hl + or a ; CF = 0 + sbc hl, bc ; FREE >= BC (Length) (HL = BlockLength - Length) + jp nc, __MEM_DONE pop hl - ld de, MEM0 - ret -#line 385 "/zxbasic/src/arch/zx48k/library-asm/print.asm" - LOCAL __ITALIC -__ITALIC: - push hl - ld hl, MEM0 + ld (TEMP), hl ex de, hl - ld bc, 8 - ldir - ld hl, MEM0 - srl (hl) - inc hl - srl (hl) - inc hl - srl (hl) - inc hl - inc hl + ld e, (hl) inc hl - sla (hl) + ld d, (hl) + ex de, hl + jp __MEM_LOOP +__MEM_DONE: ; A free block has been found. + ; Check if at least 4 bytes remains free (HL >= 4) + push hl + exx ; exx to preserve bc + pop hl + ld bc, 4 + or a + sbc hl, bc + exx + jp nc, __MEM_SUBTRACT + ; At this point... + ; less than 4 bytes remains free. So we return this block entirely + ; We must link the previous block with the next to this one + ; (DE) => Pointer to next block + ; (TEMP) => &(previous->next) + pop hl ; Discard current block pointer + push de + ex de, hl ; DE = Previous block pointer; (HL) = Next block pointer + ld a, (hl) inc hl - sla (hl) + ld h, (hl) + ld l, a ; HL = (HL) + ex de, hl ; HL = Previous block pointer; DE = Next block pointer +TEMP0: + ld hl, 0 ; Pre-previous block pointer + ld (hl), e inc hl - sla (hl) - pop hl - ld de, MEM0 + ld (hl), d ; LINKED + pop hl ; Returning block. ret -#line 413 "/zxbasic/src/arch/zx48k/library-asm/print.asm" - LOCAL __SCROLL_SCR -#line 487 "/zxbasic/src/arch/zx48k/library-asm/print.asm" - __SCROLL_SCR EQU 0DFEh ; Use ROM SCROLL -#line 489 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -#line 490 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -PRINT_COMMA: - call __LOAD_S_POSN - ld a, e - and 16 - add a, 16 -PRINT_TAB: - ; Tabulates the number of spaces in A register - ; If the current cursor position is already A, does nothing - PROC - LOCAL LOOP - call __LOAD_S_POSN ; e = current row - sub e - and 31 - ret z - ld b, a -LOOP: - ld a, ' ' - call __PRINTCHAR - djnz LOOP +__MEM_SUBTRACT: + ; At this point we have to store HL value (Length - BC) into (DE - 2) + ex de, hl + dec hl + ld (hl), d + dec hl + ld (hl), e ; Store new block length + add hl, de ; New length + DE => free-block start + pop de ; Remove previous HL off the stack + ld (hl), c ; Store length on its 1st word + inc hl + ld (hl), b + inc hl ; Return hl ret ENDP -PRINT_AT: ; Changes cursor to ROW, COL - ; COL in A register - ; ROW in stack - pop hl ; Ret address - ex (sp), hl ; callee H = ROW + pop namespace +#line 2 "/zxbasic/src/arch/zx48k/library-asm/loadstr.asm" + ; Loads a string (ptr) from HL + ; and duplicates it on dynamic memory again + ; Finally, it returns result pointer in HL + push namespace core +__ILOADSTR: ; This is the indirect pointer entry HL = (HL) + ld a, h + or l + ret z + ld a, (hl) + inc hl + ld h, (hl) ld l, a - ex de, hl - call __IN_SCREEN - ret nc ; Return if out of screen - jp __SAVE_S_POSN - LOCAL __PRINT_COM - LOCAL __PRINT_AT1 - LOCAL __PRINT_AT2 - LOCAL __PRINT_BOLD - LOCAL __PRINT_ITA - LOCAL __PRINT_INK - LOCAL __PRINT_PAP - LOCAL __PRINT_SET_STATE - LOCAL __PRINT_TABLE - LOCAL __PRINT_TAB, __PRINT_TAB1, __PRINT_TAB2 - LOCAL __PRINT_ITA2 -#line 546 "/zxbasic/src/arch/zx48k/library-asm/print.asm" - LOCAL __PRINT_BOLD2 -#line 552 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -__PRINT_TABLE: ; Jump table for 0 .. 22 codes - DW __PRINT_NOP ; 0 - DW __PRINT_NOP ; 1 - DW __PRINT_NOP ; 2 - DW __PRINT_NOP ; 3 - DW __PRINT_NOP ; 4 - DW __PRINT_NOP ; 5 - DW __PRINT_COM ; 6 COMMA - DW __PRINT_NOP ; 7 - DW __PRINT_DEL ; 8 DEL - DW __PRINT_NOP ; 9 - DW __PRINT_NOP ; 10 - DW __PRINT_NOP ; 11 - DW __PRINT_NOP ; 12 - DW __PRINT_0Dh ; 13 - DW __PRINT_BOLD ; 14 - DW __PRINT_ITA ; 15 - DW __PRINT_INK ; 16 - DW __PRINT_PAP ; 17 - DW __PRINT_FLA ; 18 - DW __PRINT_BRI ; 19 - DW __PRINT_INV ; 20 - DW __PRINT_OVR ; 21 - DW __PRINT_AT ; 22 AT - DW __PRINT_TAB ; 23 TAB - ENDP +__LOADSTR: ; __FASTCALL__ entry + ld a, h + or l + ret z ; Return if NULL + ld c, (hl) + inc hl + ld b, (hl) + dec hl ; BC = LEN(a$) + inc bc + inc bc ; BC = LEN(a$) + 2 (two bytes for length) + push hl + push bc + call __MEM_ALLOC + pop bc ; Recover length + pop de ; Recover origin + ld a, h + or l + ret z ; Return if NULL (No memory) + ex de, hl ; ldir takes HL as source, DE as destiny, so SWAP HL,DE + push de ; Saves destiny start + ldir ; Copies string (length number included) + pop hl ; Recovers destiny in hl as result + ret pop namespace -#line 57 "zx48k/param0.bas" +#line 58 "zx48k/param0.bas" #line 1 "/zxbasic/src/arch/zx48k/library-asm/printstr.asm" ; PRINT command routine ; Prints string pointed by HL @@ -1498,7 +1498,7 @@ __PRINT_STR: jp __PRINT_STR_LOOP ENDP pop namespace -#line 58 "zx48k/param0.bas" +#line 60 "zx48k/param0.bas" #line 1 "/zxbasic/src/arch/zx48k/library-asm/strcat.asm" #line 1 "/zxbasic/src/arch/zx48k/library-asm/strlen.asm" ; Returns len if a string @@ -1611,5 +1611,5 @@ __STRCATEND: ret ENDP pop namespace -#line 59 "zx48k/param0.bas" +#line 61 "zx48k/param0.bas" END diff --git a/tests/functional/zx48k/param1.asm b/tests/functional/zx48k/param1.asm index b4d6c4f08..cb4835ea7 100644 --- a/tests/functional/zx48k/param1.asm +++ b/tests/functional/zx48k/param1.asm @@ -52,6 +52,7 @@ _test: push ix ld ix, 0 add ix, sp + call .core.COPY_ATTR ld h, (ix+5) ld l, (ix+4) ld c, (hl) @@ -60,7 +61,7 @@ _test: ld l, c xor a call .core.__PRINTSTR - call .core.PRINT_EOL_ATTR + call .core.PRINT_EOL _test__leave: ld sp, ix pop ix @@ -73,9 +74,7 @@ _test__leave: DEFW 0001h DEFB 61h ;; --- end of user code --- -#line 1 "/zxbasic/src/arch/zx48k/library-asm/print_eol_attr.asm" - ; Calls PRINT_EOL and then COPY_ATTR, so saves - ; 3 bytes +#line 1 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" #line 1 "/zxbasic/src/arch/zx48k/library-asm/print.asm" ; vim:ts=4:sw=4:et: ; PRINT command routine @@ -425,60 +424,6 @@ BRIGHT_TMP: #line 1 "/zxbasic/src/arch/zx48k/library-asm/over.asm" ; Sets OVER flag in P_FLAG permanently ; Parameter: OVER flag in bit 0 of A register -#line 1 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" -#line 4 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" - push namespace core -COPY_ATTR: - ; Just copies current permanent attribs into temporal attribs - ; and sets print mode - PROC - LOCAL INVERSE1 - LOCAL __REFRESH_TMP - INVERSE1 EQU 02Fh - ld hl, (ATTR_P) - ld (ATTR_T), hl - ld hl, FLAGS2 - call __REFRESH_TMP - ld hl, P_FLAG - call __REFRESH_TMP -__SET_ATTR_MODE: ; Another entry to set print modes. A contains (P_FLAG) - LOCAL TABLE - LOCAL CONT2 - rra ; Over bit to carry - ld a, (FLAGS2) - rla ; Over bit in bit 1, Over2 bit in bit 2 - and 3 ; Only bit 0 and 1 (OVER flag) - ld c, a - ld b, 0 - ld hl, TABLE - add hl, bc - ld a, (hl) - ld (PRINT_MODE), a - ld hl, (P_FLAG) - xor a ; NOP -> INVERSE0 - bit 2, l - jr z, CONT2 - ld a, INVERSE1 ; CPL -> INVERSE1 -CONT2: - ld (INVERSE_MODE), a - ret -TABLE: - nop ; NORMAL MODE - xor (hl) ; OVER 1 MODE - and (hl) ; OVER 2 MODE - or (hl) ; OVER 3 MODE -#line 67 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" -__REFRESH_TMP: - ld a, (hl) - and 0b10101010 - ld c, a - rra - or c - ld (hl), a - ret - ENDP - pop namespace -#line 4 "/zxbasic/src/arch/zx48k/library-asm/over.asm" push namespace core OVER: PROC @@ -720,11 +665,10 @@ INVERSE_MODE: ; 00 -> NOP -> INVERSE 0 inc hl ld (DFCC), hl ld hl, (DFCCL) ; current ATTR Pos - push hl - call __SET_ATTR - pop hl inc hl - ld (DFCCL),hl + ld (DFCCL), hl + dec hl + call __SET_ATTR exx ret ; ------------- SPECIAL CHARS (< 32) ----------------- @@ -743,7 +687,7 @@ __PRINT_0Dh: ; Called WHEN printing CHR$(13) push hl call __SCROLL_SCR pop hl -#line 210 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 209 "/zxbasic/src/arch/zx48k/library-asm/print.asm" 1: ld l, 1 __PRINT_EOL_END: @@ -860,14 +804,14 @@ __PRINT_BOLD: __PRINT_BOLD2: call BOLD_TMP jp __PRINT_RESTART -#line 354 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 353 "/zxbasic/src/arch/zx48k/library-asm/print.asm" __PRINT_ITA: ld hl, __PRINT_ITA2 jp __PRINT_SET_STATE __PRINT_ITA2: call ITALIC_TMP jp __PRINT_RESTART -#line 364 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 363 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __BOLD __BOLD: push hl @@ -885,7 +829,7 @@ __BOLD: pop hl ld de, MEM0 ret -#line 385 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 384 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __ITALIC __ITALIC: push hl @@ -910,12 +854,12 @@ __ITALIC: pop hl ld de, MEM0 ret -#line 413 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 412 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __SCROLL_SCR -#line 487 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 486 "/zxbasic/src/arch/zx48k/library-asm/print.asm" __SCROLL_SCR EQU 0DFEh ; Use ROM SCROLL +#line 488 "/zxbasic/src/arch/zx48k/library-asm/print.asm" #line 489 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -#line 490 "/zxbasic/src/arch/zx48k/library-asm/print.asm" PRINT_COMMA: call __LOAD_S_POSN ld a, e @@ -958,9 +902,9 @@ PRINT_AT: ; Changes cursor to ROW, COL LOCAL __PRINT_TABLE LOCAL __PRINT_TAB, __PRINT_TAB1, __PRINT_TAB2 LOCAL __PRINT_ITA2 -#line 546 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 545 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __PRINT_BOLD2 -#line 552 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 551 "/zxbasic/src/arch/zx48k/library-asm/print.asm" __PRINT_TABLE: ; Jump table for 0 .. 22 codes DW __PRINT_NOP ; 0 DW __PRINT_NOP ; 1 @@ -988,13 +932,60 @@ __PRINT_TABLE: ; Jump table for 0 .. 22 codes DW __PRINT_TAB ; 23 TAB ENDP pop namespace -#line 5 "/zxbasic/src/arch/zx48k/library-asm/print_eol_attr.asm" +#line 3 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" +#line 4 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" push namespace core -PRINT_EOL_ATTR: - call PRINT_EOL - jp COPY_ATTR +COPY_ATTR: + ; Just copies current permanent attribs into temporal attribs + ; and sets print mode + PROC + LOCAL INVERSE1 + LOCAL __REFRESH_TMP + INVERSE1 EQU 02Fh + ld hl, (ATTR_P) + ld (ATTR_T), hl + ld hl, FLAGS2 + call __REFRESH_TMP + ld hl, P_FLAG + call __REFRESH_TMP +__SET_ATTR_MODE: ; Another entry to set print modes. A contains (P_FLAG) + LOCAL TABLE + LOCAL CONT2 + rra ; Over bit to carry + ld a, (FLAGS2) + rla ; Over bit in bit 1, Over2 bit in bit 2 + and 3 ; Only bit 0 and 1 (OVER flag) + ld c, a + ld b, 0 + ld hl, TABLE + add hl, bc + ld a, (hl) + ld (PRINT_MODE), a + ld hl, (P_FLAG) + xor a ; NOP -> INVERSE0 + bit 2, l + jr z, CONT2 + ld a, INVERSE1 ; CPL -> INVERSE1 +CONT2: + ld (INVERSE_MODE), a + ret +TABLE: + nop ; NORMAL MODE + xor (hl) ; OVER 1 MODE + and (hl) ; OVER 2 MODE + or (hl) ; OVER 3 MODE +#line 67 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" +__REFRESH_TMP: + ld a, (hl) + and 0b10101010 + ld c, a + rra + or c + ld (hl), a + ret + ENDP pop namespace -#line 47 "zx48k/param1.bas" +#line 48 "zx48k/param1.bas" #line 1 "/zxbasic/src/arch/zx48k/library-asm/printstr.asm" #line 1 "/zxbasic/src/arch/zx48k/library-asm/free.asm" ; vim: ts=4:et:sw=4: @@ -1305,7 +1296,7 @@ __PRINT_STR: jp __PRINT_STR_LOOP ENDP pop namespace -#line 48 "zx48k/param1.bas" +#line 50 "zx48k/param1.bas" #line 1 "/zxbasic/src/arch/zx48k/library-asm/storestr.asm" ; vim:ts=4:et:sw=4 ; Stores value of current string pointed by DE register into address pointed by HL @@ -1712,5 +1703,5 @@ __STORE_STR: pop hl ; Returns ptr to b$ in HL (Caller might needed to free it from memory) ret pop namespace -#line 49 "zx48k/param1.bas" +#line 51 "zx48k/param1.bas" END diff --git a/tests/functional/zx48k/param2.asm b/tests/functional/zx48k/param2.asm index 60c165485..03d32a6ed 100644 --- a/tests/functional/zx48k/param2.asm +++ b/tests/functional/zx48k/param2.asm @@ -26,6 +26,7 @@ .core.__LABEL__.ZXBASIC_USER_DATA EQU .core.ZXBASIC_USER_DATA .core.ZXBASIC_USER_DATA_END: .core.__MAIN_PROGRAM__: + call .core.COPY_ATTR ld hl, .LABEL.__LABEL0 call .core.__LOADSTR push hl @@ -79,334 +80,42 @@ _test__leave: DEFW 0001h DEFB 41h ;; --- end of user code --- -#line 1 "/zxbasic/src/arch/zx48k/library-asm/free.asm" -; vim: ts=4:et:sw=4: - ; Copyleft (K) by Jose M. Rodriguez de la Rosa - ; (a.k.a. Boriel) -; http://www.boriel.com - ; - ; This ASM library is licensed under the BSD license - ; you can use it for any purpose (even for commercial - ; closed source programs). - ; - ; Please read the BSD license on the internet - ; ----- IMPLEMENTATION NOTES ------ - ; The heap is implemented as a linked list of free blocks. -; Each free block contains this info: - ; - ; +----------------+ <-- HEAP START - ; | Size (2 bytes) | - ; | 0 | <-- Size = 0 => DUMMY HEADER BLOCK - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ <-+ - ; | Size (2 bytes) | - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ | - ; | | | <-- If Size > 4, then this contains (size - 4) bytes - ; | (0 if Size = 4)| | - ; +----------------+ <-+ - ; | Size (2 bytes) | - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ | - ; | | | - ; | (0 if Size = 4)| | - ; +----------------+ | - ; | <-- This zone is in use (Already allocated) - ; +----------------+ <-+ - ; | Size (2 bytes) | - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ | - ; | | | - ; | (0 if Size = 4)| | - ; +----------------+ <-+ - ; | Next (2 bytes) |--> NULL => END OF LIST - ; | 0 = NULL | - ; +----------------+ - ; | | - ; | (0 if Size = 4)| - ; +----------------+ - ; When a block is FREED, the previous and next pointers are examined to see - ; if we can defragment the heap. If the block to be breed is just next to the - ; previous, or to the next (or both) they will be converted into a single - ; block (so defragmented). - ; MEMORY MANAGER - ; - ; This library must be initialized calling __MEM_INIT with - ; HL = BLOCK Start & DE = Length. - ; An init directive is useful for initialization routines. - ; They will be added automatically if needed. -#line 1 "/zxbasic/src/arch/zx48k/library-asm/heapinit.asm" -; vim: ts=4:et:sw=4: - ; Copyleft (K) by Jose M. Rodriguez de la Rosa - ; (a.k.a. Boriel) -; http://www.boriel.com - ; - ; This ASM library is licensed under the BSD license - ; you can use it for any purpose (even for commercial - ; closed source programs). - ; - ; Please read the BSD license on the internet - ; ----- IMPLEMENTATION NOTES ------ - ; The heap is implemented as a linked list of free blocks. -; Each free block contains this info: - ; - ; +----------------+ <-- HEAP START - ; | Size (2 bytes) | - ; | 0 | <-- Size = 0 => DUMMY HEADER BLOCK - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ <-+ - ; | Size (2 bytes) | - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ | - ; | | | <-- If Size > 4, then this contains (size - 4) bytes - ; | (0 if Size = 4)| | - ; +----------------+ <-+ - ; | Size (2 bytes) | - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ | - ; | | | - ; | (0 if Size = 4)| | - ; +----------------+ | - ; | <-- This zone is in use (Already allocated) - ; +----------------+ <-+ - ; | Size (2 bytes) | - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ | - ; | | | - ; | (0 if Size = 4)| | - ; +----------------+ <-+ - ; | Next (2 bytes) |--> NULL => END OF LIST - ; | 0 = NULL | - ; +----------------+ - ; | | - ; | (0 if Size = 4)| - ; +----------------+ - ; When a block is FREED, the previous and next pointers are examined to see - ; if we can defragment the heap. If the block to be breed is just next to the - ; previous, or to the next (or both) they will be converted into a single - ; block (so defragmented). - ; MEMORY MANAGER - ; - ; This library must be initialized calling __MEM_INIT with - ; HL = BLOCK Start & DE = Length. - ; An init directive is useful for initialization routines. - ; They will be added automatically if needed. - ; --------------------------------------------------------------------- - ; __MEM_INIT must be called to initalize this library with the - ; standard parameters - ; --------------------------------------------------------------------- - push namespace core -__MEM_INIT: ; Initializes the library using (RAMTOP) as start, and - ld hl, ZXBASIC_MEM_HEAP ; Change this with other address of heap start - ld de, ZXBASIC_HEAP_SIZE ; Change this with your size - ; --------------------------------------------------------------------- - ; __MEM_INIT2 initalizes this library -; Parameters: -; HL : Memory address of 1st byte of the memory heap -; DE : Length in bytes of the Memory Heap - ; --------------------------------------------------------------------- -__MEM_INIT2: - ; HL as TOP - PROC - dec de - dec de - dec de - dec de ; DE = length - 4; HL = start - ; This is done, because we require 4 bytes for the empty dummy-header block - xor a - ld (hl), a - inc hl - ld (hl), a ; First "free" block is a header: size=0, Pointer=&(Block) + 4 - inc hl - ld b, h - ld c, l - inc bc - inc bc ; BC = starts of next block - ld (hl), c - inc hl - ld (hl), b - inc hl ; Pointer to next block - ld (hl), e - inc hl - ld (hl), d - inc hl ; Block size (should be length - 4 at start); This block contains all the available memory - ld (hl), a ; NULL (0000h) ; No more blocks (a list with a single block) - inc hl - ld (hl), a - ld a, 201 - ld (__MEM_INIT), a; "Pokes" with a RET so ensure this routine is not called again - ret - ENDP - pop namespace -#line 69 "/zxbasic/src/arch/zx48k/library-asm/free.asm" - ; --------------------------------------------------------------------- - ; MEM_FREE - ; Frees a block of memory - ; -; Parameters: - ; HL = Pointer to the block to be freed. If HL is NULL (0) nothing - ; is done - ; --------------------------------------------------------------------- - push namespace core -MEM_FREE: -__MEM_FREE: ; Frees the block pointed by HL - ; HL DE BC & AF modified - PROC - LOCAL __MEM_LOOP2 - LOCAL __MEM_LINK_PREV - LOCAL __MEM_JOIN_TEST - LOCAL __MEM_BLOCK_JOIN - ld a, h - or l - ret z ; Return if NULL pointer - dec hl - dec hl - ld b, h - ld c, l ; BC = Block pointer - ld hl, ZXBASIC_MEM_HEAP ; This label point to the heap start -__MEM_LOOP2: - inc hl - inc hl ; Next block ptr - ld e, (hl) - inc hl - ld d, (hl) ; Block next ptr - ex de, hl ; DE = &(block->next); HL = block->next - ld a, h ; HL == NULL? - or l - jp z, __MEM_LINK_PREV; if so, link with previous - or a ; Clear carry flag - sbc hl, bc ; Carry if BC > HL => This block if before - add hl, bc ; Restores HL, preserving Carry flag - jp c, __MEM_LOOP2 ; This block is before. Keep searching PASS the block - ;------ At this point current HL is PAST BC, so we must link (DE) with BC, and HL in BC->next -__MEM_LINK_PREV: ; Link (DE) with BC, and BC->next with HL - ex de, hl - push hl - dec hl - ld (hl), c - inc hl - ld (hl), b ; (DE) <- BC - ld h, b ; HL <- BC (Free block ptr) - ld l, c - inc hl ; Skip block length (2 bytes) - inc hl - ld (hl), e ; Block->next = DE - inc hl - ld (hl), d - ; --- LINKED ; HL = &(BC->next) + 2 - call __MEM_JOIN_TEST - pop hl -__MEM_JOIN_TEST: ; Checks for fragmented contiguous blocks and joins them - ; hl = Ptr to current block + 2 - ld d, (hl) - dec hl - ld e, (hl) - dec hl - ld b, (hl) ; Loads block length into BC - dec hl - ld c, (hl) ; - push hl ; Saves it for later - add hl, bc ; Adds its length. If HL == DE now, it must be joined - or a - sbc hl, de ; If Z, then HL == DE => We must join - pop hl - ret nz -__MEM_BLOCK_JOIN: ; Joins current block (pointed by HL) with next one (pointed by DE). HL->length already in BC - push hl ; Saves it for later - ex de, hl - ld e, (hl) ; DE -> block->next->length - inc hl - ld d, (hl) - inc hl - ex de, hl ; DE = &(block->next) - add hl, bc ; HL = Total Length - ld b, h - ld c, l ; BC = Total Length - ex de, hl - ld e, (hl) - inc hl - ld d, (hl) ; DE = block->next - pop hl ; Recovers Pointer to block - ld (hl), c - inc hl - ld (hl), b ; Length Saved - inc hl - ld (hl), e - inc hl - ld (hl), d ; Next saved - ret - ENDP - pop namespace -#line 55 "zx48k/param2.bas" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/loadstr.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/alloc.asm" -; vim: ts=4:et:sw=4: - ; Copyleft (K) by Jose M. Rodriguez de la Rosa - ; (a.k.a. Boriel) -; http://www.boriel.com - ; - ; This ASM library is licensed under the MIT license - ; you can use it for any purpose (even for commercial - ; closed source programs). - ; - ; Please read the MIT license on the internet - ; ----- IMPLEMENTATION NOTES ------ - ; The heap is implemented as a linked list of free blocks. -; Each free block contains this info: - ; - ; +----------------+ <-- HEAP START - ; | Size (2 bytes) | - ; | 0 | <-- Size = 0 => DUMMY HEADER BLOCK - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ <-+ - ; | Size (2 bytes) | - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ | - ; | | | <-- If Size > 4, then this contains (size - 4) bytes - ; | (0 if Size = 4)| | - ; +----------------+ <-+ - ; | Size (2 bytes) | - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ | - ; | | | - ; | (0 if Size = 4)| | - ; +----------------+ | - ; | <-- This zone is in use (Already allocated) - ; +----------------+ <-+ - ; | Size (2 bytes) | - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ | - ; | | | - ; | (0 if Size = 4)| | - ; +----------------+ <-+ - ; | Next (2 bytes) |--> NULL => END OF LIST - ; | 0 = NULL | - ; +----------------+ - ; | | - ; | (0 if Size = 4)| - ; +----------------+ - ; When a block is FREED, the previous and next pointers are examined to see - ; if we can defragment the heap. If the block to be freed is just next to the - ; previous, or to the next (or both) they will be converted into a single - ; block (so defragmented). - ; MEMORY MANAGER - ; - ; This library must be initialized calling __MEM_INIT with - ; HL = BLOCK Start & DE = Length. - ; An init directive is useful for initialization routines. - ; They will be added automatically if needed. +#line 1 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +; vim:ts=4:sw=4:et: + ; PRINT command routine + ; Does not print attribute. Use PRINT_STR or PRINT_NUM for that +#line 1 "/zxbasic/src/arch/zx48k/library-asm/sposn.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/sysvars.asm" + ;; ----------------------------------------------------------------------- + ;; ZX Basic System Vars + ;; Some of them will be mapped over Sinclair ROM ones for compatibility + ;; ----------------------------------------------------------------------- + push namespace core +SCREEN_ADDR: DW 16384 ; Screen address (can be pointed to other place to use a screen buffer) +SCREEN_ATTR_ADDR: DW 22528 ; Screen attribute address (ditto.) + ; These are mapped onto ZX Spectrum ROM VARS + CHARS EQU 23606 ; Pointer to ROM/RAM Charset + TVFLAGS EQU 23612 ; TV Flags + UDG EQU 23675 ; Pointer to UDG Charset + COORDS EQU 23677 ; Last PLOT coordinates + FLAGS2 EQU 23681 ; + ECHO_E EQU 23682 ; + DFCC EQU 23684 ; Next screen addr for PRINT + DFCCL EQU 23686 ; Next screen attr for PRINT + S_POSN EQU 23688 + ATTR_P EQU 23693 ; Current Permanent ATTRS set with INK, PAPER, etc commands + ATTR_T EQU 23695 ; temporary ATTRIBUTES + P_FLAG EQU 23697 ; + MEM0 EQU 23698 ; Temporary memory buffer used by ROM chars + SCR_COLS EQU 33 ; Screen with in columns + 1 + SCR_ROWS EQU 24 ; Screen height in rows + SCR_SIZE EQU (SCR_ROWS << 8) + SCR_COLS + pop namespace +#line 2 "/zxbasic/src/arch/zx48k/library-asm/sposn.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/attr.asm" + ; Attribute routines +; vim:ts=4:et:sw: #line 1 "/zxbasic/src/arch/zx48k/library-asm/error.asm" ; Simple error control routines ; vim:ts=4:et: @@ -441,457 +150,795 @@ __STOP: ld (ERR_NR), a ret pop namespace -#line 69 "/zxbasic/src/arch/zx48k/library-asm/alloc.asm" - ; --------------------------------------------------------------------- - ; MEM_ALLOC - ; Allocates a block of memory in the heap. - ; - ; Parameters - ; BC = Length of requested memory block - ; -; Returns: - ; HL = Pointer to the allocated block in memory. Returns 0 (NULL) - ; if the block could not be allocated (out of memory) - ; --------------------------------------------------------------------- +#line 6 "/zxbasic/src/arch/zx48k/library-asm/attr.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/in_screen.asm" push namespace core -MEM_ALLOC: -__MEM_ALLOC: ; Returns the 1st free block found of the given length (in BC) +__IN_SCREEN: + ; Returns NO carry if current coords (D, E) + ; are OUT of the screen limits PROC - LOCAL __MEM_LOOP - LOCAL __MEM_DONE - LOCAL __MEM_SUBTRACT - LOCAL __MEM_START - LOCAL TEMP, TEMP0 - TEMP EQU TEMP0 + 1 - ld hl, 0 - ld (TEMP), hl -__MEM_START: - ld hl, ZXBASIC_MEM_HEAP ; This label point to the heap start - inc bc - inc bc ; BC = BC + 2 ; block size needs 2 extra bytes for hidden pointer -__MEM_LOOP: ; Loads lengh at (HL, HL+). If Lenght >= BC, jump to __MEM_DONE - ld a, h ; HL = NULL (No memory available?) - or l -#line 113 "/zxbasic/src/arch/zx48k/library-asm/alloc.asm" - ret z ; NULL -#line 115 "/zxbasic/src/arch/zx48k/library-asm/alloc.asm" - ; HL = Pointer to Free block - ld e, (hl) - inc hl - ld d, (hl) - inc hl ; DE = Block Length - push hl ; HL = *pointer to -> next block - ex de, hl - or a ; CF = 0 - sbc hl, bc ; FREE >= BC (Length) (HL = BlockLength - Length) - jp nc, __MEM_DONE - pop hl - ld (TEMP), hl + LOCAL __IN_SCREEN_ERR + ld hl, SCR_SIZE + ld a, e + cp l + jr nc, __IN_SCREEN_ERR ; Do nothing and return if out of range + ld a, d + cp h + ret c ; Return if carry (OK) +__IN_SCREEN_ERR: +__OUT_OF_SCREEN_ERR: + ; Jumps here if out of screen + ld a, ERROR_OutOfScreen + jp __STOP ; Saves error code and exits + ENDP + pop namespace +#line 7 "/zxbasic/src/arch/zx48k/library-asm/attr.asm" + push namespace core +__ATTR_ADDR: + ; calc start address in DE (as (32 * d) + e) + ; Contributed by Santiago Romero at http://www.speccy.org + ld h, 0 ; 7 T-States + ld a, d ; 4 T-States + ld d, h + add a, a ; a * 2 ; 4 T-States + add a, a ; a * 4 ; 4 T-States + ld l, a ; HL = A * 4 ; 4 T-States + add hl, hl ; HL = A * 8 ; 15 T-States + add hl, hl ; HL = A * 16 ; 15 T-States + add hl, hl ; HL = A * 32 ; 15 T-States + add hl, de + ld de, (SCREEN_ATTR_ADDR) ; Adds the screen address + add hl, de + ; Return current screen address in HL + ret + ; Sets the attribute at a given screen coordinate (D, E). + ; The attribute is taken from the ATTR_T memory variable + ; Used by PRINT routines +SET_ATTR: + ; Checks for valid coords + call __IN_SCREEN + ret nc + call __ATTR_ADDR +__SET_ATTR: + ; Internal __FASTCALL__ Entry used by printing routines + ; HL contains the address of the ATTR cell to set + PROC +__SET_ATTR2: ; Sets attr from ATTR_T to (HL) which points to the scr address + ld de, (ATTR_T) ; E = ATTR_T, D = MASK_T + ld a, d + and (hl) + ld c, a ; C = current screen color, masked + ld a, d + cpl ; Negate mask + and e ; Mask current attributes + or c ; Mix them + ld (hl), a ; Store result in screen + ret + ENDP + pop namespace +#line 3 "/zxbasic/src/arch/zx48k/library-asm/sposn.asm" + ; Printing positioning library. + push namespace core + ; Loads into DE current ROW, COL print position from S_POSN mem var. +__LOAD_S_POSN: + PROC + ld de, (S_POSN) + ld hl, SCR_SIZE + or a + sbc hl, de ex de, hl + ret + ENDP + ; Saves ROW, COL from DE into S_POSN mem var. +__SAVE_S_POSN: + PROC + ld hl, SCR_SIZE + or a + sbc hl, de + ld (S_POSN), hl ; saves it again +__SET_SCR_PTR: ;; Fast + push de + call __ATTR_ADDR + ld (DFCCL), hl + pop de + ld a, d + ld c, a ; Saves it for later + and 0F8h ; Masks 3 lower bit ; zy + ld d, a + ld a, c ; Recovers it + and 07h ; MOD 7 ; y1 + rrca + rrca + rrca + or e + ld e, a + ld hl, (SCREEN_ADDR) + add hl, de ; HL = Screen address + DE + ld (DFCC), hl + ret + ENDP + pop namespace +#line 6 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/table_jump.asm" + push namespace core +JUMP_HL_PLUS_2A: ; Does JP (HL + A*2) Modifies DE. Modifies A + add a, a +JUMP_HL_PLUS_A: ; Does JP (HL + A) Modifies DE + ld e, a + ld d, 0 +JUMP_HL_PLUS_DE: ; Does JP (HL + DE) + add hl, de ld e, (hl) inc hl ld d, (hl) ex de, hl - jp __MEM_LOOP -__MEM_DONE: ; A free block has been found. - ; Check if at least 4 bytes remains free (HL >= 4) - push hl - exx ; exx to preserve bc - pop hl - ld bc, 4 +CALL_HL: + jp (hl) + pop namespace +#line 8 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/ink.asm" + ; Sets ink color in ATTR_P permanently +; Parameter: Paper color in A register + push namespace core +INK: + PROC + LOCAL __SET_INK + LOCAL __SET_INK2 + ld de, ATTR_P +__SET_INK: + cp 8 + jr nz, __SET_INK2 + inc de ; Points DE to MASK_T or MASK_P + ld a, (de) + or 7 ; Set bits 0,1,2 to enable transparency + ld (de), a + ret +__SET_INK2: + ; Another entry. This will set the ink color at location pointer by DE + and 7 ; # Gets color mod 8 + ld b, a ; Saves the color + ld a, (de) + and 0F8h ; Clears previous value + or b + ld (de), a + inc de ; Points DE to MASK_T or MASK_P + ld a, (de) + and 0F8h ; Reset bits 0,1,2 sign to disable transparency + ld (de), a ; Store new attr + ret + ; Sets the INK color passed in A register in the ATTR_T variable +INK_TMP: + ld de, ATTR_T + jp __SET_INK + ENDP + pop namespace +#line 9 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/paper.asm" + ; Sets paper color in ATTR_P permanently +; Parameter: Paper color in A register + push namespace core +PAPER: + PROC + LOCAL __SET_PAPER + LOCAL __SET_PAPER2 + ld de, ATTR_P +__SET_PAPER: + cp 8 + jr nz, __SET_PAPER2 + inc de + ld a, (de) + or 038h + ld (de), a + ret + ; Another entry. This will set the paper color at location pointer by DE +__SET_PAPER2: + and 7 ; # Remove + rlca + rlca + rlca ; a *= 8 + ld b, a ; Saves the color + ld a, (de) + and 0C7h ; Clears previous value + or b + ld (de), a + inc de ; Points to MASK_T or MASK_P accordingly + ld a, (de) + and 0C7h ; Resets bits 3,4,5 + ld (de), a + ret + ; Sets the PAPER color passed in A register in the ATTR_T variable +PAPER_TMP: + ld de, ATTR_T + jp __SET_PAPER + ENDP + pop namespace +#line 10 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/flash.asm" + ; Sets flash flag in ATTR_P permanently +; Parameter: Paper color in A register + push namespace core +FLASH: + ld hl, ATTR_P + PROC + LOCAL IS_TR + LOCAL IS_ZERO +__SET_FLASH: + ; Another entry. This will set the flash flag at location pointer by DE + cp 8 + jr z, IS_TR + ; # Convert to 0/1 or a - sbc hl, bc - exx - jp nc, __MEM_SUBTRACT - ; At this point... - ; less than 4 bytes remains free. So we return this block entirely - ; We must link the previous block with the next to this one - ; (DE) => Pointer to next block - ; (TEMP) => &(previous->next) - pop hl ; Discard current block pointer - push de - ex de, hl ; DE = Previous block pointer; (HL) = Next block pointer + jr z, IS_ZERO + ld a, 0x80 +IS_ZERO: + ld b, a ; Saves the color ld a, (hl) + and 07Fh ; Clears previous value + or b + ld (hl), a inc hl - ld h, (hl) - ld l, a ; HL = (HL) - ex de, hl ; HL = Previous block pointer; DE = Next block pointer -TEMP0: - ld hl, 0 ; Pre-previous block pointer - ld (hl), e - inc hl - ld (hl), d ; LINKED - pop hl ; Returning block. + res 7, (hl) ;Reset bit 7 to disable transparency ret -__MEM_SUBTRACT: - ; At this point we have to store HL value (Length - BC) into (DE - 2) - ex de, hl - dec hl - ld (hl), d - dec hl - ld (hl), e ; Store new block length - add hl, de ; New length + DE => free-block start - pop de ; Remove previous HL off the stack - ld (hl), c ; Store length on its 1st word - inc hl - ld (hl), b - inc hl ; Return hl +IS_TR: ; transparent + inc hl ; Points DE to MASK_T or MASK_P + set 7, (hl) ;Set bit 7 to enable transparency ret + ; Sets the FLASH flag passed in A register in the ATTR_T variable +FLASH_TMP: + ld hl, ATTR_T + jr __SET_FLASH ENDP pop namespace -#line 2 "/zxbasic/src/arch/zx48k/library-asm/loadstr.asm" - ; Loads a string (ptr) from HL - ; and duplicates it on dynamic memory again - ; Finally, it returns result pointer in HL +#line 11 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/bright.asm" + ; Sets bright flag in ATTR_P permanently +; Parameter: Paper color in A register push namespace core -__ILOADSTR: ; This is the indirect pointer entry HL = (HL) - ld a, h - or l - ret z +BRIGHT: + ld hl, ATTR_P + PROC + LOCAL IS_TR + LOCAL IS_ZERO +__SET_BRIGHT: + ; Another entry. This will set the bright flag at location pointer by DE + cp 8 + jr z, IS_TR + ; # Convert to 0/1 + or a + jr z, IS_ZERO + ld a, 0x40 +IS_ZERO: + ld b, a ; Saves the color ld a, (hl) + and 0BFh ; Clears previous value + or b + ld (hl), a inc hl - ld h, (hl) - ld l, a -__LOADSTR: ; __FASTCALL__ entry - ld a, h - or l - ret z ; Return if NULL - ld c, (hl) - inc hl - ld b, (hl) - dec hl ; BC = LEN(a$) - inc bc - inc bc ; BC = LEN(a$) + 2 (two bytes for length) - push hl - push bc - call __MEM_ALLOC - pop bc ; Recover length - pop de ; Recover origin - ld a, h - or l - ret z ; Return if NULL (No memory) - ex de, hl ; ldir takes HL as source, DE as destiny, so SWAP HL,DE - push de ; Saves destiny start - ldir ; Copies string (length number included) - pop hl ; Recovers destiny in hl as result + res 6, (hl) ;Reset bit 6 to disable transparency + ret +IS_TR: ; transparent + inc hl ; Points DE to MASK_T or MASK_P + set 6, (hl) ;Set bit 6 to enable transparency ret + ; Sets the BRIGHT flag passed in A register in the ATTR_T variable +BRIGHT_TMP: + ld hl, ATTR_T + jr __SET_BRIGHT + ENDP pop namespace -#line 56 "zx48k/param2.bas" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -; vim:ts=4:sw=4:et: - ; PRINT command routine - ; Does not print attribute. Use PRINT_STR or PRINT_NUM for that -#line 1 "/zxbasic/src/arch/zx48k/library-asm/sposn.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/sysvars.asm" - ;; ----------------------------------------------------------------------- - ;; ZX Basic System Vars - ;; Some of them will be mapped over Sinclair ROM ones for compatibility - ;; ----------------------------------------------------------------------- - push namespace core -SCREEN_ADDR: DW 16384 ; Screen address (can be pointed to other place to use a screen buffer) -SCREEN_ATTR_ADDR: DW 22528 ; Screen attribute address (ditto.) - ; These are mapped onto ZX Spectrum ROM VARS - CHARS EQU 23606 ; Pointer to ROM/RAM Charset - TVFLAGS EQU 23612 ; TV Flags - UDG EQU 23675 ; Pointer to UDG Charset - COORDS EQU 23677 ; Last PLOT coordinates - FLAGS2 EQU 23681 ; - ECHO_E EQU 23682 ; - DFCC EQU 23684 ; Next screen addr for PRINT - DFCCL EQU 23686 ; Next screen attr for PRINT - S_POSN EQU 23688 - ATTR_P EQU 23693 ; Current Permanent ATTRS set with INK, PAPER, etc commands - ATTR_T EQU 23695 ; temporary ATTRIBUTES - P_FLAG EQU 23697 ; - MEM0 EQU 23698 ; Temporary memory buffer used by ROM chars - SCR_COLS EQU 33 ; Screen with in columns + 1 - SCR_ROWS EQU 24 ; Screen height in rows - SCR_SIZE EQU (SCR_ROWS << 8) + SCR_COLS - pop namespace -#line 2 "/zxbasic/src/arch/zx48k/library-asm/sposn.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/attr.asm" - ; Attribute routines -; vim:ts=4:et:sw: -#line 1 "/zxbasic/src/arch/zx48k/library-asm/in_screen.asm" +#line 12 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/over.asm" + ; Sets OVER flag in P_FLAG permanently +; Parameter: OVER flag in bit 0 of A register push namespace core -__IN_SCREEN: - ; Returns NO carry if current coords (D, E) - ; are OUT of the screen limits +OVER: PROC - LOCAL __IN_SCREEN_ERR - ld hl, SCR_SIZE - ld a, e - cp l - jr nc, __IN_SCREEN_ERR ; Do nothing and return if out of range - ld a, d - cp h - ret c ; Return if carry (OK) -__IN_SCREEN_ERR: -__OUT_OF_SCREEN_ERR: - ; Jumps here if out of screen - ld a, ERROR_OutOfScreen - jp __STOP ; Saves error code and exits + ld c, a ; saves it for later + and 2 + ld hl, FLAGS2 + res 1, (HL) + or (hl) + ld (hl), a + ld a, c ; Recovers previous value + and 1 ; # Convert to 0/1 + add a, a; # Shift left 1 bit for permanent + ld hl, P_FLAG + res 1, (hl) + or (hl) + ld (hl), a + ret + ; Sets OVER flag in P_FLAG temporarily +OVER_TMP: + ld c, a ; saves it for later + and 2 ; gets bit 1; clears carry + rra + ld hl, FLAGS2 + res 0, (hl) + or (hl) + ld (hl), a + ld a, c ; Recovers previous value + and 1 + ld hl, P_FLAG + res 0, (hl) + or (hl) + ld (hl), a + jp __SET_ATTR_MODE + ENDP + pop namespace +#line 13 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/inverse.asm" + ; Sets INVERSE flag in P_FLAG permanently +; Parameter: INVERSE flag in bit 0 of A register + push namespace core +INVERSE: + PROC + and 1 ; # Convert to 0/1 + add a, a; # Shift left 3 bits for permanent + add a, a + add a, a + ld hl, P_FLAG + res 3, (hl) + or (hl) + ld (hl), a + ret + ; Sets INVERSE flag in P_FLAG temporarily +INVERSE_TMP: + and 1 + add a, a + add a, a; # Shift left 2 bits for temporary + ld hl, P_FLAG + res 2, (hl) + or (hl) + ld (hl), a + jp __SET_ATTR_MODE + ENDP + pop namespace +#line 14 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/bold.asm" + ; Sets BOLD flag in P_FLAG permanently +; Parameter: BOLD flag in bit 0 of A register + push namespace core +BOLD: + PROC + and 1 + rlca + rlca + rlca + ld hl, FLAGS2 + res 3, (HL) + or (hl) + ld (hl), a + ret + ; Sets BOLD flag in P_FLAG temporarily +BOLD_TMP: + and 1 + rlca + rlca + ld hl, FLAGS2 + res 2, (hl) + or (hl) + ld (hl), a + ret ENDP pop namespace -#line 7 "/zxbasic/src/arch/zx48k/library-asm/attr.asm" +#line 15 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/italic.asm" + ; Sets ITALIC flag in P_FLAG permanently +; Parameter: ITALIC flag in bit 0 of A register push namespace core -__ATTR_ADDR: - ; calc start address in DE (as (32 * d) + e) - ; Contributed by Santiago Romero at http://www.speccy.org - ld h, 0 ; 7 T-States - ld a, d ; 4 T-States - ld d, h - add a, a ; a * 2 ; 4 T-States - add a, a ; a * 4 ; 4 T-States - ld l, a ; HL = A * 4 ; 4 T-States - add hl, hl ; HL = A * 8 ; 15 T-States - add hl, hl ; HL = A * 16 ; 15 T-States - add hl, hl ; HL = A * 32 ; 15 T-States - add hl, de - ld de, (SCREEN_ATTR_ADDR) ; Adds the screen address - add hl, de - ; Return current screen address in HL - ret - ; Sets the attribute at a given screen coordinate (D, E). - ; The attribute is taken from the ATTR_T memory variable - ; Used by PRINT routines -SET_ATTR: - ; Checks for valid coords - call __IN_SCREEN - ret nc - call __ATTR_ADDR -__SET_ATTR: - ; Internal __FASTCALL__ Entry used by printing routines - ; HL contains the address of the ATTR cell to set +ITALIC: PROC -__SET_ATTR2: ; Sets attr from ATTR_T to (HL) which points to the scr address - ld de, (ATTR_T) ; E = ATTR_T, D = MASK_T - ld a, d - and (hl) - ld c, a ; C = current screen color, masked - ld a, d - cpl ; Negate mask - and e ; Mask current attributes - or c ; Mix them - ld (hl), a ; Store result in screen + and 1 + rrca + rrca + rrca + ld hl, FLAGS2 + res 5, (HL) + or (hl) + ld (hl), a + ret + ; Sets ITALIC flag in P_FLAG temporarily +ITALIC_TMP: + and 1 + rrca + rrca + rrca + rrca + ld hl, FLAGS2 + res 4, (hl) + or (hl) + ld (hl), a ret ENDP pop namespace -#line 3 "/zxbasic/src/arch/zx48k/library-asm/sposn.asm" - ; Printing positioning library. +#line 16 "/zxbasic/src/arch/zx48k/library-asm/print.asm" + ; Putting a comment starting with @INIT
+ ; will make the compiler to add a CALL to
+ ; It is useful for initialization routines. push namespace core - ; Loads into DE current ROW, COL print position from S_POSN mem var. -__LOAD_S_POSN: +__PRINT_INIT: ; To be called before program starts (initializes library) PROC - ld de, (S_POSN) + ld hl, __PRINT_START + ld (PRINT_JUMP_STATE), hl + ;; Clears ATTR2 flags (OVER 2, etc) + xor a + ld (FLAGS2), a + LOCAL SET_SCR_ADDR + call __LOAD_S_POSN + jp __SET_SCR_PTR + ;; Receives HL = future value of S_POSN + ;; Stores it at (S_POSN) and refresh screen pointers (ATTR, SCR) +SET_SCR_ADDR: + ld (S_POSN), hl + ex de, hl ld hl, SCR_SIZE or a sbc hl, de ex de, hl + dec e + jp __SET_SCR_PTR +__PRINTCHAR: ; Print character store in accumulator (A register) + ; Modifies H'L', B'C', A'F', D'E', A + LOCAL PO_GR_1 + LOCAL __PRCHAR + LOCAL __PRINT_JUMP + LOCAL __SRCADDR + LOCAL __PRINT_UDG + LOCAL __PRGRAPH + LOCAL __PRINT_START + PRINT_JUMP_STATE EQU __PRINT_JUMP + 2 +__PRINT_JUMP: + exx ; Switch to alternative registers + jp __PRINT_START ; Where to jump. If we print 22 (AT), next two calls jumps to AT1 and AT2 respectively +__PRINT_START: +__PRINT_CHR: + cp ' ' + jr c, __PRINT_SPECIAL ; Characters below ' ' are special ones + ex af, af' ; Saves a value (char to print) for later + ld hl, (S_POSN) + dec l + jr nz, 1f + ld l, SCR_COLS - 1 + dec h + jr nz, 2f + inc h + push hl + call __SCROLL_SCR + pop hl +#line 92 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +2: + call SET_SCR_ADDR + jr 4f +1: + ld (S_POSN), hl +4: + ex af, af' + cp 80h ; Is it a "normal" (printable) char + jr c, __SRCADDR + cp 90h ; Is it an UDG? + jr nc, __PRINT_UDG + ; Print an 8 bit pattern (80h to 8Fh) + ld b, a + call PO_GR_1 ; This ROM routine will generate the bit pattern at MEM0 + ld hl, MEM0 + jp __PRGRAPH + PO_GR_1 EQU 0B38h +__PRINT_UDG: + sub 90h ; Sub ASC code + ld bc, (UDG) + jr __PRGRAPH0 + __SOURCEADDR EQU (__SRCADDR + 1) ; Address of the pointer to chars source +__SRCADDR: + ld bc, (CHARS) +__PRGRAPH0: + add a, a ; A = a * 2 (since a < 80h) ; Thanks to Metalbrain at http://foro.speccy.org + ld l, a + ld h, 0 ; HL = a * 2 (accumulator) + add hl, hl + add hl, hl ; HL = a * 8 + add hl, bc ; HL = CHARS address +__PRGRAPH: + ex de, hl ; HL = Write Address, DE = CHARS address + bit 2, (iy + $47) + call nz, __BOLD +#line 139 "/zxbasic/src/arch/zx48k/library-asm/print.asm" + bit 4, (iy + $47) + call nz, __ITALIC +#line 144 "/zxbasic/src/arch/zx48k/library-asm/print.asm" + ld hl, (DFCC) + push hl + ld b, 8 ; 8 bytes per char +__PRCHAR: + ld a, (de) ; DE *must* be source, and HL destiny +PRINT_MODE: ; Which operation is used to write on the screen + ; Set it with: + ; LD A, + ; LD (PRINT_MODE), A + ; + ; Available operations: + ; NORMAL : 0h --> NOP ; OVER 0 + ; XOR : AEh --> XOR (HL) ; OVER 1 + ; OR : B6h --> OR (HL) ; PUTSPRITE + ; AND : A6h --> AND (HL) ; PUTMASK + nop ; Set to one of the values above +INVERSE_MODE: ; 00 -> NOP -> INVERSE 0 + nop ; 2F -> CPL -> INVERSE 1 + ld (hl), a + inc de + inc h ; Next line + djnz __PRCHAR + pop hl + inc hl + ld (DFCC), hl + ld hl, (DFCCL) ; current ATTR Pos + inc hl + ld (DFCCL), hl + dec hl + call __SET_ATTR + exx ret - ENDP - ; Saves ROW, COL from DE into S_POSN mem var. -__SAVE_S_POSN: - PROC - ld hl, SCR_SIZE - or a - sbc hl, de - ld (S_POSN), hl ; saves it again -__SET_SCR_PTR: ;; Fast + ; ------------- SPECIAL CHARS (< 32) ----------------- +__PRINT_SPECIAL: ; Jumps here if it is a special char + ld hl, __PRINT_TABLE + jp JUMP_HL_PLUS_2A +PRINT_EOL: ; Called WHENEVER there is no ";" at end of PRINT sentence + exx +__PRINT_0Dh: ; Called WHEN printing CHR$(13) + ld hl, (S_POSN) + dec l + jr nz, 1f + dec h + jr nz, 1f + inc h + push hl + call __SCROLL_SCR + pop hl +#line 209 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +1: + ld l, 1 +__PRINT_EOL_END: + call SET_SCR_ADDR + exx + ret +__PRINT_COM: + exx + push hl push de - call __ATTR_ADDR - ld (DFCCL), hl + push bc + call PRINT_COMMA + pop bc pop de - ld a, d - ld c, a ; Saves it for later - and 0F8h ; Masks 3 lower bit ; zy - ld d, a - ld a, c ; Recovers it - and 07h ; MOD 7 ; y1 - rrca - rrca - rrca - or e - ld e, a - ld hl, (SCREEN_ADDR) - add hl, de ; HL = Screen address + DE - ld (DFCC), hl + pop hl + ret +__PRINT_TAB: + ld hl, __PRINT_TAB1 + jr __PRINT_SET_STATE +__PRINT_TAB1: + ld (MEM0), a + ld hl, __PRINT_TAB2 + jr __PRINT_SET_STATE +__PRINT_TAB2: + ld a, (MEM0) ; Load tab code (ignore the current one) + ld hl, __PRINT_START + ld (PRINT_JUMP_STATE), hl + exx + push hl + push bc + push de + call PRINT_TAB + pop de + pop bc + pop hl ret - ENDP - pop namespace -#line 6 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/table_jump.asm" - push namespace core -JUMP_HL_PLUS_2A: ; Does JP (HL + A*2) Modifies DE. Modifies A - add a, a -JUMP_HL_PLUS_A: ; Does JP (HL + A) Modifies DE - ld e, a - ld d, 0 -JUMP_HL_PLUS_DE: ; Does JP (HL + DE) - add hl, de - ld e, (hl) - inc hl - ld d, (hl) - ex de, hl -CALL_HL: - jp (hl) - pop namespace -#line 8 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/ink.asm" - ; Sets ink color in ATTR_P permanently -; Parameter: Paper color in A register - push namespace core -INK: - PROC - LOCAL __SET_INK - LOCAL __SET_INK2 - ld de, ATTR_P -__SET_INK: - cp 8 - jr nz, __SET_INK2 - inc de ; Points DE to MASK_T or MASK_P - ld a, (de) - or 7 ; Set bits 0,1,2 to enable transparency - ld (de), a +__PRINT_AT: + ld hl, __PRINT_AT1 + jr __PRINT_SET_STATE +__PRINT_NOP: +__PRINT_RESTART: + ld hl, __PRINT_START +__PRINT_SET_STATE: + ld (PRINT_JUMP_STATE), hl ; Saves next entry call + exx ret -__SET_INK2: - ; Another entry. This will set the ink color at location pointer by DE - and 7 ; # Gets color mod 8 - ld b, a ; Saves the color - ld a, (de) - and 0F8h ; Clears previous value - or b - ld (de), a - inc de ; Points DE to MASK_T or MASK_P - ld a, (de) - and 0F8h ; Reset bits 0,1,2 sign to disable transparency - ld (de), a ; Store new attr +__PRINT_AT1: ; Jumps here if waiting for 1st parameter + ld hl, (S_POSN) + ld h, a + ld a, SCR_ROWS + sub h + ld (S_POSN + 1), a + ld hl, __PRINT_AT2 + jr __PRINT_SET_STATE +__PRINT_AT2: + call __LOAD_S_POSN + ld e, a + call __SAVE_S_POSN + jr __PRINT_RESTART +__PRINT_DEL: + call __LOAD_S_POSN ; Gets current screen position + dec e + ld a, -1 + cp e + jr nz, 3f + ld e, SCR_COLS - 2 + dec d + cp d + jr nz, 3f + ld d, SCR_ROWS - 1 +3: + call __SAVE_S_POSN + exx ret - ; Sets the INK color passed in A register in the ATTR_T variable -INK_TMP: - ld de, ATTR_T - jp __SET_INK - ENDP - pop namespace -#line 9 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/paper.asm" - ; Sets paper color in ATTR_P permanently -; Parameter: Paper color in A register - push namespace core -PAPER: - PROC - LOCAL __SET_PAPER - LOCAL __SET_PAPER2 - ld de, ATTR_P -__SET_PAPER: - cp 8 - jr nz, __SET_PAPER2 - inc de +__PRINT_INK: + ld hl, __PRINT_INK2 + jr __PRINT_SET_STATE +__PRINT_INK2: + call INK_TMP + jr __PRINT_RESTART +__PRINT_PAP: + ld hl, __PRINT_PAP2 + jr __PRINT_SET_STATE +__PRINT_PAP2: + call PAPER_TMP + jr __PRINT_RESTART +__PRINT_FLA: + ld hl, __PRINT_FLA2 + jr __PRINT_SET_STATE +__PRINT_FLA2: + call FLASH_TMP + jr __PRINT_RESTART +__PRINT_BRI: + ld hl, __PRINT_BRI2 + jr __PRINT_SET_STATE +__PRINT_BRI2: + call BRIGHT_TMP + jr __PRINT_RESTART +__PRINT_INV: + ld hl, __PRINT_INV2 + jr __PRINT_SET_STATE +__PRINT_INV2: + call INVERSE_TMP + jr __PRINT_RESTART +__PRINT_OVR: + ld hl, __PRINT_OVR2 + jr __PRINT_SET_STATE +__PRINT_OVR2: + call OVER_TMP + jr __PRINT_RESTART +__PRINT_BOLD: + ld hl, __PRINT_BOLD2 + jp __PRINT_SET_STATE +__PRINT_BOLD2: + call BOLD_TMP + jp __PRINT_RESTART +#line 353 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +__PRINT_ITA: + ld hl, __PRINT_ITA2 + jp __PRINT_SET_STATE +__PRINT_ITA2: + call ITALIC_TMP + jp __PRINT_RESTART +#line 363 "/zxbasic/src/arch/zx48k/library-asm/print.asm" + LOCAL __BOLD +__BOLD: + push hl + ld hl, MEM0 + ld b, 8 +1: ld a, (de) - or 038h - ld (de), a - ret - ; Another entry. This will set the paper color at location pointer by DE -__SET_PAPER2: - and 7 ; # Remove - rlca + ld c, a rlca - rlca ; a *= 8 - ld b, a ; Saves the color - ld a, (de) - and 0C7h ; Clears previous value - or b - ld (de), a - inc de ; Points to MASK_T or MASK_P accordingly - ld a, (de) - and 0C7h ; Resets bits 3,4,5 - ld (de), a - ret - ; Sets the PAPER color passed in A register in the ATTR_T variable -PAPER_TMP: - ld de, ATTR_T - jp __SET_PAPER - ENDP - pop namespace -#line 10 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/flash.asm" - ; Sets flash flag in ATTR_P permanently -; Parameter: Paper color in A register - push namespace core -FLASH: - ld hl, ATTR_P - PROC - LOCAL IS_TR - LOCAL IS_ZERO -__SET_FLASH: - ; Another entry. This will set the flash flag at location pointer by DE - cp 8 - jr z, IS_TR - ; # Convert to 0/1 - or a - jr z, IS_ZERO - ld a, 0x80 -IS_ZERO: - ld b, a ; Saves the color - ld a, (hl) - and 07Fh ; Clears previous value - or b + or c ld (hl), a inc hl - res 7, (hl) ;Reset bit 7 to disable transparency - ret -IS_TR: ; transparent - inc hl ; Points DE to MASK_T or MASK_P - set 7, (hl) ;Set bit 7 to enable transparency - ret - ; Sets the FLASH flag passed in A register in the ATTR_T variable -FLASH_TMP: - ld hl, ATTR_T - jr __SET_FLASH - ENDP - pop namespace -#line 11 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/bright.asm" - ; Sets bright flag in ATTR_P permanently -; Parameter: Paper color in A register - push namespace core -BRIGHT: - ld hl, ATTR_P - PROC - LOCAL IS_TR - LOCAL IS_ZERO -__SET_BRIGHT: - ; Another entry. This will set the bright flag at location pointer by DE - cp 8 - jr z, IS_TR - ; # Convert to 0/1 - or a - jr z, IS_ZERO - ld a, 0x40 -IS_ZERO: - ld b, a ; Saves the color - ld a, (hl) - and 0BFh ; Clears previous value - or b - ld (hl), a + inc de + djnz 1b + pop hl + ld de, MEM0 + ret +#line 384 "/zxbasic/src/arch/zx48k/library-asm/print.asm" + LOCAL __ITALIC +__ITALIC: + push hl + ld hl, MEM0 + ex de, hl + ld bc, 8 + ldir + ld hl, MEM0 + srl (hl) inc hl - res 6, (hl) ;Reset bit 6 to disable transparency + srl (hl) + inc hl + srl (hl) + inc hl + inc hl + inc hl + sla (hl) + inc hl + sla (hl) + inc hl + sla (hl) + pop hl + ld de, MEM0 ret -IS_TR: ; transparent - inc hl ; Points DE to MASK_T or MASK_P - set 6, (hl) ;Set bit 6 to enable transparency +#line 412 "/zxbasic/src/arch/zx48k/library-asm/print.asm" + LOCAL __SCROLL_SCR +#line 486 "/zxbasic/src/arch/zx48k/library-asm/print.asm" + __SCROLL_SCR EQU 0DFEh ; Use ROM SCROLL +#line 488 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 489 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +PRINT_COMMA: + call __LOAD_S_POSN + ld a, e + and 16 + add a, 16 +PRINT_TAB: + ; Tabulates the number of spaces in A register + ; If the current cursor position is already A, does nothing + PROC + LOCAL LOOP + call __LOAD_S_POSN ; e = current row + sub e + and 31 + ret z + ld b, a +LOOP: + ld a, ' ' + call __PRINTCHAR + djnz LOOP ret - ; Sets the BRIGHT flag passed in A register in the ATTR_T variable -BRIGHT_TMP: - ld hl, ATTR_T - jr __SET_BRIGHT + ENDP +PRINT_AT: ; Changes cursor to ROW, COL + ; COL in A register + ; ROW in stack + pop hl ; Ret address + ex (sp), hl ; callee H = ROW + ld l, a + ex de, hl + call __IN_SCREEN + ret nc ; Return if out of screen + jp __SAVE_S_POSN + LOCAL __PRINT_COM + LOCAL __PRINT_AT1 + LOCAL __PRINT_AT2 + LOCAL __PRINT_BOLD + LOCAL __PRINT_ITA + LOCAL __PRINT_INK + LOCAL __PRINT_PAP + LOCAL __PRINT_SET_STATE + LOCAL __PRINT_TABLE + LOCAL __PRINT_TAB, __PRINT_TAB1, __PRINT_TAB2 + LOCAL __PRINT_ITA2 +#line 545 "/zxbasic/src/arch/zx48k/library-asm/print.asm" + LOCAL __PRINT_BOLD2 +#line 551 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +__PRINT_TABLE: ; Jump table for 0 .. 22 codes + DW __PRINT_NOP ; 0 + DW __PRINT_NOP ; 1 + DW __PRINT_NOP ; 2 + DW __PRINT_NOP ; 3 + DW __PRINT_NOP ; 4 + DW __PRINT_NOP ; 5 + DW __PRINT_COM ; 6 COMMA + DW __PRINT_NOP ; 7 + DW __PRINT_DEL ; 8 DEL + DW __PRINT_NOP ; 9 + DW __PRINT_NOP ; 10 + DW __PRINT_NOP ; 11 + DW __PRINT_NOP ; 12 + DW __PRINT_0Dh ; 13 + DW __PRINT_BOLD ; 14 + DW __PRINT_ITA ; 15 + DW __PRINT_INK ; 16 + DW __PRINT_PAP ; 17 + DW __PRINT_FLA ; 18 + DW __PRINT_BRI ; 19 + DW __PRINT_INV ; 20 + DW __PRINT_OVR ; 21 + DW __PRINT_AT ; 22 AT + DW __PRINT_TAB ; 23 TAB ENDP pop namespace -#line 12 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/over.asm" - ; Sets OVER flag in P_FLAG permanently -; Parameter: OVER flag in bit 0 of A register -#line 1 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" +#line 3 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" #line 4 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" push namespace core COPY_ATTR: @@ -944,517 +991,470 @@ __REFRESH_TMP: ret ENDP pop namespace -#line 4 "/zxbasic/src/arch/zx48k/library-asm/over.asm" - push namespace core -OVER: - PROC - ld c, a ; saves it for later - and 2 - ld hl, FLAGS2 - res 1, (HL) - or (hl) - ld (hl), a - ld a, c ; Recovers previous value - and 1 ; # Convert to 0/1 - add a, a; # Shift left 1 bit for permanent - ld hl, P_FLAG - res 1, (hl) - or (hl) - ld (hl), a - ret - ; Sets OVER flag in P_FLAG temporarily -OVER_TMP: - ld c, a ; saves it for later - and 2 ; gets bit 1; clears carry - rra - ld hl, FLAGS2 - res 0, (hl) - or (hl) - ld (hl), a - ld a, c ; Recovers previous value - and 1 - ld hl, P_FLAG - res 0, (hl) - or (hl) - ld (hl), a - jp __SET_ATTR_MODE - ENDP - pop namespace -#line 13 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/inverse.asm" - ; Sets INVERSE flag in P_FLAG permanently -; Parameter: INVERSE flag in bit 0 of A register - push namespace core -INVERSE: - PROC - and 1 ; # Convert to 0/1 - add a, a; # Shift left 3 bits for permanent - add a, a - add a, a - ld hl, P_FLAG - res 3, (hl) - or (hl) - ld (hl), a - ret - ; Sets INVERSE flag in P_FLAG temporarily -INVERSE_TMP: - and 1 - add a, a - add a, a; # Shift left 2 bits for temporary - ld hl, P_FLAG - res 2, (hl) - or (hl) - ld (hl), a - jp __SET_ATTR_MODE - ENDP - pop namespace -#line 14 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/bold.asm" - ; Sets BOLD flag in P_FLAG permanently -; Parameter: BOLD flag in bit 0 of A register - push namespace core -BOLD: - PROC - and 1 - rlca - rlca - rlca - ld hl, FLAGS2 - res 3, (HL) - or (hl) - ld (hl), a - ret - ; Sets BOLD flag in P_FLAG temporarily -BOLD_TMP: - and 1 - rlca - rlca - ld hl, FLAGS2 - res 2, (hl) - or (hl) - ld (hl), a - ret - ENDP - pop namespace -#line 15 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/italic.asm" - ; Sets ITALIC flag in P_FLAG permanently -; Parameter: ITALIC flag in bit 0 of A register +#line 56 "zx48k/param2.bas" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/free.asm" +; vim: ts=4:et:sw=4: + ; Copyleft (K) by Jose M. Rodriguez de la Rosa + ; (a.k.a. Boriel) +; http://www.boriel.com + ; + ; This ASM library is licensed under the BSD license + ; you can use it for any purpose (even for commercial + ; closed source programs). + ; + ; Please read the BSD license on the internet + ; ----- IMPLEMENTATION NOTES ------ + ; The heap is implemented as a linked list of free blocks. +; Each free block contains this info: + ; + ; +----------------+ <-- HEAP START + ; | Size (2 bytes) | + ; | 0 | <-- Size = 0 => DUMMY HEADER BLOCK + ; +----------------+ + ; | Next (2 bytes) |---+ + ; +----------------+ <-+ + ; | Size (2 bytes) | + ; +----------------+ + ; | Next (2 bytes) |---+ + ; +----------------+ | + ; | | | <-- If Size > 4, then this contains (size - 4) bytes + ; | (0 if Size = 4)| | + ; +----------------+ <-+ + ; | Size (2 bytes) | + ; +----------------+ + ; | Next (2 bytes) |---+ + ; +----------------+ | + ; | | | + ; | (0 if Size = 4)| | + ; +----------------+ | + ; | <-- This zone is in use (Already allocated) + ; +----------------+ <-+ + ; | Size (2 bytes) | + ; +----------------+ + ; | Next (2 bytes) |---+ + ; +----------------+ | + ; | | | + ; | (0 if Size = 4)| | + ; +----------------+ <-+ + ; | Next (2 bytes) |--> NULL => END OF LIST + ; | 0 = NULL | + ; +----------------+ + ; | | + ; | (0 if Size = 4)| + ; +----------------+ + ; When a block is FREED, the previous and next pointers are examined to see + ; if we can defragment the heap. If the block to be breed is just next to the + ; previous, or to the next (or both) they will be converted into a single + ; block (so defragmented). + ; MEMORY MANAGER + ; + ; This library must be initialized calling __MEM_INIT with + ; HL = BLOCK Start & DE = Length. + ; An init directive is useful for initialization routines. + ; They will be added automatically if needed. +#line 1 "/zxbasic/src/arch/zx48k/library-asm/heapinit.asm" +; vim: ts=4:et:sw=4: + ; Copyleft (K) by Jose M. Rodriguez de la Rosa + ; (a.k.a. Boriel) +; http://www.boriel.com + ; + ; This ASM library is licensed under the BSD license + ; you can use it for any purpose (even for commercial + ; closed source programs). + ; + ; Please read the BSD license on the internet + ; ----- IMPLEMENTATION NOTES ------ + ; The heap is implemented as a linked list of free blocks. +; Each free block contains this info: + ; + ; +----------------+ <-- HEAP START + ; | Size (2 bytes) | + ; | 0 | <-- Size = 0 => DUMMY HEADER BLOCK + ; +----------------+ + ; | Next (2 bytes) |---+ + ; +----------------+ <-+ + ; | Size (2 bytes) | + ; +----------------+ + ; | Next (2 bytes) |---+ + ; +----------------+ | + ; | | | <-- If Size > 4, then this contains (size - 4) bytes + ; | (0 if Size = 4)| | + ; +----------------+ <-+ + ; | Size (2 bytes) | + ; +----------------+ + ; | Next (2 bytes) |---+ + ; +----------------+ | + ; | | | + ; | (0 if Size = 4)| | + ; +----------------+ | + ; | <-- This zone is in use (Already allocated) + ; +----------------+ <-+ + ; | Size (2 bytes) | + ; +----------------+ + ; | Next (2 bytes) |---+ + ; +----------------+ | + ; | | | + ; | (0 if Size = 4)| | + ; +----------------+ <-+ + ; | Next (2 bytes) |--> NULL => END OF LIST + ; | 0 = NULL | + ; +----------------+ + ; | | + ; | (0 if Size = 4)| + ; +----------------+ + ; When a block is FREED, the previous and next pointers are examined to see + ; if we can defragment the heap. If the block to be breed is just next to the + ; previous, or to the next (or both) they will be converted into a single + ; block (so defragmented). + ; MEMORY MANAGER + ; + ; This library must be initialized calling __MEM_INIT with + ; HL = BLOCK Start & DE = Length. + ; An init directive is useful for initialization routines. + ; They will be added automatically if needed. + ; --------------------------------------------------------------------- + ; __MEM_INIT must be called to initalize this library with the + ; standard parameters + ; --------------------------------------------------------------------- push namespace core -ITALIC: +__MEM_INIT: ; Initializes the library using (RAMTOP) as start, and + ld hl, ZXBASIC_MEM_HEAP ; Change this with other address of heap start + ld de, ZXBASIC_HEAP_SIZE ; Change this with your size + ; --------------------------------------------------------------------- + ; __MEM_INIT2 initalizes this library +; Parameters: +; HL : Memory address of 1st byte of the memory heap +; DE : Length in bytes of the Memory Heap + ; --------------------------------------------------------------------- +__MEM_INIT2: + ; HL as TOP PROC - and 1 - rrca - rrca - rrca - ld hl, FLAGS2 - res 5, (HL) - or (hl) + dec de + dec de + dec de + dec de ; DE = length - 4; HL = start + ; This is done, because we require 4 bytes for the empty dummy-header block + xor a ld (hl), a - ret - ; Sets ITALIC flag in P_FLAG temporarily -ITALIC_TMP: - and 1 - rrca - rrca - rrca - rrca - ld hl, FLAGS2 - res 4, (hl) - or (hl) + inc hl + ld (hl), a ; First "free" block is a header: size=0, Pointer=&(Block) + 4 + inc hl + ld b, h + ld c, l + inc bc + inc bc ; BC = starts of next block + ld (hl), c + inc hl + ld (hl), b + inc hl ; Pointer to next block + ld (hl), e + inc hl + ld (hl), d + inc hl ; Block size (should be length - 4 at start); This block contains all the available memory + ld (hl), a ; NULL (0000h) ; No more blocks (a list with a single block) + inc hl ld (hl), a + ld a, 201 + ld (__MEM_INIT), a; "Pokes" with a RET so ensure this routine is not called again ret ENDP pop namespace -#line 16 "/zxbasic/src/arch/zx48k/library-asm/print.asm" - ; Putting a comment starting with @INIT
- ; will make the compiler to add a CALL to
- ; It is useful for initialization routines. +#line 69 "/zxbasic/src/arch/zx48k/library-asm/free.asm" + ; --------------------------------------------------------------------- + ; MEM_FREE + ; Frees a block of memory + ; +; Parameters: + ; HL = Pointer to the block to be freed. If HL is NULL (0) nothing + ; is done + ; --------------------------------------------------------------------- push namespace core -__PRINT_INIT: ; To be called before program starts (initializes library) - PROC - ld hl, __PRINT_START - ld (PRINT_JUMP_STATE), hl - ;; Clears ATTR2 flags (OVER 2, etc) - xor a - ld (FLAGS2), a - LOCAL SET_SCR_ADDR - call __LOAD_S_POSN - jp __SET_SCR_PTR - ;; Receives HL = future value of S_POSN - ;; Stores it at (S_POSN) and refresh screen pointers (ATTR, SCR) -SET_SCR_ADDR: - ld (S_POSN), hl - ex de, hl - ld hl, SCR_SIZE - or a - sbc hl, de - ex de, hl - dec e - jp __SET_SCR_PTR -__PRINTCHAR: ; Print character store in accumulator (A register) - ; Modifies H'L', B'C', A'F', D'E', A - LOCAL PO_GR_1 - LOCAL __PRCHAR - LOCAL __PRINT_JUMP - LOCAL __SRCADDR - LOCAL __PRINT_UDG - LOCAL __PRGRAPH - LOCAL __PRINT_START - PRINT_JUMP_STATE EQU __PRINT_JUMP + 2 -__PRINT_JUMP: - exx ; Switch to alternative registers - jp __PRINT_START ; Where to jump. If we print 22 (AT), next two calls jumps to AT1 and AT2 respectively -__PRINT_START: -__PRINT_CHR: - cp ' ' - jr c, __PRINT_SPECIAL ; Characters below ' ' are special ones - ex af, af' ; Saves a value (char to print) for later - ld hl, (S_POSN) - dec l - jr nz, 1f - ld l, SCR_COLS - 1 - dec h - jr nz, 2f - inc h - push hl - call __SCROLL_SCR - pop hl -#line 92 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -2: - call SET_SCR_ADDR - jr 4f -1: - ld (S_POSN), hl -4: - ex af, af' - cp 80h ; Is it a "normal" (printable) char - jr c, __SRCADDR - cp 90h ; Is it an UDG? - jr nc, __PRINT_UDG - ; Print an 8 bit pattern (80h to 8Fh) - ld b, a - call PO_GR_1 ; This ROM routine will generate the bit pattern at MEM0 - ld hl, MEM0 - jp __PRGRAPH - PO_GR_1 EQU 0B38h -__PRINT_UDG: - sub 90h ; Sub ASC code - ld bc, (UDG) - jr __PRGRAPH0 - __SOURCEADDR EQU (__SRCADDR + 1) ; Address of the pointer to chars source -__SRCADDR: - ld bc, (CHARS) -__PRGRAPH0: - add a, a ; A = a * 2 (since a < 80h) ; Thanks to Metalbrain at http://foro.speccy.org - ld l, a - ld h, 0 ; HL = a * 2 (accumulator) - add hl, hl - add hl, hl ; HL = a * 8 - add hl, bc ; HL = CHARS address -__PRGRAPH: - ex de, hl ; HL = Write Address, DE = CHARS address - bit 2, (iy + $47) - call nz, __BOLD -#line 139 "/zxbasic/src/arch/zx48k/library-asm/print.asm" - bit 4, (iy + $47) - call nz, __ITALIC -#line 144 "/zxbasic/src/arch/zx48k/library-asm/print.asm" - ld hl, (DFCC) - push hl - ld b, 8 ; 8 bytes per char -__PRCHAR: - ld a, (de) ; DE *must* be source, and HL destiny -PRINT_MODE: ; Which operation is used to write on the screen - ; Set it with: - ; LD A, - ; LD (PRINT_MODE), A - ; - ; Available operations: - ; NORMAL : 0h --> NOP ; OVER 0 - ; XOR : AEh --> XOR (HL) ; OVER 1 - ; OR : B6h --> OR (HL) ; PUTSPRITE - ; AND : A6h --> AND (HL) ; PUTMASK - nop ; Set to one of the values above -INVERSE_MODE: ; 00 -> NOP -> INVERSE 0 - nop ; 2F -> CPL -> INVERSE 1 - ld (hl), a - inc de - inc h ; Next line - djnz __PRCHAR - pop hl +MEM_FREE: +__MEM_FREE: ; Frees the block pointed by HL + ; HL DE BC & AF modified + PROC + LOCAL __MEM_LOOP2 + LOCAL __MEM_LINK_PREV + LOCAL __MEM_JOIN_TEST + LOCAL __MEM_BLOCK_JOIN + ld a, h + or l + ret z ; Return if NULL pointer + dec hl + dec hl + ld b, h + ld c, l ; BC = Block pointer + ld hl, ZXBASIC_MEM_HEAP ; This label point to the heap start +__MEM_LOOP2: inc hl - ld (DFCC), hl - ld hl, (DFCCL) ; current ATTR Pos - push hl - call __SET_ATTR - pop hl + inc hl ; Next block ptr + ld e, (hl) inc hl - ld (DFCCL),hl - exx - ret - ; ------------- SPECIAL CHARS (< 32) ----------------- -__PRINT_SPECIAL: ; Jumps here if it is a special char - ld hl, __PRINT_TABLE - jp JUMP_HL_PLUS_2A -PRINT_EOL: ; Called WHENEVER there is no ";" at end of PRINT sentence - exx -__PRINT_0Dh: ; Called WHEN printing CHR$(13) - ld hl, (S_POSN) - dec l - jr nz, 1f - dec h - jr nz, 1f - inc h - push hl - call __SCROLL_SCR - pop hl -#line 210 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -1: - ld l, 1 -__PRINT_EOL_END: - call SET_SCR_ADDR - exx - ret -__PRINT_COM: - exx + ld d, (hl) ; Block next ptr + ex de, hl ; DE = &(block->next); HL = block->next + ld a, h ; HL == NULL? + or l + jp z, __MEM_LINK_PREV; if so, link with previous + or a ; Clear carry flag + sbc hl, bc ; Carry if BC > HL => This block if before + add hl, bc ; Restores HL, preserving Carry flag + jp c, __MEM_LOOP2 ; This block is before. Keep searching PASS the block + ;------ At this point current HL is PAST BC, so we must link (DE) with BC, and HL in BC->next +__MEM_LINK_PREV: ; Link (DE) with BC, and BC->next with HL + ex de, hl push hl - push de - push bc - call PRINT_COMMA - pop bc - pop de + dec hl + ld (hl), c + inc hl + ld (hl), b ; (DE) <- BC + ld h, b ; HL <- BC (Free block ptr) + ld l, c + inc hl ; Skip block length (2 bytes) + inc hl + ld (hl), e ; Block->next = DE + inc hl + ld (hl), d + ; --- LINKED ; HL = &(BC->next) + 2 + call __MEM_JOIN_TEST pop hl - ret -__PRINT_TAB: - ld hl, __PRINT_TAB1 - jr __PRINT_SET_STATE -__PRINT_TAB1: - ld (MEM0), a - ld hl, __PRINT_TAB2 - jr __PRINT_SET_STATE -__PRINT_TAB2: - ld a, (MEM0) ; Load tab code (ignore the current one) - ld hl, __PRINT_START - ld (PRINT_JUMP_STATE), hl - exx - push hl - push bc - push de - call PRINT_TAB - pop de - pop bc +__MEM_JOIN_TEST: ; Checks for fragmented contiguous blocks and joins them + ; hl = Ptr to current block + 2 + ld d, (hl) + dec hl + ld e, (hl) + dec hl + ld b, (hl) ; Loads block length into BC + dec hl + ld c, (hl) ; + push hl ; Saves it for later + add hl, bc ; Adds its length. If HL == DE now, it must be joined + or a + sbc hl, de ; If Z, then HL == DE => We must join pop hl + ret nz +__MEM_BLOCK_JOIN: ; Joins current block (pointed by HL) with next one (pointed by DE). HL->length already in BC + push hl ; Saves it for later + ex de, hl + ld e, (hl) ; DE -> block->next->length + inc hl + ld d, (hl) + inc hl + ex de, hl ; DE = &(block->next) + add hl, bc ; HL = Total Length + ld b, h + ld c, l ; BC = Total Length + ex de, hl + ld e, (hl) + inc hl + ld d, (hl) ; DE = block->next + pop hl ; Recovers Pointer to block + ld (hl), c + inc hl + ld (hl), b ; Length Saved + inc hl + ld (hl), e + inc hl + ld (hl), d ; Next saved ret -__PRINT_AT: - ld hl, __PRINT_AT1 - jr __PRINT_SET_STATE -__PRINT_NOP: -__PRINT_RESTART: - ld hl, __PRINT_START -__PRINT_SET_STATE: - ld (PRINT_JUMP_STATE), hl ; Saves next entry call - exx - ret -__PRINT_AT1: ; Jumps here if waiting for 1st parameter - ld hl, (S_POSN) - ld h, a - ld a, SCR_ROWS - sub h - ld (S_POSN + 1), a - ld hl, __PRINT_AT2 - jr __PRINT_SET_STATE -__PRINT_AT2: - call __LOAD_S_POSN - ld e, a - call __SAVE_S_POSN - jr __PRINT_RESTART -__PRINT_DEL: - call __LOAD_S_POSN ; Gets current screen position - dec e - ld a, -1 - cp e - jr nz, 3f - ld e, SCR_COLS - 2 - dec d - cp d - jr nz, 3f - ld d, SCR_ROWS - 1 -3: - call __SAVE_S_POSN - exx - ret -__PRINT_INK: - ld hl, __PRINT_INK2 - jr __PRINT_SET_STATE -__PRINT_INK2: - call INK_TMP - jr __PRINT_RESTART -__PRINT_PAP: - ld hl, __PRINT_PAP2 - jr __PRINT_SET_STATE -__PRINT_PAP2: - call PAPER_TMP - jr __PRINT_RESTART -__PRINT_FLA: - ld hl, __PRINT_FLA2 - jr __PRINT_SET_STATE -__PRINT_FLA2: - call FLASH_TMP - jr __PRINT_RESTART -__PRINT_BRI: - ld hl, __PRINT_BRI2 - jr __PRINT_SET_STATE -__PRINT_BRI2: - call BRIGHT_TMP - jr __PRINT_RESTART -__PRINT_INV: - ld hl, __PRINT_INV2 - jr __PRINT_SET_STATE -__PRINT_INV2: - call INVERSE_TMP - jr __PRINT_RESTART -__PRINT_OVR: - ld hl, __PRINT_OVR2 - jr __PRINT_SET_STATE -__PRINT_OVR2: - call OVER_TMP - jr __PRINT_RESTART -__PRINT_BOLD: - ld hl, __PRINT_BOLD2 - jp __PRINT_SET_STATE -__PRINT_BOLD2: - call BOLD_TMP - jp __PRINT_RESTART -#line 354 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -__PRINT_ITA: - ld hl, __PRINT_ITA2 - jp __PRINT_SET_STATE -__PRINT_ITA2: - call ITALIC_TMP - jp __PRINT_RESTART -#line 364 "/zxbasic/src/arch/zx48k/library-asm/print.asm" - LOCAL __BOLD -__BOLD: - push hl - ld hl, MEM0 - ld b, 8 -1: - ld a, (de) - ld c, a - rlca - or c - ld (hl), a + ENDP + pop namespace +#line 57 "zx48k/param2.bas" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/loadstr.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/alloc.asm" +; vim: ts=4:et:sw=4: + ; Copyleft (K) by Jose M. Rodriguez de la Rosa + ; (a.k.a. Boriel) +; http://www.boriel.com + ; + ; This ASM library is licensed under the MIT license + ; you can use it for any purpose (even for commercial + ; closed source programs). + ; + ; Please read the MIT license on the internet + ; ----- IMPLEMENTATION NOTES ------ + ; The heap is implemented as a linked list of free blocks. +; Each free block contains this info: + ; + ; +----------------+ <-- HEAP START + ; | Size (2 bytes) | + ; | 0 | <-- Size = 0 => DUMMY HEADER BLOCK + ; +----------------+ + ; | Next (2 bytes) |---+ + ; +----------------+ <-+ + ; | Size (2 bytes) | + ; +----------------+ + ; | Next (2 bytes) |---+ + ; +----------------+ | + ; | | | <-- If Size > 4, then this contains (size - 4) bytes + ; | (0 if Size = 4)| | + ; +----------------+ <-+ + ; | Size (2 bytes) | + ; +----------------+ + ; | Next (2 bytes) |---+ + ; +----------------+ | + ; | | | + ; | (0 if Size = 4)| | + ; +----------------+ | + ; | <-- This zone is in use (Already allocated) + ; +----------------+ <-+ + ; | Size (2 bytes) | + ; +----------------+ + ; | Next (2 bytes) |---+ + ; +----------------+ | + ; | | | + ; | (0 if Size = 4)| | + ; +----------------+ <-+ + ; | Next (2 bytes) |--> NULL => END OF LIST + ; | 0 = NULL | + ; +----------------+ + ; | | + ; | (0 if Size = 4)| + ; +----------------+ + ; When a block is FREED, the previous and next pointers are examined to see + ; if we can defragment the heap. If the block to be freed is just next to the + ; previous, or to the next (or both) they will be converted into a single + ; block (so defragmented). + ; MEMORY MANAGER + ; + ; This library must be initialized calling __MEM_INIT with + ; HL = BLOCK Start & DE = Length. + ; An init directive is useful for initialization routines. + ; They will be added automatically if needed. + ; --------------------------------------------------------------------- + ; MEM_ALLOC + ; Allocates a block of memory in the heap. + ; + ; Parameters + ; BC = Length of requested memory block + ; +; Returns: + ; HL = Pointer to the allocated block in memory. Returns 0 (NULL) + ; if the block could not be allocated (out of memory) + ; --------------------------------------------------------------------- + push namespace core +MEM_ALLOC: +__MEM_ALLOC: ; Returns the 1st free block found of the given length (in BC) + PROC + LOCAL __MEM_LOOP + LOCAL __MEM_DONE + LOCAL __MEM_SUBTRACT + LOCAL __MEM_START + LOCAL TEMP, TEMP0 + TEMP EQU TEMP0 + 1 + ld hl, 0 + ld (TEMP), hl +__MEM_START: + ld hl, ZXBASIC_MEM_HEAP ; This label point to the heap start + inc bc + inc bc ; BC = BC + 2 ; block size needs 2 extra bytes for hidden pointer +__MEM_LOOP: ; Loads lengh at (HL, HL+). If Lenght >= BC, jump to __MEM_DONE + ld a, h ; HL = NULL (No memory available?) + or l +#line 113 "/zxbasic/src/arch/zx48k/library-asm/alloc.asm" + ret z ; NULL +#line 115 "/zxbasic/src/arch/zx48k/library-asm/alloc.asm" + ; HL = Pointer to Free block + ld e, (hl) inc hl - inc de - djnz 1b + ld d, (hl) + inc hl ; DE = Block Length + push hl ; HL = *pointer to -> next block + ex de, hl + or a ; CF = 0 + sbc hl, bc ; FREE >= BC (Length) (HL = BlockLength - Length) + jp nc, __MEM_DONE pop hl - ld de, MEM0 - ret -#line 385 "/zxbasic/src/arch/zx48k/library-asm/print.asm" - LOCAL __ITALIC -__ITALIC: - push hl - ld hl, MEM0 + ld (TEMP), hl ex de, hl - ld bc, 8 - ldir - ld hl, MEM0 - srl (hl) - inc hl - srl (hl) - inc hl - srl (hl) - inc hl - inc hl + ld e, (hl) inc hl - sla (hl) + ld d, (hl) + ex de, hl + jp __MEM_LOOP +__MEM_DONE: ; A free block has been found. + ; Check if at least 4 bytes remains free (HL >= 4) + push hl + exx ; exx to preserve bc + pop hl + ld bc, 4 + or a + sbc hl, bc + exx + jp nc, __MEM_SUBTRACT + ; At this point... + ; less than 4 bytes remains free. So we return this block entirely + ; We must link the previous block with the next to this one + ; (DE) => Pointer to next block + ; (TEMP) => &(previous->next) + pop hl ; Discard current block pointer + push de + ex de, hl ; DE = Previous block pointer; (HL) = Next block pointer + ld a, (hl) inc hl - sla (hl) + ld h, (hl) + ld l, a ; HL = (HL) + ex de, hl ; HL = Previous block pointer; DE = Next block pointer +TEMP0: + ld hl, 0 ; Pre-previous block pointer + ld (hl), e inc hl - sla (hl) - pop hl - ld de, MEM0 + ld (hl), d ; LINKED + pop hl ; Returning block. ret -#line 413 "/zxbasic/src/arch/zx48k/library-asm/print.asm" - LOCAL __SCROLL_SCR -#line 487 "/zxbasic/src/arch/zx48k/library-asm/print.asm" - __SCROLL_SCR EQU 0DFEh ; Use ROM SCROLL -#line 489 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -#line 490 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -PRINT_COMMA: - call __LOAD_S_POSN - ld a, e - and 16 - add a, 16 -PRINT_TAB: - ; Tabulates the number of spaces in A register - ; If the current cursor position is already A, does nothing - PROC - LOCAL LOOP - call __LOAD_S_POSN ; e = current row - sub e - and 31 - ret z - ld b, a -LOOP: - ld a, ' ' - call __PRINTCHAR - djnz LOOP +__MEM_SUBTRACT: + ; At this point we have to store HL value (Length - BC) into (DE - 2) + ex de, hl + dec hl + ld (hl), d + dec hl + ld (hl), e ; Store new block length + add hl, de ; New length + DE => free-block start + pop de ; Remove previous HL off the stack + ld (hl), c ; Store length on its 1st word + inc hl + ld (hl), b + inc hl ; Return hl ret ENDP -PRINT_AT: ; Changes cursor to ROW, COL - ; COL in A register - ; ROW in stack - pop hl ; Ret address - ex (sp), hl ; callee H = ROW + pop namespace +#line 2 "/zxbasic/src/arch/zx48k/library-asm/loadstr.asm" + ; Loads a string (ptr) from HL + ; and duplicates it on dynamic memory again + ; Finally, it returns result pointer in HL + push namespace core +__ILOADSTR: ; This is the indirect pointer entry HL = (HL) + ld a, h + or l + ret z + ld a, (hl) + inc hl + ld h, (hl) ld l, a - ex de, hl - call __IN_SCREEN - ret nc ; Return if out of screen - jp __SAVE_S_POSN - LOCAL __PRINT_COM - LOCAL __PRINT_AT1 - LOCAL __PRINT_AT2 - LOCAL __PRINT_BOLD - LOCAL __PRINT_ITA - LOCAL __PRINT_INK - LOCAL __PRINT_PAP - LOCAL __PRINT_SET_STATE - LOCAL __PRINT_TABLE - LOCAL __PRINT_TAB, __PRINT_TAB1, __PRINT_TAB2 - LOCAL __PRINT_ITA2 -#line 546 "/zxbasic/src/arch/zx48k/library-asm/print.asm" - LOCAL __PRINT_BOLD2 -#line 552 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -__PRINT_TABLE: ; Jump table for 0 .. 22 codes - DW __PRINT_NOP ; 0 - DW __PRINT_NOP ; 1 - DW __PRINT_NOP ; 2 - DW __PRINT_NOP ; 3 - DW __PRINT_NOP ; 4 - DW __PRINT_NOP ; 5 - DW __PRINT_COM ; 6 COMMA - DW __PRINT_NOP ; 7 - DW __PRINT_DEL ; 8 DEL - DW __PRINT_NOP ; 9 - DW __PRINT_NOP ; 10 - DW __PRINT_NOP ; 11 - DW __PRINT_NOP ; 12 - DW __PRINT_0Dh ; 13 - DW __PRINT_BOLD ; 14 - DW __PRINT_ITA ; 15 - DW __PRINT_INK ; 16 - DW __PRINT_PAP ; 17 - DW __PRINT_FLA ; 18 - DW __PRINT_BRI ; 19 - DW __PRINT_INV ; 20 - DW __PRINT_OVR ; 21 - DW __PRINT_AT ; 22 AT - DW __PRINT_TAB ; 23 TAB - ENDP +__LOADSTR: ; __FASTCALL__ entry + ld a, h + or l + ret z ; Return if NULL + ld c, (hl) + inc hl + ld b, (hl) + dec hl ; BC = LEN(a$) + inc bc + inc bc ; BC = LEN(a$) + 2 (two bytes for length) + push hl + push bc + call __MEM_ALLOC + pop bc ; Recover length + pop de ; Recover origin + ld a, h + or l + ret z ; Return if NULL (No memory) + ex de, hl ; ldir takes HL as source, DE as destiny, so SWAP HL,DE + push de ; Saves destiny start + ldir ; Copies string (length number included) + pop hl ; Recovers destiny in hl as result + ret pop namespace -#line 57 "zx48k/param2.bas" +#line 58 "zx48k/param2.bas" #line 1 "/zxbasic/src/arch/zx48k/library-asm/printstr.asm" ; PRINT command routine ; Prints string pointed by HL @@ -1498,7 +1498,7 @@ __PRINT_STR: jp __PRINT_STR_LOOP ENDP pop namespace -#line 58 "zx48k/param2.bas" +#line 60 "zx48k/param2.bas" #line 1 "/zxbasic/src/arch/zx48k/library-asm/strcat.asm" #line 1 "/zxbasic/src/arch/zx48k/library-asm/strlen.asm" ; Returns len if a string @@ -1611,5 +1611,5 @@ __STRCATEND: ret ENDP pop namespace -#line 59 "zx48k/param2.bas" +#line 61 "zx48k/param2.bas" END diff --git a/tests/functional/zx48k/parambyref1.asm b/tests/functional/zx48k/parambyref1.asm index 8e2ea62a1..2426779a2 100644 --- a/tests/functional/zx48k/parambyref1.asm +++ b/tests/functional/zx48k/parambyref1.asm @@ -42,6 +42,7 @@ _test2: push ix ld ix, 0 add ix, sp + call .core.COPY_ATTR ld h, (ix+5) ld l, (ix+4) ld c, (hl) @@ -77,6 +78,7 @@ _test__leave: exx ret ;; --- end of user code --- +#line 1 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" #line 1 "/zxbasic/src/arch/zx48k/library-asm/print.asm" ; vim:ts=4:sw=4:et: ; PRINT command routine @@ -426,60 +428,6 @@ BRIGHT_TMP: #line 1 "/zxbasic/src/arch/zx48k/library-asm/over.asm" ; Sets OVER flag in P_FLAG permanently ; Parameter: OVER flag in bit 0 of A register -#line 1 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" -#line 4 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" - push namespace core -COPY_ATTR: - ; Just copies current permanent attribs into temporal attribs - ; and sets print mode - PROC - LOCAL INVERSE1 - LOCAL __REFRESH_TMP - INVERSE1 EQU 02Fh - ld hl, (ATTR_P) - ld (ATTR_T), hl - ld hl, FLAGS2 - call __REFRESH_TMP - ld hl, P_FLAG - call __REFRESH_TMP -__SET_ATTR_MODE: ; Another entry to set print modes. A contains (P_FLAG) - LOCAL TABLE - LOCAL CONT2 - rra ; Over bit to carry - ld a, (FLAGS2) - rla ; Over bit in bit 1, Over2 bit in bit 2 - and 3 ; Only bit 0 and 1 (OVER flag) - ld c, a - ld b, 0 - ld hl, TABLE - add hl, bc - ld a, (hl) - ld (PRINT_MODE), a - ld hl, (P_FLAG) - xor a ; NOP -> INVERSE0 - bit 2, l - jr z, CONT2 - ld a, INVERSE1 ; CPL -> INVERSE1 -CONT2: - ld (INVERSE_MODE), a - ret -TABLE: - nop ; NORMAL MODE - xor (hl) ; OVER 1 MODE - and (hl) ; OVER 2 MODE - or (hl) ; OVER 3 MODE -#line 67 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" -__REFRESH_TMP: - ld a, (hl) - and 0b10101010 - ld c, a - rra - or c - ld (hl), a - ret - ENDP - pop namespace -#line 4 "/zxbasic/src/arch/zx48k/library-asm/over.asm" push namespace core OVER: PROC @@ -721,11 +669,10 @@ INVERSE_MODE: ; 00 -> NOP -> INVERSE 0 inc hl ld (DFCC), hl ld hl, (DFCCL) ; current ATTR Pos - push hl - call __SET_ATTR - pop hl inc hl - ld (DFCCL),hl + ld (DFCCL), hl + dec hl + call __SET_ATTR exx ret ; ------------- SPECIAL CHARS (< 32) ----------------- @@ -744,7 +691,7 @@ __PRINT_0Dh: ; Called WHEN printing CHR$(13) push hl call __SCROLL_SCR pop hl -#line 210 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 209 "/zxbasic/src/arch/zx48k/library-asm/print.asm" 1: ld l, 1 __PRINT_EOL_END: @@ -861,14 +808,14 @@ __PRINT_BOLD: __PRINT_BOLD2: call BOLD_TMP jp __PRINT_RESTART -#line 354 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 353 "/zxbasic/src/arch/zx48k/library-asm/print.asm" __PRINT_ITA: ld hl, __PRINT_ITA2 jp __PRINT_SET_STATE __PRINT_ITA2: call ITALIC_TMP jp __PRINT_RESTART -#line 364 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 363 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __BOLD __BOLD: push hl @@ -886,7 +833,7 @@ __BOLD: pop hl ld de, MEM0 ret -#line 385 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 384 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __ITALIC __ITALIC: push hl @@ -911,12 +858,12 @@ __ITALIC: pop hl ld de, MEM0 ret -#line 413 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 412 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __SCROLL_SCR -#line 487 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 486 "/zxbasic/src/arch/zx48k/library-asm/print.asm" __SCROLL_SCR EQU 0DFEh ; Use ROM SCROLL +#line 488 "/zxbasic/src/arch/zx48k/library-asm/print.asm" #line 489 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -#line 490 "/zxbasic/src/arch/zx48k/library-asm/print.asm" PRINT_COMMA: call __LOAD_S_POSN ld a, e @@ -959,9 +906,9 @@ PRINT_AT: ; Changes cursor to ROW, COL LOCAL __PRINT_TABLE LOCAL __PRINT_TAB, __PRINT_TAB1, __PRINT_TAB2 LOCAL __PRINT_ITA2 -#line 546 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 545 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __PRINT_BOLD2 -#line 552 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 551 "/zxbasic/src/arch/zx48k/library-asm/print.asm" __PRINT_TABLE: ; Jump table for 0 .. 22 codes DW __PRINT_NOP ; 0 DW __PRINT_NOP ; 1 @@ -989,7 +936,60 @@ __PRINT_TABLE: ; Jump table for 0 .. 22 codes DW __PRINT_TAB ; 23 TAB ENDP pop namespace -#line 58 "zx48k/parambyref1.bas" +#line 3 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" +#line 4 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" + push namespace core +COPY_ATTR: + ; Just copies current permanent attribs into temporal attribs + ; and sets print mode + PROC + LOCAL INVERSE1 + LOCAL __REFRESH_TMP + INVERSE1 EQU 02Fh + ld hl, (ATTR_P) + ld (ATTR_T), hl + ld hl, FLAGS2 + call __REFRESH_TMP + ld hl, P_FLAG + call __REFRESH_TMP +__SET_ATTR_MODE: ; Another entry to set print modes. A contains (P_FLAG) + LOCAL TABLE + LOCAL CONT2 + rra ; Over bit to carry + ld a, (FLAGS2) + rla ; Over bit in bit 1, Over2 bit in bit 2 + and 3 ; Only bit 0 and 1 (OVER flag) + ld c, a + ld b, 0 + ld hl, TABLE + add hl, bc + ld a, (hl) + ld (PRINT_MODE), a + ld hl, (P_FLAG) + xor a ; NOP -> INVERSE0 + bit 2, l + jr z, CONT2 + ld a, INVERSE1 ; CPL -> INVERSE1 +CONT2: + ld (INVERSE_MODE), a + ret +TABLE: + nop ; NORMAL MODE + xor (hl) ; OVER 1 MODE + and (hl) ; OVER 2 MODE + or (hl) ; OVER 3 MODE +#line 67 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" +__REFRESH_TMP: + ld a, (hl) + and 0b10101010 + ld c, a + rra + or c + ld (hl), a + ret + ENDP + pop namespace +#line 59 "zx48k/parambyref1.bas" #line 1 "/zxbasic/src/arch/zx48k/library-asm/printu16.asm" #line 1 "/zxbasic/src/arch/zx48k/library-asm/printi16.asm" #line 1 "/zxbasic/src/arch/zx48k/library-asm/printnum.asm" @@ -1137,5 +1137,5 @@ __PRINTU_LOOP: ENDP pop namespace #line 2 "/zxbasic/src/arch/zx48k/library-asm/printu16.asm" -#line 59 "zx48k/parambyref1.bas" +#line 61 "zx48k/parambyref1.bas" END diff --git a/tests/functional/zx48k/plot.asm b/tests/functional/zx48k/plot.asm index a03cf091e..604241d90 100644 --- a/tests/functional/zx48k/plot.asm +++ b/tests/functional/zx48k/plot.asm @@ -24,10 +24,12 @@ _b: DEFB 00, 00, 00, 00, 00 .core.ZXBASIC_USER_DATA_END: .core.__MAIN_PROGRAM__: + call .core.COPY_ATTR ld a, 11 push af ld a, 22 call .core.PLOT + call .core.COPY_ATTR ld a, (_a) ld de, (_a + 1) ld bc, (_a + 3) @@ -36,6 +38,7 @@ _b: push af ld a, 22 call .core.PLOT + call .core.COPY_ATTR ld a, 11 push af ld a, (_a) @@ -44,6 +47,7 @@ _b: call .core.__FTOU32REG ld a, l call .core.PLOT + call .core.COPY_ATTR ld a, (_a) ld de, (_a + 1) ld bc, (_a + 3) @@ -71,6 +75,64 @@ _b: ei ret ;; --- end of user code --- +#line 1 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" +#line 4 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/sysvars.asm" + ;; ----------------------------------------------------------------------- + ;; ZX Basic System Vars + ;; Some of them will be mapped over Sinclair ROM ones for compatibility + ;; ----------------------------------------------------------------------- + push namespace core +SCREEN_ADDR: DW 16384 ; Screen address (can be pointed to other place to use a screen buffer) +SCREEN_ATTR_ADDR: DW 22528 ; Screen attribute address (ditto.) + ; These are mapped onto ZX Spectrum ROM VARS + CHARS EQU 23606 ; Pointer to ROM/RAM Charset + TVFLAGS EQU 23612 ; TV Flags + UDG EQU 23675 ; Pointer to UDG Charset + COORDS EQU 23677 ; Last PLOT coordinates + FLAGS2 EQU 23681 ; + ECHO_E EQU 23682 ; + DFCC EQU 23684 ; Next screen addr for PRINT + DFCCL EQU 23686 ; Next screen attr for PRINT + S_POSN EQU 23688 + ATTR_P EQU 23693 ; Current Permanent ATTRS set with INK, PAPER, etc commands + ATTR_T EQU 23695 ; temporary ATTRIBUTES + P_FLAG EQU 23697 ; + MEM0 EQU 23698 ; Temporary memory buffer used by ROM chars + SCR_COLS EQU 33 ; Screen with in columns + 1 + SCR_ROWS EQU 24 ; Screen height in rows + SCR_SIZE EQU (SCR_ROWS << 8) + SCR_COLS + pop namespace +#line 6 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" + push namespace core +COPY_ATTR: + ; Just copies current permanent attribs into temporal attribs + ; and sets print mode + PROC + LOCAL INVERSE1 + LOCAL __REFRESH_TMP + INVERSE1 EQU 02Fh + ld hl, (ATTR_P) + ld (ATTR_T), hl + ld hl, FLAGS2 + call __REFRESH_TMP + ld hl, P_FLAG + call __REFRESH_TMP +__SET_ATTR_MODE: ; Another entry to set print modes. A contains (P_FLAG) +#line 65 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" + ret +#line 67 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" +__REFRESH_TMP: + ld a, (hl) + and 0b10101010 + ld c, a + rra + or c + ld (hl), a + ret + ENDP + pop namespace +#line 53 "zx48k/plot.bas" #line 1 "/zxbasic/src/arch/zx48k/library-asm/ftou32reg.asm" #line 1 "/zxbasic/src/arch/zx48k/library-asm/neg32.asm" push namespace core @@ -169,7 +231,7 @@ __FTOU8: ; Converts float in C ED LH to Unsigned byte in A ld a, l ret pop namespace -#line 49 "zx48k/plot.bas" +#line 54 "zx48k/plot.bas" #line 1 "/zxbasic/src/arch/zx48k/library-asm/plot.asm" ; MIXED __FASTCAL__ / __CALLE__ PLOT Function ; Plots a point into the screen calling the ZX ROM PLOT routine @@ -212,33 +274,6 @@ __STOP: #line 8 "/zxbasic/src/arch/zx48k/library-asm/plot.asm" #line 1 "/zxbasic/src/arch/zx48k/library-asm/in_screen.asm" #line 1 "/zxbasic/src/arch/zx48k/library-asm/sposn.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/sysvars.asm" - ;; ----------------------------------------------------------------------- - ;; ZX Basic System Vars - ;; Some of them will be mapped over Sinclair ROM ones for compatibility - ;; ----------------------------------------------------------------------- - push namespace core -SCREEN_ADDR: DW 16384 ; Screen address (can be pointed to other place to use a screen buffer) -SCREEN_ATTR_ADDR: DW 22528 ; Screen attribute address (ditto.) - ; These are mapped onto ZX Spectrum ROM VARS - CHARS EQU 23606 ; Pointer to ROM/RAM Charset - TVFLAGS EQU 23612 ; TV Flags - UDG EQU 23675 ; Pointer to UDG Charset - COORDS EQU 23677 ; Last PLOT coordinates - FLAGS2 EQU 23681 ; - ECHO_E EQU 23682 ; - DFCC EQU 23684 ; Next screen addr for PRINT - DFCCL EQU 23686 ; Next screen attr for PRINT - S_POSN EQU 23688 - ATTR_P EQU 23693 ; Current Permanent ATTRS set with INK, PAPER, etc commands - ATTR_T EQU 23695 ; temporary ATTRIBUTES - P_FLAG EQU 23697 ; - MEM0 EQU 23698 ; Temporary memory buffer used by ROM chars - SCR_COLS EQU 33 ; Screen with in columns + 1 - SCR_ROWS EQU 24 ; Screen height in rows - SCR_SIZE EQU (SCR_ROWS << 8) + SCR_COLS - pop namespace -#line 2 "/zxbasic/src/arch/zx48k/library-asm/sposn.asm" #line 1 "/zxbasic/src/arch/zx48k/library-asm/attr.asm" ; Attribute routines ; vim:ts=4:et:sw: @@ -422,5 +457,5 @@ __PLOT_ERR: COORDS EQU 5C7Dh ENDP pop namespace -#line 50 "zx48k/plot.bas" +#line 55 "zx48k/plot.bas" END diff --git a/tests/functional/zx48k/print.asm b/tests/functional/zx48k/print.asm index 05a49640f..ce17dac9b 100644 --- a/tests/functional/zx48k/print.asm +++ b/tests/functional/zx48k/print.asm @@ -28,37 +28,45 @@ _a: DEFB 00, 00 .core.ZXBASIC_USER_DATA_END: .core.__MAIN_PROGRAM__: + call .core.COPY_ATTR ld a, 3 call .core.__PRINTU8 call .core.PRINT_EOL + call .core.COPY_ATTR ld a, 3 call .core.__PRINTI8 call .core.PRINT_EOL + call .core.COPY_ATTR ld hl, 3 call .core.__PRINTU16 call .core.PRINT_EOL + call .core.COPY_ATTR ld hl, 3 call .core.__PRINTI16 call .core.PRINT_EOL + call .core.COPY_ATTR ld de, 3 ld hl, 0 call .core.__PRINTF16 call .core.PRINT_EOL + call .core.COPY_ATTR ld a, 082h ld de, 00040h ld bc, 00000h call .core.__PRINTF call .core.PRINT_EOL + call .core.COPY_ATTR ld hl, .LABEL.__LABEL0 xor a call .core.__PRINTSTR call .core.PRINT_EOL + call .core.COPY_ATTR ld de, (_a) ld hl, .LABEL.__LABEL0 call .core.__ADDSTR ld a, 1 call .core.__PRINTSTR - call .core.PRINT_EOL_ATTR + call .core.PRINT_EOL ld hl, 0 ld b, h ld c, l @@ -77,6 +85,7 @@ _a: DEFW 0001h DEFB 33h ;; --- end of user code --- +#line 1 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" #line 1 "/zxbasic/src/arch/zx48k/library-asm/print.asm" ; vim:ts=4:sw=4:et: ; PRINT command routine @@ -426,60 +435,6 @@ BRIGHT_TMP: #line 1 "/zxbasic/src/arch/zx48k/library-asm/over.asm" ; Sets OVER flag in P_FLAG permanently ; Parameter: OVER flag in bit 0 of A register -#line 1 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" -#line 4 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" - push namespace core -COPY_ATTR: - ; Just copies current permanent attribs into temporal attribs - ; and sets print mode - PROC - LOCAL INVERSE1 - LOCAL __REFRESH_TMP - INVERSE1 EQU 02Fh - ld hl, (ATTR_P) - ld (ATTR_T), hl - ld hl, FLAGS2 - call __REFRESH_TMP - ld hl, P_FLAG - call __REFRESH_TMP -__SET_ATTR_MODE: ; Another entry to set print modes. A contains (P_FLAG) - LOCAL TABLE - LOCAL CONT2 - rra ; Over bit to carry - ld a, (FLAGS2) - rla ; Over bit in bit 1, Over2 bit in bit 2 - and 3 ; Only bit 0 and 1 (OVER flag) - ld c, a - ld b, 0 - ld hl, TABLE - add hl, bc - ld a, (hl) - ld (PRINT_MODE), a - ld hl, (P_FLAG) - xor a ; NOP -> INVERSE0 - bit 2, l - jr z, CONT2 - ld a, INVERSE1 ; CPL -> INVERSE1 -CONT2: - ld (INVERSE_MODE), a - ret -TABLE: - nop ; NORMAL MODE - xor (hl) ; OVER 1 MODE - and (hl) ; OVER 2 MODE - or (hl) ; OVER 3 MODE -#line 67 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" -__REFRESH_TMP: - ld a, (hl) - and 0b10101010 - ld c, a - rra - or c - ld (hl), a - ret - ENDP - pop namespace -#line 4 "/zxbasic/src/arch/zx48k/library-asm/over.asm" push namespace core OVER: PROC @@ -721,11 +676,10 @@ INVERSE_MODE: ; 00 -> NOP -> INVERSE 0 inc hl ld (DFCC), hl ld hl, (DFCCL) ; current ATTR Pos - push hl - call __SET_ATTR - pop hl inc hl - ld (DFCCL),hl + ld (DFCCL), hl + dec hl + call __SET_ATTR exx ret ; ------------- SPECIAL CHARS (< 32) ----------------- @@ -744,7 +698,7 @@ __PRINT_0Dh: ; Called WHEN printing CHR$(13) push hl call __SCROLL_SCR pop hl -#line 210 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 209 "/zxbasic/src/arch/zx48k/library-asm/print.asm" 1: ld l, 1 __PRINT_EOL_END: @@ -861,14 +815,14 @@ __PRINT_BOLD: __PRINT_BOLD2: call BOLD_TMP jp __PRINT_RESTART -#line 354 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 353 "/zxbasic/src/arch/zx48k/library-asm/print.asm" __PRINT_ITA: ld hl, __PRINT_ITA2 jp __PRINT_SET_STATE __PRINT_ITA2: call ITALIC_TMP jp __PRINT_RESTART -#line 364 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 363 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __BOLD __BOLD: push hl @@ -886,7 +840,7 @@ __BOLD: pop hl ld de, MEM0 ret -#line 385 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 384 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __ITALIC __ITALIC: push hl @@ -911,12 +865,12 @@ __ITALIC: pop hl ld de, MEM0 ret -#line 413 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 412 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __SCROLL_SCR -#line 487 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 486 "/zxbasic/src/arch/zx48k/library-asm/print.asm" __SCROLL_SCR EQU 0DFEh ; Use ROM SCROLL +#line 488 "/zxbasic/src/arch/zx48k/library-asm/print.asm" #line 489 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -#line 490 "/zxbasic/src/arch/zx48k/library-asm/print.asm" PRINT_COMMA: call __LOAD_S_POSN ld a, e @@ -959,9 +913,9 @@ PRINT_AT: ; Changes cursor to ROW, COL LOCAL __PRINT_TABLE LOCAL __PRINT_TAB, __PRINT_TAB1, __PRINT_TAB2 LOCAL __PRINT_ITA2 -#line 546 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 545 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __PRINT_BOLD2 -#line 552 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 551 "/zxbasic/src/arch/zx48k/library-asm/print.asm" __PRINT_TABLE: ; Jump table for 0 .. 22 codes DW __PRINT_NOP ; 0 DW __PRINT_NOP ; 1 @@ -989,16 +943,60 @@ __PRINT_TABLE: ; Jump table for 0 .. 22 codes DW __PRINT_TAB ; 23 TAB ENDP pop namespace -#line 51 "zx48k/print.bas" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/print_eol_attr.asm" - ; Calls PRINT_EOL and then COPY_ATTR, so saves - ; 3 bytes +#line 3 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" +#line 4 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" push namespace core -PRINT_EOL_ATTR: - call PRINT_EOL - jp COPY_ATTR +COPY_ATTR: + ; Just copies current permanent attribs into temporal attribs + ; and sets print mode + PROC + LOCAL INVERSE1 + LOCAL __REFRESH_TMP + INVERSE1 EQU 02Fh + ld hl, (ATTR_P) + ld (ATTR_T), hl + ld hl, FLAGS2 + call __REFRESH_TMP + ld hl, P_FLAG + call __REFRESH_TMP +__SET_ATTR_MODE: ; Another entry to set print modes. A contains (P_FLAG) + LOCAL TABLE + LOCAL CONT2 + rra ; Over bit to carry + ld a, (FLAGS2) + rla ; Over bit in bit 1, Over2 bit in bit 2 + and 3 ; Only bit 0 and 1 (OVER flag) + ld c, a + ld b, 0 + ld hl, TABLE + add hl, bc + ld a, (hl) + ld (PRINT_MODE), a + ld hl, (P_FLAG) + xor a ; NOP -> INVERSE0 + bit 2, l + jr z, CONT2 + ld a, INVERSE1 ; CPL -> INVERSE1 +CONT2: + ld (INVERSE_MODE), a + ret +TABLE: + nop ; NORMAL MODE + xor (hl) ; OVER 1 MODE + and (hl) ; OVER 2 MODE + or (hl) ; OVER 3 MODE +#line 67 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" +__REFRESH_TMP: + ld a, (hl) + and 0b10101010 + ld c, a + rra + or c + ld (hl), a + ret + ENDP pop namespace -#line 52 "zx48k/print.bas" +#line 59 "zx48k/print.bas" #line 1 "/zxbasic/src/arch/zx48k/library-asm/printf.asm" #line 1 "/zxbasic/src/arch/zx48k/library-asm/printstr.asm" #line 1 "/zxbasic/src/arch/zx48k/library-asm/free.asm" @@ -1380,7 +1378,7 @@ __PRINTF: ; Prints a Fixed point Number stored in C ED LH RECLAIM2 EQU 19E8h ENDP pop namespace -#line 53 "zx48k/print.bas" +#line 61 "zx48k/print.bas" #line 1 "/zxbasic/src/arch/zx48k/library-asm/printf16.asm" #line 1 "/zxbasic/src/arch/zx48k/library-asm/printnum.asm" push namespace core @@ -1598,7 +1596,7 @@ __PRINT_FIX_LOOP: jp __PRINT_FIX_LOOP ENDP pop namespace -#line 54 "zx48k/print.bas" +#line 62 "zx48k/print.bas" #line 1 "/zxbasic/src/arch/zx48k/library-asm/printi8.asm" #line 1 "/zxbasic/src/arch/zx48k/library-asm/div8.asm" ; -------------------------------- @@ -1694,11 +1692,11 @@ __PRINTU_LOOP: jp __PRINTU_LOOP ; Uses JP in loops ENDP pop namespace -#line 56 "zx48k/print.bas" +#line 64 "zx48k/print.bas" #line 1 "/zxbasic/src/arch/zx48k/library-asm/printu16.asm" -#line 58 "zx48k/print.bas" +#line 66 "zx48k/print.bas" #line 1 "/zxbasic/src/arch/zx48k/library-asm/printu8.asm" -#line 59 "zx48k/print.bas" +#line 67 "zx48k/print.bas" #line 1 "/zxbasic/src/arch/zx48k/library-asm/strcat.asm" #line 1 "/zxbasic/src/arch/zx48k/library-asm/alloc.asm" ; vim: ts=4:et:sw=4: @@ -1969,5 +1967,5 @@ __STRCATEND: ret ENDP pop namespace -#line 60 "zx48k/print.bas" +#line 68 "zx48k/print.bas" END diff --git a/tests/functional/zx48k/print_arrstr.asm b/tests/functional/zx48k/print_arrstr.asm index 1f28cc39a..7e35f60c7 100644 --- a/tests/functional/zx48k/print_arrstr.asm +++ b/tests/functional/zx48k/print_arrstr.asm @@ -59,6 +59,7 @@ _a.__DATA__: ld de, .LABEL.__LABEL0 ld hl, _a.__DATA__ + 10 call .core.__STORE_STR + call .core.COPY_ATTR ld hl, (_a.__DATA__ + 10) call .core.__LOADSTR ld a, 1 @@ -92,67 +93,42 @@ _a.__DATA__: DEFB 4Ch DEFB 44h ;; --- end of user code --- -#line 1 "/zxbasic/src/arch/zx48k/library-asm/loadstr.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/alloc.asm" -; vim: ts=4:et:sw=4: - ; Copyleft (K) by Jose M. Rodriguez de la Rosa - ; (a.k.a. Boriel) -; http://www.boriel.com - ; - ; This ASM library is licensed under the MIT license - ; you can use it for any purpose (even for commercial - ; closed source programs). - ; - ; Please read the MIT license on the internet - ; ----- IMPLEMENTATION NOTES ------ - ; The heap is implemented as a linked list of free blocks. -; Each free block contains this info: - ; - ; +----------------+ <-- HEAP START - ; | Size (2 bytes) | - ; | 0 | <-- Size = 0 => DUMMY HEADER BLOCK - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ <-+ - ; | Size (2 bytes) | - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ | - ; | | | <-- If Size > 4, then this contains (size - 4) bytes - ; | (0 if Size = 4)| | - ; +----------------+ <-+ - ; | Size (2 bytes) | - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ | - ; | | | - ; | (0 if Size = 4)| | - ; +----------------+ | - ; | <-- This zone is in use (Already allocated) - ; +----------------+ <-+ - ; | Size (2 bytes) | - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ | - ; | | | - ; | (0 if Size = 4)| | - ; +----------------+ <-+ - ; | Next (2 bytes) |--> NULL => END OF LIST - ; | 0 = NULL | - ; +----------------+ - ; | | - ; | (0 if Size = 4)| - ; +----------------+ - ; When a block is FREED, the previous and next pointers are examined to see - ; if we can defragment the heap. If the block to be freed is just next to the - ; previous, or to the next (or both) they will be converted into a single - ; block (so defragmented). - ; MEMORY MANAGER - ; - ; This library must be initialized calling __MEM_INIT with - ; HL = BLOCK Start & DE = Length. - ; An init directive is useful for initialization routines. - ; They will be added automatically if needed. +#line 1 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +; vim:ts=4:sw=4:et: + ; PRINT command routine + ; Does not print attribute. Use PRINT_STR or PRINT_NUM for that +#line 1 "/zxbasic/src/arch/zx48k/library-asm/sposn.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/sysvars.asm" + ;; ----------------------------------------------------------------------- + ;; ZX Basic System Vars + ;; Some of them will be mapped over Sinclair ROM ones for compatibility + ;; ----------------------------------------------------------------------- + push namespace core +SCREEN_ADDR: DW 16384 ; Screen address (can be pointed to other place to use a screen buffer) +SCREEN_ATTR_ADDR: DW 22528 ; Screen attribute address (ditto.) + ; These are mapped onto ZX Spectrum ROM VARS + CHARS EQU 23606 ; Pointer to ROM/RAM Charset + TVFLAGS EQU 23612 ; TV Flags + UDG EQU 23675 ; Pointer to UDG Charset + COORDS EQU 23677 ; Last PLOT coordinates + FLAGS2 EQU 23681 ; + ECHO_E EQU 23682 ; + DFCC EQU 23684 ; Next screen addr for PRINT + DFCCL EQU 23686 ; Next screen attr for PRINT + S_POSN EQU 23688 + ATTR_P EQU 23693 ; Current Permanent ATTRS set with INK, PAPER, etc commands + ATTR_T EQU 23695 ; temporary ATTRIBUTES + P_FLAG EQU 23697 ; + MEM0 EQU 23698 ; Temporary memory buffer used by ROM chars + SCR_COLS EQU 33 ; Screen with in columns + 1 + SCR_ROWS EQU 24 ; Screen height in rows + SCR_SIZE EQU (SCR_ROWS << 8) + SCR_COLS + pop namespace +#line 2 "/zxbasic/src/arch/zx48k/library-asm/sposn.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/attr.asm" + ; Attribute routines +; vim:ts=4:et:sw: #line 1 "/zxbasic/src/arch/zx48k/library-asm/error.asm" ; Simple error control routines ; vim:ts=4:et: @@ -187,307 +163,29 @@ __STOP: ld (ERR_NR), a ret pop namespace -#line 69 "/zxbasic/src/arch/zx48k/library-asm/alloc.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/heapinit.asm" -; vim: ts=4:et:sw=4: - ; Copyleft (K) by Jose M. Rodriguez de la Rosa - ; (a.k.a. Boriel) -; http://www.boriel.com - ; - ; This ASM library is licensed under the BSD license - ; you can use it for any purpose (even for commercial - ; closed source programs). - ; - ; Please read the BSD license on the internet - ; ----- IMPLEMENTATION NOTES ------ - ; The heap is implemented as a linked list of free blocks. -; Each free block contains this info: - ; - ; +----------------+ <-- HEAP START - ; | Size (2 bytes) | - ; | 0 | <-- Size = 0 => DUMMY HEADER BLOCK - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ <-+ - ; | Size (2 bytes) | - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ | - ; | | | <-- If Size > 4, then this contains (size - 4) bytes - ; | (0 if Size = 4)| | - ; +----------------+ <-+ - ; | Size (2 bytes) | - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ | - ; | | | - ; | (0 if Size = 4)| | - ; +----------------+ | - ; | <-- This zone is in use (Already allocated) - ; +----------------+ <-+ - ; | Size (2 bytes) | - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ | - ; | | | - ; | (0 if Size = 4)| | - ; +----------------+ <-+ - ; | Next (2 bytes) |--> NULL => END OF LIST - ; | 0 = NULL | - ; +----------------+ - ; | | - ; | (0 if Size = 4)| - ; +----------------+ - ; When a block is FREED, the previous and next pointers are examined to see - ; if we can defragment the heap. If the block to be breed is just next to the - ; previous, or to the next (or both) they will be converted into a single - ; block (so defragmented). - ; MEMORY MANAGER - ; - ; This library must be initialized calling __MEM_INIT with - ; HL = BLOCK Start & DE = Length. - ; An init directive is useful for initialization routines. - ; They will be added automatically if needed. - ; --------------------------------------------------------------------- - ; __MEM_INIT must be called to initalize this library with the - ; standard parameters - ; --------------------------------------------------------------------- +#line 6 "/zxbasic/src/arch/zx48k/library-asm/attr.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/in_screen.asm" push namespace core -__MEM_INIT: ; Initializes the library using (RAMTOP) as start, and - ld hl, ZXBASIC_MEM_HEAP ; Change this with other address of heap start - ld de, ZXBASIC_HEAP_SIZE ; Change this with your size - ; --------------------------------------------------------------------- - ; __MEM_INIT2 initalizes this library -; Parameters: -; HL : Memory address of 1st byte of the memory heap -; DE : Length in bytes of the Memory Heap - ; --------------------------------------------------------------------- -__MEM_INIT2: - ; HL as TOP +__IN_SCREEN: + ; Returns NO carry if current coords (D, E) + ; are OUT of the screen limits PROC - dec de - dec de - dec de - dec de ; DE = length - 4; HL = start - ; This is done, because we require 4 bytes for the empty dummy-header block - xor a - ld (hl), a - inc hl - ld (hl), a ; First "free" block is a header: size=0, Pointer=&(Block) + 4 - inc hl - ld b, h - ld c, l - inc bc - inc bc ; BC = starts of next block - ld (hl), c - inc hl - ld (hl), b - inc hl ; Pointer to next block - ld (hl), e - inc hl - ld (hl), d - inc hl ; Block size (should be length - 4 at start); This block contains all the available memory - ld (hl), a ; NULL (0000h) ; No more blocks (a list with a single block) - inc hl - ld (hl), a - ld a, 201 - ld (__MEM_INIT), a; "Pokes" with a RET so ensure this routine is not called again - ret + LOCAL __IN_SCREEN_ERR + ld hl, SCR_SIZE + ld a, e + cp l + jr nc, __IN_SCREEN_ERR ; Do nothing and return if out of range + ld a, d + cp h + ret c ; Return if carry (OK) +__IN_SCREEN_ERR: +__OUT_OF_SCREEN_ERR: + ; Jumps here if out of screen + ld a, ERROR_OutOfScreen + jp __STOP ; Saves error code and exits ENDP pop namespace -#line 70 "/zxbasic/src/arch/zx48k/library-asm/alloc.asm" - ; --------------------------------------------------------------------- - ; MEM_ALLOC - ; Allocates a block of memory in the heap. - ; - ; Parameters - ; BC = Length of requested memory block - ; -; Returns: - ; HL = Pointer to the allocated block in memory. Returns 0 (NULL) - ; if the block could not be allocated (out of memory) - ; --------------------------------------------------------------------- - push namespace core -MEM_ALLOC: -__MEM_ALLOC: ; Returns the 1st free block found of the given length (in BC) - PROC - LOCAL __MEM_LOOP - LOCAL __MEM_DONE - LOCAL __MEM_SUBTRACT - LOCAL __MEM_START - LOCAL TEMP, TEMP0 - TEMP EQU TEMP0 + 1 - ld hl, 0 - ld (TEMP), hl -__MEM_START: - ld hl, ZXBASIC_MEM_HEAP ; This label point to the heap start - inc bc - inc bc ; BC = BC + 2 ; block size needs 2 extra bytes for hidden pointer -__MEM_LOOP: ; Loads lengh at (HL, HL+). If Lenght >= BC, jump to __MEM_DONE - ld a, h ; HL = NULL (No memory available?) - or l -#line 113 "/zxbasic/src/arch/zx48k/library-asm/alloc.asm" - ret z ; NULL -#line 115 "/zxbasic/src/arch/zx48k/library-asm/alloc.asm" - ; HL = Pointer to Free block - ld e, (hl) - inc hl - ld d, (hl) - inc hl ; DE = Block Length - push hl ; HL = *pointer to -> next block - ex de, hl - or a ; CF = 0 - sbc hl, bc ; FREE >= BC (Length) (HL = BlockLength - Length) - jp nc, __MEM_DONE - pop hl - ld (TEMP), hl - ex de, hl - ld e, (hl) - inc hl - ld d, (hl) - ex de, hl - jp __MEM_LOOP -__MEM_DONE: ; A free block has been found. - ; Check if at least 4 bytes remains free (HL >= 4) - push hl - exx ; exx to preserve bc - pop hl - ld bc, 4 - or a - sbc hl, bc - exx - jp nc, __MEM_SUBTRACT - ; At this point... - ; less than 4 bytes remains free. So we return this block entirely - ; We must link the previous block with the next to this one - ; (DE) => Pointer to next block - ; (TEMP) => &(previous->next) - pop hl ; Discard current block pointer - push de - ex de, hl ; DE = Previous block pointer; (HL) = Next block pointer - ld a, (hl) - inc hl - ld h, (hl) - ld l, a ; HL = (HL) - ex de, hl ; HL = Previous block pointer; DE = Next block pointer -TEMP0: - ld hl, 0 ; Pre-previous block pointer - ld (hl), e - inc hl - ld (hl), d ; LINKED - pop hl ; Returning block. - ret -__MEM_SUBTRACT: - ; At this point we have to store HL value (Length - BC) into (DE - 2) - ex de, hl - dec hl - ld (hl), d - dec hl - ld (hl), e ; Store new block length - add hl, de ; New length + DE => free-block start - pop de ; Remove previous HL off the stack - ld (hl), c ; Store length on its 1st word - inc hl - ld (hl), b - inc hl ; Return hl - ret - ENDP - pop namespace -#line 2 "/zxbasic/src/arch/zx48k/library-asm/loadstr.asm" - ; Loads a string (ptr) from HL - ; and duplicates it on dynamic memory again - ; Finally, it returns result pointer in HL - push namespace core -__ILOADSTR: ; This is the indirect pointer entry HL = (HL) - ld a, h - or l - ret z - ld a, (hl) - inc hl - ld h, (hl) - ld l, a -__LOADSTR: ; __FASTCALL__ entry - ld a, h - or l - ret z ; Return if NULL - ld c, (hl) - inc hl - ld b, (hl) - dec hl ; BC = LEN(a$) - inc bc - inc bc ; BC = LEN(a$) + 2 (two bytes for length) - push hl - push bc - call __MEM_ALLOC - pop bc ; Recover length - pop de ; Recover origin - ld a, h - or l - ret z ; Return if NULL (No memory) - ex de, hl ; ldir takes HL as source, DE as destiny, so SWAP HL,DE - push de ; Saves destiny start - ldir ; Copies string (length number included) - pop hl ; Recovers destiny in hl as result - ret - pop namespace -#line 38 "zx48k/print_arrstr.bas" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -; vim:ts=4:sw=4:et: - ; PRINT command routine - ; Does not print attribute. Use PRINT_STR or PRINT_NUM for that -#line 1 "/zxbasic/src/arch/zx48k/library-asm/sposn.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/sysvars.asm" - ;; ----------------------------------------------------------------------- - ;; ZX Basic System Vars - ;; Some of them will be mapped over Sinclair ROM ones for compatibility - ;; ----------------------------------------------------------------------- - push namespace core -SCREEN_ADDR: DW 16384 ; Screen address (can be pointed to other place to use a screen buffer) -SCREEN_ATTR_ADDR: DW 22528 ; Screen attribute address (ditto.) - ; These are mapped onto ZX Spectrum ROM VARS - CHARS EQU 23606 ; Pointer to ROM/RAM Charset - TVFLAGS EQU 23612 ; TV Flags - UDG EQU 23675 ; Pointer to UDG Charset - COORDS EQU 23677 ; Last PLOT coordinates - FLAGS2 EQU 23681 ; - ECHO_E EQU 23682 ; - DFCC EQU 23684 ; Next screen addr for PRINT - DFCCL EQU 23686 ; Next screen attr for PRINT - S_POSN EQU 23688 - ATTR_P EQU 23693 ; Current Permanent ATTRS set with INK, PAPER, etc commands - ATTR_T EQU 23695 ; temporary ATTRIBUTES - P_FLAG EQU 23697 ; - MEM0 EQU 23698 ; Temporary memory buffer used by ROM chars - SCR_COLS EQU 33 ; Screen with in columns + 1 - SCR_ROWS EQU 24 ; Screen height in rows - SCR_SIZE EQU (SCR_ROWS << 8) + SCR_COLS - pop namespace -#line 2 "/zxbasic/src/arch/zx48k/library-asm/sposn.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/attr.asm" - ; Attribute routines -; vim:ts=4:et:sw: -#line 1 "/zxbasic/src/arch/zx48k/library-asm/in_screen.asm" - push namespace core -__IN_SCREEN: - ; Returns NO carry if current coords (D, E) - ; are OUT of the screen limits - PROC - LOCAL __IN_SCREEN_ERR - ld hl, SCR_SIZE - ld a, e - cp l - jr nc, __IN_SCREEN_ERR ; Do nothing and return if out of range - ld a, d - cp h - ret c ; Return if carry (OK) -__IN_SCREEN_ERR: -__OUT_OF_SCREEN_ERR: - ; Jumps here if out of screen - ld a, ERROR_OutOfScreen - jp __STOP ; Saves error code and exits - ENDP - pop namespace -#line 7 "/zxbasic/src/arch/zx48k/library-asm/attr.asm" +#line 7 "/zxbasic/src/arch/zx48k/library-asm/attr.asm" push namespace core __ATTR_ADDR: ; calc start address in DE (as (32 * d) + e) @@ -745,60 +443,6 @@ BRIGHT_TMP: #line 1 "/zxbasic/src/arch/zx48k/library-asm/over.asm" ; Sets OVER flag in P_FLAG permanently ; Parameter: OVER flag in bit 0 of A register -#line 1 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" -#line 4 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" - push namespace core -COPY_ATTR: - ; Just copies current permanent attribs into temporal attribs - ; and sets print mode - PROC - LOCAL INVERSE1 - LOCAL __REFRESH_TMP - INVERSE1 EQU 02Fh - ld hl, (ATTR_P) - ld (ATTR_T), hl - ld hl, FLAGS2 - call __REFRESH_TMP - ld hl, P_FLAG - call __REFRESH_TMP -__SET_ATTR_MODE: ; Another entry to set print modes. A contains (P_FLAG) - LOCAL TABLE - LOCAL CONT2 - rra ; Over bit to carry - ld a, (FLAGS2) - rla ; Over bit in bit 1, Over2 bit in bit 2 - and 3 ; Only bit 0 and 1 (OVER flag) - ld c, a - ld b, 0 - ld hl, TABLE - add hl, bc - ld a, (hl) - ld (PRINT_MODE), a - ld hl, (P_FLAG) - xor a ; NOP -> INVERSE0 - bit 2, l - jr z, CONT2 - ld a, INVERSE1 ; CPL -> INVERSE1 -CONT2: - ld (INVERSE_MODE), a - ret -TABLE: - nop ; NORMAL MODE - xor (hl) ; OVER 1 MODE - and (hl) ; OVER 2 MODE - or (hl) ; OVER 3 MODE -#line 67 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" -__REFRESH_TMP: - ld a, (hl) - and 0b10101010 - ld c, a - rra - or c - ld (hl), a - ret - ENDP - pop namespace -#line 4 "/zxbasic/src/arch/zx48k/library-asm/over.asm" push namespace core OVER: PROC @@ -1040,11 +684,10 @@ INVERSE_MODE: ; 00 -> NOP -> INVERSE 0 inc hl ld (DFCC), hl ld hl, (DFCCL) ; current ATTR Pos - push hl - call __SET_ATTR - pop hl inc hl - ld (DFCCL),hl + ld (DFCCL), hl + dec hl + call __SET_ATTR exx ret ; ------------- SPECIAL CHARS (< 32) ----------------- @@ -1063,7 +706,7 @@ __PRINT_0Dh: ; Called WHEN printing CHR$(13) push hl call __SCROLL_SCR pop hl -#line 210 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 209 "/zxbasic/src/arch/zx48k/library-asm/print.asm" 1: ld l, 1 __PRINT_EOL_END: @@ -1180,14 +823,14 @@ __PRINT_BOLD: __PRINT_BOLD2: call BOLD_TMP jp __PRINT_RESTART -#line 354 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 353 "/zxbasic/src/arch/zx48k/library-asm/print.asm" __PRINT_ITA: ld hl, __PRINT_ITA2 jp __PRINT_SET_STATE __PRINT_ITA2: call ITALIC_TMP jp __PRINT_RESTART -#line 364 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 363 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __BOLD __BOLD: push hl @@ -1200,115 +843,472 @@ __BOLD: or c ld (hl), a inc hl - inc de - djnz 1b - pop hl - ld de, MEM0 - ret -#line 385 "/zxbasic/src/arch/zx48k/library-asm/print.asm" - LOCAL __ITALIC -__ITALIC: - push hl - ld hl, MEM0 - ex de, hl - ld bc, 8 - ldir - ld hl, MEM0 - srl (hl) - inc hl - srl (hl) + inc de + djnz 1b + pop hl + ld de, MEM0 + ret +#line 384 "/zxbasic/src/arch/zx48k/library-asm/print.asm" + LOCAL __ITALIC +__ITALIC: + push hl + ld hl, MEM0 + ex de, hl + ld bc, 8 + ldir + ld hl, MEM0 + srl (hl) + inc hl + srl (hl) + inc hl + srl (hl) + inc hl + inc hl + inc hl + sla (hl) + inc hl + sla (hl) + inc hl + sla (hl) + pop hl + ld de, MEM0 + ret +#line 412 "/zxbasic/src/arch/zx48k/library-asm/print.asm" + LOCAL __SCROLL_SCR +#line 486 "/zxbasic/src/arch/zx48k/library-asm/print.asm" + __SCROLL_SCR EQU 0DFEh ; Use ROM SCROLL +#line 488 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 489 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +PRINT_COMMA: + call __LOAD_S_POSN + ld a, e + and 16 + add a, 16 +PRINT_TAB: + ; Tabulates the number of spaces in A register + ; If the current cursor position is already A, does nothing + PROC + LOCAL LOOP + call __LOAD_S_POSN ; e = current row + sub e + and 31 + ret z + ld b, a +LOOP: + ld a, ' ' + call __PRINTCHAR + djnz LOOP + ret + ENDP +PRINT_AT: ; Changes cursor to ROW, COL + ; COL in A register + ; ROW in stack + pop hl ; Ret address + ex (sp), hl ; callee H = ROW + ld l, a + ex de, hl + call __IN_SCREEN + ret nc ; Return if out of screen + jp __SAVE_S_POSN + LOCAL __PRINT_COM + LOCAL __PRINT_AT1 + LOCAL __PRINT_AT2 + LOCAL __PRINT_BOLD + LOCAL __PRINT_ITA + LOCAL __PRINT_INK + LOCAL __PRINT_PAP + LOCAL __PRINT_SET_STATE + LOCAL __PRINT_TABLE + LOCAL __PRINT_TAB, __PRINT_TAB1, __PRINT_TAB2 + LOCAL __PRINT_ITA2 +#line 545 "/zxbasic/src/arch/zx48k/library-asm/print.asm" + LOCAL __PRINT_BOLD2 +#line 551 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +__PRINT_TABLE: ; Jump table for 0 .. 22 codes + DW __PRINT_NOP ; 0 + DW __PRINT_NOP ; 1 + DW __PRINT_NOP ; 2 + DW __PRINT_NOP ; 3 + DW __PRINT_NOP ; 4 + DW __PRINT_NOP ; 5 + DW __PRINT_COM ; 6 COMMA + DW __PRINT_NOP ; 7 + DW __PRINT_DEL ; 8 DEL + DW __PRINT_NOP ; 9 + DW __PRINT_NOP ; 10 + DW __PRINT_NOP ; 11 + DW __PRINT_NOP ; 12 + DW __PRINT_0Dh ; 13 + DW __PRINT_BOLD ; 14 + DW __PRINT_ITA ; 15 + DW __PRINT_INK ; 16 + DW __PRINT_PAP ; 17 + DW __PRINT_FLA ; 18 + DW __PRINT_BRI ; 19 + DW __PRINT_INV ; 20 + DW __PRINT_OVR ; 21 + DW __PRINT_AT ; 22 AT + DW __PRINT_TAB ; 23 TAB + ENDP + pop namespace +#line 3 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" +#line 4 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" + push namespace core +COPY_ATTR: + ; Just copies current permanent attribs into temporal attribs + ; and sets print mode + PROC + LOCAL INVERSE1 + LOCAL __REFRESH_TMP + INVERSE1 EQU 02Fh + ld hl, (ATTR_P) + ld (ATTR_T), hl + ld hl, FLAGS2 + call __REFRESH_TMP + ld hl, P_FLAG + call __REFRESH_TMP +__SET_ATTR_MODE: ; Another entry to set print modes. A contains (P_FLAG) + LOCAL TABLE + LOCAL CONT2 + rra ; Over bit to carry + ld a, (FLAGS2) + rla ; Over bit in bit 1, Over2 bit in bit 2 + and 3 ; Only bit 0 and 1 (OVER flag) + ld c, a + ld b, 0 + ld hl, TABLE + add hl, bc + ld a, (hl) + ld (PRINT_MODE), a + ld hl, (P_FLAG) + xor a ; NOP -> INVERSE0 + bit 2, l + jr z, CONT2 + ld a, INVERSE1 ; CPL -> INVERSE1 +CONT2: + ld (INVERSE_MODE), a + ret +TABLE: + nop ; NORMAL MODE + xor (hl) ; OVER 1 MODE + and (hl) ; OVER 2 MODE + or (hl) ; OVER 3 MODE +#line 67 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" +__REFRESH_TMP: + ld a, (hl) + and 0b10101010 + ld c, a + rra + or c + ld (hl), a + ret + ENDP + pop namespace +#line 39 "zx48k/print_arrstr.bas" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/loadstr.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/alloc.asm" +; vim: ts=4:et:sw=4: + ; Copyleft (K) by Jose M. Rodriguez de la Rosa + ; (a.k.a. Boriel) +; http://www.boriel.com + ; + ; This ASM library is licensed under the MIT license + ; you can use it for any purpose (even for commercial + ; closed source programs). + ; + ; Please read the MIT license on the internet + ; ----- IMPLEMENTATION NOTES ------ + ; The heap is implemented as a linked list of free blocks. +; Each free block contains this info: + ; + ; +----------------+ <-- HEAP START + ; | Size (2 bytes) | + ; | 0 | <-- Size = 0 => DUMMY HEADER BLOCK + ; +----------------+ + ; | Next (2 bytes) |---+ + ; +----------------+ <-+ + ; | Size (2 bytes) | + ; +----------------+ + ; | Next (2 bytes) |---+ + ; +----------------+ | + ; | | | <-- If Size > 4, then this contains (size - 4) bytes + ; | (0 if Size = 4)| | + ; +----------------+ <-+ + ; | Size (2 bytes) | + ; +----------------+ + ; | Next (2 bytes) |---+ + ; +----------------+ | + ; | | | + ; | (0 if Size = 4)| | + ; +----------------+ | + ; | <-- This zone is in use (Already allocated) + ; +----------------+ <-+ + ; | Size (2 bytes) | + ; +----------------+ + ; | Next (2 bytes) |---+ + ; +----------------+ | + ; | | | + ; | (0 if Size = 4)| | + ; +----------------+ <-+ + ; | Next (2 bytes) |--> NULL => END OF LIST + ; | 0 = NULL | + ; +----------------+ + ; | | + ; | (0 if Size = 4)| + ; +----------------+ + ; When a block is FREED, the previous and next pointers are examined to see + ; if we can defragment the heap. If the block to be freed is just next to the + ; previous, or to the next (or both) they will be converted into a single + ; block (so defragmented). + ; MEMORY MANAGER + ; + ; This library must be initialized calling __MEM_INIT with + ; HL = BLOCK Start & DE = Length. + ; An init directive is useful for initialization routines. + ; They will be added automatically if needed. +#line 1 "/zxbasic/src/arch/zx48k/library-asm/heapinit.asm" +; vim: ts=4:et:sw=4: + ; Copyleft (K) by Jose M. Rodriguez de la Rosa + ; (a.k.a. Boriel) +; http://www.boriel.com + ; + ; This ASM library is licensed under the BSD license + ; you can use it for any purpose (even for commercial + ; closed source programs). + ; + ; Please read the BSD license on the internet + ; ----- IMPLEMENTATION NOTES ------ + ; The heap is implemented as a linked list of free blocks. +; Each free block contains this info: + ; + ; +----------------+ <-- HEAP START + ; | Size (2 bytes) | + ; | 0 | <-- Size = 0 => DUMMY HEADER BLOCK + ; +----------------+ + ; | Next (2 bytes) |---+ + ; +----------------+ <-+ + ; | Size (2 bytes) | + ; +----------------+ + ; | Next (2 bytes) |---+ + ; +----------------+ | + ; | | | <-- If Size > 4, then this contains (size - 4) bytes + ; | (0 if Size = 4)| | + ; +----------------+ <-+ + ; | Size (2 bytes) | + ; +----------------+ + ; | Next (2 bytes) |---+ + ; +----------------+ | + ; | | | + ; | (0 if Size = 4)| | + ; +----------------+ | + ; | <-- This zone is in use (Already allocated) + ; +----------------+ <-+ + ; | Size (2 bytes) | + ; +----------------+ + ; | Next (2 bytes) |---+ + ; +----------------+ | + ; | | | + ; | (0 if Size = 4)| | + ; +----------------+ <-+ + ; | Next (2 bytes) |--> NULL => END OF LIST + ; | 0 = NULL | + ; +----------------+ + ; | | + ; | (0 if Size = 4)| + ; +----------------+ + ; When a block is FREED, the previous and next pointers are examined to see + ; if we can defragment the heap. If the block to be breed is just next to the + ; previous, or to the next (or both) they will be converted into a single + ; block (so defragmented). + ; MEMORY MANAGER + ; + ; This library must be initialized calling __MEM_INIT with + ; HL = BLOCK Start & DE = Length. + ; An init directive is useful for initialization routines. + ; They will be added automatically if needed. + ; --------------------------------------------------------------------- + ; __MEM_INIT must be called to initalize this library with the + ; standard parameters + ; --------------------------------------------------------------------- + push namespace core +__MEM_INIT: ; Initializes the library using (RAMTOP) as start, and + ld hl, ZXBASIC_MEM_HEAP ; Change this with other address of heap start + ld de, ZXBASIC_HEAP_SIZE ; Change this with your size + ; --------------------------------------------------------------------- + ; __MEM_INIT2 initalizes this library +; Parameters: +; HL : Memory address of 1st byte of the memory heap +; DE : Length in bytes of the Memory Heap + ; --------------------------------------------------------------------- +__MEM_INIT2: + ; HL as TOP + PROC + dec de + dec de + dec de + dec de ; DE = length - 4; HL = start + ; This is done, because we require 4 bytes for the empty dummy-header block + xor a + ld (hl), a + inc hl + ld (hl), a ; First "free" block is a header: size=0, Pointer=&(Block) + 4 inc hl - srl (hl) + ld b, h + ld c, l + inc bc + inc bc ; BC = starts of next block + ld (hl), c inc hl + ld (hl), b + inc hl ; Pointer to next block + ld (hl), e inc hl + ld (hl), d + inc hl ; Block size (should be length - 4 at start); This block contains all the available memory + ld (hl), a ; NULL (0000h) ; No more blocks (a list with a single block) inc hl - sla (hl) + ld (hl), a + ld a, 201 + ld (__MEM_INIT), a; "Pokes" with a RET so ensure this routine is not called again + ret + ENDP + pop namespace +#line 70 "/zxbasic/src/arch/zx48k/library-asm/alloc.asm" + ; --------------------------------------------------------------------- + ; MEM_ALLOC + ; Allocates a block of memory in the heap. + ; + ; Parameters + ; BC = Length of requested memory block + ; +; Returns: + ; HL = Pointer to the allocated block in memory. Returns 0 (NULL) + ; if the block could not be allocated (out of memory) + ; --------------------------------------------------------------------- + push namespace core +MEM_ALLOC: +__MEM_ALLOC: ; Returns the 1st free block found of the given length (in BC) + PROC + LOCAL __MEM_LOOP + LOCAL __MEM_DONE + LOCAL __MEM_SUBTRACT + LOCAL __MEM_START + LOCAL TEMP, TEMP0 + TEMP EQU TEMP0 + 1 + ld hl, 0 + ld (TEMP), hl +__MEM_START: + ld hl, ZXBASIC_MEM_HEAP ; This label point to the heap start + inc bc + inc bc ; BC = BC + 2 ; block size needs 2 extra bytes for hidden pointer +__MEM_LOOP: ; Loads lengh at (HL, HL+). If Lenght >= BC, jump to __MEM_DONE + ld a, h ; HL = NULL (No memory available?) + or l +#line 113 "/zxbasic/src/arch/zx48k/library-asm/alloc.asm" + ret z ; NULL +#line 115 "/zxbasic/src/arch/zx48k/library-asm/alloc.asm" + ; HL = Pointer to Free block + ld e, (hl) inc hl - sla (hl) + ld d, (hl) + inc hl ; DE = Block Length + push hl ; HL = *pointer to -> next block + ex de, hl + or a ; CF = 0 + sbc hl, bc ; FREE >= BC (Length) (HL = BlockLength - Length) + jp nc, __MEM_DONE + pop hl + ld (TEMP), hl + ex de, hl + ld e, (hl) inc hl - sla (hl) + ld d, (hl) + ex de, hl + jp __MEM_LOOP +__MEM_DONE: ; A free block has been found. + ; Check if at least 4 bytes remains free (HL >= 4) + push hl + exx ; exx to preserve bc pop hl - ld de, MEM0 + ld bc, 4 + or a + sbc hl, bc + exx + jp nc, __MEM_SUBTRACT + ; At this point... + ; less than 4 bytes remains free. So we return this block entirely + ; We must link the previous block with the next to this one + ; (DE) => Pointer to next block + ; (TEMP) => &(previous->next) + pop hl ; Discard current block pointer + push de + ex de, hl ; DE = Previous block pointer; (HL) = Next block pointer + ld a, (hl) + inc hl + ld h, (hl) + ld l, a ; HL = (HL) + ex de, hl ; HL = Previous block pointer; DE = Next block pointer +TEMP0: + ld hl, 0 ; Pre-previous block pointer + ld (hl), e + inc hl + ld (hl), d ; LINKED + pop hl ; Returning block. ret -#line 413 "/zxbasic/src/arch/zx48k/library-asm/print.asm" - LOCAL __SCROLL_SCR -#line 487 "/zxbasic/src/arch/zx48k/library-asm/print.asm" - __SCROLL_SCR EQU 0DFEh ; Use ROM SCROLL -#line 489 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -#line 490 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -PRINT_COMMA: - call __LOAD_S_POSN - ld a, e - and 16 - add a, 16 -PRINT_TAB: - ; Tabulates the number of spaces in A register - ; If the current cursor position is already A, does nothing - PROC - LOCAL LOOP - call __LOAD_S_POSN ; e = current row - sub e - and 31 - ret z - ld b, a -LOOP: - ld a, ' ' - call __PRINTCHAR - djnz LOOP +__MEM_SUBTRACT: + ; At this point we have to store HL value (Length - BC) into (DE - 2) + ex de, hl + dec hl + ld (hl), d + dec hl + ld (hl), e ; Store new block length + add hl, de ; New length + DE => free-block start + pop de ; Remove previous HL off the stack + ld (hl), c ; Store length on its 1st word + inc hl + ld (hl), b + inc hl ; Return hl ret ENDP -PRINT_AT: ; Changes cursor to ROW, COL - ; COL in A register - ; ROW in stack - pop hl ; Ret address - ex (sp), hl ; callee H = ROW + pop namespace +#line 2 "/zxbasic/src/arch/zx48k/library-asm/loadstr.asm" + ; Loads a string (ptr) from HL + ; and duplicates it on dynamic memory again + ; Finally, it returns result pointer in HL + push namespace core +__ILOADSTR: ; This is the indirect pointer entry HL = (HL) + ld a, h + or l + ret z + ld a, (hl) + inc hl + ld h, (hl) ld l, a - ex de, hl - call __IN_SCREEN - ret nc ; Return if out of screen - jp __SAVE_S_POSN - LOCAL __PRINT_COM - LOCAL __PRINT_AT1 - LOCAL __PRINT_AT2 - LOCAL __PRINT_BOLD - LOCAL __PRINT_ITA - LOCAL __PRINT_INK - LOCAL __PRINT_PAP - LOCAL __PRINT_SET_STATE - LOCAL __PRINT_TABLE - LOCAL __PRINT_TAB, __PRINT_TAB1, __PRINT_TAB2 - LOCAL __PRINT_ITA2 -#line 546 "/zxbasic/src/arch/zx48k/library-asm/print.asm" - LOCAL __PRINT_BOLD2 -#line 552 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -__PRINT_TABLE: ; Jump table for 0 .. 22 codes - DW __PRINT_NOP ; 0 - DW __PRINT_NOP ; 1 - DW __PRINT_NOP ; 2 - DW __PRINT_NOP ; 3 - DW __PRINT_NOP ; 4 - DW __PRINT_NOP ; 5 - DW __PRINT_COM ; 6 COMMA - DW __PRINT_NOP ; 7 - DW __PRINT_DEL ; 8 DEL - DW __PRINT_NOP ; 9 - DW __PRINT_NOP ; 10 - DW __PRINT_NOP ; 11 - DW __PRINT_NOP ; 12 - DW __PRINT_0Dh ; 13 - DW __PRINT_BOLD ; 14 - DW __PRINT_ITA ; 15 - DW __PRINT_INK ; 16 - DW __PRINT_PAP ; 17 - DW __PRINT_FLA ; 18 - DW __PRINT_BRI ; 19 - DW __PRINT_INV ; 20 - DW __PRINT_OVR ; 21 - DW __PRINT_AT ; 22 AT - DW __PRINT_TAB ; 23 TAB - ENDP +__LOADSTR: ; __FASTCALL__ entry + ld a, h + or l + ret z ; Return if NULL + ld c, (hl) + inc hl + ld b, (hl) + dec hl ; BC = LEN(a$) + inc bc + inc bc ; BC = LEN(a$) + 2 (two bytes for length) + push hl + push bc + call __MEM_ALLOC + pop bc ; Recover length + pop de ; Recover origin + ld a, h + or l + ret z ; Return if NULL (No memory) + ex de, hl ; ldir takes HL as source, DE as destiny, so SWAP HL,DE + push de ; Saves destiny start + ldir ; Copies string (length number included) + pop hl ; Recovers destiny in hl as result + ret pop namespace -#line 39 "zx48k/print_arrstr.bas" +#line 40 "zx48k/print_arrstr.bas" #line 1 "/zxbasic/src/arch/zx48k/library-asm/printstr.asm" #line 1 "/zxbasic/src/arch/zx48k/library-asm/free.asm" ; vim: ts=4:et:sw=4: @@ -1511,7 +1511,7 @@ __PRINT_STR: jp __PRINT_STR_LOOP ENDP pop namespace -#line 40 "zx48k/print_arrstr.bas" +#line 42 "zx48k/print_arrstr.bas" #line 1 "/zxbasic/src/arch/zx48k/library-asm/storestr.asm" ; vim:ts=4:et:sw=4 ; Stores value of current string pointed by DE register into address pointed by HL @@ -1760,5 +1760,5 @@ __STORE_STR: pop hl ; Returns ptr to b$ in HL (Caller might needed to free it from memory) ret pop namespace -#line 41 "zx48k/print_arrstr.bas" +#line 43 "zx48k/print_arrstr.bas" END diff --git a/tests/functional/zx48k/print_at.asm b/tests/functional/zx48k/print_at.asm index 7bccf7ca6..0d3bc2f64 100644 --- a/tests/functional/zx48k/print_at.asm +++ b/tests/functional/zx48k/print_at.asm @@ -26,6 +26,7 @@ .core.__LABEL__.ZXBASIC_USER_DATA EQU .core.ZXBASIC_USER_DATA .core.ZXBASIC_USER_DATA_END: .core.__MAIN_PROGRAM__: + call .core.COPY_ATTR ld a, 10 push af ld a, 10 @@ -51,6 +52,7 @@ DEFW 0001h DEFB 20h ;; --- end of user code --- +#line 1 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" #line 1 "/zxbasic/src/arch/zx48k/library-asm/print.asm" ; vim:ts=4:sw=4:et: ; PRINT command routine @@ -400,60 +402,6 @@ BRIGHT_TMP: #line 1 "/zxbasic/src/arch/zx48k/library-asm/over.asm" ; Sets OVER flag in P_FLAG permanently ; Parameter: OVER flag in bit 0 of A register -#line 1 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" -#line 4 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" - push namespace core -COPY_ATTR: - ; Just copies current permanent attribs into temporal attribs - ; and sets print mode - PROC - LOCAL INVERSE1 - LOCAL __REFRESH_TMP - INVERSE1 EQU 02Fh - ld hl, (ATTR_P) - ld (ATTR_T), hl - ld hl, FLAGS2 - call __REFRESH_TMP - ld hl, P_FLAG - call __REFRESH_TMP -__SET_ATTR_MODE: ; Another entry to set print modes. A contains (P_FLAG) - LOCAL TABLE - LOCAL CONT2 - rra ; Over bit to carry - ld a, (FLAGS2) - rla ; Over bit in bit 1, Over2 bit in bit 2 - and 3 ; Only bit 0 and 1 (OVER flag) - ld c, a - ld b, 0 - ld hl, TABLE - add hl, bc - ld a, (hl) - ld (PRINT_MODE), a - ld hl, (P_FLAG) - xor a ; NOP -> INVERSE0 - bit 2, l - jr z, CONT2 - ld a, INVERSE1 ; CPL -> INVERSE1 -CONT2: - ld (INVERSE_MODE), a - ret -TABLE: - nop ; NORMAL MODE - xor (hl) ; OVER 1 MODE - and (hl) ; OVER 2 MODE - or (hl) ; OVER 3 MODE -#line 67 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" -__REFRESH_TMP: - ld a, (hl) - and 0b10101010 - ld c, a - rra - or c - ld (hl), a - ret - ENDP - pop namespace -#line 4 "/zxbasic/src/arch/zx48k/library-asm/over.asm" push namespace core OVER: PROC @@ -695,11 +643,10 @@ INVERSE_MODE: ; 00 -> NOP -> INVERSE 0 inc hl ld (DFCC), hl ld hl, (DFCCL) ; current ATTR Pos - push hl - call __SET_ATTR - pop hl inc hl - ld (DFCCL),hl + ld (DFCCL), hl + dec hl + call __SET_ATTR exx ret ; ------------- SPECIAL CHARS (< 32) ----------------- @@ -718,7 +665,7 @@ __PRINT_0Dh: ; Called WHEN printing CHR$(13) push hl call __SCROLL_SCR pop hl -#line 210 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 209 "/zxbasic/src/arch/zx48k/library-asm/print.asm" 1: ld l, 1 __PRINT_EOL_END: @@ -835,14 +782,14 @@ __PRINT_BOLD: __PRINT_BOLD2: call BOLD_TMP jp __PRINT_RESTART -#line 354 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 353 "/zxbasic/src/arch/zx48k/library-asm/print.asm" __PRINT_ITA: ld hl, __PRINT_ITA2 jp __PRINT_SET_STATE __PRINT_ITA2: call ITALIC_TMP jp __PRINT_RESTART -#line 364 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 363 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __BOLD __BOLD: push hl @@ -860,7 +807,7 @@ __BOLD: pop hl ld de, MEM0 ret -#line 385 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 384 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __ITALIC __ITALIC: push hl @@ -885,12 +832,12 @@ __ITALIC: pop hl ld de, MEM0 ret -#line 413 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 412 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __SCROLL_SCR -#line 487 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 486 "/zxbasic/src/arch/zx48k/library-asm/print.asm" __SCROLL_SCR EQU 0DFEh ; Use ROM SCROLL +#line 488 "/zxbasic/src/arch/zx48k/library-asm/print.asm" #line 489 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -#line 490 "/zxbasic/src/arch/zx48k/library-asm/print.asm" PRINT_COMMA: call __LOAD_S_POSN ld a, e @@ -933,9 +880,9 @@ PRINT_AT: ; Changes cursor to ROW, COL LOCAL __PRINT_TABLE LOCAL __PRINT_TAB, __PRINT_TAB1, __PRINT_TAB2 LOCAL __PRINT_ITA2 -#line 546 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 545 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __PRINT_BOLD2 -#line 552 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 551 "/zxbasic/src/arch/zx48k/library-asm/print.asm" __PRINT_TABLE: ; Jump table for 0 .. 22 codes DW __PRINT_NOP ; 0 DW __PRINT_NOP ; 1 @@ -963,7 +910,60 @@ __PRINT_TABLE: ; Jump table for 0 .. 22 codes DW __PRINT_TAB ; 23 TAB ENDP pop namespace -#line 27 "zx48k/print_at.bas" +#line 3 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" +#line 4 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" + push namespace core +COPY_ATTR: + ; Just copies current permanent attribs into temporal attribs + ; and sets print mode + PROC + LOCAL INVERSE1 + LOCAL __REFRESH_TMP + INVERSE1 EQU 02Fh + ld hl, (ATTR_P) + ld (ATTR_T), hl + ld hl, FLAGS2 + call __REFRESH_TMP + ld hl, P_FLAG + call __REFRESH_TMP +__SET_ATTR_MODE: ; Another entry to set print modes. A contains (P_FLAG) + LOCAL TABLE + LOCAL CONT2 + rra ; Over bit to carry + ld a, (FLAGS2) + rla ; Over bit in bit 1, Over2 bit in bit 2 + and 3 ; Only bit 0 and 1 (OVER flag) + ld c, a + ld b, 0 + ld hl, TABLE + add hl, bc + ld a, (hl) + ld (PRINT_MODE), a + ld hl, (P_FLAG) + xor a ; NOP -> INVERSE0 + bit 2, l + jr z, CONT2 + ld a, INVERSE1 ; CPL -> INVERSE1 +CONT2: + ld (INVERSE_MODE), a + ret +TABLE: + nop ; NORMAL MODE + xor (hl) ; OVER 1 MODE + and (hl) ; OVER 2 MODE + or (hl) ; OVER 3 MODE +#line 67 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" +__REFRESH_TMP: + ld a, (hl) + and 0b10101010 + ld c, a + rra + or c + ld (hl), a + ret + ENDP + pop namespace +#line 28 "zx48k/print_at.bas" #line 1 "/zxbasic/src/arch/zx48k/library-asm/printstr.asm" #line 1 "/zxbasic/src/arch/zx48k/library-asm/free.asm" ; vim: ts=4:et:sw=4: @@ -1274,5 +1274,5 @@ __PRINT_STR: jp __PRINT_STR_LOOP ENDP pop namespace -#line 28 "zx48k/print_at.bas" +#line 30 "zx48k/print_at.bas" END diff --git a/tests/functional/zx48k/print_comma.asm b/tests/functional/zx48k/print_comma.asm index 918bf5d73..71884737f 100644 --- a/tests/functional/zx48k/print_comma.asm +++ b/tests/functional/zx48k/print_comma.asm @@ -21,6 +21,7 @@ .core.__LABEL__.ZXBASIC_USER_DATA EQU .core.ZXBASIC_USER_DATA .core.ZXBASIC_USER_DATA_END: .core.__MAIN_PROGRAM__: + call .core.COPY_ATTR ld a, 1 call .core.__PRINTU8 call .core.PRINT_COMMA @@ -42,6 +43,7 @@ ei ret ;; --- end of user code --- +#line 1 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" #line 1 "/zxbasic/src/arch/zx48k/library-asm/print.asm" ; vim:ts=4:sw=4:et: ; PRINT command routine @@ -391,60 +393,6 @@ BRIGHT_TMP: #line 1 "/zxbasic/src/arch/zx48k/library-asm/over.asm" ; Sets OVER flag in P_FLAG permanently ; Parameter: OVER flag in bit 0 of A register -#line 1 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" -#line 4 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" - push namespace core -COPY_ATTR: - ; Just copies current permanent attribs into temporal attribs - ; and sets print mode - PROC - LOCAL INVERSE1 - LOCAL __REFRESH_TMP - INVERSE1 EQU 02Fh - ld hl, (ATTR_P) - ld (ATTR_T), hl - ld hl, FLAGS2 - call __REFRESH_TMP - ld hl, P_FLAG - call __REFRESH_TMP -__SET_ATTR_MODE: ; Another entry to set print modes. A contains (P_FLAG) - LOCAL TABLE - LOCAL CONT2 - rra ; Over bit to carry - ld a, (FLAGS2) - rla ; Over bit in bit 1, Over2 bit in bit 2 - and 3 ; Only bit 0 and 1 (OVER flag) - ld c, a - ld b, 0 - ld hl, TABLE - add hl, bc - ld a, (hl) - ld (PRINT_MODE), a - ld hl, (P_FLAG) - xor a ; NOP -> INVERSE0 - bit 2, l - jr z, CONT2 - ld a, INVERSE1 ; CPL -> INVERSE1 -CONT2: - ld (INVERSE_MODE), a - ret -TABLE: - nop ; NORMAL MODE - xor (hl) ; OVER 1 MODE - and (hl) ; OVER 2 MODE - or (hl) ; OVER 3 MODE -#line 67 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" -__REFRESH_TMP: - ld a, (hl) - and 0b10101010 - ld c, a - rra - or c - ld (hl), a - ret - ENDP - pop namespace -#line 4 "/zxbasic/src/arch/zx48k/library-asm/over.asm" push namespace core OVER: PROC @@ -686,11 +634,10 @@ INVERSE_MODE: ; 00 -> NOP -> INVERSE 0 inc hl ld (DFCC), hl ld hl, (DFCCL) ; current ATTR Pos - push hl - call __SET_ATTR - pop hl inc hl - ld (DFCCL),hl + ld (DFCCL), hl + dec hl + call __SET_ATTR exx ret ; ------------- SPECIAL CHARS (< 32) ----------------- @@ -709,7 +656,7 @@ __PRINT_0Dh: ; Called WHEN printing CHR$(13) push hl call __SCROLL_SCR pop hl -#line 210 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 209 "/zxbasic/src/arch/zx48k/library-asm/print.asm" 1: ld l, 1 __PRINT_EOL_END: @@ -826,14 +773,14 @@ __PRINT_BOLD: __PRINT_BOLD2: call BOLD_TMP jp __PRINT_RESTART -#line 354 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 353 "/zxbasic/src/arch/zx48k/library-asm/print.asm" __PRINT_ITA: ld hl, __PRINT_ITA2 jp __PRINT_SET_STATE __PRINT_ITA2: call ITALIC_TMP jp __PRINT_RESTART -#line 364 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 363 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __BOLD __BOLD: push hl @@ -851,7 +798,7 @@ __BOLD: pop hl ld de, MEM0 ret -#line 385 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 384 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __ITALIC __ITALIC: push hl @@ -876,12 +823,12 @@ __ITALIC: pop hl ld de, MEM0 ret -#line 413 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 412 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __SCROLL_SCR -#line 487 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 486 "/zxbasic/src/arch/zx48k/library-asm/print.asm" __SCROLL_SCR EQU 0DFEh ; Use ROM SCROLL +#line 488 "/zxbasic/src/arch/zx48k/library-asm/print.asm" #line 489 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -#line 490 "/zxbasic/src/arch/zx48k/library-asm/print.asm" PRINT_COMMA: call __LOAD_S_POSN ld a, e @@ -924,9 +871,9 @@ PRINT_AT: ; Changes cursor to ROW, COL LOCAL __PRINT_TABLE LOCAL __PRINT_TAB, __PRINT_TAB1, __PRINT_TAB2 LOCAL __PRINT_ITA2 -#line 546 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 545 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __PRINT_BOLD2 -#line 552 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 551 "/zxbasic/src/arch/zx48k/library-asm/print.asm" __PRINT_TABLE: ; Jump table for 0 .. 22 codes DW __PRINT_NOP ; 0 DW __PRINT_NOP ; 1 @@ -954,7 +901,60 @@ __PRINT_TABLE: ; Jump table for 0 .. 22 codes DW __PRINT_TAB ; 23 TAB ENDP pop namespace -#line 23 "zx48k/print_comma.bas" +#line 3 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" +#line 4 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" + push namespace core +COPY_ATTR: + ; Just copies current permanent attribs into temporal attribs + ; and sets print mode + PROC + LOCAL INVERSE1 + LOCAL __REFRESH_TMP + INVERSE1 EQU 02Fh + ld hl, (ATTR_P) + ld (ATTR_T), hl + ld hl, FLAGS2 + call __REFRESH_TMP + ld hl, P_FLAG + call __REFRESH_TMP +__SET_ATTR_MODE: ; Another entry to set print modes. A contains (P_FLAG) + LOCAL TABLE + LOCAL CONT2 + rra ; Over bit to carry + ld a, (FLAGS2) + rla ; Over bit in bit 1, Over2 bit in bit 2 + and 3 ; Only bit 0 and 1 (OVER flag) + ld c, a + ld b, 0 + ld hl, TABLE + add hl, bc + ld a, (hl) + ld (PRINT_MODE), a + ld hl, (P_FLAG) + xor a ; NOP -> INVERSE0 + bit 2, l + jr z, CONT2 + ld a, INVERSE1 ; CPL -> INVERSE1 +CONT2: + ld (INVERSE_MODE), a + ret +TABLE: + nop ; NORMAL MODE + xor (hl) ; OVER 1 MODE + and (hl) ; OVER 2 MODE + or (hl) ; OVER 3 MODE +#line 67 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" +__REFRESH_TMP: + ld a, (hl) + and 0b10101010 + ld c, a + rra + or c + ld (hl), a + ret + ENDP + pop namespace +#line 24 "zx48k/print_comma.bas" #line 1 "/zxbasic/src/arch/zx48k/library-asm/printu8.asm" #line 1 "/zxbasic/src/arch/zx48k/library-asm/printi8.asm" #line 1 "/zxbasic/src/arch/zx48k/library-asm/printnum.asm" @@ -1076,5 +1076,5 @@ __PRINTU_LOOP: ENDP pop namespace #line 2 "/zxbasic/src/arch/zx48k/library-asm/printu8.asm" -#line 24 "zx48k/print_comma.bas" +#line 26 "zx48k/print_comma.bas" END diff --git a/tests/functional/zx48k/print_eol.asm b/tests/functional/zx48k/print_eol.asm index 7a08f7112..cd35647d4 100644 --- a/tests/functional/zx48k/print_eol.asm +++ b/tests/functional/zx48k/print_eol.asm @@ -21,6 +21,7 @@ .core.__LABEL__.ZXBASIC_USER_DATA EQU .core.ZXBASIC_USER_DATA .core.ZXBASIC_USER_DATA_END: .core.__MAIN_PROGRAM__: + call .core.COPY_ATTR call .core.PRINT_EOL ld hl, 0 ld b, h @@ -37,6 +38,7 @@ ei ret ;; --- end of user code --- +#line 1 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" #line 1 "/zxbasic/src/arch/zx48k/library-asm/print.asm" ; vim:ts=4:sw=4:et: ; PRINT command routine @@ -386,60 +388,6 @@ BRIGHT_TMP: #line 1 "/zxbasic/src/arch/zx48k/library-asm/over.asm" ; Sets OVER flag in P_FLAG permanently ; Parameter: OVER flag in bit 0 of A register -#line 1 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" -#line 4 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" - push namespace core -COPY_ATTR: - ; Just copies current permanent attribs into temporal attribs - ; and sets print mode - PROC - LOCAL INVERSE1 - LOCAL __REFRESH_TMP - INVERSE1 EQU 02Fh - ld hl, (ATTR_P) - ld (ATTR_T), hl - ld hl, FLAGS2 - call __REFRESH_TMP - ld hl, P_FLAG - call __REFRESH_TMP -__SET_ATTR_MODE: ; Another entry to set print modes. A contains (P_FLAG) - LOCAL TABLE - LOCAL CONT2 - rra ; Over bit to carry - ld a, (FLAGS2) - rla ; Over bit in bit 1, Over2 bit in bit 2 - and 3 ; Only bit 0 and 1 (OVER flag) - ld c, a - ld b, 0 - ld hl, TABLE - add hl, bc - ld a, (hl) - ld (PRINT_MODE), a - ld hl, (P_FLAG) - xor a ; NOP -> INVERSE0 - bit 2, l - jr z, CONT2 - ld a, INVERSE1 ; CPL -> INVERSE1 -CONT2: - ld (INVERSE_MODE), a - ret -TABLE: - nop ; NORMAL MODE - xor (hl) ; OVER 1 MODE - and (hl) ; OVER 2 MODE - or (hl) ; OVER 3 MODE -#line 67 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" -__REFRESH_TMP: - ld a, (hl) - and 0b10101010 - ld c, a - rra - or c - ld (hl), a - ret - ENDP - pop namespace -#line 4 "/zxbasic/src/arch/zx48k/library-asm/over.asm" push namespace core OVER: PROC @@ -681,11 +629,10 @@ INVERSE_MODE: ; 00 -> NOP -> INVERSE 0 inc hl ld (DFCC), hl ld hl, (DFCCL) ; current ATTR Pos - push hl - call __SET_ATTR - pop hl inc hl - ld (DFCCL),hl + ld (DFCCL), hl + dec hl + call __SET_ATTR exx ret ; ------------- SPECIAL CHARS (< 32) ----------------- @@ -704,7 +651,7 @@ __PRINT_0Dh: ; Called WHEN printing CHR$(13) push hl call __SCROLL_SCR pop hl -#line 210 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 209 "/zxbasic/src/arch/zx48k/library-asm/print.asm" 1: ld l, 1 __PRINT_EOL_END: @@ -821,14 +768,14 @@ __PRINT_BOLD: __PRINT_BOLD2: call BOLD_TMP jp __PRINT_RESTART -#line 354 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 353 "/zxbasic/src/arch/zx48k/library-asm/print.asm" __PRINT_ITA: ld hl, __PRINT_ITA2 jp __PRINT_SET_STATE __PRINT_ITA2: call ITALIC_TMP jp __PRINT_RESTART -#line 364 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 363 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __BOLD __BOLD: push hl @@ -846,7 +793,7 @@ __BOLD: pop hl ld de, MEM0 ret -#line 385 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 384 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __ITALIC __ITALIC: push hl @@ -871,12 +818,12 @@ __ITALIC: pop hl ld de, MEM0 ret -#line 413 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 412 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __SCROLL_SCR -#line 487 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 486 "/zxbasic/src/arch/zx48k/library-asm/print.asm" __SCROLL_SCR EQU 0DFEh ; Use ROM SCROLL +#line 488 "/zxbasic/src/arch/zx48k/library-asm/print.asm" #line 489 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -#line 490 "/zxbasic/src/arch/zx48k/library-asm/print.asm" PRINT_COMMA: call __LOAD_S_POSN ld a, e @@ -919,9 +866,9 @@ PRINT_AT: ; Changes cursor to ROW, COL LOCAL __PRINT_TABLE LOCAL __PRINT_TAB, __PRINT_TAB1, __PRINT_TAB2 LOCAL __PRINT_ITA2 -#line 546 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 545 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __PRINT_BOLD2 -#line 552 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 551 "/zxbasic/src/arch/zx48k/library-asm/print.asm" __PRINT_TABLE: ; Jump table for 0 .. 22 codes DW __PRINT_NOP ; 0 DW __PRINT_NOP ; 1 @@ -949,5 +896,58 @@ __PRINT_TABLE: ; Jump table for 0 .. 22 codes DW __PRINT_TAB ; 23 TAB ENDP pop namespace -#line 18 "zx48k/print_eol.bas" +#line 3 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" +#line 4 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" + push namespace core +COPY_ATTR: + ; Just copies current permanent attribs into temporal attribs + ; and sets print mode + PROC + LOCAL INVERSE1 + LOCAL __REFRESH_TMP + INVERSE1 EQU 02Fh + ld hl, (ATTR_P) + ld (ATTR_T), hl + ld hl, FLAGS2 + call __REFRESH_TMP + ld hl, P_FLAG + call __REFRESH_TMP +__SET_ATTR_MODE: ; Another entry to set print modes. A contains (P_FLAG) + LOCAL TABLE + LOCAL CONT2 + rra ; Over bit to carry + ld a, (FLAGS2) + rla ; Over bit in bit 1, Over2 bit in bit 2 + and 3 ; Only bit 0 and 1 (OVER flag) + ld c, a + ld b, 0 + ld hl, TABLE + add hl, bc + ld a, (hl) + ld (PRINT_MODE), a + ld hl, (P_FLAG) + xor a ; NOP -> INVERSE0 + bit 2, l + jr z, CONT2 + ld a, INVERSE1 ; CPL -> INVERSE1 +CONT2: + ld (INVERSE_MODE), a + ret +TABLE: + nop ; NORMAL MODE + xor (hl) ; OVER 1 MODE + and (hl) ; OVER 2 MODE + or (hl) ; OVER 3 MODE +#line 67 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" +__REFRESH_TMP: + ld a, (hl) + and 0b10101010 + ld c, a + rra + or c + ld (hl), a + ret + ENDP + pop namespace +#line 19 "zx48k/print_eol.bas" END diff --git a/tests/functional/zx48k/print_eol_attr.asm b/tests/functional/zx48k/print_eol_attr.asm index 99fff1184..c34cc87ec 100644 --- a/tests/functional/zx48k/print_eol_attr.asm +++ b/tests/functional/zx48k/print_eol_attr.asm @@ -28,10 +28,11 @@ _a: DEFB 00, 00 .core.ZXBASIC_USER_DATA_END: .core.__MAIN_PROGRAM__: + call .core.COPY_ATTR ld hl, (_a) xor a call .core.__PRINTSTR - call .core.PRINT_EOL_ATTR + call .core.PRINT_EOL ld hl, 0 ld b, h ld c, l @@ -47,9 +48,7 @@ _a: ei ret ;; --- end of user code --- -#line 1 "/zxbasic/src/arch/zx48k/library-asm/print_eol_attr.asm" - ; Calls PRINT_EOL and then COPY_ATTR, so saves - ; 3 bytes +#line 1 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" #line 1 "/zxbasic/src/arch/zx48k/library-asm/print.asm" ; vim:ts=4:sw=4:et: ; PRINT command routine @@ -399,60 +398,6 @@ BRIGHT_TMP: #line 1 "/zxbasic/src/arch/zx48k/library-asm/over.asm" ; Sets OVER flag in P_FLAG permanently ; Parameter: OVER flag in bit 0 of A register -#line 1 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" -#line 4 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" - push namespace core -COPY_ATTR: - ; Just copies current permanent attribs into temporal attribs - ; and sets print mode - PROC - LOCAL INVERSE1 - LOCAL __REFRESH_TMP - INVERSE1 EQU 02Fh - ld hl, (ATTR_P) - ld (ATTR_T), hl - ld hl, FLAGS2 - call __REFRESH_TMP - ld hl, P_FLAG - call __REFRESH_TMP -__SET_ATTR_MODE: ; Another entry to set print modes. A contains (P_FLAG) - LOCAL TABLE - LOCAL CONT2 - rra ; Over bit to carry - ld a, (FLAGS2) - rla ; Over bit in bit 1, Over2 bit in bit 2 - and 3 ; Only bit 0 and 1 (OVER flag) - ld c, a - ld b, 0 - ld hl, TABLE - add hl, bc - ld a, (hl) - ld (PRINT_MODE), a - ld hl, (P_FLAG) - xor a ; NOP -> INVERSE0 - bit 2, l - jr z, CONT2 - ld a, INVERSE1 ; CPL -> INVERSE1 -CONT2: - ld (INVERSE_MODE), a - ret -TABLE: - nop ; NORMAL MODE - xor (hl) ; OVER 1 MODE - and (hl) ; OVER 2 MODE - or (hl) ; OVER 3 MODE -#line 67 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" -__REFRESH_TMP: - ld a, (hl) - and 0b10101010 - ld c, a - rra - or c - ld (hl), a - ret - ENDP - pop namespace -#line 4 "/zxbasic/src/arch/zx48k/library-asm/over.asm" push namespace core OVER: PROC @@ -694,11 +639,10 @@ INVERSE_MODE: ; 00 -> NOP -> INVERSE 0 inc hl ld (DFCC), hl ld hl, (DFCCL) ; current ATTR Pos - push hl - call __SET_ATTR - pop hl inc hl - ld (DFCCL),hl + ld (DFCCL), hl + dec hl + call __SET_ATTR exx ret ; ------------- SPECIAL CHARS (< 32) ----------------- @@ -717,7 +661,7 @@ __PRINT_0Dh: ; Called WHEN printing CHR$(13) push hl call __SCROLL_SCR pop hl -#line 210 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 209 "/zxbasic/src/arch/zx48k/library-asm/print.asm" 1: ld l, 1 __PRINT_EOL_END: @@ -834,14 +778,14 @@ __PRINT_BOLD: __PRINT_BOLD2: call BOLD_TMP jp __PRINT_RESTART -#line 354 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 353 "/zxbasic/src/arch/zx48k/library-asm/print.asm" __PRINT_ITA: ld hl, __PRINT_ITA2 jp __PRINT_SET_STATE __PRINT_ITA2: call ITALIC_TMP jp __PRINT_RESTART -#line 364 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 363 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __BOLD __BOLD: push hl @@ -859,7 +803,7 @@ __BOLD: pop hl ld de, MEM0 ret -#line 385 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 384 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __ITALIC __ITALIC: push hl @@ -884,12 +828,12 @@ __ITALIC: pop hl ld de, MEM0 ret -#line 413 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 412 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __SCROLL_SCR -#line 487 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 486 "/zxbasic/src/arch/zx48k/library-asm/print.asm" __SCROLL_SCR EQU 0DFEh ; Use ROM SCROLL +#line 488 "/zxbasic/src/arch/zx48k/library-asm/print.asm" #line 489 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -#line 490 "/zxbasic/src/arch/zx48k/library-asm/print.asm" PRINT_COMMA: call __LOAD_S_POSN ld a, e @@ -932,9 +876,9 @@ PRINT_AT: ; Changes cursor to ROW, COL LOCAL __PRINT_TABLE LOCAL __PRINT_TAB, __PRINT_TAB1, __PRINT_TAB2 LOCAL __PRINT_ITA2 -#line 546 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 545 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __PRINT_BOLD2 -#line 552 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 551 "/zxbasic/src/arch/zx48k/library-asm/print.asm" __PRINT_TABLE: ; Jump table for 0 .. 22 codes DW __PRINT_NOP ; 0 DW __PRINT_NOP ; 1 @@ -962,13 +906,60 @@ __PRINT_TABLE: ; Jump table for 0 .. 22 codes DW __PRINT_TAB ; 23 TAB ENDP pop namespace -#line 5 "/zxbasic/src/arch/zx48k/library-asm/print_eol_attr.asm" +#line 3 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" +#line 4 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" push namespace core -PRINT_EOL_ATTR: - call PRINT_EOL - jp COPY_ATTR +COPY_ATTR: + ; Just copies current permanent attribs into temporal attribs + ; and sets print mode + PROC + LOCAL INVERSE1 + LOCAL __REFRESH_TMP + INVERSE1 EQU 02Fh + ld hl, (ATTR_P) + ld (ATTR_T), hl + ld hl, FLAGS2 + call __REFRESH_TMP + ld hl, P_FLAG + call __REFRESH_TMP +__SET_ATTR_MODE: ; Another entry to set print modes. A contains (P_FLAG) + LOCAL TABLE + LOCAL CONT2 + rra ; Over bit to carry + ld a, (FLAGS2) + rla ; Over bit in bit 1, Over2 bit in bit 2 + and 3 ; Only bit 0 and 1 (OVER flag) + ld c, a + ld b, 0 + ld hl, TABLE + add hl, bc + ld a, (hl) + ld (PRINT_MODE), a + ld hl, (P_FLAG) + xor a ; NOP -> INVERSE0 + bit 2, l + jr z, CONT2 + ld a, INVERSE1 ; CPL -> INVERSE1 +CONT2: + ld (INVERSE_MODE), a + ret +TABLE: + nop ; NORMAL MODE + xor (hl) ; OVER 1 MODE + and (hl) ; OVER 2 MODE + or (hl) ; OVER 3 MODE +#line 67 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" +__REFRESH_TMP: + ld a, (hl) + and 0b10101010 + ld c, a + rra + or c + ld (hl), a + ret + ENDP pop namespace -#line 21 "zx48k/print_eol_attr.bas" +#line 22 "zx48k/print_eol_attr.bas" #line 1 "/zxbasic/src/arch/zx48k/library-asm/printstr.asm" #line 1 "/zxbasic/src/arch/zx48k/library-asm/free.asm" ; vim: ts=4:et:sw=4: @@ -1279,5 +1270,5 @@ __PRINT_STR: jp __PRINT_STR_LOOP ENDP pop namespace -#line 22 "zx48k/print_eol_attr.bas" +#line 24 "zx48k/print_eol_attr.bas" END diff --git a/tests/functional/zx48k/print_f.asm b/tests/functional/zx48k/print_f.asm index db61fb649..42f59136b 100644 --- a/tests/functional/zx48k/print_f.asm +++ b/tests/functional/zx48k/print_f.asm @@ -28,6 +28,7 @@ _a: DEFB 00, 00, 00, 00, 00 .core.ZXBASIC_USER_DATA_END: .core.__MAIN_PROGRAM__: + call .core.COPY_ATTR ld a, (_a) ld de, (_a + 1) ld bc, (_a + 3) @@ -47,8 +48,7 @@ _a: ei ret ;; --- end of user code --- -#line 1 "/zxbasic/src/arch/zx48k/library-asm/printf.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/printstr.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" #line 1 "/zxbasic/src/arch/zx48k/library-asm/print.asm" ; vim:ts=4:sw=4:et: ; PRINT command routine @@ -398,60 +398,6 @@ BRIGHT_TMP: #line 1 "/zxbasic/src/arch/zx48k/library-asm/over.asm" ; Sets OVER flag in P_FLAG permanently ; Parameter: OVER flag in bit 0 of A register -#line 1 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" -#line 4 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" - push namespace core -COPY_ATTR: - ; Just copies current permanent attribs into temporal attribs - ; and sets print mode - PROC - LOCAL INVERSE1 - LOCAL __REFRESH_TMP - INVERSE1 EQU 02Fh - ld hl, (ATTR_P) - ld (ATTR_T), hl - ld hl, FLAGS2 - call __REFRESH_TMP - ld hl, P_FLAG - call __REFRESH_TMP -__SET_ATTR_MODE: ; Another entry to set print modes. A contains (P_FLAG) - LOCAL TABLE - LOCAL CONT2 - rra ; Over bit to carry - ld a, (FLAGS2) - rla ; Over bit in bit 1, Over2 bit in bit 2 - and 3 ; Only bit 0 and 1 (OVER flag) - ld c, a - ld b, 0 - ld hl, TABLE - add hl, bc - ld a, (hl) - ld (PRINT_MODE), a - ld hl, (P_FLAG) - xor a ; NOP -> INVERSE0 - bit 2, l - jr z, CONT2 - ld a, INVERSE1 ; CPL -> INVERSE1 -CONT2: - ld (INVERSE_MODE), a - ret -TABLE: - nop ; NORMAL MODE - xor (hl) ; OVER 1 MODE - and (hl) ; OVER 2 MODE - or (hl) ; OVER 3 MODE -#line 67 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" -__REFRESH_TMP: - ld a, (hl) - and 0b10101010 - ld c, a - rra - or c - ld (hl), a - ret - ENDP - pop namespace -#line 4 "/zxbasic/src/arch/zx48k/library-asm/over.asm" push namespace core OVER: PROC @@ -693,11 +639,10 @@ INVERSE_MODE: ; 00 -> NOP -> INVERSE 0 inc hl ld (DFCC), hl ld hl, (DFCCL) ; current ATTR Pos - push hl - call __SET_ATTR - pop hl inc hl - ld (DFCCL),hl + ld (DFCCL), hl + dec hl + call __SET_ATTR exx ret ; ------------- SPECIAL CHARS (< 32) ----------------- @@ -716,7 +661,7 @@ __PRINT_0Dh: ; Called WHEN printing CHR$(13) push hl call __SCROLL_SCR pop hl -#line 210 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 209 "/zxbasic/src/arch/zx48k/library-asm/print.asm" 1: ld l, 1 __PRINT_EOL_END: @@ -833,14 +778,14 @@ __PRINT_BOLD: __PRINT_BOLD2: call BOLD_TMP jp __PRINT_RESTART -#line 354 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 353 "/zxbasic/src/arch/zx48k/library-asm/print.asm" __PRINT_ITA: ld hl, __PRINT_ITA2 jp __PRINT_SET_STATE __PRINT_ITA2: call ITALIC_TMP jp __PRINT_RESTART -#line 364 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 363 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __BOLD __BOLD: push hl @@ -858,7 +803,7 @@ __BOLD: pop hl ld de, MEM0 ret -#line 385 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 384 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __ITALIC __ITALIC: push hl @@ -883,12 +828,12 @@ __ITALIC: pop hl ld de, MEM0 ret -#line 413 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 412 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __SCROLL_SCR -#line 487 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 486 "/zxbasic/src/arch/zx48k/library-asm/print.asm" __SCROLL_SCR EQU 0DFEh ; Use ROM SCROLL +#line 488 "/zxbasic/src/arch/zx48k/library-asm/print.asm" #line 489 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -#line 490 "/zxbasic/src/arch/zx48k/library-asm/print.asm" PRINT_COMMA: call __LOAD_S_POSN ld a, e @@ -931,9 +876,9 @@ PRINT_AT: ; Changes cursor to ROW, COL LOCAL __PRINT_TABLE LOCAL __PRINT_TAB, __PRINT_TAB1, __PRINT_TAB2 LOCAL __PRINT_ITA2 -#line 546 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 545 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __PRINT_BOLD2 -#line 552 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 551 "/zxbasic/src/arch/zx48k/library-asm/print.asm" __PRINT_TABLE: ; Jump table for 0 .. 22 codes DW __PRINT_NOP ; 0 DW __PRINT_NOP ; 1 @@ -961,7 +906,62 @@ __PRINT_TABLE: ; Jump table for 0 .. 22 codes DW __PRINT_TAB ; 23 TAB ENDP pop namespace -#line 2 "/zxbasic/src/arch/zx48k/library-asm/printstr.asm" +#line 3 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" +#line 4 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" + push namespace core +COPY_ATTR: + ; Just copies current permanent attribs into temporal attribs + ; and sets print mode + PROC + LOCAL INVERSE1 + LOCAL __REFRESH_TMP + INVERSE1 EQU 02Fh + ld hl, (ATTR_P) + ld (ATTR_T), hl + ld hl, FLAGS2 + call __REFRESH_TMP + ld hl, P_FLAG + call __REFRESH_TMP +__SET_ATTR_MODE: ; Another entry to set print modes. A contains (P_FLAG) + LOCAL TABLE + LOCAL CONT2 + rra ; Over bit to carry + ld a, (FLAGS2) + rla ; Over bit in bit 1, Over2 bit in bit 2 + and 3 ; Only bit 0 and 1 (OVER flag) + ld c, a + ld b, 0 + ld hl, TABLE + add hl, bc + ld a, (hl) + ld (PRINT_MODE), a + ld hl, (P_FLAG) + xor a ; NOP -> INVERSE0 + bit 2, l + jr z, CONT2 + ld a, INVERSE1 ; CPL -> INVERSE1 +CONT2: + ld (INVERSE_MODE), a + ret +TABLE: + nop ; NORMAL MODE + xor (hl) ; OVER 1 MODE + and (hl) ; OVER 2 MODE + or (hl) ; OVER 3 MODE +#line 67 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" +__REFRESH_TMP: + ld a, (hl) + and 0b10101010 + ld c, a + rra + or c + ld (hl), a + ret + ENDP + pop namespace +#line 22 "zx48k/print_f.bas" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/printf.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/printstr.asm" #line 1 "/zxbasic/src/arch/zx48k/library-asm/free.asm" ; vim: ts=4:et:sw=4: ; Copyleft (K) by Jose M. Rodriguez de la Rosa @@ -1341,5 +1341,5 @@ __PRINTF: ; Prints a Fixed point Number stored in C ED LH RECLAIM2 EQU 19E8h ENDP pop namespace -#line 21 "zx48k/print_f.bas" +#line 23 "zx48k/print_f.bas" END diff --git a/tests/functional/zx48k/print_f16.asm b/tests/functional/zx48k/print_f16.asm index d83f989c1..435054266 100644 --- a/tests/functional/zx48k/print_f16.asm +++ b/tests/functional/zx48k/print_f16.asm @@ -23,6 +23,7 @@ _a: DEFB 00, 00, 00, 00 .core.ZXBASIC_USER_DATA_END: .core.__MAIN_PROGRAM__: + call .core.COPY_ATTR ld hl, (_a) ld de, (_a + 2) call .core.__PRINTF16 @@ -41,8 +42,7 @@ _a: ei ret ;; --- end of user code --- -#line 1 "/zxbasic/src/arch/zx48k/library-asm/printf16.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/printnum.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" #line 1 "/zxbasic/src/arch/zx48k/library-asm/print.asm" ; vim:ts=4:sw=4:et: ; PRINT command routine @@ -392,60 +392,6 @@ BRIGHT_TMP: #line 1 "/zxbasic/src/arch/zx48k/library-asm/over.asm" ; Sets OVER flag in P_FLAG permanently ; Parameter: OVER flag in bit 0 of A register -#line 1 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" -#line 4 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" - push namespace core -COPY_ATTR: - ; Just copies current permanent attribs into temporal attribs - ; and sets print mode - PROC - LOCAL INVERSE1 - LOCAL __REFRESH_TMP - INVERSE1 EQU 02Fh - ld hl, (ATTR_P) - ld (ATTR_T), hl - ld hl, FLAGS2 - call __REFRESH_TMP - ld hl, P_FLAG - call __REFRESH_TMP -__SET_ATTR_MODE: ; Another entry to set print modes. A contains (P_FLAG) - LOCAL TABLE - LOCAL CONT2 - rra ; Over bit to carry - ld a, (FLAGS2) - rla ; Over bit in bit 1, Over2 bit in bit 2 - and 3 ; Only bit 0 and 1 (OVER flag) - ld c, a - ld b, 0 - ld hl, TABLE - add hl, bc - ld a, (hl) - ld (PRINT_MODE), a - ld hl, (P_FLAG) - xor a ; NOP -> INVERSE0 - bit 2, l - jr z, CONT2 - ld a, INVERSE1 ; CPL -> INVERSE1 -CONT2: - ld (INVERSE_MODE), a - ret -TABLE: - nop ; NORMAL MODE - xor (hl) ; OVER 1 MODE - and (hl) ; OVER 2 MODE - or (hl) ; OVER 3 MODE -#line 67 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" -__REFRESH_TMP: - ld a, (hl) - and 0b10101010 - ld c, a - rra - or c - ld (hl), a - ret - ENDP - pop namespace -#line 4 "/zxbasic/src/arch/zx48k/library-asm/over.asm" push namespace core OVER: PROC @@ -687,11 +633,10 @@ INVERSE_MODE: ; 00 -> NOP -> INVERSE 0 inc hl ld (DFCC), hl ld hl, (DFCCL) ; current ATTR Pos - push hl - call __SET_ATTR - pop hl inc hl - ld (DFCCL),hl + ld (DFCCL), hl + dec hl + call __SET_ATTR exx ret ; ------------- SPECIAL CHARS (< 32) ----------------- @@ -710,7 +655,7 @@ __PRINT_0Dh: ; Called WHEN printing CHR$(13) push hl call __SCROLL_SCR pop hl -#line 210 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 209 "/zxbasic/src/arch/zx48k/library-asm/print.asm" 1: ld l, 1 __PRINT_EOL_END: @@ -827,14 +772,14 @@ __PRINT_BOLD: __PRINT_BOLD2: call BOLD_TMP jp __PRINT_RESTART -#line 354 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 353 "/zxbasic/src/arch/zx48k/library-asm/print.asm" __PRINT_ITA: ld hl, __PRINT_ITA2 jp __PRINT_SET_STATE __PRINT_ITA2: call ITALIC_TMP jp __PRINT_RESTART -#line 364 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 363 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __BOLD __BOLD: push hl @@ -852,7 +797,7 @@ __BOLD: pop hl ld de, MEM0 ret -#line 385 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 384 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __ITALIC __ITALIC: push hl @@ -877,12 +822,12 @@ __ITALIC: pop hl ld de, MEM0 ret -#line 413 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 412 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __SCROLL_SCR -#line 487 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 486 "/zxbasic/src/arch/zx48k/library-asm/print.asm" __SCROLL_SCR EQU 0DFEh ; Use ROM SCROLL +#line 488 "/zxbasic/src/arch/zx48k/library-asm/print.asm" #line 489 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -#line 490 "/zxbasic/src/arch/zx48k/library-asm/print.asm" PRINT_COMMA: call __LOAD_S_POSN ld a, e @@ -925,9 +870,9 @@ PRINT_AT: ; Changes cursor to ROW, COL LOCAL __PRINT_TABLE LOCAL __PRINT_TAB, __PRINT_TAB1, __PRINT_TAB2 LOCAL __PRINT_ITA2 -#line 546 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 545 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __PRINT_BOLD2 -#line 552 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 551 "/zxbasic/src/arch/zx48k/library-asm/print.asm" __PRINT_TABLE: ; Jump table for 0 .. 22 codes DW __PRINT_NOP ; 0 DW __PRINT_NOP ; 1 @@ -955,7 +900,62 @@ __PRINT_TABLE: ; Jump table for 0 .. 22 codes DW __PRINT_TAB ; 23 TAB ENDP pop namespace -#line 2 "/zxbasic/src/arch/zx48k/library-asm/printnum.asm" +#line 3 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" +#line 4 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" + push namespace core +COPY_ATTR: + ; Just copies current permanent attribs into temporal attribs + ; and sets print mode + PROC + LOCAL INVERSE1 + LOCAL __REFRESH_TMP + INVERSE1 EQU 02Fh + ld hl, (ATTR_P) + ld (ATTR_T), hl + ld hl, FLAGS2 + call __REFRESH_TMP + ld hl, P_FLAG + call __REFRESH_TMP +__SET_ATTR_MODE: ; Another entry to set print modes. A contains (P_FLAG) + LOCAL TABLE + LOCAL CONT2 + rra ; Over bit to carry + ld a, (FLAGS2) + rla ; Over bit in bit 1, Over2 bit in bit 2 + and 3 ; Only bit 0 and 1 (OVER flag) + ld c, a + ld b, 0 + ld hl, TABLE + add hl, bc + ld a, (hl) + ld (PRINT_MODE), a + ld hl, (P_FLAG) + xor a ; NOP -> INVERSE0 + bit 2, l + jr z, CONT2 + ld a, INVERSE1 ; CPL -> INVERSE1 +CONT2: + ld (INVERSE_MODE), a + ret +TABLE: + nop ; NORMAL MODE + xor (hl) ; OVER 1 MODE + and (hl) ; OVER 2 MODE + or (hl) ; OVER 3 MODE +#line 67 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" +__REFRESH_TMP: + ld a, (hl) + and 0b10101010 + ld c, a + rra + or c + ld (hl), a + ret + ENDP + pop namespace +#line 21 "zx48k/print_f16.bas" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/printf16.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/printnum.asm" push namespace core __PRINTU_START: PROC @@ -1171,5 +1171,5 @@ __PRINT_FIX_LOOP: jp __PRINT_FIX_LOOP ENDP pop namespace -#line 20 "zx48k/print_f16.bas" +#line 22 "zx48k/print_f16.bas" END diff --git a/tests/functional/zx48k/print_i16.asm b/tests/functional/zx48k/print_i16.asm index c5023a2fa..6028ccecf 100644 --- a/tests/functional/zx48k/print_i16.asm +++ b/tests/functional/zx48k/print_i16.asm @@ -23,6 +23,7 @@ _a: DEFB 00, 00 .core.ZXBASIC_USER_DATA_END: .core.__MAIN_PROGRAM__: + call .core.COPY_ATTR ld hl, (_a) call .core.__PRINTI16 ld hl, 0 @@ -40,8 +41,7 @@ _a: ei ret ;; --- end of user code --- -#line 1 "/zxbasic/src/arch/zx48k/library-asm/printi16.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/printnum.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" #line 1 "/zxbasic/src/arch/zx48k/library-asm/print.asm" ; vim:ts=4:sw=4:et: ; PRINT command routine @@ -391,60 +391,6 @@ BRIGHT_TMP: #line 1 "/zxbasic/src/arch/zx48k/library-asm/over.asm" ; Sets OVER flag in P_FLAG permanently ; Parameter: OVER flag in bit 0 of A register -#line 1 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" -#line 4 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" - push namespace core -COPY_ATTR: - ; Just copies current permanent attribs into temporal attribs - ; and sets print mode - PROC - LOCAL INVERSE1 - LOCAL __REFRESH_TMP - INVERSE1 EQU 02Fh - ld hl, (ATTR_P) - ld (ATTR_T), hl - ld hl, FLAGS2 - call __REFRESH_TMP - ld hl, P_FLAG - call __REFRESH_TMP -__SET_ATTR_MODE: ; Another entry to set print modes. A contains (P_FLAG) - LOCAL TABLE - LOCAL CONT2 - rra ; Over bit to carry - ld a, (FLAGS2) - rla ; Over bit in bit 1, Over2 bit in bit 2 - and 3 ; Only bit 0 and 1 (OVER flag) - ld c, a - ld b, 0 - ld hl, TABLE - add hl, bc - ld a, (hl) - ld (PRINT_MODE), a - ld hl, (P_FLAG) - xor a ; NOP -> INVERSE0 - bit 2, l - jr z, CONT2 - ld a, INVERSE1 ; CPL -> INVERSE1 -CONT2: - ld (INVERSE_MODE), a - ret -TABLE: - nop ; NORMAL MODE - xor (hl) ; OVER 1 MODE - and (hl) ; OVER 2 MODE - or (hl) ; OVER 3 MODE -#line 67 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" -__REFRESH_TMP: - ld a, (hl) - and 0b10101010 - ld c, a - rra - or c - ld (hl), a - ret - ENDP - pop namespace -#line 4 "/zxbasic/src/arch/zx48k/library-asm/over.asm" push namespace core OVER: PROC @@ -686,11 +632,10 @@ INVERSE_MODE: ; 00 -> NOP -> INVERSE 0 inc hl ld (DFCC), hl ld hl, (DFCCL) ; current ATTR Pos - push hl - call __SET_ATTR - pop hl inc hl - ld (DFCCL),hl + ld (DFCCL), hl + dec hl + call __SET_ATTR exx ret ; ------------- SPECIAL CHARS (< 32) ----------------- @@ -709,7 +654,7 @@ __PRINT_0Dh: ; Called WHEN printing CHR$(13) push hl call __SCROLL_SCR pop hl -#line 210 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 209 "/zxbasic/src/arch/zx48k/library-asm/print.asm" 1: ld l, 1 __PRINT_EOL_END: @@ -826,14 +771,14 @@ __PRINT_BOLD: __PRINT_BOLD2: call BOLD_TMP jp __PRINT_RESTART -#line 354 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 353 "/zxbasic/src/arch/zx48k/library-asm/print.asm" __PRINT_ITA: ld hl, __PRINT_ITA2 jp __PRINT_SET_STATE __PRINT_ITA2: call ITALIC_TMP jp __PRINT_RESTART -#line 364 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 363 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __BOLD __BOLD: push hl @@ -851,7 +796,7 @@ __BOLD: pop hl ld de, MEM0 ret -#line 385 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 384 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __ITALIC __ITALIC: push hl @@ -876,12 +821,12 @@ __ITALIC: pop hl ld de, MEM0 ret -#line 413 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 412 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __SCROLL_SCR -#line 487 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 486 "/zxbasic/src/arch/zx48k/library-asm/print.asm" __SCROLL_SCR EQU 0DFEh ; Use ROM SCROLL +#line 488 "/zxbasic/src/arch/zx48k/library-asm/print.asm" #line 489 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -#line 490 "/zxbasic/src/arch/zx48k/library-asm/print.asm" PRINT_COMMA: call __LOAD_S_POSN ld a, e @@ -924,9 +869,9 @@ PRINT_AT: ; Changes cursor to ROW, COL LOCAL __PRINT_TABLE LOCAL __PRINT_TAB, __PRINT_TAB1, __PRINT_TAB2 LOCAL __PRINT_ITA2 -#line 546 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 545 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __PRINT_BOLD2 -#line 552 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 551 "/zxbasic/src/arch/zx48k/library-asm/print.asm" __PRINT_TABLE: ; Jump table for 0 .. 22 codes DW __PRINT_NOP ; 0 DW __PRINT_NOP ; 1 @@ -954,7 +899,62 @@ __PRINT_TABLE: ; Jump table for 0 .. 22 codes DW __PRINT_TAB ; 23 TAB ENDP pop namespace -#line 2 "/zxbasic/src/arch/zx48k/library-asm/printnum.asm" +#line 3 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" +#line 4 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" + push namespace core +COPY_ATTR: + ; Just copies current permanent attribs into temporal attribs + ; and sets print mode + PROC + LOCAL INVERSE1 + LOCAL __REFRESH_TMP + INVERSE1 EQU 02Fh + ld hl, (ATTR_P) + ld (ATTR_T), hl + ld hl, FLAGS2 + call __REFRESH_TMP + ld hl, P_FLAG + call __REFRESH_TMP +__SET_ATTR_MODE: ; Another entry to set print modes. A contains (P_FLAG) + LOCAL TABLE + LOCAL CONT2 + rra ; Over bit to carry + ld a, (FLAGS2) + rla ; Over bit in bit 1, Over2 bit in bit 2 + and 3 ; Only bit 0 and 1 (OVER flag) + ld c, a + ld b, 0 + ld hl, TABLE + add hl, bc + ld a, (hl) + ld (PRINT_MODE), a + ld hl, (P_FLAG) + xor a ; NOP -> INVERSE0 + bit 2, l + jr z, CONT2 + ld a, INVERSE1 ; CPL -> INVERSE1 +CONT2: + ld (INVERSE_MODE), a + ret +TABLE: + nop ; NORMAL MODE + xor (hl) ; OVER 1 MODE + and (hl) ; OVER 2 MODE + or (hl) ; OVER 3 MODE +#line 67 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" +__REFRESH_TMP: + ld a, (hl) + and 0b10101010 + ld c, a + rra + or c + ld (hl), a + ret + ENDP + pop namespace +#line 20 "zx48k/print_i16.bas" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/printi16.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/printnum.asm" push namespace core __PRINTU_START: PROC @@ -1098,5 +1098,5 @@ __PRINTU_LOOP: jp __PRINTU_LOOP ; Uses JP in loops ENDP pop namespace -#line 19 "zx48k/print_i16.bas" +#line 21 "zx48k/print_i16.bas" END diff --git a/tests/functional/zx48k/print_i32.asm b/tests/functional/zx48k/print_i32.asm index 2ae01b77b..0b9ac0f85 100644 --- a/tests/functional/zx48k/print_i32.asm +++ b/tests/functional/zx48k/print_i32.asm @@ -23,6 +23,7 @@ _a: DEFB 00, 00, 00, 00 .core.ZXBASIC_USER_DATA_END: .core.__MAIN_PROGRAM__: + call .core.COPY_ATTR ld hl, (_a) ld de, (_a + 2) call .core.__PRINTI32 @@ -41,8 +42,7 @@ _a: ei ret ;; --- end of user code --- -#line 1 "/zxbasic/src/arch/zx48k/library-asm/printi32.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/printnum.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" #line 1 "/zxbasic/src/arch/zx48k/library-asm/print.asm" ; vim:ts=4:sw=4:et: ; PRINT command routine @@ -392,60 +392,6 @@ BRIGHT_TMP: #line 1 "/zxbasic/src/arch/zx48k/library-asm/over.asm" ; Sets OVER flag in P_FLAG permanently ; Parameter: OVER flag in bit 0 of A register -#line 1 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" -#line 4 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" - push namespace core -COPY_ATTR: - ; Just copies current permanent attribs into temporal attribs - ; and sets print mode - PROC - LOCAL INVERSE1 - LOCAL __REFRESH_TMP - INVERSE1 EQU 02Fh - ld hl, (ATTR_P) - ld (ATTR_T), hl - ld hl, FLAGS2 - call __REFRESH_TMP - ld hl, P_FLAG - call __REFRESH_TMP -__SET_ATTR_MODE: ; Another entry to set print modes. A contains (P_FLAG) - LOCAL TABLE - LOCAL CONT2 - rra ; Over bit to carry - ld a, (FLAGS2) - rla ; Over bit in bit 1, Over2 bit in bit 2 - and 3 ; Only bit 0 and 1 (OVER flag) - ld c, a - ld b, 0 - ld hl, TABLE - add hl, bc - ld a, (hl) - ld (PRINT_MODE), a - ld hl, (P_FLAG) - xor a ; NOP -> INVERSE0 - bit 2, l - jr z, CONT2 - ld a, INVERSE1 ; CPL -> INVERSE1 -CONT2: - ld (INVERSE_MODE), a - ret -TABLE: - nop ; NORMAL MODE - xor (hl) ; OVER 1 MODE - and (hl) ; OVER 2 MODE - or (hl) ; OVER 3 MODE -#line 67 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" -__REFRESH_TMP: - ld a, (hl) - and 0b10101010 - ld c, a - rra - or c - ld (hl), a - ret - ENDP - pop namespace -#line 4 "/zxbasic/src/arch/zx48k/library-asm/over.asm" push namespace core OVER: PROC @@ -687,11 +633,10 @@ INVERSE_MODE: ; 00 -> NOP -> INVERSE 0 inc hl ld (DFCC), hl ld hl, (DFCCL) ; current ATTR Pos - push hl - call __SET_ATTR - pop hl inc hl - ld (DFCCL),hl + ld (DFCCL), hl + dec hl + call __SET_ATTR exx ret ; ------------- SPECIAL CHARS (< 32) ----------------- @@ -710,7 +655,7 @@ __PRINT_0Dh: ; Called WHEN printing CHR$(13) push hl call __SCROLL_SCR pop hl -#line 210 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 209 "/zxbasic/src/arch/zx48k/library-asm/print.asm" 1: ld l, 1 __PRINT_EOL_END: @@ -827,14 +772,14 @@ __PRINT_BOLD: __PRINT_BOLD2: call BOLD_TMP jp __PRINT_RESTART -#line 354 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 353 "/zxbasic/src/arch/zx48k/library-asm/print.asm" __PRINT_ITA: ld hl, __PRINT_ITA2 jp __PRINT_SET_STATE __PRINT_ITA2: call ITALIC_TMP jp __PRINT_RESTART -#line 364 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 363 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __BOLD __BOLD: push hl @@ -852,7 +797,7 @@ __BOLD: pop hl ld de, MEM0 ret -#line 385 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 384 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __ITALIC __ITALIC: push hl @@ -877,12 +822,12 @@ __ITALIC: pop hl ld de, MEM0 ret -#line 413 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 412 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __SCROLL_SCR -#line 487 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 486 "/zxbasic/src/arch/zx48k/library-asm/print.asm" __SCROLL_SCR EQU 0DFEh ; Use ROM SCROLL +#line 488 "/zxbasic/src/arch/zx48k/library-asm/print.asm" #line 489 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -#line 490 "/zxbasic/src/arch/zx48k/library-asm/print.asm" PRINT_COMMA: call __LOAD_S_POSN ld a, e @@ -925,9 +870,9 @@ PRINT_AT: ; Changes cursor to ROW, COL LOCAL __PRINT_TABLE LOCAL __PRINT_TAB, __PRINT_TAB1, __PRINT_TAB2 LOCAL __PRINT_ITA2 -#line 546 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 545 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __PRINT_BOLD2 -#line 552 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 551 "/zxbasic/src/arch/zx48k/library-asm/print.asm" __PRINT_TABLE: ; Jump table for 0 .. 22 codes DW __PRINT_NOP ; 0 DW __PRINT_NOP ; 1 @@ -955,7 +900,62 @@ __PRINT_TABLE: ; Jump table for 0 .. 22 codes DW __PRINT_TAB ; 23 TAB ENDP pop namespace -#line 2 "/zxbasic/src/arch/zx48k/library-asm/printnum.asm" +#line 3 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" +#line 4 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" + push namespace core +COPY_ATTR: + ; Just copies current permanent attribs into temporal attribs + ; and sets print mode + PROC + LOCAL INVERSE1 + LOCAL __REFRESH_TMP + INVERSE1 EQU 02Fh + ld hl, (ATTR_P) + ld (ATTR_T), hl + ld hl, FLAGS2 + call __REFRESH_TMP + ld hl, P_FLAG + call __REFRESH_TMP +__SET_ATTR_MODE: ; Another entry to set print modes. A contains (P_FLAG) + LOCAL TABLE + LOCAL CONT2 + rra ; Over bit to carry + ld a, (FLAGS2) + rla ; Over bit in bit 1, Over2 bit in bit 2 + and 3 ; Only bit 0 and 1 (OVER flag) + ld c, a + ld b, 0 + ld hl, TABLE + add hl, bc + ld a, (hl) + ld (PRINT_MODE), a + ld hl, (P_FLAG) + xor a ; NOP -> INVERSE0 + bit 2, l + jr z, CONT2 + ld a, INVERSE1 ; CPL -> INVERSE1 +CONT2: + ld (INVERSE_MODE), a + ret +TABLE: + nop ; NORMAL MODE + xor (hl) ; OVER 1 MODE + and (hl) ; OVER 2 MODE + or (hl) ; OVER 3 MODE +#line 67 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" +__REFRESH_TMP: + ld a, (hl) + and 0b10101010 + ld c, a + rra + or c + ld (hl), a + ret + ENDP + pop namespace +#line 21 "zx48k/print_i32.bas" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/printi32.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/printnum.asm" push namespace core __PRINTU_START: PROC @@ -1152,5 +1152,5 @@ __PRINTU_LOOP: jp __PRINTU_LOOP ; Uses JP in loops ENDP pop namespace -#line 20 "zx48k/print_i32.bas" +#line 22 "zx48k/print_i32.bas" END diff --git a/tests/functional/zx48k/print_i8.asm b/tests/functional/zx48k/print_i8.asm index f17840036..684f4affe 100644 --- a/tests/functional/zx48k/print_i8.asm +++ b/tests/functional/zx48k/print_i8.asm @@ -23,6 +23,7 @@ _a: DEFB 00 .core.ZXBASIC_USER_DATA_END: .core.__MAIN_PROGRAM__: + call .core.COPY_ATTR ld a, (_a) call .core.__PRINTI8 ld hl, 0 @@ -40,8 +41,7 @@ _a: ei ret ;; --- end of user code --- -#line 1 "/zxbasic/src/arch/zx48k/library-asm/printi8.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/printnum.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" #line 1 "/zxbasic/src/arch/zx48k/library-asm/print.asm" ; vim:ts=4:sw=4:et: ; PRINT command routine @@ -391,60 +391,6 @@ BRIGHT_TMP: #line 1 "/zxbasic/src/arch/zx48k/library-asm/over.asm" ; Sets OVER flag in P_FLAG permanently ; Parameter: OVER flag in bit 0 of A register -#line 1 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" -#line 4 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" - push namespace core -COPY_ATTR: - ; Just copies current permanent attribs into temporal attribs - ; and sets print mode - PROC - LOCAL INVERSE1 - LOCAL __REFRESH_TMP - INVERSE1 EQU 02Fh - ld hl, (ATTR_P) - ld (ATTR_T), hl - ld hl, FLAGS2 - call __REFRESH_TMP - ld hl, P_FLAG - call __REFRESH_TMP -__SET_ATTR_MODE: ; Another entry to set print modes. A contains (P_FLAG) - LOCAL TABLE - LOCAL CONT2 - rra ; Over bit to carry - ld a, (FLAGS2) - rla ; Over bit in bit 1, Over2 bit in bit 2 - and 3 ; Only bit 0 and 1 (OVER flag) - ld c, a - ld b, 0 - ld hl, TABLE - add hl, bc - ld a, (hl) - ld (PRINT_MODE), a - ld hl, (P_FLAG) - xor a ; NOP -> INVERSE0 - bit 2, l - jr z, CONT2 - ld a, INVERSE1 ; CPL -> INVERSE1 -CONT2: - ld (INVERSE_MODE), a - ret -TABLE: - nop ; NORMAL MODE - xor (hl) ; OVER 1 MODE - and (hl) ; OVER 2 MODE - or (hl) ; OVER 3 MODE -#line 67 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" -__REFRESH_TMP: - ld a, (hl) - and 0b10101010 - ld c, a - rra - or c - ld (hl), a - ret - ENDP - pop namespace -#line 4 "/zxbasic/src/arch/zx48k/library-asm/over.asm" push namespace core OVER: PROC @@ -686,11 +632,10 @@ INVERSE_MODE: ; 00 -> NOP -> INVERSE 0 inc hl ld (DFCC), hl ld hl, (DFCCL) ; current ATTR Pos - push hl - call __SET_ATTR - pop hl inc hl - ld (DFCCL),hl + ld (DFCCL), hl + dec hl + call __SET_ATTR exx ret ; ------------- SPECIAL CHARS (< 32) ----------------- @@ -709,7 +654,7 @@ __PRINT_0Dh: ; Called WHEN printing CHR$(13) push hl call __SCROLL_SCR pop hl -#line 210 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 209 "/zxbasic/src/arch/zx48k/library-asm/print.asm" 1: ld l, 1 __PRINT_EOL_END: @@ -826,14 +771,14 @@ __PRINT_BOLD: __PRINT_BOLD2: call BOLD_TMP jp __PRINT_RESTART -#line 354 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 353 "/zxbasic/src/arch/zx48k/library-asm/print.asm" __PRINT_ITA: ld hl, __PRINT_ITA2 jp __PRINT_SET_STATE __PRINT_ITA2: call ITALIC_TMP jp __PRINT_RESTART -#line 364 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 363 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __BOLD __BOLD: push hl @@ -851,7 +796,7 @@ __BOLD: pop hl ld de, MEM0 ret -#line 385 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 384 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __ITALIC __ITALIC: push hl @@ -876,12 +821,12 @@ __ITALIC: pop hl ld de, MEM0 ret -#line 413 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 412 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __SCROLL_SCR -#line 487 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 486 "/zxbasic/src/arch/zx48k/library-asm/print.asm" __SCROLL_SCR EQU 0DFEh ; Use ROM SCROLL +#line 488 "/zxbasic/src/arch/zx48k/library-asm/print.asm" #line 489 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -#line 490 "/zxbasic/src/arch/zx48k/library-asm/print.asm" PRINT_COMMA: call __LOAD_S_POSN ld a, e @@ -924,9 +869,9 @@ PRINT_AT: ; Changes cursor to ROW, COL LOCAL __PRINT_TABLE LOCAL __PRINT_TAB, __PRINT_TAB1, __PRINT_TAB2 LOCAL __PRINT_ITA2 -#line 546 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 545 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __PRINT_BOLD2 -#line 552 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 551 "/zxbasic/src/arch/zx48k/library-asm/print.asm" __PRINT_TABLE: ; Jump table for 0 .. 22 codes DW __PRINT_NOP ; 0 DW __PRINT_NOP ; 1 @@ -954,7 +899,62 @@ __PRINT_TABLE: ; Jump table for 0 .. 22 codes DW __PRINT_TAB ; 23 TAB ENDP pop namespace -#line 2 "/zxbasic/src/arch/zx48k/library-asm/printnum.asm" +#line 3 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" +#line 4 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" + push namespace core +COPY_ATTR: + ; Just copies current permanent attribs into temporal attribs + ; and sets print mode + PROC + LOCAL INVERSE1 + LOCAL __REFRESH_TMP + INVERSE1 EQU 02Fh + ld hl, (ATTR_P) + ld (ATTR_T), hl + ld hl, FLAGS2 + call __REFRESH_TMP + ld hl, P_FLAG + call __REFRESH_TMP +__SET_ATTR_MODE: ; Another entry to set print modes. A contains (P_FLAG) + LOCAL TABLE + LOCAL CONT2 + rra ; Over bit to carry + ld a, (FLAGS2) + rla ; Over bit in bit 1, Over2 bit in bit 2 + and 3 ; Only bit 0 and 1 (OVER flag) + ld c, a + ld b, 0 + ld hl, TABLE + add hl, bc + ld a, (hl) + ld (PRINT_MODE), a + ld hl, (P_FLAG) + xor a ; NOP -> INVERSE0 + bit 2, l + jr z, CONT2 + ld a, INVERSE1 ; CPL -> INVERSE1 +CONT2: + ld (INVERSE_MODE), a + ret +TABLE: + nop ; NORMAL MODE + xor (hl) ; OVER 1 MODE + and (hl) ; OVER 2 MODE + or (hl) ; OVER 3 MODE +#line 67 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" +__REFRESH_TMP: + ld a, (hl) + and 0b10101010 + ld c, a + rra + or c + ld (hl), a + ret + ENDP + pop namespace +#line 20 "zx48k/print_i8.bas" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/printi8.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/printnum.asm" push namespace core __PRINTU_START: PROC @@ -1072,5 +1072,5 @@ __PRINTU_LOOP: jp __PRINTU_LOOP ; Uses JP in loops ENDP pop namespace -#line 19 "zx48k/print_i8.bas" +#line 21 "zx48k/print_i8.bas" END diff --git a/tests/functional/zx48k/print_tab.asm b/tests/functional/zx48k/print_tab.asm index 101e2405f..98e8ff023 100644 --- a/tests/functional/zx48k/print_tab.asm +++ b/tests/functional/zx48k/print_tab.asm @@ -21,6 +21,7 @@ .core.__LABEL__.ZXBASIC_USER_DATA EQU .core.ZXBASIC_USER_DATA .core.ZXBASIC_USER_DATA_END: .core.__MAIN_PROGRAM__: + call .core.COPY_ATTR ld a, 5 call .core.PRINT_TAB ld hl, 0 @@ -38,6 +39,7 @@ ei ret ;; --- end of user code --- +#line 1 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" #line 1 "/zxbasic/src/arch/zx48k/library-asm/print.asm" ; vim:ts=4:sw=4:et: ; PRINT command routine @@ -387,60 +389,6 @@ BRIGHT_TMP: #line 1 "/zxbasic/src/arch/zx48k/library-asm/over.asm" ; Sets OVER flag in P_FLAG permanently ; Parameter: OVER flag in bit 0 of A register -#line 1 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" -#line 4 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" - push namespace core -COPY_ATTR: - ; Just copies current permanent attribs into temporal attribs - ; and sets print mode - PROC - LOCAL INVERSE1 - LOCAL __REFRESH_TMP - INVERSE1 EQU 02Fh - ld hl, (ATTR_P) - ld (ATTR_T), hl - ld hl, FLAGS2 - call __REFRESH_TMP - ld hl, P_FLAG - call __REFRESH_TMP -__SET_ATTR_MODE: ; Another entry to set print modes. A contains (P_FLAG) - LOCAL TABLE - LOCAL CONT2 - rra ; Over bit to carry - ld a, (FLAGS2) - rla ; Over bit in bit 1, Over2 bit in bit 2 - and 3 ; Only bit 0 and 1 (OVER flag) - ld c, a - ld b, 0 - ld hl, TABLE - add hl, bc - ld a, (hl) - ld (PRINT_MODE), a - ld hl, (P_FLAG) - xor a ; NOP -> INVERSE0 - bit 2, l - jr z, CONT2 - ld a, INVERSE1 ; CPL -> INVERSE1 -CONT2: - ld (INVERSE_MODE), a - ret -TABLE: - nop ; NORMAL MODE - xor (hl) ; OVER 1 MODE - and (hl) ; OVER 2 MODE - or (hl) ; OVER 3 MODE -#line 67 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" -__REFRESH_TMP: - ld a, (hl) - and 0b10101010 - ld c, a - rra - or c - ld (hl), a - ret - ENDP - pop namespace -#line 4 "/zxbasic/src/arch/zx48k/library-asm/over.asm" push namespace core OVER: PROC @@ -682,11 +630,10 @@ INVERSE_MODE: ; 00 -> NOP -> INVERSE 0 inc hl ld (DFCC), hl ld hl, (DFCCL) ; current ATTR Pos - push hl - call __SET_ATTR - pop hl inc hl - ld (DFCCL),hl + ld (DFCCL), hl + dec hl + call __SET_ATTR exx ret ; ------------- SPECIAL CHARS (< 32) ----------------- @@ -705,7 +652,7 @@ __PRINT_0Dh: ; Called WHEN printing CHR$(13) push hl call __SCROLL_SCR pop hl -#line 210 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 209 "/zxbasic/src/arch/zx48k/library-asm/print.asm" 1: ld l, 1 __PRINT_EOL_END: @@ -822,14 +769,14 @@ __PRINT_BOLD: __PRINT_BOLD2: call BOLD_TMP jp __PRINT_RESTART -#line 354 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 353 "/zxbasic/src/arch/zx48k/library-asm/print.asm" __PRINT_ITA: ld hl, __PRINT_ITA2 jp __PRINT_SET_STATE __PRINT_ITA2: call ITALIC_TMP jp __PRINT_RESTART -#line 364 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 363 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __BOLD __BOLD: push hl @@ -847,7 +794,7 @@ __BOLD: pop hl ld de, MEM0 ret -#line 385 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 384 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __ITALIC __ITALIC: push hl @@ -872,12 +819,12 @@ __ITALIC: pop hl ld de, MEM0 ret -#line 413 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 412 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __SCROLL_SCR -#line 487 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 486 "/zxbasic/src/arch/zx48k/library-asm/print.asm" __SCROLL_SCR EQU 0DFEh ; Use ROM SCROLL +#line 488 "/zxbasic/src/arch/zx48k/library-asm/print.asm" #line 489 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -#line 490 "/zxbasic/src/arch/zx48k/library-asm/print.asm" PRINT_COMMA: call __LOAD_S_POSN ld a, e @@ -920,9 +867,9 @@ PRINT_AT: ; Changes cursor to ROW, COL LOCAL __PRINT_TABLE LOCAL __PRINT_TAB, __PRINT_TAB1, __PRINT_TAB2 LOCAL __PRINT_ITA2 -#line 546 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 545 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __PRINT_BOLD2 -#line 552 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 551 "/zxbasic/src/arch/zx48k/library-asm/print.asm" __PRINT_TABLE: ; Jump table for 0 .. 22 codes DW __PRINT_NOP ; 0 DW __PRINT_NOP ; 1 @@ -950,5 +897,58 @@ __PRINT_TABLE: ; Jump table for 0 .. 22 codes DW __PRINT_TAB ; 23 TAB ENDP pop namespace -#line 19 "zx48k/print_tab.bas" +#line 3 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" +#line 4 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" + push namespace core +COPY_ATTR: + ; Just copies current permanent attribs into temporal attribs + ; and sets print mode + PROC + LOCAL INVERSE1 + LOCAL __REFRESH_TMP + INVERSE1 EQU 02Fh + ld hl, (ATTR_P) + ld (ATTR_T), hl + ld hl, FLAGS2 + call __REFRESH_TMP + ld hl, P_FLAG + call __REFRESH_TMP +__SET_ATTR_MODE: ; Another entry to set print modes. A contains (P_FLAG) + LOCAL TABLE + LOCAL CONT2 + rra ; Over bit to carry + ld a, (FLAGS2) + rla ; Over bit in bit 1, Over2 bit in bit 2 + and 3 ; Only bit 0 and 1 (OVER flag) + ld c, a + ld b, 0 + ld hl, TABLE + add hl, bc + ld a, (hl) + ld (PRINT_MODE), a + ld hl, (P_FLAG) + xor a ; NOP -> INVERSE0 + bit 2, l + jr z, CONT2 + ld a, INVERSE1 ; CPL -> INVERSE1 +CONT2: + ld (INVERSE_MODE), a + ret +TABLE: + nop ; NORMAL MODE + xor (hl) ; OVER 1 MODE + and (hl) ; OVER 2 MODE + or (hl) ; OVER 3 MODE +#line 67 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" +__REFRESH_TMP: + ld a, (hl) + and 0b10101010 + ld c, a + rra + or c + ld (hl), a + ret + ENDP + pop namespace +#line 20 "zx48k/print_tab.bas" END diff --git a/tests/functional/zx48k/print_u16.asm b/tests/functional/zx48k/print_u16.asm index 1d5f94bf1..37a6fed3b 100644 --- a/tests/functional/zx48k/print_u16.asm +++ b/tests/functional/zx48k/print_u16.asm @@ -23,6 +23,7 @@ _a: DEFB 00, 00 .core.ZXBASIC_USER_DATA_END: .core.__MAIN_PROGRAM__: + call .core.COPY_ATTR ld hl, (_a) call .core.__PRINTU16 ld hl, 0 @@ -40,9 +41,7 @@ _a: ei ret ;; --- end of user code --- -#line 1 "/zxbasic/src/arch/zx48k/library-asm/printu16.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/printi16.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/printnum.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" #line 1 "/zxbasic/src/arch/zx48k/library-asm/print.asm" ; vim:ts=4:sw=4:et: ; PRINT command routine @@ -392,60 +391,6 @@ BRIGHT_TMP: #line 1 "/zxbasic/src/arch/zx48k/library-asm/over.asm" ; Sets OVER flag in P_FLAG permanently ; Parameter: OVER flag in bit 0 of A register -#line 1 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" -#line 4 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" - push namespace core -COPY_ATTR: - ; Just copies current permanent attribs into temporal attribs - ; and sets print mode - PROC - LOCAL INVERSE1 - LOCAL __REFRESH_TMP - INVERSE1 EQU 02Fh - ld hl, (ATTR_P) - ld (ATTR_T), hl - ld hl, FLAGS2 - call __REFRESH_TMP - ld hl, P_FLAG - call __REFRESH_TMP -__SET_ATTR_MODE: ; Another entry to set print modes. A contains (P_FLAG) - LOCAL TABLE - LOCAL CONT2 - rra ; Over bit to carry - ld a, (FLAGS2) - rla ; Over bit in bit 1, Over2 bit in bit 2 - and 3 ; Only bit 0 and 1 (OVER flag) - ld c, a - ld b, 0 - ld hl, TABLE - add hl, bc - ld a, (hl) - ld (PRINT_MODE), a - ld hl, (P_FLAG) - xor a ; NOP -> INVERSE0 - bit 2, l - jr z, CONT2 - ld a, INVERSE1 ; CPL -> INVERSE1 -CONT2: - ld (INVERSE_MODE), a - ret -TABLE: - nop ; NORMAL MODE - xor (hl) ; OVER 1 MODE - and (hl) ; OVER 2 MODE - or (hl) ; OVER 3 MODE -#line 67 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" -__REFRESH_TMP: - ld a, (hl) - and 0b10101010 - ld c, a - rra - or c - ld (hl), a - ret - ENDP - pop namespace -#line 4 "/zxbasic/src/arch/zx48k/library-asm/over.asm" push namespace core OVER: PROC @@ -687,11 +632,10 @@ INVERSE_MODE: ; 00 -> NOP -> INVERSE 0 inc hl ld (DFCC), hl ld hl, (DFCCL) ; current ATTR Pos - push hl - call __SET_ATTR - pop hl inc hl - ld (DFCCL),hl + ld (DFCCL), hl + dec hl + call __SET_ATTR exx ret ; ------------- SPECIAL CHARS (< 32) ----------------- @@ -710,7 +654,7 @@ __PRINT_0Dh: ; Called WHEN printing CHR$(13) push hl call __SCROLL_SCR pop hl -#line 210 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 209 "/zxbasic/src/arch/zx48k/library-asm/print.asm" 1: ld l, 1 __PRINT_EOL_END: @@ -827,14 +771,14 @@ __PRINT_BOLD: __PRINT_BOLD2: call BOLD_TMP jp __PRINT_RESTART -#line 354 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 353 "/zxbasic/src/arch/zx48k/library-asm/print.asm" __PRINT_ITA: ld hl, __PRINT_ITA2 jp __PRINT_SET_STATE __PRINT_ITA2: call ITALIC_TMP jp __PRINT_RESTART -#line 364 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 363 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __BOLD __BOLD: push hl @@ -852,7 +796,7 @@ __BOLD: pop hl ld de, MEM0 ret -#line 385 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 384 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __ITALIC __ITALIC: push hl @@ -877,12 +821,12 @@ __ITALIC: pop hl ld de, MEM0 ret -#line 413 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 412 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __SCROLL_SCR -#line 487 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 486 "/zxbasic/src/arch/zx48k/library-asm/print.asm" __SCROLL_SCR EQU 0DFEh ; Use ROM SCROLL +#line 488 "/zxbasic/src/arch/zx48k/library-asm/print.asm" #line 489 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -#line 490 "/zxbasic/src/arch/zx48k/library-asm/print.asm" PRINT_COMMA: call __LOAD_S_POSN ld a, e @@ -925,9 +869,9 @@ PRINT_AT: ; Changes cursor to ROW, COL LOCAL __PRINT_TABLE LOCAL __PRINT_TAB, __PRINT_TAB1, __PRINT_TAB2 LOCAL __PRINT_ITA2 -#line 546 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 545 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __PRINT_BOLD2 -#line 552 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 551 "/zxbasic/src/arch/zx48k/library-asm/print.asm" __PRINT_TABLE: ; Jump table for 0 .. 22 codes DW __PRINT_NOP ; 0 DW __PRINT_NOP ; 1 @@ -955,7 +899,63 @@ __PRINT_TABLE: ; Jump table for 0 .. 22 codes DW __PRINT_TAB ; 23 TAB ENDP pop namespace -#line 2 "/zxbasic/src/arch/zx48k/library-asm/printnum.asm" +#line 3 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" +#line 4 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" + push namespace core +COPY_ATTR: + ; Just copies current permanent attribs into temporal attribs + ; and sets print mode + PROC + LOCAL INVERSE1 + LOCAL __REFRESH_TMP + INVERSE1 EQU 02Fh + ld hl, (ATTR_P) + ld (ATTR_T), hl + ld hl, FLAGS2 + call __REFRESH_TMP + ld hl, P_FLAG + call __REFRESH_TMP +__SET_ATTR_MODE: ; Another entry to set print modes. A contains (P_FLAG) + LOCAL TABLE + LOCAL CONT2 + rra ; Over bit to carry + ld a, (FLAGS2) + rla ; Over bit in bit 1, Over2 bit in bit 2 + and 3 ; Only bit 0 and 1 (OVER flag) + ld c, a + ld b, 0 + ld hl, TABLE + add hl, bc + ld a, (hl) + ld (PRINT_MODE), a + ld hl, (P_FLAG) + xor a ; NOP -> INVERSE0 + bit 2, l + jr z, CONT2 + ld a, INVERSE1 ; CPL -> INVERSE1 +CONT2: + ld (INVERSE_MODE), a + ret +TABLE: + nop ; NORMAL MODE + xor (hl) ; OVER 1 MODE + and (hl) ; OVER 2 MODE + or (hl) ; OVER 3 MODE +#line 67 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" +__REFRESH_TMP: + ld a, (hl) + and 0b10101010 + ld c, a + rra + or c + ld (hl), a + ret + ENDP + pop namespace +#line 20 "zx48k/print_u16.bas" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/printu16.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/printi16.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/printnum.asm" push namespace core __PRINTU_START: PROC @@ -1100,5 +1100,5 @@ __PRINTU_LOOP: ENDP pop namespace #line 2 "/zxbasic/src/arch/zx48k/library-asm/printu16.asm" -#line 19 "zx48k/print_u16.bas" +#line 21 "zx48k/print_u16.bas" END diff --git a/tests/functional/zx48k/print_u32.asm b/tests/functional/zx48k/print_u32.asm index f784e54af..b0150f8e3 100644 --- a/tests/functional/zx48k/print_u32.asm +++ b/tests/functional/zx48k/print_u32.asm @@ -23,6 +23,7 @@ _a: DEFB 00, 00, 00, 00 .core.ZXBASIC_USER_DATA_END: .core.__MAIN_PROGRAM__: + call .core.COPY_ATTR ld hl, (_a) ld de, (_a + 2) call .core.__PRINTU32 @@ -41,9 +42,7 @@ _a: ei ret ;; --- end of user code --- -#line 1 "/zxbasic/src/arch/zx48k/library-asm/printu32.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/printi32.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/printnum.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" #line 1 "/zxbasic/src/arch/zx48k/library-asm/print.asm" ; vim:ts=4:sw=4:et: ; PRINT command routine @@ -393,60 +392,6 @@ BRIGHT_TMP: #line 1 "/zxbasic/src/arch/zx48k/library-asm/over.asm" ; Sets OVER flag in P_FLAG permanently ; Parameter: OVER flag in bit 0 of A register -#line 1 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" -#line 4 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" - push namespace core -COPY_ATTR: - ; Just copies current permanent attribs into temporal attribs - ; and sets print mode - PROC - LOCAL INVERSE1 - LOCAL __REFRESH_TMP - INVERSE1 EQU 02Fh - ld hl, (ATTR_P) - ld (ATTR_T), hl - ld hl, FLAGS2 - call __REFRESH_TMP - ld hl, P_FLAG - call __REFRESH_TMP -__SET_ATTR_MODE: ; Another entry to set print modes. A contains (P_FLAG) - LOCAL TABLE - LOCAL CONT2 - rra ; Over bit to carry - ld a, (FLAGS2) - rla ; Over bit in bit 1, Over2 bit in bit 2 - and 3 ; Only bit 0 and 1 (OVER flag) - ld c, a - ld b, 0 - ld hl, TABLE - add hl, bc - ld a, (hl) - ld (PRINT_MODE), a - ld hl, (P_FLAG) - xor a ; NOP -> INVERSE0 - bit 2, l - jr z, CONT2 - ld a, INVERSE1 ; CPL -> INVERSE1 -CONT2: - ld (INVERSE_MODE), a - ret -TABLE: - nop ; NORMAL MODE - xor (hl) ; OVER 1 MODE - and (hl) ; OVER 2 MODE - or (hl) ; OVER 3 MODE -#line 67 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" -__REFRESH_TMP: - ld a, (hl) - and 0b10101010 - ld c, a - rra - or c - ld (hl), a - ret - ENDP - pop namespace -#line 4 "/zxbasic/src/arch/zx48k/library-asm/over.asm" push namespace core OVER: PROC @@ -688,11 +633,10 @@ INVERSE_MODE: ; 00 -> NOP -> INVERSE 0 inc hl ld (DFCC), hl ld hl, (DFCCL) ; current ATTR Pos - push hl - call __SET_ATTR - pop hl inc hl - ld (DFCCL),hl + ld (DFCCL), hl + dec hl + call __SET_ATTR exx ret ; ------------- SPECIAL CHARS (< 32) ----------------- @@ -711,7 +655,7 @@ __PRINT_0Dh: ; Called WHEN printing CHR$(13) push hl call __SCROLL_SCR pop hl -#line 210 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 209 "/zxbasic/src/arch/zx48k/library-asm/print.asm" 1: ld l, 1 __PRINT_EOL_END: @@ -828,14 +772,14 @@ __PRINT_BOLD: __PRINT_BOLD2: call BOLD_TMP jp __PRINT_RESTART -#line 354 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 353 "/zxbasic/src/arch/zx48k/library-asm/print.asm" __PRINT_ITA: ld hl, __PRINT_ITA2 jp __PRINT_SET_STATE __PRINT_ITA2: call ITALIC_TMP jp __PRINT_RESTART -#line 364 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 363 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __BOLD __BOLD: push hl @@ -853,7 +797,7 @@ __BOLD: pop hl ld de, MEM0 ret -#line 385 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 384 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __ITALIC __ITALIC: push hl @@ -878,12 +822,12 @@ __ITALIC: pop hl ld de, MEM0 ret -#line 413 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 412 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __SCROLL_SCR -#line 487 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 486 "/zxbasic/src/arch/zx48k/library-asm/print.asm" __SCROLL_SCR EQU 0DFEh ; Use ROM SCROLL +#line 488 "/zxbasic/src/arch/zx48k/library-asm/print.asm" #line 489 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -#line 490 "/zxbasic/src/arch/zx48k/library-asm/print.asm" PRINT_COMMA: call __LOAD_S_POSN ld a, e @@ -926,9 +870,9 @@ PRINT_AT: ; Changes cursor to ROW, COL LOCAL __PRINT_TABLE LOCAL __PRINT_TAB, __PRINT_TAB1, __PRINT_TAB2 LOCAL __PRINT_ITA2 -#line 546 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 545 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __PRINT_BOLD2 -#line 552 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 551 "/zxbasic/src/arch/zx48k/library-asm/print.asm" __PRINT_TABLE: ; Jump table for 0 .. 22 codes DW __PRINT_NOP ; 0 DW __PRINT_NOP ; 1 @@ -956,7 +900,63 @@ __PRINT_TABLE: ; Jump table for 0 .. 22 codes DW __PRINT_TAB ; 23 TAB ENDP pop namespace -#line 2 "/zxbasic/src/arch/zx48k/library-asm/printnum.asm" +#line 3 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" +#line 4 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" + push namespace core +COPY_ATTR: + ; Just copies current permanent attribs into temporal attribs + ; and sets print mode + PROC + LOCAL INVERSE1 + LOCAL __REFRESH_TMP + INVERSE1 EQU 02Fh + ld hl, (ATTR_P) + ld (ATTR_T), hl + ld hl, FLAGS2 + call __REFRESH_TMP + ld hl, P_FLAG + call __REFRESH_TMP +__SET_ATTR_MODE: ; Another entry to set print modes. A contains (P_FLAG) + LOCAL TABLE + LOCAL CONT2 + rra ; Over bit to carry + ld a, (FLAGS2) + rla ; Over bit in bit 1, Over2 bit in bit 2 + and 3 ; Only bit 0 and 1 (OVER flag) + ld c, a + ld b, 0 + ld hl, TABLE + add hl, bc + ld a, (hl) + ld (PRINT_MODE), a + ld hl, (P_FLAG) + xor a ; NOP -> INVERSE0 + bit 2, l + jr z, CONT2 + ld a, INVERSE1 ; CPL -> INVERSE1 +CONT2: + ld (INVERSE_MODE), a + ret +TABLE: + nop ; NORMAL MODE + xor (hl) ; OVER 1 MODE + and (hl) ; OVER 2 MODE + or (hl) ; OVER 3 MODE +#line 67 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" +__REFRESH_TMP: + ld a, (hl) + and 0b10101010 + ld c, a + rra + or c + ld (hl), a + ret + ENDP + pop namespace +#line 21 "zx48k/print_u32.bas" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/printu32.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/printi32.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/printnum.asm" push namespace core __PRINTU_START: PROC @@ -1154,5 +1154,5 @@ __PRINTU_LOOP: ENDP pop namespace #line 2 "/zxbasic/src/arch/zx48k/library-asm/printu32.asm" -#line 20 "zx48k/print_u32.bas" +#line 22 "zx48k/print_u32.bas" END diff --git a/tests/functional/zx48k/print_u8.asm b/tests/functional/zx48k/print_u8.asm index 2ae96383e..e2451e220 100644 --- a/tests/functional/zx48k/print_u8.asm +++ b/tests/functional/zx48k/print_u8.asm @@ -23,6 +23,7 @@ _a: DEFB 00 .core.ZXBASIC_USER_DATA_END: .core.__MAIN_PROGRAM__: + call .core.COPY_ATTR ld a, (_a) call .core.__PRINTU8 ld hl, 0 @@ -40,9 +41,7 @@ _a: ei ret ;; --- end of user code --- -#line 1 "/zxbasic/src/arch/zx48k/library-asm/printu8.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/printi8.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/printnum.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" #line 1 "/zxbasic/src/arch/zx48k/library-asm/print.asm" ; vim:ts=4:sw=4:et: ; PRINT command routine @@ -392,60 +391,6 @@ BRIGHT_TMP: #line 1 "/zxbasic/src/arch/zx48k/library-asm/over.asm" ; Sets OVER flag in P_FLAG permanently ; Parameter: OVER flag in bit 0 of A register -#line 1 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" -#line 4 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" - push namespace core -COPY_ATTR: - ; Just copies current permanent attribs into temporal attribs - ; and sets print mode - PROC - LOCAL INVERSE1 - LOCAL __REFRESH_TMP - INVERSE1 EQU 02Fh - ld hl, (ATTR_P) - ld (ATTR_T), hl - ld hl, FLAGS2 - call __REFRESH_TMP - ld hl, P_FLAG - call __REFRESH_TMP -__SET_ATTR_MODE: ; Another entry to set print modes. A contains (P_FLAG) - LOCAL TABLE - LOCAL CONT2 - rra ; Over bit to carry - ld a, (FLAGS2) - rla ; Over bit in bit 1, Over2 bit in bit 2 - and 3 ; Only bit 0 and 1 (OVER flag) - ld c, a - ld b, 0 - ld hl, TABLE - add hl, bc - ld a, (hl) - ld (PRINT_MODE), a - ld hl, (P_FLAG) - xor a ; NOP -> INVERSE0 - bit 2, l - jr z, CONT2 - ld a, INVERSE1 ; CPL -> INVERSE1 -CONT2: - ld (INVERSE_MODE), a - ret -TABLE: - nop ; NORMAL MODE - xor (hl) ; OVER 1 MODE - and (hl) ; OVER 2 MODE - or (hl) ; OVER 3 MODE -#line 67 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" -__REFRESH_TMP: - ld a, (hl) - and 0b10101010 - ld c, a - rra - or c - ld (hl), a - ret - ENDP - pop namespace -#line 4 "/zxbasic/src/arch/zx48k/library-asm/over.asm" push namespace core OVER: PROC @@ -687,11 +632,10 @@ INVERSE_MODE: ; 00 -> NOP -> INVERSE 0 inc hl ld (DFCC), hl ld hl, (DFCCL) ; current ATTR Pos - push hl - call __SET_ATTR - pop hl inc hl - ld (DFCCL),hl + ld (DFCCL), hl + dec hl + call __SET_ATTR exx ret ; ------------- SPECIAL CHARS (< 32) ----------------- @@ -710,7 +654,7 @@ __PRINT_0Dh: ; Called WHEN printing CHR$(13) push hl call __SCROLL_SCR pop hl -#line 210 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 209 "/zxbasic/src/arch/zx48k/library-asm/print.asm" 1: ld l, 1 __PRINT_EOL_END: @@ -827,14 +771,14 @@ __PRINT_BOLD: __PRINT_BOLD2: call BOLD_TMP jp __PRINT_RESTART -#line 354 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 353 "/zxbasic/src/arch/zx48k/library-asm/print.asm" __PRINT_ITA: ld hl, __PRINT_ITA2 jp __PRINT_SET_STATE __PRINT_ITA2: call ITALIC_TMP jp __PRINT_RESTART -#line 364 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 363 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __BOLD __BOLD: push hl @@ -852,7 +796,7 @@ __BOLD: pop hl ld de, MEM0 ret -#line 385 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 384 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __ITALIC __ITALIC: push hl @@ -877,12 +821,12 @@ __ITALIC: pop hl ld de, MEM0 ret -#line 413 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 412 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __SCROLL_SCR -#line 487 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 486 "/zxbasic/src/arch/zx48k/library-asm/print.asm" __SCROLL_SCR EQU 0DFEh ; Use ROM SCROLL +#line 488 "/zxbasic/src/arch/zx48k/library-asm/print.asm" #line 489 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -#line 490 "/zxbasic/src/arch/zx48k/library-asm/print.asm" PRINT_COMMA: call __LOAD_S_POSN ld a, e @@ -925,9 +869,9 @@ PRINT_AT: ; Changes cursor to ROW, COL LOCAL __PRINT_TABLE LOCAL __PRINT_TAB, __PRINT_TAB1, __PRINT_TAB2 LOCAL __PRINT_ITA2 -#line 546 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 545 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __PRINT_BOLD2 -#line 552 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 551 "/zxbasic/src/arch/zx48k/library-asm/print.asm" __PRINT_TABLE: ; Jump table for 0 .. 22 codes DW __PRINT_NOP ; 0 DW __PRINT_NOP ; 1 @@ -955,7 +899,63 @@ __PRINT_TABLE: ; Jump table for 0 .. 22 codes DW __PRINT_TAB ; 23 TAB ENDP pop namespace -#line 2 "/zxbasic/src/arch/zx48k/library-asm/printnum.asm" +#line 3 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" +#line 4 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" + push namespace core +COPY_ATTR: + ; Just copies current permanent attribs into temporal attribs + ; and sets print mode + PROC + LOCAL INVERSE1 + LOCAL __REFRESH_TMP + INVERSE1 EQU 02Fh + ld hl, (ATTR_P) + ld (ATTR_T), hl + ld hl, FLAGS2 + call __REFRESH_TMP + ld hl, P_FLAG + call __REFRESH_TMP +__SET_ATTR_MODE: ; Another entry to set print modes. A contains (P_FLAG) + LOCAL TABLE + LOCAL CONT2 + rra ; Over bit to carry + ld a, (FLAGS2) + rla ; Over bit in bit 1, Over2 bit in bit 2 + and 3 ; Only bit 0 and 1 (OVER flag) + ld c, a + ld b, 0 + ld hl, TABLE + add hl, bc + ld a, (hl) + ld (PRINT_MODE), a + ld hl, (P_FLAG) + xor a ; NOP -> INVERSE0 + bit 2, l + jr z, CONT2 + ld a, INVERSE1 ; CPL -> INVERSE1 +CONT2: + ld (INVERSE_MODE), a + ret +TABLE: + nop ; NORMAL MODE + xor (hl) ; OVER 1 MODE + and (hl) ; OVER 2 MODE + or (hl) ; OVER 3 MODE +#line 67 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" +__REFRESH_TMP: + ld a, (hl) + and 0b10101010 + ld c, a + rra + or c + ld (hl), a + ret + ENDP + pop namespace +#line 20 "zx48k/print_u8.bas" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/printu8.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/printi8.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/printnum.asm" push namespace core __PRINTU_START: PROC @@ -1074,5 +1074,5 @@ __PRINTU_LOOP: ENDP pop namespace #line 2 "/zxbasic/src/arch/zx48k/library-asm/printu8.asm" -#line 19 "zx48k/print_u8.bas" +#line 21 "zx48k/print_u8.bas" END diff --git a/tests/functional/zx48k/read10.asm b/tests/functional/zx48k/read10.asm index 7883ccccf..810d6f568 100644 --- a/tests/functional/zx48k/read10.asm +++ b/tests/functional/zx48k/read10.asm @@ -64,6 +64,7 @@ _p: call .core.__READ ld hl, -6 call .core.__PSTOREF + call .core.COPY_ATTR push ix pop hl ld de, -6 @@ -145,132 +146,7 @@ ___DATA__FUNCPTR__2__leave: __DATA__END: DEFB 00h ;; --- end of user code --- -#line 1 "/zxbasic/src/arch/zx48k/library-asm/mulf.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/stackf.asm" - ; ------------------------------------------------------------- - ; Functions to manage FP-Stack of the ZX Spectrum ROM CALC - ; ------------------------------------------------------------- - push namespace core - __FPSTACK_PUSH EQU 2AB6h ; Stores an FP number into the ROM FP stack (A, ED CB) - __FPSTACK_POP EQU 2BF1h ; Pops an FP number out of the ROM FP stack (A, ED CB) -__FPSTACK_PUSH2: ; Pushes Current A ED CB registers and top of the stack on (SP + 4) - ; Second argument to push into the stack calculator is popped out of the stack - ; Since the caller routine also receives the parameters into the top of the stack - ; four bytes must be removed from SP before pop them out - call __FPSTACK_PUSH ; Pushes A ED CB into the FP-STACK - exx - pop hl ; Caller-Caller return addr - exx - pop hl ; Caller return addr - pop af - pop de - pop bc - push hl ; Caller return addr - exx - push hl ; Caller-Caller return addr - exx - jp __FPSTACK_PUSH -__FPSTACK_I16: ; Pushes 16 bits integer in HL into the FP ROM STACK - ; This format is specified in the ZX 48K Manual - ; You can push a 16 bit signed integer as - ; 0 SS LL HH 0, being SS the sign and LL HH the low - ; and High byte respectively - ld a, h - rla ; sign to Carry - sbc a, a ; 0 if positive, FF if negative - ld e, a - ld d, l - ld c, h - xor a - ld b, a - jp __FPSTACK_PUSH - pop namespace -#line 2 "/zxbasic/src/arch/zx48k/library-asm/mulf.asm" - ; ------------------------------------------------------------- - ; Floating point library using the FP ROM Calculator (ZX 48K) - ; All of them uses A EDCB registers as 1st paramter. - ; For binary operators, the 2n operator must be pushed into the - ; stack, in the order A DE BC. - ; - ; Uses CALLEE convention - ; ------------------------------------------------------------- - push namespace core -__MULF: ; Multiplication - call __FPSTACK_PUSH2 - ; ------------- ROM MUL - rst 28h - defb 04h ; - defb 38h; ; END CALC - jp __FPSTACK_POP - pop namespace -#line 115 "zx48k/read10.bas" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/ploadf.asm" - ; Parameter / Local var load - ; A => Offset - ; IX = Stack Frame -; RESULT: HL => IX + DE -#line 1 "/zxbasic/src/arch/zx48k/library-asm/iloadf.asm" - ; __FASTCALL__ routine which - ; loads a 40 bits floating point into A ED CB - ; stored at position pointed by POINTER HL - ;A DE, BC <-- ((HL)) - push namespace core -__ILOADF: - ld a, (hl) - inc hl - ld h, (hl) - ld l, a - ; __FASTCALL__ routine which - ; loads a 40 bits floating point into A ED CB - ; stored at position pointed by POINTER HL - ;A DE, BC <-- (HL) -__LOADF: ; Loads a 40 bits FP number from address pointed by HL - ld a, (hl) - inc hl - ld e, (hl) - inc hl - ld d, (hl) - inc hl - ld c, (hl) - inc hl - ld b, (hl) - ret - pop namespace -#line 7 "/zxbasic/src/arch/zx48k/library-asm/ploadf.asm" - push namespace core -__PLOADF: - push ix - pop hl - add hl, de - jp __LOADF - pop namespace -#line 116 "zx48k/read10.bas" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/pow.asm" - ; ------------------------------------------------------------- - ; Floating point library using the FP ROM Calculator (ZX 48K) - ; All of them uses A EDCB registers as 1st paramter. - ; For binary operators, the 2n operator must be pushed into the - ; stack, in the order A DE BC. - ; - ; Uses CALLEE convention - ; -; Operands comes swapped: - ; 1 st parameter is the BASE (A ED CB) - ; 2 nd parameter (Top of the stack) is Exponent - ; ------------------------------------------------------------- - push namespace core -__POW: ; Exponentiation - PROC - call __FPSTACK_PUSH2 - ; ------------- ROM POW - rst 28h - defb 01h ; Exchange => 1, Base - defb 06h ; POW - defb 38h; ; END CALC - jp __FPSTACK_POP - ENDP - pop namespace -#line 117 "zx48k/read10.bas" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" #line 1 "/zxbasic/src/arch/zx48k/library-asm/print.asm" ; vim:ts=4:sw=4:et: ; PRINT command routine @@ -620,60 +496,6 @@ BRIGHT_TMP: #line 1 "/zxbasic/src/arch/zx48k/library-asm/over.asm" ; Sets OVER flag in P_FLAG permanently ; Parameter: OVER flag in bit 0 of A register -#line 1 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" -#line 4 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" - push namespace core -COPY_ATTR: - ; Just copies current permanent attribs into temporal attribs - ; and sets print mode - PROC - LOCAL INVERSE1 - LOCAL __REFRESH_TMP - INVERSE1 EQU 02Fh - ld hl, (ATTR_P) - ld (ATTR_T), hl - ld hl, FLAGS2 - call __REFRESH_TMP - ld hl, P_FLAG - call __REFRESH_TMP -__SET_ATTR_MODE: ; Another entry to set print modes. A contains (P_FLAG) - LOCAL TABLE - LOCAL CONT2 - rra ; Over bit to carry - ld a, (FLAGS2) - rla ; Over bit in bit 1, Over2 bit in bit 2 - and 3 ; Only bit 0 and 1 (OVER flag) - ld c, a - ld b, 0 - ld hl, TABLE - add hl, bc - ld a, (hl) - ld (PRINT_MODE), a - ld hl, (P_FLAG) - xor a ; NOP -> INVERSE0 - bit 2, l - jr z, CONT2 - ld a, INVERSE1 ; CPL -> INVERSE1 -CONT2: - ld (INVERSE_MODE), a - ret -TABLE: - nop ; NORMAL MODE - xor (hl) ; OVER 1 MODE - and (hl) ; OVER 2 MODE - or (hl) ; OVER 3 MODE -#line 67 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" -__REFRESH_TMP: - ld a, (hl) - and 0b10101010 - ld c, a - rra - or c - ld (hl), a - ret - ENDP - pop namespace -#line 4 "/zxbasic/src/arch/zx48k/library-asm/over.asm" push namespace core OVER: PROC @@ -915,11 +737,10 @@ INVERSE_MODE: ; 00 -> NOP -> INVERSE 0 inc hl ld (DFCC), hl ld hl, (DFCCL) ; current ATTR Pos - push hl - call __SET_ATTR - pop hl inc hl - ld (DFCCL),hl + ld (DFCCL), hl + dec hl + call __SET_ATTR exx ret ; ------------- SPECIAL CHARS (< 32) ----------------- @@ -938,7 +759,7 @@ __PRINT_0Dh: ; Called WHEN printing CHR$(13) push hl call __SCROLL_SCR pop hl -#line 210 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 209 "/zxbasic/src/arch/zx48k/library-asm/print.asm" 1: ld l, 1 __PRINT_EOL_END: @@ -1055,14 +876,14 @@ __PRINT_BOLD: __PRINT_BOLD2: call BOLD_TMP jp __PRINT_RESTART -#line 354 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 353 "/zxbasic/src/arch/zx48k/library-asm/print.asm" __PRINT_ITA: ld hl, __PRINT_ITA2 jp __PRINT_SET_STATE __PRINT_ITA2: call ITALIC_TMP jp __PRINT_RESTART -#line 364 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 363 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __BOLD __BOLD: push hl @@ -1080,7 +901,7 @@ __BOLD: pop hl ld de, MEM0 ret -#line 385 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 384 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __ITALIC __ITALIC: push hl @@ -1105,12 +926,12 @@ __ITALIC: pop hl ld de, MEM0 ret -#line 413 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 412 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __SCROLL_SCR -#line 487 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 486 "/zxbasic/src/arch/zx48k/library-asm/print.asm" __SCROLL_SCR EQU 0DFEh ; Use ROM SCROLL +#line 488 "/zxbasic/src/arch/zx48k/library-asm/print.asm" #line 489 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -#line 490 "/zxbasic/src/arch/zx48k/library-asm/print.asm" PRINT_COMMA: call __LOAD_S_POSN ld a, e @@ -1153,9 +974,9 @@ PRINT_AT: ; Changes cursor to ROW, COL LOCAL __PRINT_TABLE LOCAL __PRINT_TAB, __PRINT_TAB1, __PRINT_TAB2 LOCAL __PRINT_ITA2 -#line 546 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 545 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __PRINT_BOLD2 -#line 552 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 551 "/zxbasic/src/arch/zx48k/library-asm/print.asm" __PRINT_TABLE: ; Jump table for 0 .. 22 codes DW __PRINT_NOP ; 0 DW __PRINT_NOP ; 1 @@ -1183,7 +1004,186 @@ __PRINT_TABLE: ; Jump table for 0 .. 22 codes DW __PRINT_TAB ; 23 TAB ENDP pop namespace +#line 3 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" +#line 4 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" + push namespace core +COPY_ATTR: + ; Just copies current permanent attribs into temporal attribs + ; and sets print mode + PROC + LOCAL INVERSE1 + LOCAL __REFRESH_TMP + INVERSE1 EQU 02Fh + ld hl, (ATTR_P) + ld (ATTR_T), hl + ld hl, FLAGS2 + call __REFRESH_TMP + ld hl, P_FLAG + call __REFRESH_TMP +__SET_ATTR_MODE: ; Another entry to set print modes. A contains (P_FLAG) + LOCAL TABLE + LOCAL CONT2 + rra ; Over bit to carry + ld a, (FLAGS2) + rla ; Over bit in bit 1, Over2 bit in bit 2 + and 3 ; Only bit 0 and 1 (OVER flag) + ld c, a + ld b, 0 + ld hl, TABLE + add hl, bc + ld a, (hl) + ld (PRINT_MODE), a + ld hl, (P_FLAG) + xor a ; NOP -> INVERSE0 + bit 2, l + jr z, CONT2 + ld a, INVERSE1 ; CPL -> INVERSE1 +CONT2: + ld (INVERSE_MODE), a + ret +TABLE: + nop ; NORMAL MODE + xor (hl) ; OVER 1 MODE + and (hl) ; OVER 2 MODE + or (hl) ; OVER 3 MODE +#line 67 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" +__REFRESH_TMP: + ld a, (hl) + and 0b10101010 + ld c, a + rra + or c + ld (hl), a + ret + ENDP + pop namespace +#line 116 "zx48k/read10.bas" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/mulf.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/stackf.asm" + ; ------------------------------------------------------------- + ; Functions to manage FP-Stack of the ZX Spectrum ROM CALC + ; ------------------------------------------------------------- + push namespace core + __FPSTACK_PUSH EQU 2AB6h ; Stores an FP number into the ROM FP stack (A, ED CB) + __FPSTACK_POP EQU 2BF1h ; Pops an FP number out of the ROM FP stack (A, ED CB) +__FPSTACK_PUSH2: ; Pushes Current A ED CB registers and top of the stack on (SP + 4) + ; Second argument to push into the stack calculator is popped out of the stack + ; Since the caller routine also receives the parameters into the top of the stack + ; four bytes must be removed from SP before pop them out + call __FPSTACK_PUSH ; Pushes A ED CB into the FP-STACK + exx + pop hl ; Caller-Caller return addr + exx + pop hl ; Caller return addr + pop af + pop de + pop bc + push hl ; Caller return addr + exx + push hl ; Caller-Caller return addr + exx + jp __FPSTACK_PUSH +__FPSTACK_I16: ; Pushes 16 bits integer in HL into the FP ROM STACK + ; This format is specified in the ZX 48K Manual + ; You can push a 16 bit signed integer as + ; 0 SS LL HH 0, being SS the sign and LL HH the low + ; and High byte respectively + ld a, h + rla ; sign to Carry + sbc a, a ; 0 if positive, FF if negative + ld e, a + ld d, l + ld c, h + xor a + ld b, a + jp __FPSTACK_PUSH + pop namespace +#line 2 "/zxbasic/src/arch/zx48k/library-asm/mulf.asm" + ; ------------------------------------------------------------- + ; Floating point library using the FP ROM Calculator (ZX 48K) + ; All of them uses A EDCB registers as 1st paramter. + ; For binary operators, the 2n operator must be pushed into the + ; stack, in the order A DE BC. + ; + ; Uses CALLEE convention + ; ------------------------------------------------------------- + push namespace core +__MULF: ; Multiplication + call __FPSTACK_PUSH2 + ; ------------- ROM MUL + rst 28h + defb 04h ; + defb 38h; ; END CALC + jp __FPSTACK_POP + pop namespace +#line 117 "zx48k/read10.bas" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/ploadf.asm" + ; Parameter / Local var load + ; A => Offset + ; IX = Stack Frame +; RESULT: HL => IX + DE +#line 1 "/zxbasic/src/arch/zx48k/library-asm/iloadf.asm" + ; __FASTCALL__ routine which + ; loads a 40 bits floating point into A ED CB + ; stored at position pointed by POINTER HL + ;A DE, BC <-- ((HL)) + push namespace core +__ILOADF: + ld a, (hl) + inc hl + ld h, (hl) + ld l, a + ; __FASTCALL__ routine which + ; loads a 40 bits floating point into A ED CB + ; stored at position pointed by POINTER HL + ;A DE, BC <-- (HL) +__LOADF: ; Loads a 40 bits FP number from address pointed by HL + ld a, (hl) + inc hl + ld e, (hl) + inc hl + ld d, (hl) + inc hl + ld c, (hl) + inc hl + ld b, (hl) + ret + pop namespace +#line 7 "/zxbasic/src/arch/zx48k/library-asm/ploadf.asm" + push namespace core +__PLOADF: + push ix + pop hl + add hl, de + jp __LOADF + pop namespace #line 118 "zx48k/read10.bas" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/pow.asm" + ; ------------------------------------------------------------- + ; Floating point library using the FP ROM Calculator (ZX 48K) + ; All of them uses A EDCB registers as 1st paramter. + ; For binary operators, the 2n operator must be pushed into the + ; stack, in the order A DE BC. + ; + ; Uses CALLEE convention + ; +; Operands comes swapped: + ; 1 st parameter is the BASE (A ED CB) + ; 2 nd parameter (Top of the stack) is Exponent + ; ------------------------------------------------------------- + push namespace core +__POW: ; Exponentiation + PROC + call __FPSTACK_PUSH2 + ; ------------- ROM POW + rst 28h + defb 01h ; Exchange => 1, Base + defb 06h ; POW + defb 38h; ; END CALC + jp __FPSTACK_POP + ENDP + pop namespace +#line 119 "zx48k/read10.bas" #line 1 "/zxbasic/src/arch/zx48k/library-asm/printf.asm" #line 1 "/zxbasic/src/arch/zx48k/library-asm/printstr.asm" #line 1 "/zxbasic/src/arch/zx48k/library-asm/free.asm" @@ -1525,7 +1525,7 @@ __PRINTF: ; Prints a Fixed point Number stored in C ED LH RECLAIM2 EQU 19E8h ENDP pop namespace -#line 119 "zx48k/read10.bas" +#line 121 "zx48k/read10.bas" #line 1 "/zxbasic/src/arch/zx48k/library-asm/pstoref.asm" ; Stores FP number in A ED CB at location HL+IX ; HL = Offset @@ -1571,7 +1571,7 @@ __PSTOREF: pop de jp __STOREF pop namespace -#line 120 "zx48k/read10.bas" +#line 122 "zx48k/read10.bas" #line 1 "/zxbasic/src/arch/zx48k/library-asm/read_restore.asm" ;; This implements READ & RESTORE functions ;; Reads a new element from the DATA Address code @@ -2331,7 +2331,7 @@ __DATA_ADDR: ;; Stores current DATA ptr dw .DATA.__DATA__0 ENDP pop namespace -#line 121 "zx48k/read10.bas" +#line 123 "zx48k/read10.bas" #line 1 "/zxbasic/src/arch/zx48k/library-asm/sin.asm" push namespace core SIN: ; Computes SIN using ROM FP-CALC @@ -2341,7 +2341,7 @@ SIN: ; Computes SIN using ROM FP-CALC defb 38h ; END CALC jp __FPSTACK_POP pop namespace -#line 122 "zx48k/read10.bas" +#line 124 "zx48k/read10.bas" #line 1 "/zxbasic/src/arch/zx48k/library-asm/tan.asm" push namespace core TAN: ; Computes TAN using ROM FP-CALC @@ -2351,5 +2351,5 @@ TAN: ; Computes TAN using ROM FP-CALC defb 38h ; END CALC jp __FPSTACK_POP pop namespace -#line 123 "zx48k/read10.bas" +#line 125 "zx48k/read10.bas" END diff --git a/tests/functional/zx48k/read12.asm b/tests/functional/zx48k/read12.asm index b995f57ab..e987272e2 100644 --- a/tests/functional/zx48k/read12.asm +++ b/tests/functional/zx48k/read12.asm @@ -33,11 +33,15 @@ _a: ld a, 2 call .core.__READ ld (_a), a + call .core.COPY_ATTR + ld a, (_a) call .core.__PRINTI8 call .core.PRINT_EOL ld a, 2 call .core.__READ ld (_a), a + call .core.COPY_ATTR + ld a, (_a) call .core.__PRINTI8 call .core.PRINT_EOL .LABEL._test: @@ -77,67 +81,42 @@ __DATA__END: DEFB 6Ch DEFB 61h ;; --- end of user code --- -#line 1 "/zxbasic/src/arch/zx48k/library-asm/loadstr.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/alloc.asm" -; vim: ts=4:et:sw=4: - ; Copyleft (K) by Jose M. Rodriguez de la Rosa - ; (a.k.a. Boriel) -; http://www.boriel.com - ; - ; This ASM library is licensed under the MIT license - ; you can use it for any purpose (even for commercial - ; closed source programs). - ; - ; Please read the MIT license on the internet - ; ----- IMPLEMENTATION NOTES ------ - ; The heap is implemented as a linked list of free blocks. -; Each free block contains this info: - ; - ; +----------------+ <-- HEAP START - ; | Size (2 bytes) | - ; | 0 | <-- Size = 0 => DUMMY HEADER BLOCK - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ <-+ - ; | Size (2 bytes) | - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ | - ; | | | <-- If Size > 4, then this contains (size - 4) bytes - ; | (0 if Size = 4)| | - ; +----------------+ <-+ - ; | Size (2 bytes) | - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ | - ; | | | - ; | (0 if Size = 4)| | - ; +----------------+ | - ; | <-- This zone is in use (Already allocated) - ; +----------------+ <-+ - ; | Size (2 bytes) | - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ | - ; | | | - ; | (0 if Size = 4)| | - ; +----------------+ <-+ - ; | Next (2 bytes) |--> NULL => END OF LIST - ; | 0 = NULL | - ; +----------------+ - ; | | - ; | (0 if Size = 4)| - ; +----------------+ - ; When a block is FREED, the previous and next pointers are examined to see - ; if we can defragment the heap. If the block to be freed is just next to the - ; previous, or to the next (or both) they will be converted into a single - ; block (so defragmented). - ; MEMORY MANAGER - ; - ; This library must be initialized calling __MEM_INIT with - ; HL = BLOCK Start & DE = Length. - ; An init directive is useful for initialization routines. - ; They will be added automatically if needed. +#line 1 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +; vim:ts=4:sw=4:et: + ; PRINT command routine + ; Does not print attribute. Use PRINT_STR or PRINT_NUM for that +#line 1 "/zxbasic/src/arch/zx48k/library-asm/sposn.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/sysvars.asm" + ;; ----------------------------------------------------------------------- + ;; ZX Basic System Vars + ;; Some of them will be mapped over Sinclair ROM ones for compatibility + ;; ----------------------------------------------------------------------- + push namespace core +SCREEN_ADDR: DW 16384 ; Screen address (can be pointed to other place to use a screen buffer) +SCREEN_ATTR_ADDR: DW 22528 ; Screen attribute address (ditto.) + ; These are mapped onto ZX Spectrum ROM VARS + CHARS EQU 23606 ; Pointer to ROM/RAM Charset + TVFLAGS EQU 23612 ; TV Flags + UDG EQU 23675 ; Pointer to UDG Charset + COORDS EQU 23677 ; Last PLOT coordinates + FLAGS2 EQU 23681 ; + ECHO_E EQU 23682 ; + DFCC EQU 23684 ; Next screen addr for PRINT + DFCCL EQU 23686 ; Next screen attr for PRINT + S_POSN EQU 23688 + ATTR_P EQU 23693 ; Current Permanent ATTRS set with INK, PAPER, etc commands + ATTR_T EQU 23695 ; temporary ATTRIBUTES + P_FLAG EQU 23697 ; + MEM0 EQU 23698 ; Temporary memory buffer used by ROM chars + SCR_COLS EQU 33 ; Screen with in columns + 1 + SCR_ROWS EQU 24 ; Screen height in rows + SCR_SIZE EQU (SCR_ROWS << 8) + SCR_COLS + pop namespace +#line 2 "/zxbasic/src/arch/zx48k/library-asm/sposn.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/attr.asm" + ; Attribute routines +; vim:ts=4:et:sw: #line 1 "/zxbasic/src/arch/zx48k/library-asm/error.asm" ; Simple error control routines ; vim:ts=4:et: @@ -172,307 +151,29 @@ __STOP: ld (ERR_NR), a ret pop namespace -#line 69 "/zxbasic/src/arch/zx48k/library-asm/alloc.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/heapinit.asm" -; vim: ts=4:et:sw=4: - ; Copyleft (K) by Jose M. Rodriguez de la Rosa - ; (a.k.a. Boriel) -; http://www.boriel.com - ; - ; This ASM library is licensed under the BSD license - ; you can use it for any purpose (even for commercial - ; closed source programs). - ; - ; Please read the BSD license on the internet - ; ----- IMPLEMENTATION NOTES ------ - ; The heap is implemented as a linked list of free blocks. -; Each free block contains this info: - ; - ; +----------------+ <-- HEAP START - ; | Size (2 bytes) | - ; | 0 | <-- Size = 0 => DUMMY HEADER BLOCK - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ <-+ - ; | Size (2 bytes) | - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ | - ; | | | <-- If Size > 4, then this contains (size - 4) bytes - ; | (0 if Size = 4)| | - ; +----------------+ <-+ - ; | Size (2 bytes) | - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ | - ; | | | - ; | (0 if Size = 4)| | - ; +----------------+ | - ; | <-- This zone is in use (Already allocated) - ; +----------------+ <-+ - ; | Size (2 bytes) | - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ | - ; | | | - ; | (0 if Size = 4)| | - ; +----------------+ <-+ - ; | Next (2 bytes) |--> NULL => END OF LIST - ; | 0 = NULL | - ; +----------------+ - ; | | - ; | (0 if Size = 4)| - ; +----------------+ - ; When a block is FREED, the previous and next pointers are examined to see - ; if we can defragment the heap. If the block to be breed is just next to the - ; previous, or to the next (or both) they will be converted into a single - ; block (so defragmented). - ; MEMORY MANAGER - ; - ; This library must be initialized calling __MEM_INIT with - ; HL = BLOCK Start & DE = Length. - ; An init directive is useful for initialization routines. - ; They will be added automatically if needed. - ; --------------------------------------------------------------------- - ; __MEM_INIT must be called to initalize this library with the - ; standard parameters - ; --------------------------------------------------------------------- +#line 6 "/zxbasic/src/arch/zx48k/library-asm/attr.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/in_screen.asm" push namespace core -__MEM_INIT: ; Initializes the library using (RAMTOP) as start, and - ld hl, ZXBASIC_MEM_HEAP ; Change this with other address of heap start - ld de, ZXBASIC_HEAP_SIZE ; Change this with your size - ; --------------------------------------------------------------------- - ; __MEM_INIT2 initalizes this library -; Parameters: -; HL : Memory address of 1st byte of the memory heap -; DE : Length in bytes of the Memory Heap - ; --------------------------------------------------------------------- -__MEM_INIT2: - ; HL as TOP +__IN_SCREEN: + ; Returns NO carry if current coords (D, E) + ; are OUT of the screen limits PROC - dec de - dec de - dec de - dec de ; DE = length - 4; HL = start - ; This is done, because we require 4 bytes for the empty dummy-header block - xor a - ld (hl), a - inc hl - ld (hl), a ; First "free" block is a header: size=0, Pointer=&(Block) + 4 - inc hl - ld b, h - ld c, l - inc bc - inc bc ; BC = starts of next block - ld (hl), c - inc hl - ld (hl), b - inc hl ; Pointer to next block - ld (hl), e - inc hl - ld (hl), d - inc hl ; Block size (should be length - 4 at start); This block contains all the available memory - ld (hl), a ; NULL (0000h) ; No more blocks (a list with a single block) - inc hl - ld (hl), a - ld a, 201 - ld (__MEM_INIT), a; "Pokes" with a RET so ensure this routine is not called again - ret + LOCAL __IN_SCREEN_ERR + ld hl, SCR_SIZE + ld a, e + cp l + jr nc, __IN_SCREEN_ERR ; Do nothing and return if out of range + ld a, d + cp h + ret c ; Return if carry (OK) +__IN_SCREEN_ERR: +__OUT_OF_SCREEN_ERR: + ; Jumps here if out of screen + ld a, ERROR_OutOfScreen + jp __STOP ; Saves error code and exits ENDP pop namespace -#line 70 "/zxbasic/src/arch/zx48k/library-asm/alloc.asm" - ; --------------------------------------------------------------------- - ; MEM_ALLOC - ; Allocates a block of memory in the heap. - ; - ; Parameters - ; BC = Length of requested memory block - ; -; Returns: - ; HL = Pointer to the allocated block in memory. Returns 0 (NULL) - ; if the block could not be allocated (out of memory) - ; --------------------------------------------------------------------- - push namespace core -MEM_ALLOC: -__MEM_ALLOC: ; Returns the 1st free block found of the given length (in BC) - PROC - LOCAL __MEM_LOOP - LOCAL __MEM_DONE - LOCAL __MEM_SUBTRACT - LOCAL __MEM_START - LOCAL TEMP, TEMP0 - TEMP EQU TEMP0 + 1 - ld hl, 0 - ld (TEMP), hl -__MEM_START: - ld hl, ZXBASIC_MEM_HEAP ; This label point to the heap start - inc bc - inc bc ; BC = BC + 2 ; block size needs 2 extra bytes for hidden pointer -__MEM_LOOP: ; Loads lengh at (HL, HL+). If Lenght >= BC, jump to __MEM_DONE - ld a, h ; HL = NULL (No memory available?) - or l -#line 113 "/zxbasic/src/arch/zx48k/library-asm/alloc.asm" - ret z ; NULL -#line 115 "/zxbasic/src/arch/zx48k/library-asm/alloc.asm" - ; HL = Pointer to Free block - ld e, (hl) - inc hl - ld d, (hl) - inc hl ; DE = Block Length - push hl ; HL = *pointer to -> next block - ex de, hl - or a ; CF = 0 - sbc hl, bc ; FREE >= BC (Length) (HL = BlockLength - Length) - jp nc, __MEM_DONE - pop hl - ld (TEMP), hl - ex de, hl - ld e, (hl) - inc hl - ld d, (hl) - ex de, hl - jp __MEM_LOOP -__MEM_DONE: ; A free block has been found. - ; Check if at least 4 bytes remains free (HL >= 4) - push hl - exx ; exx to preserve bc - pop hl - ld bc, 4 - or a - sbc hl, bc - exx - jp nc, __MEM_SUBTRACT - ; At this point... - ; less than 4 bytes remains free. So we return this block entirely - ; We must link the previous block with the next to this one - ; (DE) => Pointer to next block - ; (TEMP) => &(previous->next) - pop hl ; Discard current block pointer - push de - ex de, hl ; DE = Previous block pointer; (HL) = Next block pointer - ld a, (hl) - inc hl - ld h, (hl) - ld l, a ; HL = (HL) - ex de, hl ; HL = Previous block pointer; DE = Next block pointer -TEMP0: - ld hl, 0 ; Pre-previous block pointer - ld (hl), e - inc hl - ld (hl), d ; LINKED - pop hl ; Returning block. - ret -__MEM_SUBTRACT: - ; At this point we have to store HL value (Length - BC) into (DE - 2) - ex de, hl - dec hl - ld (hl), d - dec hl - ld (hl), e ; Store new block length - add hl, de ; New length + DE => free-block start - pop de ; Remove previous HL off the stack - ld (hl), c ; Store length on its 1st word - inc hl - ld (hl), b - inc hl ; Return hl - ret - ENDP - pop namespace -#line 2 "/zxbasic/src/arch/zx48k/library-asm/loadstr.asm" - ; Loads a string (ptr) from HL - ; and duplicates it on dynamic memory again - ; Finally, it returns result pointer in HL - push namespace core -__ILOADSTR: ; This is the indirect pointer entry HL = (HL) - ld a, h - or l - ret z - ld a, (hl) - inc hl - ld h, (hl) - ld l, a -__LOADSTR: ; __FASTCALL__ entry - ld a, h - or l - ret z ; Return if NULL - ld c, (hl) - inc hl - ld b, (hl) - dec hl ; BC = LEN(a$) - inc bc - inc bc ; BC = LEN(a$) + 2 (two bytes for length) - push hl - push bc - call __MEM_ALLOC - pop bc ; Recover length - pop de ; Recover origin - ld a, h - or l - ret z ; Return if NULL (No memory) - ex de, hl ; ldir takes HL as source, DE as destiny, so SWAP HL,DE - push de ; Saves destiny start - ldir ; Copies string (length number included) - pop hl ; Recovers destiny in hl as result - ret - pop namespace -#line 51 "zx48k/read12.bas" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -; vim:ts=4:sw=4:et: - ; PRINT command routine - ; Does not print attribute. Use PRINT_STR or PRINT_NUM for that -#line 1 "/zxbasic/src/arch/zx48k/library-asm/sposn.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/sysvars.asm" - ;; ----------------------------------------------------------------------- - ;; ZX Basic System Vars - ;; Some of them will be mapped over Sinclair ROM ones for compatibility - ;; ----------------------------------------------------------------------- - push namespace core -SCREEN_ADDR: DW 16384 ; Screen address (can be pointed to other place to use a screen buffer) -SCREEN_ATTR_ADDR: DW 22528 ; Screen attribute address (ditto.) - ; These are mapped onto ZX Spectrum ROM VARS - CHARS EQU 23606 ; Pointer to ROM/RAM Charset - TVFLAGS EQU 23612 ; TV Flags - UDG EQU 23675 ; Pointer to UDG Charset - COORDS EQU 23677 ; Last PLOT coordinates - FLAGS2 EQU 23681 ; - ECHO_E EQU 23682 ; - DFCC EQU 23684 ; Next screen addr for PRINT - DFCCL EQU 23686 ; Next screen attr for PRINT - S_POSN EQU 23688 - ATTR_P EQU 23693 ; Current Permanent ATTRS set with INK, PAPER, etc commands - ATTR_T EQU 23695 ; temporary ATTRIBUTES - P_FLAG EQU 23697 ; - MEM0 EQU 23698 ; Temporary memory buffer used by ROM chars - SCR_COLS EQU 33 ; Screen with in columns + 1 - SCR_ROWS EQU 24 ; Screen height in rows - SCR_SIZE EQU (SCR_ROWS << 8) + SCR_COLS - pop namespace -#line 2 "/zxbasic/src/arch/zx48k/library-asm/sposn.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/attr.asm" - ; Attribute routines -; vim:ts=4:et:sw: -#line 1 "/zxbasic/src/arch/zx48k/library-asm/in_screen.asm" - push namespace core -__IN_SCREEN: - ; Returns NO carry if current coords (D, E) - ; are OUT of the screen limits - PROC - LOCAL __IN_SCREEN_ERR - ld hl, SCR_SIZE - ld a, e - cp l - jr nc, __IN_SCREEN_ERR ; Do nothing and return if out of range - ld a, d - cp h - ret c ; Return if carry (OK) -__IN_SCREEN_ERR: -__OUT_OF_SCREEN_ERR: - ; Jumps here if out of screen - ld a, ERROR_OutOfScreen - jp __STOP ; Saves error code and exits - ENDP - pop namespace -#line 7 "/zxbasic/src/arch/zx48k/library-asm/attr.asm" +#line 7 "/zxbasic/src/arch/zx48k/library-asm/attr.asm" push namespace core __ATTR_ADDR: ; calc start address in DE (as (32 * d) + e) @@ -730,60 +431,6 @@ BRIGHT_TMP: #line 1 "/zxbasic/src/arch/zx48k/library-asm/over.asm" ; Sets OVER flag in P_FLAG permanently ; Parameter: OVER flag in bit 0 of A register -#line 1 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" -#line 4 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" - push namespace core -COPY_ATTR: - ; Just copies current permanent attribs into temporal attribs - ; and sets print mode - PROC - LOCAL INVERSE1 - LOCAL __REFRESH_TMP - INVERSE1 EQU 02Fh - ld hl, (ATTR_P) - ld (ATTR_T), hl - ld hl, FLAGS2 - call __REFRESH_TMP - ld hl, P_FLAG - call __REFRESH_TMP -__SET_ATTR_MODE: ; Another entry to set print modes. A contains (P_FLAG) - LOCAL TABLE - LOCAL CONT2 - rra ; Over bit to carry - ld a, (FLAGS2) - rla ; Over bit in bit 1, Over2 bit in bit 2 - and 3 ; Only bit 0 and 1 (OVER flag) - ld c, a - ld b, 0 - ld hl, TABLE - add hl, bc - ld a, (hl) - ld (PRINT_MODE), a - ld hl, (P_FLAG) - xor a ; NOP -> INVERSE0 - bit 2, l - jr z, CONT2 - ld a, INVERSE1 ; CPL -> INVERSE1 -CONT2: - ld (INVERSE_MODE), a - ret -TABLE: - nop ; NORMAL MODE - xor (hl) ; OVER 1 MODE - and (hl) ; OVER 2 MODE - or (hl) ; OVER 3 MODE -#line 67 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" -__REFRESH_TMP: - ld a, (hl) - and 0b10101010 - ld c, a - rra - or c - ld (hl), a - ret - ENDP - pop namespace -#line 4 "/zxbasic/src/arch/zx48k/library-asm/over.asm" push namespace core OVER: PROC @@ -1025,11 +672,10 @@ INVERSE_MODE: ; 00 -> NOP -> INVERSE 0 inc hl ld (DFCC), hl ld hl, (DFCCL) ; current ATTR Pos - push hl - call __SET_ATTR - pop hl inc hl - ld (DFCCL),hl + ld (DFCCL), hl + dec hl + call __SET_ATTR exx ret ; ------------- SPECIAL CHARS (< 32) ----------------- @@ -1048,7 +694,7 @@ __PRINT_0Dh: ; Called WHEN printing CHR$(13) push hl call __SCROLL_SCR pop hl -#line 210 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 209 "/zxbasic/src/arch/zx48k/library-asm/print.asm" 1: ld l, 1 __PRINT_EOL_END: @@ -1165,14 +811,14 @@ __PRINT_BOLD: __PRINT_BOLD2: call BOLD_TMP jp __PRINT_RESTART -#line 354 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 353 "/zxbasic/src/arch/zx48k/library-asm/print.asm" __PRINT_ITA: ld hl, __PRINT_ITA2 jp __PRINT_SET_STATE __PRINT_ITA2: call ITALIC_TMP jp __PRINT_RESTART -#line 364 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 363 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __BOLD __BOLD: push hl @@ -1190,7 +836,7 @@ __BOLD: pop hl ld de, MEM0 ret -#line 385 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 384 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __ITALIC __ITALIC: push hl @@ -1215,12 +861,12 @@ __ITALIC: pop hl ld de, MEM0 ret -#line 413 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 412 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __SCROLL_SCR -#line 487 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 486 "/zxbasic/src/arch/zx48k/library-asm/print.asm" __SCROLL_SCR EQU 0DFEh ; Use ROM SCROLL +#line 488 "/zxbasic/src/arch/zx48k/library-asm/print.asm" #line 489 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -#line 490 "/zxbasic/src/arch/zx48k/library-asm/print.asm" PRINT_COMMA: call __LOAD_S_POSN ld a, e @@ -1263,9 +909,9 @@ PRINT_AT: ; Changes cursor to ROW, COL LOCAL __PRINT_TABLE LOCAL __PRINT_TAB, __PRINT_TAB1, __PRINT_TAB2 LOCAL __PRINT_ITA2 -#line 546 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 545 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __PRINT_BOLD2 -#line 552 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 551 "/zxbasic/src/arch/zx48k/library-asm/print.asm" __PRINT_TABLE: ; Jump table for 0 .. 22 codes DW __PRINT_NOP ; 0 DW __PRINT_NOP ; 1 @@ -1293,7 +939,364 @@ __PRINT_TABLE: ; Jump table for 0 .. 22 codes DW __PRINT_TAB ; 23 TAB ENDP pop namespace -#line 52 "zx48k/read12.bas" +#line 3 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" +#line 4 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" + push namespace core +COPY_ATTR: + ; Just copies current permanent attribs into temporal attribs + ; and sets print mode + PROC + LOCAL INVERSE1 + LOCAL __REFRESH_TMP + INVERSE1 EQU 02Fh + ld hl, (ATTR_P) + ld (ATTR_T), hl + ld hl, FLAGS2 + call __REFRESH_TMP + ld hl, P_FLAG + call __REFRESH_TMP +__SET_ATTR_MODE: ; Another entry to set print modes. A contains (P_FLAG) + LOCAL TABLE + LOCAL CONT2 + rra ; Over bit to carry + ld a, (FLAGS2) + rla ; Over bit in bit 1, Over2 bit in bit 2 + and 3 ; Only bit 0 and 1 (OVER flag) + ld c, a + ld b, 0 + ld hl, TABLE + add hl, bc + ld a, (hl) + ld (PRINT_MODE), a + ld hl, (P_FLAG) + xor a ; NOP -> INVERSE0 + bit 2, l + jr z, CONT2 + ld a, INVERSE1 ; CPL -> INVERSE1 +CONT2: + ld (INVERSE_MODE), a + ret +TABLE: + nop ; NORMAL MODE + xor (hl) ; OVER 1 MODE + and (hl) ; OVER 2 MODE + or (hl) ; OVER 3 MODE +#line 67 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" +__REFRESH_TMP: + ld a, (hl) + and 0b10101010 + ld c, a + rra + or c + ld (hl), a + ret + ENDP + pop namespace +#line 55 "zx48k/read12.bas" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/loadstr.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/alloc.asm" +; vim: ts=4:et:sw=4: + ; Copyleft (K) by Jose M. Rodriguez de la Rosa + ; (a.k.a. Boriel) +; http://www.boriel.com + ; + ; This ASM library is licensed under the MIT license + ; you can use it for any purpose (even for commercial + ; closed source programs). + ; + ; Please read the MIT license on the internet + ; ----- IMPLEMENTATION NOTES ------ + ; The heap is implemented as a linked list of free blocks. +; Each free block contains this info: + ; + ; +----------------+ <-- HEAP START + ; | Size (2 bytes) | + ; | 0 | <-- Size = 0 => DUMMY HEADER BLOCK + ; +----------------+ + ; | Next (2 bytes) |---+ + ; +----------------+ <-+ + ; | Size (2 bytes) | + ; +----------------+ + ; | Next (2 bytes) |---+ + ; +----------------+ | + ; | | | <-- If Size > 4, then this contains (size - 4) bytes + ; | (0 if Size = 4)| | + ; +----------------+ <-+ + ; | Size (2 bytes) | + ; +----------------+ + ; | Next (2 bytes) |---+ + ; +----------------+ | + ; | | | + ; | (0 if Size = 4)| | + ; +----------------+ | + ; | <-- This zone is in use (Already allocated) + ; +----------------+ <-+ + ; | Size (2 bytes) | + ; +----------------+ + ; | Next (2 bytes) |---+ + ; +----------------+ | + ; | | | + ; | (0 if Size = 4)| | + ; +----------------+ <-+ + ; | Next (2 bytes) |--> NULL => END OF LIST + ; | 0 = NULL | + ; +----------------+ + ; | | + ; | (0 if Size = 4)| + ; +----------------+ + ; When a block is FREED, the previous and next pointers are examined to see + ; if we can defragment the heap. If the block to be freed is just next to the + ; previous, or to the next (or both) they will be converted into a single + ; block (so defragmented). + ; MEMORY MANAGER + ; + ; This library must be initialized calling __MEM_INIT with + ; HL = BLOCK Start & DE = Length. + ; An init directive is useful for initialization routines. + ; They will be added automatically if needed. +#line 1 "/zxbasic/src/arch/zx48k/library-asm/heapinit.asm" +; vim: ts=4:et:sw=4: + ; Copyleft (K) by Jose M. Rodriguez de la Rosa + ; (a.k.a. Boriel) +; http://www.boriel.com + ; + ; This ASM library is licensed under the BSD license + ; you can use it for any purpose (even for commercial + ; closed source programs). + ; + ; Please read the BSD license on the internet + ; ----- IMPLEMENTATION NOTES ------ + ; The heap is implemented as a linked list of free blocks. +; Each free block contains this info: + ; + ; +----------------+ <-- HEAP START + ; | Size (2 bytes) | + ; | 0 | <-- Size = 0 => DUMMY HEADER BLOCK + ; +----------------+ + ; | Next (2 bytes) |---+ + ; +----------------+ <-+ + ; | Size (2 bytes) | + ; +----------------+ + ; | Next (2 bytes) |---+ + ; +----------------+ | + ; | | | <-- If Size > 4, then this contains (size - 4) bytes + ; | (0 if Size = 4)| | + ; +----------------+ <-+ + ; | Size (2 bytes) | + ; +----------------+ + ; | Next (2 bytes) |---+ + ; +----------------+ | + ; | | | + ; | (0 if Size = 4)| | + ; +----------------+ | + ; | <-- This zone is in use (Already allocated) + ; +----------------+ <-+ + ; | Size (2 bytes) | + ; +----------------+ + ; | Next (2 bytes) |---+ + ; +----------------+ | + ; | | | + ; | (0 if Size = 4)| | + ; +----------------+ <-+ + ; | Next (2 bytes) |--> NULL => END OF LIST + ; | 0 = NULL | + ; +----------------+ + ; | | + ; | (0 if Size = 4)| + ; +----------------+ + ; When a block is FREED, the previous and next pointers are examined to see + ; if we can defragment the heap. If the block to be breed is just next to the + ; previous, or to the next (or both) they will be converted into a single + ; block (so defragmented). + ; MEMORY MANAGER + ; + ; This library must be initialized calling __MEM_INIT with + ; HL = BLOCK Start & DE = Length. + ; An init directive is useful for initialization routines. + ; They will be added automatically if needed. + ; --------------------------------------------------------------------- + ; __MEM_INIT must be called to initalize this library with the + ; standard parameters + ; --------------------------------------------------------------------- + push namespace core +__MEM_INIT: ; Initializes the library using (RAMTOP) as start, and + ld hl, ZXBASIC_MEM_HEAP ; Change this with other address of heap start + ld de, ZXBASIC_HEAP_SIZE ; Change this with your size + ; --------------------------------------------------------------------- + ; __MEM_INIT2 initalizes this library +; Parameters: +; HL : Memory address of 1st byte of the memory heap +; DE : Length in bytes of the Memory Heap + ; --------------------------------------------------------------------- +__MEM_INIT2: + ; HL as TOP + PROC + dec de + dec de + dec de + dec de ; DE = length - 4; HL = start + ; This is done, because we require 4 bytes for the empty dummy-header block + xor a + ld (hl), a + inc hl + ld (hl), a ; First "free" block is a header: size=0, Pointer=&(Block) + 4 + inc hl + ld b, h + ld c, l + inc bc + inc bc ; BC = starts of next block + ld (hl), c + inc hl + ld (hl), b + inc hl ; Pointer to next block + ld (hl), e + inc hl + ld (hl), d + inc hl ; Block size (should be length - 4 at start); This block contains all the available memory + ld (hl), a ; NULL (0000h) ; No more blocks (a list with a single block) + inc hl + ld (hl), a + ld a, 201 + ld (__MEM_INIT), a; "Pokes" with a RET so ensure this routine is not called again + ret + ENDP + pop namespace +#line 70 "/zxbasic/src/arch/zx48k/library-asm/alloc.asm" + ; --------------------------------------------------------------------- + ; MEM_ALLOC + ; Allocates a block of memory in the heap. + ; + ; Parameters + ; BC = Length of requested memory block + ; +; Returns: + ; HL = Pointer to the allocated block in memory. Returns 0 (NULL) + ; if the block could not be allocated (out of memory) + ; --------------------------------------------------------------------- + push namespace core +MEM_ALLOC: +__MEM_ALLOC: ; Returns the 1st free block found of the given length (in BC) + PROC + LOCAL __MEM_LOOP + LOCAL __MEM_DONE + LOCAL __MEM_SUBTRACT + LOCAL __MEM_START + LOCAL TEMP, TEMP0 + TEMP EQU TEMP0 + 1 + ld hl, 0 + ld (TEMP), hl +__MEM_START: + ld hl, ZXBASIC_MEM_HEAP ; This label point to the heap start + inc bc + inc bc ; BC = BC + 2 ; block size needs 2 extra bytes for hidden pointer +__MEM_LOOP: ; Loads lengh at (HL, HL+). If Lenght >= BC, jump to __MEM_DONE + ld a, h ; HL = NULL (No memory available?) + or l +#line 113 "/zxbasic/src/arch/zx48k/library-asm/alloc.asm" + ret z ; NULL +#line 115 "/zxbasic/src/arch/zx48k/library-asm/alloc.asm" + ; HL = Pointer to Free block + ld e, (hl) + inc hl + ld d, (hl) + inc hl ; DE = Block Length + push hl ; HL = *pointer to -> next block + ex de, hl + or a ; CF = 0 + sbc hl, bc ; FREE >= BC (Length) (HL = BlockLength - Length) + jp nc, __MEM_DONE + pop hl + ld (TEMP), hl + ex de, hl + ld e, (hl) + inc hl + ld d, (hl) + ex de, hl + jp __MEM_LOOP +__MEM_DONE: ; A free block has been found. + ; Check if at least 4 bytes remains free (HL >= 4) + push hl + exx ; exx to preserve bc + pop hl + ld bc, 4 + or a + sbc hl, bc + exx + jp nc, __MEM_SUBTRACT + ; At this point... + ; less than 4 bytes remains free. So we return this block entirely + ; We must link the previous block with the next to this one + ; (DE) => Pointer to next block + ; (TEMP) => &(previous->next) + pop hl ; Discard current block pointer + push de + ex de, hl ; DE = Previous block pointer; (HL) = Next block pointer + ld a, (hl) + inc hl + ld h, (hl) + ld l, a ; HL = (HL) + ex de, hl ; HL = Previous block pointer; DE = Next block pointer +TEMP0: + ld hl, 0 ; Pre-previous block pointer + ld (hl), e + inc hl + ld (hl), d ; LINKED + pop hl ; Returning block. + ret +__MEM_SUBTRACT: + ; At this point we have to store HL value (Length - BC) into (DE - 2) + ex de, hl + dec hl + ld (hl), d + dec hl + ld (hl), e ; Store new block length + add hl, de ; New length + DE => free-block start + pop de ; Remove previous HL off the stack + ld (hl), c ; Store length on its 1st word + inc hl + ld (hl), b + inc hl ; Return hl + ret + ENDP + pop namespace +#line 2 "/zxbasic/src/arch/zx48k/library-asm/loadstr.asm" + ; Loads a string (ptr) from HL + ; and duplicates it on dynamic memory again + ; Finally, it returns result pointer in HL + push namespace core +__ILOADSTR: ; This is the indirect pointer entry HL = (HL) + ld a, h + or l + ret z + ld a, (hl) + inc hl + ld h, (hl) + ld l, a +__LOADSTR: ; __FASTCALL__ entry + ld a, h + or l + ret z ; Return if NULL + ld c, (hl) + inc hl + ld b, (hl) + dec hl ; BC = LEN(a$) + inc bc + inc bc ; BC = LEN(a$) + 2 (two bytes for length) + push hl + push bc + call __MEM_ALLOC + pop bc ; Recover length + pop de ; Recover origin + ld a, h + or l + ret z ; Return if NULL (No memory) + ex de, hl ; ldir takes HL as source, DE as destiny, so SWAP HL,DE + push de ; Saves destiny start + ldir ; Copies string (length number included) + pop hl ; Recovers destiny in hl as result + ret + pop namespace +#line 56 "zx48k/read12.bas" #line 1 "/zxbasic/src/arch/zx48k/library-asm/printi8.asm" #line 1 "/zxbasic/src/arch/zx48k/library-asm/printnum.asm" push namespace core @@ -1413,7 +1416,7 @@ __PRINTU_LOOP: jp __PRINTU_LOOP ; Uses JP in loops ENDP pop namespace -#line 53 "zx48k/read12.bas" +#line 58 "zx48k/read12.bas" #line 1 "/zxbasic/src/arch/zx48k/library-asm/read_restore.asm" ;; This implements READ & RESTORE functions ;; Reads a new element from the DATA Address code @@ -2164,5 +2167,5 @@ __DATA_ADDR: ;; Stores current DATA ptr dw .DATA.__DATA__0 ENDP pop namespace -#line 54 "zx48k/read12.bas" +#line 59 "zx48k/read12.bas" END diff --git a/tests/functional/zx48k/read13.asm b/tests/functional/zx48k/read13.asm index f031a6d5c..91e5ccf6b 100644 --- a/tests/functional/zx48k/read13.asm +++ b/tests/functional/zx48k/read13.asm @@ -76,6 +76,7 @@ _c.__DATA__: pop bc pop de call .core.__STORE32 + call .core.COPY_ATTR ld a, (_i) ld l, a ld h, 0 @@ -297,1253 +298,1252 @@ TMP_ARR_PTR: DW 0 ; temporary storage for pointer to tables ENDP pop namespace -#line 110 "zx48k/read13.bas" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/f16tofreg.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/neg32.asm" +#line 111 "zx48k/read13.bas" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +; vim:ts=4:sw=4:et: + ; PRINT command routine + ; Does not print attribute. Use PRINT_STR or PRINT_NUM for that +#line 1 "/zxbasic/src/arch/zx48k/library-asm/sposn.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/sysvars.asm" + ;; ----------------------------------------------------------------------- + ;; ZX Basic System Vars + ;; Some of them will be mapped over Sinclair ROM ones for compatibility + ;; ----------------------------------------------------------------------- + push namespace core +SCREEN_ADDR: DW 16384 ; Screen address (can be pointed to other place to use a screen buffer) +SCREEN_ATTR_ADDR: DW 22528 ; Screen attribute address (ditto.) + ; These are mapped onto ZX Spectrum ROM VARS + CHARS EQU 23606 ; Pointer to ROM/RAM Charset + TVFLAGS EQU 23612 ; TV Flags + UDG EQU 23675 ; Pointer to UDG Charset + COORDS EQU 23677 ; Last PLOT coordinates + FLAGS2 EQU 23681 ; + ECHO_E EQU 23682 ; + DFCC EQU 23684 ; Next screen addr for PRINT + DFCCL EQU 23686 ; Next screen attr for PRINT + S_POSN EQU 23688 + ATTR_P EQU 23693 ; Current Permanent ATTRS set with INK, PAPER, etc commands + ATTR_T EQU 23695 ; temporary ATTRIBUTES + P_FLAG EQU 23697 ; + MEM0 EQU 23698 ; Temporary memory buffer used by ROM chars + SCR_COLS EQU 33 ; Screen with in columns + 1 + SCR_ROWS EQU 24 ; Screen height in rows + SCR_SIZE EQU (SCR_ROWS << 8) + SCR_COLS + pop namespace +#line 2 "/zxbasic/src/arch/zx48k/library-asm/sposn.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/attr.asm" + ; Attribute routines +; vim:ts=4:et:sw: +#line 1 "/zxbasic/src/arch/zx48k/library-asm/error.asm" + ; Simple error control routines +; vim:ts=4:et: push namespace core -__ABS32: - bit 7, d - ret z -__NEG32: ; Negates DEHL (Two's complement) - ld a, l - cpl - ld l, a - ld a, h - cpl - ld h, a - ld a, e - cpl - ld e, a - ld a, d - cpl - ld d, a - inc l - ret nz - inc h - ret nz - inc de + ERR_NR EQU 23610 ; Error code system variable + ; Error code definitions (as in ZX spectrum manual) +; Set error code with: + ; ld a, ERROR_CODE + ; ld (ERR_NR), a + ERROR_Ok EQU -1 + ERROR_SubscriptWrong EQU 2 + ERROR_OutOfMemory EQU 3 + ERROR_OutOfScreen EQU 4 + ERROR_NumberTooBig EQU 5 + ERROR_InvalidArg EQU 9 + ERROR_IntOutOfRange EQU 10 + ERROR_NonsenseInBasic EQU 11 + ERROR_InvalidFileName EQU 14 + ERROR_InvalidColour EQU 19 + ERROR_BreakIntoProgram EQU 20 + ERROR_TapeLoadingErr EQU 26 + ; Raises error using RST #8 +__ERROR: + ld (__ERROR_CODE), a + rst 8 +__ERROR_CODE: + nop + ret + ; Sets the error system variable, but keeps running. + ; Usually this instruction if followed by the END intermediate instruction. +__STOP: + ld (ERR_NR), a ret pop namespace -#line 2 "/zxbasic/src/arch/zx48k/library-asm/f16tofreg.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/u32tofreg.asm" +#line 6 "/zxbasic/src/arch/zx48k/library-asm/attr.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/in_screen.asm" push namespace core -__I8TOFREG: - ld l, a - rlca - sbc a, a ; A = SGN(A) - ld h, a - ld e, a - ld d, a -__I32TOFREG: ; Converts a 32bit signed integer (stored in DEHL) - ; to a Floating Point Number returned in (A ED CB) +__IN_SCREEN: + ; Returns NO carry if current coords (D, E) + ; are OUT of the screen limits + PROC + LOCAL __IN_SCREEN_ERR + ld hl, SCR_SIZE + ld a, e + cp l + jr nc, __IN_SCREEN_ERR ; Do nothing and return if out of range ld a, d - or a ; Test sign - jp p, __U32TOFREG ; It was positive, proceed as 32bit unsigned - call __NEG32 ; Convert it to positive - call __U32TOFREG ; Convert it to Floating point - set 7, e ; Put the sign bit (negative) in the 31bit of mantissa - ret -__U8TOFREG: - ; Converts an unsigned 8 bit (A) to Floating point - ld l, a - ld h, 0 - ld e, h + cp h + ret c ; Return if carry (OK) +__IN_SCREEN_ERR: +__OUT_OF_SCREEN_ERR: + ; Jumps here if out of screen + ld a, ERROR_OutOfScreen + jp __STOP ; Saves error code and exits + ENDP + pop namespace +#line 7 "/zxbasic/src/arch/zx48k/library-asm/attr.asm" + push namespace core +__ATTR_ADDR: + ; calc start address in DE (as (32 * d) + e) + ; Contributed by Santiago Romero at http://www.speccy.org + ld h, 0 ; 7 T-States + ld a, d ; 4 T-States ld d, h -__U32TOFREG: ; Converts an unsigned 32 bit integer (DEHL) - ; to a Floating point number returned in A ED CB + add a, a ; a * 2 ; 4 T-States + add a, a ; a * 4 ; 4 T-States + ld l, a ; HL = A * 4 ; 4 T-States + add hl, hl ; HL = A * 8 ; 15 T-States + add hl, hl ; HL = A * 16 ; 15 T-States + add hl, hl ; HL = A * 32 ; 15 T-States + add hl, de + ld de, (SCREEN_ATTR_ADDR) ; Adds the screen address + add hl, de + ; Return current screen address in HL + ret + ; Sets the attribute at a given screen coordinate (D, E). + ; The attribute is taken from the ATTR_T memory variable + ; Used by PRINT routines +SET_ATTR: + ; Checks for valid coords + call __IN_SCREEN + ret nc + call __ATTR_ADDR +__SET_ATTR: + ; Internal __FASTCALL__ Entry used by printing routines + ; HL contains the address of the ATTR cell to set PROC - LOCAL __U32TOFREG_END +__SET_ATTR2: ; Sets attr from ATTR_T to (HL) which points to the scr address + ld de, (ATTR_T) ; E = ATTR_T, D = MASK_T ld a, d - or e - or h - or l - ld b, d - ld c, e ; Returns 00 0000 0000 if ZERO - ret z - push de - push hl - exx - pop de ; Loads integer into B'C' D'E' - pop bc - exx - ld l, 128 ; Exponent - ld bc, 0 ; DEBC = 0 - ld d, b - ld e, c -__U32TOFREG_LOOP: ; Also an entry point for __F16TOFREG - exx - ld a, d ; B'C'D'E' == 0 ? - or e - or b - or c - jp z, __U32TOFREG_END ; We are done - srl b ; Shift B'C' D'E' >> 1, output bit stays in Carry - rr c - rr d - rr e - exx - rr e ; Shift EDCB >> 1, inserting the carry on the left - rr d - rr c - rr b - inc l ; Increment exponent - jp __U32TOFREG_LOOP -__U32TOFREG_END: - exx - ld a, l ; Puts the exponent in a - res 7, e ; Sets the sign bit to 0 (positive) + and (hl) + ld c, a ; C = current screen color, masked + ld a, d + cpl ; Negate mask + and e ; Mask current attributes + or c ; Mix them + ld (hl), a ; Store result in screen ret ENDP pop namespace -#line 3 "/zxbasic/src/arch/zx48k/library-asm/f16tofreg.asm" +#line 3 "/zxbasic/src/arch/zx48k/library-asm/sposn.asm" + ; Printing positioning library. push namespace core -__F16TOFREG: ; Converts a 16.16 signed fixed point (stored in DEHL) - ; to a Floating Point Number returned in (C ED CB) + ; Loads into DE current ROW, COL print position from S_POSN mem var. +__LOAD_S_POSN: PROC - LOCAL __F16TOFREG2 - ld a, d - or a ; Test sign - jp p, __F16TOFREG2 ; It was positive, proceed as 32bit unsigned - call __NEG32 ; Convert it to positive - call __F16TOFREG2 ; Convert it to Floating point - set 7, e ; Put the sign bit (negative) in the 31bit of mantissa + ld de, (S_POSN) + ld hl, SCR_SIZE + or a + sbc hl, de + ex de, hl ret -__F16TOFREG2: ; Converts an unsigned 32 bit integer (DEHL) - ; to a Floating point number returned in C DE HL + ENDP + ; Saves ROW, COL from DE into S_POSN mem var. +__SAVE_S_POSN: + PROC + ld hl, SCR_SIZE + or a + sbc hl, de + ld (S_POSN), hl ; saves it again +__SET_SCR_PTR: ;; Fast + push de + call __ATTR_ADDR + ld (DFCCL), hl + pop de ld a, d + ld c, a ; Saves it for later + and 0F8h ; Masks 3 lower bit ; zy + ld d, a + ld a, c ; Recovers it + and 07h ; MOD 7 ; y1 + rrca + rrca + rrca or e - or h - or l - ld b, h - ld c, l - ret z ; Return 00 0000 0000 if 0 - push de - push hl - exx - pop de ; Loads integer into B'C' D'E' - pop bc - exx - ld l, 112 ; Exponent - ld bc, 0 ; DEBC = 0 - ld d, b - ld e, c - jp __U32TOFREG_LOOP ; Proceed as an integer + ld e, a + ld hl, (SCREEN_ADDR) + add hl, de ; HL = Screen address + DE + ld (DFCC), hl + ret ENDP pop namespace -#line 111 "zx48k/read13.bas" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/iload32.asm" - ; __FASTCALL__ routine which - ; loads a 32 bits integer into DE,HL - ; stored at position pointed by POINTER HL - ; DE,HL <-- (HL) +#line 6 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/table_jump.asm" push namespace core -__ILOAD32: +JUMP_HL_PLUS_2A: ; Does JP (HL + A*2) Modifies DE. Modifies A + add a, a +JUMP_HL_PLUS_A: ; Does JP (HL + A) Modifies DE + ld e, a + ld d, 0 +JUMP_HL_PLUS_DE: ; Does JP (HL + DE) + add hl, de ld e, (hl) inc hl ld d, (hl) - inc hl - ld a, (hl) - inc hl - ld h, (hl) - ld l, a ex de, hl +CALL_HL: + jp (hl) + pop namespace +#line 8 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/ink.asm" + ; Sets ink color in ATTR_P permanently +; Parameter: Paper color in A register + push namespace core +INK: + PROC + LOCAL __SET_INK + LOCAL __SET_INK2 + ld de, ATTR_P +__SET_INK: + cp 8 + jr nz, __SET_INK2 + inc de ; Points DE to MASK_T or MASK_P + ld a, (de) + or 7 ; Set bits 0,1,2 to enable transparency + ld (de), a + ret +__SET_INK2: + ; Another entry. This will set the ink color at location pointer by DE + and 7 ; # Gets color mod 8 + ld b, a ; Saves the color + ld a, (de) + and 0F8h ; Clears previous value + or b + ld (de), a + inc de ; Points DE to MASK_T or MASK_P + ld a, (de) + and 0F8h ; Reset bits 0,1,2 sign to disable transparency + ld (de), a ; Store new attr ret + ; Sets the INK color passed in A register in the ATTR_T variable +INK_TMP: + ld de, ATTR_T + jp __SET_INK + ENDP pop namespace -#line 112 "zx48k/read13.bas" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/mulf.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/stackf.asm" - ; ------------------------------------------------------------- - ; Functions to manage FP-Stack of the ZX Spectrum ROM CALC - ; ------------------------------------------------------------- +#line 9 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/paper.asm" + ; Sets paper color in ATTR_P permanently +; Parameter: Paper color in A register push namespace core - __FPSTACK_PUSH EQU 2AB6h ; Stores an FP number into the ROM FP stack (A, ED CB) - __FPSTACK_POP EQU 2BF1h ; Pops an FP number out of the ROM FP stack (A, ED CB) -__FPSTACK_PUSH2: ; Pushes Current A ED CB registers and top of the stack on (SP + 4) - ; Second argument to push into the stack calculator is popped out of the stack - ; Since the caller routine also receives the parameters into the top of the stack - ; four bytes must be removed from SP before pop them out - call __FPSTACK_PUSH ; Pushes A ED CB into the FP-STACK - exx - pop hl ; Caller-Caller return addr - exx - pop hl ; Caller return addr - pop af - pop de - pop bc - push hl ; Caller return addr - exx - push hl ; Caller-Caller return addr - exx - jp __FPSTACK_PUSH -__FPSTACK_I16: ; Pushes 16 bits integer in HL into the FP ROM STACK - ; This format is specified in the ZX 48K Manual - ; You can push a 16 bit signed integer as - ; 0 SS LL HH 0, being SS the sign and LL HH the low - ; and High byte respectively - ld a, h - rla ; sign to Carry - sbc a, a ; 0 if positive, FF if negative - ld e, a - ld d, l - ld c, h - xor a - ld b, a - jp __FPSTACK_PUSH +PAPER: + PROC + LOCAL __SET_PAPER + LOCAL __SET_PAPER2 + ld de, ATTR_P +__SET_PAPER: + cp 8 + jr nz, __SET_PAPER2 + inc de + ld a, (de) + or 038h + ld (de), a + ret + ; Another entry. This will set the paper color at location pointer by DE +__SET_PAPER2: + and 7 ; # Remove + rlca + rlca + rlca ; a *= 8 + ld b, a ; Saves the color + ld a, (de) + and 0C7h ; Clears previous value + or b + ld (de), a + inc de ; Points to MASK_T or MASK_P accordingly + ld a, (de) + and 0C7h ; Resets bits 3,4,5 + ld (de), a + ret + ; Sets the PAPER color passed in A register in the ATTR_T variable +PAPER_TMP: + ld de, ATTR_T + jp __SET_PAPER + ENDP pop namespace -#line 2 "/zxbasic/src/arch/zx48k/library-asm/mulf.asm" - ; ------------------------------------------------------------- - ; Floating point library using the FP ROM Calculator (ZX 48K) - ; All of them uses A EDCB registers as 1st paramter. - ; For binary operators, the 2n operator must be pushed into the - ; stack, in the order A DE BC. - ; - ; Uses CALLEE convention - ; ------------------------------------------------------------- +#line 10 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/flash.asm" + ; Sets flash flag in ATTR_P permanently +; Parameter: Paper color in A register push namespace core -__MULF: ; Multiplication - call __FPSTACK_PUSH2 - ; ------------- ROM MUL - rst 28h - defb 04h ; - defb 38h; ; END CALC - jp __FPSTACK_POP +FLASH: + ld hl, ATTR_P + PROC + LOCAL IS_TR + LOCAL IS_ZERO +__SET_FLASH: + ; Another entry. This will set the flash flag at location pointer by DE + cp 8 + jr z, IS_TR + ; # Convert to 0/1 + or a + jr z, IS_ZERO + ld a, 0x80 +IS_ZERO: + ld b, a ; Saves the color + ld a, (hl) + and 07Fh ; Clears previous value + or b + ld (hl), a + inc hl + res 7, (hl) ;Reset bit 7 to disable transparency + ret +IS_TR: ; transparent + inc hl ; Points DE to MASK_T or MASK_P + set 7, (hl) ;Set bit 7 to enable transparency + ret + ; Sets the FLASH flag passed in A register in the ATTR_T variable +FLASH_TMP: + ld hl, ATTR_T + jr __SET_FLASH + ENDP pop namespace -#line 113 "zx48k/read13.bas" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/mulf16.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/_mul32.asm" -; Ripped from: http://www.andreadrian.de/oldcpu/z80_number_cruncher.html#moztocid784223 - ; Used with permission. - ; Multiplies 32x32 bit integer (DEHL x D'E'H'L') - ; 64bit result is returned in H'L'H L B'C'A C +#line 11 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/bright.asm" + ; Sets bright flag in ATTR_P permanently +; Parameter: Paper color in A register push namespace core -__MUL32_64START: - push hl - exx - ld b, h - ld c, l ; BC = Low Part (A) - pop hl ; HL = Load Part (B) - ex de, hl ; DE = Low Part (B), HL = HightPart(A) (must be in B'C') - push hl - exx - pop bc ; B'C' = HightPart(A) - exx ; A = B'C'BC , B = D'E'DE - ; multiply routine 32 * 32bit = 64bit - ; h'l'hlb'c'ac = b'c'bc * d'e'de - ; needs register a, changes flags - ; - ; this routine was with tiny differences in the - ; sinclair zx81 rom for the mantissa multiply -__LMUL: - xor a ; reset carry flag - ld h, a ; result bits 32..47 = 0 - ld l, a - exx - ld h, a ; result bits 48..63 = 0 - ld l, a - exx - ld a,b ; mpr is b'c'ac - ld b,33 ; initialize loop counter - jp __LMULSTART -__LMULLOOP: - jr nc,__LMULNOADD ; JP is 2 cycles faster than JR. Since it's inside a LOOP - ; it can save up to 33 * 2 = 66 cycles - ; But JR if 3 cycles faster if JUMP not taken! - add hl,de ; result += mpd - exx - adc hl,de - exx -__LMULNOADD: - exx - rr h ; right shift upper - rr l ; 32bit of result - exx - rr h - rr l -__LMULSTART: - exx - rr b ; right shift mpr/ - rr c ; lower 32bit of result - exx - rra ; equivalent to rr a - rr c - djnz __LMULLOOP - ret ; result in h'l'hlb'c'ac +BRIGHT: + ld hl, ATTR_P + PROC + LOCAL IS_TR + LOCAL IS_ZERO +__SET_BRIGHT: + ; Another entry. This will set the bright flag at location pointer by DE + cp 8 + jr z, IS_TR + ; # Convert to 0/1 + or a + jr z, IS_ZERO + ld a, 0x40 +IS_ZERO: + ld b, a ; Saves the color + ld a, (hl) + and 0BFh ; Clears previous value + or b + ld (hl), a + inc hl + res 6, (hl) ;Reset bit 6 to disable transparency + ret +IS_TR: ; transparent + inc hl ; Points DE to MASK_T or MASK_P + set 6, (hl) ;Set bit 6 to enable transparency + ret + ; Sets the BRIGHT flag passed in A register in the ATTR_T variable +BRIGHT_TMP: + ld hl, ATTR_T + jr __SET_BRIGHT + ENDP pop namespace -#line 3 "/zxbasic/src/arch/zx48k/library-asm/mulf16.asm" +#line 12 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/over.asm" + ; Sets OVER flag in P_FLAG permanently +; Parameter: OVER flag in bit 0 of A register push namespace core -__MULF16: ; - ld a, d ; load sgn into a - ex af, af' ; saves it - call __ABS32 ; convert to positive - exx - pop hl ; Return address - pop de ; Low part - ex (sp), hl ; CALLEE caller convention; Now HL = Hight part, (SP) = Return address - ex de, hl ; D'E' = High part (B), H'L' = Low part (B) (must be in DE) - ex af, af' - xor d ; A register contains resulting sgn - ex af, af' - call __ABS32 ; convert to positive - call __MUL32_64START - ; rounding (was not included in zx81) -__ROUND_FIX: ; rounds a 64bit (32.32) fixed point number to 16.16 - ; result returned in dehl - ; input in h'l'hlb'c'ac - sla a ; result bit 47 to carry - exx - ld hl,0 ; ld does not change carry - adc hl,bc ; hl = hl + 0 + carry - push hl - exx - ld bc,0 - adc hl,bc ; hl = hl + 0 + carry - ex de, hl - pop hl ; rounded result in de.hl - ex af, af' ; recovers result sign - or a - jp m, __NEG32 ; if negative, negates it +OVER: + PROC + ld c, a ; saves it for later + and 2 + ld hl, FLAGS2 + res 1, (HL) + or (hl) + ld (hl), a + ld a, c ; Recovers previous value + and 1 ; # Convert to 0/1 + add a, a; # Shift left 1 bit for permanent + ld hl, P_FLAG + res 1, (hl) + or (hl) + ld (hl), a ret + ; Sets OVER flag in P_FLAG temporarily +OVER_TMP: + ld c, a ; saves it for later + and 2 ; gets bit 1; clears carry + rra + ld hl, FLAGS2 + res 0, (hl) + or (hl) + ld (hl), a + ld a, c ; Recovers previous value + and 1 + ld hl, P_FLAG + res 0, (hl) + or (hl) + ld (hl), a + jp __SET_ATTR_MODE + ENDP pop namespace -#line 114 "zx48k/read13.bas" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/pow.asm" - ; ------------------------------------------------------------- - ; Floating point library using the FP ROM Calculator (ZX 48K) - ; All of them uses A EDCB registers as 1st paramter. - ; For binary operators, the 2n operator must be pushed into the - ; stack, in the order A DE BC. - ; - ; Uses CALLEE convention - ; -; Operands comes swapped: - ; 1 st parameter is the BASE (A ED CB) - ; 2 nd parameter (Top of the stack) is Exponent - ; ------------------------------------------------------------- +#line 13 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/inverse.asm" + ; Sets INVERSE flag in P_FLAG permanently +; Parameter: INVERSE flag in bit 0 of A register push namespace core -__POW: ; Exponentiation +INVERSE: PROC - call __FPSTACK_PUSH2 - ; ------------- ROM POW - rst 28h - defb 01h ; Exchange => 1, Base - defb 06h ; POW - defb 38h; ; END CALC - jp __FPSTACK_POP + and 1 ; # Convert to 0/1 + add a, a; # Shift left 3 bits for permanent + add a, a + add a, a + ld hl, P_FLAG + res 3, (hl) + or (hl) + ld (hl), a + ret + ; Sets INVERSE flag in P_FLAG temporarily +INVERSE_TMP: + and 1 + add a, a + add a, a; # Shift left 2 bits for temporary + ld hl, P_FLAG + res 2, (hl) + or (hl) + ld (hl), a + jp __SET_ATTR_MODE ENDP pop namespace -#line 115 "zx48k/read13.bas" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -; vim:ts=4:sw=4:et: - ; PRINT command routine - ; Does not print attribute. Use PRINT_STR or PRINT_NUM for that -#line 1 "/zxbasic/src/arch/zx48k/library-asm/sposn.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/sysvars.asm" - ;; ----------------------------------------------------------------------- - ;; ZX Basic System Vars - ;; Some of them will be mapped over Sinclair ROM ones for compatibility - ;; ----------------------------------------------------------------------- - push namespace core -SCREEN_ADDR: DW 16384 ; Screen address (can be pointed to other place to use a screen buffer) -SCREEN_ATTR_ADDR: DW 22528 ; Screen attribute address (ditto.) - ; These are mapped onto ZX Spectrum ROM VARS - CHARS EQU 23606 ; Pointer to ROM/RAM Charset - TVFLAGS EQU 23612 ; TV Flags - UDG EQU 23675 ; Pointer to UDG Charset - COORDS EQU 23677 ; Last PLOT coordinates - FLAGS2 EQU 23681 ; - ECHO_E EQU 23682 ; - DFCC EQU 23684 ; Next screen addr for PRINT - DFCCL EQU 23686 ; Next screen attr for PRINT - S_POSN EQU 23688 - ATTR_P EQU 23693 ; Current Permanent ATTRS set with INK, PAPER, etc commands - ATTR_T EQU 23695 ; temporary ATTRIBUTES - P_FLAG EQU 23697 ; - MEM0 EQU 23698 ; Temporary memory buffer used by ROM chars - SCR_COLS EQU 33 ; Screen with in columns + 1 - SCR_ROWS EQU 24 ; Screen height in rows - SCR_SIZE EQU (SCR_ROWS << 8) + SCR_COLS - pop namespace -#line 2 "/zxbasic/src/arch/zx48k/library-asm/sposn.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/attr.asm" - ; Attribute routines -; vim:ts=4:et:sw: -#line 1 "/zxbasic/src/arch/zx48k/library-asm/error.asm" - ; Simple error control routines -; vim:ts=4:et: +#line 14 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/bold.asm" + ; Sets BOLD flag in P_FLAG permanently +; Parameter: BOLD flag in bit 0 of A register push namespace core - ERR_NR EQU 23610 ; Error code system variable - ; Error code definitions (as in ZX spectrum manual) -; Set error code with: - ; ld a, ERROR_CODE - ; ld (ERR_NR), a - ERROR_Ok EQU -1 - ERROR_SubscriptWrong EQU 2 - ERROR_OutOfMemory EQU 3 - ERROR_OutOfScreen EQU 4 - ERROR_NumberTooBig EQU 5 - ERROR_InvalidArg EQU 9 - ERROR_IntOutOfRange EQU 10 - ERROR_NonsenseInBasic EQU 11 - ERROR_InvalidFileName EQU 14 - ERROR_InvalidColour EQU 19 - ERROR_BreakIntoProgram EQU 20 - ERROR_TapeLoadingErr EQU 26 - ; Raises error using RST #8 -__ERROR: - ld (__ERROR_CODE), a - rst 8 -__ERROR_CODE: - nop +BOLD: + PROC + and 1 + rlca + rlca + rlca + ld hl, FLAGS2 + res 3, (HL) + or (hl) + ld (hl), a ret - ; Sets the error system variable, but keeps running. - ; Usually this instruction if followed by the END intermediate instruction. -__STOP: - ld (ERR_NR), a + ; Sets BOLD flag in P_FLAG temporarily +BOLD_TMP: + and 1 + rlca + rlca + ld hl, FLAGS2 + res 2, (hl) + or (hl) + ld (hl), a ret + ENDP pop namespace -#line 6 "/zxbasic/src/arch/zx48k/library-asm/attr.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/in_screen.asm" +#line 15 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/italic.asm" + ; Sets ITALIC flag in P_FLAG permanently +; Parameter: ITALIC flag in bit 0 of A register push namespace core -__IN_SCREEN: - ; Returns NO carry if current coords (D, E) - ; are OUT of the screen limits +ITALIC: PROC - LOCAL __IN_SCREEN_ERR - ld hl, SCR_SIZE - ld a, e - cp l - jr nc, __IN_SCREEN_ERR ; Do nothing and return if out of range - ld a, d - cp h - ret c ; Return if carry (OK) -__IN_SCREEN_ERR: -__OUT_OF_SCREEN_ERR: - ; Jumps here if out of screen - ld a, ERROR_OutOfScreen - jp __STOP ; Saves error code and exits - ENDP - pop namespace -#line 7 "/zxbasic/src/arch/zx48k/library-asm/attr.asm" - push namespace core -__ATTR_ADDR: - ; calc start address in DE (as (32 * d) + e) - ; Contributed by Santiago Romero at http://www.speccy.org - ld h, 0 ; 7 T-States - ld a, d ; 4 T-States - ld d, h - add a, a ; a * 2 ; 4 T-States - add a, a ; a * 4 ; 4 T-States - ld l, a ; HL = A * 4 ; 4 T-States - add hl, hl ; HL = A * 8 ; 15 T-States - add hl, hl ; HL = A * 16 ; 15 T-States - add hl, hl ; HL = A * 32 ; 15 T-States - add hl, de - ld de, (SCREEN_ATTR_ADDR) ; Adds the screen address - add hl, de - ; Return current screen address in HL + and 1 + rrca + rrca + rrca + ld hl, FLAGS2 + res 5, (HL) + or (hl) + ld (hl), a ret - ; Sets the attribute at a given screen coordinate (D, E). - ; The attribute is taken from the ATTR_T memory variable - ; Used by PRINT routines -SET_ATTR: - ; Checks for valid coords - call __IN_SCREEN - ret nc - call __ATTR_ADDR -__SET_ATTR: - ; Internal __FASTCALL__ Entry used by printing routines - ; HL contains the address of the ATTR cell to set - PROC -__SET_ATTR2: ; Sets attr from ATTR_T to (HL) which points to the scr address - ld de, (ATTR_T) ; E = ATTR_T, D = MASK_T - ld a, d - and (hl) - ld c, a ; C = current screen color, masked - ld a, d - cpl ; Negate mask - and e ; Mask current attributes - or c ; Mix them - ld (hl), a ; Store result in screen + ; Sets ITALIC flag in P_FLAG temporarily +ITALIC_TMP: + and 1 + rrca + rrca + rrca + rrca + ld hl, FLAGS2 + res 4, (hl) + or (hl) + ld (hl), a ret ENDP pop namespace -#line 3 "/zxbasic/src/arch/zx48k/library-asm/sposn.asm" - ; Printing positioning library. +#line 16 "/zxbasic/src/arch/zx48k/library-asm/print.asm" + ; Putting a comment starting with @INIT
+ ; will make the compiler to add a CALL to
+ ; It is useful for initialization routines. push namespace core - ; Loads into DE current ROW, COL print position from S_POSN mem var. -__LOAD_S_POSN: +__PRINT_INIT: ; To be called before program starts (initializes library) PROC - ld de, (S_POSN) + ld hl, __PRINT_START + ld (PRINT_JUMP_STATE), hl + ;; Clears ATTR2 flags (OVER 2, etc) + xor a + ld (FLAGS2), a + LOCAL SET_SCR_ADDR + call __LOAD_S_POSN + jp __SET_SCR_PTR + ;; Receives HL = future value of S_POSN + ;; Stores it at (S_POSN) and refresh screen pointers (ATTR, SCR) +SET_SCR_ADDR: + ld (S_POSN), hl + ex de, hl ld hl, SCR_SIZE or a sbc hl, de ex de, hl + dec e + jp __SET_SCR_PTR +__PRINTCHAR: ; Print character store in accumulator (A register) + ; Modifies H'L', B'C', A'F', D'E', A + LOCAL PO_GR_1 + LOCAL __PRCHAR + LOCAL __PRINT_JUMP + LOCAL __SRCADDR + LOCAL __PRINT_UDG + LOCAL __PRGRAPH + LOCAL __PRINT_START + PRINT_JUMP_STATE EQU __PRINT_JUMP + 2 +__PRINT_JUMP: + exx ; Switch to alternative registers + jp __PRINT_START ; Where to jump. If we print 22 (AT), next two calls jumps to AT1 and AT2 respectively +__PRINT_START: +__PRINT_CHR: + cp ' ' + jr c, __PRINT_SPECIAL ; Characters below ' ' are special ones + ex af, af' ; Saves a value (char to print) for later + ld hl, (S_POSN) + dec l + jr nz, 1f + ld l, SCR_COLS - 1 + dec h + jr nz, 2f + inc h + push hl + call __SCROLL_SCR + pop hl +#line 92 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +2: + call SET_SCR_ADDR + jr 4f +1: + ld (S_POSN), hl +4: + ex af, af' + cp 80h ; Is it a "normal" (printable) char + jr c, __SRCADDR + cp 90h ; Is it an UDG? + jr nc, __PRINT_UDG + ; Print an 8 bit pattern (80h to 8Fh) + ld b, a + call PO_GR_1 ; This ROM routine will generate the bit pattern at MEM0 + ld hl, MEM0 + jp __PRGRAPH + PO_GR_1 EQU 0B38h +__PRINT_UDG: + sub 90h ; Sub ASC code + ld bc, (UDG) + jr __PRGRAPH0 + __SOURCEADDR EQU (__SRCADDR + 1) ; Address of the pointer to chars source +__SRCADDR: + ld bc, (CHARS) +__PRGRAPH0: + add a, a ; A = a * 2 (since a < 80h) ; Thanks to Metalbrain at http://foro.speccy.org + ld l, a + ld h, 0 ; HL = a * 2 (accumulator) + add hl, hl + add hl, hl ; HL = a * 8 + add hl, bc ; HL = CHARS address +__PRGRAPH: + ex de, hl ; HL = Write Address, DE = CHARS address + bit 2, (iy + $47) + call nz, __BOLD +#line 139 "/zxbasic/src/arch/zx48k/library-asm/print.asm" + bit 4, (iy + $47) + call nz, __ITALIC +#line 144 "/zxbasic/src/arch/zx48k/library-asm/print.asm" + ld hl, (DFCC) + push hl + ld b, 8 ; 8 bytes per char +__PRCHAR: + ld a, (de) ; DE *must* be source, and HL destiny +PRINT_MODE: ; Which operation is used to write on the screen + ; Set it with: + ; LD A, + ; LD (PRINT_MODE), A + ; + ; Available operations: + ; NORMAL : 0h --> NOP ; OVER 0 + ; XOR : AEh --> XOR (HL) ; OVER 1 + ; OR : B6h --> OR (HL) ; PUTSPRITE + ; AND : A6h --> AND (HL) ; PUTMASK + nop ; Set to one of the values above +INVERSE_MODE: ; 00 -> NOP -> INVERSE 0 + nop ; 2F -> CPL -> INVERSE 1 + ld (hl), a + inc de + inc h ; Next line + djnz __PRCHAR + pop hl + inc hl + ld (DFCC), hl + ld hl, (DFCCL) ; current ATTR Pos + inc hl + ld (DFCCL), hl + dec hl + call __SET_ATTR + exx ret - ENDP - ; Saves ROW, COL from DE into S_POSN mem var. -__SAVE_S_POSN: - PROC - ld hl, SCR_SIZE - or a - sbc hl, de - ld (S_POSN), hl ; saves it again -__SET_SCR_PTR: ;; Fast + ; ------------- SPECIAL CHARS (< 32) ----------------- +__PRINT_SPECIAL: ; Jumps here if it is a special char + ld hl, __PRINT_TABLE + jp JUMP_HL_PLUS_2A +PRINT_EOL: ; Called WHENEVER there is no ";" at end of PRINT sentence + exx +__PRINT_0Dh: ; Called WHEN printing CHR$(13) + ld hl, (S_POSN) + dec l + jr nz, 1f + dec h + jr nz, 1f + inc h + push hl + call __SCROLL_SCR + pop hl +#line 209 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +1: + ld l, 1 +__PRINT_EOL_END: + call SET_SCR_ADDR + exx + ret +__PRINT_COM: + exx + push hl push de - call __ATTR_ADDR - ld (DFCCL), hl + push bc + call PRINT_COMMA + pop bc pop de - ld a, d - ld c, a ; Saves it for later - and 0F8h ; Masks 3 lower bit ; zy - ld d, a - ld a, c ; Recovers it - and 07h ; MOD 7 ; y1 - rrca - rrca - rrca - or e - ld e, a - ld hl, (SCREEN_ADDR) - add hl, de ; HL = Screen address + DE - ld (DFCC), hl + pop hl ret - ENDP - pop namespace -#line 6 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/table_jump.asm" - push namespace core -JUMP_HL_PLUS_2A: ; Does JP (HL + A*2) Modifies DE. Modifies A - add a, a -JUMP_HL_PLUS_A: ; Does JP (HL + A) Modifies DE - ld e, a - ld d, 0 -JUMP_HL_PLUS_DE: ; Does JP (HL + DE) - add hl, de - ld e, (hl) - inc hl - ld d, (hl) - ex de, hl -CALL_HL: - jp (hl) - pop namespace -#line 8 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/ink.asm" - ; Sets ink color in ATTR_P permanently -; Parameter: Paper color in A register - push namespace core -INK: - PROC - LOCAL __SET_INK - LOCAL __SET_INK2 - ld de, ATTR_P -__SET_INK: - cp 8 - jr nz, __SET_INK2 - inc de ; Points DE to MASK_T or MASK_P - ld a, (de) - or 7 ; Set bits 0,1,2 to enable transparency - ld (de), a +__PRINT_TAB: + ld hl, __PRINT_TAB1 + jr __PRINT_SET_STATE +__PRINT_TAB1: + ld (MEM0), a + ld hl, __PRINT_TAB2 + jr __PRINT_SET_STATE +__PRINT_TAB2: + ld a, (MEM0) ; Load tab code (ignore the current one) + ld hl, __PRINT_START + ld (PRINT_JUMP_STATE), hl + exx + push hl + push bc + push de + call PRINT_TAB + pop de + pop bc + pop hl ret -__SET_INK2: - ; Another entry. This will set the ink color at location pointer by DE - and 7 ; # Gets color mod 8 - ld b, a ; Saves the color - ld a, (de) - and 0F8h ; Clears previous value - or b - ld (de), a - inc de ; Points DE to MASK_T or MASK_P - ld a, (de) - and 0F8h ; Reset bits 0,1,2 sign to disable transparency - ld (de), a ; Store new attr +__PRINT_AT: + ld hl, __PRINT_AT1 + jr __PRINT_SET_STATE +__PRINT_NOP: +__PRINT_RESTART: + ld hl, __PRINT_START +__PRINT_SET_STATE: + ld (PRINT_JUMP_STATE), hl ; Saves next entry call + exx ret - ; Sets the INK color passed in A register in the ATTR_T variable -INK_TMP: - ld de, ATTR_T - jp __SET_INK - ENDP - pop namespace -#line 9 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/paper.asm" - ; Sets paper color in ATTR_P permanently -; Parameter: Paper color in A register - push namespace core -PAPER: - PROC - LOCAL __SET_PAPER - LOCAL __SET_PAPER2 - ld de, ATTR_P -__SET_PAPER: - cp 8 - jr nz, __SET_PAPER2 - inc de - ld a, (de) - or 038h - ld (de), a +__PRINT_AT1: ; Jumps here if waiting for 1st parameter + ld hl, (S_POSN) + ld h, a + ld a, SCR_ROWS + sub h + ld (S_POSN + 1), a + ld hl, __PRINT_AT2 + jr __PRINT_SET_STATE +__PRINT_AT2: + call __LOAD_S_POSN + ld e, a + call __SAVE_S_POSN + jr __PRINT_RESTART +__PRINT_DEL: + call __LOAD_S_POSN ; Gets current screen position + dec e + ld a, -1 + cp e + jr nz, 3f + ld e, SCR_COLS - 2 + dec d + cp d + jr nz, 3f + ld d, SCR_ROWS - 1 +3: + call __SAVE_S_POSN + exx ret - ; Another entry. This will set the paper color at location pointer by DE -__SET_PAPER2: - and 7 ; # Remove - rlca - rlca - rlca ; a *= 8 - ld b, a ; Saves the color - ld a, (de) - and 0C7h ; Clears previous value - or b - ld (de), a - inc de ; Points to MASK_T or MASK_P accordingly +__PRINT_INK: + ld hl, __PRINT_INK2 + jr __PRINT_SET_STATE +__PRINT_INK2: + call INK_TMP + jr __PRINT_RESTART +__PRINT_PAP: + ld hl, __PRINT_PAP2 + jr __PRINT_SET_STATE +__PRINT_PAP2: + call PAPER_TMP + jr __PRINT_RESTART +__PRINT_FLA: + ld hl, __PRINT_FLA2 + jr __PRINT_SET_STATE +__PRINT_FLA2: + call FLASH_TMP + jr __PRINT_RESTART +__PRINT_BRI: + ld hl, __PRINT_BRI2 + jr __PRINT_SET_STATE +__PRINT_BRI2: + call BRIGHT_TMP + jr __PRINT_RESTART +__PRINT_INV: + ld hl, __PRINT_INV2 + jr __PRINT_SET_STATE +__PRINT_INV2: + call INVERSE_TMP + jr __PRINT_RESTART +__PRINT_OVR: + ld hl, __PRINT_OVR2 + jr __PRINT_SET_STATE +__PRINT_OVR2: + call OVER_TMP + jr __PRINT_RESTART +__PRINT_BOLD: + ld hl, __PRINT_BOLD2 + jp __PRINT_SET_STATE +__PRINT_BOLD2: + call BOLD_TMP + jp __PRINT_RESTART +#line 353 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +__PRINT_ITA: + ld hl, __PRINT_ITA2 + jp __PRINT_SET_STATE +__PRINT_ITA2: + call ITALIC_TMP + jp __PRINT_RESTART +#line 363 "/zxbasic/src/arch/zx48k/library-asm/print.asm" + LOCAL __BOLD +__BOLD: + push hl + ld hl, MEM0 + ld b, 8 +1: ld a, (de) - and 0C7h ; Resets bits 3,4,5 - ld (de), a - ret - ; Sets the PAPER color passed in A register in the ATTR_T variable -PAPER_TMP: - ld de, ATTR_T - jp __SET_PAPER - ENDP - pop namespace -#line 10 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/flash.asm" - ; Sets flash flag in ATTR_P permanently -; Parameter: Paper color in A register - push namespace core -FLASH: - ld hl, ATTR_P - PROC - LOCAL IS_TR - LOCAL IS_ZERO -__SET_FLASH: - ; Another entry. This will set the flash flag at location pointer by DE - cp 8 - jr z, IS_TR - ; # Convert to 0/1 - or a - jr z, IS_ZERO - ld a, 0x80 -IS_ZERO: - ld b, a ; Saves the color - ld a, (hl) - and 07Fh ; Clears previous value - or b + ld c, a + rlca + or c ld (hl), a inc hl - res 7, (hl) ;Reset bit 7 to disable transparency - ret -IS_TR: ; transparent - inc hl ; Points DE to MASK_T or MASK_P - set 7, (hl) ;Set bit 7 to enable transparency + inc de + djnz 1b + pop hl + ld de, MEM0 ret - ; Sets the FLASH flag passed in A register in the ATTR_T variable -FLASH_TMP: - ld hl, ATTR_T - jr __SET_FLASH - ENDP - pop namespace -#line 11 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/bright.asm" - ; Sets bright flag in ATTR_P permanently -; Parameter: Paper color in A register - push namespace core -BRIGHT: - ld hl, ATTR_P - PROC - LOCAL IS_TR - LOCAL IS_ZERO -__SET_BRIGHT: - ; Another entry. This will set the bright flag at location pointer by DE - cp 8 - jr z, IS_TR - ; # Convert to 0/1 - or a - jr z, IS_ZERO - ld a, 0x40 -IS_ZERO: - ld b, a ; Saves the color - ld a, (hl) - and 0BFh ; Clears previous value - or b - ld (hl), a +#line 384 "/zxbasic/src/arch/zx48k/library-asm/print.asm" + LOCAL __ITALIC +__ITALIC: + push hl + ld hl, MEM0 + ex de, hl + ld bc, 8 + ldir + ld hl, MEM0 + srl (hl) inc hl - res 6, (hl) ;Reset bit 6 to disable transparency - ret -IS_TR: ; transparent - inc hl ; Points DE to MASK_T or MASK_P - set 6, (hl) ;Set bit 6 to enable transparency - ret - ; Sets the BRIGHT flag passed in A register in the ATTR_T variable -BRIGHT_TMP: - ld hl, ATTR_T - jr __SET_BRIGHT - ENDP - pop namespace -#line 12 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/over.asm" - ; Sets OVER flag in P_FLAG permanently -; Parameter: OVER flag in bit 0 of A register -#line 1 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" -#line 4 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" - push namespace core -COPY_ATTR: - ; Just copies current permanent attribs into temporal attribs - ; and sets print mode - PROC - LOCAL INVERSE1 - LOCAL __REFRESH_TMP - INVERSE1 EQU 02Fh - ld hl, (ATTR_P) - ld (ATTR_T), hl - ld hl, FLAGS2 - call __REFRESH_TMP - ld hl, P_FLAG - call __REFRESH_TMP -__SET_ATTR_MODE: ; Another entry to set print modes. A contains (P_FLAG) - LOCAL TABLE - LOCAL CONT2 - rra ; Over bit to carry - ld a, (FLAGS2) - rla ; Over bit in bit 1, Over2 bit in bit 2 - and 3 ; Only bit 0 and 1 (OVER flag) - ld c, a - ld b, 0 - ld hl, TABLE - add hl, bc - ld a, (hl) - ld (PRINT_MODE), a - ld hl, (P_FLAG) - xor a ; NOP -> INVERSE0 - bit 2, l - jr z, CONT2 - ld a, INVERSE1 ; CPL -> INVERSE1 -CONT2: - ld (INVERSE_MODE), a - ret -TABLE: - nop ; NORMAL MODE - xor (hl) ; OVER 1 MODE - and (hl) ; OVER 2 MODE - or (hl) ; OVER 3 MODE -#line 67 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" -__REFRESH_TMP: - ld a, (hl) - and 0b10101010 - ld c, a - rra - or c - ld (hl), a + srl (hl) + inc hl + srl (hl) + inc hl + inc hl + inc hl + sla (hl) + inc hl + sla (hl) + inc hl + sla (hl) + pop hl + ld de, MEM0 ret - ENDP - pop namespace -#line 4 "/zxbasic/src/arch/zx48k/library-asm/over.asm" - push namespace core -OVER: +#line 412 "/zxbasic/src/arch/zx48k/library-asm/print.asm" + LOCAL __SCROLL_SCR +#line 486 "/zxbasic/src/arch/zx48k/library-asm/print.asm" + __SCROLL_SCR EQU 0DFEh ; Use ROM SCROLL +#line 488 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 489 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +PRINT_COMMA: + call __LOAD_S_POSN + ld a, e + and 16 + add a, 16 +PRINT_TAB: + ; Tabulates the number of spaces in A register + ; If the current cursor position is already A, does nothing PROC - ld c, a ; saves it for later - and 2 - ld hl, FLAGS2 - res 1, (HL) - or (hl) - ld (hl), a - ld a, c ; Recovers previous value - and 1 ; # Convert to 0/1 - add a, a; # Shift left 1 bit for permanent - ld hl, P_FLAG - res 1, (hl) - or (hl) - ld (hl), a + LOCAL LOOP + call __LOAD_S_POSN ; e = current row + sub e + and 31 + ret z + ld b, a +LOOP: + ld a, ' ' + call __PRINTCHAR + djnz LOOP ret - ; Sets OVER flag in P_FLAG temporarily -OVER_TMP: - ld c, a ; saves it for later - and 2 ; gets bit 1; clears carry - rra - ld hl, FLAGS2 - res 0, (hl) - or (hl) - ld (hl), a - ld a, c ; Recovers previous value - and 1 - ld hl, P_FLAG - res 0, (hl) - or (hl) - ld (hl), a - jp __SET_ATTR_MODE ENDP - pop namespace -#line 13 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/inverse.asm" - ; Sets INVERSE flag in P_FLAG permanently -; Parameter: INVERSE flag in bit 0 of A register - push namespace core -INVERSE: - PROC - and 1 ; # Convert to 0/1 - add a, a; # Shift left 3 bits for permanent - add a, a - add a, a - ld hl, P_FLAG - res 3, (hl) - or (hl) - ld (hl), a - ret - ; Sets INVERSE flag in P_FLAG temporarily -INVERSE_TMP: - and 1 - add a, a - add a, a; # Shift left 2 bits for temporary - ld hl, P_FLAG - res 2, (hl) - or (hl) - ld (hl), a - jp __SET_ATTR_MODE +PRINT_AT: ; Changes cursor to ROW, COL + ; COL in A register + ; ROW in stack + pop hl ; Ret address + ex (sp), hl ; callee H = ROW + ld l, a + ex de, hl + call __IN_SCREEN + ret nc ; Return if out of screen + jp __SAVE_S_POSN + LOCAL __PRINT_COM + LOCAL __PRINT_AT1 + LOCAL __PRINT_AT2 + LOCAL __PRINT_BOLD + LOCAL __PRINT_ITA + LOCAL __PRINT_INK + LOCAL __PRINT_PAP + LOCAL __PRINT_SET_STATE + LOCAL __PRINT_TABLE + LOCAL __PRINT_TAB, __PRINT_TAB1, __PRINT_TAB2 + LOCAL __PRINT_ITA2 +#line 545 "/zxbasic/src/arch/zx48k/library-asm/print.asm" + LOCAL __PRINT_BOLD2 +#line 551 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +__PRINT_TABLE: ; Jump table for 0 .. 22 codes + DW __PRINT_NOP ; 0 + DW __PRINT_NOP ; 1 + DW __PRINT_NOP ; 2 + DW __PRINT_NOP ; 3 + DW __PRINT_NOP ; 4 + DW __PRINT_NOP ; 5 + DW __PRINT_COM ; 6 COMMA + DW __PRINT_NOP ; 7 + DW __PRINT_DEL ; 8 DEL + DW __PRINT_NOP ; 9 + DW __PRINT_NOP ; 10 + DW __PRINT_NOP ; 11 + DW __PRINT_NOP ; 12 + DW __PRINT_0Dh ; 13 + DW __PRINT_BOLD ; 14 + DW __PRINT_ITA ; 15 + DW __PRINT_INK ; 16 + DW __PRINT_PAP ; 17 + DW __PRINT_FLA ; 18 + DW __PRINT_BRI ; 19 + DW __PRINT_INV ; 20 + DW __PRINT_OVR ; 21 + DW __PRINT_AT ; 22 AT + DW __PRINT_TAB ; 23 TAB ENDP pop namespace -#line 14 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/bold.asm" - ; Sets BOLD flag in P_FLAG permanently -; Parameter: BOLD flag in bit 0 of A register +#line 3 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" +#line 4 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" push namespace core -BOLD: +COPY_ATTR: + ; Just copies current permanent attribs into temporal attribs + ; and sets print mode PROC - and 1 - rlca - rlca - rlca + LOCAL INVERSE1 + LOCAL __REFRESH_TMP + INVERSE1 EQU 02Fh + ld hl, (ATTR_P) + ld (ATTR_T), hl ld hl, FLAGS2 - res 3, (HL) - or (hl) - ld (hl), a + call __REFRESH_TMP + ld hl, P_FLAG + call __REFRESH_TMP +__SET_ATTR_MODE: ; Another entry to set print modes. A contains (P_FLAG) + LOCAL TABLE + LOCAL CONT2 + rra ; Over bit to carry + ld a, (FLAGS2) + rla ; Over bit in bit 1, Over2 bit in bit 2 + and 3 ; Only bit 0 and 1 (OVER flag) + ld c, a + ld b, 0 + ld hl, TABLE + add hl, bc + ld a, (hl) + ld (PRINT_MODE), a + ld hl, (P_FLAG) + xor a ; NOP -> INVERSE0 + bit 2, l + jr z, CONT2 + ld a, INVERSE1 ; CPL -> INVERSE1 +CONT2: + ld (INVERSE_MODE), a ret - ; Sets BOLD flag in P_FLAG temporarily -BOLD_TMP: - and 1 - rlca - rlca - ld hl, FLAGS2 - res 2, (hl) - or (hl) +TABLE: + nop ; NORMAL MODE + xor (hl) ; OVER 1 MODE + and (hl) ; OVER 2 MODE + or (hl) ; OVER 3 MODE +#line 67 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" +__REFRESH_TMP: + ld a, (hl) + and 0b10101010 + ld c, a + rra + or c ld (hl), a ret ENDP pop namespace -#line 15 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/italic.asm" - ; Sets ITALIC flag in P_FLAG permanently -; Parameter: ITALIC flag in bit 0 of A register +#line 112 "zx48k/read13.bas" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/f16tofreg.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/neg32.asm" push namespace core -ITALIC: - PROC - and 1 - rrca - rrca - rrca - ld hl, FLAGS2 - res 5, (HL) - or (hl) - ld (hl), a - ret - ; Sets ITALIC flag in P_FLAG temporarily -ITALIC_TMP: - and 1 - rrca - rrca - rrca - rrca - ld hl, FLAGS2 - res 4, (hl) - or (hl) - ld (hl), a +__ABS32: + bit 7, d + ret z +__NEG32: ; Negates DEHL (Two's complement) + ld a, l + cpl + ld l, a + ld a, h + cpl + ld h, a + ld a, e + cpl + ld e, a + ld a, d + cpl + ld d, a + inc l + ret nz + inc h + ret nz + inc de ret - ENDP pop namespace -#line 16 "/zxbasic/src/arch/zx48k/library-asm/print.asm" - ; Putting a comment starting with @INIT
- ; will make the compiler to add a CALL to
- ; It is useful for initialization routines. +#line 2 "/zxbasic/src/arch/zx48k/library-asm/f16tofreg.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/u32tofreg.asm" push namespace core -__PRINT_INIT: ; To be called before program starts (initializes library) - PROC - ld hl, __PRINT_START - ld (PRINT_JUMP_STATE), hl - ;; Clears ATTR2 flags (OVER 2, etc) - xor a - ld (FLAGS2), a - LOCAL SET_SCR_ADDR - call __LOAD_S_POSN - jp __SET_SCR_PTR - ;; Receives HL = future value of S_POSN - ;; Stores it at (S_POSN) and refresh screen pointers (ATTR, SCR) -SET_SCR_ADDR: - ld (S_POSN), hl - ex de, hl - ld hl, SCR_SIZE - or a - sbc hl, de - ex de, hl - dec e - jp __SET_SCR_PTR -__PRINTCHAR: ; Print character store in accumulator (A register) - ; Modifies H'L', B'C', A'F', D'E', A - LOCAL PO_GR_1 - LOCAL __PRCHAR - LOCAL __PRINT_JUMP - LOCAL __SRCADDR - LOCAL __PRINT_UDG - LOCAL __PRGRAPH - LOCAL __PRINT_START - PRINT_JUMP_STATE EQU __PRINT_JUMP + 2 -__PRINT_JUMP: - exx ; Switch to alternative registers - jp __PRINT_START ; Where to jump. If we print 22 (AT), next two calls jumps to AT1 and AT2 respectively -__PRINT_START: -__PRINT_CHR: - cp ' ' - jr c, __PRINT_SPECIAL ; Characters below ' ' are special ones - ex af, af' ; Saves a value (char to print) for later - ld hl, (S_POSN) - dec l - jr nz, 1f - ld l, SCR_COLS - 1 - dec h - jr nz, 2f - inc h - push hl - call __SCROLL_SCR - pop hl -#line 92 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -2: - call SET_SCR_ADDR - jr 4f -1: - ld (S_POSN), hl -4: - ex af, af' - cp 80h ; Is it a "normal" (printable) char - jr c, __SRCADDR - cp 90h ; Is it an UDG? - jr nc, __PRINT_UDG - ; Print an 8 bit pattern (80h to 8Fh) - ld b, a - call PO_GR_1 ; This ROM routine will generate the bit pattern at MEM0 - ld hl, MEM0 - jp __PRGRAPH - PO_GR_1 EQU 0B38h -__PRINT_UDG: - sub 90h ; Sub ASC code - ld bc, (UDG) - jr __PRGRAPH0 - __SOURCEADDR EQU (__SRCADDR + 1) ; Address of the pointer to chars source -__SRCADDR: - ld bc, (CHARS) -__PRGRAPH0: - add a, a ; A = a * 2 (since a < 80h) ; Thanks to Metalbrain at http://foro.speccy.org +__I8TOFREG: ld l, a - ld h, 0 ; HL = a * 2 (accumulator) - add hl, hl - add hl, hl ; HL = a * 8 - add hl, bc ; HL = CHARS address -__PRGRAPH: - ex de, hl ; HL = Write Address, DE = CHARS address - bit 2, (iy + $47) - call nz, __BOLD -#line 139 "/zxbasic/src/arch/zx48k/library-asm/print.asm" - bit 4, (iy + $47) - call nz, __ITALIC -#line 144 "/zxbasic/src/arch/zx48k/library-asm/print.asm" - ld hl, (DFCC) - push hl - ld b, 8 ; 8 bytes per char -__PRCHAR: - ld a, (de) ; DE *must* be source, and HL destiny -PRINT_MODE: ; Which operation is used to write on the screen - ; Set it with: - ; LD A, - ; LD (PRINT_MODE), A - ; - ; Available operations: - ; NORMAL : 0h --> NOP ; OVER 0 - ; XOR : AEh --> XOR (HL) ; OVER 1 - ; OR : B6h --> OR (HL) ; PUTSPRITE - ; AND : A6h --> AND (HL) ; PUTMASK - nop ; Set to one of the values above -INVERSE_MODE: ; 00 -> NOP -> INVERSE 0 - nop ; 2F -> CPL -> INVERSE 1 - ld (hl), a - inc de - inc h ; Next line - djnz __PRCHAR - pop hl - inc hl - ld (DFCC), hl - ld hl, (DFCCL) ; current ATTR Pos + rlca + sbc a, a ; A = SGN(A) + ld h, a + ld e, a + ld d, a +__I32TOFREG: ; Converts a 32bit signed integer (stored in DEHL) + ; to a Floating Point Number returned in (A ED CB) + ld a, d + or a ; Test sign + jp p, __U32TOFREG ; It was positive, proceed as 32bit unsigned + call __NEG32 ; Convert it to positive + call __U32TOFREG ; Convert it to Floating point + set 7, e ; Put the sign bit (negative) in the 31bit of mantissa + ret +__U8TOFREG: + ; Converts an unsigned 8 bit (A) to Floating point + ld l, a + ld h, 0 + ld e, h + ld d, h +__U32TOFREG: ; Converts an unsigned 32 bit integer (DEHL) + ; to a Floating point number returned in A ED CB + PROC + LOCAL __U32TOFREG_END + ld a, d + or e + or h + or l + ld b, d + ld c, e ; Returns 00 0000 0000 if ZERO + ret z + push de push hl - call __SET_ATTR - pop hl - inc hl - ld (DFCCL),hl exx - ret - ; ------------- SPECIAL CHARS (< 32) ----------------- -__PRINT_SPECIAL: ; Jumps here if it is a special char - ld hl, __PRINT_TABLE - jp JUMP_HL_PLUS_2A -PRINT_EOL: ; Called WHENEVER there is no ";" at end of PRINT sentence + pop de ; Loads integer into B'C' D'E' + pop bc exx -__PRINT_0Dh: ; Called WHEN printing CHR$(13) - ld hl, (S_POSN) - dec l - jr nz, 1f - dec h - jr nz, 1f - inc h - push hl - call __SCROLL_SCR - pop hl -#line 210 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -1: - ld l, 1 -__PRINT_EOL_END: - call SET_SCR_ADDR + ld l, 128 ; Exponent + ld bc, 0 ; DEBC = 0 + ld d, b + ld e, c +__U32TOFREG_LOOP: ; Also an entry point for __F16TOFREG exx - ret -__PRINT_COM: + ld a, d ; B'C'D'E' == 0 ? + or e + or b + or c + jp z, __U32TOFREG_END ; We are done + srl b ; Shift B'C' D'E' >> 1, output bit stays in Carry + rr c + rr d + rr e exx - push hl + rr e ; Shift EDCB >> 1, inserting the carry on the left + rr d + rr c + rr b + inc l ; Increment exponent + jp __U32TOFREG_LOOP +__U32TOFREG_END: + exx + ld a, l ; Puts the exponent in a + res 7, e ; Sets the sign bit to 0 (positive) + ret + ENDP + pop namespace +#line 3 "/zxbasic/src/arch/zx48k/library-asm/f16tofreg.asm" + push namespace core +__F16TOFREG: ; Converts a 16.16 signed fixed point (stored in DEHL) + ; to a Floating Point Number returned in (C ED CB) + PROC + LOCAL __F16TOFREG2 + ld a, d + or a ; Test sign + jp p, __F16TOFREG2 ; It was positive, proceed as 32bit unsigned + call __NEG32 ; Convert it to positive + call __F16TOFREG2 ; Convert it to Floating point + set 7, e ; Put the sign bit (negative) in the 31bit of mantissa + ret +__F16TOFREG2: ; Converts an unsigned 32 bit integer (DEHL) + ; to a Floating point number returned in C DE HL + ld a, d + or e + or h + or l + ld b, h + ld c, l + ret z ; Return 00 0000 0000 if 0 push de - push bc - call PRINT_COMMA + push hl + exx + pop de ; Loads integer into B'C' D'E' pop bc - pop de - pop hl + exx + ld l, 112 ; Exponent + ld bc, 0 ; DEBC = 0 + ld d, b + ld e, c + jp __U32TOFREG_LOOP ; Proceed as an integer + ENDP + pop namespace +#line 113 "zx48k/read13.bas" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/iload32.asm" + ; __FASTCALL__ routine which + ; loads a 32 bits integer into DE,HL + ; stored at position pointed by POINTER HL + ; DE,HL <-- (HL) + push namespace core +__ILOAD32: + ld e, (hl) + inc hl + ld d, (hl) + inc hl + ld a, (hl) + inc hl + ld h, (hl) + ld l, a + ex de, hl ret -__PRINT_TAB: - ld hl, __PRINT_TAB1 - jr __PRINT_SET_STATE -__PRINT_TAB1: - ld (MEM0), a - ld hl, __PRINT_TAB2 - jr __PRINT_SET_STATE -__PRINT_TAB2: - ld a, (MEM0) ; Load tab code (ignore the current one) - ld hl, __PRINT_START - ld (PRINT_JUMP_STATE), hl + pop namespace +#line 114 "zx48k/read13.bas" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/mulf.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/stackf.asm" + ; ------------------------------------------------------------- + ; Functions to manage FP-Stack of the ZX Spectrum ROM CALC + ; ------------------------------------------------------------- + push namespace core + __FPSTACK_PUSH EQU 2AB6h ; Stores an FP number into the ROM FP stack (A, ED CB) + __FPSTACK_POP EQU 2BF1h ; Pops an FP number out of the ROM FP stack (A, ED CB) +__FPSTACK_PUSH2: ; Pushes Current A ED CB registers and top of the stack on (SP + 4) + ; Second argument to push into the stack calculator is popped out of the stack + ; Since the caller routine also receives the parameters into the top of the stack + ; four bytes must be removed from SP before pop them out + call __FPSTACK_PUSH ; Pushes A ED CB into the FP-STACK exx - push hl - push bc - push de - call PRINT_TAB + pop hl ; Caller-Caller return addr + exx + pop hl ; Caller return addr + pop af pop de pop bc - pop hl - ret -__PRINT_AT: - ld hl, __PRINT_AT1 - jr __PRINT_SET_STATE -__PRINT_NOP: -__PRINT_RESTART: - ld hl, __PRINT_START -__PRINT_SET_STATE: - ld (PRINT_JUMP_STATE), hl ; Saves next entry call + push hl ; Caller return addr exx - ret -__PRINT_AT1: ; Jumps here if waiting for 1st parameter - ld hl, (S_POSN) - ld h, a - ld a, SCR_ROWS - sub h - ld (S_POSN + 1), a - ld hl, __PRINT_AT2 - jr __PRINT_SET_STATE -__PRINT_AT2: - call __LOAD_S_POSN - ld e, a - call __SAVE_S_POSN - jr __PRINT_RESTART -__PRINT_DEL: - call __LOAD_S_POSN ; Gets current screen position - dec e - ld a, -1 - cp e - jr nz, 3f - ld e, SCR_COLS - 2 - dec d - cp d - jr nz, 3f - ld d, SCR_ROWS - 1 -3: - call __SAVE_S_POSN + push hl ; Caller-Caller return addr exx - ret -__PRINT_INK: - ld hl, __PRINT_INK2 - jr __PRINT_SET_STATE -__PRINT_INK2: - call INK_TMP - jr __PRINT_RESTART -__PRINT_PAP: - ld hl, __PRINT_PAP2 - jr __PRINT_SET_STATE -__PRINT_PAP2: - call PAPER_TMP - jr __PRINT_RESTART -__PRINT_FLA: - ld hl, __PRINT_FLA2 - jr __PRINT_SET_STATE -__PRINT_FLA2: - call FLASH_TMP - jr __PRINT_RESTART -__PRINT_BRI: - ld hl, __PRINT_BRI2 - jr __PRINT_SET_STATE -__PRINT_BRI2: - call BRIGHT_TMP - jr __PRINT_RESTART -__PRINT_INV: - ld hl, __PRINT_INV2 - jr __PRINT_SET_STATE -__PRINT_INV2: - call INVERSE_TMP - jr __PRINT_RESTART -__PRINT_OVR: - ld hl, __PRINT_OVR2 - jr __PRINT_SET_STATE -__PRINT_OVR2: - call OVER_TMP - jr __PRINT_RESTART -__PRINT_BOLD: - ld hl, __PRINT_BOLD2 - jp __PRINT_SET_STATE -__PRINT_BOLD2: - call BOLD_TMP - jp __PRINT_RESTART -#line 354 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -__PRINT_ITA: - ld hl, __PRINT_ITA2 - jp __PRINT_SET_STATE -__PRINT_ITA2: - call ITALIC_TMP - jp __PRINT_RESTART -#line 364 "/zxbasic/src/arch/zx48k/library-asm/print.asm" - LOCAL __BOLD -__BOLD: + jp __FPSTACK_PUSH +__FPSTACK_I16: ; Pushes 16 bits integer in HL into the FP ROM STACK + ; This format is specified in the ZX 48K Manual + ; You can push a 16 bit signed integer as + ; 0 SS LL HH 0, being SS the sign and LL HH the low + ; and High byte respectively + ld a, h + rla ; sign to Carry + sbc a, a ; 0 if positive, FF if negative + ld e, a + ld d, l + ld c, h + xor a + ld b, a + jp __FPSTACK_PUSH + pop namespace +#line 2 "/zxbasic/src/arch/zx48k/library-asm/mulf.asm" + ; ------------------------------------------------------------- + ; Floating point library using the FP ROM Calculator (ZX 48K) + ; All of them uses A EDCB registers as 1st paramter. + ; For binary operators, the 2n operator must be pushed into the + ; stack, in the order A DE BC. + ; + ; Uses CALLEE convention + ; ------------------------------------------------------------- + push namespace core +__MULF: ; Multiplication + call __FPSTACK_PUSH2 + ; ------------- ROM MUL + rst 28h + defb 04h ; + defb 38h; ; END CALC + jp __FPSTACK_POP + pop namespace +#line 115 "zx48k/read13.bas" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/mulf16.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/_mul32.asm" +; Ripped from: http://www.andreadrian.de/oldcpu/z80_number_cruncher.html#moztocid784223 + ; Used with permission. + ; Multiplies 32x32 bit integer (DEHL x D'E'H'L') + ; 64bit result is returned in H'L'H L B'C'A C + push namespace core +__MUL32_64START: push hl - ld hl, MEM0 - ld b, 8 -1: - ld a, (de) - ld c, a - rlca - or c - ld (hl), a - inc hl - inc de - djnz 1b - pop hl - ld de, MEM0 - ret -#line 385 "/zxbasic/src/arch/zx48k/library-asm/print.asm" - LOCAL __ITALIC -__ITALIC: + exx + ld b, h + ld c, l ; BC = Low Part (A) + pop hl ; HL = Load Part (B) + ex de, hl ; DE = Low Part (B), HL = HightPart(A) (must be in B'C') push hl - ld hl, MEM0 - ex de, hl - ld bc, 8 - ldir - ld hl, MEM0 - srl (hl) - inc hl - srl (hl) - inc hl - srl (hl) - inc hl - inc hl - inc hl - sla (hl) - inc hl - sla (hl) - inc hl - sla (hl) - pop hl - ld de, MEM0 + exx + pop bc ; B'C' = HightPart(A) + exx ; A = B'C'BC , B = D'E'DE + ; multiply routine 32 * 32bit = 64bit + ; h'l'hlb'c'ac = b'c'bc * d'e'de + ; needs register a, changes flags + ; + ; this routine was with tiny differences in the + ; sinclair zx81 rom for the mantissa multiply +__LMUL: + xor a ; reset carry flag + ld h, a ; result bits 32..47 = 0 + ld l, a + exx + ld h, a ; result bits 48..63 = 0 + ld l, a + exx + ld a,b ; mpr is b'c'ac + ld b,33 ; initialize loop counter + jp __LMULSTART +__LMULLOOP: + jr nc,__LMULNOADD ; JP is 2 cycles faster than JR. Since it's inside a LOOP + ; it can save up to 33 * 2 = 66 cycles + ; But JR if 3 cycles faster if JUMP not taken! + add hl,de ; result += mpd + exx + adc hl,de + exx +__LMULNOADD: + exx + rr h ; right shift upper + rr l ; 32bit of result + exx + rr h + rr l +__LMULSTART: + exx + rr b ; right shift mpr/ + rr c ; lower 32bit of result + exx + rra ; equivalent to rr a + rr c + djnz __LMULLOOP + ret ; result in h'l'hlb'c'ac + pop namespace +#line 3 "/zxbasic/src/arch/zx48k/library-asm/mulf16.asm" + push namespace core +__MULF16: ; + ld a, d ; load sgn into a + ex af, af' ; saves it + call __ABS32 ; convert to positive + exx + pop hl ; Return address + pop de ; Low part + ex (sp), hl ; CALLEE caller convention; Now HL = Hight part, (SP) = Return address + ex de, hl ; D'E' = High part (B), H'L' = Low part (B) (must be in DE) + ex af, af' + xor d ; A register contains resulting sgn + ex af, af' + call __ABS32 ; convert to positive + call __MUL32_64START + ; rounding (was not included in zx81) +__ROUND_FIX: ; rounds a 64bit (32.32) fixed point number to 16.16 + ; result returned in dehl + ; input in h'l'hlb'c'ac + sla a ; result bit 47 to carry + exx + ld hl,0 ; ld does not change carry + adc hl,bc ; hl = hl + 0 + carry + push hl + exx + ld bc,0 + adc hl,bc ; hl = hl + 0 + carry + ex de, hl + pop hl ; rounded result in de.hl + ex af, af' ; recovers result sign + or a + jp m, __NEG32 ; if negative, negates it ret -#line 413 "/zxbasic/src/arch/zx48k/library-asm/print.asm" - LOCAL __SCROLL_SCR -#line 487 "/zxbasic/src/arch/zx48k/library-asm/print.asm" - __SCROLL_SCR EQU 0DFEh ; Use ROM SCROLL -#line 489 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -#line 490 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -PRINT_COMMA: - call __LOAD_S_POSN - ld a, e - and 16 - add a, 16 -PRINT_TAB: - ; Tabulates the number of spaces in A register - ; If the current cursor position is already A, does nothing + pop namespace +#line 116 "zx48k/read13.bas" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/pow.asm" + ; ------------------------------------------------------------- + ; Floating point library using the FP ROM Calculator (ZX 48K) + ; All of them uses A EDCB registers as 1st paramter. + ; For binary operators, the 2n operator must be pushed into the + ; stack, in the order A DE BC. + ; + ; Uses CALLEE convention + ; +; Operands comes swapped: + ; 1 st parameter is the BASE (A ED CB) + ; 2 nd parameter (Top of the stack) is Exponent + ; ------------------------------------------------------------- + push namespace core +__POW: ; Exponentiation PROC - LOCAL LOOP - call __LOAD_S_POSN ; e = current row - sub e - and 31 - ret z - ld b, a -LOOP: - ld a, ' ' - call __PRINTCHAR - djnz LOOP - ret - ENDP -PRINT_AT: ; Changes cursor to ROW, COL - ; COL in A register - ; ROW in stack - pop hl ; Ret address - ex (sp), hl ; callee H = ROW - ld l, a - ex de, hl - call __IN_SCREEN - ret nc ; Return if out of screen - jp __SAVE_S_POSN - LOCAL __PRINT_COM - LOCAL __PRINT_AT1 - LOCAL __PRINT_AT2 - LOCAL __PRINT_BOLD - LOCAL __PRINT_ITA - LOCAL __PRINT_INK - LOCAL __PRINT_PAP - LOCAL __PRINT_SET_STATE - LOCAL __PRINT_TABLE - LOCAL __PRINT_TAB, __PRINT_TAB1, __PRINT_TAB2 - LOCAL __PRINT_ITA2 -#line 546 "/zxbasic/src/arch/zx48k/library-asm/print.asm" - LOCAL __PRINT_BOLD2 -#line 552 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -__PRINT_TABLE: ; Jump table for 0 .. 22 codes - DW __PRINT_NOP ; 0 - DW __PRINT_NOP ; 1 - DW __PRINT_NOP ; 2 - DW __PRINT_NOP ; 3 - DW __PRINT_NOP ; 4 - DW __PRINT_NOP ; 5 - DW __PRINT_COM ; 6 COMMA - DW __PRINT_NOP ; 7 - DW __PRINT_DEL ; 8 DEL - DW __PRINT_NOP ; 9 - DW __PRINT_NOP ; 10 - DW __PRINT_NOP ; 11 - DW __PRINT_NOP ; 12 - DW __PRINT_0Dh ; 13 - DW __PRINT_BOLD ; 14 - DW __PRINT_ITA ; 15 - DW __PRINT_INK ; 16 - DW __PRINT_PAP ; 17 - DW __PRINT_FLA ; 18 - DW __PRINT_BRI ; 19 - DW __PRINT_INV ; 20 - DW __PRINT_OVR ; 21 - DW __PRINT_AT ; 22 AT - DW __PRINT_TAB ; 23 TAB + call __FPSTACK_PUSH2 + ; ------------- ROM POW + rst 28h + defb 01h ; Exchange => 1, Base + defb 06h ; POW + defb 38h; ; END CALC + jp __FPSTACK_POP ENDP pop namespace -#line 116 "zx48k/read13.bas" +#line 117 "zx48k/read13.bas" #line 1 "/zxbasic/src/arch/zx48k/library-asm/printf16.asm" #line 1 "/zxbasic/src/arch/zx48k/library-asm/printnum.asm" push namespace core @@ -1735,7 +1735,7 @@ __PRINT_FIX_LOOP: jp __PRINT_FIX_LOOP ENDP pop namespace -#line 117 "zx48k/read13.bas" +#line 119 "zx48k/read13.bas" #line 1 "/zxbasic/src/arch/zx48k/library-asm/read_restore.asm" ;; This implements READ & RESTORE functions ;; Reads a new element from the DATA Address code @@ -2638,7 +2638,7 @@ __DATA_ADDR: ;; Stores current DATA ptr dw .DATA.__DATA__0 ENDP pop namespace -#line 118 "zx48k/read13.bas" +#line 120 "zx48k/read13.bas" #line 1 "/zxbasic/src/arch/zx48k/library-asm/sin.asm" push namespace core SIN: ; Computes SIN using ROM FP-CALC @@ -2648,7 +2648,7 @@ SIN: ; Computes SIN using ROM FP-CALC defb 38h ; END CALC jp __FPSTACK_POP pop namespace -#line 119 "zx48k/read13.bas" +#line 121 "zx48k/read13.bas" #line 1 "/zxbasic/src/arch/zx48k/library-asm/store32.asm" push namespace core __PISTORE32: @@ -2672,7 +2672,7 @@ __STORE32: ; Stores the given integer in DEBC at address HL ld (hl), d ret pop namespace -#line 120 "zx48k/read13.bas" +#line 122 "zx48k/read13.bas" #line 1 "/zxbasic/src/arch/zx48k/library-asm/tan.asm" push namespace core TAN: ; Computes TAN using ROM FP-CALC @@ -2682,5 +2682,5 @@ TAN: ; Computes TAN using ROM FP-CALC defb 38h ; END CALC jp __FPSTACK_POP pop namespace -#line 121 "zx48k/read13.bas" +#line 123 "zx48k/read13.bas" END diff --git a/tests/functional/zx48k/read5.asm b/tests/functional/zx48k/read5.asm index 2989bbcde..6ca965231 100644 --- a/tests/functional/zx48k/read5.asm +++ b/tests/functional/zx48k/read5.asm @@ -52,6 +52,7 @@ _i: call .core.__READ ld hl, _d call .core.__STOREF + call .core.COPY_ATTR ld a, (_c) ld de, (_c + 1) ld bc, (_c + 3) @@ -145,91 +146,7 @@ ___DATA__FUNCPTR__2__leave: __DATA__END: DEFB 00h ;; --- end of user code --- -#line 1 "/zxbasic/src/arch/zx48k/library-asm/mulf.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/stackf.asm" - ; ------------------------------------------------------------- - ; Functions to manage FP-Stack of the ZX Spectrum ROM CALC - ; ------------------------------------------------------------- - push namespace core - __FPSTACK_PUSH EQU 2AB6h ; Stores an FP number into the ROM FP stack (A, ED CB) - __FPSTACK_POP EQU 2BF1h ; Pops an FP number out of the ROM FP stack (A, ED CB) -__FPSTACK_PUSH2: ; Pushes Current A ED CB registers and top of the stack on (SP + 4) - ; Second argument to push into the stack calculator is popped out of the stack - ; Since the caller routine also receives the parameters into the top of the stack - ; four bytes must be removed from SP before pop them out - call __FPSTACK_PUSH ; Pushes A ED CB into the FP-STACK - exx - pop hl ; Caller-Caller return addr - exx - pop hl ; Caller return addr - pop af - pop de - pop bc - push hl ; Caller return addr - exx - push hl ; Caller-Caller return addr - exx - jp __FPSTACK_PUSH -__FPSTACK_I16: ; Pushes 16 bits integer in HL into the FP ROM STACK - ; This format is specified in the ZX 48K Manual - ; You can push a 16 bit signed integer as - ; 0 SS LL HH 0, being SS the sign and LL HH the low - ; and High byte respectively - ld a, h - rla ; sign to Carry - sbc a, a ; 0 if positive, FF if negative - ld e, a - ld d, l - ld c, h - xor a - ld b, a - jp __FPSTACK_PUSH - pop namespace -#line 2 "/zxbasic/src/arch/zx48k/library-asm/mulf.asm" - ; ------------------------------------------------------------- - ; Floating point library using the FP ROM Calculator (ZX 48K) - ; All of them uses A EDCB registers as 1st paramter. - ; For binary operators, the 2n operator must be pushed into the - ; stack, in the order A DE BC. - ; - ; Uses CALLEE convention - ; ------------------------------------------------------------- - push namespace core -__MULF: ; Multiplication - call __FPSTACK_PUSH2 - ; ------------- ROM MUL - rst 28h - defb 04h ; - defb 38h; ; END CALC - jp __FPSTACK_POP - pop namespace -#line 109 "zx48k/read5.bas" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/pow.asm" - ; ------------------------------------------------------------- - ; Floating point library using the FP ROM Calculator (ZX 48K) - ; All of them uses A EDCB registers as 1st paramter. - ; For binary operators, the 2n operator must be pushed into the - ; stack, in the order A DE BC. - ; - ; Uses CALLEE convention - ; -; Operands comes swapped: - ; 1 st parameter is the BASE (A ED CB) - ; 2 nd parameter (Top of the stack) is Exponent - ; ------------------------------------------------------------- - push namespace core -__POW: ; Exponentiation - PROC - call __FPSTACK_PUSH2 - ; ------------- ROM POW - rst 28h - defb 01h ; Exchange => 1, Base - defb 06h ; POW - defb 38h; ; END CALC - jp __FPSTACK_POP - ENDP - pop namespace -#line 110 "zx48k/read5.bas" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" #line 1 "/zxbasic/src/arch/zx48k/library-asm/print.asm" ; vim:ts=4:sw=4:et: ; PRINT command routine @@ -579,60 +496,6 @@ BRIGHT_TMP: #line 1 "/zxbasic/src/arch/zx48k/library-asm/over.asm" ; Sets OVER flag in P_FLAG permanently ; Parameter: OVER flag in bit 0 of A register -#line 1 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" -#line 4 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" - push namespace core -COPY_ATTR: - ; Just copies current permanent attribs into temporal attribs - ; and sets print mode - PROC - LOCAL INVERSE1 - LOCAL __REFRESH_TMP - INVERSE1 EQU 02Fh - ld hl, (ATTR_P) - ld (ATTR_T), hl - ld hl, FLAGS2 - call __REFRESH_TMP - ld hl, P_FLAG - call __REFRESH_TMP -__SET_ATTR_MODE: ; Another entry to set print modes. A contains (P_FLAG) - LOCAL TABLE - LOCAL CONT2 - rra ; Over bit to carry - ld a, (FLAGS2) - rla ; Over bit in bit 1, Over2 bit in bit 2 - and 3 ; Only bit 0 and 1 (OVER flag) - ld c, a - ld b, 0 - ld hl, TABLE - add hl, bc - ld a, (hl) - ld (PRINT_MODE), a - ld hl, (P_FLAG) - xor a ; NOP -> INVERSE0 - bit 2, l - jr z, CONT2 - ld a, INVERSE1 ; CPL -> INVERSE1 -CONT2: - ld (INVERSE_MODE), a - ret -TABLE: - nop ; NORMAL MODE - xor (hl) ; OVER 1 MODE - and (hl) ; OVER 2 MODE - or (hl) ; OVER 3 MODE -#line 67 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" -__REFRESH_TMP: - ld a, (hl) - and 0b10101010 - ld c, a - rra - or c - ld (hl), a - ret - ENDP - pop namespace -#line 4 "/zxbasic/src/arch/zx48k/library-asm/over.asm" push namespace core OVER: PROC @@ -874,11 +737,10 @@ INVERSE_MODE: ; 00 -> NOP -> INVERSE 0 inc hl ld (DFCC), hl ld hl, (DFCCL) ; current ATTR Pos - push hl - call __SET_ATTR - pop hl inc hl - ld (DFCCL),hl + ld (DFCCL), hl + dec hl + call __SET_ATTR exx ret ; ------------- SPECIAL CHARS (< 32) ----------------- @@ -897,7 +759,7 @@ __PRINT_0Dh: ; Called WHEN printing CHR$(13) push hl call __SCROLL_SCR pop hl -#line 210 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 209 "/zxbasic/src/arch/zx48k/library-asm/print.asm" 1: ld l, 1 __PRINT_EOL_END: @@ -1014,14 +876,14 @@ __PRINT_BOLD: __PRINT_BOLD2: call BOLD_TMP jp __PRINT_RESTART -#line 354 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 353 "/zxbasic/src/arch/zx48k/library-asm/print.asm" __PRINT_ITA: ld hl, __PRINT_ITA2 jp __PRINT_SET_STATE __PRINT_ITA2: call ITALIC_TMP jp __PRINT_RESTART -#line 364 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 363 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __BOLD __BOLD: push hl @@ -1039,7 +901,7 @@ __BOLD: pop hl ld de, MEM0 ret -#line 385 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 384 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __ITALIC __ITALIC: push hl @@ -1064,12 +926,12 @@ __ITALIC: pop hl ld de, MEM0 ret -#line 413 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 412 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __SCROLL_SCR -#line 487 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 486 "/zxbasic/src/arch/zx48k/library-asm/print.asm" __SCROLL_SCR EQU 0DFEh ; Use ROM SCROLL +#line 488 "/zxbasic/src/arch/zx48k/library-asm/print.asm" #line 489 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -#line 490 "/zxbasic/src/arch/zx48k/library-asm/print.asm" PRINT_COMMA: call __LOAD_S_POSN ld a, e @@ -1112,9 +974,9 @@ PRINT_AT: ; Changes cursor to ROW, COL LOCAL __PRINT_TABLE LOCAL __PRINT_TAB, __PRINT_TAB1, __PRINT_TAB2 LOCAL __PRINT_ITA2 -#line 546 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 545 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __PRINT_BOLD2 -#line 552 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 551 "/zxbasic/src/arch/zx48k/library-asm/print.asm" __PRINT_TABLE: ; Jump table for 0 .. 22 codes DW __PRINT_NOP ; 0 DW __PRINT_NOP ; 1 @@ -1142,7 +1004,145 @@ __PRINT_TABLE: ; Jump table for 0 .. 22 codes DW __PRINT_TAB ; 23 TAB ENDP pop namespace +#line 3 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" +#line 4 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" + push namespace core +COPY_ATTR: + ; Just copies current permanent attribs into temporal attribs + ; and sets print mode + PROC + LOCAL INVERSE1 + LOCAL __REFRESH_TMP + INVERSE1 EQU 02Fh + ld hl, (ATTR_P) + ld (ATTR_T), hl + ld hl, FLAGS2 + call __REFRESH_TMP + ld hl, P_FLAG + call __REFRESH_TMP +__SET_ATTR_MODE: ; Another entry to set print modes. A contains (P_FLAG) + LOCAL TABLE + LOCAL CONT2 + rra ; Over bit to carry + ld a, (FLAGS2) + rla ; Over bit in bit 1, Over2 bit in bit 2 + and 3 ; Only bit 0 and 1 (OVER flag) + ld c, a + ld b, 0 + ld hl, TABLE + add hl, bc + ld a, (hl) + ld (PRINT_MODE), a + ld hl, (P_FLAG) + xor a ; NOP -> INVERSE0 + bit 2, l + jr z, CONT2 + ld a, INVERSE1 ; CPL -> INVERSE1 +CONT2: + ld (INVERSE_MODE), a + ret +TABLE: + nop ; NORMAL MODE + xor (hl) ; OVER 1 MODE + and (hl) ; OVER 2 MODE + or (hl) ; OVER 3 MODE +#line 67 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" +__REFRESH_TMP: + ld a, (hl) + and 0b10101010 + ld c, a + rra + or c + ld (hl), a + ret + ENDP + pop namespace +#line 110 "zx48k/read5.bas" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/mulf.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/stackf.asm" + ; ------------------------------------------------------------- + ; Functions to manage FP-Stack of the ZX Spectrum ROM CALC + ; ------------------------------------------------------------- + push namespace core + __FPSTACK_PUSH EQU 2AB6h ; Stores an FP number into the ROM FP stack (A, ED CB) + __FPSTACK_POP EQU 2BF1h ; Pops an FP number out of the ROM FP stack (A, ED CB) +__FPSTACK_PUSH2: ; Pushes Current A ED CB registers and top of the stack on (SP + 4) + ; Second argument to push into the stack calculator is popped out of the stack + ; Since the caller routine also receives the parameters into the top of the stack + ; four bytes must be removed from SP before pop them out + call __FPSTACK_PUSH ; Pushes A ED CB into the FP-STACK + exx + pop hl ; Caller-Caller return addr + exx + pop hl ; Caller return addr + pop af + pop de + pop bc + push hl ; Caller return addr + exx + push hl ; Caller-Caller return addr + exx + jp __FPSTACK_PUSH +__FPSTACK_I16: ; Pushes 16 bits integer in HL into the FP ROM STACK + ; This format is specified in the ZX 48K Manual + ; You can push a 16 bit signed integer as + ; 0 SS LL HH 0, being SS the sign and LL HH the low + ; and High byte respectively + ld a, h + rla ; sign to Carry + sbc a, a ; 0 if positive, FF if negative + ld e, a + ld d, l + ld c, h + xor a + ld b, a + jp __FPSTACK_PUSH + pop namespace +#line 2 "/zxbasic/src/arch/zx48k/library-asm/mulf.asm" + ; ------------------------------------------------------------- + ; Floating point library using the FP ROM Calculator (ZX 48K) + ; All of them uses A EDCB registers as 1st paramter. + ; For binary operators, the 2n operator must be pushed into the + ; stack, in the order A DE BC. + ; + ; Uses CALLEE convention + ; ------------------------------------------------------------- + push namespace core +__MULF: ; Multiplication + call __FPSTACK_PUSH2 + ; ------------- ROM MUL + rst 28h + defb 04h ; + defb 38h; ; END CALC + jp __FPSTACK_POP + pop namespace #line 111 "zx48k/read5.bas" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/pow.asm" + ; ------------------------------------------------------------- + ; Floating point library using the FP ROM Calculator (ZX 48K) + ; All of them uses A EDCB registers as 1st paramter. + ; For binary operators, the 2n operator must be pushed into the + ; stack, in the order A DE BC. + ; + ; Uses CALLEE convention + ; +; Operands comes swapped: + ; 1 st parameter is the BASE (A ED CB) + ; 2 nd parameter (Top of the stack) is Exponent + ; ------------------------------------------------------------- + push namespace core +__POW: ; Exponentiation + PROC + call __FPSTACK_PUSH2 + ; ------------- ROM POW + rst 28h + defb 01h ; Exchange => 1, Base + defb 06h ; POW + defb 38h; ; END CALC + jp __FPSTACK_POP + ENDP + pop namespace +#line 112 "zx48k/read5.bas" #line 1 "/zxbasic/src/arch/zx48k/library-asm/printf.asm" #line 1 "/zxbasic/src/arch/zx48k/library-asm/printstr.asm" #line 1 "/zxbasic/src/arch/zx48k/library-asm/free.asm" @@ -1484,7 +1484,7 @@ __PRINTF: ; Prints a Fixed point Number stored in C ED LH RECLAIM2 EQU 19E8h ENDP pop namespace -#line 112 "zx48k/read5.bas" +#line 114 "zx48k/read5.bas" #line 1 "/zxbasic/src/arch/zx48k/library-asm/read_restore.asm" ;; This implements READ & RESTORE functions ;; Reads a new element from the DATA Address code @@ -2272,7 +2272,7 @@ __DATA_ADDR: ;; Stores current DATA ptr dw .DATA.__DATA__0 ENDP pop namespace -#line 113 "zx48k/read5.bas" +#line 115 "zx48k/read5.bas" #line 1 "/zxbasic/src/arch/zx48k/library-asm/sin.asm" push namespace core SIN: ; Computes SIN using ROM FP-CALC @@ -2282,7 +2282,7 @@ SIN: ; Computes SIN using ROM FP-CALC defb 38h ; END CALC jp __FPSTACK_POP pop namespace -#line 114 "zx48k/read5.bas" +#line 116 "zx48k/read5.bas" #line 1 "/zxbasic/src/arch/zx48k/library-asm/storef.asm" push namespace core __PISTOREF: ; Indect Stores a float (A, E, D, C, B) at location stored in memory, pointed by (IX + HL) @@ -2311,7 +2311,7 @@ __STOREF: ; Stores the given FP number in A EDCB at address HL ld (hl), b ret pop namespace -#line 115 "zx48k/read5.bas" +#line 117 "zx48k/read5.bas" #line 1 "/zxbasic/src/arch/zx48k/library-asm/tan.asm" push namespace core TAN: ; Computes TAN using ROM FP-CALC @@ -2321,5 +2321,5 @@ TAN: ; Computes TAN using ROM FP-CALC defb 38h ; END CALC jp __FPSTACK_POP pop namespace -#line 116 "zx48k/read5.bas" +#line 118 "zx48k/read5.bas" END diff --git a/tests/functional/zx48k/read8.asm b/tests/functional/zx48k/read8.asm index 8bb2555c2..4a4cddd73 100644 --- a/tests/functional/zx48k/read8.asm +++ b/tests/functional/zx48k/read8.asm @@ -72,6 +72,7 @@ _c.__DATA__: call .core.__READ ld hl, _c + 5 call .core.__STOREF + call .core.COPY_ATTR ld a, (_c.__DATA__ + 5) ld de, (_c.__DATA__ + 5 + 1) ld bc, (_c.__DATA__ + 5 + 3) @@ -160,91 +161,7 @@ ___DATA__FUNCPTR__2__leave: __DATA__END: DEFB 00h ;; --- end of user code --- -#line 1 "/zxbasic/src/arch/zx48k/library-asm/mulf.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/stackf.asm" - ; ------------------------------------------------------------- - ; Functions to manage FP-Stack of the ZX Spectrum ROM CALC - ; ------------------------------------------------------------- - push namespace core - __FPSTACK_PUSH EQU 2AB6h ; Stores an FP number into the ROM FP stack (A, ED CB) - __FPSTACK_POP EQU 2BF1h ; Pops an FP number out of the ROM FP stack (A, ED CB) -__FPSTACK_PUSH2: ; Pushes Current A ED CB registers and top of the stack on (SP + 4) - ; Second argument to push into the stack calculator is popped out of the stack - ; Since the caller routine also receives the parameters into the top of the stack - ; four bytes must be removed from SP before pop them out - call __FPSTACK_PUSH ; Pushes A ED CB into the FP-STACK - exx - pop hl ; Caller-Caller return addr - exx - pop hl ; Caller return addr - pop af - pop de - pop bc - push hl ; Caller return addr - exx - push hl ; Caller-Caller return addr - exx - jp __FPSTACK_PUSH -__FPSTACK_I16: ; Pushes 16 bits integer in HL into the FP ROM STACK - ; This format is specified in the ZX 48K Manual - ; You can push a 16 bit signed integer as - ; 0 SS LL HH 0, being SS the sign and LL HH the low - ; and High byte respectively - ld a, h - rla ; sign to Carry - sbc a, a ; 0 if positive, FF if negative - ld e, a - ld d, l - ld c, h - xor a - ld b, a - jp __FPSTACK_PUSH - pop namespace -#line 2 "/zxbasic/src/arch/zx48k/library-asm/mulf.asm" - ; ------------------------------------------------------------- - ; Floating point library using the FP ROM Calculator (ZX 48K) - ; All of them uses A EDCB registers as 1st paramter. - ; For binary operators, the 2n operator must be pushed into the - ; stack, in the order A DE BC. - ; - ; Uses CALLEE convention - ; ------------------------------------------------------------- - push namespace core -__MULF: ; Multiplication - call __FPSTACK_PUSH2 - ; ------------- ROM MUL - rst 28h - defb 04h ; - defb 38h; ; END CALC - jp __FPSTACK_POP - pop namespace -#line 100 "zx48k/read8.bas" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/pow.asm" - ; ------------------------------------------------------------- - ; Floating point library using the FP ROM Calculator (ZX 48K) - ; All of them uses A EDCB registers as 1st paramter. - ; For binary operators, the 2n operator must be pushed into the - ; stack, in the order A DE BC. - ; - ; Uses CALLEE convention - ; -; Operands comes swapped: - ; 1 st parameter is the BASE (A ED CB) - ; 2 nd parameter (Top of the stack) is Exponent - ; ------------------------------------------------------------- - push namespace core -__POW: ; Exponentiation - PROC - call __FPSTACK_PUSH2 - ; ------------- ROM POW - rst 28h - defb 01h ; Exchange => 1, Base - defb 06h ; POW - defb 38h; ; END CALC - jp __FPSTACK_POP - ENDP - pop namespace -#line 101 "zx48k/read8.bas" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" #line 1 "/zxbasic/src/arch/zx48k/library-asm/print.asm" ; vim:ts=4:sw=4:et: ; PRINT command routine @@ -594,60 +511,6 @@ BRIGHT_TMP: #line 1 "/zxbasic/src/arch/zx48k/library-asm/over.asm" ; Sets OVER flag in P_FLAG permanently ; Parameter: OVER flag in bit 0 of A register -#line 1 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" -#line 4 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" - push namespace core -COPY_ATTR: - ; Just copies current permanent attribs into temporal attribs - ; and sets print mode - PROC - LOCAL INVERSE1 - LOCAL __REFRESH_TMP - INVERSE1 EQU 02Fh - ld hl, (ATTR_P) - ld (ATTR_T), hl - ld hl, FLAGS2 - call __REFRESH_TMP - ld hl, P_FLAG - call __REFRESH_TMP -__SET_ATTR_MODE: ; Another entry to set print modes. A contains (P_FLAG) - LOCAL TABLE - LOCAL CONT2 - rra ; Over bit to carry - ld a, (FLAGS2) - rla ; Over bit in bit 1, Over2 bit in bit 2 - and 3 ; Only bit 0 and 1 (OVER flag) - ld c, a - ld b, 0 - ld hl, TABLE - add hl, bc - ld a, (hl) - ld (PRINT_MODE), a - ld hl, (P_FLAG) - xor a ; NOP -> INVERSE0 - bit 2, l - jr z, CONT2 - ld a, INVERSE1 ; CPL -> INVERSE1 -CONT2: - ld (INVERSE_MODE), a - ret -TABLE: - nop ; NORMAL MODE - xor (hl) ; OVER 1 MODE - and (hl) ; OVER 2 MODE - or (hl) ; OVER 3 MODE -#line 67 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" -__REFRESH_TMP: - ld a, (hl) - and 0b10101010 - ld c, a - rra - or c - ld (hl), a - ret - ENDP - pop namespace -#line 4 "/zxbasic/src/arch/zx48k/library-asm/over.asm" push namespace core OVER: PROC @@ -889,11 +752,10 @@ INVERSE_MODE: ; 00 -> NOP -> INVERSE 0 inc hl ld (DFCC), hl ld hl, (DFCCL) ; current ATTR Pos - push hl - call __SET_ATTR - pop hl inc hl - ld (DFCCL),hl + ld (DFCCL), hl + dec hl + call __SET_ATTR exx ret ; ------------- SPECIAL CHARS (< 32) ----------------- @@ -912,7 +774,7 @@ __PRINT_0Dh: ; Called WHEN printing CHR$(13) push hl call __SCROLL_SCR pop hl -#line 210 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 209 "/zxbasic/src/arch/zx48k/library-asm/print.asm" 1: ld l, 1 __PRINT_EOL_END: @@ -1029,14 +891,14 @@ __PRINT_BOLD: __PRINT_BOLD2: call BOLD_TMP jp __PRINT_RESTART -#line 354 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 353 "/zxbasic/src/arch/zx48k/library-asm/print.asm" __PRINT_ITA: ld hl, __PRINT_ITA2 jp __PRINT_SET_STATE __PRINT_ITA2: call ITALIC_TMP jp __PRINT_RESTART -#line 364 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 363 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __BOLD __BOLD: push hl @@ -1054,7 +916,7 @@ __BOLD: pop hl ld de, MEM0 ret -#line 385 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 384 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __ITALIC __ITALIC: push hl @@ -1079,12 +941,12 @@ __ITALIC: pop hl ld de, MEM0 ret -#line 413 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 412 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __SCROLL_SCR -#line 487 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 486 "/zxbasic/src/arch/zx48k/library-asm/print.asm" __SCROLL_SCR EQU 0DFEh ; Use ROM SCROLL +#line 488 "/zxbasic/src/arch/zx48k/library-asm/print.asm" #line 489 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -#line 490 "/zxbasic/src/arch/zx48k/library-asm/print.asm" PRINT_COMMA: call __LOAD_S_POSN ld a, e @@ -1127,9 +989,9 @@ PRINT_AT: ; Changes cursor to ROW, COL LOCAL __PRINT_TABLE LOCAL __PRINT_TAB, __PRINT_TAB1, __PRINT_TAB2 LOCAL __PRINT_ITA2 -#line 546 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 545 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __PRINT_BOLD2 -#line 552 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 551 "/zxbasic/src/arch/zx48k/library-asm/print.asm" __PRINT_TABLE: ; Jump table for 0 .. 22 codes DW __PRINT_NOP ; 0 DW __PRINT_NOP ; 1 @@ -1157,7 +1019,145 @@ __PRINT_TABLE: ; Jump table for 0 .. 22 codes DW __PRINT_TAB ; 23 TAB ENDP pop namespace +#line 3 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" +#line 4 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" + push namespace core +COPY_ATTR: + ; Just copies current permanent attribs into temporal attribs + ; and sets print mode + PROC + LOCAL INVERSE1 + LOCAL __REFRESH_TMP + INVERSE1 EQU 02Fh + ld hl, (ATTR_P) + ld (ATTR_T), hl + ld hl, FLAGS2 + call __REFRESH_TMP + ld hl, P_FLAG + call __REFRESH_TMP +__SET_ATTR_MODE: ; Another entry to set print modes. A contains (P_FLAG) + LOCAL TABLE + LOCAL CONT2 + rra ; Over bit to carry + ld a, (FLAGS2) + rla ; Over bit in bit 1, Over2 bit in bit 2 + and 3 ; Only bit 0 and 1 (OVER flag) + ld c, a + ld b, 0 + ld hl, TABLE + add hl, bc + ld a, (hl) + ld (PRINT_MODE), a + ld hl, (P_FLAG) + xor a ; NOP -> INVERSE0 + bit 2, l + jr z, CONT2 + ld a, INVERSE1 ; CPL -> INVERSE1 +CONT2: + ld (INVERSE_MODE), a + ret +TABLE: + nop ; NORMAL MODE + xor (hl) ; OVER 1 MODE + and (hl) ; OVER 2 MODE + or (hl) ; OVER 3 MODE +#line 67 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" +__REFRESH_TMP: + ld a, (hl) + and 0b10101010 + ld c, a + rra + or c + ld (hl), a + ret + ENDP + pop namespace +#line 101 "zx48k/read8.bas" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/mulf.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/stackf.asm" + ; ------------------------------------------------------------- + ; Functions to manage FP-Stack of the ZX Spectrum ROM CALC + ; ------------------------------------------------------------- + push namespace core + __FPSTACK_PUSH EQU 2AB6h ; Stores an FP number into the ROM FP stack (A, ED CB) + __FPSTACK_POP EQU 2BF1h ; Pops an FP number out of the ROM FP stack (A, ED CB) +__FPSTACK_PUSH2: ; Pushes Current A ED CB registers and top of the stack on (SP + 4) + ; Second argument to push into the stack calculator is popped out of the stack + ; Since the caller routine also receives the parameters into the top of the stack + ; four bytes must be removed from SP before pop them out + call __FPSTACK_PUSH ; Pushes A ED CB into the FP-STACK + exx + pop hl ; Caller-Caller return addr + exx + pop hl ; Caller return addr + pop af + pop de + pop bc + push hl ; Caller return addr + exx + push hl ; Caller-Caller return addr + exx + jp __FPSTACK_PUSH +__FPSTACK_I16: ; Pushes 16 bits integer in HL into the FP ROM STACK + ; This format is specified in the ZX 48K Manual + ; You can push a 16 bit signed integer as + ; 0 SS LL HH 0, being SS the sign and LL HH the low + ; and High byte respectively + ld a, h + rla ; sign to Carry + sbc a, a ; 0 if positive, FF if negative + ld e, a + ld d, l + ld c, h + xor a + ld b, a + jp __FPSTACK_PUSH + pop namespace +#line 2 "/zxbasic/src/arch/zx48k/library-asm/mulf.asm" + ; ------------------------------------------------------------- + ; Floating point library using the FP ROM Calculator (ZX 48K) + ; All of them uses A EDCB registers as 1st paramter. + ; For binary operators, the 2n operator must be pushed into the + ; stack, in the order A DE BC. + ; + ; Uses CALLEE convention + ; ------------------------------------------------------------- + push namespace core +__MULF: ; Multiplication + call __FPSTACK_PUSH2 + ; ------------- ROM MUL + rst 28h + defb 04h ; + defb 38h; ; END CALC + jp __FPSTACK_POP + pop namespace #line 102 "zx48k/read8.bas" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/pow.asm" + ; ------------------------------------------------------------- + ; Floating point library using the FP ROM Calculator (ZX 48K) + ; All of them uses A EDCB registers as 1st paramter. + ; For binary operators, the 2n operator must be pushed into the + ; stack, in the order A DE BC. + ; + ; Uses CALLEE convention + ; +; Operands comes swapped: + ; 1 st parameter is the BASE (A ED CB) + ; 2 nd parameter (Top of the stack) is Exponent + ; ------------------------------------------------------------- + push namespace core +__POW: ; Exponentiation + PROC + call __FPSTACK_PUSH2 + ; ------------- ROM POW + rst 28h + defb 01h ; Exchange => 1, Base + defb 06h ; POW + defb 38h; ; END CALC + jp __FPSTACK_POP + ENDP + pop namespace +#line 103 "zx48k/read8.bas" #line 1 "/zxbasic/src/arch/zx48k/library-asm/printf.asm" #line 1 "/zxbasic/src/arch/zx48k/library-asm/printstr.asm" #line 1 "/zxbasic/src/arch/zx48k/library-asm/free.asm" @@ -1499,7 +1499,7 @@ __PRINTF: ; Prints a Fixed point Number stored in C ED LH RECLAIM2 EQU 19E8h ENDP pop namespace -#line 103 "zx48k/read8.bas" +#line 105 "zx48k/read8.bas" #line 1 "/zxbasic/src/arch/zx48k/library-asm/read_restore.asm" ;; This implements READ & RESTORE functions ;; Reads a new element from the DATA Address code @@ -2287,7 +2287,7 @@ __DATA_ADDR: ;; Stores current DATA ptr dw .DATA.__DATA__0 ENDP pop namespace -#line 104 "zx48k/read8.bas" +#line 106 "zx48k/read8.bas" #line 1 "/zxbasic/src/arch/zx48k/library-asm/sin.asm" push namespace core SIN: ; Computes SIN using ROM FP-CALC @@ -2297,7 +2297,7 @@ SIN: ; Computes SIN using ROM FP-CALC defb 38h ; END CALC jp __FPSTACK_POP pop namespace -#line 105 "zx48k/read8.bas" +#line 107 "zx48k/read8.bas" #line 1 "/zxbasic/src/arch/zx48k/library-asm/storef.asm" push namespace core __PISTOREF: ; Indect Stores a float (A, E, D, C, B) at location stored in memory, pointed by (IX + HL) @@ -2326,7 +2326,7 @@ __STOREF: ; Stores the given FP number in A EDCB at address HL ld (hl), b ret pop namespace -#line 106 "zx48k/read8.bas" +#line 108 "zx48k/read8.bas" #line 1 "/zxbasic/src/arch/zx48k/library-asm/tan.asm" push namespace core TAN: ; Computes TAN using ROM FP-CALC @@ -2336,5 +2336,5 @@ TAN: ; Computes TAN using ROM FP-CALC defb 38h ; END CALC jp __FPSTACK_POP pop namespace -#line 107 "zx48k/read8.bas" +#line 109 "zx48k/read8.bas" END diff --git a/tests/functional/zx48k/read9.asm b/tests/functional/zx48k/read9.asm index 64ba1ac9a..af7128d03 100644 --- a/tests/functional/zx48k/read9.asm +++ b/tests/functional/zx48k/read9.asm @@ -83,6 +83,7 @@ _c.__DATA__: pop de pop bc call .core.__STOREF + call .core.COPY_ATTR ld a, (_i) ld l, a ld h, 0 @@ -307,120 +308,8 @@ TMP_ARR_PTR: DW 0 ; temporary storage for pointer to tables ENDP pop namespace -#line 115 "zx48k/read9.bas" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/iloadf.asm" - ; __FASTCALL__ routine which - ; loads a 40 bits floating point into A ED CB - ; stored at position pointed by POINTER HL - ;A DE, BC <-- ((HL)) - push namespace core -__ILOADF: - ld a, (hl) - inc hl - ld h, (hl) - ld l, a - ; __FASTCALL__ routine which - ; loads a 40 bits floating point into A ED CB - ; stored at position pointed by POINTER HL - ;A DE, BC <-- (HL) -__LOADF: ; Loads a 40 bits FP number from address pointed by HL - ld a, (hl) - inc hl - ld e, (hl) - inc hl - ld d, (hl) - inc hl - ld c, (hl) - inc hl - ld b, (hl) - ret - pop namespace #line 116 "zx48k/read9.bas" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/mulf.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/stackf.asm" - ; ------------------------------------------------------------- - ; Functions to manage FP-Stack of the ZX Spectrum ROM CALC - ; ------------------------------------------------------------- - push namespace core - __FPSTACK_PUSH EQU 2AB6h ; Stores an FP number into the ROM FP stack (A, ED CB) - __FPSTACK_POP EQU 2BF1h ; Pops an FP number out of the ROM FP stack (A, ED CB) -__FPSTACK_PUSH2: ; Pushes Current A ED CB registers and top of the stack on (SP + 4) - ; Second argument to push into the stack calculator is popped out of the stack - ; Since the caller routine also receives the parameters into the top of the stack - ; four bytes must be removed from SP before pop them out - call __FPSTACK_PUSH ; Pushes A ED CB into the FP-STACK - exx - pop hl ; Caller-Caller return addr - exx - pop hl ; Caller return addr - pop af - pop de - pop bc - push hl ; Caller return addr - exx - push hl ; Caller-Caller return addr - exx - jp __FPSTACK_PUSH -__FPSTACK_I16: ; Pushes 16 bits integer in HL into the FP ROM STACK - ; This format is specified in the ZX 48K Manual - ; You can push a 16 bit signed integer as - ; 0 SS LL HH 0, being SS the sign and LL HH the low - ; and High byte respectively - ld a, h - rla ; sign to Carry - sbc a, a ; 0 if positive, FF if negative - ld e, a - ld d, l - ld c, h - xor a - ld b, a - jp __FPSTACK_PUSH - pop namespace -#line 2 "/zxbasic/src/arch/zx48k/library-asm/mulf.asm" - ; ------------------------------------------------------------- - ; Floating point library using the FP ROM Calculator (ZX 48K) - ; All of them uses A EDCB registers as 1st paramter. - ; For binary operators, the 2n operator must be pushed into the - ; stack, in the order A DE BC. - ; - ; Uses CALLEE convention - ; ------------------------------------------------------------- - push namespace core -__MULF: ; Multiplication - call __FPSTACK_PUSH2 - ; ------------- ROM MUL - rst 28h - defb 04h ; - defb 38h; ; END CALC - jp __FPSTACK_POP - pop namespace -#line 117 "zx48k/read9.bas" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/pow.asm" - ; ------------------------------------------------------------- - ; Floating point library using the FP ROM Calculator (ZX 48K) - ; All of them uses A EDCB registers as 1st paramter. - ; For binary operators, the 2n operator must be pushed into the - ; stack, in the order A DE BC. - ; - ; Uses CALLEE convention - ; -; Operands comes swapped: - ; 1 st parameter is the BASE (A ED CB) - ; 2 nd parameter (Top of the stack) is Exponent - ; ------------------------------------------------------------- - push namespace core -__POW: ; Exponentiation - PROC - call __FPSTACK_PUSH2 - ; ------------- ROM POW - rst 28h - defb 01h ; Exchange => 1, Base - defb 06h ; POW - defb 38h; ; END CALC - jp __FPSTACK_POP - ENDP - pop namespace -#line 118 "zx48k/read9.bas" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" #line 1 "/zxbasic/src/arch/zx48k/library-asm/print.asm" ; vim:ts=4:sw=4:et: ; PRINT command routine @@ -770,60 +659,6 @@ BRIGHT_TMP: #line 1 "/zxbasic/src/arch/zx48k/library-asm/over.asm" ; Sets OVER flag in P_FLAG permanently ; Parameter: OVER flag in bit 0 of A register -#line 1 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" -#line 4 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" - push namespace core -COPY_ATTR: - ; Just copies current permanent attribs into temporal attribs - ; and sets print mode - PROC - LOCAL INVERSE1 - LOCAL __REFRESH_TMP - INVERSE1 EQU 02Fh - ld hl, (ATTR_P) - ld (ATTR_T), hl - ld hl, FLAGS2 - call __REFRESH_TMP - ld hl, P_FLAG - call __REFRESH_TMP -__SET_ATTR_MODE: ; Another entry to set print modes. A contains (P_FLAG) - LOCAL TABLE - LOCAL CONT2 - rra ; Over bit to carry - ld a, (FLAGS2) - rla ; Over bit in bit 1, Over2 bit in bit 2 - and 3 ; Only bit 0 and 1 (OVER flag) - ld c, a - ld b, 0 - ld hl, TABLE - add hl, bc - ld a, (hl) - ld (PRINT_MODE), a - ld hl, (P_FLAG) - xor a ; NOP -> INVERSE0 - bit 2, l - jr z, CONT2 - ld a, INVERSE1 ; CPL -> INVERSE1 -CONT2: - ld (INVERSE_MODE), a - ret -TABLE: - nop ; NORMAL MODE - xor (hl) ; OVER 1 MODE - and (hl) ; OVER 2 MODE - or (hl) ; OVER 3 MODE -#line 67 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" -__REFRESH_TMP: - ld a, (hl) - and 0b10101010 - ld c, a - rra - or c - ld (hl), a - ret - ENDP - pop namespace -#line 4 "/zxbasic/src/arch/zx48k/library-asm/over.asm" push namespace core OVER: PROC @@ -1065,11 +900,10 @@ INVERSE_MODE: ; 00 -> NOP -> INVERSE 0 inc hl ld (DFCC), hl ld hl, (DFCCL) ; current ATTR Pos - push hl - call __SET_ATTR - pop hl inc hl - ld (DFCCL),hl + ld (DFCCL), hl + dec hl + call __SET_ATTR exx ret ; ------------- SPECIAL CHARS (< 32) ----------------- @@ -1088,7 +922,7 @@ __PRINT_0Dh: ; Called WHEN printing CHR$(13) push hl call __SCROLL_SCR pop hl -#line 210 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 209 "/zxbasic/src/arch/zx48k/library-asm/print.asm" 1: ld l, 1 __PRINT_EOL_END: @@ -1205,14 +1039,14 @@ __PRINT_BOLD: __PRINT_BOLD2: call BOLD_TMP jp __PRINT_RESTART -#line 354 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 353 "/zxbasic/src/arch/zx48k/library-asm/print.asm" __PRINT_ITA: ld hl, __PRINT_ITA2 jp __PRINT_SET_STATE __PRINT_ITA2: call ITALIC_TMP jp __PRINT_RESTART -#line 364 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 363 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __BOLD __BOLD: push hl @@ -1230,7 +1064,7 @@ __BOLD: pop hl ld de, MEM0 ret -#line 385 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 384 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __ITALIC __ITALIC: push hl @@ -1255,12 +1089,12 @@ __ITALIC: pop hl ld de, MEM0 ret -#line 413 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 412 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __SCROLL_SCR -#line 487 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 486 "/zxbasic/src/arch/zx48k/library-asm/print.asm" __SCROLL_SCR EQU 0DFEh ; Use ROM SCROLL +#line 488 "/zxbasic/src/arch/zx48k/library-asm/print.asm" #line 489 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -#line 490 "/zxbasic/src/arch/zx48k/library-asm/print.asm" PRINT_COMMA: call __LOAD_S_POSN ld a, e @@ -1303,9 +1137,9 @@ PRINT_AT: ; Changes cursor to ROW, COL LOCAL __PRINT_TABLE LOCAL __PRINT_TAB, __PRINT_TAB1, __PRINT_TAB2 LOCAL __PRINT_ITA2 -#line 546 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 545 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __PRINT_BOLD2 -#line 552 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 551 "/zxbasic/src/arch/zx48k/library-asm/print.asm" __PRINT_TABLE: ; Jump table for 0 .. 22 codes DW __PRINT_NOP ; 0 DW __PRINT_NOP ; 1 @@ -1333,7 +1167,173 @@ __PRINT_TABLE: ; Jump table for 0 .. 22 codes DW __PRINT_TAB ; 23 TAB ENDP pop namespace +#line 3 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" +#line 4 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" + push namespace core +COPY_ATTR: + ; Just copies current permanent attribs into temporal attribs + ; and sets print mode + PROC + LOCAL INVERSE1 + LOCAL __REFRESH_TMP + INVERSE1 EQU 02Fh + ld hl, (ATTR_P) + ld (ATTR_T), hl + ld hl, FLAGS2 + call __REFRESH_TMP + ld hl, P_FLAG + call __REFRESH_TMP +__SET_ATTR_MODE: ; Another entry to set print modes. A contains (P_FLAG) + LOCAL TABLE + LOCAL CONT2 + rra ; Over bit to carry + ld a, (FLAGS2) + rla ; Over bit in bit 1, Over2 bit in bit 2 + and 3 ; Only bit 0 and 1 (OVER flag) + ld c, a + ld b, 0 + ld hl, TABLE + add hl, bc + ld a, (hl) + ld (PRINT_MODE), a + ld hl, (P_FLAG) + xor a ; NOP -> INVERSE0 + bit 2, l + jr z, CONT2 + ld a, INVERSE1 ; CPL -> INVERSE1 +CONT2: + ld (INVERSE_MODE), a + ret +TABLE: + nop ; NORMAL MODE + xor (hl) ; OVER 1 MODE + and (hl) ; OVER 2 MODE + or (hl) ; OVER 3 MODE +#line 67 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" +__REFRESH_TMP: + ld a, (hl) + and 0b10101010 + ld c, a + rra + or c + ld (hl), a + ret + ENDP + pop namespace +#line 117 "zx48k/read9.bas" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/iloadf.asm" + ; __FASTCALL__ routine which + ; loads a 40 bits floating point into A ED CB + ; stored at position pointed by POINTER HL + ;A DE, BC <-- ((HL)) + push namespace core +__ILOADF: + ld a, (hl) + inc hl + ld h, (hl) + ld l, a + ; __FASTCALL__ routine which + ; loads a 40 bits floating point into A ED CB + ; stored at position pointed by POINTER HL + ;A DE, BC <-- (HL) +__LOADF: ; Loads a 40 bits FP number from address pointed by HL + ld a, (hl) + inc hl + ld e, (hl) + inc hl + ld d, (hl) + inc hl + ld c, (hl) + inc hl + ld b, (hl) + ret + pop namespace +#line 118 "zx48k/read9.bas" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/mulf.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/stackf.asm" + ; ------------------------------------------------------------- + ; Functions to manage FP-Stack of the ZX Spectrum ROM CALC + ; ------------------------------------------------------------- + push namespace core + __FPSTACK_PUSH EQU 2AB6h ; Stores an FP number into the ROM FP stack (A, ED CB) + __FPSTACK_POP EQU 2BF1h ; Pops an FP number out of the ROM FP stack (A, ED CB) +__FPSTACK_PUSH2: ; Pushes Current A ED CB registers and top of the stack on (SP + 4) + ; Second argument to push into the stack calculator is popped out of the stack + ; Since the caller routine also receives the parameters into the top of the stack + ; four bytes must be removed from SP before pop them out + call __FPSTACK_PUSH ; Pushes A ED CB into the FP-STACK + exx + pop hl ; Caller-Caller return addr + exx + pop hl ; Caller return addr + pop af + pop de + pop bc + push hl ; Caller return addr + exx + push hl ; Caller-Caller return addr + exx + jp __FPSTACK_PUSH +__FPSTACK_I16: ; Pushes 16 bits integer in HL into the FP ROM STACK + ; This format is specified in the ZX 48K Manual + ; You can push a 16 bit signed integer as + ; 0 SS LL HH 0, being SS the sign and LL HH the low + ; and High byte respectively + ld a, h + rla ; sign to Carry + sbc a, a ; 0 if positive, FF if negative + ld e, a + ld d, l + ld c, h + xor a + ld b, a + jp __FPSTACK_PUSH + pop namespace +#line 2 "/zxbasic/src/arch/zx48k/library-asm/mulf.asm" + ; ------------------------------------------------------------- + ; Floating point library using the FP ROM Calculator (ZX 48K) + ; All of them uses A EDCB registers as 1st paramter. + ; For binary operators, the 2n operator must be pushed into the + ; stack, in the order A DE BC. + ; + ; Uses CALLEE convention + ; ------------------------------------------------------------- + push namespace core +__MULF: ; Multiplication + call __FPSTACK_PUSH2 + ; ------------- ROM MUL + rst 28h + defb 04h ; + defb 38h; ; END CALC + jp __FPSTACK_POP + pop namespace #line 119 "zx48k/read9.bas" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/pow.asm" + ; ------------------------------------------------------------- + ; Floating point library using the FP ROM Calculator (ZX 48K) + ; All of them uses A EDCB registers as 1st paramter. + ; For binary operators, the 2n operator must be pushed into the + ; stack, in the order A DE BC. + ; + ; Uses CALLEE convention + ; +; Operands comes swapped: + ; 1 st parameter is the BASE (A ED CB) + ; 2 nd parameter (Top of the stack) is Exponent + ; ------------------------------------------------------------- + push namespace core +__POW: ; Exponentiation + PROC + call __FPSTACK_PUSH2 + ; ------------- ROM POW + rst 28h + defb 01h ; Exchange => 1, Base + defb 06h ; POW + defb 38h; ; END CALC + jp __FPSTACK_POP + ENDP + pop namespace +#line 120 "zx48k/read9.bas" #line 1 "/zxbasic/src/arch/zx48k/library-asm/printf.asm" #line 1 "/zxbasic/src/arch/zx48k/library-asm/printstr.asm" #line 1 "/zxbasic/src/arch/zx48k/library-asm/free.asm" @@ -1675,7 +1675,7 @@ __PRINTF: ; Prints a Fixed point Number stored in C ED LH RECLAIM2 EQU 19E8h ENDP pop namespace -#line 120 "zx48k/read9.bas" +#line 122 "zx48k/read9.bas" #line 1 "/zxbasic/src/arch/zx48k/library-asm/read_restore.asm" ;; This implements READ & RESTORE functions ;; Reads a new element from the DATA Address code @@ -2435,7 +2435,7 @@ __DATA_ADDR: ;; Stores current DATA ptr dw .DATA.__DATA__0 ENDP pop namespace -#line 121 "zx48k/read9.bas" +#line 123 "zx48k/read9.bas" #line 1 "/zxbasic/src/arch/zx48k/library-asm/sin.asm" push namespace core SIN: ; Computes SIN using ROM FP-CALC @@ -2445,7 +2445,7 @@ SIN: ; Computes SIN using ROM FP-CALC defb 38h ; END CALC jp __FPSTACK_POP pop namespace -#line 122 "zx48k/read9.bas" +#line 124 "zx48k/read9.bas" #line 1 "/zxbasic/src/arch/zx48k/library-asm/storef.asm" push namespace core __PISTOREF: ; Indect Stores a float (A, E, D, C, B) at location stored in memory, pointed by (IX + HL) @@ -2474,7 +2474,7 @@ __STOREF: ; Stores the given FP number in A EDCB at address HL ld (hl), b ret pop namespace -#line 123 "zx48k/read9.bas" +#line 125 "zx48k/read9.bas" #line 1 "/zxbasic/src/arch/zx48k/library-asm/tan.asm" push namespace core TAN: ; Computes TAN using ROM FP-CALC @@ -2484,5 +2484,5 @@ TAN: ; Computes TAN using ROM FP-CALC defb 38h ; END CALC jp __FPSTACK_POP pop namespace -#line 124 "zx48k/read9.bas" +#line 126 "zx48k/read9.bas" END diff --git a/tests/functional/zx48k/readokdown.asm b/tests/functional/zx48k/readokdown.asm index 8449f7d07..d0e1b7c32 100644 --- a/tests/functional/zx48k/readokdown.asm +++ b/tests/functional/zx48k/readokdown.asm @@ -47,6 +47,8 @@ _flt: ld a, 2 call .core.__READ ld (_i8), a + call .core.COPY_ATTR + ld a, (_i8) call .core.__PRINTI8 call .core.PRINT_EOL ld hl, .DATA.__DATA__0 @@ -54,6 +56,8 @@ _flt: ld a, 3 call .core.__READ ld (_u8), a + call .core.COPY_ATTR + ld a, (_u8) call .core.__PRINTU8 call .core.PRINT_EOL ld hl, .DATA.__DATA__0 @@ -61,6 +65,8 @@ _flt: ld a, 4 call .core.__READ ld (_i16), hl + call .core.COPY_ATTR + ld hl, (_i16) call .core.__PRINTI16 call .core.PRINT_EOL ld hl, .DATA.__DATA__0 @@ -68,6 +74,8 @@ _flt: ld a, 5 call .core.__READ ld (_u16), hl + call .core.COPY_ATTR + ld hl, (_u16) call .core.__PRINTU16 call .core.PRINT_EOL ld hl, .DATA.__DATA__0 @@ -76,6 +84,7 @@ _flt: call .core.__READ ld (_i32), hl ld (_i32 + 2), de + call .core.COPY_ATTR ld hl, (_i32) ld de, (_i32 + 2) call .core.__PRINTI32 @@ -86,6 +95,7 @@ _flt: call .core.__READ ld (_u32), hl ld (_u32 + 2), de + call .core.COPY_ATTR ld hl, (_u32) ld de, (_u32 + 2) call .core.__PRINTU32 @@ -96,6 +106,7 @@ _flt: call .core.__READ ld (_f16), hl ld (_f16 + 2), de + call .core.COPY_ATTR ld hl, (_f16) ld de, (_f16 + 2) call .core.__PRINTF16 @@ -106,6 +117,7 @@ _flt: call .core.__READ ld hl, _flt call .core.__STOREF + call .core.COPY_ATTR ld a, (_flt) ld de, (_flt + 1) ld bc, (_flt + 3) @@ -132,6 +144,7 @@ _flt: __DATA__END: DEFB 00h ;; --- end of user code --- +#line 1 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" #line 1 "/zxbasic/src/arch/zx48k/library-asm/print.asm" ; vim:ts=4:sw=4:et: ; PRINT command routine @@ -481,60 +494,6 @@ BRIGHT_TMP: #line 1 "/zxbasic/src/arch/zx48k/library-asm/over.asm" ; Sets OVER flag in P_FLAG permanently ; Parameter: OVER flag in bit 0 of A register -#line 1 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" -#line 4 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" - push namespace core -COPY_ATTR: - ; Just copies current permanent attribs into temporal attribs - ; and sets print mode - PROC - LOCAL INVERSE1 - LOCAL __REFRESH_TMP - INVERSE1 EQU 02Fh - ld hl, (ATTR_P) - ld (ATTR_T), hl - ld hl, FLAGS2 - call __REFRESH_TMP - ld hl, P_FLAG - call __REFRESH_TMP -__SET_ATTR_MODE: ; Another entry to set print modes. A contains (P_FLAG) - LOCAL TABLE - LOCAL CONT2 - rra ; Over bit to carry - ld a, (FLAGS2) - rla ; Over bit in bit 1, Over2 bit in bit 2 - and 3 ; Only bit 0 and 1 (OVER flag) - ld c, a - ld b, 0 - ld hl, TABLE - add hl, bc - ld a, (hl) - ld (PRINT_MODE), a - ld hl, (P_FLAG) - xor a ; NOP -> INVERSE0 - bit 2, l - jr z, CONT2 - ld a, INVERSE1 ; CPL -> INVERSE1 -CONT2: - ld (INVERSE_MODE), a - ret -TABLE: - nop ; NORMAL MODE - xor (hl) ; OVER 1 MODE - and (hl) ; OVER 2 MODE - or (hl) ; OVER 3 MODE -#line 67 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" -__REFRESH_TMP: - ld a, (hl) - and 0b10101010 - ld c, a - rra - or c - ld (hl), a - ret - ENDP - pop namespace -#line 4 "/zxbasic/src/arch/zx48k/library-asm/over.asm" push namespace core OVER: PROC @@ -776,11 +735,10 @@ INVERSE_MODE: ; 00 -> NOP -> INVERSE 0 inc hl ld (DFCC), hl ld hl, (DFCCL) ; current ATTR Pos - push hl - call __SET_ATTR - pop hl inc hl - ld (DFCCL),hl + ld (DFCCL), hl + dec hl + call __SET_ATTR exx ret ; ------------- SPECIAL CHARS (< 32) ----------------- @@ -799,7 +757,7 @@ __PRINT_0Dh: ; Called WHEN printing CHR$(13) push hl call __SCROLL_SCR pop hl -#line 210 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 209 "/zxbasic/src/arch/zx48k/library-asm/print.asm" 1: ld l, 1 __PRINT_EOL_END: @@ -916,14 +874,14 @@ __PRINT_BOLD: __PRINT_BOLD2: call BOLD_TMP jp __PRINT_RESTART -#line 354 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 353 "/zxbasic/src/arch/zx48k/library-asm/print.asm" __PRINT_ITA: ld hl, __PRINT_ITA2 jp __PRINT_SET_STATE __PRINT_ITA2: call ITALIC_TMP jp __PRINT_RESTART -#line 364 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 363 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __BOLD __BOLD: push hl @@ -941,7 +899,7 @@ __BOLD: pop hl ld de, MEM0 ret -#line 385 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 384 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __ITALIC __ITALIC: push hl @@ -966,12 +924,12 @@ __ITALIC: pop hl ld de, MEM0 ret -#line 413 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 412 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __SCROLL_SCR -#line 487 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 486 "/zxbasic/src/arch/zx48k/library-asm/print.asm" __SCROLL_SCR EQU 0DFEh ; Use ROM SCROLL +#line 488 "/zxbasic/src/arch/zx48k/library-asm/print.asm" #line 489 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -#line 490 "/zxbasic/src/arch/zx48k/library-asm/print.asm" PRINT_COMMA: call __LOAD_S_POSN ld a, e @@ -1014,9 +972,9 @@ PRINT_AT: ; Changes cursor to ROW, COL LOCAL __PRINT_TABLE LOCAL __PRINT_TAB, __PRINT_TAB1, __PRINT_TAB2 LOCAL __PRINT_ITA2 -#line 546 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 545 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __PRINT_BOLD2 -#line 552 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 551 "/zxbasic/src/arch/zx48k/library-asm/print.asm" __PRINT_TABLE: ; Jump table for 0 .. 22 codes DW __PRINT_NOP ; 0 DW __PRINT_NOP ; 1 @@ -1044,7 +1002,60 @@ __PRINT_TABLE: ; Jump table for 0 .. 22 codes DW __PRINT_TAB ; 23 TAB ENDP pop namespace -#line 92 "zx48k/readokdown.bas" +#line 3 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" +#line 4 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" + push namespace core +COPY_ATTR: + ; Just copies current permanent attribs into temporal attribs + ; and sets print mode + PROC + LOCAL INVERSE1 + LOCAL __REFRESH_TMP + INVERSE1 EQU 02Fh + ld hl, (ATTR_P) + ld (ATTR_T), hl + ld hl, FLAGS2 + call __REFRESH_TMP + ld hl, P_FLAG + call __REFRESH_TMP +__SET_ATTR_MODE: ; Another entry to set print modes. A contains (P_FLAG) + LOCAL TABLE + LOCAL CONT2 + rra ; Over bit to carry + ld a, (FLAGS2) + rla ; Over bit in bit 1, Over2 bit in bit 2 + and 3 ; Only bit 0 and 1 (OVER flag) + ld c, a + ld b, 0 + ld hl, TABLE + add hl, bc + ld a, (hl) + ld (PRINT_MODE), a + ld hl, (P_FLAG) + xor a ; NOP -> INVERSE0 + bit 2, l + jr z, CONT2 + ld a, INVERSE1 ; CPL -> INVERSE1 +CONT2: + ld (INVERSE_MODE), a + ret +TABLE: + nop ; NORMAL MODE + xor (hl) ; OVER 1 MODE + and (hl) ; OVER 2 MODE + or (hl) ; OVER 3 MODE +#line 67 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" +__REFRESH_TMP: + ld a, (hl) + and 0b10101010 + ld c, a + rra + or c + ld (hl), a + ret + ENDP + pop namespace +#line 104 "zx48k/readokdown.bas" #line 1 "/zxbasic/src/arch/zx48k/library-asm/printf.asm" #line 1 "/zxbasic/src/arch/zx48k/library-asm/printstr.asm" #line 1 "/zxbasic/src/arch/zx48k/library-asm/free.asm" @@ -1426,7 +1437,7 @@ __PRINTF: ; Prints a Fixed point Number stored in C ED LH RECLAIM2 EQU 19E8h ENDP pop namespace -#line 93 "zx48k/readokdown.bas" +#line 106 "zx48k/readokdown.bas" #line 1 "/zxbasic/src/arch/zx48k/library-asm/printf16.asm" #line 1 "/zxbasic/src/arch/zx48k/library-asm/printnum.asm" push namespace core @@ -1644,7 +1655,7 @@ __PRINT_FIX_LOOP: jp __PRINT_FIX_LOOP ENDP pop namespace -#line 94 "zx48k/readokdown.bas" +#line 107 "zx48k/readokdown.bas" #line 1 "/zxbasic/src/arch/zx48k/library-asm/printi32.asm" #line 1 "/zxbasic/src/arch/zx48k/library-asm/div32.asm" ; --------------------------------------------------------- @@ -1793,7 +1804,7 @@ __PRINTU_LOOP: jp __PRINTU_LOOP ; Uses JP in loops ENDP pop namespace -#line 96 "zx48k/readokdown.bas" +#line 109 "zx48k/readokdown.bas" #line 1 "/zxbasic/src/arch/zx48k/library-asm/printi8.asm" #line 1 "/zxbasic/src/arch/zx48k/library-asm/div8.asm" ; -------------------------------- @@ -1889,13 +1900,13 @@ __PRINTU_LOOP: jp __PRINTU_LOOP ; Uses JP in loops ENDP pop namespace -#line 97 "zx48k/readokdown.bas" +#line 110 "zx48k/readokdown.bas" #line 1 "/zxbasic/src/arch/zx48k/library-asm/printu16.asm" -#line 98 "zx48k/readokdown.bas" +#line 111 "zx48k/readokdown.bas" #line 1 "/zxbasic/src/arch/zx48k/library-asm/printu32.asm" -#line 99 "zx48k/readokdown.bas" +#line 112 "zx48k/readokdown.bas" #line 1 "/zxbasic/src/arch/zx48k/library-asm/printu8.asm" -#line 100 "zx48k/readokdown.bas" +#line 113 "zx48k/readokdown.bas" #line 1 "/zxbasic/src/arch/zx48k/library-asm/read_restore.asm" ;; This implements READ & RESTORE functions ;; Reads a new element from the DATA Address code @@ -2657,7 +2668,7 @@ __DATA_ADDR: ;; Stores current DATA ptr dw .DATA.__DATA__0 ENDP pop namespace -#line 101 "zx48k/readokdown.bas" +#line 114 "zx48k/readokdown.bas" #line 1 "/zxbasic/src/arch/zx48k/library-asm/storef.asm" push namespace core __PISTOREF: ; Indect Stores a float (A, E, D, C, B) at location stored in memory, pointed by (IX + HL) @@ -2686,5 +2697,5 @@ __STOREF: ; Stores the given FP number in A EDCB at address HL ld (hl), b ret pop namespace -#line 102 "zx48k/readokdown.bas" +#line 115 "zx48k/readokdown.bas" END diff --git a/tests/functional/zx48k/readokup.asm b/tests/functional/zx48k/readokup.asm index 70483b869..62270ddc6 100644 --- a/tests/functional/zx48k/readokup.asm +++ b/tests/functional/zx48k/readokup.asm @@ -47,6 +47,8 @@ _flt: ld a, 2 call .core.__READ ld (_i8), a + call .core.COPY_ATTR + ld a, (_i8) call .core.__PRINTI8 call .core.PRINT_EOL ld hl, .DATA.__DATA__0 @@ -54,6 +56,8 @@ _flt: ld a, 3 call .core.__READ ld (_u8), a + call .core.COPY_ATTR + ld a, (_u8) call .core.__PRINTU8 call .core.PRINT_EOL ld hl, .DATA.__DATA__0 @@ -61,6 +65,8 @@ _flt: ld a, 4 call .core.__READ ld (_i16), hl + call .core.COPY_ATTR + ld hl, (_i16) call .core.__PRINTI16 call .core.PRINT_EOL ld hl, .DATA.__DATA__0 @@ -68,6 +74,8 @@ _flt: ld a, 5 call .core.__READ ld (_u16), hl + call .core.COPY_ATTR + ld hl, (_u16) call .core.__PRINTU16 call .core.PRINT_EOL ld hl, .DATA.__DATA__0 @@ -76,6 +84,7 @@ _flt: call .core.__READ ld (_i32), hl ld (_i32 + 2), de + call .core.COPY_ATTR ld hl, (_i32) ld de, (_i32 + 2) call .core.__PRINTI32 @@ -86,6 +95,7 @@ _flt: call .core.__READ ld (_u32), hl ld (_u32 + 2), de + call .core.COPY_ATTR ld hl, (_u32) ld de, (_u32 + 2) call .core.__PRINTU32 @@ -96,6 +106,7 @@ _flt: call .core.__READ ld (_f16), hl ld (_f16 + 2), de + call .core.COPY_ATTR ld hl, (_f16) ld de, (_f16 + 2) call .core.__PRINTF16 @@ -106,6 +117,7 @@ _flt: call .core.__READ ld hl, _flt call .core.__STOREF + call .core.COPY_ATTR ld a, (_flt) ld de, (_flt + 1) ld bc, (_flt + 3) @@ -131,6 +143,7 @@ _flt: __DATA__END: DEFB 00h ;; --- end of user code --- +#line 1 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" #line 1 "/zxbasic/src/arch/zx48k/library-asm/print.asm" ; vim:ts=4:sw=4:et: ; PRINT command routine @@ -480,60 +493,6 @@ BRIGHT_TMP: #line 1 "/zxbasic/src/arch/zx48k/library-asm/over.asm" ; Sets OVER flag in P_FLAG permanently ; Parameter: OVER flag in bit 0 of A register -#line 1 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" -#line 4 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" - push namespace core -COPY_ATTR: - ; Just copies current permanent attribs into temporal attribs - ; and sets print mode - PROC - LOCAL INVERSE1 - LOCAL __REFRESH_TMP - INVERSE1 EQU 02Fh - ld hl, (ATTR_P) - ld (ATTR_T), hl - ld hl, FLAGS2 - call __REFRESH_TMP - ld hl, P_FLAG - call __REFRESH_TMP -__SET_ATTR_MODE: ; Another entry to set print modes. A contains (P_FLAG) - LOCAL TABLE - LOCAL CONT2 - rra ; Over bit to carry - ld a, (FLAGS2) - rla ; Over bit in bit 1, Over2 bit in bit 2 - and 3 ; Only bit 0 and 1 (OVER flag) - ld c, a - ld b, 0 - ld hl, TABLE - add hl, bc - ld a, (hl) - ld (PRINT_MODE), a - ld hl, (P_FLAG) - xor a ; NOP -> INVERSE0 - bit 2, l - jr z, CONT2 - ld a, INVERSE1 ; CPL -> INVERSE1 -CONT2: - ld (INVERSE_MODE), a - ret -TABLE: - nop ; NORMAL MODE - xor (hl) ; OVER 1 MODE - and (hl) ; OVER 2 MODE - or (hl) ; OVER 3 MODE -#line 67 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" -__REFRESH_TMP: - ld a, (hl) - and 0b10101010 - ld c, a - rra - or c - ld (hl), a - ret - ENDP - pop namespace -#line 4 "/zxbasic/src/arch/zx48k/library-asm/over.asm" push namespace core OVER: PROC @@ -775,11 +734,10 @@ INVERSE_MODE: ; 00 -> NOP -> INVERSE 0 inc hl ld (DFCC), hl ld hl, (DFCCL) ; current ATTR Pos - push hl - call __SET_ATTR - pop hl inc hl - ld (DFCCL),hl + ld (DFCCL), hl + dec hl + call __SET_ATTR exx ret ; ------------- SPECIAL CHARS (< 32) ----------------- @@ -798,7 +756,7 @@ __PRINT_0Dh: ; Called WHEN printing CHR$(13) push hl call __SCROLL_SCR pop hl -#line 210 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 209 "/zxbasic/src/arch/zx48k/library-asm/print.asm" 1: ld l, 1 __PRINT_EOL_END: @@ -915,14 +873,14 @@ __PRINT_BOLD: __PRINT_BOLD2: call BOLD_TMP jp __PRINT_RESTART -#line 354 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 353 "/zxbasic/src/arch/zx48k/library-asm/print.asm" __PRINT_ITA: ld hl, __PRINT_ITA2 jp __PRINT_SET_STATE __PRINT_ITA2: call ITALIC_TMP jp __PRINT_RESTART -#line 364 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 363 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __BOLD __BOLD: push hl @@ -940,7 +898,7 @@ __BOLD: pop hl ld de, MEM0 ret -#line 385 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 384 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __ITALIC __ITALIC: push hl @@ -965,12 +923,12 @@ __ITALIC: pop hl ld de, MEM0 ret -#line 413 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 412 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __SCROLL_SCR -#line 487 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 486 "/zxbasic/src/arch/zx48k/library-asm/print.asm" __SCROLL_SCR EQU 0DFEh ; Use ROM SCROLL +#line 488 "/zxbasic/src/arch/zx48k/library-asm/print.asm" #line 489 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -#line 490 "/zxbasic/src/arch/zx48k/library-asm/print.asm" PRINT_COMMA: call __LOAD_S_POSN ld a, e @@ -1013,9 +971,9 @@ PRINT_AT: ; Changes cursor to ROW, COL LOCAL __PRINT_TABLE LOCAL __PRINT_TAB, __PRINT_TAB1, __PRINT_TAB2 LOCAL __PRINT_ITA2 -#line 546 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 545 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __PRINT_BOLD2 -#line 552 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 551 "/zxbasic/src/arch/zx48k/library-asm/print.asm" __PRINT_TABLE: ; Jump table for 0 .. 22 codes DW __PRINT_NOP ; 0 DW __PRINT_NOP ; 1 @@ -1043,7 +1001,60 @@ __PRINT_TABLE: ; Jump table for 0 .. 22 codes DW __PRINT_TAB ; 23 TAB ENDP pop namespace -#line 91 "zx48k/readokup.bas" +#line 3 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" +#line 4 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" + push namespace core +COPY_ATTR: + ; Just copies current permanent attribs into temporal attribs + ; and sets print mode + PROC + LOCAL INVERSE1 + LOCAL __REFRESH_TMP + INVERSE1 EQU 02Fh + ld hl, (ATTR_P) + ld (ATTR_T), hl + ld hl, FLAGS2 + call __REFRESH_TMP + ld hl, P_FLAG + call __REFRESH_TMP +__SET_ATTR_MODE: ; Another entry to set print modes. A contains (P_FLAG) + LOCAL TABLE + LOCAL CONT2 + rra ; Over bit to carry + ld a, (FLAGS2) + rla ; Over bit in bit 1, Over2 bit in bit 2 + and 3 ; Only bit 0 and 1 (OVER flag) + ld c, a + ld b, 0 + ld hl, TABLE + add hl, bc + ld a, (hl) + ld (PRINT_MODE), a + ld hl, (P_FLAG) + xor a ; NOP -> INVERSE0 + bit 2, l + jr z, CONT2 + ld a, INVERSE1 ; CPL -> INVERSE1 +CONT2: + ld (INVERSE_MODE), a + ret +TABLE: + nop ; NORMAL MODE + xor (hl) ; OVER 1 MODE + and (hl) ; OVER 2 MODE + or (hl) ; OVER 3 MODE +#line 67 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" +__REFRESH_TMP: + ld a, (hl) + and 0b10101010 + ld c, a + rra + or c + ld (hl), a + ret + ENDP + pop namespace +#line 103 "zx48k/readokup.bas" #line 1 "/zxbasic/src/arch/zx48k/library-asm/printf.asm" #line 1 "/zxbasic/src/arch/zx48k/library-asm/printstr.asm" #line 1 "/zxbasic/src/arch/zx48k/library-asm/free.asm" @@ -1425,7 +1436,7 @@ __PRINTF: ; Prints a Fixed point Number stored in C ED LH RECLAIM2 EQU 19E8h ENDP pop namespace -#line 92 "zx48k/readokup.bas" +#line 105 "zx48k/readokup.bas" #line 1 "/zxbasic/src/arch/zx48k/library-asm/printf16.asm" #line 1 "/zxbasic/src/arch/zx48k/library-asm/printnum.asm" push namespace core @@ -1643,7 +1654,7 @@ __PRINT_FIX_LOOP: jp __PRINT_FIX_LOOP ENDP pop namespace -#line 93 "zx48k/readokup.bas" +#line 106 "zx48k/readokup.bas" #line 1 "/zxbasic/src/arch/zx48k/library-asm/printi32.asm" #line 1 "/zxbasic/src/arch/zx48k/library-asm/div32.asm" ; --------------------------------------------------------- @@ -1792,7 +1803,7 @@ __PRINTU_LOOP: jp __PRINTU_LOOP ; Uses JP in loops ENDP pop namespace -#line 95 "zx48k/readokup.bas" +#line 108 "zx48k/readokup.bas" #line 1 "/zxbasic/src/arch/zx48k/library-asm/printi8.asm" #line 1 "/zxbasic/src/arch/zx48k/library-asm/div8.asm" ; -------------------------------- @@ -1888,13 +1899,13 @@ __PRINTU_LOOP: jp __PRINTU_LOOP ; Uses JP in loops ENDP pop namespace -#line 96 "zx48k/readokup.bas" +#line 109 "zx48k/readokup.bas" #line 1 "/zxbasic/src/arch/zx48k/library-asm/printu16.asm" -#line 97 "zx48k/readokup.bas" +#line 110 "zx48k/readokup.bas" #line 1 "/zxbasic/src/arch/zx48k/library-asm/printu32.asm" -#line 98 "zx48k/readokup.bas" +#line 111 "zx48k/readokup.bas" #line 1 "/zxbasic/src/arch/zx48k/library-asm/printu8.asm" -#line 99 "zx48k/readokup.bas" +#line 112 "zx48k/readokup.bas" #line 1 "/zxbasic/src/arch/zx48k/library-asm/read_restore.asm" ;; This implements READ & RESTORE functions ;; Reads a new element from the DATA Address code @@ -2656,7 +2667,7 @@ __DATA_ADDR: ;; Stores current DATA ptr dw .DATA.__DATA__0 ENDP pop namespace -#line 100 "zx48k/readokup.bas" +#line 113 "zx48k/readokup.bas" #line 1 "/zxbasic/src/arch/zx48k/library-asm/storef.asm" push namespace core __PISTOREF: ; Indect Stores a float (A, E, D, C, B) at location stored in memory, pointed by (IX + HL) @@ -2685,5 +2696,5 @@ __STOREF: ; Stores the given FP number in A EDCB at address HL ld (hl), b ret pop namespace -#line 101 "zx48k/readokup.bas" +#line 114 "zx48k/readokup.bas" END diff --git a/tests/functional/zx48k/simple.asm b/tests/functional/zx48k/simple.asm index 13e13ea26..5fd36f24f 100644 --- a/tests/functional/zx48k/simple.asm +++ b/tests/functional/zx48k/simple.asm @@ -26,6 +26,7 @@ .core.__LABEL__.ZXBASIC_USER_DATA EQU .core.ZXBASIC_USER_DATA .core.ZXBASIC_USER_DATA_END: .core.__MAIN_PROGRAM__: + call .core.COPY_ATTR ld hl, .LABEL.__LABEL0 xor a call .core.__PRINTSTR @@ -58,6 +59,7 @@ DEFB 4Ch DEFB 44h ;; --- end of user code --- +#line 1 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" #line 1 "/zxbasic/src/arch/zx48k/library-asm/print.asm" ; vim:ts=4:sw=4:et: ; PRINT command routine @@ -407,60 +409,6 @@ BRIGHT_TMP: #line 1 "/zxbasic/src/arch/zx48k/library-asm/over.asm" ; Sets OVER flag in P_FLAG permanently ; Parameter: OVER flag in bit 0 of A register -#line 1 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" -#line 4 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" - push namespace core -COPY_ATTR: - ; Just copies current permanent attribs into temporal attribs - ; and sets print mode - PROC - LOCAL INVERSE1 - LOCAL __REFRESH_TMP - INVERSE1 EQU 02Fh - ld hl, (ATTR_P) - ld (ATTR_T), hl - ld hl, FLAGS2 - call __REFRESH_TMP - ld hl, P_FLAG - call __REFRESH_TMP -__SET_ATTR_MODE: ; Another entry to set print modes. A contains (P_FLAG) - LOCAL TABLE - LOCAL CONT2 - rra ; Over bit to carry - ld a, (FLAGS2) - rla ; Over bit in bit 1, Over2 bit in bit 2 - and 3 ; Only bit 0 and 1 (OVER flag) - ld c, a - ld b, 0 - ld hl, TABLE - add hl, bc - ld a, (hl) - ld (PRINT_MODE), a - ld hl, (P_FLAG) - xor a ; NOP -> INVERSE0 - bit 2, l - jr z, CONT2 - ld a, INVERSE1 ; CPL -> INVERSE1 -CONT2: - ld (INVERSE_MODE), a - ret -TABLE: - nop ; NORMAL MODE - xor (hl) ; OVER 1 MODE - and (hl) ; OVER 2 MODE - or (hl) ; OVER 3 MODE -#line 67 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" -__REFRESH_TMP: - ld a, (hl) - and 0b10101010 - ld c, a - rra - or c - ld (hl), a - ret - ENDP - pop namespace -#line 4 "/zxbasic/src/arch/zx48k/library-asm/over.asm" push namespace core OVER: PROC @@ -702,11 +650,10 @@ INVERSE_MODE: ; 00 -> NOP -> INVERSE 0 inc hl ld (DFCC), hl ld hl, (DFCCL) ; current ATTR Pos - push hl - call __SET_ATTR - pop hl inc hl - ld (DFCCL),hl + ld (DFCCL), hl + dec hl + call __SET_ATTR exx ret ; ------------- SPECIAL CHARS (< 32) ----------------- @@ -725,7 +672,7 @@ __PRINT_0Dh: ; Called WHEN printing CHR$(13) push hl call __SCROLL_SCR pop hl -#line 210 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 209 "/zxbasic/src/arch/zx48k/library-asm/print.asm" 1: ld l, 1 __PRINT_EOL_END: @@ -842,14 +789,14 @@ __PRINT_BOLD: __PRINT_BOLD2: call BOLD_TMP jp __PRINT_RESTART -#line 354 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 353 "/zxbasic/src/arch/zx48k/library-asm/print.asm" __PRINT_ITA: ld hl, __PRINT_ITA2 jp __PRINT_SET_STATE __PRINT_ITA2: call ITALIC_TMP jp __PRINT_RESTART -#line 364 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 363 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __BOLD __BOLD: push hl @@ -867,7 +814,7 @@ __BOLD: pop hl ld de, MEM0 ret -#line 385 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 384 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __ITALIC __ITALIC: push hl @@ -892,12 +839,12 @@ __ITALIC: pop hl ld de, MEM0 ret -#line 413 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 412 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __SCROLL_SCR -#line 487 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 486 "/zxbasic/src/arch/zx48k/library-asm/print.asm" __SCROLL_SCR EQU 0DFEh ; Use ROM SCROLL +#line 488 "/zxbasic/src/arch/zx48k/library-asm/print.asm" #line 489 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -#line 490 "/zxbasic/src/arch/zx48k/library-asm/print.asm" PRINT_COMMA: call __LOAD_S_POSN ld a, e @@ -940,9 +887,9 @@ PRINT_AT: ; Changes cursor to ROW, COL LOCAL __PRINT_TABLE LOCAL __PRINT_TAB, __PRINT_TAB1, __PRINT_TAB2 LOCAL __PRINT_ITA2 -#line 546 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 545 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __PRINT_BOLD2 -#line 552 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 551 "/zxbasic/src/arch/zx48k/library-asm/print.asm" __PRINT_TABLE: ; Jump table for 0 .. 22 codes DW __PRINT_NOP ; 0 DW __PRINT_NOP ; 1 @@ -970,7 +917,60 @@ __PRINT_TABLE: ; Jump table for 0 .. 22 codes DW __PRINT_TAB ; 23 TAB ENDP pop namespace -#line 34 "zx48k/simple.bas" +#line 3 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" +#line 4 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" + push namespace core +COPY_ATTR: + ; Just copies current permanent attribs into temporal attribs + ; and sets print mode + PROC + LOCAL INVERSE1 + LOCAL __REFRESH_TMP + INVERSE1 EQU 02Fh + ld hl, (ATTR_P) + ld (ATTR_T), hl + ld hl, FLAGS2 + call __REFRESH_TMP + ld hl, P_FLAG + call __REFRESH_TMP +__SET_ATTR_MODE: ; Another entry to set print modes. A contains (P_FLAG) + LOCAL TABLE + LOCAL CONT2 + rra ; Over bit to carry + ld a, (FLAGS2) + rla ; Over bit in bit 1, Over2 bit in bit 2 + and 3 ; Only bit 0 and 1 (OVER flag) + ld c, a + ld b, 0 + ld hl, TABLE + add hl, bc + ld a, (hl) + ld (PRINT_MODE), a + ld hl, (P_FLAG) + xor a ; NOP -> INVERSE0 + bit 2, l + jr z, CONT2 + ld a, INVERSE1 ; CPL -> INVERSE1 +CONT2: + ld (INVERSE_MODE), a + ret +TABLE: + nop ; NORMAL MODE + xor (hl) ; OVER 1 MODE + and (hl) ; OVER 2 MODE + or (hl) ; OVER 3 MODE +#line 67 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" +__REFRESH_TMP: + ld a, (hl) + and 0b10101010 + ld c, a + rra + or c + ld (hl), a + ret + ENDP + pop namespace +#line 35 "zx48k/simple.bas" #line 1 "/zxbasic/src/arch/zx48k/library-asm/printstr.asm" #line 1 "/zxbasic/src/arch/zx48k/library-asm/free.asm" ; vim: ts=4:et:sw=4: @@ -1281,5 +1281,5 @@ __PRINT_STR: jp __PRINT_STR_LOOP ENDP pop namespace -#line 35 "zx48k/simple.bas" +#line 37 "zx48k/simple.bas" END diff --git a/tests/functional/zx48k/spfill.asm b/tests/functional/zx48k/spfill.asm index 0a959865f..7da992acf 100644 --- a/tests/functional/zx48k/spfill.asm +++ b/tests/functional/zx48k/spfill.asm @@ -28,6 +28,7 @@ .LABEL._10: call .core.CLS .LABEL._20: + call .core.COPY_ATTR ld a, 128 push af ld a, 87 @@ -1135,6 +1136,37 @@ CLS: ENDP pop namespace #line 556 "/zxbasic/src/arch/zx48k/library/SP/Fill.bas" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" +#line 4 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" + push namespace core +COPY_ATTR: + ; Just copies current permanent attribs into temporal attribs + ; and sets print mode + PROC + LOCAL INVERSE1 + LOCAL __REFRESH_TMP + INVERSE1 EQU 02Fh + ld hl, (ATTR_P) + ld (ATTR_T), hl + ld hl, FLAGS2 + call __REFRESH_TMP + ld hl, P_FLAG + call __REFRESH_TMP +__SET_ATTR_MODE: ; Another entry to set print modes. A contains (P_FLAG) +#line 65 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" + ret +#line 67 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" +__REFRESH_TMP: + ld a, (hl) + and 0b10101010 + ld c, a + rra + or c + ld (hl), a + ret + ENDP + pop namespace +#line 557 "/zxbasic/src/arch/zx48k/library/SP/Fill.bas" #line 1 "/zxbasic/src/arch/zx48k/library-asm/pause.asm" ; The PAUSE statement (Calling the ROM) push namespace core @@ -1143,7 +1175,7 @@ __PAUSE: ld c, l jp 1F3Dh ; PAUSE_1 pop namespace -#line 557 "/zxbasic/src/arch/zx48k/library/SP/Fill.bas" +#line 558 "/zxbasic/src/arch/zx48k/library/SP/Fill.bas" #line 1 "/zxbasic/src/arch/zx48k/library-asm/usr_str.asm" ; This function just returns the address of the UDG of the given str. ; If the str is EMPTY or not a letter, 0 is returned and ERR_NR set @@ -1467,5 +1499,5 @@ USR_ERROR: ret ENDP pop namespace -#line 558 "/zxbasic/src/arch/zx48k/library/SP/Fill.bas" +#line 559 "/zxbasic/src/arch/zx48k/library/SP/Fill.bas" END diff --git a/tests/functional/zx48k/str0.asm b/tests/functional/zx48k/str0.asm index 84794f616..e440eba81 100644 --- a/tests/functional/zx48k/str0.asm +++ b/tests/functional/zx48k/str0.asm @@ -54,11 +54,12 @@ _test: push ix ld ix, 0 add ix, sp + call .core.COPY_ATTR ld l, (ix+4) ld h, (ix+5) xor a call .core.__PRINTSTR - call .core.PRINT_EOL_ATTR + call .core.PRINT_EOL ld l, (ix+4) ld h, (ix+5) push hl @@ -84,276 +85,7 @@ _test__leave: DEFW 0001h DEFB 31h ;; --- end of user code --- -#line 1 "/zxbasic/src/arch/zx48k/library-asm/free.asm" -; vim: ts=4:et:sw=4: - ; Copyleft (K) by Jose M. Rodriguez de la Rosa - ; (a.k.a. Boriel) -; http://www.boriel.com - ; - ; This ASM library is licensed under the BSD license - ; you can use it for any purpose (even for commercial - ; closed source programs). - ; - ; Please read the BSD license on the internet - ; ----- IMPLEMENTATION NOTES ------ - ; The heap is implemented as a linked list of free blocks. -; Each free block contains this info: - ; - ; +----------------+ <-- HEAP START - ; | Size (2 bytes) | - ; | 0 | <-- Size = 0 => DUMMY HEADER BLOCK - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ <-+ - ; | Size (2 bytes) | - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ | - ; | | | <-- If Size > 4, then this contains (size - 4) bytes - ; | (0 if Size = 4)| | - ; +----------------+ <-+ - ; | Size (2 bytes) | - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ | - ; | | | - ; | (0 if Size = 4)| | - ; +----------------+ | - ; | <-- This zone is in use (Already allocated) - ; +----------------+ <-+ - ; | Size (2 bytes) | - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ | - ; | | | - ; | (0 if Size = 4)| | - ; +----------------+ <-+ - ; | Next (2 bytes) |--> NULL => END OF LIST - ; | 0 = NULL | - ; +----------------+ - ; | | - ; | (0 if Size = 4)| - ; +----------------+ - ; When a block is FREED, the previous and next pointers are examined to see - ; if we can defragment the heap. If the block to be breed is just next to the - ; previous, or to the next (or both) they will be converted into a single - ; block (so defragmented). - ; MEMORY MANAGER - ; - ; This library must be initialized calling __MEM_INIT with - ; HL = BLOCK Start & DE = Length. - ; An init directive is useful for initialization routines. - ; They will be added automatically if needed. -#line 1 "/zxbasic/src/arch/zx48k/library-asm/heapinit.asm" -; vim: ts=4:et:sw=4: - ; Copyleft (K) by Jose M. Rodriguez de la Rosa - ; (a.k.a. Boriel) -; http://www.boriel.com - ; - ; This ASM library is licensed under the BSD license - ; you can use it for any purpose (even for commercial - ; closed source programs). - ; - ; Please read the BSD license on the internet - ; ----- IMPLEMENTATION NOTES ------ - ; The heap is implemented as a linked list of free blocks. -; Each free block contains this info: - ; - ; +----------------+ <-- HEAP START - ; | Size (2 bytes) | - ; | 0 | <-- Size = 0 => DUMMY HEADER BLOCK - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ <-+ - ; | Size (2 bytes) | - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ | - ; | | | <-- If Size > 4, then this contains (size - 4) bytes - ; | (0 if Size = 4)| | - ; +----------------+ <-+ - ; | Size (2 bytes) | - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ | - ; | | | - ; | (0 if Size = 4)| | - ; +----------------+ | - ; | <-- This zone is in use (Already allocated) - ; +----------------+ <-+ - ; | Size (2 bytes) | - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ | - ; | | | - ; | (0 if Size = 4)| | - ; +----------------+ <-+ - ; | Next (2 bytes) |--> NULL => END OF LIST - ; | 0 = NULL | - ; +----------------+ - ; | | - ; | (0 if Size = 4)| - ; +----------------+ - ; When a block is FREED, the previous and next pointers are examined to see - ; if we can defragment the heap. If the block to be breed is just next to the - ; previous, or to the next (or both) they will be converted into a single - ; block (so defragmented). - ; MEMORY MANAGER - ; - ; This library must be initialized calling __MEM_INIT with - ; HL = BLOCK Start & DE = Length. - ; An init directive is useful for initialization routines. - ; They will be added automatically if needed. - ; --------------------------------------------------------------------- - ; __MEM_INIT must be called to initalize this library with the - ; standard parameters - ; --------------------------------------------------------------------- - push namespace core -__MEM_INIT: ; Initializes the library using (RAMTOP) as start, and - ld hl, ZXBASIC_MEM_HEAP ; Change this with other address of heap start - ld de, ZXBASIC_HEAP_SIZE ; Change this with your size - ; --------------------------------------------------------------------- - ; __MEM_INIT2 initalizes this library -; Parameters: -; HL : Memory address of 1st byte of the memory heap -; DE : Length in bytes of the Memory Heap - ; --------------------------------------------------------------------- -__MEM_INIT2: - ; HL as TOP - PROC - dec de - dec de - dec de - dec de ; DE = length - 4; HL = start - ; This is done, because we require 4 bytes for the empty dummy-header block - xor a - ld (hl), a - inc hl - ld (hl), a ; First "free" block is a header: size=0, Pointer=&(Block) + 4 - inc hl - ld b, h - ld c, l - inc bc - inc bc ; BC = starts of next block - ld (hl), c - inc hl - ld (hl), b - inc hl ; Pointer to next block - ld (hl), e - inc hl - ld (hl), d - inc hl ; Block size (should be length - 4 at start); This block contains all the available memory - ld (hl), a ; NULL (0000h) ; No more blocks (a list with a single block) - inc hl - ld (hl), a - ld a, 201 - ld (__MEM_INIT), a; "Pokes" with a RET so ensure this routine is not called again - ret - ENDP - pop namespace -#line 69 "/zxbasic/src/arch/zx48k/library-asm/free.asm" - ; --------------------------------------------------------------------- - ; MEM_FREE - ; Frees a block of memory - ; -; Parameters: - ; HL = Pointer to the block to be freed. If HL is NULL (0) nothing - ; is done - ; --------------------------------------------------------------------- - push namespace core -MEM_FREE: -__MEM_FREE: ; Frees the block pointed by HL - ; HL DE BC & AF modified - PROC - LOCAL __MEM_LOOP2 - LOCAL __MEM_LINK_PREV - LOCAL __MEM_JOIN_TEST - LOCAL __MEM_BLOCK_JOIN - ld a, h - or l - ret z ; Return if NULL pointer - dec hl - dec hl - ld b, h - ld c, l ; BC = Block pointer - ld hl, ZXBASIC_MEM_HEAP ; This label point to the heap start -__MEM_LOOP2: - inc hl - inc hl ; Next block ptr - ld e, (hl) - inc hl - ld d, (hl) ; Block next ptr - ex de, hl ; DE = &(block->next); HL = block->next - ld a, h ; HL == NULL? - or l - jp z, __MEM_LINK_PREV; if so, link with previous - or a ; Clear carry flag - sbc hl, bc ; Carry if BC > HL => This block if before - add hl, bc ; Restores HL, preserving Carry flag - jp c, __MEM_LOOP2 ; This block is before. Keep searching PASS the block - ;------ At this point current HL is PAST BC, so we must link (DE) with BC, and HL in BC->next -__MEM_LINK_PREV: ; Link (DE) with BC, and BC->next with HL - ex de, hl - push hl - dec hl - ld (hl), c - inc hl - ld (hl), b ; (DE) <- BC - ld h, b ; HL <- BC (Free block ptr) - ld l, c - inc hl ; Skip block length (2 bytes) - inc hl - ld (hl), e ; Block->next = DE - inc hl - ld (hl), d - ; --- LINKED ; HL = &(BC->next) + 2 - call __MEM_JOIN_TEST - pop hl -__MEM_JOIN_TEST: ; Checks for fragmented contiguous blocks and joins them - ; hl = Ptr to current block + 2 - ld d, (hl) - dec hl - ld e, (hl) - dec hl - ld b, (hl) ; Loads block length into BC - dec hl - ld c, (hl) ; - push hl ; Saves it for later - add hl, bc ; Adds its length. If HL == DE now, it must be joined - or a - sbc hl, de ; If Z, then HL == DE => We must join - pop hl - ret nz -__MEM_BLOCK_JOIN: ; Joins current block (pointed by HL) with next one (pointed by DE). HL->length already in BC - push hl ; Saves it for later - ex de, hl - ld e, (hl) ; DE -> block->next->length - inc hl - ld d, (hl) - inc hl - ex de, hl ; DE = &(block->next) - add hl, bc ; HL = Total Length - ld b, h - ld c, l ; BC = Total Length - ex de, hl - ld e, (hl) - inc hl - ld d, (hl) ; DE = block->next - pop hl ; Recovers Pointer to block - ld (hl), c - inc hl - ld (hl), b ; Length Saved - inc hl - ld (hl), e - inc hl - ld (hl), d ; Next saved - ret - ENDP - pop namespace -#line 58 "zx48k/str0.bas" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/print_eol_attr.asm" - ; Calls PRINT_EOL and then COPY_ATTR, so saves - ; 3 bytes +#line 1 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" #line 1 "/zxbasic/src/arch/zx48k/library-asm/print.asm" ; vim:ts=4:sw=4:et: ; PRINT command routine @@ -703,60 +435,6 @@ BRIGHT_TMP: #line 1 "/zxbasic/src/arch/zx48k/library-asm/over.asm" ; Sets OVER flag in P_FLAG permanently ; Parameter: OVER flag in bit 0 of A register -#line 1 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" -#line 4 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" - push namespace core -COPY_ATTR: - ; Just copies current permanent attribs into temporal attribs - ; and sets print mode - PROC - LOCAL INVERSE1 - LOCAL __REFRESH_TMP - INVERSE1 EQU 02Fh - ld hl, (ATTR_P) - ld (ATTR_T), hl - ld hl, FLAGS2 - call __REFRESH_TMP - ld hl, P_FLAG - call __REFRESH_TMP -__SET_ATTR_MODE: ; Another entry to set print modes. A contains (P_FLAG) - LOCAL TABLE - LOCAL CONT2 - rra ; Over bit to carry - ld a, (FLAGS2) - rla ; Over bit in bit 1, Over2 bit in bit 2 - and 3 ; Only bit 0 and 1 (OVER flag) - ld c, a - ld b, 0 - ld hl, TABLE - add hl, bc - ld a, (hl) - ld (PRINT_MODE), a - ld hl, (P_FLAG) - xor a ; NOP -> INVERSE0 - bit 2, l - jr z, CONT2 - ld a, INVERSE1 ; CPL -> INVERSE1 -CONT2: - ld (INVERSE_MODE), a - ret -TABLE: - nop ; NORMAL MODE - xor (hl) ; OVER 1 MODE - and (hl) ; OVER 2 MODE - or (hl) ; OVER 3 MODE -#line 67 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" -__REFRESH_TMP: - ld a, (hl) - and 0b10101010 - ld c, a - rra - or c - ld (hl), a - ret - ENDP - pop namespace -#line 4 "/zxbasic/src/arch/zx48k/library-asm/over.asm" push namespace core OVER: PROC @@ -997,12 +675,11 @@ INVERSE_MODE: ; 00 -> NOP -> INVERSE 0 pop hl inc hl ld (DFCC), hl - ld hl, (DFCCL) ; current ATTR Pos - push hl - call __SET_ATTR - pop hl + ld hl, (DFCCL) ; current ATTR Pos inc hl - ld (DFCCL),hl + ld (DFCCL), hl + dec hl + call __SET_ATTR exx ret ; ------------- SPECIAL CHARS (< 32) ----------------- @@ -1021,7 +698,7 @@ __PRINT_0Dh: ; Called WHEN printing CHR$(13) push hl call __SCROLL_SCR pop hl -#line 210 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 209 "/zxbasic/src/arch/zx48k/library-asm/print.asm" 1: ld l, 1 __PRINT_EOL_END: @@ -1138,14 +815,14 @@ __PRINT_BOLD: __PRINT_BOLD2: call BOLD_TMP jp __PRINT_RESTART -#line 354 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 353 "/zxbasic/src/arch/zx48k/library-asm/print.asm" __PRINT_ITA: ld hl, __PRINT_ITA2 jp __PRINT_SET_STATE __PRINT_ITA2: call ITALIC_TMP jp __PRINT_RESTART -#line 364 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 363 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __BOLD __BOLD: push hl @@ -1158,121 +835,435 @@ __BOLD: or c ld (hl), a inc hl - inc de - djnz 1b - pop hl - ld de, MEM0 + inc de + djnz 1b + pop hl + ld de, MEM0 + ret +#line 384 "/zxbasic/src/arch/zx48k/library-asm/print.asm" + LOCAL __ITALIC +__ITALIC: + push hl + ld hl, MEM0 + ex de, hl + ld bc, 8 + ldir + ld hl, MEM0 + srl (hl) + inc hl + srl (hl) + inc hl + srl (hl) + inc hl + inc hl + inc hl + sla (hl) + inc hl + sla (hl) + inc hl + sla (hl) + pop hl + ld de, MEM0 + ret +#line 412 "/zxbasic/src/arch/zx48k/library-asm/print.asm" + LOCAL __SCROLL_SCR +#line 486 "/zxbasic/src/arch/zx48k/library-asm/print.asm" + __SCROLL_SCR EQU 0DFEh ; Use ROM SCROLL +#line 488 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 489 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +PRINT_COMMA: + call __LOAD_S_POSN + ld a, e + and 16 + add a, 16 +PRINT_TAB: + ; Tabulates the number of spaces in A register + ; If the current cursor position is already A, does nothing + PROC + LOCAL LOOP + call __LOAD_S_POSN ; e = current row + sub e + and 31 + ret z + ld b, a +LOOP: + ld a, ' ' + call __PRINTCHAR + djnz LOOP + ret + ENDP +PRINT_AT: ; Changes cursor to ROW, COL + ; COL in A register + ; ROW in stack + pop hl ; Ret address + ex (sp), hl ; callee H = ROW + ld l, a + ex de, hl + call __IN_SCREEN + ret nc ; Return if out of screen + jp __SAVE_S_POSN + LOCAL __PRINT_COM + LOCAL __PRINT_AT1 + LOCAL __PRINT_AT2 + LOCAL __PRINT_BOLD + LOCAL __PRINT_ITA + LOCAL __PRINT_INK + LOCAL __PRINT_PAP + LOCAL __PRINT_SET_STATE + LOCAL __PRINT_TABLE + LOCAL __PRINT_TAB, __PRINT_TAB1, __PRINT_TAB2 + LOCAL __PRINT_ITA2 +#line 545 "/zxbasic/src/arch/zx48k/library-asm/print.asm" + LOCAL __PRINT_BOLD2 +#line 551 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +__PRINT_TABLE: ; Jump table for 0 .. 22 codes + DW __PRINT_NOP ; 0 + DW __PRINT_NOP ; 1 + DW __PRINT_NOP ; 2 + DW __PRINT_NOP ; 3 + DW __PRINT_NOP ; 4 + DW __PRINT_NOP ; 5 + DW __PRINT_COM ; 6 COMMA + DW __PRINT_NOP ; 7 + DW __PRINT_DEL ; 8 DEL + DW __PRINT_NOP ; 9 + DW __PRINT_NOP ; 10 + DW __PRINT_NOP ; 11 + DW __PRINT_NOP ; 12 + DW __PRINT_0Dh ; 13 + DW __PRINT_BOLD ; 14 + DW __PRINT_ITA ; 15 + DW __PRINT_INK ; 16 + DW __PRINT_PAP ; 17 + DW __PRINT_FLA ; 18 + DW __PRINT_BRI ; 19 + DW __PRINT_INV ; 20 + DW __PRINT_OVR ; 21 + DW __PRINT_AT ; 22 AT + DW __PRINT_TAB ; 23 TAB + ENDP + pop namespace +#line 3 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" +#line 4 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" + push namespace core +COPY_ATTR: + ; Just copies current permanent attribs into temporal attribs + ; and sets print mode + PROC + LOCAL INVERSE1 + LOCAL __REFRESH_TMP + INVERSE1 EQU 02Fh + ld hl, (ATTR_P) + ld (ATTR_T), hl + ld hl, FLAGS2 + call __REFRESH_TMP + ld hl, P_FLAG + call __REFRESH_TMP +__SET_ATTR_MODE: ; Another entry to set print modes. A contains (P_FLAG) + LOCAL TABLE + LOCAL CONT2 + rra ; Over bit to carry + ld a, (FLAGS2) + rla ; Over bit in bit 1, Over2 bit in bit 2 + and 3 ; Only bit 0 and 1 (OVER flag) + ld c, a + ld b, 0 + ld hl, TABLE + add hl, bc + ld a, (hl) + ld (PRINT_MODE), a + ld hl, (P_FLAG) + xor a ; NOP -> INVERSE0 + bit 2, l + jr z, CONT2 + ld a, INVERSE1 ; CPL -> INVERSE1 +CONT2: + ld (INVERSE_MODE), a + ret +TABLE: + nop ; NORMAL MODE + xor (hl) ; OVER 1 MODE + and (hl) ; OVER 2 MODE + or (hl) ; OVER 3 MODE +#line 67 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" +__REFRESH_TMP: + ld a, (hl) + and 0b10101010 + ld c, a + rra + or c + ld (hl), a + ret + ENDP + pop namespace +#line 59 "zx48k/str0.bas" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/free.asm" +; vim: ts=4:et:sw=4: + ; Copyleft (K) by Jose M. Rodriguez de la Rosa + ; (a.k.a. Boriel) +; http://www.boriel.com + ; + ; This ASM library is licensed under the BSD license + ; you can use it for any purpose (even for commercial + ; closed source programs). + ; + ; Please read the BSD license on the internet + ; ----- IMPLEMENTATION NOTES ------ + ; The heap is implemented as a linked list of free blocks. +; Each free block contains this info: + ; + ; +----------------+ <-- HEAP START + ; | Size (2 bytes) | + ; | 0 | <-- Size = 0 => DUMMY HEADER BLOCK + ; +----------------+ + ; | Next (2 bytes) |---+ + ; +----------------+ <-+ + ; | Size (2 bytes) | + ; +----------------+ + ; | Next (2 bytes) |---+ + ; +----------------+ | + ; | | | <-- If Size > 4, then this contains (size - 4) bytes + ; | (0 if Size = 4)| | + ; +----------------+ <-+ + ; | Size (2 bytes) | + ; +----------------+ + ; | Next (2 bytes) |---+ + ; +----------------+ | + ; | | | + ; | (0 if Size = 4)| | + ; +----------------+ | + ; | <-- This zone is in use (Already allocated) + ; +----------------+ <-+ + ; | Size (2 bytes) | + ; +----------------+ + ; | Next (2 bytes) |---+ + ; +----------------+ | + ; | | | + ; | (0 if Size = 4)| | + ; +----------------+ <-+ + ; | Next (2 bytes) |--> NULL => END OF LIST + ; | 0 = NULL | + ; +----------------+ + ; | | + ; | (0 if Size = 4)| + ; +----------------+ + ; When a block is FREED, the previous and next pointers are examined to see + ; if we can defragment the heap. If the block to be breed is just next to the + ; previous, or to the next (or both) they will be converted into a single + ; block (so defragmented). + ; MEMORY MANAGER + ; + ; This library must be initialized calling __MEM_INIT with + ; HL = BLOCK Start & DE = Length. + ; An init directive is useful for initialization routines. + ; They will be added automatically if needed. +#line 1 "/zxbasic/src/arch/zx48k/library-asm/heapinit.asm" +; vim: ts=4:et:sw=4: + ; Copyleft (K) by Jose M. Rodriguez de la Rosa + ; (a.k.a. Boriel) +; http://www.boriel.com + ; + ; This ASM library is licensed under the BSD license + ; you can use it for any purpose (even for commercial + ; closed source programs). + ; + ; Please read the BSD license on the internet + ; ----- IMPLEMENTATION NOTES ------ + ; The heap is implemented as a linked list of free blocks. +; Each free block contains this info: + ; + ; +----------------+ <-- HEAP START + ; | Size (2 bytes) | + ; | 0 | <-- Size = 0 => DUMMY HEADER BLOCK + ; +----------------+ + ; | Next (2 bytes) |---+ + ; +----------------+ <-+ + ; | Size (2 bytes) | + ; +----------------+ + ; | Next (2 bytes) |---+ + ; +----------------+ | + ; | | | <-- If Size > 4, then this contains (size - 4) bytes + ; | (0 if Size = 4)| | + ; +----------------+ <-+ + ; | Size (2 bytes) | + ; +----------------+ + ; | Next (2 bytes) |---+ + ; +----------------+ | + ; | | | + ; | (0 if Size = 4)| | + ; +----------------+ | + ; | <-- This zone is in use (Already allocated) + ; +----------------+ <-+ + ; | Size (2 bytes) | + ; +----------------+ + ; | Next (2 bytes) |---+ + ; +----------------+ | + ; | | | + ; | (0 if Size = 4)| | + ; +----------------+ <-+ + ; | Next (2 bytes) |--> NULL => END OF LIST + ; | 0 = NULL | + ; +----------------+ + ; | | + ; | (0 if Size = 4)| + ; +----------------+ + ; When a block is FREED, the previous and next pointers are examined to see + ; if we can defragment the heap. If the block to be breed is just next to the + ; previous, or to the next (or both) they will be converted into a single + ; block (so defragmented). + ; MEMORY MANAGER + ; + ; This library must be initialized calling __MEM_INIT with + ; HL = BLOCK Start & DE = Length. + ; An init directive is useful for initialization routines. + ; They will be added automatically if needed. + ; --------------------------------------------------------------------- + ; __MEM_INIT must be called to initalize this library with the + ; standard parameters + ; --------------------------------------------------------------------- + push namespace core +__MEM_INIT: ; Initializes the library using (RAMTOP) as start, and + ld hl, ZXBASIC_MEM_HEAP ; Change this with other address of heap start + ld de, ZXBASIC_HEAP_SIZE ; Change this with your size + ; --------------------------------------------------------------------- + ; __MEM_INIT2 initalizes this library +; Parameters: +; HL : Memory address of 1st byte of the memory heap +; DE : Length in bytes of the Memory Heap + ; --------------------------------------------------------------------- +__MEM_INIT2: + ; HL as TOP + PROC + dec de + dec de + dec de + dec de ; DE = length - 4; HL = start + ; This is done, because we require 4 bytes for the empty dummy-header block + xor a + ld (hl), a + inc hl + ld (hl), a ; First "free" block is a header: size=0, Pointer=&(Block) + 4 + inc hl + ld b, h + ld c, l + inc bc + inc bc ; BC = starts of next block + ld (hl), c + inc hl + ld (hl), b + inc hl ; Pointer to next block + ld (hl), e + inc hl + ld (hl), d + inc hl ; Block size (should be length - 4 at start); This block contains all the available memory + ld (hl), a ; NULL (0000h) ; No more blocks (a list with a single block) + inc hl + ld (hl), a + ld a, 201 + ld (__MEM_INIT), a; "Pokes" with a RET so ensure this routine is not called again ret -#line 385 "/zxbasic/src/arch/zx48k/library-asm/print.asm" - LOCAL __ITALIC -__ITALIC: - push hl - ld hl, MEM0 + ENDP + pop namespace +#line 69 "/zxbasic/src/arch/zx48k/library-asm/free.asm" + ; --------------------------------------------------------------------- + ; MEM_FREE + ; Frees a block of memory + ; +; Parameters: + ; HL = Pointer to the block to be freed. If HL is NULL (0) nothing + ; is done + ; --------------------------------------------------------------------- + push namespace core +MEM_FREE: +__MEM_FREE: ; Frees the block pointed by HL + ; HL DE BC & AF modified + PROC + LOCAL __MEM_LOOP2 + LOCAL __MEM_LINK_PREV + LOCAL __MEM_JOIN_TEST + LOCAL __MEM_BLOCK_JOIN + ld a, h + or l + ret z ; Return if NULL pointer + dec hl + dec hl + ld b, h + ld c, l ; BC = Block pointer + ld hl, ZXBASIC_MEM_HEAP ; This label point to the heap start +__MEM_LOOP2: + inc hl + inc hl ; Next block ptr + ld e, (hl) + inc hl + ld d, (hl) ; Block next ptr + ex de, hl ; DE = &(block->next); HL = block->next + ld a, h ; HL == NULL? + or l + jp z, __MEM_LINK_PREV; if so, link with previous + or a ; Clear carry flag + sbc hl, bc ; Carry if BC > HL => This block if before + add hl, bc ; Restores HL, preserving Carry flag + jp c, __MEM_LOOP2 ; This block is before. Keep searching PASS the block + ;------ At this point current HL is PAST BC, so we must link (DE) with BC, and HL in BC->next +__MEM_LINK_PREV: ; Link (DE) with BC, and BC->next with HL ex de, hl - ld bc, 8 - ldir - ld hl, MEM0 - srl (hl) + push hl + dec hl + ld (hl), c inc hl - srl (hl) + ld (hl), b ; (DE) <- BC + ld h, b ; HL <- BC (Free block ptr) + ld l, c + inc hl ; Skip block length (2 bytes) inc hl - srl (hl) + ld (hl), e ; Block->next = DE inc hl + ld (hl), d + ; --- LINKED ; HL = &(BC->next) + 2 + call __MEM_JOIN_TEST + pop hl +__MEM_JOIN_TEST: ; Checks for fragmented contiguous blocks and joins them + ; hl = Ptr to current block + 2 + ld d, (hl) + dec hl + ld e, (hl) + dec hl + ld b, (hl) ; Loads block length into BC + dec hl + ld c, (hl) ; + push hl ; Saves it for later + add hl, bc ; Adds its length. If HL == DE now, it must be joined + or a + sbc hl, de ; If Z, then HL == DE => We must join + pop hl + ret nz +__MEM_BLOCK_JOIN: ; Joins current block (pointed by HL) with next one (pointed by DE). HL->length already in BC + push hl ; Saves it for later + ex de, hl + ld e, (hl) ; DE -> block->next->length inc hl + ld d, (hl) inc hl - sla (hl) + ex de, hl ; DE = &(block->next) + add hl, bc ; HL = Total Length + ld b, h + ld c, l ; BC = Total Length + ex de, hl + ld e, (hl) inc hl - sla (hl) + ld d, (hl) ; DE = block->next + pop hl ; Recovers Pointer to block + ld (hl), c inc hl - sla (hl) - pop hl - ld de, MEM0 - ret -#line 413 "/zxbasic/src/arch/zx48k/library-asm/print.asm" - LOCAL __SCROLL_SCR -#line 487 "/zxbasic/src/arch/zx48k/library-asm/print.asm" - __SCROLL_SCR EQU 0DFEh ; Use ROM SCROLL -#line 489 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -#line 490 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -PRINT_COMMA: - call __LOAD_S_POSN - ld a, e - and 16 - add a, 16 -PRINT_TAB: - ; Tabulates the number of spaces in A register - ; If the current cursor position is already A, does nothing - PROC - LOCAL LOOP - call __LOAD_S_POSN ; e = current row - sub e - and 31 - ret z - ld b, a -LOOP: - ld a, ' ' - call __PRINTCHAR - djnz LOOP + ld (hl), b ; Length Saved + inc hl + ld (hl), e + inc hl + ld (hl), d ; Next saved ret ENDP -PRINT_AT: ; Changes cursor to ROW, COL - ; COL in A register - ; ROW in stack - pop hl ; Ret address - ex (sp), hl ; callee H = ROW - ld l, a - ex de, hl - call __IN_SCREEN - ret nc ; Return if out of screen - jp __SAVE_S_POSN - LOCAL __PRINT_COM - LOCAL __PRINT_AT1 - LOCAL __PRINT_AT2 - LOCAL __PRINT_BOLD - LOCAL __PRINT_ITA - LOCAL __PRINT_INK - LOCAL __PRINT_PAP - LOCAL __PRINT_SET_STATE - LOCAL __PRINT_TABLE - LOCAL __PRINT_TAB, __PRINT_TAB1, __PRINT_TAB2 - LOCAL __PRINT_ITA2 -#line 546 "/zxbasic/src/arch/zx48k/library-asm/print.asm" - LOCAL __PRINT_BOLD2 -#line 552 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -__PRINT_TABLE: ; Jump table for 0 .. 22 codes - DW __PRINT_NOP ; 0 - DW __PRINT_NOP ; 1 - DW __PRINT_NOP ; 2 - DW __PRINT_NOP ; 3 - DW __PRINT_NOP ; 4 - DW __PRINT_NOP ; 5 - DW __PRINT_COM ; 6 COMMA - DW __PRINT_NOP ; 7 - DW __PRINT_DEL ; 8 DEL - DW __PRINT_NOP ; 9 - DW __PRINT_NOP ; 10 - DW __PRINT_NOP ; 11 - DW __PRINT_NOP ; 12 - DW __PRINT_0Dh ; 13 - DW __PRINT_BOLD ; 14 - DW __PRINT_ITA ; 15 - DW __PRINT_INK ; 16 - DW __PRINT_PAP ; 17 - DW __PRINT_FLA ; 18 - DW __PRINT_BRI ; 19 - DW __PRINT_INV ; 20 - DW __PRINT_OVR ; 21 - DW __PRINT_AT ; 22 AT - DW __PRINT_TAB ; 23 TAB - ENDP - pop namespace -#line 5 "/zxbasic/src/arch/zx48k/library-asm/print_eol_attr.asm" - push namespace core -PRINT_EOL_ATTR: - call PRINT_EOL - jp COPY_ATTR pop namespace -#line 59 "zx48k/str0.bas" +#line 60 "zx48k/str0.bas" #line 1 "/zxbasic/src/arch/zx48k/library-asm/printstr.asm" ; PRINT command routine ; Prints string pointed by HL @@ -1316,7 +1307,7 @@ __PRINT_STR: jp __PRINT_STR_LOOP ENDP pop namespace -#line 60 "zx48k/str0.bas" +#line 62 "zx48k/str0.bas" #line 1 "/zxbasic/src/arch/zx48k/library-asm/str.asm" ; The STR$( ) BASIC function implementation ; Given a FP number in C ED LH @@ -1571,7 +1562,7 @@ __STR_END: STK_END EQU 5C65h ENDP pop namespace -#line 61 "zx48k/str0.bas" +#line 63 "zx48k/str0.bas" #line 1 "/zxbasic/src/arch/zx48k/library-asm/strcat.asm" #line 1 "/zxbasic/src/arch/zx48k/library-asm/strlen.asm" ; Returns len if a string @@ -1684,7 +1675,7 @@ __STRCATEND: ret ENDP pop namespace -#line 62 "zx48k/str0.bas" +#line 64 "zx48k/str0.bas" #line 1 "/zxbasic/src/arch/zx48k/library-asm/u32tofreg.asm" #line 1 "/zxbasic/src/arch/zx48k/library-asm/neg32.asm" push namespace core @@ -1781,5 +1772,5 @@ __U32TOFREG_END: ret ENDP pop namespace -#line 63 "zx48k/str0.bas" +#line 65 "zx48k/str0.bas" END diff --git a/tests/functional/zx48k/strbase2.asm b/tests/functional/zx48k/strbase2.asm index 13d651336..19ed3d493 100644 --- a/tests/functional/zx48k/strbase2.asm +++ b/tests/functional/zx48k/strbase2.asm @@ -54,14 +54,16 @@ _b: ex de, hl ld hl, _b call .core.__STORE_STR2 + call .core.COPY_ATTR ld hl, (_a) xor a call .core.__PRINTSTR - call .core.PRINT_EOL_ATTR + call .core.PRINT_EOL + call .core.COPY_ATTR ld hl, (_b) xor a call .core.__PRINTSTR - call .core.PRINT_EOL_ATTR + call .core.PRINT_EOL ld hl, 0 ld b, h ld c, l @@ -86,747 +88,865 @@ _b: DEFW 0001h DEFB 6Fh ;; --- end of user code --- -#line 1 "/zxbasic/src/arch/zx48k/library-asm/letsubstr.asm" - ; Substring assigment eg. LET a$(p0 TO p1) = "xxxx" - ; HL = Start of string - ; TOP of the stack -> p1 (16 bit, unsigned) - ; TOP -1 of the stack -> p0 register - ; TOP -2 Flag (popped out in A register) - ; A Register => 0 if HL is not freed from memory - ; => Not 0 if HL must be freed from memory on exit - ; TOP -3 B$ address -#line 1 "/zxbasic/src/arch/zx48k/library-asm/free.asm" -; vim: ts=4:et:sw=4: - ; Copyleft (K) by Jose M. Rodriguez de la Rosa - ; (a.k.a. Boriel) -; http://www.boriel.com - ; - ; This ASM library is licensed under the BSD license - ; you can use it for any purpose (even for commercial - ; closed source programs). - ; - ; Please read the BSD license on the internet - ; ----- IMPLEMENTATION NOTES ------ - ; The heap is implemented as a linked list of free blocks. -; Each free block contains this info: - ; - ; +----------------+ <-- HEAP START - ; | Size (2 bytes) | - ; | 0 | <-- Size = 0 => DUMMY HEADER BLOCK - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ <-+ - ; | Size (2 bytes) | - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ | - ; | | | <-- If Size > 4, then this contains (size - 4) bytes - ; | (0 if Size = 4)| | - ; +----------------+ <-+ - ; | Size (2 bytes) | - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ | - ; | | | - ; | (0 if Size = 4)| | - ; +----------------+ | - ; | <-- This zone is in use (Already allocated) - ; +----------------+ <-+ - ; | Size (2 bytes) | - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ | - ; | | | - ; | (0 if Size = 4)| | - ; +----------------+ <-+ - ; | Next (2 bytes) |--> NULL => END OF LIST - ; | 0 = NULL | - ; +----------------+ - ; | | - ; | (0 if Size = 4)| - ; +----------------+ - ; When a block is FREED, the previous and next pointers are examined to see - ; if we can defragment the heap. If the block to be breed is just next to the - ; previous, or to the next (or both) they will be converted into a single - ; block (so defragmented). - ; MEMORY MANAGER - ; - ; This library must be initialized calling __MEM_INIT with - ; HL = BLOCK Start & DE = Length. - ; An init directive is useful for initialization routines. - ; They will be added automatically if needed. -#line 1 "/zxbasic/src/arch/zx48k/library-asm/heapinit.asm" -; vim: ts=4:et:sw=4: - ; Copyleft (K) by Jose M. Rodriguez de la Rosa - ; (a.k.a. Boriel) -; http://www.boriel.com - ; - ; This ASM library is licensed under the BSD license - ; you can use it for any purpose (even for commercial - ; closed source programs). - ; - ; Please read the BSD license on the internet - ; ----- IMPLEMENTATION NOTES ------ - ; The heap is implemented as a linked list of free blocks. -; Each free block contains this info: - ; - ; +----------------+ <-- HEAP START - ; | Size (2 bytes) | - ; | 0 | <-- Size = 0 => DUMMY HEADER BLOCK - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ <-+ - ; | Size (2 bytes) | - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ | - ; | | | <-- If Size > 4, then this contains (size - 4) bytes - ; | (0 if Size = 4)| | - ; +----------------+ <-+ - ; | Size (2 bytes) | - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ | - ; | | | - ; | (0 if Size = 4)| | - ; +----------------+ | - ; | <-- This zone is in use (Already allocated) - ; +----------------+ <-+ - ; | Size (2 bytes) | - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ | - ; | | | - ; | (0 if Size = 4)| | - ; +----------------+ <-+ - ; | Next (2 bytes) |--> NULL => END OF LIST - ; | 0 = NULL | - ; +----------------+ - ; | | - ; | (0 if Size = 4)| - ; +----------------+ - ; When a block is FREED, the previous and next pointers are examined to see - ; if we can defragment the heap. If the block to be breed is just next to the - ; previous, or to the next (or both) they will be converted into a single - ; block (so defragmented). - ; MEMORY MANAGER - ; - ; This library must be initialized calling __MEM_INIT with - ; HL = BLOCK Start & DE = Length. - ; An init directive is useful for initialization routines. - ; They will be added automatically if needed. - ; --------------------------------------------------------------------- - ; __MEM_INIT must be called to initalize this library with the - ; standard parameters - ; --------------------------------------------------------------------- +#line 1 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +; vim:ts=4:sw=4:et: + ; PRINT command routine + ; Does not print attribute. Use PRINT_STR or PRINT_NUM for that +#line 1 "/zxbasic/src/arch/zx48k/library-asm/sposn.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/sysvars.asm" + ;; ----------------------------------------------------------------------- + ;; ZX Basic System Vars + ;; Some of them will be mapped over Sinclair ROM ones for compatibility + ;; ----------------------------------------------------------------------- + push namespace core +SCREEN_ADDR: DW 16384 ; Screen address (can be pointed to other place to use a screen buffer) +SCREEN_ATTR_ADDR: DW 22528 ; Screen attribute address (ditto.) + ; These are mapped onto ZX Spectrum ROM VARS + CHARS EQU 23606 ; Pointer to ROM/RAM Charset + TVFLAGS EQU 23612 ; TV Flags + UDG EQU 23675 ; Pointer to UDG Charset + COORDS EQU 23677 ; Last PLOT coordinates + FLAGS2 EQU 23681 ; + ECHO_E EQU 23682 ; + DFCC EQU 23684 ; Next screen addr for PRINT + DFCCL EQU 23686 ; Next screen attr for PRINT + S_POSN EQU 23688 + ATTR_P EQU 23693 ; Current Permanent ATTRS set with INK, PAPER, etc commands + ATTR_T EQU 23695 ; temporary ATTRIBUTES + P_FLAG EQU 23697 ; + MEM0 EQU 23698 ; Temporary memory buffer used by ROM chars + SCR_COLS EQU 33 ; Screen with in columns + 1 + SCR_ROWS EQU 24 ; Screen height in rows + SCR_SIZE EQU (SCR_ROWS << 8) + SCR_COLS + pop namespace +#line 2 "/zxbasic/src/arch/zx48k/library-asm/sposn.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/attr.asm" + ; Attribute routines +; vim:ts=4:et:sw: +#line 1 "/zxbasic/src/arch/zx48k/library-asm/error.asm" + ; Simple error control routines +; vim:ts=4:et: push namespace core -__MEM_INIT: ; Initializes the library using (RAMTOP) as start, and - ld hl, ZXBASIC_MEM_HEAP ; Change this with other address of heap start - ld de, ZXBASIC_HEAP_SIZE ; Change this with your size - ; --------------------------------------------------------------------- - ; __MEM_INIT2 initalizes this library -; Parameters: -; HL : Memory address of 1st byte of the memory heap -; DE : Length in bytes of the Memory Heap - ; --------------------------------------------------------------------- -__MEM_INIT2: - ; HL as TOP + ERR_NR EQU 23610 ; Error code system variable + ; Error code definitions (as in ZX spectrum manual) +; Set error code with: + ; ld a, ERROR_CODE + ; ld (ERR_NR), a + ERROR_Ok EQU -1 + ERROR_SubscriptWrong EQU 2 + ERROR_OutOfMemory EQU 3 + ERROR_OutOfScreen EQU 4 + ERROR_NumberTooBig EQU 5 + ERROR_InvalidArg EQU 9 + ERROR_IntOutOfRange EQU 10 + ERROR_NonsenseInBasic EQU 11 + ERROR_InvalidFileName EQU 14 + ERROR_InvalidColour EQU 19 + ERROR_BreakIntoProgram EQU 20 + ERROR_TapeLoadingErr EQU 26 + ; Raises error using RST #8 +__ERROR: + ld (__ERROR_CODE), a + rst 8 +__ERROR_CODE: + nop + ret + ; Sets the error system variable, but keeps running. + ; Usually this instruction if followed by the END intermediate instruction. +__STOP: + ld (ERR_NR), a + ret + pop namespace +#line 6 "/zxbasic/src/arch/zx48k/library-asm/attr.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/in_screen.asm" + push namespace core +__IN_SCREEN: + ; Returns NO carry if current coords (D, E) + ; are OUT of the screen limits PROC - dec de - dec de - dec de - dec de ; DE = length - 4; HL = start - ; This is done, because we require 4 bytes for the empty dummy-header block - xor a - ld (hl), a - inc hl - ld (hl), a ; First "free" block is a header: size=0, Pointer=&(Block) + 4 - inc hl - ld b, h - ld c, l - inc bc - inc bc ; BC = starts of next block - ld (hl), c - inc hl - ld (hl), b - inc hl ; Pointer to next block - ld (hl), e - inc hl - ld (hl), d - inc hl ; Block size (should be length - 4 at start); This block contains all the available memory - ld (hl), a ; NULL (0000h) ; No more blocks (a list with a single block) - inc hl - ld (hl), a - ld a, 201 - ld (__MEM_INIT), a; "Pokes" with a RET so ensure this routine is not called again + LOCAL __IN_SCREEN_ERR + ld hl, SCR_SIZE + ld a, e + cp l + jr nc, __IN_SCREEN_ERR ; Do nothing and return if out of range + ld a, d + cp h + ret c ; Return if carry (OK) +__IN_SCREEN_ERR: +__OUT_OF_SCREEN_ERR: + ; Jumps here if out of screen + ld a, ERROR_OutOfScreen + jp __STOP ; Saves error code and exits + ENDP + pop namespace +#line 7 "/zxbasic/src/arch/zx48k/library-asm/attr.asm" + push namespace core +__ATTR_ADDR: + ; calc start address in DE (as (32 * d) + e) + ; Contributed by Santiago Romero at http://www.speccy.org + ld h, 0 ; 7 T-States + ld a, d ; 4 T-States + ld d, h + add a, a ; a * 2 ; 4 T-States + add a, a ; a * 4 ; 4 T-States + ld l, a ; HL = A * 4 ; 4 T-States + add hl, hl ; HL = A * 8 ; 15 T-States + add hl, hl ; HL = A * 16 ; 15 T-States + add hl, hl ; HL = A * 32 ; 15 T-States + add hl, de + ld de, (SCREEN_ATTR_ADDR) ; Adds the screen address + add hl, de + ; Return current screen address in HL + ret + ; Sets the attribute at a given screen coordinate (D, E). + ; The attribute is taken from the ATTR_T memory variable + ; Used by PRINT routines +SET_ATTR: + ; Checks for valid coords + call __IN_SCREEN + ret nc + call __ATTR_ADDR +__SET_ATTR: + ; Internal __FASTCALL__ Entry used by printing routines + ; HL contains the address of the ATTR cell to set + PROC +__SET_ATTR2: ; Sets attr from ATTR_T to (HL) which points to the scr address + ld de, (ATTR_T) ; E = ATTR_T, D = MASK_T + ld a, d + and (hl) + ld c, a ; C = current screen color, masked + ld a, d + cpl ; Negate mask + and e ; Mask current attributes + or c ; Mix them + ld (hl), a ; Store result in screen + ret + ENDP + pop namespace +#line 3 "/zxbasic/src/arch/zx48k/library-asm/sposn.asm" + ; Printing positioning library. + push namespace core + ; Loads into DE current ROW, COL print position from S_POSN mem var. +__LOAD_S_POSN: + PROC + ld de, (S_POSN) + ld hl, SCR_SIZE + or a + sbc hl, de + ex de, hl + ret + ENDP + ; Saves ROW, COL from DE into S_POSN mem var. +__SAVE_S_POSN: + PROC + ld hl, SCR_SIZE + or a + sbc hl, de + ld (S_POSN), hl ; saves it again +__SET_SCR_PTR: ;; Fast + push de + call __ATTR_ADDR + ld (DFCCL), hl + pop de + ld a, d + ld c, a ; Saves it for later + and 0F8h ; Masks 3 lower bit ; zy + ld d, a + ld a, c ; Recovers it + and 07h ; MOD 7 ; y1 + rrca + rrca + rrca + or e + ld e, a + ld hl, (SCREEN_ADDR) + add hl, de ; HL = Screen address + DE + ld (DFCC), hl ret ENDP pop namespace -#line 69 "/zxbasic/src/arch/zx48k/library-asm/free.asm" - ; --------------------------------------------------------------------- - ; MEM_FREE - ; Frees a block of memory - ; -; Parameters: - ; HL = Pointer to the block to be freed. If HL is NULL (0) nothing - ; is done - ; --------------------------------------------------------------------- +#line 6 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/table_jump.asm" push namespace core -MEM_FREE: -__MEM_FREE: ; Frees the block pointed by HL - ; HL DE BC & AF modified - PROC - LOCAL __MEM_LOOP2 - LOCAL __MEM_LINK_PREV - LOCAL __MEM_JOIN_TEST - LOCAL __MEM_BLOCK_JOIN - ld a, h - or l - ret z ; Return if NULL pointer - dec hl - dec hl - ld b, h - ld c, l ; BC = Block pointer - ld hl, ZXBASIC_MEM_HEAP ; This label point to the heap start -__MEM_LOOP2: - inc hl - inc hl ; Next block ptr - ld e, (hl) - inc hl - ld d, (hl) ; Block next ptr - ex de, hl ; DE = &(block->next); HL = block->next - ld a, h ; HL == NULL? - or l - jp z, __MEM_LINK_PREV; if so, link with previous - or a ; Clear carry flag - sbc hl, bc ; Carry if BC > HL => This block if before - add hl, bc ; Restores HL, preserving Carry flag - jp c, __MEM_LOOP2 ; This block is before. Keep searching PASS the block - ;------ At this point current HL is PAST BC, so we must link (DE) with BC, and HL in BC->next -__MEM_LINK_PREV: ; Link (DE) with BC, and BC->next with HL - ex de, hl - push hl - dec hl - ld (hl), c - inc hl - ld (hl), b ; (DE) <- BC - ld h, b ; HL <- BC (Free block ptr) - ld l, c - inc hl ; Skip block length (2 bytes) - inc hl - ld (hl), e ; Block->next = DE - inc hl - ld (hl), d - ; --- LINKED ; HL = &(BC->next) + 2 - call __MEM_JOIN_TEST - pop hl -__MEM_JOIN_TEST: ; Checks for fragmented contiguous blocks and joins them - ; hl = Ptr to current block + 2 - ld d, (hl) - dec hl +JUMP_HL_PLUS_2A: ; Does JP (HL + A*2) Modifies DE. Modifies A + add a, a +JUMP_HL_PLUS_A: ; Does JP (HL + A) Modifies DE + ld e, a + ld d, 0 +JUMP_HL_PLUS_DE: ; Does JP (HL + DE) + add hl, de ld e, (hl) - dec hl - ld b, (hl) ; Loads block length into BC - dec hl - ld c, (hl) ; - push hl ; Saves it for later - add hl, bc ; Adds its length. If HL == DE now, it must be joined - or a - sbc hl, de ; If Z, then HL == DE => We must join - pop hl - ret nz -__MEM_BLOCK_JOIN: ; Joins current block (pointed by HL) with next one (pointed by DE). HL->length already in BC - push hl ; Saves it for later - ex de, hl - ld e, (hl) ; DE -> block->next->length inc hl ld d, (hl) - inc hl - ex de, hl ; DE = &(block->next) - add hl, bc ; HL = Total Length - ld b, h - ld c, l ; BC = Total Length ex de, hl - ld e, (hl) - inc hl - ld d, (hl) ; DE = block->next - pop hl ; Recovers Pointer to block - ld (hl), c - inc hl - ld (hl), b ; Length Saved - inc hl - ld (hl), e - inc hl - ld (hl), d ; Next saved - ret - ENDP +CALL_HL: + jp (hl) pop namespace -#line 11 "/zxbasic/src/arch/zx48k/library-asm/letsubstr.asm" +#line 8 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/ink.asm" + ; Sets ink color in ATTR_P permanently +; Parameter: Paper color in A register push namespace core -__LETSUBSTR: +INK: PROC - LOCAL __CONT0 - LOCAL __CONT1 - LOCAL __CONT2 - LOCAL __FREE_STR - exx - pop hl ; Return address - pop de ; p1 - pop bc ; p0 - exx - pop af ; Flag - ex af, af' ; Save it for later - pop de ; B$ - exx - push hl ; push ret addr back - exx - push de ; B$ addr to be freed upon return (if A != 0) - ld a, h - or l - jp z, __FREE_STR ; Return if null - ld c, (hl) - inc hl - ld b, (hl) ; BC = Str length - inc hl ; HL = String start - push bc - exx - ex de, hl - or a - sbc hl, bc ; HL = Length of string requested by user - inc hl ; len (a$(p0 TO p1)) = p1 - p0 + 1 - ex de, hl ; Saves it in DE - pop hl ; HL = String length - exx - jp c, __FREE_STR ; Return if p0 > p1 - exx - or a - sbc hl, bc ; P0 >= String length? - exx - jp z, __FREE_STR ; Return if equal - jp c, __FREE_STR ; Return if greater - exx - add hl, bc ; Add it back - sbc hl, de ; Length of substring > string => Truncate it - add hl, de ; add it back - jr nc, __CONT0 ; Length of substring within a$ - ld d, h - ld e, l ; Truncate length of substring to fit within the strlen -__CONT0: ; At this point DE = Length of substring to copy - ; BC = start of char to copy - push de - push bc - exx - pop bc - add hl, bc ; Start address (within a$) so copy from b$ (in DE) - push hl - exx - pop hl ; Start address (within a$) so copy from b$ (in DE) - ld b, d ; Length of string - ld c, e - ld (hl), ' ' - ld d, h - ld e, l - inc de - dec bc - ld a, b - or c - jr z, __CONT2 - ; At this point HL = DE = Start of Write zone in a$ - ; BC = Number of chars to write - ldir -__CONT2: - pop bc ; Recovers Length of string to copy - exx - ex de, hl ; HL = Source, DE = Target - ld a, h - or l - jp z, __FREE_STR ; Return if B$ is NULL - ld c, (hl) - inc hl - ld b, (hl) - inc hl - ld a, b - or c - jp z, __FREE_STR ; Return if len(b$) = 0 - ; Now if len(b$) < len(char to copy), copy only len(b$) chars - push de - push hl - push bc - exx - pop hl ; LEN (b$) - or a - sbc hl, bc - add hl, bc - jr nc, __CONT1 - ; If len(b$) < len(to copy) - ld b, h ; BC = len(to copy) - ld c, l -__CONT1: - pop hl - pop de - ldir ; Copy b$ into a$(x to y) -__FREE_STR: - pop hl - ex af, af' - or a ; If not 0, free - jp nz, __MEM_FREE + LOCAL __SET_INK + LOCAL __SET_INK2 + ld de, ATTR_P +__SET_INK: + cp 8 + jr nz, __SET_INK2 + inc de ; Points DE to MASK_T or MASK_P + ld a, (de) + or 7 ; Set bits 0,1,2 to enable transparency + ld (de), a + ret +__SET_INK2: + ; Another entry. This will set the ink color at location pointer by DE + and 7 ; # Gets color mod 8 + ld b, a ; Saves the color + ld a, (de) + and 0F8h ; Clears previous value + or b + ld (de), a + inc de ; Points DE to MASK_T or MASK_P + ld a, (de) + and 0F8h ; Reset bits 0,1,2 sign to disable transparency + ld (de), a ; Store new attr + ret + ; Sets the INK color passed in A register in the ATTR_T variable +INK_TMP: + ld de, ATTR_T + jp __SET_INK + ENDP + pop namespace +#line 9 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/paper.asm" + ; Sets paper color in ATTR_P permanently +; Parameter: Paper color in A register + push namespace core +PAPER: + PROC + LOCAL __SET_PAPER + LOCAL __SET_PAPER2 + ld de, ATTR_P +__SET_PAPER: + cp 8 + jr nz, __SET_PAPER2 + inc de + ld a, (de) + or 038h + ld (de), a + ret + ; Another entry. This will set the paper color at location pointer by DE +__SET_PAPER2: + and 7 ; # Remove + rlca + rlca + rlca ; a *= 8 + ld b, a ; Saves the color + ld a, (de) + and 0C7h ; Clears previous value + or b + ld (de), a + inc de ; Points to MASK_T or MASK_P accordingly + ld a, (de) + and 0C7h ; Resets bits 3,4,5 + ld (de), a ret + ; Sets the PAPER color passed in A register in the ATTR_T variable +PAPER_TMP: + ld de, ATTR_T + jp __SET_PAPER ENDP pop namespace -#line 58 "zx48k/strbase2.bas" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/print_eol_attr.asm" - ; Calls PRINT_EOL and then COPY_ATTR, so saves - ; 3 bytes -#line 1 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -; vim:ts=4:sw=4:et: - ; PRINT command routine - ; Does not print attribute. Use PRINT_STR or PRINT_NUM for that -#line 1 "/zxbasic/src/arch/zx48k/library-asm/sposn.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/sysvars.asm" - ;; ----------------------------------------------------------------------- - ;; ZX Basic System Vars - ;; Some of them will be mapped over Sinclair ROM ones for compatibility - ;; ----------------------------------------------------------------------- - push namespace core -SCREEN_ADDR: DW 16384 ; Screen address (can be pointed to other place to use a screen buffer) -SCREEN_ATTR_ADDR: DW 22528 ; Screen attribute address (ditto.) - ; These are mapped onto ZX Spectrum ROM VARS - CHARS EQU 23606 ; Pointer to ROM/RAM Charset - TVFLAGS EQU 23612 ; TV Flags - UDG EQU 23675 ; Pointer to UDG Charset - COORDS EQU 23677 ; Last PLOT coordinates - FLAGS2 EQU 23681 ; - ECHO_E EQU 23682 ; - DFCC EQU 23684 ; Next screen addr for PRINT - DFCCL EQU 23686 ; Next screen attr for PRINT - S_POSN EQU 23688 - ATTR_P EQU 23693 ; Current Permanent ATTRS set with INK, PAPER, etc commands - ATTR_T EQU 23695 ; temporary ATTRIBUTES - P_FLAG EQU 23697 ; - MEM0 EQU 23698 ; Temporary memory buffer used by ROM chars - SCR_COLS EQU 33 ; Screen with in columns + 1 - SCR_ROWS EQU 24 ; Screen height in rows - SCR_SIZE EQU (SCR_ROWS << 8) + SCR_COLS - pop namespace -#line 2 "/zxbasic/src/arch/zx48k/library-asm/sposn.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/attr.asm" - ; Attribute routines -; vim:ts=4:et:sw: -#line 1 "/zxbasic/src/arch/zx48k/library-asm/error.asm" - ; Simple error control routines -; vim:ts=4:et: +#line 10 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/flash.asm" + ; Sets flash flag in ATTR_P permanently +; Parameter: Paper color in A register push namespace core - ERR_NR EQU 23610 ; Error code system variable - ; Error code definitions (as in ZX spectrum manual) -; Set error code with: - ; ld a, ERROR_CODE - ; ld (ERR_NR), a - ERROR_Ok EQU -1 - ERROR_SubscriptWrong EQU 2 - ERROR_OutOfMemory EQU 3 - ERROR_OutOfScreen EQU 4 - ERROR_NumberTooBig EQU 5 - ERROR_InvalidArg EQU 9 - ERROR_IntOutOfRange EQU 10 - ERROR_NonsenseInBasic EQU 11 - ERROR_InvalidFileName EQU 14 - ERROR_InvalidColour EQU 19 - ERROR_BreakIntoProgram EQU 20 - ERROR_TapeLoadingErr EQU 26 - ; Raises error using RST #8 -__ERROR: - ld (__ERROR_CODE), a - rst 8 -__ERROR_CODE: - nop +FLASH: + ld hl, ATTR_P + PROC + LOCAL IS_TR + LOCAL IS_ZERO +__SET_FLASH: + ; Another entry. This will set the flash flag at location pointer by DE + cp 8 + jr z, IS_TR + ; # Convert to 0/1 + or a + jr z, IS_ZERO + ld a, 0x80 +IS_ZERO: + ld b, a ; Saves the color + ld a, (hl) + and 07Fh ; Clears previous value + or b + ld (hl), a + inc hl + res 7, (hl) ;Reset bit 7 to disable transparency ret - ; Sets the error system variable, but keeps running. - ; Usually this instruction if followed by the END intermediate instruction. -__STOP: - ld (ERR_NR), a +IS_TR: ; transparent + inc hl ; Points DE to MASK_T or MASK_P + set 7, (hl) ;Set bit 7 to enable transparency ret + ; Sets the FLASH flag passed in A register in the ATTR_T variable +FLASH_TMP: + ld hl, ATTR_T + jr __SET_FLASH + ENDP pop namespace -#line 6 "/zxbasic/src/arch/zx48k/library-asm/attr.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/in_screen.asm" +#line 11 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/bright.asm" + ; Sets bright flag in ATTR_P permanently +; Parameter: Paper color in A register push namespace core -__IN_SCREEN: - ; Returns NO carry if current coords (D, E) - ; are OUT of the screen limits +BRIGHT: + ld hl, ATTR_P PROC - LOCAL __IN_SCREEN_ERR - ld hl, SCR_SIZE - ld a, e - cp l - jr nc, __IN_SCREEN_ERR ; Do nothing and return if out of range - ld a, d - cp h - ret c ; Return if carry (OK) -__IN_SCREEN_ERR: -__OUT_OF_SCREEN_ERR: - ; Jumps here if out of screen - ld a, ERROR_OutOfScreen - jp __STOP ; Saves error code and exits + LOCAL IS_TR + LOCAL IS_ZERO +__SET_BRIGHT: + ; Another entry. This will set the bright flag at location pointer by DE + cp 8 + jr z, IS_TR + ; # Convert to 0/1 + or a + jr z, IS_ZERO + ld a, 0x40 +IS_ZERO: + ld b, a ; Saves the color + ld a, (hl) + and 0BFh ; Clears previous value + or b + ld (hl), a + inc hl + res 6, (hl) ;Reset bit 6 to disable transparency + ret +IS_TR: ; transparent + inc hl ; Points DE to MASK_T or MASK_P + set 6, (hl) ;Set bit 6 to enable transparency + ret + ; Sets the BRIGHT flag passed in A register in the ATTR_T variable +BRIGHT_TMP: + ld hl, ATTR_T + jr __SET_BRIGHT ENDP pop namespace -#line 7 "/zxbasic/src/arch/zx48k/library-asm/attr.asm" +#line 12 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/over.asm" + ; Sets OVER flag in P_FLAG permanently +; Parameter: OVER flag in bit 0 of A register push namespace core -__ATTR_ADDR: - ; calc start address in DE (as (32 * d) + e) - ; Contributed by Santiago Romero at http://www.speccy.org - ld h, 0 ; 7 T-States - ld a, d ; 4 T-States - ld d, h - add a, a ; a * 2 ; 4 T-States - add a, a ; a * 4 ; 4 T-States - ld l, a ; HL = A * 4 ; 4 T-States - add hl, hl ; HL = A * 8 ; 15 T-States - add hl, hl ; HL = A * 16 ; 15 T-States - add hl, hl ; HL = A * 32 ; 15 T-States - add hl, de - ld de, (SCREEN_ATTR_ADDR) ; Adds the screen address - add hl, de - ; Return current screen address in HL +OVER: + PROC + ld c, a ; saves it for later + and 2 + ld hl, FLAGS2 + res 1, (HL) + or (hl) + ld (hl), a + ld a, c ; Recovers previous value + and 1 ; # Convert to 0/1 + add a, a; # Shift left 1 bit for permanent + ld hl, P_FLAG + res 1, (hl) + or (hl) + ld (hl), a ret - ; Sets the attribute at a given screen coordinate (D, E). - ; The attribute is taken from the ATTR_T memory variable - ; Used by PRINT routines -SET_ATTR: - ; Checks for valid coords - call __IN_SCREEN - ret nc - call __ATTR_ADDR -__SET_ATTR: - ; Internal __FASTCALL__ Entry used by printing routines - ; HL contains the address of the ATTR cell to set + ; Sets OVER flag in P_FLAG temporarily +OVER_TMP: + ld c, a ; saves it for later + and 2 ; gets bit 1; clears carry + rra + ld hl, FLAGS2 + res 0, (hl) + or (hl) + ld (hl), a + ld a, c ; Recovers previous value + and 1 + ld hl, P_FLAG + res 0, (hl) + or (hl) + ld (hl), a + jp __SET_ATTR_MODE + ENDP + pop namespace +#line 13 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/inverse.asm" + ; Sets INVERSE flag in P_FLAG permanently +; Parameter: INVERSE flag in bit 0 of A register + push namespace core +INVERSE: PROC -__SET_ATTR2: ; Sets attr from ATTR_T to (HL) which points to the scr address - ld de, (ATTR_T) ; E = ATTR_T, D = MASK_T - ld a, d - and (hl) - ld c, a ; C = current screen color, masked - ld a, d - cpl ; Negate mask - and e ; Mask current attributes - or c ; Mix them - ld (hl), a ; Store result in screen + and 1 ; # Convert to 0/1 + add a, a; # Shift left 3 bits for permanent + add a, a + add a, a + ld hl, P_FLAG + res 3, (hl) + or (hl) + ld (hl), a ret + ; Sets INVERSE flag in P_FLAG temporarily +INVERSE_TMP: + and 1 + add a, a + add a, a; # Shift left 2 bits for temporary + ld hl, P_FLAG + res 2, (hl) + or (hl) + ld (hl), a + jp __SET_ATTR_MODE ENDP pop namespace -#line 3 "/zxbasic/src/arch/zx48k/library-asm/sposn.asm" - ; Printing positioning library. +#line 14 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/bold.asm" + ; Sets BOLD flag in P_FLAG permanently +; Parameter: BOLD flag in bit 0 of A register push namespace core - ; Loads into DE current ROW, COL print position from S_POSN mem var. -__LOAD_S_POSN: +BOLD: PROC - ld de, (S_POSN) - ld hl, SCR_SIZE - or a - sbc hl, de - ex de, hl + and 1 + rlca + rlca + rlca + ld hl, FLAGS2 + res 3, (HL) + or (hl) + ld (hl), a + ret + ; Sets BOLD flag in P_FLAG temporarily +BOLD_TMP: + and 1 + rlca + rlca + ld hl, FLAGS2 + res 2, (hl) + or (hl) + ld (hl), a ret ENDP - ; Saves ROW, COL from DE into S_POSN mem var. -__SAVE_S_POSN: + pop namespace +#line 15 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/italic.asm" + ; Sets ITALIC flag in P_FLAG permanently +; Parameter: ITALIC flag in bit 0 of A register + push namespace core +ITALIC: PROC - ld hl, SCR_SIZE - or a - sbc hl, de - ld (S_POSN), hl ; saves it again -__SET_SCR_PTR: ;; Fast - push de - call __ATTR_ADDR - ld (DFCCL), hl - pop de - ld a, d - ld c, a ; Saves it for later - and 0F8h ; Masks 3 lower bit ; zy - ld d, a - ld a, c ; Recovers it - and 07h ; MOD 7 ; y1 + and 1 rrca rrca rrca - or e - ld e, a - ld hl, (SCREEN_ADDR) - add hl, de ; HL = Screen address + DE - ld (DFCC), hl + ld hl, FLAGS2 + res 5, (HL) + or (hl) + ld (hl), a + ret + ; Sets ITALIC flag in P_FLAG temporarily +ITALIC_TMP: + and 1 + rrca + rrca + rrca + rrca + ld hl, FLAGS2 + res 4, (hl) + or (hl) + ld (hl), a ret ENDP pop namespace -#line 6 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/table_jump.asm" - push namespace core -JUMP_HL_PLUS_2A: ; Does JP (HL + A*2) Modifies DE. Modifies A - add a, a -JUMP_HL_PLUS_A: ; Does JP (HL + A) Modifies DE - ld e, a - ld d, 0 -JUMP_HL_PLUS_DE: ; Does JP (HL + DE) - add hl, de - ld e, (hl) - inc hl - ld d, (hl) - ex de, hl -CALL_HL: - jp (hl) - pop namespace -#line 8 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/ink.asm" - ; Sets ink color in ATTR_P permanently -; Parameter: Paper color in A register +#line 16 "/zxbasic/src/arch/zx48k/library-asm/print.asm" + ; Putting a comment starting with @INIT
+ ; will make the compiler to add a CALL to
+ ; It is useful for initialization routines. push namespace core -INK: +__PRINT_INIT: ; To be called before program starts (initializes library) PROC - LOCAL __SET_INK - LOCAL __SET_INK2 - ld de, ATTR_P -__SET_INK: - cp 8 - jr nz, __SET_INK2 - inc de ; Points DE to MASK_T or MASK_P - ld a, (de) - or 7 ; Set bits 0,1,2 to enable transparency - ld (de), a + ld hl, __PRINT_START + ld (PRINT_JUMP_STATE), hl + ;; Clears ATTR2 flags (OVER 2, etc) + xor a + ld (FLAGS2), a + LOCAL SET_SCR_ADDR + call __LOAD_S_POSN + jp __SET_SCR_PTR + ;; Receives HL = future value of S_POSN + ;; Stores it at (S_POSN) and refresh screen pointers (ATTR, SCR) +SET_SCR_ADDR: + ld (S_POSN), hl + ex de, hl + ld hl, SCR_SIZE + or a + sbc hl, de + ex de, hl + dec e + jp __SET_SCR_PTR +__PRINTCHAR: ; Print character store in accumulator (A register) + ; Modifies H'L', B'C', A'F', D'E', A + LOCAL PO_GR_1 + LOCAL __PRCHAR + LOCAL __PRINT_JUMP + LOCAL __SRCADDR + LOCAL __PRINT_UDG + LOCAL __PRGRAPH + LOCAL __PRINT_START + PRINT_JUMP_STATE EQU __PRINT_JUMP + 2 +__PRINT_JUMP: + exx ; Switch to alternative registers + jp __PRINT_START ; Where to jump. If we print 22 (AT), next two calls jumps to AT1 and AT2 respectively +__PRINT_START: +__PRINT_CHR: + cp ' ' + jr c, __PRINT_SPECIAL ; Characters below ' ' are special ones + ex af, af' ; Saves a value (char to print) for later + ld hl, (S_POSN) + dec l + jr nz, 1f + ld l, SCR_COLS - 1 + dec h + jr nz, 2f + inc h + push hl + call __SCROLL_SCR + pop hl +#line 92 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +2: + call SET_SCR_ADDR + jr 4f +1: + ld (S_POSN), hl +4: + ex af, af' + cp 80h ; Is it a "normal" (printable) char + jr c, __SRCADDR + cp 90h ; Is it an UDG? + jr nc, __PRINT_UDG + ; Print an 8 bit pattern (80h to 8Fh) + ld b, a + call PO_GR_1 ; This ROM routine will generate the bit pattern at MEM0 + ld hl, MEM0 + jp __PRGRAPH + PO_GR_1 EQU 0B38h +__PRINT_UDG: + sub 90h ; Sub ASC code + ld bc, (UDG) + jr __PRGRAPH0 + __SOURCEADDR EQU (__SRCADDR + 1) ; Address of the pointer to chars source +__SRCADDR: + ld bc, (CHARS) +__PRGRAPH0: + add a, a ; A = a * 2 (since a < 80h) ; Thanks to Metalbrain at http://foro.speccy.org + ld l, a + ld h, 0 ; HL = a * 2 (accumulator) + add hl, hl + add hl, hl ; HL = a * 8 + add hl, bc ; HL = CHARS address +__PRGRAPH: + ex de, hl ; HL = Write Address, DE = CHARS address + bit 2, (iy + $47) + call nz, __BOLD +#line 139 "/zxbasic/src/arch/zx48k/library-asm/print.asm" + bit 4, (iy + $47) + call nz, __ITALIC +#line 144 "/zxbasic/src/arch/zx48k/library-asm/print.asm" + ld hl, (DFCC) + push hl + ld b, 8 ; 8 bytes per char +__PRCHAR: + ld a, (de) ; DE *must* be source, and HL destiny +PRINT_MODE: ; Which operation is used to write on the screen + ; Set it with: + ; LD A, + ; LD (PRINT_MODE), A + ; + ; Available operations: + ; NORMAL : 0h --> NOP ; OVER 0 + ; XOR : AEh --> XOR (HL) ; OVER 1 + ; OR : B6h --> OR (HL) ; PUTSPRITE + ; AND : A6h --> AND (HL) ; PUTMASK + nop ; Set to one of the values above +INVERSE_MODE: ; 00 -> NOP -> INVERSE 0 + nop ; 2F -> CPL -> INVERSE 1 + ld (hl), a + inc de + inc h ; Next line + djnz __PRCHAR + pop hl + inc hl + ld (DFCC), hl + ld hl, (DFCCL) ; current ATTR Pos + inc hl + ld (DFCCL), hl + dec hl + call __SET_ATTR + exx ret -__SET_INK2: - ; Another entry. This will set the ink color at location pointer by DE - and 7 ; # Gets color mod 8 - ld b, a ; Saves the color - ld a, (de) - and 0F8h ; Clears previous value - or b - ld (de), a - inc de ; Points DE to MASK_T or MASK_P - ld a, (de) - and 0F8h ; Reset bits 0,1,2 sign to disable transparency - ld (de), a ; Store new attr + ; ------------- SPECIAL CHARS (< 32) ----------------- +__PRINT_SPECIAL: ; Jumps here if it is a special char + ld hl, __PRINT_TABLE + jp JUMP_HL_PLUS_2A +PRINT_EOL: ; Called WHENEVER there is no ";" at end of PRINT sentence + exx +__PRINT_0Dh: ; Called WHEN printing CHR$(13) + ld hl, (S_POSN) + dec l + jr nz, 1f + dec h + jr nz, 1f + inc h + push hl + call __SCROLL_SCR + pop hl +#line 209 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +1: + ld l, 1 +__PRINT_EOL_END: + call SET_SCR_ADDR + exx ret - ; Sets the INK color passed in A register in the ATTR_T variable -INK_TMP: - ld de, ATTR_T - jp __SET_INK - ENDP - pop namespace -#line 9 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/paper.asm" - ; Sets paper color in ATTR_P permanently -; Parameter: Paper color in A register - push namespace core -PAPER: - PROC - LOCAL __SET_PAPER - LOCAL __SET_PAPER2 - ld de, ATTR_P -__SET_PAPER: - cp 8 - jr nz, __SET_PAPER2 - inc de - ld a, (de) - or 038h - ld (de), a +__PRINT_COM: + exx + push hl + push de + push bc + call PRINT_COMMA + pop bc + pop de + pop hl ret - ; Another entry. This will set the paper color at location pointer by DE -__SET_PAPER2: - and 7 ; # Remove - rlca - rlca - rlca ; a *= 8 - ld b, a ; Saves the color - ld a, (de) - and 0C7h ; Clears previous value - or b - ld (de), a - inc de ; Points to MASK_T or MASK_P accordingly - ld a, (de) - and 0C7h ; Resets bits 3,4,5 - ld (de), a +__PRINT_TAB: + ld hl, __PRINT_TAB1 + jr __PRINT_SET_STATE +__PRINT_TAB1: + ld (MEM0), a + ld hl, __PRINT_TAB2 + jr __PRINT_SET_STATE +__PRINT_TAB2: + ld a, (MEM0) ; Load tab code (ignore the current one) + ld hl, __PRINT_START + ld (PRINT_JUMP_STATE), hl + exx + push hl + push bc + push de + call PRINT_TAB + pop de + pop bc + pop hl ret - ; Sets the PAPER color passed in A register in the ATTR_T variable -PAPER_TMP: - ld de, ATTR_T - jp __SET_PAPER - ENDP - pop namespace -#line 10 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/flash.asm" - ; Sets flash flag in ATTR_P permanently -; Parameter: Paper color in A register - push namespace core -FLASH: - ld hl, ATTR_P - PROC - LOCAL IS_TR - LOCAL IS_ZERO -__SET_FLASH: - ; Another entry. This will set the flash flag at location pointer by DE - cp 8 - jr z, IS_TR - ; # Convert to 0/1 - or a - jr z, IS_ZERO - ld a, 0x80 -IS_ZERO: - ld b, a ; Saves the color - ld a, (hl) - and 07Fh ; Clears previous value - or b - ld (hl), a - inc hl - res 7, (hl) ;Reset bit 7 to disable transparency +__PRINT_AT: + ld hl, __PRINT_AT1 + jr __PRINT_SET_STATE +__PRINT_NOP: +__PRINT_RESTART: + ld hl, __PRINT_START +__PRINT_SET_STATE: + ld (PRINT_JUMP_STATE), hl ; Saves next entry call + exx ret -IS_TR: ; transparent - inc hl ; Points DE to MASK_T or MASK_P - set 7, (hl) ;Set bit 7 to enable transparency +__PRINT_AT1: ; Jumps here if waiting for 1st parameter + ld hl, (S_POSN) + ld h, a + ld a, SCR_ROWS + sub h + ld (S_POSN + 1), a + ld hl, __PRINT_AT2 + jr __PRINT_SET_STATE +__PRINT_AT2: + call __LOAD_S_POSN + ld e, a + call __SAVE_S_POSN + jr __PRINT_RESTART +__PRINT_DEL: + call __LOAD_S_POSN ; Gets current screen position + dec e + ld a, -1 + cp e + jr nz, 3f + ld e, SCR_COLS - 2 + dec d + cp d + jr nz, 3f + ld d, SCR_ROWS - 1 +3: + call __SAVE_S_POSN + exx ret - ; Sets the FLASH flag passed in A register in the ATTR_T variable -FLASH_TMP: - ld hl, ATTR_T - jr __SET_FLASH - ENDP - pop namespace -#line 11 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/bright.asm" - ; Sets bright flag in ATTR_P permanently -; Parameter: Paper color in A register - push namespace core -BRIGHT: - ld hl, ATTR_P - PROC - LOCAL IS_TR - LOCAL IS_ZERO -__SET_BRIGHT: - ; Another entry. This will set the bright flag at location pointer by DE - cp 8 - jr z, IS_TR - ; # Convert to 0/1 - or a - jr z, IS_ZERO - ld a, 0x40 -IS_ZERO: - ld b, a ; Saves the color - ld a, (hl) - and 0BFh ; Clears previous value - or b +__PRINT_INK: + ld hl, __PRINT_INK2 + jr __PRINT_SET_STATE +__PRINT_INK2: + call INK_TMP + jr __PRINT_RESTART +__PRINT_PAP: + ld hl, __PRINT_PAP2 + jr __PRINT_SET_STATE +__PRINT_PAP2: + call PAPER_TMP + jr __PRINT_RESTART +__PRINT_FLA: + ld hl, __PRINT_FLA2 + jr __PRINT_SET_STATE +__PRINT_FLA2: + call FLASH_TMP + jr __PRINT_RESTART +__PRINT_BRI: + ld hl, __PRINT_BRI2 + jr __PRINT_SET_STATE +__PRINT_BRI2: + call BRIGHT_TMP + jr __PRINT_RESTART +__PRINT_INV: + ld hl, __PRINT_INV2 + jr __PRINT_SET_STATE +__PRINT_INV2: + call INVERSE_TMP + jr __PRINT_RESTART +__PRINT_OVR: + ld hl, __PRINT_OVR2 + jr __PRINT_SET_STATE +__PRINT_OVR2: + call OVER_TMP + jr __PRINT_RESTART +__PRINT_BOLD: + ld hl, __PRINT_BOLD2 + jp __PRINT_SET_STATE +__PRINT_BOLD2: + call BOLD_TMP + jp __PRINT_RESTART +#line 353 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +__PRINT_ITA: + ld hl, __PRINT_ITA2 + jp __PRINT_SET_STATE +__PRINT_ITA2: + call ITALIC_TMP + jp __PRINT_RESTART +#line 363 "/zxbasic/src/arch/zx48k/library-asm/print.asm" + LOCAL __BOLD +__BOLD: + push hl + ld hl, MEM0 + ld b, 8 +1: + ld a, (de) + ld c, a + rlca + or c ld (hl), a inc hl - res 6, (hl) ;Reset bit 6 to disable transparency + inc de + djnz 1b + pop hl + ld de, MEM0 ret -IS_TR: ; transparent - inc hl ; Points DE to MASK_T or MASK_P - set 6, (hl) ;Set bit 6 to enable transparency +#line 384 "/zxbasic/src/arch/zx48k/library-asm/print.asm" + LOCAL __ITALIC +__ITALIC: + push hl + ld hl, MEM0 + ex de, hl + ld bc, 8 + ldir + ld hl, MEM0 + srl (hl) + inc hl + srl (hl) + inc hl + srl (hl) + inc hl + inc hl + inc hl + sla (hl) + inc hl + sla (hl) + inc hl + sla (hl) + pop hl + ld de, MEM0 ret - ; Sets the BRIGHT flag passed in A register in the ATTR_T variable -BRIGHT_TMP: - ld hl, ATTR_T - jr __SET_BRIGHT +#line 412 "/zxbasic/src/arch/zx48k/library-asm/print.asm" + LOCAL __SCROLL_SCR +#line 486 "/zxbasic/src/arch/zx48k/library-asm/print.asm" + __SCROLL_SCR EQU 0DFEh ; Use ROM SCROLL +#line 488 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 489 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +PRINT_COMMA: + call __LOAD_S_POSN + ld a, e + and 16 + add a, 16 +PRINT_TAB: + ; Tabulates the number of spaces in A register + ; If the current cursor position is already A, does nothing + PROC + LOCAL LOOP + call __LOAD_S_POSN ; e = current row + sub e + and 31 + ret z + ld b, a +LOOP: + ld a, ' ' + call __PRINTCHAR + djnz LOOP + ret + ENDP +PRINT_AT: ; Changes cursor to ROW, COL + ; COL in A register + ; ROW in stack + pop hl ; Ret address + ex (sp), hl ; callee H = ROW + ld l, a + ex de, hl + call __IN_SCREEN + ret nc ; Return if out of screen + jp __SAVE_S_POSN + LOCAL __PRINT_COM + LOCAL __PRINT_AT1 + LOCAL __PRINT_AT2 + LOCAL __PRINT_BOLD + LOCAL __PRINT_ITA + LOCAL __PRINT_INK + LOCAL __PRINT_PAP + LOCAL __PRINT_SET_STATE + LOCAL __PRINT_TABLE + LOCAL __PRINT_TAB, __PRINT_TAB1, __PRINT_TAB2 + LOCAL __PRINT_ITA2 +#line 545 "/zxbasic/src/arch/zx48k/library-asm/print.asm" + LOCAL __PRINT_BOLD2 +#line 551 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +__PRINT_TABLE: ; Jump table for 0 .. 22 codes + DW __PRINT_NOP ; 0 + DW __PRINT_NOP ; 1 + DW __PRINT_NOP ; 2 + DW __PRINT_NOP ; 3 + DW __PRINT_NOP ; 4 + DW __PRINT_NOP ; 5 + DW __PRINT_COM ; 6 COMMA + DW __PRINT_NOP ; 7 + DW __PRINT_DEL ; 8 DEL + DW __PRINT_NOP ; 9 + DW __PRINT_NOP ; 10 + DW __PRINT_NOP ; 11 + DW __PRINT_NOP ; 12 + DW __PRINT_0Dh ; 13 + DW __PRINT_BOLD ; 14 + DW __PRINT_ITA ; 15 + DW __PRINT_INK ; 16 + DW __PRINT_PAP ; 17 + DW __PRINT_FLA ; 18 + DW __PRINT_BRI ; 19 + DW __PRINT_INV ; 20 + DW __PRINT_OVR ; 21 + DW __PRINT_AT ; 22 AT + DW __PRINT_TAB ; 23 TAB ENDP pop namespace -#line 12 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/over.asm" - ; Sets OVER flag in P_FLAG permanently -; Parameter: OVER flag in bit 0 of A register -#line 1 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" +#line 3 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" #line 4 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" push namespace core COPY_ATTR: @@ -853,549 +973,421 @@ __SET_ATTR_MODE: ; Another entry to set print modes. A contains (P_FLAG) ld b, 0 ld hl, TABLE add hl, bc - ld a, (hl) - ld (PRINT_MODE), a - ld hl, (P_FLAG) - xor a ; NOP -> INVERSE0 - bit 2, l - jr z, CONT2 - ld a, INVERSE1 ; CPL -> INVERSE1 -CONT2: - ld (INVERSE_MODE), a - ret -TABLE: - nop ; NORMAL MODE - xor (hl) ; OVER 1 MODE - and (hl) ; OVER 2 MODE - or (hl) ; OVER 3 MODE -#line 67 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" -__REFRESH_TMP: - ld a, (hl) - and 0b10101010 - ld c, a - rra - or c - ld (hl), a - ret - ENDP - pop namespace -#line 4 "/zxbasic/src/arch/zx48k/library-asm/over.asm" - push namespace core -OVER: - PROC - ld c, a ; saves it for later - and 2 - ld hl, FLAGS2 - res 1, (HL) - or (hl) - ld (hl), a - ld a, c ; Recovers previous value - and 1 ; # Convert to 0/1 - add a, a; # Shift left 1 bit for permanent - ld hl, P_FLAG - res 1, (hl) - or (hl) - ld (hl), a - ret - ; Sets OVER flag in P_FLAG temporarily -OVER_TMP: - ld c, a ; saves it for later - and 2 ; gets bit 1; clears carry - rra - ld hl, FLAGS2 - res 0, (hl) - or (hl) - ld (hl), a - ld a, c ; Recovers previous value - and 1 - ld hl, P_FLAG - res 0, (hl) - or (hl) - ld (hl), a - jp __SET_ATTR_MODE - ENDP - pop namespace -#line 13 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/inverse.asm" - ; Sets INVERSE flag in P_FLAG permanently -; Parameter: INVERSE flag in bit 0 of A register - push namespace core -INVERSE: - PROC - and 1 ; # Convert to 0/1 - add a, a; # Shift left 3 bits for permanent - add a, a - add a, a - ld hl, P_FLAG - res 3, (hl) - or (hl) - ld (hl), a - ret - ; Sets INVERSE flag in P_FLAG temporarily -INVERSE_TMP: - and 1 - add a, a - add a, a; # Shift left 2 bits for temporary - ld hl, P_FLAG - res 2, (hl) - or (hl) - ld (hl), a - jp __SET_ATTR_MODE - ENDP - pop namespace -#line 14 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/bold.asm" - ; Sets BOLD flag in P_FLAG permanently -; Parameter: BOLD flag in bit 0 of A register - push namespace core -BOLD: - PROC - and 1 - rlca - rlca - rlca - ld hl, FLAGS2 - res 3, (HL) - or (hl) - ld (hl), a - ret - ; Sets BOLD flag in P_FLAG temporarily -BOLD_TMP: - and 1 - rlca - rlca - ld hl, FLAGS2 - res 2, (hl) - or (hl) - ld (hl), a - ret - ENDP - pop namespace -#line 15 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/italic.asm" - ; Sets ITALIC flag in P_FLAG permanently -; Parameter: ITALIC flag in bit 0 of A register - push namespace core -ITALIC: - PROC - and 1 - rrca - rrca - rrca - ld hl, FLAGS2 - res 5, (HL) - or (hl) - ld (hl), a + ld a, (hl) + ld (PRINT_MODE), a + ld hl, (P_FLAG) + xor a ; NOP -> INVERSE0 + bit 2, l + jr z, CONT2 + ld a, INVERSE1 ; CPL -> INVERSE1 +CONT2: + ld (INVERSE_MODE), a ret - ; Sets ITALIC flag in P_FLAG temporarily -ITALIC_TMP: - and 1 - rrca - rrca - rrca - rrca - ld hl, FLAGS2 - res 4, (hl) - or (hl) +TABLE: + nop ; NORMAL MODE + xor (hl) ; OVER 1 MODE + and (hl) ; OVER 2 MODE + or (hl) ; OVER 3 MODE +#line 67 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" +__REFRESH_TMP: + ld a, (hl) + and 0b10101010 + ld c, a + rra + or c ld (hl), a ret ENDP pop namespace -#line 16 "/zxbasic/src/arch/zx48k/library-asm/print.asm" - ; Putting a comment starting with @INIT
- ; will make the compiler to add a CALL to
- ; It is useful for initialization routines. - push namespace core -__PRINT_INIT: ; To be called before program starts (initializes library) - PROC - ld hl, __PRINT_START - ld (PRINT_JUMP_STATE), hl - ;; Clears ATTR2 flags (OVER 2, etc) - xor a - ld (FLAGS2), a - LOCAL SET_SCR_ADDR - call __LOAD_S_POSN - jp __SET_SCR_PTR - ;; Receives HL = future value of S_POSN - ;; Stores it at (S_POSN) and refresh screen pointers (ATTR, SCR) -SET_SCR_ADDR: - ld (S_POSN), hl - ex de, hl - ld hl, SCR_SIZE - or a - sbc hl, de - ex de, hl - dec e - jp __SET_SCR_PTR -__PRINTCHAR: ; Print character store in accumulator (A register) - ; Modifies H'L', B'C', A'F', D'E', A - LOCAL PO_GR_1 - LOCAL __PRCHAR - LOCAL __PRINT_JUMP - LOCAL __SRCADDR - LOCAL __PRINT_UDG - LOCAL __PRGRAPH - LOCAL __PRINT_START - PRINT_JUMP_STATE EQU __PRINT_JUMP + 2 -__PRINT_JUMP: - exx ; Switch to alternative registers - jp __PRINT_START ; Where to jump. If we print 22 (AT), next two calls jumps to AT1 and AT2 respectively -__PRINT_START: -__PRINT_CHR: - cp ' ' - jr c, __PRINT_SPECIAL ; Characters below ' ' are special ones - ex af, af' ; Saves a value (char to print) for later - ld hl, (S_POSN) - dec l - jr nz, 1f - ld l, SCR_COLS - 1 - dec h - jr nz, 2f - inc h - push hl - call __SCROLL_SCR - pop hl -#line 92 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -2: - call SET_SCR_ADDR - jr 4f -1: - ld (S_POSN), hl -4: - ex af, af' - cp 80h ; Is it a "normal" (printable) char - jr c, __SRCADDR - cp 90h ; Is it an UDG? - jr nc, __PRINT_UDG - ; Print an 8 bit pattern (80h to 8Fh) - ld b, a - call PO_GR_1 ; This ROM routine will generate the bit pattern at MEM0 - ld hl, MEM0 - jp __PRGRAPH - PO_GR_1 EQU 0B38h -__PRINT_UDG: - sub 90h ; Sub ASC code - ld bc, (UDG) - jr __PRGRAPH0 - __SOURCEADDR EQU (__SRCADDR + 1) ; Address of the pointer to chars source -__SRCADDR: - ld bc, (CHARS) -__PRGRAPH0: - add a, a ; A = a * 2 (since a < 80h) ; Thanks to Metalbrain at http://foro.speccy.org - ld l, a - ld h, 0 ; HL = a * 2 (accumulator) - add hl, hl - add hl, hl ; HL = a * 8 - add hl, bc ; HL = CHARS address -__PRGRAPH: - ex de, hl ; HL = Write Address, DE = CHARS address - bit 2, (iy + $47) - call nz, __BOLD -#line 139 "/zxbasic/src/arch/zx48k/library-asm/print.asm" - bit 4, (iy + $47) - call nz, __ITALIC -#line 144 "/zxbasic/src/arch/zx48k/library-asm/print.asm" - ld hl, (DFCC) - push hl - ld b, 8 ; 8 bytes per char -__PRCHAR: - ld a, (de) ; DE *must* be source, and HL destiny -PRINT_MODE: ; Which operation is used to write on the screen - ; Set it with: - ; LD A, - ; LD (PRINT_MODE), A - ; - ; Available operations: - ; NORMAL : 0h --> NOP ; OVER 0 - ; XOR : AEh --> XOR (HL) ; OVER 1 - ; OR : B6h --> OR (HL) ; PUTSPRITE - ; AND : A6h --> AND (HL) ; PUTMASK - nop ; Set to one of the values above -INVERSE_MODE: ; 00 -> NOP -> INVERSE 0 - nop ; 2F -> CPL -> INVERSE 1 +#line 60 "zx48k/strbase2.bas" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/letsubstr.asm" + ; Substring assigment eg. LET a$(p0 TO p1) = "xxxx" + ; HL = Start of string + ; TOP of the stack -> p1 (16 bit, unsigned) + ; TOP -1 of the stack -> p0 register + ; TOP -2 Flag (popped out in A register) + ; A Register => 0 if HL is not freed from memory + ; => Not 0 if HL must be freed from memory on exit + ; TOP -3 B$ address +#line 1 "/zxbasic/src/arch/zx48k/library-asm/free.asm" +; vim: ts=4:et:sw=4: + ; Copyleft (K) by Jose M. Rodriguez de la Rosa + ; (a.k.a. Boriel) +; http://www.boriel.com + ; + ; This ASM library is licensed under the BSD license + ; you can use it for any purpose (even for commercial + ; closed source programs). + ; + ; Please read the BSD license on the internet + ; ----- IMPLEMENTATION NOTES ------ + ; The heap is implemented as a linked list of free blocks. +; Each free block contains this info: + ; + ; +----------------+ <-- HEAP START + ; | Size (2 bytes) | + ; | 0 | <-- Size = 0 => DUMMY HEADER BLOCK + ; +----------------+ + ; | Next (2 bytes) |---+ + ; +----------------+ <-+ + ; | Size (2 bytes) | + ; +----------------+ + ; | Next (2 bytes) |---+ + ; +----------------+ | + ; | | | <-- If Size > 4, then this contains (size - 4) bytes + ; | (0 if Size = 4)| | + ; +----------------+ <-+ + ; | Size (2 bytes) | + ; +----------------+ + ; | Next (2 bytes) |---+ + ; +----------------+ | + ; | | | + ; | (0 if Size = 4)| | + ; +----------------+ | + ; | <-- This zone is in use (Already allocated) + ; +----------------+ <-+ + ; | Size (2 bytes) | + ; +----------------+ + ; | Next (2 bytes) |---+ + ; +----------------+ | + ; | | | + ; | (0 if Size = 4)| | + ; +----------------+ <-+ + ; | Next (2 bytes) |--> NULL => END OF LIST + ; | 0 = NULL | + ; +----------------+ + ; | | + ; | (0 if Size = 4)| + ; +----------------+ + ; When a block is FREED, the previous and next pointers are examined to see + ; if we can defragment the heap. If the block to be breed is just next to the + ; previous, or to the next (or both) they will be converted into a single + ; block (so defragmented). + ; MEMORY MANAGER + ; + ; This library must be initialized calling __MEM_INIT with + ; HL = BLOCK Start & DE = Length. + ; An init directive is useful for initialization routines. + ; They will be added automatically if needed. +#line 1 "/zxbasic/src/arch/zx48k/library-asm/heapinit.asm" +; vim: ts=4:et:sw=4: + ; Copyleft (K) by Jose M. Rodriguez de la Rosa + ; (a.k.a. Boriel) +; http://www.boriel.com + ; + ; This ASM library is licensed under the BSD license + ; you can use it for any purpose (even for commercial + ; closed source programs). + ; + ; Please read the BSD license on the internet + ; ----- IMPLEMENTATION NOTES ------ + ; The heap is implemented as a linked list of free blocks. +; Each free block contains this info: + ; + ; +----------------+ <-- HEAP START + ; | Size (2 bytes) | + ; | 0 | <-- Size = 0 => DUMMY HEADER BLOCK + ; +----------------+ + ; | Next (2 bytes) |---+ + ; +----------------+ <-+ + ; | Size (2 bytes) | + ; +----------------+ + ; | Next (2 bytes) |---+ + ; +----------------+ | + ; | | | <-- If Size > 4, then this contains (size - 4) bytes + ; | (0 if Size = 4)| | + ; +----------------+ <-+ + ; | Size (2 bytes) | + ; +----------------+ + ; | Next (2 bytes) |---+ + ; +----------------+ | + ; | | | + ; | (0 if Size = 4)| | + ; +----------------+ | + ; | <-- This zone is in use (Already allocated) + ; +----------------+ <-+ + ; | Size (2 bytes) | + ; +----------------+ + ; | Next (2 bytes) |---+ + ; +----------------+ | + ; | | | + ; | (0 if Size = 4)| | + ; +----------------+ <-+ + ; | Next (2 bytes) |--> NULL => END OF LIST + ; | 0 = NULL | + ; +----------------+ + ; | | + ; | (0 if Size = 4)| + ; +----------------+ + ; When a block is FREED, the previous and next pointers are examined to see + ; if we can defragment the heap. If the block to be breed is just next to the + ; previous, or to the next (or both) they will be converted into a single + ; block (so defragmented). + ; MEMORY MANAGER + ; + ; This library must be initialized calling __MEM_INIT with + ; HL = BLOCK Start & DE = Length. + ; An init directive is useful for initialization routines. + ; They will be added automatically if needed. + ; --------------------------------------------------------------------- + ; __MEM_INIT must be called to initalize this library with the + ; standard parameters + ; --------------------------------------------------------------------- + push namespace core +__MEM_INIT: ; Initializes the library using (RAMTOP) as start, and + ld hl, ZXBASIC_MEM_HEAP ; Change this with other address of heap start + ld de, ZXBASIC_HEAP_SIZE ; Change this with your size + ; --------------------------------------------------------------------- + ; __MEM_INIT2 initalizes this library +; Parameters: +; HL : Memory address of 1st byte of the memory heap +; DE : Length in bytes of the Memory Heap + ; --------------------------------------------------------------------- +__MEM_INIT2: + ; HL as TOP + PROC + dec de + dec de + dec de + dec de ; DE = length - 4; HL = start + ; This is done, because we require 4 bytes for the empty dummy-header block + xor a ld (hl), a - inc de - inc h ; Next line - djnz __PRCHAR - pop hl inc hl - ld (DFCC), hl - ld hl, (DFCCL) ; current ATTR Pos - push hl - call __SET_ATTR - pop hl + ld (hl), a ; First "free" block is a header: size=0, Pointer=&(Block) + 4 + inc hl + ld b, h + ld c, l + inc bc + inc bc ; BC = starts of next block + ld (hl), c + inc hl + ld (hl), b + inc hl ; Pointer to next block + ld (hl), e + inc hl + ld (hl), d + inc hl ; Block size (should be length - 4 at start); This block contains all the available memory + ld (hl), a ; NULL (0000h) ; No more blocks (a list with a single block) inc hl - ld (DFCCL),hl - exx - ret - ; ------------- SPECIAL CHARS (< 32) ----------------- -__PRINT_SPECIAL: ; Jumps here if it is a special char - ld hl, __PRINT_TABLE - jp JUMP_HL_PLUS_2A -PRINT_EOL: ; Called WHENEVER there is no ";" at end of PRINT sentence - exx -__PRINT_0Dh: ; Called WHEN printing CHR$(13) - ld hl, (S_POSN) - dec l - jr nz, 1f - dec h - jr nz, 1f - inc h - push hl - call __SCROLL_SCR - pop hl -#line 210 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -1: - ld l, 1 -__PRINT_EOL_END: - call SET_SCR_ADDR - exx - ret -__PRINT_COM: - exx - push hl - push de - push bc - call PRINT_COMMA - pop bc - pop de - pop hl - ret -__PRINT_TAB: - ld hl, __PRINT_TAB1 - jr __PRINT_SET_STATE -__PRINT_TAB1: - ld (MEM0), a - ld hl, __PRINT_TAB2 - jr __PRINT_SET_STATE -__PRINT_TAB2: - ld a, (MEM0) ; Load tab code (ignore the current one) - ld hl, __PRINT_START - ld (PRINT_JUMP_STATE), hl - exx - push hl - push bc - push de - call PRINT_TAB - pop de - pop bc - pop hl - ret -__PRINT_AT: - ld hl, __PRINT_AT1 - jr __PRINT_SET_STATE -__PRINT_NOP: -__PRINT_RESTART: - ld hl, __PRINT_START -__PRINT_SET_STATE: - ld (PRINT_JUMP_STATE), hl ; Saves next entry call - exx - ret -__PRINT_AT1: ; Jumps here if waiting for 1st parameter - ld hl, (S_POSN) - ld h, a - ld a, SCR_ROWS - sub h - ld (S_POSN + 1), a - ld hl, __PRINT_AT2 - jr __PRINT_SET_STATE -__PRINT_AT2: - call __LOAD_S_POSN - ld e, a - call __SAVE_S_POSN - jr __PRINT_RESTART -__PRINT_DEL: - call __LOAD_S_POSN ; Gets current screen position - dec e - ld a, -1 - cp e - jr nz, 3f - ld e, SCR_COLS - 2 - dec d - cp d - jr nz, 3f - ld d, SCR_ROWS - 1 -3: - call __SAVE_S_POSN - exx - ret -__PRINT_INK: - ld hl, __PRINT_INK2 - jr __PRINT_SET_STATE -__PRINT_INK2: - call INK_TMP - jr __PRINT_RESTART -__PRINT_PAP: - ld hl, __PRINT_PAP2 - jr __PRINT_SET_STATE -__PRINT_PAP2: - call PAPER_TMP - jr __PRINT_RESTART -__PRINT_FLA: - ld hl, __PRINT_FLA2 - jr __PRINT_SET_STATE -__PRINT_FLA2: - call FLASH_TMP - jr __PRINT_RESTART -__PRINT_BRI: - ld hl, __PRINT_BRI2 - jr __PRINT_SET_STATE -__PRINT_BRI2: - call BRIGHT_TMP - jr __PRINT_RESTART -__PRINT_INV: - ld hl, __PRINT_INV2 - jr __PRINT_SET_STATE -__PRINT_INV2: - call INVERSE_TMP - jr __PRINT_RESTART -__PRINT_OVR: - ld hl, __PRINT_OVR2 - jr __PRINT_SET_STATE -__PRINT_OVR2: - call OVER_TMP - jr __PRINT_RESTART -__PRINT_BOLD: - ld hl, __PRINT_BOLD2 - jp __PRINT_SET_STATE -__PRINT_BOLD2: - call BOLD_TMP - jp __PRINT_RESTART -#line 354 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -__PRINT_ITA: - ld hl, __PRINT_ITA2 - jp __PRINT_SET_STATE -__PRINT_ITA2: - call ITALIC_TMP - jp __PRINT_RESTART -#line 364 "/zxbasic/src/arch/zx48k/library-asm/print.asm" - LOCAL __BOLD -__BOLD: - push hl - ld hl, MEM0 - ld b, 8 -1: - ld a, (de) - ld c, a - rlca - or c ld (hl), a + ld a, 201 + ld (__MEM_INIT), a; "Pokes" with a RET so ensure this routine is not called again + ret + ENDP + pop namespace +#line 69 "/zxbasic/src/arch/zx48k/library-asm/free.asm" + ; --------------------------------------------------------------------- + ; MEM_FREE + ; Frees a block of memory + ; +; Parameters: + ; HL = Pointer to the block to be freed. If HL is NULL (0) nothing + ; is done + ; --------------------------------------------------------------------- + push namespace core +MEM_FREE: +__MEM_FREE: ; Frees the block pointed by HL + ; HL DE BC & AF modified + PROC + LOCAL __MEM_LOOP2 + LOCAL __MEM_LINK_PREV + LOCAL __MEM_JOIN_TEST + LOCAL __MEM_BLOCK_JOIN + ld a, h + or l + ret z ; Return if NULL pointer + dec hl + dec hl + ld b, h + ld c, l ; BC = Block pointer + ld hl, ZXBASIC_MEM_HEAP ; This label point to the heap start +__MEM_LOOP2: + inc hl + inc hl ; Next block ptr + ld e, (hl) + inc hl + ld d, (hl) ; Block next ptr + ex de, hl ; DE = &(block->next); HL = block->next + ld a, h ; HL == NULL? + or l + jp z, __MEM_LINK_PREV; if so, link with previous + or a ; Clear carry flag + sbc hl, bc ; Carry if BC > HL => This block if before + add hl, bc ; Restores HL, preserving Carry flag + jp c, __MEM_LOOP2 ; This block is before. Keep searching PASS the block + ;------ At this point current HL is PAST BC, so we must link (DE) with BC, and HL in BC->next +__MEM_LINK_PREV: ; Link (DE) with BC, and BC->next with HL + ex de, hl + push hl + dec hl + ld (hl), c inc hl - inc de - djnz 1b + ld (hl), b ; (DE) <- BC + ld h, b ; HL <- BC (Free block ptr) + ld l, c + inc hl ; Skip block length (2 bytes) + inc hl + ld (hl), e ; Block->next = DE + inc hl + ld (hl), d + ; --- LINKED ; HL = &(BC->next) + 2 + call __MEM_JOIN_TEST pop hl - ld de, MEM0 - ret -#line 385 "/zxbasic/src/arch/zx48k/library-asm/print.asm" - LOCAL __ITALIC -__ITALIC: - push hl - ld hl, MEM0 +__MEM_JOIN_TEST: ; Checks for fragmented contiguous blocks and joins them + ; hl = Ptr to current block + 2 + ld d, (hl) + dec hl + ld e, (hl) + dec hl + ld b, (hl) ; Loads block length into BC + dec hl + ld c, (hl) ; + push hl ; Saves it for later + add hl, bc ; Adds its length. If HL == DE now, it must be joined + or a + sbc hl, de ; If Z, then HL == DE => We must join + pop hl + ret nz +__MEM_BLOCK_JOIN: ; Joins current block (pointed by HL) with next one (pointed by DE). HL->length already in BC + push hl ; Saves it for later ex de, hl - ld bc, 8 - ldir - ld hl, MEM0 - srl (hl) - inc hl - srl (hl) + ld e, (hl) ; DE -> block->next->length inc hl - srl (hl) + ld d, (hl) inc hl + ex de, hl ; DE = &(block->next) + add hl, bc ; HL = Total Length + ld b, h + ld c, l ; BC = Total Length + ex de, hl + ld e, (hl) inc hl + ld d, (hl) ; DE = block->next + pop hl ; Recovers Pointer to block + ld (hl), c inc hl - sla (hl) + ld (hl), b ; Length Saved inc hl - sla (hl) + ld (hl), e inc hl - sla (hl) - pop hl - ld de, MEM0 - ret -#line 413 "/zxbasic/src/arch/zx48k/library-asm/print.asm" - LOCAL __SCROLL_SCR -#line 487 "/zxbasic/src/arch/zx48k/library-asm/print.asm" - __SCROLL_SCR EQU 0DFEh ; Use ROM SCROLL -#line 489 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -#line 490 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -PRINT_COMMA: - call __LOAD_S_POSN - ld a, e - and 16 - add a, 16 -PRINT_TAB: - ; Tabulates the number of spaces in A register - ; If the current cursor position is already A, does nothing - PROC - LOCAL LOOP - call __LOAD_S_POSN ; e = current row - sub e - and 31 - ret z - ld b, a -LOOP: - ld a, ' ' - call __PRINTCHAR - djnz LOOP + ld (hl), d ; Next saved ret ENDP -PRINT_AT: ; Changes cursor to ROW, COL - ; COL in A register - ; ROW in stack - pop hl ; Ret address - ex (sp), hl ; callee H = ROW - ld l, a - ex de, hl - call __IN_SCREEN - ret nc ; Return if out of screen - jp __SAVE_S_POSN - LOCAL __PRINT_COM - LOCAL __PRINT_AT1 - LOCAL __PRINT_AT2 - LOCAL __PRINT_BOLD - LOCAL __PRINT_ITA - LOCAL __PRINT_INK - LOCAL __PRINT_PAP - LOCAL __PRINT_SET_STATE - LOCAL __PRINT_TABLE - LOCAL __PRINT_TAB, __PRINT_TAB1, __PRINT_TAB2 - LOCAL __PRINT_ITA2 -#line 546 "/zxbasic/src/arch/zx48k/library-asm/print.asm" - LOCAL __PRINT_BOLD2 -#line 552 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -__PRINT_TABLE: ; Jump table for 0 .. 22 codes - DW __PRINT_NOP ; 0 - DW __PRINT_NOP ; 1 - DW __PRINT_NOP ; 2 - DW __PRINT_NOP ; 3 - DW __PRINT_NOP ; 4 - DW __PRINT_NOP ; 5 - DW __PRINT_COM ; 6 COMMA - DW __PRINT_NOP ; 7 - DW __PRINT_DEL ; 8 DEL - DW __PRINT_NOP ; 9 - DW __PRINT_NOP ; 10 - DW __PRINT_NOP ; 11 - DW __PRINT_NOP ; 12 - DW __PRINT_0Dh ; 13 - DW __PRINT_BOLD ; 14 - DW __PRINT_ITA ; 15 - DW __PRINT_INK ; 16 - DW __PRINT_PAP ; 17 - DW __PRINT_FLA ; 18 - DW __PRINT_BRI ; 19 - DW __PRINT_INV ; 20 - DW __PRINT_OVR ; 21 - DW __PRINT_AT ; 22 AT - DW __PRINT_TAB ; 23 TAB - ENDP pop namespace -#line 5 "/zxbasic/src/arch/zx48k/library-asm/print_eol_attr.asm" +#line 11 "/zxbasic/src/arch/zx48k/library-asm/letsubstr.asm" push namespace core -PRINT_EOL_ATTR: - call PRINT_EOL - jp COPY_ATTR +__LETSUBSTR: + PROC + LOCAL __CONT0 + LOCAL __CONT1 + LOCAL __CONT2 + LOCAL __FREE_STR + exx + pop hl ; Return address + pop de ; p1 + pop bc ; p0 + exx + pop af ; Flag + ex af, af' ; Save it for later + pop de ; B$ + exx + push hl ; push ret addr back + exx + push de ; B$ addr to be freed upon return (if A != 0) + ld a, h + or l + jp z, __FREE_STR ; Return if null + ld c, (hl) + inc hl + ld b, (hl) ; BC = Str length + inc hl ; HL = String start + push bc + exx + ex de, hl + or a + sbc hl, bc ; HL = Length of string requested by user + inc hl ; len (a$(p0 TO p1)) = p1 - p0 + 1 + ex de, hl ; Saves it in DE + pop hl ; HL = String length + exx + jp c, __FREE_STR ; Return if p0 > p1 + exx + or a + sbc hl, bc ; P0 >= String length? + exx + jp z, __FREE_STR ; Return if equal + jp c, __FREE_STR ; Return if greater + exx + add hl, bc ; Add it back + sbc hl, de ; Length of substring > string => Truncate it + add hl, de ; add it back + jr nc, __CONT0 ; Length of substring within a$ + ld d, h + ld e, l ; Truncate length of substring to fit within the strlen +__CONT0: ; At this point DE = Length of substring to copy + ; BC = start of char to copy + push de + push bc + exx + pop bc + add hl, bc ; Start address (within a$) so copy from b$ (in DE) + push hl + exx + pop hl ; Start address (within a$) so copy from b$ (in DE) + ld b, d ; Length of string + ld c, e + ld (hl), ' ' + ld d, h + ld e, l + inc de + dec bc + ld a, b + or c + jr z, __CONT2 + ; At this point HL = DE = Start of Write zone in a$ + ; BC = Number of chars to write + ldir +__CONT2: + pop bc ; Recovers Length of string to copy + exx + ex de, hl ; HL = Source, DE = Target + ld a, h + or l + jp z, __FREE_STR ; Return if B$ is NULL + ld c, (hl) + inc hl + ld b, (hl) + inc hl + ld a, b + or c + jp z, __FREE_STR ; Return if len(b$) = 0 + ; Now if len(b$) < len(char to copy), copy only len(b$) chars + push de + push hl + push bc + exx + pop hl ; LEN (b$) + or a + sbc hl, bc + add hl, bc + jr nc, __CONT1 + ; If len(b$) < len(to copy) + ld b, h ; BC = len(to copy) + ld c, l +__CONT1: + pop hl + pop de + ldir ; Copy b$ into a$(x to y) +__FREE_STR: + pop hl + ex af, af' + or a ; If not 0, free + jp nz, __MEM_FREE + ret + ENDP pop namespace -#line 59 "zx48k/strbase2.bas" +#line 61 "zx48k/strbase2.bas" #line 1 "/zxbasic/src/arch/zx48k/library-asm/printstr.asm" ; PRINT command routine ; Prints string pointed by HL @@ -1439,7 +1431,7 @@ __PRINT_STR: jp __PRINT_STR_LOOP ENDP pop namespace -#line 60 "zx48k/strbase2.bas" +#line 63 "zx48k/strbase2.bas" #line 1 "/zxbasic/src/arch/zx48k/library-asm/storestr.asm" ; vim:ts=4:et:sw=4 ; Stores value of current string pointed by DE register into address pointed by HL @@ -1846,7 +1838,7 @@ __STORE_STR: pop hl ; Returns ptr to b$ in HL (Caller might needed to free it from memory) ret pop namespace -#line 61 "zx48k/strbase2.bas" +#line 64 "zx48k/strbase2.bas" #line 1 "/zxbasic/src/arch/zx48k/library-asm/storestr2.asm" ; Similar to __STORE_STR, but this one is called when ; the value of B$ if already duplicated onto the stack. @@ -1880,7 +1872,7 @@ __STORE_STR2: dec hl ; HL points to mem address variable. This might be useful in the future. ret pop namespace -#line 62 "zx48k/strbase2.bas" +#line 65 "zx48k/strbase2.bas" #line 1 "/zxbasic/src/arch/zx48k/library-asm/strslice.asm" ; String slicing library ; HL = Str pointer @@ -1982,5 +1974,5 @@ __FREE_ON_EXIT: ret ENDP pop namespace -#line 63 "zx48k/strbase2.bas" +#line 66 "zx48k/strbase2.bas" END diff --git a/tests/functional/zx48k/stringparam.asm b/tests/functional/zx48k/stringparam.asm index 0b02d80c8..0813f4363 100644 --- a/tests/functional/zx48k/stringparam.asm +++ b/tests/functional/zx48k/stringparam.asm @@ -48,11 +48,12 @@ _testStr: push ix ld ix, 0 add ix, sp + call .core.COPY_ATTR ld l, (ix+4) ld h, (ix+5) xor a call .core.__PRINTSTR - call .core.PRINT_EOL_ATTR + call .core.PRINT_EOL _testStr__leave: ex af, af' exx @@ -76,334 +77,42 @@ _testStr__leave: DEFB 6Ch DEFB 6Fh ;; --- end of user code --- -#line 1 "/zxbasic/src/arch/zx48k/library-asm/free.asm" -; vim: ts=4:et:sw=4: - ; Copyleft (K) by Jose M. Rodriguez de la Rosa - ; (a.k.a. Boriel) -; http://www.boriel.com - ; - ; This ASM library is licensed under the BSD license - ; you can use it for any purpose (even for commercial - ; closed source programs). - ; - ; Please read the BSD license on the internet - ; ----- IMPLEMENTATION NOTES ------ - ; The heap is implemented as a linked list of free blocks. -; Each free block contains this info: - ; - ; +----------------+ <-- HEAP START - ; | Size (2 bytes) | - ; | 0 | <-- Size = 0 => DUMMY HEADER BLOCK - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ <-+ - ; | Size (2 bytes) | - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ | - ; | | | <-- If Size > 4, then this contains (size - 4) bytes - ; | (0 if Size = 4)| | - ; +----------------+ <-+ - ; | Size (2 bytes) | - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ | - ; | | | - ; | (0 if Size = 4)| | - ; +----------------+ | - ; | <-- This zone is in use (Already allocated) - ; +----------------+ <-+ - ; | Size (2 bytes) | - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ | - ; | | | - ; | (0 if Size = 4)| | - ; +----------------+ <-+ - ; | Next (2 bytes) |--> NULL => END OF LIST - ; | 0 = NULL | - ; +----------------+ - ; | | - ; | (0 if Size = 4)| - ; +----------------+ - ; When a block is FREED, the previous and next pointers are examined to see - ; if we can defragment the heap. If the block to be breed is just next to the - ; previous, or to the next (or both) they will be converted into a single - ; block (so defragmented). - ; MEMORY MANAGER - ; - ; This library must be initialized calling __MEM_INIT with - ; HL = BLOCK Start & DE = Length. - ; An init directive is useful for initialization routines. - ; They will be added automatically if needed. -#line 1 "/zxbasic/src/arch/zx48k/library-asm/heapinit.asm" -; vim: ts=4:et:sw=4: - ; Copyleft (K) by Jose M. Rodriguez de la Rosa - ; (a.k.a. Boriel) -; http://www.boriel.com - ; - ; This ASM library is licensed under the BSD license - ; you can use it for any purpose (even for commercial - ; closed source programs). - ; - ; Please read the BSD license on the internet - ; ----- IMPLEMENTATION NOTES ------ - ; The heap is implemented as a linked list of free blocks. -; Each free block contains this info: - ; - ; +----------------+ <-- HEAP START - ; | Size (2 bytes) | - ; | 0 | <-- Size = 0 => DUMMY HEADER BLOCK - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ <-+ - ; | Size (2 bytes) | - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ | - ; | | | <-- If Size > 4, then this contains (size - 4) bytes - ; | (0 if Size = 4)| | - ; +----------------+ <-+ - ; | Size (2 bytes) | - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ | - ; | | | - ; | (0 if Size = 4)| | - ; +----------------+ | - ; | <-- This zone is in use (Already allocated) - ; +----------------+ <-+ - ; | Size (2 bytes) | - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ | - ; | | | - ; | (0 if Size = 4)| | - ; +----------------+ <-+ - ; | Next (2 bytes) |--> NULL => END OF LIST - ; | 0 = NULL | - ; +----------------+ - ; | | - ; | (0 if Size = 4)| - ; +----------------+ - ; When a block is FREED, the previous and next pointers are examined to see - ; if we can defragment the heap. If the block to be breed is just next to the - ; previous, or to the next (or both) they will be converted into a single - ; block (so defragmented). - ; MEMORY MANAGER - ; - ; This library must be initialized calling __MEM_INIT with - ; HL = BLOCK Start & DE = Length. - ; An init directive is useful for initialization routines. - ; They will be added automatically if needed. - ; --------------------------------------------------------------------- - ; __MEM_INIT must be called to initalize this library with the - ; standard parameters - ; --------------------------------------------------------------------- - push namespace core -__MEM_INIT: ; Initializes the library using (RAMTOP) as start, and - ld hl, ZXBASIC_MEM_HEAP ; Change this with other address of heap start - ld de, ZXBASIC_HEAP_SIZE ; Change this with your size - ; --------------------------------------------------------------------- - ; __MEM_INIT2 initalizes this library -; Parameters: -; HL : Memory address of 1st byte of the memory heap -; DE : Length in bytes of the Memory Heap - ; --------------------------------------------------------------------- -__MEM_INIT2: - ; HL as TOP - PROC - dec de - dec de - dec de - dec de ; DE = length - 4; HL = start - ; This is done, because we require 4 bytes for the empty dummy-header block - xor a - ld (hl), a - inc hl - ld (hl), a ; First "free" block is a header: size=0, Pointer=&(Block) + 4 - inc hl - ld b, h - ld c, l - inc bc - inc bc ; BC = starts of next block - ld (hl), c - inc hl - ld (hl), b - inc hl ; Pointer to next block - ld (hl), e - inc hl - ld (hl), d - inc hl ; Block size (should be length - 4 at start); This block contains all the available memory - ld (hl), a ; NULL (0000h) ; No more blocks (a list with a single block) - inc hl - ld (hl), a - ld a, 201 - ld (__MEM_INIT), a; "Pokes" with a RET so ensure this routine is not called again - ret - ENDP - pop namespace -#line 69 "/zxbasic/src/arch/zx48k/library-asm/free.asm" - ; --------------------------------------------------------------------- - ; MEM_FREE - ; Frees a block of memory - ; -; Parameters: - ; HL = Pointer to the block to be freed. If HL is NULL (0) nothing - ; is done - ; --------------------------------------------------------------------- - push namespace core -MEM_FREE: -__MEM_FREE: ; Frees the block pointed by HL - ; HL DE BC & AF modified - PROC - LOCAL __MEM_LOOP2 - LOCAL __MEM_LINK_PREV - LOCAL __MEM_JOIN_TEST - LOCAL __MEM_BLOCK_JOIN - ld a, h - or l - ret z ; Return if NULL pointer - dec hl - dec hl - ld b, h - ld c, l ; BC = Block pointer - ld hl, ZXBASIC_MEM_HEAP ; This label point to the heap start -__MEM_LOOP2: - inc hl - inc hl ; Next block ptr - ld e, (hl) - inc hl - ld d, (hl) ; Block next ptr - ex de, hl ; DE = &(block->next); HL = block->next - ld a, h ; HL == NULL? - or l - jp z, __MEM_LINK_PREV; if so, link with previous - or a ; Clear carry flag - sbc hl, bc ; Carry if BC > HL => This block if before - add hl, bc ; Restores HL, preserving Carry flag - jp c, __MEM_LOOP2 ; This block is before. Keep searching PASS the block - ;------ At this point current HL is PAST BC, so we must link (DE) with BC, and HL in BC->next -__MEM_LINK_PREV: ; Link (DE) with BC, and BC->next with HL - ex de, hl - push hl - dec hl - ld (hl), c - inc hl - ld (hl), b ; (DE) <- BC - ld h, b ; HL <- BC (Free block ptr) - ld l, c - inc hl ; Skip block length (2 bytes) - inc hl - ld (hl), e ; Block->next = DE - inc hl - ld (hl), d - ; --- LINKED ; HL = &(BC->next) + 2 - call __MEM_JOIN_TEST - pop hl -__MEM_JOIN_TEST: ; Checks for fragmented contiguous blocks and joins them - ; hl = Ptr to current block + 2 - ld d, (hl) - dec hl - ld e, (hl) - dec hl - ld b, (hl) ; Loads block length into BC - dec hl - ld c, (hl) ; - push hl ; Saves it for later - add hl, bc ; Adds its length. If HL == DE now, it must be joined - or a - sbc hl, de ; If Z, then HL == DE => We must join - pop hl - ret nz -__MEM_BLOCK_JOIN: ; Joins current block (pointed by HL) with next one (pointed by DE). HL->length already in BC - push hl ; Saves it for later - ex de, hl - ld e, (hl) ; DE -> block->next->length - inc hl - ld d, (hl) - inc hl - ex de, hl ; DE = &(block->next) - add hl, bc ; HL = Total Length - ld b, h - ld c, l ; BC = Total Length - ex de, hl - ld e, (hl) - inc hl - ld d, (hl) ; DE = block->next - pop hl ; Recovers Pointer to block - ld (hl), c - inc hl - ld (hl), b ; Length Saved - inc hl - ld (hl), e - inc hl - ld (hl), d ; Next saved - ret - ENDP - pop namespace -#line 52 "zx48k/stringparam.bas" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/loadstr.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/alloc.asm" -; vim: ts=4:et:sw=4: - ; Copyleft (K) by Jose M. Rodriguez de la Rosa - ; (a.k.a. Boriel) -; http://www.boriel.com - ; - ; This ASM library is licensed under the MIT license - ; you can use it for any purpose (even for commercial - ; closed source programs). - ; - ; Please read the MIT license on the internet - ; ----- IMPLEMENTATION NOTES ------ - ; The heap is implemented as a linked list of free blocks. -; Each free block contains this info: - ; - ; +----------------+ <-- HEAP START - ; | Size (2 bytes) | - ; | 0 | <-- Size = 0 => DUMMY HEADER BLOCK - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ <-+ - ; | Size (2 bytes) | - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ | - ; | | | <-- If Size > 4, then this contains (size - 4) bytes - ; | (0 if Size = 4)| | - ; +----------------+ <-+ - ; | Size (2 bytes) | - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ | - ; | | | - ; | (0 if Size = 4)| | - ; +----------------+ | - ; | <-- This zone is in use (Already allocated) - ; +----------------+ <-+ - ; | Size (2 bytes) | - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ | - ; | | | - ; | (0 if Size = 4)| | - ; +----------------+ <-+ - ; | Next (2 bytes) |--> NULL => END OF LIST - ; | 0 = NULL | - ; +----------------+ - ; | | - ; | (0 if Size = 4)| - ; +----------------+ - ; When a block is FREED, the previous and next pointers are examined to see - ; if we can defragment the heap. If the block to be freed is just next to the - ; previous, or to the next (or both) they will be converted into a single - ; block (so defragmented). - ; MEMORY MANAGER - ; - ; This library must be initialized calling __MEM_INIT with - ; HL = BLOCK Start & DE = Length. - ; An init directive is useful for initialization routines. - ; They will be added automatically if needed. +#line 1 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +; vim:ts=4:sw=4:et: + ; PRINT command routine + ; Does not print attribute. Use PRINT_STR or PRINT_NUM for that +#line 1 "/zxbasic/src/arch/zx48k/library-asm/sposn.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/sysvars.asm" + ;; ----------------------------------------------------------------------- + ;; ZX Basic System Vars + ;; Some of them will be mapped over Sinclair ROM ones for compatibility + ;; ----------------------------------------------------------------------- + push namespace core +SCREEN_ADDR: DW 16384 ; Screen address (can be pointed to other place to use a screen buffer) +SCREEN_ATTR_ADDR: DW 22528 ; Screen attribute address (ditto.) + ; These are mapped onto ZX Spectrum ROM VARS + CHARS EQU 23606 ; Pointer to ROM/RAM Charset + TVFLAGS EQU 23612 ; TV Flags + UDG EQU 23675 ; Pointer to UDG Charset + COORDS EQU 23677 ; Last PLOT coordinates + FLAGS2 EQU 23681 ; + ECHO_E EQU 23682 ; + DFCC EQU 23684 ; Next screen addr for PRINT + DFCCL EQU 23686 ; Next screen attr for PRINT + S_POSN EQU 23688 + ATTR_P EQU 23693 ; Current Permanent ATTRS set with INK, PAPER, etc commands + ATTR_T EQU 23695 ; temporary ATTRIBUTES + P_FLAG EQU 23697 ; + MEM0 EQU 23698 ; Temporary memory buffer used by ROM chars + SCR_COLS EQU 33 ; Screen with in columns + 1 + SCR_ROWS EQU 24 ; Screen height in rows + SCR_SIZE EQU (SCR_ROWS << 8) + SCR_COLS + pop namespace +#line 2 "/zxbasic/src/arch/zx48k/library-asm/sposn.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/attr.asm" + ; Attribute routines +; vim:ts=4:et:sw: #line 1 "/zxbasic/src/arch/zx48k/library-asm/error.asm" ; Simple error control routines ; vim:ts=4:et: @@ -438,460 +147,795 @@ __STOP: ld (ERR_NR), a ret pop namespace -#line 69 "/zxbasic/src/arch/zx48k/library-asm/alloc.asm" - ; --------------------------------------------------------------------- - ; MEM_ALLOC - ; Allocates a block of memory in the heap. - ; - ; Parameters - ; BC = Length of requested memory block - ; -; Returns: - ; HL = Pointer to the allocated block in memory. Returns 0 (NULL) - ; if the block could not be allocated (out of memory) - ; --------------------------------------------------------------------- +#line 6 "/zxbasic/src/arch/zx48k/library-asm/attr.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/in_screen.asm" push namespace core -MEM_ALLOC: -__MEM_ALLOC: ; Returns the 1st free block found of the given length (in BC) +__IN_SCREEN: + ; Returns NO carry if current coords (D, E) + ; are OUT of the screen limits PROC - LOCAL __MEM_LOOP - LOCAL __MEM_DONE - LOCAL __MEM_SUBTRACT - LOCAL __MEM_START - LOCAL TEMP, TEMP0 - TEMP EQU TEMP0 + 1 - ld hl, 0 - ld (TEMP), hl -__MEM_START: - ld hl, ZXBASIC_MEM_HEAP ; This label point to the heap start - inc bc - inc bc ; BC = BC + 2 ; block size needs 2 extra bytes for hidden pointer -__MEM_LOOP: ; Loads lengh at (HL, HL+). If Lenght >= BC, jump to __MEM_DONE - ld a, h ; HL = NULL (No memory available?) - or l -#line 113 "/zxbasic/src/arch/zx48k/library-asm/alloc.asm" - ret z ; NULL -#line 115 "/zxbasic/src/arch/zx48k/library-asm/alloc.asm" - ; HL = Pointer to Free block - ld e, (hl) - inc hl - ld d, (hl) - inc hl ; DE = Block Length - push hl ; HL = *pointer to -> next block - ex de, hl - or a ; CF = 0 - sbc hl, bc ; FREE >= BC (Length) (HL = BlockLength - Length) - jp nc, __MEM_DONE - pop hl - ld (TEMP), hl + LOCAL __IN_SCREEN_ERR + ld hl, SCR_SIZE + ld a, e + cp l + jr nc, __IN_SCREEN_ERR ; Do nothing and return if out of range + ld a, d + cp h + ret c ; Return if carry (OK) +__IN_SCREEN_ERR: +__OUT_OF_SCREEN_ERR: + ; Jumps here if out of screen + ld a, ERROR_OutOfScreen + jp __STOP ; Saves error code and exits + ENDP + pop namespace +#line 7 "/zxbasic/src/arch/zx48k/library-asm/attr.asm" + push namespace core +__ATTR_ADDR: + ; calc start address in DE (as (32 * d) + e) + ; Contributed by Santiago Romero at http://www.speccy.org + ld h, 0 ; 7 T-States + ld a, d ; 4 T-States + ld d, h + add a, a ; a * 2 ; 4 T-States + add a, a ; a * 4 ; 4 T-States + ld l, a ; HL = A * 4 ; 4 T-States + add hl, hl ; HL = A * 8 ; 15 T-States + add hl, hl ; HL = A * 16 ; 15 T-States + add hl, hl ; HL = A * 32 ; 15 T-States + add hl, de + ld de, (SCREEN_ATTR_ADDR) ; Adds the screen address + add hl, de + ; Return current screen address in HL + ret + ; Sets the attribute at a given screen coordinate (D, E). + ; The attribute is taken from the ATTR_T memory variable + ; Used by PRINT routines +SET_ATTR: + ; Checks for valid coords + call __IN_SCREEN + ret nc + call __ATTR_ADDR +__SET_ATTR: + ; Internal __FASTCALL__ Entry used by printing routines + ; HL contains the address of the ATTR cell to set + PROC +__SET_ATTR2: ; Sets attr from ATTR_T to (HL) which points to the scr address + ld de, (ATTR_T) ; E = ATTR_T, D = MASK_T + ld a, d + and (hl) + ld c, a ; C = current screen color, masked + ld a, d + cpl ; Negate mask + and e ; Mask current attributes + or c ; Mix them + ld (hl), a ; Store result in screen + ret + ENDP + pop namespace +#line 3 "/zxbasic/src/arch/zx48k/library-asm/sposn.asm" + ; Printing positioning library. + push namespace core + ; Loads into DE current ROW, COL print position from S_POSN mem var. +__LOAD_S_POSN: + PROC + ld de, (S_POSN) + ld hl, SCR_SIZE + or a + sbc hl, de ex de, hl + ret + ENDP + ; Saves ROW, COL from DE into S_POSN mem var. +__SAVE_S_POSN: + PROC + ld hl, SCR_SIZE + or a + sbc hl, de + ld (S_POSN), hl ; saves it again +__SET_SCR_PTR: ;; Fast + push de + call __ATTR_ADDR + ld (DFCCL), hl + pop de + ld a, d + ld c, a ; Saves it for later + and 0F8h ; Masks 3 lower bit ; zy + ld d, a + ld a, c ; Recovers it + and 07h ; MOD 7 ; y1 + rrca + rrca + rrca + or e + ld e, a + ld hl, (SCREEN_ADDR) + add hl, de ; HL = Screen address + DE + ld (DFCC), hl + ret + ENDP + pop namespace +#line 6 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/table_jump.asm" + push namespace core +JUMP_HL_PLUS_2A: ; Does JP (HL + A*2) Modifies DE. Modifies A + add a, a +JUMP_HL_PLUS_A: ; Does JP (HL + A) Modifies DE + ld e, a + ld d, 0 +JUMP_HL_PLUS_DE: ; Does JP (HL + DE) + add hl, de ld e, (hl) inc hl ld d, (hl) ex de, hl - jp __MEM_LOOP -__MEM_DONE: ; A free block has been found. - ; Check if at least 4 bytes remains free (HL >= 4) - push hl - exx ; exx to preserve bc - pop hl - ld bc, 4 +CALL_HL: + jp (hl) + pop namespace +#line 8 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/ink.asm" + ; Sets ink color in ATTR_P permanently +; Parameter: Paper color in A register + push namespace core +INK: + PROC + LOCAL __SET_INK + LOCAL __SET_INK2 + ld de, ATTR_P +__SET_INK: + cp 8 + jr nz, __SET_INK2 + inc de ; Points DE to MASK_T or MASK_P + ld a, (de) + or 7 ; Set bits 0,1,2 to enable transparency + ld (de), a + ret +__SET_INK2: + ; Another entry. This will set the ink color at location pointer by DE + and 7 ; # Gets color mod 8 + ld b, a ; Saves the color + ld a, (de) + and 0F8h ; Clears previous value + or b + ld (de), a + inc de ; Points DE to MASK_T or MASK_P + ld a, (de) + and 0F8h ; Reset bits 0,1,2 sign to disable transparency + ld (de), a ; Store new attr + ret + ; Sets the INK color passed in A register in the ATTR_T variable +INK_TMP: + ld de, ATTR_T + jp __SET_INK + ENDP + pop namespace +#line 9 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/paper.asm" + ; Sets paper color in ATTR_P permanently +; Parameter: Paper color in A register + push namespace core +PAPER: + PROC + LOCAL __SET_PAPER + LOCAL __SET_PAPER2 + ld de, ATTR_P +__SET_PAPER: + cp 8 + jr nz, __SET_PAPER2 + inc de + ld a, (de) + or 038h + ld (de), a + ret + ; Another entry. This will set the paper color at location pointer by DE +__SET_PAPER2: + and 7 ; # Remove + rlca + rlca + rlca ; a *= 8 + ld b, a ; Saves the color + ld a, (de) + and 0C7h ; Clears previous value + or b + ld (de), a + inc de ; Points to MASK_T or MASK_P accordingly + ld a, (de) + and 0C7h ; Resets bits 3,4,5 + ld (de), a + ret + ; Sets the PAPER color passed in A register in the ATTR_T variable +PAPER_TMP: + ld de, ATTR_T + jp __SET_PAPER + ENDP + pop namespace +#line 10 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/flash.asm" + ; Sets flash flag in ATTR_P permanently +; Parameter: Paper color in A register + push namespace core +FLASH: + ld hl, ATTR_P + PROC + LOCAL IS_TR + LOCAL IS_ZERO +__SET_FLASH: + ; Another entry. This will set the flash flag at location pointer by DE + cp 8 + jr z, IS_TR + ; # Convert to 0/1 or a - sbc hl, bc - exx - jp nc, __MEM_SUBTRACT - ; At this point... - ; less than 4 bytes remains free. So we return this block entirely - ; We must link the previous block with the next to this one - ; (DE) => Pointer to next block - ; (TEMP) => &(previous->next) - pop hl ; Discard current block pointer - push de - ex de, hl ; DE = Previous block pointer; (HL) = Next block pointer + jr z, IS_ZERO + ld a, 0x80 +IS_ZERO: + ld b, a ; Saves the color ld a, (hl) + and 07Fh ; Clears previous value + or b + ld (hl), a inc hl - ld h, (hl) - ld l, a ; HL = (HL) - ex de, hl ; HL = Previous block pointer; DE = Next block pointer -TEMP0: - ld hl, 0 ; Pre-previous block pointer - ld (hl), e - inc hl - ld (hl), d ; LINKED - pop hl ; Returning block. + res 7, (hl) ;Reset bit 7 to disable transparency ret -__MEM_SUBTRACT: - ; At this point we have to store HL value (Length - BC) into (DE - 2) - ex de, hl - dec hl - ld (hl), d - dec hl - ld (hl), e ; Store new block length - add hl, de ; New length + DE => free-block start - pop de ; Remove previous HL off the stack - ld (hl), c ; Store length on its 1st word - inc hl - ld (hl), b - inc hl ; Return hl +IS_TR: ; transparent + inc hl ; Points DE to MASK_T or MASK_P + set 7, (hl) ;Set bit 7 to enable transparency ret + ; Sets the FLASH flag passed in A register in the ATTR_T variable +FLASH_TMP: + ld hl, ATTR_T + jr __SET_FLASH ENDP pop namespace -#line 2 "/zxbasic/src/arch/zx48k/library-asm/loadstr.asm" - ; Loads a string (ptr) from HL - ; and duplicates it on dynamic memory again - ; Finally, it returns result pointer in HL +#line 11 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/bright.asm" + ; Sets bright flag in ATTR_P permanently +; Parameter: Paper color in A register push namespace core -__ILOADSTR: ; This is the indirect pointer entry HL = (HL) - ld a, h - or l - ret z +BRIGHT: + ld hl, ATTR_P + PROC + LOCAL IS_TR + LOCAL IS_ZERO +__SET_BRIGHT: + ; Another entry. This will set the bright flag at location pointer by DE + cp 8 + jr z, IS_TR + ; # Convert to 0/1 + or a + jr z, IS_ZERO + ld a, 0x40 +IS_ZERO: + ld b, a ; Saves the color ld a, (hl) + and 0BFh ; Clears previous value + or b + ld (hl), a inc hl - ld h, (hl) - ld l, a -__LOADSTR: ; __FASTCALL__ entry - ld a, h - or l - ret z ; Return if NULL - ld c, (hl) - inc hl - ld b, (hl) - dec hl ; BC = LEN(a$) - inc bc - inc bc ; BC = LEN(a$) + 2 (two bytes for length) - push hl - push bc - call __MEM_ALLOC - pop bc ; Recover length - pop de ; Recover origin - ld a, h - or l - ret z ; Return if NULL (No memory) - ex de, hl ; ldir takes HL as source, DE as destiny, so SWAP HL,DE - push de ; Saves destiny start - ldir ; Copies string (length number included) - pop hl ; Recovers destiny in hl as result + res 6, (hl) ;Reset bit 6 to disable transparency + ret +IS_TR: ; transparent + inc hl ; Points DE to MASK_T or MASK_P + set 6, (hl) ;Set bit 6 to enable transparency ret + ; Sets the BRIGHT flag passed in A register in the ATTR_T variable +BRIGHT_TMP: + ld hl, ATTR_T + jr __SET_BRIGHT + ENDP pop namespace -#line 53 "zx48k/stringparam.bas" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/print_eol_attr.asm" - ; Calls PRINT_EOL and then COPY_ATTR, so saves - ; 3 bytes -#line 1 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -; vim:ts=4:sw=4:et: - ; PRINT command routine - ; Does not print attribute. Use PRINT_STR or PRINT_NUM for that -#line 1 "/zxbasic/src/arch/zx48k/library-asm/sposn.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/sysvars.asm" - ;; ----------------------------------------------------------------------- - ;; ZX Basic System Vars - ;; Some of them will be mapped over Sinclair ROM ones for compatibility - ;; ----------------------------------------------------------------------- - push namespace core -SCREEN_ADDR: DW 16384 ; Screen address (can be pointed to other place to use a screen buffer) -SCREEN_ATTR_ADDR: DW 22528 ; Screen attribute address (ditto.) - ; These are mapped onto ZX Spectrum ROM VARS - CHARS EQU 23606 ; Pointer to ROM/RAM Charset - TVFLAGS EQU 23612 ; TV Flags - UDG EQU 23675 ; Pointer to UDG Charset - COORDS EQU 23677 ; Last PLOT coordinates - FLAGS2 EQU 23681 ; - ECHO_E EQU 23682 ; - DFCC EQU 23684 ; Next screen addr for PRINT - DFCCL EQU 23686 ; Next screen attr for PRINT - S_POSN EQU 23688 - ATTR_P EQU 23693 ; Current Permanent ATTRS set with INK, PAPER, etc commands - ATTR_T EQU 23695 ; temporary ATTRIBUTES - P_FLAG EQU 23697 ; - MEM0 EQU 23698 ; Temporary memory buffer used by ROM chars - SCR_COLS EQU 33 ; Screen with in columns + 1 - SCR_ROWS EQU 24 ; Screen height in rows - SCR_SIZE EQU (SCR_ROWS << 8) + SCR_COLS - pop namespace -#line 2 "/zxbasic/src/arch/zx48k/library-asm/sposn.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/attr.asm" - ; Attribute routines -; vim:ts=4:et:sw: -#line 1 "/zxbasic/src/arch/zx48k/library-asm/in_screen.asm" +#line 12 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/over.asm" + ; Sets OVER flag in P_FLAG permanently +; Parameter: OVER flag in bit 0 of A register push namespace core -__IN_SCREEN: - ; Returns NO carry if current coords (D, E) - ; are OUT of the screen limits +OVER: PROC - LOCAL __IN_SCREEN_ERR - ld hl, SCR_SIZE - ld a, e - cp l - jr nc, __IN_SCREEN_ERR ; Do nothing and return if out of range - ld a, d - cp h - ret c ; Return if carry (OK) -__IN_SCREEN_ERR: -__OUT_OF_SCREEN_ERR: - ; Jumps here if out of screen - ld a, ERROR_OutOfScreen - jp __STOP ; Saves error code and exits + ld c, a ; saves it for later + and 2 + ld hl, FLAGS2 + res 1, (HL) + or (hl) + ld (hl), a + ld a, c ; Recovers previous value + and 1 ; # Convert to 0/1 + add a, a; # Shift left 1 bit for permanent + ld hl, P_FLAG + res 1, (hl) + or (hl) + ld (hl), a + ret + ; Sets OVER flag in P_FLAG temporarily +OVER_TMP: + ld c, a ; saves it for later + and 2 ; gets bit 1; clears carry + rra + ld hl, FLAGS2 + res 0, (hl) + or (hl) + ld (hl), a + ld a, c ; Recovers previous value + and 1 + ld hl, P_FLAG + res 0, (hl) + or (hl) + ld (hl), a + jp __SET_ATTR_MODE + ENDP + pop namespace +#line 13 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/inverse.asm" + ; Sets INVERSE flag in P_FLAG permanently +; Parameter: INVERSE flag in bit 0 of A register + push namespace core +INVERSE: + PROC + and 1 ; # Convert to 0/1 + add a, a; # Shift left 3 bits for permanent + add a, a + add a, a + ld hl, P_FLAG + res 3, (hl) + or (hl) + ld (hl), a + ret + ; Sets INVERSE flag in P_FLAG temporarily +INVERSE_TMP: + and 1 + add a, a + add a, a; # Shift left 2 bits for temporary + ld hl, P_FLAG + res 2, (hl) + or (hl) + ld (hl), a + jp __SET_ATTR_MODE + ENDP + pop namespace +#line 14 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/bold.asm" + ; Sets BOLD flag in P_FLAG permanently +; Parameter: BOLD flag in bit 0 of A register + push namespace core +BOLD: + PROC + and 1 + rlca + rlca + rlca + ld hl, FLAGS2 + res 3, (HL) + or (hl) + ld (hl), a + ret + ; Sets BOLD flag in P_FLAG temporarily +BOLD_TMP: + and 1 + rlca + rlca + ld hl, FLAGS2 + res 2, (hl) + or (hl) + ld (hl), a + ret ENDP pop namespace -#line 7 "/zxbasic/src/arch/zx48k/library-asm/attr.asm" +#line 15 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/italic.asm" + ; Sets ITALIC flag in P_FLAG permanently +; Parameter: ITALIC flag in bit 0 of A register push namespace core -__ATTR_ADDR: - ; calc start address in DE (as (32 * d) + e) - ; Contributed by Santiago Romero at http://www.speccy.org - ld h, 0 ; 7 T-States - ld a, d ; 4 T-States - ld d, h - add a, a ; a * 2 ; 4 T-States - add a, a ; a * 4 ; 4 T-States - ld l, a ; HL = A * 4 ; 4 T-States - add hl, hl ; HL = A * 8 ; 15 T-States - add hl, hl ; HL = A * 16 ; 15 T-States - add hl, hl ; HL = A * 32 ; 15 T-States - add hl, de - ld de, (SCREEN_ATTR_ADDR) ; Adds the screen address - add hl, de - ; Return current screen address in HL - ret - ; Sets the attribute at a given screen coordinate (D, E). - ; The attribute is taken from the ATTR_T memory variable - ; Used by PRINT routines -SET_ATTR: - ; Checks for valid coords - call __IN_SCREEN - ret nc - call __ATTR_ADDR -__SET_ATTR: - ; Internal __FASTCALL__ Entry used by printing routines - ; HL contains the address of the ATTR cell to set +ITALIC: PROC -__SET_ATTR2: ; Sets attr from ATTR_T to (HL) which points to the scr address - ld de, (ATTR_T) ; E = ATTR_T, D = MASK_T - ld a, d - and (hl) - ld c, a ; C = current screen color, masked - ld a, d - cpl ; Negate mask - and e ; Mask current attributes - or c ; Mix them - ld (hl), a ; Store result in screen + and 1 + rrca + rrca + rrca + ld hl, FLAGS2 + res 5, (HL) + or (hl) + ld (hl), a + ret + ; Sets ITALIC flag in P_FLAG temporarily +ITALIC_TMP: + and 1 + rrca + rrca + rrca + rrca + ld hl, FLAGS2 + res 4, (hl) + or (hl) + ld (hl), a ret ENDP pop namespace -#line 3 "/zxbasic/src/arch/zx48k/library-asm/sposn.asm" - ; Printing positioning library. +#line 16 "/zxbasic/src/arch/zx48k/library-asm/print.asm" + ; Putting a comment starting with @INIT
+ ; will make the compiler to add a CALL to
+ ; It is useful for initialization routines. push namespace core - ; Loads into DE current ROW, COL print position from S_POSN mem var. -__LOAD_S_POSN: +__PRINT_INIT: ; To be called before program starts (initializes library) PROC - ld de, (S_POSN) + ld hl, __PRINT_START + ld (PRINT_JUMP_STATE), hl + ;; Clears ATTR2 flags (OVER 2, etc) + xor a + ld (FLAGS2), a + LOCAL SET_SCR_ADDR + call __LOAD_S_POSN + jp __SET_SCR_PTR + ;; Receives HL = future value of S_POSN + ;; Stores it at (S_POSN) and refresh screen pointers (ATTR, SCR) +SET_SCR_ADDR: + ld (S_POSN), hl + ex de, hl ld hl, SCR_SIZE or a sbc hl, de ex de, hl + dec e + jp __SET_SCR_PTR +__PRINTCHAR: ; Print character store in accumulator (A register) + ; Modifies H'L', B'C', A'F', D'E', A + LOCAL PO_GR_1 + LOCAL __PRCHAR + LOCAL __PRINT_JUMP + LOCAL __SRCADDR + LOCAL __PRINT_UDG + LOCAL __PRGRAPH + LOCAL __PRINT_START + PRINT_JUMP_STATE EQU __PRINT_JUMP + 2 +__PRINT_JUMP: + exx ; Switch to alternative registers + jp __PRINT_START ; Where to jump. If we print 22 (AT), next two calls jumps to AT1 and AT2 respectively +__PRINT_START: +__PRINT_CHR: + cp ' ' + jr c, __PRINT_SPECIAL ; Characters below ' ' are special ones + ex af, af' ; Saves a value (char to print) for later + ld hl, (S_POSN) + dec l + jr nz, 1f + ld l, SCR_COLS - 1 + dec h + jr nz, 2f + inc h + push hl + call __SCROLL_SCR + pop hl +#line 92 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +2: + call SET_SCR_ADDR + jr 4f +1: + ld (S_POSN), hl +4: + ex af, af' + cp 80h ; Is it a "normal" (printable) char + jr c, __SRCADDR + cp 90h ; Is it an UDG? + jr nc, __PRINT_UDG + ; Print an 8 bit pattern (80h to 8Fh) + ld b, a + call PO_GR_1 ; This ROM routine will generate the bit pattern at MEM0 + ld hl, MEM0 + jp __PRGRAPH + PO_GR_1 EQU 0B38h +__PRINT_UDG: + sub 90h ; Sub ASC code + ld bc, (UDG) + jr __PRGRAPH0 + __SOURCEADDR EQU (__SRCADDR + 1) ; Address of the pointer to chars source +__SRCADDR: + ld bc, (CHARS) +__PRGRAPH0: + add a, a ; A = a * 2 (since a < 80h) ; Thanks to Metalbrain at http://foro.speccy.org + ld l, a + ld h, 0 ; HL = a * 2 (accumulator) + add hl, hl + add hl, hl ; HL = a * 8 + add hl, bc ; HL = CHARS address +__PRGRAPH: + ex de, hl ; HL = Write Address, DE = CHARS address + bit 2, (iy + $47) + call nz, __BOLD +#line 139 "/zxbasic/src/arch/zx48k/library-asm/print.asm" + bit 4, (iy + $47) + call nz, __ITALIC +#line 144 "/zxbasic/src/arch/zx48k/library-asm/print.asm" + ld hl, (DFCC) + push hl + ld b, 8 ; 8 bytes per char +__PRCHAR: + ld a, (de) ; DE *must* be source, and HL destiny +PRINT_MODE: ; Which operation is used to write on the screen + ; Set it with: + ; LD A, + ; LD (PRINT_MODE), A + ; + ; Available operations: + ; NORMAL : 0h --> NOP ; OVER 0 + ; XOR : AEh --> XOR (HL) ; OVER 1 + ; OR : B6h --> OR (HL) ; PUTSPRITE + ; AND : A6h --> AND (HL) ; PUTMASK + nop ; Set to one of the values above +INVERSE_MODE: ; 00 -> NOP -> INVERSE 0 + nop ; 2F -> CPL -> INVERSE 1 + ld (hl), a + inc de + inc h ; Next line + djnz __PRCHAR + pop hl + inc hl + ld (DFCC), hl + ld hl, (DFCCL) ; current ATTR Pos + inc hl + ld (DFCCL), hl + dec hl + call __SET_ATTR + exx ret - ENDP - ; Saves ROW, COL from DE into S_POSN mem var. -__SAVE_S_POSN: - PROC - ld hl, SCR_SIZE - or a - sbc hl, de - ld (S_POSN), hl ; saves it again -__SET_SCR_PTR: ;; Fast + ; ------------- SPECIAL CHARS (< 32) ----------------- +__PRINT_SPECIAL: ; Jumps here if it is a special char + ld hl, __PRINT_TABLE + jp JUMP_HL_PLUS_2A +PRINT_EOL: ; Called WHENEVER there is no ";" at end of PRINT sentence + exx +__PRINT_0Dh: ; Called WHEN printing CHR$(13) + ld hl, (S_POSN) + dec l + jr nz, 1f + dec h + jr nz, 1f + inc h + push hl + call __SCROLL_SCR + pop hl +#line 209 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +1: + ld l, 1 +__PRINT_EOL_END: + call SET_SCR_ADDR + exx + ret +__PRINT_COM: + exx + push hl push de - call __ATTR_ADDR - ld (DFCCL), hl + push bc + call PRINT_COMMA + pop bc pop de - ld a, d - ld c, a ; Saves it for later - and 0F8h ; Masks 3 lower bit ; zy - ld d, a - ld a, c ; Recovers it - and 07h ; MOD 7 ; y1 - rrca - rrca - rrca - or e - ld e, a - ld hl, (SCREEN_ADDR) - add hl, de ; HL = Screen address + DE - ld (DFCC), hl + pop hl + ret +__PRINT_TAB: + ld hl, __PRINT_TAB1 + jr __PRINT_SET_STATE +__PRINT_TAB1: + ld (MEM0), a + ld hl, __PRINT_TAB2 + jr __PRINT_SET_STATE +__PRINT_TAB2: + ld a, (MEM0) ; Load tab code (ignore the current one) + ld hl, __PRINT_START + ld (PRINT_JUMP_STATE), hl + exx + push hl + push bc + push de + call PRINT_TAB + pop de + pop bc + pop hl ret - ENDP - pop namespace -#line 6 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/table_jump.asm" - push namespace core -JUMP_HL_PLUS_2A: ; Does JP (HL + A*2) Modifies DE. Modifies A - add a, a -JUMP_HL_PLUS_A: ; Does JP (HL + A) Modifies DE - ld e, a - ld d, 0 -JUMP_HL_PLUS_DE: ; Does JP (HL + DE) - add hl, de - ld e, (hl) - inc hl - ld d, (hl) - ex de, hl -CALL_HL: - jp (hl) - pop namespace -#line 8 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/ink.asm" - ; Sets ink color in ATTR_P permanently -; Parameter: Paper color in A register - push namespace core -INK: - PROC - LOCAL __SET_INK - LOCAL __SET_INK2 - ld de, ATTR_P -__SET_INK: - cp 8 - jr nz, __SET_INK2 - inc de ; Points DE to MASK_T or MASK_P - ld a, (de) - or 7 ; Set bits 0,1,2 to enable transparency - ld (de), a +__PRINT_AT: + ld hl, __PRINT_AT1 + jr __PRINT_SET_STATE +__PRINT_NOP: +__PRINT_RESTART: + ld hl, __PRINT_START +__PRINT_SET_STATE: + ld (PRINT_JUMP_STATE), hl ; Saves next entry call + exx ret -__SET_INK2: - ; Another entry. This will set the ink color at location pointer by DE - and 7 ; # Gets color mod 8 - ld b, a ; Saves the color - ld a, (de) - and 0F8h ; Clears previous value - or b - ld (de), a - inc de ; Points DE to MASK_T or MASK_P - ld a, (de) - and 0F8h ; Reset bits 0,1,2 sign to disable transparency - ld (de), a ; Store new attr +__PRINT_AT1: ; Jumps here if waiting for 1st parameter + ld hl, (S_POSN) + ld h, a + ld a, SCR_ROWS + sub h + ld (S_POSN + 1), a + ld hl, __PRINT_AT2 + jr __PRINT_SET_STATE +__PRINT_AT2: + call __LOAD_S_POSN + ld e, a + call __SAVE_S_POSN + jr __PRINT_RESTART +__PRINT_DEL: + call __LOAD_S_POSN ; Gets current screen position + dec e + ld a, -1 + cp e + jr nz, 3f + ld e, SCR_COLS - 2 + dec d + cp d + jr nz, 3f + ld d, SCR_ROWS - 1 +3: + call __SAVE_S_POSN + exx ret - ; Sets the INK color passed in A register in the ATTR_T variable -INK_TMP: - ld de, ATTR_T - jp __SET_INK - ENDP - pop namespace -#line 9 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/paper.asm" - ; Sets paper color in ATTR_P permanently -; Parameter: Paper color in A register - push namespace core -PAPER: - PROC - LOCAL __SET_PAPER - LOCAL __SET_PAPER2 - ld de, ATTR_P -__SET_PAPER: - cp 8 - jr nz, __SET_PAPER2 - inc de +__PRINT_INK: + ld hl, __PRINT_INK2 + jr __PRINT_SET_STATE +__PRINT_INK2: + call INK_TMP + jr __PRINT_RESTART +__PRINT_PAP: + ld hl, __PRINT_PAP2 + jr __PRINT_SET_STATE +__PRINT_PAP2: + call PAPER_TMP + jr __PRINT_RESTART +__PRINT_FLA: + ld hl, __PRINT_FLA2 + jr __PRINT_SET_STATE +__PRINT_FLA2: + call FLASH_TMP + jr __PRINT_RESTART +__PRINT_BRI: + ld hl, __PRINT_BRI2 + jr __PRINT_SET_STATE +__PRINT_BRI2: + call BRIGHT_TMP + jr __PRINT_RESTART +__PRINT_INV: + ld hl, __PRINT_INV2 + jr __PRINT_SET_STATE +__PRINT_INV2: + call INVERSE_TMP + jr __PRINT_RESTART +__PRINT_OVR: + ld hl, __PRINT_OVR2 + jr __PRINT_SET_STATE +__PRINT_OVR2: + call OVER_TMP + jr __PRINT_RESTART +__PRINT_BOLD: + ld hl, __PRINT_BOLD2 + jp __PRINT_SET_STATE +__PRINT_BOLD2: + call BOLD_TMP + jp __PRINT_RESTART +#line 353 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +__PRINT_ITA: + ld hl, __PRINT_ITA2 + jp __PRINT_SET_STATE +__PRINT_ITA2: + call ITALIC_TMP + jp __PRINT_RESTART +#line 363 "/zxbasic/src/arch/zx48k/library-asm/print.asm" + LOCAL __BOLD +__BOLD: + push hl + ld hl, MEM0 + ld b, 8 +1: ld a, (de) - or 038h - ld (de), a - ret - ; Another entry. This will set the paper color at location pointer by DE -__SET_PAPER2: - and 7 ; # Remove - rlca + ld c, a rlca - rlca ; a *= 8 - ld b, a ; Saves the color - ld a, (de) - and 0C7h ; Clears previous value - or b - ld (de), a - inc de ; Points to MASK_T or MASK_P accordingly - ld a, (de) - and 0C7h ; Resets bits 3,4,5 - ld (de), a - ret - ; Sets the PAPER color passed in A register in the ATTR_T variable -PAPER_TMP: - ld de, ATTR_T - jp __SET_PAPER - ENDP - pop namespace -#line 10 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/flash.asm" - ; Sets flash flag in ATTR_P permanently -; Parameter: Paper color in A register - push namespace core -FLASH: - ld hl, ATTR_P - PROC - LOCAL IS_TR - LOCAL IS_ZERO -__SET_FLASH: - ; Another entry. This will set the flash flag at location pointer by DE - cp 8 - jr z, IS_TR - ; # Convert to 0/1 - or a - jr z, IS_ZERO - ld a, 0x80 -IS_ZERO: - ld b, a ; Saves the color - ld a, (hl) - and 07Fh ; Clears previous value - or b + or c ld (hl), a inc hl - res 7, (hl) ;Reset bit 7 to disable transparency - ret -IS_TR: ; transparent - inc hl ; Points DE to MASK_T or MASK_P - set 7, (hl) ;Set bit 7 to enable transparency - ret - ; Sets the FLASH flag passed in A register in the ATTR_T variable -FLASH_TMP: - ld hl, ATTR_T - jr __SET_FLASH - ENDP - pop namespace -#line 11 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/bright.asm" - ; Sets bright flag in ATTR_P permanently -; Parameter: Paper color in A register - push namespace core -BRIGHT: - ld hl, ATTR_P - PROC - LOCAL IS_TR - LOCAL IS_ZERO -__SET_BRIGHT: - ; Another entry. This will set the bright flag at location pointer by DE - cp 8 - jr z, IS_TR - ; # Convert to 0/1 - or a - jr z, IS_ZERO - ld a, 0x40 -IS_ZERO: - ld b, a ; Saves the color - ld a, (hl) - and 0BFh ; Clears previous value - or b - ld (hl), a + inc de + djnz 1b + pop hl + ld de, MEM0 + ret +#line 384 "/zxbasic/src/arch/zx48k/library-asm/print.asm" + LOCAL __ITALIC +__ITALIC: + push hl + ld hl, MEM0 + ex de, hl + ld bc, 8 + ldir + ld hl, MEM0 + srl (hl) inc hl - res 6, (hl) ;Reset bit 6 to disable transparency + srl (hl) + inc hl + srl (hl) + inc hl + inc hl + inc hl + sla (hl) + inc hl + sla (hl) + inc hl + sla (hl) + pop hl + ld de, MEM0 ret -IS_TR: ; transparent - inc hl ; Points DE to MASK_T or MASK_P - set 6, (hl) ;Set bit 6 to enable transparency +#line 412 "/zxbasic/src/arch/zx48k/library-asm/print.asm" + LOCAL __SCROLL_SCR +#line 486 "/zxbasic/src/arch/zx48k/library-asm/print.asm" + __SCROLL_SCR EQU 0DFEh ; Use ROM SCROLL +#line 488 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 489 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +PRINT_COMMA: + call __LOAD_S_POSN + ld a, e + and 16 + add a, 16 +PRINT_TAB: + ; Tabulates the number of spaces in A register + ; If the current cursor position is already A, does nothing + PROC + LOCAL LOOP + call __LOAD_S_POSN ; e = current row + sub e + and 31 + ret z + ld b, a +LOOP: + ld a, ' ' + call __PRINTCHAR + djnz LOOP ret - ; Sets the BRIGHT flag passed in A register in the ATTR_T variable -BRIGHT_TMP: - ld hl, ATTR_T - jr __SET_BRIGHT + ENDP +PRINT_AT: ; Changes cursor to ROW, COL + ; COL in A register + ; ROW in stack + pop hl ; Ret address + ex (sp), hl ; callee H = ROW + ld l, a + ex de, hl + call __IN_SCREEN + ret nc ; Return if out of screen + jp __SAVE_S_POSN + LOCAL __PRINT_COM + LOCAL __PRINT_AT1 + LOCAL __PRINT_AT2 + LOCAL __PRINT_BOLD + LOCAL __PRINT_ITA + LOCAL __PRINT_INK + LOCAL __PRINT_PAP + LOCAL __PRINT_SET_STATE + LOCAL __PRINT_TABLE + LOCAL __PRINT_TAB, __PRINT_TAB1, __PRINT_TAB2 + LOCAL __PRINT_ITA2 +#line 545 "/zxbasic/src/arch/zx48k/library-asm/print.asm" + LOCAL __PRINT_BOLD2 +#line 551 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +__PRINT_TABLE: ; Jump table for 0 .. 22 codes + DW __PRINT_NOP ; 0 + DW __PRINT_NOP ; 1 + DW __PRINT_NOP ; 2 + DW __PRINT_NOP ; 3 + DW __PRINT_NOP ; 4 + DW __PRINT_NOP ; 5 + DW __PRINT_COM ; 6 COMMA + DW __PRINT_NOP ; 7 + DW __PRINT_DEL ; 8 DEL + DW __PRINT_NOP ; 9 + DW __PRINT_NOP ; 10 + DW __PRINT_NOP ; 11 + DW __PRINT_NOP ; 12 + DW __PRINT_0Dh ; 13 + DW __PRINT_BOLD ; 14 + DW __PRINT_ITA ; 15 + DW __PRINT_INK ; 16 + DW __PRINT_PAP ; 17 + DW __PRINT_FLA ; 18 + DW __PRINT_BRI ; 19 + DW __PRINT_INV ; 20 + DW __PRINT_OVR ; 21 + DW __PRINT_AT ; 22 AT + DW __PRINT_TAB ; 23 TAB ENDP pop namespace -#line 12 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/over.asm" - ; Sets OVER flag in P_FLAG permanently -; Parameter: OVER flag in bit 0 of A register -#line 1 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" +#line 3 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" #line 4 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" push namespace core COPY_ATTR: @@ -944,523 +988,470 @@ __REFRESH_TMP: ret ENDP pop namespace -#line 4 "/zxbasic/src/arch/zx48k/library-asm/over.asm" - push namespace core -OVER: - PROC - ld c, a ; saves it for later - and 2 - ld hl, FLAGS2 - res 1, (HL) - or (hl) - ld (hl), a - ld a, c ; Recovers previous value - and 1 ; # Convert to 0/1 - add a, a; # Shift left 1 bit for permanent - ld hl, P_FLAG - res 1, (hl) - or (hl) - ld (hl), a - ret - ; Sets OVER flag in P_FLAG temporarily -OVER_TMP: - ld c, a ; saves it for later - and 2 ; gets bit 1; clears carry - rra - ld hl, FLAGS2 - res 0, (hl) - or (hl) - ld (hl), a - ld a, c ; Recovers previous value - and 1 - ld hl, P_FLAG - res 0, (hl) - or (hl) - ld (hl), a - jp __SET_ATTR_MODE - ENDP - pop namespace -#line 13 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/inverse.asm" - ; Sets INVERSE flag in P_FLAG permanently -; Parameter: INVERSE flag in bit 0 of A register - push namespace core -INVERSE: - PROC - and 1 ; # Convert to 0/1 - add a, a; # Shift left 3 bits for permanent - add a, a - add a, a - ld hl, P_FLAG - res 3, (hl) - or (hl) - ld (hl), a - ret - ; Sets INVERSE flag in P_FLAG temporarily -INVERSE_TMP: - and 1 - add a, a - add a, a; # Shift left 2 bits for temporary - ld hl, P_FLAG - res 2, (hl) - or (hl) - ld (hl), a - jp __SET_ATTR_MODE - ENDP - pop namespace -#line 14 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/bold.asm" - ; Sets BOLD flag in P_FLAG permanently -; Parameter: BOLD flag in bit 0 of A register - push namespace core -BOLD: - PROC - and 1 - rlca - rlca - rlca - ld hl, FLAGS2 - res 3, (HL) - or (hl) - ld (hl), a - ret - ; Sets BOLD flag in P_FLAG temporarily -BOLD_TMP: - and 1 - rlca - rlca - ld hl, FLAGS2 - res 2, (hl) - or (hl) - ld (hl), a - ret - ENDP - pop namespace -#line 15 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/italic.asm" - ; Sets ITALIC flag in P_FLAG permanently -; Parameter: ITALIC flag in bit 0 of A register +#line 53 "zx48k/stringparam.bas" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/free.asm" +; vim: ts=4:et:sw=4: + ; Copyleft (K) by Jose M. Rodriguez de la Rosa + ; (a.k.a. Boriel) +; http://www.boriel.com + ; + ; This ASM library is licensed under the BSD license + ; you can use it for any purpose (even for commercial + ; closed source programs). + ; + ; Please read the BSD license on the internet + ; ----- IMPLEMENTATION NOTES ------ + ; The heap is implemented as a linked list of free blocks. +; Each free block contains this info: + ; + ; +----------------+ <-- HEAP START + ; | Size (2 bytes) | + ; | 0 | <-- Size = 0 => DUMMY HEADER BLOCK + ; +----------------+ + ; | Next (2 bytes) |---+ + ; +----------------+ <-+ + ; | Size (2 bytes) | + ; +----------------+ + ; | Next (2 bytes) |---+ + ; +----------------+ | + ; | | | <-- If Size > 4, then this contains (size - 4) bytes + ; | (0 if Size = 4)| | + ; +----------------+ <-+ + ; | Size (2 bytes) | + ; +----------------+ + ; | Next (2 bytes) |---+ + ; +----------------+ | + ; | | | + ; | (0 if Size = 4)| | + ; +----------------+ | + ; | <-- This zone is in use (Already allocated) + ; +----------------+ <-+ + ; | Size (2 bytes) | + ; +----------------+ + ; | Next (2 bytes) |---+ + ; +----------------+ | + ; | | | + ; | (0 if Size = 4)| | + ; +----------------+ <-+ + ; | Next (2 bytes) |--> NULL => END OF LIST + ; | 0 = NULL | + ; +----------------+ + ; | | + ; | (0 if Size = 4)| + ; +----------------+ + ; When a block is FREED, the previous and next pointers are examined to see + ; if we can defragment the heap. If the block to be breed is just next to the + ; previous, or to the next (or both) they will be converted into a single + ; block (so defragmented). + ; MEMORY MANAGER + ; + ; This library must be initialized calling __MEM_INIT with + ; HL = BLOCK Start & DE = Length. + ; An init directive is useful for initialization routines. + ; They will be added automatically if needed. +#line 1 "/zxbasic/src/arch/zx48k/library-asm/heapinit.asm" +; vim: ts=4:et:sw=4: + ; Copyleft (K) by Jose M. Rodriguez de la Rosa + ; (a.k.a. Boriel) +; http://www.boriel.com + ; + ; This ASM library is licensed under the BSD license + ; you can use it for any purpose (even for commercial + ; closed source programs). + ; + ; Please read the BSD license on the internet + ; ----- IMPLEMENTATION NOTES ------ + ; The heap is implemented as a linked list of free blocks. +; Each free block contains this info: + ; + ; +----------------+ <-- HEAP START + ; | Size (2 bytes) | + ; | 0 | <-- Size = 0 => DUMMY HEADER BLOCK + ; +----------------+ + ; | Next (2 bytes) |---+ + ; +----------------+ <-+ + ; | Size (2 bytes) | + ; +----------------+ + ; | Next (2 bytes) |---+ + ; +----------------+ | + ; | | | <-- If Size > 4, then this contains (size - 4) bytes + ; | (0 if Size = 4)| | + ; +----------------+ <-+ + ; | Size (2 bytes) | + ; +----------------+ + ; | Next (2 bytes) |---+ + ; +----------------+ | + ; | | | + ; | (0 if Size = 4)| | + ; +----------------+ | + ; | <-- This zone is in use (Already allocated) + ; +----------------+ <-+ + ; | Size (2 bytes) | + ; +----------------+ + ; | Next (2 bytes) |---+ + ; +----------------+ | + ; | | | + ; | (0 if Size = 4)| | + ; +----------------+ <-+ + ; | Next (2 bytes) |--> NULL => END OF LIST + ; | 0 = NULL | + ; +----------------+ + ; | | + ; | (0 if Size = 4)| + ; +----------------+ + ; When a block is FREED, the previous and next pointers are examined to see + ; if we can defragment the heap. If the block to be breed is just next to the + ; previous, or to the next (or both) they will be converted into a single + ; block (so defragmented). + ; MEMORY MANAGER + ; + ; This library must be initialized calling __MEM_INIT with + ; HL = BLOCK Start & DE = Length. + ; An init directive is useful for initialization routines. + ; They will be added automatically if needed. + ; --------------------------------------------------------------------- + ; __MEM_INIT must be called to initalize this library with the + ; standard parameters + ; --------------------------------------------------------------------- push namespace core -ITALIC: +__MEM_INIT: ; Initializes the library using (RAMTOP) as start, and + ld hl, ZXBASIC_MEM_HEAP ; Change this with other address of heap start + ld de, ZXBASIC_HEAP_SIZE ; Change this with your size + ; --------------------------------------------------------------------- + ; __MEM_INIT2 initalizes this library +; Parameters: +; HL : Memory address of 1st byte of the memory heap +; DE : Length in bytes of the Memory Heap + ; --------------------------------------------------------------------- +__MEM_INIT2: + ; HL as TOP PROC - and 1 - rrca - rrca - rrca - ld hl, FLAGS2 - res 5, (HL) - or (hl) + dec de + dec de + dec de + dec de ; DE = length - 4; HL = start + ; This is done, because we require 4 bytes for the empty dummy-header block + xor a ld (hl), a - ret - ; Sets ITALIC flag in P_FLAG temporarily -ITALIC_TMP: - and 1 - rrca - rrca - rrca - rrca - ld hl, FLAGS2 - res 4, (hl) - or (hl) + inc hl + ld (hl), a ; First "free" block is a header: size=0, Pointer=&(Block) + 4 + inc hl + ld b, h + ld c, l + inc bc + inc bc ; BC = starts of next block + ld (hl), c + inc hl + ld (hl), b + inc hl ; Pointer to next block + ld (hl), e + inc hl + ld (hl), d + inc hl ; Block size (should be length - 4 at start); This block contains all the available memory + ld (hl), a ; NULL (0000h) ; No more blocks (a list with a single block) + inc hl ld (hl), a + ld a, 201 + ld (__MEM_INIT), a; "Pokes" with a RET so ensure this routine is not called again ret ENDP pop namespace -#line 16 "/zxbasic/src/arch/zx48k/library-asm/print.asm" - ; Putting a comment starting with @INIT
- ; will make the compiler to add a CALL to
- ; It is useful for initialization routines. +#line 69 "/zxbasic/src/arch/zx48k/library-asm/free.asm" + ; --------------------------------------------------------------------- + ; MEM_FREE + ; Frees a block of memory + ; +; Parameters: + ; HL = Pointer to the block to be freed. If HL is NULL (0) nothing + ; is done + ; --------------------------------------------------------------------- push namespace core -__PRINT_INIT: ; To be called before program starts (initializes library) - PROC - ld hl, __PRINT_START - ld (PRINT_JUMP_STATE), hl - ;; Clears ATTR2 flags (OVER 2, etc) - xor a - ld (FLAGS2), a - LOCAL SET_SCR_ADDR - call __LOAD_S_POSN - jp __SET_SCR_PTR - ;; Receives HL = future value of S_POSN - ;; Stores it at (S_POSN) and refresh screen pointers (ATTR, SCR) -SET_SCR_ADDR: - ld (S_POSN), hl - ex de, hl - ld hl, SCR_SIZE - or a - sbc hl, de - ex de, hl - dec e - jp __SET_SCR_PTR -__PRINTCHAR: ; Print character store in accumulator (A register) - ; Modifies H'L', B'C', A'F', D'E', A - LOCAL PO_GR_1 - LOCAL __PRCHAR - LOCAL __PRINT_JUMP - LOCAL __SRCADDR - LOCAL __PRINT_UDG - LOCAL __PRGRAPH - LOCAL __PRINT_START - PRINT_JUMP_STATE EQU __PRINT_JUMP + 2 -__PRINT_JUMP: - exx ; Switch to alternative registers - jp __PRINT_START ; Where to jump. If we print 22 (AT), next two calls jumps to AT1 and AT2 respectively -__PRINT_START: -__PRINT_CHR: - cp ' ' - jr c, __PRINT_SPECIAL ; Characters below ' ' are special ones - ex af, af' ; Saves a value (char to print) for later - ld hl, (S_POSN) - dec l - jr nz, 1f - ld l, SCR_COLS - 1 - dec h - jr nz, 2f - inc h - push hl - call __SCROLL_SCR - pop hl -#line 92 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -2: - call SET_SCR_ADDR - jr 4f -1: - ld (S_POSN), hl -4: - ex af, af' - cp 80h ; Is it a "normal" (printable) char - jr c, __SRCADDR - cp 90h ; Is it an UDG? - jr nc, __PRINT_UDG - ; Print an 8 bit pattern (80h to 8Fh) - ld b, a - call PO_GR_1 ; This ROM routine will generate the bit pattern at MEM0 - ld hl, MEM0 - jp __PRGRAPH - PO_GR_1 EQU 0B38h -__PRINT_UDG: - sub 90h ; Sub ASC code - ld bc, (UDG) - jr __PRGRAPH0 - __SOURCEADDR EQU (__SRCADDR + 1) ; Address of the pointer to chars source -__SRCADDR: - ld bc, (CHARS) -__PRGRAPH0: - add a, a ; A = a * 2 (since a < 80h) ; Thanks to Metalbrain at http://foro.speccy.org - ld l, a - ld h, 0 ; HL = a * 2 (accumulator) - add hl, hl - add hl, hl ; HL = a * 8 - add hl, bc ; HL = CHARS address -__PRGRAPH: - ex de, hl ; HL = Write Address, DE = CHARS address - bit 2, (iy + $47) - call nz, __BOLD -#line 139 "/zxbasic/src/arch/zx48k/library-asm/print.asm" - bit 4, (iy + $47) - call nz, __ITALIC -#line 144 "/zxbasic/src/arch/zx48k/library-asm/print.asm" - ld hl, (DFCC) - push hl - ld b, 8 ; 8 bytes per char -__PRCHAR: - ld a, (de) ; DE *must* be source, and HL destiny -PRINT_MODE: ; Which operation is used to write on the screen - ; Set it with: - ; LD A, - ; LD (PRINT_MODE), A - ; - ; Available operations: - ; NORMAL : 0h --> NOP ; OVER 0 - ; XOR : AEh --> XOR (HL) ; OVER 1 - ; OR : B6h --> OR (HL) ; PUTSPRITE - ; AND : A6h --> AND (HL) ; PUTMASK - nop ; Set to one of the values above -INVERSE_MODE: ; 00 -> NOP -> INVERSE 0 - nop ; 2F -> CPL -> INVERSE 1 - ld (hl), a - inc de - inc h ; Next line - djnz __PRCHAR - pop hl +MEM_FREE: +__MEM_FREE: ; Frees the block pointed by HL + ; HL DE BC & AF modified + PROC + LOCAL __MEM_LOOP2 + LOCAL __MEM_LINK_PREV + LOCAL __MEM_JOIN_TEST + LOCAL __MEM_BLOCK_JOIN + ld a, h + or l + ret z ; Return if NULL pointer + dec hl + dec hl + ld b, h + ld c, l ; BC = Block pointer + ld hl, ZXBASIC_MEM_HEAP ; This label point to the heap start +__MEM_LOOP2: inc hl - ld (DFCC), hl - ld hl, (DFCCL) ; current ATTR Pos - push hl - call __SET_ATTR - pop hl + inc hl ; Next block ptr + ld e, (hl) inc hl - ld (DFCCL),hl - exx - ret - ; ------------- SPECIAL CHARS (< 32) ----------------- -__PRINT_SPECIAL: ; Jumps here if it is a special char - ld hl, __PRINT_TABLE - jp JUMP_HL_PLUS_2A -PRINT_EOL: ; Called WHENEVER there is no ";" at end of PRINT sentence - exx -__PRINT_0Dh: ; Called WHEN printing CHR$(13) - ld hl, (S_POSN) - dec l - jr nz, 1f - dec h - jr nz, 1f - inc h - push hl - call __SCROLL_SCR - pop hl -#line 210 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -1: - ld l, 1 -__PRINT_EOL_END: - call SET_SCR_ADDR - exx - ret -__PRINT_COM: - exx + ld d, (hl) ; Block next ptr + ex de, hl ; DE = &(block->next); HL = block->next + ld a, h ; HL == NULL? + or l + jp z, __MEM_LINK_PREV; if so, link with previous + or a ; Clear carry flag + sbc hl, bc ; Carry if BC > HL => This block if before + add hl, bc ; Restores HL, preserving Carry flag + jp c, __MEM_LOOP2 ; This block is before. Keep searching PASS the block + ;------ At this point current HL is PAST BC, so we must link (DE) with BC, and HL in BC->next +__MEM_LINK_PREV: ; Link (DE) with BC, and BC->next with HL + ex de, hl push hl - push de - push bc - call PRINT_COMMA - pop bc - pop de + dec hl + ld (hl), c + inc hl + ld (hl), b ; (DE) <- BC + ld h, b ; HL <- BC (Free block ptr) + ld l, c + inc hl ; Skip block length (2 bytes) + inc hl + ld (hl), e ; Block->next = DE + inc hl + ld (hl), d + ; --- LINKED ; HL = &(BC->next) + 2 + call __MEM_JOIN_TEST pop hl - ret -__PRINT_TAB: - ld hl, __PRINT_TAB1 - jr __PRINT_SET_STATE -__PRINT_TAB1: - ld (MEM0), a - ld hl, __PRINT_TAB2 - jr __PRINT_SET_STATE -__PRINT_TAB2: - ld a, (MEM0) ; Load tab code (ignore the current one) - ld hl, __PRINT_START - ld (PRINT_JUMP_STATE), hl - exx - push hl - push bc - push de - call PRINT_TAB - pop de - pop bc +__MEM_JOIN_TEST: ; Checks for fragmented contiguous blocks and joins them + ; hl = Ptr to current block + 2 + ld d, (hl) + dec hl + ld e, (hl) + dec hl + ld b, (hl) ; Loads block length into BC + dec hl + ld c, (hl) ; + push hl ; Saves it for later + add hl, bc ; Adds its length. If HL == DE now, it must be joined + or a + sbc hl, de ; If Z, then HL == DE => We must join pop hl + ret nz +__MEM_BLOCK_JOIN: ; Joins current block (pointed by HL) with next one (pointed by DE). HL->length already in BC + push hl ; Saves it for later + ex de, hl + ld e, (hl) ; DE -> block->next->length + inc hl + ld d, (hl) + inc hl + ex de, hl ; DE = &(block->next) + add hl, bc ; HL = Total Length + ld b, h + ld c, l ; BC = Total Length + ex de, hl + ld e, (hl) + inc hl + ld d, (hl) ; DE = block->next + pop hl ; Recovers Pointer to block + ld (hl), c + inc hl + ld (hl), b ; Length Saved + inc hl + ld (hl), e + inc hl + ld (hl), d ; Next saved ret -__PRINT_AT: - ld hl, __PRINT_AT1 - jr __PRINT_SET_STATE -__PRINT_NOP: -__PRINT_RESTART: - ld hl, __PRINT_START -__PRINT_SET_STATE: - ld (PRINT_JUMP_STATE), hl ; Saves next entry call - exx - ret -__PRINT_AT1: ; Jumps here if waiting for 1st parameter - ld hl, (S_POSN) - ld h, a - ld a, SCR_ROWS - sub h - ld (S_POSN + 1), a - ld hl, __PRINT_AT2 - jr __PRINT_SET_STATE -__PRINT_AT2: - call __LOAD_S_POSN - ld e, a - call __SAVE_S_POSN - jr __PRINT_RESTART -__PRINT_DEL: - call __LOAD_S_POSN ; Gets current screen position - dec e - ld a, -1 - cp e - jr nz, 3f - ld e, SCR_COLS - 2 - dec d - cp d - jr nz, 3f - ld d, SCR_ROWS - 1 -3: - call __SAVE_S_POSN - exx - ret -__PRINT_INK: - ld hl, __PRINT_INK2 - jr __PRINT_SET_STATE -__PRINT_INK2: - call INK_TMP - jr __PRINT_RESTART -__PRINT_PAP: - ld hl, __PRINT_PAP2 - jr __PRINT_SET_STATE -__PRINT_PAP2: - call PAPER_TMP - jr __PRINT_RESTART -__PRINT_FLA: - ld hl, __PRINT_FLA2 - jr __PRINT_SET_STATE -__PRINT_FLA2: - call FLASH_TMP - jr __PRINT_RESTART -__PRINT_BRI: - ld hl, __PRINT_BRI2 - jr __PRINT_SET_STATE -__PRINT_BRI2: - call BRIGHT_TMP - jr __PRINT_RESTART -__PRINT_INV: - ld hl, __PRINT_INV2 - jr __PRINT_SET_STATE -__PRINT_INV2: - call INVERSE_TMP - jr __PRINT_RESTART -__PRINT_OVR: - ld hl, __PRINT_OVR2 - jr __PRINT_SET_STATE -__PRINT_OVR2: - call OVER_TMP - jr __PRINT_RESTART -__PRINT_BOLD: - ld hl, __PRINT_BOLD2 - jp __PRINT_SET_STATE -__PRINT_BOLD2: - call BOLD_TMP - jp __PRINT_RESTART -#line 354 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -__PRINT_ITA: - ld hl, __PRINT_ITA2 - jp __PRINT_SET_STATE -__PRINT_ITA2: - call ITALIC_TMP - jp __PRINT_RESTART -#line 364 "/zxbasic/src/arch/zx48k/library-asm/print.asm" - LOCAL __BOLD -__BOLD: - push hl - ld hl, MEM0 - ld b, 8 -1: - ld a, (de) - ld c, a - rlca - or c - ld (hl), a + ENDP + pop namespace +#line 54 "zx48k/stringparam.bas" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/loadstr.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/alloc.asm" +; vim: ts=4:et:sw=4: + ; Copyleft (K) by Jose M. Rodriguez de la Rosa + ; (a.k.a. Boriel) +; http://www.boriel.com + ; + ; This ASM library is licensed under the MIT license + ; you can use it for any purpose (even for commercial + ; closed source programs). + ; + ; Please read the MIT license on the internet + ; ----- IMPLEMENTATION NOTES ------ + ; The heap is implemented as a linked list of free blocks. +; Each free block contains this info: + ; + ; +----------------+ <-- HEAP START + ; | Size (2 bytes) | + ; | 0 | <-- Size = 0 => DUMMY HEADER BLOCK + ; +----------------+ + ; | Next (2 bytes) |---+ + ; +----------------+ <-+ + ; | Size (2 bytes) | + ; +----------------+ + ; | Next (2 bytes) |---+ + ; +----------------+ | + ; | | | <-- If Size > 4, then this contains (size - 4) bytes + ; | (0 if Size = 4)| | + ; +----------------+ <-+ + ; | Size (2 bytes) | + ; +----------------+ + ; | Next (2 bytes) |---+ + ; +----------------+ | + ; | | | + ; | (0 if Size = 4)| | + ; +----------------+ | + ; | <-- This zone is in use (Already allocated) + ; +----------------+ <-+ + ; | Size (2 bytes) | + ; +----------------+ + ; | Next (2 bytes) |---+ + ; +----------------+ | + ; | | | + ; | (0 if Size = 4)| | + ; +----------------+ <-+ + ; | Next (2 bytes) |--> NULL => END OF LIST + ; | 0 = NULL | + ; +----------------+ + ; | | + ; | (0 if Size = 4)| + ; +----------------+ + ; When a block is FREED, the previous and next pointers are examined to see + ; if we can defragment the heap. If the block to be freed is just next to the + ; previous, or to the next (or both) they will be converted into a single + ; block (so defragmented). + ; MEMORY MANAGER + ; + ; This library must be initialized calling __MEM_INIT with + ; HL = BLOCK Start & DE = Length. + ; An init directive is useful for initialization routines. + ; They will be added automatically if needed. + ; --------------------------------------------------------------------- + ; MEM_ALLOC + ; Allocates a block of memory in the heap. + ; + ; Parameters + ; BC = Length of requested memory block + ; +; Returns: + ; HL = Pointer to the allocated block in memory. Returns 0 (NULL) + ; if the block could not be allocated (out of memory) + ; --------------------------------------------------------------------- + push namespace core +MEM_ALLOC: +__MEM_ALLOC: ; Returns the 1st free block found of the given length (in BC) + PROC + LOCAL __MEM_LOOP + LOCAL __MEM_DONE + LOCAL __MEM_SUBTRACT + LOCAL __MEM_START + LOCAL TEMP, TEMP0 + TEMP EQU TEMP0 + 1 + ld hl, 0 + ld (TEMP), hl +__MEM_START: + ld hl, ZXBASIC_MEM_HEAP ; This label point to the heap start + inc bc + inc bc ; BC = BC + 2 ; block size needs 2 extra bytes for hidden pointer +__MEM_LOOP: ; Loads lengh at (HL, HL+). If Lenght >= BC, jump to __MEM_DONE + ld a, h ; HL = NULL (No memory available?) + or l +#line 113 "/zxbasic/src/arch/zx48k/library-asm/alloc.asm" + ret z ; NULL +#line 115 "/zxbasic/src/arch/zx48k/library-asm/alloc.asm" + ; HL = Pointer to Free block + ld e, (hl) inc hl - inc de - djnz 1b + ld d, (hl) + inc hl ; DE = Block Length + push hl ; HL = *pointer to -> next block + ex de, hl + or a ; CF = 0 + sbc hl, bc ; FREE >= BC (Length) (HL = BlockLength - Length) + jp nc, __MEM_DONE pop hl - ld de, MEM0 - ret -#line 385 "/zxbasic/src/arch/zx48k/library-asm/print.asm" - LOCAL __ITALIC -__ITALIC: - push hl - ld hl, MEM0 + ld (TEMP), hl ex de, hl - ld bc, 8 - ldir - ld hl, MEM0 - srl (hl) - inc hl - srl (hl) - inc hl - srl (hl) - inc hl - inc hl + ld e, (hl) inc hl - sla (hl) + ld d, (hl) + ex de, hl + jp __MEM_LOOP +__MEM_DONE: ; A free block has been found. + ; Check if at least 4 bytes remains free (HL >= 4) + push hl + exx ; exx to preserve bc + pop hl + ld bc, 4 + or a + sbc hl, bc + exx + jp nc, __MEM_SUBTRACT + ; At this point... + ; less than 4 bytes remains free. So we return this block entirely + ; We must link the previous block with the next to this one + ; (DE) => Pointer to next block + ; (TEMP) => &(previous->next) + pop hl ; Discard current block pointer + push de + ex de, hl ; DE = Previous block pointer; (HL) = Next block pointer + ld a, (hl) inc hl - sla (hl) + ld h, (hl) + ld l, a ; HL = (HL) + ex de, hl ; HL = Previous block pointer; DE = Next block pointer +TEMP0: + ld hl, 0 ; Pre-previous block pointer + ld (hl), e inc hl - sla (hl) - pop hl - ld de, MEM0 - ret -#line 413 "/zxbasic/src/arch/zx48k/library-asm/print.asm" - LOCAL __SCROLL_SCR -#line 487 "/zxbasic/src/arch/zx48k/library-asm/print.asm" - __SCROLL_SCR EQU 0DFEh ; Use ROM SCROLL -#line 489 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -#line 490 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -PRINT_COMMA: - call __LOAD_S_POSN - ld a, e - and 16 - add a, 16 -PRINT_TAB: - ; Tabulates the number of spaces in A register - ; If the current cursor position is already A, does nothing - PROC - LOCAL LOOP - call __LOAD_S_POSN ; e = current row - sub e - and 31 - ret z - ld b, a -LOOP: - ld a, ' ' - call __PRINTCHAR - djnz LOOP + ld (hl), d ; LINKED + pop hl ; Returning block. ret - ENDP -PRINT_AT: ; Changes cursor to ROW, COL - ; COL in A register - ; ROW in stack - pop hl ; Ret address - ex (sp), hl ; callee H = ROW - ld l, a +__MEM_SUBTRACT: + ; At this point we have to store HL value (Length - BC) into (DE - 2) ex de, hl - call __IN_SCREEN - ret nc ; Return if out of screen - jp __SAVE_S_POSN - LOCAL __PRINT_COM - LOCAL __PRINT_AT1 - LOCAL __PRINT_AT2 - LOCAL __PRINT_BOLD - LOCAL __PRINT_ITA - LOCAL __PRINT_INK - LOCAL __PRINT_PAP - LOCAL __PRINT_SET_STATE - LOCAL __PRINT_TABLE - LOCAL __PRINT_TAB, __PRINT_TAB1, __PRINT_TAB2 - LOCAL __PRINT_ITA2 -#line 546 "/zxbasic/src/arch/zx48k/library-asm/print.asm" - LOCAL __PRINT_BOLD2 -#line 552 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -__PRINT_TABLE: ; Jump table for 0 .. 22 codes - DW __PRINT_NOP ; 0 - DW __PRINT_NOP ; 1 - DW __PRINT_NOP ; 2 - DW __PRINT_NOP ; 3 - DW __PRINT_NOP ; 4 - DW __PRINT_NOP ; 5 - DW __PRINT_COM ; 6 COMMA - DW __PRINT_NOP ; 7 - DW __PRINT_DEL ; 8 DEL - DW __PRINT_NOP ; 9 - DW __PRINT_NOP ; 10 - DW __PRINT_NOP ; 11 - DW __PRINT_NOP ; 12 - DW __PRINT_0Dh ; 13 - DW __PRINT_BOLD ; 14 - DW __PRINT_ITA ; 15 - DW __PRINT_INK ; 16 - DW __PRINT_PAP ; 17 - DW __PRINT_FLA ; 18 - DW __PRINT_BRI ; 19 - DW __PRINT_INV ; 20 - DW __PRINT_OVR ; 21 - DW __PRINT_AT ; 22 AT - DW __PRINT_TAB ; 23 TAB + dec hl + ld (hl), d + dec hl + ld (hl), e ; Store new block length + add hl, de ; New length + DE => free-block start + pop de ; Remove previous HL off the stack + ld (hl), c ; Store length on its 1st word + inc hl + ld (hl), b + inc hl ; Return hl + ret ENDP pop namespace -#line 5 "/zxbasic/src/arch/zx48k/library-asm/print_eol_attr.asm" +#line 2 "/zxbasic/src/arch/zx48k/library-asm/loadstr.asm" + ; Loads a string (ptr) from HL + ; and duplicates it on dynamic memory again + ; Finally, it returns result pointer in HL push namespace core -PRINT_EOL_ATTR: - call PRINT_EOL - jp COPY_ATTR +__ILOADSTR: ; This is the indirect pointer entry HL = (HL) + ld a, h + or l + ret z + ld a, (hl) + inc hl + ld h, (hl) + ld l, a +__LOADSTR: ; __FASTCALL__ entry + ld a, h + or l + ret z ; Return if NULL + ld c, (hl) + inc hl + ld b, (hl) + dec hl ; BC = LEN(a$) + inc bc + inc bc ; BC = LEN(a$) + 2 (two bytes for length) + push hl + push bc + call __MEM_ALLOC + pop bc ; Recover length + pop de ; Recover origin + ld a, h + or l + ret z ; Return if NULL (No memory) + ex de, hl ; ldir takes HL as source, DE as destiny, so SWAP HL,DE + push de ; Saves destiny start + ldir ; Copies string (length number included) + pop hl ; Recovers destiny in hl as result + ret pop namespace -#line 54 "zx48k/stringparam.bas" +#line 55 "zx48k/stringparam.bas" #line 1 "/zxbasic/src/arch/zx48k/library-asm/printstr.asm" ; PRINT command routine ; Prints string pointed by HL @@ -1504,5 +1495,5 @@ __PRINT_STR: jp __PRINT_STR_LOOP ENDP pop namespace -#line 55 "zx48k/stringparam.bas" +#line 57 "zx48k/stringparam.bas" END diff --git a/tests/functional/zx48k/strlocal0.asm b/tests/functional/zx48k/strlocal0.asm index 493a5210f..fad3490ea 100644 --- a/tests/functional/zx48k/strlocal0.asm +++ b/tests/functional/zx48k/strlocal0.asm @@ -50,11 +50,12 @@ _test: ld de, .LABEL.__LABEL0 ld bc, -2 call .core.__PSTORE_STR + call .core.COPY_ATTR ld l, (ix-2) ld h, (ix-1) xor a call .core.__PRINTSTR - call .core.PRINT_EOL_ATTR + call .core.PRINT_EOL _test__leave: ex af, af' exx @@ -80,276 +81,7 @@ _test__leave: DEFB 6Ch DEFB 64h ;; --- end of user code --- -#line 1 "/zxbasic/src/arch/zx48k/library-asm/free.asm" -; vim: ts=4:et:sw=4: - ; Copyleft (K) by Jose M. Rodriguez de la Rosa - ; (a.k.a. Boriel) -; http://www.boriel.com - ; - ; This ASM library is licensed under the BSD license - ; you can use it for any purpose (even for commercial - ; closed source programs). - ; - ; Please read the BSD license on the internet - ; ----- IMPLEMENTATION NOTES ------ - ; The heap is implemented as a linked list of free blocks. -; Each free block contains this info: - ; - ; +----------------+ <-- HEAP START - ; | Size (2 bytes) | - ; | 0 | <-- Size = 0 => DUMMY HEADER BLOCK - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ <-+ - ; | Size (2 bytes) | - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ | - ; | | | <-- If Size > 4, then this contains (size - 4) bytes - ; | (0 if Size = 4)| | - ; +----------------+ <-+ - ; | Size (2 bytes) | - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ | - ; | | | - ; | (0 if Size = 4)| | - ; +----------------+ | - ; | <-- This zone is in use (Already allocated) - ; +----------------+ <-+ - ; | Size (2 bytes) | - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ | - ; | | | - ; | (0 if Size = 4)| | - ; +----------------+ <-+ - ; | Next (2 bytes) |--> NULL => END OF LIST - ; | 0 = NULL | - ; +----------------+ - ; | | - ; | (0 if Size = 4)| - ; +----------------+ - ; When a block is FREED, the previous and next pointers are examined to see - ; if we can defragment the heap. If the block to be breed is just next to the - ; previous, or to the next (or both) they will be converted into a single - ; block (so defragmented). - ; MEMORY MANAGER - ; - ; This library must be initialized calling __MEM_INIT with - ; HL = BLOCK Start & DE = Length. - ; An init directive is useful for initialization routines. - ; They will be added automatically if needed. -#line 1 "/zxbasic/src/arch/zx48k/library-asm/heapinit.asm" -; vim: ts=4:et:sw=4: - ; Copyleft (K) by Jose M. Rodriguez de la Rosa - ; (a.k.a. Boriel) -; http://www.boriel.com - ; - ; This ASM library is licensed under the BSD license - ; you can use it for any purpose (even for commercial - ; closed source programs). - ; - ; Please read the BSD license on the internet - ; ----- IMPLEMENTATION NOTES ------ - ; The heap is implemented as a linked list of free blocks. -; Each free block contains this info: - ; - ; +----------------+ <-- HEAP START - ; | Size (2 bytes) | - ; | 0 | <-- Size = 0 => DUMMY HEADER BLOCK - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ <-+ - ; | Size (2 bytes) | - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ | - ; | | | <-- If Size > 4, then this contains (size - 4) bytes - ; | (0 if Size = 4)| | - ; +----------------+ <-+ - ; | Size (2 bytes) | - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ | - ; | | | - ; | (0 if Size = 4)| | - ; +----------------+ | - ; | <-- This zone is in use (Already allocated) - ; +----------------+ <-+ - ; | Size (2 bytes) | - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ | - ; | | | - ; | (0 if Size = 4)| | - ; +----------------+ <-+ - ; | Next (2 bytes) |--> NULL => END OF LIST - ; | 0 = NULL | - ; +----------------+ - ; | | - ; | (0 if Size = 4)| - ; +----------------+ - ; When a block is FREED, the previous and next pointers are examined to see - ; if we can defragment the heap. If the block to be breed is just next to the - ; previous, or to the next (or both) they will be converted into a single - ; block (so defragmented). - ; MEMORY MANAGER - ; - ; This library must be initialized calling __MEM_INIT with - ; HL = BLOCK Start & DE = Length. - ; An init directive is useful for initialization routines. - ; They will be added automatically if needed. - ; --------------------------------------------------------------------- - ; __MEM_INIT must be called to initalize this library with the - ; standard parameters - ; --------------------------------------------------------------------- - push namespace core -__MEM_INIT: ; Initializes the library using (RAMTOP) as start, and - ld hl, ZXBASIC_MEM_HEAP ; Change this with other address of heap start - ld de, ZXBASIC_HEAP_SIZE ; Change this with your size - ; --------------------------------------------------------------------- - ; __MEM_INIT2 initalizes this library -; Parameters: -; HL : Memory address of 1st byte of the memory heap -; DE : Length in bytes of the Memory Heap - ; --------------------------------------------------------------------- -__MEM_INIT2: - ; HL as TOP - PROC - dec de - dec de - dec de - dec de ; DE = length - 4; HL = start - ; This is done, because we require 4 bytes for the empty dummy-header block - xor a - ld (hl), a - inc hl - ld (hl), a ; First "free" block is a header: size=0, Pointer=&(Block) + 4 - inc hl - ld b, h - ld c, l - inc bc - inc bc ; BC = starts of next block - ld (hl), c - inc hl - ld (hl), b - inc hl ; Pointer to next block - ld (hl), e - inc hl - ld (hl), d - inc hl ; Block size (should be length - 4 at start); This block contains all the available memory - ld (hl), a ; NULL (0000h) ; No more blocks (a list with a single block) - inc hl - ld (hl), a - ld a, 201 - ld (__MEM_INIT), a; "Pokes" with a RET so ensure this routine is not called again - ret - ENDP - pop namespace -#line 69 "/zxbasic/src/arch/zx48k/library-asm/free.asm" - ; --------------------------------------------------------------------- - ; MEM_FREE - ; Frees a block of memory - ; -; Parameters: - ; HL = Pointer to the block to be freed. If HL is NULL (0) nothing - ; is done - ; --------------------------------------------------------------------- - push namespace core -MEM_FREE: -__MEM_FREE: ; Frees the block pointed by HL - ; HL DE BC & AF modified - PROC - LOCAL __MEM_LOOP2 - LOCAL __MEM_LINK_PREV - LOCAL __MEM_JOIN_TEST - LOCAL __MEM_BLOCK_JOIN - ld a, h - or l - ret z ; Return if NULL pointer - dec hl - dec hl - ld b, h - ld c, l ; BC = Block pointer - ld hl, ZXBASIC_MEM_HEAP ; This label point to the heap start -__MEM_LOOP2: - inc hl - inc hl ; Next block ptr - ld e, (hl) - inc hl - ld d, (hl) ; Block next ptr - ex de, hl ; DE = &(block->next); HL = block->next - ld a, h ; HL == NULL? - or l - jp z, __MEM_LINK_PREV; if so, link with previous - or a ; Clear carry flag - sbc hl, bc ; Carry if BC > HL => This block if before - add hl, bc ; Restores HL, preserving Carry flag - jp c, __MEM_LOOP2 ; This block is before. Keep searching PASS the block - ;------ At this point current HL is PAST BC, so we must link (DE) with BC, and HL in BC->next -__MEM_LINK_PREV: ; Link (DE) with BC, and BC->next with HL - ex de, hl - push hl - dec hl - ld (hl), c - inc hl - ld (hl), b ; (DE) <- BC - ld h, b ; HL <- BC (Free block ptr) - ld l, c - inc hl ; Skip block length (2 bytes) - inc hl - ld (hl), e ; Block->next = DE - inc hl - ld (hl), d - ; --- LINKED ; HL = &(BC->next) + 2 - call __MEM_JOIN_TEST - pop hl -__MEM_JOIN_TEST: ; Checks for fragmented contiguous blocks and joins them - ; hl = Ptr to current block + 2 - ld d, (hl) - dec hl - ld e, (hl) - dec hl - ld b, (hl) ; Loads block length into BC - dec hl - ld c, (hl) ; - push hl ; Saves it for later - add hl, bc ; Adds its length. If HL == DE now, it must be joined - or a - sbc hl, de ; If Z, then HL == DE => We must join - pop hl - ret nz -__MEM_BLOCK_JOIN: ; Joins current block (pointed by HL) with next one (pointed by DE). HL->length already in BC - push hl ; Saves it for later - ex de, hl - ld e, (hl) ; DE -> block->next->length - inc hl - ld d, (hl) - inc hl - ex de, hl ; DE = &(block->next) - add hl, bc ; HL = Total Length - ld b, h - ld c, l ; BC = Total Length - ex de, hl - ld e, (hl) - inc hl - ld d, (hl) ; DE = block->next - pop hl ; Recovers Pointer to block - ld (hl), c - inc hl - ld (hl), b ; Length Saved - inc hl - ld (hl), e - inc hl - ld (hl), d ; Next saved - ret - ENDP - pop namespace -#line 56 "zx48k/strlocal0.bas" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/print_eol_attr.asm" - ; Calls PRINT_EOL and then COPY_ATTR, so saves - ; 3 bytes +#line 1 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" #line 1 "/zxbasic/src/arch/zx48k/library-asm/print.asm" ; vim:ts=4:sw=4:et: ; PRINT command routine @@ -697,62 +429,8 @@ BRIGHT_TMP: pop namespace #line 12 "/zxbasic/src/arch/zx48k/library-asm/print.asm" #line 1 "/zxbasic/src/arch/zx48k/library-asm/over.asm" - ; Sets OVER flag in P_FLAG permanently -; Parameter: OVER flag in bit 0 of A register -#line 1 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" -#line 4 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" - push namespace core -COPY_ATTR: - ; Just copies current permanent attribs into temporal attribs - ; and sets print mode - PROC - LOCAL INVERSE1 - LOCAL __REFRESH_TMP - INVERSE1 EQU 02Fh - ld hl, (ATTR_P) - ld (ATTR_T), hl - ld hl, FLAGS2 - call __REFRESH_TMP - ld hl, P_FLAG - call __REFRESH_TMP -__SET_ATTR_MODE: ; Another entry to set print modes. A contains (P_FLAG) - LOCAL TABLE - LOCAL CONT2 - rra ; Over bit to carry - ld a, (FLAGS2) - rla ; Over bit in bit 1, Over2 bit in bit 2 - and 3 ; Only bit 0 and 1 (OVER flag) - ld c, a - ld b, 0 - ld hl, TABLE - add hl, bc - ld a, (hl) - ld (PRINT_MODE), a - ld hl, (P_FLAG) - xor a ; NOP -> INVERSE0 - bit 2, l - jr z, CONT2 - ld a, INVERSE1 ; CPL -> INVERSE1 -CONT2: - ld (INVERSE_MODE), a - ret -TABLE: - nop ; NORMAL MODE - xor (hl) ; OVER 1 MODE - and (hl) ; OVER 2 MODE - or (hl) ; OVER 3 MODE -#line 67 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" -__REFRESH_TMP: - ld a, (hl) - and 0b10101010 - ld c, a - rra - or c - ld (hl), a - ret - ENDP - pop namespace -#line 4 "/zxbasic/src/arch/zx48k/library-asm/over.asm" + ; Sets OVER flag in P_FLAG permanently +; Parameter: OVER flag in bit 0 of A register push namespace core OVER: PROC @@ -994,11 +672,10 @@ INVERSE_MODE: ; 00 -> NOP -> INVERSE 0 inc hl ld (DFCC), hl ld hl, (DFCCL) ; current ATTR Pos - push hl - call __SET_ATTR - pop hl inc hl - ld (DFCCL),hl + ld (DFCCL), hl + dec hl + call __SET_ATTR exx ret ; ------------- SPECIAL CHARS (< 32) ----------------- @@ -1017,7 +694,7 @@ __PRINT_0Dh: ; Called WHEN printing CHR$(13) push hl call __SCROLL_SCR pop hl -#line 210 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 209 "/zxbasic/src/arch/zx48k/library-asm/print.asm" 1: ld l, 1 __PRINT_EOL_END: @@ -1134,14 +811,14 @@ __PRINT_BOLD: __PRINT_BOLD2: call BOLD_TMP jp __PRINT_RESTART -#line 354 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 353 "/zxbasic/src/arch/zx48k/library-asm/print.asm" __PRINT_ITA: ld hl, __PRINT_ITA2 jp __PRINT_SET_STATE __PRINT_ITA2: call ITALIC_TMP jp __PRINT_RESTART -#line 364 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 363 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __BOLD __BOLD: push hl @@ -1154,121 +831,435 @@ __BOLD: or c ld (hl), a inc hl - inc de - djnz 1b - pop hl - ld de, MEM0 + inc de + djnz 1b + pop hl + ld de, MEM0 + ret +#line 384 "/zxbasic/src/arch/zx48k/library-asm/print.asm" + LOCAL __ITALIC +__ITALIC: + push hl + ld hl, MEM0 + ex de, hl + ld bc, 8 + ldir + ld hl, MEM0 + srl (hl) + inc hl + srl (hl) + inc hl + srl (hl) + inc hl + inc hl + inc hl + sla (hl) + inc hl + sla (hl) + inc hl + sla (hl) + pop hl + ld de, MEM0 + ret +#line 412 "/zxbasic/src/arch/zx48k/library-asm/print.asm" + LOCAL __SCROLL_SCR +#line 486 "/zxbasic/src/arch/zx48k/library-asm/print.asm" + __SCROLL_SCR EQU 0DFEh ; Use ROM SCROLL +#line 488 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 489 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +PRINT_COMMA: + call __LOAD_S_POSN + ld a, e + and 16 + add a, 16 +PRINT_TAB: + ; Tabulates the number of spaces in A register + ; If the current cursor position is already A, does nothing + PROC + LOCAL LOOP + call __LOAD_S_POSN ; e = current row + sub e + and 31 + ret z + ld b, a +LOOP: + ld a, ' ' + call __PRINTCHAR + djnz LOOP + ret + ENDP +PRINT_AT: ; Changes cursor to ROW, COL + ; COL in A register + ; ROW in stack + pop hl ; Ret address + ex (sp), hl ; callee H = ROW + ld l, a + ex de, hl + call __IN_SCREEN + ret nc ; Return if out of screen + jp __SAVE_S_POSN + LOCAL __PRINT_COM + LOCAL __PRINT_AT1 + LOCAL __PRINT_AT2 + LOCAL __PRINT_BOLD + LOCAL __PRINT_ITA + LOCAL __PRINT_INK + LOCAL __PRINT_PAP + LOCAL __PRINT_SET_STATE + LOCAL __PRINT_TABLE + LOCAL __PRINT_TAB, __PRINT_TAB1, __PRINT_TAB2 + LOCAL __PRINT_ITA2 +#line 545 "/zxbasic/src/arch/zx48k/library-asm/print.asm" + LOCAL __PRINT_BOLD2 +#line 551 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +__PRINT_TABLE: ; Jump table for 0 .. 22 codes + DW __PRINT_NOP ; 0 + DW __PRINT_NOP ; 1 + DW __PRINT_NOP ; 2 + DW __PRINT_NOP ; 3 + DW __PRINT_NOP ; 4 + DW __PRINT_NOP ; 5 + DW __PRINT_COM ; 6 COMMA + DW __PRINT_NOP ; 7 + DW __PRINT_DEL ; 8 DEL + DW __PRINT_NOP ; 9 + DW __PRINT_NOP ; 10 + DW __PRINT_NOP ; 11 + DW __PRINT_NOP ; 12 + DW __PRINT_0Dh ; 13 + DW __PRINT_BOLD ; 14 + DW __PRINT_ITA ; 15 + DW __PRINT_INK ; 16 + DW __PRINT_PAP ; 17 + DW __PRINT_FLA ; 18 + DW __PRINT_BRI ; 19 + DW __PRINT_INV ; 20 + DW __PRINT_OVR ; 21 + DW __PRINT_AT ; 22 AT + DW __PRINT_TAB ; 23 TAB + ENDP + pop namespace +#line 3 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" +#line 4 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" + push namespace core +COPY_ATTR: + ; Just copies current permanent attribs into temporal attribs + ; and sets print mode + PROC + LOCAL INVERSE1 + LOCAL __REFRESH_TMP + INVERSE1 EQU 02Fh + ld hl, (ATTR_P) + ld (ATTR_T), hl + ld hl, FLAGS2 + call __REFRESH_TMP + ld hl, P_FLAG + call __REFRESH_TMP +__SET_ATTR_MODE: ; Another entry to set print modes. A contains (P_FLAG) + LOCAL TABLE + LOCAL CONT2 + rra ; Over bit to carry + ld a, (FLAGS2) + rla ; Over bit in bit 1, Over2 bit in bit 2 + and 3 ; Only bit 0 and 1 (OVER flag) + ld c, a + ld b, 0 + ld hl, TABLE + add hl, bc + ld a, (hl) + ld (PRINT_MODE), a + ld hl, (P_FLAG) + xor a ; NOP -> INVERSE0 + bit 2, l + jr z, CONT2 + ld a, INVERSE1 ; CPL -> INVERSE1 +CONT2: + ld (INVERSE_MODE), a + ret +TABLE: + nop ; NORMAL MODE + xor (hl) ; OVER 1 MODE + and (hl) ; OVER 2 MODE + or (hl) ; OVER 3 MODE +#line 67 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" +__REFRESH_TMP: + ld a, (hl) + and 0b10101010 + ld c, a + rra + or c + ld (hl), a + ret + ENDP + pop namespace +#line 57 "zx48k/strlocal0.bas" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/free.asm" +; vim: ts=4:et:sw=4: + ; Copyleft (K) by Jose M. Rodriguez de la Rosa + ; (a.k.a. Boriel) +; http://www.boriel.com + ; + ; This ASM library is licensed under the BSD license + ; you can use it for any purpose (even for commercial + ; closed source programs). + ; + ; Please read the BSD license on the internet + ; ----- IMPLEMENTATION NOTES ------ + ; The heap is implemented as a linked list of free blocks. +; Each free block contains this info: + ; + ; +----------------+ <-- HEAP START + ; | Size (2 bytes) | + ; | 0 | <-- Size = 0 => DUMMY HEADER BLOCK + ; +----------------+ + ; | Next (2 bytes) |---+ + ; +----------------+ <-+ + ; | Size (2 bytes) | + ; +----------------+ + ; | Next (2 bytes) |---+ + ; +----------------+ | + ; | | | <-- If Size > 4, then this contains (size - 4) bytes + ; | (0 if Size = 4)| | + ; +----------------+ <-+ + ; | Size (2 bytes) | + ; +----------------+ + ; | Next (2 bytes) |---+ + ; +----------------+ | + ; | | | + ; | (0 if Size = 4)| | + ; +----------------+ | + ; | <-- This zone is in use (Already allocated) + ; +----------------+ <-+ + ; | Size (2 bytes) | + ; +----------------+ + ; | Next (2 bytes) |---+ + ; +----------------+ | + ; | | | + ; | (0 if Size = 4)| | + ; +----------------+ <-+ + ; | Next (2 bytes) |--> NULL => END OF LIST + ; | 0 = NULL | + ; +----------------+ + ; | | + ; | (0 if Size = 4)| + ; +----------------+ + ; When a block is FREED, the previous and next pointers are examined to see + ; if we can defragment the heap. If the block to be breed is just next to the + ; previous, or to the next (or both) they will be converted into a single + ; block (so defragmented). + ; MEMORY MANAGER + ; + ; This library must be initialized calling __MEM_INIT with + ; HL = BLOCK Start & DE = Length. + ; An init directive is useful for initialization routines. + ; They will be added automatically if needed. +#line 1 "/zxbasic/src/arch/zx48k/library-asm/heapinit.asm" +; vim: ts=4:et:sw=4: + ; Copyleft (K) by Jose M. Rodriguez de la Rosa + ; (a.k.a. Boriel) +; http://www.boriel.com + ; + ; This ASM library is licensed under the BSD license + ; you can use it for any purpose (even for commercial + ; closed source programs). + ; + ; Please read the BSD license on the internet + ; ----- IMPLEMENTATION NOTES ------ + ; The heap is implemented as a linked list of free blocks. +; Each free block contains this info: + ; + ; +----------------+ <-- HEAP START + ; | Size (2 bytes) | + ; | 0 | <-- Size = 0 => DUMMY HEADER BLOCK + ; +----------------+ + ; | Next (2 bytes) |---+ + ; +----------------+ <-+ + ; | Size (2 bytes) | + ; +----------------+ + ; | Next (2 bytes) |---+ + ; +----------------+ | + ; | | | <-- If Size > 4, then this contains (size - 4) bytes + ; | (0 if Size = 4)| | + ; +----------------+ <-+ + ; | Size (2 bytes) | + ; +----------------+ + ; | Next (2 bytes) |---+ + ; +----------------+ | + ; | | | + ; | (0 if Size = 4)| | + ; +----------------+ | + ; | <-- This zone is in use (Already allocated) + ; +----------------+ <-+ + ; | Size (2 bytes) | + ; +----------------+ + ; | Next (2 bytes) |---+ + ; +----------------+ | + ; | | | + ; | (0 if Size = 4)| | + ; +----------------+ <-+ + ; | Next (2 bytes) |--> NULL => END OF LIST + ; | 0 = NULL | + ; +----------------+ + ; | | + ; | (0 if Size = 4)| + ; +----------------+ + ; When a block is FREED, the previous and next pointers are examined to see + ; if we can defragment the heap. If the block to be breed is just next to the + ; previous, or to the next (or both) they will be converted into a single + ; block (so defragmented). + ; MEMORY MANAGER + ; + ; This library must be initialized calling __MEM_INIT with + ; HL = BLOCK Start & DE = Length. + ; An init directive is useful for initialization routines. + ; They will be added automatically if needed. + ; --------------------------------------------------------------------- + ; __MEM_INIT must be called to initalize this library with the + ; standard parameters + ; --------------------------------------------------------------------- + push namespace core +__MEM_INIT: ; Initializes the library using (RAMTOP) as start, and + ld hl, ZXBASIC_MEM_HEAP ; Change this with other address of heap start + ld de, ZXBASIC_HEAP_SIZE ; Change this with your size + ; --------------------------------------------------------------------- + ; __MEM_INIT2 initalizes this library +; Parameters: +; HL : Memory address of 1st byte of the memory heap +; DE : Length in bytes of the Memory Heap + ; --------------------------------------------------------------------- +__MEM_INIT2: + ; HL as TOP + PROC + dec de + dec de + dec de + dec de ; DE = length - 4; HL = start + ; This is done, because we require 4 bytes for the empty dummy-header block + xor a + ld (hl), a + inc hl + ld (hl), a ; First "free" block is a header: size=0, Pointer=&(Block) + 4 + inc hl + ld b, h + ld c, l + inc bc + inc bc ; BC = starts of next block + ld (hl), c + inc hl + ld (hl), b + inc hl ; Pointer to next block + ld (hl), e + inc hl + ld (hl), d + inc hl ; Block size (should be length - 4 at start); This block contains all the available memory + ld (hl), a ; NULL (0000h) ; No more blocks (a list with a single block) + inc hl + ld (hl), a + ld a, 201 + ld (__MEM_INIT), a; "Pokes" with a RET so ensure this routine is not called again ret -#line 385 "/zxbasic/src/arch/zx48k/library-asm/print.asm" - LOCAL __ITALIC -__ITALIC: - push hl - ld hl, MEM0 + ENDP + pop namespace +#line 69 "/zxbasic/src/arch/zx48k/library-asm/free.asm" + ; --------------------------------------------------------------------- + ; MEM_FREE + ; Frees a block of memory + ; +; Parameters: + ; HL = Pointer to the block to be freed. If HL is NULL (0) nothing + ; is done + ; --------------------------------------------------------------------- + push namespace core +MEM_FREE: +__MEM_FREE: ; Frees the block pointed by HL + ; HL DE BC & AF modified + PROC + LOCAL __MEM_LOOP2 + LOCAL __MEM_LINK_PREV + LOCAL __MEM_JOIN_TEST + LOCAL __MEM_BLOCK_JOIN + ld a, h + or l + ret z ; Return if NULL pointer + dec hl + dec hl + ld b, h + ld c, l ; BC = Block pointer + ld hl, ZXBASIC_MEM_HEAP ; This label point to the heap start +__MEM_LOOP2: + inc hl + inc hl ; Next block ptr + ld e, (hl) + inc hl + ld d, (hl) ; Block next ptr + ex de, hl ; DE = &(block->next); HL = block->next + ld a, h ; HL == NULL? + or l + jp z, __MEM_LINK_PREV; if so, link with previous + or a ; Clear carry flag + sbc hl, bc ; Carry if BC > HL => This block if before + add hl, bc ; Restores HL, preserving Carry flag + jp c, __MEM_LOOP2 ; This block is before. Keep searching PASS the block + ;------ At this point current HL is PAST BC, so we must link (DE) with BC, and HL in BC->next +__MEM_LINK_PREV: ; Link (DE) with BC, and BC->next with HL ex de, hl - ld bc, 8 - ldir - ld hl, MEM0 - srl (hl) + push hl + dec hl + ld (hl), c inc hl - srl (hl) + ld (hl), b ; (DE) <- BC + ld h, b ; HL <- BC (Free block ptr) + ld l, c + inc hl ; Skip block length (2 bytes) inc hl - srl (hl) + ld (hl), e ; Block->next = DE inc hl + ld (hl), d + ; --- LINKED ; HL = &(BC->next) + 2 + call __MEM_JOIN_TEST + pop hl +__MEM_JOIN_TEST: ; Checks for fragmented contiguous blocks and joins them + ; hl = Ptr to current block + 2 + ld d, (hl) + dec hl + ld e, (hl) + dec hl + ld b, (hl) ; Loads block length into BC + dec hl + ld c, (hl) ; + push hl ; Saves it for later + add hl, bc ; Adds its length. If HL == DE now, it must be joined + or a + sbc hl, de ; If Z, then HL == DE => We must join + pop hl + ret nz +__MEM_BLOCK_JOIN: ; Joins current block (pointed by HL) with next one (pointed by DE). HL->length already in BC + push hl ; Saves it for later + ex de, hl + ld e, (hl) ; DE -> block->next->length inc hl + ld d, (hl) inc hl - sla (hl) + ex de, hl ; DE = &(block->next) + add hl, bc ; HL = Total Length + ld b, h + ld c, l ; BC = Total Length + ex de, hl + ld e, (hl) inc hl - sla (hl) + ld d, (hl) ; DE = block->next + pop hl ; Recovers Pointer to block + ld (hl), c inc hl - sla (hl) - pop hl - ld de, MEM0 - ret -#line 413 "/zxbasic/src/arch/zx48k/library-asm/print.asm" - LOCAL __SCROLL_SCR -#line 487 "/zxbasic/src/arch/zx48k/library-asm/print.asm" - __SCROLL_SCR EQU 0DFEh ; Use ROM SCROLL -#line 489 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -#line 490 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -PRINT_COMMA: - call __LOAD_S_POSN - ld a, e - and 16 - add a, 16 -PRINT_TAB: - ; Tabulates the number of spaces in A register - ; If the current cursor position is already A, does nothing - PROC - LOCAL LOOP - call __LOAD_S_POSN ; e = current row - sub e - and 31 - ret z - ld b, a -LOOP: - ld a, ' ' - call __PRINTCHAR - djnz LOOP + ld (hl), b ; Length Saved + inc hl + ld (hl), e + inc hl + ld (hl), d ; Next saved ret ENDP -PRINT_AT: ; Changes cursor to ROW, COL - ; COL in A register - ; ROW in stack - pop hl ; Ret address - ex (sp), hl ; callee H = ROW - ld l, a - ex de, hl - call __IN_SCREEN - ret nc ; Return if out of screen - jp __SAVE_S_POSN - LOCAL __PRINT_COM - LOCAL __PRINT_AT1 - LOCAL __PRINT_AT2 - LOCAL __PRINT_BOLD - LOCAL __PRINT_ITA - LOCAL __PRINT_INK - LOCAL __PRINT_PAP - LOCAL __PRINT_SET_STATE - LOCAL __PRINT_TABLE - LOCAL __PRINT_TAB, __PRINT_TAB1, __PRINT_TAB2 - LOCAL __PRINT_ITA2 -#line 546 "/zxbasic/src/arch/zx48k/library-asm/print.asm" - LOCAL __PRINT_BOLD2 -#line 552 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -__PRINT_TABLE: ; Jump table for 0 .. 22 codes - DW __PRINT_NOP ; 0 - DW __PRINT_NOP ; 1 - DW __PRINT_NOP ; 2 - DW __PRINT_NOP ; 3 - DW __PRINT_NOP ; 4 - DW __PRINT_NOP ; 5 - DW __PRINT_COM ; 6 COMMA - DW __PRINT_NOP ; 7 - DW __PRINT_DEL ; 8 DEL - DW __PRINT_NOP ; 9 - DW __PRINT_NOP ; 10 - DW __PRINT_NOP ; 11 - DW __PRINT_NOP ; 12 - DW __PRINT_0Dh ; 13 - DW __PRINT_BOLD ; 14 - DW __PRINT_ITA ; 15 - DW __PRINT_INK ; 16 - DW __PRINT_PAP ; 17 - DW __PRINT_FLA ; 18 - DW __PRINT_BRI ; 19 - DW __PRINT_INV ; 20 - DW __PRINT_OVR ; 21 - DW __PRINT_AT ; 22 AT - DW __PRINT_TAB ; 23 TAB - ENDP - pop namespace -#line 5 "/zxbasic/src/arch/zx48k/library-asm/print_eol_attr.asm" - push namespace core -PRINT_EOL_ATTR: - call PRINT_EOL - jp COPY_ATTR pop namespace -#line 57 "zx48k/strlocal0.bas" +#line 58 "zx48k/strlocal0.bas" #line 1 "/zxbasic/src/arch/zx48k/library-asm/printstr.asm" ; PRINT command routine ; Prints string pointed by HL @@ -1312,7 +1303,7 @@ __PRINT_STR: jp __PRINT_STR_LOOP ENDP pop namespace -#line 58 "zx48k/strlocal0.bas" +#line 60 "zx48k/strlocal0.bas" #line 1 "/zxbasic/src/arch/zx48k/library-asm/pstorestr.asm" ; vim:ts=4:et:sw=4 ; @@ -1733,5 +1724,5 @@ __PSTORE_STR: add hl, bc jp __STORE_STR pop namespace -#line 59 "zx48k/strlocal0.bas" +#line 61 "zx48k/strlocal0.bas" END diff --git a/tests/functional/zx48k/strparam0.asm b/tests/functional/zx48k/strparam0.asm index 5ebf40593..54faa56f2 100644 --- a/tests/functional/zx48k/strparam0.asm +++ b/tests/functional/zx48k/strparam0.asm @@ -48,11 +48,12 @@ _test2: push ix ld ix, 0 add ix, sp + call .core.COPY_ATTR ld l, (ix+4) ld h, (ix+5) xor a call .core.__PRINTSTR - call .core.PRINT_EOL_ATTR + call .core.PRINT_EOL _test2__leave: ex af, af' exx @@ -106,334 +107,42 @@ _test1__leave: DEFB 6Ch DEFB 64h ;; --- end of user code --- -#line 1 "/zxbasic/src/arch/zx48k/library-asm/free.asm" -; vim: ts=4:et:sw=4: - ; Copyleft (K) by Jose M. Rodriguez de la Rosa - ; (a.k.a. Boriel) -; http://www.boriel.com - ; - ; This ASM library is licensed under the BSD license - ; you can use it for any purpose (even for commercial - ; closed source programs). - ; - ; Please read the BSD license on the internet - ; ----- IMPLEMENTATION NOTES ------ - ; The heap is implemented as a linked list of free blocks. -; Each free block contains this info: - ; - ; +----------------+ <-- HEAP START - ; | Size (2 bytes) | - ; | 0 | <-- Size = 0 => DUMMY HEADER BLOCK - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ <-+ - ; | Size (2 bytes) | - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ | - ; | | | <-- If Size > 4, then this contains (size - 4) bytes - ; | (0 if Size = 4)| | - ; +----------------+ <-+ - ; | Size (2 bytes) | - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ | - ; | | | - ; | (0 if Size = 4)| | - ; +----------------+ | - ; | <-- This zone is in use (Already allocated) - ; +----------------+ <-+ - ; | Size (2 bytes) | - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ | - ; | | | - ; | (0 if Size = 4)| | - ; +----------------+ <-+ - ; | Next (2 bytes) |--> NULL => END OF LIST - ; | 0 = NULL | - ; +----------------+ - ; | | - ; | (0 if Size = 4)| - ; +----------------+ - ; When a block is FREED, the previous and next pointers are examined to see - ; if we can defragment the heap. If the block to be breed is just next to the - ; previous, or to the next (or both) they will be converted into a single - ; block (so defragmented). - ; MEMORY MANAGER - ; - ; This library must be initialized calling __MEM_INIT with - ; HL = BLOCK Start & DE = Length. - ; An init directive is useful for initialization routines. - ; They will be added automatically if needed. -#line 1 "/zxbasic/src/arch/zx48k/library-asm/heapinit.asm" -; vim: ts=4:et:sw=4: - ; Copyleft (K) by Jose M. Rodriguez de la Rosa - ; (a.k.a. Boriel) -; http://www.boriel.com - ; - ; This ASM library is licensed under the BSD license - ; you can use it for any purpose (even for commercial - ; closed source programs). - ; - ; Please read the BSD license on the internet - ; ----- IMPLEMENTATION NOTES ------ - ; The heap is implemented as a linked list of free blocks. -; Each free block contains this info: - ; - ; +----------------+ <-- HEAP START - ; | Size (2 bytes) | - ; | 0 | <-- Size = 0 => DUMMY HEADER BLOCK - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ <-+ - ; | Size (2 bytes) | - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ | - ; | | | <-- If Size > 4, then this contains (size - 4) bytes - ; | (0 if Size = 4)| | - ; +----------------+ <-+ - ; | Size (2 bytes) | - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ | - ; | | | - ; | (0 if Size = 4)| | - ; +----------------+ | - ; | <-- This zone is in use (Already allocated) - ; +----------------+ <-+ - ; | Size (2 bytes) | - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ | - ; | | | - ; | (0 if Size = 4)| | - ; +----------------+ <-+ - ; | Next (2 bytes) |--> NULL => END OF LIST - ; | 0 = NULL | - ; +----------------+ - ; | | - ; | (0 if Size = 4)| - ; +----------------+ - ; When a block is FREED, the previous and next pointers are examined to see - ; if we can defragment the heap. If the block to be breed is just next to the - ; previous, or to the next (or both) they will be converted into a single - ; block (so defragmented). - ; MEMORY MANAGER - ; - ; This library must be initialized calling __MEM_INIT with - ; HL = BLOCK Start & DE = Length. - ; An init directive is useful for initialization routines. - ; They will be added automatically if needed. - ; --------------------------------------------------------------------- - ; __MEM_INIT must be called to initalize this library with the - ; standard parameters - ; --------------------------------------------------------------------- - push namespace core -__MEM_INIT: ; Initializes the library using (RAMTOP) as start, and - ld hl, ZXBASIC_MEM_HEAP ; Change this with other address of heap start - ld de, ZXBASIC_HEAP_SIZE ; Change this with your size - ; --------------------------------------------------------------------- - ; __MEM_INIT2 initalizes this library -; Parameters: -; HL : Memory address of 1st byte of the memory heap -; DE : Length in bytes of the Memory Heap - ; --------------------------------------------------------------------- -__MEM_INIT2: - ; HL as TOP - PROC - dec de - dec de - dec de - dec de ; DE = length - 4; HL = start - ; This is done, because we require 4 bytes for the empty dummy-header block - xor a - ld (hl), a - inc hl - ld (hl), a ; First "free" block is a header: size=0, Pointer=&(Block) + 4 - inc hl - ld b, h - ld c, l - inc bc - inc bc ; BC = starts of next block - ld (hl), c - inc hl - ld (hl), b - inc hl ; Pointer to next block - ld (hl), e - inc hl - ld (hl), d - inc hl ; Block size (should be length - 4 at start); This block contains all the available memory - ld (hl), a ; NULL (0000h) ; No more blocks (a list with a single block) - inc hl - ld (hl), a - ld a, 201 - ld (__MEM_INIT), a; "Pokes" with a RET so ensure this routine is not called again - ret - ENDP - pop namespace -#line 69 "/zxbasic/src/arch/zx48k/library-asm/free.asm" - ; --------------------------------------------------------------------- - ; MEM_FREE - ; Frees a block of memory - ; -; Parameters: - ; HL = Pointer to the block to be freed. If HL is NULL (0) nothing - ; is done - ; --------------------------------------------------------------------- - push namespace core -MEM_FREE: -__MEM_FREE: ; Frees the block pointed by HL - ; HL DE BC & AF modified - PROC - LOCAL __MEM_LOOP2 - LOCAL __MEM_LINK_PREV - LOCAL __MEM_JOIN_TEST - LOCAL __MEM_BLOCK_JOIN - ld a, h - or l - ret z ; Return if NULL pointer - dec hl - dec hl - ld b, h - ld c, l ; BC = Block pointer - ld hl, ZXBASIC_MEM_HEAP ; This label point to the heap start -__MEM_LOOP2: - inc hl - inc hl ; Next block ptr - ld e, (hl) - inc hl - ld d, (hl) ; Block next ptr - ex de, hl ; DE = &(block->next); HL = block->next - ld a, h ; HL == NULL? - or l - jp z, __MEM_LINK_PREV; if so, link with previous - or a ; Clear carry flag - sbc hl, bc ; Carry if BC > HL => This block if before - add hl, bc ; Restores HL, preserving Carry flag - jp c, __MEM_LOOP2 ; This block is before. Keep searching PASS the block - ;------ At this point current HL is PAST BC, so we must link (DE) with BC, and HL in BC->next -__MEM_LINK_PREV: ; Link (DE) with BC, and BC->next with HL - ex de, hl - push hl - dec hl - ld (hl), c - inc hl - ld (hl), b ; (DE) <- BC - ld h, b ; HL <- BC (Free block ptr) - ld l, c - inc hl ; Skip block length (2 bytes) - inc hl - ld (hl), e ; Block->next = DE - inc hl - ld (hl), d - ; --- LINKED ; HL = &(BC->next) + 2 - call __MEM_JOIN_TEST - pop hl -__MEM_JOIN_TEST: ; Checks for fragmented contiguous blocks and joins them - ; hl = Ptr to current block + 2 - ld d, (hl) - dec hl - ld e, (hl) - dec hl - ld b, (hl) ; Loads block length into BC - dec hl - ld c, (hl) ; - push hl ; Saves it for later - add hl, bc ; Adds its length. If HL == DE now, it must be joined - or a - sbc hl, de ; If Z, then HL == DE => We must join - pop hl - ret nz -__MEM_BLOCK_JOIN: ; Joins current block (pointed by HL) with next one (pointed by DE). HL->length already in BC - push hl ; Saves it for later - ex de, hl - ld e, (hl) ; DE -> block->next->length - inc hl - ld d, (hl) - inc hl - ex de, hl ; DE = &(block->next) - add hl, bc ; HL = Total Length - ld b, h - ld c, l ; BC = Total Length - ex de, hl - ld e, (hl) - inc hl - ld d, (hl) ; DE = block->next - pop hl ; Recovers Pointer to block - ld (hl), c - inc hl - ld (hl), b ; Length Saved - inc hl - ld (hl), e - inc hl - ld (hl), d ; Next saved - ret - ENDP - pop namespace -#line 82 "zx48k/strparam0.bas" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/loadstr.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/alloc.asm" -; vim: ts=4:et:sw=4: - ; Copyleft (K) by Jose M. Rodriguez de la Rosa - ; (a.k.a. Boriel) -; http://www.boriel.com - ; - ; This ASM library is licensed under the MIT license - ; you can use it for any purpose (even for commercial - ; closed source programs). - ; - ; Please read the MIT license on the internet - ; ----- IMPLEMENTATION NOTES ------ - ; The heap is implemented as a linked list of free blocks. -; Each free block contains this info: - ; - ; +----------------+ <-- HEAP START - ; | Size (2 bytes) | - ; | 0 | <-- Size = 0 => DUMMY HEADER BLOCK - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ <-+ - ; | Size (2 bytes) | - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ | - ; | | | <-- If Size > 4, then this contains (size - 4) bytes - ; | (0 if Size = 4)| | - ; +----------------+ <-+ - ; | Size (2 bytes) | - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ | - ; | | | - ; | (0 if Size = 4)| | - ; +----------------+ | - ; | <-- This zone is in use (Already allocated) - ; +----------------+ <-+ - ; | Size (2 bytes) | - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ | - ; | | | - ; | (0 if Size = 4)| | - ; +----------------+ <-+ - ; | Next (2 bytes) |--> NULL => END OF LIST - ; | 0 = NULL | - ; +----------------+ - ; | | - ; | (0 if Size = 4)| - ; +----------------+ - ; When a block is FREED, the previous and next pointers are examined to see - ; if we can defragment the heap. If the block to be freed is just next to the - ; previous, or to the next (or both) they will be converted into a single - ; block (so defragmented). - ; MEMORY MANAGER - ; - ; This library must be initialized calling __MEM_INIT with - ; HL = BLOCK Start & DE = Length. - ; An init directive is useful for initialization routines. - ; They will be added automatically if needed. +#line 1 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +; vim:ts=4:sw=4:et: + ; PRINT command routine + ; Does not print attribute. Use PRINT_STR or PRINT_NUM for that +#line 1 "/zxbasic/src/arch/zx48k/library-asm/sposn.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/sysvars.asm" + ;; ----------------------------------------------------------------------- + ;; ZX Basic System Vars + ;; Some of them will be mapped over Sinclair ROM ones for compatibility + ;; ----------------------------------------------------------------------- + push namespace core +SCREEN_ADDR: DW 16384 ; Screen address (can be pointed to other place to use a screen buffer) +SCREEN_ATTR_ADDR: DW 22528 ; Screen attribute address (ditto.) + ; These are mapped onto ZX Spectrum ROM VARS + CHARS EQU 23606 ; Pointer to ROM/RAM Charset + TVFLAGS EQU 23612 ; TV Flags + UDG EQU 23675 ; Pointer to UDG Charset + COORDS EQU 23677 ; Last PLOT coordinates + FLAGS2 EQU 23681 ; + ECHO_E EQU 23682 ; + DFCC EQU 23684 ; Next screen addr for PRINT + DFCCL EQU 23686 ; Next screen attr for PRINT + S_POSN EQU 23688 + ATTR_P EQU 23693 ; Current Permanent ATTRS set with INK, PAPER, etc commands + ATTR_T EQU 23695 ; temporary ATTRIBUTES + P_FLAG EQU 23697 ; + MEM0 EQU 23698 ; Temporary memory buffer used by ROM chars + SCR_COLS EQU 33 ; Screen with in columns + 1 + SCR_ROWS EQU 24 ; Screen height in rows + SCR_SIZE EQU (SCR_ROWS << 8) + SCR_COLS + pop namespace +#line 2 "/zxbasic/src/arch/zx48k/library-asm/sposn.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/attr.asm" + ; Attribute routines +; vim:ts=4:et:sw: #line 1 "/zxbasic/src/arch/zx48k/library-asm/error.asm" ; Simple error control routines ; vim:ts=4:et: @@ -468,460 +177,795 @@ __STOP: ld (ERR_NR), a ret pop namespace -#line 69 "/zxbasic/src/arch/zx48k/library-asm/alloc.asm" - ; --------------------------------------------------------------------- - ; MEM_ALLOC - ; Allocates a block of memory in the heap. - ; - ; Parameters - ; BC = Length of requested memory block - ; -; Returns: - ; HL = Pointer to the allocated block in memory. Returns 0 (NULL) - ; if the block could not be allocated (out of memory) - ; --------------------------------------------------------------------- +#line 6 "/zxbasic/src/arch/zx48k/library-asm/attr.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/in_screen.asm" push namespace core -MEM_ALLOC: -__MEM_ALLOC: ; Returns the 1st free block found of the given length (in BC) +__IN_SCREEN: + ; Returns NO carry if current coords (D, E) + ; are OUT of the screen limits PROC - LOCAL __MEM_LOOP - LOCAL __MEM_DONE - LOCAL __MEM_SUBTRACT - LOCAL __MEM_START - LOCAL TEMP, TEMP0 - TEMP EQU TEMP0 + 1 - ld hl, 0 - ld (TEMP), hl -__MEM_START: - ld hl, ZXBASIC_MEM_HEAP ; This label point to the heap start - inc bc - inc bc ; BC = BC + 2 ; block size needs 2 extra bytes for hidden pointer -__MEM_LOOP: ; Loads lengh at (HL, HL+). If Lenght >= BC, jump to __MEM_DONE - ld a, h ; HL = NULL (No memory available?) - or l -#line 113 "/zxbasic/src/arch/zx48k/library-asm/alloc.asm" - ret z ; NULL -#line 115 "/zxbasic/src/arch/zx48k/library-asm/alloc.asm" - ; HL = Pointer to Free block - ld e, (hl) - inc hl - ld d, (hl) - inc hl ; DE = Block Length - push hl ; HL = *pointer to -> next block - ex de, hl - or a ; CF = 0 - sbc hl, bc ; FREE >= BC (Length) (HL = BlockLength - Length) - jp nc, __MEM_DONE - pop hl - ld (TEMP), hl + LOCAL __IN_SCREEN_ERR + ld hl, SCR_SIZE + ld a, e + cp l + jr nc, __IN_SCREEN_ERR ; Do nothing and return if out of range + ld a, d + cp h + ret c ; Return if carry (OK) +__IN_SCREEN_ERR: +__OUT_OF_SCREEN_ERR: + ; Jumps here if out of screen + ld a, ERROR_OutOfScreen + jp __STOP ; Saves error code and exits + ENDP + pop namespace +#line 7 "/zxbasic/src/arch/zx48k/library-asm/attr.asm" + push namespace core +__ATTR_ADDR: + ; calc start address in DE (as (32 * d) + e) + ; Contributed by Santiago Romero at http://www.speccy.org + ld h, 0 ; 7 T-States + ld a, d ; 4 T-States + ld d, h + add a, a ; a * 2 ; 4 T-States + add a, a ; a * 4 ; 4 T-States + ld l, a ; HL = A * 4 ; 4 T-States + add hl, hl ; HL = A * 8 ; 15 T-States + add hl, hl ; HL = A * 16 ; 15 T-States + add hl, hl ; HL = A * 32 ; 15 T-States + add hl, de + ld de, (SCREEN_ATTR_ADDR) ; Adds the screen address + add hl, de + ; Return current screen address in HL + ret + ; Sets the attribute at a given screen coordinate (D, E). + ; The attribute is taken from the ATTR_T memory variable + ; Used by PRINT routines +SET_ATTR: + ; Checks for valid coords + call __IN_SCREEN + ret nc + call __ATTR_ADDR +__SET_ATTR: + ; Internal __FASTCALL__ Entry used by printing routines + ; HL contains the address of the ATTR cell to set + PROC +__SET_ATTR2: ; Sets attr from ATTR_T to (HL) which points to the scr address + ld de, (ATTR_T) ; E = ATTR_T, D = MASK_T + ld a, d + and (hl) + ld c, a ; C = current screen color, masked + ld a, d + cpl ; Negate mask + and e ; Mask current attributes + or c ; Mix them + ld (hl), a ; Store result in screen + ret + ENDP + pop namespace +#line 3 "/zxbasic/src/arch/zx48k/library-asm/sposn.asm" + ; Printing positioning library. + push namespace core + ; Loads into DE current ROW, COL print position from S_POSN mem var. +__LOAD_S_POSN: + PROC + ld de, (S_POSN) + ld hl, SCR_SIZE + or a + sbc hl, de ex de, hl + ret + ENDP + ; Saves ROW, COL from DE into S_POSN mem var. +__SAVE_S_POSN: + PROC + ld hl, SCR_SIZE + or a + sbc hl, de + ld (S_POSN), hl ; saves it again +__SET_SCR_PTR: ;; Fast + push de + call __ATTR_ADDR + ld (DFCCL), hl + pop de + ld a, d + ld c, a ; Saves it for later + and 0F8h ; Masks 3 lower bit ; zy + ld d, a + ld a, c ; Recovers it + and 07h ; MOD 7 ; y1 + rrca + rrca + rrca + or e + ld e, a + ld hl, (SCREEN_ADDR) + add hl, de ; HL = Screen address + DE + ld (DFCC), hl + ret + ENDP + pop namespace +#line 6 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/table_jump.asm" + push namespace core +JUMP_HL_PLUS_2A: ; Does JP (HL + A*2) Modifies DE. Modifies A + add a, a +JUMP_HL_PLUS_A: ; Does JP (HL + A) Modifies DE + ld e, a + ld d, 0 +JUMP_HL_PLUS_DE: ; Does JP (HL + DE) + add hl, de ld e, (hl) inc hl ld d, (hl) ex de, hl - jp __MEM_LOOP -__MEM_DONE: ; A free block has been found. - ; Check if at least 4 bytes remains free (HL >= 4) - push hl - exx ; exx to preserve bc - pop hl - ld bc, 4 +CALL_HL: + jp (hl) + pop namespace +#line 8 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/ink.asm" + ; Sets ink color in ATTR_P permanently +; Parameter: Paper color in A register + push namespace core +INK: + PROC + LOCAL __SET_INK + LOCAL __SET_INK2 + ld de, ATTR_P +__SET_INK: + cp 8 + jr nz, __SET_INK2 + inc de ; Points DE to MASK_T or MASK_P + ld a, (de) + or 7 ; Set bits 0,1,2 to enable transparency + ld (de), a + ret +__SET_INK2: + ; Another entry. This will set the ink color at location pointer by DE + and 7 ; # Gets color mod 8 + ld b, a ; Saves the color + ld a, (de) + and 0F8h ; Clears previous value + or b + ld (de), a + inc de ; Points DE to MASK_T or MASK_P + ld a, (de) + and 0F8h ; Reset bits 0,1,2 sign to disable transparency + ld (de), a ; Store new attr + ret + ; Sets the INK color passed in A register in the ATTR_T variable +INK_TMP: + ld de, ATTR_T + jp __SET_INK + ENDP + pop namespace +#line 9 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/paper.asm" + ; Sets paper color in ATTR_P permanently +; Parameter: Paper color in A register + push namespace core +PAPER: + PROC + LOCAL __SET_PAPER + LOCAL __SET_PAPER2 + ld de, ATTR_P +__SET_PAPER: + cp 8 + jr nz, __SET_PAPER2 + inc de + ld a, (de) + or 038h + ld (de), a + ret + ; Another entry. This will set the paper color at location pointer by DE +__SET_PAPER2: + and 7 ; # Remove + rlca + rlca + rlca ; a *= 8 + ld b, a ; Saves the color + ld a, (de) + and 0C7h ; Clears previous value + or b + ld (de), a + inc de ; Points to MASK_T or MASK_P accordingly + ld a, (de) + and 0C7h ; Resets bits 3,4,5 + ld (de), a + ret + ; Sets the PAPER color passed in A register in the ATTR_T variable +PAPER_TMP: + ld de, ATTR_T + jp __SET_PAPER + ENDP + pop namespace +#line 10 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/flash.asm" + ; Sets flash flag in ATTR_P permanently +; Parameter: Paper color in A register + push namespace core +FLASH: + ld hl, ATTR_P + PROC + LOCAL IS_TR + LOCAL IS_ZERO +__SET_FLASH: + ; Another entry. This will set the flash flag at location pointer by DE + cp 8 + jr z, IS_TR + ; # Convert to 0/1 or a - sbc hl, bc - exx - jp nc, __MEM_SUBTRACT - ; At this point... - ; less than 4 bytes remains free. So we return this block entirely - ; We must link the previous block with the next to this one - ; (DE) => Pointer to next block - ; (TEMP) => &(previous->next) - pop hl ; Discard current block pointer - push de - ex de, hl ; DE = Previous block pointer; (HL) = Next block pointer + jr z, IS_ZERO + ld a, 0x80 +IS_ZERO: + ld b, a ; Saves the color ld a, (hl) + and 07Fh ; Clears previous value + or b + ld (hl), a inc hl - ld h, (hl) - ld l, a ; HL = (HL) - ex de, hl ; HL = Previous block pointer; DE = Next block pointer -TEMP0: - ld hl, 0 ; Pre-previous block pointer - ld (hl), e - inc hl - ld (hl), d ; LINKED - pop hl ; Returning block. + res 7, (hl) ;Reset bit 7 to disable transparency ret -__MEM_SUBTRACT: - ; At this point we have to store HL value (Length - BC) into (DE - 2) - ex de, hl - dec hl - ld (hl), d - dec hl - ld (hl), e ; Store new block length - add hl, de ; New length + DE => free-block start - pop de ; Remove previous HL off the stack - ld (hl), c ; Store length on its 1st word - inc hl - ld (hl), b - inc hl ; Return hl +IS_TR: ; transparent + inc hl ; Points DE to MASK_T or MASK_P + set 7, (hl) ;Set bit 7 to enable transparency ret + ; Sets the FLASH flag passed in A register in the ATTR_T variable +FLASH_TMP: + ld hl, ATTR_T + jr __SET_FLASH ENDP pop namespace -#line 2 "/zxbasic/src/arch/zx48k/library-asm/loadstr.asm" - ; Loads a string (ptr) from HL - ; and duplicates it on dynamic memory again - ; Finally, it returns result pointer in HL +#line 11 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/bright.asm" + ; Sets bright flag in ATTR_P permanently +; Parameter: Paper color in A register push namespace core -__ILOADSTR: ; This is the indirect pointer entry HL = (HL) - ld a, h - or l - ret z +BRIGHT: + ld hl, ATTR_P + PROC + LOCAL IS_TR + LOCAL IS_ZERO +__SET_BRIGHT: + ; Another entry. This will set the bright flag at location pointer by DE + cp 8 + jr z, IS_TR + ; # Convert to 0/1 + or a + jr z, IS_ZERO + ld a, 0x40 +IS_ZERO: + ld b, a ; Saves the color ld a, (hl) + and 0BFh ; Clears previous value + or b + ld (hl), a inc hl - ld h, (hl) - ld l, a -__LOADSTR: ; __FASTCALL__ entry - ld a, h - or l - ret z ; Return if NULL - ld c, (hl) - inc hl - ld b, (hl) - dec hl ; BC = LEN(a$) - inc bc - inc bc ; BC = LEN(a$) + 2 (two bytes for length) - push hl - push bc - call __MEM_ALLOC - pop bc ; Recover length - pop de ; Recover origin - ld a, h - or l - ret z ; Return if NULL (No memory) - ex de, hl ; ldir takes HL as source, DE as destiny, so SWAP HL,DE - push de ; Saves destiny start - ldir ; Copies string (length number included) - pop hl ; Recovers destiny in hl as result + res 6, (hl) ;Reset bit 6 to disable transparency + ret +IS_TR: ; transparent + inc hl ; Points DE to MASK_T or MASK_P + set 6, (hl) ;Set bit 6 to enable transparency ret + ; Sets the BRIGHT flag passed in A register in the ATTR_T variable +BRIGHT_TMP: + ld hl, ATTR_T + jr __SET_BRIGHT + ENDP pop namespace -#line 83 "zx48k/strparam0.bas" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/print_eol_attr.asm" - ; Calls PRINT_EOL and then COPY_ATTR, so saves - ; 3 bytes -#line 1 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -; vim:ts=4:sw=4:et: - ; PRINT command routine - ; Does not print attribute. Use PRINT_STR or PRINT_NUM for that -#line 1 "/zxbasic/src/arch/zx48k/library-asm/sposn.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/sysvars.asm" - ;; ----------------------------------------------------------------------- - ;; ZX Basic System Vars - ;; Some of them will be mapped over Sinclair ROM ones for compatibility - ;; ----------------------------------------------------------------------- - push namespace core -SCREEN_ADDR: DW 16384 ; Screen address (can be pointed to other place to use a screen buffer) -SCREEN_ATTR_ADDR: DW 22528 ; Screen attribute address (ditto.) - ; These are mapped onto ZX Spectrum ROM VARS - CHARS EQU 23606 ; Pointer to ROM/RAM Charset - TVFLAGS EQU 23612 ; TV Flags - UDG EQU 23675 ; Pointer to UDG Charset - COORDS EQU 23677 ; Last PLOT coordinates - FLAGS2 EQU 23681 ; - ECHO_E EQU 23682 ; - DFCC EQU 23684 ; Next screen addr for PRINT - DFCCL EQU 23686 ; Next screen attr for PRINT - S_POSN EQU 23688 - ATTR_P EQU 23693 ; Current Permanent ATTRS set with INK, PAPER, etc commands - ATTR_T EQU 23695 ; temporary ATTRIBUTES - P_FLAG EQU 23697 ; - MEM0 EQU 23698 ; Temporary memory buffer used by ROM chars - SCR_COLS EQU 33 ; Screen with in columns + 1 - SCR_ROWS EQU 24 ; Screen height in rows - SCR_SIZE EQU (SCR_ROWS << 8) + SCR_COLS - pop namespace -#line 2 "/zxbasic/src/arch/zx48k/library-asm/sposn.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/attr.asm" - ; Attribute routines -; vim:ts=4:et:sw: -#line 1 "/zxbasic/src/arch/zx48k/library-asm/in_screen.asm" +#line 12 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/over.asm" + ; Sets OVER flag in P_FLAG permanently +; Parameter: OVER flag in bit 0 of A register push namespace core -__IN_SCREEN: - ; Returns NO carry if current coords (D, E) - ; are OUT of the screen limits +OVER: PROC - LOCAL __IN_SCREEN_ERR - ld hl, SCR_SIZE - ld a, e - cp l - jr nc, __IN_SCREEN_ERR ; Do nothing and return if out of range - ld a, d - cp h - ret c ; Return if carry (OK) -__IN_SCREEN_ERR: -__OUT_OF_SCREEN_ERR: - ; Jumps here if out of screen - ld a, ERROR_OutOfScreen - jp __STOP ; Saves error code and exits + ld c, a ; saves it for later + and 2 + ld hl, FLAGS2 + res 1, (HL) + or (hl) + ld (hl), a + ld a, c ; Recovers previous value + and 1 ; # Convert to 0/1 + add a, a; # Shift left 1 bit for permanent + ld hl, P_FLAG + res 1, (hl) + or (hl) + ld (hl), a + ret + ; Sets OVER flag in P_FLAG temporarily +OVER_TMP: + ld c, a ; saves it for later + and 2 ; gets bit 1; clears carry + rra + ld hl, FLAGS2 + res 0, (hl) + or (hl) + ld (hl), a + ld a, c ; Recovers previous value + and 1 + ld hl, P_FLAG + res 0, (hl) + or (hl) + ld (hl), a + jp __SET_ATTR_MODE + ENDP + pop namespace +#line 13 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/inverse.asm" + ; Sets INVERSE flag in P_FLAG permanently +; Parameter: INVERSE flag in bit 0 of A register + push namespace core +INVERSE: + PROC + and 1 ; # Convert to 0/1 + add a, a; # Shift left 3 bits for permanent + add a, a + add a, a + ld hl, P_FLAG + res 3, (hl) + or (hl) + ld (hl), a + ret + ; Sets INVERSE flag in P_FLAG temporarily +INVERSE_TMP: + and 1 + add a, a + add a, a; # Shift left 2 bits for temporary + ld hl, P_FLAG + res 2, (hl) + or (hl) + ld (hl), a + jp __SET_ATTR_MODE + ENDP + pop namespace +#line 14 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/bold.asm" + ; Sets BOLD flag in P_FLAG permanently +; Parameter: BOLD flag in bit 0 of A register + push namespace core +BOLD: + PROC + and 1 + rlca + rlca + rlca + ld hl, FLAGS2 + res 3, (HL) + or (hl) + ld (hl), a + ret + ; Sets BOLD flag in P_FLAG temporarily +BOLD_TMP: + and 1 + rlca + rlca + ld hl, FLAGS2 + res 2, (hl) + or (hl) + ld (hl), a + ret ENDP pop namespace -#line 7 "/zxbasic/src/arch/zx48k/library-asm/attr.asm" +#line 15 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/italic.asm" + ; Sets ITALIC flag in P_FLAG permanently +; Parameter: ITALIC flag in bit 0 of A register push namespace core -__ATTR_ADDR: - ; calc start address in DE (as (32 * d) + e) - ; Contributed by Santiago Romero at http://www.speccy.org - ld h, 0 ; 7 T-States - ld a, d ; 4 T-States - ld d, h - add a, a ; a * 2 ; 4 T-States - add a, a ; a * 4 ; 4 T-States - ld l, a ; HL = A * 4 ; 4 T-States - add hl, hl ; HL = A * 8 ; 15 T-States - add hl, hl ; HL = A * 16 ; 15 T-States - add hl, hl ; HL = A * 32 ; 15 T-States - add hl, de - ld de, (SCREEN_ATTR_ADDR) ; Adds the screen address - add hl, de - ; Return current screen address in HL - ret - ; Sets the attribute at a given screen coordinate (D, E). - ; The attribute is taken from the ATTR_T memory variable - ; Used by PRINT routines -SET_ATTR: - ; Checks for valid coords - call __IN_SCREEN - ret nc - call __ATTR_ADDR -__SET_ATTR: - ; Internal __FASTCALL__ Entry used by printing routines - ; HL contains the address of the ATTR cell to set +ITALIC: PROC -__SET_ATTR2: ; Sets attr from ATTR_T to (HL) which points to the scr address - ld de, (ATTR_T) ; E = ATTR_T, D = MASK_T - ld a, d - and (hl) - ld c, a ; C = current screen color, masked - ld a, d - cpl ; Negate mask - and e ; Mask current attributes - or c ; Mix them - ld (hl), a ; Store result in screen + and 1 + rrca + rrca + rrca + ld hl, FLAGS2 + res 5, (HL) + or (hl) + ld (hl), a + ret + ; Sets ITALIC flag in P_FLAG temporarily +ITALIC_TMP: + and 1 + rrca + rrca + rrca + rrca + ld hl, FLAGS2 + res 4, (hl) + or (hl) + ld (hl), a ret ENDP pop namespace -#line 3 "/zxbasic/src/arch/zx48k/library-asm/sposn.asm" - ; Printing positioning library. +#line 16 "/zxbasic/src/arch/zx48k/library-asm/print.asm" + ; Putting a comment starting with @INIT
+ ; will make the compiler to add a CALL to
+ ; It is useful for initialization routines. push namespace core - ; Loads into DE current ROW, COL print position from S_POSN mem var. -__LOAD_S_POSN: +__PRINT_INIT: ; To be called before program starts (initializes library) PROC - ld de, (S_POSN) + ld hl, __PRINT_START + ld (PRINT_JUMP_STATE), hl + ;; Clears ATTR2 flags (OVER 2, etc) + xor a + ld (FLAGS2), a + LOCAL SET_SCR_ADDR + call __LOAD_S_POSN + jp __SET_SCR_PTR + ;; Receives HL = future value of S_POSN + ;; Stores it at (S_POSN) and refresh screen pointers (ATTR, SCR) +SET_SCR_ADDR: + ld (S_POSN), hl + ex de, hl ld hl, SCR_SIZE or a sbc hl, de ex de, hl + dec e + jp __SET_SCR_PTR +__PRINTCHAR: ; Print character store in accumulator (A register) + ; Modifies H'L', B'C', A'F', D'E', A + LOCAL PO_GR_1 + LOCAL __PRCHAR + LOCAL __PRINT_JUMP + LOCAL __SRCADDR + LOCAL __PRINT_UDG + LOCAL __PRGRAPH + LOCAL __PRINT_START + PRINT_JUMP_STATE EQU __PRINT_JUMP + 2 +__PRINT_JUMP: + exx ; Switch to alternative registers + jp __PRINT_START ; Where to jump. If we print 22 (AT), next two calls jumps to AT1 and AT2 respectively +__PRINT_START: +__PRINT_CHR: + cp ' ' + jr c, __PRINT_SPECIAL ; Characters below ' ' are special ones + ex af, af' ; Saves a value (char to print) for later + ld hl, (S_POSN) + dec l + jr nz, 1f + ld l, SCR_COLS - 1 + dec h + jr nz, 2f + inc h + push hl + call __SCROLL_SCR + pop hl +#line 92 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +2: + call SET_SCR_ADDR + jr 4f +1: + ld (S_POSN), hl +4: + ex af, af' + cp 80h ; Is it a "normal" (printable) char + jr c, __SRCADDR + cp 90h ; Is it an UDG? + jr nc, __PRINT_UDG + ; Print an 8 bit pattern (80h to 8Fh) + ld b, a + call PO_GR_1 ; This ROM routine will generate the bit pattern at MEM0 + ld hl, MEM0 + jp __PRGRAPH + PO_GR_1 EQU 0B38h +__PRINT_UDG: + sub 90h ; Sub ASC code + ld bc, (UDG) + jr __PRGRAPH0 + __SOURCEADDR EQU (__SRCADDR + 1) ; Address of the pointer to chars source +__SRCADDR: + ld bc, (CHARS) +__PRGRAPH0: + add a, a ; A = a * 2 (since a < 80h) ; Thanks to Metalbrain at http://foro.speccy.org + ld l, a + ld h, 0 ; HL = a * 2 (accumulator) + add hl, hl + add hl, hl ; HL = a * 8 + add hl, bc ; HL = CHARS address +__PRGRAPH: + ex de, hl ; HL = Write Address, DE = CHARS address + bit 2, (iy + $47) + call nz, __BOLD +#line 139 "/zxbasic/src/arch/zx48k/library-asm/print.asm" + bit 4, (iy + $47) + call nz, __ITALIC +#line 144 "/zxbasic/src/arch/zx48k/library-asm/print.asm" + ld hl, (DFCC) + push hl + ld b, 8 ; 8 bytes per char +__PRCHAR: + ld a, (de) ; DE *must* be source, and HL destiny +PRINT_MODE: ; Which operation is used to write on the screen + ; Set it with: + ; LD A, + ; LD (PRINT_MODE), A + ; + ; Available operations: + ; NORMAL : 0h --> NOP ; OVER 0 + ; XOR : AEh --> XOR (HL) ; OVER 1 + ; OR : B6h --> OR (HL) ; PUTSPRITE + ; AND : A6h --> AND (HL) ; PUTMASK + nop ; Set to one of the values above +INVERSE_MODE: ; 00 -> NOP -> INVERSE 0 + nop ; 2F -> CPL -> INVERSE 1 + ld (hl), a + inc de + inc h ; Next line + djnz __PRCHAR + pop hl + inc hl + ld (DFCC), hl + ld hl, (DFCCL) ; current ATTR Pos + inc hl + ld (DFCCL), hl + dec hl + call __SET_ATTR + exx ret - ENDP - ; Saves ROW, COL from DE into S_POSN mem var. -__SAVE_S_POSN: - PROC - ld hl, SCR_SIZE - or a - sbc hl, de - ld (S_POSN), hl ; saves it again -__SET_SCR_PTR: ;; Fast + ; ------------- SPECIAL CHARS (< 32) ----------------- +__PRINT_SPECIAL: ; Jumps here if it is a special char + ld hl, __PRINT_TABLE + jp JUMP_HL_PLUS_2A +PRINT_EOL: ; Called WHENEVER there is no ";" at end of PRINT sentence + exx +__PRINT_0Dh: ; Called WHEN printing CHR$(13) + ld hl, (S_POSN) + dec l + jr nz, 1f + dec h + jr nz, 1f + inc h + push hl + call __SCROLL_SCR + pop hl +#line 209 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +1: + ld l, 1 +__PRINT_EOL_END: + call SET_SCR_ADDR + exx + ret +__PRINT_COM: + exx + push hl push de - call __ATTR_ADDR - ld (DFCCL), hl + push bc + call PRINT_COMMA + pop bc pop de - ld a, d - ld c, a ; Saves it for later - and 0F8h ; Masks 3 lower bit ; zy - ld d, a - ld a, c ; Recovers it - and 07h ; MOD 7 ; y1 - rrca - rrca - rrca - or e - ld e, a - ld hl, (SCREEN_ADDR) - add hl, de ; HL = Screen address + DE - ld (DFCC), hl + pop hl + ret +__PRINT_TAB: + ld hl, __PRINT_TAB1 + jr __PRINT_SET_STATE +__PRINT_TAB1: + ld (MEM0), a + ld hl, __PRINT_TAB2 + jr __PRINT_SET_STATE +__PRINT_TAB2: + ld a, (MEM0) ; Load tab code (ignore the current one) + ld hl, __PRINT_START + ld (PRINT_JUMP_STATE), hl + exx + push hl + push bc + push de + call PRINT_TAB + pop de + pop bc + pop hl ret - ENDP - pop namespace -#line 6 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/table_jump.asm" - push namespace core -JUMP_HL_PLUS_2A: ; Does JP (HL + A*2) Modifies DE. Modifies A - add a, a -JUMP_HL_PLUS_A: ; Does JP (HL + A) Modifies DE - ld e, a - ld d, 0 -JUMP_HL_PLUS_DE: ; Does JP (HL + DE) - add hl, de - ld e, (hl) - inc hl - ld d, (hl) - ex de, hl -CALL_HL: - jp (hl) - pop namespace -#line 8 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/ink.asm" - ; Sets ink color in ATTR_P permanently -; Parameter: Paper color in A register - push namespace core -INK: - PROC - LOCAL __SET_INK - LOCAL __SET_INK2 - ld de, ATTR_P -__SET_INK: - cp 8 - jr nz, __SET_INK2 - inc de ; Points DE to MASK_T or MASK_P - ld a, (de) - or 7 ; Set bits 0,1,2 to enable transparency - ld (de), a +__PRINT_AT: + ld hl, __PRINT_AT1 + jr __PRINT_SET_STATE +__PRINT_NOP: +__PRINT_RESTART: + ld hl, __PRINT_START +__PRINT_SET_STATE: + ld (PRINT_JUMP_STATE), hl ; Saves next entry call + exx ret -__SET_INK2: - ; Another entry. This will set the ink color at location pointer by DE - and 7 ; # Gets color mod 8 - ld b, a ; Saves the color - ld a, (de) - and 0F8h ; Clears previous value - or b - ld (de), a - inc de ; Points DE to MASK_T or MASK_P - ld a, (de) - and 0F8h ; Reset bits 0,1,2 sign to disable transparency - ld (de), a ; Store new attr +__PRINT_AT1: ; Jumps here if waiting for 1st parameter + ld hl, (S_POSN) + ld h, a + ld a, SCR_ROWS + sub h + ld (S_POSN + 1), a + ld hl, __PRINT_AT2 + jr __PRINT_SET_STATE +__PRINT_AT2: + call __LOAD_S_POSN + ld e, a + call __SAVE_S_POSN + jr __PRINT_RESTART +__PRINT_DEL: + call __LOAD_S_POSN ; Gets current screen position + dec e + ld a, -1 + cp e + jr nz, 3f + ld e, SCR_COLS - 2 + dec d + cp d + jr nz, 3f + ld d, SCR_ROWS - 1 +3: + call __SAVE_S_POSN + exx ret - ; Sets the INK color passed in A register in the ATTR_T variable -INK_TMP: - ld de, ATTR_T - jp __SET_INK - ENDP - pop namespace -#line 9 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/paper.asm" - ; Sets paper color in ATTR_P permanently -; Parameter: Paper color in A register - push namespace core -PAPER: - PROC - LOCAL __SET_PAPER - LOCAL __SET_PAPER2 - ld de, ATTR_P -__SET_PAPER: - cp 8 - jr nz, __SET_PAPER2 - inc de +__PRINT_INK: + ld hl, __PRINT_INK2 + jr __PRINT_SET_STATE +__PRINT_INK2: + call INK_TMP + jr __PRINT_RESTART +__PRINT_PAP: + ld hl, __PRINT_PAP2 + jr __PRINT_SET_STATE +__PRINT_PAP2: + call PAPER_TMP + jr __PRINT_RESTART +__PRINT_FLA: + ld hl, __PRINT_FLA2 + jr __PRINT_SET_STATE +__PRINT_FLA2: + call FLASH_TMP + jr __PRINT_RESTART +__PRINT_BRI: + ld hl, __PRINT_BRI2 + jr __PRINT_SET_STATE +__PRINT_BRI2: + call BRIGHT_TMP + jr __PRINT_RESTART +__PRINT_INV: + ld hl, __PRINT_INV2 + jr __PRINT_SET_STATE +__PRINT_INV2: + call INVERSE_TMP + jr __PRINT_RESTART +__PRINT_OVR: + ld hl, __PRINT_OVR2 + jr __PRINT_SET_STATE +__PRINT_OVR2: + call OVER_TMP + jr __PRINT_RESTART +__PRINT_BOLD: + ld hl, __PRINT_BOLD2 + jp __PRINT_SET_STATE +__PRINT_BOLD2: + call BOLD_TMP + jp __PRINT_RESTART +#line 353 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +__PRINT_ITA: + ld hl, __PRINT_ITA2 + jp __PRINT_SET_STATE +__PRINT_ITA2: + call ITALIC_TMP + jp __PRINT_RESTART +#line 363 "/zxbasic/src/arch/zx48k/library-asm/print.asm" + LOCAL __BOLD +__BOLD: + push hl + ld hl, MEM0 + ld b, 8 +1: ld a, (de) - or 038h - ld (de), a - ret - ; Another entry. This will set the paper color at location pointer by DE -__SET_PAPER2: - and 7 ; # Remove - rlca + ld c, a rlca - rlca ; a *= 8 - ld b, a ; Saves the color - ld a, (de) - and 0C7h ; Clears previous value - or b - ld (de), a - inc de ; Points to MASK_T or MASK_P accordingly - ld a, (de) - and 0C7h ; Resets bits 3,4,5 - ld (de), a - ret - ; Sets the PAPER color passed in A register in the ATTR_T variable -PAPER_TMP: - ld de, ATTR_T - jp __SET_PAPER - ENDP - pop namespace -#line 10 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/flash.asm" - ; Sets flash flag in ATTR_P permanently -; Parameter: Paper color in A register - push namespace core -FLASH: - ld hl, ATTR_P - PROC - LOCAL IS_TR - LOCAL IS_ZERO -__SET_FLASH: - ; Another entry. This will set the flash flag at location pointer by DE - cp 8 - jr z, IS_TR - ; # Convert to 0/1 - or a - jr z, IS_ZERO - ld a, 0x80 -IS_ZERO: - ld b, a ; Saves the color - ld a, (hl) - and 07Fh ; Clears previous value - or b + or c ld (hl), a inc hl - res 7, (hl) ;Reset bit 7 to disable transparency - ret -IS_TR: ; transparent - inc hl ; Points DE to MASK_T or MASK_P - set 7, (hl) ;Set bit 7 to enable transparency - ret - ; Sets the FLASH flag passed in A register in the ATTR_T variable -FLASH_TMP: - ld hl, ATTR_T - jr __SET_FLASH - ENDP - pop namespace -#line 11 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/bright.asm" - ; Sets bright flag in ATTR_P permanently -; Parameter: Paper color in A register - push namespace core -BRIGHT: - ld hl, ATTR_P - PROC - LOCAL IS_TR - LOCAL IS_ZERO -__SET_BRIGHT: - ; Another entry. This will set the bright flag at location pointer by DE - cp 8 - jr z, IS_TR - ; # Convert to 0/1 - or a - jr z, IS_ZERO - ld a, 0x40 -IS_ZERO: - ld b, a ; Saves the color - ld a, (hl) - and 0BFh ; Clears previous value - or b - ld (hl), a + inc de + djnz 1b + pop hl + ld de, MEM0 + ret +#line 384 "/zxbasic/src/arch/zx48k/library-asm/print.asm" + LOCAL __ITALIC +__ITALIC: + push hl + ld hl, MEM0 + ex de, hl + ld bc, 8 + ldir + ld hl, MEM0 + srl (hl) inc hl - res 6, (hl) ;Reset bit 6 to disable transparency + srl (hl) + inc hl + srl (hl) + inc hl + inc hl + inc hl + sla (hl) + inc hl + sla (hl) + inc hl + sla (hl) + pop hl + ld de, MEM0 ret -IS_TR: ; transparent - inc hl ; Points DE to MASK_T or MASK_P - set 6, (hl) ;Set bit 6 to enable transparency +#line 412 "/zxbasic/src/arch/zx48k/library-asm/print.asm" + LOCAL __SCROLL_SCR +#line 486 "/zxbasic/src/arch/zx48k/library-asm/print.asm" + __SCROLL_SCR EQU 0DFEh ; Use ROM SCROLL +#line 488 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 489 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +PRINT_COMMA: + call __LOAD_S_POSN + ld a, e + and 16 + add a, 16 +PRINT_TAB: + ; Tabulates the number of spaces in A register + ; If the current cursor position is already A, does nothing + PROC + LOCAL LOOP + call __LOAD_S_POSN ; e = current row + sub e + and 31 + ret z + ld b, a +LOOP: + ld a, ' ' + call __PRINTCHAR + djnz LOOP ret - ; Sets the BRIGHT flag passed in A register in the ATTR_T variable -BRIGHT_TMP: - ld hl, ATTR_T - jr __SET_BRIGHT + ENDP +PRINT_AT: ; Changes cursor to ROW, COL + ; COL in A register + ; ROW in stack + pop hl ; Ret address + ex (sp), hl ; callee H = ROW + ld l, a + ex de, hl + call __IN_SCREEN + ret nc ; Return if out of screen + jp __SAVE_S_POSN + LOCAL __PRINT_COM + LOCAL __PRINT_AT1 + LOCAL __PRINT_AT2 + LOCAL __PRINT_BOLD + LOCAL __PRINT_ITA + LOCAL __PRINT_INK + LOCAL __PRINT_PAP + LOCAL __PRINT_SET_STATE + LOCAL __PRINT_TABLE + LOCAL __PRINT_TAB, __PRINT_TAB1, __PRINT_TAB2 + LOCAL __PRINT_ITA2 +#line 545 "/zxbasic/src/arch/zx48k/library-asm/print.asm" + LOCAL __PRINT_BOLD2 +#line 551 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +__PRINT_TABLE: ; Jump table for 0 .. 22 codes + DW __PRINT_NOP ; 0 + DW __PRINT_NOP ; 1 + DW __PRINT_NOP ; 2 + DW __PRINT_NOP ; 3 + DW __PRINT_NOP ; 4 + DW __PRINT_NOP ; 5 + DW __PRINT_COM ; 6 COMMA + DW __PRINT_NOP ; 7 + DW __PRINT_DEL ; 8 DEL + DW __PRINT_NOP ; 9 + DW __PRINT_NOP ; 10 + DW __PRINT_NOP ; 11 + DW __PRINT_NOP ; 12 + DW __PRINT_0Dh ; 13 + DW __PRINT_BOLD ; 14 + DW __PRINT_ITA ; 15 + DW __PRINT_INK ; 16 + DW __PRINT_PAP ; 17 + DW __PRINT_FLA ; 18 + DW __PRINT_BRI ; 19 + DW __PRINT_INV ; 20 + DW __PRINT_OVR ; 21 + DW __PRINT_AT ; 22 AT + DW __PRINT_TAB ; 23 TAB ENDP pop namespace -#line 12 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/over.asm" - ; Sets OVER flag in P_FLAG permanently -; Parameter: OVER flag in bit 0 of A register -#line 1 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" +#line 3 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" #line 4 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" push namespace core COPY_ATTR: @@ -974,523 +1018,470 @@ __REFRESH_TMP: ret ENDP pop namespace -#line 4 "/zxbasic/src/arch/zx48k/library-asm/over.asm" - push namespace core -OVER: - PROC - ld c, a ; saves it for later - and 2 - ld hl, FLAGS2 - res 1, (HL) - or (hl) - ld (hl), a - ld a, c ; Recovers previous value - and 1 ; # Convert to 0/1 - add a, a; # Shift left 1 bit for permanent - ld hl, P_FLAG - res 1, (hl) - or (hl) - ld (hl), a - ret - ; Sets OVER flag in P_FLAG temporarily -OVER_TMP: - ld c, a ; saves it for later - and 2 ; gets bit 1; clears carry - rra - ld hl, FLAGS2 - res 0, (hl) - or (hl) - ld (hl), a - ld a, c ; Recovers previous value - and 1 - ld hl, P_FLAG - res 0, (hl) - or (hl) - ld (hl), a - jp __SET_ATTR_MODE - ENDP - pop namespace -#line 13 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/inverse.asm" - ; Sets INVERSE flag in P_FLAG permanently -; Parameter: INVERSE flag in bit 0 of A register - push namespace core -INVERSE: - PROC - and 1 ; # Convert to 0/1 - add a, a; # Shift left 3 bits for permanent - add a, a - add a, a - ld hl, P_FLAG - res 3, (hl) - or (hl) - ld (hl), a - ret - ; Sets INVERSE flag in P_FLAG temporarily -INVERSE_TMP: - and 1 - add a, a - add a, a; # Shift left 2 bits for temporary - ld hl, P_FLAG - res 2, (hl) - or (hl) - ld (hl), a - jp __SET_ATTR_MODE - ENDP - pop namespace -#line 14 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/bold.asm" - ; Sets BOLD flag in P_FLAG permanently -; Parameter: BOLD flag in bit 0 of A register - push namespace core -BOLD: - PROC - and 1 - rlca - rlca - rlca - ld hl, FLAGS2 - res 3, (HL) - or (hl) - ld (hl), a - ret - ; Sets BOLD flag in P_FLAG temporarily -BOLD_TMP: - and 1 - rlca - rlca - ld hl, FLAGS2 - res 2, (hl) - or (hl) - ld (hl), a - ret - ENDP - pop namespace -#line 15 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/italic.asm" - ; Sets ITALIC flag in P_FLAG permanently -; Parameter: ITALIC flag in bit 0 of A register +#line 83 "zx48k/strparam0.bas" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/free.asm" +; vim: ts=4:et:sw=4: + ; Copyleft (K) by Jose M. Rodriguez de la Rosa + ; (a.k.a. Boriel) +; http://www.boriel.com + ; + ; This ASM library is licensed under the BSD license + ; you can use it for any purpose (even for commercial + ; closed source programs). + ; + ; Please read the BSD license on the internet + ; ----- IMPLEMENTATION NOTES ------ + ; The heap is implemented as a linked list of free blocks. +; Each free block contains this info: + ; + ; +----------------+ <-- HEAP START + ; | Size (2 bytes) | + ; | 0 | <-- Size = 0 => DUMMY HEADER BLOCK + ; +----------------+ + ; | Next (2 bytes) |---+ + ; +----------------+ <-+ + ; | Size (2 bytes) | + ; +----------------+ + ; | Next (2 bytes) |---+ + ; +----------------+ | + ; | | | <-- If Size > 4, then this contains (size - 4) bytes + ; | (0 if Size = 4)| | + ; +----------------+ <-+ + ; | Size (2 bytes) | + ; +----------------+ + ; | Next (2 bytes) |---+ + ; +----------------+ | + ; | | | + ; | (0 if Size = 4)| | + ; +----------------+ | + ; | <-- This zone is in use (Already allocated) + ; +----------------+ <-+ + ; | Size (2 bytes) | + ; +----------------+ + ; | Next (2 bytes) |---+ + ; +----------------+ | + ; | | | + ; | (0 if Size = 4)| | + ; +----------------+ <-+ + ; | Next (2 bytes) |--> NULL => END OF LIST + ; | 0 = NULL | + ; +----------------+ + ; | | + ; | (0 if Size = 4)| + ; +----------------+ + ; When a block is FREED, the previous and next pointers are examined to see + ; if we can defragment the heap. If the block to be breed is just next to the + ; previous, or to the next (or both) they will be converted into a single + ; block (so defragmented). + ; MEMORY MANAGER + ; + ; This library must be initialized calling __MEM_INIT with + ; HL = BLOCK Start & DE = Length. + ; An init directive is useful for initialization routines. + ; They will be added automatically if needed. +#line 1 "/zxbasic/src/arch/zx48k/library-asm/heapinit.asm" +; vim: ts=4:et:sw=4: + ; Copyleft (K) by Jose M. Rodriguez de la Rosa + ; (a.k.a. Boriel) +; http://www.boriel.com + ; + ; This ASM library is licensed under the BSD license + ; you can use it for any purpose (even for commercial + ; closed source programs). + ; + ; Please read the BSD license on the internet + ; ----- IMPLEMENTATION NOTES ------ + ; The heap is implemented as a linked list of free blocks. +; Each free block contains this info: + ; + ; +----------------+ <-- HEAP START + ; | Size (2 bytes) | + ; | 0 | <-- Size = 0 => DUMMY HEADER BLOCK + ; +----------------+ + ; | Next (2 bytes) |---+ + ; +----------------+ <-+ + ; | Size (2 bytes) | + ; +----------------+ + ; | Next (2 bytes) |---+ + ; +----------------+ | + ; | | | <-- If Size > 4, then this contains (size - 4) bytes + ; | (0 if Size = 4)| | + ; +----------------+ <-+ + ; | Size (2 bytes) | + ; +----------------+ + ; | Next (2 bytes) |---+ + ; +----------------+ | + ; | | | + ; | (0 if Size = 4)| | + ; +----------------+ | + ; | <-- This zone is in use (Already allocated) + ; +----------------+ <-+ + ; | Size (2 bytes) | + ; +----------------+ + ; | Next (2 bytes) |---+ + ; +----------------+ | + ; | | | + ; | (0 if Size = 4)| | + ; +----------------+ <-+ + ; | Next (2 bytes) |--> NULL => END OF LIST + ; | 0 = NULL | + ; +----------------+ + ; | | + ; | (0 if Size = 4)| + ; +----------------+ + ; When a block is FREED, the previous and next pointers are examined to see + ; if we can defragment the heap. If the block to be breed is just next to the + ; previous, or to the next (or both) they will be converted into a single + ; block (so defragmented). + ; MEMORY MANAGER + ; + ; This library must be initialized calling __MEM_INIT with + ; HL = BLOCK Start & DE = Length. + ; An init directive is useful for initialization routines. + ; They will be added automatically if needed. + ; --------------------------------------------------------------------- + ; __MEM_INIT must be called to initalize this library with the + ; standard parameters + ; --------------------------------------------------------------------- push namespace core -ITALIC: +__MEM_INIT: ; Initializes the library using (RAMTOP) as start, and + ld hl, ZXBASIC_MEM_HEAP ; Change this with other address of heap start + ld de, ZXBASIC_HEAP_SIZE ; Change this with your size + ; --------------------------------------------------------------------- + ; __MEM_INIT2 initalizes this library +; Parameters: +; HL : Memory address of 1st byte of the memory heap +; DE : Length in bytes of the Memory Heap + ; --------------------------------------------------------------------- +__MEM_INIT2: + ; HL as TOP PROC - and 1 - rrca - rrca - rrca - ld hl, FLAGS2 - res 5, (HL) - or (hl) + dec de + dec de + dec de + dec de ; DE = length - 4; HL = start + ; This is done, because we require 4 bytes for the empty dummy-header block + xor a ld (hl), a - ret - ; Sets ITALIC flag in P_FLAG temporarily -ITALIC_TMP: - and 1 - rrca - rrca - rrca - rrca - ld hl, FLAGS2 - res 4, (hl) - or (hl) + inc hl + ld (hl), a ; First "free" block is a header: size=0, Pointer=&(Block) + 4 + inc hl + ld b, h + ld c, l + inc bc + inc bc ; BC = starts of next block + ld (hl), c + inc hl + ld (hl), b + inc hl ; Pointer to next block + ld (hl), e + inc hl + ld (hl), d + inc hl ; Block size (should be length - 4 at start); This block contains all the available memory + ld (hl), a ; NULL (0000h) ; No more blocks (a list with a single block) + inc hl ld (hl), a + ld a, 201 + ld (__MEM_INIT), a; "Pokes" with a RET so ensure this routine is not called again ret ENDP pop namespace -#line 16 "/zxbasic/src/arch/zx48k/library-asm/print.asm" - ; Putting a comment starting with @INIT
- ; will make the compiler to add a CALL to
- ; It is useful for initialization routines. +#line 69 "/zxbasic/src/arch/zx48k/library-asm/free.asm" + ; --------------------------------------------------------------------- + ; MEM_FREE + ; Frees a block of memory + ; +; Parameters: + ; HL = Pointer to the block to be freed. If HL is NULL (0) nothing + ; is done + ; --------------------------------------------------------------------- push namespace core -__PRINT_INIT: ; To be called before program starts (initializes library) - PROC - ld hl, __PRINT_START - ld (PRINT_JUMP_STATE), hl - ;; Clears ATTR2 flags (OVER 2, etc) - xor a - ld (FLAGS2), a - LOCAL SET_SCR_ADDR - call __LOAD_S_POSN - jp __SET_SCR_PTR - ;; Receives HL = future value of S_POSN - ;; Stores it at (S_POSN) and refresh screen pointers (ATTR, SCR) -SET_SCR_ADDR: - ld (S_POSN), hl - ex de, hl - ld hl, SCR_SIZE - or a - sbc hl, de - ex de, hl - dec e - jp __SET_SCR_PTR -__PRINTCHAR: ; Print character store in accumulator (A register) - ; Modifies H'L', B'C', A'F', D'E', A - LOCAL PO_GR_1 - LOCAL __PRCHAR - LOCAL __PRINT_JUMP - LOCAL __SRCADDR - LOCAL __PRINT_UDG - LOCAL __PRGRAPH - LOCAL __PRINT_START - PRINT_JUMP_STATE EQU __PRINT_JUMP + 2 -__PRINT_JUMP: - exx ; Switch to alternative registers - jp __PRINT_START ; Where to jump. If we print 22 (AT), next two calls jumps to AT1 and AT2 respectively -__PRINT_START: -__PRINT_CHR: - cp ' ' - jr c, __PRINT_SPECIAL ; Characters below ' ' are special ones - ex af, af' ; Saves a value (char to print) for later - ld hl, (S_POSN) - dec l - jr nz, 1f - ld l, SCR_COLS - 1 - dec h - jr nz, 2f - inc h - push hl - call __SCROLL_SCR - pop hl -#line 92 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -2: - call SET_SCR_ADDR - jr 4f -1: - ld (S_POSN), hl -4: - ex af, af' - cp 80h ; Is it a "normal" (printable) char - jr c, __SRCADDR - cp 90h ; Is it an UDG? - jr nc, __PRINT_UDG - ; Print an 8 bit pattern (80h to 8Fh) - ld b, a - call PO_GR_1 ; This ROM routine will generate the bit pattern at MEM0 - ld hl, MEM0 - jp __PRGRAPH - PO_GR_1 EQU 0B38h -__PRINT_UDG: - sub 90h ; Sub ASC code - ld bc, (UDG) - jr __PRGRAPH0 - __SOURCEADDR EQU (__SRCADDR + 1) ; Address of the pointer to chars source -__SRCADDR: - ld bc, (CHARS) -__PRGRAPH0: - add a, a ; A = a * 2 (since a < 80h) ; Thanks to Metalbrain at http://foro.speccy.org - ld l, a - ld h, 0 ; HL = a * 2 (accumulator) - add hl, hl - add hl, hl ; HL = a * 8 - add hl, bc ; HL = CHARS address -__PRGRAPH: - ex de, hl ; HL = Write Address, DE = CHARS address - bit 2, (iy + $47) - call nz, __BOLD -#line 139 "/zxbasic/src/arch/zx48k/library-asm/print.asm" - bit 4, (iy + $47) - call nz, __ITALIC -#line 144 "/zxbasic/src/arch/zx48k/library-asm/print.asm" - ld hl, (DFCC) - push hl - ld b, 8 ; 8 bytes per char -__PRCHAR: - ld a, (de) ; DE *must* be source, and HL destiny -PRINT_MODE: ; Which operation is used to write on the screen - ; Set it with: - ; LD A, - ; LD (PRINT_MODE), A - ; - ; Available operations: - ; NORMAL : 0h --> NOP ; OVER 0 - ; XOR : AEh --> XOR (HL) ; OVER 1 - ; OR : B6h --> OR (HL) ; PUTSPRITE - ; AND : A6h --> AND (HL) ; PUTMASK - nop ; Set to one of the values above -INVERSE_MODE: ; 00 -> NOP -> INVERSE 0 - nop ; 2F -> CPL -> INVERSE 1 - ld (hl), a - inc de - inc h ; Next line - djnz __PRCHAR - pop hl +MEM_FREE: +__MEM_FREE: ; Frees the block pointed by HL + ; HL DE BC & AF modified + PROC + LOCAL __MEM_LOOP2 + LOCAL __MEM_LINK_PREV + LOCAL __MEM_JOIN_TEST + LOCAL __MEM_BLOCK_JOIN + ld a, h + or l + ret z ; Return if NULL pointer + dec hl + dec hl + ld b, h + ld c, l ; BC = Block pointer + ld hl, ZXBASIC_MEM_HEAP ; This label point to the heap start +__MEM_LOOP2: inc hl - ld (DFCC), hl - ld hl, (DFCCL) ; current ATTR Pos - push hl - call __SET_ATTR - pop hl + inc hl ; Next block ptr + ld e, (hl) inc hl - ld (DFCCL),hl - exx - ret - ; ------------- SPECIAL CHARS (< 32) ----------------- -__PRINT_SPECIAL: ; Jumps here if it is a special char - ld hl, __PRINT_TABLE - jp JUMP_HL_PLUS_2A -PRINT_EOL: ; Called WHENEVER there is no ";" at end of PRINT sentence - exx -__PRINT_0Dh: ; Called WHEN printing CHR$(13) - ld hl, (S_POSN) - dec l - jr nz, 1f - dec h - jr nz, 1f - inc h - push hl - call __SCROLL_SCR - pop hl -#line 210 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -1: - ld l, 1 -__PRINT_EOL_END: - call SET_SCR_ADDR - exx - ret -__PRINT_COM: - exx + ld d, (hl) ; Block next ptr + ex de, hl ; DE = &(block->next); HL = block->next + ld a, h ; HL == NULL? + or l + jp z, __MEM_LINK_PREV; if so, link with previous + or a ; Clear carry flag + sbc hl, bc ; Carry if BC > HL => This block if before + add hl, bc ; Restores HL, preserving Carry flag + jp c, __MEM_LOOP2 ; This block is before. Keep searching PASS the block + ;------ At this point current HL is PAST BC, so we must link (DE) with BC, and HL in BC->next +__MEM_LINK_PREV: ; Link (DE) with BC, and BC->next with HL + ex de, hl push hl - push de - push bc - call PRINT_COMMA - pop bc - pop de + dec hl + ld (hl), c + inc hl + ld (hl), b ; (DE) <- BC + ld h, b ; HL <- BC (Free block ptr) + ld l, c + inc hl ; Skip block length (2 bytes) + inc hl + ld (hl), e ; Block->next = DE + inc hl + ld (hl), d + ; --- LINKED ; HL = &(BC->next) + 2 + call __MEM_JOIN_TEST pop hl - ret -__PRINT_TAB: - ld hl, __PRINT_TAB1 - jr __PRINT_SET_STATE -__PRINT_TAB1: - ld (MEM0), a - ld hl, __PRINT_TAB2 - jr __PRINT_SET_STATE -__PRINT_TAB2: - ld a, (MEM0) ; Load tab code (ignore the current one) - ld hl, __PRINT_START - ld (PRINT_JUMP_STATE), hl - exx - push hl - push bc - push de - call PRINT_TAB - pop de - pop bc +__MEM_JOIN_TEST: ; Checks for fragmented contiguous blocks and joins them + ; hl = Ptr to current block + 2 + ld d, (hl) + dec hl + ld e, (hl) + dec hl + ld b, (hl) ; Loads block length into BC + dec hl + ld c, (hl) ; + push hl ; Saves it for later + add hl, bc ; Adds its length. If HL == DE now, it must be joined + or a + sbc hl, de ; If Z, then HL == DE => We must join pop hl + ret nz +__MEM_BLOCK_JOIN: ; Joins current block (pointed by HL) with next one (pointed by DE). HL->length already in BC + push hl ; Saves it for later + ex de, hl + ld e, (hl) ; DE -> block->next->length + inc hl + ld d, (hl) + inc hl + ex de, hl ; DE = &(block->next) + add hl, bc ; HL = Total Length + ld b, h + ld c, l ; BC = Total Length + ex de, hl + ld e, (hl) + inc hl + ld d, (hl) ; DE = block->next + pop hl ; Recovers Pointer to block + ld (hl), c + inc hl + ld (hl), b ; Length Saved + inc hl + ld (hl), e + inc hl + ld (hl), d ; Next saved ret -__PRINT_AT: - ld hl, __PRINT_AT1 - jr __PRINT_SET_STATE -__PRINT_NOP: -__PRINT_RESTART: - ld hl, __PRINT_START -__PRINT_SET_STATE: - ld (PRINT_JUMP_STATE), hl ; Saves next entry call - exx - ret -__PRINT_AT1: ; Jumps here if waiting for 1st parameter - ld hl, (S_POSN) - ld h, a - ld a, SCR_ROWS - sub h - ld (S_POSN + 1), a - ld hl, __PRINT_AT2 - jr __PRINT_SET_STATE -__PRINT_AT2: - call __LOAD_S_POSN - ld e, a - call __SAVE_S_POSN - jr __PRINT_RESTART -__PRINT_DEL: - call __LOAD_S_POSN ; Gets current screen position - dec e - ld a, -1 - cp e - jr nz, 3f - ld e, SCR_COLS - 2 - dec d - cp d - jr nz, 3f - ld d, SCR_ROWS - 1 -3: - call __SAVE_S_POSN - exx - ret -__PRINT_INK: - ld hl, __PRINT_INK2 - jr __PRINT_SET_STATE -__PRINT_INK2: - call INK_TMP - jr __PRINT_RESTART -__PRINT_PAP: - ld hl, __PRINT_PAP2 - jr __PRINT_SET_STATE -__PRINT_PAP2: - call PAPER_TMP - jr __PRINT_RESTART -__PRINT_FLA: - ld hl, __PRINT_FLA2 - jr __PRINT_SET_STATE -__PRINT_FLA2: - call FLASH_TMP - jr __PRINT_RESTART -__PRINT_BRI: - ld hl, __PRINT_BRI2 - jr __PRINT_SET_STATE -__PRINT_BRI2: - call BRIGHT_TMP - jr __PRINT_RESTART -__PRINT_INV: - ld hl, __PRINT_INV2 - jr __PRINT_SET_STATE -__PRINT_INV2: - call INVERSE_TMP - jr __PRINT_RESTART -__PRINT_OVR: - ld hl, __PRINT_OVR2 - jr __PRINT_SET_STATE -__PRINT_OVR2: - call OVER_TMP - jr __PRINT_RESTART -__PRINT_BOLD: - ld hl, __PRINT_BOLD2 - jp __PRINT_SET_STATE -__PRINT_BOLD2: - call BOLD_TMP - jp __PRINT_RESTART -#line 354 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -__PRINT_ITA: - ld hl, __PRINT_ITA2 - jp __PRINT_SET_STATE -__PRINT_ITA2: - call ITALIC_TMP - jp __PRINT_RESTART -#line 364 "/zxbasic/src/arch/zx48k/library-asm/print.asm" - LOCAL __BOLD -__BOLD: - push hl - ld hl, MEM0 - ld b, 8 -1: - ld a, (de) - ld c, a - rlca - or c - ld (hl), a + ENDP + pop namespace +#line 84 "zx48k/strparam0.bas" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/loadstr.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/alloc.asm" +; vim: ts=4:et:sw=4: + ; Copyleft (K) by Jose M. Rodriguez de la Rosa + ; (a.k.a. Boriel) +; http://www.boriel.com + ; + ; This ASM library is licensed under the MIT license + ; you can use it for any purpose (even for commercial + ; closed source programs). + ; + ; Please read the MIT license on the internet + ; ----- IMPLEMENTATION NOTES ------ + ; The heap is implemented as a linked list of free blocks. +; Each free block contains this info: + ; + ; +----------------+ <-- HEAP START + ; | Size (2 bytes) | + ; | 0 | <-- Size = 0 => DUMMY HEADER BLOCK + ; +----------------+ + ; | Next (2 bytes) |---+ + ; +----------------+ <-+ + ; | Size (2 bytes) | + ; +----------------+ + ; | Next (2 bytes) |---+ + ; +----------------+ | + ; | | | <-- If Size > 4, then this contains (size - 4) bytes + ; | (0 if Size = 4)| | + ; +----------------+ <-+ + ; | Size (2 bytes) | + ; +----------------+ + ; | Next (2 bytes) |---+ + ; +----------------+ | + ; | | | + ; | (0 if Size = 4)| | + ; +----------------+ | + ; | <-- This zone is in use (Already allocated) + ; +----------------+ <-+ + ; | Size (2 bytes) | + ; +----------------+ + ; | Next (2 bytes) |---+ + ; +----------------+ | + ; | | | + ; | (0 if Size = 4)| | + ; +----------------+ <-+ + ; | Next (2 bytes) |--> NULL => END OF LIST + ; | 0 = NULL | + ; +----------------+ + ; | | + ; | (0 if Size = 4)| + ; +----------------+ + ; When a block is FREED, the previous and next pointers are examined to see + ; if we can defragment the heap. If the block to be freed is just next to the + ; previous, or to the next (or both) they will be converted into a single + ; block (so defragmented). + ; MEMORY MANAGER + ; + ; This library must be initialized calling __MEM_INIT with + ; HL = BLOCK Start & DE = Length. + ; An init directive is useful for initialization routines. + ; They will be added automatically if needed. + ; --------------------------------------------------------------------- + ; MEM_ALLOC + ; Allocates a block of memory in the heap. + ; + ; Parameters + ; BC = Length of requested memory block + ; +; Returns: + ; HL = Pointer to the allocated block in memory. Returns 0 (NULL) + ; if the block could not be allocated (out of memory) + ; --------------------------------------------------------------------- + push namespace core +MEM_ALLOC: +__MEM_ALLOC: ; Returns the 1st free block found of the given length (in BC) + PROC + LOCAL __MEM_LOOP + LOCAL __MEM_DONE + LOCAL __MEM_SUBTRACT + LOCAL __MEM_START + LOCAL TEMP, TEMP0 + TEMP EQU TEMP0 + 1 + ld hl, 0 + ld (TEMP), hl +__MEM_START: + ld hl, ZXBASIC_MEM_HEAP ; This label point to the heap start + inc bc + inc bc ; BC = BC + 2 ; block size needs 2 extra bytes for hidden pointer +__MEM_LOOP: ; Loads lengh at (HL, HL+). If Lenght >= BC, jump to __MEM_DONE + ld a, h ; HL = NULL (No memory available?) + or l +#line 113 "/zxbasic/src/arch/zx48k/library-asm/alloc.asm" + ret z ; NULL +#line 115 "/zxbasic/src/arch/zx48k/library-asm/alloc.asm" + ; HL = Pointer to Free block + ld e, (hl) inc hl - inc de - djnz 1b + ld d, (hl) + inc hl ; DE = Block Length + push hl ; HL = *pointer to -> next block + ex de, hl + or a ; CF = 0 + sbc hl, bc ; FREE >= BC (Length) (HL = BlockLength - Length) + jp nc, __MEM_DONE pop hl - ld de, MEM0 - ret -#line 385 "/zxbasic/src/arch/zx48k/library-asm/print.asm" - LOCAL __ITALIC -__ITALIC: - push hl - ld hl, MEM0 + ld (TEMP), hl ex de, hl - ld bc, 8 - ldir - ld hl, MEM0 - srl (hl) - inc hl - srl (hl) - inc hl - srl (hl) - inc hl - inc hl + ld e, (hl) inc hl - sla (hl) + ld d, (hl) + ex de, hl + jp __MEM_LOOP +__MEM_DONE: ; A free block has been found. + ; Check if at least 4 bytes remains free (HL >= 4) + push hl + exx ; exx to preserve bc + pop hl + ld bc, 4 + or a + sbc hl, bc + exx + jp nc, __MEM_SUBTRACT + ; At this point... + ; less than 4 bytes remains free. So we return this block entirely + ; We must link the previous block with the next to this one + ; (DE) => Pointer to next block + ; (TEMP) => &(previous->next) + pop hl ; Discard current block pointer + push de + ex de, hl ; DE = Previous block pointer; (HL) = Next block pointer + ld a, (hl) inc hl - sla (hl) + ld h, (hl) + ld l, a ; HL = (HL) + ex de, hl ; HL = Previous block pointer; DE = Next block pointer +TEMP0: + ld hl, 0 ; Pre-previous block pointer + ld (hl), e inc hl - sla (hl) - pop hl - ld de, MEM0 - ret -#line 413 "/zxbasic/src/arch/zx48k/library-asm/print.asm" - LOCAL __SCROLL_SCR -#line 487 "/zxbasic/src/arch/zx48k/library-asm/print.asm" - __SCROLL_SCR EQU 0DFEh ; Use ROM SCROLL -#line 489 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -#line 490 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -PRINT_COMMA: - call __LOAD_S_POSN - ld a, e - and 16 - add a, 16 -PRINT_TAB: - ; Tabulates the number of spaces in A register - ; If the current cursor position is already A, does nothing - PROC - LOCAL LOOP - call __LOAD_S_POSN ; e = current row - sub e - and 31 - ret z - ld b, a -LOOP: - ld a, ' ' - call __PRINTCHAR - djnz LOOP + ld (hl), d ; LINKED + pop hl ; Returning block. ret - ENDP -PRINT_AT: ; Changes cursor to ROW, COL - ; COL in A register - ; ROW in stack - pop hl ; Ret address - ex (sp), hl ; callee H = ROW - ld l, a +__MEM_SUBTRACT: + ; At this point we have to store HL value (Length - BC) into (DE - 2) ex de, hl - call __IN_SCREEN - ret nc ; Return if out of screen - jp __SAVE_S_POSN - LOCAL __PRINT_COM - LOCAL __PRINT_AT1 - LOCAL __PRINT_AT2 - LOCAL __PRINT_BOLD - LOCAL __PRINT_ITA - LOCAL __PRINT_INK - LOCAL __PRINT_PAP - LOCAL __PRINT_SET_STATE - LOCAL __PRINT_TABLE - LOCAL __PRINT_TAB, __PRINT_TAB1, __PRINT_TAB2 - LOCAL __PRINT_ITA2 -#line 546 "/zxbasic/src/arch/zx48k/library-asm/print.asm" - LOCAL __PRINT_BOLD2 -#line 552 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -__PRINT_TABLE: ; Jump table for 0 .. 22 codes - DW __PRINT_NOP ; 0 - DW __PRINT_NOP ; 1 - DW __PRINT_NOP ; 2 - DW __PRINT_NOP ; 3 - DW __PRINT_NOP ; 4 - DW __PRINT_NOP ; 5 - DW __PRINT_COM ; 6 COMMA - DW __PRINT_NOP ; 7 - DW __PRINT_DEL ; 8 DEL - DW __PRINT_NOP ; 9 - DW __PRINT_NOP ; 10 - DW __PRINT_NOP ; 11 - DW __PRINT_NOP ; 12 - DW __PRINT_0Dh ; 13 - DW __PRINT_BOLD ; 14 - DW __PRINT_ITA ; 15 - DW __PRINT_INK ; 16 - DW __PRINT_PAP ; 17 - DW __PRINT_FLA ; 18 - DW __PRINT_BRI ; 19 - DW __PRINT_INV ; 20 - DW __PRINT_OVR ; 21 - DW __PRINT_AT ; 22 AT - DW __PRINT_TAB ; 23 TAB + dec hl + ld (hl), d + dec hl + ld (hl), e ; Store new block length + add hl, de ; New length + DE => free-block start + pop de ; Remove previous HL off the stack + ld (hl), c ; Store length on its 1st word + inc hl + ld (hl), b + inc hl ; Return hl + ret ENDP pop namespace -#line 5 "/zxbasic/src/arch/zx48k/library-asm/print_eol_attr.asm" +#line 2 "/zxbasic/src/arch/zx48k/library-asm/loadstr.asm" + ; Loads a string (ptr) from HL + ; and duplicates it on dynamic memory again + ; Finally, it returns result pointer in HL push namespace core -PRINT_EOL_ATTR: - call PRINT_EOL - jp COPY_ATTR +__ILOADSTR: ; This is the indirect pointer entry HL = (HL) + ld a, h + or l + ret z + ld a, (hl) + inc hl + ld h, (hl) + ld l, a +__LOADSTR: ; __FASTCALL__ entry + ld a, h + or l + ret z ; Return if NULL + ld c, (hl) + inc hl + ld b, (hl) + dec hl ; BC = LEN(a$) + inc bc + inc bc ; BC = LEN(a$) + 2 (two bytes for length) + push hl + push bc + call __MEM_ALLOC + pop bc ; Recover length + pop de ; Recover origin + ld a, h + or l + ret z ; Return if NULL (No memory) + ex de, hl ; ldir takes HL as source, DE as destiny, so SWAP HL,DE + push de ; Saves destiny start + ldir ; Copies string (length number included) + pop hl ; Recovers destiny in hl as result + ret pop namespace -#line 84 "zx48k/strparam0.bas" +#line 85 "zx48k/strparam0.bas" #line 1 "/zxbasic/src/arch/zx48k/library-asm/printstr.asm" ; PRINT command routine ; Prints string pointed by HL @@ -1534,5 +1525,5 @@ __PRINT_STR: jp __PRINT_STR_LOOP ENDP pop namespace -#line 85 "zx48k/strparam0.bas" +#line 87 "zx48k/strparam0.bas" END diff --git a/tests/functional/zx48k/strparam2.asm b/tests/functional/zx48k/strparam2.asm index 056261194..e0786d53c 100644 --- a/tests/functional/zx48k/strparam2.asm +++ b/tests/functional/zx48k/strparam2.asm @@ -52,6 +52,7 @@ _test2: push ix ld ix, 0 add ix, sp + call .core.COPY_ATTR ld h, (ix+5) ld l, (ix+4) ld c, (hl) @@ -60,7 +61,7 @@ _test2: ld l, c xor a call .core.__PRINTSTR - call .core.PRINT_EOL_ATTR + call .core.PRINT_EOL _test2__leave: ld sp, ix pop ix @@ -95,9 +96,7 @@ _test__leave: DEFB 49h DEFB 43h ;; --- end of user code --- -#line 1 "/zxbasic/src/arch/zx48k/library-asm/print_eol_attr.asm" - ; Calls PRINT_EOL and then COPY_ATTR, so saves - ; 3 bytes +#line 1 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" #line 1 "/zxbasic/src/arch/zx48k/library-asm/print.asm" ; vim:ts=4:sw=4:et: ; PRINT command routine @@ -447,60 +446,6 @@ BRIGHT_TMP: #line 1 "/zxbasic/src/arch/zx48k/library-asm/over.asm" ; Sets OVER flag in P_FLAG permanently ; Parameter: OVER flag in bit 0 of A register -#line 1 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" -#line 4 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" - push namespace core -COPY_ATTR: - ; Just copies current permanent attribs into temporal attribs - ; and sets print mode - PROC - LOCAL INVERSE1 - LOCAL __REFRESH_TMP - INVERSE1 EQU 02Fh - ld hl, (ATTR_P) - ld (ATTR_T), hl - ld hl, FLAGS2 - call __REFRESH_TMP - ld hl, P_FLAG - call __REFRESH_TMP -__SET_ATTR_MODE: ; Another entry to set print modes. A contains (P_FLAG) - LOCAL TABLE - LOCAL CONT2 - rra ; Over bit to carry - ld a, (FLAGS2) - rla ; Over bit in bit 1, Over2 bit in bit 2 - and 3 ; Only bit 0 and 1 (OVER flag) - ld c, a - ld b, 0 - ld hl, TABLE - add hl, bc - ld a, (hl) - ld (PRINT_MODE), a - ld hl, (P_FLAG) - xor a ; NOP -> INVERSE0 - bit 2, l - jr z, CONT2 - ld a, INVERSE1 ; CPL -> INVERSE1 -CONT2: - ld (INVERSE_MODE), a - ret -TABLE: - nop ; NORMAL MODE - xor (hl) ; OVER 1 MODE - and (hl) ; OVER 2 MODE - or (hl) ; OVER 3 MODE -#line 67 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" -__REFRESH_TMP: - ld a, (hl) - and 0b10101010 - ld c, a - rra - or c - ld (hl), a - ret - ENDP - pop namespace -#line 4 "/zxbasic/src/arch/zx48k/library-asm/over.asm" push namespace core OVER: PROC @@ -742,11 +687,10 @@ INVERSE_MODE: ; 00 -> NOP -> INVERSE 0 inc hl ld (DFCC), hl ld hl, (DFCCL) ; current ATTR Pos - push hl - call __SET_ATTR - pop hl inc hl - ld (DFCCL),hl + ld (DFCCL), hl + dec hl + call __SET_ATTR exx ret ; ------------- SPECIAL CHARS (< 32) ----------------- @@ -765,7 +709,7 @@ __PRINT_0Dh: ; Called WHEN printing CHR$(13) push hl call __SCROLL_SCR pop hl -#line 210 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 209 "/zxbasic/src/arch/zx48k/library-asm/print.asm" 1: ld l, 1 __PRINT_EOL_END: @@ -882,14 +826,14 @@ __PRINT_BOLD: __PRINT_BOLD2: call BOLD_TMP jp __PRINT_RESTART -#line 354 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 353 "/zxbasic/src/arch/zx48k/library-asm/print.asm" __PRINT_ITA: ld hl, __PRINT_ITA2 jp __PRINT_SET_STATE __PRINT_ITA2: call ITALIC_TMP jp __PRINT_RESTART -#line 364 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 363 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __BOLD __BOLD: push hl @@ -907,7 +851,7 @@ __BOLD: pop hl ld de, MEM0 ret -#line 385 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 384 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __ITALIC __ITALIC: push hl @@ -932,12 +876,12 @@ __ITALIC: pop hl ld de, MEM0 ret -#line 413 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 412 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __SCROLL_SCR -#line 487 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 486 "/zxbasic/src/arch/zx48k/library-asm/print.asm" __SCROLL_SCR EQU 0DFEh ; Use ROM SCROLL +#line 488 "/zxbasic/src/arch/zx48k/library-asm/print.asm" #line 489 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -#line 490 "/zxbasic/src/arch/zx48k/library-asm/print.asm" PRINT_COMMA: call __LOAD_S_POSN ld a, e @@ -980,9 +924,9 @@ PRINT_AT: ; Changes cursor to ROW, COL LOCAL __PRINT_TABLE LOCAL __PRINT_TAB, __PRINT_TAB1, __PRINT_TAB2 LOCAL __PRINT_ITA2 -#line 546 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 545 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __PRINT_BOLD2 -#line 552 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 551 "/zxbasic/src/arch/zx48k/library-asm/print.asm" __PRINT_TABLE: ; Jump table for 0 .. 22 codes DW __PRINT_NOP ; 0 DW __PRINT_NOP ; 1 @@ -1010,13 +954,60 @@ __PRINT_TABLE: ; Jump table for 0 .. 22 codes DW __PRINT_TAB ; 23 TAB ENDP pop namespace -#line 5 "/zxbasic/src/arch/zx48k/library-asm/print_eol_attr.asm" +#line 3 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" +#line 4 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" push namespace core -PRINT_EOL_ATTR: - call PRINT_EOL - jp COPY_ATTR +COPY_ATTR: + ; Just copies current permanent attribs into temporal attribs + ; and sets print mode + PROC + LOCAL INVERSE1 + LOCAL __REFRESH_TMP + INVERSE1 EQU 02Fh + ld hl, (ATTR_P) + ld (ATTR_T), hl + ld hl, FLAGS2 + call __REFRESH_TMP + ld hl, P_FLAG + call __REFRESH_TMP +__SET_ATTR_MODE: ; Another entry to set print modes. A contains (P_FLAG) + LOCAL TABLE + LOCAL CONT2 + rra ; Over bit to carry + ld a, (FLAGS2) + rla ; Over bit in bit 1, Over2 bit in bit 2 + and 3 ; Only bit 0 and 1 (OVER flag) + ld c, a + ld b, 0 + ld hl, TABLE + add hl, bc + ld a, (hl) + ld (PRINT_MODE), a + ld hl, (P_FLAG) + xor a ; NOP -> INVERSE0 + bit 2, l + jr z, CONT2 + ld a, INVERSE1 ; CPL -> INVERSE1 +CONT2: + ld (INVERSE_MODE), a + ret +TABLE: + nop ; NORMAL MODE + xor (hl) ; OVER 1 MODE + and (hl) ; OVER 2 MODE + or (hl) ; OVER 3 MODE +#line 67 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" +__REFRESH_TMP: + ld a, (hl) + and 0b10101010 + ld c, a + rra + or c + ld (hl), a + ret + ENDP pop namespace -#line 69 "zx48k/strparam2.bas" +#line 70 "zx48k/strparam2.bas" #line 1 "/zxbasic/src/arch/zx48k/library-asm/printstr.asm" #line 1 "/zxbasic/src/arch/zx48k/library-asm/free.asm" ; vim: ts=4:et:sw=4: @@ -1327,7 +1318,7 @@ __PRINT_STR: jp __PRINT_STR_LOOP ENDP pop namespace -#line 70 "zx48k/strparam2.bas" +#line 72 "zx48k/strparam2.bas" #line 1 "/zxbasic/src/arch/zx48k/library-asm/storestr.asm" ; vim:ts=4:et:sw=4 ; Stores value of current string pointed by DE register into address pointed by HL @@ -1734,5 +1725,5 @@ __STORE_STR: pop hl ; Returns ptr to b$ in HL (Caller might needed to free it from memory) ret pop namespace -#line 71 "zx48k/strparam2.bas" +#line 73 "zx48k/strparam2.bas" END diff --git a/tests/functional/zx48k/strparam3.asm b/tests/functional/zx48k/strparam3.asm index a6d69bb03..d10fba6ea 100644 --- a/tests/functional/zx48k/strparam3.asm +++ b/tests/functional/zx48k/strparam3.asm @@ -48,6 +48,7 @@ _test2: push ix ld ix, 0 add ix, sp + call .core.COPY_ATTR ld h, (ix+5) ld l, (ix+4) ld c, (hl) @@ -56,7 +57,7 @@ _test2: ld l, c xor a call .core.__PRINTSTR - call .core.PRINT_EOL_ATTR + call .core.PRINT_EOL _test2__leave: ld sp, ix pop ix @@ -100,334 +101,42 @@ _test__leave: DEFB 49h DEFB 43h ;; --- end of user code --- -#line 1 "/zxbasic/src/arch/zx48k/library-asm/free.asm" -; vim: ts=4:et:sw=4: - ; Copyleft (K) by Jose M. Rodriguez de la Rosa - ; (a.k.a. Boriel) -; http://www.boriel.com - ; - ; This ASM library is licensed under the BSD license - ; you can use it for any purpose (even for commercial - ; closed source programs). - ; - ; Please read the BSD license on the internet - ; ----- IMPLEMENTATION NOTES ------ - ; The heap is implemented as a linked list of free blocks. -; Each free block contains this info: - ; - ; +----------------+ <-- HEAP START - ; | Size (2 bytes) | - ; | 0 | <-- Size = 0 => DUMMY HEADER BLOCK - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ <-+ - ; | Size (2 bytes) | - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ | - ; | | | <-- If Size > 4, then this contains (size - 4) bytes - ; | (0 if Size = 4)| | - ; +----------------+ <-+ - ; | Size (2 bytes) | - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ | - ; | | | - ; | (0 if Size = 4)| | - ; +----------------+ | - ; | <-- This zone is in use (Already allocated) - ; +----------------+ <-+ - ; | Size (2 bytes) | - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ | - ; | | | - ; | (0 if Size = 4)| | - ; +----------------+ <-+ - ; | Next (2 bytes) |--> NULL => END OF LIST - ; | 0 = NULL | - ; +----------------+ - ; | | - ; | (0 if Size = 4)| - ; +----------------+ - ; When a block is FREED, the previous and next pointers are examined to see - ; if we can defragment the heap. If the block to be breed is just next to the - ; previous, or to the next (or both) they will be converted into a single - ; block (so defragmented). - ; MEMORY MANAGER - ; - ; This library must be initialized calling __MEM_INIT with - ; HL = BLOCK Start & DE = Length. - ; An init directive is useful for initialization routines. - ; They will be added automatically if needed. -#line 1 "/zxbasic/src/arch/zx48k/library-asm/heapinit.asm" -; vim: ts=4:et:sw=4: - ; Copyleft (K) by Jose M. Rodriguez de la Rosa - ; (a.k.a. Boriel) -; http://www.boriel.com - ; - ; This ASM library is licensed under the BSD license - ; you can use it for any purpose (even for commercial - ; closed source programs). - ; - ; Please read the BSD license on the internet - ; ----- IMPLEMENTATION NOTES ------ - ; The heap is implemented as a linked list of free blocks. -; Each free block contains this info: - ; - ; +----------------+ <-- HEAP START - ; | Size (2 bytes) | - ; | 0 | <-- Size = 0 => DUMMY HEADER BLOCK - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ <-+ - ; | Size (2 bytes) | - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ | - ; | | | <-- If Size > 4, then this contains (size - 4) bytes - ; | (0 if Size = 4)| | - ; +----------------+ <-+ - ; | Size (2 bytes) | - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ | - ; | | | - ; | (0 if Size = 4)| | - ; +----------------+ | - ; | <-- This zone is in use (Already allocated) - ; +----------------+ <-+ - ; | Size (2 bytes) | - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ | - ; | | | - ; | (0 if Size = 4)| | - ; +----------------+ <-+ - ; | Next (2 bytes) |--> NULL => END OF LIST - ; | 0 = NULL | - ; +----------------+ - ; | | - ; | (0 if Size = 4)| - ; +----------------+ - ; When a block is FREED, the previous and next pointers are examined to see - ; if we can defragment the heap. If the block to be breed is just next to the - ; previous, or to the next (or both) they will be converted into a single - ; block (so defragmented). - ; MEMORY MANAGER - ; - ; This library must be initialized calling __MEM_INIT with - ; HL = BLOCK Start & DE = Length. - ; An init directive is useful for initialization routines. - ; They will be added automatically if needed. - ; --------------------------------------------------------------------- - ; __MEM_INIT must be called to initalize this library with the - ; standard parameters - ; --------------------------------------------------------------------- - push namespace core -__MEM_INIT: ; Initializes the library using (RAMTOP) as start, and - ld hl, ZXBASIC_MEM_HEAP ; Change this with other address of heap start - ld de, ZXBASIC_HEAP_SIZE ; Change this with your size - ; --------------------------------------------------------------------- - ; __MEM_INIT2 initalizes this library -; Parameters: -; HL : Memory address of 1st byte of the memory heap -; DE : Length in bytes of the Memory Heap - ; --------------------------------------------------------------------- -__MEM_INIT2: - ; HL as TOP - PROC - dec de - dec de - dec de - dec de ; DE = length - 4; HL = start - ; This is done, because we require 4 bytes for the empty dummy-header block - xor a - ld (hl), a - inc hl - ld (hl), a ; First "free" block is a header: size=0, Pointer=&(Block) + 4 - inc hl - ld b, h - ld c, l - inc bc - inc bc ; BC = starts of next block - ld (hl), c - inc hl - ld (hl), b - inc hl ; Pointer to next block - ld (hl), e - inc hl - ld (hl), d - inc hl ; Block size (should be length - 4 at start); This block contains all the available memory - ld (hl), a ; NULL (0000h) ; No more blocks (a list with a single block) - inc hl - ld (hl), a - ld a, 201 - ld (__MEM_INIT), a; "Pokes" with a RET so ensure this routine is not called again - ret - ENDP - pop namespace -#line 69 "/zxbasic/src/arch/zx48k/library-asm/free.asm" - ; --------------------------------------------------------------------- - ; MEM_FREE - ; Frees a block of memory - ; -; Parameters: - ; HL = Pointer to the block to be freed. If HL is NULL (0) nothing - ; is done - ; --------------------------------------------------------------------- - push namespace core -MEM_FREE: -__MEM_FREE: ; Frees the block pointed by HL - ; HL DE BC & AF modified - PROC - LOCAL __MEM_LOOP2 - LOCAL __MEM_LINK_PREV - LOCAL __MEM_JOIN_TEST - LOCAL __MEM_BLOCK_JOIN - ld a, h - or l - ret z ; Return if NULL pointer - dec hl - dec hl - ld b, h - ld c, l ; BC = Block pointer - ld hl, ZXBASIC_MEM_HEAP ; This label point to the heap start -__MEM_LOOP2: - inc hl - inc hl ; Next block ptr - ld e, (hl) - inc hl - ld d, (hl) ; Block next ptr - ex de, hl ; DE = &(block->next); HL = block->next - ld a, h ; HL == NULL? - or l - jp z, __MEM_LINK_PREV; if so, link with previous - or a ; Clear carry flag - sbc hl, bc ; Carry if BC > HL => This block if before - add hl, bc ; Restores HL, preserving Carry flag - jp c, __MEM_LOOP2 ; This block is before. Keep searching PASS the block - ;------ At this point current HL is PAST BC, so we must link (DE) with BC, and HL in BC->next -__MEM_LINK_PREV: ; Link (DE) with BC, and BC->next with HL - ex de, hl - push hl - dec hl - ld (hl), c - inc hl - ld (hl), b ; (DE) <- BC - ld h, b ; HL <- BC (Free block ptr) - ld l, c - inc hl ; Skip block length (2 bytes) - inc hl - ld (hl), e ; Block->next = DE - inc hl - ld (hl), d - ; --- LINKED ; HL = &(BC->next) + 2 - call __MEM_JOIN_TEST - pop hl -__MEM_JOIN_TEST: ; Checks for fragmented contiguous blocks and joins them - ; hl = Ptr to current block + 2 - ld d, (hl) - dec hl - ld e, (hl) - dec hl - ld b, (hl) ; Loads block length into BC - dec hl - ld c, (hl) ; - push hl ; Saves it for later - add hl, bc ; Adds its length. If HL == DE now, it must be joined - or a - sbc hl, de ; If Z, then HL == DE => We must join - pop hl - ret nz -__MEM_BLOCK_JOIN: ; Joins current block (pointed by HL) with next one (pointed by DE). HL->length already in BC - push hl ; Saves it for later - ex de, hl - ld e, (hl) ; DE -> block->next->length - inc hl - ld d, (hl) - inc hl - ex de, hl ; DE = &(block->next) - add hl, bc ; HL = Total Length - ld b, h - ld c, l ; BC = Total Length - ex de, hl - ld e, (hl) - inc hl - ld d, (hl) ; DE = block->next - pop hl ; Recovers Pointer to block - ld (hl), c - inc hl - ld (hl), b ; Length Saved - inc hl - ld (hl), e - inc hl - ld (hl), d ; Next saved - ret - ENDP - pop namespace -#line 76 "zx48k/strparam3.bas" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/loadstr.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/alloc.asm" -; vim: ts=4:et:sw=4: - ; Copyleft (K) by Jose M. Rodriguez de la Rosa - ; (a.k.a. Boriel) -; http://www.boriel.com - ; - ; This ASM library is licensed under the MIT license - ; you can use it for any purpose (even for commercial - ; closed source programs). - ; - ; Please read the MIT license on the internet - ; ----- IMPLEMENTATION NOTES ------ - ; The heap is implemented as a linked list of free blocks. -; Each free block contains this info: - ; - ; +----------------+ <-- HEAP START - ; | Size (2 bytes) | - ; | 0 | <-- Size = 0 => DUMMY HEADER BLOCK - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ <-+ - ; | Size (2 bytes) | - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ | - ; | | | <-- If Size > 4, then this contains (size - 4) bytes - ; | (0 if Size = 4)| | - ; +----------------+ <-+ - ; | Size (2 bytes) | - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ | - ; | | | - ; | (0 if Size = 4)| | - ; +----------------+ | - ; | <-- This zone is in use (Already allocated) - ; +----------------+ <-+ - ; | Size (2 bytes) | - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ | - ; | | | - ; | (0 if Size = 4)| | - ; +----------------+ <-+ - ; | Next (2 bytes) |--> NULL => END OF LIST - ; | 0 = NULL | - ; +----------------+ - ; | | - ; | (0 if Size = 4)| - ; +----------------+ - ; When a block is FREED, the previous and next pointers are examined to see - ; if we can defragment the heap. If the block to be freed is just next to the - ; previous, or to the next (or both) they will be converted into a single - ; block (so defragmented). - ; MEMORY MANAGER - ; - ; This library must be initialized calling __MEM_INIT with - ; HL = BLOCK Start & DE = Length. - ; An init directive is useful for initialization routines. - ; They will be added automatically if needed. +#line 1 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +; vim:ts=4:sw=4:et: + ; PRINT command routine + ; Does not print attribute. Use PRINT_STR or PRINT_NUM for that +#line 1 "/zxbasic/src/arch/zx48k/library-asm/sposn.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/sysvars.asm" + ;; ----------------------------------------------------------------------- + ;; ZX Basic System Vars + ;; Some of them will be mapped over Sinclair ROM ones for compatibility + ;; ----------------------------------------------------------------------- + push namespace core +SCREEN_ADDR: DW 16384 ; Screen address (can be pointed to other place to use a screen buffer) +SCREEN_ATTR_ADDR: DW 22528 ; Screen attribute address (ditto.) + ; These are mapped onto ZX Spectrum ROM VARS + CHARS EQU 23606 ; Pointer to ROM/RAM Charset + TVFLAGS EQU 23612 ; TV Flags + UDG EQU 23675 ; Pointer to UDG Charset + COORDS EQU 23677 ; Last PLOT coordinates + FLAGS2 EQU 23681 ; + ECHO_E EQU 23682 ; + DFCC EQU 23684 ; Next screen addr for PRINT + DFCCL EQU 23686 ; Next screen attr for PRINT + S_POSN EQU 23688 + ATTR_P EQU 23693 ; Current Permanent ATTRS set with INK, PAPER, etc commands + ATTR_T EQU 23695 ; temporary ATTRIBUTES + P_FLAG EQU 23697 ; + MEM0 EQU 23698 ; Temporary memory buffer used by ROM chars + SCR_COLS EQU 33 ; Screen with in columns + 1 + SCR_ROWS EQU 24 ; Screen height in rows + SCR_SIZE EQU (SCR_ROWS << 8) + SCR_COLS + pop namespace +#line 2 "/zxbasic/src/arch/zx48k/library-asm/sposn.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/attr.asm" + ; Attribute routines +; vim:ts=4:et:sw: #line 1 "/zxbasic/src/arch/zx48k/library-asm/error.asm" ; Simple error control routines ; vim:ts=4:et: @@ -462,460 +171,795 @@ __STOP: ld (ERR_NR), a ret pop namespace -#line 69 "/zxbasic/src/arch/zx48k/library-asm/alloc.asm" - ; --------------------------------------------------------------------- - ; MEM_ALLOC - ; Allocates a block of memory in the heap. - ; - ; Parameters - ; BC = Length of requested memory block - ; -; Returns: - ; HL = Pointer to the allocated block in memory. Returns 0 (NULL) - ; if the block could not be allocated (out of memory) - ; --------------------------------------------------------------------- +#line 6 "/zxbasic/src/arch/zx48k/library-asm/attr.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/in_screen.asm" push namespace core -MEM_ALLOC: -__MEM_ALLOC: ; Returns the 1st free block found of the given length (in BC) +__IN_SCREEN: + ; Returns NO carry if current coords (D, E) + ; are OUT of the screen limits PROC - LOCAL __MEM_LOOP - LOCAL __MEM_DONE - LOCAL __MEM_SUBTRACT - LOCAL __MEM_START - LOCAL TEMP, TEMP0 - TEMP EQU TEMP0 + 1 - ld hl, 0 - ld (TEMP), hl -__MEM_START: - ld hl, ZXBASIC_MEM_HEAP ; This label point to the heap start - inc bc - inc bc ; BC = BC + 2 ; block size needs 2 extra bytes for hidden pointer -__MEM_LOOP: ; Loads lengh at (HL, HL+). If Lenght >= BC, jump to __MEM_DONE - ld a, h ; HL = NULL (No memory available?) - or l -#line 113 "/zxbasic/src/arch/zx48k/library-asm/alloc.asm" - ret z ; NULL -#line 115 "/zxbasic/src/arch/zx48k/library-asm/alloc.asm" - ; HL = Pointer to Free block - ld e, (hl) - inc hl - ld d, (hl) - inc hl ; DE = Block Length - push hl ; HL = *pointer to -> next block - ex de, hl - or a ; CF = 0 - sbc hl, bc ; FREE >= BC (Length) (HL = BlockLength - Length) - jp nc, __MEM_DONE - pop hl - ld (TEMP), hl + LOCAL __IN_SCREEN_ERR + ld hl, SCR_SIZE + ld a, e + cp l + jr nc, __IN_SCREEN_ERR ; Do nothing and return if out of range + ld a, d + cp h + ret c ; Return if carry (OK) +__IN_SCREEN_ERR: +__OUT_OF_SCREEN_ERR: + ; Jumps here if out of screen + ld a, ERROR_OutOfScreen + jp __STOP ; Saves error code and exits + ENDP + pop namespace +#line 7 "/zxbasic/src/arch/zx48k/library-asm/attr.asm" + push namespace core +__ATTR_ADDR: + ; calc start address in DE (as (32 * d) + e) + ; Contributed by Santiago Romero at http://www.speccy.org + ld h, 0 ; 7 T-States + ld a, d ; 4 T-States + ld d, h + add a, a ; a * 2 ; 4 T-States + add a, a ; a * 4 ; 4 T-States + ld l, a ; HL = A * 4 ; 4 T-States + add hl, hl ; HL = A * 8 ; 15 T-States + add hl, hl ; HL = A * 16 ; 15 T-States + add hl, hl ; HL = A * 32 ; 15 T-States + add hl, de + ld de, (SCREEN_ATTR_ADDR) ; Adds the screen address + add hl, de + ; Return current screen address in HL + ret + ; Sets the attribute at a given screen coordinate (D, E). + ; The attribute is taken from the ATTR_T memory variable + ; Used by PRINT routines +SET_ATTR: + ; Checks for valid coords + call __IN_SCREEN + ret nc + call __ATTR_ADDR +__SET_ATTR: + ; Internal __FASTCALL__ Entry used by printing routines + ; HL contains the address of the ATTR cell to set + PROC +__SET_ATTR2: ; Sets attr from ATTR_T to (HL) which points to the scr address + ld de, (ATTR_T) ; E = ATTR_T, D = MASK_T + ld a, d + and (hl) + ld c, a ; C = current screen color, masked + ld a, d + cpl ; Negate mask + and e ; Mask current attributes + or c ; Mix them + ld (hl), a ; Store result in screen + ret + ENDP + pop namespace +#line 3 "/zxbasic/src/arch/zx48k/library-asm/sposn.asm" + ; Printing positioning library. + push namespace core + ; Loads into DE current ROW, COL print position from S_POSN mem var. +__LOAD_S_POSN: + PROC + ld de, (S_POSN) + ld hl, SCR_SIZE + or a + sbc hl, de ex de, hl + ret + ENDP + ; Saves ROW, COL from DE into S_POSN mem var. +__SAVE_S_POSN: + PROC + ld hl, SCR_SIZE + or a + sbc hl, de + ld (S_POSN), hl ; saves it again +__SET_SCR_PTR: ;; Fast + push de + call __ATTR_ADDR + ld (DFCCL), hl + pop de + ld a, d + ld c, a ; Saves it for later + and 0F8h ; Masks 3 lower bit ; zy + ld d, a + ld a, c ; Recovers it + and 07h ; MOD 7 ; y1 + rrca + rrca + rrca + or e + ld e, a + ld hl, (SCREEN_ADDR) + add hl, de ; HL = Screen address + DE + ld (DFCC), hl + ret + ENDP + pop namespace +#line 6 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/table_jump.asm" + push namespace core +JUMP_HL_PLUS_2A: ; Does JP (HL + A*2) Modifies DE. Modifies A + add a, a +JUMP_HL_PLUS_A: ; Does JP (HL + A) Modifies DE + ld e, a + ld d, 0 +JUMP_HL_PLUS_DE: ; Does JP (HL + DE) + add hl, de ld e, (hl) inc hl ld d, (hl) ex de, hl - jp __MEM_LOOP -__MEM_DONE: ; A free block has been found. - ; Check if at least 4 bytes remains free (HL >= 4) - push hl - exx ; exx to preserve bc - pop hl - ld bc, 4 +CALL_HL: + jp (hl) + pop namespace +#line 8 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/ink.asm" + ; Sets ink color in ATTR_P permanently +; Parameter: Paper color in A register + push namespace core +INK: + PROC + LOCAL __SET_INK + LOCAL __SET_INK2 + ld de, ATTR_P +__SET_INK: + cp 8 + jr nz, __SET_INK2 + inc de ; Points DE to MASK_T or MASK_P + ld a, (de) + or 7 ; Set bits 0,1,2 to enable transparency + ld (de), a + ret +__SET_INK2: + ; Another entry. This will set the ink color at location pointer by DE + and 7 ; # Gets color mod 8 + ld b, a ; Saves the color + ld a, (de) + and 0F8h ; Clears previous value + or b + ld (de), a + inc de ; Points DE to MASK_T or MASK_P + ld a, (de) + and 0F8h ; Reset bits 0,1,2 sign to disable transparency + ld (de), a ; Store new attr + ret + ; Sets the INK color passed in A register in the ATTR_T variable +INK_TMP: + ld de, ATTR_T + jp __SET_INK + ENDP + pop namespace +#line 9 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/paper.asm" + ; Sets paper color in ATTR_P permanently +; Parameter: Paper color in A register + push namespace core +PAPER: + PROC + LOCAL __SET_PAPER + LOCAL __SET_PAPER2 + ld de, ATTR_P +__SET_PAPER: + cp 8 + jr nz, __SET_PAPER2 + inc de + ld a, (de) + or 038h + ld (de), a + ret + ; Another entry. This will set the paper color at location pointer by DE +__SET_PAPER2: + and 7 ; # Remove + rlca + rlca + rlca ; a *= 8 + ld b, a ; Saves the color + ld a, (de) + and 0C7h ; Clears previous value + or b + ld (de), a + inc de ; Points to MASK_T or MASK_P accordingly + ld a, (de) + and 0C7h ; Resets bits 3,4,5 + ld (de), a + ret + ; Sets the PAPER color passed in A register in the ATTR_T variable +PAPER_TMP: + ld de, ATTR_T + jp __SET_PAPER + ENDP + pop namespace +#line 10 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/flash.asm" + ; Sets flash flag in ATTR_P permanently +; Parameter: Paper color in A register + push namespace core +FLASH: + ld hl, ATTR_P + PROC + LOCAL IS_TR + LOCAL IS_ZERO +__SET_FLASH: + ; Another entry. This will set the flash flag at location pointer by DE + cp 8 + jr z, IS_TR + ; # Convert to 0/1 or a - sbc hl, bc - exx - jp nc, __MEM_SUBTRACT - ; At this point... - ; less than 4 bytes remains free. So we return this block entirely - ; We must link the previous block with the next to this one - ; (DE) => Pointer to next block - ; (TEMP) => &(previous->next) - pop hl ; Discard current block pointer - push de - ex de, hl ; DE = Previous block pointer; (HL) = Next block pointer + jr z, IS_ZERO + ld a, 0x80 +IS_ZERO: + ld b, a ; Saves the color ld a, (hl) + and 07Fh ; Clears previous value + or b + ld (hl), a inc hl - ld h, (hl) - ld l, a ; HL = (HL) - ex de, hl ; HL = Previous block pointer; DE = Next block pointer -TEMP0: - ld hl, 0 ; Pre-previous block pointer - ld (hl), e - inc hl - ld (hl), d ; LINKED - pop hl ; Returning block. + res 7, (hl) ;Reset bit 7 to disable transparency ret -__MEM_SUBTRACT: - ; At this point we have to store HL value (Length - BC) into (DE - 2) - ex de, hl - dec hl - ld (hl), d - dec hl - ld (hl), e ; Store new block length - add hl, de ; New length + DE => free-block start - pop de ; Remove previous HL off the stack - ld (hl), c ; Store length on its 1st word - inc hl - ld (hl), b - inc hl ; Return hl +IS_TR: ; transparent + inc hl ; Points DE to MASK_T or MASK_P + set 7, (hl) ;Set bit 7 to enable transparency ret + ; Sets the FLASH flag passed in A register in the ATTR_T variable +FLASH_TMP: + ld hl, ATTR_T + jr __SET_FLASH ENDP pop namespace -#line 2 "/zxbasic/src/arch/zx48k/library-asm/loadstr.asm" - ; Loads a string (ptr) from HL - ; and duplicates it on dynamic memory again - ; Finally, it returns result pointer in HL +#line 11 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/bright.asm" + ; Sets bright flag in ATTR_P permanently +; Parameter: Paper color in A register push namespace core -__ILOADSTR: ; This is the indirect pointer entry HL = (HL) - ld a, h - or l - ret z +BRIGHT: + ld hl, ATTR_P + PROC + LOCAL IS_TR + LOCAL IS_ZERO +__SET_BRIGHT: + ; Another entry. This will set the bright flag at location pointer by DE + cp 8 + jr z, IS_TR + ; # Convert to 0/1 + or a + jr z, IS_ZERO + ld a, 0x40 +IS_ZERO: + ld b, a ; Saves the color ld a, (hl) + and 0BFh ; Clears previous value + or b + ld (hl), a inc hl - ld h, (hl) - ld l, a -__LOADSTR: ; __FASTCALL__ entry - ld a, h - or l - ret z ; Return if NULL - ld c, (hl) - inc hl - ld b, (hl) - dec hl ; BC = LEN(a$) - inc bc - inc bc ; BC = LEN(a$) + 2 (two bytes for length) - push hl - push bc - call __MEM_ALLOC - pop bc ; Recover length - pop de ; Recover origin - ld a, h - or l - ret z ; Return if NULL (No memory) - ex de, hl ; ldir takes HL as source, DE as destiny, so SWAP HL,DE - push de ; Saves destiny start - ldir ; Copies string (length number included) - pop hl ; Recovers destiny in hl as result + res 6, (hl) ;Reset bit 6 to disable transparency + ret +IS_TR: ; transparent + inc hl ; Points DE to MASK_T or MASK_P + set 6, (hl) ;Set bit 6 to enable transparency ret + ; Sets the BRIGHT flag passed in A register in the ATTR_T variable +BRIGHT_TMP: + ld hl, ATTR_T + jr __SET_BRIGHT + ENDP pop namespace -#line 77 "zx48k/strparam3.bas" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/print_eol_attr.asm" - ; Calls PRINT_EOL and then COPY_ATTR, so saves - ; 3 bytes -#line 1 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -; vim:ts=4:sw=4:et: - ; PRINT command routine - ; Does not print attribute. Use PRINT_STR or PRINT_NUM for that -#line 1 "/zxbasic/src/arch/zx48k/library-asm/sposn.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/sysvars.asm" - ;; ----------------------------------------------------------------------- - ;; ZX Basic System Vars - ;; Some of them will be mapped over Sinclair ROM ones for compatibility - ;; ----------------------------------------------------------------------- - push namespace core -SCREEN_ADDR: DW 16384 ; Screen address (can be pointed to other place to use a screen buffer) -SCREEN_ATTR_ADDR: DW 22528 ; Screen attribute address (ditto.) - ; These are mapped onto ZX Spectrum ROM VARS - CHARS EQU 23606 ; Pointer to ROM/RAM Charset - TVFLAGS EQU 23612 ; TV Flags - UDG EQU 23675 ; Pointer to UDG Charset - COORDS EQU 23677 ; Last PLOT coordinates - FLAGS2 EQU 23681 ; - ECHO_E EQU 23682 ; - DFCC EQU 23684 ; Next screen addr for PRINT - DFCCL EQU 23686 ; Next screen attr for PRINT - S_POSN EQU 23688 - ATTR_P EQU 23693 ; Current Permanent ATTRS set with INK, PAPER, etc commands - ATTR_T EQU 23695 ; temporary ATTRIBUTES - P_FLAG EQU 23697 ; - MEM0 EQU 23698 ; Temporary memory buffer used by ROM chars - SCR_COLS EQU 33 ; Screen with in columns + 1 - SCR_ROWS EQU 24 ; Screen height in rows - SCR_SIZE EQU (SCR_ROWS << 8) + SCR_COLS - pop namespace -#line 2 "/zxbasic/src/arch/zx48k/library-asm/sposn.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/attr.asm" - ; Attribute routines -; vim:ts=4:et:sw: -#line 1 "/zxbasic/src/arch/zx48k/library-asm/in_screen.asm" +#line 12 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/over.asm" + ; Sets OVER flag in P_FLAG permanently +; Parameter: OVER flag in bit 0 of A register push namespace core -__IN_SCREEN: - ; Returns NO carry if current coords (D, E) - ; are OUT of the screen limits +OVER: PROC - LOCAL __IN_SCREEN_ERR - ld hl, SCR_SIZE - ld a, e - cp l - jr nc, __IN_SCREEN_ERR ; Do nothing and return if out of range - ld a, d - cp h - ret c ; Return if carry (OK) -__IN_SCREEN_ERR: -__OUT_OF_SCREEN_ERR: - ; Jumps here if out of screen - ld a, ERROR_OutOfScreen - jp __STOP ; Saves error code and exits + ld c, a ; saves it for later + and 2 + ld hl, FLAGS2 + res 1, (HL) + or (hl) + ld (hl), a + ld a, c ; Recovers previous value + and 1 ; # Convert to 0/1 + add a, a; # Shift left 1 bit for permanent + ld hl, P_FLAG + res 1, (hl) + or (hl) + ld (hl), a + ret + ; Sets OVER flag in P_FLAG temporarily +OVER_TMP: + ld c, a ; saves it for later + and 2 ; gets bit 1; clears carry + rra + ld hl, FLAGS2 + res 0, (hl) + or (hl) + ld (hl), a + ld a, c ; Recovers previous value + and 1 + ld hl, P_FLAG + res 0, (hl) + or (hl) + ld (hl), a + jp __SET_ATTR_MODE + ENDP + pop namespace +#line 13 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/inverse.asm" + ; Sets INVERSE flag in P_FLAG permanently +; Parameter: INVERSE flag in bit 0 of A register + push namespace core +INVERSE: + PROC + and 1 ; # Convert to 0/1 + add a, a; # Shift left 3 bits for permanent + add a, a + add a, a + ld hl, P_FLAG + res 3, (hl) + or (hl) + ld (hl), a + ret + ; Sets INVERSE flag in P_FLAG temporarily +INVERSE_TMP: + and 1 + add a, a + add a, a; # Shift left 2 bits for temporary + ld hl, P_FLAG + res 2, (hl) + or (hl) + ld (hl), a + jp __SET_ATTR_MODE + ENDP + pop namespace +#line 14 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/bold.asm" + ; Sets BOLD flag in P_FLAG permanently +; Parameter: BOLD flag in bit 0 of A register + push namespace core +BOLD: + PROC + and 1 + rlca + rlca + rlca + ld hl, FLAGS2 + res 3, (HL) + or (hl) + ld (hl), a + ret + ; Sets BOLD flag in P_FLAG temporarily +BOLD_TMP: + and 1 + rlca + rlca + ld hl, FLAGS2 + res 2, (hl) + or (hl) + ld (hl), a + ret ENDP pop namespace -#line 7 "/zxbasic/src/arch/zx48k/library-asm/attr.asm" +#line 15 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/italic.asm" + ; Sets ITALIC flag in P_FLAG permanently +; Parameter: ITALIC flag in bit 0 of A register push namespace core -__ATTR_ADDR: - ; calc start address in DE (as (32 * d) + e) - ; Contributed by Santiago Romero at http://www.speccy.org - ld h, 0 ; 7 T-States - ld a, d ; 4 T-States - ld d, h - add a, a ; a * 2 ; 4 T-States - add a, a ; a * 4 ; 4 T-States - ld l, a ; HL = A * 4 ; 4 T-States - add hl, hl ; HL = A * 8 ; 15 T-States - add hl, hl ; HL = A * 16 ; 15 T-States - add hl, hl ; HL = A * 32 ; 15 T-States - add hl, de - ld de, (SCREEN_ATTR_ADDR) ; Adds the screen address - add hl, de - ; Return current screen address in HL - ret - ; Sets the attribute at a given screen coordinate (D, E). - ; The attribute is taken from the ATTR_T memory variable - ; Used by PRINT routines -SET_ATTR: - ; Checks for valid coords - call __IN_SCREEN - ret nc - call __ATTR_ADDR -__SET_ATTR: - ; Internal __FASTCALL__ Entry used by printing routines - ; HL contains the address of the ATTR cell to set +ITALIC: PROC -__SET_ATTR2: ; Sets attr from ATTR_T to (HL) which points to the scr address - ld de, (ATTR_T) ; E = ATTR_T, D = MASK_T - ld a, d - and (hl) - ld c, a ; C = current screen color, masked - ld a, d - cpl ; Negate mask - and e ; Mask current attributes - or c ; Mix them - ld (hl), a ; Store result in screen + and 1 + rrca + rrca + rrca + ld hl, FLAGS2 + res 5, (HL) + or (hl) + ld (hl), a + ret + ; Sets ITALIC flag in P_FLAG temporarily +ITALIC_TMP: + and 1 + rrca + rrca + rrca + rrca + ld hl, FLAGS2 + res 4, (hl) + or (hl) + ld (hl), a ret ENDP pop namespace -#line 3 "/zxbasic/src/arch/zx48k/library-asm/sposn.asm" - ; Printing positioning library. +#line 16 "/zxbasic/src/arch/zx48k/library-asm/print.asm" + ; Putting a comment starting with @INIT
+ ; will make the compiler to add a CALL to
+ ; It is useful for initialization routines. push namespace core - ; Loads into DE current ROW, COL print position from S_POSN mem var. -__LOAD_S_POSN: +__PRINT_INIT: ; To be called before program starts (initializes library) PROC - ld de, (S_POSN) + ld hl, __PRINT_START + ld (PRINT_JUMP_STATE), hl + ;; Clears ATTR2 flags (OVER 2, etc) + xor a + ld (FLAGS2), a + LOCAL SET_SCR_ADDR + call __LOAD_S_POSN + jp __SET_SCR_PTR + ;; Receives HL = future value of S_POSN + ;; Stores it at (S_POSN) and refresh screen pointers (ATTR, SCR) +SET_SCR_ADDR: + ld (S_POSN), hl + ex de, hl ld hl, SCR_SIZE or a sbc hl, de ex de, hl + dec e + jp __SET_SCR_PTR +__PRINTCHAR: ; Print character store in accumulator (A register) + ; Modifies H'L', B'C', A'F', D'E', A + LOCAL PO_GR_1 + LOCAL __PRCHAR + LOCAL __PRINT_JUMP + LOCAL __SRCADDR + LOCAL __PRINT_UDG + LOCAL __PRGRAPH + LOCAL __PRINT_START + PRINT_JUMP_STATE EQU __PRINT_JUMP + 2 +__PRINT_JUMP: + exx ; Switch to alternative registers + jp __PRINT_START ; Where to jump. If we print 22 (AT), next two calls jumps to AT1 and AT2 respectively +__PRINT_START: +__PRINT_CHR: + cp ' ' + jr c, __PRINT_SPECIAL ; Characters below ' ' are special ones + ex af, af' ; Saves a value (char to print) for later + ld hl, (S_POSN) + dec l + jr nz, 1f + ld l, SCR_COLS - 1 + dec h + jr nz, 2f + inc h + push hl + call __SCROLL_SCR + pop hl +#line 92 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +2: + call SET_SCR_ADDR + jr 4f +1: + ld (S_POSN), hl +4: + ex af, af' + cp 80h ; Is it a "normal" (printable) char + jr c, __SRCADDR + cp 90h ; Is it an UDG? + jr nc, __PRINT_UDG + ; Print an 8 bit pattern (80h to 8Fh) + ld b, a + call PO_GR_1 ; This ROM routine will generate the bit pattern at MEM0 + ld hl, MEM0 + jp __PRGRAPH + PO_GR_1 EQU 0B38h +__PRINT_UDG: + sub 90h ; Sub ASC code + ld bc, (UDG) + jr __PRGRAPH0 + __SOURCEADDR EQU (__SRCADDR + 1) ; Address of the pointer to chars source +__SRCADDR: + ld bc, (CHARS) +__PRGRAPH0: + add a, a ; A = a * 2 (since a < 80h) ; Thanks to Metalbrain at http://foro.speccy.org + ld l, a + ld h, 0 ; HL = a * 2 (accumulator) + add hl, hl + add hl, hl ; HL = a * 8 + add hl, bc ; HL = CHARS address +__PRGRAPH: + ex de, hl ; HL = Write Address, DE = CHARS address + bit 2, (iy + $47) + call nz, __BOLD +#line 139 "/zxbasic/src/arch/zx48k/library-asm/print.asm" + bit 4, (iy + $47) + call nz, __ITALIC +#line 144 "/zxbasic/src/arch/zx48k/library-asm/print.asm" + ld hl, (DFCC) + push hl + ld b, 8 ; 8 bytes per char +__PRCHAR: + ld a, (de) ; DE *must* be source, and HL destiny +PRINT_MODE: ; Which operation is used to write on the screen + ; Set it with: + ; LD A, + ; LD (PRINT_MODE), A + ; + ; Available operations: + ; NORMAL : 0h --> NOP ; OVER 0 + ; XOR : AEh --> XOR (HL) ; OVER 1 + ; OR : B6h --> OR (HL) ; PUTSPRITE + ; AND : A6h --> AND (HL) ; PUTMASK + nop ; Set to one of the values above +INVERSE_MODE: ; 00 -> NOP -> INVERSE 0 + nop ; 2F -> CPL -> INVERSE 1 + ld (hl), a + inc de + inc h ; Next line + djnz __PRCHAR + pop hl + inc hl + ld (DFCC), hl + ld hl, (DFCCL) ; current ATTR Pos + inc hl + ld (DFCCL), hl + dec hl + call __SET_ATTR + exx ret - ENDP - ; Saves ROW, COL from DE into S_POSN mem var. -__SAVE_S_POSN: - PROC - ld hl, SCR_SIZE - or a - sbc hl, de - ld (S_POSN), hl ; saves it again -__SET_SCR_PTR: ;; Fast + ; ------------- SPECIAL CHARS (< 32) ----------------- +__PRINT_SPECIAL: ; Jumps here if it is a special char + ld hl, __PRINT_TABLE + jp JUMP_HL_PLUS_2A +PRINT_EOL: ; Called WHENEVER there is no ";" at end of PRINT sentence + exx +__PRINT_0Dh: ; Called WHEN printing CHR$(13) + ld hl, (S_POSN) + dec l + jr nz, 1f + dec h + jr nz, 1f + inc h + push hl + call __SCROLL_SCR + pop hl +#line 209 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +1: + ld l, 1 +__PRINT_EOL_END: + call SET_SCR_ADDR + exx + ret +__PRINT_COM: + exx + push hl push de - call __ATTR_ADDR - ld (DFCCL), hl + push bc + call PRINT_COMMA + pop bc pop de - ld a, d - ld c, a ; Saves it for later - and 0F8h ; Masks 3 lower bit ; zy - ld d, a - ld a, c ; Recovers it - and 07h ; MOD 7 ; y1 - rrca - rrca - rrca - or e - ld e, a - ld hl, (SCREEN_ADDR) - add hl, de ; HL = Screen address + DE - ld (DFCC), hl + pop hl + ret +__PRINT_TAB: + ld hl, __PRINT_TAB1 + jr __PRINT_SET_STATE +__PRINT_TAB1: + ld (MEM0), a + ld hl, __PRINT_TAB2 + jr __PRINT_SET_STATE +__PRINT_TAB2: + ld a, (MEM0) ; Load tab code (ignore the current one) + ld hl, __PRINT_START + ld (PRINT_JUMP_STATE), hl + exx + push hl + push bc + push de + call PRINT_TAB + pop de + pop bc + pop hl ret - ENDP - pop namespace -#line 6 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/table_jump.asm" - push namespace core -JUMP_HL_PLUS_2A: ; Does JP (HL + A*2) Modifies DE. Modifies A - add a, a -JUMP_HL_PLUS_A: ; Does JP (HL + A) Modifies DE - ld e, a - ld d, 0 -JUMP_HL_PLUS_DE: ; Does JP (HL + DE) - add hl, de - ld e, (hl) - inc hl - ld d, (hl) - ex de, hl -CALL_HL: - jp (hl) - pop namespace -#line 8 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/ink.asm" - ; Sets ink color in ATTR_P permanently -; Parameter: Paper color in A register - push namespace core -INK: - PROC - LOCAL __SET_INK - LOCAL __SET_INK2 - ld de, ATTR_P -__SET_INK: - cp 8 - jr nz, __SET_INK2 - inc de ; Points DE to MASK_T or MASK_P - ld a, (de) - or 7 ; Set bits 0,1,2 to enable transparency - ld (de), a +__PRINT_AT: + ld hl, __PRINT_AT1 + jr __PRINT_SET_STATE +__PRINT_NOP: +__PRINT_RESTART: + ld hl, __PRINT_START +__PRINT_SET_STATE: + ld (PRINT_JUMP_STATE), hl ; Saves next entry call + exx ret -__SET_INK2: - ; Another entry. This will set the ink color at location pointer by DE - and 7 ; # Gets color mod 8 - ld b, a ; Saves the color - ld a, (de) - and 0F8h ; Clears previous value - or b - ld (de), a - inc de ; Points DE to MASK_T or MASK_P - ld a, (de) - and 0F8h ; Reset bits 0,1,2 sign to disable transparency - ld (de), a ; Store new attr +__PRINT_AT1: ; Jumps here if waiting for 1st parameter + ld hl, (S_POSN) + ld h, a + ld a, SCR_ROWS + sub h + ld (S_POSN + 1), a + ld hl, __PRINT_AT2 + jr __PRINT_SET_STATE +__PRINT_AT2: + call __LOAD_S_POSN + ld e, a + call __SAVE_S_POSN + jr __PRINT_RESTART +__PRINT_DEL: + call __LOAD_S_POSN ; Gets current screen position + dec e + ld a, -1 + cp e + jr nz, 3f + ld e, SCR_COLS - 2 + dec d + cp d + jr nz, 3f + ld d, SCR_ROWS - 1 +3: + call __SAVE_S_POSN + exx ret - ; Sets the INK color passed in A register in the ATTR_T variable -INK_TMP: - ld de, ATTR_T - jp __SET_INK - ENDP - pop namespace -#line 9 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/paper.asm" - ; Sets paper color in ATTR_P permanently -; Parameter: Paper color in A register - push namespace core -PAPER: - PROC - LOCAL __SET_PAPER - LOCAL __SET_PAPER2 - ld de, ATTR_P -__SET_PAPER: - cp 8 - jr nz, __SET_PAPER2 - inc de +__PRINT_INK: + ld hl, __PRINT_INK2 + jr __PRINT_SET_STATE +__PRINT_INK2: + call INK_TMP + jr __PRINT_RESTART +__PRINT_PAP: + ld hl, __PRINT_PAP2 + jr __PRINT_SET_STATE +__PRINT_PAP2: + call PAPER_TMP + jr __PRINT_RESTART +__PRINT_FLA: + ld hl, __PRINT_FLA2 + jr __PRINT_SET_STATE +__PRINT_FLA2: + call FLASH_TMP + jr __PRINT_RESTART +__PRINT_BRI: + ld hl, __PRINT_BRI2 + jr __PRINT_SET_STATE +__PRINT_BRI2: + call BRIGHT_TMP + jr __PRINT_RESTART +__PRINT_INV: + ld hl, __PRINT_INV2 + jr __PRINT_SET_STATE +__PRINT_INV2: + call INVERSE_TMP + jr __PRINT_RESTART +__PRINT_OVR: + ld hl, __PRINT_OVR2 + jr __PRINT_SET_STATE +__PRINT_OVR2: + call OVER_TMP + jr __PRINT_RESTART +__PRINT_BOLD: + ld hl, __PRINT_BOLD2 + jp __PRINT_SET_STATE +__PRINT_BOLD2: + call BOLD_TMP + jp __PRINT_RESTART +#line 353 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +__PRINT_ITA: + ld hl, __PRINT_ITA2 + jp __PRINT_SET_STATE +__PRINT_ITA2: + call ITALIC_TMP + jp __PRINT_RESTART +#line 363 "/zxbasic/src/arch/zx48k/library-asm/print.asm" + LOCAL __BOLD +__BOLD: + push hl + ld hl, MEM0 + ld b, 8 +1: ld a, (de) - or 038h - ld (de), a - ret - ; Another entry. This will set the paper color at location pointer by DE -__SET_PAPER2: - and 7 ; # Remove - rlca + ld c, a rlca - rlca ; a *= 8 - ld b, a ; Saves the color - ld a, (de) - and 0C7h ; Clears previous value - or b - ld (de), a - inc de ; Points to MASK_T or MASK_P accordingly - ld a, (de) - and 0C7h ; Resets bits 3,4,5 - ld (de), a - ret - ; Sets the PAPER color passed in A register in the ATTR_T variable -PAPER_TMP: - ld de, ATTR_T - jp __SET_PAPER - ENDP - pop namespace -#line 10 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/flash.asm" - ; Sets flash flag in ATTR_P permanently -; Parameter: Paper color in A register - push namespace core -FLASH: - ld hl, ATTR_P - PROC - LOCAL IS_TR - LOCAL IS_ZERO -__SET_FLASH: - ; Another entry. This will set the flash flag at location pointer by DE - cp 8 - jr z, IS_TR - ; # Convert to 0/1 - or a - jr z, IS_ZERO - ld a, 0x80 -IS_ZERO: - ld b, a ; Saves the color - ld a, (hl) - and 07Fh ; Clears previous value - or b + or c ld (hl), a inc hl - res 7, (hl) ;Reset bit 7 to disable transparency - ret -IS_TR: ; transparent - inc hl ; Points DE to MASK_T or MASK_P - set 7, (hl) ;Set bit 7 to enable transparency - ret - ; Sets the FLASH flag passed in A register in the ATTR_T variable -FLASH_TMP: - ld hl, ATTR_T - jr __SET_FLASH - ENDP - pop namespace -#line 11 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/bright.asm" - ; Sets bright flag in ATTR_P permanently -; Parameter: Paper color in A register - push namespace core -BRIGHT: - ld hl, ATTR_P - PROC - LOCAL IS_TR - LOCAL IS_ZERO -__SET_BRIGHT: - ; Another entry. This will set the bright flag at location pointer by DE - cp 8 - jr z, IS_TR - ; # Convert to 0/1 - or a - jr z, IS_ZERO - ld a, 0x40 -IS_ZERO: - ld b, a ; Saves the color - ld a, (hl) - and 0BFh ; Clears previous value - or b - ld (hl), a + inc de + djnz 1b + pop hl + ld de, MEM0 + ret +#line 384 "/zxbasic/src/arch/zx48k/library-asm/print.asm" + LOCAL __ITALIC +__ITALIC: + push hl + ld hl, MEM0 + ex de, hl + ld bc, 8 + ldir + ld hl, MEM0 + srl (hl) inc hl - res 6, (hl) ;Reset bit 6 to disable transparency + srl (hl) + inc hl + srl (hl) + inc hl + inc hl + inc hl + sla (hl) + inc hl + sla (hl) + inc hl + sla (hl) + pop hl + ld de, MEM0 ret -IS_TR: ; transparent - inc hl ; Points DE to MASK_T or MASK_P - set 6, (hl) ;Set bit 6 to enable transparency +#line 412 "/zxbasic/src/arch/zx48k/library-asm/print.asm" + LOCAL __SCROLL_SCR +#line 486 "/zxbasic/src/arch/zx48k/library-asm/print.asm" + __SCROLL_SCR EQU 0DFEh ; Use ROM SCROLL +#line 488 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 489 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +PRINT_COMMA: + call __LOAD_S_POSN + ld a, e + and 16 + add a, 16 +PRINT_TAB: + ; Tabulates the number of spaces in A register + ; If the current cursor position is already A, does nothing + PROC + LOCAL LOOP + call __LOAD_S_POSN ; e = current row + sub e + and 31 + ret z + ld b, a +LOOP: + ld a, ' ' + call __PRINTCHAR + djnz LOOP ret - ; Sets the BRIGHT flag passed in A register in the ATTR_T variable -BRIGHT_TMP: - ld hl, ATTR_T - jr __SET_BRIGHT + ENDP +PRINT_AT: ; Changes cursor to ROW, COL + ; COL in A register + ; ROW in stack + pop hl ; Ret address + ex (sp), hl ; callee H = ROW + ld l, a + ex de, hl + call __IN_SCREEN + ret nc ; Return if out of screen + jp __SAVE_S_POSN + LOCAL __PRINT_COM + LOCAL __PRINT_AT1 + LOCAL __PRINT_AT2 + LOCAL __PRINT_BOLD + LOCAL __PRINT_ITA + LOCAL __PRINT_INK + LOCAL __PRINT_PAP + LOCAL __PRINT_SET_STATE + LOCAL __PRINT_TABLE + LOCAL __PRINT_TAB, __PRINT_TAB1, __PRINT_TAB2 + LOCAL __PRINT_ITA2 +#line 545 "/zxbasic/src/arch/zx48k/library-asm/print.asm" + LOCAL __PRINT_BOLD2 +#line 551 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +__PRINT_TABLE: ; Jump table for 0 .. 22 codes + DW __PRINT_NOP ; 0 + DW __PRINT_NOP ; 1 + DW __PRINT_NOP ; 2 + DW __PRINT_NOP ; 3 + DW __PRINT_NOP ; 4 + DW __PRINT_NOP ; 5 + DW __PRINT_COM ; 6 COMMA + DW __PRINT_NOP ; 7 + DW __PRINT_DEL ; 8 DEL + DW __PRINT_NOP ; 9 + DW __PRINT_NOP ; 10 + DW __PRINT_NOP ; 11 + DW __PRINT_NOP ; 12 + DW __PRINT_0Dh ; 13 + DW __PRINT_BOLD ; 14 + DW __PRINT_ITA ; 15 + DW __PRINT_INK ; 16 + DW __PRINT_PAP ; 17 + DW __PRINT_FLA ; 18 + DW __PRINT_BRI ; 19 + DW __PRINT_INV ; 20 + DW __PRINT_OVR ; 21 + DW __PRINT_AT ; 22 AT + DW __PRINT_TAB ; 23 TAB ENDP pop namespace -#line 12 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/over.asm" - ; Sets OVER flag in P_FLAG permanently -; Parameter: OVER flag in bit 0 of A register -#line 1 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" +#line 3 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" #line 4 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" push namespace core COPY_ATTR: @@ -968,523 +1012,470 @@ __REFRESH_TMP: ret ENDP pop namespace -#line 4 "/zxbasic/src/arch/zx48k/library-asm/over.asm" - push namespace core -OVER: - PROC - ld c, a ; saves it for later - and 2 - ld hl, FLAGS2 - res 1, (HL) - or (hl) - ld (hl), a - ld a, c ; Recovers previous value - and 1 ; # Convert to 0/1 - add a, a; # Shift left 1 bit for permanent - ld hl, P_FLAG - res 1, (hl) - or (hl) - ld (hl), a - ret - ; Sets OVER flag in P_FLAG temporarily -OVER_TMP: - ld c, a ; saves it for later - and 2 ; gets bit 1; clears carry - rra - ld hl, FLAGS2 - res 0, (hl) - or (hl) - ld (hl), a - ld a, c ; Recovers previous value - and 1 - ld hl, P_FLAG - res 0, (hl) - or (hl) - ld (hl), a - jp __SET_ATTR_MODE - ENDP - pop namespace -#line 13 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/inverse.asm" - ; Sets INVERSE flag in P_FLAG permanently -; Parameter: INVERSE flag in bit 0 of A register - push namespace core -INVERSE: - PROC - and 1 ; # Convert to 0/1 - add a, a; # Shift left 3 bits for permanent - add a, a - add a, a - ld hl, P_FLAG - res 3, (hl) - or (hl) - ld (hl), a - ret - ; Sets INVERSE flag in P_FLAG temporarily -INVERSE_TMP: - and 1 - add a, a - add a, a; # Shift left 2 bits for temporary - ld hl, P_FLAG - res 2, (hl) - or (hl) - ld (hl), a - jp __SET_ATTR_MODE - ENDP - pop namespace -#line 14 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/bold.asm" - ; Sets BOLD flag in P_FLAG permanently -; Parameter: BOLD flag in bit 0 of A register - push namespace core -BOLD: - PROC - and 1 - rlca - rlca - rlca - ld hl, FLAGS2 - res 3, (HL) - or (hl) - ld (hl), a - ret - ; Sets BOLD flag in P_FLAG temporarily -BOLD_TMP: - and 1 - rlca - rlca - ld hl, FLAGS2 - res 2, (hl) - or (hl) - ld (hl), a - ret - ENDP - pop namespace -#line 15 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/italic.asm" - ; Sets ITALIC flag in P_FLAG permanently -; Parameter: ITALIC flag in bit 0 of A register +#line 77 "zx48k/strparam3.bas" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/free.asm" +; vim: ts=4:et:sw=4: + ; Copyleft (K) by Jose M. Rodriguez de la Rosa + ; (a.k.a. Boriel) +; http://www.boriel.com + ; + ; This ASM library is licensed under the BSD license + ; you can use it for any purpose (even for commercial + ; closed source programs). + ; + ; Please read the BSD license on the internet + ; ----- IMPLEMENTATION NOTES ------ + ; The heap is implemented as a linked list of free blocks. +; Each free block contains this info: + ; + ; +----------------+ <-- HEAP START + ; | Size (2 bytes) | + ; | 0 | <-- Size = 0 => DUMMY HEADER BLOCK + ; +----------------+ + ; | Next (2 bytes) |---+ + ; +----------------+ <-+ + ; | Size (2 bytes) | + ; +----------------+ + ; | Next (2 bytes) |---+ + ; +----------------+ | + ; | | | <-- If Size > 4, then this contains (size - 4) bytes + ; | (0 if Size = 4)| | + ; +----------------+ <-+ + ; | Size (2 bytes) | + ; +----------------+ + ; | Next (2 bytes) |---+ + ; +----------------+ | + ; | | | + ; | (0 if Size = 4)| | + ; +----------------+ | + ; | <-- This zone is in use (Already allocated) + ; +----------------+ <-+ + ; | Size (2 bytes) | + ; +----------------+ + ; | Next (2 bytes) |---+ + ; +----------------+ | + ; | | | + ; | (0 if Size = 4)| | + ; +----------------+ <-+ + ; | Next (2 bytes) |--> NULL => END OF LIST + ; | 0 = NULL | + ; +----------------+ + ; | | + ; | (0 if Size = 4)| + ; +----------------+ + ; When a block is FREED, the previous and next pointers are examined to see + ; if we can defragment the heap. If the block to be breed is just next to the + ; previous, or to the next (or both) they will be converted into a single + ; block (so defragmented). + ; MEMORY MANAGER + ; + ; This library must be initialized calling __MEM_INIT with + ; HL = BLOCK Start & DE = Length. + ; An init directive is useful for initialization routines. + ; They will be added automatically if needed. +#line 1 "/zxbasic/src/arch/zx48k/library-asm/heapinit.asm" +; vim: ts=4:et:sw=4: + ; Copyleft (K) by Jose M. Rodriguez de la Rosa + ; (a.k.a. Boriel) +; http://www.boriel.com + ; + ; This ASM library is licensed under the BSD license + ; you can use it for any purpose (even for commercial + ; closed source programs). + ; + ; Please read the BSD license on the internet + ; ----- IMPLEMENTATION NOTES ------ + ; The heap is implemented as a linked list of free blocks. +; Each free block contains this info: + ; + ; +----------------+ <-- HEAP START + ; | Size (2 bytes) | + ; | 0 | <-- Size = 0 => DUMMY HEADER BLOCK + ; +----------------+ + ; | Next (2 bytes) |---+ + ; +----------------+ <-+ + ; | Size (2 bytes) | + ; +----------------+ + ; | Next (2 bytes) |---+ + ; +----------------+ | + ; | | | <-- If Size > 4, then this contains (size - 4) bytes + ; | (0 if Size = 4)| | + ; +----------------+ <-+ + ; | Size (2 bytes) | + ; +----------------+ + ; | Next (2 bytes) |---+ + ; +----------------+ | + ; | | | + ; | (0 if Size = 4)| | + ; +----------------+ | + ; | <-- This zone is in use (Already allocated) + ; +----------------+ <-+ + ; | Size (2 bytes) | + ; +----------------+ + ; | Next (2 bytes) |---+ + ; +----------------+ | + ; | | | + ; | (0 if Size = 4)| | + ; +----------------+ <-+ + ; | Next (2 bytes) |--> NULL => END OF LIST + ; | 0 = NULL | + ; +----------------+ + ; | | + ; | (0 if Size = 4)| + ; +----------------+ + ; When a block is FREED, the previous and next pointers are examined to see + ; if we can defragment the heap. If the block to be breed is just next to the + ; previous, or to the next (or both) they will be converted into a single + ; block (so defragmented). + ; MEMORY MANAGER + ; + ; This library must be initialized calling __MEM_INIT with + ; HL = BLOCK Start & DE = Length. + ; An init directive is useful for initialization routines. + ; They will be added automatically if needed. + ; --------------------------------------------------------------------- + ; __MEM_INIT must be called to initalize this library with the + ; standard parameters + ; --------------------------------------------------------------------- push namespace core -ITALIC: +__MEM_INIT: ; Initializes the library using (RAMTOP) as start, and + ld hl, ZXBASIC_MEM_HEAP ; Change this with other address of heap start + ld de, ZXBASIC_HEAP_SIZE ; Change this with your size + ; --------------------------------------------------------------------- + ; __MEM_INIT2 initalizes this library +; Parameters: +; HL : Memory address of 1st byte of the memory heap +; DE : Length in bytes of the Memory Heap + ; --------------------------------------------------------------------- +__MEM_INIT2: + ; HL as TOP PROC - and 1 - rrca - rrca - rrca - ld hl, FLAGS2 - res 5, (HL) - or (hl) + dec de + dec de + dec de + dec de ; DE = length - 4; HL = start + ; This is done, because we require 4 bytes for the empty dummy-header block + xor a ld (hl), a - ret - ; Sets ITALIC flag in P_FLAG temporarily -ITALIC_TMP: - and 1 - rrca - rrca - rrca - rrca - ld hl, FLAGS2 - res 4, (hl) - or (hl) + inc hl + ld (hl), a ; First "free" block is a header: size=0, Pointer=&(Block) + 4 + inc hl + ld b, h + ld c, l + inc bc + inc bc ; BC = starts of next block + ld (hl), c + inc hl + ld (hl), b + inc hl ; Pointer to next block + ld (hl), e + inc hl + ld (hl), d + inc hl ; Block size (should be length - 4 at start); This block contains all the available memory + ld (hl), a ; NULL (0000h) ; No more blocks (a list with a single block) + inc hl ld (hl), a + ld a, 201 + ld (__MEM_INIT), a; "Pokes" with a RET so ensure this routine is not called again ret ENDP pop namespace -#line 16 "/zxbasic/src/arch/zx48k/library-asm/print.asm" - ; Putting a comment starting with @INIT
- ; will make the compiler to add a CALL to
- ; It is useful for initialization routines. +#line 69 "/zxbasic/src/arch/zx48k/library-asm/free.asm" + ; --------------------------------------------------------------------- + ; MEM_FREE + ; Frees a block of memory + ; +; Parameters: + ; HL = Pointer to the block to be freed. If HL is NULL (0) nothing + ; is done + ; --------------------------------------------------------------------- push namespace core -__PRINT_INIT: ; To be called before program starts (initializes library) - PROC - ld hl, __PRINT_START - ld (PRINT_JUMP_STATE), hl - ;; Clears ATTR2 flags (OVER 2, etc) - xor a - ld (FLAGS2), a - LOCAL SET_SCR_ADDR - call __LOAD_S_POSN - jp __SET_SCR_PTR - ;; Receives HL = future value of S_POSN - ;; Stores it at (S_POSN) and refresh screen pointers (ATTR, SCR) -SET_SCR_ADDR: - ld (S_POSN), hl - ex de, hl - ld hl, SCR_SIZE - or a - sbc hl, de - ex de, hl - dec e - jp __SET_SCR_PTR -__PRINTCHAR: ; Print character store in accumulator (A register) - ; Modifies H'L', B'C', A'F', D'E', A - LOCAL PO_GR_1 - LOCAL __PRCHAR - LOCAL __PRINT_JUMP - LOCAL __SRCADDR - LOCAL __PRINT_UDG - LOCAL __PRGRAPH - LOCAL __PRINT_START - PRINT_JUMP_STATE EQU __PRINT_JUMP + 2 -__PRINT_JUMP: - exx ; Switch to alternative registers - jp __PRINT_START ; Where to jump. If we print 22 (AT), next two calls jumps to AT1 and AT2 respectively -__PRINT_START: -__PRINT_CHR: - cp ' ' - jr c, __PRINT_SPECIAL ; Characters below ' ' are special ones - ex af, af' ; Saves a value (char to print) for later - ld hl, (S_POSN) - dec l - jr nz, 1f - ld l, SCR_COLS - 1 - dec h - jr nz, 2f - inc h - push hl - call __SCROLL_SCR - pop hl -#line 92 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -2: - call SET_SCR_ADDR - jr 4f -1: - ld (S_POSN), hl -4: - ex af, af' - cp 80h ; Is it a "normal" (printable) char - jr c, __SRCADDR - cp 90h ; Is it an UDG? - jr nc, __PRINT_UDG - ; Print an 8 bit pattern (80h to 8Fh) - ld b, a - call PO_GR_1 ; This ROM routine will generate the bit pattern at MEM0 - ld hl, MEM0 - jp __PRGRAPH - PO_GR_1 EQU 0B38h -__PRINT_UDG: - sub 90h ; Sub ASC code - ld bc, (UDG) - jr __PRGRAPH0 - __SOURCEADDR EQU (__SRCADDR + 1) ; Address of the pointer to chars source -__SRCADDR: - ld bc, (CHARS) -__PRGRAPH0: - add a, a ; A = a * 2 (since a < 80h) ; Thanks to Metalbrain at http://foro.speccy.org - ld l, a - ld h, 0 ; HL = a * 2 (accumulator) - add hl, hl - add hl, hl ; HL = a * 8 - add hl, bc ; HL = CHARS address -__PRGRAPH: - ex de, hl ; HL = Write Address, DE = CHARS address - bit 2, (iy + $47) - call nz, __BOLD -#line 139 "/zxbasic/src/arch/zx48k/library-asm/print.asm" - bit 4, (iy + $47) - call nz, __ITALIC -#line 144 "/zxbasic/src/arch/zx48k/library-asm/print.asm" - ld hl, (DFCC) - push hl - ld b, 8 ; 8 bytes per char -__PRCHAR: - ld a, (de) ; DE *must* be source, and HL destiny -PRINT_MODE: ; Which operation is used to write on the screen - ; Set it with: - ; LD A, - ; LD (PRINT_MODE), A - ; - ; Available operations: - ; NORMAL : 0h --> NOP ; OVER 0 - ; XOR : AEh --> XOR (HL) ; OVER 1 - ; OR : B6h --> OR (HL) ; PUTSPRITE - ; AND : A6h --> AND (HL) ; PUTMASK - nop ; Set to one of the values above -INVERSE_MODE: ; 00 -> NOP -> INVERSE 0 - nop ; 2F -> CPL -> INVERSE 1 - ld (hl), a - inc de - inc h ; Next line - djnz __PRCHAR - pop hl +MEM_FREE: +__MEM_FREE: ; Frees the block pointed by HL + ; HL DE BC & AF modified + PROC + LOCAL __MEM_LOOP2 + LOCAL __MEM_LINK_PREV + LOCAL __MEM_JOIN_TEST + LOCAL __MEM_BLOCK_JOIN + ld a, h + or l + ret z ; Return if NULL pointer + dec hl + dec hl + ld b, h + ld c, l ; BC = Block pointer + ld hl, ZXBASIC_MEM_HEAP ; This label point to the heap start +__MEM_LOOP2: inc hl - ld (DFCC), hl - ld hl, (DFCCL) ; current ATTR Pos - push hl - call __SET_ATTR - pop hl + inc hl ; Next block ptr + ld e, (hl) inc hl - ld (DFCCL),hl - exx - ret - ; ------------- SPECIAL CHARS (< 32) ----------------- -__PRINT_SPECIAL: ; Jumps here if it is a special char - ld hl, __PRINT_TABLE - jp JUMP_HL_PLUS_2A -PRINT_EOL: ; Called WHENEVER there is no ";" at end of PRINT sentence - exx -__PRINT_0Dh: ; Called WHEN printing CHR$(13) - ld hl, (S_POSN) - dec l - jr nz, 1f - dec h - jr nz, 1f - inc h - push hl - call __SCROLL_SCR - pop hl -#line 210 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -1: - ld l, 1 -__PRINT_EOL_END: - call SET_SCR_ADDR - exx - ret -__PRINT_COM: - exx + ld d, (hl) ; Block next ptr + ex de, hl ; DE = &(block->next); HL = block->next + ld a, h ; HL == NULL? + or l + jp z, __MEM_LINK_PREV; if so, link with previous + or a ; Clear carry flag + sbc hl, bc ; Carry if BC > HL => This block if before + add hl, bc ; Restores HL, preserving Carry flag + jp c, __MEM_LOOP2 ; This block is before. Keep searching PASS the block + ;------ At this point current HL is PAST BC, so we must link (DE) with BC, and HL in BC->next +__MEM_LINK_PREV: ; Link (DE) with BC, and BC->next with HL + ex de, hl push hl - push de - push bc - call PRINT_COMMA - pop bc - pop de + dec hl + ld (hl), c + inc hl + ld (hl), b ; (DE) <- BC + ld h, b ; HL <- BC (Free block ptr) + ld l, c + inc hl ; Skip block length (2 bytes) + inc hl + ld (hl), e ; Block->next = DE + inc hl + ld (hl), d + ; --- LINKED ; HL = &(BC->next) + 2 + call __MEM_JOIN_TEST pop hl - ret -__PRINT_TAB: - ld hl, __PRINT_TAB1 - jr __PRINT_SET_STATE -__PRINT_TAB1: - ld (MEM0), a - ld hl, __PRINT_TAB2 - jr __PRINT_SET_STATE -__PRINT_TAB2: - ld a, (MEM0) ; Load tab code (ignore the current one) - ld hl, __PRINT_START - ld (PRINT_JUMP_STATE), hl - exx - push hl - push bc - push de - call PRINT_TAB - pop de - pop bc +__MEM_JOIN_TEST: ; Checks for fragmented contiguous blocks and joins them + ; hl = Ptr to current block + 2 + ld d, (hl) + dec hl + ld e, (hl) + dec hl + ld b, (hl) ; Loads block length into BC + dec hl + ld c, (hl) ; + push hl ; Saves it for later + add hl, bc ; Adds its length. If HL == DE now, it must be joined + or a + sbc hl, de ; If Z, then HL == DE => We must join pop hl + ret nz +__MEM_BLOCK_JOIN: ; Joins current block (pointed by HL) with next one (pointed by DE). HL->length already in BC + push hl ; Saves it for later + ex de, hl + ld e, (hl) ; DE -> block->next->length + inc hl + ld d, (hl) + inc hl + ex de, hl ; DE = &(block->next) + add hl, bc ; HL = Total Length + ld b, h + ld c, l ; BC = Total Length + ex de, hl + ld e, (hl) + inc hl + ld d, (hl) ; DE = block->next + pop hl ; Recovers Pointer to block + ld (hl), c + inc hl + ld (hl), b ; Length Saved + inc hl + ld (hl), e + inc hl + ld (hl), d ; Next saved ret -__PRINT_AT: - ld hl, __PRINT_AT1 - jr __PRINT_SET_STATE -__PRINT_NOP: -__PRINT_RESTART: - ld hl, __PRINT_START -__PRINT_SET_STATE: - ld (PRINT_JUMP_STATE), hl ; Saves next entry call - exx - ret -__PRINT_AT1: ; Jumps here if waiting for 1st parameter - ld hl, (S_POSN) - ld h, a - ld a, SCR_ROWS - sub h - ld (S_POSN + 1), a - ld hl, __PRINT_AT2 - jr __PRINT_SET_STATE -__PRINT_AT2: - call __LOAD_S_POSN - ld e, a - call __SAVE_S_POSN - jr __PRINT_RESTART -__PRINT_DEL: - call __LOAD_S_POSN ; Gets current screen position - dec e - ld a, -1 - cp e - jr nz, 3f - ld e, SCR_COLS - 2 - dec d - cp d - jr nz, 3f - ld d, SCR_ROWS - 1 -3: - call __SAVE_S_POSN - exx - ret -__PRINT_INK: - ld hl, __PRINT_INK2 - jr __PRINT_SET_STATE -__PRINT_INK2: - call INK_TMP - jr __PRINT_RESTART -__PRINT_PAP: - ld hl, __PRINT_PAP2 - jr __PRINT_SET_STATE -__PRINT_PAP2: - call PAPER_TMP - jr __PRINT_RESTART -__PRINT_FLA: - ld hl, __PRINT_FLA2 - jr __PRINT_SET_STATE -__PRINT_FLA2: - call FLASH_TMP - jr __PRINT_RESTART -__PRINT_BRI: - ld hl, __PRINT_BRI2 - jr __PRINT_SET_STATE -__PRINT_BRI2: - call BRIGHT_TMP - jr __PRINT_RESTART -__PRINT_INV: - ld hl, __PRINT_INV2 - jr __PRINT_SET_STATE -__PRINT_INV2: - call INVERSE_TMP - jr __PRINT_RESTART -__PRINT_OVR: - ld hl, __PRINT_OVR2 - jr __PRINT_SET_STATE -__PRINT_OVR2: - call OVER_TMP - jr __PRINT_RESTART -__PRINT_BOLD: - ld hl, __PRINT_BOLD2 - jp __PRINT_SET_STATE -__PRINT_BOLD2: - call BOLD_TMP - jp __PRINT_RESTART -#line 354 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -__PRINT_ITA: - ld hl, __PRINT_ITA2 - jp __PRINT_SET_STATE -__PRINT_ITA2: - call ITALIC_TMP - jp __PRINT_RESTART -#line 364 "/zxbasic/src/arch/zx48k/library-asm/print.asm" - LOCAL __BOLD -__BOLD: - push hl - ld hl, MEM0 - ld b, 8 -1: - ld a, (de) - ld c, a - rlca - or c - ld (hl), a + ENDP + pop namespace +#line 78 "zx48k/strparam3.bas" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/loadstr.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/alloc.asm" +; vim: ts=4:et:sw=4: + ; Copyleft (K) by Jose M. Rodriguez de la Rosa + ; (a.k.a. Boriel) +; http://www.boriel.com + ; + ; This ASM library is licensed under the MIT license + ; you can use it for any purpose (even for commercial + ; closed source programs). + ; + ; Please read the MIT license on the internet + ; ----- IMPLEMENTATION NOTES ------ + ; The heap is implemented as a linked list of free blocks. +; Each free block contains this info: + ; + ; +----------------+ <-- HEAP START + ; | Size (2 bytes) | + ; | 0 | <-- Size = 0 => DUMMY HEADER BLOCK + ; +----------------+ + ; | Next (2 bytes) |---+ + ; +----------------+ <-+ + ; | Size (2 bytes) | + ; +----------------+ + ; | Next (2 bytes) |---+ + ; +----------------+ | + ; | | | <-- If Size > 4, then this contains (size - 4) bytes + ; | (0 if Size = 4)| | + ; +----------------+ <-+ + ; | Size (2 bytes) | + ; +----------------+ + ; | Next (2 bytes) |---+ + ; +----------------+ | + ; | | | + ; | (0 if Size = 4)| | + ; +----------------+ | + ; | <-- This zone is in use (Already allocated) + ; +----------------+ <-+ + ; | Size (2 bytes) | + ; +----------------+ + ; | Next (2 bytes) |---+ + ; +----------------+ | + ; | | | + ; | (0 if Size = 4)| | + ; +----------------+ <-+ + ; | Next (2 bytes) |--> NULL => END OF LIST + ; | 0 = NULL | + ; +----------------+ + ; | | + ; | (0 if Size = 4)| + ; +----------------+ + ; When a block is FREED, the previous and next pointers are examined to see + ; if we can defragment the heap. If the block to be freed is just next to the + ; previous, or to the next (or both) they will be converted into a single + ; block (so defragmented). + ; MEMORY MANAGER + ; + ; This library must be initialized calling __MEM_INIT with + ; HL = BLOCK Start & DE = Length. + ; An init directive is useful for initialization routines. + ; They will be added automatically if needed. + ; --------------------------------------------------------------------- + ; MEM_ALLOC + ; Allocates a block of memory in the heap. + ; + ; Parameters + ; BC = Length of requested memory block + ; +; Returns: + ; HL = Pointer to the allocated block in memory. Returns 0 (NULL) + ; if the block could not be allocated (out of memory) + ; --------------------------------------------------------------------- + push namespace core +MEM_ALLOC: +__MEM_ALLOC: ; Returns the 1st free block found of the given length (in BC) + PROC + LOCAL __MEM_LOOP + LOCAL __MEM_DONE + LOCAL __MEM_SUBTRACT + LOCAL __MEM_START + LOCAL TEMP, TEMP0 + TEMP EQU TEMP0 + 1 + ld hl, 0 + ld (TEMP), hl +__MEM_START: + ld hl, ZXBASIC_MEM_HEAP ; This label point to the heap start + inc bc + inc bc ; BC = BC + 2 ; block size needs 2 extra bytes for hidden pointer +__MEM_LOOP: ; Loads lengh at (HL, HL+). If Lenght >= BC, jump to __MEM_DONE + ld a, h ; HL = NULL (No memory available?) + or l +#line 113 "/zxbasic/src/arch/zx48k/library-asm/alloc.asm" + ret z ; NULL +#line 115 "/zxbasic/src/arch/zx48k/library-asm/alloc.asm" + ; HL = Pointer to Free block + ld e, (hl) inc hl - inc de - djnz 1b + ld d, (hl) + inc hl ; DE = Block Length + push hl ; HL = *pointer to -> next block + ex de, hl + or a ; CF = 0 + sbc hl, bc ; FREE >= BC (Length) (HL = BlockLength - Length) + jp nc, __MEM_DONE pop hl - ld de, MEM0 - ret -#line 385 "/zxbasic/src/arch/zx48k/library-asm/print.asm" - LOCAL __ITALIC -__ITALIC: - push hl - ld hl, MEM0 + ld (TEMP), hl ex de, hl - ld bc, 8 - ldir - ld hl, MEM0 - srl (hl) - inc hl - srl (hl) - inc hl - srl (hl) - inc hl - inc hl + ld e, (hl) inc hl - sla (hl) + ld d, (hl) + ex de, hl + jp __MEM_LOOP +__MEM_DONE: ; A free block has been found. + ; Check if at least 4 bytes remains free (HL >= 4) + push hl + exx ; exx to preserve bc + pop hl + ld bc, 4 + or a + sbc hl, bc + exx + jp nc, __MEM_SUBTRACT + ; At this point... + ; less than 4 bytes remains free. So we return this block entirely + ; We must link the previous block with the next to this one + ; (DE) => Pointer to next block + ; (TEMP) => &(previous->next) + pop hl ; Discard current block pointer + push de + ex de, hl ; DE = Previous block pointer; (HL) = Next block pointer + ld a, (hl) inc hl - sla (hl) + ld h, (hl) + ld l, a ; HL = (HL) + ex de, hl ; HL = Previous block pointer; DE = Next block pointer +TEMP0: + ld hl, 0 ; Pre-previous block pointer + ld (hl), e inc hl - sla (hl) - pop hl - ld de, MEM0 - ret -#line 413 "/zxbasic/src/arch/zx48k/library-asm/print.asm" - LOCAL __SCROLL_SCR -#line 487 "/zxbasic/src/arch/zx48k/library-asm/print.asm" - __SCROLL_SCR EQU 0DFEh ; Use ROM SCROLL -#line 489 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -#line 490 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -PRINT_COMMA: - call __LOAD_S_POSN - ld a, e - and 16 - add a, 16 -PRINT_TAB: - ; Tabulates the number of spaces in A register - ; If the current cursor position is already A, does nothing - PROC - LOCAL LOOP - call __LOAD_S_POSN ; e = current row - sub e - and 31 - ret z - ld b, a -LOOP: - ld a, ' ' - call __PRINTCHAR - djnz LOOP + ld (hl), d ; LINKED + pop hl ; Returning block. ret - ENDP -PRINT_AT: ; Changes cursor to ROW, COL - ; COL in A register - ; ROW in stack - pop hl ; Ret address - ex (sp), hl ; callee H = ROW - ld l, a +__MEM_SUBTRACT: + ; At this point we have to store HL value (Length - BC) into (DE - 2) ex de, hl - call __IN_SCREEN - ret nc ; Return if out of screen - jp __SAVE_S_POSN - LOCAL __PRINT_COM - LOCAL __PRINT_AT1 - LOCAL __PRINT_AT2 - LOCAL __PRINT_BOLD - LOCAL __PRINT_ITA - LOCAL __PRINT_INK - LOCAL __PRINT_PAP - LOCAL __PRINT_SET_STATE - LOCAL __PRINT_TABLE - LOCAL __PRINT_TAB, __PRINT_TAB1, __PRINT_TAB2 - LOCAL __PRINT_ITA2 -#line 546 "/zxbasic/src/arch/zx48k/library-asm/print.asm" - LOCAL __PRINT_BOLD2 -#line 552 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -__PRINT_TABLE: ; Jump table for 0 .. 22 codes - DW __PRINT_NOP ; 0 - DW __PRINT_NOP ; 1 - DW __PRINT_NOP ; 2 - DW __PRINT_NOP ; 3 - DW __PRINT_NOP ; 4 - DW __PRINT_NOP ; 5 - DW __PRINT_COM ; 6 COMMA - DW __PRINT_NOP ; 7 - DW __PRINT_DEL ; 8 DEL - DW __PRINT_NOP ; 9 - DW __PRINT_NOP ; 10 - DW __PRINT_NOP ; 11 - DW __PRINT_NOP ; 12 - DW __PRINT_0Dh ; 13 - DW __PRINT_BOLD ; 14 - DW __PRINT_ITA ; 15 - DW __PRINT_INK ; 16 - DW __PRINT_PAP ; 17 - DW __PRINT_FLA ; 18 - DW __PRINT_BRI ; 19 - DW __PRINT_INV ; 20 - DW __PRINT_OVR ; 21 - DW __PRINT_AT ; 22 AT - DW __PRINT_TAB ; 23 TAB + dec hl + ld (hl), d + dec hl + ld (hl), e ; Store new block length + add hl, de ; New length + DE => free-block start + pop de ; Remove previous HL off the stack + ld (hl), c ; Store length on its 1st word + inc hl + ld (hl), b + inc hl ; Return hl + ret ENDP pop namespace -#line 5 "/zxbasic/src/arch/zx48k/library-asm/print_eol_attr.asm" +#line 2 "/zxbasic/src/arch/zx48k/library-asm/loadstr.asm" + ; Loads a string (ptr) from HL + ; and duplicates it on dynamic memory again + ; Finally, it returns result pointer in HL push namespace core -PRINT_EOL_ATTR: - call PRINT_EOL - jp COPY_ATTR +__ILOADSTR: ; This is the indirect pointer entry HL = (HL) + ld a, h + or l + ret z + ld a, (hl) + inc hl + ld h, (hl) + ld l, a +__LOADSTR: ; __FASTCALL__ entry + ld a, h + or l + ret z ; Return if NULL + ld c, (hl) + inc hl + ld b, (hl) + dec hl ; BC = LEN(a$) + inc bc + inc bc ; BC = LEN(a$) + 2 (two bytes for length) + push hl + push bc + call __MEM_ALLOC + pop bc ; Recover length + pop de ; Recover origin + ld a, h + or l + ret z ; Return if NULL (No memory) + ex de, hl ; ldir takes HL as source, DE as destiny, so SWAP HL,DE + push de ; Saves destiny start + ldir ; Copies string (length number included) + pop hl ; Recovers destiny in hl as result + ret pop namespace -#line 78 "zx48k/strparam3.bas" +#line 79 "zx48k/strparam3.bas" #line 1 "/zxbasic/src/arch/zx48k/library-asm/printstr.asm" ; PRINT command routine ; Prints string pointed by HL @@ -1528,5 +1519,5 @@ __PRINT_STR: jp __PRINT_STR_LOOP ENDP pop namespace -#line 79 "zx48k/strparam3.bas" +#line 81 "zx48k/strparam3.bas" END diff --git a/tests/functional/zx48k/subrec.asm b/tests/functional/zx48k/subrec.asm index 76a31a3e7..16a703f8b 100644 --- a/tests/functional/zx48k/subrec.asm +++ b/tests/functional/zx48k/subrec.asm @@ -50,6 +50,7 @@ _x: push de push hl call _fact + call .core.COPY_ATTR ld hl, .LABEL.__LABEL5 xor a call .core.__PRINTSTR @@ -204,90 +205,8 @@ CLS: ret ENDP pop namespace -#line 116 "zx48k/subrec.bas" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/mul32.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/_mul32.asm" -; Ripped from: http://www.andreadrian.de/oldcpu/z80_number_cruncher.html#moztocid784223 - ; Used with permission. - ; Multiplies 32x32 bit integer (DEHL x D'E'H'L') - ; 64bit result is returned in H'L'H L B'C'A C - push namespace core -__MUL32_64START: - push hl - exx - ld b, h - ld c, l ; BC = Low Part (A) - pop hl ; HL = Load Part (B) - ex de, hl ; DE = Low Part (B), HL = HightPart(A) (must be in B'C') - push hl - exx - pop bc ; B'C' = HightPart(A) - exx ; A = B'C'BC , B = D'E'DE - ; multiply routine 32 * 32bit = 64bit - ; h'l'hlb'c'ac = b'c'bc * d'e'de - ; needs register a, changes flags - ; - ; this routine was with tiny differences in the - ; sinclair zx81 rom for the mantissa multiply -__LMUL: - xor a ; reset carry flag - ld h, a ; result bits 32..47 = 0 - ld l, a - exx - ld h, a ; result bits 48..63 = 0 - ld l, a - exx - ld a,b ; mpr is b'c'ac - ld b,33 ; initialize loop counter - jp __LMULSTART -__LMULLOOP: - jr nc,__LMULNOADD ; JP is 2 cycles faster than JR. Since it's inside a LOOP - ; it can save up to 33 * 2 = 66 cycles - ; But JR if 3 cycles faster if JUMP not taken! - add hl,de ; result += mpd - exx - adc hl,de - exx -__LMULNOADD: - exx - rr h ; right shift upper - rr l ; 32bit of result - exx - rr h - rr l -__LMULSTART: - exx - rr b ; right shift mpr/ - rr c ; lower 32bit of result - exx - rra ; equivalent to rr a - rr c - djnz __LMULLOOP - ret ; result in h'l'hlb'c'ac - pop namespace -#line 2 "/zxbasic/src/arch/zx48k/library-asm/mul32.asm" - push namespace core -__MUL32: - ; multiplies 32 bit un/signed integer. - ; First operand stored in DEHL, and 2nd onto stack - ; Lowest part of 2nd operand on top of the stack - ; returns the result in DE.HL - exx - pop hl ; Return ADDRESS - pop de ; Low part - ex (sp), hl ; CALLEE -> HL = High part - ex de, hl - call __MUL32_64START -__TO32BIT: ; Converts H'L'HLB'C'AC to DEHL (Discards H'L'HL) - exx - push bc - exx - pop de - ld h, a - ld l, c - ret - pop namespace #line 117 "zx48k/subrec.bas" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" #line 1 "/zxbasic/src/arch/zx48k/library-asm/print.asm" ; vim:ts=4:sw=4:et: ; PRINT command routine @@ -610,60 +529,6 @@ BRIGHT_TMP: #line 1 "/zxbasic/src/arch/zx48k/library-asm/over.asm" ; Sets OVER flag in P_FLAG permanently ; Parameter: OVER flag in bit 0 of A register -#line 1 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" -#line 4 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" - push namespace core -COPY_ATTR: - ; Just copies current permanent attribs into temporal attribs - ; and sets print mode - PROC - LOCAL INVERSE1 - LOCAL __REFRESH_TMP - INVERSE1 EQU 02Fh - ld hl, (ATTR_P) - ld (ATTR_T), hl - ld hl, FLAGS2 - call __REFRESH_TMP - ld hl, P_FLAG - call __REFRESH_TMP -__SET_ATTR_MODE: ; Another entry to set print modes. A contains (P_FLAG) - LOCAL TABLE - LOCAL CONT2 - rra ; Over bit to carry - ld a, (FLAGS2) - rla ; Over bit in bit 1, Over2 bit in bit 2 - and 3 ; Only bit 0 and 1 (OVER flag) - ld c, a - ld b, 0 - ld hl, TABLE - add hl, bc - ld a, (hl) - ld (PRINT_MODE), a - ld hl, (P_FLAG) - xor a ; NOP -> INVERSE0 - bit 2, l - jr z, CONT2 - ld a, INVERSE1 ; CPL -> INVERSE1 -CONT2: - ld (INVERSE_MODE), a - ret -TABLE: - nop ; NORMAL MODE - xor (hl) ; OVER 1 MODE - and (hl) ; OVER 2 MODE - or (hl) ; OVER 3 MODE -#line 67 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" -__REFRESH_TMP: - ld a, (hl) - and 0b10101010 - ld c, a - rra - or c - ld (hl), a - ret - ENDP - pop namespace -#line 4 "/zxbasic/src/arch/zx48k/library-asm/over.asm" push namespace core OVER: PROC @@ -905,11 +770,10 @@ INVERSE_MODE: ; 00 -> NOP -> INVERSE 0 inc hl ld (DFCC), hl ld hl, (DFCCL) ; current ATTR Pos - push hl - call __SET_ATTR - pop hl inc hl - ld (DFCCL),hl + ld (DFCCL), hl + dec hl + call __SET_ATTR exx ret ; ------------- SPECIAL CHARS (< 32) ----------------- @@ -928,7 +792,7 @@ __PRINT_0Dh: ; Called WHEN printing CHR$(13) push hl call __SCROLL_SCR pop hl -#line 210 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 209 "/zxbasic/src/arch/zx48k/library-asm/print.asm" 1: ld l, 1 __PRINT_EOL_END: @@ -1045,14 +909,14 @@ __PRINT_BOLD: __PRINT_BOLD2: call BOLD_TMP jp __PRINT_RESTART -#line 354 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 353 "/zxbasic/src/arch/zx48k/library-asm/print.asm" __PRINT_ITA: ld hl, __PRINT_ITA2 jp __PRINT_SET_STATE __PRINT_ITA2: call ITALIC_TMP jp __PRINT_RESTART -#line 364 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 363 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __BOLD __BOLD: push hl @@ -1070,7 +934,7 @@ __BOLD: pop hl ld de, MEM0 ret -#line 385 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 384 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __ITALIC __ITALIC: push hl @@ -1095,12 +959,12 @@ __ITALIC: pop hl ld de, MEM0 ret -#line 413 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 412 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __SCROLL_SCR -#line 487 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 486 "/zxbasic/src/arch/zx48k/library-asm/print.asm" __SCROLL_SCR EQU 0DFEh ; Use ROM SCROLL +#line 488 "/zxbasic/src/arch/zx48k/library-asm/print.asm" #line 489 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -#line 490 "/zxbasic/src/arch/zx48k/library-asm/print.asm" PRINT_COMMA: call __LOAD_S_POSN ld a, e @@ -1143,9 +1007,9 @@ PRINT_AT: ; Changes cursor to ROW, COL LOCAL __PRINT_TABLE LOCAL __PRINT_TAB, __PRINT_TAB1, __PRINT_TAB2 LOCAL __PRINT_ITA2 -#line 546 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 545 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __PRINT_BOLD2 -#line 552 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 551 "/zxbasic/src/arch/zx48k/library-asm/print.asm" __PRINT_TABLE: ; Jump table for 0 .. 22 codes DW __PRINT_NOP ; 0 DW __PRINT_NOP ; 1 @@ -1173,7 +1037,143 @@ __PRINT_TABLE: ; Jump table for 0 .. 22 codes DW __PRINT_TAB ; 23 TAB ENDP pop namespace +#line 3 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" +#line 4 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" + push namespace core +COPY_ATTR: + ; Just copies current permanent attribs into temporal attribs + ; and sets print mode + PROC + LOCAL INVERSE1 + LOCAL __REFRESH_TMP + INVERSE1 EQU 02Fh + ld hl, (ATTR_P) + ld (ATTR_T), hl + ld hl, FLAGS2 + call __REFRESH_TMP + ld hl, P_FLAG + call __REFRESH_TMP +__SET_ATTR_MODE: ; Another entry to set print modes. A contains (P_FLAG) + LOCAL TABLE + LOCAL CONT2 + rra ; Over bit to carry + ld a, (FLAGS2) + rla ; Over bit in bit 1, Over2 bit in bit 2 + and 3 ; Only bit 0 and 1 (OVER flag) + ld c, a + ld b, 0 + ld hl, TABLE + add hl, bc + ld a, (hl) + ld (PRINT_MODE), a + ld hl, (P_FLAG) + xor a ; NOP -> INVERSE0 + bit 2, l + jr z, CONT2 + ld a, INVERSE1 ; CPL -> INVERSE1 +CONT2: + ld (INVERSE_MODE), a + ret +TABLE: + nop ; NORMAL MODE + xor (hl) ; OVER 1 MODE + and (hl) ; OVER 2 MODE + or (hl) ; OVER 3 MODE +#line 67 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" +__REFRESH_TMP: + ld a, (hl) + and 0b10101010 + ld c, a + rra + or c + ld (hl), a + ret + ENDP + pop namespace #line 118 "zx48k/subrec.bas" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/mul32.asm" +#line 1 "/zxbasic/src/arch/zx48k/library-asm/_mul32.asm" +; Ripped from: http://www.andreadrian.de/oldcpu/z80_number_cruncher.html#moztocid784223 + ; Used with permission. + ; Multiplies 32x32 bit integer (DEHL x D'E'H'L') + ; 64bit result is returned in H'L'H L B'C'A C + push namespace core +__MUL32_64START: + push hl + exx + ld b, h + ld c, l ; BC = Low Part (A) + pop hl ; HL = Load Part (B) + ex de, hl ; DE = Low Part (B), HL = HightPart(A) (must be in B'C') + push hl + exx + pop bc ; B'C' = HightPart(A) + exx ; A = B'C'BC , B = D'E'DE + ; multiply routine 32 * 32bit = 64bit + ; h'l'hlb'c'ac = b'c'bc * d'e'de + ; needs register a, changes flags + ; + ; this routine was with tiny differences in the + ; sinclair zx81 rom for the mantissa multiply +__LMUL: + xor a ; reset carry flag + ld h, a ; result bits 32..47 = 0 + ld l, a + exx + ld h, a ; result bits 48..63 = 0 + ld l, a + exx + ld a,b ; mpr is b'c'ac + ld b,33 ; initialize loop counter + jp __LMULSTART +__LMULLOOP: + jr nc,__LMULNOADD ; JP is 2 cycles faster than JR. Since it's inside a LOOP + ; it can save up to 33 * 2 = 66 cycles + ; But JR if 3 cycles faster if JUMP not taken! + add hl,de ; result += mpd + exx + adc hl,de + exx +__LMULNOADD: + exx + rr h ; right shift upper + rr l ; 32bit of result + exx + rr h + rr l +__LMULSTART: + exx + rr b ; right shift mpr/ + rr c ; lower 32bit of result + exx + rra ; equivalent to rr a + rr c + djnz __LMULLOOP + ret ; result in h'l'hlb'c'ac + pop namespace +#line 2 "/zxbasic/src/arch/zx48k/library-asm/mul32.asm" + push namespace core +__MUL32: + ; multiplies 32 bit un/signed integer. + ; First operand stored in DEHL, and 2nd onto stack + ; Lowest part of 2nd operand on top of the stack + ; returns the result in DE.HL + exx + pop hl ; Return ADDRESS + pop de ; Low part + ex (sp), hl ; CALLEE -> HL = High part + ex de, hl + call __MUL32_64START +__TO32BIT: ; Converts H'L'HLB'C'AC to DEHL (Discards H'L'HL) + exx + push bc + exx + pop de + ld h, a + ld l, c + ret + pop namespace +#line 119 "zx48k/subrec.bas" #line 1 "/zxbasic/src/arch/zx48k/library-asm/printstr.asm" #line 1 "/zxbasic/src/arch/zx48k/library-asm/free.asm" ; vim: ts=4:et:sw=4: @@ -1484,7 +1484,7 @@ __PRINT_STR: jp __PRINT_STR_LOOP ENDP pop namespace -#line 119 "zx48k/subrec.bas" +#line 121 "zx48k/subrec.bas" #line 1 "/zxbasic/src/arch/zx48k/library-asm/printu32.asm" #line 1 "/zxbasic/src/arch/zx48k/library-asm/printi32.asm" #line 1 "/zxbasic/src/arch/zx48k/library-asm/printnum.asm" @@ -1685,7 +1685,7 @@ __PRINTU_LOOP: ENDP pop namespace #line 2 "/zxbasic/src/arch/zx48k/library-asm/printu32.asm" -#line 120 "zx48k/subrec.bas" +#line 122 "zx48k/subrec.bas" #line 1 "/zxbasic/src/arch/zx48k/library-asm/printu8.asm" #line 1 "/zxbasic/src/arch/zx48k/library-asm/printi8.asm" #line 1 "/zxbasic/src/arch/zx48k/library-asm/div8.asm" @@ -1783,7 +1783,7 @@ __PRINTU_LOOP: ENDP pop namespace #line 2 "/zxbasic/src/arch/zx48k/library-asm/printu8.asm" -#line 121 "zx48k/subrec.bas" +#line 123 "zx48k/subrec.bas" #line 1 "/zxbasic/src/arch/zx48k/library-asm/sub32.asm" ; SUB32 ; Perform TOP of the stack - DEHL @@ -1810,5 +1810,5 @@ __SUB32: exx ret pop namespace -#line 122 "zx48k/subrec.bas" +#line 124 "zx48k/subrec.bas" END diff --git a/tests/functional/zx48k/tap_00.tap b/tests/functional/zx48k/tap_00.tap index a5664525f..9e808009e 100644 Binary files a/tests/functional/zx48k/tap_00.tap and b/tests/functional/zx48k/tap_00.tap differ diff --git a/tests/functional/zx48k/tzx_00.tzx b/tests/functional/zx48k/tzx_00.tzx index f99ff5767..8146e3f0b 100644 Binary files a/tests/functional/zx48k/tzx_00.tzx and b/tests/functional/zx48k/tzx_00.tzx differ diff --git a/tests/functional/zx48k/usr0.asm b/tests/functional/zx48k/usr0.asm index 431c88339..71bc4eebc 100644 --- a/tests/functional/zx48k/usr0.asm +++ b/tests/functional/zx48k/usr0.asm @@ -26,6 +26,7 @@ .core.__LABEL__.ZXBASIC_USER_DATA EQU .core.ZXBASIC_USER_DATA .core.ZXBASIC_USER_DATA_END: .core.__MAIN_PROGRAM__: + call .core.COPY_ATTR ld hl, .LABEL.__LABEL0 xor a call .core.USR_STR @@ -49,6 +50,7 @@ DEFW 0001h DEFB 41h ;; --- end of user code --- +#line 1 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" #line 1 "/zxbasic/src/arch/zx48k/library-asm/print.asm" ; vim:ts=4:sw=4:et: ; PRINT command routine @@ -398,60 +400,6 @@ BRIGHT_TMP: #line 1 "/zxbasic/src/arch/zx48k/library-asm/over.asm" ; Sets OVER flag in P_FLAG permanently ; Parameter: OVER flag in bit 0 of A register -#line 1 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" -#line 4 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" - push namespace core -COPY_ATTR: - ; Just copies current permanent attribs into temporal attribs - ; and sets print mode - PROC - LOCAL INVERSE1 - LOCAL __REFRESH_TMP - INVERSE1 EQU 02Fh - ld hl, (ATTR_P) - ld (ATTR_T), hl - ld hl, FLAGS2 - call __REFRESH_TMP - ld hl, P_FLAG - call __REFRESH_TMP -__SET_ATTR_MODE: ; Another entry to set print modes. A contains (P_FLAG) - LOCAL TABLE - LOCAL CONT2 - rra ; Over bit to carry - ld a, (FLAGS2) - rla ; Over bit in bit 1, Over2 bit in bit 2 - and 3 ; Only bit 0 and 1 (OVER flag) - ld c, a - ld b, 0 - ld hl, TABLE - add hl, bc - ld a, (hl) - ld (PRINT_MODE), a - ld hl, (P_FLAG) - xor a ; NOP -> INVERSE0 - bit 2, l - jr z, CONT2 - ld a, INVERSE1 ; CPL -> INVERSE1 -CONT2: - ld (INVERSE_MODE), a - ret -TABLE: - nop ; NORMAL MODE - xor (hl) ; OVER 1 MODE - and (hl) ; OVER 2 MODE - or (hl) ; OVER 3 MODE -#line 67 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" -__REFRESH_TMP: - ld a, (hl) - and 0b10101010 - ld c, a - rra - or c - ld (hl), a - ret - ENDP - pop namespace -#line 4 "/zxbasic/src/arch/zx48k/library-asm/over.asm" push namespace core OVER: PROC @@ -693,11 +641,10 @@ INVERSE_MODE: ; 00 -> NOP -> INVERSE 0 inc hl ld (DFCC), hl ld hl, (DFCCL) ; current ATTR Pos - push hl - call __SET_ATTR - pop hl inc hl - ld (DFCCL),hl + ld (DFCCL), hl + dec hl + call __SET_ATTR exx ret ; ------------- SPECIAL CHARS (< 32) ----------------- @@ -716,7 +663,7 @@ __PRINT_0Dh: ; Called WHEN printing CHR$(13) push hl call __SCROLL_SCR pop hl -#line 210 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 209 "/zxbasic/src/arch/zx48k/library-asm/print.asm" 1: ld l, 1 __PRINT_EOL_END: @@ -833,14 +780,14 @@ __PRINT_BOLD: __PRINT_BOLD2: call BOLD_TMP jp __PRINT_RESTART -#line 354 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 353 "/zxbasic/src/arch/zx48k/library-asm/print.asm" __PRINT_ITA: ld hl, __PRINT_ITA2 jp __PRINT_SET_STATE __PRINT_ITA2: call ITALIC_TMP jp __PRINT_RESTART -#line 364 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 363 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __BOLD __BOLD: push hl @@ -858,7 +805,7 @@ __BOLD: pop hl ld de, MEM0 ret -#line 385 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 384 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __ITALIC __ITALIC: push hl @@ -883,12 +830,12 @@ __ITALIC: pop hl ld de, MEM0 ret -#line 413 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 412 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __SCROLL_SCR -#line 487 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 486 "/zxbasic/src/arch/zx48k/library-asm/print.asm" __SCROLL_SCR EQU 0DFEh ; Use ROM SCROLL +#line 488 "/zxbasic/src/arch/zx48k/library-asm/print.asm" #line 489 "/zxbasic/src/arch/zx48k/library-asm/print.asm" -#line 490 "/zxbasic/src/arch/zx48k/library-asm/print.asm" PRINT_COMMA: call __LOAD_S_POSN ld a, e @@ -931,9 +878,9 @@ PRINT_AT: ; Changes cursor to ROW, COL LOCAL __PRINT_TABLE LOCAL __PRINT_TAB, __PRINT_TAB1, __PRINT_TAB2 LOCAL __PRINT_ITA2 -#line 546 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 545 "/zxbasic/src/arch/zx48k/library-asm/print.asm" LOCAL __PRINT_BOLD2 -#line 552 "/zxbasic/src/arch/zx48k/library-asm/print.asm" +#line 551 "/zxbasic/src/arch/zx48k/library-asm/print.asm" __PRINT_TABLE: ; Jump table for 0 .. 22 codes DW __PRINT_NOP ; 0 DW __PRINT_NOP ; 1 @@ -961,7 +908,60 @@ __PRINT_TABLE: ; Jump table for 0 .. 22 codes DW __PRINT_TAB ; 23 TAB ENDP pop namespace -#line 25 "zx48k/usr0.bas" +#line 3 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" +#line 4 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" + push namespace core +COPY_ATTR: + ; Just copies current permanent attribs into temporal attribs + ; and sets print mode + PROC + LOCAL INVERSE1 + LOCAL __REFRESH_TMP + INVERSE1 EQU 02Fh + ld hl, (ATTR_P) + ld (ATTR_T), hl + ld hl, FLAGS2 + call __REFRESH_TMP + ld hl, P_FLAG + call __REFRESH_TMP +__SET_ATTR_MODE: ; Another entry to set print modes. A contains (P_FLAG) + LOCAL TABLE + LOCAL CONT2 + rra ; Over bit to carry + ld a, (FLAGS2) + rla ; Over bit in bit 1, Over2 bit in bit 2 + and 3 ; Only bit 0 and 1 (OVER flag) + ld c, a + ld b, 0 + ld hl, TABLE + add hl, bc + ld a, (hl) + ld (PRINT_MODE), a + ld hl, (P_FLAG) + xor a ; NOP -> INVERSE0 + bit 2, l + jr z, CONT2 + ld a, INVERSE1 ; CPL -> INVERSE1 +CONT2: + ld (INVERSE_MODE), a + ret +TABLE: + nop ; NORMAL MODE + xor (hl) ; OVER 1 MODE + and (hl) ; OVER 2 MODE + or (hl) ; OVER 3 MODE +#line 67 "/zxbasic/src/arch/zx48k/library-asm/copy_attr.asm" +__REFRESH_TMP: + ld a, (hl) + and 0b10101010 + ld c, a + rra + or c + ld (hl), a + ret + ENDP + pop namespace +#line 26 "zx48k/usr0.bas" #line 1 "/zxbasic/src/arch/zx48k/library-asm/printu16.asm" #line 1 "/zxbasic/src/arch/zx48k/library-asm/printi16.asm" #line 1 "/zxbasic/src/arch/zx48k/library-asm/printnum.asm" @@ -1109,7 +1109,7 @@ __PRINTU_LOOP: ENDP pop namespace #line 2 "/zxbasic/src/arch/zx48k/library-asm/printu16.asm" -#line 26 "zx48k/usr0.bas" +#line 28 "zx48k/usr0.bas" #line 1 "/zxbasic/src/arch/zx48k/library-asm/usr_str.asm" ; This function just returns the address of the UDG of the given str. ; If the str is EMPTY or not a letter, 0 is returned and ERR_NR set @@ -1433,5 +1433,5 @@ USR_ERROR: ret ENDP pop namespace -#line 27 "zx48k/usr0.bas" +#line 29 "zx48k/usr0.bas" END diff --git a/tests/runtime/cases/drawing_primitives.bas b/tests/runtime/cases/drawing_primitives.bas new file mode 100644 index 000000000..a7a9b5462 --- /dev/null +++ b/tests/runtime/cases/drawing_primitives.bas @@ -0,0 +1,21 @@ +#include "lib/tst_framework.bas" + +INIT("Testing PRINT color") + +Declare sub CenterText (ByVal Row as ubyte, ByVal Text as string) + +Ink 6 +Paper 1 +Print "x"; + +Ink 7 +Paper 0 +Text ("Hello") +FINISH + +Sub Text (ByVal Txt as string) + PLOT 10, 10 + DRAW 20, 20 + CIRCLE 100, 100, 20 + DRAW 30, 30, 30 +End sub diff --git a/tests/runtime/cases/print_color.bas b/tests/runtime/cases/print_color.bas new file mode 100644 index 000000000..80deded99 --- /dev/null +++ b/tests/runtime/cases/print_color.bas @@ -0,0 +1,18 @@ +#include "lib/tst_framework.bas" + +INIT("Testing PRINT color") + +Declare sub CenterText (ByVal Row as ubyte, ByVal Text as string) + +Ink 6 +Paper 1 +Print "x"; + +Ink 7 +Paper 0 +Text ("Hello") +FINISH + +Sub Text (ByVal Txt as string) + PRINT Txt; +End sub diff --git a/tests/runtime/expected/drawing_primitives.tzx.scr b/tests/runtime/expected/drawing_primitives.tzx.scr new file mode 100644 index 000000000..1825199e0 Binary files /dev/null and b/tests/runtime/expected/drawing_primitives.tzx.scr differ diff --git a/tests/runtime/expected/print_color.tzx.scr b/tests/runtime/expected/print_color.tzx.scr new file mode 100644 index 000000000..6615f9adf Binary files /dev/null and b/tests/runtime/expected/print_color.tzx.scr differ