; -------------------------------------------------------------------------
; Spherical Objects Z80 Source Code
; Program published in Popular Computing Weekly 
; Date: October 1986
; Author: Geoffrey Wearmouth
; -------------------------------------------------------------------------

.org $6787

; This routine copies the 6K source screen above RAMTOP
; It is located at 26476.

L6787:  LD      HL,$4000
        LD      DE,$6800
        LD      BC,$1800
        LDIR    
        RET     

; This is the main routine at 26488
; I've named it DEFORM in this revision.
; The second byte is poked in by the BASIC program.

DEFORM  LD      A,$51			; Load accumulator with radius
        CALL    $2D28  			; ROM routine STACK-A

        RST     28H			; R.
	.byte $A2 ;; stk-half		; R, .5 
	.byte $03 ;; subtract		; R - .5 = r
	.byte $C5 ;; st-mem-05		; r.

CLOOP	.byte $A0 ;; stk-zero		; y, 0.
	.byte $C4 ;; st-mem-04		; y, 0.
	.byte $02 ;; delete		; y.

      	.byte $1B ;; negate		; y. Pass1 -ve, pass2 +ve.
	.byte $31 ;; duplicate		; y, y.
	.byte $34 ;; stk-data
	.byte $37 ;; Exponent: $87,
          	  ;; Bytes:  1
	.byte $2F ;; (+00, +00, +00)    ; y, y, 87.5.

; 87.5 is the centre of the Y axis

	.byte $0F ;; addition		; y, y+87.5.
	.byte $38 ;; end-calc		; y, y+87.5.

L67A6   CALL $2DD5 ; FP-TO-A		; y.

        LD      (IY+$70),A 		; Store Y coord. in MEM-4 5th

        LD      A,($5C08)  		; Check LAST-K for last key.
      	CP	$20			; Has space been pressed ?
        JP	Z,$16C5 		; Exit if so, to BASIC via SET-STK

        RST     28H			; y.
	.byte $31 ;; duplicate		; y, y.
	.byte $31 ;; duplicate		; y, y, y.
	.byte $E5 ;; get-mem-05		; y, y, y, r. 
	.byte $05 ;; division		; y, y, y/r.
	.byte $22 ;; asn		; y, y, angle.
	.byte $A3 ;; stk-pi/2		; y, y, angle, rightangle.
	.byte $05 ;; division 		; y, y, fraction =f. 
	.byte $A1 ;; stk-one		; y, y, f, 1.
	.byte $0F ;; addition		; y, y, f+1.
	.byte $34 ;; stk-data
	.byte $37 ;; Exponent: $87,
        	  ;; Bytes:  1
	.byte $2F ;; (+00, +00, +00)  	; y, y, f+1, 87.5
	.byte $04 ;; multiply		; y, y. Y.

; We now have Y - the value of the source line. Bring back y - the plot 
; offset and use it to calculate the radius of the plot line x by 
; Pythagoras.

	.byte $01 ;; exchange 		; y, Y, y.
	.byte $31 ;; duplicate 		; y, Y, y, y.
	.byte $04 ;; multiply		; y, Y, y*y.
	.byte $E5 ;; get-mem-05 	; y, Y, y*y, r.
	.byte $31 ;; duplicate		; y, Y, y*y, r, r.
	.byte $04 ;; multiply		; y, Y, y*y, r*r.
	.byte $01 ;; exchange		; y, Y, r*r, y*y.
	.byte $03 ;; subtract		; y, Y. r*r - y*y.
	.byte $28 ;; sqr 		; y, Y, x.
	.byte $C3 ;; st-mem-03		; y, Y, x.
	.byte $02 ;; delete 		; y, Y.
	.byte $38 ;; end-calc		; y, Y.

L67CE   CALL $2DD5  ; FP-TO-A		; y.
        LD      C,B			; Load C (x) with zero screen left.
        LD      B,A			; Load B with Y.

        CALL    $22AA 			; ROM routine PIXEL-ADD

        LD      A,$28			; Offset to second screen
        ADD     A,H			; Add to high byte of address
        LD      H,A			; Now HL addresses source line.

        LD      B,$20			; For thirty two screen bytes.

L67DC   PUSH    BC			; Preserve the byte counter.
        LD      B,$08			; For eight bits within byte.

L67DF   PUSH    BC			; Preserve the bit counter.
        RLC     (HL)			; Spin a bit into carry.
        JR      NC,L67FE         	; If pixel not set then forward.

        PUSH    HL			; Preserve source screen address.

        RST     28H			; y.
	.byte $34 ;; stk-data
	.byte $37 ;; Exponent: $87,
        	  ;; Bytes:  1
	.byte $7F ;; (+00, +00, +00)  	; y, 127.5
	.byte $31 ;; duplicate		; y, 127.5, 127.5.
	.byte $E4 ;; get-mem-04		; y, 127.5, 127.5, 0-255.
	.byte $01 ;; exchange		; y, 127.5, 0-255, 127.5.
	.byte $05 ;; division		; y, 127.5, 0-2.
	.byte $A3 ;; stk-pi/2		; y, 127.5, 0-2, pi/2.
	.byte $04 ;; multiply		; y, 127.5, 0-pi. 
	.byte $20 ;; cos		; y, 127.5, x-fraction
	.byte $E3 ;; get-mem-03		; y, 127.5, x-fraction, x-radius
	.byte $04 ;; multiply		; y, 127.5, x-offset.
	.byte $03 ;; subtract		; y, x-coord.
	.byte $38 ;; end-calc		; y, x-coord (plot)

L67F4   CALL $2DA2 			; FP-TO-BC
        LD      B,(IY+$70) 		; MEM-4 5th  (y-coord)
        CALL    $22E9  			; PLOT-SUB + 5

        POP     HL			; Retrieve source screen address.

; In all cases increment the source X value

L67FE   INC     (IY+$6E) 		; MEM-4 3rd

        POP     BC		 	; Retrieve the 8 counter.
        DJNZ    L67DF            	; Repeat for all eight bits

        INC     L			; Increment screen address.

        POP     BC		 	; Retrieve the 32 counter.
        DJNZ    L67DC            	; Repeat for all thirty two bytes

        RST     28H			; y.
	.byte $31 ;; duplicate		; y, y.
	.byte $36 ;; less-0		; y, (0/1)
	.byte $00 ;; jump-true		; y.
	.byte CLOOP - $			; Back for a positive run.

	.byte $A1 ;; stk-one		; y, 1.
	.byte $03 ;; subtract		; y-1 = new y.
	.byte $31 ;; duplicate		; y, y.
	.byte $37 ;; greater-0		; y, (0/1)
	.byte $00 ;; jump-true		; y.
	.byte CLOOP - $			; loop back until negative.

	.byte $02 ;; delete		; . 
	.byte $38 ;; end-calc		; . (flat)

L6815   RET				; Return to BASIC

.end

; -------------------------------------------------------------------------
; NOTES
; -----
; The Spectrum Interrupt routine keeps the System Variable LAST-K holding 
; the value of the last key pressed. We look for the SPACE key to quit.
;
; The Spectrum has an internal stack-based language that has been likened 
; to FORTH. 
; It is entered using RST 28H. 
; While it normal to have a value on the floating point stack already, data 
; can be added from within the Calculator as a limited range of constants 
; or, by using following bytes with trailing zeroes removed, as any number. 
; 
; The following ROM routines are used.
; 
; $2D28 STACK-A - places value in A on calculator stack in 5 byte form.
; $2DD5 FP-TO-A - Loads value on calculator stack into accumulator A.
; $16C5 SET-STK - Cleans up calculator stack if quitting early.
; $22AA PIXEL-ADD - returns pixel address in HL for BC holding X and Y.
; $2DA2 FP-TO-BC - used as a quick method of getting X into register C.
; $22E9 PLOT-SUB+5 - PLOT subroutine entry point for X in C, Y in B.
;
; The calculator has six storage cells which can store values in 5-byte 
; form.
; mem-0 to mem-2 are frequently used by functions but in this case mem-3, 
; mem-4 and mem-5 are available for the DEFORM program.
;
; MEM-3 is used to hold the radius in the x-axis of the slice being 
;       plotted.
; MEM-4 is used to cycle through integer values 0-255. It is initialized to 
;       zero (once would have done) and it is incremented directly by 
;       manipulating the LSB byte -  INC (IY+$67). 
;       For integers, the fifth byte is unused so holds the Y coordinate of 
;       the line being plotted.
; MEM-5 holds the radius of the sphere (constant). It is reduced by a half
;       at the start for aesthetic reasons.
;
; -------------------------------------------------------------------------
