*      
* lib3d extensions
*
* A collection of routines which extends
* the 3d library, adding routines for creating,
* manipulating, and rendering objects.
*
* SLJ March/April 1999
*

*
* Idea: Maintain a list of objects.
* Each object is of the following form:
*
* Object:
*        CenterX          2 bytes
*        CenterY          2 bytes
*        CenterZ          2 bytes
*        Obj data pointer 2 bytes
*        ID byte          1 byte
*        User byte        1 byte
*        Center position  1 byte
*        CenterXRem       1 byte
*              YRem       1 byte
*              ZRem       1 byte
*        Orientation matrix 18 bytes

ObjCX    = 0
ObjCY    = 2
ObjCZ    = 4
ObjData  = 6
ObjID    = 8
ObjUser  = 9
ObCenPos = 10
ObjCXRem = 11
ObjCYRem = 12
ObjCZRem = 13
ObjMat   = 14
ObjSize  = 32             ;32 bytes total

*
* CenterX/Y/Z represents the object location
* Data pointer points to object data, below.
* ID and user byte is optional, to let the user assign an ID to an object
* CenterX/Y/ZRem is the fractional part of the object centers,
*   used by the movement routines
* Orientation matrix consists of 9-byte integer matrix and 9-byte remainder
*

*
* Object data: There are two types of
* objects, normal and compound, which
* are objects made up of a number of
* smaller "oblets".  Normal object data
* is of the following form:
*
*        TypeID = 0   1 byte
*        # of points  1 byte
*        # of faces   1 byte
*        xcoords      n bytes
*        ycoords      n bytes
*        zcoords      n bytes
*    faces:
*        # of points  1 byte
*        fill pattern 1 byte
*        point list   m bytes
*
* that is, point data followed by a list of faces.
* Fill pattern is an index into fill pattern list, used with solid polygons.
* x/y/zcoords consist of p object points (-96..96) followed by q normals.
*
* Compound objects are of the form:
*
*        TypeID = $80 1 byte
*        # of points  1 byte
*        # of oblets  1 byte
*        xcoords      n bytes
*        ycoords      n bytes
*        zcoords      n bytes
*    oblets:
*        ref points   p bytes
*        oblet 1
*          oblet size (in bytes)
*                     1 byte
*          # of faces 1 byte
*          faces
*        oblet 2 ...
*
* Each oblet is similar to a normal object, but is associated with a point
* in the point list -- the reference point.  The oblets are drawn by first
* depth-sorting these points and drawing from back to front.
*

         org $5000

         jmp Init3D       ;Initialize lib3d
         jmp AddObj       ;Add object to object list
         jmp DelObj       ;Delete object from list
         jmp SetCurOb     ;Set current object
         jmp GetCurOb     ;Get current object
         jmp GetNextOb    ;Get next object in list
         jmp GetObj       ;Get pointer to object

         jmp SetMat       ;Calculate and set object matrix
         jmp Pitch        ;Pitch - rotate object around x-axis
         jmp Yaw          ;Yaw - rotate around y-axis
         jmp Roll         ;Roll - rotate around z-axis
         jmp MoveSide     ;Move object
         jmp MoveDown
         jmp MoveForwards
         jmp GetSideVec   ;Orientation vectors
         jmp GetDownVec   ;(length=64)
         jmp GetFrontVec

         jmp SetParms     ;Set rendering parameters
         jmp SetVisParms  ;Set visibility parameters
         jmp CalcView     ;Set viewpoint = object
         jmp SortVis      ;Compute and sort visible objects
         jmp DrawAllVis   ;Draw all visible objects
         jmp GetNextVis   ;Draw next objesible object list
         jmp RotDraw      ;Rotate and draw object
         jmp DrawFace     ;Draw single face (polygon)

NUMOBJS  DFB 00           ;Number of objects
NUMCENTS DFB 00           ;Number of object senter
CUROBJ   DFB 00           ;Current object
LASTOBJ  DFB 00
ZMAX     DA $2000         ;Maximum range
ZMIN     DFB 100          ;Minimum range
OBJECTS  DA $0800         ;Object records 1227 = 3456 bytes = $0D80


*===============================

tempa    = $55
tempx    = $56
tempy    = $57
temp     = $58            ;two bytes
point    = $5a            ;two bytes

X1       = $60            ;Line x-coord
Y1       = $62
X2       = $64
Y2       = $66

LINELO   = $4F00          ;Lines drawn
LINEHI   = $4F68          ;speeds up wireframe
MAXLINES = $67

OBLETS   = $4FD0          ;Oblet list
OBHEAD   = $2F            ;Head of list = $55FF

OBJLO    = $5600          ;Object pointers
OBJHI    = $5680          ;if 0 then empty
VISOBJS  = $5700
OBCEN    = $5781          ;Center object #
                          ;Note: will bug if 128 vis objs

CX       = $5800          ;Rotated/relativecenters
HCX      = $5880
CY       = $5900
HCY      = $5980
CZ       = $5A00
HCZ      = $5A80

PLISTX   EQU $5B00        ;Point lists (projected)
PLISTY   EQU $5C00
PLISTZ   EQU $5D00

MPROJ    = $5E00          ;Two pages

*===============================

* lib3d stuff

CALCMAT  EQU $8800
ACCROTX  EQU $8803
ACCROTY  EQU $8806
ACCROTZ  EQU $8809
GLOBROT  EQU $880C
ROTPROJ  EQU $880F
POLYFILL EQU $8812
PLOT     EQU $8815
DRAWLINE EQU $8818
VERSION  EQU $881B
PQ       EQU $0200        ;Point queue

MATRIX   = $41            ;Local rotation matrix
VIEWMAT  = $4A            ;Viewpoint rotation matrix

XOFFSET  EQU $53
YOFFSET  EQU $54

MULTLO1  EQU $B1          ;Multiplication tables
MULTLO2  EQU $B3
MULTHI1  EQU $B5
MULTHI2  EQU $B7

BITMAP   EQU $B9          ;Page of bitmap base

FILLPAT  EQU $BB          ;Pointer to fill pattern

PLISTXLO EQU $BD          ;Pointers to plotted points
PLISTXHI EQU $BF
PLISTYLO EQU $C1
PLISTYHI EQU $C3

PLISTZLO EQU $8B          ;Rotated z-coords
PLISTZHI EQU $8D


C0XLO    EQU $63          ;Pointers to centers to rotate
C0XHI    EQU $65
C0YLO    EQU $67
C0YHI    EQU $69
C0ZLO    EQU $6B
C0ZHI    EQU $6D

CXLO     EQU $A3          ;Pointers to rotated centers
CXHI     EQU $A5
CYLO     EQU $A7
CYHI     EQU $A9
CZLO     EQU $AB
CZHI     EQU $AD

ROTMATH  EQU $AF          ;Pointer to rotation math table

P0X      EQU $69          ;Pointers to points to be rotated
P0Y      EQU $6B
P0Z      EQU $6D

*
* Initialize lib3d pointers, variables
*
* On entry: .AY = pointer to object records
*

Init3D   
         STA OBJECTS
         STY OBJECTS+1
         LDA #>MPROJ      ;Table at $8000
         STA ROTMATH+1
         LDX #$C1
         STX MULTLO1+1
         DEX
         STX MULTLO2+1
         LDX #$C4
         STX MULTHI1+1
         DEX
         STX MULTHI2+1

         LDA #$FF
         STA CUROBJ
         LDA #00
         STA NUMOBJS
         STA LASTOBJ

         STA PLISTXLO
         STA PLISTYLO
         STA PLISTZLO
         LDA #$80
         STA PLISTXHI
         STA PLISTYHI
         STA PLISTZHI
         LDX #>PLISTX
         STX PLISTXLO+1
         STX PLISTXHI+1
         INX
         STX PLISTYLO+1
         STX PLISTYHI+1
         INX
         STX PLISTZLO+1
         STX PLISTZHI+1


         LDX #<CX
         STX CXLO
         STX CYLO
         STX CZLO
         LDX #<HCX
         STX CXHI
         STX CYHI
         STX CZHI

         LDX #>CX
         STX CXLO+1
         LDX #>HCX
         STX CXHI+1
         LDX #>CY
         STX CYLO+1
         LDX #>HCY
         STX CYHI+1
         LDX #>CZ
         STX CZLO+1
         LDX #>HCZ
         STX CZHI+1

         LDX #159         ;(0,0) = center of screen
         LDY #99
         JSR VERSION
         BPL :NOM
         LDX #79          ;Multicolor
:NOM     STX XOFFSET
         STY YOFFSET

         LDY #00          ;Zero out object pointers
         TYA
:L1      STA OBJHI,Y
         INY
         BPL :L1          ;128 entries

         RTS

*
* AddObj -- Add object to object list
*
* On entry: .AY = pointer to object point data
*           .X  = optional ID byte
*
* On exit: .AY = pointer to object
*          .X  = object number
*          C set indicates an error
*

AddObj   
         sta tempa
         sty tempy
         stx tempx

         ldx #00          ;Find open slot
         txa
         sta temp
         clc
:loop    ldy objhi,x
         beq :found
         adc #ObjSize     ;32 bytes per record
         bcc :c1
         inc temp
         clc
:c1      inx
         bpl :loop
         sec
         rts

:found   adc objects
         sta point
         sta objlo,x
         lda temp
         adc objects+1
         sta point+1
         sta objhi,x
         inc numobjs
         cpx lastobj
         bcc :init
         stx lastobj
:init    
         ldy #ObjSize-1   ;Init object
         lda #00
:l2      sta (point),y
         dey
         bpl :l2

         lda #64          ;Identity matrix
         ldy #ObjMat
         sta (point),y
         ldy #ObjMat+4
         sta (point),y
         ldy #ObjMat+8
         sta (point),y

         ldy #ObjID
         lda tempx        ;ID
         sta (point),y

         lda tempy        ;Obj data pointer
         dey
         sta (point),y
         lda tempa
         dey
         sta (point),y

SetCurOb stx curobj
GetCurOb ldx curobj
GetObj   lda objlo,x
         ldy objhi,x
         rts

*
* DelObj -- Remove object from list
*           by setting high byte=0
*
* On entry: .X = object number
*           C set means serious error!
*
DelObj   LDA #00
         STA OBJHI,X
         LDA NUMOBJS
         BEQ :RTS
         DEC NUMOBJS
         CPX LASTOBJ      ;Last object in list
         BCC :RTS
:L1      LDA OBJHI,X
         BNE :STX
         DEX
         BPL :L1
         SEC              ;Out of objects!
         INX
:STX     STX LASTOBJ
:RTS     RTS

*
* GetNextOb -- Get next object in list
*
* On exit: .X = object number
*          .AY= object pointer
*          C set indicates error
*          Current object set to .X
*
GetNextOb
         LDA NUMOBJS
         BEQ :ERR
         LDX CUROBJ
         BMI :ERR
         CPX LASTOBJ
         BCC :C1
         LDX #$FF
:C1      INX
         LDY OBJHI,X
         BEQ :C1
         LDA OBJLO,X
         STX CUROBJ
         CLC
         RTS

:ERR     SEC
         RTS

*-------------------------------
*
* Object manipulation routines
*
*-------------------------------

*
* SetMat -- Calculate matrix for current object
*
* On entry: .A = Angle around z-axis
*           .Y = Angle around y-axis
*           .X = Angle around x-axis
*
SetMat   
         JSR CALCMAT      ;Result -> MATRIX
         LDX CUROBJ
         BMI :RTS
         LDA OBJLO,X
         CLC
         ADC #ObjMat      ;Matrix
         STA POINT
         LDA OBJHI,X
         ADC #00
         STA POINT+1

         LDA #00
         LDY #17
:L2      STA (POINT),Y    ;Zero remainder
         DEY
         CPY #8
         BNE :L2

:LOOP    LDA MATRIX,Y
         STA (POINT),Y
         DEY
         BPL :LOOP

:RTS     RTS

*
* Yaw/Pitch/Roll -- Accumulate a rotation on current object
*
* On entry: C clear -> positive rotation
*           C set -> negative rotation
*

GetCurMat
         PHP
         JSR GetCurOb
         CLC
         ADC #ObjMat
         BCC :plp
         INY
:plp     PLP
         RTS

Pitch    
         JSR GetCurMat
         JMP ACCROTX
Yaw      
         JSR GetCurMat
         JMP ACCROTY
Roll     
         JSR GetCurMat
         JMP ACCROTZ

*
* MoveDown/Side/Forwards -- Move object along its
*   (local) X Y or Z axis.
*
* Note that orientation matrix is inverse of object matrix
*
* On entry: .A = velocity (signed)
*
MOVRTS   RTS
MoveDown 
         LDY #ObjMat      ;Row 1
         DFB $2C
MoveSide 
         LDY #ObjMat+3    ;Row 2
         DFB $2C
MoveForwards
         LDY #ObjMat+6
         STY TEMPY        ;Object offset
         CMP #00
         BEQ MOVRTS
         STA MULTLO1      ;Plain signed multply
         STA MULTHI1
         EOR #$FF
         CLC
         ADC #01
         STA MULTLO2
         STA MULTHI2

         LDX CUROBJ
         BMI MOVRTS
         LDA OBJLO,X
         STA POINT
         LDA OBJHI,X
         STA POINT+1

         LDA (POINT),Y
         TAY
         LDA #ObjCXRem
         LDX #ObjCX
         JSR MovMult

         LDY TEMPY
         INY
         STY TEMPY
         LDA (POINT),Y
         TAY
         LDA #ObjCYRem
         LDX #ObjCY
         JSR MovMult

         LDY TEMPY
         INY
         LDA (POINT),Y
         TAY
         LDA #ObjCZRem
         LDX #ObjCZ

MovMult  
         STX TEMPX        ;Coord
         STA TEMPA        ;Remainder
         LDA (MULTLO1),Y
         SEC
         SBC (MULTLO2),Y
         STA TEMP
         LDA (MULTHI1),Y
         SBC (MULTHI2),Y
         CPY #$80         ;Fix up signs
         BCC :POS1
         SBC MULTLO1
:POS1    LDX MULTLO1
         BPL :DIV
         STY TEMP+1
         SEC
         SBC TEMP+1

:DIV     STA TEMP+1       ;Now div by 16
         LDY #00
         AND #$FF
         BPL :POSA
         DEY              ;High byte
:POSA    TYA
         ASL TEMP
         ROL TEMP+1
         ROL
         ASL TEMP
         ROL TEMP+1
         ROL
         ASL TEMP
         ROL TEMP+1
         ROL
         ASL TEMP
         ROL TEMP+1
         ROL

         TAX
         LDA TEMP
         LDY TEMPA        ;Remainder
         CLC
         ADC (POINT),Y
         STA (POINT),Y
         LDY TEMPX        ;Coord
         LDA TEMP+1
         ADC (POINT),Y
         STA (POINT),Y
         INY
         TXA
         ADC (POINT),Y
         STA (POINT),Y
         RTS

*
* GetDown/Side/FrontVec
*
* Get orientation vector
* On entry: Current object set
* On exit: (.X,.Y,.A) = (X,Y,Z) signed
*          direction vector, length=64
*

GetDownVec
         LDY #ObjMat      ;Row 1
         DFB $2C
GetSideVec
         LDY #ObjMat+3    ;Row 2
         DFB $2C
GetFrontVec
         LDY #ObjMat+6

         LDX CUROBJ
         BMI :RTS
         LDA OBJLO,X
         STA POINT
         LDA OBJHI,X
         STA POINT+1

         LDA (POINT),Y
         TAX
         INY
         INY
         LDA (POINT),Y
         PHA
         DEY
         LDA (POINT),Y
         TAY
         PLA
:RTS     RTS



*-------------------------------
*
* Visualization routines
*
*-------------------------------

ViewObj  DFB 00           ;Viewpoint object
SOLIDPOL DFB 00           ;Solid/wireframe polygons
PATTAB   DA $1000         ;Pattern table

*
* SetParms -- Set rendering parameters
*
* On entry: .AY = Pointer to pattern table
*           .X  = Bitmap page
*            C set   -> solid polygons
*            C clear -> wireframe
*

SetParms 
         ROR SOLIDPOL
         STA PATTAB
         STY PATTAB+1
         STX BITMAP
         RTS

*
* SetVisParms -- Set visibility parms
*
* On entry: .AY = Maximum object range
*           .X  = Minimum object range
*

SetVisParms
         STA ZMAX
         STY ZMAX+1
         STX ZMIN
         RTS

*
* CalcView -- Calculate view (Set viewpoint, translate and rotate centers)
*
* On entry: .X = viewpoint object
*
* On exit: translated rotated centers
*          in CX/CY/CZ
*

CalcView 
         STX ViewObj
         JSR SetCurOb
         STA POINT
         STY POINT+1
         LDX #8
         LDY #ObjMat+8
:loop    LDA (POINT),Y    ;Viewpoint matrix
         STA VIEWMAT,X
         DEY
         DEX
         BPL :loop

         LDX #11          ;Set up pointers
:cl      LDA CXLO,X
         STA C0XLO,X
         DEX
         BPL :cl

         LDX #00
         STX TEMPX        ;Object index

:getloop JSR GetNextOb
         CPX ViewObj
         BEQ :done

         STA TEMP
         STY TEMP+1
         TXA
         LDX TEMPX
         STA OBCEN,X      ;Object number
         TXA
         LDY #ObCenPos    ;Position in center list
         STA (TEMP),Y

         LDY #00
         LDA (TEMP),Y     ;Translate
         SEC
         SBC (POINT),Y
         STA CX,X
         INY
         LDA (TEMP),Y
         SBC (POINT),Y
         STA HCX,X

         INY
         LDA (TEMP),Y     ;Translate
         SEC
         SBC (POINT),Y
         STA CY,X
         INY
         LDA (TEMP),Y
         SBC (POINT),Y
         STA HCY,X

         INY
         LDA (TEMP),Y     ;Translate
         SEC
         SBC (POINT),Y
         STA CZ,X
         INY
         LDA (TEMP),Y
         SBC (POINT),Y
         STA HCZ,X

         INC TEMPX
         BPL :getloop
:done    
         LDY TEMPX        ;# of objects
         STY NUMCENTS
         JMP GLOBROT      ;off she goes!

*
* SortVis -- Compute and sort all visible objects
*
* On entry: centers stored in CX etc.
*
* On exit: VisObjs = linked list of visible objects
*   (farthest objects at start of list)
*
* Visibility conditions:
*   x+z>0, x-z<0 (within view area)
*   same for x+y/x-y
*   z > 8192 will be treated as too far away to see
*   z < 180 is treated as being too near.
*
NUMVIS   DFB 00

SortVis  

         LDA #00
         STA NUMVIS
         LDA #$80
         STA VISOBJS+$80
         LDX NUMCENTS
         DEX
         BMI :rts
:loop    LDA HCZ,X        ;high byte
         STA TEMP+1
         LDA CZ,X         ;low byte
         STA TEMP
         CMP ZMAX
         LDA TEMP+1
         SBC ZMAX+1       ;Greater than 8192?
         BCS :SKIP        ;(or negative)
         LDA TEMP
         CMP ZMIN
         LDA TEMP+1
         SBC #00
         BCC :SKIP

         LDA TEMP         ;x+z>0
         CLC
         ADC CX,X
         LDA TEMP+1
         ADC HCX,X
         BMI :SKIP

         LDA TEMP         ;z-x>0
         CMP CX,X
         LDA TEMP+1
         SBC HCX,X
         BMI :SKIP

         LDA TEMP         ;y+z>0
         CLC
         ADC CY,X
         LDA TEMP+1
         ADC HCY,X
         BMI :SKIP

         LDA TEMP         ;z-y>0
         CMP CY,X
         LDA TEMP+1
         SBC HCY,X
         BMI :SKIP

         LDY #$80         ;Head of list
:l1      LDA VISOBJS,Y    ;Linked list of objects
         BMI :link
         STY TEMPY
         TAY              ;Next object
         LDA CZ,Y         ;If farther, then
         CMP TEMP         ;move down list
         LDA HCZ,Y
         SBC TEMP+1
         BCS :l1
                          ;Nearest objects last in list
         TYA
         LDY TEMPY        ;Insert into list
:link    STA VISOBJS,X    ;X -> rest of list
         TXA
         STA VISOBJS,Y    ;beginning of list -> X
:skip    DEX
         BPL :loop
         LDY #$80
         STY COB          ;Current object
:rts     RTS

*
* DrawAllVis -- Draw all visible objects
*   in linked list.
*
COB      DFB 00           ;Current object

DrawLoop 
         STY COB
***
* FIX ME!!!
***
         LDA OBCEN,Y      ;Actual object number
         TAX
         JSR RotDraw
DrawAllVis
         LDX COB          ;Head = #$80
         LDY VISOBJS,X
         BPL DrawLoop
:done    
DrawRTS  RTS

*
* GetNextVis -- Get next object in
*   visible list.
*
* On exit: N set indicates end of list
*
GetNextVis
         LDX COB
         LDY VISOBJS,X
         BMI DrawRTS
         STY COB
* yet another FIX ME!!!
         DFB $BE
         DA OBCEN         ;LDX OBCEN,Y
         LDA #00
         STA NUMLINES
         JMP SetCurOb


*
* RotDraw -- Rotate and draw an object
*
* On entry: Object number in .X
*   SetParms already called.
*
DATAP    DA 0             ;Temp pointer
NPOINTS  DFB 00
OBTYPE   DFB 00

NFACES   DFB 00           ;Faces/Oblets

RotDraw  
         LDA OBJLO,X
         STA POINT
         LDA OBJHI,X
         STA POINT+1

         LDY #ObjMat      ;Matrix -> ZP
         LDX #00
         STX NUMLINES
:mli     STX TEMP
         LDA #3
         STA TEMP+1
:ml      LDA (POINT),Y    ;Take transpose to get
         STA MATRIX,X     ;orientation matrix
         INY
         INX
         INX
         INX
         DEC TEMP+1
         BNE :ml
         LDX TEMP
         INX
         CPX #3
         BNE :mli

         LDY #ObCenPos
         LDA (POINT),Y
         STA TEMPA        ;Position of center in list
         LDY #ObjData     ;Get data pointer for later
         LDA (POINT),Y
         STA DATAP
         TAX
         INY
         LDA (POINT),Y
         STA DATAP+1
         STA POINT+1
         STX POINT

         LDY #00
         LDA (POINT),Y
         STA OBTYPE       ;Normal/compound
         INY
         LDA (POINT),Y    ;Number of points
         BEQ :rts
         STA NPOINTS
         INY
         LDA (POINT),Y
         STA NFACES

         INY              ;Point pointers
         TYA
         CLC
         ADC POINT
         STA P0X
         LDX POINT+1
         BCC :c1
         INX
         CLC
:c1      STX P0X+1
         ADC NPOINTS
         STA P0Y
         BCC :c2
         INX
         CLC
:c2      STX P0Y+1
         ADC NPOINTS
         STA P0Z
         BCC :c3
         INX
         CLC
:c3      STX P0Z+1
         ADC NPOINTS
         STA FACEPTR
         TXA
         ADC #00
         STA FACEPTR+1

         LDY NPOINTS
         LDX TEMPA        ;Center index
         SEC              ;Rot and proj
         JSR ROTPROJ
         LDA NFACES       ;Maybe just want tointsate p
         BEQ :rts
         LDA FACEPTR
         LDY FACEPTR+1
         LDX OBTYPE
         BMI Compound
:dloop   JSR DrawFace
         DEC NFACES
         BNE :dloop
:rts     RTS

*
* Compound objects are made up of
* a smaller number of "oblets",
* drawn in order after sorting their
* reference points.
*
COBLET   DFB 00           ;Current oblet
OBLPTR   DA 00            ;Pointer to oblets

Compound 
         STA POINT
         STY POINT+1
         CLC
         ADC NFACES
         STA OBLPTR
         TYA
         ADC #00
         STA OBLPTR+1

         LDA #OBHEAD
         STA OBLETS+OBHEAD ;Head of list
         DEC NFACES

:sort    LDY NFACES       ;Number of oblets
         LDA (POINT),Y    ;= # ref points
         TAX
         LDA PLISTZ,X
         STA TEMP
         LDA PLISTZ+$80,X
         STA TEMP+1

         LDX NFACES       ;Current oblet
         LDY #OBHEAD      ;Head of list
:l1      LDA OBLETS,Y     ;Linked list
         CMP #OBHEAD
         BCS :link
         STY TEMPY
         TAY              ;Next object
         LDA PLISTZ,Y     ;If farther, then
         CMP TEMP         ;move down list
         LDA PLISTZ+$80,Y
         SBC TEMP+1
         BCS :l1
                          ;Nearest objects last in list
         TYA
         LDY TEMPY        ;Insert into list
:link    STA OBLETS,X     ;X -> rest of list
         TXA
         STA OBLETS,Y     ;beginning of list -> X
         DEC NFACES
         BPL :sort
                          ;Now draw them
         LDY #OBHEAD
:loop    LDA OBLETS,Y
*
* FIX ME!
*
         TAX
         STX COBLET
         CPX #OBHEAD
         BCS :rts
         LDA OBLPTR+1
         STA POINT+1
         LDA OBLPTR       ;Locate it
         STA POINT
         CPX #00
         BEQ :draw

         LDY #00
         CLC
:l2      ADC (POINT),Y
         STA POINT
         BCC :dex
         INC POINT+1
         CLC
:dex     DEX
         BNE :l2

:draw    LDY #1
         LDA (POINT),Y    ;Number of faces
         STA NFACES
         LDY POINT+1
         LDA POINT
         CLC
         ADC #2
         BCC :dloop
         INY
:dloop   JSR DrawFace
         DEC NFACES
         BNE :dloop

         LDY COBLET
         BPL :loop
:rts     RTS

*
* DrawFace -- Draw a polygon
*
* On entry: .AY points to face data
* On exit: .AY points to next face
*
* Wireframe: C clear -> face not drawn
*
NVERTS   DFB 00           ;Number of vertices
FACEPTR  DA 00            ;Pointer to face

DrawFace 
         STA POINT
         STY POINT+1

         LDY #00
         LDA (POINT),Y
         STA NVERTS
         SEC              ;N+1 in list
         ADC #2           ;(closes on itself)
         ADC POINT
         STA FACEPTR      ;Next face
         LDA #00
         STA TEMP
         ADC POINT+1
         STA FACEPTR+1

         LDY #1           ;Fill pattern
         LDA (POINT),Y    ;index
         ASL
         ROL TEMP
         ASL
         ROL TEMP
         ASL
         ROL TEMP
         ADC PATTAB
         STA FILLPAT
         LDA TEMP
         ADC PATTAB+1
         STA FILLPAT+1

         LDX SOLIDPOL
         BPL :Wire

         LDX #$FF
:pq      INX
         INY
         LDA (POINT),Y    ;Copy to queue
         STA PQ,X
         CPX NVERTS
         BNE :pq
         TXA              ;Empty face
         BEQ :exit
         JSR POLYFILL
:exit    LDA FACEPTR
         LDY FACEPTR+1
         RTS
                          ;Wireframe routine
:Wire                     ;JSR IsVis
                          ;BCC :exit

         LDY #2           ;Connect the dots...
:l2      LDA (POINT),Y
         TAX
         LDA PLISTX,X
         STA X1
         LDA PLISTX+$80,X
         STA X1+1
         LDA PLISTY,X
         STA Y1
         LDA PLISTY+$80,X
         STA Y1+1
         STX TEMPA

         INY
         LDA (POINT),Y
         TAX
         LDA PLISTX,X
         STA X2
         LDA PLISTX+$80,X
         STA X2+1
         LDA PLISTY,X
         STA Y2
         LDA PLISTY+$80,X
         STA Y2+1

         STY TEMPY

* Check for line connections
* Points in TEMPA and .X

         LDY #00
:loop    CPY NUMLINES
         BEQ :store
         TXA
         CMP LINELO,Y
         BNE :test2
         LDA TEMPA
         CMP LINEHI,Y
         BEQ :skip
:iny     INY
         BPL :loop
:store   LDA TEMPA
         STA LINELO,Y
         TXA
         STA LINEHI,Y
         CPY #MAXLINES
         BEQ :jsr
         INC NUMLINES

:jsr     JSR DrawLine

:skip    LDY TEMPY
         DEC NVERTS
         BNE :l2
         SEC
         BCS :exit

:test2   CMP LINEHI,Y
         BNE :iny
         LDA TEMPA
         CMP LINELO,Y
         BNE :iny
         BEQ :skip

NUMLINES DFB 00

*
* IsVis -- Compute whether face is
*    visible, using cross-products
*
* On entry: .AY = pointer to face
* On exit: C set -> visible
*          C clear -> not visible
*
IsVis    
*-------------------------------
         do 0
         STA POINT
         STY POINT+1
         LDY #4           ;N+1
         LDA (POINT),Y
         TAX
         DEY
         LDA (POINT),Y    ;N
         TAY
         LDA PLISTX,X
         SEC
         SBC PLISTX,Y
         STA X1
         LDA PLISTX+$80,X
         SBC PLISTX+$80,Y
         STA X1+1         ;DX

         LDA PLISTY,X
         SEC
         SBC PLISTY,Y
         STA Y1
         LDA PLISTY+$80,X
         SBC PLISTY+$80,Y
         STA Y1+1

         BPL :XCHK        ;If >
         BEQ :XCHK
         fin

*-------------------------------


