From 8b6c2afe7edc31f76665ad2a89e349fb49b0c17b Mon Sep 17 00:00:00 2001 From: Jose Rodriguez Date: Tue, 2 Sep 2025 23:41:45 +0200 Subject: [PATCH] feat: add getPaintData and getChars functions These does the opposite of putChars() and paint() functions. --- src/lib/arch/zx48k/stdlib/putchars.bas | 202 +++++++++++++++++- src/lib/arch/zxnext/stdlib/putchars.bas | 202 +++++++++++++++++- .../functional/arch/zx48k/stdlib_putchars.asm | 181 +++++++++++++++- 3 files changed, 576 insertions(+), 9 deletions(-) diff --git a/src/lib/arch/zx48k/stdlib/putchars.bas b/src/lib/arch/zx48k/stdlib/putchars.bas index fb355004a..a89aca160 100644 --- a/src/lib/arch/zx48k/stdlib/putchars.bas +++ b/src/lib/arch/zx48k/stdlib/putchars.bas @@ -148,6 +148,139 @@ BLPutCharsEnd: END SUB +' ---------------------------------------------------------------- +' SUB getChars +' +' Gets a rectangle region of the screen into many chars (opposite of putChars) +' +' Parameters: +' x - x coordinate (cell column) +' y - y coordinate (cell row) +' width - width (number of columns) +' height - height (number of rows) +' dataAddress - Chars bytes address +' +' ---------------------------------------------------------------- +SUB getChars(x as uByte,y as uByte, width as uByte, height as uByte, dataAddress as uInteger) +' Copyleft Britlion Feel free to use as you will. Please attribute me if you use this, however! + + Asm + PROC + LOCAL BLGetChar, BLGetCharColumnLoop, BLGetCharInColumnLoop, BLGetCharSameThird + LOCAL BLGetCharNextThird, BLGetCharNextColumn, BLGetCharsEnd + +BLGetChar: + ld a,(ix+5) + ld l,a + ld a,(ix+7) ; Y value + ld d,a + and 24 + ld h,a + ld a,d + and 7 + rrca + rrca + rrca + or l + ld l,a + + push hl ; save our address + ld e,(ix+12) ; data address + ld d,(ix+13) + ld b,(ix+9) ; width + push bc ; save our column count + +BLGetCharColumnLoop: + ld b, (ix+11) ; height + +BLGetCharInColumnLoop: + + push hl + push de + ld de, (.core.SCREEN_ADDR) + add hl, de ;Adds the offset to the screen att address + pop de + + ; gets screen address in HL, and bytes address in DE. Copies the 8 bytes from the screen + ld a,(hl) ; First Row + ld (de),a + + inc de + inc h + ld a,(hl) + ld (de),a ; second Row + + inc de + inc h + ld a,(hl) + ld (de),a ; Third Row + + inc de + inc h + ld a,(hl) + ld (de),a ; Fourth Row + + inc de + inc h + ld a,(hl) + ld (de),a ; Fifth Row + + inc de + inc h + ld a,(hl) + ld (de),a ; Sixth Row + + inc de + inc h + ld a,(hl) + ld (de),a ; Seventh Row + + inc de + inc h + ld a,(hl) + ld (de),a ; Eighth Row + + pop hl + inc de ; Move to next data item. + dec b + jr z, BLGetCharNextColumn + + ;The following code calculates the address of the next line down below current HL address. + push de ; save DE + ld a,l + and 224 + cp 224 + jr z,BLGetCharNextThird + +BLGetCharSameThird: + ld de,32 + add hl,de + pop de ; get our data point back. + jp BLGetCharInColumnLoop + +BLGetCharNextThird: + ld de,1824 + add hl,de + pop de ; get our data point back. + jp BLGetCharInColumnLoop + +BLGetCharNextColumn: + pop bc + pop hl + dec b + jr z, BLGetCharsEnd + + inc l ; Note this would normally be Increase HL - but block painting should never need to increase H, since that would wrap around. + push hl + push bc + jp BLGetCharColumnLoop + +BLGetCharsEnd: + ENDP + End Asm +END SUB + + ' ---------------------------------------------------------------- ' SUB Paint ' @@ -281,6 +414,74 @@ BLPaintDataHeightExitLoop: END SUB +' ---------------------------------------------------------------- +' SUB getPaintData +' +' Gets the colors of a rectangle region of the screen into memory (opposite of paintData) +' +' Parameters: +' x - x coordinate (cell column) +' y - y coordinate (cell row) +' width - width (number of columns) +' height - height (number of rows) +' address - address of the byte-encoded attr sequence +' +' ---------------------------------------------------------------- +SUB getPaintData(x as uByte,y as uByte, width as uByte, height as uByte, address as uInteger) +REM Copyleft Britlion. Feel free to use as you will. Please attribute me if you use this, however! + + Asm + PROC + LOCAL BLGetPaintDataHeightLoop, BLGetPaintDataWidthLoop, BLGetPaintDataWidthExitLoop, BLGetPaintDataHeightExitLoop + + ld a,(ix+7) ;ypos + rrca + rrca + rrca ; Multiply by 32 + ld l,a ; Pass to L + and 3 ; Mask with 00000011 + ld h,a ; Put it in the High Byte + ld a,l ; We get y value *32 + and 224 ; Mask with 11100000 + ld l,a ; Put it in L + ld a,(ix+5) ; xpos + add a,l ; Add it to the Low byte + ld l,a ; Put it back in L, and we're done. HL=Address. + ld de,(.core.SCREEN_ATTR_ADDR) + add hl, de ;Adds the offset to the screen att address + + push hl ; save address + ld d,(ix+13) + ld e,(ix+12) + ld c,(ix+11) ; height + +BLGetPaintDataHeightLoop: + ld b,(ix+9) ; width + +BLGetPaintDataWidthLoop: + ld a,(hl) + ld (de),a ; paint a character + inc hl + inc de + djnz BLGetPaintDataWidthLoop + +BLGetPaintDataWidthExitLoop: + pop hl ; recover our left edge + dec c + jr z, BLGetPaintDataHeightExitLoop + push de + ld de,32 + add hl,de ; move 32 down + pop de + push hl ; save it again + jp BLGetPaintDataHeightLoop + +BLGetPaintDataHeightExitLoop: + ENDP + End Asm +END SUB + + ' ---------------------------------------------------------------- ' SUB putCharsOverMode ' @@ -464,4 +665,3 @@ END SUB #pragma pop(case_insensitive) #endif - diff --git a/src/lib/arch/zxnext/stdlib/putchars.bas b/src/lib/arch/zxnext/stdlib/putchars.bas index fb355004a..a89aca160 100644 --- a/src/lib/arch/zxnext/stdlib/putchars.bas +++ b/src/lib/arch/zxnext/stdlib/putchars.bas @@ -148,6 +148,139 @@ BLPutCharsEnd: END SUB +' ---------------------------------------------------------------- +' SUB getChars +' +' Gets a rectangle region of the screen into many chars (opposite of putChars) +' +' Parameters: +' x - x coordinate (cell column) +' y - y coordinate (cell row) +' width - width (number of columns) +' height - height (number of rows) +' dataAddress - Chars bytes address +' +' ---------------------------------------------------------------- +SUB getChars(x as uByte,y as uByte, width as uByte, height as uByte, dataAddress as uInteger) +' Copyleft Britlion Feel free to use as you will. Please attribute me if you use this, however! + + Asm + PROC + LOCAL BLGetChar, BLGetCharColumnLoop, BLGetCharInColumnLoop, BLGetCharSameThird + LOCAL BLGetCharNextThird, BLGetCharNextColumn, BLGetCharsEnd + +BLGetChar: + ld a,(ix+5) + ld l,a + ld a,(ix+7) ; Y value + ld d,a + and 24 + ld h,a + ld a,d + and 7 + rrca + rrca + rrca + or l + ld l,a + + push hl ; save our address + ld e,(ix+12) ; data address + ld d,(ix+13) + ld b,(ix+9) ; width + push bc ; save our column count + +BLGetCharColumnLoop: + ld b, (ix+11) ; height + +BLGetCharInColumnLoop: + + push hl + push de + ld de, (.core.SCREEN_ADDR) + add hl, de ;Adds the offset to the screen att address + pop de + + ; gets screen address in HL, and bytes address in DE. Copies the 8 bytes from the screen + ld a,(hl) ; First Row + ld (de),a + + inc de + inc h + ld a,(hl) + ld (de),a ; second Row + + inc de + inc h + ld a,(hl) + ld (de),a ; Third Row + + inc de + inc h + ld a,(hl) + ld (de),a ; Fourth Row + + inc de + inc h + ld a,(hl) + ld (de),a ; Fifth Row + + inc de + inc h + ld a,(hl) + ld (de),a ; Sixth Row + + inc de + inc h + ld a,(hl) + ld (de),a ; Seventh Row + + inc de + inc h + ld a,(hl) + ld (de),a ; Eighth Row + + pop hl + inc de ; Move to next data item. + dec b + jr z, BLGetCharNextColumn + + ;The following code calculates the address of the next line down below current HL address. + push de ; save DE + ld a,l + and 224 + cp 224 + jr z,BLGetCharNextThird + +BLGetCharSameThird: + ld de,32 + add hl,de + pop de ; get our data point back. + jp BLGetCharInColumnLoop + +BLGetCharNextThird: + ld de,1824 + add hl,de + pop de ; get our data point back. + jp BLGetCharInColumnLoop + +BLGetCharNextColumn: + pop bc + pop hl + dec b + jr z, BLGetCharsEnd + + inc l ; Note this would normally be Increase HL - but block painting should never need to increase H, since that would wrap around. + push hl + push bc + jp BLGetCharColumnLoop + +BLGetCharsEnd: + ENDP + End Asm +END SUB + + ' ---------------------------------------------------------------- ' SUB Paint ' @@ -281,6 +414,74 @@ BLPaintDataHeightExitLoop: END SUB +' ---------------------------------------------------------------- +' SUB getPaintData +' +' Gets the colors of a rectangle region of the screen into memory (opposite of paintData) +' +' Parameters: +' x - x coordinate (cell column) +' y - y coordinate (cell row) +' width - width (number of columns) +' height - height (number of rows) +' address - address of the byte-encoded attr sequence +' +' ---------------------------------------------------------------- +SUB getPaintData(x as uByte,y as uByte, width as uByte, height as uByte, address as uInteger) +REM Copyleft Britlion. Feel free to use as you will. Please attribute me if you use this, however! + + Asm + PROC + LOCAL BLGetPaintDataHeightLoop, BLGetPaintDataWidthLoop, BLGetPaintDataWidthExitLoop, BLGetPaintDataHeightExitLoop + + ld a,(ix+7) ;ypos + rrca + rrca + rrca ; Multiply by 32 + ld l,a ; Pass to L + and 3 ; Mask with 00000011 + ld h,a ; Put it in the High Byte + ld a,l ; We get y value *32 + and 224 ; Mask with 11100000 + ld l,a ; Put it in L + ld a,(ix+5) ; xpos + add a,l ; Add it to the Low byte + ld l,a ; Put it back in L, and we're done. HL=Address. + ld de,(.core.SCREEN_ATTR_ADDR) + add hl, de ;Adds the offset to the screen att address + + push hl ; save address + ld d,(ix+13) + ld e,(ix+12) + ld c,(ix+11) ; height + +BLGetPaintDataHeightLoop: + ld b,(ix+9) ; width + +BLGetPaintDataWidthLoop: + ld a,(hl) + ld (de),a ; paint a character + inc hl + inc de + djnz BLGetPaintDataWidthLoop + +BLGetPaintDataWidthExitLoop: + pop hl ; recover our left edge + dec c + jr z, BLGetPaintDataHeightExitLoop + push de + ld de,32 + add hl,de ; move 32 down + pop de + push hl ; save it again + jp BLGetPaintDataHeightLoop + +BLGetPaintDataHeightExitLoop: + ENDP + End Asm +END SUB + + ' ---------------------------------------------------------------- ' SUB putCharsOverMode ' @@ -464,4 +665,3 @@ END SUB #pragma pop(case_insensitive) #endif - diff --git a/tests/functional/arch/zx48k/stdlib_putchars.asm b/tests/functional/arch/zx48k/stdlib_putchars.asm index 4dafaca2a..de8f960c0 100644 --- a/tests/functional/arch/zx48k/stdlib_putchars.asm +++ b/tests/functional/arch/zx48k/stdlib_putchars.asm @@ -140,11 +140,119 @@ _putChars__leave: ex (sp), hl exx ret -_paint: +_getChars: push ix ld ix, 0 add ix, sp #line 167 "/zxbasic/src/lib/arch/zx48k/stdlib/putchars.bas" + PROC + LOCAL BLGetChar, BLGetCharColumnLoop, BLGetCharInColumnLoop, BLGetCharSameThird + LOCAL BLGetCharNextThird, BLGetCharNextColumn, BLGetCharsEnd +BLGetChar: + ld a,(ix+5) + ld l,a + ld a,(ix+7) + ld d,a + and 24 + ld h,a + ld a,d + and 7 + rrca + rrca + rrca + or l + ld l,a + push hl + ld e,(ix+12) + ld d,(ix+13) + ld b,(ix+9) + push bc +BLGetCharColumnLoop: + ld b, (ix+11) +BLGetCharInColumnLoop: + push hl + push de + ld de, (.core.SCREEN_ADDR) + add hl, de + pop de + ld a,(hl) + ld (de),a + inc de + inc h + ld a,(hl) + ld (de),a + inc de + inc h + ld a,(hl) + ld (de),a + inc de + inc h + ld a,(hl) + ld (de),a + inc de + inc h + ld a,(hl) + ld (de),a + inc de + inc h + ld a,(hl) + ld (de),a + inc de + inc h + ld a,(hl) + ld (de),a + inc de + inc h + ld a,(hl) + ld (de),a + pop hl + inc de + dec b + jr z, BLGetCharNextColumn + push de + ld a,l + and 224 + cp 224 + jr z,BLGetCharNextThird +BLGetCharSameThird: + ld de,32 + add hl,de + pop de + jp BLGetCharInColumnLoop +BLGetCharNextThird: + ld de,1824 + add hl,de + pop de + jp BLGetCharInColumnLoop +BLGetCharNextColumn: + pop bc + pop hl + dec b + jr z, BLGetCharsEnd + inc l + push hl + push bc + jp BLGetCharColumnLoop +BLGetCharsEnd: + ENDP +#line 281 "/zxbasic/src/lib/arch/zx48k/stdlib/putchars.bas" +_getChars__leave: + ld sp, ix + pop ix + exx + pop hl + pop bc + pop bc + pop bc + pop bc + ex (sp), hl + exx + ret +_paint: + push ix + ld ix, 0 + add ix, sp +#line 300 "/zxbasic/src/lib/arch/zx48k/stdlib/putchars.bas" PROC LOCAL BLPaintHeightLoop, BLPaintWidthLoop, BLPaintWidthExitLoop, BLPaintHeightExitLoop ld a,(ix+7) @@ -181,7 +289,7 @@ BLPaintWidthExitLoop: jp BLPaintHeightLoop BLPaintHeightExitLoop: ENDP -#line 212 "/zxbasic/src/lib/arch/zx48k/stdlib/putchars.bas" +#line 345 "/zxbasic/src/lib/arch/zx48k/stdlib/putchars.bas" _paint__leave: ld sp, ix pop ix @@ -198,7 +306,7 @@ _paintData: push ix ld ix, 0 add ix, sp -#line 232 "/zxbasic/src/lib/arch/zx48k/stdlib/putchars.bas" +#line 365 "/zxbasic/src/lib/arch/zx48k/stdlib/putchars.bas" PROC LOCAL BLPaintDataHeightLoop, BLPaintDataWidthLoop, BLPaintDataWidthExitLoop, BLPaintDataHeightExitLoop ld a,(ix+7) @@ -240,7 +348,7 @@ BLPaintDataWidthExitLoop: jp BLPaintDataHeightLoop BLPaintDataHeightExitLoop: ENDP -#line 281 "/zxbasic/src/lib/arch/zx48k/stdlib/putchars.bas" +#line 414 "/zxbasic/src/lib/arch/zx48k/stdlib/putchars.bas" _paintData__leave: ld sp, ix pop ix @@ -253,11 +361,70 @@ _paintData__leave: ex (sp), hl exx ret +_getPaintData: + push ix + ld ix, 0 + add ix, sp +#line 433 "/zxbasic/src/lib/arch/zx48k/stdlib/putchars.bas" + PROC + LOCAL BLGetPaintDataHeightLoop, BLGetPaintDataWidthLoop, BLGetPaintDataWidthExitLoop, BLGetPaintDataHeightExitLoop + ld a,(ix+7) + rrca + rrca + rrca + ld l,a + and 3 + ld h,a + ld a,l + and 224 + ld l,a + ld a,(ix+5) + add a,l + ld l,a + ld de,(.core.SCREEN_ATTR_ADDR) + add hl, de + push hl + ld d,(ix+13) + ld e,(ix+12) + ld c,(ix+11) +BLGetPaintDataHeightLoop: + ld b,(ix+9) +BLGetPaintDataWidthLoop: + ld a,(hl) + ld (de),a + inc hl + inc de + djnz BLGetPaintDataWidthLoop +BLGetPaintDataWidthExitLoop: + pop hl + dec c + jr z, BLGetPaintDataHeightExitLoop + push de + ld de,32 + add hl,de + pop de + push hl + jp BLGetPaintDataHeightLoop +BLGetPaintDataHeightExitLoop: + ENDP +#line 482 "/zxbasic/src/lib/arch/zx48k/stdlib/putchars.bas" +_getPaintData__leave: + ld sp, ix + pop ix + exx + pop hl + pop bc + pop bc + pop bc + pop bc + ex (sp), hl + exx + ret _putCharsOverMode: push ix ld ix, 0 add ix, sp -#line 306 "/zxbasic/src/lib/arch/zx48k/stdlib/putchars.bas" +#line 507 "/zxbasic/src/lib/arch/zx48k/stdlib/putchars.bas" PROC LOCAL BLPutChar, BLPutCharColumnLoop, BLPutCharInColumnLoop, BLPutCharSameThird LOCAL BLPutCharNextThird, BLPutCharNextColumn, BLPutCharsEnd @@ -388,7 +555,7 @@ BLPutCharNextColumn: jp BLPutCharColumnLoop BLPutCharsEnd: ENDP -#line 460 "/zxbasic/src/lib/arch/zx48k/stdlib/putchars.bas" +#line 661 "/zxbasic/src/lib/arch/zx48k/stdlib/putchars.bas" _putCharsOverMode__leave: exx ld hl, 12 @@ -428,5 +595,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 475 "/zxbasic/src/lib/arch/zx48k/stdlib/putchars.bas" +#line 676 "/zxbasic/src/lib/arch/zx48k/stdlib/putchars.bas" END