;3D-Tests

.nolist
#include "asm.inc"
#define ASM

#ifdef APP
.org 4000h
#define APPNAME "SpaceWar"
#include "apphead.inc"
#endif

#ifdef ASM
.org userMem-2
.db 0BBh, 06Dh
#endif

.list

; Memory Equates
stepx    .equ saferam1 + 0
stepy    .equ saferam1 + 1
x1       .equ saferam1 + 2
y1       .equ saferam1 + 3
randSeed .equ saferam1 + 4 ; word

; Other Equates
zDist    .equ 8

;--Main Code-----------------------------------------------------------------

StartApp:

 ; Clear buffer
 call clrBuf

 ; Draw object
 ld b, 6
 ld hl, cube
loop:
 push bc
 ld d, (hl)
 inc hl 
 ld e, (hl)
 inc hl
 ld a, (hl)
 add a, zDist
 inc hl
 push hl
 ld l, a
 call calcPoint
 pop hl
 push de
 ld d, (hl)
 inc hl
 ld e, (hl)
 inc hl
 ld a, (hl)
 add a, zDist
 inc hl
 push hl
 ld l, a
 call calcPoint
 pop hl
 pop bc
 push hl
 call drawLine
 pop hl
 pop bc
 djnz loop

 ; Display buffer
 call dispBuf

 ; Wait for key
 bcall(_GetKey)

 ; Exit
#ifdef APP
 bjump(_JForceCmdNoChar)
#endif
#ifdef ASM
 ret
#endif

;--Functions (BCALLs)--------------------------------------------------------

; FUNCTION: putStr - Displays string in small font
; hl=addr
putStr:
 ld a, (hl)
 inc hl
 or a
 ret z
 bcall(_VPutMap)
 jr nc, putStr
 ret

;--Functions (no BCALLs)-----------------------------------------------------

; FUNCTION: calcPerspect - Calculates the perspective of a co-ord
; hl=e*64/l
calcPerspect:
 ld bc, divTable - 1
 ld h, 0
 add hl, bc
 ld c, (hl)

 ld hl, 0
 ld d, h
 bit 7, e
 jr z, calcPerspectPos
 ld d, 255
calcPerspectPos:
 ld b, 8
calcPerspectLoop:
 srl c
 jr nc, calcPerspectSkip
 add hl, de
calcPerspectSkip:
 sla e
 rl d
 djnz calcPerspectLoop
 ret

; FUNCTION: calcPoint - Calculates the position on the screen of a 3D point
; l=z, d=x, e=y
calcPoint:
 push de
 push hl
 call calcPerspect
 ld a, l
 add a, 32
 pop hl
 pop de
 ld e, a
 push de
 ld e, d
 call calcPerspect
 ld a, l
 add a, 48
 pop de
 ld d, a
 ret

; FUNCTION: clrBuf - Clears graph buffer
; none
clrBuf:
 ld hl, plotsscreen
 xor a
 ld b, a
clrBufLoop1:
 ld (hl), a
 inc hl
 djnz clrBufLoop1
 ld b, a
clrBufLoop2:
 ld (hl), a
 inc hl
 djnz clrBufLoop2
 ld b, a
clrBufLoop3:
 ld (hl), a
 inc hl
 djnz clrBufLoop3
 ret

; FUNCTION: dispBuf - Displays the graph buffer on the screen
; none
dispBuf:
 di                                 ; 4
 ld a, 80h                          ; 7
 out ($10), a                       ; 11
 ld hl, plotsscreen-12-(-(12*64)+1) ; 10
 ld a, 20h                          ; 7
 ld c,a                             ; 4
 inc hl                             ; 6 waste
 dec hl                             ; 6 waste
dispBufAgain:
 ld b, 64                           ; 7
 inc c                              ; 4
 ld de, -(12*64)+1                  ; 10
 out ($10), a                       ; 11
 add hl, de                         ; 11
 ld  de, 10                         ; 10
dispBufLoop:
 add hl, de                         ; 11
 inc hl                             ; 6 waste
 inc hl                             ; 6 waste
 inc de                             ; 6
 ld a, (hl)                         ; 7
 out ($11), a                       ; 11
 dec de                             ; 6
 djnz dispBufLoop                   ; 13/8
 ld a,c                             ; 4
 cp 2Bh+1                           ; 7
 jr nz, dispBufAgain                ; 10/1
 ret                                ; 10

; FUNCTION: drawLine - Draws a line on the graph buffer
; b=x0, c=y0, d=x1, e=y1
drawLine:

 ; Draw first pixel
 push de
 ld a, b
 ld e, c
 call drawPoint
 pop de

 ; Save x1 and y1
 ld a, d
 ld (x1), a
 ld a, e
 ld (y1), a

 ; Calculate dy and stepy
 ld h, 1
 ld a, e
 sub c
 jr nc, posDy
 neg
 ld h, -1
posDy:
 ld e, a
 ld a, h
 ld (stepy), a

 ; Calculate dx and stepx
 ld h, 1
 ld a, d
 sub b
 jr nc, posDx
 neg
 ld h, -1
posDx:
 ld d, a
 ld a, h
 ld (stepx), a

 ; Compare dx and dy
 ld a, e
 cp d
 jr nc, dx_lte_dy
 
 ; ** dx > dy

 ; Calulate fraction
 ld h, d
 sra h
 sub h
 ld h, a

 ; Load x1 into l
 ld a, (x1)
 ld l, a

 ; Draw line
lineLoop1:
 ld a, l
 cp b
 ret z

 ; Check if fraction is positive
 bit 7, h
 jp nz, skipLine1

 ; Add stepy to y0
 ld a, (stepy)
 add a, c
 ld c, a

 ; Subtract dx from fraction
 ld a, h
 sub d
 ld h, a
skipLine1:

 ; Add dy to fraction
 ld a, h
 add a, e
 ld h, a

 ; Add stepx to x0
 ld a, (stepx)
 add a, b
 ld b, a

 ; Display pixel
 push de
 push hl
 ld a, b
 ld e, c
 call drawPoint
 pop hl
 pop de
 jp lineLoop1

 ; ** dx <= dy
dx_lte_dy:

 ; Calculate fraction
 ld h, e
 sra h
 ld a, d
 sub h
 ld h, a

 ; Load y1 into l
 ld a, (y1)
 ld l, a

 ; Draw line
lineLoop2:
 ld a, l
 cp c
 ret z

 ; Check if fraction is positive
 bit 7, h
 jp nz, skipLine2

 ; Add stepx to x0
 ld a, (stepx)
 add a, b
 ld b, a

 ; Subtract dy from fraction
 ld a, h
 sub e
 ld h, a
skipLine2:

 ; Add dx to fraction
 ld a, h
 add a, d
 ld h, a

 ; Add stepy to y0
 ld a, (stepy)
 add a, c
 ld c, a

 ; Display pixel
 push de
 push hl
 ld a, b
 ld e, c
 call drawPoint
 pop hl
 pop de
 jp lineLoop2

; FUNCTION: drawPoint - Draws a point on the graph buffer
; x=a, y=e
drawPoint:
 ld      d, 0 ; Do y*12
 sla     e
 sla     e
 ld      hl, 0
 add     hl, de
 add     hl, de
 add     hl, de
 ld      d, 0 ; Do x/8
 ld      e, a
 srl     e
 srl     e
 srl     e   
 add     hl,de
 ld      de, plotsscreen
 add     hl, de ; Add address to graphbuf
 ld      de, 0007h ; Get the remainder of x/8
 and     e
 ld      e,a
 ld      ix, drawPointTable ; Look up in table pixel to set
 add     ix, de
 ld      a, (ix+0) ; and load this
 or      (hl)
 ld      (hl), a
 ret

; FUNCTION: getRand - Gets an 8-bit random number
; 0<=a<b
getRand:
 ld hl, (randSeed)
 ld a, r
 ld d, a
 ld e, (hl)
 add hl, de
 add a, l
 xor h
 ld (randSeed), hl
 sbc hl, hl
 ld e, a
 ld d, h
getRandLoop:
 add hl, de
 djnz getRandLoop
 ld a, h
 ret

;--Data---------------------------------------------------------------------

; DATA: Table for point drawing routine
drawPointTable:
.db 10000000b
.db 01000000b
.db 00100000b
.db 00010000b
.db 00001000b
.db 00000100b
.db 00000010b
.db 00000001b

; DATA: Table for 64/n
divTable:
.db 64,32,21,16,12,10,9,8,7,6,5,5,4,4,4,4
.db 3,3,3,3,3,2,2,2,2,2,2,2,2,2,2,2
.db 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
.db 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1

; DATA: Cube (not anymore :)
cube:
.db -2,0,0,2,0,0
.db -2,0,0,0,3,0
.db 0,3,0,2,0,0

.db -2,0,0,0,0,-1
.db 2,0,0,0,0,-1
.db 0,3,0,0,0,-1

.end

