Routines |
Prev: 247D | Up: Map | Next: 24FB |
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. | |
REPORT_B_3 | 24F9 | RST $08 | Call the error handling routine. | |
24FA | DEFB $0A |
Prev: 247D | Up: Map | Next: 24FB |