*-------------------------------
*
* main4.s
*
* This is the main part of the code for the 4k demo contest.
* It initializes the various tables and contains the main
* loop, as well as the rotation and projection routines.
*
* Stephen L. Judd 6/4/96
* Written in a period of cooling off from PhD Qualifiers
* four days after the quals, on June 4.  Four days of
* coding.
                          
         DSK "main4"      
                          
         REL              
                          
DRAW     EXT              ;External procedures
FILL     EXT              
SPLAT    EXT              
SYMM     EXT              
DEFOBS   EXT              
MUSINIT  EXT              
                          
* Were I not so lazy perhaps all variables could be put
* into an include file.
                          
* Constants
                          
BUFF1    EQU $3000        ;First character set
BUFF2    EQU $3800        ;Second character set
                          
SINTAB   EQU $0F00        ;Table of sines, right below us
HISIN    EQU $60          ;Sin table currently starts at $6000
PATTERN1 EQU $C100        ;Table of patterns to fill with
PATTERN2 EQU $C180        
MUSTABS  EQU $C200        ;Music routine uses $C200-$C3FF
OBLISTW  EQU $C400        ;The actual object points
OBLISTX  EQU $C480        
OBLISTY  EQU $C500        
OBLISTZ  EQU $C580        
PLISTW   EQU $C600        ;List of rotated+projected points
PLISTX   EQU $C680        
PLISTY   EQU $C700        
PLISTZ   EQU $C780        
BITP     EQU $C800        ;Bit table for line routine
LO40     EQU $C900        ;Tables of 40*x/8
HI40     EQU $C980        ;To locate offset into buffer
LO96     EQU $CA00        ;for a given column
HI96     EQU $CA80        
REVLIST  EQU $CB00        ;Used by symmetry routine
CONLIST1 EQU $CC00        ;First point in connection list
CONLIST2 EQU $CD00        ;Second point in connection list
DRAWCON  EQU $CE00        ;List of connection indices
CONFLAG  EQU $CF00        ;Flags to keep from redrawing stuff
                          
SCRNLOC  EQU 1024         ;Where is the screen located?
                          
* VIC
                          
VMCSB    EQU $D018        
BKGND    EQU $D020        
BORDER   EQU $D021        
                          
* Kernal
                          
CINT     EQU $FF81        
IOINIT   EQU $FF84        
CHROUT   EQU $FFD2        
SCNKEY   EQU $FF9F        
GETIN    EQU $FFE4        
                          
* Some variables
                          
MUSVARS  EQU $03          ;Locations $03-$0D are used by
                          ;the music routine.
                          
SIN1     EQU $57          ;Pointers to sine and cosine
COS1     EQU $59          ;tables.
SIN2     EQU $5B          
COS2     EQU $5D          
PROJTAB  EQU $5F          ;Pointer to projection tables
                          
COLSTEP  = $51            ;Lines: How many bytes per col
COUNTPTS = $52            
WXINC    = $53            
XYINC    = $54            
YZINC    = $55            
XZINC    = $56            
SWX      = $63            
SXY      = $64            ;These are the angles used by
SYZ      = $65            ;ROTPROJ
SXZ      = $66            
                          
DX       EQU $67          
DY       EQU $68          
                          
NUMTOROT EQU $69          ;Number of points to rotate in ROTPROJ
                          
POINT1   EQU $6A          ;Some spare pointers
POINT2   EQU $6C          
SCREENP  EQU $6E          ;Pointer used by screen plotter
COLORP   EQU $70          ;pointer into color RAM
COLOR    EQU $72          ;Color to store in color RAM
                          
NUMSIDE  EQU $8B          ;# of chars per side of square
                          
BUFFER   EQU $A3          ;Pointer to drawing buffer
                          
NUMOB1   EQU $A5          ;Number of points in object 1
NUMOB12  EQU $A6          
TOTNUM   EQU $A7          ;Total number of points in list
OFFSET   EQU $A8          ;Offset into grid
NUMCONS  EQU $A9          ;Total number of connections
                          
COUNT    EQU $AA          ;A counter
STARCHAR EQU $AB          ;Basically measures which object
                          ;we are on
RANDOM   EQU $AC          ;Used by GETRAND (two bytes)
OLDCOL   EQU $AE          
COUNT3D  EQU $AF          ;Another counter
IMONOB   EQU $B0          ;I'm on object number...
                          
DOTTED   EQU $B1          ;Flag for dotted lines.
DOTFLAG  EQU $B2          ;Flag to draw or not draw
                          ;dotted lines.
                          
X1       EQU $FB          ;Points for drawing a line
Y1       EQU $FC          ;These zero page addresses
X2       EQU $FD          ;don't conflict with BASIC
Y2       EQU $FE          
OLDX     EQU $FD          
CHUNK    EQU $FE          
TEMP1    EQU $FB          ;Of course, could conflict with x1
TEMP2    EQU $FC          ;Temporary variables
ZTEMP    EQU $02          ;Used for buffer swap.  Don't touch.
ACC      EQU $22          ;Used by math routine
AUX      EQU $24          
EXT      EQU $26          
                          
*-------------------------------
*
* The observation is that after a RS/RESTORE and SYS
* the program works fine.  This part therefore redirects
* the BASIC vector to the program and calls the BRK routine.
*
* It works!  AAAAAAAAAAAAHHHHHHHHHHH!
                          
         LDA #<START      
         STA $0302        
         LDA #>START      
         STA $0303        
         JMP $FE66        ;Warm start routine.
                          
START    ENT              ;Starting address of program
         LDA #$36         
         STA $01          ;BASIC goes out
                          
* LDA VMCSB
* AND #%00001111 ;Screen memory to 1024
* ORA #%00010000
* LDA VMCSB
* AND #%11110001 ;Start here so that swap buffers
* ORA #%00001110 ;will work right
* STA VMCSB
                          
         LDA #%00011110   ;Dork
         STA VMCSB        
                          
         SEI              
         JSR MUSINIT      ;Initialize music
         CLI              ;Start up music
                          
**** Clear screen and set up "bitmap"
SETUP                     
                          
* LDA #<BUFF1
* STA BUFFER
* LDA #>BUFF1
* STA BUFFER+1
* LDY #$00
* LDX #16 ;Assuming both buffers are
* LDA #$00 ;back-to-back
*:BLOOP STA (BUFFER),Y
* INY
* BNE :BLOOP
* INC BUFFER+1
* DEX
* BNE :BLOOP
                          
**** Clear front buffer for circle plotter thing.
*
* LDA #>BUFF2
* STA ZTEMP
* JSR CLRBUFF
                          
                          
**** Set up buffers
                          
* LDA #<BUFF1
* STA BUFFER
         LDA #>BUFF1      
* STA BUFFER+1
         STA ZTEMP        ;ztemp will make life simple for us
                          
         LDA #6           
         STA COUNT        
                          
         LDA #00          
         LDX #$15         
:L1      STA $51,X        
         DEX              
         BPL :L1          
* STA WXINC
* STA XYINC
* STA YZINC
* STA XZINC
* STA SWX
* STA SXY
* STA SYZ
* STA SXZ
         STA $D020        
         STA IMONOB       
                          
* LDA #00 ;Use this character to...
* JSR CLEARSET ;Clear and set up screen
                          
                          
*-------------------------------
* Set up tables
*
* The program expects a single sine table at $C000
* of f(x)=64*sin(x)+64, x=0..127
*
* First the table is extended by 32 bytes to generate
* a simple cosine table (cos(x) = sin(x+pi/2)).
* From this table a series of tables is created,
* g(r,x) = r*sin(x), via the relation
*       g(r,x) = r*f(x)/64 - r
*
* Moreover, a projection table of h(r,x)=r*d/(z-z0)
* is stuck in the same 256-byte chunk.
                          
TABLES                    
* Set up BITP table for line drawing routine.
BITPTAB                   
* LDY #00
         TAY              ;A contains zero
         LDA #$FF         ;Yes, I really need that byte!
:LOOP3   STA BITP,Y       
         LSR              
         BNE :CONT        
         LDA #$FF         
:CONT    INY              
         BNE :LOOP3       
                          
* Set up column index tables for DRAW
DRAWTAB                   
:LOOP    TYA              
         AND #$F8         
         STA AUX          
         LDA #5           ;40*x div 8=5*x and $F8
         STA ACC          
         JSR MULT         
         STA HI40,Y       
         LDA ACC          
         STA LO40,Y       
         LDA #12          ;Now 96*x div 8
         STA ACC          
         JSR MULT         
         STA HI96,Y       
         LDA ACC          
         STA LO96,Y       
         INY              
         BPL :LOOP        
                          
* Set up trig tables
                          
         LDY #31          ;First extend the table
:EXTEND  LDA SINTAB,Y     
         STA SINTAB+128,Y 
         DEY              
         BPL :EXTEND      
                          
         LDA #32          
         STA COS1         
         STA COS2         
         LDA #128+32      ;96 entries for ztab
         STA PROJTAB      
         LDA #$90         ;Start in the middle and
         STA SIN1+1       ;move outwards
         STA SIN2+1       
         LDA #$00         
         STA SIN1         
         STA SIN2         
                          
         TAX              
:LOOP1   LDY #00          
         STX AUX          
:LOOP2   LDA SINTAB,Y     
         STA ACC          
         JSR MULT         ;Accumulator contains hi, ACC lo
         ASL ACC          ;Next, divide by 64
         ROL              
         ASL ACC          
         ROL              
         SEC              
         SBC AUX          ;And subtract off r
         STA (SIN1),Y     ;Store positive r in top half
         EOR #$FF         
         CLC              
         ADC #$01         
         STA (SIN2),Y     ;2's complement in bottom half
         INY              
         BNE :LOOP2       
                          
*===============================
*
* This somewhat neat thing must be chopped out to get
* the thing to crunch AND run :(
*
         DO 0             
                          
:TEST    LDA SIN1+1       ;Test those tables!
         STA COS1+1       ;Get a table of cosines too
:CIRCLE                   
* LDA #00
* STA BUFFER
         LDA (COS1),Y     ;x=rcos(t)
         CLC              
         ADC #48          ;Center in a 96x96 grid
         TAX              
         LDA LO96,X       ;Test out the column indices
         STA BUFFER       
         LDA HI96,X       
         CLC              
         ADC #>BUFF2      
         STA BUFFER+1     ;Now we're in the right column
         LDA (SIN1),Y     
         CLC              
         ADC #48          
         STY TEMP1        
         TAY              ;y=r*sin(t)
         LDA BITP,X       
         LSR              ;Only want the bit
         EOR BITP,X       
         ORA (BUFFER),Y   
         STA (BUFFER),Y   
         LDY TEMP1        
         INY              
         BPL :CIRCLE      
         FIN              
*===============================
                          
         INC SIN1+1       ;Move to the next page
         DEC SIN2+1       
         LDX AUX          
         INX              
         CPX #49          ;Note that this overwrites original
         BNE :LOOP1       ;table!
                          
                          
*
* Try this here to see if ABcrunch will then work right.
*
* SEI
* JSR MUSINIT ;Start up music
* CLI
                          
*
* Set up reverse table.  This sets up a table of reversed
* bit positions, for use in reflecting an object through
* x=0.
REVSET                    
* Y is set to zero above
* LDY #00
:CROW    STY TEMP1        
         LDX #8           
:SERVO   LSR TEMP1        
         ROL              
         DEX              
         BNE :SERVO       
         STA REVLIST,Y    
         INY              
         BNE :CROW        
                          
*
* Set up custom character data
*
         LDX #31          ;4 chars * 8
:JOEL    LDA CHARDAT,X    
         STA 8*247+BUFF1,X ;Chars 247-250 are custom
         STA 8*247+BUFF2,X
         EOR #$FF         
         STA 8*251+BUFF1,X ;with 251-254 reversed
         STA 8*251+BUFF2,X
         DEX              ;255 is clear character
         BPL :JOEL        
                          
*
* Sort-of seed the random number generator
*
* LDA $DC09 ;TOD seconds reg
* STA RANDOM
                          
*
* Initialization going into the main loop
*
INITMAIN                  
         DEC IMONOB       
         LDX IMONOB       
         BPL :CONT0       
         LDX #3           ;We are on object 3 now
         STX IMONOB       
* Set up the pattern fill table
         LDX #40          
:CAMBOT  TXA              
         AND #$07         ;modulo-8
         TAY              
         LDA 252*8+BUFF1,Y
         STA PATTERN1,X   
         LDA 254*8+BUFF1,Y
         STA PATTERN2,X   
         DEX              
         BPL :CAMBOT      
         LDA #251         ;Fill char
         BNE :DONE        
                          
:CONT0                    ;CPX #00 ;Object 0?
         BNE :CONT1       
         LDX #40          
:FRANK   TXA              
         AND #$07         ;modulo-8
         TAY              
         LDA 247*8+BUFF1,Y
         STA PATTERN1,X   
         LDA 248*8+BUFF1,Y
         STA PATTERN2,X   
         DEX              
         BPL :FRANK       
         LDA #253         ;Fill char
         BNE :DONE        
                          
:CONT1   CPX #01          ;Object 1?
         BNE :CONT2       
         LDX #40          
:CLAYTON TXA              
         AND #$07         ;modulo-8
         TAY              
         LDA 251*8+BUFF1,Y
         STA PATTERN1,X   
         LDA 249*8+BUFF1,Y
         STA PATTERN2,X   
         DEX              
         BPL :CLAYTON     
         LDA #247         ;Fill char
         BNE :DONE        
                          
:CONT2   LDX #40          
:MIKE    TXA              
         AND #$07         ;modulo-8
         TAY              
         LDA 254*8+BUFF1,Y
         STA PATTERN1,X   
         LDA 248*8+BUFF1,Y
         STA PATTERN2,X   
         DEX              
         BPL :MIKE        
         LDA #250         ;Fill char
:DONE    JSR CLEARSET     
                          
*
* This guy clears the object lists.
*
         LDX #00          
         TXA              
:LOP     STA OBLISTW,X    
         STA OBLISTY,X    
         INX              
         BNE :LOP         
         STA OLDCOL       
         STA COUNT3D      
         STA DOTFLAG      ;Draw dotted lines
         BEQ DONEKEY      ;Skip keypress read the first time
                          ;through, so we don't get double
                          ;keypresses by accident.
                          
*-------------------------------
* Main loop
                          
**** First, the SUPER SECRET characters
MAIN                      
KPRESS   JSR SCNKEY       
         LDA $CB          
         CMP #11          ;4 goes into turbo mode
         BNE :F4          
         LDX #$FD         
         STX XYINC        
         LDX #$04         
         STX XZINC        
:F4      CMP #5           ;F4 (or F3) goes into 4D mode
         BNE :D           
         LDA #02          
         STA WXINC        
         LDA #00          
         STA XYINC        
         STA YZINC        
         STA XZINC        
:D       CMP #18          ;D goes into normal mode
         BNE :DOT         
         LDX #$FF         
         STX XYINC        
         LDX #01          
         STX WXINC        
         STX YZINC        
         INX              
         STX XZINC        
:DOT     CMP #44          ;44, the dot, toggles dotted lines
         BNE :3D          
         LDA DOTFLAG      
         EOR #$01         
         STA DOTFLAG      
:3D      CMP #63          ;RUN/STOP goes into 3D mode
         BNE :SPACE       
         LDX #00          
         STX WXINC        
         STX XYINC        ;This to freeze splatting
* STX YZINC
* STX XZINC
:SPACE   CMP #60          ;Space advances to the next object
         BNE :CONT        
         JMP INITMAIN     
:CONT                     
DONEKEY                   
                          
**** Clear buffer
CLRBUFF                   
         LDA ZTEMP        ;High byte
         STA BUFFER+1     
         LDA #00          
         STA BUFFER       
                          
CLRDRAW  LDX #06          ;Don't need to clear whole thing
* LDA #00
:FOOL    TAY              ;LDY #00
:DOPE    STA (BUFFER),Y   
         INY              
         BNE :DOPE        
         INC BUFFER+1     
         DEX              
         BNE :FOOL        
                          
*-------------------------------
*
* Update angles
                          
UPDATE   LDA SWX          
         CLC              
         ADC WXINC        
         AND #$7F         
         STA SWX          
         LDA SXY          
         CLC              
         ADC XYINC        
         AND #$7F         
         STA SXY          
         LDA SYZ          
         CLC              
         ADC YZINC        
         AND #$7F         
         STA SYZ          
         LDA SXZ          
         CLC              
         ADC XZINC        
         AND #$7F         
         STA SXZ          
                          
         LDA XYINC        ;Maybe I don't want to splat
         BEQ :CONT        
         DEC COUNT        ;Is it time to splat an object
         BNE :CONT        ;on there?
         LDA #8           
         STA COUNT        
         LDA #5           
         STA NUMSIDE      
:OOPS    JSR GETRAND      ;Get a randomish number
         AND #$0F         
         CMP #6           ;Don't want background color!
         BEQ :OOPS        
         STA COLOR        
         LDA OLDCOL       ;Advance column
         CLC              
         ADC #06          
         CMP #40          
         BCC :OK          
         SBC #40          
:OK      TAX              
         STA OLDCOL       
         JSR GETRAND      
         AND #22          
         TAY              ;Row
         LDA STARCHAR     
         BNE :ONWARDS     
         LDA #244         ;244-25=219
:ONWARDS SEC              
         SBC #25          
         BMI :READY       ;Hit 119 and we're done
         DEC COUNT3D      ;I want 7 3D objects for every
         BMI :NOW4D       ;4D object (8 total, looks better)
         LDA #194         
         BNE :READY       
:NOW4D                    
         INC COUNT3D      
         INC COUNT3D      
         LDA #12          
         STA NUMSIDE      
         LDA #00          
:READY   STA STARCHAR     
         JSR SPLAT        
:CONT                     
         LDA OBLISTW      
         CMP #24          ;Check if object is all set up
         BCS ROTATE       
         JSR DEFOBS       ;Set up objects
                          
*-------------------------------
*
* Rotate and project points
*
* There is just one long list of points, but I want
* to be able to rotate objects individually, so we need
* to be careful.
*
* The rotation subroutine will need a pointer in X and a
* counter set up by the calling routine, the pointer X
* is an index to the list of points to be rotated, and the
* counter tells it how many points to rotate using
* the angles swx,sxy,syz,sxz,etc which may thus be changed
* independently.  (I do not anticipate having more than
* 256 points!)
                          
ROTATE                    
                          
         LDA NUMOB1       ;Number of points in primary
         STA NUMTOROT     
         LDA #48          
         STA OFFSET       
         LDX #00          
                          
         JSR ROTPROJ      
                          
         LDA NUMOB12      ;Number of points in secondary
         STA NUMTOROT     
         LDA #20          
         STA OFFSET       
         LDA SWX          ;Zero out the x4 rotations
         PHA              
         LDA #00          
         STA SWX          
         JSR ROTPROJ      ;Keep X where it is
         PLA              
         STA SWX          
                          
         LDA #96          
         STA COLSTEP      ;Number of bytes per column
                          
         LDX NUMCONS      ;Number of connections
         LDA #00          
:CL      STA CONFLAG,X    ;Reset the draw flags
         DEX              
         BNE :CL          
         STA CONFLAG      
                          
* The drawing routine works as follows: connections
* from the connection list are successively read in and
* joined, until a zero is hit.  The next point is then
* read in as a normal index.  If zero, then we are done,
* otherwise this normal is checked to see if the face
* is visible.  If not then it skips to the next point,
* otherwise it does the drawing thing above.
*
* As each connection is drawn a corresponding flag is
* set in a similar connection list.  This way, connections
* shared between visible faces do not need to be drawn twice.
                          
:CHARGE  TAY              ;LDY #00
         LDA DRAWCON      ;Either 0 or could be $80
         STA DOTTED       ;Zero out dotted flag
:LOOP2   STY AUX          ;Need to STY anyways
         ASL              ;Pick off the DOTTED flag
         ROL DOTTED       ;DOTTED will be 00 or 01
         LSR              ;Restore to actual index
         TAY              
         LDA CONFLAG,Y    ;Have we already drawn this connection?
         BNE :NODRAW      ;If so, then don't draw it again!
         ORA #01          
         STA CONFLAG,Y    
         LDA CONLIST1,Y   ;First point to connect
         TAX              
         LDA PLISTX,X     
         STA X1           
         LDA PLISTY,X     
         STA Y1           
         LDA CONLIST2,Y   ;Point to connect it to
         TAX              
         LDA PLISTX,X     
         STA X2           
         LDA PLISTY,X     
         STA Y2           
         LDA DOTTED       
         AND DOTFLAG      ;Are we drawing dotted lines?
         BNE :NODRAW      ;DOTFLAG=1 means don't draw
         JSR DRAW         
:NODRAW  LDY AUX          
         INY              
         LDA #00          
         STA DOTTED       ;Make it zero in case it wasn't
         LDA DRAWCON,Y    ;List of connection indices
         BNE :LOOP2       
:DONE                     
         LDA #40          ;Shift to 5x5 guy
         STA COLSTEP      
         LSR              
         STA OFFSET       
                          
:NEXT    INY              
         LDA DRAWCON,Y    ;Grab next normal
         BEQ :ALLDONE     ;If zero, then all done
         TAX              
         LDA PLISTZ,X     ;Otherwise, check if visible
         CMP #03          ;experimentally obtained
         BMI :SKIP        ;If not, then go to next point
         INY              
         LDA DRAWCON,Y    ;If so, then draw it!
         BNE :LOOP2       
                          
:SKIP    INY              
         LDA DRAWCON,Y    
         BNE :SKIP        
         BEQ :NEXT        
                          
:ALLDONE                  
                          
         JSR FILL         ;Fill in the 5x5 3D object
                          ;at BUFFER+$0480
         JSR SYMM         ;Fill out the symmetry-related objs
                          
                          
OBJDONE                   
** Wait for raster refresh
*:WAIT LDA $D012
* BNE :WAIT
                          
**** Swap buffers
                          
SWAPBUF  LDA VMCSB        
         EOR #$02         ;Pretty tricky, eh?
         STA VMCSB        
         LDA #$08         
         EOR ZTEMP        ;ztemp=high byte just flips
         STA ZTEMP        ;between $30 and $38
                          
         JMP MAIN         ;Around and around we go...
                          
*-------------------------------
** Rotate, project, and store the points
*
* This guy simply goes down the point list, rotating and
* projecting points.  It needs X passed in as an initial
* index into the list of points, and it also needs a
* counter NUMTOROT set up ahead of time.  It only projects
* a certain number of points so that different objects
* may be manipulated differently.
*
* It first rotates (2D) in the w-x plane, then x-y, then
* y-z, and finally x-z.
* It then projects through the origin, first into the
* hyperplane w=const, then into the plane z=const.
* Then the points are stored as an x-y list of coords,
* with an intermediate list of x-y-z coords, so a
* hidden face normal can be easily implemented.
*
* Note that I don't worry about getting signs right or
* thing like that -- I don't mind a reflected solution.
*
* Note that points originate in OBLIST and end up in
* PLIST.
*
* Mini subroutine: to save some space, the rotation
* part is subcontracted out to another little routine,
* ROT.
                          
ROTPROJ                   
         LDA OBLISTW,X    
         STA TEMP1        
         LDA OBLISTX,X    
         LDY SWX          
         JSR ROT          ;A contains W, temp1 X
         STA PLISTW,X     
         LDA OBLISTY,X    ;Next, xy
         LDY SXY          
         JSR ROT          
         STA PLISTX,X     
         LDA OBLISTZ,X    ;Und vhy-zee
         LDY SYZ          
         JSR ROT          
         STA PLISTY,X     
         LDY TEMP1        ;temp1 has rotated z
         LDA PLISTX,X     ;Need rotated x now
         STA TEMP1        
         TYA              ;Coordinates do not commute!
         LDY SXZ          
         JSR ROT          ;Now xz
         STA PLISTX,X     
         LDA TEMP1        
         STA PLISTZ,X     ;Now everyone should be rotated
                          
         LDA PLISTW,X     ;So, let's get projecting!
         CLC              
         ADC #48          ;Don't forget to shift z!
         TAY              
         LDA PLISTX,X     ;First into w=const
         CLC              
         ADC #HISIN+48    
         STA PROJTAB+1    
         LDA (PROJTAB),Y  
         STA PLISTX,X     
         LDA PLISTY,X     
         CLC              
         ADC #HISIN+48    
         STA PROJTAB+1    
         LDA (PROJTAB),Y  
         STA PLISTY,X     
         LDA PLISTZ,X     
         CLC              
         ADC #HISIN+48    
         STA PROJTAB+1    
         LDA (PROJTAB),Y  
         STA PLISTZ,X     
                          
         CLC              
         ADC #48          
         TAY              ;Now into z=const
         LDA PLISTX,X     
         CLC              
         ADC #HISIN+48    
         STA PROJTAB+1    
         LDA (PROJTAB),Y  
         CLC              
         ADC OFFSET       
         BPL :OK2         ;Guard against COMPLETELY trashing mem
         LDA OFFSET       ;Don't give it a chance
:OK2     STA PLISTX,X     
         LDA PLISTY,X     
         CLC              
         ADC #HISIN+48    
         STA PROJTAB+1    
         LDA (PROJTAB),Y  
         CLC              
         ADC OFFSET       
         BPL :OK3         
         LDA OFFSET       ;Zap it to the origin
:OK3     STA PLISTY,X     
                          
         INX              
         DEC NUMTOROT     
         BEQ :DONE        
         JMP ROTPROJ      
:DONE    RTS              
                          
*-------------------------------
* Suubroutine ROT
*
* This little guy needs as set-up temp1=x1 and A=x2
* and the appropriate angle needs to be set up in Y.
* Upon return, rotated x2 is stored in temp1
* and rotated x1 is in A
                          
ROT                       
         CLC              ;Next, xy
         ADC #HISIN+48    
         STA SIN2+1       
         STA COS2+1       
         LDA TEMP1        
         CLC              
         ADC #HISIN+48    
         STA SIN1+1       
         STA COS1+1       
         LDA (SIN1),Y     
         CLC              
         ADC (COS2),Y     
         STA TEMP1        
         LDA (COS1),Y     
         SEC              
         SBC (SIN2),Y     
         RTS              
                          
*
* CLEARSET
*
* This little subroutine fills the screen with the contents
* of A and places a 12x12 character block in the middle
* of the screen, in addition to clearing the screen and
* setting the background colors, etc.
*
CLEARSET                  
         PHA              
         LDA #$02         ;Red
         STA $D021        ;This is done so that older
         LDA #28          
         JSR CHROUT       ;(not to mention newer)
         LDA #147         ;machines will set up
         JSR CHROUT       
         LDA #6           ;correctly
         STA $D021        ;(and the flash looks cool too)
                          
         LDX #00          
         PLA              ;Custom character
:GYPSY   STA SCRNLOC,X    
         STA SCRNLOC+256,X
         STA SCRNLOC+512,X
         STA SCRNLOC+768,X
         INX              
         BNE :GYPSY       
                          
         LDA #7           ;Yellow
         STA COLOR        ;Try out that snazzy new routine
         LDA #12          
         STA NUMSIDE      ;12 chars per side
* LDA #00 ;start char
         TXA              
         STA STARCHAR     
         LDX #14          ;col
         LDY #5           ;row
         JMP SPLAT        ;SPLAT will return for us
                          
*-------------------------------
*
* A destructive 8x8 -> 16 bit multiply routine
*
* ACC*AUX -> [ACC,accumulator] (low,hi) 16 bit result
* AUX remains unchanged
                          
MULT     CLC              
         LDA #00          
         LDX #$08         
:LOOP    ROR              
         ROR ACC          
         BCC :CONT        
         CLC              
         ADC AUX          
:CONT    DEX              
         BPL :LOOP        
* STA AUX
         RTS              
                          
*-------------------------------
*
* GETRAND
*
* Generate a somewhat random repeating sequence.  I use
* a typical linear congruential algorithm
*      I(n+1) = (I(n)*a + c) mod m
* with m=65536, a=5, and c=13841 ($3611).  c was chosen
* to be a prime number near (1/2 - 1/6 sqrt(3))*m.
*
* Note that in general the higher bits are "more random"
* than the lower bits, so for instance in this program
* since only small integers (0..15, 0..39, etc.) are desired,
* they should be taken from the high byte RANDOM+1, which
* is returned in A.
*
GETRAND                   
         LDA RANDOM+1     
         STA TEMP1        
         LDA RANDOM       
         ASL              
         ROL TEMP1        
         ASL              
         ROL TEMP1        
* ASL
* ROL TEMP1
* ASL
* ROL TEMP1
         CLC              
         ADC RANDOM       
         PHA              
         LDA TEMP1        
         ADC RANDOM+1     
         STA RANDOM+1     
         PLA              
         ADC #$11         
         STA RANDOM       
         LDA RANDOM+1     
         ADC #$36         
         STA RANDOM+1     
         RTS              
                          
*-------------------------------
*
* This is some custom character data; these
* were stolen from Polygonamy.
*
CHARDAT                   
CROSSSM  HEX 55EE55BB55EE55BB
DITHER1  HEX AA55AA55AA55AA55
ZIGS     HEX EEDDBB77EEDDBB77
ZAGS     HEX 77BBDDEE77BBDDEE
