Plot function in z88dk

Any discussions related to the creation of new hardware or software for the ZX80 or ZX81
User avatar
Andy Rea
Posts: 1503
Joined: Fri May 09, 2008 2:48 pm
Location: notts UK

Re: Plot function in z88dk

Post by Andy Rea » Tue Feb 06, 2018 11:34 pm

here we go again new function added zx_point

int zx_point(short x, short y)

tests the point at x,y return 1 is set , 0 if unset

zx_plot altered somewhat but usage remains the same as before

common code used by both functions now reside in a third function that should not be called from C it contains 2 assembler subroutines used by the main function routines.

anyway see ow you go with that.

regards Andy

Code: Select all

// found at https://www.z88dk.org/forum/viewtopic.php?id=6271
// Contributors: swensont, siggi, Timmy, alvin

#include <stdio.h>
#include <zx81.h>

// alvin: "It's faster to pop them or use HL to walk the stack.  The best solution is 
// Timmy's which uses CALLEE linkage so that the subroutine can pop the parameters 
// off the stack and not put them back:


// ZX81 quarter block plot/unplot/xor-plot and point (test)
// routine in ASM BY A. Rea FEB 2018

// NO BOUNDS CHECK max X 0 to 63 max Y 0 to 47
// FOR STANDARD DISPLAY MODE ONLY
// ASSUMES D-FILE IS NOT COLLAPSED 


// test a quarter block point
// if set returns 1
// if unset returns 0
int __CALLEE__ zx_point(short x, short y)
{
 __asm

 POP HL   ; HL = return address
 POP BC   ; C  = y,  and  remove y from stack (necessary for CALLEE functions)
 EX (SP),HL
 LD  B,L  ; BC = XY

 CALL CALC_DFILE_ADD
 CALL GET_BLOCK

TEST_POINT:
 LD HL,0	
 AND	B
 RET Z
 INC HL
 RET
 
	__endasm
}

// zx_plot
// x is 0 to 63
// y is 0 to 47
// pmode is 0 = unplot, 1 = plot, 2 =xor plot

static void __CALLEE__ zx_plot( short x, short y, short pmode)
{
  __asm 
  POP HL   ; HL = return address
  POP DE   ; E  = plot mode
  POP BC   ; C  = y,  and  remove y from stack (necessary for CALLEE functions)
  EX (SP),HL
  LD  B,L  ; BC = XY
  PUSH DE  ; SAVE PMODE FOR LATER
  
  CALL CALC_DFILE_ADD

	;screen address now in HL

  CALL GET_BLOCK		;returns with the current screen char in A ( or zero if non block char at screen location and the quarter block for the point we wnat in B

        ; so at this point we have the screen char ( or zero if not a valif block graphic ) in A
        ; and the quarter block graphic in B, for plotting we OR B with A result in A
        ; for unplotting we complment ( invert )  B and then AND with A
	; for XOR plot we XOR B with A
	
	ld	C,a	;save for unplot.... 

	pop	de
	dec	e
	jr	z,do_plot
	dec	e
	jr	z,xor_plot
        
	;else unplot

do_unplot:
	LD A,B
	CPL
	AND	C
	jr	plot_done

xor_plot:
	xOR	B
	jr	plot_done


do_plot:
	OR	b

plot_done:
	CP	8
	JR	C,put_char
	XOR	$8F



put_char:
	LD	(HL),A



	



    ;; note the compiler automatically adds RET on closing '}' so this is not required
   __endasm;
}


/* the following function should not be called from C
   it is meant to be called directly from assembler */
/* THE FOLLOWING FUNCTION SHOULD NOT BE CALLED FROM C
	THE 2 ASSEMBLER ROUTINE ARE CALLED DIRECTLY 
	  FROM OTHER FUNCTIONS. */

static void plot_subs ()
{

	__asm
GET_BLOCK:
	LD      A,$01        
        SRA     C              
        JR      NC,EVEN_Y

        LD      A,$04


EVEN_Y: SRA     B          
        JR      NC,EVEN_X  

        RLCA			; 1 OR 4 BECOMES 2 OR 8                

EVEN_X:
	LD	B,A		;SAVE the new pixwl block in b

	LD 	A,(HL)		;GET BYTE FROM SCREEN
	RLCA
	CP	16
	JR	NC,A_ZERO
	RRCA
	JR	NC,GOOD_CHAR
	XOR	$8F		;ELSE INVERTED CHAR
	JR	GOOD_CHAR
A_ZERO:
	XOR	A
GOOD_CHAR:
	RET

CALC_DFILE_ADD:
	;WORK OUT SCREEN BYTE FROM CO-ORDS in BC = x/y
	LD	A,C			;GET CURRENT Y POSITION 0 TO 47
	SRL	A			;A = 0 TO 23
					
	LD	E,A			;E = 1 * A
	
	LD	D,0			;DE = 1 *  A
	ADD	A,A			;A = 2* ,	MAX = 46
	ADD	A,A			;A = 4 *  , MAX = 92
	ADD	A,A			;A = 8 * , MAX =184
	ADD	A,A			;A = 16 Y , MAX = 112 AND CARRY SET
	LD 	H,0			;NO EFFECT ON CARRY
	RL	H			;PICK UP ANY CARRY	
	LD	L,A
	ADD	HL,HL		;HL = 32 * Y
	ADD	HL,DE		;HL = 33 * Y
	
	
	
	LD	A,B			;GET X POSITION 
	SRL	A			;DIVIDE BY 2
	LD	E,A
	LD	D,0			
	ADD	HL,DE		;HL NOW = SCREEN OFFSET
	LD	DE,($400C)
	ADD	HL,DE		;HL NOW = CURRENT DFILE + OFFSET
	
	INC	HL			;COMPENSATE FOR 1ST HALT IN DFILE

	RET
	  __endasm;
}



main ( )
{

  short x,y;
 printf("plotting...\n\n\n\n"); 

   /* plot points */	
   zx_plot(5,10,1);
   zx_plot(15,20,1);
	printf("point 5,10 is %d\n",zx_point(5,10));
	printf("point 6,6 is %d\n",zx_point(6,6));
	printf("point 15,20 is %d\n",zx_point(15,20));
 
   
	
   for (x = 0; x <= 63; ++x)
   {
	zx_plot(x, 47,1);
	zx_plot(x, 0,1);
   }
   for (y = 1; y <= 47; ++y)
   {
	zx_plot(0, y,1);
	zx_plot(63, y,1);
   }

 for (x = 0; x <= 63; ++x)
   {
	zx_plot(x, 47,0);
	zx_plot(x, 0,0);
   }
   for (y = 1; y <= 47; ++y)
   {
	zx_plot(0, y,0);
	zx_plot(63, y,0);
   }
   printf("done.\n");

 for (y=1; y <= 47; ++y)
  {
    for (x=0; x<=63; x += y)
      {
         zx_plot (x,y,2);
         zx_plot (63-x, 47-y,2);
      }
   }

   
}


6 x ZX81, 1 x TS1500 , 1 x +3e, 1 x timex 2040 printer, 1 x timex 2020 cassette deck, siclair printer and some spectrum

User avatar
RobertK
Posts: 42
Joined: Tue Dec 19, 2017 4:29 pm
Location: Vienna

Re: Plot function in z88dk

Post by RobertK » Sun Feb 11, 2018 4:56 pm

The zx_point() function works great as well. Thank you so much, now I should have everything that I need.

BTW, the y axis of your functions is inverted (0 at the top) compared to the ZX Basic plot command (0 at the bottom).
Was this your intention? If not, then maybe it would be better to keep with the ZX Basic standard (although it's of course no big problem if this should have any technical reasons).

Another question: a Bresenham line function would be nice to have, but what is maybe more important: do you think that ASM functions to draw either a horizontal or vertical line would perform better than repeated zx_plot() calls in C for each point of the line?
If so, then zx_hline(x,y,length) and zx_vline(x,y,length) would be appropriate function names...

User avatar
RobertK
Posts: 42
Joined: Tue Dec 19, 2017 4:29 pm
Location: Vienna

Re: Plot function in z88dk

Post by RobertK » Sat Feb 17, 2018 8:59 pm

I have made a little Moon Patrol-style scrolling mountains demo using Andy's zxplot function.

zxplot_mountains.jpg
zxplot_mountains.jpg (1.62 KiB) Viewed 1043 times

It is still too slow to be used for anything useful, but it is unbelievably fast compared to if it had been made in ZX Basic...

It also still lacks double-buffering - I have seen in the source of the z8048 game that this can be made by moving the display memory start address back and forth. But this would probably require further modifications to Andy's functions.

@Andy, see my previous posting: a zx_vline() function could speed this up a little (not much, as the mountain line ranges within a height of only 5 pixels). Do you think that such a function could be done efficiently in ASM?
Attachments
zxplot_mountains_2018-02-17.zip
(5.08 KiB) Downloaded 29 times

User avatar
Andy Rea
Posts: 1503
Joined: Fri May 09, 2008 2:48 pm
Location: notts UK

Re: Plot function in z88dk

Post by Andy Rea » Sat Feb 17, 2018 9:35 pm

what you want there is 2 frame video buffer , 1 for odd x positions and 1 for even x positions then you only need to scroll everything left and update the last 2 quarter block columns, the LDIR block move should be quick enough for 3 character lines ( 6 block pixels) dont forget to make sure the newlines are not disturbed... or even do it a 3 lots of moves... leaving the newlines untouched... either way redrawing everything each frame is not really that practical i dont think

BTW that is rather impressive for a zx81, imagine how slow that would be in basic :lol:

regards Andy
6 x ZX81, 1 x TS1500 , 1 x +3e, 1 x timex 2040 printer, 1 x timex 2020 cassette deck, siclair printer and some spectrum

sirmorris
Posts: 2813
Joined: Thu May 08, 2008 5:45 pm

Re: Plot function in z88dk

Post by sirmorris » Sat Feb 17, 2018 10:29 pm

Games don't PLOT. Just sayin' ;)

User avatar
RobertK
Posts: 42
Joined: Tue Dec 19, 2017 4:29 pm
Location: Vienna

Re: Plot function in z88dk

Post by RobertK » Sun Feb 18, 2018 11:23 am

sirmorris wrote:
Sat Feb 17, 2018 10:29 pm
Games don't PLOT. Just sayin' ;)
But maybe a game could first plot and then scroll. :D

If anyone wants to turn my "simple full-plot scrolling" demo into real scrolling as described by Andy: go for it!

User avatar
siggi
Posts: 875
Joined: Thu May 08, 2008 9:30 am
Location: Dauernheim, Germany
Contact:

Re: Plot function in z88dk

Post by siggi » Sun Feb 18, 2018 11:30 am

sirmorris wrote:
Sat Feb 17, 2018 10:29 pm
Games don't PLOT. Just sayin' ;)
But my game "AUTORENNEN" does it:
autorenn.p
(5.65 KiB) Downloaded 29 times
:mrgreen:
Siggi
My ZX81 web-server: online since 2007
http://zx81-siggi.endoftheinternet.org/index.html

User avatar
Andy Rea
Posts: 1503
Joined: Fri May 09, 2008 2:48 pm
Location: notts UK

Re: Plot function in z88dk

Post by Andy Rea » Sun Feb 18, 2018 3:03 pm

Tron trails does a bit of plotting.. .
6 x ZX81, 1 x TS1500 , 1 x +3e, 1 x timex 2040 printer, 1 x timex 2020 cassette deck, siclair printer and some spectrum

sirmorris
Posts: 2813
Joined: Thu May 08, 2008 5:45 pm

Re: Plot function in z88dk

Post by sirmorris » Sun Feb 18, 2018 5:19 pm

OH ALL RIGHT ALL RIGHT so games _do_ PLOT :P :lol:

User avatar
siggi
Posts: 875
Joined: Thu May 08, 2008 9:30 am
Location: Dauernheim, Germany
Contact:

Re: Plot function in z88dk

Post by siggi » Mon Feb 26, 2018 12:37 pm

My ZX81 web-server: online since 2007
http://zx81-siggi.endoftheinternet.org/index.html

Post Reply