diff --git a/src/lib/arch/zx48k/stdlib/winscroll.bas b/src/lib/arch/zx48k/stdlib/winscroll.bas index 45e5a9a4e..381f02250 100644 --- a/src/lib/arch/zx48k/stdlib/winscroll.bas +++ b/src/lib/arch/zx48k/stdlib/winscroll.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 ' ---------------------------------------------------------------- @@ -19,75 +20,39 @@ REM Avoid recursive / multiple inclusion ' --------------------------------------------------------------------- ' sub WinScrollRight ' scrolls the window defined by (row, col, width, height) 1 cell right +' it works with width=1 or height=1 but it is not impressive +' nothing is done if width=0 or height=0 ' --------------------------------------------------------------------- sub fastcall WinScrollRight(row as uByte, col as uByte, width as Ubyte, height as Ubyte) asm push namespace core - LOCAL BucleChars - LOCAL BucleScans - LOCAL BucleAttrs - PROC - ld b, a - pop hl - pop de - ld c, d + LOCAL BucleRows, BucleScans, AfterLDDR, AfterLDDR2, AfterLDDR3 + +; Read parameters, return if they are bad + ld b, a ;row + pop hl ;return address pop de + ld a, d ;colLeft + pop de ;width + add a, d + dec a + ld c, a ;colRight = colLeft + width - 1 ex (sp), hl - ld e, h + ld e, h ;height ld a, e or a - ret z - or d - ret z - push bc - ld a,b - and 18h - ld h,a - ld a,b - and 07h - add a,a - add a,a - add a,a - add a,a - add a,a - add a,c - add a,d - dec a - ld l,a ;HL=top-left window address in bitmap coord - ld bc, (SCREEN_ADDR) - add hl, bc - ld b,e - -BucleChars: - push bc - ld b,8 - -BucleScans: - push bc - push de - push hl - ld c,d - dec c - ld b,0 - ld d,h - ld e,l - dec l - lddr - ; clean up latest - xor a - ld (de),a - pop hl - pop de - inc h - pop bc - djnz BucleScans - dec h - call SP.PixelDown - pop bc - djnz BucleChars - - pop bc + ret z ;height=0 + ld a, d + or a + ret z ;width=0 + +; Compute Attributes address + sub 2 ;CF=1 if width=1, CF=0 if width>1 + inc a + ex af,af' ;A' = width-1, CF'=1 if width=1, CF'=0 if width>1 + push ix + ld ixL,e ;IXl = height, iterative variable ld l,b ld h,0 add hl,hl @@ -97,33 +62,77 @@ BucleScans: add hl,hl ld a,l add a,c - add a,d - dec a - ld l,a - ld a,h - ld h,a ;HL=top-left window address in attr coord - ld bc, (SCREEN_ATTR_ADDR) - add hl, bc - ld b,e - -BucleAttrs: - push bc - push de - push hl - ld c,d - dec c - ld b,0 - ld d,h - ld e,l - dec l - lddr - pop hl - ld de,32 + ld l,a ;HL = row*32 + colRight + ld de,(SCREEN_ATTR_ADDR) add hl,de - pop de - pop bc - djnz BucleAttrs +; For each row, compute Display File address +BucleRows: + push bc ;coords = row,col + push hl ;attr address + ld a,b ;row + and %00011000 ;select third (0,1,2) + ld h,a + ld a,b + and %00000111 ;select Row In Third (0,...,7) + rrca + rrca + rrca ;A = %RIT00000 + add a,c + ld l,a ;HL = %000th000RITcolmn + ld de,(SCREEN_ADDR) + add hl,de + ld b,0 + ex af,af' ;A = width-1, CF=1 if width=1, CF=0 if width>1 + ld ixH,7 + +; For each row, transfer 8 scans +BucleScans: + push hl + jr c,AfterLDDR + ld d,h + ld e,l ;DE = to address + dec hl ;HL = from address + ld c,a + lddr ;1st-7th scan in row + ex de,hl +AfterLDDR: + ld (hl),b ;clean up leftmost + pop hl + inc h ;scan below + dec ixH + jp nz,BucleScans + + jr c,AfterLDDR2 + ld d,h + ld e,l ;DE = to address + dec hl ;HL = from address + ld c,a + lddr ;8th scan in row + ex de,hl +AfterLDDR2: + ld (hl),b ;clean up leftmost + +; For each row, transfer a line of attributes + pop hl ;attr address + jr c,AfterLDDR3 + ld d,h + ld e,l ;DE = to address + dec hl ;HL = from address + ld c,a + push de + lddr ;attrs in row + pop hl +AfterLDDR3: + ex af,af' ;A' = width-1, CF'=1 if width=1, CF'=0 if width>1 + ld de,32 + add hl,de ;row below + pop bc + inc b ;row below + dec ixL + jp nz,BucleRows + + pop ix ENDP pop namespace end asm @@ -133,74 +142,36 @@ end sub ' --------------------------------------------------------------------- ' sub WinScrollLeft ' scrolls the window defined by (row, col, width, height) 1 cell left +' it works with width=1 or height=1 but it is not impressive +' nothing is done if width=0 or height=0 ' --------------------------------------------------------------------- sub fastcall WinScrollLeft(row as uByte, col as uByte, width as Ubyte, height as Ubyte) asm push namespace core PROC - LOCAL BucleChars - LOCAL BucleScans - LOCAL BucleAttrs + LOCAL BucleRows, BucleScans, AfterLDIR, AfterLDIR2, AfterLDIR3 - ld b, a - pop hl - pop de - ld c, d +; Read parameters, return if they are bad + ld b, a ;row + pop hl ;return address pop de + ld c, d ;col + pop de ;width ex (sp), hl - ld e, h + ld e, h ;height ld a, e or a - ret z - or d - ret z - push bc - ld a,b - and 18h - ld h,a - ld a,b - and 07h - add a,a - add a,a - add a,a - add a,a - add a,a - add a,c - ld l,a ;HL=top-left window address in bitmap coord - ld bc, (SCREEN_ADDR) - add hl, bc - ld b,e - -BucleChars: - push bc - ld b,8 - -BucleScans: - push bc - push de - push hl - ld c,d - dec c - ld b,0 - ld d,h - ld e,l - inc e - ex de,hl - ldir - ; clean up latest - xor a - ld (de),a - pop hl - pop de - inc h - pop bc - djnz BucleScans - dec h - call SP.PixelDown - pop bc - djnz BucleChars - - pop bc + ret z ;height=0 + ld a, d + or a + ret z ;width=0 + +; Compute Attributes address + sub 2 ;CF=1 if width=1, CF=0 if width>1 + inc a + ex af,af' ;A' = width-1, CF'=1 if width=1, CF'=0 if width>1 + push ix + ld ixL,e ;IXl = height, iterative variable ld l,b ld h,0 add hl,hl @@ -210,31 +181,77 @@ BucleScans: add hl,hl ld a,l add a,c - ld l,a - ld a,h - ld h,a ;HL=top-left address in attr coords - ld bc, (SCREEN_ATTR_ADDR) - add hl, bc - ld b,e - -BucleAttrs: - push bc - push de - push hl - ld c,d - dec c - ld b,0 - ld d,h - ld e,l - inc e - ex de,hl - ldir - pop hl - ld de,32 + ld l,a ;HL = row*32 + col + ld de,(SCREEN_ATTR_ADDR) add hl,de - pop de - pop bc - djnz BucleAttrs + +; For each row, compute Display File address +BucleRows: + push bc ;coords = row,col + push hl ;attr address + ld a,b ;row + and %00011000 ;select third (0,1,2) + ld h,a + ld a,b + and %00000111 ;select Row In Third (0,...,7) + rrca + rrca + rrca ;A = %RIT00000 + add a,c + ld l,a ;HL = %000th000RITcolmn + ld de,(SCREEN_ADDR) + add hl,de + ld b,0 + ex af,af' ;A = width-1, CF=1 if width=1, CF=0 if width>1 + ld ixH,7 + +; For each row, transfer 8 scans +BucleScans: + push hl + jr c,AfterLDIR + ld d,h + ld e,l ;DE = to address + inc hl ;HL = from address + ld c,a + ldir ;1st-7th scan in row + ex de,hl +AfterLDIR: + ld (hl),b ;clean up rightmost + pop hl + inc h ;scan below + dec ixH + jp nz,BucleScans + + jr c,AfterLDIR2 + ld d,h + ld e,l ;DE = to address + inc hl ;HL = from address + ld c,a + ldir ;8th scan in row + ex de,hl +AfterLDIR2: + ld (hl),b ;clean up rightmost + +; For each row, transfer a line of attributes + pop hl ;attr address + jr c,AfterLDIR3 + ld d,h + ld e,l ;DE = to address + inc hl ;HL = from address + ld c,a + push de + ldir ;attrs in row + pop hl +AfterLDIR3: + ex af,af' ;A' = width-1, CF'=1 if width=1, CF'=0 if width>1 + ld de,32 + add hl,de ;row below + pop bc + inc b ;row below + dec ixL + jp nz,BucleRows + + pop ix ENDP pop namespace end asm @@ -244,107 +261,35 @@ end sub ' --------------------------------------------------------------------- ' sub WinScrollUp ' scrolls the window defined by (row, col, width, height) 1 cell up +' it works with width=1 or height=1 but it is not impressive +' nothing is done if width=0 or height=0 ' --------------------------------------------------------------------- sub fastcall WinScrollUp(row as uByte, col as uByte, width as Ubyte, height as Ubyte) asm push namespace core PROC - LOCAL BucleScans, BucleAttrs, ScrollAttrs - LOCAL CleanLast, CleanLastLoop, EndCleanScan + LOCAL BucleRows, BucleScans, AttrAddress + LOCAL CleanBottomRow, CleanBottomScans, AfterLDIR - ld b, a - pop hl - pop de - ld c, d +; Read parameters, return if they are bad + ld b, a ;row + pop hl ;return address pop de + ld c, d ;col + pop de ;width ex (sp), hl - ld e, h + ld e, h ;height ld a, e or a - ret z - or d - ret z - - push bc - push de - - ld a,b - and 18h - ld h,a - ld a,b - and 07h - add a,a - add a,a - add a,a - add a,a - add a,a - add a,c - ld l,a ;HL=top-left window address in bitmap coord - ld bc, (SCREEN_ADDR) - add hl, bc - ld a,e - ld c, d ; c = width - ld d, h - ld e, l - dec a - jr z, CleanLast - add a,a - add a,a - add a,a - ld b, a ; b = 8 * (height - 1) - - inc h - inc h - inc h - inc h - inc h - inc h - inc h - call SP.PixelDown - -BucleScans: - push bc - push de - push hl - ld b, 0 - ldir - pop hl - pop de - pop bc - call SP.PixelDown - ex de, hl - call SP.PixelDown - ex de, hl - djnz BucleScans - -CleanLast: - ex de,hl - pop de - ld b, 8 - ld c, d - push de - -CleanLastLoop: - push bc - push hl - ld (hl), 0 - dec c - jr z, EndCleanScan - ld d, h - ld e, l - inc de - ld b, 0 - ldir - -EndCleanScan: - pop hl - pop bc - inc h - djnz CleanLastLoop + ret z ;height=0 + ld a, d + or a + ret z ;width=0 -ScrollAttrs: - pop de - pop bc +; Compute TopRow Attributes address + ex af,af' ;A' = width + push ix + ld ixL,e ;IXl = height, iterative variable ld l,b ld h,0 add hl,hl @@ -354,147 +299,145 @@ ScrollAttrs: add hl,hl ld a,l add a,c - ld l,a - ld a,h - ld h,a ;HL=top-left address in attr coords - ld bc, (SCREEN_ATTR_ADDR) - add hl, bc - ld b,e - dec b - ret z - -BucleAttrs: - push bc - push de - push hl - ld b,0 - ld c,d - ex de,hl - ld hl,32 + ld l,a ;HL = row*32 + col + ld de,(SCREEN_ATTR_ADDR) add hl,de - ldir - pop hl - ld de,32 + ld (AttrAddress+1),hl + +; Compute TopRow Display File address + ld a,b ;row + and %00011000 ;select third (0,1,2) + ld h,a + ld a,b + and %00000111 ;select Row In Third (0,...,7) + rrca + rrca + rrca ;A = %RIT00000 + add a,c + ld l,a ;HL = %000th000RITcolmn + ld de,(SCREEN_ADDR) add hl,de - pop de - pop bc - djnz BucleAttrs + push hl ;HL = from address + +BucleRows: + dec ixL + jr z,CleanBottomRow +; For each row, compute Display File address + inc b ;row below + ld a,b ;row + and %00011000 ;select third (0,1,2) + ld h,a + ld a,b + and %00000111 ;select Row In Third (0,...,7) + rrca + rrca + rrca ;A = %RIT00000 + add a,c + ld l,a ;HL = %000th000RITcolmn + ld de,(SCREEN_ADDR) + add hl,de + +; For each row, transfer 8 scans + pop de ;DE = to address, obtained from last "push hl; from address" + push hl ;HL = from address, will be the next "to address" + push bc ;coords = row,col + ld b,0 + ex af,af' ;A = width + ld ixH,7 +BucleScans: + ld c,a + push de + push hl + ldir ;1st-7th scan in row + pop hl + pop de + inc h ;scan below + inc d ;scan below + dec ixH + jp nz,BucleScans + + ld c,a + ldir ;8th scan in row + +; For each row, transfer a line of attributes +AttrAddress: + ld hl,AttrAddress + ld d,h + ld e,l ;DE = to address + ld c,32 + add hl,bc ;HL = from address + ld (AttrAddress+1),hl + ld c,a + ldir ;attrs in row + ex af,af' ;A' = width + pop bc + jp BucleRows + +; Clean bottom row (Display File, not Attributes) +CleanBottomRow: + ld b,0 + ex af,af' ;A = width + ld ixH,8 ;no need to speed up code by processing scans 1-7 apart of scan 8 + pop hl +CleanBottomScans: + ld (hl),b + ld c,a + dec c + jr z,AfterLDIR + push hl + ld d,h + ld e,l + inc de + ldir + pop hl +AfterLDIR: + inc h + dec ixH + jp nz,CleanBottomScans + + pop ix ENDP pop namespace end asm - end sub ' --------------------------------------------------------------------- ' sub WinScrollDown ' scrolls the window defined by (row, col, width, height) 1 cell down +' it works with width=1 or height=1 but it is not impressive +' nothing is done if width=0 or height=0 ' --------------------------------------------------------------------- sub fastcall WinScrollDown(row as uByte, col as uByte, width as Ubyte, height as Ubyte) asm push namespace core PROC - LOCAL BucleScans, BucleAttrs, ScrollAttrs - LOCAL CleanLast, CleanLastLoop, EndCleanScan + LOCAL BucleRows, BucleScans, AttrAddress + LOCAL CleanTopRow, CleanTopScans, AfterLDIR - ld b, a - pop hl - pop de - ld c, d +; Read parameters, return if they are bad + ld b, a ;rowTop + pop hl ;return address pop de + ld c, d ;col + pop de ;width ex (sp), hl - ld e, h - ld a, e - or a - ret z - or d - ret z - + ld e, h ;height ld a, b add a, e dec a - ld b, a ; b = row + height - 1 = top most row - - push bc - push de - - ld a,b - and 18h - ld h,a - ld a,b - and 07h - add a,a - add a,a - add a,a - add a,a - add a,a - add a,c - ld l,a ;HL=bottom-left window address in bitmap coord - ld bc, (SCREEN_ADDR) - add hl, bc - ld a,e - ld c, d ; c = width - ld d, h - ld e, l - dec a - jr z, CleanLast - add a,a - add a,a - add a,a - ld b, a ; b = 8 * (height - 1) - - inc d - inc d - inc d - inc d - inc d - inc d - inc d - call SP.PixelUp - -BucleScans: - push bc - push de - push hl - ld b, 0 - ldir - pop hl - pop de - pop bc - call SP.PixelUp - ex de, hl - call SP.PixelUp - ex de, hl - djnz BucleScans - -CleanLast: - ex de,hl - pop de - ld b, 8 - ld c, d - push de - -CleanLastLoop: - push bc - push hl - ld (hl), 0 - dec c - jr z, EndCleanScan - ld d, h - ld e, l - inc de - ld b, 0 - ldir - -EndCleanScan: - pop hl - pop bc - dec h - djnz CleanLastLoop + ld b, a ;rowBottom = rowTop + height - 1 + ld a, e + or a + ret z ;height=0 + ld a, d + or a + ret z ;width=0 -ScrollAttrs: - pop de - pop bc +; Compute BottomRow Attributes address + ex af,af' ;A' = width + push ix + ld ixL,e ;IXl = height, iterative variable ld l,b ld h,0 add hl,hl @@ -504,43 +447,111 @@ ScrollAttrs: add hl,hl ld a,l add a,c - ld l,a - ld a,h - ld h,a ;HL=top-left address in attr coords - ld bc, (SCREEN_ATTR_ADDR) - add hl, bc - ld b,e - dec b - ret z - -BucleAttrs: - push bc - push de - push hl - ld b,0 - ld c,d - ex de,hl - ld hl,-32 + ld l,a ;HL = row*32 + col + ld de,(SCREEN_ATTR_ADDR) add hl,de - ldir - pop hl - ld de,-32 + ld (AttrAddress+1),hl + +; Compute BottomRow Display File address + ld a,b ;row + and %00011000 ;select third (0,1,2) + ld h,a + ld a,b + and %00000111 ;select Row In Third (0,...,7) + rrca + rrca + rrca ;A = %RIT00000 + add a,c + ld l,a ;HL = %000th000RITcolmn + ld de,(SCREEN_ADDR) add hl,de - pop de - pop bc - djnz BucleAttrs + push hl ;HL = from address + +BucleRows: + dec ixL + jr z,CleanTopRow +; For each row, compute Display File address + dec b ;row above + ld a,b ;row + and %00011000 ;select third (0,1,2) + ld h,a + ld a,b + and %00000111 ;select Row In Third (0,...,7) + rrca + rrca + rrca ;A = %RIT00000 + add a,c + ld l,a ;HL = %000th000RITcolmn + ld de,(SCREEN_ADDR) + add hl,de + +; For each row, transfer 8 scans + pop de ;DE = to address, obtained from last "push hl; from address" + push hl ;HL = from address, will be the next "to address" + push bc ;coords = row,col + ld b,0 + ex af,af' ;A = width + ld ixH,7 +BucleScans: + ld c,a + push de + push hl + ldir ;1st-7th scan in row + pop hl + pop de + inc h ;scan below + inc d ;scan below + dec ixH + jp nz,BucleScans + + ld c,a + ldir ;8th scan in row + +; For each row, transfer a line of attributes +AttrAddress: + ld hl,AttrAddress + ld d,h + ld e,l ;DE = to address + ld c,32 ;it is a "mORAcle" that CarryFlag is always 0 here + sbc hl,bc ;HL = from address + ld (AttrAddress+1),hl + ld c,a + ldir ;attrs in row + ex af,af' ;A' = width + pop bc + jp BucleRows + +; Clean top row (Display File, not Attributes) +CleanTopRow: + ld b,0 + ex af,af' ;A = width + ld ixH,8 ;no need to speed up code by processing scans 1-7 apart of scan 8 + pop hl +CleanTopScans: + ld (hl),b + ld c,a + dec c + jr z,AfterLDIR + push hl + ld d,h + ld e,l + inc de + ldir + pop hl +AfterLDIR: + inc h + dec ixH + jp nz,CleanTopScans + + pop ix ENDP pop namespace end asm - end sub #pragma pop(case_insensitive) -REM the following is required, because it defines screen start addr -#require "cls.asm" -#require "SP/PixelDown.asm" -#require "SP/PixelUp.asm" +REM the following is required, because it defines SCREEN_ADDR and SCREEN_ATTR_ADDR #require "sysvars.asm" diff --git a/src/lib/arch/zxnext/stdlib/winscroll.bas b/src/lib/arch/zxnext/stdlib/winscroll.bas index 45e5a9a4e..381f02250 100644 --- a/src/lib/arch/zxnext/stdlib/winscroll.bas +++ b/src/lib/arch/zxnext/stdlib/winscroll.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 ' ---------------------------------------------------------------- @@ -19,75 +20,39 @@ REM Avoid recursive / multiple inclusion ' --------------------------------------------------------------------- ' sub WinScrollRight ' scrolls the window defined by (row, col, width, height) 1 cell right +' it works with width=1 or height=1 but it is not impressive +' nothing is done if width=0 or height=0 ' --------------------------------------------------------------------- sub fastcall WinScrollRight(row as uByte, col as uByte, width as Ubyte, height as Ubyte) asm push namespace core - LOCAL BucleChars - LOCAL BucleScans - LOCAL BucleAttrs - PROC - ld b, a - pop hl - pop de - ld c, d + LOCAL BucleRows, BucleScans, AfterLDDR, AfterLDDR2, AfterLDDR3 + +; Read parameters, return if they are bad + ld b, a ;row + pop hl ;return address pop de + ld a, d ;colLeft + pop de ;width + add a, d + dec a + ld c, a ;colRight = colLeft + width - 1 ex (sp), hl - ld e, h + ld e, h ;height ld a, e or a - ret z - or d - ret z - push bc - ld a,b - and 18h - ld h,a - ld a,b - and 07h - add a,a - add a,a - add a,a - add a,a - add a,a - add a,c - add a,d - dec a - ld l,a ;HL=top-left window address in bitmap coord - ld bc, (SCREEN_ADDR) - add hl, bc - ld b,e - -BucleChars: - push bc - ld b,8 - -BucleScans: - push bc - push de - push hl - ld c,d - dec c - ld b,0 - ld d,h - ld e,l - dec l - lddr - ; clean up latest - xor a - ld (de),a - pop hl - pop de - inc h - pop bc - djnz BucleScans - dec h - call SP.PixelDown - pop bc - djnz BucleChars - - pop bc + ret z ;height=0 + ld a, d + or a + ret z ;width=0 + +; Compute Attributes address + sub 2 ;CF=1 if width=1, CF=0 if width>1 + inc a + ex af,af' ;A' = width-1, CF'=1 if width=1, CF'=0 if width>1 + push ix + ld ixL,e ;IXl = height, iterative variable ld l,b ld h,0 add hl,hl @@ -97,33 +62,77 @@ BucleScans: add hl,hl ld a,l add a,c - add a,d - dec a - ld l,a - ld a,h - ld h,a ;HL=top-left window address in attr coord - ld bc, (SCREEN_ATTR_ADDR) - add hl, bc - ld b,e - -BucleAttrs: - push bc - push de - push hl - ld c,d - dec c - ld b,0 - ld d,h - ld e,l - dec l - lddr - pop hl - ld de,32 + ld l,a ;HL = row*32 + colRight + ld de,(SCREEN_ATTR_ADDR) add hl,de - pop de - pop bc - djnz BucleAttrs +; For each row, compute Display File address +BucleRows: + push bc ;coords = row,col + push hl ;attr address + ld a,b ;row + and %00011000 ;select third (0,1,2) + ld h,a + ld a,b + and %00000111 ;select Row In Third (0,...,7) + rrca + rrca + rrca ;A = %RIT00000 + add a,c + ld l,a ;HL = %000th000RITcolmn + ld de,(SCREEN_ADDR) + add hl,de + ld b,0 + ex af,af' ;A = width-1, CF=1 if width=1, CF=0 if width>1 + ld ixH,7 + +; For each row, transfer 8 scans +BucleScans: + push hl + jr c,AfterLDDR + ld d,h + ld e,l ;DE = to address + dec hl ;HL = from address + ld c,a + lddr ;1st-7th scan in row + ex de,hl +AfterLDDR: + ld (hl),b ;clean up leftmost + pop hl + inc h ;scan below + dec ixH + jp nz,BucleScans + + jr c,AfterLDDR2 + ld d,h + ld e,l ;DE = to address + dec hl ;HL = from address + ld c,a + lddr ;8th scan in row + ex de,hl +AfterLDDR2: + ld (hl),b ;clean up leftmost + +; For each row, transfer a line of attributes + pop hl ;attr address + jr c,AfterLDDR3 + ld d,h + ld e,l ;DE = to address + dec hl ;HL = from address + ld c,a + push de + lddr ;attrs in row + pop hl +AfterLDDR3: + ex af,af' ;A' = width-1, CF'=1 if width=1, CF'=0 if width>1 + ld de,32 + add hl,de ;row below + pop bc + inc b ;row below + dec ixL + jp nz,BucleRows + + pop ix ENDP pop namespace end asm @@ -133,74 +142,36 @@ end sub ' --------------------------------------------------------------------- ' sub WinScrollLeft ' scrolls the window defined by (row, col, width, height) 1 cell left +' it works with width=1 or height=1 but it is not impressive +' nothing is done if width=0 or height=0 ' --------------------------------------------------------------------- sub fastcall WinScrollLeft(row as uByte, col as uByte, width as Ubyte, height as Ubyte) asm push namespace core PROC - LOCAL BucleChars - LOCAL BucleScans - LOCAL BucleAttrs + LOCAL BucleRows, BucleScans, AfterLDIR, AfterLDIR2, AfterLDIR3 - ld b, a - pop hl - pop de - ld c, d +; Read parameters, return if they are bad + ld b, a ;row + pop hl ;return address pop de + ld c, d ;col + pop de ;width ex (sp), hl - ld e, h + ld e, h ;height ld a, e or a - ret z - or d - ret z - push bc - ld a,b - and 18h - ld h,a - ld a,b - and 07h - add a,a - add a,a - add a,a - add a,a - add a,a - add a,c - ld l,a ;HL=top-left window address in bitmap coord - ld bc, (SCREEN_ADDR) - add hl, bc - ld b,e - -BucleChars: - push bc - ld b,8 - -BucleScans: - push bc - push de - push hl - ld c,d - dec c - ld b,0 - ld d,h - ld e,l - inc e - ex de,hl - ldir - ; clean up latest - xor a - ld (de),a - pop hl - pop de - inc h - pop bc - djnz BucleScans - dec h - call SP.PixelDown - pop bc - djnz BucleChars - - pop bc + ret z ;height=0 + ld a, d + or a + ret z ;width=0 + +; Compute Attributes address + sub 2 ;CF=1 if width=1, CF=0 if width>1 + inc a + ex af,af' ;A' = width-1, CF'=1 if width=1, CF'=0 if width>1 + push ix + ld ixL,e ;IXl = height, iterative variable ld l,b ld h,0 add hl,hl @@ -210,31 +181,77 @@ BucleScans: add hl,hl ld a,l add a,c - ld l,a - ld a,h - ld h,a ;HL=top-left address in attr coords - ld bc, (SCREEN_ATTR_ADDR) - add hl, bc - ld b,e - -BucleAttrs: - push bc - push de - push hl - ld c,d - dec c - ld b,0 - ld d,h - ld e,l - inc e - ex de,hl - ldir - pop hl - ld de,32 + ld l,a ;HL = row*32 + col + ld de,(SCREEN_ATTR_ADDR) add hl,de - pop de - pop bc - djnz BucleAttrs + +; For each row, compute Display File address +BucleRows: + push bc ;coords = row,col + push hl ;attr address + ld a,b ;row + and %00011000 ;select third (0,1,2) + ld h,a + ld a,b + and %00000111 ;select Row In Third (0,...,7) + rrca + rrca + rrca ;A = %RIT00000 + add a,c + ld l,a ;HL = %000th000RITcolmn + ld de,(SCREEN_ADDR) + add hl,de + ld b,0 + ex af,af' ;A = width-1, CF=1 if width=1, CF=0 if width>1 + ld ixH,7 + +; For each row, transfer 8 scans +BucleScans: + push hl + jr c,AfterLDIR + ld d,h + ld e,l ;DE = to address + inc hl ;HL = from address + ld c,a + ldir ;1st-7th scan in row + ex de,hl +AfterLDIR: + ld (hl),b ;clean up rightmost + pop hl + inc h ;scan below + dec ixH + jp nz,BucleScans + + jr c,AfterLDIR2 + ld d,h + ld e,l ;DE = to address + inc hl ;HL = from address + ld c,a + ldir ;8th scan in row + ex de,hl +AfterLDIR2: + ld (hl),b ;clean up rightmost + +; For each row, transfer a line of attributes + pop hl ;attr address + jr c,AfterLDIR3 + ld d,h + ld e,l ;DE = to address + inc hl ;HL = from address + ld c,a + push de + ldir ;attrs in row + pop hl +AfterLDIR3: + ex af,af' ;A' = width-1, CF'=1 if width=1, CF'=0 if width>1 + ld de,32 + add hl,de ;row below + pop bc + inc b ;row below + dec ixL + jp nz,BucleRows + + pop ix ENDP pop namespace end asm @@ -244,107 +261,35 @@ end sub ' --------------------------------------------------------------------- ' sub WinScrollUp ' scrolls the window defined by (row, col, width, height) 1 cell up +' it works with width=1 or height=1 but it is not impressive +' nothing is done if width=0 or height=0 ' --------------------------------------------------------------------- sub fastcall WinScrollUp(row as uByte, col as uByte, width as Ubyte, height as Ubyte) asm push namespace core PROC - LOCAL BucleScans, BucleAttrs, ScrollAttrs - LOCAL CleanLast, CleanLastLoop, EndCleanScan + LOCAL BucleRows, BucleScans, AttrAddress + LOCAL CleanBottomRow, CleanBottomScans, AfterLDIR - ld b, a - pop hl - pop de - ld c, d +; Read parameters, return if they are bad + ld b, a ;row + pop hl ;return address pop de + ld c, d ;col + pop de ;width ex (sp), hl - ld e, h + ld e, h ;height ld a, e or a - ret z - or d - ret z - - push bc - push de - - ld a,b - and 18h - ld h,a - ld a,b - and 07h - add a,a - add a,a - add a,a - add a,a - add a,a - add a,c - ld l,a ;HL=top-left window address in bitmap coord - ld bc, (SCREEN_ADDR) - add hl, bc - ld a,e - ld c, d ; c = width - ld d, h - ld e, l - dec a - jr z, CleanLast - add a,a - add a,a - add a,a - ld b, a ; b = 8 * (height - 1) - - inc h - inc h - inc h - inc h - inc h - inc h - inc h - call SP.PixelDown - -BucleScans: - push bc - push de - push hl - ld b, 0 - ldir - pop hl - pop de - pop bc - call SP.PixelDown - ex de, hl - call SP.PixelDown - ex de, hl - djnz BucleScans - -CleanLast: - ex de,hl - pop de - ld b, 8 - ld c, d - push de - -CleanLastLoop: - push bc - push hl - ld (hl), 0 - dec c - jr z, EndCleanScan - ld d, h - ld e, l - inc de - ld b, 0 - ldir - -EndCleanScan: - pop hl - pop bc - inc h - djnz CleanLastLoop + ret z ;height=0 + ld a, d + or a + ret z ;width=0 -ScrollAttrs: - pop de - pop bc +; Compute TopRow Attributes address + ex af,af' ;A' = width + push ix + ld ixL,e ;IXl = height, iterative variable ld l,b ld h,0 add hl,hl @@ -354,147 +299,145 @@ ScrollAttrs: add hl,hl ld a,l add a,c - ld l,a - ld a,h - ld h,a ;HL=top-left address in attr coords - ld bc, (SCREEN_ATTR_ADDR) - add hl, bc - ld b,e - dec b - ret z - -BucleAttrs: - push bc - push de - push hl - ld b,0 - ld c,d - ex de,hl - ld hl,32 + ld l,a ;HL = row*32 + col + ld de,(SCREEN_ATTR_ADDR) add hl,de - ldir - pop hl - ld de,32 + ld (AttrAddress+1),hl + +; Compute TopRow Display File address + ld a,b ;row + and %00011000 ;select third (0,1,2) + ld h,a + ld a,b + and %00000111 ;select Row In Third (0,...,7) + rrca + rrca + rrca ;A = %RIT00000 + add a,c + ld l,a ;HL = %000th000RITcolmn + ld de,(SCREEN_ADDR) add hl,de - pop de - pop bc - djnz BucleAttrs + push hl ;HL = from address + +BucleRows: + dec ixL + jr z,CleanBottomRow +; For each row, compute Display File address + inc b ;row below + ld a,b ;row + and %00011000 ;select third (0,1,2) + ld h,a + ld a,b + and %00000111 ;select Row In Third (0,...,7) + rrca + rrca + rrca ;A = %RIT00000 + add a,c + ld l,a ;HL = %000th000RITcolmn + ld de,(SCREEN_ADDR) + add hl,de + +; For each row, transfer 8 scans + pop de ;DE = to address, obtained from last "push hl; from address" + push hl ;HL = from address, will be the next "to address" + push bc ;coords = row,col + ld b,0 + ex af,af' ;A = width + ld ixH,7 +BucleScans: + ld c,a + push de + push hl + ldir ;1st-7th scan in row + pop hl + pop de + inc h ;scan below + inc d ;scan below + dec ixH + jp nz,BucleScans + + ld c,a + ldir ;8th scan in row + +; For each row, transfer a line of attributes +AttrAddress: + ld hl,AttrAddress + ld d,h + ld e,l ;DE = to address + ld c,32 + add hl,bc ;HL = from address + ld (AttrAddress+1),hl + ld c,a + ldir ;attrs in row + ex af,af' ;A' = width + pop bc + jp BucleRows + +; Clean bottom row (Display File, not Attributes) +CleanBottomRow: + ld b,0 + ex af,af' ;A = width + ld ixH,8 ;no need to speed up code by processing scans 1-7 apart of scan 8 + pop hl +CleanBottomScans: + ld (hl),b + ld c,a + dec c + jr z,AfterLDIR + push hl + ld d,h + ld e,l + inc de + ldir + pop hl +AfterLDIR: + inc h + dec ixH + jp nz,CleanBottomScans + + pop ix ENDP pop namespace end asm - end sub ' --------------------------------------------------------------------- ' sub WinScrollDown ' scrolls the window defined by (row, col, width, height) 1 cell down +' it works with width=1 or height=1 but it is not impressive +' nothing is done if width=0 or height=0 ' --------------------------------------------------------------------- sub fastcall WinScrollDown(row as uByte, col as uByte, width as Ubyte, height as Ubyte) asm push namespace core PROC - LOCAL BucleScans, BucleAttrs, ScrollAttrs - LOCAL CleanLast, CleanLastLoop, EndCleanScan + LOCAL BucleRows, BucleScans, AttrAddress + LOCAL CleanTopRow, CleanTopScans, AfterLDIR - ld b, a - pop hl - pop de - ld c, d +; Read parameters, return if they are bad + ld b, a ;rowTop + pop hl ;return address pop de + ld c, d ;col + pop de ;width ex (sp), hl - ld e, h - ld a, e - or a - ret z - or d - ret z - + ld e, h ;height ld a, b add a, e dec a - ld b, a ; b = row + height - 1 = top most row - - push bc - push de - - ld a,b - and 18h - ld h,a - ld a,b - and 07h - add a,a - add a,a - add a,a - add a,a - add a,a - add a,c - ld l,a ;HL=bottom-left window address in bitmap coord - ld bc, (SCREEN_ADDR) - add hl, bc - ld a,e - ld c, d ; c = width - ld d, h - ld e, l - dec a - jr z, CleanLast - add a,a - add a,a - add a,a - ld b, a ; b = 8 * (height - 1) - - inc d - inc d - inc d - inc d - inc d - inc d - inc d - call SP.PixelUp - -BucleScans: - push bc - push de - push hl - ld b, 0 - ldir - pop hl - pop de - pop bc - call SP.PixelUp - ex de, hl - call SP.PixelUp - ex de, hl - djnz BucleScans - -CleanLast: - ex de,hl - pop de - ld b, 8 - ld c, d - push de - -CleanLastLoop: - push bc - push hl - ld (hl), 0 - dec c - jr z, EndCleanScan - ld d, h - ld e, l - inc de - ld b, 0 - ldir - -EndCleanScan: - pop hl - pop bc - dec h - djnz CleanLastLoop + ld b, a ;rowBottom = rowTop + height - 1 + ld a, e + or a + ret z ;height=0 + ld a, d + or a + ret z ;width=0 -ScrollAttrs: - pop de - pop bc +; Compute BottomRow Attributes address + ex af,af' ;A' = width + push ix + ld ixL,e ;IXl = height, iterative variable ld l,b ld h,0 add hl,hl @@ -504,43 +447,111 @@ ScrollAttrs: add hl,hl ld a,l add a,c - ld l,a - ld a,h - ld h,a ;HL=top-left address in attr coords - ld bc, (SCREEN_ATTR_ADDR) - add hl, bc - ld b,e - dec b - ret z - -BucleAttrs: - push bc - push de - push hl - ld b,0 - ld c,d - ex de,hl - ld hl,-32 + ld l,a ;HL = row*32 + col + ld de,(SCREEN_ATTR_ADDR) add hl,de - ldir - pop hl - ld de,-32 + ld (AttrAddress+1),hl + +; Compute BottomRow Display File address + ld a,b ;row + and %00011000 ;select third (0,1,2) + ld h,a + ld a,b + and %00000111 ;select Row In Third (0,...,7) + rrca + rrca + rrca ;A = %RIT00000 + add a,c + ld l,a ;HL = %000th000RITcolmn + ld de,(SCREEN_ADDR) add hl,de - pop de - pop bc - djnz BucleAttrs + push hl ;HL = from address + +BucleRows: + dec ixL + jr z,CleanTopRow +; For each row, compute Display File address + dec b ;row above + ld a,b ;row + and %00011000 ;select third (0,1,2) + ld h,a + ld a,b + and %00000111 ;select Row In Third (0,...,7) + rrca + rrca + rrca ;A = %RIT00000 + add a,c + ld l,a ;HL = %000th000RITcolmn + ld de,(SCREEN_ADDR) + add hl,de + +; For each row, transfer 8 scans + pop de ;DE = to address, obtained from last "push hl; from address" + push hl ;HL = from address, will be the next "to address" + push bc ;coords = row,col + ld b,0 + ex af,af' ;A = width + ld ixH,7 +BucleScans: + ld c,a + push de + push hl + ldir ;1st-7th scan in row + pop hl + pop de + inc h ;scan below + inc d ;scan below + dec ixH + jp nz,BucleScans + + ld c,a + ldir ;8th scan in row + +; For each row, transfer a line of attributes +AttrAddress: + ld hl,AttrAddress + ld d,h + ld e,l ;DE = to address + ld c,32 ;it is a "mORAcle" that CarryFlag is always 0 here + sbc hl,bc ;HL = from address + ld (AttrAddress+1),hl + ld c,a + ldir ;attrs in row + ex af,af' ;A' = width + pop bc + jp BucleRows + +; Clean top row (Display File, not Attributes) +CleanTopRow: + ld b,0 + ex af,af' ;A = width + ld ixH,8 ;no need to speed up code by processing scans 1-7 apart of scan 8 + pop hl +CleanTopScans: + ld (hl),b + ld c,a + dec c + jr z,AfterLDIR + push hl + ld d,h + ld e,l + inc de + ldir + pop hl +AfterLDIR: + inc h + dec ixH + jp nz,CleanTopScans + + pop ix ENDP pop namespace end asm - end sub #pragma pop(case_insensitive) -REM the following is required, because it defines screen start addr -#require "cls.asm" -#require "SP/PixelDown.asm" -#require "SP/PixelUp.asm" +REM the following is required, because it defines SCREEN_ADDR and SCREEN_ATTR_ADDR #require "sysvars.asm" diff --git a/tests/functional/arch/zx48k/stdlib_winscroll.asm b/tests/functional/arch/zx48k/stdlib_winscroll.asm index 1929d3fa2..b19c0a96f 100644 --- a/tests/functional/arch/zx48k/stdlib_winscroll.asm +++ b/tests/functional/arch/zx48k/stdlib_winscroll.asm @@ -33,68 +33,31 @@ ei ret _WinScrollRight: -#line 24 "/zxbasic/src/lib/arch/zx48k/stdlib/winscroll.bas" +#line 27 "/zxbasic/src/lib/arch/zx48k/stdlib/winscroll.bas" push namespace core - LOCAL BucleChars - LOCAL BucleScans - LOCAL BucleAttrs PROC + LOCAL BucleRows, BucleScans, AfterLDDR, AfterLDDR2, AfterLDDR3 ld b, a pop hl pop de - ld c, d + ld a, d pop de + add a, d + dec a + ld c, a ex (sp), hl ld e, h ld a, e or a ret z - or d + ld a, d + or a ret z - push bc - ld a,b - and 18h - ld h,a - ld a,b - and 07h - add a,a - add a,a - add a,a - add a,a - add a,a - add a,c - add a,d - dec a - ld l,a - ld bc, (SCREEN_ADDR) - add hl, bc - ld b,e -BucleChars: - push bc - ld b,8 -BucleScans: - push bc - push de - push hl - ld c,d - dec c - ld b,0 - ld d,h - ld e,l - dec l - lddr - xor a - ld (de),a - pop hl - pop de - inc h - pop bc - djnz BucleScans - dec h - call SP.PixelDown - pop bc - djnz BucleChars - pop bc + sub 2 + inc a + ex af,af' + push ix + ld ixL,e ld l,b ld h,0 add hl,hl @@ -104,43 +67,79 @@ BucleScans: add hl,hl ld a,l add a,c - add a,d - dec a ld l,a - ld a,h - ld h,a - ld bc, (SCREEN_ATTR_ADDR) - add hl, bc - ld b,e -BucleAttrs: + ld de,(SCREEN_ATTR_ADDR) + add hl,de +BucleRows: push bc - push de push hl - ld c,d - dec c + ld a,b + and %00011000 + ld h,a + ld a,b + and %00000111 + rrca + rrca + rrca + add a,c + ld l,a + ld de,(SCREEN_ADDR) + add hl,de ld b,0 + ex af,af' + ld ixH,7 +BucleScans: + push hl + jr c,AfterLDDR ld d,h ld e,l - dec l + dec hl + ld c,a + lddr + ex de,hl +AfterLDDR: + ld (hl),b + pop hl + inc h + dec ixH + jp nz,BucleScans + jr c,AfterLDDR2 + ld d,h + ld e,l + dec hl + ld c,a + lddr + ex de,hl +AfterLDDR2: + ld (hl),b + pop hl + jr c,AfterLDDR3 + ld d,h + ld e,l + dec hl + ld c,a + push de lddr pop hl +AfterLDDR3: + ex af,af' ld de,32 add hl,de - pop de pop bc - djnz BucleAttrs + inc b + dec ixL + jp nz,BucleRows + pop ix ENDP pop namespace -#line 130 "/zxbasic/src/lib/arch/zx48k/stdlib/winscroll.bas" +#line 139 "/zxbasic/src/lib/arch/zx48k/stdlib/winscroll.bas" _WinScrollRight__leave: ret _WinScrollLeft: -#line 138 "/zxbasic/src/lib/arch/zx48k/stdlib/winscroll.bas" +#line 149 "/zxbasic/src/lib/arch/zx48k/stdlib/winscroll.bas" push namespace core PROC - LOCAL BucleChars - LOCAL BucleScans - LOCAL BucleAttrs + LOCAL BucleRows, BucleScans, AfterLDIR, AfterLDIR2, AfterLDIR3 ld b, a pop hl pop de @@ -151,51 +150,14 @@ _WinScrollLeft: ld a, e or a ret z - or d + ld a, d + or a ret z - push bc - ld a,b - and 18h - ld h,a - ld a,b - and 07h - add a,a - add a,a - add a,a - add a,a - add a,a - add a,c - ld l,a - ld bc, (SCREEN_ADDR) - add hl, bc - ld b,e -BucleChars: - push bc - ld b,8 -BucleScans: - push bc - push de - push hl - ld c,d - dec c - ld b,0 - ld d,h - ld e,l - inc e - ex de,hl - ldir - xor a - ld (de),a - pop hl - pop de - inc h - pop bc - djnz BucleScans - dec h - call SP.PixelDown - pop bc - djnz BucleChars - pop bc + sub 2 + inc a + ex af,af' + push ix + ld ixL,e ld l,b ld h,0 add hl,hl @@ -206,40 +168,79 @@ BucleScans: ld a,l add a,c ld l,a - ld a,h - ld h,a - ld bc, (SCREEN_ATTR_ADDR) - add hl, bc - ld b,e -BucleAttrs: + ld de,(SCREEN_ATTR_ADDR) + add hl,de +BucleRows: push bc - push de push hl - ld c,d - dec c + ld a,b + and %00011000 + ld h,a + ld a,b + and %00000111 + rrca + rrca + rrca + add a,c + ld l,a + ld de,(SCREEN_ADDR) + add hl,de ld b,0 + ex af,af' + ld ixH,7 +BucleScans: + push hl + jr c,AfterLDIR + ld d,h + ld e,l + inc hl + ld c,a + ldir + ex de,hl +AfterLDIR: + ld (hl),b + pop hl + inc h + dec ixH + jp nz,BucleScans + jr c,AfterLDIR2 ld d,h ld e,l - inc e + inc hl + ld c,a + ldir ex de,hl +AfterLDIR2: + ld (hl),b + pop hl + jr c,AfterLDIR3 + ld d,h + ld e,l + inc hl + ld c,a + push de ldir pop hl +AfterLDIR3: + ex af,af' ld de,32 add hl,de - pop de pop bc - djnz BucleAttrs + inc b + dec ixL + jp nz,BucleRows + pop ix ENDP pop namespace -#line 241 "/zxbasic/src/lib/arch/zx48k/stdlib/winscroll.bas" +#line 258 "/zxbasic/src/lib/arch/zx48k/stdlib/winscroll.bas" _WinScrollLeft__leave: ret _WinScrollUp: -#line 249 "/zxbasic/src/lib/arch/zx48k/stdlib/winscroll.bas" +#line 268 "/zxbasic/src/lib/arch/zx48k/stdlib/winscroll.bas" push namespace core PROC - LOCAL BucleScans, BucleAttrs, ScrollAttrs - LOCAL CleanLast, CleanLastLoop, EndCleanScan + LOCAL BucleRows, BucleScans, AttrAddress + LOCAL CleanBottomRow, CleanBottomScans, AfterLDIR ld b, a pop hl pop de @@ -250,81 +251,12 @@ _WinScrollUp: ld a, e or a ret z - or d + ld a, d + or a ret z - push bc - push de - ld a,b - and 18h - ld h,a - ld a,b - and 07h - add a,a - add a,a - add a,a - add a,a - add a,a - add a,c - ld l,a - ld bc, (SCREEN_ADDR) - add hl, bc - ld a,e - ld c, d - ld d, h - ld e, l - dec a - jr z, CleanLast - add a,a - add a,a - add a,a - ld b, a - inc h - inc h - inc h - inc h - inc h - inc h - inc h - call SP.PixelDown -BucleScans: - push bc - push de - push hl - ld b, 0 - ldir - pop hl - pop de - pop bc - call SP.PixelDown - ex de, hl - call SP.PixelDown - ex de, hl - djnz BucleScans -CleanLast: - ex de,hl - pop de - ld b, 8 - ld c, d - push de -CleanLastLoop: - push bc - push hl - ld (hl), 0 - dec c - jr z, EndCleanScan - ld d, h - ld e, l - inc de - ld b, 0 - ldir -EndCleanScan: - pop hl - pop bc - inc h - djnz CleanLastLoop -ScrollAttrs: - pop de - pop bc + ex af,af' + push ix + ld ixL,e ld l,b ld h,0 add hl,hl @@ -335,40 +267,101 @@ ScrollAttrs: ld a,l add a,c ld l,a - ld a,h + ld de,(SCREEN_ATTR_ADDR) + add hl,de + ld (AttrAddress+1),hl + ld a,b + and %00011000 ld h,a - ld bc, (SCREEN_ATTR_ADDR) - add hl, bc - ld b,e - dec b - ret z -BucleAttrs: + ld a,b + and %00000111 + rrca + rrca + rrca + add a,c + ld l,a + ld de,(SCREEN_ADDR) + add hl,de + push hl +BucleRows: + dec ixL + jr z,CleanBottomRow + inc b + ld a,b + and %00011000 + ld h,a + ld a,b + and %00000111 + rrca + rrca + rrca + add a,c + ld l,a + ld de,(SCREEN_ADDR) + add hl,de + pop de + push hl push bc + ld b,0 + ex af,af' + ld ixH,7 +BucleScans: + ld c,a push de push hl - ld b,0 - ld c,d - ex de,hl - ld hl,32 - add hl,de ldir pop hl - ld de,32 - add hl,de pop de + inc h + inc d + dec ixH + jp nz,BucleScans + ld c,a + ldir +AttrAddress: + ld hl,AttrAddress + ld d,h + ld e,l + ld c,32 + add hl,bc + ld (AttrAddress+1),hl + ld c,a + ldir + ex af,af' pop bc - djnz BucleAttrs + jp BucleRows +CleanBottomRow: + ld b,0 + ex af,af' + ld ixH,8 + pop hl +CleanBottomScans: + ld (hl),b + ld c,a + dec c + jr z,AfterLDIR + push hl + ld d,h + ld e,l + inc de + ldir + pop hl +AfterLDIR: + inc h + dec ixH + jp nz,CleanBottomScans + pop ix ENDP pop namespace -#line 385 "/zxbasic/src/lib/arch/zx48k/stdlib/winscroll.bas" +#line 402 "/zxbasic/src/lib/arch/zx48k/stdlib/winscroll.bas" _WinScrollUp__leave: ret _WinScrollDown: -#line 394 "/zxbasic/src/lib/arch/zx48k/stdlib/winscroll.bas" +#line 412 "/zxbasic/src/lib/arch/zx48k/stdlib/winscroll.bas" push namespace core PROC - LOCAL BucleScans, BucleAttrs, ScrollAttrs - LOCAL CleanLast, CleanLastLoop, EndCleanScan + LOCAL BucleRows, BucleScans, AttrAddress + LOCAL CleanTopRow, CleanTopScans, AfterLDIR ld b, a pop hl pop de @@ -376,88 +369,19 @@ _WinScrollDown: pop de ex (sp), hl ld e, h - ld a, e - or a - ret z - or d - ret z ld a, b add a, e dec a ld b, a - push bc - push de - ld a,b - and 18h - ld h,a - ld a,b - and 07h - add a,a - add a,a - add a,a - add a,a - add a,a - add a,c - ld l,a - ld bc, (SCREEN_ADDR) - add hl, bc - ld a,e - ld c, d - ld d, h - ld e, l - dec a - jr z, CleanLast - add a,a - add a,a - add a,a - ld b, a - inc d - inc d - inc d - inc d - inc d - inc d - inc d - call SP.PixelUp -BucleScans: - push bc - push de - push hl - ld b, 0 - ldir - pop hl - pop de - pop bc - call SP.PixelUp - ex de, hl - call SP.PixelUp - ex de, hl - djnz BucleScans -CleanLast: - ex de,hl - pop de - ld b, 8 - ld c, d - push de -CleanLastLoop: - push bc - push hl - ld (hl), 0 - dec c - jr z, EndCleanScan - ld d, h - ld e, l - inc de - ld b, 0 - ldir -EndCleanScan: - pop hl - pop bc - dec h - djnz CleanLastLoop -ScrollAttrs: - pop de - pop bc + ld a, e + or a + ret z + ld a, d + or a + ret z + ex af,af' + push ix + ld ixL,e ld l,b ld h,0 add hl,hl @@ -468,85 +392,96 @@ ScrollAttrs: ld a,l add a,c ld l,a - ld a,h + ld de,(SCREEN_ATTR_ADDR) + add hl,de + ld (AttrAddress+1),hl + ld a,b + and %00011000 ld h,a - ld bc, (SCREEN_ATTR_ADDR) - add hl, bc - ld b,e + ld a,b + and %00000111 + rrca + rrca + rrca + add a,c + ld l,a + ld de,(SCREEN_ADDR) + add hl,de + push hl +BucleRows: + dec ixL + jr z,CleanTopRow dec b - ret z -BucleAttrs: + ld a,b + and %00011000 + ld h,a + ld a,b + and %00000111 + rrca + rrca + rrca + add a,c + ld l,a + ld de,(SCREEN_ADDR) + add hl,de + pop de + push hl push bc + ld b,0 + ex af,af' + ld ixH,7 +BucleScans: + ld c,a push de push hl - ld b,0 - ld c,d - ex de,hl - ld hl,-32 - add hl,de ldir pop hl - ld de,-32 - add hl,de pop de + inc h + inc d + dec ixH + jp nz,BucleScans + ld c,a + ldir +AttrAddress: + ld hl,AttrAddress + ld d,h + ld e,l + ld c,32 + sbc hl,bc + ld (AttrAddress+1),hl + ld c,a + ldir + ex af,af' pop bc - djnz BucleAttrs + jp BucleRows +CleanTopRow: + ld b,0 + ex af,af' + ld ixH,8 + pop hl +CleanTopScans: + ld (hl),b + ld c,a + dec c + jr z,AfterLDIR + push hl + ld d,h + ld e,l + inc de + ldir + pop hl +AfterLDIR: + inc h + dec ixH + jp nz,CleanTopScans + pop ix ENDP pop namespace -#line 535 "/zxbasic/src/lib/arch/zx48k/stdlib/winscroll.bas" +#line 550 "/zxbasic/src/lib/arch/zx48k/stdlib/winscroll.bas" _WinScrollDown__leave: ret ;; --- end of user code --- -#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 1 "/zxbasic/src/lib/arch/zx48k/runtime/sysvars.asm" ;; ----------------------------------------------------------------------- ;; ZX Basic System Vars @@ -573,84 +508,5 @@ SCREEN_ATTR_ADDR: DW 22528 ; Screen attribute address (ditto.) SCR_ROWS EQU 24 ; Screen height in rows SCR_SIZE EQU (SCR_ROWS << 8) + SCR_COLS pop namespace -#line 58 "/zxbasic/src/lib/arch/zx48k/runtime/SP/PixelDown.asm" -#line 540 "/zxbasic/src/lib/arch/zx48k/stdlib/winscroll.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 541 "/zxbasic/src/lib/arch/zx48k/stdlib/winscroll.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 542 "/zxbasic/src/lib/arch/zx48k/stdlib/winscroll.bas" +#line 555 "/zxbasic/src/lib/arch/zx48k/stdlib/winscroll.bas" END