From 46a3578de45010ca053e7ab5874e1626722955c9 Mon Sep 17 00:00:00 2001 From: ConradoBadenas Date: Fri, 24 Oct 2025 19:02:51 +0200 Subject: [PATCH] Updated tests and scroll.bas --- src/lib/arch/zx48k/stdlib/scroll.bas | 683 ++++++++++++++---- src/lib/arch/zxnext/stdlib/scroll.bas | 683 ++++++++++++++---- tests/functional/arch/zx48k/stdlib_scroll.asm | 597 +++++++++++---- 3 files changed, 1531 insertions(+), 432 deletions(-) diff --git a/src/lib/arch/zx48k/stdlib/scroll.bas b/src/lib/arch/zx48k/stdlib/scroll.bas index 33cfa9919..deec71f2d 100644 --- a/src/lib/arch/zx48k/stdlib/scroll.bas +++ b/src/lib/arch/zx48k/stdlib/scroll.bas @@ -1,8 +1,9 @@ ' ---------------------------------------------------------------- ' This file is released under the MIT License ' -' Copyleft (k) 2008 +' Copyleft (k) 2008, 2025 ' by Jose Rodriguez-Rosa (a.k.a. Boriel) +' and Conrado Badenas ' ' Use this file as a template to develop your own library file ' ---------------------------------------------------------------- @@ -26,9 +27,10 @@ sub fastcall ScrollRight(x1 as uByte, y1 as uByte, x2 as Ubyte, y2 as Ubyte) push namespace core PROC - LOCAL LOOP1 - LOCAL LOOP2 + LOCAL LOOP1, LOOP2, MASK1, MASK2, COLUMNN, NEQ1 + LOCAL AND1, AND2, AND3, AND4, AND5, AND6, AND7, AND8 +; Read parameters, return if they are bad ; a = x1 pop hl ; RET address pop bc ; b = y1 @@ -40,51 +42,152 @@ sub fastcall ScrollRight(x1 as uByte, y1 as uByte, x2 as Ubyte, y2 as Ubyte) sub c ret c ; x1 > x2 - srl a - srl a - srl a - inc a - ld e, a ; e = (x2 - x1) / 8 + 1 - ld a, h sub b ret c ; y1 > y2 +; Compute height and masks inc a - ld d, a ; d = y2 - y1 + 1 + ld e, a ; e = y2 - y1 + 1 + + ld a,c ;e.g. x1 = 3, mask1 = %11100000, CPL = %00011111 + and 7 + inc a + ld b,a ;B = 1 + (x1 MOD 8) = 1,2,...,8 for x1 = 0,1,...,7 + 8*n + xor a +MASK1: + rra + scf ;inject B-1 1s from the left + djnz MASK1 + ld (AND1+1),a ;e.g. %11100000 + ld (AND5+1),a + cpl + ld (AND2+1),a ;e.g. %00011111 + ld (AND7+1),a + + ld a,d ;e.g. x2 = 5, mask2 = %11111100, CPL = %00000011 + and 7 + inc a + ld b,a ;B = 1 + (x2 MOD 8) = 1,2,...,8 for x2 = 0,1,...,7 + 8*n + xor a +MASK2: + scf ;inject B 1s from the left + rra + djnz MASK2 + ld (AND4+1),a ;e.g. %11111100 + ld (AND8+1),a + cpl + ld (AND3+1),a ;e.g. %00000011 + ld (AND6+1),a + +; Compute Ncols and Display File address, and choose branch + ld a,c ;x1 + and %11111000 + rrca + rrca + rrca + ld b,a ;col1 + ld a,d ;x2 + and %11111000 + rrca + rrca + rrca ;col2 + sub b ;A = Ncols - 1 = col2 - col1 + ex af,af' ;save Ncols-1 and ZeroFlag ld b, h ; BC = y2x1 ld a, 191 - LOCAL __PIXEL_ADDR -__PIXEL_ADDR EQU 22ACh - call __PIXEL_ADDR + call 22ACh ; 2 bytes after the 'PIXEL ADDRESS' subroutine, because +; https://skoolkid.github.io/rom/asm/22AA.html starts with LD A,175 res 6, h ; Starts from 0 ld bc, (SCREEN_ADDR) add hl, bc ; Now current offset + ex af,af' ;load Ncols-1 and ZeroFlag + jr z,NEQ1 + +; N > 1 (there are 2 or more columns) + dec a ;A = Ncols - 2 + ld d,a ;D = N-2 LOOP1: - push hl - ld b, e ; C cols - or a ; clear carry flag + push hl +; Scroll column 1 + ld a,(hl) +AND1: + and %11100000 ;e.g. x1 = 3 + ld c,a ;get out-window part of byte + ld a,(hl) +AND2: + and %00011111 ;e.g. x1 = 3 + rra ;scroll in-window part of byte + rl b ;CF is stored as bit0 of B + or c ;put out-window part of byte + ld (hl),a + inc hl +; Scroll columns 2,3,...,N-1 + ld a,d ;N-2 + and a ;A=0 iff N=2 + jr z,COLUMNN + rr b ;CF is on stage + ld b,a LOOP2: - rr (hl) - inc hl - djnz LOOP2 - pop hl - - dec d - ret z - call SP.PixelDown - jp LOOP1 + rr (hl) + inc hl + djnz LOOP2 + rl b ;CF is stored as bit0 of B +; Scroll column N +COLUMNN: + ld a,(hl) +AND3: + and %00000011 ;e.g. x2 = 5 + ld c,a ;get out-window part of byte + ld a,(hl) + rr b ;CF is on stage + rra ;scroll in-window part of byte +AND4: + and %11111100 ;e.g. x2 = 5 + or c ;put out-window part of byte + ld (hl),a +; Scroll another line + pop hl + dec e + ret z + call SP.PixelDown + jp LOOP1 + +; N = 1 (there is only one column) +NEQ1: + ld b,(hl) + ld a,b +AND5: + and %11100000 ;e.g. x1 = 3 + ld c,a + ld a,b +AND6: + and %00000011 ;e.g. x2 = 5 + or c + ld c,a ;get out-window part of byte + ld a,b +AND7: + and %00011111 ;e.g. x1 = 3 + rra ;scroll in-window part of byte +AND8: + and %11111100 ;e.g. x2 = 5 + or c ;put out-window part of byte + ld (hl),a +; Scroll another line + dec e + ret z + call SP.PixelDown + jp NEQ1 ENDP pop namespace end asm end sub - ' ---------------------------------------------------------------- -' sub ScrolLeft +' sub ScrollLeft ' pixel by pixel left scroll ' scrolls 1 pixel left the window defined by (x1, y1, x2, y2) ' ---------------------------------------------------------------- @@ -93,9 +196,10 @@ sub fastcall ScrollLeft(x1 as uByte, y1 as uByte, x2 as Ubyte, y2 as Ubyte) push namespace core PROC - LOCAL LOOP1 - LOCAL LOOP2 + LOCAL LOOP1, LOOP2, MASK1, MASK2, COLUMN1, NEQ1 + LOCAL AND1, AND2, AND3, AND4, AND5, AND6, AND7, AND8 +; Read parameters, return if they are bad ; a = x1 pop hl ; RET address pop bc ; b = y1 @@ -107,43 +211,145 @@ sub fastcall ScrollLeft(x1 as uByte, y1 as uByte, x2 as Ubyte, y2 as Ubyte) sub c ret c ; x1 > x2 - srl a - srl a - srl a - inc a - ld e, a ; e = (x2 - x1) / 8 + 1 - ld a, h sub b ret c ; y1 > y2 - ld c, d +; Compute height and masks inc a - ld d, a ; d = y2 - y1 + 1 + ld e, a ; e = y2 - y1 + 1 - ld b, h ; BC = y2x1 + ld a,c ;e.g. x1 = 3, mask1 = %11100000, CPL = %00011111 + and 7 + inc a + ld b,a ;B = 1 + (x1 MOD 8) = 1,2,...,8 for x1 = 0,1,...,7 + 8*n + xor a +MASK1: + rra + scf ;inject B-1 1s from the left + djnz MASK1 + ld (AND3+1),a ;e.g. %00000011 + ld (AND6+1),a + cpl + ld (AND4+1),a ;e.g. %11111100 + ld (AND8+1),a + + ld a,d ;e.g. x2 = 5, mask2 = %11111100, CPL = %00000011 + and 7 + inc a + ld b,a ;B = 1 + (x2 MOD 8) = 1,2,...,8 for x2 = 0,1,...,7 + 8*n + xor a +MASK2: + scf ;inject B 1s from the left + rra + djnz MASK2 + ld (AND2+1),a ;e.g. %00011111 + ld (AND7+1),a + cpl + ld (AND1+1),a ;e.g. %11100000 + ld (AND5+1),a + +; Compute Ncols and Display File address, and choose branch + ld a,c ;x1 + and %11111000 + rrca + rrca + rrca + ld b,a ;col1 + ld a,d ;x2 + and %11111000 + rrca + rrca + rrca ;col2 + sub b ;A = Ncols - 1 = col2 - col1 + ex af,af' ;save Ncols-1 and ZeroFlag + + ld c, d + ld b, h ; BC = y2x2 ld a, 191 - LOCAL __PIXEL_ADDR -__PIXEL_ADDR EQU 22ACh - call __PIXEL_ADDR + call 22ACh ; 2 bytes after the 'PIXEL ADDRESS' subroutine, because +; https://skoolkid.github.io/rom/asm/22AA.html starts with LD A,175 res 6, h ; Starts from 0 ld bc, (SCREEN_ADDR) add hl, bc ; Now current offset + ex af,af' ;load Ncols-1 and ZeroFlag + jr z,NEQ1 + +; N > 1 (there are 2 or more columns) + dec a ;A = Ncols - 2 + ld d,a ;D = N-2 LOOP1: - push hl - ld b, e ; C cols - or a ; clear carry flag + push hl +; Scroll column N + ld a,(hl) +AND1: + and %00000011 ;e.g. x2 = 5 + ld c,a ;get out-window part of byte + ld a,(hl) +AND2: + and %11111100 ;e.g. x2 = 5 + rla ;scroll in-window part of byte + rl b ;CF is stored as bit0 of B + or c ;put out-window part of byte + ld (hl),a + dec hl +; Scroll columns N-1,...,3,2 + ld a,d ;N-2 + and a ;A=0 iff N=2 + jr z,COLUMN1 + rr b ;CF is on stage + ld b,a LOOP2: - rl (hl) - dec hl - djnz LOOP2 - pop hl - - dec d - ret z - call SP.PixelDown - jp LOOP1 + rl (hl) + dec hl + djnz LOOP2 + rl b ;CF is stored as bit0 of B +; Scroll column 1 +COLUMN1: + ld a,(hl) +AND3: + and %11100000 ;e.g. x1 = 3 + ld c,a ;get out-window part of byte + ld a,(hl) + rr b ;CF is on stage + rla ;scroll in-window part of byte +AND4: + and %00011111 ;e.g. x1 = 3 + or c ;put out-window part of byte + ld (hl),a +; Scroll another line + pop hl + dec e + ret z + call SP.PixelDown + jp LOOP1 + +; N = 1 (there is only one column) +NEQ1: + ld b,(hl) + ld a,b +AND5: + and %00000011 ;e.g. x2 = 5 + ld c,a + ld a,b +AND6: + and %11100000 ;e.g. x1 = 3 + or c + ld c,a ;get out-window part of byte + ld a,b +AND7: + and %11111100 ;e.g. x2 = 5 + rla ;scroll in-window part of byte +AND8: + and %00011111 ;e.g. x1 = 3 + or c ;put out-window part of byte + ld (hl),a +; Scroll another line + dec e + ret z + call SP.PixelDown + jp NEQ1 ENDP pop namespace @@ -152,7 +358,7 @@ end sub ' ---------------------------------------------------------------- -' sub ScrolUp +' sub ScrollUp ' pixel by pixel up scroll ' scrolls 1 pixel up the window defined by (x1, y1, x2, y2) ' ---------------------------------------------------------------- @@ -161,8 +367,11 @@ sub fastcall ScrollUp(x1 as uByte, y1 as uByte, x2 as Ubyte, y2 as Ubyte) push namespace core PROC - LOCAL LOOP1 + LOCAL LOOP1, MASK1, MASK2, COLUMNN, NEQ1 + LOCAL AND1, AND2, AND3, AND4, AND5, AND6, AND7, AND8 + LOCAL EMPTYLINE +; Read parameters, return if they are bad ; a = x1 pop hl ; RET address pop bc ; b = y1 @@ -174,62 +383,153 @@ sub fastcall ScrollUp(x1 as uByte, y1 as uByte, x2 as Ubyte, y2 as Ubyte) sub c ret c ; x1 > x2 - srl a - srl a - srl a - inc a - ld e, a ; e = (x2 - x1) / 8 + 1 - ex af, af' ; save it for later - ld a, h sub b ret c ; y1 > y2 +; Compute height and masks + push ix inc a - ld d, a ; d = y2 - y1 + 1 + ld ixL,a;ixL = y2 - y1 + 1 + + ld a,c ;e.g. x1 = 3, mask1 = %11100000, CPL = %00011111 + and 7 + inc a + ld b,a ;B = 1 + (x1 MOD 8) = 1,2,...,8 for x1 = 0,1,...,7 + 8*n + xor a +MASK1: + rra + scf ;inject B-1 1s from the left + djnz MASK1 + ld (AND1+1),a ;e.g. %11100000 + ld (AND5+1),a + cpl + ld (AND2+1),a ;e.g. %00011111 + ld (AND7+1),a + + ld a,d ;e.g. x2 = 5, mask2 = %11111100, CPL = %00000011 + and 7 + inc a + ld b,a ;B = 1 + (x2 MOD 8) = 1,2,...,8 for x2 = 0,1,...,7 + 8*n + xor a +MASK2: + scf ;inject B 1s from the left + rra + djnz MASK2 + ld (AND4+1),a ;e.g. %11111100 + ld (AND8+1),a + cpl + ld (AND3+1),a ;e.g. %00000011 + ld (AND6+1),a + +; Compute Ncols and Display File address, and choose branch + ld a,c ;x1 + and %11111000 + rrca + rrca + rrca + ld b,a ;col1 + ld a,d ;x2 + and %11111000 + rrca + rrca + rrca ;col2 + sub b ;A = Ncols - 1 = col2 - col1 + ex af,af' ;save Ncols-1 and ZeroFlag ld b, h ; BC = y2x1 ld a, 191 - LOCAL __PIXEL_ADDR -__PIXEL_ADDR EQU 22ACh - call __PIXEL_ADDR + call 22ACh ; 2 bytes after the 'PIXEL ADDRESS' subroutine, because +; https://skoolkid.github.io/rom/asm/22AA.html starts with LD A,175 res 6, h ; Starts from 0 ld bc, (SCREEN_ADDR) add hl, bc ; Now current offset - ld a, d ; Num. of scan lines - ld b, 0 - exx - ld b, a ; Scan lines counter - ex af, af' ; Recovers cols - ld c, a - jp LOOP_START + ex af,af' ;load Ncols-1 and ZeroFlag + jr z,NEQ1 +; N > 1 (there are 2 or more columns) + dec a ;A = Ncols - 2 + ld ixH,a ;save Ncols-2 + ld b,0 LOOP1: - exx - ld d, h - ld e, l - ld c, a ; C cols - call SP.PixelDown - push hl - ldir - pop hl - exx - ld a, c ; Recovers C Cols - LOCAL LOOP_START -LOOP_START: - djnz LOOP1 - - ; Clears bottom line - exx - ld (hl), 0 - ld d, h - ld e, l - inc de - ld c, a - dec c - ret z - ldir + dec ixL + ld d,h + ld e,l + call z,EMPTYLINE ;HL at empty line + call nz,SP.PixelDown ;HL at line below + inc ixL ;restore iterative variable for a second check + push hl +; Scroll column 1 + ld a,(hl) +AND2: + and %00011111 ;e.g. x1 = 3 + ld c,a ;get in-window part of byte + ld a,(de) +AND1: + and %11100000 ;e.g. x1 = 3 + or c ;put in-window part of byte + ld (de),a + inc hl + inc de +; Scroll columns 2,3,...,N-1 + ld a,ixH ;load Ncols-2 + and a + jr z,COLUMNN + ld c,a + ldir +; Scroll column N +COLUMNN: + ld a,(hl) +AND4: + and %11111100 ;e.g. x2 = 5 + ld c,a ;get in-window part of byte + ld a,(de) +AND3: + and %00000011 ;e.g. x2 = 5 + or c ;put in-window part of byte + ld (de),a +; Scroll another line + pop hl + dec ixL + jp nz,LOOP1 + pop ix + ret + +; N = 1 (there is only one column) +NEQ1: + dec ixL + ld d,h + ld e,l + call z,EMPTYLINE ;HL at empty line + call nz,SP.PixelDown ;HL at line below + inc ixL ;restore iterative variable for a second check + + ld a,(hl) +AND7: + and %00011111 ;e.g. x1 = 3 +AND8: + and %11111100 ;e.g. x2 = 5 + ld c,a ;get in-window part of byte + ld a,(de) +AND5: + and %11100000 ;e.g. x1 = 3 + ld b,a + ld a,(de) +AND6: + and %00000011 ;e.g. x2 = 5 + or b + or c ;put in-window part of byte + ld (de),a +; Scroll another line + dec ixL + jp nz,NEQ1 + pop ix + ret + + defs 32,0 ;empty line with 32 zero-bytes +EMPTYLINE: + ld hl,EMPTYLINE-32 ENDP pop namespace @@ -238,7 +538,7 @@ end sub ' ---------------------------------------------------------------- -' sub ScrolDown +' sub ScrollDown ' pixel by pixel down scroll ' scrolls 1 pixel down the window defined by (x1, y1, x2, y2) ' ---------------------------------------------------------------- @@ -247,8 +547,11 @@ sub fastcall ScrollDown(x1 as uByte, y1 as uByte, x2 as Ubyte, y2 as Ubyte) push namespace core PROC - LOCAL LOOP1 + LOCAL LOOP1, MASK1, MASK2, COLUMNN, NEQ1 + LOCAL AND1, AND2, AND3, AND4, AND5, AND6, AND7, AND8 + LOCAL EMPTYLINE +; Read parameters, return if they are bad ; a = x1 pop hl ; RET address pop bc ; b = y1 @@ -260,62 +563,154 @@ sub fastcall ScrollDown(x1 as uByte, y1 as uByte, x2 as Ubyte, y2 as Ubyte) sub c ret c ; x1 > x2 - srl a - srl a - srl a - inc a - ld e, a ; e = (x2 - x1) / 8 + 1 - ex af, af' ; save it for later - ld a, h sub b ret c ; y1 > y2 +; Compute height and masks + push ix inc a - ld d, a ; d = y2 - y1 + 1 + ld ixL,a;ixL = y2 - y1 + 1 + ld h,b ;y1 + ld a,c ;e.g. x1 = 3, mask1 = %11100000, CPL = %00011111 + and 7 + inc a + ld b,a ;B = 1 + (x1 MOD 8) = 1,2,...,8 for x1 = 0,1,...,7 + 8*n + xor a +MASK1: + rra + scf ;inject B-1 1s from the left + djnz MASK1 + ld (AND1+1),a ;e.g. %11100000 + ld (AND5+1),a + cpl + ld (AND2+1),a ;e.g. %00011111 + ld (AND7+1),a + + ld a,d ;e.g. x2 = 5, mask2 = %11111100, CPL = %00000011 + and 7 + inc a + ld b,a ;B = 1 + (x2 MOD 8) = 1,2,...,8 for x2 = 0,1,...,7 + 8*n + xor a +MASK2: + scf ;inject B 1s from the left + rra + djnz MASK2 + ld (AND4+1),a ;e.g. %11111100 + ld (AND8+1),a + cpl + ld (AND3+1),a ;e.g. %00000011 + ld (AND6+1),a + +; Compute Ncols and Display File address, and choose branch + ld a,c ;x1 + and %11111000 + rrca + rrca + rrca + ld b,a ;col1 + ld a,d ;x2 + and %11111000 + rrca + rrca + rrca ;col2 + sub b ;A = Ncols - 1 = col2 - col1 + ex af,af' ;save Ncols-1 and ZeroFlag + + ld b, h ; BC = y1x1 ld a, 191 - LOCAL __PIXEL_ADDR -__PIXEL_ADDR EQU 22ACh - call __PIXEL_ADDR + call 22ACh ; 2 bytes after the 'PIXEL ADDRESS' subroutine, because +; https://skoolkid.github.io/rom/asm/22AA.html starts with LD A,175 res 6, h ; Starts from 0 ld bc, (SCREEN_ADDR) add hl, bc ; Now current offset - ld a, d ; Num. of scan lines - ld b, 0 - exx - ld b, a ; Scan lines counter - ex af, af' ; Recovers cols - ld c, a - jp LOOP_START + ex af,af' ;load Ncols-1 and ZeroFlag + jr z,NEQ1 +; N > 1 (there are 2 or more columns) + dec a ;A = Ncols - 2 + ld ixH,a ;save Ncols-2 + ld b,0 LOOP1: - exx - ld d, h - ld e, l - ld c, a ; C cols - call SP.PixelUp - push hl - ldir - pop hl - exx - ld a, c ; Recovers C Cols - LOCAL LOOP_START -LOOP_START: - djnz LOOP1 - - ; Clears top line - exx - ld (hl), 0 - ld d, h - ld e, l - inc de - ld c, a - dec c - ret z - ldir - + dec ixL + ld d,h + ld e,l + call z,EMPTYLINE ;HL at empty line + call nz,SP.PixelUp ;HL at line above + inc ixL ;restore iterative variable for a second check + push hl +; Scroll column 1 + ld a,(hl) +AND2: + and %00011111 ;e.g. x1 = 3 + ld c,a ;get in-window part of byte + ld a,(de) +AND1: + and %11100000 ;e.g. x1 = 3 + or c ;put in-window part of byte + ld (de),a + inc hl + inc de +; Scroll columns 2,3,...,N-1 + ld a,ixH ;load Ncols-2 + and a + jr z,COLUMNN + ld c,a + ldir +; Scroll column N +COLUMNN: + ld a,(hl) +AND4: + and %11111100 ;e.g. x2 = 5 + ld c,a ;get in-window part of byte + ld a,(de) +AND3: + and %00000011 ;e.g. x2 = 5 + or c ;put in-window part of byte + ld (de),a +; Scroll another line + pop hl + dec ixL + jp nz,LOOP1 + pop ix + ret + +; N = 1 (there is only one column) +NEQ1: + dec ixL + ld d,h + ld e,l + call z,EMPTYLINE ;HL at empty line + call nz,SP.PixelUp ;HL at line below + inc ixL ;restore iterative variable for a second check + + ld a,(hl) +AND7: + and %00011111 ;e.g. x1 = 3 +AND8: + and %11111100 ;e.g. x2 = 5 + ld c,a ;get in-window part of byte + ld a,(de) +AND5: + and %11100000 ;e.g. x1 = 3 + ld b,a + ld a,(de) +AND6: + and %00000011 ;e.g. x2 = 5 + or b + or c ;put in-window part of byte + ld (de),a +; Scroll another line + dec ixL + jp nz,NEQ1 + pop ix + ret + + defs 32,0 ;empty line with 32 zero-bytes +EMPTYLINE: + ld hl,EMPTYLINE-32 ENDP pop namespace @@ -324,8 +719,8 @@ end sub #pragma pop(case_insensitive) -REM the following is required, because it defines screen start addr -#require "cls.asm" +REM the following is required, because it defines SCREEN_ADDR and SCREEN_ATTR_ADDR +#require "sysvars.asm" #require "SP/PixelDown.asm" #require "SP/PixelUp.asm" diff --git a/src/lib/arch/zxnext/stdlib/scroll.bas b/src/lib/arch/zxnext/stdlib/scroll.bas index 33cfa9919..deec71f2d 100644 --- a/src/lib/arch/zxnext/stdlib/scroll.bas +++ b/src/lib/arch/zxnext/stdlib/scroll.bas @@ -1,8 +1,9 @@ ' ---------------------------------------------------------------- ' This file is released under the MIT License ' -' Copyleft (k) 2008 +' Copyleft (k) 2008, 2025 ' by Jose Rodriguez-Rosa (a.k.a. Boriel) +' and Conrado Badenas ' ' Use this file as a template to develop your own library file ' ---------------------------------------------------------------- @@ -26,9 +27,10 @@ sub fastcall ScrollRight(x1 as uByte, y1 as uByte, x2 as Ubyte, y2 as Ubyte) push namespace core PROC - LOCAL LOOP1 - LOCAL LOOP2 + LOCAL LOOP1, LOOP2, MASK1, MASK2, COLUMNN, NEQ1 + LOCAL AND1, AND2, AND3, AND4, AND5, AND6, AND7, AND8 +; Read parameters, return if they are bad ; a = x1 pop hl ; RET address pop bc ; b = y1 @@ -40,51 +42,152 @@ sub fastcall ScrollRight(x1 as uByte, y1 as uByte, x2 as Ubyte, y2 as Ubyte) sub c ret c ; x1 > x2 - srl a - srl a - srl a - inc a - ld e, a ; e = (x2 - x1) / 8 + 1 - ld a, h sub b ret c ; y1 > y2 +; Compute height and masks inc a - ld d, a ; d = y2 - y1 + 1 + ld e, a ; e = y2 - y1 + 1 + + ld a,c ;e.g. x1 = 3, mask1 = %11100000, CPL = %00011111 + and 7 + inc a + ld b,a ;B = 1 + (x1 MOD 8) = 1,2,...,8 for x1 = 0,1,...,7 + 8*n + xor a +MASK1: + rra + scf ;inject B-1 1s from the left + djnz MASK1 + ld (AND1+1),a ;e.g. %11100000 + ld (AND5+1),a + cpl + ld (AND2+1),a ;e.g. %00011111 + ld (AND7+1),a + + ld a,d ;e.g. x2 = 5, mask2 = %11111100, CPL = %00000011 + and 7 + inc a + ld b,a ;B = 1 + (x2 MOD 8) = 1,2,...,8 for x2 = 0,1,...,7 + 8*n + xor a +MASK2: + scf ;inject B 1s from the left + rra + djnz MASK2 + ld (AND4+1),a ;e.g. %11111100 + ld (AND8+1),a + cpl + ld (AND3+1),a ;e.g. %00000011 + ld (AND6+1),a + +; Compute Ncols and Display File address, and choose branch + ld a,c ;x1 + and %11111000 + rrca + rrca + rrca + ld b,a ;col1 + ld a,d ;x2 + and %11111000 + rrca + rrca + rrca ;col2 + sub b ;A = Ncols - 1 = col2 - col1 + ex af,af' ;save Ncols-1 and ZeroFlag ld b, h ; BC = y2x1 ld a, 191 - LOCAL __PIXEL_ADDR -__PIXEL_ADDR EQU 22ACh - call __PIXEL_ADDR + call 22ACh ; 2 bytes after the 'PIXEL ADDRESS' subroutine, because +; https://skoolkid.github.io/rom/asm/22AA.html starts with LD A,175 res 6, h ; Starts from 0 ld bc, (SCREEN_ADDR) add hl, bc ; Now current offset + ex af,af' ;load Ncols-1 and ZeroFlag + jr z,NEQ1 + +; N > 1 (there are 2 or more columns) + dec a ;A = Ncols - 2 + ld d,a ;D = N-2 LOOP1: - push hl - ld b, e ; C cols - or a ; clear carry flag + push hl +; Scroll column 1 + ld a,(hl) +AND1: + and %11100000 ;e.g. x1 = 3 + ld c,a ;get out-window part of byte + ld a,(hl) +AND2: + and %00011111 ;e.g. x1 = 3 + rra ;scroll in-window part of byte + rl b ;CF is stored as bit0 of B + or c ;put out-window part of byte + ld (hl),a + inc hl +; Scroll columns 2,3,...,N-1 + ld a,d ;N-2 + and a ;A=0 iff N=2 + jr z,COLUMNN + rr b ;CF is on stage + ld b,a LOOP2: - rr (hl) - inc hl - djnz LOOP2 - pop hl - - dec d - ret z - call SP.PixelDown - jp LOOP1 + rr (hl) + inc hl + djnz LOOP2 + rl b ;CF is stored as bit0 of B +; Scroll column N +COLUMNN: + ld a,(hl) +AND3: + and %00000011 ;e.g. x2 = 5 + ld c,a ;get out-window part of byte + ld a,(hl) + rr b ;CF is on stage + rra ;scroll in-window part of byte +AND4: + and %11111100 ;e.g. x2 = 5 + or c ;put out-window part of byte + ld (hl),a +; Scroll another line + pop hl + dec e + ret z + call SP.PixelDown + jp LOOP1 + +; N = 1 (there is only one column) +NEQ1: + ld b,(hl) + ld a,b +AND5: + and %11100000 ;e.g. x1 = 3 + ld c,a + ld a,b +AND6: + and %00000011 ;e.g. x2 = 5 + or c + ld c,a ;get out-window part of byte + ld a,b +AND7: + and %00011111 ;e.g. x1 = 3 + rra ;scroll in-window part of byte +AND8: + and %11111100 ;e.g. x2 = 5 + or c ;put out-window part of byte + ld (hl),a +; Scroll another line + dec e + ret z + call SP.PixelDown + jp NEQ1 ENDP pop namespace end asm end sub - ' ---------------------------------------------------------------- -' sub ScrolLeft +' sub ScrollLeft ' pixel by pixel left scroll ' scrolls 1 pixel left the window defined by (x1, y1, x2, y2) ' ---------------------------------------------------------------- @@ -93,9 +196,10 @@ sub fastcall ScrollLeft(x1 as uByte, y1 as uByte, x2 as Ubyte, y2 as Ubyte) push namespace core PROC - LOCAL LOOP1 - LOCAL LOOP2 + LOCAL LOOP1, LOOP2, MASK1, MASK2, COLUMN1, NEQ1 + LOCAL AND1, AND2, AND3, AND4, AND5, AND6, AND7, AND8 +; Read parameters, return if they are bad ; a = x1 pop hl ; RET address pop bc ; b = y1 @@ -107,43 +211,145 @@ sub fastcall ScrollLeft(x1 as uByte, y1 as uByte, x2 as Ubyte, y2 as Ubyte) sub c ret c ; x1 > x2 - srl a - srl a - srl a - inc a - ld e, a ; e = (x2 - x1) / 8 + 1 - ld a, h sub b ret c ; y1 > y2 - ld c, d +; Compute height and masks inc a - ld d, a ; d = y2 - y1 + 1 + ld e, a ; e = y2 - y1 + 1 - ld b, h ; BC = y2x1 + ld a,c ;e.g. x1 = 3, mask1 = %11100000, CPL = %00011111 + and 7 + inc a + ld b,a ;B = 1 + (x1 MOD 8) = 1,2,...,8 for x1 = 0,1,...,7 + 8*n + xor a +MASK1: + rra + scf ;inject B-1 1s from the left + djnz MASK1 + ld (AND3+1),a ;e.g. %00000011 + ld (AND6+1),a + cpl + ld (AND4+1),a ;e.g. %11111100 + ld (AND8+1),a + + ld a,d ;e.g. x2 = 5, mask2 = %11111100, CPL = %00000011 + and 7 + inc a + ld b,a ;B = 1 + (x2 MOD 8) = 1,2,...,8 for x2 = 0,1,...,7 + 8*n + xor a +MASK2: + scf ;inject B 1s from the left + rra + djnz MASK2 + ld (AND2+1),a ;e.g. %00011111 + ld (AND7+1),a + cpl + ld (AND1+1),a ;e.g. %11100000 + ld (AND5+1),a + +; Compute Ncols and Display File address, and choose branch + ld a,c ;x1 + and %11111000 + rrca + rrca + rrca + ld b,a ;col1 + ld a,d ;x2 + and %11111000 + rrca + rrca + rrca ;col2 + sub b ;A = Ncols - 1 = col2 - col1 + ex af,af' ;save Ncols-1 and ZeroFlag + + ld c, d + ld b, h ; BC = y2x2 ld a, 191 - LOCAL __PIXEL_ADDR -__PIXEL_ADDR EQU 22ACh - call __PIXEL_ADDR + call 22ACh ; 2 bytes after the 'PIXEL ADDRESS' subroutine, because +; https://skoolkid.github.io/rom/asm/22AA.html starts with LD A,175 res 6, h ; Starts from 0 ld bc, (SCREEN_ADDR) add hl, bc ; Now current offset + ex af,af' ;load Ncols-1 and ZeroFlag + jr z,NEQ1 + +; N > 1 (there are 2 or more columns) + dec a ;A = Ncols - 2 + ld d,a ;D = N-2 LOOP1: - push hl - ld b, e ; C cols - or a ; clear carry flag + push hl +; Scroll column N + ld a,(hl) +AND1: + and %00000011 ;e.g. x2 = 5 + ld c,a ;get out-window part of byte + ld a,(hl) +AND2: + and %11111100 ;e.g. x2 = 5 + rla ;scroll in-window part of byte + rl b ;CF is stored as bit0 of B + or c ;put out-window part of byte + ld (hl),a + dec hl +; Scroll columns N-1,...,3,2 + ld a,d ;N-2 + and a ;A=0 iff N=2 + jr z,COLUMN1 + rr b ;CF is on stage + ld b,a LOOP2: - rl (hl) - dec hl - djnz LOOP2 - pop hl - - dec d - ret z - call SP.PixelDown - jp LOOP1 + rl (hl) + dec hl + djnz LOOP2 + rl b ;CF is stored as bit0 of B +; Scroll column 1 +COLUMN1: + ld a,(hl) +AND3: + and %11100000 ;e.g. x1 = 3 + ld c,a ;get out-window part of byte + ld a,(hl) + rr b ;CF is on stage + rla ;scroll in-window part of byte +AND4: + and %00011111 ;e.g. x1 = 3 + or c ;put out-window part of byte + ld (hl),a +; Scroll another line + pop hl + dec e + ret z + call SP.PixelDown + jp LOOP1 + +; N = 1 (there is only one column) +NEQ1: + ld b,(hl) + ld a,b +AND5: + and %00000011 ;e.g. x2 = 5 + ld c,a + ld a,b +AND6: + and %11100000 ;e.g. x1 = 3 + or c + ld c,a ;get out-window part of byte + ld a,b +AND7: + and %11111100 ;e.g. x2 = 5 + rla ;scroll in-window part of byte +AND8: + and %00011111 ;e.g. x1 = 3 + or c ;put out-window part of byte + ld (hl),a +; Scroll another line + dec e + ret z + call SP.PixelDown + jp NEQ1 ENDP pop namespace @@ -152,7 +358,7 @@ end sub ' ---------------------------------------------------------------- -' sub ScrolUp +' sub ScrollUp ' pixel by pixel up scroll ' scrolls 1 pixel up the window defined by (x1, y1, x2, y2) ' ---------------------------------------------------------------- @@ -161,8 +367,11 @@ sub fastcall ScrollUp(x1 as uByte, y1 as uByte, x2 as Ubyte, y2 as Ubyte) push namespace core PROC - LOCAL LOOP1 + LOCAL LOOP1, MASK1, MASK2, COLUMNN, NEQ1 + LOCAL AND1, AND2, AND3, AND4, AND5, AND6, AND7, AND8 + LOCAL EMPTYLINE +; Read parameters, return if they are bad ; a = x1 pop hl ; RET address pop bc ; b = y1 @@ -174,62 +383,153 @@ sub fastcall ScrollUp(x1 as uByte, y1 as uByte, x2 as Ubyte, y2 as Ubyte) sub c ret c ; x1 > x2 - srl a - srl a - srl a - inc a - ld e, a ; e = (x2 - x1) / 8 + 1 - ex af, af' ; save it for later - ld a, h sub b ret c ; y1 > y2 +; Compute height and masks + push ix inc a - ld d, a ; d = y2 - y1 + 1 + ld ixL,a;ixL = y2 - y1 + 1 + + ld a,c ;e.g. x1 = 3, mask1 = %11100000, CPL = %00011111 + and 7 + inc a + ld b,a ;B = 1 + (x1 MOD 8) = 1,2,...,8 for x1 = 0,1,...,7 + 8*n + xor a +MASK1: + rra + scf ;inject B-1 1s from the left + djnz MASK1 + ld (AND1+1),a ;e.g. %11100000 + ld (AND5+1),a + cpl + ld (AND2+1),a ;e.g. %00011111 + ld (AND7+1),a + + ld a,d ;e.g. x2 = 5, mask2 = %11111100, CPL = %00000011 + and 7 + inc a + ld b,a ;B = 1 + (x2 MOD 8) = 1,2,...,8 for x2 = 0,1,...,7 + 8*n + xor a +MASK2: + scf ;inject B 1s from the left + rra + djnz MASK2 + ld (AND4+1),a ;e.g. %11111100 + ld (AND8+1),a + cpl + ld (AND3+1),a ;e.g. %00000011 + ld (AND6+1),a + +; Compute Ncols and Display File address, and choose branch + ld a,c ;x1 + and %11111000 + rrca + rrca + rrca + ld b,a ;col1 + ld a,d ;x2 + and %11111000 + rrca + rrca + rrca ;col2 + sub b ;A = Ncols - 1 = col2 - col1 + ex af,af' ;save Ncols-1 and ZeroFlag ld b, h ; BC = y2x1 ld a, 191 - LOCAL __PIXEL_ADDR -__PIXEL_ADDR EQU 22ACh - call __PIXEL_ADDR + call 22ACh ; 2 bytes after the 'PIXEL ADDRESS' subroutine, because +; https://skoolkid.github.io/rom/asm/22AA.html starts with LD A,175 res 6, h ; Starts from 0 ld bc, (SCREEN_ADDR) add hl, bc ; Now current offset - ld a, d ; Num. of scan lines - ld b, 0 - exx - ld b, a ; Scan lines counter - ex af, af' ; Recovers cols - ld c, a - jp LOOP_START + ex af,af' ;load Ncols-1 and ZeroFlag + jr z,NEQ1 +; N > 1 (there are 2 or more columns) + dec a ;A = Ncols - 2 + ld ixH,a ;save Ncols-2 + ld b,0 LOOP1: - exx - ld d, h - ld e, l - ld c, a ; C cols - call SP.PixelDown - push hl - ldir - pop hl - exx - ld a, c ; Recovers C Cols - LOCAL LOOP_START -LOOP_START: - djnz LOOP1 - - ; Clears bottom line - exx - ld (hl), 0 - ld d, h - ld e, l - inc de - ld c, a - dec c - ret z - ldir + dec ixL + ld d,h + ld e,l + call z,EMPTYLINE ;HL at empty line + call nz,SP.PixelDown ;HL at line below + inc ixL ;restore iterative variable for a second check + push hl +; Scroll column 1 + ld a,(hl) +AND2: + and %00011111 ;e.g. x1 = 3 + ld c,a ;get in-window part of byte + ld a,(de) +AND1: + and %11100000 ;e.g. x1 = 3 + or c ;put in-window part of byte + ld (de),a + inc hl + inc de +; Scroll columns 2,3,...,N-1 + ld a,ixH ;load Ncols-2 + and a + jr z,COLUMNN + ld c,a + ldir +; Scroll column N +COLUMNN: + ld a,(hl) +AND4: + and %11111100 ;e.g. x2 = 5 + ld c,a ;get in-window part of byte + ld a,(de) +AND3: + and %00000011 ;e.g. x2 = 5 + or c ;put in-window part of byte + ld (de),a +; Scroll another line + pop hl + dec ixL + jp nz,LOOP1 + pop ix + ret + +; N = 1 (there is only one column) +NEQ1: + dec ixL + ld d,h + ld e,l + call z,EMPTYLINE ;HL at empty line + call nz,SP.PixelDown ;HL at line below + inc ixL ;restore iterative variable for a second check + + ld a,(hl) +AND7: + and %00011111 ;e.g. x1 = 3 +AND8: + and %11111100 ;e.g. x2 = 5 + ld c,a ;get in-window part of byte + ld a,(de) +AND5: + and %11100000 ;e.g. x1 = 3 + ld b,a + ld a,(de) +AND6: + and %00000011 ;e.g. x2 = 5 + or b + or c ;put in-window part of byte + ld (de),a +; Scroll another line + dec ixL + jp nz,NEQ1 + pop ix + ret + + defs 32,0 ;empty line with 32 zero-bytes +EMPTYLINE: + ld hl,EMPTYLINE-32 ENDP pop namespace @@ -238,7 +538,7 @@ end sub ' ---------------------------------------------------------------- -' sub ScrolDown +' sub ScrollDown ' pixel by pixel down scroll ' scrolls 1 pixel down the window defined by (x1, y1, x2, y2) ' ---------------------------------------------------------------- @@ -247,8 +547,11 @@ sub fastcall ScrollDown(x1 as uByte, y1 as uByte, x2 as Ubyte, y2 as Ubyte) push namespace core PROC - LOCAL LOOP1 + LOCAL LOOP1, MASK1, MASK2, COLUMNN, NEQ1 + LOCAL AND1, AND2, AND3, AND4, AND5, AND6, AND7, AND8 + LOCAL EMPTYLINE +; Read parameters, return if they are bad ; a = x1 pop hl ; RET address pop bc ; b = y1 @@ -260,62 +563,154 @@ sub fastcall ScrollDown(x1 as uByte, y1 as uByte, x2 as Ubyte, y2 as Ubyte) sub c ret c ; x1 > x2 - srl a - srl a - srl a - inc a - ld e, a ; e = (x2 - x1) / 8 + 1 - ex af, af' ; save it for later - ld a, h sub b ret c ; y1 > y2 +; Compute height and masks + push ix inc a - ld d, a ; d = y2 - y1 + 1 + ld ixL,a;ixL = y2 - y1 + 1 + ld h,b ;y1 + ld a,c ;e.g. x1 = 3, mask1 = %11100000, CPL = %00011111 + and 7 + inc a + ld b,a ;B = 1 + (x1 MOD 8) = 1,2,...,8 for x1 = 0,1,...,7 + 8*n + xor a +MASK1: + rra + scf ;inject B-1 1s from the left + djnz MASK1 + ld (AND1+1),a ;e.g. %11100000 + ld (AND5+1),a + cpl + ld (AND2+1),a ;e.g. %00011111 + ld (AND7+1),a + + ld a,d ;e.g. x2 = 5, mask2 = %11111100, CPL = %00000011 + and 7 + inc a + ld b,a ;B = 1 + (x2 MOD 8) = 1,2,...,8 for x2 = 0,1,...,7 + 8*n + xor a +MASK2: + scf ;inject B 1s from the left + rra + djnz MASK2 + ld (AND4+1),a ;e.g. %11111100 + ld (AND8+1),a + cpl + ld (AND3+1),a ;e.g. %00000011 + ld (AND6+1),a + +; Compute Ncols and Display File address, and choose branch + ld a,c ;x1 + and %11111000 + rrca + rrca + rrca + ld b,a ;col1 + ld a,d ;x2 + and %11111000 + rrca + rrca + rrca ;col2 + sub b ;A = Ncols - 1 = col2 - col1 + ex af,af' ;save Ncols-1 and ZeroFlag + + ld b, h ; BC = y1x1 ld a, 191 - LOCAL __PIXEL_ADDR -__PIXEL_ADDR EQU 22ACh - call __PIXEL_ADDR + call 22ACh ; 2 bytes after the 'PIXEL ADDRESS' subroutine, because +; https://skoolkid.github.io/rom/asm/22AA.html starts with LD A,175 res 6, h ; Starts from 0 ld bc, (SCREEN_ADDR) add hl, bc ; Now current offset - ld a, d ; Num. of scan lines - ld b, 0 - exx - ld b, a ; Scan lines counter - ex af, af' ; Recovers cols - ld c, a - jp LOOP_START + ex af,af' ;load Ncols-1 and ZeroFlag + jr z,NEQ1 +; N > 1 (there are 2 or more columns) + dec a ;A = Ncols - 2 + ld ixH,a ;save Ncols-2 + ld b,0 LOOP1: - exx - ld d, h - ld e, l - ld c, a ; C cols - call SP.PixelUp - push hl - ldir - pop hl - exx - ld a, c ; Recovers C Cols - LOCAL LOOP_START -LOOP_START: - djnz LOOP1 - - ; Clears top line - exx - ld (hl), 0 - ld d, h - ld e, l - inc de - ld c, a - dec c - ret z - ldir - + dec ixL + ld d,h + ld e,l + call z,EMPTYLINE ;HL at empty line + call nz,SP.PixelUp ;HL at line above + inc ixL ;restore iterative variable for a second check + push hl +; Scroll column 1 + ld a,(hl) +AND2: + and %00011111 ;e.g. x1 = 3 + ld c,a ;get in-window part of byte + ld a,(de) +AND1: + and %11100000 ;e.g. x1 = 3 + or c ;put in-window part of byte + ld (de),a + inc hl + inc de +; Scroll columns 2,3,...,N-1 + ld a,ixH ;load Ncols-2 + and a + jr z,COLUMNN + ld c,a + ldir +; Scroll column N +COLUMNN: + ld a,(hl) +AND4: + and %11111100 ;e.g. x2 = 5 + ld c,a ;get in-window part of byte + ld a,(de) +AND3: + and %00000011 ;e.g. x2 = 5 + or c ;put in-window part of byte + ld (de),a +; Scroll another line + pop hl + dec ixL + jp nz,LOOP1 + pop ix + ret + +; N = 1 (there is only one column) +NEQ1: + dec ixL + ld d,h + ld e,l + call z,EMPTYLINE ;HL at empty line + call nz,SP.PixelUp ;HL at line below + inc ixL ;restore iterative variable for a second check + + ld a,(hl) +AND7: + and %00011111 ;e.g. x1 = 3 +AND8: + and %11111100 ;e.g. x2 = 5 + ld c,a ;get in-window part of byte + ld a,(de) +AND5: + and %11100000 ;e.g. x1 = 3 + ld b,a + ld a,(de) +AND6: + and %00000011 ;e.g. x2 = 5 + or b + or c ;put in-window part of byte + ld (de),a +; Scroll another line + dec ixL + jp nz,NEQ1 + pop ix + ret + + defs 32,0 ;empty line with 32 zero-bytes +EMPTYLINE: + ld hl,EMPTYLINE-32 ENDP pop namespace @@ -324,8 +719,8 @@ end sub #pragma pop(case_insensitive) -REM the following is required, because it defines screen start addr -#require "cls.asm" +REM the following is required, because it defines SCREEN_ADDR and SCREEN_ATTR_ADDR +#require "sysvars.asm" #require "SP/PixelDown.asm" #require "SP/PixelUp.asm" diff --git a/tests/functional/arch/zx48k/stdlib_scroll.asm b/tests/functional/arch/zx48k/stdlib_scroll.asm index f7de2f0c5..9258d112f 100644 --- a/tests/functional/arch/zx48k/stdlib_scroll.asm +++ b/tests/functional/arch/zx48k/stdlib_scroll.asm @@ -33,11 +33,11 @@ ei ret _ScrollRight: -#line 25 "/zxbasic/src/lib/arch/zx48k/stdlib/scroll.bas" +#line 26 "/zxbasic/src/lib/arch/zx48k/stdlib/scroll.bas" push namespace core PROC - LOCAL LOOP1 - LOCAL LOOP2 + LOCAL LOOP1, LOOP2, MASK1, MASK2, COLUMNN, NEQ1 + LOCAL AND1, AND2, AND3, AND4, AND5, AND6, AND7, AND8 pop hl pop bc pop de @@ -46,48 +46,137 @@ _ScrollRight: ld a, d sub c ret c - srl a - srl a - srl a - inc a - ld e, a ld a, h sub b ret c inc a - ld d, a + ld e, a + ld a,c + and 7 + inc a + ld b,a + xor a +MASK1: + rra + scf + djnz MASK1 + ld (AND1+1),a + ld (AND5+1),a + cpl + ld (AND2+1),a + ld (AND7+1),a + ld a,d + and 7 + inc a + ld b,a + xor a +MASK2: + scf + rra + djnz MASK2 + ld (AND4+1),a + ld (AND8+1),a + cpl + ld (AND3+1),a + ld (AND6+1),a + ld a,c + and %11111000 + rrca + rrca + rrca + ld b,a + ld a,d + and %11111000 + rrca + rrca + rrca + sub b + ex af,af' ld b, h ld a, 191 - LOCAL __PIXEL_ADDR - __PIXEL_ADDR EQU 22ACh - call __PIXEL_ADDR + call 22ACh res 6, h ld bc, (SCREEN_ADDR) add hl, bc + ex af,af' + jr z,NEQ1 + dec a + ld d,a LOOP1: push hl - ld b, e - or a + ld a,(hl) +AND1: + and %11100000 + ld c,a + ld a,(hl) +AND2: + and %00011111 + rra + rl b + or c + ld (hl),a + inc hl + ld a,d + and a + jr z,COLUMNN + rr b + ld b,a LOOP2: rr (hl) inc hl djnz LOOP2 + rl b +COLUMNN: + ld a,(hl) +AND3: + and %00000011 + ld c,a + ld a,(hl) + rr b + rra +AND4: + and %11111100 + or c + ld (hl),a pop hl - dec d + dec e ret z call SP.PixelDown jp LOOP1 +NEQ1: + ld b,(hl) + ld a,b +AND5: + and %11100000 + ld c,a + ld a,b +AND6: + and %00000011 + or c + ld c,a + ld a,b +AND7: + and %00011111 + rra +AND8: + and %11111100 + or c + ld (hl),a + dec e + ret z + call SP.PixelDown + jp NEQ1 ENDP pop namespace -#line 83 "/zxbasic/src/lib/arch/zx48k/stdlib/scroll.bas" +#line 187 "/zxbasic/src/lib/arch/zx48k/stdlib/scroll.bas" _ScrollRight__leave: ret _ScrollLeft: -#line 92 "/zxbasic/src/lib/arch/zx48k/stdlib/scroll.bas" +#line 195 "/zxbasic/src/lib/arch/zx48k/stdlib/scroll.bas" push namespace core PROC - LOCAL LOOP1 - LOCAL LOOP2 + LOCAL LOOP1, LOOP2, MASK1, MASK2, COLUMN1, NEQ1 + LOCAL AND1, AND2, AND3, AND4, AND5, AND6, AND7, AND8 pop hl pop bc pop de @@ -96,48 +185,139 @@ _ScrollLeft: ld a, d sub c ret c - srl a - srl a - srl a - inc a - ld e, a ld a, h sub b ret c - ld c, d inc a - ld d, a + ld e, a + ld a,c + and 7 + inc a + ld b,a + xor a +MASK1: + rra + scf + djnz MASK1 + ld (AND3+1),a + ld (AND6+1),a + cpl + ld (AND4+1),a + ld (AND8+1),a + ld a,d + and 7 + inc a + ld b,a + xor a +MASK2: + scf + rra + djnz MASK2 + ld (AND2+1),a + ld (AND7+1),a + cpl + ld (AND1+1),a + ld (AND5+1),a + ld a,c + and %11111000 + rrca + rrca + rrca + ld b,a + ld a,d + and %11111000 + rrca + rrca + rrca + sub b + ex af,af' + ld c, d ld b, h ld a, 191 - LOCAL __PIXEL_ADDR - __PIXEL_ADDR EQU 22ACh - call __PIXEL_ADDR + call 22ACh res 6, h ld bc, (SCREEN_ADDR) add hl, bc + ex af,af' + jr z,NEQ1 + dec a + ld d,a LOOP1: push hl - ld b, e - or a + ld a,(hl) +AND1: + and %00000011 + ld c,a + ld a,(hl) +AND2: + and %11111100 + rla + rl b + or c + ld (hl),a + dec hl + ld a,d + and a + jr z,COLUMN1 + rr b + ld b,a LOOP2: rl (hl) dec hl djnz LOOP2 + rl b +COLUMN1: + ld a,(hl) +AND3: + and %11100000 + ld c,a + ld a,(hl) + rr b + rla +AND4: + and %00011111 + or c + ld (hl),a pop hl - dec d + dec e ret z call SP.PixelDown jp LOOP1 +NEQ1: + ld b,(hl) + ld a,b +AND5: + and %00000011 + ld c,a + ld a,b +AND6: + and %11100000 + or c + ld c,a + ld a,b +AND7: + and %11111100 + rla +AND8: + and %00011111 + or c + ld (hl),a + dec e + ret z + call SP.PixelDown + jp NEQ1 ENDP pop namespace -#line 151 "/zxbasic/src/lib/arch/zx48k/stdlib/scroll.bas" +#line 357 "/zxbasic/src/lib/arch/zx48k/stdlib/scroll.bas" _ScrollLeft__leave: ret _ScrollUp: -#line 160 "/zxbasic/src/lib/arch/zx48k/stdlib/scroll.bas" +#line 366 "/zxbasic/src/lib/arch/zx48k/stdlib/scroll.bas" push namespace core PROC - LOCAL LOOP1 + LOCAL LOOP1, MASK1, MASK2, COLUMNN, NEQ1 + LOCAL AND1, AND2, AND3, AND4, AND5, AND6, AND7, AND8 + LOCAL EMPTYLINE pop hl pop bc pop de @@ -146,65 +326,145 @@ _ScrollUp: ld a, d sub c ret c - srl a - srl a - srl a - inc a - ld e, a - ex af, af' ld a, h sub b ret c + push ix + inc a + ld ixL,a + ld a,c + and 7 inc a - ld d, a + ld b,a + xor a +MASK1: + rra + scf + djnz MASK1 + ld (AND1+1),a + ld (AND5+1),a + cpl + ld (AND2+1),a + ld (AND7+1),a + ld a,d + and 7 + inc a + ld b,a + xor a +MASK2: + scf + rra + djnz MASK2 + ld (AND4+1),a + ld (AND8+1),a + cpl + ld (AND3+1),a + ld (AND6+1),a + ld a,c + and %11111000 + rrca + rrca + rrca + ld b,a + ld a,d + and %11111000 + rrca + rrca + rrca + sub b + ex af,af' ld b, h ld a, 191 - LOCAL __PIXEL_ADDR - __PIXEL_ADDR EQU 22ACh - call __PIXEL_ADDR + call 22ACh res 6, h ld bc, (SCREEN_ADDR) add hl, bc - ld a, d - ld b, 0 - exx - ld b, a - ex af, af' - ld c, a - jp LOOP_START + ex af,af' + jr z,NEQ1 + dec a + ld ixH,a + ld b,0 LOOP1: - exx - ld d, h - ld e, l - ld c, a - call SP.PixelDown + dec ixL + ld d,h + ld e,l + call z,EMPTYLINE + call nz,SP.PixelDown + inc ixL push hl - ldir - pop hl - exx - ld a, c - LOCAL LOOP_START -LOOP_START: - djnz LOOP1 - exx - ld (hl), 0 - ld d, h - ld e, l + ld a,(hl) +AND2: + and %00011111 + ld c,a + ld a,(de) +AND1: + and %11100000 + or c + ld (de),a + inc hl inc de - ld c, a - dec c - ret z + ld a,ixH + and a + jr z,COLUMNN + ld c,a ldir +COLUMNN: + ld a,(hl) +AND4: + and %11111100 + ld c,a + ld a,(de) +AND3: + and %00000011 + or c + ld (de),a + pop hl + dec ixL + jp nz,LOOP1 + pop ix + ret +NEQ1: + dec ixL + ld d,h + ld e,l + call z,EMPTYLINE + call nz,SP.PixelDown + inc ixL + ld a,(hl) +AND7: + and %00011111 +AND8: + and %11111100 + ld c,a + ld a,(de) +AND5: + and %11100000 + ld b,a + ld a,(de) +AND6: + and %00000011 + or b + or c + ld (de),a + dec ixL + jp nz,NEQ1 + pop ix + ret + defs 32,0 +EMPTYLINE: + ld hl,EMPTYLINE-32 ENDP pop namespace -#line 237 "/zxbasic/src/lib/arch/zx48k/stdlib/scroll.bas" +#line 537 "/zxbasic/src/lib/arch/zx48k/stdlib/scroll.bas" _ScrollUp__leave: ret _ScrollDown: -#line 246 "/zxbasic/src/lib/arch/zx48k/stdlib/scroll.bas" +#line 546 "/zxbasic/src/lib/arch/zx48k/stdlib/scroll.bas" push namespace core PROC - LOCAL LOOP1 + LOCAL LOOP1, MASK1, MASK2, COLUMNN, NEQ1 + LOCAL AND1, AND2, AND3, AND4, AND5, AND6, AND7, AND8 + LOCAL EMPTYLINE pop hl pop bc pop de @@ -213,57 +473,137 @@ _ScrollDown: ld a, d sub c ret c - srl a - srl a - srl a - inc a - ld e, a - ex af, af' ld a, h sub b ret c + push ix + inc a + ld ixL,a + ld h,b + ld a,c + and 7 + inc a + ld b,a + xor a +MASK1: + rra + scf + djnz MASK1 + ld (AND1+1),a + ld (AND5+1),a + cpl + ld (AND2+1),a + ld (AND7+1),a + ld a,d + and 7 inc a - ld d, a + ld b,a + xor a +MASK2: + scf + rra + djnz MASK2 + ld (AND4+1),a + ld (AND8+1),a + cpl + ld (AND3+1),a + ld (AND6+1),a + ld a,c + and %11111000 + rrca + rrca + rrca + ld b,a + ld a,d + and %11111000 + rrca + rrca + rrca + sub b + ex af,af' + ld b, h ld a, 191 - LOCAL __PIXEL_ADDR - __PIXEL_ADDR EQU 22ACh - call __PIXEL_ADDR + call 22ACh res 6, h ld bc, (SCREEN_ADDR) add hl, bc - ld a, d - ld b, 0 - exx - ld b, a - ex af, af' - ld c, a - jp LOOP_START + ex af,af' + jr z,NEQ1 + dec a + ld ixH,a + ld b,0 LOOP1: - exx - ld d, h - ld e, l - ld c, a - call SP.PixelUp + dec ixL + ld d,h + ld e,l + call z,EMPTYLINE + call nz,SP.PixelUp + inc ixL push hl - ldir - pop hl - exx - ld a, c - LOCAL LOOP_START -LOOP_START: - djnz LOOP1 - exx - ld (hl), 0 - ld d, h - ld e, l + ld a,(hl) +AND2: + and %00011111 + ld c,a + ld a,(de) +AND1: + and %11100000 + or c + ld (de),a + inc hl inc de - ld c, a - dec c - ret z + ld a,ixH + and a + jr z,COLUMNN + ld c,a ldir +COLUMNN: + ld a,(hl) +AND4: + and %11111100 + ld c,a + ld a,(de) +AND3: + and %00000011 + or c + ld (de),a + pop hl + dec ixL + jp nz,LOOP1 + pop ix + ret +NEQ1: + dec ixL + ld d,h + ld e,l + call z,EMPTYLINE + call nz,SP.PixelUp + inc ixL + ld a,(hl) +AND7: + and %00011111 +AND8: + and %11111100 + ld c,a + ld a,(de) +AND5: + and %11100000 + ld b,a + ld a,(de) +AND6: + and %00000011 + or b + or c + ld (de),a + dec ixL + jp nz,NEQ1 + pop ix + ret + defs 32,0 +EMPTYLINE: + ld hl,EMPTYLINE-32 ENDP pop namespace -#line 323 "/zxbasic/src/lib/arch/zx48k/stdlib/scroll.bas" +#line 718 "/zxbasic/src/lib/arch/zx48k/stdlib/scroll.bas" _ScrollDown__leave: ret ;; --- end of user code --- @@ -344,7 +684,7 @@ SCREEN_ATTR_ADDR: DW 22528 ; Screen attribute address (ditto.) SCR_SIZE EQU (SCR_ROWS << 8) + SCR_COLS pop namespace #line 58 "/zxbasic/src/lib/arch/zx48k/runtime/SP/PixelDown.asm" -#line 328 "/zxbasic/src/lib/arch/zx48k/stdlib/scroll.bas" +#line 723 "/zxbasic/src/lib/arch/zx48k/stdlib/scroll.bas" #line 1 "/zxbasic/src/lib/arch/zx48k/runtime/SP/PixelUp.asm" ; ; PixelUp @@ -391,36 +731,5 @@ leave: ret ENDP pop namespace -#line 329 "/zxbasic/src/lib/arch/zx48k/stdlib/scroll.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 330 "/zxbasic/src/lib/arch/zx48k/stdlib/scroll.bas" +#line 724 "/zxbasic/src/lib/arch/zx48k/stdlib/scroll.bas" END