Prev: 247D Up: Map Next: 24FB
24B7: THE 'LINE-DRAWING' SUBROUTINE
This subroutine is called by DRAW to draw an approximation to a straight line from the point X0, Y0 held in COORDS to the point X0+X, Y0+Y, where the increments X and Y are on the top of the calculator stack. The subroutine was originally intended for the ZX80 and ZX81 8K ROM, and it is described in a BASIC program on page 121 of the ZX81 manual.
The method is to intersperse as many horizontal or vertical steps as are needed among a basic set of diagonal steps, using an algorithm that spaces the horizontal or vertical steps as evenly as possible.
DRAW_LINE 24B7 CALL STK_TO_BC ABS Y to B; ABS X to C; SGN Y to D; SGN X to E.
24BA LD A,C Jump if ABS X is greater than or equal to ABS Y, so that the smaller goes to L, and the larger (later) goes to H.
24BB CP B
24BC JR NC,DL_X_GE_Y
24BE LD L,C
24BF PUSH DE Save diagonal step (+/-1,+/-1) in DE.
24C0 XOR A Insert a vertical step (+/-1,0) into DE (D holds SGN Y).
24C1 LD E,A
24C2 JR DL_LARGER Now jump to set H.
DL_X_GE_Y 24C4 OR C Return if ABS X and ABS Y are both zero.
24C5 RET Z
24C6 LD L,B The smaller (ABS Y here) goes to L.
24C7 LD B,C ABS X to B here, for H.
24C8 PUSH DE Save the diagonal step here too.
24C9 LD D,$00 Horizontal step (0,+/-1) to DE here.
DL_LARGER 24CB LD H,B Larger of ABS X, ABS Y to H now.
The algorithm starts here. The larger of ABS X and ABS Y, say H, is put into A and reduced to INT (H/2). The H-L horizontal or vertical steps and L diagonal steps are taken (where L is the smaller of ABS X and ABS Y) in this way: L is added to A; if A now equals or exceeds H, it is reduced by H and a diagonal step is taken; otherwise a horizontal or vertical step is taken. This is repeated H times (B also holds H). Note that meanwhile the exchange registers H' and L' are used to hold COORDS.
24CC LD A,B B to A as well as to H.
24CD RRA A starts at INT (H/2).
D_L_LOOP 24CE ADD A,L L is added to A.
24CF JR C,D_L_DIAG If 256 or more, jump - diagonal step.
24D1 CP H If A is less than H, jump for horizontal or vertical step.
24D2 JR C,D_L_HR_VT
D_L_DIAG 24D4 SUB H Reduce A by H.
24D5 LD C,A Restore it to C.
24D6 EXX Now use the exchange resisters.
24D7 POP BC Diagonal step to BC'.
24D8 PUSH BC Save it too.
24D9 JR D_L_STEP Jump to take the step.
D_L_HR_VT 24DB LD C,A Save A (unreduced) in C.
24DC PUSH DE Step to stack briefly.
24DD EXX Get exchange registers.
24DE POP BC Step to BC' now.
D_L_STEP 24DF LD HL,($5C7D) Now take the step: first, COORDS to HL' as the start point.
24E2 LD A,B Y-step from B' to A.
24E3 ADD A,H Add in H'.
24E4 LD B,A Result to B'.
24E5 LD A,C Now the X-step; it will be tested for range (Y will be tested in PLOT).
24E6 INC A
24E7 ADD A,L Add L' to C' in A, jump on carry for further test.
24E8 JR C,D_L_RANGE
24EA JR Z,REPORT_B_3 Zero after no carry denotes X-position -1, out of range.
D_L_PLOT 24EC DEC A Restore true value to A.
24ED LD C,A Value to C' for plotting.
24EE CALL PLOT_SUB Plot the step.
24F1 EXX Restore main registers.
24F2 LD A,C C back to A to continue algorithm.
24F3 DJNZ D_L_LOOP Loop back for B steps (i.e. H steps).
24F5 POP DE Clear machine stack.
24F6 RET Finished.
D_L_RANGE 24F7 JR Z,D_L_PLOT Zero after carry denotes X-position 255, in range.
This entry point is used by the routines at PIXEL_ADD and STK_TO_A.
Report B - Integer out of range.
REPORT_B_3 24F9 RST $08 Call the error handling routine.
24FA DEFB $0A
Prev: 247D Up: Map Next: 24FB