*-------------------------------
*
* 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 $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+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+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