Prev: 09341 Up: Map Next: 09467
09399: 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 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.
This entry point is used by the routines at PIXEL_ADD and STK_TO_A.
Report B - Integer out of range.
REPORT_B_3 09465 RST 8 Call the error handling routine.
09466 DEFB 10
Prev: 09341 Up: Map Next: 09467