From 0a5ae81957c2aea8665f6c6a4448756017313fc4 Mon Sep 17 00:00:00 2001 From: Jose Rodriguez Date: Sun, 15 Dec 2024 11:26:23 +0100 Subject: [PATCH 1/3] fix: crash on PRINT (a = a) --- src/arch/z80/visitor/translator.py | 1 + src/arch/z80/visitor/translator_inst_visitor.py | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/arch/z80/visitor/translator.py b/src/arch/z80/visitor/translator.py index 86f735e72..db2c1caea 100644 --- a/src/arch/z80/visitor/translator.py +++ b/src/arch/z80/visitor/translator.py @@ -794,6 +794,7 @@ def visit_PRINT(self, node): self.ic_fparam(i.type_, i.t) label = { + "bool": RuntimeLabel.PRINTU8, "i8": RuntimeLabel.PRINTI8, "u8": RuntimeLabel.PRINTU8, "i16": RuntimeLabel.PRINTI16, diff --git a/src/arch/z80/visitor/translator_inst_visitor.py b/src/arch/z80/visitor/translator_inst_visitor.py index 04c100e11..adaa870a3 100644 --- a/src/arch/z80/visitor/translator_inst_visitor.py +++ b/src/arch/z80/visitor/translator_inst_visitor.py @@ -106,7 +106,7 @@ def ic_exchg(self) -> None: self.emit("exchg") def ic_fparam(self, type_: TYPE | symbols.BASICTYPE, t) -> None: - self.emit("fparam" + self.TSUFFIX(type_), t) + self.emit(f"fparam{self._no_bool(type_)}", t) def ic_fpload(self, type_: TYPE | symbols.BASICTYPE, t, offset) -> None: self.emit("fpload" + self.TSUFFIX(type_), t, offset) From 1e8a9a43c10b7fa419ee00ef84cfc6da138aac98 Mon Sep 17 00:00:00 2001 From: Jose Rodriguez Date: Tue, 17 Dec 2024 00:10:50 +0100 Subject: [PATCH 2/3] feat: ensure PRINTs output actual normalized bool --- src/parsetab/tabs.dbm.bak | 2 +- src/parsetab/tabs.dbm.dat | Bin 1201315 -> 1201342 bytes src/parsetab/tabs.dbm.dir | 2 +- src/zxbc/zxbparser.py | 10 ++++++++-- 4 files changed, 10 insertions(+), 4 deletions(-) diff --git a/src/parsetab/tabs.dbm.bak b/src/parsetab/tabs.dbm.bak index 342fa703c..9357bb728 100644 --- a/src/parsetab/tabs.dbm.bak +++ b/src/parsetab/tabs.dbm.bak @@ -1,4 +1,4 @@ 'zxbpp', (0, 67003) 'asmparse', (67072, 233956) 'zxnext_asmparse', (301056, 259034) -'zxbparser', (560128, 641187) +'zxbparser', (560128, 641214) diff --git a/src/parsetab/tabs.dbm.dat b/src/parsetab/tabs.dbm.dat index e65a05f9af9389e0b7cb40ba04d7940f297bdb41..3dd407408656a536b75cf6f112a5780220736dba 100644 GIT binary patch delta 31662 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 diff --git a/src/parsetab/tabs.dbm.dir b/src/parsetab/tabs.dbm.dir index 342fa703c..9357bb728 100644 --- a/src/parsetab/tabs.dbm.dir +++ b/src/parsetab/tabs.dbm.dir @@ -1,4 +1,4 @@ 'zxbpp', (0, 67003) 'asmparse', (67072, 233956) 'zxnext_asmparse', (301056, 259034) -'zxbparser', (560128, 641187) +'zxbparser', (560128, 641214) diff --git a/src/zxbc/zxbparser.py b/src/zxbc/zxbparser.py index 3abc576a3..fde90fc35 100755 --- a/src/zxbc/zxbparser.py +++ b/src/zxbc/zxbparser.py @@ -1983,9 +1983,15 @@ def p_print_sentence(p): PRINT_IS_USED = True +def p_print_elem_expr(p): + """print_elem : expr""" + p[0] = p[1] + if p[1] is not None and p[1].type_ == TYPE.boolean: + p[0] = make_typecast(TYPE.ubyte, p[1], p.lineno(1)) + + def p_print_list_expr(p): - """print_elem : expr - | print_at + """print_elem : print_at | print_tab | attr | BOLD expr From 49142e9c7495b9025e3eda39b8dbb4a339cced46 Mon Sep 17 00:00:00 2001 From: Jose Rodriguez Date: Tue, 17 Dec 2024 00:13:12 +0100 Subject: [PATCH 3/3] test: add tests --- tests/functional/arch/zx48k/print_bool.asm | 1086 ++++++++++++++++++++ tests/functional/arch/zx48k/print_bool.bas | 3 + 2 files changed, 1089 insertions(+) create mode 100644 tests/functional/arch/zx48k/print_bool.asm create mode 100644 tests/functional/arch/zx48k/print_bool.bas diff --git a/tests/functional/arch/zx48k/print_bool.asm b/tests/functional/arch/zx48k/print_bool.asm new file mode 100644 index 000000000..66c092897 --- /dev/null +++ b/tests/functional/arch/zx48k/print_bool.asm @@ -0,0 +1,1086 @@ + org 32768 +.core.__START_PROGRAM: + di + push ix + push iy + exx + push hl + exx + ld hl, 0 + add hl, sp + ld (.core.__CALL_BACK__), hl + ei + call .core.__PRINT_INIT + jp .core.__MAIN_PROGRAM__ +.core.__CALL_BACK__: + DEFW 0 +.core.ZXBASIC_USER_DATA: + ; Defines USER DATA Length in bytes +.core.ZXBASIC_USER_DATA_LEN EQU .core.ZXBASIC_USER_DATA_END - .core.ZXBASIC_USER_DATA + .core.__LABEL__.ZXBASIC_USER_DATA_LEN EQU .core.ZXBASIC_USER_DATA_LEN + .core.__LABEL__.ZXBASIC_USER_DATA EQU .core.ZXBASIC_USER_DATA +_a: + DEFB 00 +.core.ZXBASIC_USER_DATA_END: +.core.__MAIN_PROGRAM__: + call .core.COPY_ATTR + ld hl, (_a - 1) + ld a, (_a) + sub h + sub 1 + sbc a, a + neg + call .core.__PRINTU8 + call .core.PRINT_EOL + ld hl, 0 + ld b, h + ld c, l +.core.__END_PROGRAM: + di + ld hl, (.core.__CALL_BACK__) + ld sp, hl + exx + pop hl + exx + pop iy + pop ix + ei + ret + ;; --- end of user code --- +#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/copy_attr.asm" +#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/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/lib/arch/zx48k/runtime/sposn.asm" +#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/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 + TV_FLAG EQU 23612 ; Flags for controlling output to screen + 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/lib/arch/zx48k/runtime/sposn.asm" +#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/attr.asm" + ; Attribute routines +; vim:ts=4:et:sw: +#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/error.asm" + ; Simple error control routines +; vim:ts=4:et: + 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 + 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/lib/arch/zx48k/runtime/attr.asm" +#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/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/lib/arch/zx48k/runtime/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/lib/arch/zx48k/runtime/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/lib/arch/zx48k/runtime/print.asm" +#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/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/lib/arch/zx48k/runtime/print.asm" +#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/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/lib/arch/zx48k/runtime/print.asm" +#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/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/lib/arch/zx48k/runtime/print.asm" +#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/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 + 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/lib/arch/zx48k/runtime/print.asm" +#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/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 + 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/lib/arch/zx48k/runtime/print.asm" +#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/over.asm" + ; Sets OVER flag in P_FLAG permanently +; Parameter: OVER flag in bit 0 of A register + 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/lib/arch/zx48k/runtime/print.asm" +#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/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/lib/arch/zx48k/runtime/print.asm" +#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/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/lib/arch/zx48k/runtime/print.asm" +#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/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 + 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 16 "/zxbasic/src/lib/arch/zx48k/runtime/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 + ld hl, TV_FLAG + res 0, (hl) + 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 94 "/zxbasic/src/lib/arch/zx48k/runtime/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 141 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" + bit 4, (iy + $47) + call nz, __ITALIC +#line 146 "/zxbasic/src/lib/arch/zx48k/runtime/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 + ; ------------- 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 211 "/zxbasic/src/lib/arch/zx48k/runtime/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 355 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" +__PRINT_ITA: + ld hl, __PRINT_ITA2 + jp __PRINT_SET_STATE +__PRINT_ITA2: + call ITALIC_TMP + jp __PRINT_RESTART +#line 365 "/zxbasic/src/lib/arch/zx48k/runtime/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 + inc de + djnz 1b + pop hl + ld de, MEM0 + ret +#line 386 "/zxbasic/src/lib/arch/zx48k/runtime/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 414 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" + LOCAL __SCROLL_SCR +#line 488 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" + __SCROLL_SCR EQU 0DFEh ; Use ROM SCROLL +#line 490 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" +#line 491 "/zxbasic/src/lib/arch/zx48k/runtime/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 547 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" + LOCAL __PRINT_BOLD2 +#line 553 "/zxbasic/src/lib/arch/zx48k/runtime/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/lib/arch/zx48k/runtime/copy_attr.asm" +#line 4 "/zxbasic/src/lib/arch/zx48k/runtime/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/lib/arch/zx48k/runtime/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 "arch/zx48k/print_bool.bas" +#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/printu8.asm" +#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/printi8.asm" +#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/printnum.asm" + push namespace core +__PRINTU_START: + PROC + LOCAL __PRINTU_CONT + ld a, b + or a + jp nz, __PRINTU_CONT + ld a, '0' + jp __PRINT_DIGIT +__PRINTU_CONT: + pop af + push bc + call __PRINT_DIGIT + pop bc + djnz __PRINTU_CONT + ret + ENDP +__PRINT_MINUS: ; PRINT the MINUS (-) sign. CALLER must preserve registers + ld a, '-' + jp __PRINT_DIGIT + __PRINT_DIGIT EQU __PRINTCHAR ; PRINTS the char in A register, and puts its attrs + pop namespace +#line 2 "/zxbasic/src/lib/arch/zx48k/runtime/printi8.asm" +#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/arith/div8.asm" + ; -------------------------------- + push namespace core +__DIVU8: ; 8 bit unsigned integer division + ; Divides (Top of stack, High Byte) / A + pop hl ; -------------------------------- + ex (sp), hl ; CALLEE +__DIVU8_FAST: ; Does A / H + ld l, h + ld h, a ; At this point do H / L + ld b, 8 + xor a ; A = 0, Carry Flag = 0 +__DIV8LOOP: + sla h + rla + cp l + jr c, __DIV8NOSUB + sub l + inc h +__DIV8NOSUB: + djnz __DIV8LOOP + ld l, a ; save remainder + ld a, h ; + ret ; a = Quotient, + ; -------------------------------- +__DIVI8: ; 8 bit signed integer division Divides (Top of stack) / A + pop hl ; -------------------------------- + ex (sp), hl +__DIVI8_FAST: + ld e, a ; store operands for later + ld c, h + or a ; negative? + jp p, __DIV8A + neg ; Make it positive +__DIV8A: + ex af, af' + ld a, h + or a + jp p, __DIV8B + neg + ld h, a ; make it positive +__DIV8B: + ex af, af' + call __DIVU8_FAST + ld a, c + xor l ; bit 7 of A = 1 if result is negative + ld a, h ; Quotient + ret p ; return if positive + neg + ret +__MODU8: ; 8 bit module. REturns A mod (Top of stack) (unsigned operands) + pop hl + ex (sp), hl ; CALLEE +__MODU8_FAST: ; __FASTCALL__ entry + call __DIVU8_FAST + ld a, l ; Remainder + ret ; a = Modulus +__MODI8: ; 8 bit module. REturns A mod (Top of stack) (For singed operands) + pop hl + ex (sp), hl ; CALLEE +__MODI8_FAST: ; __FASTCALL__ entry + call __DIVI8_FAST + ld a, l ; remainder + ret ; a = Modulus + pop namespace +#line 3 "/zxbasic/src/lib/arch/zx48k/runtime/printi8.asm" + push namespace core +__PRINTI8: ; Prints an 8 bits number in Accumulator (A) + ; Converts 8 to 32 bits + or a + jp p, __PRINTU8 + push af + call __PRINT_MINUS + pop af + neg +__PRINTU8: + PROC + LOCAL __PRINTU_LOOP + ld b, 0 ; Counter +__PRINTU_LOOP: + or a + jp z, __PRINTU_START + push bc + ld h, 10 + call __DIVU8_FAST ; Divides by 10. D'E'H'L' contains modulo (L' since < 10) + pop bc + ld a, l + or '0' ; Stores ASCII digit (must be print in reversed order) + push af + ld a, h + inc b + jp __PRINTU_LOOP ; Uses JP in loops + ENDP + pop namespace +#line 2 "/zxbasic/src/lib/arch/zx48k/runtime/printu8.asm" +#line 28 "arch/zx48k/print_bool.bas" + END diff --git a/tests/functional/arch/zx48k/print_bool.bas b/tests/functional/arch/zx48k/print_bool.bas new file mode 100644 index 000000000..2d0116264 --- /dev/null +++ b/tests/functional/arch/zx48k/print_bool.bas @@ -0,0 +1,3 @@ +DIM a as UByte + +PRINT (a = a)