Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
BritLion's Putchars
#1
LCD play with this.

The question is, this doesn't do attributes right now. How would you want that handled?

1> Assume it's at the end of the data block? (So if you use putchars for one character, it's the 9th byte. For a 2X2 block, it's the 65th, 66th, 67th and 68th...
2> A separate putAttribs function that works the same way
3> Leave it up to the user to do print at y,x, over 1, paper x, ink y;"<space>"

Something else?

I haven't tested mine against yours, I'm just assuming because of code efficiency, this is faster screen handling.
Edit: See below for test results

Edit: Fixed a bug - in BLPutCharNextThird add HL,DE and POP DE were backwards. Thanks to Compiuter for reporting this.

Edit: Shaved a few clock cycles off the graphics printing, and added a paint sub

Edit: Added a paintData sub

Code:
SUB paint (x as uByte,y as uByte, width as uByte, height as uByte, attribute as ubyte) asm ld a,(IX+7) ;ypos rrca rrca rrca ; Multiply by 32 ld l,a ; Pass to L and 3 ; Mask with 00000011 add a,88 ; 88 * 256 = 22528 - start of attributes. Change this if you are working with a buffer or somesuch. 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. push HL ; save address LD A, (IX+13) ; attribute LD DE,32 LD c,(IX+11) ; height BLPaintHeightLoop: LD b,(IX+9) ; width BLPaintWidthLoop: LD (HL),a ; paint a character INC L ; Move to the right (Note that we only would have to inc H if we are crossing from the right edge to the left, and we shouldn't be needing to do that) DJNZ BLPaintWidthLoop BLPaintWidthExitLoop: POP HL ; recover our left edge DEC C JR Z, BLPaintHeightExitLoop ADD HL,DE ; move 32 down PUSH HL ; save it again JP BLPaintHeightLoop BLPaintHeightExitLoop: end asm END SUB SUB paintData (x as uByte,y as uByte, width as uByte, height as uByte, address as uInteger) asm ld a,(IX+7) ;ypos rrca rrca rrca ; Multiply by 32 ld l,a ; Pass to L and 3 ; Mask with 00000011 add a,88 ; 88 * 256 = 22528 - start of attributes. Change this if you are working with a buffer or somesuch. 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. push HL ; save address LD D, (IX+13) LD E, (IX+12) LD c,(IX+11) ; height BLPaintDataHeightLoop: LD b,(IX+9) ; width BLPaintDataWidthLoop: LD a,(DE) LD (HL),a ; paint a character INC L ; Move to the right (Note that we only would have to inc H if we are crossing from the right edge to the left, and we shouldn't be needing to do that) INC DE DJNZ BLPaintDataWidthLoop BLPaintDataWidthExitLoop: POP HL ; recover our left edge DEC C JR Z, BLPaintDataHeightExitLoop PUSH DE LD DE,32 ADD HL,DE ; move 32 down POP DE PUSH HL ; save it again JP BLPaintDataHeightLoop BLPaintDataHeightExitLoop: end asm END SUB SUB putChars(x as uByte,y as uByte, width as uByte, height as uByte, dataAddress as uInteger) asm BLPutChar: LD a,(IX+5) ;AND 31 ld l,a ld a,(IX+7) ; Y value ld d,a AND 24 add a,64 ; 256 byte "page" for screen - 256*64=16384. Change this if you are working with a screen address elsewhere, such as a buffer. 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 BLPutCharColumnLoop: LD B,(IX+11) ; height BLPutCharInColumnLoop: ; gets screen address in HL, and bytes address in DE. Copies the 8 bytes to the screen ld a,(DE) ; First Row LD (HL),a INC DE INC H ld a,(DE) LD (HL),a ; second Row INC DE INC H ld a,(DE) LD (HL),a ; Third Row INC DE INC H ld a,(DE) LD (HL),a ; Fourth Row INC DE INC H ld a,(DE) LD (HL),a ; Fifth Row INC DE INC H ld a,(DE) LD (HL),a ; Sixth Row INC DE INC H ld a,(DE) LD (HL),a ; Seventh Row INC DE INC H ld a,(DE) LD (HL),a ; Eigth Row INC DE ; Move to next data item. DEC B JR Z,BLPutCharNextColumn ;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 jp z,BLPutCharNextThird BLPutCharSameThird: ld de,-1760 ;and a add hl,de POP DE ; get our data point back. jp BLPutCharInColumnLoop BLPutCharNextThird: ld de,32 ;and a add hl,de POP DE ; get our data point back. JP BLPutCharInColumnLoop BLPutCharNextColumn: POP BC POP HL DEC B JP Z, BLPutCharsEnd 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 BLPutCharColumnLoop BLPutCharsEnd: end asm END SUB goto start datapoint: asm defb 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32 defb 33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64 defb 65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96 defb 97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128 end asm start: cls putChars(10,10,3,3,@datapoint) paint(10,10,3,3,79)
Reply
#2
LCD, you wanted fast screen handling?

I tested your routine against mine. And against PRINT.

Perhaps I did something wrong, but according to my tests "PRINT AT" is faster than your routine...

(obviously, you are including attributes, and I'm not; yet.)


Code:
10,000 loop test: PRINT AT 10,10;"A" 289 Frames PRINT AT 10,10;"AA" 473 Frames PRINT AT 10,10;"A";AT 11,10;"A" 526 Frames PRINT AT 10,10;"AA";AT 11,10;"AA" 896 Frames BL Putchars - 1X1 163 frames 2x1 211 frames 1x2 211 Frames 2X2 301 Frames 3X3 534 Frames 4X4 853 Frames 8X8 3074 Frames BL's PutTile 2X2 276 Frames* - Best estimate. This can't be frame timed *See other thread for this code. May make it into the wiki library. LCD's 1X1 346 Frames 1X2 658 Frames 2X1 658 Frames 2X2 1294 Frames


For repeating the tests, here's the whole code I used:

EDIT: This code is bugged. My bugfixed version is above!

Code:
'=========================== '= putchar lcd compiuter = '= version 1.100603 <-date = '=========================== '#include <sinclair.bas> '#include <memcopy.bas> '#include <keys.bas> '#include <print42.bas> '#include <attr.bas> '--- 'cls 'border 5 '------------------------------------- sub putcharLcd1x1(x as Uinteger,y as Uinteger,adr as Uinteger) dim scr as Uinteger dim a as Uinteger a=peek(@linebuffer+y) scr=(a<<5)+x+16384 poke ubyte scr,peek(adr) poke ubyte scr+256,peek(adr+1) poke ubyte scr+512,peek(adr+2) poke ubyte scr+768,peek(adr+3) poke ubyte scr+1024,peek(adr+4) poke ubyte scr+1280,peek(adr+5) poke ubyte scr+1536,peek(adr+6) poke ubyte scr+1792,peek(adr+7) poke ubyte 22528+x+(y<<5),peek (adr+8) End sub '------------------------------------------- sub putcharLcd1x2(x as Uinteger,y as Uinteger,adr as Uinteger) dim scr as Uinteger dim a as Uinteger a=peek(@linebuffer+y) scr=(a<<5)+x+16384 poke ubyte scr,peek(adr) poke ubyte scr+256,peek(adr+1) poke ubyte scr+512,peek(adr+2) poke ubyte scr+768,peek(adr+3) poke ubyte scr+1024,peek(adr+4) poke ubyte scr+1280,peek(adr+5) poke ubyte scr+1536,peek(adr+6) poke ubyte scr+1792,peek(adr+7) poke ubyte 22528+x+(y<<5),peek (adr+8) x=x+1 a=peek(@linebuffer+y) scr=(a<<5)+x+16384 poke ubyte scr,peek(adr+9) poke ubyte scr+256,peek(adr+10) poke ubyte scr+512,peek(adr+11) poke ubyte scr+768,peek(adr+12) poke ubyte scr+1024,peek(adr+13) poke ubyte scr+1280,peek(adr+14) poke ubyte scr+1536,peek(adr+15) poke ubyte scr+1792,peek(adr+16) poke ubyte 22528+x+(y<<5),peek (adr+17) End sub '------------------------------------------- sub putcharLcd2x1(x as Uinteger,y as Uinteger,adr as Uinteger) dim scr as Uinteger dim a as Uinteger a=peek(@linebuffer+y) scr=(a<<5)+x+16384 poke ubyte scr,peek(adr) poke ubyte scr+256,peek(adr+1) poke ubyte scr+512,peek(adr+2) poke ubyte scr+768,peek(adr+3) poke ubyte scr+1024,peek(adr+4) poke ubyte scr+1280,peek(adr+5) poke ubyte scr+1536,peek(adr+6) poke ubyte scr+1792,peek(adr+7) poke ubyte 22528+x+(y<<5),peek (adr+8) y=y+1 a=peek(@linebuffer+y) scr=(a<<5)+x+16384 poke ubyte scr,peek(adr+9) poke ubyte scr+256,peek(adr+10) poke ubyte scr+512,peek(adr+11) poke ubyte scr+768,peek(adr+12) poke ubyte scr+1024,peek(adr+13) poke ubyte scr+1280,peek(adr+14) poke ubyte scr+1536,peek(adr+15) poke ubyte scr+1792,peek(adr+16) poke ubyte 22528+x+(y<<5),peek (adr+17) End sub '------------------------------------------- sub putcharLcd2x2(x as Uinteger,y as Uinteger,adr as Uinteger) dim scr as Uinteger dim a as Uinteger a=peek(@linebuffer+y) scr=(a<<5)+x+16384 poke ubyte scr,peek(adr) poke ubyte scr+256,peek(adr+1) poke ubyte scr+512,peek(adr+2) poke ubyte scr+768,peek(adr+3) poke ubyte scr+1024,peek(adr+4) poke ubyte scr+1280,peek(adr+5) poke ubyte scr+1536,peek(adr+6) poke ubyte scr+1792,peek(adr+7) poke ubyte 22528+x+(y<<5),peek (adr+8) x=x+1 a=peek(@linebuffer+y) scr=(a<<5)+x+16384 poke ubyte scr,peek(adr+9) poke ubyte scr+256,peek(adr+10) poke ubyte scr+512,peek(adr+11) poke ubyte scr+768,peek(adr+12) poke ubyte scr+1024,peek(adr+13) poke ubyte scr+1280,peek(adr+14) poke ubyte scr+1536,peek(adr+15) poke ubyte scr+1792,peek(adr+16) poke ubyte 22528+x+(y<<5),peek (adr+17) x=x-1 y=y+1 a=peek(@linebuffer+y) scr=(a<<5)+x+16384 poke ubyte scr,peek(adr+18) poke ubyte scr+256,peek(adr+19) poke ubyte scr+512,peek(adr+20) poke ubyte scr+768,peek(adr+21) poke ubyte scr+1024,peek(adr+22) poke ubyte scr+1280,peek(adr+23) poke ubyte scr+1536,peek(adr+24) poke ubyte scr+1792,peek(adr+25) poke ubyte 22528+x+(y<<5),peek (adr+26) x=x+1 a=peek(@linebuffer+y) scr=(a<<5)+x+16384 poke ubyte scr,peek(adr+27) poke ubyte scr+256,peek(adr+28) poke ubyte scr+512,peek(adr+29) poke ubyte scr+768,peek(adr+30) poke ubyte scr+1024,peek(adr+31) poke ubyte scr+1280,peek(adr+32) poke ubyte scr+1536,peek(adr+33) poke ubyte scr+1792,peek(adr+34) poke ubyte 22528+x+(y<<5),peek (adr+35) End sub '---next will be probably putcharlcd1x3 '--- goto start linebuffer: asm defb 0,1,2,3,4,5,6,7,64,65,66,67,68,69,70,71,128,129,130,131,132,133,134,135 end asm '-------------------------- 'start: '---fin--- END '---------------------------------------- 'gfx1a: 'ASM 'DEFB 0,8,8,8,8,8,8,0,00010001B 'DEFB 0,60,4,4,60,32,60,0,00011001B 'DEFB 0,60,4,4,60,4,60,0,00100001B 'DEFB 0,36,36,36,60,4,4,0,00101001B 'END ASM '----------------------------------------- FUNCTION t() as uLong asm LD DE,(23674) LD D,0 LD HL,(23672) end asm end function SUB putChars(x as uByte,y as uByte,height as uByte,width as uByte,dataAddress as uInteger) DIM columns as uByte REM Let's put our variables into our code: POKE @BLPutCharWidth+1,width POKE @BLPutCharHeight+1,height POKE @BLPutCharX+1, x POKE @BLPutCharY+1, y POKE uInteger @BLPutCharData+1,dataAddress asm call BLPutChar end asm return BLPutCharX: asm BLPutChar: LD a,1 AND 31 ld l,a end asm BLPutCharY: asm ld a,2 ; Y value ld d,a AND 24 add a,64 ld h,a ld a,d AND 7 rrca rrca rrca OR l ld l,a PUSH HL ; save our address. end asm BLPutCharData: asm LD DE,16384 ; Marker - This will be poked for the data address by the subroutine end asm BLPutCharWidth: asm LD B,3 ; Marker - this will be poked for the width PUSH BC ; save our column count. BLPutCharColumnLoop: end asm BLPutCharHeight: asm LD B,1 ; Marker - this will be poked for the height by the subroutine. BLPutCharInColumnLoop: call BLPutBytes DEC B JR Z,BLPutCharNextColumn ;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 jp z,BLPutCharSameThird BLPutCharNextThird: ld de,-1760 ;and a add hl,de POP DE ; get our data point back. jp BLPutCharInColumnLoop BLPutCharSameThird: ld de,32 ;and a POP DE ; get our data point back. add hl,de JP BLPutCharInColumnLoop BLPutCharNextColumn: POP BC POP HL DEC B RET Z INC HL PUSH HL PUSH BC JP BLPutCharColumnLoop end asm asm BLPutBytes: ; gets screen address in HL, and bytes address in DE. Copies the 8 bytes to the screen. ld a,(DE) LD (HL),a INC DE INC H ld a,(DE) LD (HL),a INC DE INC H ld a,(DE) LD (HL),a INC DE INC H ld a,(DE) LD (HL),a INC DE INC H ld a,(DE) LD (HL),a INC DE INC H ld a,(DE) LD (HL),a INC DE INC H ld a,(DE) LD (HL),a INC DE INC H ld a,(DE) LD (HL),a INC DE ret end asm END SUB goto start datapoint: asm defb 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32 defb 33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64 defb 65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96 defb 97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128 end asm start: cls DIM time as uLong DIM i as uInteger time=t() for i=1 to 10000 'putChars(10,10,1,1,@datapoint) : REM Uncomment these lines as you need them. 'print at 10,10;"AA"; AT 11,10;"AA" 'putcharLcd1x1(10,10,@datapoint) 'putcharLcd1x2(10,10,@datapoint) 'putcharLcd2x1(10,10,@datapoint) putcharLcd2x2(10,10,@datapoint) next i print t()-time
Reply
#3
It seems to be clear that your putchar is faster and handly.
Now We need to go for another parameter for atributtes.
Or another sub created for this that suply this.
I´m trying to access your routine for this,
but I acces the position but not atributtes.
I´´m accesin this with Lcd´s function attraddress.
Reply
#4
compiuter Wrote:It seems to be clear that your putchar is faster and handly.
Now We need to go for another parameter for atributtes.
Or another sub created for this that suply this.
I´m trying to access your routine for this,
but I acces the position but not atributtes.
I´´m accesin this with Lcd´s function attraddress.
You can also try SETATTR(x, y, aTTR) routine from the library.
Just use
Code:
#include <attr.bas>
Reply
#5
Ok, thx,I try tomorrow.
Reply
#6
compiuter Wrote:It seems to be clear that your putchar is faster and handly.
Now We need to go for another parameter for atributtes.
Or another sub created for this that suply this.
I´m trying to access your routine for this,
but I acces the position but not atributtes.
I´´m accesin this with Lcd´s function attraddress.

As I said, it doesn't do attributes yet. I was waiting for LCD's opinion on how that should be done - and as Boriel has pointed out, there's a utility for it already. (*evil grin* More speed trials ahead!)

Looking at setAttr - it would be hard to improve on it by much, speedwise. Some, maybe. I can compare optimizations in getting the ATTR address (which Boriel is looking at), and make assumptions about the location of the attributes file, and that if we're called with numbers outside the screen area, we are entitled to crash. (that is, we don't do error checking). Not sure how big a difference it will make though.
Reply
#7
I know that the speed of my routine is not optimal, but unlike PRINT it allows to use more then 96 Characters+blocks+UDGs. In fact you can use fonts of 256 Characters or even more. BorIDE has now a font editow which allows to define such large fonts of 256 characters. I have added all fonts available in Retro-X and can add more later. It can also be used for small tiles. I can also display special characters like kana, german, polish, etc.
My Opinion: I would prefer to have multiple versions to choose from. One with attributes, one without. This will allow to choose speedwise the best routine. Thanks to you Britlion for optimising.
------------------------------------------------------------
http://lcd-one.da.ru redirector is dead
Visit my http://members.inode.at/838331/index.html home page!
Reply
#8
You are quite welcome, LCD. My routine beats out the print routine purely because it's special purposed to copy data to the screen.

I think I rather like the fact that by looping columns and then rows it can do up to 8X8 blocks too. I was quite proud of that - all with just one screen address search. The downside is it has NO error trapping at all. It will happily try to write off the bottom or right hand sides of the screen.

(Though don't forget that exactly the same data could be put on the screen by changing CHARS and using print as well - and by rotating the CHARS system variable, you can print as many graphics characters to the screen at a time as you wish!)


As for attributes, it could be built into the routine as well, LCD. I just wasn't sure how you'd want to handle the data. If you're determined to make it 8+1 bytes per character, then honestly it's faster to skip the attributes on one pass, and then go back and put every 9th byte in as an attribute afterwards. That could be done as two subroutines, called by a third, one after the other, pointed at the same data.
Reply
#9
It seems cut the sprites on screen thirds.
Code:
SUB putChars(x as uByte,y as uByte,height as uByte,width as uByte,dataAddress as uInteger) DIM columns as uByte REM Let's put our variables into our code: POKE @BLPutCharWidth+1,width POKE @BLPutCharHeight+1,height POKE @BLPutCharX+1, x POKE @BLPutCharY+1, y POKE uInteger @BLPutCharData+1,dataAddress asm call BLPutChar end asm return BLPutCharX: asm BLPutChar: LD a,1 AND 31 ld l,a end asm BLPutCharY: asm ld a,2 ; Y value ld d,a AND 24 add a,64 ld h,a ld a,d AND 7 rrca rrca rrca OR l ld l,a PUSH HL ; save our address. end asm BLPutCharData: asm LD DE,16384 ; Marker - This will be poked for the data address by the subroutine end asm BLPutCharWidth: asm LD B,3 ; Marker - this will be poked for the width PUSH BC ; save our column count. BLPutCharColumnLoop: end asm BLPutCharHeight: asm LD B,1 ; Marker - this will be poked for the height by the subroutine. BLPutCharInColumnLoop: call BLPutBytes DEC B JR Z,BLPutCharNextColumn ;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 jp z,BLPutCharSameThird BLPutCharNextThird: ld de,-1760 ;and a add hl,de POP DE ; get our data point back. jp BLPutCharInColumnLoop BLPutCharSameThird: ld de,32 ;and a POP DE ; get our data point back. add hl,de JP BLPutCharInColumnLoop BLPutCharNextColumn: POP BC POP HL DEC B RET Z INC HL PUSH HL PUSH BC JP BLPutCharColumnLoop end asm asm BLPutBytes: ; gets screen address in HL, and bytes address in DE. Copies the 8 bytes to the screen. ld a,(DE) LD (HL),a INC DE INC H ld a,(DE) LD (HL),a INC DE INC H ld a,(DE) LD (HL),a INC DE INC H ld a,(DE) LD (HL),a INC DE INC H ld a,(DE) LD (HL),a INC DE INC H ld a,(DE) LD (HL),a INC DE INC H ld a,(DE) LD (HL),a INC DE INC H ld a,(DE) LD (HL),a INC DE ret end asm END SUB goto start datapoint: asm defb 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32 defb 33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64 end asm start: cls putChars(0,0,2,2,@datapoint) putChars(0,7,2,2,@datapoint) putChars(0,15,2,2,@datapoint) print at 19,0;"error when line=7 or line=15"
Reply
#10
I will have to look into this. Thanks for spotting bugs!
Reply
#11
compiuter Wrote:It seems cut the sprites on screen thirds.

Got it. The pop DE was in the wrong place, so it wasn't working across thirds. Think it's fixed now. Try it again please!
Reply
#12
Waiting for something better ...
In 10-06-10 I modified this routine because Britlion suggest that atributtes are readed better per files instead of per columns, as the cathodic ray bright the pixels in the tv(I say first all the chars of file 0, all chars file 1, ...)for see this uncomment the pause demo besides setattr commands
Code:
'=========================== '= putchat britlion = '=========================== 'thx2Boriel idea using setattr 'modified by compiuter 'version 2.100609 <-date #include <attr.bas> '=========================================== SUB putChars(x as uByte,y as uByte,height as uByte,width as uByte,dataAddress as uInteger) DIM columns as uByte REM Let's put our variables into our code: POKE @BLPutCharWidth+1,width POKE @BLPutCharHeight+1,height POKE @BLPutCharX+1, x POKE @BLPutCharY+1, y POKE uInteger @BLPutCharData+1,dataAddress asm call BLPutChar end asm return BLPutCharX: asm BLPutChar: LD a,1 AND 31 ld l,a end asm BLPutCharY: asm ld a,2 ; Y value ld d,a AND 24 add a,64 ld h,a ld a,d AND 7 rrca rrca rrca OR l ld l,a PUSH HL ; save our address. end asm BLPutCharData: asm LD DE,16384 ; Marker - This will be poked for the data address by the subroutine end asm BLPutCharWidth: asm LD B,3 ; Marker - this will be poked for the width PUSH BC ; save our column count. BLPutCharColumnLoop: end asm BLPutCharHeight: asm LD B,1 ; Marker - this will be poked for the height by the subroutine. BLPutCharInColumnLoop: call BLPutBytes DEC B JR Z,BLPutCharNextColumn ;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 jp z,BLPutCharSameThird BLPutCharNextThird: ld de,-1760 ;and a add hl,de POP DE ; get our data point back. jp BLPutCharInColumnLoop BLPutCharSameThird: ld de,32 ;and a add hl,de POP DE ; get our data point back. JP BLPutCharInColumnLoop BLPutCharNextColumn: POP BC POP HL DEC B RET Z INC HL PUSH HL PUSH BC JP BLPutCharColumnLoop end asm asm BLPutBytes: ; gets screen address in HL, and bytes address in DE. Copies the 8 bytes to the screen. ld a,(DE) LD (HL),a INC DE INC H ld a,(DE) LD (HL),a INC DE INC H ld a,(DE) LD (HL),a INC DE INC H ld a,(DE) LD (HL),a INC DE INC H ld a,(DE) LD (HL),a INC DE INC H ld a,(DE) LD (HL),a INC DE INC H ld a,(DE) LD (HL),a INC DE INC H ld a,(DE) LD (HL),a INC DE ret end asm END SUB '===================================== '### version atr x files ############# '##################################### SUB putCharsAtr(x as uByte,y as uByte,height as uByte,width as uByte,Atr as Ubyte) dim f,n as ubyte for g=0 to height-1 for f=0 to width-1 setattr(y+g,x+f,Atr) 'for demo pause(10) next next END SUB '##################################### '### version atr x columns ########### ' SUB putCharsAtr(x as uByte,y as uByte,height as uByte,width as uByte,Atr as Ubyte) ' dim f,g as ubyte ' for g=0 to width-1 ' for f=0 to height-1 ' setattr(y+f,x+g,Atr) 'for demo pause(10) ' pause(10) ' next ' next ' END SUB '##################################### '===================================== SUB putChAt(x as uByte,y as uByte,height as uByte,width as uByte,dataAddress as uInteger,Atr as Ubyte) putChars(x,y,height,width,dataAddress) putCharsAtr(x,y,height,width,Atr) END SUB '===================================== start: cls dim f as ubyte for f=1 to 19 step 4 putChAt(0+f,0,2,3,@gfx1a,11110011b) putChAt(0+f,2+f,3,9,@gfx1a,11100010b) putChAt(0+f,18,3,2,@gfx1a,11000110b) next END '---------------------------------------- gfx1a: ASM DEFB 8,8,8,8,8,8,8,8 DEFB 0,60,4,4,60,32,60,0 DEFB 0,60,4,4,60,4,60,0 DEFB 0,36,36,36,60,4,4,0 datapoint: defb 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32 defb 33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64 end asm '-----------------------------------------
Reply
#13
compiuter Wrote:Waiting for something better ...

And that would be....?

Just posting code doesn't tell me what's wrong with what you have...

What do you actually need it to do? I suspect you have some issue with attributes; but LCD hasn't mentioned what he wanted on that front either; so I'm a bit stuck for what additions or changes to make. If any.
Reply
#14
britlion Wrote:What do you actually need it to do? I suspect you have some issue with attributes; but LCD hasn't mentioned what he wanted on that front either; so I'm a bit stuck for what additions or changes to make. If any.

For 2x2 char I'm happy with your version BritLion as it is extremly fast. For 1x1 char I prefer to have two versions: One where you read 9 bytes inclusive chars, and one with 8 bytes, where the attribute byte is handed over in SUB call (PutChar(x,y,@adress,attribute))

Oh, I have a nice one for bigger blocks:
Code:
FUNCTION scrAddress(x as uByte, y as uByte) as Uinteger asm ;' This fn returns the address into HL of the screen address ;' x,y in character grid notation. ;' Original code was extracted by BloodBaz - Adapted for ZX BASiC by Britlion from Na_TH_AN's fourspriter ; x Arrives in A, y is in stack. and 31 ld l,a ld a,(IX+7) ; Y value ld d,a and 24 add a,64 ld h,a ld a,d and 7 rrca rrca rrca or l ld l,a end asm END FUNCTION FUNCTION attrAddress(x as uByte, y as uByte) as uInteger ';; This function returns the memory address of the Character Position ';; x,y in the attribute screen memory. ';; Adapted from code by Jonathan Cauldwell - Adapted for ZX BASiC by Britlion from Na_TH_AN's fourspriter asm ld a,(IX+7) ;ypos rrca rrca rrca ; Multiply by 32 ld l,a ; Pass to L and 3 ; Mask with 00000011 add a,88 ; 88 * 256 = 22528 - start of attributes. 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. end asm END FUNCTION sub putblock(x as Ubyte,y as ubyte,wid as ubyte,hgt as ubyte,adr as Uinteger) dim scr,attribute as Uinteger dim x1,y1 as Ubyte dim a as Ubyte poke uinteger @putblock1+7,wid poke uinteger @putblock2+7,wid for y1=0 to hgt-1 scr=scrAddress(x,y+y1) for a=0 to 7 poke uinteger @putblock1+1,adr poke uinteger @putblock1+4,scr putblock1: asm ld hl,1 ld de,2 ld bc,3 ldir end asm adr=adr+wid scr=scr+256 next a next y1 attribute=attrAddress(x,y) for y1=0 to hgt-1 poke uinteger @putblock2+1,adr poke uinteger @putblock2+4,attribute adr=adr+wid attribute=attribute+32 putblock2: asm ld hl,4 ld de,5 ld bc,6 ldir end asm next y1 End sub start: putblock(0,18,8,6,0) putblock(24,18,8,6,0) putblock(24,0,8,6,0) putblock(0,0,24,18,0) pause 0

The speed is much better than the one I coded ten years ago.
------------------------------------------------------------
http://lcd-one.da.ru redirector is dead
Visit my http://members.inode.at/838331/index.html home page!
Reply
#15
LCD Wrote:For 2x2 char I'm happy with your version BritLion as it is extremly fast. For 1x1 char I prefer to have two versions: One where you read 9 bytes inclusive chars, and one with 8 bytes, where the attribute byte is handed over in SUB call

You do realise that mine should be able to do anything from 1 character to a whole screen just by changing height and width (and making sure there's enough data at the address given!) ?

I'll see about tweaking it to accept attributes....

Do you need FLASH? It might be clever to assume you won't want to set a flashing attribute and have it assume that an attribute >128 (or negative) means that the attributes are in the data...
Reply


Forum Jump:


Users browsing this thread: 1 Guest(s)