![]() |
Routines |
Prev: 09341 | Up: Map |
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 |