FAQ  •  Register  •  Login

BritLion's Putchars

<<

britlion

Posts: 766

Joined: Mon Apr 27, 2009 7:26 pm

Location: Slough, Berkshire, UK

Post Fri Jun 04, 2010 5:35 pm

BritLion's Putchars

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)


Last edited by britlion on Thu Jun 17, 2010 3:18 pm, edited 9 times in total.
<<

britlion

Posts: 766

Joined: Mon Apr 27, 2009 7:26 pm

Location: Slough, Berkshire, UK

Post Fri Jun 04, 2010 6:03 pm

Re: BritLion's Putchars - Speed Test

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


Last edited by britlion on Fri Jun 18, 2010 4:55 am, edited 7 times in total.
<<

compiuter

Posts: 51

Joined: Mon May 10, 2010 10:47 pm

Post Fri Jun 04, 2010 8:04 pm

Re: BritLion's Putchars

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.
<<

boriel

Site Admin

Posts: 1463

Joined: Wed Nov 01, 2006 6:18 pm

Location: Santa Cruz de Tenerife, Spain

Post Fri Jun 04, 2010 8:16 pm

Re: BritLion's Putchars

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>
<<

compiuter

Posts: 51

Joined: Mon May 10, 2010 10:47 pm

Post Fri Jun 04, 2010 8:27 pm

Re: BritLion's Putchars

Ok, thx,I try tomorrow.
<<

britlion

Posts: 766

Joined: Mon Apr 27, 2009 7:26 pm

Location: Slough, Berkshire, UK

Post Fri Jun 04, 2010 9:00 pm

Re: BritLion's Putchars

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.
<<

LCD

Posts: 596

Joined: Fri Feb 13, 2009 3:11 pm

Location: Vienna, Austria

Post Sat Jun 05, 2010 12:40 pm

Re: BritLion's Putchars

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!
<<

britlion

Posts: 766

Joined: Mon Apr 27, 2009 7:26 pm

Location: Slough, Berkshire, UK

Post Sat Jun 05, 2010 1:01 pm

Re: BritLion's Putchars

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.
<<

compiuter

Posts: 51

Joined: Mon May 10, 2010 10:47 pm

Post Sat Jun 05, 2010 2:22 pm

Re: BritLion's Putchars

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"

<<

britlion

Posts: 766

Joined: Mon Apr 27, 2009 7:26 pm

Location: Slough, Berkshire, UK

Post Sun Jun 06, 2010 5:05 am

Re: BritLion's Putchars

I will have to look into this. Thanks for spotting bugs!
<<

britlion

Posts: 766

Joined: Mon Apr 27, 2009 7:26 pm

Location: Slough, Berkshire, UK

Post Sun Jun 06, 2010 5:30 pm

Re: BritLion's Putchars

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!
<<

compiuter

Posts: 51

Joined: Mon May 10, 2010 10:47 pm

Post Sun Jun 06, 2010 9:52 pm

Re: BritLion's Putchars

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
'-----------------------------------------
Last edited by compiuter on Wed Jun 09, 2010 11:15 pm, edited 1 time in total.
<<

britlion

Posts: 766

Joined: Mon Apr 27, 2009 7:26 pm

Location: Slough, Berkshire, UK

Post Sun Jun 06, 2010 10:05 pm

Re: BritLion's Putchars

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.
<<

LCD

Posts: 596

Joined: Fri Feb 13, 2009 3:11 pm

Location: Vienna, Austria

Post Mon Jun 07, 2010 12:19 am

Re: BritLion's Putchars

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!
<<

britlion

Posts: 766

Joined: Mon Apr 27, 2009 7:26 pm

Location: Slough, Berkshire, UK

Post Mon Jun 07, 2010 1:21 am

Re: BritLion's Putchars

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...
Next

Return to How-To & Tutorials

Who is online

Users browsing this forum: No registered users and 1 guest

cron
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group.
Designed by Vjacheslav Trushkin for Free Forums/DivisionCore.

phpBB SEO