| Routines

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