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