diff --git a/tests/functional/arch/zx48k/einarshift.asm b/tests/functional/arch/zx48k/einarshift.asm index 9a5a70900..2b7a93d86 100644 --- a/tests/functional/arch/zx48k/einarshift.asm +++ b/tests/functional/arch/zx48k/einarshift.asm @@ -10,7 +10,6 @@ add hl, sp ld (.core.__CALL_BACK__), hl ei - call .core.__PRINT_INIT jp .core.__MAIN_PROGRAM__ .core.__CALL_BACK__: DEFW 0 @@ -25,7 +24,6 @@ _b: DEFB 02h .core.ZXBASIC_USER_DATA_END: .core.__MAIN_PROGRAM__: - call .core.COPY_ATTR ld a, 3 ld hl, (_b - 1) sub h @@ -38,8 +36,7 @@ _b: add a, a djnz .LABEL.__LABEL0 .LABEL.__LABEL1: - call .core.__PRINTU8 - call .core.PRINT_EOL + ld (_a), a ld hl, 0 ld b, h ld c, l @@ -55,1040 +52,4 @@ _b: 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 32 "arch/zx48k/einarshift.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/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 34 "arch/zx48k/einarshift.bas" END diff --git a/tests/functional/arch/zx48k/einarshift.bas b/tests/functional/arch/zx48k/einarshift.bas index 246062891..60364b798 100644 --- a/tests/functional/arch/zx48k/einarshift.bas +++ b/tests/functional/arch/zx48k/einarshift.bas @@ -1,4 +1,4 @@ DIM a AS UBYTE = 3 DIM b AS UBYTE = 2 - PRINT a << (3-b) + LET a = a << (3-b) diff --git a/tests/functional/arch/zx48k/fact.asm b/tests/functional/arch/zx48k/fact.asm index c52d31b9d..e585a22cb 100644 --- a/tests/functional/arch/zx48k/fact.asm +++ b/tests/functional/arch/zx48k/fact.asm @@ -10,48 +10,31 @@ add hl, sp ld (.core.__CALL_BACK__), hl ei - call .core.__MEM_INIT - call .core.__PRINT_INIT jp .core.__MAIN_PROGRAM__ .core.__CALL_BACK__: DEFW 0 .core.ZXBASIC_USER_DATA: - ; Defines HEAP SIZE -.core.ZXBASIC_HEAP_SIZE EQU 4768 -.core.ZXBASIC_MEM_HEAP: - DEFS 4768 ; 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 +_y: + DEFB 00, 00, 00, 00 _x: DEFB 00 .core.ZXBASIC_USER_DATA_END: .core.__MAIN_PROGRAM__: - call .core.CLS ld a, 1 ld (_x), a jp .LABEL.__LABEL0 .LABEL.__LABEL3: - call .core.COPY_ATTR - ld hl, .LABEL.__LABEL5 - xor a - call .core.__PRINTSTR - ld a, (_x) - call .core.__PRINTU8 - ld hl, .LABEL.__LABEL6 - xor a - call .core.__PRINTSTR ld a, (_x) ld l, a ld h, 0 ld e, h ld d, h - push de - push hl - call _fact - call .core.__PRINTU32 - call .core.PRINT_EOL + ld (_y), hl + ld (_y + 2), de .LABEL.__LABEL4: ld hl, _x inc (hl) @@ -88,11 +71,11 @@ _fact: ld de, 0 ld hl, 2 call .core.__SUB32 - jp nc, .LABEL.__LABEL8 + jp nc, .LABEL.__LABEL6 ld de, 0 ld hl, 1 jp _fact__leave -.LABEL.__LABEL8: +.LABEL.__LABEL6: ld l, (ix+4) ld h, (ix+5) ld e, (ix+6) @@ -121,20 +104,6 @@ _fact__leave: ex (sp), hl exx ret -.LABEL.__LABEL5: - DEFW 0006h - DEFB 46h - DEFB 61h - DEFB 63h - DEFB 74h - DEFB 20h - DEFB 28h -.LABEL.__LABEL6: - DEFW 0004h - DEFB 29h - DEFB 20h - DEFB 3Dh - DEFB 20h ;; --- end of user code --- #line 1 "/zxbasic/src/lib/arch/zx48k/runtime/arith/mul32.asm" #line 1 "/zxbasic/src/lib/arch/zx48k/runtime/arith/_mul32.asm" @@ -219,7 +188,7 @@ __TO32BIT: ; Converts H'L'HLB'C'AC to DEHL (Discards H'L'HL) ret pop namespace f -#line 110 "arch/zx48k/fact.bas" +#line 83 "arch/zx48k/fact.bas" #line 1 "/zxbasic/src/lib/arch/zx48k/runtime/arith/sub32.asm" ; SUB32 ; Perform TOP of the stack - DEHL @@ -246,1560 +215,5 @@ __SUB32: exx ret pop namespace -#line 111 "arch/zx48k/fact.bas" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/cls.asm" - ;; Clears the user screen (24 rows) -#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 4 "/zxbasic/src/lib/arch/zx48k/runtime/cls.asm" - push namespace core -CLS: - PROC - ld hl, 0 - ld (COORDS), hl - ld hl, SCR_SIZE - ld (S_POSN), hl - ld hl, (SCREEN_ADDR) - ld (DFCC), hl - ld (hl), 0 - ld d, h - ld e, l - inc de - ld bc, 6143 - ldir - ; Now clear attributes - ld hl, (SCREEN_ATTR_ADDR) - ld (DFCCL), hl - ld d, h - ld e, l - inc de - ld a, (ATTR_P) - ld (hl), a - ld bc, 767 - ldir - ret - ENDP - pop namespace -#line 112 "arch/zx48k/fact.bas" -#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/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 113 "arch/zx48k/fact.bas" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/printstr.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/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/lib/arch/zx48k/runtime/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/lib/arch/zx48k/runtime/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 5 "/zxbasic/src/lib/arch/zx48k/runtime/printstr.asm" - ; PRINT command routine - ; Prints string pointed by HL - push namespace core -PRINT_STR: -__PRINTSTR: ; __FASTCALL__ Entry to print_string - PROC - LOCAL __PRINT_STR_LOOP - LOCAL __PRINT_STR_END - ld d, a ; Saves A reg (Flag) for later - ld a, h - or l - ret z ; Return if the pointer is NULL - push hl - ld c, (hl) - inc hl - ld b, (hl) - inc hl ; BC = LEN(a$); HL = &a$ -__PRINT_STR_LOOP: - ld a, b - or c - jr z, __PRINT_STR_END ; END if BC (counter = 0) - ld a, (hl) - call __PRINTCHAR - inc hl - dec bc - jp __PRINT_STR_LOOP -__PRINT_STR_END: - pop hl - ld a, d ; Recovers A flag - or a ; If not 0 this is a temporary string. Free it - ret z - jp __MEM_FREE ; Frees str from heap and return from there -__PRINT_STR: - ; Fastcall Entry - ; It ONLY prints strings - ; HL = String start - ; BC = String length (Number of chars) - push hl ; Push str address for later - ld d, a ; Saves a FLAG - jp __PRINT_STR_LOOP - ENDP - pop namespace -#line 115 "arch/zx48k/fact.bas" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/printu32.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/printi32.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/printi32.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/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 3 "/zxbasic/src/lib/arch/zx48k/runtime/printi32.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/arith/div32.asm" - ; --------------------------------------------------------- - push namespace core -__DIVU32: ; 32 bit unsigned division - ; DEHL = Dividend, Stack Top = Divisor - ; OPERANDS P = Dividend, Q = Divisor => OPERATION => P / Q - ; - ; Changes A, BC DE HL B'C' D'E' H'L' - ; --------------------------------------------------------- - exx - pop hl ; return address - pop de ; low part - ex (sp), hl ; CALLEE Convention ; H'L'D'E' => Dividend -__DIVU32START: ; Performs D'E'H'L' / HLDE - ; Now switch to DIVIDEND = B'C'BC / DIVISOR = D'E'DE (A / B) - push de ; push Lowpart(Q) - ex de, hl ; DE = HL - ld hl, 0 - exx - ld b, h - ld c, l - pop hl - push de - ex de, hl - ld hl, 0 ; H'L'HL = 0 - exx - pop bc ; Pop HightPart(B) => B = B'C'BC - exx - ld a, 32 ; Loop count -__DIV32LOOP: - sll c ; B'C'BC << 1 ; Output most left bit to carry - rl b - exx - rl c - rl b - exx - adc hl, hl - exx - adc hl, hl - exx - sbc hl,de - exx - sbc hl,de - exx - jp nc, __DIV32NOADD ; use JP inside a loop for being faster - add hl, de - exx - adc hl, de - exx - dec bc -__DIV32NOADD: - dec a - jp nz, __DIV32LOOP ; use JP inside a loop for being faster - ; At this point, quotient is stored in B'C'BC and the reminder in H'L'HL - push hl - exx - pop de - ex de, hl ; D'E'H'L' = 32 bits modulus - push bc - exx - pop de ; DE = B'C' - ld h, b - ld l, c ; DEHL = quotient D'E'H'L' = Modulus - ret ; DEHL = quotient, D'E'H'L' = Modulus -__MODU32: ; 32 bit modulus for 32bit unsigned division - ; DEHL = Dividend, Stack Top = Divisor (DE, HL) - exx - pop hl ; return address - pop de ; low part - ex (sp), hl ; CALLEE Convention ; H'L'D'E' => Dividend - call __DIVU32START ; At return, modulus is at D'E'H'L' -__MODU32START: - exx - push de - push hl - exx - pop hl - pop de - ret -__DIVI32: ; 32 bit signed division - ; DEHL = Dividend, Stack Top = Divisor - ; A = Dividend, B = Divisor => A / B - exx - pop hl ; return address - pop de ; low part - ex (sp), hl ; CALLEE Convention ; H'L'D'E' => Dividend -__DIVI32START: - exx - ld a, d ; Save sign - ex af, af' - bit 7, d ; Negative? - call nz, __NEG32 ; Negates DEHL - exx ; Now works with H'L'D'E' - ex af, af' - xor h - ex af, af' ; Stores sign of the result for later - bit 7, h ; Negative? - ex de, hl ; HLDE = DEHL - call nz, __NEG32 - ex de, hl - call __DIVU32START - ex af, af' ; Recovers sign - and 128 ; positive? - ret z - jp __NEG32 ; Negates DEHL and returns from there -__MODI32: ; 32bits signed division modulus - exx - pop hl ; return address - pop de ; low part - ex (sp), hl ; CALLEE Convention ; H'L'D'E' => Dividend - call __DIVI32START - jp __MODU32START - pop namespace -#line 4 "/zxbasic/src/lib/arch/zx48k/runtime/printi32.asm" - push namespace core -__PRINTI32: - ld a, d - or a - jp p, __PRINTU32 - call __PRINT_MINUS - call __NEG32 -__PRINTU32: - PROC - LOCAL __PRINTU_LOOP - ld b, 0 ; Counter -__PRINTU_LOOP: - ld a, h - or l - or d - or e - jp z, __PRINTU_START - push bc - ld bc, 0 - push bc - ld bc, 10 - push bc ; Push 00 0A (10 Dec) into the stack = divisor - call __DIVU32 ; Divides by 32. D'E'H'L' contains modulo (L' since < 10) - pop bc - exx - ld a, l - or '0' ; Stores ASCII digit (must be print in reversed order) - push af - exx - inc b - jp __PRINTU_LOOP ; Uses JP in loops - ENDP - pop namespace -#line 2 "/zxbasic/src/lib/arch/zx48k/runtime/printu32.asm" -#line 116 "arch/zx48k/fact.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/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 117 "arch/zx48k/fact.bas" +#line 84 "arch/zx48k/fact.bas" END diff --git a/tests/functional/arch/zx48k/fact.bas b/tests/functional/arch/zx48k/fact.bas index 831f650a9..80cf0e1d6 100644 --- a/tests/functional/arch/zx48k/fact.bas +++ b/tests/functional/arch/zx48k/fact.bas @@ -1,4 +1,5 @@ REM Factorial recursive test +DIM y as ulong function fact(x as ulong) as ulong if x < 2 then @@ -8,7 +9,6 @@ function fact(x as ulong) as ulong return x * fact(x - 1) end function -cls for x = 1 To 10: - print "Fact ("; x; ") = "; fact(x) + let y = x: rem dummy next x diff --git a/tests/functional/arch/zx48k/for0.asm b/tests/functional/arch/zx48k/for0.asm index a7a7725aa..a9c8693e3 100644 --- a/tests/functional/arch/zx48k/for0.asm +++ b/tests/functional/arch/zx48k/for0.asm @@ -10,35 +10,26 @@ add hl, sp ld (.core.__CALL_BACK__), hl ei - call .core.__MEM_INIT - call .core.__PRINT_INIT jp .core.__MAIN_PROGRAM__ .core.__CALL_BACK__: DEFW 0 .core.ZXBASIC_USER_DATA: - ; Defines HEAP SIZE -.core.ZXBASIC_HEAP_SIZE EQU 4768 -.core.ZXBASIC_MEM_HEAP: - DEFS 4768 ; 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 _x: DEFB 00 +_y: + DEFB 00 .core.ZXBASIC_USER_DATA_END: .core.__MAIN_PROGRAM__: - call .core.CLS ld a, 128 ld (_x), a jp .LABEL.__LABEL0 .LABEL.__LABEL3: - call .core.COPY_ATTR ld a, (_x) - call .core.__PRINTI8 - ld hl, .LABEL.__LABEL5 - xor a - call .core.__PRINTSTR + ld (_y), a .LABEL.__LABEL4: ld hl, _x inc (hl) @@ -63,68 +54,7 @@ _x: pop ix ei ret -.LABEL.__LABEL5: - DEFW 0001h - DEFB 20h ;; --- end of user code --- -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/cls.asm" - ;; Clears the user screen (24 rows) -#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 4 "/zxbasic/src/lib/arch/zx48k/runtime/cls.asm" - push namespace core -CLS: - PROC - ld hl, 0 - ld (COORDS), hl - ld hl, SCR_SIZE - ld (S_POSN), hl - ld hl, (SCREEN_ADDR) - ld (DFCC), hl - ld (hl), 0 - ld d, h - ld e, l - inc de - ld bc, 6143 - ldir - ; Now clear attributes - ld hl, (SCREEN_ATTR_ADDR) - ld (DFCCL), hl - ld d, h - ld e, l - inc de - ld a, (ATTR_P) - ld (hl), a - ld bc, 767 - ldir - ret - ENDP - pop namespace -#line 41 "arch/zx48k/for0.bas" #line 1 "/zxbasic/src/lib/arch/zx48k/runtime/cmp/lti8.asm" #line 1 "/zxbasic/src/lib/arch/zx48k/runtime/cmp/lei8.asm" push namespace core @@ -149,1323 +79,5 @@ checkParity: ENDP pop namespace #line 2 "/zxbasic/src/lib/arch/zx48k/runtime/cmp/lti8.asm" -#line 42 "arch/zx48k/for0.bas" -#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/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 43 "arch/zx48k/for0.bas" -#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 44 "arch/zx48k/for0.bas" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/printstr.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/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/lib/arch/zx48k/runtime/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/lib/arch/zx48k/runtime/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 5 "/zxbasic/src/lib/arch/zx48k/runtime/printstr.asm" - ; PRINT command routine - ; Prints string pointed by HL - push namespace core -PRINT_STR: -__PRINTSTR: ; __FASTCALL__ Entry to print_string - PROC - LOCAL __PRINT_STR_LOOP - LOCAL __PRINT_STR_END - ld d, a ; Saves A reg (Flag) for later - ld a, h - or l - ret z ; Return if the pointer is NULL - push hl - ld c, (hl) - inc hl - ld b, (hl) - inc hl ; BC = LEN(a$); HL = &a$ -__PRINT_STR_LOOP: - ld a, b - or c - jr z, __PRINT_STR_END ; END if BC (counter = 0) - ld a, (hl) - call __PRINTCHAR - inc hl - dec bc - jp __PRINT_STR_LOOP -__PRINT_STR_END: - pop hl - ld a, d ; Recovers A flag - or a ; If not 0 this is a temporary string. Free it - ret z - jp __MEM_FREE ; Frees str from heap and return from there -__PRINT_STR: - ; Fastcall Entry - ; It ONLY prints strings - ; HL = String start - ; BC = String length (Number of chars) - push hl ; Push str address for later - ld d, a ; Saves a FLAG - jp __PRINT_STR_LOOP - ENDP - pop namespace -#line 45 "arch/zx48k/for0.bas" +#line 33 "arch/zx48k/for0.bas" END diff --git a/tests/functional/arch/zx48k/for0.bas b/tests/functional/arch/zx48k/for0.bas index 554e41c15..cbb1d3418 100644 --- a/tests/functional/arch/zx48k/for0.bas +++ b/tests/functional/arch/zx48k/for0.bas @@ -1,7 +1,7 @@ -DIM x as byte +DIM x, y as byte + -cls for x=-128 to 126 -print x; " "; + let y = x next x diff --git a/tests/functional/arch/zx48k/ifelse1.asm b/tests/functional/arch/zx48k/ifelse1.asm index de51a7349..390787ffb 100644 --- a/tests/functional/arch/zx48k/ifelse1.asm +++ b/tests/functional/arch/zx48k/ifelse1.asm @@ -10,16 +10,10 @@ add hl, sp ld (.core.__CALL_BACK__), hl ei - call .core.__MEM_INIT - call .core.__PRINT_INIT jp .core.__MAIN_PROGRAM__ .core.__CALL_BACK__: DEFW 0 .core.ZXBASIC_USER_DATA: - ; Defines HEAP SIZE -.core.ZXBASIC_HEAP_SIZE EQU 4768 -.core.ZXBASIC_MEM_HEAP: - DEFS 4768 ; 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 @@ -32,11 +26,8 @@ _a: sub 2 jp z, .LABEL.__LABEL1 .LABEL.__LABEL0: - call .core.COPY_ATTR - ld hl, .LABEL.__LABEL2 xor a - call .core.__PRINTSTR - call .core.PRINT_EOL + ld (_a), a .LABEL.__LABEL1: ld hl, 0 ld b, h @@ -52,1245 +43,5 @@ _a: pop ix ei ret -.LABEL.__LABEL2: - DEFW 000Dh - DEFB 43h - DEFB 61h - DEFB 6Eh - DEFB 27h - DEFB 74h - DEFB 20h - DEFB 68h - DEFB 61h - DEFB 70h - DEFB 70h - DEFB 65h - DEFB 6Eh - DEFB 21h ;; --- 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 42 "arch/zx48k/ifelse1.bas" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/printstr.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/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/lib/arch/zx48k/runtime/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/lib/arch/zx48k/runtime/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 5 "/zxbasic/src/lib/arch/zx48k/runtime/printstr.asm" - ; PRINT command routine - ; Prints string pointed by HL - push namespace core -PRINT_STR: -__PRINTSTR: ; __FASTCALL__ Entry to print_string - PROC - LOCAL __PRINT_STR_LOOP - LOCAL __PRINT_STR_END - ld d, a ; Saves A reg (Flag) for later - ld a, h - or l - ret z ; Return if the pointer is NULL - push hl - ld c, (hl) - inc hl - ld b, (hl) - inc hl ; BC = LEN(a$); HL = &a$ -__PRINT_STR_LOOP: - ld a, b - or c - jr z, __PRINT_STR_END ; END if BC (counter = 0) - ld a, (hl) - call __PRINTCHAR - inc hl - dec bc - jp __PRINT_STR_LOOP -__PRINT_STR_END: - pop hl - ld a, d ; Recovers A flag - or a ; If not 0 this is a temporary string. Free it - ret z - jp __MEM_FREE ; Frees str from heap and return from there -__PRINT_STR: - ; Fastcall Entry - ; It ONLY prints strings - ; HL = String start - ; BC = String length (Number of chars) - push hl ; Push str address for later - ld d, a ; Saves a FLAG - jp __PRINT_STR_LOOP - ENDP - pop namespace -#line 44 "arch/zx48k/ifelse1.bas" END diff --git a/tests/functional/arch/zx48k/ifelse1.bas b/tests/functional/arch/zx48k/ifelse1.bas index d4d9a8e6d..823824fb3 100644 --- a/tests/functional/arch/zx48k/ifelse1.bas +++ b/tests/functional/arch/zx48k/ifelse1.bas @@ -2,5 +2,5 @@ DIM a As Ubyte = 2 if a = 2 then else - print "Can't happen!" + LET a = 0: REM "Can't happen!" end if diff --git a/tests/functional/arch/zx48k/ifwhilex.asm b/tests/functional/arch/zx48k/ifwhilex.asm index 17d2fd8bf..9916ae102 100644 --- a/tests/functional/arch/zx48k/ifwhilex.asm +++ b/tests/functional/arch/zx48k/ifwhilex.asm @@ -10,7 +10,6 @@ add hl, sp ld (.core.__CALL_BACK__), hl ei - call .core.__PRINT_INIT jp .core.__MAIN_PROGRAM__ .core.__CALL_BACK__: DEFW 0 @@ -38,10 +37,8 @@ _i: inc (hl) jp .LABEL.__LABEL2 .LABEL.__LABEL3: - call .core.COPY_ATTR - ld a, (_i) - call .core.__PRINTI8 - call .core.PRINT_EOL + xor a + ld (_i), a .LABEL.__LABEL1: ld hl, 0 ld b, h @@ -82,1039 +79,5 @@ checkParity: ENDP pop namespace #line 2 "/zxbasic/src/lib/arch/zx48k/runtime/cmp/lti8.asm" -#line 37 "arch/zx48k/ifwhilex.bas" -#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 38 "arch/zx48k/ifwhilex.bas" -#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 40 "arch/zx48k/ifwhilex.bas" +#line 35 "arch/zx48k/ifwhilex.bas" END diff --git a/tests/functional/arch/zx48k/ifwhilex.bas b/tests/functional/arch/zx48k/ifwhilex.bas index ec387c559..610e4a750 100644 --- a/tests/functional/arch/zx48k/ifwhilex.bas +++ b/tests/functional/arch/zx48k/ifwhilex.bas @@ -3,4 +3,4 @@ DIM i as Byte IF i < 0 THEN WHILE i < 10: LET i = i + 1 - END WHILE: PRINT i + END WHILE: LET i = 0 diff --git a/tests/functional/arch/zx48k/lcd3.asm b/tests/functional/arch/zx48k/lcd3.asm index 09d979a87..87abf78b3 100644 --- a/tests/functional/arch/zx48k/lcd3.asm +++ b/tests/functional/arch/zx48k/lcd3.asm @@ -11,7 +11,6 @@ ld (.core.__CALL_BACK__), hl ei call .core.__MEM_INIT - call .core.__PRINT_INIT jp .core.__MAIN_PROGRAM__ .core.__CALL_BACK__: DEFW 0 @@ -24,25 +23,15 @@ .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 +_z: + DEFB 00, 00 _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 - call .core.PRINT_AT - ld hl, .LABEL.__LABEL0 - xor a - call .core.__PRINTSTR - ld a, 1 - push af - ld a, 30 - call .core.PRINT_AT ld a, 2 push af - ld hl, .LABEL.__LABEL1 + ld hl, .LABEL.__LABEL0 call .core.__LOADSTR push hl ld a, (_adr) @@ -54,22 +43,12 @@ _adr: call .core.__STR_FAST push hl call _lset - ld a, 1 - call .core.__PRINTSTR - ld a, 2 - push af - ld a, 30 - call .core.PRINT_AT - ld hl, .LABEL.__LABEL2 - xor a - call .core.__PRINTSTR - ld a, 3 - push af - ld a, 30 - call .core.PRINT_AT + ex de, hl + ld hl, _z + call .core.__STORE_STR2 ld a, 2 push af - ld hl, .LABEL.__LABEL1 + ld hl, .LABEL.__LABEL0 call .core.__LOADSTR push hl ld hl, _adr + 4 @@ -84,9 +63,9 @@ _adr: call .core.__STR_FAST push hl call _lset - ld a, 1 - call .core.__PRINTSTR - call .core.PRINT_EOL + ex de, hl + ld hl, _z + call .core.__STORE_STR2 ld hl, 0 ld b, h ld c, l @@ -105,7 +84,7 @@ _lset: push ix ld ix, 0 add ix, sp -.LABEL.__LABEL3: +.LABEL.__LABEL1: ld l, (ix+4) ld h, (ix+5) call .core.__STRLEN @@ -117,7 +96,7 @@ _lset: pop hl or a sbc hl, de - jp nc, .LABEL.__LABEL4 + jp nc, .LABEL.__LABEL2 ld l, (ix+6) ld h, (ix+7) push hl @@ -130,8 +109,8 @@ _lset: ld e, l ld bc, 4 call .core.__PSTORE_STR2 - jp .LABEL.__LABEL3 -.LABEL.__LABEL4: + jp .LABEL.__LABEL1 +.LABEL.__LABEL2: ld l, (ix+4) ld h, (ix+5) call .core.__LOADSTR @@ -156,18 +135,10 @@ _lset__leave: exx ret .LABEL.__LABEL0: - DEFW 0002h - DEFB 48h - DEFB 50h -.LABEL.__LABEL1: DEFW 0001h DEFB 30h -.LABEL.__LABEL2: - DEFW 0002h - DEFB 4Fh - DEFB 46h ;; --- end of user code --- -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/addf.asm" +#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/arith/addf.asm" #line 1 "/zxbasic/src/lib/arch/zx48k/runtime/stackf.asm" ; ------------------------------------------------------------- ; Functions to manage FP-Stack of the ZX Spectrum ROM CALC @@ -207,7 +178,7 @@ __FPSTACK_I16: ; Pushes 16 bits integer in HL into the FP ROM STACK ld b, a jp __FPSTACK_PUSH pop namespace -#line 2 "/zxbasic/src/lib/arch/zx48k/runtime/addf.asm" +#line 2 "/zxbasic/src/lib/arch/zx48k/runtime/arith/addf.asm" ; ------------------------------------------------------------- ; Floating point library using the FP ROM Calculator (ZX 48K) ; All of them uses A EDCB registers as 1st paramter. @@ -225,921 +196,7 @@ __ADDF: ; Addition defb 38h; ; END CALC jp __FPSTACK_POP pop namespace -#line 141 "arch/zx48k/lcd3.bas" -#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 142 "arch/zx48k/lcd3.bas" +#line 111 "arch/zx48k/lcd3.bas" #line 1 "/zxbasic/src/lib/arch/zx48k/runtime/free.asm" ; vim: ts=4:et:sw=4: ; Copyleft (K) by Jose M. Rodriguez de la Rosa @@ -1406,7 +463,7 @@ __MEM_BLOCK_JOIN: ; Joins current block (pointed by HL) with next one (pointed ret ENDP pop namespace -#line 143 "arch/zx48k/lcd3.bas" +#line 112 "arch/zx48k/lcd3.bas" #line 1 "/zxbasic/src/lib/arch/zx48k/runtime/ftou32reg.asm" #line 1 "/zxbasic/src/lib/arch/zx48k/runtime/neg32.asm" push namespace core @@ -1505,7 +562,7 @@ __FTOU8: ; Converts float in C ED LH to Unsigned byte in A ld a, l ret pop namespace -#line 144 "arch/zx48k/lcd3.bas" +#line 113 "arch/zx48k/lcd3.bas" #line 1 "/zxbasic/src/lib/arch/zx48k/runtime/loadstr.asm" #line 1 "/zxbasic/src/lib/arch/zx48k/runtime/alloc.asm" ; vim: ts=4:et:sw=4: @@ -1567,6 +624,41 @@ __FTOU8: ; Converts float in C ED LH to Unsigned byte in A ; HL = BLOCK Start & DE = Length. ; An init directive is useful for initialization routines. ; They will be added automatically if needed. +#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 69 "/zxbasic/src/lib/arch/zx48k/runtime/alloc.asm" ; --------------------------------------------------------------------- ; MEM_ALLOC ; Allocates a block of memory in the heap. @@ -1701,51 +793,7 @@ __LOADSTR: ; __FASTCALL__ entry pop hl ; Recovers destiny in hl as result ret pop namespace -#line 145 "arch/zx48k/lcd3.bas" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/printstr.asm" - ; PRINT command routine - ; Prints string pointed by HL - push namespace core -PRINT_STR: -__PRINTSTR: ; __FASTCALL__ Entry to print_string - PROC - LOCAL __PRINT_STR_LOOP - LOCAL __PRINT_STR_END - ld d, a ; Saves A reg (Flag) for later - ld a, h - or l - ret z ; Return if the pointer is NULL - push hl - ld c, (hl) - inc hl - ld b, (hl) - inc hl ; BC = LEN(a$); HL = &a$ -__PRINT_STR_LOOP: - ld a, b - or c - jr z, __PRINT_STR_END ; END if BC (counter = 0) - ld a, (hl) - call __PRINTCHAR - inc hl - dec bc - jp __PRINT_STR_LOOP -__PRINT_STR_END: - pop hl - ld a, d ; Recovers A flag - or a ; If not 0 this is a temporary string. Free it - ret z - jp __MEM_FREE ; Frees str from heap and return from there -__PRINT_STR: - ; Fastcall Entry - ; It ONLY prints strings - ; HL = String start - ; BC = String length (Number of chars) - push hl ; Push str address for later - ld d, a ; Saves a FLAG - jp __PRINT_STR_LOOP - ENDP - pop namespace -#line 147 "arch/zx48k/lcd3.bas" +#line 114 "arch/zx48k/lcd3.bas" #line 1 "/zxbasic/src/lib/arch/zx48k/runtime/pstorestr2.asm" ; vim:ts=4:et:sw=4 ; @@ -1794,7 +842,7 @@ __PSTORE_STR2: add hl, bc jp __STORE_STR2 pop namespace -#line 148 "arch/zx48k/lcd3.bas" +#line 115 "arch/zx48k/lcd3.bas" #line 1 "/zxbasic/src/lib/arch/zx48k/runtime/pushf.asm" ; Routine to push Float pointed by HL ; Into the stack. Notice that the hl points to the last @@ -1822,12 +870,39 @@ __FP_PUSH_REV: exx ret pop namespace -#line 149 "arch/zx48k/lcd3.bas" +#line 116 "arch/zx48k/lcd3.bas" #line 1 "/zxbasic/src/lib/arch/zx48k/runtime/str.asm" ; The STR$( ) BASIC function implementation ; Given a FP number in C ED LH ; Returns a pointer (in HL) to the memory heap ; containing the FP number string representation +#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 10 "/zxbasic/src/lib/arch/zx48k/runtime/str.asm" push namespace core __STR: __STR_FAST: @@ -1879,7 +954,7 @@ __STR_END: STK_END EQU 5C65h ENDP pop namespace -#line 150 "arch/zx48k/lcd3.bas" +#line 118 "arch/zx48k/lcd3.bas" #line 1 "/zxbasic/src/lib/arch/zx48k/runtime/strcat.asm" #line 1 "/zxbasic/src/lib/arch/zx48k/runtime/strlen.asm" ; Returns len if a string @@ -1992,7 +1067,7 @@ __STRCATEND: ret ENDP pop namespace -#line 151 "arch/zx48k/lcd3.bas" +#line 119 "arch/zx48k/lcd3.bas" #line 1 "/zxbasic/src/lib/arch/zx48k/runtime/u32tofreg.asm" push namespace core __I8TOFREG: @@ -2063,5 +1138,5 @@ __U32TOFREG_END: ret ENDP pop namespace -#line 153 "arch/zx48k/lcd3.bas" +#line 121 "arch/zx48k/lcd3.bas" END diff --git a/tests/functional/arch/zx48k/lcd3.bas b/tests/functional/arch/zx48k/lcd3.bas index f0fff929a..958de8af7 100644 --- a/tests/functional/arch/zx48k/lcd3.bas +++ b/tests/functional/arch/zx48k/lcd3.bas @@ -1,4 +1,5 @@ ' A bug encountered by LCD +DIM z as String function lset(a$ as string,setchar$ as string,length as ubyte) as string while len(a$) - ; 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 72 "arch/zx48k/lcd7.bas" #line 1 "/zxbasic/src/lib/arch/zx48k/runtime/free.asm" ; vim: ts=4:et:sw=4: ; Copyleft (K) by Jose M. Rodriguez de la Rosa @@ -1276,7 +361,7 @@ __MEM_BLOCK_JOIN: ; Joins current block (pointed by HL) with next one (pointed ret ENDP pop namespace -#line 73 "arch/zx48k/lcd7.bas" +#line 70 "arch/zx48k/lcd7.bas" #line 1 "/zxbasic/src/lib/arch/zx48k/runtime/loadstr.asm" #line 1 "/zxbasic/src/lib/arch/zx48k/runtime/alloc.asm" ; vim: ts=4:et:sw=4: @@ -1338,6 +423,41 @@ __MEM_BLOCK_JOIN: ; Joins current block (pointed by HL) with next one (pointed ; HL = BLOCK Start & DE = Length. ; An init directive is useful for initialization routines. ; They will be added automatically if needed. +#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 69 "/zxbasic/src/lib/arch/zx48k/runtime/alloc.asm" ; --------------------------------------------------------------------- ; MEM_ALLOC ; Allocates a block of memory in the heap. @@ -1472,51 +592,7 @@ __LOADSTR: ; __FASTCALL__ entry pop hl ; Recovers destiny in hl as result ret pop namespace -#line 74 "arch/zx48k/lcd7.bas" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/printstr.asm" - ; PRINT command routine - ; Prints string pointed by HL - push namespace core -PRINT_STR: -__PRINTSTR: ; __FASTCALL__ Entry to print_string - PROC - LOCAL __PRINT_STR_LOOP - LOCAL __PRINT_STR_END - ld d, a ; Saves A reg (Flag) for later - ld a, h - or l - ret z ; Return if the pointer is NULL - push hl - ld c, (hl) - inc hl - ld b, (hl) - inc hl ; BC = LEN(a$); HL = &a$ -__PRINT_STR_LOOP: - ld a, b - or c - jr z, __PRINT_STR_END ; END if BC (counter = 0) - ld a, (hl) - call __PRINTCHAR - inc hl - dec bc - jp __PRINT_STR_LOOP -__PRINT_STR_END: - pop hl - ld a, d ; Recovers A flag - or a ; If not 0 this is a temporary string. Free it - ret z - jp __MEM_FREE ; Frees str from heap and return from there -__PRINT_STR: - ; Fastcall Entry - ; It ONLY prints strings - ; HL = String start - ; BC = String length (Number of chars) - push hl ; Push str address for later - ld d, a ; Saves a FLAG - jp __PRINT_STR_LOOP - ENDP - pop namespace -#line 76 "arch/zx48k/lcd7.bas" +#line 71 "arch/zx48k/lcd7.bas" #line 1 "/zxbasic/src/lib/arch/zx48k/runtime/pstorestr.asm" ; vim:ts=4:et:sw=4 ; @@ -1779,5 +855,21 @@ __PSTORE_STR: add hl, bc jp __STORE_STR pop namespace -#line 77 "arch/zx48k/lcd7.bas" +#line 72 "arch/zx48k/lcd7.bas" +#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/strlen.asm" + ; Returns len if a string + ; If a string is NULL, its len is also 0 + ; Result returned in HL + push namespace core +__STRLEN: ; Direct FASTCALL entry + ld a, h + or l + ret z + ld a, (hl) + inc hl + ld h, (hl) ; LEN(str) in HL + ld l, a + ret + pop namespace +#line 73 "arch/zx48k/lcd7.bas" END diff --git a/tests/functional/arch/zx48k/lcd7.bas b/tests/functional/arch/zx48k/lcd7.bas index 44ce9724c..5a6b004d4 100644 --- a/tests/functional/arch/zx48k/lcd7.bas +++ b/tests/functional/arch/zx48k/lcd7.bas @@ -1,5 +1,7 @@ +DIM dummy As UInteger + sub printerPutString(char$ as string) - print char$ + let dummy = LEN(char$) end sub sub Frame() diff --git a/tests/functional/arch/zx48k/lcd8.asm b/tests/functional/arch/zx48k/lcd8.asm index 701d56919..f6a82200c 100644 --- a/tests/functional/arch/zx48k/lcd8.asm +++ b/tests/functional/arch/zx48k/lcd8.asm @@ -11,7 +11,6 @@ ld (.core.__CALL_BACK__), hl ei call .core.__MEM_INIT - call .core.__PRINT_INIT jp .core.__MAIN_PROGRAM__ .core.__CALL_BACK__: DEFW 0 @@ -24,6 +23,8 @@ .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 +_dummy: + DEFB 00, 00 .core.ZXBASIC_USER_DATA_END: .core.__MAIN_PROGRAM__: ld hl, .LABEL.__LABEL0 @@ -48,12 +49,10 @@ _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 + call .core.__STRLEN + ld (_dummy), hl _printerPutString__leave: ex af, af' exx @@ -98,920 +97,6 @@ _Frame__leave: DEFB 4Fh DEFB 4Bh ;; --- 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 74 "arch/zx48k/lcd8.bas" #line 1 "/zxbasic/src/lib/arch/zx48k/runtime/free.asm" ; vim: ts=4:et:sw=4: ; Copyleft (K) by Jose M. Rodriguez de la Rosa @@ -1278,7 +363,7 @@ __MEM_BLOCK_JOIN: ; Joins current block (pointed by HL) with next one (pointed ret ENDP pop namespace -#line 75 "arch/zx48k/lcd8.bas" +#line 72 "arch/zx48k/lcd8.bas" #line 1 "/zxbasic/src/lib/arch/zx48k/runtime/loadstr.asm" #line 1 "/zxbasic/src/lib/arch/zx48k/runtime/alloc.asm" ; vim: ts=4:et:sw=4: @@ -1340,6 +425,41 @@ __MEM_BLOCK_JOIN: ; Joins current block (pointed by HL) with next one (pointed ; HL = BLOCK Start & DE = Length. ; An init directive is useful for initialization routines. ; They will be added automatically if needed. +#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 69 "/zxbasic/src/lib/arch/zx48k/runtime/alloc.asm" ; --------------------------------------------------------------------- ; MEM_ALLOC ; Allocates a block of memory in the heap. @@ -1474,49 +594,21 @@ __LOADSTR: ; __FASTCALL__ entry pop hl ; Recovers destiny in hl as result ret pop namespace -#line 76 "arch/zx48k/lcd8.bas" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/printstr.asm" - ; PRINT command routine - ; Prints string pointed by HL +#line 73 "arch/zx48k/lcd8.bas" +#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/strlen.asm" + ; Returns len if a string + ; If a string is NULL, its len is also 0 + ; Result returned in HL push namespace core -PRINT_STR: -__PRINTSTR: ; __FASTCALL__ Entry to print_string - PROC - LOCAL __PRINT_STR_LOOP - LOCAL __PRINT_STR_END - ld d, a ; Saves A reg (Flag) for later +__STRLEN: ; Direct FASTCALL entry ld a, h or l - ret z ; Return if the pointer is NULL - push hl - ld c, (hl) - inc hl - ld b, (hl) - inc hl ; BC = LEN(a$); HL = &a$ -__PRINT_STR_LOOP: - ld a, b - or c - jr z, __PRINT_STR_END ; END if BC (counter = 0) + ret z ld a, (hl) - call __PRINTCHAR inc hl - dec bc - jp __PRINT_STR_LOOP -__PRINT_STR_END: - pop hl - ld a, d ; Recovers A flag - or a ; If not 0 this is a temporary string. Free it - ret z - jp __MEM_FREE ; Frees str from heap and return from there -__PRINT_STR: - ; Fastcall Entry - ; It ONLY prints strings - ; HL = String start - ; BC = String length (Number of chars) - push hl ; Push str address for later - ld d, a ; Saves a FLAG - jp __PRINT_STR_LOOP - ENDP + ld h, (hl) ; LEN(str) in HL + ld l, a + ret pop namespace -#line 78 "arch/zx48k/lcd8.bas" +#line 74 "arch/zx48k/lcd8.bas" END diff --git a/tests/functional/arch/zx48k/lcd8.bas b/tests/functional/arch/zx48k/lcd8.bas index d4be731ab..c68d04040 100644 --- a/tests/functional/arch/zx48k/lcd8.bas +++ b/tests/functional/arch/zx48k/lcd8.bas @@ -1,5 +1,7 @@ +DIM dummy as UInteger + sub printerPutString(char$ as string) - print char$ + let dummy = LEN(char$) end sub sub Frame(strg$ as string) diff --git a/tests/functional/arch/zx48k/lcd9.asm b/tests/functional/arch/zx48k/lcd9.asm index 38c1d4e05..bc10eb0df 100644 --- a/tests/functional/arch/zx48k/lcd9.asm +++ b/tests/functional/arch/zx48k/lcd9.asm @@ -11,7 +11,6 @@ ld (.core.__CALL_BACK__), hl ei call .core.__MEM_INIT - call .core.__PRINT_INIT jp .core.__MAIN_PROGRAM__ .core.__CALL_BACK__: DEFW 0 @@ -24,6 +23,8 @@ .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 +_dummy: + DEFB 00, 00 _strg: DEFB 00, 00 .core.ZXBASIC_USER_DATA_END: @@ -50,12 +51,10 @@ _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 + call .core.__STRLEN + ld (_dummy), hl _printerPutString__leave: ex af, af' exx @@ -88,920 +87,6 @@ _Frame__leave: DEFB 4Fh DEFB 4Bh ;; --- 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 62 "arch/zx48k/lcd9.bas" #line 1 "/zxbasic/src/lib/arch/zx48k/runtime/free.asm" ; vim: ts=4:et:sw=4: ; Copyleft (K) by Jose M. Rodriguez de la Rosa @@ -1268,7 +353,7 @@ __MEM_BLOCK_JOIN: ; Joins current block (pointed by HL) with next one (pointed ret ENDP pop namespace -#line 63 "arch/zx48k/lcd9.bas" +#line 60 "arch/zx48k/lcd9.bas" #line 1 "/zxbasic/src/lib/arch/zx48k/runtime/loadstr.asm" #line 1 "/zxbasic/src/lib/arch/zx48k/runtime/alloc.asm" ; vim: ts=4:et:sw=4: @@ -1330,6 +415,41 @@ __MEM_BLOCK_JOIN: ; Joins current block (pointed by HL) with next one (pointed ; HL = BLOCK Start & DE = Length. ; An init directive is useful for initialization routines. ; They will be added automatically if needed. +#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 69 "/zxbasic/src/lib/arch/zx48k/runtime/alloc.asm" ; --------------------------------------------------------------------- ; MEM_ALLOC ; Allocates a block of memory in the heap. @@ -1464,51 +584,7 @@ __LOADSTR: ; __FASTCALL__ entry pop hl ; Recovers destiny in hl as result ret pop namespace -#line 64 "arch/zx48k/lcd9.bas" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/printstr.asm" - ; PRINT command routine - ; Prints string pointed by HL - push namespace core -PRINT_STR: -__PRINTSTR: ; __FASTCALL__ Entry to print_string - PROC - LOCAL __PRINT_STR_LOOP - LOCAL __PRINT_STR_END - ld d, a ; Saves A reg (Flag) for later - ld a, h - or l - ret z ; Return if the pointer is NULL - push hl - ld c, (hl) - inc hl - ld b, (hl) - inc hl ; BC = LEN(a$); HL = &a$ -__PRINT_STR_LOOP: - ld a, b - or c - jr z, __PRINT_STR_END ; END if BC (counter = 0) - ld a, (hl) - call __PRINTCHAR - inc hl - dec bc - jp __PRINT_STR_LOOP -__PRINT_STR_END: - pop hl - ld a, d ; Recovers A flag - or a ; If not 0 this is a temporary string. Free it - ret z - jp __MEM_FREE ; Frees str from heap and return from there -__PRINT_STR: - ; Fastcall Entry - ; It ONLY prints strings - ; HL = String start - ; BC = String length (Number of chars) - push hl ; Push str address for later - ld d, a ; Saves a FLAG - jp __PRINT_STR_LOOP - ENDP - pop namespace -#line 66 "arch/zx48k/lcd9.bas" +#line 61 "arch/zx48k/lcd9.bas" #line 1 "/zxbasic/src/lib/arch/zx48k/runtime/storestr.asm" ; vim:ts=4:et:sw=4 ; Stores value of current string pointed by DE register into address pointed by HL @@ -1757,5 +833,21 @@ __STORE_STR: pop hl ; Returns ptr to b$ in HL (Caller might needed to free it from memory) ret pop namespace -#line 67 "arch/zx48k/lcd9.bas" +#line 62 "arch/zx48k/lcd9.bas" +#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/strlen.asm" + ; Returns len if a string + ; If a string is NULL, its len is also 0 + ; Result returned in HL + push namespace core +__STRLEN: ; Direct FASTCALL entry + ld a, h + or l + ret z + ld a, (hl) + inc hl + ld h, (hl) ; LEN(str) in HL + ld l, a + ret + pop namespace +#line 63 "arch/zx48k/lcd9.bas" END diff --git a/tests/functional/arch/zx48k/lcd9.bas b/tests/functional/arch/zx48k/lcd9.bas index 2630e335e..62b156432 100644 --- a/tests/functional/arch/zx48k/lcd9.bas +++ b/tests/functional/arch/zx48k/lcd9.bas @@ -1,8 +1,8 @@ - +DIM dummy as UInteger LET strg$ = "OK" sub printerPutString(char$ as string) - print char$ + LET dummy = LEN(char$) end sub sub Frame() diff --git a/tests/functional/arch/zx48k/ltee1.asm b/tests/functional/arch/zx48k/ltee1.asm index 709f65df6..b9ddf319c 100644 --- a/tests/functional/arch/zx48k/ltee1.asm +++ b/tests/functional/arch/zx48k/ltee1.asm @@ -11,7 +11,6 @@ ld (.core.__CALL_BACK__), hl ei call .core.__MEM_INIT - call .core.__PRINT_INIT jp .core.__MAIN_PROGRAM__ .core.__CALL_BACK__: DEFW 0 @@ -35,11 +34,12 @@ _newMsg: ex de, hl ld hl, _newMsg call .core.__STORE_STR2 - call .core.COPY_ATTR ld hl, (_newMsg) + call .core.__STRLEN + push hl xor a - call .core.__PRINTSTR - call .core.PRINT_EOL + pop hl + ld (hl), a ld hl, 0 ld b, h ld c, l @@ -113,920 +113,6 @@ _addWibble__leave: DEFB 6Ch DEFB 65h ;; --- 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 87 "arch/zx48k/ltee1.bas" #line 1 "/zxbasic/src/lib/arch/zx48k/runtime/free.asm" ; vim: ts=4:et:sw=4: ; Copyleft (K) by Jose M. Rodriguez de la Rosa @@ -1355,6 +441,41 @@ __MEM_BLOCK_JOIN: ; Joins current block (pointed by HL) with next one (pointed ; HL = BLOCK Start & DE = Length. ; An init directive is useful for initialization routines. ; They will be added automatically if needed. +#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 69 "/zxbasic/src/lib/arch/zx48k/runtime/alloc.asm" ; --------------------------------------------------------------------- ; MEM_ALLOC ; Allocates a block of memory in the heap. @@ -1490,50 +611,6 @@ __LOADSTR: ; __FASTCALL__ entry ret pop namespace #line 89 "arch/zx48k/ltee1.bas" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/printstr.asm" - ; PRINT command routine - ; Prints string pointed by HL - push namespace core -PRINT_STR: -__PRINTSTR: ; __FASTCALL__ Entry to print_string - PROC - LOCAL __PRINT_STR_LOOP - LOCAL __PRINT_STR_END - ld d, a ; Saves A reg (Flag) for later - ld a, h - or l - ret z ; Return if the pointer is NULL - push hl - ld c, (hl) - inc hl - ld b, (hl) - inc hl ; BC = LEN(a$); HL = &a$ -__PRINT_STR_LOOP: - ld a, b - or c - jr z, __PRINT_STR_END ; END if BC (counter = 0) - ld a, (hl) - call __PRINTCHAR - inc hl - dec bc - jp __PRINT_STR_LOOP -__PRINT_STR_END: - pop hl - ld a, d ; Recovers A flag - or a ; If not 0 this is a temporary string. Free it - ret z - jp __MEM_FREE ; Frees str from heap and return from there -__PRINT_STR: - ; Fastcall Entry - ; It ONLY prints strings - ; HL = String start - ; BC = String length (Number of chars) - push hl ; Push str address for later - ld d, a ; Saves a FLAG - jp __PRINT_STR_LOOP - ENDP - pop namespace -#line 91 "arch/zx48k/ltee1.bas" #line 1 "/zxbasic/src/lib/arch/zx48k/runtime/pstorestr.asm" ; vim:ts=4:et:sw=4 ; @@ -1796,7 +873,7 @@ __PSTORE_STR: add hl, bc jp __STORE_STR pop namespace -#line 92 "arch/zx48k/ltee1.bas" +#line 90 "arch/zx48k/ltee1.bas" #line 1 "/zxbasic/src/lib/arch/zx48k/runtime/pstorestr2.asm" ; vim:ts=4:et:sw=4 ; @@ -1845,7 +922,7 @@ __PSTORE_STR2: add hl, bc jp __STORE_STR2 pop namespace -#line 93 "arch/zx48k/ltee1.bas" +#line 91 "arch/zx48k/ltee1.bas" #line 1 "/zxbasic/src/lib/arch/zx48k/runtime/strcat.asm" #line 1 "/zxbasic/src/lib/arch/zx48k/runtime/strlen.asm" ; Returns len if a string @@ -1958,5 +1035,5 @@ __STRCATEND: ret ENDP pop namespace -#line 95 "arch/zx48k/ltee1.bas" +#line 93 "arch/zx48k/ltee1.bas" END diff --git a/tests/functional/arch/zx48k/ltee1.bas b/tests/functional/arch/zx48k/ltee1.bas index 73a0a11e1..18b2877ec 100644 --- a/tests/functional/arch/zx48k/ltee1.bas +++ b/tests/functional/arch/zx48k/ltee1.bas @@ -4,7 +4,7 @@ 'call addWibble even though it's declared down there vvvv dim newMsg as String newMsg = addWibble("Hello") - print newMsg + POKE len(newMsg), 0 'return a string suffixed with 'wibble' function addWibble(msg as String) as String diff --git a/tests/functional/arch/zx48k/param0.asm b/tests/functional/arch/zx48k/param0.asm index 58a688cee..817588dc6 100644 --- a/tests/functional/arch/zx48k/param0.asm +++ b/tests/functional/arch/zx48k/param0.asm @@ -11,7 +11,6 @@ ld (.core.__CALL_BACK__), hl ei call .core.__MEM_INIT - call .core.__PRINT_INIT jp .core.__MAIN_PROGRAM__ .core.__CALL_BACK__: DEFW 0 @@ -26,14 +25,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.__LABEL0 call .core.__LOADSTR push hl call _test - ld a, 1 - call .core.__PRINTSTR - call .core.PRINT_EOL + call .core.__MEM_FREE ld hl, 0 ld b, h ld c, l @@ -80,920 +76,6 @@ _test__leave: DEFW 0001h DEFB 41h ;; --- 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 56 "arch/zx48k/param0.bas" #line 1 "/zxbasic/src/lib/arch/zx48k/runtime/free.asm" ; vim: ts=4:et:sw=4: ; Copyleft (K) by Jose M. Rodriguez de la Rosa @@ -1260,7 +342,7 @@ __MEM_BLOCK_JOIN: ; Joins current block (pointed by HL) with next one (pointed ret ENDP pop namespace -#line 57 "arch/zx48k/param0.bas" +#line 53 "arch/zx48k/param0.bas" #line 1 "/zxbasic/src/lib/arch/zx48k/runtime/loadstr.asm" #line 1 "/zxbasic/src/lib/arch/zx48k/runtime/alloc.asm" ; vim: ts=4:et:sw=4: @@ -1322,6 +404,41 @@ __MEM_BLOCK_JOIN: ; Joins current block (pointed by HL) with next one (pointed ; HL = BLOCK Start & DE = Length. ; An init directive is useful for initialization routines. ; They will be added automatically if needed. +#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 69 "/zxbasic/src/lib/arch/zx48k/runtime/alloc.asm" ; --------------------------------------------------------------------- ; MEM_ALLOC ; Allocates a block of memory in the heap. @@ -1456,51 +573,7 @@ __LOADSTR: ; __FASTCALL__ entry pop hl ; Recovers destiny in hl as result ret pop namespace -#line 58 "arch/zx48k/param0.bas" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/printstr.asm" - ; PRINT command routine - ; Prints string pointed by HL - push namespace core -PRINT_STR: -__PRINTSTR: ; __FASTCALL__ Entry to print_string - PROC - LOCAL __PRINT_STR_LOOP - LOCAL __PRINT_STR_END - ld d, a ; Saves A reg (Flag) for later - ld a, h - or l - ret z ; Return if the pointer is NULL - push hl - ld c, (hl) - inc hl - ld b, (hl) - inc hl ; BC = LEN(a$); HL = &a$ -__PRINT_STR_LOOP: - ld a, b - or c - jr z, __PRINT_STR_END ; END if BC (counter = 0) - ld a, (hl) - call __PRINTCHAR - inc hl - dec bc - jp __PRINT_STR_LOOP -__PRINT_STR_END: - pop hl - ld a, d ; Recovers A flag - or a ; If not 0 this is a temporary string. Free it - ret z - jp __MEM_FREE ; Frees str from heap and return from there -__PRINT_STR: - ; Fastcall Entry - ; It ONLY prints strings - ; HL = String start - ; BC = String length (Number of chars) - push hl ; Push str address for later - ld d, a ; Saves a FLAG - jp __PRINT_STR_LOOP - ENDP - pop namespace -#line 60 "arch/zx48k/param0.bas" +#line 54 "arch/zx48k/param0.bas" #line 1 "/zxbasic/src/lib/arch/zx48k/runtime/strcat.asm" #line 1 "/zxbasic/src/lib/arch/zx48k/runtime/strlen.asm" ; Returns len if a string @@ -1613,5 +686,5 @@ __STRCATEND: ret ENDP pop namespace -#line 61 "arch/zx48k/param0.bas" +#line 55 "arch/zx48k/param0.bas" END diff --git a/tests/functional/arch/zx48k/param0.bas b/tests/functional/arch/zx48k/param0.bas index 69416ab77..baba10d40 100644 --- a/tests/functional/arch/zx48k/param0.bas +++ b/tests/functional/arch/zx48k/param0.bas @@ -4,4 +4,4 @@ function test$(s$) return s$ + "A" end function -print test("H") +test("H") diff --git a/tests/functional/arch/zx48k/param1.asm b/tests/functional/arch/zx48k/param1.asm index b662a9323..cee3a3c39 100644 --- a/tests/functional/arch/zx48k/param1.asm +++ b/tests/functional/arch/zx48k/param1.asm @@ -11,7 +11,6 @@ ld (.core.__CALL_BACK__), hl ei call .core.__MEM_INIT - call .core.__PRINT_INIT jp .core.__MAIN_PROGRAM__ .core.__CALL_BACK__: DEFW 0 @@ -52,16 +51,15 @@ _test: push ix ld ix, 0 add ix, sp - call .core.COPY_ATTR ld h, (ix+5) ld l, (ix+4) ld c, (hl) inc hl ld h, (hl) ld l, c - xor a - call .core.__PRINTSTR - call .core.PRINT_EOL + call .core.__STRLEN + ld a, l + ld (0), a _test__leave: ld sp, ix pop ix @@ -74,982 +72,19 @@ _test__leave: DEFW 0001h DEFB 61h ;; --- 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 48 "arch/zx48k/param1.bas" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/printstr.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/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: +#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/storestr.asm" +; vim:ts=4:et:sw=4 + ; Stores value of current string pointed by DE register into address pointed by HL + ; Returns DE = Address pointer (&a$) + ; Returns HL = HL (b$ => might be needed later to free it from the heap) ; - ; +----------------+ <-- 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 + ; e.g. => HL = _variableName (DIM _variableName$) + ; DE = Address into the HEAP ; - ; 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/lib/arch/zx48k/runtime/heapinit.asm" + ; This function will resize (REALLOC) the space pointed by HL + ; before copying the content of b$ into a$ +#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/strcpy.asm" +#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/realloc.asm" ; vim: ts=4:et:sw=4: ; Copyleft (K) by Jose M. Rodriguez de la Rosa ; (a.k.a. Boriel) @@ -1109,219 +144,52 @@ __REFRESH_TMP: ; 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/lib/arch/zx48k/runtime/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 5 "/zxbasic/src/lib/arch/zx48k/runtime/printstr.asm" - ; PRINT command routine - ; Prints string pointed by HL +#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/error.asm" + ; Simple error control routines +; vim:ts=4:et: push namespace core -PRINT_STR: -__PRINTSTR: ; __FASTCALL__ Entry to print_string - PROC - LOCAL __PRINT_STR_LOOP - LOCAL __PRINT_STR_END - ld d, a ; Saves A reg (Flag) for later - ld a, h - or l - ret z ; Return if the pointer is NULL - push hl - ld c, (hl) - inc hl - ld b, (hl) - inc hl ; BC = LEN(a$); HL = &a$ -__PRINT_STR_LOOP: - ld a, b - or c - jr z, __PRINT_STR_END ; END if BC (counter = 0) - ld a, (hl) - call __PRINTCHAR - inc hl - dec bc - jp __PRINT_STR_LOOP -__PRINT_STR_END: - pop hl - ld a, d ; Recovers A flag - or a ; If not 0 this is a temporary string. Free it - ret z - jp __MEM_FREE ; Frees str from heap and return from there -__PRINT_STR: - ; Fastcall Entry - ; It ONLY prints strings - ; HL = String start - ; BC = String length (Number of chars) - push hl ; Push str address for later - ld d, a ; Saves a FLAG - jp __PRINT_STR_LOOP - ENDP + 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 50 "arch/zx48k/param1.bas" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/storestr.asm" -; vim:ts=4:et:sw=4 - ; Stores value of current string pointed by DE register into address pointed by HL - ; Returns DE = Address pointer (&a$) - ; Returns HL = HL (b$ => might be needed later to free it from the heap) - ; - ; e.g. => HL = _variableName (DIM _variableName$) - ; DE = Address into the HEAP - ; - ; This function will resize (REALLOC) the space pointed by HL - ; before copying the content of b$ into a$ -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/strcpy.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/realloc.asm" +#line 70 "/zxbasic/src/lib/arch/zx48k/runtime/realloc.asm" +#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/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 BSD license + ; 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 BSD license on the internet + ; 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: @@ -1362,7 +230,7 @@ __PRINT_STR: ; | (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 + ; 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 @@ -1371,17 +239,17 @@ __PRINT_STR: ; HL = BLOCK Start & DE = Length. ; An init directive is useful for initialization routines. ; They will be added automatically if needed. -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/alloc.asm" +#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/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 MIT license + ; 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 MIT license on the internet + ; 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: @@ -1422,7 +290,7 @@ __PRINT_STR: ; | (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 + ; 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 @@ -1431,6 +299,54 @@ __PRINT_STR: ; 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/lib/arch/zx48k/runtime/alloc.asm" ; --------------------------------------------------------------------- ; MEM_ALLOC ; Allocates a block of memory in the heap. @@ -1529,6 +445,165 @@ __MEM_SUBTRACT: ENDP pop namespace #line 71 "/zxbasic/src/lib/arch/zx48k/runtime/realloc.asm" +#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/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 72 "/zxbasic/src/lib/arch/zx48k/runtime/realloc.asm" ; --------------------------------------------------------------------- ; MEM_REALLOC ; Reallocates a block of memory in the heap. @@ -1705,5 +780,21 @@ __STORE_STR: pop hl ; Returns ptr to b$ in HL (Caller might needed to free it from memory) ret pop namespace -#line 51 "arch/zx48k/param1.bas" +#line 47 "arch/zx48k/param1.bas" +#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/strlen.asm" + ; Returns len if a string + ; If a string is NULL, its len is also 0 + ; Result returned in HL + push namespace core +__STRLEN: ; Direct FASTCALL entry + ld a, h + or l + ret z + ld a, (hl) + inc hl + ld h, (hl) ; LEN(str) in HL + ld l, a + ret + pop namespace +#line 48 "arch/zx48k/param1.bas" END diff --git a/tests/functional/arch/zx48k/param1.bas b/tests/functional/arch/zx48k/param1.bas index 10dc52b75..0034814a2 100644 --- a/tests/functional/arch/zx48k/param1.bas +++ b/tests/functional/arch/zx48k/param1.bas @@ -1,7 +1,7 @@ function test(ByRef a as string) - print a$ + POKE 0, len(a$) end function a$="a" diff --git a/tests/functional/arch/zx48k/param2.asm b/tests/functional/arch/zx48k/param2.asm index 4191bdec4..d2c310d3a 100644 --- a/tests/functional/arch/zx48k/param2.asm +++ b/tests/functional/arch/zx48k/param2.asm @@ -11,7 +11,6 @@ ld (.core.__CALL_BACK__), hl ei call .core.__MEM_INIT - call .core.__PRINT_INIT jp .core.__MAIN_PROGRAM__ .core.__CALL_BACK__: DEFW 0 @@ -26,14 +25,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.__LABEL0 call .core.__LOADSTR push hl call _test - ld a, 1 - call .core.__PRINTSTR - call .core.PRINT_EOL + call .core.__MEM_FREE ld hl, 0 ld b, h ld c, l @@ -80,920 +76,6 @@ _test__leave: DEFW 0001h DEFB 41h ;; --- 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 56 "arch/zx48k/param2.bas" #line 1 "/zxbasic/src/lib/arch/zx48k/runtime/free.asm" ; vim: ts=4:et:sw=4: ; Copyleft (K) by Jose M. Rodriguez de la Rosa @@ -1260,7 +342,7 @@ __MEM_BLOCK_JOIN: ; Joins current block (pointed by HL) with next one (pointed ret ENDP pop namespace -#line 57 "arch/zx48k/param2.bas" +#line 53 "arch/zx48k/param2.bas" #line 1 "/zxbasic/src/lib/arch/zx48k/runtime/loadstr.asm" #line 1 "/zxbasic/src/lib/arch/zx48k/runtime/alloc.asm" ; vim: ts=4:et:sw=4: @@ -1322,6 +404,41 @@ __MEM_BLOCK_JOIN: ; Joins current block (pointed by HL) with next one (pointed ; HL = BLOCK Start & DE = Length. ; An init directive is useful for initialization routines. ; They will be added automatically if needed. +#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 69 "/zxbasic/src/lib/arch/zx48k/runtime/alloc.asm" ; --------------------------------------------------------------------- ; MEM_ALLOC ; Allocates a block of memory in the heap. @@ -1456,51 +573,7 @@ __LOADSTR: ; __FASTCALL__ entry pop hl ; Recovers destiny in hl as result ret pop namespace -#line 58 "arch/zx48k/param2.bas" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/printstr.asm" - ; PRINT command routine - ; Prints string pointed by HL - push namespace core -PRINT_STR: -__PRINTSTR: ; __FASTCALL__ Entry to print_string - PROC - LOCAL __PRINT_STR_LOOP - LOCAL __PRINT_STR_END - ld d, a ; Saves A reg (Flag) for later - ld a, h - or l - ret z ; Return if the pointer is NULL - push hl - ld c, (hl) - inc hl - ld b, (hl) - inc hl ; BC = LEN(a$); HL = &a$ -__PRINT_STR_LOOP: - ld a, b - or c - jr z, __PRINT_STR_END ; END if BC (counter = 0) - ld a, (hl) - call __PRINTCHAR - inc hl - dec bc - jp __PRINT_STR_LOOP -__PRINT_STR_END: - pop hl - ld a, d ; Recovers A flag - or a ; If not 0 this is a temporary string. Free it - ret z - jp __MEM_FREE ; Frees str from heap and return from there -__PRINT_STR: - ; Fastcall Entry - ; It ONLY prints strings - ; HL = String start - ; BC = String length (Number of chars) - push hl ; Push str address for later - ld d, a ; Saves a FLAG - jp __PRINT_STR_LOOP - ENDP - pop namespace -#line 60 "arch/zx48k/param2.bas" +#line 54 "arch/zx48k/param2.bas" #line 1 "/zxbasic/src/lib/arch/zx48k/runtime/strcat.asm" #line 1 "/zxbasic/src/lib/arch/zx48k/runtime/strlen.asm" ; Returns len if a string @@ -1613,5 +686,5 @@ __STRCATEND: ret ENDP pop namespace -#line 61 "arch/zx48k/param2.bas" +#line 55 "arch/zx48k/param2.bas" END diff --git a/tests/functional/arch/zx48k/param2.bas b/tests/functional/arch/zx48k/param2.bas index 241de1dc8..f1c4eb6cd 100644 --- a/tests/functional/arch/zx48k/param2.bas +++ b/tests/functional/arch/zx48k/param2.bas @@ -6,4 +6,4 @@ function test(s$) return s$ + "A" end function -print test("H") +test("H") diff --git a/tests/functional/arch/zx48k/spfill.asm b/tests/functional/arch/zx48k/spfill.asm deleted file mode 100644 index c5ea8c1e4..000000000 --- a/tests/functional/arch/zx48k/spfill.asm +++ /dev/null @@ -1,1472 +0,0 @@ - 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.__MEM_INIT - jp .core.__MAIN_PROGRAM__ -.core.__CALL_BACK__: - DEFW 0 -.core.ZXBASIC_USER_DATA: - ; Defines HEAP SIZE -.core.ZXBASIC_HEAP_SIZE EQU 4768 -.core.ZXBASIC_MEM_HEAP: - DEFS 4768 - ; 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 -.core.ZXBASIC_USER_DATA_END: -.core.__MAIN_PROGRAM__: -.LABEL._10: - call .core.CLS -.LABEL._20: - call .core.COPY_ATTR - ld a, 128 - push af - ld a, 87 - push af - ld a, 87 - call .core.CIRCLE -.LABEL._30: - ld hl, .LABEL.__LABEL0 - xor a - call .core.USR_STR - push hl - ld a, 87 - push af - ld a, 128 - call _SPFill -.LABEL._40: - ld hl, 0 - call .core.__PAUSE - 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 -_SPFill: -#line 11 "/zxbasic/src/lib/arch/zx48k/stdlib/SP/Fill.bas" - push namespace core - PROC - LOCAL SPPFill - LOCAL SPPFill_start - LOCAL SPPFill_end - POP BC - POP HL - POP DE - LD L,A - PUSH BC - push ix - call SPPFill_start - pop ix - ret -SPPFill_IXBuffer: - DEFB 0,0 -SPPFill_start: - LD BC,300 - LD (SPPFill_IXBuffer),IX -SPPFill: - push de - dec bc - push bc - call SPGetScrnAddr - ex de,hl - call bytefill - jr c, viable - pop bc - pop de - jp SPPFill_end - LOCAL viable -viable: - ex de,hl - ld hl,-7 - add hl,sp - push hl - push hl - pop ix - dec hl - dec hl - dec hl - push hl - ld hl,-12 - add hl,sp - push hl - xor a - push af - dec sp - push de - push bc - inc sp - push af - dec sp - ld c,(ix+7) - ld b,(ix+8) - inc bc - ld l,c - ld h,b - add hl,bc - add hl,bc - ld c,l - ld b,h - ld hl,0 - sbc hl,bc - add hl,sp - ld (hl),0 - ld sp,hl - ld a,$80 - push af - inc sp - ld e,l - ld d,h - inc de - dec bc - ldir - LOCAL pfloop -pfloop: - ld l,(ix+3) - ld h,(ix+4) - ld e,(ix+1) - ld d,(ix+2) - call investigate - ld (ix+1),e - ld (ix+2),d - ld (ix+3),l - ld (ix+4),h - ld l,(ix+5) - ld h,(ix+6) - ld c,(ix+7) - ld b,(ix+8) - call applypattern - ld (ix+7),c - ld (ix+8),b - ld (ix+5),l - ld (ix+6),h - ld a,(hl) - cp 40h - jp nc, pfloop - LOCAL endpfill -endpfill: - ld de,11 - add ix,de - ld sp,ix - or a - ret - LOCAL investigate -investigate: - ld a,(hl) - cp 80h - jp c, inowrap - push ix - pop hl - ld a,(hl) - LOCAL inowrap -inowrap: - cp 40h - jp c, endinv - ld b,a - dec hl - ld c,(hl) - dec hl - ld a,(hl) - dec hl - push hl - ld l,c - ld h,b - ld b,a - LOCAL goup -goup: - push hl - call SP.PixelUp - jr c, updeadend - push bc - call bytefill - call c, addnew - pop bc - LOCAL updeadend -updeadend: - pop hl - LOCAL godown -godown: - push hl - call SP.PixelDown - jr c, downdeadend - push bc - call bytefill - call c, addnew - pop bc - LOCAL downdeadend -downdeadend: - pop hl - LOCAL goleft -goleft: - bit 7,b - jr z, goright - ld a,l - and 31 - jr nz, okleft - bit 5,h - jr z, goright - LOCAL okleft -okleft: - push hl - call SP.CharLeft - push bc - ld b,01h - call bytefill - call c, addnew - pop bc - pop hl - LOCAL goright -goright: - bit 0,b - jr z, nextinv - or a - call SP.CharRight - jr c, nextinv - ld a,l - and 31 - jr z, nextinv - ld b,80h - call bytefill - call c, addnew - LOCAL nextinv -nextinv: - pop hl - jp investigate - LOCAL endinv -endinv: - dec hl - dec hl - dec hl - ld a,(de) - cp 80h - jr c, nowrapnew - defb $dd - ld e,l - defb $dd - ld d,h - LOCAL nowrapnew -nowrapnew: - xor a - ld (de),a - dec de - dec de - dec de - ret - LOCAL bytefill -bytefill: - ld a,b - xor (hl) - and b - ret z - LOCAL bfloop -bfloop: - ld b,a - rra - ld c,a - ld a,b - add a,a - or c - or b - ld c,a - xor (hl) - and c - cp b - jp nz, bfloop - or (hl) - ld (hl),a - scf - ret - LOCAL addnew -addnew: - push hl - ld l,(ix+7) - ld h,(ix+8) - ld a,h - or l - jr z, bail - dec hl - ld (ix+7),l - ld (ix+8),h - pop hl - ld a,(de) - cp 80h - jr c, annowrap - defb $dd - ld e,l - defb $dd - ld d,h - LOCAL annowrap -annowrap: - ex de,hl - ld (hl),d - dec hl - ld (hl),e - dec hl - ld (hl),b - dec hl - ex de,hl - ret - LOCAL bail -bail: - pop hl - ld a,b - xor (hl) - ld (hl),a - xor a - ld (de),a - ld l,(ix+5) - ld h,(ix+6) - call applypattern - call applypattern - call applypattern - ld de,11 - add ix,de - ld sp,ix - scf - jp SPPFill_end - LOCAL applypattern -applypattern: - ld a,(hl) - cp 80h - jp c, apnowrap - push ix - pop hl - ld a,(hl) - LOCAL apnowrap -apnowrap: - cp 40h - jr c, endapply - and 07h - add a,(ix+9) - ld e,a - ld a,0 - adc a,(ix+10) - ld d,a - ld a,(de) - ld d,(hl) - dec hl - ld e,(hl) - dec hl - and (hl) - sub (hl) - dec a - ex de,hl - and (hl) - ld (hl),a - ex de,hl - dec hl - inc bc - jp applypattern - LOCAL endapply -endapply: - dec hl - dec hl - dec hl - ret -SPPFill_end: - LD IX,(SPPFill_IXBuffer) - ENDP - pop namespace -#line 541 "/zxbasic/src/lib/arch/zx48k/stdlib/SP/Fill.bas" -_SPFill__leave: - ret -.LABEL.__LABEL0: - DEFW 0001h - DEFB 61h - ;; --- end of user code --- -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/SP/CharLeft.asm" - ; - ; CharLeft - ; Alvin Albrecht 2002 - ; - ;INCLUDE "SPconfig.def" - ;XLIB SPCharLeft - ; Char Left - ; - ; Adjusts screen address HL to move one character to the left - ; on the display. Start of line wraps to the previous row. - ; -; enter: HL = valid screen address - ; Carry reset -; exit : Carry = moved off screen - ; HL = moves one character left, with line wrap -; used : AF, HL - ;IF !DISP_HIRES - push namespace core -SP.CharLeft: - ld a,l - dec l - or a - ret nz - ld a,h - sub $08 - ld h,a - cp $40 - ret - pop namespace - ;ELSE - ;.SPCharLeft - ; ld a,h - ; xor $20 - ; ld h,a - ; cp $58 - ; ccf - ; ret nc - ; ld a,l - ; dec l - ; or a - ; ret nz - ; ld a,h - ; sub $08 - ; ld h,a - ; and $18 - ; cp $18 - ; ccf - ; ret - ; ENDIF -#line 549 "/zxbasic/src/lib/arch/zx48k/stdlib/SP/Fill.bas" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/SP/CharRight.asm" - ; - ; CharRight - ; Alvin Albrecht 2002 - ; - ;INCLUDE "SPconfig.def" - ;XLIB SPCharRight - ; Char Right - ; - ; Adjusts screen address HL to move one character to the right - ; on the display. End of line wraps to the next row. - ; -; enter: HL = valid screen address - ; Carry reset -; exit : Carry = moved off screen - ; HL = moves one character right, with line wrap -; used : AF, HL - ;IF !DISP_HIRES - push namespace core -SP.CharRight: - inc l - ret nz - ld a,8 - add a,h - ld h,a - cp $58 - ccf - ret - pop namespace - ;ELSE - ;.SPCharRight - ; ld a,h - ; xor $20 - ; ld h,a - ; cp $58 - ; ret nc - ; inc l - ; ret nz - ; ld a,8 - ; add a,h - ; ld h,a - ; cp $58 - ; ccf - ; ret - ; ENDIF -#line 550 "/zxbasic/src/lib/arch/zx48k/stdlib/SP/Fill.bas" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/SP/GetScrnAddr.asm" - ; - ; GetScrnAddr - ; Alvin Albrecht 2002 - ; - ; Get Screen Address - ; - ; Computes the screen address given a valid pixel coordinate. - ; (0,0) is located at the top left corner of the screen. - ; -; enter: h = y coord - ; l = x coord - ; In hi-res mode, Carry is most significant bit of x coord (0..511 pixels) -; exit : de = screen address, b = pixel mask -; uses : af, b, de, hl - push namespace core - PROC - LOCAL rotloop, norotate -SPGetScrnAddr: - ld a,h - and $07 - ld d,a - ld a,h - rra - rra - rra - and $18 - or d - ld d,a - ld a,l - and $07 - ld b,a - ld a,$80 - jr z, norotate -rotloop: - rra - djnz rotloop -norotate: - ld b,a - srl l - srl l - srl l - ld a,h - rla - rla - and $e0 - or l - ld e,a - ld hl, (SCREEN_ADDR) - add hl, de - ex de, hl - ret - ENDP - pop namespace -#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 63 "/zxbasic/src/lib/arch/zx48k/runtime/SP/GetScrnAddr.asm" -#line 551 "/zxbasic/src/lib/arch/zx48k/stdlib/SP/Fill.bas" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/SP/PixelDown.asm" - ; - ; PixelDown - ; Alvin Albrecht 2002 - ; - ; Pixel Down - ; - ; Adjusts screen address HL to move one pixel down in the display. - ; (0,0) is located at the top left corner of the screen. - ; -; enter: HL = valid screen address -; exit : Carry = moved off screen - ; Carry'= moved off current cell (needs ATTR update) - ; HL = moves one pixel down -; used : AF, HL - push namespace core -SP.PixelDown: - PROC - LOCAL leave - push de - ld de, (SCREEN_ADDR) - or a - sbc hl, de - inc h - ld a,h - and $07 - jr nz, leave - scf ; Sets carry on F', which flags ATTR must be updated - ex af, af' - ld a,h - sub $08 - ld h,a - ld a,l - add a,$20 - ld l,a - jr nc, leave - ld a,h - add a,$08 - ld h,a - cp $19 ; carry = 0 => Out of screen - jr c, leave ; returns if out of screen - ccf - pop de - ret -leave: - add hl, de ; This always sets Carry = 0 - pop de - ret - ENDP - pop namespace -#line 552 "/zxbasic/src/lib/arch/zx48k/stdlib/SP/Fill.bas" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/SP/PixelUp.asm" - ; - ; PixelUp - ; Alvin Albrecht 2002 - ; - ; Pixel Up - ; - ; Adjusts screen address HL to move one pixel up in the display. - ; (0,0) is located at the top left corner of the screen. - ; -; enter: HL = valid screen address -; exit : Carry = moved off screen - ; HL = moves one pixel up -; used : AF, HL - push namespace core -SP.PixelUp: - PROC - LOCAL leave - push de - ld de, (SCREEN_ADDR) - or a - sbc hl, de - ld a,h - dec h - and $07 - jr nz, leave - scf ; sets C' to 1 (ATTR update needed) - ex af, af' - ld a,$08 - add a,h - ld h,a - ld a,l - sub $20 - ld l,a - jr nc, leave - ld a,h - sub $08 - ld h,a -leave: - push af - add hl, de - pop af - pop de - ret - ENDP - pop namespace -#line 553 "/zxbasic/src/lib/arch/zx48k/stdlib/SP/Fill.bas" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/circle.asm" - ; Bresenham's like circle algorithm - ; best known as Middle Point Circle drawing algorithm -#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 5 "/zxbasic/src/lib/arch/zx48k/runtime/circle.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/plot.asm" - ; MIXED __FASTCAL__ / __CALLE__ PLOT Function - ; Plots a point into the screen calling the ZX ROM PLOT routine - ; Y in A (accumulator) - ; X in top of the stack -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/in_screen.asm" -#line 1 "/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: - 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 2 "/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 9 "/zxbasic/src/lib/arch/zx48k/runtime/plot.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/set_pixel_addr_attr.asm" - push namespace core - ; Sets the attribute at a given screen pixel address in hl - ; HL contains the address in RAM for a given pixel (not a coordinate) -SET_PIXEL_ADDR_ATTR: - ;; gets ATTR position with offset given in SCREEN_ADDR - ld de, (SCREEN_ADDR) - or a - sbc hl, de - ld a, h - rrca - rrca - rrca - and 3 - ld h, a - ld de, (SCREEN_ATTR_ADDR) - add hl, de ;; Final screen addr - jp __SET_ATTR2 - pop namespace -#line 11 "/zxbasic/src/lib/arch/zx48k/runtime/plot.asm" - push namespace core -PLOT: - PROC - LOCAL PLOT_SUB - LOCAL PIXEL_ADDR - LOCAL COORDS - LOCAL __PLOT_ERR - LOCAL P_FLAG - LOCAL __PLOT_OVER1 - P_FLAG EQU 23697 - pop hl - ex (sp), hl ; Callee - ld b, a - ld c, h -#line 37 "/zxbasic/src/lib/arch/zx48k/runtime/plot.asm" -#line 43 "/zxbasic/src/lib/arch/zx48k/runtime/plot.asm" - ld a, 191 - cp b - jr c, __PLOT_ERR ; jr is faster here (#1) -__PLOT: ; __FASTCALL__ entry (b, c) = pixel coords (y, x) - ld (COORDS), bc ; Saves current point - ld a, 191 ; Max y coord - call PIXEL_ADDR - res 6, h ; Starts from 0 - ld bc, (SCREEN_ADDR) - add hl, bc ; Now current offset - ld b, a - inc b - ld a, 0FEh - LOCAL __PLOT_LOOP -__PLOT_LOOP: - rrca - djnz __PLOT_LOOP - ld b, a - ld a, (P_FLAG) - ld c, a - ld a, (hl) - bit 0, c ; is it OVER 1 - jr nz, __PLOT_OVER1 - and b -__PLOT_OVER1: - bit 2, c ; is it inverse 1 - jr nz, __PLOT_END - xor b - cpl - LOCAL __PLOT_END -__PLOT_END: - ld (hl), a - jp SET_PIXEL_ADDR_ATTR -__PLOT_ERR: - jp __OUT_OF_SCREEN_ERR ; Spent 3 bytes, but saves 3 T-States at (#1) - PLOT_SUB EQU 22ECh - PIXEL_ADDR EQU 22ACh - COORDS EQU 5C7Dh - ENDP - pop namespace -#line 6 "/zxbasic/src/lib/arch/zx48k/runtime/circle.asm" - ; Draws a circle at X, Y of radius R - ; X, Y on the Stack, R in accumulator (Byte) - push namespace core - PROC - LOCAL __CIRCLE_ERROR - LOCAL __CIRCLE_LOOP - LOCAL __CIRCLE_NEXT -__CIRCLE_ERROR: - jp __OUT_OF_SCREEN_ERR -CIRCLE: - ;; Entry point - pop hl ; Return Address - pop de ; D = Y - ex (sp), hl ; __CALLEE__ convention - ld e, h ; E = X - ld h, a ; H = R -#line 33 "/zxbasic/src/lib/arch/zx48k/runtime/circle.asm" -#line 39 "/zxbasic/src/lib/arch/zx48k/runtime/circle.asm" - ld a, h - add a, d - sub 192 - jr nc, __CIRCLE_ERROR - ld a, d - sub h - jr c, __CIRCLE_ERROR - ld a, e - sub h - jr c, __CIRCLE_ERROR - ld a, h - add a, e - jr c, __CIRCLE_ERROR -; __FASTCALL__ Entry: D, E = Y, X point of the center - ; A = Radious -__CIRCLE: - push de - ld a, h - exx - pop de ; D'E' = x0, y0 - ld h, a ; H' = r - ld c, e - ld a, h - add a, d - ld b, a - call __CIRCLE_PLOT ; PLOT (x0, y0 + r) - ld b, d - ld a, h - add a, e - ld c, a - call __CIRCLE_PLOT ; PLOT (x0 + r, y0) - ld c, e - ld a, d - sub h - ld b, a - call __CIRCLE_PLOT ; PLOT (x0, y0 - r) - ld b, d - ld a, e - sub h - ld c, a - call __CIRCLE_PLOT ; PLOT (x0 - r, y0) - exx - ld b, 0 ; B = x = 0 - ld c, h ; C = y = Radius - ld hl, 1 - or a - sbc hl, bc ; HL = f = 1 - radius - ex de, hl - ld hl, 0 - or a - sbc hl, bc ; HL = -radius - add hl, hl ; HL = -2 * radius - ex de, hl ; DE = -2 * radius = ddF_y, HL = f - xor a ; A = ddF_x = 0 - ex af, af' ; Saves it -__CIRCLE_LOOP: - ld a, b - inc a - cp c - ret nc ; Returns when x >= y - bit 7, h ; HL >= 0? : if (f >= 0)... - jp nz, __CIRCLE_NEXT - dec c ; y-- - inc de - inc de ; ddF_y += 2 - add hl, de ; f += ddF_y -__CIRCLE_NEXT: - inc b ; x++ - ex af, af' - add a, 2 ; 1 Cycle faster than inc a, inc a - inc hl ; f++ - push af - add a, l - ld l, a - ld a, h - adc a, 0 ; f = f + ddF_x - ld h, a - pop af - ex af, af' - push bc - exx - pop hl ; H'L' = Y, X - ld a, d - add a, h - ld b, a ; B = y0 + y - ld a, e - add a, l - ld c, a ; C = x0 + x - call __CIRCLE_PLOT ; plot(x0 + x, y0 + y) - ld a, d - add a, h - ld b, a ; B = y0 + y - ld a, e - sub l - ld c, a ; C = x0 - x - call __CIRCLE_PLOT ; plot(x0 - x, y0 + y) - ld a, d - sub h - ld b, a ; B = y0 - y - ld a, e - add a, l - ld c, a ; C = x0 + x - call __CIRCLE_PLOT ; plot(x0 + x, y0 - y) - ld a, d - sub h - ld b, a ; B = y0 - y - ld a, e - sub l - ld c, a ; C = x0 - x - call __CIRCLE_PLOT ; plot(x0 - x, y0 - y) - ld a, l - cp h - jr z, 1f - ld a, d - add a, l - ld b, a ; B = y0 + x - ld a, e - add a, h - ld c, a ; C = x0 + y - call __CIRCLE_PLOT ; plot(x0 + y, y0 + x) - ld a, d - add a, l - ld b, a ; B = y0 + x - ld a, e - sub h - ld c, a ; C = x0 - y - call __CIRCLE_PLOT ; plot(x0 - y, y0 + x) - ld a, d - sub l - ld b, a ; B = y0 - x - ld a, e - add a, h - ld c, a ; C = x0 + y - call __CIRCLE_PLOT ; plot(x0 + y, y0 - x) - ld a, d - sub l - ld b, a ; B = y0 - x - ld a, e - sub h - ld c, a ; C = x0 + y - call __CIRCLE_PLOT ; plot(x0 - y, y0 - x) -1: - exx - jp __CIRCLE_LOOP -__CIRCLE_PLOT: - ; Plots a point of the circle, preserving HL and DE - push hl - push de - call __PLOT - pop de - pop hl - ret - ENDP - pop namespace -#line 554 "/zxbasic/src/lib/arch/zx48k/stdlib/SP/Fill.bas" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/cls.asm" - ;; Clears the user screen (24 rows) - push namespace core -CLS: - PROC - ld hl, 0 - ld (COORDS), hl - ld hl, SCR_SIZE - ld (S_POSN), hl - ld hl, (SCREEN_ADDR) - ld (DFCC), hl - ld (hl), 0 - ld d, h - ld e, l - inc de - ld bc, 6143 - ldir - ; Now clear attributes - ld hl, (SCREEN_ATTR_ADDR) - ld (DFCCL), hl - ld d, h - ld e, l - inc de - ld a, (ATTR_P) - ld (hl), a - ld bc, 767 - ldir - ret - ENDP - pop namespace -#line 555 "/zxbasic/src/lib/arch/zx48k/stdlib/SP/Fill.bas" -#line 1 "/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) -#line 65 "/zxbasic/src/lib/arch/zx48k/runtime/copy_attr.asm" - ret -#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 556 "/zxbasic/src/lib/arch/zx48k/stdlib/SP/Fill.bas" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/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 557 "/zxbasic/src/lib/arch/zx48k/stdlib/SP/Fill.bas" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/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 -; to "A: Invalid Argument" - ; On entry HL points to the string - ; and A register is non-zero if the string must be freed (TMP string) -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/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/lib/arch/zx48k/runtime/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/lib/arch/zx48k/runtime/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 11 "/zxbasic/src/lib/arch/zx48k/runtime/usr_str.asm" - push namespace core -USR_STR: - PROC - ex af, af' ; Saves A flag - ld a, h - or l - jr z, USR_ERROR ; a$ = NULL => Invalid Arg - ld d, h ; Saves HL in DE, for - ld e, l ; later usage - ld c, (hl) - inc hl - ld a, (hl) - or c - jr z, USR_ERROR ; a$ = "" => Invalid Arg - inc hl - ld a, (hl) ; Only the 1st char is needed - and %11011111 ; Convert it to UPPER CASE - sub 144 ; CODE(UDG "A") - jr nc, CONT - add a, 144 ; It was a letter - sub 'A' - LOCAL CONT -CONT: - ld l, a - ld h, 0 - add hl, hl - add hl, hl - add hl, hl ; hl = A * 8 - ld bc, (UDG) - add hl, bc - ;; Now checks if the string must be released - ex af, af' ; Recovers A flag - or a - ret z ; return if not - push hl ; saves result since __MEM_FREE changes HL - ex de, hl ; Recovers original HL value - call __MEM_FREE - pop hl - ret -USR_ERROR: - ex de, hl ; Recovers original HL value - ex af, af' ; Recovers A flag - or a - call nz, __MEM_FREE - ld a, ERROR_InvalidArg - ld (ERR_NR), a - ld hl, 0 - ret - ENDP - pop namespace -#line 558 "/zxbasic/src/lib/arch/zx48k/stdlib/SP/Fill.bas" - END diff --git a/tests/functional/arch/zx48k/usr0.asm b/tests/functional/arch/zx48k/usr0.asm index f0b79daeb..72f533336 100644 --- a/tests/functional/arch/zx48k/usr0.asm +++ b/tests/functional/arch/zx48k/usr0.asm @@ -11,7 +11,6 @@ ld (.core.__CALL_BACK__), hl ei call .core.__MEM_INIT - call .core.__PRINT_INIT jp .core.__MAIN_PROGRAM__ .core.__CALL_BACK__: DEFW 0 @@ -24,14 +23,14 @@ .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, 00 .core.ZXBASIC_USER_DATA_END: .core.__MAIN_PROGRAM__: - call .core.COPY_ATTR ld hl, .LABEL.__LABEL0 xor a call .core.USR_STR - call .core.__PRINTU16 - call .core.PRINT_EOL + ld (_a), hl ld hl, 0 ld b, h ld c, l @@ -50,42 +49,12 @@ DEFW 0001h DEFB 41h ;; --- 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/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 +; to "A: Invalid Argument" + ; On entry HL points to the string + ; and A register is non-zero if the string must be freed (TMP string) #line 1 "/zxbasic/src/lib/arch/zx48k/runtime/error.asm" ; Simple error control routines ; vim:ts=4:et: @@ -120,1004 +89,34 @@ __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/usr0.bas" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/printu16.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/printi16.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/printi16.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/div16.asm" - ; 16 bit division and modulo functions - ; for both signed and unsigned values -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/neg16.asm" - ; Negates HL value (16 bit) - push namespace core -__ABS16: - bit 7, h - ret z -__NEGHL: - ld a, l ; HL = -HL - cpl - ld l, a - ld a, h - cpl - ld h, a - inc hl - ret - pop namespace -#line 5 "/zxbasic/src/lib/arch/zx48k/runtime/div16.asm" - push namespace core -__DIVU16: ; 16 bit unsigned division - ; HL = Dividend, Stack Top = Divisor - ; -- OBSOLETE ; Now uses FASTCALL convention - ; ex de, hl - ; pop hl ; Return address - ; ex (sp), hl ; CALLEE Convention -__DIVU16_FAST: - ld a, h - ld c, l - ld hl, 0 - ld b, 16 -__DIV16LOOP: - sll c - rla - adc hl,hl - sbc hl,de - jr nc, __DIV16NOADD - add hl,de - dec c -__DIV16NOADD: - djnz __DIV16LOOP - ex de, hl - ld h, a - ld l, c - ret ; HL = quotient, DE = Mudulus -__MODU16: ; 16 bit modulus - ; HL = Dividend, Stack Top = Divisor - ;ex de, hl - ;pop hl - ;ex (sp), hl ; CALLEE Convention - call __DIVU16_FAST - ex de, hl ; hl = reminder (modulus) - ; de = quotient - ret -__DIVI16: ; 16 bit signed division - ; --- The following is OBSOLETE --- - ; ex de, hl - ; pop hl - ; ex (sp), hl ; CALLEE Convention -__DIVI16_FAST: - ld a, d - xor h - ex af, af' ; BIT 7 of a contains result - bit 7, d ; DE is negative? - jr z, __DIVI16A - ld a, e ; DE = -DE - cpl - ld e, a - ld a, d - cpl - ld d, a - inc de -__DIVI16A: - bit 7, h ; HL is negative? - call nz, __NEGHL -__DIVI16B: - call __DIVU16_FAST - ex af, af' - or a - ret p ; return if positive - jp __NEGHL -__MODI16: ; 16 bit modulus - ; HL = Dividend, Stack Top = Divisor - ;ex de, hl - ;pop hl - ;ex (sp), hl ; CALLEE Convention - call __DIVI16_FAST - ex de, hl ; hl = reminder (modulus) - ; de = quotient - ret - pop namespace -#line 3 "/zxbasic/src/lib/arch/zx48k/runtime/printi16.asm" - push namespace core -__PRINTI16: ; Prints a 16bits signed in HL - ; Converts 16 to 32 bits - PROC - LOCAL __PRINTU_LOOP - ld a, h - or a - jp p, __PRINTU16 - call __PRINT_MINUS - call __NEGHL -__PRINTU16: - ld b, 0 -__PRINTU_LOOP: - ld a, h - or l - jp z, __PRINTU_START - push bc - ld de, 10 - call __DIVU16_FAST ; Divides by DE. DE = MODULUS at exit. Since < 256, E = Modulus - pop bc - ld a, e - or '0' ; Stores ASCII digit (must be print in reversed order) - push af - inc b - jp __PRINTU_LOOP ; Uses JP in loops - ENDP - pop namespace -#line 2 "/zxbasic/src/lib/arch/zx48k/runtime/printu16.asm" -#line 28 "arch/zx48k/usr0.bas" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/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 -; to "A: Invalid Argument" - ; On entry HL points to the string - ; and A register is non-zero if the string must be freed (TMP string) +#line 9 "/zxbasic/src/lib/arch/zx48k/runtime/usr_str.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 10 "/zxbasic/src/lib/arch/zx48k/runtime/usr_str.asm" #line 1 "/zxbasic/src/lib/arch/zx48k/runtime/free.asm" ; vim: ts=4:et:sw=4: ; Copyleft (K) by Jose M. Rodriguez de la Rosa @@ -1435,5 +434,5 @@ USR_ERROR: ret ENDP pop namespace -#line 29 "arch/zx48k/usr0.bas" +#line 24 "arch/zx48k/usr0.bas" END diff --git a/tests/functional/arch/zx48k/usr0.bas b/tests/functional/arch/zx48k/usr0.bas index 38eb51c57..8cf4a9609 100644 --- a/tests/functional/arch/zx48k/usr0.bas +++ b/tests/functional/arch/zx48k/usr0.bas @@ -1 +1,2 @@ -PRINT USR "A" +DIM a AS UInteger +LET a = USR "A" diff --git a/tests/functional/arch/zxnext/fact.asm b/tests/functional/arch/zxnext/fact.asm new file mode 100644 index 000000000..53f8ee768 --- /dev/null +++ b/tests/functional/arch/zxnext/fact.asm @@ -0,0 +1,211 @@ + org 32768 +.core.__START_PROGRAM: + di + push iy + ld iy, 0x5C3A ; ZX Spectrum ROM variables address + ld hl, 0 + add hl, sp + ld (.core.__CALL_BACK__), hl + ei + 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 +_y: + DEFB 00, 00, 00, 00 +_x: + DEFB 00 +.core.ZXBASIC_USER_DATA_END: +.core.__MAIN_PROGRAM__: + ld a, 1 + ld (_x), a + jp .LABEL.__LABEL0 +.LABEL.__LABEL3: + ld a, (_x) + ld l, a + ld h, 0 + ld e, h + ld d, h + ld (_y), hl + ld (_y + 2), de +.LABEL.__LABEL4: + ld hl, _x + inc (hl) +.LABEL.__LABEL0: + ld a, 10 + ld hl, (_x - 1) + cp h + jp nc, .LABEL.__LABEL3 +.LABEL.__LABEL2: + ld hl, 0 + ld b, h + ld c, l +.core.__END_PROGRAM: + di + ld hl, (.core.__CALL_BACK__) + ld sp, hl + pop iy + ei + ret +_fact: + push ix + ld ix, 0 + add ix, sp + ld l, (ix+4) + ld h, (ix+5) + ld e, (ix+6) + ld d, (ix+7) + push de + push hl + ld de, 0 + ld hl, 2 + call .core.__SUB32 + jp nc, .LABEL.__LABEL6 + ld de, 0 + ld hl, 1 + jp _fact__leave +.LABEL.__LABEL6: + ld l, (ix+4) + ld h, (ix+5) + ld e, (ix+6) + ld d, (ix+7) + push de + push hl + ld l, (ix+4) + ld h, (ix+5) + ld e, (ix+6) + ld d, (ix+7) + push de + push hl + ld de, 0 + ld hl, 1 + call .core.__SUB32 + push de + push hl + call _fact + call .core.__MUL32 +_fact__leave: + ld sp, ix + pop ix + exx + pop hl + pop bc + ex (sp), hl + exx + ret + ;; --- end of user code --- +#line 1 "/zxbasic/src/lib/arch/zxnext/runtime/arith/mul32.asm" +#line 1 "/zxbasic/src/lib/arch/zxnext/runtime/arith/_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/lib/arch/zxnext/runtime/arith/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 79 "arch/zxnext/fact.bas" +#line 1 "/zxbasic/src/lib/arch/zxnext/runtime/arith/sub32.asm" + ; SUB32 + ; Perform TOP of the stack - DEHL + ; Pops operand out of the stack (CALLEE) + ; and returns result in DEHL. Carry an Z are set correctly + push namespace core +__SUB32: + exx + pop bc ; saves return address in BC' + exx + or a ; clears carry flag + ld b, h ; Operands come reversed => BC <- HL, HL = HL - BC + ld c, l + pop hl + sbc hl, bc + ex de, hl + ld b, h ; High part (DE) now in HL. Repeat operation + ld c, l + pop hl + sbc hl, bc + ex de, hl ; DEHL now has de 32 bit result + exx + push bc ; puts return address back + exx + ret + pop namespace +#line 80 "arch/zxnext/fact.bas" + END diff --git a/tests/functional/arch/zxnext/fact.bas b/tests/functional/arch/zxnext/fact.bas new file mode 100644 index 000000000..80cf0e1d6 --- /dev/null +++ b/tests/functional/arch/zxnext/fact.bas @@ -0,0 +1,14 @@ +REM Factorial recursive test +DIM y as ulong + +function fact(x as ulong) as ulong + if x < 2 then + return 1 + end if + + return x * fact(x - 1) +end function + +for x = 1 To 10: + let y = x: rem dummy +next x diff --git a/tests/functional/arch/zx48k/spfill.bas b/tests/runtime/cases/spfill.bas similarity index 56% rename from tests/functional/arch/zx48k/spfill.bas rename to tests/runtime/cases/spfill.bas index 1ed358ef1..d9480b60d 100644 --- a/tests/functional/arch/zx48k/spfill.bas +++ b/tests/runtime/cases/spfill.bas @@ -3,8 +3,9 @@ ' Ported to ZX Basic by Paul Fisher (Britlion) #Include +#Include "lib/tst_framework.bas" -10 CLS -20 CIRCLE 128, 87, 87 -30 SPFill(128, 87, USR "a") -40 PAUSE 0 +INIT("Testing SPFill...") +CIRCLE 128, 87, 87 +SPFill(128, 87, USR "a") +REPORT_OK diff --git a/tests/runtime/expected/spfill.tzx.scr b/tests/runtime/expected/spfill.tzx.scr new file mode 100644 index 000000000..c2bcc3965 Binary files /dev/null and b/tests/runtime/expected/spfill.tzx.scr differ