Routines |
Prev: 09341 | Up: Map | Next: 09467 |
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 | 09399 | CALL STK_TO_BC | ABS Y to B; ABS X to C; SGN Y to D; SGN X to E. | |
09402 | 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. | ||
09403 | CP B | |||
09404 | JR NC,DL_X_GE_Y | |||
09406 | LD L,C | |||
09407 | PUSH DE | Save diagonal step (+/-1,+/-1) in DE. | ||
09408 | XOR A | Insert a vertical step (+/-1,0) into DE (D holds SGN Y). | ||
09409 | LD E,A | |||
09410 | JR DL_LARGER | Now jump to set H. | ||
DL_X_GE_Y | 09412 | OR C | Return if ABS X and ABS Y are both zero. | |
09413 | RET Z | |||
09414 | LD L,B | The smaller (ABS Y here) goes to L. | ||
09415 | LD B,C | ABS X to B here, for H. | ||
09416 | PUSH DE | Save the diagonal step here too. | ||
09417 | LD D,0 | Horizontal step (0,+/-1) to DE here. | ||
DL_LARGER | 09419 | 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.
|
||||
09420 | LD A,B | B to A as well as to H. | ||
09421 | RRA | A starts at INT (H/2). | ||
D_L_LOOP | 09422 | ADD A,L | L is added to A. | |
09423 | JR C,D_L_DIAG | If 256 or more, jump - diagonal step. | ||
09425 | CP H | If A is less than H, jump for horizontal or vertical step. | ||
09426 | JR C,D_L_HR_VT | |||
D_L_DIAG | 09428 | SUB H | Reduce A by H. | |
09429 | LD C,A | Restore it to C. | ||
09430 | EXX | Now use the exchange resisters. | ||
09431 | POP BC | Diagonal step to BC'. | ||
09432 | PUSH BC | Save it too. | ||
09433 | JR D_L_STEP | Jump to take the step. | ||
D_L_HR_VT | 09435 | LD C,A | Save A (unreduced) in C. | |
09436 | PUSH DE | Step to stack briefly. | ||
09437 | EXX | Get exchange registers. | ||
09438 | POP BC | Step to BC' now. | ||
D_L_STEP | 09439 | LD HL,(23677) | Now take the step: first, COORDS to HL' as the start point. | |
09442 | LD A,B | Y-step from B' to A. | ||
09443 | ADD A,H | Add in H'. | ||
09444 | LD B,A | Result to B'. | ||
09445 | LD A,C | Now the X-step; it will be tested for range (Y will be tested in PLOT). | ||
09446 | INC A | |||
09447 | ADD A,L | Add L' to C' in A, jump on carry for further test. | ||
09448 | JR C,D_L_RANGE | |||
09450 | JR Z,REPORT_B_3 | Zero after no carry denotes X-position -1, out of range. | ||
D_L_PLOT | 09452 | DEC A | Restore true value to A. | |
09453 | LD C,A | Value to C' for plotting. | ||
09454 | CALL PLOT_SUB | Plot the step. | ||
09457 | EXX | Restore main registers. | ||
09458 | LD A,C | C back to A to continue algorithm. | ||
09459 | DJNZ D_L_LOOP | Loop back for B steps (i.e. H steps). | ||
09461 | POP DE | Clear machine stack. | ||
09462 | RET | Finished. | ||
D_L_RANGE | 09463 | JR Z,D_L_PLOT | Zero after carry denotes X-position 255, in range. | |
REPORT_B_3 | 09465 | RST 8 | Call the error handling routine. | |
09466 | DEFB 10 |
Prev: 09341 | Up: Map | Next: 09467 |