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);
}
}
}