Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Screen handling
#1
This is interesting. There's quite a lot of overhead in PLOT, I think - this is fairly unoptimized, still - and appears to be a little buggy. It also doesn't use the screen tables lookup yet. But it's late and I need to go to bed Smile

Code:
SUB plotPoint (x as uByte, y as uByte)
ASM
ld d,(IX+5) ;'X
ld e,(IX+7) ;'Y

    ld a, 191
    sub e    
    ret c    
    ld e, a    
    and a    
    
    rra        
    scf        
    rra        
    and a    
    rra        
    xor e            
    and 248
    xor e
    ld h, a
    ld a, d
    rlca
    rlca
    rlca
    xor e
    and 199
    xor e
    rlca
    rlca
    ld l, a
    
    ld a, d
    and 7
    ld b, a
    inc b
    ld a, 1
    
    plotPoint_loop:
        rrca
    djnz plotPoint_loop    
    ;cpl
    ld b, a    
    ld a, (hl)
    or b    
    ld (hl), a
    
END ASM
END SUB

FUNCTION t() as uLong
asm
    DI
    LD DE,(23674)
    LD D,0
    LD HL,(23672)
    EI
end asm
end function


dim time0, time1, time2 as long
dim n as uInteger

cls

for n=1 to 150
plotPoint(n,n-1)
plot n,n+3
next n


time0=t()
for n=0 to 50000
plot 50,50
next n

time1=t()
for n=0 to 50000
plotPoint(50,50)
next n

time2=t()

print "ZX Basic 50,000 plot:"
print time1-time0;"frames =";(time1-time0)/cast(float,50);" seconds"
print
print "plotPoint 50,000 times:"
print time2-time1;"frames=";(time2-time1)/cast(float,50);" seconds"
Reply
#2
nice, i got 11 secs for zxbasic and 7 secs for your function

I cant seem to get any colour of dots except black

Code:
SUB plotPoint (x as uByte, y as uByte)
ASM
ld d,(IX+5) ;'X
ld e,(IX+7) ;'Y

    ld a, 191
   sub e  
   ret c  
   ld e, a  
   and a  
  
    rra      
   scf      
   rra      
   and a  
   rra      
   xor e        
   and 248
   xor e
   ld h, a
   ld a, d
   rlca
   rlca
   rlca
   xor e
   and 199
   xor e
   rlca
   rlca
   ld l, a
  
    ld a, d
   and 7
   ld b, a
   inc b
   ld a, 1
  
    plotPoint_loop:
        rrca
   djnz plotPoint_loop  
   ;cpl
    ld b, a  
   ld a, (hl)
   or b  
   ld (hl), a
  
END ASM
END SUB

FUNCTION t() as uLong
asm
    DI
    LD DE,(23674)
    LD D,0
    LD HL,(23672)
    EI
end asm
end function


dim time0, time1, time2 as long
dim n as uInteger

cls

for n=1 to 150
plotPoint(n,n-1)
plot n,n+3
next n



time0=t()

Paper 5
INK 2
for n=0 to 191
for y=0 to 191

plotPoint(n,y)
next y
next n
time1=t()


Paper 3
INK 4
for n=0 to 191
for y=0 to 191
plot y,n
next y
next n
time2=t()

print "plotpoint 50,000 plot:"
print time1-time0;"frames =";(time1-time0)/cast(float,50);" seconds"
print
print "zxbasic 50,000 times:"
print time2-time1;"frames=";(time2-time1)/cast(float,50);" seconds"

On the second pass only the green paper shows up
Reply
#3
You know, looking at this, I'm particularly impressed with this bit:

Code:
    
        rra        
    scf        
    rra        
    and a    
    rra        
    

        xor e            
    and 248
    xor e

As we know, the bit pattern for a screen address is 010LLrrr LLLCCCCC - where L = character line number (0-31), r=row in character. C=column.

This rotates in the 010, and slides over the two first line bits LL.

Then it does something really clever. It puts in the last 3 bits from the original, left in e. I'd have probably done something like:

Code:
RRCA
RRCA
RRCA
AND %010110000
ld d,a
ld a,e
and 7
or d

Which is far more faffing. XOR/AND/XOR. How cool is that for three instructions to merge some bits of one register with another? New trick learned.
Reply
#4
slenkar Wrote:nice, i got 11 secs for zxbasic and 7 secs for your function
ZX Basic uses ROMs PLOT (which is already somewhat optimized, BTW!), but uses a different entry point, to allow 192 scanlines.
On the other hand, DRAW has already been optimized and no longer uses PLOT, but PIXELADDR for the 1st point of a scan line (remaining points are computed relatively to the last plotted dot).

Also, keep en mind that ZX Basic/ROM PLOT routine also updates ATTR according to TEMP ATTRs and also take into account the SCREEN_ADDR variable (so you can draw/print in another memory/region like a temporary buffer).
Reply
#5
slenkar Wrote:nice, i got 11 secs for zxbasic and 7 secs for your function

I cant seem to get any colour of dots except black


On the second pass only the green paper shows up

The routine, as it stands, just sets the ink point on - it doesn't touch attributes, change the current plot values or any such thing - it's optimized to get that point changed, and do nothing else. Slenkar - if you did a CLS after setting ink and paper values, you'd get what you were looking for, since that would change all the attribute data on the screen for you.

As Boriel points out, the standard plot routine also changes the attribute value and does some housekeeping in the background. That said, it's pretty rare that a draw needs to do this, since the effect is usually terrible. I can't think of any games that would require it - usually all the attribs in the game area are set already.

It might be reasonable to set up a fastplot and fastdraw routine for games purposes, that don't do the overhead. If so, it would be a plot similar to this, an absolute draw (from x1,y1 to x2,y2 - no relative movement), and routines to change the ink and paper in an area block - which would go with the clearblock routine.

The reason for not using relative draw is if you were working with a vector game, you'd generate the vertices explicitly, so a draw from vertex point 1 to vertex point 2 is probably more useful.
Reply
#6
Code:
SUB plotPoint (x as uByte, y as uByte)
ASM

ld d,a ;'X

    ld a, 191
    sub (IX+7) ;' y
    jr c, plotPoint_end    
    ld l,a    

ld h,ScreenTables/256
ld a,(HL)
inc h
ld l,(HL)
ld h,a
; now we're on the right row on screen.

ld a,d
RRCA  ; divide column by 8 for bytes.
RRCA
RRCA
AND 31
add a,l
ld l,a
    
    ld a, d
    and 7
    ld b, a
    inc b
    ld a, 1
    
    plotPoint_loop:
        rrca
    djnz plotPoint_loop    
    ld b, a    
    ld a, (hl)
    or b    
    ld (hl), a

plotPoint_end:
    
END ASM
END SUB

Using screen address tables shaves this down to 6.42 seconds for 50,000 points plotted. That's not too bad, all told.
(screentables.asm is available elsewhere in the forum, I promise!)

Considering that quite a few routines can use the screen lookup tables, 512 bytes of screen tables isn't crazy for a solid speedup (and of course, if you are using a shadow screen, then you could either rewrite a bit, or make screen tables that point to your shadow screen memory).

Not sure requiring rotate tables, which is much bigger, is a win, here for one loop removal.
Reply
#7
ive never required any color dots than black anyway i suppose,
the zxbasic plot doesnt seem to draw colored dots either I dont think.

those lookup tables really seem worth using
Reply
#8
Uncontended Memory: ZXBC Plot: 11 Sec. Britlions FastPlot: 7.7 sec
Contended Memory: ZXBC Plot: 12.1 Sec. Britlions FastPlot: 9.1 sec
Impressive!!!
------------------------------------------------------------
http://lcd-one.da.ru redirector is dead
Visit my http://members.inode.at/838331/index.html home page!
Reply
#9
slenkar Wrote:ive never required any color dots than black anyway i suppose,
the zxbasic plot doesnt seem to draw colored dots either I dont think.

those lookup tables really seem worth using
It does (otherwise, it would be a bug). ZXBC tries to mimic Sinclair BASIC command as much as possible while trying not to increase the overhead.
BTW impressive measures!
Reply
#10
Slenkar: Perhaps these are useful for setting colours?

They both paint a rectangle in the specified colours - one needs ink/paper/bright/flash separately, the second takes the attribute byte directly.

Code:
SUB WindowPaint(x as uByte,y as uByte, width as uByte, height as uByte, inkCol as ubyte, paperCol as uByte, isBright as uByte, isFlash as uByte)
paint(x,y,width,height,(isFlash<<7+isBright<<6+paperCol<<3+inkCol))
END 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
Reply


Forum Jump:


Users browsing this thread: 2 Guest(s)