here you go straight out of the notepad..... zx_plot and zx_unplot and another question or problem for someone more familiar with z88DK for zx81
i tried to expand the number of parameters passed to the function to allow a plotmode param however it just kept crashing the zx81, as you'll see much of the code for plot and unplot is the same so it is a little stupid to have 2 functions ...
any way... its pretty fast... NO BOUNDS CHECK and only works in standard text display mode with a FULL d-file.
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:
static void __CALLEE__ zx_plot( 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
CALC_DFILE_BYTE:
;WORK OUT SCREEN BYTE FROM CO-ORDS
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
;screen address now in HL
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 C,A ;SAVE A FOR NOW
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:
OR C
CP 8
JR C,LAST_BIT
XOR $8F
LAST_BIT:
LD (HL),A
RET ;; note the compiler automatically adds RET on closing '}' so this is not required
__endasm;
}
static void __CALLEE__ zx_unplot( 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
UN_CALC_DFILE_BYTE:
;WORK OUT SCREEN BYTE FROM CO-ORDS
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
;screen address now in HL
LD A,$01
SRA C
JR NC,UN_EVEN_Y
LD A,$04
UN_EVEN_Y: SRA B
JR NC,UN_EVEN_X
RLCA ; 1 OR 4 BECOMES 2 OR 8
UN_EVEN_X:
LD C,A ;SAVE A FOR NOW
LD A,(HL) ;GET BYTE FROM SCREEN
RLCA
CP 16
JR NC,UN_A_ZERO
RRCA
JR NC,UN_GOOD_CHAR
XOR $8F ;ELSE INVERTED CHAR
JR UN_GOOD_CHAR
UN_A_ZERO:
XOR A
UN_GOOD_CHAR:
LD B,A
LD A,C
CPL
AND B
CP 8
JR C,UN_LAST_BIT
XOR $8F
UN_LAST_BIT:
LD (HL),A
RET ;; note the compiler automatically adds RET on closing '}' so this is not required
__endasm;
}
main ( )
{
short x,y;
printf("plotting...\n\n");
/* plot points */
zx_plot(5,10);
zx_plot(15,20);
/* draw a border around the screen */
for (x = 0; x <= 63; ++x)
{
zx_plot(x, 47);
zx_plot(x, 0);
}
for (y = 1; y <= 47; ++y)
{
zx_plot(0, y);
zx_plot(63, y);
}
for (x = 0; x <= 63; ++x)
{
zx_unplot(x, 47);
zx_unplot(x, 0);
}
for (y = 1; y <= 47; ++y)
{
zx_unplot(0, y);
zx_unplot(63, y);
}
printf("done.\n");
for (y=1; y <= 47; ++y)
{
for (x=0; x<=63; x += y)
{
zx_plot (x,y);
zx_plot ((63-x), (47-y));
}
}
}