Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
A Fast(er) Plot Routine for Boriel Basic
#1
I orginally posted this on SpectrumComputing Forum - copied here in case anyone wants to play with it :-)

Hi

Hope this helps someone else :-)

I saw a post by Andy Dansby who writes at https://zxspectrumcoding.wordpress.com/

He has created a fast plot routine, (hellaplot), so I thought I'd try and convert it to a Boriel Basic (BB) subroutine, just for fun and learning - and as it was a single routine.

I had to do a little bit of reading, but also had to ask for help from the BB telegram community, as to begin with the code was crashing the emulator. Turns out it was a simple fix when you know how - FASTCALL was needed when passing parameters for ASM to use from a SUB routine.

Andy's code needs the x/y locations in DE, so I had to do a little bit to get them set up like this - I assume there might be some more efficiency if different registers were used as BB passes from the subroutine call, the first parameter into A, and the second parameter is the second item on the stack (the first being the return address).

When I started, xPos was the first parameter, and yPos the second (as I like x,y), but this meant to get them into DE, took another load (POP DE, LD E with D, LD D with A, compared to POP DE, LD E with A)

So some "non exact" timings - plot included as the library in BB takes about 15 seconds to fill up the screen with "points". Andy's one takes 5 seconds to do the same.

As far as Andy's code goes, I understand the comments, but not exactly how it works :-)

Anyway, code below :

SUB FASTCALL HellaPrint(yPos as UBYTE, xPos as UBYTE)
' HellaPrint prints an x,y pixel
' 0,0 is top left
' Original code by Andy Lansby
' https://zxspectrumcoding.wordpress.com/
' yPos is first, as it save a LD instruction when putting xPos and yPos into DE
ASM

JP START ; Put this in as it's like this on the Wiki ASM desciption - can it be avoided?
X_PositionBits: defb 128,64,32,16,8,4,2,1
; Might there be a quicker way to do the above, so it's not needed every time the program is run? or does it not work like this and is created once at compile time?

START: ; plot d = x-axis, e = y-axis
; A contains the yPos, xPos is on stack.
POP HL ; Pops the return address into HL
POP DE ; xPos is on the stack, and it needs to be in D
LD E, A ; A has our first paramter (yPos), load it into E. D should be Xpos, E should be yPos
PUSH HL ; Puts the return address back onto stack ...
; 166 T states per pixel
XOR A ; reset A to 0 and flags to default
LD A,E ; load Y plot point
RRA ; rotate Right --- divide in half
SCF ; turn on Carry flag-
RRA ; rotate right with the carry flag
OR A ; set flag S on - C flag off
RRA ; rotate Right --- divide in half

LD L,A ; temp store in L
XOR E ; XOR the Y value
AND %11111000 ; mask out bottom 3 bits
XOR E ; XOR the Y value

LD H,A ; store High byte
LD A,D ; load X plot point
XOR L ; XOR the temp value
AND %00000111 ; mask out unwanted bits
XOR D ; XOR the X value
RRCA ; divide by 2
RRCA ; divide by 4
RRCA ; divide by 8

LD L,A ; store Low byte
; now we have the full address
; now use LUT to find which bit to set
LD A,D ; load X plot point
AND %00000111 ; mask out unwanted bits

; use a LUT to quickly find the bit position for the X position
LD DE,X_PositionBits ; load LUT address into DE
ADD A,E ; Add A to E to get offset into table
LD E,A ; E now points to the LUT entry
LD A,(DE) ; load answer into A

; output to screen
OR (HL) ; or with contents of address HL
LD (HL),A ; load address HL with Answer from A
END ASM
END SUB
Reply


Forum Jump:


Users browsing this thread: 2 Guest(s)