*      
* Cool World (Polygonamy II: Monogonamy)
*
* Just yer basic realtime 3d virtual world program for
* the C64.  This program is intended to demonstrate the
* 3d library.
*
* SLJ 8/15/97
*

         ORG $4400

GETIN    EQU $FFE4
SCNKEY   EQU $FF9F

* Point lists, variables, etc.

SINDEL   EQU $3B00        ;Table of x*sin(delta), x>0
SINREM   EQU $3C00        ;remainder

CRAWL    = 1
WALK     = 2
RUN      = 3
FLY      = 4

NSTARS   = 11             ;0..11

INITOFF  EQU 500          ;Initial center z-offset
                          ;(So we start at z=-initoff)

TEMP1    = $60
TEMP2    = $61
TEMP3    = $62

DELTACX  = $63
DELTACY  = $64
DELTACZ  = $65

C0X      EQU $0400        ;Object center lists
C0Y      EQU $0600
C0Z      = $0800
CX       = $0A00          ;Rotated/relative centers
HCX      = $0B00
CY       = $0C00
HCY      = $0D00
CZ       = $0E00
HCZ      = $0F00

STARXHI  = $3D00
STARXLO  = $3D20
STARXREM = $3D40
STARY    = $3D60
STARYREM = $3D80
OBLIST   = $3DA0          ;Visible objects
PLISTX   EQU $3E00        ;Point lists (projected)
PLISTY   EQU $3F00

NEWANG   = $02            ;Flag
MOVCZ    = $03            ;Flags
THETSTEP = $04            ;Step in theta
CMASK    = $05            ;For center calculations
CDIV     = $06

NUMOBJS  = $7             ;Number of objects/centers.
NUMPTS   = $8             ;Number of points in point list
                          ;(dynamic)
COUNT    = $9             ;fps counter
NUMVIS   = $0A            ;Number of visible objects

RANDOM   = $0B            ;Two bytes!
TEMP     = $0D
BPOINT   = $0E            ;Bitmap pointer (for starfield)
TEMPSTEP = $10

THX1     = $11            ;Thetas for first rotation
THY1     = $12            ;matrix
THZ1     = $13

* lib3d stuff

CALCMAT  EQU $8A00
ACCROTX  EQU $8A03
ACCROTY  EQU $8A06
ACCROTZ  EQU $8A09
GLOBROT  EQU $8A0C
ROTPROJ  EQU $8A0F
POLYFILL EQU $8A12
PQ       EQU $0200        ;Point queue

MATRIX   = $B1            ;Rotation matrix $B1-$B9
MATREM   = $4A            ;Decmial parts $4A-$52

XOFFSET  EQU $53
YOFFSET  EQU $54

MULTLO1  EQU $F7          ;Multiplication tables
MULTLO2  EQU $F9
MULTHI1  EQU $FB
MULTHI2  EQU $FD

BITMAP   EQU $FF          ;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

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

ROTP0X   = $59            ;Pointers to store rotated points
ROTP0Y   = $5B            ;at.
ROTP0Z   = $5D

* Set up pointers

SETUP    
         LDA $01          ;No BASIC
         AND #$FE
         STA $01
         LDA #$80
         STA $028A        ;Repeat keys

         LDA #$84         ;Table at $8400
         STA ROTMATH+1
         LDX #$C1
         STX MULTLO1+1
         DEX
         STX MULTLO2+1
         LDX #$C4
         STX MULTHI1+1
         DEX
         STX MULTHI2+1

         LDA #$60         ;Buffer 1 at $6000
         STA BITMAP
         LDA $DD02
         ORA #3
         STA $DD02
         LDA $DD00
         AND #$FC
         ORA #2           ;Bank 1
         STA $DD00
         LDA #$3B
         STA $D011
         LDA #$08         ;Color at $4000
         STA $D018

         LDA #$16         ;white+blue
         LDY #00
:LOOP    STA $4000,Y
         STA $4100,Y
         STA $4200,Y
         STA $4300,Y
         STA $8000,Y
         STA $8100,Y
         STA $8200,Y
         STA $8300,Y
         INY
         BNE :LOOP

         LDA #00
         STA MOVCZ
         STA ACCX
         STA ACCY
         STA ACCZ

         STA NUMOBJS

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

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

         LDX #>CX
         STX CXLO+1
         INX
         STX CXHI+1
         LDX #>CY
         STX CYLO+1
         INX
         STX CYHI+1
         LDX #>CZ
         STX CZLO+1
         INX
         STX CZHI+1

         LDA #160         ;(0,0) = center of screen
         STA XOFFSET
         LDA #100
         STA YOFFSET

         LDA #RUN
         STA THETSTEP
         LDA #1           ;-32..32
         STA CDIV
         STA CMASK        ;Just one bit

         LDA #00
         LDX #8
:L1      STA MATRIX,X     ;Initialize rotation matrix
         STA MATREM,X
         DEX
         BPL :L1
         LDA #64          ;Identity matrix
         STA MATRIX
         STA MATRIX+4
         STA MATRIX+8

INITOBS  
         JSR INITMUS      ;Start music

         JSR INITSTAR
         JSR INITOB1      ;Initialize object 1
         JSR INITOB2
         JSR INITOB3
         JSR INITOB4
         JSR INITOB5
         JSR INITOB6
         JSR INITOB7
         JSR INITOB8
         JSR INITOB9
         JSR INITOB10
         JSR INITOB11
         JSR INITOB12
         JSR INITOB13
         JSR INITOB14
         JSR INITOB15
         JSR INITOB16
         JSR INITOB17

         LDA #01
         STA NEWANG       ;Force an update
         JSR UPD8POS

* Main loop

MAINLOOP 
         LDA #00          ;Reset PLIST index
         STA NUMPTS
         STA MOVCZ        ;and flags
         STA NEWANG

         LDA BITMAP       ;$60 or $A0
         BPL :BUFF2
         LDA $DD00        ;View buffer 2
         AND #$FC
         ORA #1           ;Bank 2
         STA $DD00
         LDA #$60         ;Draw into buffer 1
         STA BITMAP
         STA $D07E        ;Enable SuperCPU optimization
         STA $D075        ;bank 1
         STA $D07F
         JSR CLBUF1       ;Clear buffer 1
         JMP :FPS
:BUFF2   LDA #$A0
         STA BITMAP
         STA $D07E
         STA $D074
         STA $D07F
         LDA $DD00
         AND #$FC
         ORA #2           ;Bank 1
         STA $DD00
         JSR CLBUF2

:FPS     INC COUNT        ;Fps counter
         BNE :C1
         INC $D020

:C1      JSR READKEY
         JSR UPD8POS      ;Update position if necessary

         JSR UPD8ROT      ;Update second rotation matrix

         JSR PLOTSTAR

         JSR SORT         ;Construct visible object lst

:LDRAW   LDY NUMVIS       ;Draw objects from object list
         BEQ :DONE
         LDA OBLIST-1,Y   ;Get object number
         ASL
         TAX
         LDA VISTAB,X
         STA :JSR+1
         LDA VISTAB+1,X
         STA :JSR+2
:JSR     JSR DRAWOB1
         DEC NUMVIS
         BNE :LDRAW
:DONE    
         JMP MAINLOOP

VISTAB   DA DRAWOB1
         DA DRAWOB2
         DA DRAWOB3
         DA DRAWOB4
         DA DRAWOB5
         DA DRAWOB6
         DA DRAWOB7
         DA DRAWOB8
         DA DRAWOB9
         DA DRAWOB10
         DA DRAWOB11
         DA DRAWOB12
         DA DRAWOB13
         DA DRAWOB14
         DA DRAWOB15
         DA DRAWOB16
         DA DRAWOB17


ZEROS    DFB 0,0,0,0,0,0,0,0

SOLID    HEX FFFFFFFFFFFFFFFF
DITHER1  HEX 55AA55AA55AA55AA
DITHER2  HEX AA55AA55AA55AA55
BRICK    HEX 00EEEEEE00BBBBBB
CROSSSM  HEX 55EE55BB55EE55BB
ZIGS     HEX EEDDBB77EEDDBB77
ZAGS     HEX 77BBDDEE77BBDDEE
ZIGZAG   HEX BB55EEFFBB55EEFF
HOLES    HEX BD7EE7DBDBE77EBD
HSTRIPES HEX FF00FF00FF00FF00
VSTRIPES HEX AAAAAAAAAAAAAAAA
SQUARES  HEX FFAAFFAAFFAAFFAA
INVSQ    HEX 0055005500550055

*
* SORT -- Figure out which objects are visible, and
*   construct a sorted list of them.
*
* Conditions of visibility: 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.
*
SORT     
         LDA #00
         STA NUMVIS
         LDX NUMOBJS
         DEX
:LOOP    LDA HCZ,X        ;high byte
         CMP #$20         ;Greater than 8192?
         BCS :SKIP        ;(or negative)
         STA TEMP2
         LDA CZ,X         ;low byte
         STA TEMP1
         CMP #180         ;Subtract 180
         LDA TEMP2
         SBC #00
         BCC :SKIP

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

         LDA TEMP1        ;z-x>0
         CMP CX,X
         LDA TEMP2
         SBC HCX,X
         BMI :SKIP

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

         LDA TEMP1        ;z-y>0
         CMP CY,X
         LDA TEMP2
         SBC HCY,X
         BMI :SKIP

         STX TEMP3        ;Insert into list
         LDY NUMVIS       ;Largest z are at top of
         DEY
         BMI :FOUND       ;list
:LOOP2   LDX OBLIST,Y
         LDA CZ,X         ;if z larger
         CMP TEMP1
         LDA HCZ,X
         SBC TEMP2
         BCC :FOUND
         TXA              ;...then bump up the list
         STA OBLIST+1,Y
         DEY
         BPL :LOOP2
:FOUND   INY
         LDA TEMP3        ;Current object
         STA OBLIST,Y
         INC NUMVIS

         TAX
:SKIP    DEX
         BPL :LOOP
         RTS

*
* Start up de tune
*
INITMUS  
         JSR $1006        ;Initializes interrupt correctly
         SEI
         LDA #<IRQ
         STA $0314
         LDA #>IRQ
         STA $0315
         CLI
         RTS

IRQ      JSR $1000        ;Play
         JSR SCNKEY       ;Read keys
         LDA $DC0D
         PLA
         TAY
         PLA
         TAX
         PLA
         RTI


         PUT 'stars.s'    ;Starfield routines


*
* Object 1: A simple tetrahedron.
*
* (1,1,1) (1,-1,-1) (-1,1,-1) (-1,-1,1)

TETX     DFB 65,65,-65,-65
TETY     DFB 65,-65,65,-65
TETZ     DFB 65,-65,-65,65

* Point list

FACE1    DFB 0,1,2,0
FACE2    DFB 3,2,1,3
FACE3    DFB 3,0,2,3
FACE4    DFB 3,1,0,3

TETCX    DA 0             ;Center at center of screen
TETCY    DA 00
TETCZ    DA INITOFF       ;and back a little ways.


OB1POS   DFB 00           ;Position in the point list
OB1CEN   DFB 00           ;Position of center

*
* ]1, ]2, ]3 = object cx,cy,cz
*
INITOB   MAC
         LDA ]1
         STA C0X,X
         LDA ]1+1
         STA C0X+256,X
         LDA ]2
         STA C0Y,X
         LDA ]2+1
         STA C0Y+256,X
         LDA ]3
         STA C0Z,X
         LDA ]3+1
         STA C0Z+256,X
         <<<

INITOB1                   ;Install center into center list
         LDX NUMOBJS
         STX OB1CEN
         >>> INITOB,TETCX;TETCY;TETCZ
         INC NUMOBJS
         RTS

*
* Rotate and draw the first object.
*
* PLISTXLO etc. already point to correct offset.

* ]1,]2,]3 = object X,Y,Z point lists
SETPOINT MAC
         LDA #<]1         ;Set point pointers
         STA P0X
         LDA #>]1
         STA P0X+1
         LDA #<]2
         STA P0Y
         LDA #>]2
         STA P0Y+1
         LDA #<]3
         STA P0Z
         LDA #>]3
         STA P0Z+1
         <<<

DRAWOB1  
         LDX OB1CEN       ;Center index
ROTTET                    ;Alternative entry point

         >>> SETPOINT,TETX;TETY;TETZ

         LDY #4           ;Four points to rotate
         SEC              ;rotate and project
         JSR ROTPROJ

* Draw the object

SETFILL  MAC
                          ;]1 = number of points
                          ;]2 = Face point list
                          ;]3 = pattern
         LDY #]1
L1       LDA ]2,Y
         STA PQ,Y
         DEY
         BPL L1
         LDA #<]3
         STA FILLPAT
         LDA #>]3
         STA FILLPAT+1
         LDX #]1
         <<<

DRAWTET                   ;Yet another entry point

         >>> SETFILL,3;FACE1;DITHER1
         JSR POLYFILL

         >>> SETFILL,3;FACE2;ZIGZAG
         JSR POLYFILL

         >>> SETFILL,3;FACE3;CROSSSM
         JSR POLYFILL

         >>> SETFILL,3;FACE4;SOLID
         JMP POLYFILL

*
* Squaresville: A tetrahedron in the center, surrounded
*   by four cubes.
*

SQOFF    EQU 290          ;Offset unit

SQCX     EQU 3600         ;Center
SQCY     EQU 4000
SQCZ     EQU 8900+INITOFF

SQTETCX  DA SQCX
SQTETCY  DA SQCY
SQTETCZ  DA SQCZ

OB2CEN   DFB 00

* The center, a tetrahedron.
INITOB2  
         LDX NUMOBJS
         STX OB2CEN
         >>> INITOB,SQTETCX;SQTETCY;SQTETCZ
         INC NUMOBJS
         RTS

DRAWOB2  
         LDX OB2CEN       ;Center index
         JMP ROTTET       ;Use code above

*
* Object 3: A cube.
*
* (1,-1,1) (1,-1,-1) ...

CUBEX    DFB 55,55,55,55,-55,-55,-55,-55
CUBEY    DFB -55,-55,55,55,-55,-55,55,55
CUBEZ    DFB -55,55,55,-55,-55,55,55,-55

* Point list

CFACE1   DFB 0,3,2,1,0
CFACE2   DFB 4,5,6,7,4
CFACE3   DFB 0,4,7,3,0
CFACE4   DFB 1,2,6,5,1
CFACE5   DFB 0,1,5,4,0
CFACE6   DFB 2,3,7,6,2

CUBECX   DA SQCX+SQOFF    ;Center, 1 1 -1
CUBECY   DA SQCY+SQOFF
CUBECZ   DA SQCZ-SQOFF

OB3CEN   DFB 00           ;Position of center

INITOB3                   ;Install center into center list
         LDX NUMOBJS
         STX OB3CEN
         >>> INITOB,CUBECX;CUBECY;CUBECZ
         INC NUMOBJS
         RTS

*
* Rotate and draw cube.
*
* PLISTXLO etc. already point to correct offset.

DRAWOB3  
         LDX OB3CEN       ;Center index

ROTCUBE  JSR RFETCH       ;Use secondary rotation matrix

SETCUBE  >>> SETPOINT,CUBEX;CUBEY;CUBEZ

         LDY #8           ;Eight points to rotate
         SEC              ;rotate and project
         JSR ROTPROJ
         JSR IFETCH       ;Restore accumulation matrix

* Draw the object
DRAWCUBE 
         >>> SETFILL,4;CFACE1;BRICK
         JSR POLYFILL

         >>> SETFILL,4;CFACE2;ZIGS
         JSR POLYFILL

         >>> SETFILL,4;CFACE3;ZAGS
         JSR POLYFILL

         >>> SETFILL,4;CFACE4;HOLES
         JSR POLYFILL

         >>> SETFILL,4;CFACE5;CROSSSM
         JSR POLYFILL

         >>> SETFILL,4;CFACE6;DITHER2
         JMP POLYFILL

*
* Object 4: another cube.
*

CUBE2CX  DA SQCX-SQOFF    ;Center, -1 1 1
CUBE2CY  DA SQCY+SQOFF
CUBE2CZ  DA SQCZ+SQOFF

OB4CEN   DFB 00           ;Position of center

INITOB4                   ;Install center into center list
         LDX NUMOBJS
         STX OB4CEN
         >>> INITOB,CUBE2CX;CUBE2CY;CUBE2CZ
         INC NUMOBJS
         RTS

DRAWOB4  
         LDX OB4CEN       ;Center index
         JSR R2FETCH      ;Use second permutation
         JMP SETCUBE

*
* Object 5: another cube.
*

CUBE3CX  DA SQCX+SQOFF    ;Center, 1 -1 1
CUBE3CY  DA SQCY-SQOFF
CUBE3CZ  DA SQCZ+SQOFF

OB5CEN   DFB 00           ;Position of center

INITOB5                   ;Install center into center list
         LDX NUMOBJS
         STX OB5CEN
         >>> INITOB,CUBE3CX;CUBE3CY;CUBE3CZ
         INC NUMOBJS
         RTS
DRAWOB5  
         LDX OB5CEN       ;Center index
         JSR R3FETCH
         JMP SETCUBE


*
* Object 6: the fourth cube.  It points back to the center
*   of the world, and does not rotate.


CUBE4CX  DA SQCX-SQOFF    ;Center, -1 -1 -1
CUBE4CY  DA SQCY-SQOFF
CUBE4CZ  DA SQCZ-SQOFF

OB6CEN   DFB 00           ;Position of center

INITOB6                   ;Install center into center list
         LDX NUMOBJS
         STX OB6CEN
         >>> INITOB,CUBE4CX;CUBE4CY;CUBE4CZ
         INC NUMOBJS
         RTS

*
* Rotate and draw cube.  This time, use accumulation
*   matrix.  It is at -1, -1, -1 and hence points
*   back to the center of the world.
*
DRAWOB6  
         LDX OB6CEN
         >>> SETPOINT,CUBEX;CUBEY;CUBEZ

         LDY #8           ;Eight points to rotate
         SEC              ;rotate and project
         JSR ROTPROJ
         JMP DRAWCUBE

*
* All-Stars: A bunch of the cool star things.
*

STOFF    EQU 530          ;Offset unit

STCX     EQU -8000        ;Center
STCY     EQU 1200
STCZ     EQU -400+INITOFF

STAR1CX  DA STCX
STAR1CY  DA STCY
STAR1CZ  DA STCZ

OB7CEN   DFB 00

STAR1X   DFB 25,-25,25,-25,50,50,-50,-50
STAR1Y   DFB -25,-25,25,25,-50,50,50,-50
STAR1Z   DFB 25,-25,-25,25,-50,50,-50,50

S1T1F1   DFB 4,2,0,4      ;Star 1, Tine 1, face 1
S1T1F2   DFB 4,1,2,4
S1T1F3   DFB 4,0,1,4

S1T2F1   DFB 5,0,2,5
S1T2F2   DFB 5,3,0,5
S1T2F3   DFB 5,2,3,5

S1T3F1   DFB 6,2,1,6
S1T3F2   DFB 6,3,2,6
S1T3F3   DFB 6,1,3,6

S1T4F1   DFB 7,1,0,7
S1T4F2   DFB 7,0,3,7
S1T4F3   DFB 7,3,1,7

INITOB7  
         LDX NUMOBJS
         STX OB7CEN
         >>> INITOB,STAR1CX;STAR1CY;STAR1CZ
         INC NUMOBJS
         RTS

DRAWOB7  
         LDX OB7CEN       ;Center index

ROTSTAR1 JSR RFETCH       ;Use secondary rotation matrix

SETSTAR1 >>> SETPOINT,STAR1X;STAR1Y;STAR1Z

         LDY #8           ;Eight points to rotate
         SEC              ;rotate and project
         JSR ROTPROJ

         JSR ST1SORT      ;Sort the tines
         JSR IFETCH       ;Restore accumulation matrix

* Draw the object.  In order to handle overlaps correctly,
* the tines must first be depth-sorted, above.
DRAWST1  
         LDX #03
ST1LOOP  STX TEMP
         LDY T1LIST,X     ;Sorted tine list
         BEQ :TINE1
         DEY
         BNE :C1
         JMP :TINE2
:C1      DEY
         BNE :TINE4
         JMP :TINE3
:TINE4   
         >>> SETFILL,3;S1T4F1;SOLID
         JSR POLYFILL
         >>> SETFILL,3;S1T4F2;DITHER1
         JSR POLYFILL
         >>> SETFILL,3;S1T4F3;DITHER2
         JSR POLYFILL
:NEXT    LDX TEMP
         DEX
         BPL ST1LOOP
         RTS

:TINE1   >>> SETFILL,3;S1T1F1;CROSSSM
         JSR POLYFILL
         >>> SETFILL,3;S1T1F2;SOLID
         JSR POLYFILL
         >>> SETFILL,3;S1T1F3;ZIGZAG
         JSR POLYFILL
         JMP :NEXT

:TINE2   >>> SETFILL,3;S1T2F1;ZIGS
         JSR POLYFILL
         >>> SETFILL,3;S1T2F2;ZAGS
         JSR POLYFILL
         >>> SETFILL,3;S1T2F3;SOLID
         JSR POLYFILL
         JMP :NEXT

:TINE3   >>> SETFILL,3;S1T3F1;BRICK
         JSR POLYFILL
         >>> SETFILL,3;S1T3F2;HOLES
         JSR POLYFILL
         >>> SETFILL,3;S1T3F3;SOLID
         JSR POLYFILL
         JMP :NEXT


T1LIST   DS 6             ;Tine sort list
T1Z      DS 6

*
* Sort the tines.  All that matters is the z-coord,
* thus we simply dot the third row of the matrix
* with the tine endpoint, add 128 for convenience,
* and figure out where stuff goes in the list.
*
ST1SORT                   ;Sort the tines
         LDX #00
         LDA MATRIX+6     ;Tine 1: 1,-1,-1
         SEC
         SBC MATRIX+7
         SEC
         SBC MATRIX+8
         EOR #$80         ;Add 128
         STA T1Z          ;z-coord
         STX T1LIST

         LDA MATRIX+6     ;Tine 2: 1,1,1
         CLC
         ADC MATRIX+7
         CLC
         ADC MATRIX+8
         EOR #$80
         STA T1Z+1
         INX
         STX T1LIST+1

         LDA MATRIX+7     ;Tine 3: -1,1,-1
         SEC
         SBC MATRIX+6
         SEC
         SBC MATRIX+8
         EOR #$80
         STA T1Z+2
         INX
         STX T1LIST+2

         LDA MATRIX+8     ;Tine 4: -1,-1,1
         SEC
         SBC MATRIX+7
         SEC
         SBC MATRIX+6
         EOR #$80
         STA T1Z+3
         INX
         STX T1LIST+3

         CMP T1Z+2        ;Now bubble-sort the list
         BCS :C1          ;largest values on top
         DEX              ;So find the largest value!
         LDA T1Z+2
:C1      CMP T1Z+1
         BCS :C2
         LDX #1
         LDA T1Z+1
:C2      CMP T1Z
         BCS :C3
         LDX #00
         LDA T1Z
:C3      LDY T1Z+3        ;...and stick it at the top
         STA T1Z+3
         TYA
         STA T1Z,X        ;swap with largest
         LDY T1LIST+3     ;T1LIST contains positions
         STX T1LIST+3     ;of tines
         TYA
         STA T1LIST,X

         LDX #2
         LDA T1Z+2        ;Top is largest, now find next-
         CMP T1Z+1        ;largest
         BCS :C4
         DEX
         LDA T1Z+1
:C4      CMP T1Z
         BCS :C5
         LDX #00
         LDA T1Z
:C5      LDY T1Z+2
         STA T1Z+2
         TYA
         STA T1Z,X
         LDY T1LIST+2
         LDA T1LIST,X
         STA T1LIST+2
         TYA
         STA T1LIST,X

         LDA T1Z+1        ;Only two left
         CMP T1Z
         BCS :DONE
         LDY T1LIST+1     ;Swap last two list elements
         LDA T1LIST
         STA T1LIST+1
         STY T1LIST
:DONE    RTS              ;T1LIST contains sorted list
                          ;of tine positions, farthest
                          ;ones at the top.

*
* Sort the tines for the second star type.  Since the
* points lie exactly on an axis, the z-coord is a
* single element of the third row of the rotation
* matrix.
*

ST2SORT                   ;Sort the tines
         LDX #00
         LDA MATRIX+6     ;Tine 0: 1,0,0
         EOR #$80         ;Add 128
         STA T1Z          ;z-coord
         STX T1LIST

                          ;Tine 1: -1,0,0
         EOR #$7F         ;Note the EOR $80 above...
         CLC
         ADC #$81
         STA T1Z+1
         INX
         STX T1LIST+1

         LDA MATRIX+7     ;Tine 2: 0,1,0
         EOR #$80
         STA T1Z+2
         INX
         STX T1LIST+2

                          ;Tine 3: 0,-1,0
         EOR #$7F
         CLC
         ADC #$81
         STA T1Z+3
         INX
         STX T1LIST+3

         LDA MATRIX+8     ;Tine 4: 0,0,1
         EOR #$80
         STA T1Z+4
         INX
         STX T1LIST+4

         EOR #$7F         ;Tine 5: 0,0,-1
         CLC
         ADC #$81
         STA T1Z+5
         INX
         STX T1LIST+5

                          ;A kind of bubbly sort.
         LDX #5           ;Loop counter
:LOOP1   TXA
         TAY
         LDA T1Z,X
         STY TEMP         ;Largest value
:LOOP2   DEY
         BMI :OUT
:LOOP2A  CMP T1Z,Y
         BCS :LOOP2
         STY TEMP         ;TEMP will hold largest element
         LDA T1Z,Y        ;number
         DEY
         BPL :LOOP2A
:OUT     
         LDY T1Z,X        ;Swap values t1,X with t1,TEMP
         STA T1Z,X        ;Now contains largest
         TYA
         LDY TEMP
         STA T1Z,Y
         LDA T1LIST,Y     ;Swap list,X with list,TEMP
         STA TEMP2
         LDA T1LIST,X
         STA T1LIST,Y
         LDA TEMP2
         STA T1LIST,X

         DEX
         BNE :LOOP1

:DONE    RTS              ;T1LIST contains sorted list
                          ;of tine positions, farthest
                          ;ones at the top.

*
* Object 8 -- A star built from a cube.
*

STAR2CX  DA STCX+STOFF+STOFF
STAR2CY  DA STCY-STOFF
STAR2CZ  DA STCZ

OB8CEN   DFB 00

STAR2X   DFB 94,-94,0,0,0,0,15,15,15,15,-15,-15,-15,-15
STAR2Y   DFB 0,0,94,-94,0,0,15,15,-15,-15,15,15,-15,-15
STAR2Z   DFB 0,0,0,0,94,-94,15,-15,-15,15,15,-15,-15,15

S2T0F1   DFB 0,8,7,0      ;Star 2, Tine 0, face 1
S2T0F2   DFB 0,7,6,0
S2T0F3   DFB 0,6,9,0
S2T0F4   DFB 0,9,8,0

S2T1F1   DFB 1,11,12,1
S2T1F2   DFB 1,12,13,1
S2T1F3   DFB 1,13,10,1
S2T1F4   DFB 1,10,11,1

S2T2F1   DFB 2,7,11,2
S2T2F2   DFB 2,6,7,2
S2T2F3   DFB 2,10,6,2
S2T2F4   DFB 2,11,10,2

S2T3F1   DFB 3,12,8,3
S2T3F2   DFB 3,8,9,3
S2T3F3   DFB 3,9,13,3
S2T3F4   DFB 3,13,12,3

S2T4F1   DFB 4,9,6,4
S2T4F2   DFB 4,6,10,4
S2T4F3   DFB 4,10,13,4
S2T4F4   DFB 4,13,9,4

S2T5F1   DFB 5,8,12,5
S2T5F2   DFB 5,12,11,5
S2T5F3   DFB 5,11,7,5
S2T5F4   DFB 5,7,8,5

INITOB8  
         LDX NUMOBJS
         STX OB8CEN
         >>> INITOB,STAR2CX;STAR2CY;STAR2CZ
         INC NUMOBJS
         RTS

DRAWOB8  
         LDX OB8CEN       ;Center index

ROTSTAR2 JSR R2FETCH      ;Use secondary rotation matrix

SETSTAR2 >>> SETPOINT,STAR2X;STAR2Y;STAR2Z

         LDY #14          ;Fourteen points to rotate
         SEC              ;rotate and project
         JSR ROTPROJ

         JSR ST2SORT      ;Sort the tines
         JSR IFETCH       ;Restore accumulation matrix

* Draw the object.  In order to handle overlaps correctly,
* the tines must first be depth-sorted, above.
DRAWST2  
         LDX #05
ST2LOOP  STX TEMP
         LDY T1LIST,X     ;Sorted tine list
         LDA :JTABLO,Y
         STA :JMP+1
         LDA :JTABHI,Y
         STA :JMP+2
:JMP     JMP ST2LOOP
:NEXT    LDX TEMP
         DEX
         BPL ST2LOOP
         RTS

:JTABLO  DFB <:TINE0,<:TINE1,<:TINE2,<:TINE3,<:TINE4
         DFB <:TINE5
:JTABHI  DFB >:TINE0,>:TINE1,>:TINE2,>:TINE3,>:TINE4
         DFB >:TINE5

:TINE0   
         >>> SETFILL,3;S2T0F1;SQUARES
         JSR POLYFILL
         >>> SETFILL,3;S2T0F2;DITHER1
         JSR POLYFILL
         >>> SETFILL,3;S2T0F3;DITHER2
         JSR POLYFILL
         >>> SETFILL,3;S2T0F4;SOLID
         JSR POLYFILL
         JMP :NEXT

:TINE1   
         >>> SETFILL,3;S2T1F1;SQUARES
         JSR POLYFILL
         >>> SETFILL,3;S2T1F2;HSTRIPES
         JSR POLYFILL
         >>> SETFILL,3;S2T1F3;VSTRIPES
         JSR POLYFILL
         >>> SETFILL,3;S2T1F4;SOLID
         JSR POLYFILL
         JMP :NEXT

:TINE2   
         >>> SETFILL,3;S2T2F1;SOLID
         JSR POLYFILL
         >>> SETFILL,3;S2T2F2;DITHER2
         JSR POLYFILL
         >>> SETFILL,3;S2T2F3;HOLES
         JSR POLYFILL
         >>> SETFILL,3;S2T2F4;DITHER1
         JSR POLYFILL
         JMP :NEXT

:TINE3   
         >>> SETFILL,3;S2T3F1;SOLID
         JSR POLYFILL
         >>> SETFILL,3;S2T3F2;ZIGS
         JSR POLYFILL
         >>> SETFILL,3;S2T3F3;ZAGS
         JSR POLYFILL
         >>> SETFILL,3;S2T3F4;VSTRIPES
         JSR POLYFILL
         JMP :NEXT

:TINE4   
         >>> SETFILL,3;S2T4F1;SOLID
         JSR POLYFILL
         >>> SETFILL,3;S2T4F2;VSTRIPES
         JSR POLYFILL
         >>> SETFILL,3;S2T4F3;SQUARES
         JSR POLYFILL
         >>> SETFILL,3;S2T4F4;CROSSSM
         JSR POLYFILL
         JMP :NEXT

:TINE5   
         >>> SETFILL,3;S2T5F1;ZIGS
         JSR POLYFILL
         >>> SETFILL,3;S2T5F2;HSTRIPES
         JSR POLYFILL
         >>> SETFILL,3;S2T5F3;ZAGS
         JSR POLYFILL
         >>> SETFILL,3;S2T5F4;SOLID
         JSR POLYFILL
         JMP :NEXT

* A few more stars

OB9CEN   DFB 0

OB9CX    DA STCX+STOFF+STOFF
OB9CY    DA STCY-STOFF
OB9CZ    DA STCZ-STOFF-STOFF

INITOB9  
         LDX NUMOBJS
         STX OB9CEN
         >>> INITOB,OB9CX;OB9CY;OB9CZ
         INC NUMOBJS
         RTS

DRAWOB9  
         LDX OB9CEN       ;Center index

         JSR RFETCH       ;Use secondary rotation matrix
         JMP SETSTAR2


OB10CEN  DFB 0

OB10CX   DA STCX+STOFF+STOFF+STOFF
OB10CY   DA STCY-STOFF
OB10CZ   DA STCZ

INITOB10 
         LDX NUMOBJS
         STX OB10CEN
         >>> INITOB,OB10CX;OB10CY;OB10CZ
         INC NUMOBJS
         RTS

DRAWOB10 
         LDX OB10CEN      ;Center index

         JSR R3FETCH      ;Use secondary rotation matrix
         JMP SETSTAR1

OB11CEN  DFB 0

OB11CX   DA STCX
OB11CY   DA STCY+STOFF+STOFF
OB11CZ   DA STCZ-STOFF-STOFF-STOFF

INITOB11 
         LDX NUMOBJS
         STX OB11CEN
         >>> INITOB,OB11CX;OB11CY;OB11CZ
         INC NUMOBJS
         RTS

DRAWOB11 
         LDX OB11CEN      ;Center index

         JSR R2FETCH      ;Use secondary rotation matrix
         JMP SETSTAR1

*
* Pyromania -- A series of pyramids (tetrahedrons) all
*   in a straight line, to give a sense of depth.
*

PYRCX    EQU 600
PYRCY    EQU -800
PYRCZ    EQU -8800+INITOFF

PYROFF   EQU 600

OB12CX   DA PYRCX
OB12CY   DA PYRCY
OB12CZ   DA PYRCZ

OB12CEN  DFB 00

INITOB12 
         LDX NUMOBJS
         STX OB12CEN
         >>> INITOB,OB12CX;OB12CY;OB12CZ
         INC NUMOBJS
         RTS

DRAWOB12 
         LDX OB12CEN      ;Center index
         JMP ROTTET       ;Use tetrahedron code above


OB13CX   DA PYRCX
OB13CY   DA PYRCY
OB13CZ   DA -PYROFF+PYRCZ

OB13CEN  DFB 00

INITOB13 
         LDX NUMOBJS
         STX OB13CEN
         >>> INITOB,OB13CX;OB13CY;OB13CZ
         INC NUMOBJS
         RTS

DRAWOB13 
         LDX OB13CEN      ;Center index
         JMP ROTTET       ;Use tetrahedron code above


OB14CX   DA PYRCX
OB14CY   DA PYRCY
OB14CZ   DA -2*PYROFF+PYRCZ

OB14CEN  DFB 00

INITOB14 
         LDX NUMOBJS
         STX OB14CEN
         >>> INITOB,OB14CX;OB14CY;OB14CZ
         INC NUMOBJS
         RTS

DRAWOB14 
         LDX OB14CEN      ;Center index
         JMP ROTTET       ;Use tetrahedron code above


OB15CX   DA PYRCX
OB15CY   DA PYRCY
OB15CZ   DA -3*PYROFF+PYRCZ

OB15CEN  DFB 00

INITOB15 
         LDX NUMOBJS
         STX OB15CEN
         >>> INITOB,OB15CX;OB15CY;OB15CZ
         INC NUMOBJS
         RTS

DRAWOB15 
         LDX OB15CEN      ;Center index
         JMP ROTTET       ;Use tetrahedron code above


OB16CX   DA PYRCX
OB16CY   DA PYRCY
OB16CZ   DA -4*PYROFF+PYRCZ

OB16CEN  DFB 00

INITOB16 
         LDX NUMOBJS
         STX OB16CEN
         >>> INITOB,OB16CX;OB16CY;OB16CZ
         INC NUMOBJS
         RTS

DRAWOB16 
         LDX OB16CEN      ;Center index
         JMP ROTTET       ;Use tetrahedron code above

*
* Finally, the boneyard.  Just some Elite ships.
*

BONECX   EQU 400
BONECY   EQU -8000
BONECZ   EQU -660

BONEOFF  EQU 800          ;Wiiiide spacing.

* Cobra Mk. III

COBCX    DA BONECX
COBCY    DA BONECY
COBCZ    DA BONECZ

COBX     DFB 48,-42,-42,-8,-8,-42,-42,48,-42,-42,-42,8
         DFB -42,-42,-42,-42,-42,-42,-42,-42
COBY     DFB 21,21,84,76,-76,-84,-21,-21,-46,0,46,0
         DFB -8,-8,-25,-25,8,25,25,8
COBZ     DFB -16,-16,-4,-4,-4,-4,-16,-16,8,16,8,16
         DFB 4,-8,-6,2,4,2,-6,-8

COBF1    DFB 0,1,2,3,0
COBF2    DFB 0,7,6,1,0
COBF3    DFB 4,5,6,7,4
COBF4    DFB 0,11,7,0
COBF5    DFB 3,2,10,3
COBF6    DFB 0,3,10,0
COBF7    DFB 0,10,11,0
COBF8    DFB 9,11,10,9
COBF9    DFB 5,4,8,5
COBF10   DFB 4,7,8,4
COBF11   DFB 7,11,8,7
COBF12   DFB 11,9,8,11
COBF13   DFB 9,10,2,1,6,5,8,9 ;Backplate
COBF14   DFB 13,14,15,12,13   ;Engines
COBF15   DFB 17,18,19,16,17

OB17CEN  DFB 00           ;Position of center

INITOB17                  ;Install center into center list
         LDX NUMOBJS
         STX OB17CEN
         >>> INITOB,COBCX;COBCY;COBCZ
         INC NUMOBJS
         RTS

DRAWOB17 
         LDX OB17CEN
         JSR RFETCH
         >>> SETPOINT,COBX;COBY;COBZ

         LDY #20          ;Twenty points to rotate
         SEC              ;rotate and project
         JSR ROTPROJ
         JSR IFETCH       ;Restore accumulation matrix

* Draw
         >>> SETFILL,4;COBF1;ZIGS
         JSR POLYFILL

         >>> SETFILL,4;COBF2;VSTRIPES
         JSR POLYFILL

         >>> SETFILL,4;COBF3;ZAGS
         JSR POLYFILL

         >>> SETFILL,3;COBF4;INVSQ
         JSR POLYFILL

         >>> SETFILL,3;COBF5;ZAGS
         JSR POLYFILL

         >>> SETFILL,3;COBF6;VSTRIPES
         JSR POLYFILL

         >>> SETFILL,3;COBF7;SQUARES
         JSR POLYFILL

         >>> SETFILL,3;COBF8;DITHER1
         JSR POLYFILL

         >>> SETFILL,3;COBF9;ZIGS
         JSR POLYFILL

         >>> SETFILL,3;COBF10;VSTRIPES
         JSR POLYFILL

         >>> SETFILL,3;COBF11;SQUARES
         JSR POLYFILL

         >>> SETFILL,3;COBF12;DITHER2
         JSR POLYFILL

         >>> SETFILL,7;COBF13;INVSQ
         JSR POLYFILL

         >>> SETFILL,4;COBF14;HOLES
         JSR POLYFILL

         >>> SETFILL,4;COBF15;HOLES
         JMP POLYFILL


         PUT 'worldutils.s' ;Utility routines, like
                          ;UPD8POS, READKEY, etc.
