[stella] Better Music Driver Demo

Subject: [stella] Better Music Driver Demo
From: Paul Slocum <paul-stella@xxxxxxxxxxxxxx>
Date: Sun, 03 Feb 2002 02:54:17 -0600
I managed to cram the music driver into Combat. I programmed it to play a poorly rendered "Rock the Casbah" by The Clash so I could call it "Combat Rock". :o)

The main problem I had was trying to find enough memory to run the driver. I cut the unnecessary memory usage, and got it down to 2 bytes plus 3 temp bytes. The driver and data take up 1.5k for this one, but the song's pretty long.


-Paul
SAUDC0 = $15
SAUDF0 = $17
SAUDV0 = $19

; Song Data
; ----------------------------------------------------------
; song1 and song2 are lists of patterns to be played
; out of the patternArray.
; They are played simlutaneously using the two oscillators

song1
	byte 2, 4, 6, 6
	byte 2, 4, 6, 6

	byte 20,22,20,24
	byte 20,22,20,42

	byte 2, 4,6,44
	byte 2, 4,6,6

	byte 20,22,20,24
	byte 20,22,20,42

	byte 2, 4,6,44
	byte 2, 4,6,6

	byte 12, 40, 12,36
	byte 34, 34, 34,38
	byte 12, 40, 12,36
	byte 34, 34, 34,38

	byte 12, 40, 12,36
	byte 48, 48, 34,38
	byte 52, 52, 12,36
	byte 52, 52, 12,36

	byte 50, 50, 34,38
	byte 48, 48, 34,38
	byte 52, 52, 12,36
	byte 52, 52, 12,0

	byte 12, 40, 12,36
	byte 34, 34, 34,38
	byte 12, 40, 12,36
	byte 34, 34, 34,38

	byte 255

	; intro
	byte 16
	byte 255


song2
	byte 8,10,12,12
	byte 8,10,12,12
	
	byte 26,12,28,12
	byte 26,12,28,12

	byte 30,12,32,32
	byte 30,12,32,32

	byte 26,12,28,12
	byte 26,12,28,12

	byte 30,12,32,32
	byte 30,12,32,32

	byte 14,14,14,14
	byte 14,14,14,14
	byte 14,14,14,14
	byte 14,14,14,14
	
	byte 46,46,46,46
	byte 46,46,46,46
	byte 46,46,46,46
	byte 46,46,46,46

	byte 46,46,46,46
	byte 46,46,46,46
	byte 46,46,46,46
	byte 46,46,46,46

	byte 14,14,14,14
	byte 14,14,14,14
	byte 14,14,14,14
	byte 14,14,14,14
	
	byte 255

	;intro
	byte 18
	byte 255
	

patternArray
	word patternMute, bass1 ;0 2
	word bass2, bass3		;4 6
	word piano1, piano2		;8 10
	word beat1, hat			;12 14
	word introbeat, intropiano	;16 18
	word bass4, bass5		;20 22
	word bass6, verse1		;24 26
	word verse2, chorus1	;28 30
	word chorus2, beat2		;32 34
	word beat1fill, beat2fill;36 38
	word beat1fill2, bass6leadin;40 42
	word bass3leadin, chorusAlt	;44 46
	word chorusAlt2, chorusAlt3	;48 50
	word chorusAlt4				;52


; Pattern Data
; ----------------------------------------------------------
;
; The patterns are made up of 32 numbers (bytes) of note data followed
; by 4 numbers (bytes) of accent data.
;
; Note Encoding
; ----------------------------------------------------------
;
; The 32 note numbers are encoded with sound type and pitch.
;
; The first three bits (1's and  0's) determine the 
; sound type according to the following table:
;
; 000 Square
; 001 Bass  
; 010 Pitfall
; 011 Noise  
; 100 Buzz   
; 101 Lead   
; 110 Saw    
; 111 Engine 
;
; The remaining 5 bits determine the pitch.
;
; 11111 is a very low pitch
; 00001 us a very high pitch
; 00100 is somewhere in between
;
; Synthcart major scale:
;
;  29=11101 26=11010 23=10111 
;  19=10011 17=10001 15=01111
;  14=01110 11=01011  9=01001
;   4=00100  2=00010  1=00001
;
; (!) Note that 255 or %11111111 means no sound (a rest)
;
; Accent Encoding
; ----------------------------------------------------------
;
; The four numbers at the end of the pattern data 
; that look like this:
;  
;	byte #%10001000, #%10001000, #%10001000, #%10001000
;
; determine which notes are accented.  The 32 bits
; from left to right correspond to the 32 notes in
; the pattern.  0=no accent, 1=accent


chorus1
	byte %10101110, %10101110
	byte %10101110, %10101110
	byte %10101111, %10101111
	byte %10101111, %10101111

	byte %10110001, %10110001
	byte %10110001, %10110001
	byte %10110011, %10110011
	byte %10110011, %10110011

	byte %10101111, %10101111
	byte %10101111, %10101111
	byte %10101111, %10101111
	byte 255, 255

	byte %10110001, %10110001
	byte %10110001, %10110001
	byte %10110011, %10110011
	byte %10110011, %10110011

	byte #%11001100, #%11001100, #%11000000, #%11001100

chorusAlt
	byte %10110111, 255
	byte %10110111, 255
	byte %10110111, 255
	byte %10110111, 255

	byte %10110011, 255
	byte %10110011, 255
	byte %10110011, 255
	byte %10110011, 255

	byte %10101111, 255
	byte %10101111, 255
	byte %10101111, 255
	byte %10101111, 255

	byte %10110011, 255
	byte %10110011, 255
	byte %10110011, 255
	byte %10110011, 255

	byte #%00000000, #%00000000, #%00000000, #%00000000

chorusAlt2
	byte %10101110, 255
	byte %10101110, 255
	byte %10101111, 255
	byte %10101111, 255

	byte %01100101, 255
	byte %10110001, 255
	byte %10110011, 255
	byte %10110011, 255

	byte %10101111, 255
	byte %10101111, 255
	byte %10101111, 255
	byte 255, 255

	byte %01100101, 255
	byte %10110001, 255
	byte %10110011, 255
	byte %10110011, 255

	byte #%11001100, #%11001100, #%11000000, #%11001100

chorusAlt3
	byte %10110111, %10101001
	byte %10110111, %10101001
	byte %10110111, %10101001
	byte %10110111, %10101001

	byte %01100101, %10101001
	byte %10110011, %10101001
	byte %10110011, %10101011
	byte %10110011, %10101011

	byte %10101111, %10110111 
	byte %10101111, %10110111 
	byte %10101111, %10110111 
	byte %10101111, %10110111 

	byte %01100101, %10110111 
	byte %10110011, %10110111 
	byte %10110011, %10110111 
	byte %10110011, %10110111 

	byte #%00000000, #%00000000, #%00000000, #%00000000

chorusAlt4
	byte %11111110, %11111010
	byte %10110001, 255
	byte %10101111, 255
	byte %10110001, 255

	byte %01100101, 255
	byte %10110001, 255
	byte %10101111, 255
	byte %10110001, 255

	byte %11111110, %11111010
	byte %10110001, 255
	byte %10101111, 255
	byte %10110001, 255

	byte %01100101, 255
	byte %10110001, 255
	byte %10101111, 255
	byte %10110001, 255


	byte #%11001100, #%11001100, #%11000000, #%11001100

chorus2
	byte %10101111, %10101111
	byte %10101111,255
	byte %01100001, 255
	byte 255,255

	byte %10110111, 255
	byte 255,255
	byte %10110111,255
	byte 255,255

	byte %11111110, %11111010
	byte 255, 255
	byte %10110111, 255
	byte 255, 255

	byte %01000101, 255
	byte 255, 255
	byte %01100001, 255
	byte 255, 255

	byte #%11000000, #%11101000, #%10001000, #%00000000




verse1
	byte %10110111, %10110111
	byte 255,255
	byte %10110111, 255
	byte 255,255

	byte %10110111, 255
	byte 255,255
	byte %10110111, 255
	byte 255,255

	byte %10110011, %10110011
	byte 255, 255
	byte %10110111, %11111010
	byte 255, 255

	byte %01000101, 255
	byte 255, 255
	byte %01100001, 255
	byte 255, 255

	byte #%11001000, #%10001000, #%11001000, #%00001000


verse2
	byte %10110111, %10110111
	byte 255,255
	byte %10110111, 255
	byte 255,255

	byte %10110111, 255
	byte 255,255
	byte %10110111, 255
	byte 255,255

	byte %10110001, %10110001
	byte %10110001, %10110001
	byte %10110011, %11110011
	byte %10110111, %11111010

	byte %01000101, 255
	byte 255, 255
	byte %01100001, 255
	byte 255, 255

	byte #%10001000, #%10001000, #%11001000, #%00001000




bass4
	byte %10110111, %10110111
	byte %01100000, 255
	byte %10110111, 255
	byte %01100000, 255

	byte %01100101, 255
	byte %01100000, 255
	byte %01100000, 255
	byte %01100000, 255

	byte %10110111, %10110111
	byte %10110111,255
	byte %01100101, 255
	byte 255,255

	byte %01100101, 255
	byte 255, 255
	byte %01100000, 255
	byte 255, 255

	byte %11001000, %10000000, %11001100, %10000000


bass5
	byte %10101111, %10101111
	byte %10101111,255
	byte %10101111, 255
	byte 255,255

	byte %01100101, 255
	byte 255,255
	byte %01100000, 255
	byte 255,255

	byte %10101111, %10101111
	byte %10101111,255
	byte %10101111, 255
	byte 255,255

	byte %01100101, 255
	byte 255, 255
	byte %01100000, 255
	byte 255, 255

	byte %00000000, %10000000, %00000000, %10000000


bass6
	byte %10110001, %10110001
	byte %10110001,255
	byte %10110001, 255
	byte 255,255

	byte %01100101, 255
	byte 255,255
	byte %01100000, 255
	byte 255,255

	byte %10110001, %10110001
	byte %10110001,255
	byte %10110001, 255
	byte 255,255

	byte %01100101, 255
	byte 255, 255
	byte %01100000, 255
	byte 255, 255

	byte %00000000, %10000000, %00000000, %10000000



bass6leadin
	byte %10110001, %10110001
	byte %10110001,255
	byte %10110001, 255
	byte 255,255

	byte %01100101, 255
	byte 255,255
	byte 255, 255
	byte 255,255

	byte %10110001, %10110001
	byte %10110001,255
	byte %10110001, 255
	byte 255,255

	byte 255, 255
	byte 255, 255
	byte %10101111, %10101111
	byte %10101111, %10101111

	byte %00000000, %10000000, %00000000, %10000000




introbeat
	byte 255,255
	byte 255,255
	byte 255,255
	byte 255,255

	byte 255,255
	byte 255,255
	byte 255,255
	byte 255,255

	byte 255,255
	byte 255, 255
	byte %01100101, 255
	byte 255, 255

	byte %01100101, 255
	byte 255, 255
	byte %01100101, 255
	byte 255, 255

	byte #%10001000, #%00001000, #%10000000, #%10001000

intropiano
	byte 255, 255
	byte 255, 255
	byte 255, 255
	byte 255,255

	byte 255, 255
	byte 255, 255
	byte 255, 255
	byte 255,255

	byte 255, 255
	byte 255, 255

	byte %10110001, %10110001
	byte %10110001, %10110001
	byte %10101110, %10101110
	byte 255, 255

	byte 255, 255
	byte 255, 255

	byte %11001000, %10001000, %11001100, %10001000



beat1
	byte %11111110, %11111010
	byte 255,255
	byte %01100001, 255
	byte 255,255

	byte %01100101, 255
	byte 255,255
	byte %01100001, 255
	byte 255,255

	byte %11111110, %11111010
	byte 255, 255
	byte %11111110, %11111010
	byte 255, 255

	byte %01100101, 255
	byte 255, 255
	byte %01100001, 255
	byte 255, 255

	byte #%10000000, #%10000000, #%10000000, #%10000000

beat1fill
	byte %11111110, %11111010
	byte 255,255
	byte %01100001, 255
	byte 255,255

	byte %01100101, 255
	byte 255,255
	byte %01100001, 255
	byte 255,255

	byte %11111110, %11111010
	byte 255, 255
	byte %01100101, 255
	byte 255, 255

	byte %01100101, 255
	byte 255, 255
	byte %01100001, 255
	byte 255, 255

	byte #%10000000, #%10000000, #%10001000, #%10000000

beat1fill2
	byte %11111110, %11111010
	byte 255,255
	byte %01100001, 255
	byte 255,255

	byte %01100101, 255
	byte 255,255
	byte %01100001, 255
	byte 255,255

	byte %11111110, %11111010
	byte %01100101, 255
	byte %01100001, 255
	byte 255, 255

	byte %01100101, 255
	byte 255, 255
	byte %01100001, 255
	byte 255, 255

	byte #%10000000, #%10000000, #%11100000, #%10000000



piano2
	byte 255,255
	byte 255,255
	byte %10101110, %10101110
	byte %10101110, 255

	byte %10101011, %10101011
	byte 255, 255
	byte %10101001, 255
	byte 255, 255

	byte %10101011, %10101011
	byte 255, 255
	byte %10101110, 255
	byte 255, 255

	byte %10101111, %10101110
	byte 255, 255
	byte %10110001, %10110001
	byte %10110001, 255

	byte %11001000, %10001000, %11001100, %10001000

piano1
	byte %10101110, %10101110
	byte %10101011, %10101011
	byte %01100000, 255
	byte 255,255

	byte %10101110, %10101011
	byte %10101011, %10101011
	byte %01100000, 255
	byte 255,255

	byte %10101110, %10101110
	byte %10101110, 255
	byte %10110001, %10110001
	byte 255, 255

	byte %10110011, 255
	byte 255, 255
	byte %01100000, 255
	byte 255, 255

	byte %11001000, %10001000, %11001100, %10001000



bass1
	byte %10110111, 255
	byte 255,255
	byte %10110111, 255
	byte 255,255

	byte %01100101, 255
	byte 255,255
	byte %01100000, 255
	byte 255,255

	byte %10110111, 255
	byte 255,255
	byte %10110111, 255
	byte 255,255

	byte %01100101, 255
	byte 255, 255
	byte %01100000, 255
	byte 255, 255

	byte %10001000, %10000000, %10001000, %10000000

bass2
	byte %10101111, %10101111
	byte %10101111, %10101111
	byte %10101111, 255
	byte 255,255

	byte %01100101, 255
	byte 255,255
	byte %10110001, %10110001
	byte %10110001, %10110001

	byte %10110001, %10110001
	byte %10110001, 255
	byte %01100000, 255
	byte 255, 255

	byte %01100101, 255
	byte 255, 255
	byte %01100000, 255
	byte 255, 255

	byte %00000000, %10000000, %00000000, %10000000

bass3
	byte %10101111, %10101111
	byte %10101111, %10101111
	byte 255,255
	byte 255,255

	byte %01100101, 255
	byte 255,255
	byte %10110111, %10110111
	byte 255,255

	byte 255, 255
	byte 255, 255
	byte %10110111, %10110111
	byte 255, 255

	byte %01100101, 255
	byte 255, 255
	byte %01100000, 255
	byte 255, 255

	byte %11001000, %10000000, %11001100, %10000000

bass3leadin
	byte %10101111, %10101111
	byte %10101111, %10101111
	byte 255,255
	byte 255,255

	byte %01100101, 255
	byte 255,255
	byte %10110111, %10110111
	byte 255,255

	byte 255, 255
	byte 255, 255
	byte %10110111, %10110111
	byte 255, 255

	byte %01100101, 255
	byte 255, 255
	byte %10101111, %10101111
	byte %10101111, %10101111

	byte %11001000, %10000000, %11001100, %10000000




hat
	byte %01100000, 255
	byte 255, 255
	byte %01100000, 255
	byte 255, 255

	byte 255, 255
	byte 255, 255
	byte %01100000, 255
	byte 255, 255

	byte %01100000, 255
	byte 255, 255
	byte %01100000, 255
	byte 255, 255

	byte 255, 255
	byte 255, 255
	byte %01100000, 255
	byte 255, 255

	byte #%00000000, #%00000000, #%00000000, #%00000000

beat2
	byte %11111110, %11111010
	byte 255,255
	byte %01100001, 255
	byte 255,%11100101

	byte %01100101, 255
	byte 255,255
	byte %01100001, 255
	byte 255,255

	byte %11111110, %11111010
	byte 255, 255
	byte %11111110, %11111010
	byte 255,%11100101

	byte %01100101, 255
	byte 255, 255
	byte %01100001, 255
	byte 255, 255

	byte #%10000000, #%10000000, #%10000000, #%10000000

beat2fill
	byte %11111110, %11111010
	byte 255,255
	byte %01100001, 255
	byte 255,%11100101

	byte %01100101, 255
	byte 255,255
	byte %01100001, 255
	byte 255,255

	byte %11111110, %11111010
	byte 255, 255
	byte %01100101, 255
	byte 255,%11100101

	byte %01100101, 255
	byte 255, 255
	byte %01100001, 255
	byte 255, 255

	byte #%10000000, #%10000000, #%10001000, #%10000000




patternMute
	byte 255,255,255,255
	byte 255,255,255,255
	byte 255,255,255,255
	byte 255,255,255,255

	byte 255,255,255,255
	byte 255,255,255,255
	byte 255,255,255,255
	byte 255,255,255,255




soundTypeArray
	byte 4,6,7,8
	byte 15,12,1,3







;--------------------------------------------------------------------------
; Accent Reader
;--------------------------------------------------------------------------
; Each set of pattern data is followed by 4 accept bytes.
; Each bit in order represents the accent (on or off)
; of its corresponding 32nd note.  This function
; returns the attenuation of a note in a pattern.
;
; - temp16 must contain an indirect pointer to the pattern data
; - Y must contain the current 32nd note (beat)
;
; = will return the volume in ACC
;
; changes X,Y,ACC
;--------------------------------------------------------------------------
bitMaskArray
	byte #%10000000
	byte #%01000000
	byte #%00100000
	byte #%00010000
	byte #%00001000
	byte #%00000100
	byte #%00000010
	byte #%00000001

accentReader
	; There are 4 accent bytes.  Get the
	; correct one.
	tya
	pha

	and #%00011000
	lsr
	lsr
	lsr

	; The 4 accent bytes are after the 32 bytes
	; that make up the pattern.
	clc
	adc #32
	tay

	; Now set up a mask for the bit
	pla
	and #%00000111
	tax
	
	lda (temp16L),y
	and bitMaskArray,x
	beq noAccent

	; It's an Accent, so don't attenuate
	lda #15

	rts

noAccent

	; No accent, so use a lower volume
	lda #5

	rts ; accentReader


;--------------------------------------------------------------------------
; Extract Pattern Data
;--------------------------------------------------------------------------
; Each byte of pattern data contains the frequency and 
; sound type data.  This function separates and decodes them.
;
; The encoding is: the 3 high bits contain the encoded sound
; type and the lower 5 bits contain the freq data.
;
; - ACC must contain pattern byte
;
; = ACC will return the freq
; = X will return the sound type
; 
; changes ACC,X
;--------------------------------------------------------------------------
extractPatternData
	cmp #255
	beq noNote
	
	tax

	; Extract freq data and push it
	and #%00011111
	pha

	txa
	lsr
	lsr
	lsr
	lsr
	lsr
	tax
	
	lda soundTypeArray,x

	tax
	pla

	rts

noNote
	lda #255

	rts ; extractPatternData : other rts





;--------------------------------------------------------------------------
; playPattern
;--------------------------------------------------------------------------
; Plays a pattern
;
; - X should contain the offset in the patternArray of the pattern to play
; - ACC should contain the oscillator to be used (0 or 1)
;
;--------------------------------------------------------------------------
playPattern
	; save osc number
	sta temp

	; Get address of selected pattern
	lda patternArray,x
	sta temp16L
	inx
	lda patternArray,x
	sta temp16H

	; The variable, beat, contains the 32nd note
	; that the beat is currently on.
	lda beat
	and #%00011111
	tay

	lda (temp16L),y

	jsr extractPatternData

	; Get the osc number again
	ldy temp

	sta SAUDF0,y
	stx SAUDC0,y	

	cmp #255
	beq noteOff1

	tax
	lda beat
	and #%00011111
	tay
	txa
	
	jsr accentReader

	; Get the osc number again
	ldy temp
	sta SAUDV0,y

	rts
noteOff1

	lda #0
	ldy temp
	sta SAUDV0,y

	rts ; playPattern



;--------------------------------------------------------------------------
; songPlayer
;--------------------------------------------------------------------------
; Plays up to two pre-programmed patterns simlutaneously.
;
; Call this once per screen-draw.
;--------------------------------------------------------------------------
songPlayer

; Tempo
;--------------------------------------------------------------------------
	; I'm using the top 3 bits of the beat as a tempo counter.
	; I increase the beat number every 3 screen draws.

	lda beat
	and #%11100000
	beq tempoStep1

	cmp #%00100000
	beq tempoStep2

	;reset tempo count
	lda beat
	and #%00011111
	sta beat

	tax
	inx
	stx beat
	cpx #32
	bne quitTempo

	inc measure

	lda #0
	sta beat

	jmp quitTempo

tempoStep1
	lda beat
	ora #%00100000
	sta beat
	jmp quitTempo

tempoStep2
	lda beat
	ora #%01100000
	sta beat
	
quitTempo

; Now the actual player
;--------------------------------------------------------------------------

	ldy measure	
	ldx song1,y

	; Check to see if the end of the song was reached
	cpx #255
	bne notEndOfSong
	
	; Go back to the first measure
	ldy #0
	sty measure
	ldx song1,y

notEndOfSong

	lda #0 ; oscillator zero
	jsr playPattern

	ldy measure	
	ldx song2,y

	lda #1 ; oscillator one
	jsr playPattern

	rts ; songPlayer




; Combat for Atari by Larry Wagner
;
; Original disassembly by Harry Dodgson
; Commented further by Nick Bensema.
; Last Update: 8/26/97
;
; First a bit of history.  Combat was included with the
; famous Atari 2600/VCS for many years.  As a result,
; if you go to any thrift store, you will find crates
; of Combat cartridges, and some guy from
; rec.games.video.classic swimming through it, refusing
; to admit that Sum Guy just ran off with the mega-rare
; Chase the Chuckwagon cart with the misprinted sideways
; label that he's looking for.
;
; To fully appreciate the trouble people had to go through
; to make an Atari 2600 game, I decided to try my hand at
; picking apart a relatively simple game, Combat.  This
; game works in only 2K or ROM and not even the full 128
; bytes of RAM made available to it.  As if that weren't
; enough, the program has to literally draw the screen
; every single frame, and even Combat had to resort
; to changing some graphic or other in the middle of
; a scanline.  And the programmer had to walk five miles
; to work, uphill both ways!  And he only got a nickel
; a day for writing code!
;
; The Atari 2600, or the VCS, or the 2600VCS, or the
; Atari VCS, or the 2600, or the VCS-2600, or the Sears
; Home Arcade System, or the Intellivision Add-On Thingy
; That Plays Atari 2600, VCS, 2600VCS, Atari VCS, 2600,
; VCS-2600, and Sears games, runs with a 6507 processof.
; This processor is exactly like the 6502 found in Apple,
; Atari, and Commodore home computers except for two
; things:  1) it has a wait state, and 2) it has only
; 13 address lines instead of 16.  So, while your Apple
; II can address $0000-$FFFF, the Atari 2600 could
; only address $0000-$1FFF.  That's a whopping 8K.
; The cartridge ROM accounted for anything about $1000.
; You're going to love this part.  It had 128 bytes of RAM
; at $0080-$00FF, and the TIA, its video chip, which
; doubles as the 2600's entire video memory, at both
; $0000-$007F, and $0100-$017F.  The first copy, along
; with the RAM, could be accessed with zero-page addresses,
; saving space on the ROM, which by the way was 2K.
; The second copy infiltrated the last 128 bytes of the
; 6507's built-in stack.  In the source code, you'll see
; how this is used to the programmer's advantage.
;
; That's all I'm explaining.  If you want to hear more
; on the 2600's specifications, do a web search for
; 2600 programming information, because I've already
; wasted so much of your time.
;
; I did a lot of cutting and pasting and searching
; and replacing.  Be sure to check that this compiles
; to exactly 2048 bytes, and that it matches up with
; all of your uncommented source code before trying to
; modify it... if you dare!  For some reason the guy
; who disassembled this didn't put $ before all the hex
; numbers... so keep in mind, hex is always implied.
;
; I also suggest you hand this to those who want to pirate
; 2600 cartridges.  Not that it'll stop them, but it might
; make them feel guilty enough to seek absolution.
;
; Not having an assembler, and of course not wanting
; to try to use an emulator, I may have screwed up
; big-time on many aspects of this program.
; Forgive me if I did.
;
; Note a few things:
;
; 1. If you don't know what the BIT instruction does,
;    I'll just sum up how Kaplan used it here.  Kaplan
;    used BIT to test bits 7 and 6 of a memory location.
;    If bit 7 was set, the negative flag would be set, 
;    so the following BMI would cause a branch.  If bit 
;    6 was set, the overflow flag would be set, so the
;    following BVS would cause a branch.  If I find an
;    assembler that does macros, I'll use those to do this.
;
; 2. I might refer to players as tanks even though they
;    could just as easily be biplanes or jets.
;

        processor 6502
        include vcs.h

GAMVAR  =     $A3 ;Game Variation
BCDvar  =     $81 ;Game Variation in BCD
DIRECTN =     $95 ;Players and missiles' current bearing.
GAMSHP  =     $85 ;Shape of player and game type
		  ;0 = Tank
		  ;1 = Biplane
		  ;2 = Jet Fighter
SCROFF  =     $E0 ;Score pattern offsets
NUMG0   =     $DE ;Storage for current byte
NUMG1   =     $DF ;of score number graphics.
TMPSTK  =     $D3 ;Temporary storage for stack.

GUIDED  =     $83 ;Whether game is a guided missile game
GTIMER  =     $86 ;Game timer.
SHOWSCR =     $87 ;Show/hide right player score

ScanLine  =     $B4 ;Current scanline on the playfield.

SHAPES  =     $BB ;Pointer to player sprites
SCORE   =     $A1  ;Player scores in BCD.

TankY0   =     $A4  ;Tank 0's Y-position
TankY1   =     $A5  ;
MissileY0   =     $A6  ;Missile 0's Y-position
MissileY1   =     $A7  ;

TEMP    =     $D2;"score conversion temporary"
 
XOFFS   =     $B0 ;X-offset for Hmove.

LORES   =     $B5 ;lo-res indirect addresses.
HIRES   =     $BD ;Hi-res shape data.
		 ;Left player's shape stored in
		 ;all even bytes, right player's
		 ;shape stored in all odd bytes.

DIFSWCH = $D5

Color0  =     $D6 ;Tank Colors.
Color1  =     $D7


;---------------------------------------------------------------------------
; Song player variables

temp = TEMP

; 16 bit temp
temp16L = NUMG0
temp16H = NUMG1

; Metrenome stuff
beat = $F4
measure = $F5


;selectSwitch = $DB
;tempoCount = $D9



audioDefer = temp

DAUDC0 = audioDefer
DAUDV0 = audioDefer
DAUDF0 = audioDefer


	org $1000
	
START   ; Two bytes of housekeeping that must be done...
	SEI  ; Disable interrupts
	CLD  ; Clear decimal bit
	LDX  #$FF
	TXS  ; Set stack to beginning.
	; In all truthfulness, 
	LDX  #$5D
	JSR  ClearMem ;            zero out $00 thru $A2
	LDA  #$10
	STA  SWCHB+1    ;Port B data direction register
	STA  $88         ;and $88...
	JSR songSetup
;	JSR  J11A3
MLOOP   JSR  NWSCR ;            $1014
;	JSR  ConSwitch
	JSR excuseMe
	JSR  J1572
	JSR  J12DA
	JSR  J1444
	JSR  J1214
	JSR  J12A9
	JSR  BCD2SCR
	JSR  DRAW
	JMP  MLOOP
;
NWSCR   INC  GTIMER ;  initial blanking and retrace start
	STA  HMCLR ;Clear horizontal move registers.
	LDA  #2
	STA  WSYNC
	STA  VBLANK
	STA  WSYNC
	STA  WSYNC
	STA  WSYNC
	STA  VSYNC
	STA  WSYNC
	STA  WSYNC
	LDA  #0
	STA  WSYNC
	STA  VSYNC
	LDA  #43
	STA  TIM64T ;set 64 clock interval.
	RTS  
;
; Drawing the screen in the following routine.
; We start with the score, then we render the
; playfield, tanks, and missiles simultaneously.
; All in all, an average day for a VCS.
;
DRAW    LDA  #$20
	STA  ScanLine  ;We're assuming scanline 20.
	STA  WSYNC
	STA  HMOVE   ;Move sprites horizontally.
B105C   LDA  INTIM
	BNE  B105C   ;Wait for INTIM to time-out.
	STA  WSYNC
	STA  CXCLR   ;Clear collision latches
	STA  VBLANK  ;We even have to do our own
		     ;vertical blanking!  Oh, the
		     ;humanity!
	TSX  
	STX  TMPSTK ;               Save stack pointer
	LDA  #$02
	STA  CTRLPF      ; Double, instead of reflect.
	LDX  $DC
B1070   STA  WSYNC  ; Skip a few scanlines...
	DEX  
	BNE  B1070
	LDA  $DC
	CMP  #$0E      
	BEQ  B10CD
	; DC is set as such so that when the score is to
	; be displayed, it waits for just the right time
	; to start drawing the score, but if the score is
	; not to be displayed, as when the score flashes
	; signifying "time's almost up", it waits for just
	; the right time to start drawing the rest of the
	; screen.
;
; Start by drawing the score.
;
	LDX  #$05      ;Score is five bytes high.
	LDA  #$00      ;Clear number graphics.
	STA  NUMG0    ;They won't be calculated yet,
	STA  NUMG1    ;but first time through the loop
		      ;the game will try to draw with
		      ;them anyway.
DRWSCR   STA  WSYNC    ;Start with a fresh scanline.
	LDA  NUMG0    ;Take last scanline's left score,
	STA  PF1           ;and recycle it,
	;Here, we begin drawing the next scanline's
	;left score, as the electron beam moves towards
	;the right score's position in this scanline.
	LDY  SCROFF+2       
	LDA  NUMBERS,Y  ;Get left digit.
	AND  #$F0       
	STA  NUMG0     
	LDY  SCROFF
	LDA  NUMBERS,Y  ;Get right digit.
	AND  #$0F
	ORA  NUMG0
	STA  NUMG0   ;Left score is ready to ship.
	LDA  NUMG1   ;Take last scanline's right score,
	STA  PF1          ;and recycle it.
	LDY  SCROFF+3
	LDA  NUMBERS,Y ;Left digit...
	AND  #$F0
	STA  NUMG1
	LDY  SCROFF+1
	LDA  NUMBERS,Y ;right digit...
	AND  SHOWSCR   
	  ;Now, we use our fresh, new 
	  ;score graphics in
	  ;this next scanline.
	STA  WSYNC                         ; *COUNT*
	ORA  NUMG1   ;Finish calculating     (0) +3
	STA  NUMG1   ;right score.           (3) +3
	LDA  NUMG0                         ; (6) +3
	STA  PF1                           ; *9* +3
	  ;We use this time to check 
	  ;whether we're at
	  ;the end of our loop.
	DEX                                ; (12)+2
	BMI  B10CD                         ; (14)+2 No Branch
	;If so, we're out of here.  Don't worry,
	;the score will be cleared immediately, so
	;nobody will know that we've gone past five
	;bytes and are displaying garbage.
	INC  SCROFF                        ; (16)+5
	INC  SCROFF+2   ; Get ready to draw the next
	INC  SCROFF+1   ; line of the byte.
	INC  SCROFF+3
	LDA  NUMG1
	STA  PF1   ; Right score is in place.
	JMP  DRWSCR  ;Go to next scanline,
				; and that is how we do that...
;
; See what it takes just to display a pair of two-digit
; scores?  If you think that's rough, figure out how
; they displayed those six-digit scores in the early
; 1980's.  Also consider Stellar Track.... well, if
; you've seen Stellar Track, you know exactly what I'm
; talking about.  Full-fledged twelve-column text.
;
; Display loop for playfield.
;
B10CD   LDA  #$00 ;              Inner Display Loop
	STA  PF1 ;  Clear the score.
	STA  WSYNC              
	LDA  #$05
	STA  CTRLPF  ;Reflecting playfield.
	LDA  Color0
	STA  COLUP0 ;How often must THIS be done?
	LDA  Color1
	STA  COLUP1
DRWFLD   LDX  #$1E
	TXS ;Very Sneaky - set stack to missle registers
	SEC  
	; This yields which line of player 0 to draw.
	LDA  TankY0
	SBC  ScanLine  ; A=TankY0-ScanLine
	AND  #$FE     ;Force an even number
	TAX
	; Only sixteen bytes of sprite memory, so...
	AND  #$F0
	BEQ  B10F2   ; If not valid,
	; If it's not valid, blank the tank.
	LDA  #$00 
	BEQ  B10F4 
	; Else, load the appropriate byte.
B10F2   LDA  HIRES,X
B10F4   STA  WSYNC ;---------------END OF ONE LINE------
	STA  GRP0    ; Just for player 0.
	; Keep in mind that at this point, the stack pointer
	; is set to the missile registers, and the "zero-result"
	; bit of the P register is the same at the bit ENAM0/1
	; looks at.
	LDA  MissileY1
	EOR  ScanLine
	AND  #$FE
	PHP ;       This turns the missle 1 on/off
	LDA  MissileY0
	EOR  ScanLine  
	AND  #$FE
	PHP ;       This turns the missle 0 on/off
	;We've got the missile taken care of.
	;Now let's see which line of the playfield to draw.
	LDA  ScanLine  ;
	BPL  B110C   ;If on the bottom half of the screen,
	EOR  #$F8     ;reverse direction so we can mirror.
B110C   CMP  #$20     ;
	BCC  B1114    ;Branch if at bottom.
	LSR   
	LSR   
	LSR          ;Divide by eight,
	TAY          ;and stow it in the Y-register.
	;By now, the electron beam is already at the next
	;scanline, so we don't have to do a STA WSYNC.
	
	; This yields which line of Tank 1 to draw.
B1114   LDA  TankY1      ;TankY1 is other player's position.
	SEC  
	SBC  ScanLine  ;A=TankY1 - ScanLine
	INC  ScanLine  ;Increment the loop.
	NOP
	ORA  #$01     ;Add bit 0, force odd number.
	TAX  
	; There are only sixteen bytes of sprite memory, so...
	AND  #$F0 
	BEQ  B1127 
	; If tank is not ready, blank it.
	LDA  #$00  
	BEQ  B1129 
	; Else, draw tank.
B1127   LDA  HIRES,X    ;draw the tank
B1129   BIT  $82
	STA  GRP1
	BMI  B113B ;If 82 bit set to 1, skip draw. (?)
	LDA  (LORES),Y
	STA  PF0
	LDA  (LORES+2),Y
	STA  PF1
	LDA  (LORES+4),Y
	STA  PF2
B113B   INC  ScanLine   ;One more up in the loop.
	LDA  ScanLine
	EOR  #$EC      ;When we've reached the $ECth line,
	BNE  DRWFLD    ;we've had enough.
	LDX  TMPSTK ; Restore stack pointer
	TXS         ; which is NEVER USED ANYWHERE ELSE...
	STA  ENAM0    ; Clear a bunch of registers.
	STA  ENAM1
	STA  GRP0
	STA  GRP1
	STA  GRP0    ;In case GRP0 isn't COMPLETELY zeroed.
	STA  PF0
	STA  PF1
	STA  PF2
	RTS  
;
; Executed immediately after NWSCR.
;
; This subroutine parses all the console switches.
;
ConSwitch   
	LDA  SWCHB   ;Start/Reset button....
	LSR          ;Shove bit 0 into carry flag,
	BCS  B1170   ;and if it's pushed...
	; Start a new game.
	LDA  #$0F
	STA  SHOWSCR      ;Show right score.
	LDA  #$FF     ;Set all bits
	STA  $88      ;in $88.  
	LDA  #$80   
	STA  $DD 
	LDX  #$E6
	JSR  ClearMem ;            zero out $89 thru $A2
	BEQ  ResetField ;Unconditional branch
B1170   LDY  #$02
	LDA  $DD
	AND  $88
	CMP  #$F0
	BCC  B1182
	LDA  GTIMER      ;GTIMER is the timer.
	AND  #$30
	BNE  B1182
	LDY  #$0E
B1182   STY  $DC
	LDA  GTIMER
	AND  #$3F
	BNE  B1192
	STA  $89
	INC  $DD
	BNE  B1192
	STA  $88
B1192   LDA  SWCHB  ; Select button.  ???
	AND  #$02
	BEQ  B119D
	STA  $89
	BNE  CS_RTS
B119D   BIT  $89
	BMI  CS_RTS
	INC  $80      ;Go to next game.
J11A3   LDX  #$DF   ;Clear data from current game
B11A5   JSR  ClearMem  ;
	LDA  #$FF
	STA  $89
	LDY  $80
	LDA  VARDATA,Y  ;Get data bits for this variation.
	STA  GAMVAR
	EOR  #$FF  ;#$FF signifies end of variations
	BNE  B11BB
	LDX  #$DD
	BNE  B11A5  ; Clear all gamewise memory and start over.
B11BB   LDA  BCDvar
	;Remember we have to increment with BCD...
	SED  
	CLC  
	ADC  #1
	STA  BCDvar
	STA  SCORE
	CLD
	BIT  GAMVAR
	BPL  ResetField  ;if this is a plane game,
	INC  GAMSHP     ;increase GAMSHP.
	BVC  ResetField  ;if this is a jet game,
	INC  GAMSHP      ;increase GAMSHP further still.
	; Branch here when game is started, too.
ResetField 
	JSR  InitField
	; Assuming plane game for now, we set the right player
	; at a slightly higher position than the left player,
	; and the position of the right player is irrelevant.
	LDA  #50
	STA  TankY1
	LDA  #134
	STA  TankY0
	BIT  GAMVAR ;Check to see if it is a tank game.
	BMI  CS_RTS   
	; If it really is a tank game..
	STA  TankY1  ; Right tank has same Y value,
	STA  RESP1   ;and tank is at opposite side.
	LDA  #$08
	STA  DIRECTN+1  ;and right player faces left.
	LDA  #$20
	STA  HMP0
	STA  HMP1
	STA  WSYNC
	STA  HMOVE
CS_RTS   RTS  

;
; convert BCD scores to score pattern offset.
; This involves the horrible, horrible implications
; involved in multiplying by five.
;
; If it weren't for the geniuses at NMOS using BCD,
; this routine would be a nightmare.
;
BCD2SCR LDX  #$01
B11F4   LDA  SCORE,X
	AND  #$0F
	STA  TEMP
	ASL   
	ASL   
	CLC  
	ADC  TEMP
	STA  SCROFF,X
	LDA  SCORE,X
	AND  #$F0
	LSR   
	LSR   
	STA  TEMP
	LSR   
	LSR   
	CLC  
	ADC  TEMP
	STA  SCROFF+2,X
	DEX  
	BPL  B11F4
	RTS  

;
;
;
J1214   BIT  GUIDED
	BVC  B121C   ;Branch if bit 6 of 83 is clear.
	LDA  #$30
	BPL  B121E   ;JMP.
B121C   LDA  #$20
B121E   STA  $B1   ;Either $30 or $20 goes here...
	LDX  #$03
	JSR  J1254
	DEX        ;X, I _think_, is now 2.
	JSR  J1254
	DEX        ;And I _think_ it's now 1.
B122A   LDA  $8D,X ;Velocity register
	AND  #$08
	LSR   
	LSR   
	STX  $D1
	CLC  
	ADC  $D1    
	TAY  ;     Y=($8D,X)&8 / 4 + X
	; $00A8,Y is either $00A8,X or $00AA,X.
	LDA  $00A8,Y ;We can't use zero-page? Waaah!
	SEC  
	BMI  B123D
	CLC
      ;^^ That's just a fancy way to
      ;   transfer bit 7 to Carry Bit.
B123D   ROL        ;ROL, the wave of the future.
	STA  $00A8,Y
	BCC  B1250
	LDA  $AC,X
	AND  #$01
	ASL   
	ASL   
	ASL   
	ASL   
	STA  $B1  ; B1 = (AC & 1) << 4
	JSR  J1254
B1250   DEX           ;Move to _previous_ player.
	BEQ  B122A    ;Stop if about to do player -1.  :)
	RTS  
;
; This routine will move both tanks and missiles.
; Special cases are made for missiles, which are
; otherwise treated as players 2 and 3.
;
; It doesn't change the X register, but it does
; utilize it.
;
J1254   INC  $AC,X
	LDA  DIRECTN,X
	AND  #$0F
	CLC  
	ADC  $B1
	TAY  
	LDA  L15F7,Y  ;This has offset information.
	STA  XOFFS      ;Store the X-offset.
	BIT  $82
	BVS  B127A   ;Branch if bit 6 of 82 is set.
	LDA  DIRECTN,X
	SEC  
	SBC  #$02
	AND  #$03
	BNE  B127A
	LDA  $AC,X
	AND  #$03
	BNE  B127A   ;if AC isn't set, we're go for move.
	LDA  #$08
	STA  XOFFS
B127A   LDA  XOFFS       
J127C   STA  HMP0,X   ;Use this to move the tank.
	AND  #$0F
	SEC  
	SBC  #$08
	STA  $D4
	CLC  
	ADC  TankY0,X
	BIT  GAMVAR
	BMI  B1290    ;Branch if a plane game.
	;What follows is probably a bounds check.
	CPX  #$02
	BCS  B12A0    ;Branch if moving a player
B1290   CMP  #$DB
	BCS  B1298
	CMP  #$25
	BCS  B12A0
B1298   LDA  #$D9
	BIT  $D4
	BMI  B12A0
	LDA  #$28    ;#$28 if D4 is positive, #$D9 if not
B12A0   STA  TankY0,X  ;The tank/missile is moved here.
	CPX  #$02
	BCS  B12A8   ;Skip if moving a missile.
	STA  VDELP0,X ;Vertical Delay Player X...
B12A8   RTS  
;
; This subroutine sets up the sprite data for each player by copying
; them into sixteen bytes of RAM. 
; 
; The X-register starts at 0x0E plus player number and goes down by two 
; each time through the loop, until it hits zero.  This way, after calling 
; this subroutine twice, every even-numbered byte contains the left player 
; shape, and every odd-numbered byte contains the right player shape.  Since 
; each player is updated every two scanlines, this saves us some math.
;
; Only the first 180 degrees of rotation has been drawn into ROM.  In the
; case of the other 180 degrees, this subroutine renders a flipped version
; by doing the following:
;
; 1. It sets the TIA's reflection flag for that player, taking care of 
;    the horizontal aspect rather easily.
;
; 2. It copies the bytes into memory last-to-first instead of first-to-
;    last, using the carry bit as a flag for which to do.
;
J12A9   LDA  #$01
	AND  GTIMER
	TAX  
	LDA  DIRECTN,X
	STA  REFP0,X    ;Step 1 taken care of.
	AND  #$0F
	TAY         ;Y = DIRECTN[X] & 0x0F.
	BIT  GUIDED     
	BPL  B12BB  ;If bit 7 is set,
	STY  DIRECTN+2,X   ;then set missile bearings(?)
B12BB   TXA        ;  X ^= 0x0E,
	EOR  #$0E   ;
	TAX        ;
	TYA  
	ASL   
	ASL   
	ASL   
	CMP  #$3F      ;And so step 2 begins...
	CLC  
	BMI  B12CB    ;Branch if <180 deg.
	SEC
	EOR  #$47      ;and it doesn't end here.
	;The EOR sets bits 0-2, and clears bit 4
	;to subtract 180 degrees from the memory
	;pointer, too.
B12CB   TAY  
	;Put all the shapes where they ought to be.
B12CC   LDA  (SHAPES),Y
	STA  HIRES,X
	BCC  B12D4 
	DEY  ; Decrement instead of increment
	DEY  ; plus cancel the upcoming INY.
B12D4   INY           ;More of step 2.
	DEX  
	DEX     ;X-=2.
	BPL  B12CC ;Keep going until X runs out.
	RTS  
;
;  Stir the tanks.  :-)
;
J12DA   LDA  $8A
	SEC  
	SBC  #$02   
	BCC  B130C ;If tank is not exploding,
		   ;parse joystick instead.
	STA  $8A
	CMP  #$02
	BCC  B130B   ;RTS if tank has
		     ;just finished exploding.
	AND  #$01     ;Stir the LOSER's tank.
	TAX  
	;One of these is the tank's bearings.
	INC  DIRECTN,X
	LDA  $D8,X
	STA  Color0,X
	LDA  $8A
	CMP  #$F7
	BCC  B12F9
	JSR  J1508
B12F9   LDA  $8A
	BPL  B130B    ;Don't start decrementing
		      ;volume until halfway through.
	LSR   
	LSR   
	LSR   
J1300   STA  DAUDV0,X  ;Sound effects.  BOOOM!
	LDA  #$08
	STA  DAUDC0,X
	LDA  L17FE,X
	STA  DAUDF0,X
B130B   RTS
;
; Process joysticks.
;
B130C   LDX  #$01
	LDA  SWCHB ;Console switches.
	STA  DIFSWCH    ;Store switches in D5.
	LDA  SWCHA ;Joysticks.
B1316   BIT  $88    
	BMI  B131C ;Branch if bit 7 is set.
	LDA  #$FF  ;Freeze all joystick movement.
B131C   EOR  #$FF  ;Reverse all bits
	AND  #$0F  ;Keep high four bits (Right Player)
	;At this point, the joystick's switches are in
	;the A-register, with a bit set wherever the
     ;joystick is pointed.
	; Bit 0 = up    Bit 1 = down
	; Bit 2 = left  Bit 3 = right
	STA  TEMP
	LDY  GAMSHP
	LDA  L170F,Y   ;Account for two-dimensional array
	CLC  
	ADC  TEMP
	TAY  
	LDA  CTRLTBL,Y
	AND  #$0F      ;Get rotation from table.
	STA  $D1
	BEQ  B1338     ;Branch if no turn.
	CMP  $91,X
	BNE  B133C     ;Some speed control I'm guessing.
B1338   DEC  $93,X
	BNE  B1349
B133C   STA  $91,X
	LDA  #$0F
	STA  $93,X
	; Turn the tank here. 
	LDA  $D1
	CLC  
	ADC  DIRECTN,X
	STA  DIRECTN,X
B1349   INC  $8D,X
	BMI  B136B
	LDA  CTRLTBL,Y
	LSR   
	LSR   
	LSR   
	LSR         ;Get velocity from table.
	BIT  DIFSWCH
	BMI  B137B
B1358   STA  $8B,X  ; Stash velocity in $8B
	ASL         ;Multiply by two
	TAY         ;Stash in Y.
	LDA  L1637,Y
	STA  $A8,X    ;This is the player's ?
	INY  
	LDA  L1637,Y
	STA  $AA,X
	LDA  #$F0
	STA  $8D,X  
B136B   JSR  J1380
	LDA  SWCHA   ;Joysticks..
	LSR   
	LSR   
	LSR   
	LSR        ;Keep bottom four bits (Left Player)
	ASL  DIFSWCH   ;Use other difficulty switch.
	DEX  
	BEQ  B1316   ;
	RTS  
;
B137B   SEC  
	SBC  GAMSHP
	BPL  B1358   ;If GAMSHP<A, then pass A-GAMSHP here.
J1380   LDA  GAMVAR
	BMI  B138C ;If this is a tank game,
	AND  #$01   ;check also for bit 0.
	BEQ  B138C
	LDA  $DB
	STA  Color0,X ;Only then may it be Colored such.
B138C   LDA  $99,X
	BEQ  B13B7
	LDA  $D8,X
	STA  Color0,X
	LDA  $99,X
	CMP  #$07
	BCC  J13AE
	BIT  DIFSWCH
	BPL  B13A2
	CMP  #$1C
	BCC  J13AE
B13A2   CMP  #$30
	BCC  B13C5
	CMP  #$37
	BCS  J13CB
	BIT  GUIDED
	BVC  J13CB     ;Branch if machine gun.
J13AE   LDA  #$00
	STA  $99,X
	LDA  #$FF
B13B4   STA  RESMP0,X  ;Reset missile to player.
	RTS  
	; I assume we get the trigger from here.
B13B7   BIT  $88
	BPL  B13BF   ;if it's negative, go ahead.
	LDA  INPT4,X ;Read Input (Trigger) X.
	BPL  B13F6
	;^^ Since the specs say there is no bit 7,
	;   I guess that means "JMP B13F6.
B13BF   JSR  J1410
	JMP  J13AE
B13C5   JSR  J1410
	JMP  J13DE
J13CB   LDA  $9F,X
	BEQ  B13D9
	JSR  J1410
	LDA  #$30
	STA  $99,X
	JMP  J13DE
;
B13D9   LDA  $99,X
	JSR  J1300
J13DE   LDA  GTIMER
	AND  #$03
	BEQ  B13F0
	BIT  $84
	BVS  B13F2
	BIT  $82
	BVC  B13F0
	AND  #$01
	BNE  B13F2
B13F0   DEC  $99,X
B13F2   LDA  #$00
	BEQ  B13B4  ;Reset missiles to tanks and RTS.
	;Launch a tank.
B13F6   LDA  #$3F
	STA  $99,X
	SEC  
	LDA  TankY0,X  ;Copy Y-position...
	SBC  #$06      ;The barrel is 6 scanlines down.
	STA  MissileY0,X
	LDA  DIRECTN,X ;Copy player bearing to missile.
	STA  DIRECTN+2,X
	LDA  #$1F
	STA  $9B,X     ;9B has to do with missiles & sound.
	LDA  #$00
	STA  $9D,X     ;9D also has to do with missiles.
	JMP  J13CB
;
; This routine parses the sound effects.
;
J1410   LDA  $9F,X
	BEQ  B1421
	;Gunshot sound.
	LDA  #$04
	STA  DAUDC0,X
	LDA  #$07
	STA  DAUDV0,X
	LDA  $9B,X  
	STA  DAUDF0,X
	RTS  
	;Ambient sound.
B1421   LDY  GAMSHP
	LDA  SNDV,Y
	AND  $88   ;$88 affects sound too? wow.
		   ;Perhaps speed too
	STA  DAUDV0,X ;see how it affects volume?
	LDA  SNDC,Y
	STA  DAUDC0,X
	CLC  
	LDA  #$00
B1432   DEY  
	BMI  B1439
	ADC  #$0C
	BPL  B1432
B1439   ADC  $8B,X
	TAY  
	TXA  
	ASL   
	ADC  SNDP,Y
	STA  DAUDF0,X
	RTS  
;
; Check to see whether, during all that drawing,
; a missile hit one of the tanks.
;
J1444   LDX  #$01
J1446   LDA  CXM0P,X
	BPL  B1476
	BIT  $84
	BVC  B1454
	LDA  $9B,X
	CMP  #$1F
	BEQ  B1476
	;A touch, a touch!  I do confess.
B1454   INC  DIRECTN,X  ; Turn the tanks 22.5 degrees.
	INC  DIRECTN+2,X
	;Increase player's score.
	;A simple INC SCORE,X won't do because
	;we're doing it in BCD.
	SED  
	LDA  SCORE,X
	CLC  
	ADC  #$01
	STA  SCORE,X
	CLD  
	TXA  
	CLC  
	ADC  #$FD
	STA  $8A
	;Now 8a contains loser's ID in bit 0,
	;victor's ID in bit 1, and set bits
	;2-7: the clock is ticking.
	LDA  #$FF
	STA  RESMP0   ;Reset both missiles.
	STA  RESMP1
	LDA  #$00
	STA  DAUDV0,X  ;Turn off the victor's engine.
	STA  $99       ;clear 99
	STA  $9A       ;and 9A.
	RTS  

;
B1476   BIT  GAMVAR
	BPL  B147D  ;Branch if a tank game.
	JMP  J1501
B147D   LDA  $9F,X
	BEQ  B148B
	CMP  #$04
	INC  $9F,X
	BCC  B148B
	LDA  #$00
	STA  $9F,X
B148B   LDA  CXM0FB,X   ;Tank collision with ball?
	BMI  B1496      ;If true(?), go below...
	LDA  #$00
	STA  $9D,X       ;clear.
	JMP  J14D6
;
B1496   BIT  $82
	BVC  B14D0  ;Branch if bit 6 is clear.
	LDA  $9D,X
	BNE  B14B7
	INC  $9F,X
	DEC  $9B,X
	LDA  DIRECTN+2,X
	STA  $B2,X
	EOR  #$FF
	STA  DIRECTN+2,X
	INC  DIRECTN+2,X
	LDA  DIRECTN+2,X
	AND  #$03
	BNE  B14B4
	INC  DIRECTN+2,X
B14B4   JMP  J14D4
;
B14B7   CMP  #$01
	BEQ  B14C6
	CMP  #$03
	BCC  J14D4
	BNE  J14D4
	LDA  $B2,X
	JMP  J14C8
;
; Bounce for Tank Pong... maybe.
; If I'm reading this right, it calls for a
; complete 180-degree turn.  I guess whatever
; happens after jumping to J14D4 helps a lot.
;
B14C6   LDA  DIRECTN+2,X
J14C8   CLC  
	ADC  #$08
	STA  DIRECTN+2,X
	JMP  J14D4
;
B14D0   LDA  #$01
	STA  $99,X
J14D4   INC  $9D,X
J14D6   LDA  CXP0FB,X
	BMI  B14DE   ;check if tank collided
		     ;with a wall.
	LDA  CXPPMM  ;check for a tank collision.
	BPL  B14E7
B14DE   LDA  $8A     ;See if timer has run out.
	CMP  #$02
	BCC  B14ED
	JSR  J1508
B14E7   LDA  #$03
	STA  $E4,X
	BNE  B1501
B14ED   DEC  $E4,X
	BMI  B14F7
	LDA  $8B,X
	BEQ  B1501
	BNE  B14F9
B14F7   INC  DIRECTN,X
B14F9   LDA  DIRECTN,X
	CLC  
	ADC  #$08       ;Add 180 degrees to direction.
	JSR  J150F
J1501
B1501   DEX  
	BMI  B1507      ;Return if X<0.
	JMP  J1446
B1507   RTS  
;
; I bet this moves the missiles.
;
J1508   TXA  
	EOR  #$01
	TAY        ; Y = NOT X
	LDA  DIRECTN+2,Y ;Missile's Direction
J150F   AND  #$0F
	TAY  
	LDA  HDGTBL,Y ;Nove 
	JSR  J127C    ;Move object in that direction.
	LDA  #$00
	STA  $A8,X
	STA  $AA,X
	STA  $8D,X  ;Stop it dead in its tracks....
	LDA  $D8,X
	STA  Color0,X
	RTS  

;
; Set everything up to draw the playfield.
;
; When we find out what BB and BC are for,
; we'll keep in mind 
;
InitField   LDX  GAMSHP
	LDA  SPRLO,X ;Appropriate something for velocity.
	STA  SHAPES      ;Velocity could double as sprite
	LDA  SPRHI,X ;shape.
	STA  SHAPES+1
	LDA  GAMVAR
	LSR   
	LSR   
	AND  #$03  ;Determine maze type.
	TAX       ;send it to X.
	LDA  GAMVAR ;Determine game type.
	BPL  B1546  ;If a plane game,
	AND  #$08    ;test for clouds
	BEQ  B1544  ;If there are any,
	LDX  #$03    ;replace X with 3.
	;That, I don't get.  They wanted 3,
	;that fits into two bits, so why not just
	;put a 3 in there instead of going through
	;all of this?
	BPL  B1548  ;skip to next test.
B1544   LDA  #$80    ;Otherwise,
B1546   STA  $82     ;store $80 in 82.
B1548   LDA  GAMVAR ;Next test..
	ASL   
	ASL         ;Do this again....
	BIT  GAMVAR 
	BMI  B1556  ;Branch if a plane game.
	STA  WSYNC
	STA  $84     ;Store GAMVAR*4 in 84.
	AND  #$80    ;IF it's a tank game.
B1556   STA  GUIDED     ;store in 83.
	;GUIDED is ZERO if a tank game
	;it is negative if a guided missile game,
	;it is overflowed if a machine gun game.
	;(Inapplicable in tank games, hence the
	;previous branch trick)
	LDA  #$F7     ;Store page F7
	STA  LORES+1 ;as high order byte
	STA  LORES+3 ;for all of these pointers,
	STA  LORES+5 ;'cause that's where it is.
	;Store the proper offsets for each column of
	;playfield from the vectors given
	LDA  PLFPNT,X
	STA  RESP0   ;Reset player 0 while we're at it.
	STA  LORES 
	LDA  PLFPNT+4,X
	STA  LORES+2
	LDA  PLFPNT+8,X
	STA  LORES+4
	RTS  
;
; I think this one determines sprite shape.
;
J1572   LDA  GAMVAR
	AND  #$87
	BMI  B157A
	;If bit 7 is set, we are playing with one or more
	;planes.  If not, well, we can only have one tank,
	;so...
	LDA  #$00
B157A   ASL   
	TAX  
	LDA  WIDTHS,X   ;The TIA's NUSIZ registers make
	STA  NUSIZ0     ;it as easy to play with two or
	LDA  WIDTHS+1,X ;three planes as it is for one
	STA  NUSIZ1     ;freakin' huge bomber.
	LDA  GAMVAR
	AND  #$C0
	LSR   
	LSR   
	LSR   
	LSR         ;Our hardware is now in bits 3 and 2.
	TAY         ;Of the Y-register.
	; Render joysticks immobile if game not in play.
	LDA  $88    ;1 = Game in play
	STA  SWCHB  ;1 = Joysticks enabled.
	EOR  #$FF
	AND  $DD
	STA  $D1
	LDX  #$FF
	LDA  SWCHB
	AND  #$08
	BNE  B15A7
	LDY  #$10
	LDX  #$0F
B15A7   STX  TEMP
	LDX  #$03
B15AB   LDA  L1765,Y
	EOR  $D1
	AND  TEMP
	STA  COLUP0,X  ;Color the real tank.
	STA  Color0,X  ;Color the virtual tank.
	STA  $D8,X
	INY  
	DEX  
	BPL  B15AB
	RTS  
;
; Zero all memory up to $A2.  Returns with zero bit set.
;
ClearMem   LDA  #$00
B15BF   INX  
	STA  $A2,X
	BNE  B15BF  ;Continue until X rolls over.
	RTS  

; *= $15C5
;
;                               Patterns for numbers
;
NUMBERS .byte $0E ;|    XXX | $F5C5   Leading zero is not drawn
       .byte $0A ; |    X X | $F5C6   because it's never used.
       .byte $0A ; |    X X | $F5C7
       .byte $0A ; |    X X | $F5C8
       .byte $0E ; |    XXX | $F5C9
       
       .byte $22 ; |  X   X | $F5CA
       .byte $22 ; |  X   X | $F5CB
       .byte $22 ; |  X   X | $F5CC
       .byte $22 ; |  X   X | $F5CD
       .byte $22 ; |  X   X | $F5CE
       
       .byte $EE ; |XXX XXX | $F5CF
       .byte $22 ; |  X   X | $F5D0
       .byte $EE ; |XXX XXX | $F5D1
       .byte $88 ; |X   X   | $F5D2
       .byte $EE ; |XXX XXX | $F5D3
       
       .byte $EE ; |XXX XXX | $F5D4
       .byte $22 ; |  X   X | $F5D5
       .byte $66 ; | XX  XX | $F5D6
       .byte $22 ; |  X   X | $F5D7
       .byte $EE ; |XXX XXX | $F5D8
       
       .byte $AA ; |X X X X | $F5D9
       .byte $AA ; |X X X X | $F5DA
       .byte $EE ; |XXX XXX | $F5DB
       .byte $22 ; |  X   X | $F5DC
       .byte $22 ; |  X   X | $F5DD
       
       .byte $EE ; |XXX XXX | $F5DE
       .byte $88 ; |X   X   | $F5DF
       .byte $EE ; |XXX XXX | $F5E0
       .byte $22 ; |  X   X | $F5E1
       .byte $EE ; |XXX XXX | $F5E2
       
       .byte $EE ; |XXX XXX | $F5E3
       .byte $88 ; |X   X   | $F5E4
       .byte $EE ; |XXX XXX | $F5E5
       .byte $AA ; |X X X X | $F5E6
       .byte $EE ; |XXX XXX | $F5E7
       
       .byte $EE ; |XXX XXX | $F5E8
       .byte $22 ; |  X   X | $F5E9
       .byte $22 ; |  X   X | $F5EA
       .byte $22 ; |  X   X | $F5EB
       .byte $22 ; |  X   X | $F5EC
       
       .byte $EE ; |XXX XXX | $F5ED
       .byte $AA ; |X X X X | $F5EE
       .byte $EE ; |XXX XXX | $F5EF
       .byte $AA ; |X X X X | $F5F0
       .byte $EE ; |XXX XXX | $F5F1
       
       .byte $EE ; |XXX XXX | $F5F2
       .byte $AA ; |X X X X | $F5F3
       .byte $EE ; |XXX XXX | $F5F4
       .byte $22 ; |  X   X | $F5F5
       .byte $EE ; |XXX XXX | $F5F6

;
;  A bunch of data read with the Y-register.
;  I still don't know.
;
L15F7   .BYTE  $F8 ,$F7 ,$F6 ,$06 ,$06
	.BYTE  $06 ,$16 ,$17 ,$18 ;     $15FC
	.BYTE  $19 ,$1A ,$0A ,$0A ;     $1600
	.BYTE  $0A ,$FA ,$F9 ,$F8 ;     $1604
	.BYTE  $F7 ,$F6 ,$F6 ,$06 ;     $1608
	.BYTE  $16 ,$16 ,$17 ,$18 ;     $160C
	.BYTE  $19 ,$1A ,$1A ,$0A ;     $1610
	.BYTE  $FA ,$FA ,$F9 ,$E8 ;     $1614
	.BYTE  $E6 ,$E4 ,$F4 ,$04 ;     $1618
	.BYTE  $14 ,$24 ,$26 ,$28 ;     $161C
	.BYTE  $2A ,$2C ,$1C ,$0C ;     $1620
	.BYTE  $FC ,$EC ,$EA ;          $1624
;
; Vectors for all sixteen possible headings, in 22.5
; degree increments.  This uses some sort of binary
; notation, or it might just go by nybble.  I just
; haven't figured it out yet.
;
HDGTBL   .BYTE  $C8 ,$C4 ,$C0 ,$E0
	.BYTE  $00 ,$20 ,$40 ,$44 
	.BYTE  $48 ,$4C ,$4F ,$2F
	.BYTE  $0F ,$EF ,$CF ,$CC

;
; Has to do with player velocity.  Every
; even location goes to $A8,X and every
; odd location goes to $AA,X.  Bit 7 is
; significant.  I can't help but think
; this is a multiplication table of some
; kind.
;
L1637   .BYTE  $00 ,$00 ,$80 ,$80
	.BYTE  $84 ,$20 ,$88 ,$88
	.BYTE  $92 ,$48 ,$A4 ,$A4
	.BYTE  $A9 ,$52 ,$AA ,$AA
	.BYTE  $D5 ,$AA ,$DA ,$DA
	.BYTE  $DB ,$6D ,$EE ,$EE
;
; These are all the sprite shapes.
; The most I suspect any of you will do is
; modify these.  And/or the number shapes.
;
TankShape
       .byte $00 ; |        | $F64F
       .byte $FC ; |XXXXXX  | $F650
       .byte $FC ; |XXXXXX  | $F651
       .byte $38 ; |  XXX   | $F652
       .byte $3F ; |  XXXXXX| $F653
       .byte $38 ; |  XXX   | $F654
       .byte $FC ; |XXXXXX  | $F655
       .byte $FC ; |XXXXXX  | $F656
       
       .byte $1C ; |   XXX  | $F657
       .byte $78 ; | XXXX   | $F658
       .byte $FB ; |XXXXX XX| $F659
       .byte $7C ; | XXXXX  | $F65A
       .byte $1C ; |   XXX  | $F65B
       .byte $1F ; |   XXXXX| $F65C
       .byte $3E ; |  XXXXX | $F65D
       .byte $18 ; |   XX   | $F65E

       .byte $19 ; |   XX  X| $F65F
       .byte $3A ; |  XXX X | $F660
       .byte $7C ; | XXXXX  | $F661
       .byte $FF ; |XXXXXXXX| $F662
       .byte $DF ; |XX XXXXX| $F663
       .byte $0E ; |    XXX | $F664
       .byte $1C ; |   XXX  | $F665
       .byte $18 ; |   XX   | $F666
       
       .byte $24 ; |  X  X  | $F667
       .byte $64 ; | XX  X  | $F668
       .byte $79 ; | XXXX  X| $F669
       .byte $FF ; |XXXXXXXX| $F66A
       .byte $FF ; |XXXXXXXX| $F66B
       .byte $4E ; | X  XXX | $F66C
       .byte $0E ; |    XXX | $F66D
       .byte $04 ; |     X  | $F66E
       
       .byte $08 ; |    X   | $F66F
       .byte $08 ; |    X   | $F670
       .byte $6B ; | XX X XX| $F671
       .byte $7F ; | XXXXXXX| $F672
       .byte $7F ; | XXXXXXX| $F673
       .byte $7F ; | XXXXXXX| $F674
       .byte $63 ; | XX   XX| $F675
       .byte $63 ; | XX   XX| $F676
       
       .byte $24 ; |  X  X  | $F677
       .byte $26 ; |  X  XX | $F678
       .byte $9E ; |X  XXXX | $F679
       .byte $FF ; |XXXXXXXX| $F67A
       .byte $FF ; |XXXXXXXX| $F67B
       .byte $72 ; | XXX  X | $F67C
       .byte $70 ; | XXX    | $F67D
       .byte $20 ; |  X     | $F67E
       
       .byte $98 ; |X  XX   | $F67F
       .byte $5C ; | X XXX  | $F680
       .byte $3E ; |  XXXXX | $F681
       .byte $FF ; |XXXXXXXX| $F682
       .byte $FB ; |XXXXX XX| $F683
       .byte $70 ; | XXX    | $F684
       .byte $38 ; |  XXX   | $F685
       .byte $18 ; |   XX   | $F686
       
       .byte $38 ; |  XXX   | $F687
       .byte $1E ; |   XXXX | $F688
       .byte $DF ; |XX XXXXX| $F689
       .byte $3E ; |  XXXXX | $F68A
       .byte $38 ; |  XXX   | $F68B
       .byte $F8 ; |XXXXX   | $F68C
       .byte $7C ; | XXXXX  | $F68D
       .byte $18 ; |   XX   | $F68E

JetShape
       .byte $60 ; | XX     | $F68F
       .byte $70 ; | XXX    | $F690
       .byte $78 ; | XXXX   | $F691
       .byte $FF ; |XXXXXXXX| $F692
       .byte $78 ; | XXXX   | $F693
       .byte $70 ; | XXX    | $F694
       .byte $60 ; | XX     | $F695
       .byte $00 ; |        | $F696
       
       .byte $00 ; |        | $F697
       .byte $C1 ; |XX     X| $F698
       .byte $FE ; |XXXXXXX | $F699
       .byte $7C ; | XXXXX  | $F69A
       .byte $78 ; | XXXX   | $F69B
       .byte $30 ; |  XX    | $F69C
       .byte $30 ; |  XX    | $F69D
       .byte $30 ; |  XX    | $F69E
       
       .byte $00 ; |        | $F69F
       .byte $03 ; |      XX| $F6A0
       .byte $06 ; |     XX | $F6A1
       .byte $FC ; |XXXXXX  | $F6A2
       .byte $FC ; |XXXXXX  | $F6A3
       .byte $3C ; |  XXXX  | $F6A4
       .byte $0C ; |    XX  | $F6A5
       .byte $0C ; |    XX  | $F6A6
       
       .byte $02 ; |      X | $F6A7
       .byte $04 ; |     X  | $F6A8
       .byte $0C ; |    XX  | $F6A9
       .byte $1C ; |   XXX  | $F6AA
       .byte $FC ; |XXXXXX  | $F6AB
       .byte $FC ; |XXXXXX  | $F6AC
       .byte $1E ; |   XXXX | $F6AD
       .byte $06 ; |     XX | $F6AE
       
       .byte $10 ; |   X    | $F6AF
       .byte $10 ; |   X    | $F6B0
       .byte $10 ; |   X    | $F6B1
       .byte $38 ; |  XXX   | $F6B2
       .byte $7C ; | XXXXX  | $F6B3
       .byte $FE ; |XXXXXXX | $F6B4
       .byte $FE ; |XXXXXXX | $F6B5
       .byte $10 ; |   X    | $F6B6
       
       .byte $40 ; | X      | $F6B7
       .byte $20 ; |  X     | $F6B8
       .byte $30 ; |  XX    | $F6B9
       .byte $38 ; |  XXX   | $F6BA
       .byte $3F ; |  XXXXXX| $F6BB
       .byte $3F ; |  XXXXXX| $F6BC
       .byte $78 ; | XXXX   | $F6BD
       .byte $60 ; | XX     | $F6BE
       
       .byte $40 ; | X      | $F6BF
       .byte $60 ; | XX     | $F6C0
       .byte $3F ; |  XXXXXX| $F6C1
       .byte $1F ; |   XXXXX| $F6C2
       .byte $1E ; |   XXXX | $F6C3
       .byte $1E ; |   XXXX | $F6C4
       .byte $18 ; |   XX   | $F6C5
       .byte $18 ; |   XX   | $F6C6
       
       .byte $00 ; |        | $F6C7
       .byte $83 ; |X     XX| $F6C8
       .byte $7F ; | XXXXXXX| $F6C9
       .byte $3E ; |  XXXXX | $F6CA
       .byte $1E ; |   XXXX | $F6CB
       .byte $0C ; |    XX  | $F6CC
       .byte $0C ; |    XX  | $F6CD
       .byte $0C ; |    XX  | $F6CE
PlaneShape
       .byte $00 ; |        | $F6CF
       .byte $8E ; |X   XXX | $F6D0
       .byte $84 ; |X    X  | $F6D1
       .byte $FF ; |XXXXXXXX| $F6D2
       .byte $FF ; |XXXXXXXX| $F6D3
       .byte $04 ; |     X  | $F6D4
       .byte $0E ; |    XXX | $F6D5
       .byte $00 ; |        | $F6D6
       
       .byte $00 ; |        | $F6D7
       .byte $0E ; |    XXX | $F6D8
       .byte $04 ; |     X  | $F6D9
       .byte $8F ; |X   XXXX| $F6DA
       .byte $7F ; | XXXXXXX| $F6DB
       .byte $72 ; | XXX  X | $F6DC
       .byte $07 ; |     XXX| $F6DD
       .byte $00 ; |        | $F6DE
       
       .byte $10 ; |   X    | $F6DF
       .byte $36 ; |  XX XX | $F6E0
       .byte $2E ; |  X XXX | $F6E1
       .byte $0C ; |    XX  | $F6E2
       .byte $1F ; |   XXXXX| $F6E3
       .byte $B2 ; |X XX  X | $F6E4
       .byte $E0 ; |XXX     | $F6E5
       .byte $40 ; | X      | $F6E6
       
       .byte $24 ; |  X  X  | $F6E7
       .byte $2C ; |  X XX  | $F6E8
       .byte $5D ; | X XXX X| $F6E9
       .byte $1A ; |   XX X | $F6EA
       .byte $1A ; |   XX X | $F6EB
       .byte $30 ; |  XX    | $F6EC
       .byte $F0 ; |XXXX    | $F6ED
       .byte $60 ; | XX     | $F6EE
       
       .byte $18 ; |   XX   | $F6EF
       .byte $5A ; | X XX X | $F6F0
       .byte $7E ; | XXXXXX | $F6F1
       .byte $5A ; | X XX X | $F6F2
       .byte $18 ; |   XX   | $F6F3
       .byte $18 ; |   XX   | $F6F4
       .byte $18 ; |   XX   | $F6F5
       .byte $78 ; | XXXX   | $F6F6
       
       .byte $34 ; |  XX X  | $F6F7
       .byte $36 ; |  XX XX | $F6F8
       .byte $5A ; | X XX X | $F6F9
       .byte $78 ; | XXXX   | $F6FA
       .byte $2C ; |  X XX  | $F6FB
       .byte $0C ; |    XX  | $F6FC
       .byte $06 ; |     XX | $F6FD
       .byte $0C ; |    XX  | $F6FE
       
       .byte $08 ; |    X   | $F6FF
       .byte $6C ; | XX XX  | $F700
       .byte $70 ; | XXX    | $F701
       .byte $B8 ; |X XXX   | $F702
       .byte $DC ; |XX XXX  | $F703
       .byte $4E ; | X  XXX | $F704
       .byte $07 ; |     XXX| $F705
       .byte $06 ; |     XX | $F706
       
       .byte $38 ; |  XXX   | $F707
       .byte $10 ; |   X    | $F708
       .byte $F0 ; |XXXX    | $F709
       .byte $7C ; | XXXXX  | $F70A
       .byte $4F ; | X  XXXX| $F70B
       .byte $E3 ; |XXX   XX| $F70C
       .byte $02 ; |      X | $F70D
       .byte $00 ; |        | $F70E
;
; These are sub-pointers, used to set up the
; two-dimensional array at CTRLTBL.
;
L170F   .BYTE  $00 ,$0B ,$16

;
; Two-dimensional array, 12x3.
;
; This array specifies what the joystick does
; in each game.  Looking at it now the format looks
; like this:
;
;   Low nybble = Amount to rotate object (signed)
;                   $00 = Not at all
;                   $01 = Clockwise         (+1)
;                   $0F = Counter-clockwise (-1)
;   High nybble = Speed to move object (unsigned)
;                   $00 = Not moving
;                   $F0 = Warp speed
;
; Observe the $FF's.  Notice how indexing out of bounds with impossible
; joystick movements will cause strange behavior.
;
; Tank movement
;                    UP  DOWN (No reverse)
CTRLTBL .BYTE  $00 ,$10 ,$00 ,$FF
	.BYTE  $01 ,$11 ,$01 ,$FF ;LEFT
	.BYTE  $0F ,$1F ,$0F      ;RIGHT
;
; Biplane movement (This is why controls are sideways)
;                    UP  DOWN
	.BYTE  $50 ,$5F ,$51 ,$FF ;
	.BYTE  $30 ,$3F ,$31 ,$FF ;LEFT
	.BYTE  $70 ,$7F ,$71      ;RIGHT
;
; Jet fighter movement
;                    UP  DOWN
	.BYTE  $90 ,$B0 ,$70 ,$FF ;
	.BYTE  $91 ,$B1 ,$71 ,$FF ;LEFT
	.BYTE  $9F ,$BF ,$7F      ;RIGHT
;
	ORG $1733
; Sound information for different game types.
; Different tools of destruction make different
; sound.
;
; There is some more data below which looks to
; be other information; different machines at
; different speeds.  However this is reached,
; this could be called a three-dimensional array.
;
;         Tanks Biplane, Jet Fighter
SNDV   .BYTE  $08 ,$02 ,$02 ;          sound volumes
SNDC   .BYTE  $02 ,$03 ,$08 ;          sound types
SNDP   .BYTE  $1D ,$05 ,$00 ;          sound pitches
	.BYTE  $00 ,$00 ,$00 ,$00 ;     $173C
	.BYTE  $00 ,$00 ,$00 ,$00 ;     $1740
	.BYTE  $00 ,$00 ,$00 ,$1D ;     $1747
	.BYTE  $1D ,$16 ,$16      ;     $174A
	.BYTE  $0F ,$0F ,$00 
	.BYTE  $00 ,$00 ,$00  ;     $174E
	.BYTE  $00 ,$00 ,$00  ;     $1751
	.BYTE  $00 ,$00 ,$12  ;     $1754
	.BYTE  $10 ,$10 ,$0C  ;     $1757
	.BYTE  $0C ,$07 ,$07  ;        $175A

	ORG $175D
;
; Player widths for various plane games.
; Through the miracle of the Atari 2600's NUSIZ
; register, the difference between a 1 vs. 1 game
; and a Bomber vs. 3 game is contained in just
; two bytes.
;
WIDTHS   .BYTE  $00 ,$00  ;1 vs. 1
	.BYTE  $01 ,$01  ;2 vs. 2
	.BYTE  $00 ,$03  ;1 vs. 3
	.BYTE  $27 ,$03  ;Bomber vs. 3

	ORG $1765
L1765: .byte $EA ; |XXX X X | $F765
       .byte $3C ; |  XXXX  | $F766
       .byte $82 ; |X     X | $F767
       .byte $44 ; | X   X  | $F768
       .byte $32 ; |  XX  X | $F769
       .byte $2C ; |  X XX  | $F76A
       .byte $8A ; |X   X X | $F76B
       .byte $DA ; |XX XX X | $F76C
       .byte $80 ; |X       | $F76D
       .byte $9C ; |X  XXX  | $F76E
       .byte $DA ; |XX XX X | $F76F
       .byte $3A ; |  XXX X | $F770
       .byte $64 ; | XX  X  | $F771
       .byte $A8 ; |X X X   | $F772
       .byte $DA ; |XX XX X | $F773
       .byte $4A ; | X  X X | $F774
PFWall1
       .byte $08 ; |    X   | $F775
       .byte $04 ; |     X  | $F776
       .byte $00 ; |        | $F777
       .byte $0E ; |    XXX | $F778
       .byte $F0 ; |XXXX    | $F779
       .byte $10 ; |   X    | $F77A
       .byte $10 ; |   X    | $F77B
       .byte $10 ; |   X    | $F77C
       .byte $10 ; |   X    | $F77D
       .byte $10 ; |   X    | $F77E
       .byte $10 ; |   X    | $F77F
       .byte $10 ; |   X    | $F780
       .byte $10 ; |   X    | $F781
       .byte $10 ; |   X    | $F782
       .byte $10 ; |   X    | $F783
       .byte $10 ; |   X    | $F784
       .byte $FF ; |XXXXXXXX| $F785
       .byte $00 ; |        | $F786
       .byte $00 ; |        | $F787
       .byte $00 ; |        | $F788
       .byte $38 ; |  XXX   | $F789
       .byte $00 ; |        | $F78A
       .byte $00 ; |        | $F78B
       .byte $00 ; |        | $F78C
       .byte $60 ; | XX     | $F78D
       .byte $20 ; |  X     | $F78E
       .byte $20 ; |  X     | $F78F
       .byte $23 ; |  X   XX| $F790
       .byte $FF ; |XXXXXXXX| $F791
       .byte $80 ; |X       | $F792
       .byte $80 ; |X       | $F793
       .byte $00 ; |        | $F794
       .byte $00 ; |        | $F795
       .byte $00 ; |        | $F796
       .byte $1C ; |   XXX  | $F797
       .byte $04 ; |     X  | $F798
PFWall2
       .byte $00 ; |        | $F799
       .byte $00 ; |        | $F79A
       .byte $00 ; |        | $F79B
       .byte $00 ; |        | $F79C
       .byte $FF ; |XXXXXXXX| $F79D
       .byte $00 ; |        | $F79E
       .byte $00 ; |        | $F79F
       .byte $00 ; |        | $F7A0
       .byte $00 ; |        | $F7A1
       .byte $00 ; |        | $F7A2
       .byte $00 ; |        | $F7A3
       .byte $00 ; |        | $F7A4
       .byte $00 ; |        | $F7A5
       .byte $00 ; |        | $F7A6
       .byte $00 ; |        | $F7A7
       .byte $00 ; |        | $F7A8
       .byte $00 ; |        | $F7A9
       .byte $07 ; |     XXX| $F7AA
       .byte $1F ; |   XXXXX| $F7AB
       .byte $3F ; |  XXXXXX| $F7AC
       .byte $7F ; | XXXXXXX| $F7AD
       .byte $FF ; |XXXXXXXX| $F7AE
       .byte $00 ; |        | $F7AF
       .byte $00 ; |        | $F7B0
       .byte $00 ; |        | $F7B1
       .byte $00 ; |        | $F7B2
       .byte $00 ; |        | $F7B3
       .byte $00 ; |        | $F7B4
       .byte $00 ; |        | $F7B5
       .byte $00 ; |        | $F7B6
       .byte $60 ; | XX     | $F7B7
       .byte $20 ; |  X     | $F7B8
       .byte $21 ; |  X    X| $F7B9
       .byte $FF ; |XXXXXXXX| $F7BA
       .byte $00 ; |        | $F7BB
       .byte $00 ; |        | $F7BC
       .byte $00 ; |        | $F7BD
       .byte $80 ; |X       | $F7BE
       .byte $80 ; |X       | $F7BF
       .byte $80 ; |X       | $F7C0
       .byte $80 ; |X       | $F7C1
       .byte $00 ; |        | $F7C2
       .byte $00 ; |        | $F7C3
       .byte $00 ; |        | $F7C4
       .byte $07 ; |     XXX| $F7C5

; Addresses for Sprite Graphics

SPRLO   .BYTE  #<TankShape, #<PlaneShape, #<JetShape
SPRHI   .BYTE  #>TankShape, #>PlaneShape, #>JetShape


; Playfield address data
;
;         Complex, None, Simple, Clouds
PLFPNT  .BYTE  $75 ,$75 ,$75 ,$9A
	.BYTE  $81 ,$99 ,$AA ,$9D
	.BYTE  $8D ,$99 ,$B6 ,$9D

; Format of game, best guess I have so far...
;
; bits   
;   1,0:      TANKS         PLANES
;        00 = Normal        1 vs. 1
;        01 = Invisible     2 vs. 2
;        10 =               3 vs. 1
;        11 =               3 vs. Giant
;   3,2: 01 = No maze
;        10 = Simple maze or clouds
;        00 = Complex maze or no clouds
;     4: Tanks, 1 = Must bounce to score hit
;        Planes, 1 = Machine Gun
;     5: 1 = Guided Missiles
;   7,6: 00 = Tanks
;        01 = Tank Pong
;        10 = Biplanes
;        11 = Jet Fighter
; (Bit 7 controls whether this is a tank or plane game)
;     
VARDATA   .BYTE  $24 ;Game 1:  0010 0100  TANK
	.BYTE  $28 ;Game 2:  0010 1000
	.BYTE  $08 ;Game 3:  0000 1000
	.BYTE  $20 ;Game 4:  0010 0000
	.BYTE  $00 ;Game 5:  0000 0000
	.BYTE  $48 ;Game 6:  0100 1000  TANK PONG
	.BYTE  $40 ;Game 7:  0100 0000
	.BYTE  $54 ;Game 8:  0101 0100
	.BYTE  $58 ;Game 9:  0101 1000
	.BYTE  $25 ;Game 10: 0010 0101  INVISIBLE TANK
	.BYTE  $29 ;Game 11: 0010 1001
	.BYTE  $49 ;Game 12: 0100 1001
	.BYTE  $55 ;Game 13: 0101 0101
	.BYTE  $59 ;Game 14: 0101 1001
	.BYTE  $A8 ;Game 15: 1010 1000  BIPLANE
	.BYTE  $88 ;Game 16: 1000 1000
	.BYTE  $98 ;Game 17: 1001 1000
	.BYTE  $90 ;Game 18: 1001 0000
	.BYTE  $A1 ;Game 19: 1010 0001
	.BYTE  $83 ;Game 20: 1000 0011
	.BYTE  $E8 ;Game 21: 1110 1000  JET FIGHTER
	.BYTE  $C8 ;Game 22: 1100 1000
	.BYTE  $E0 ;Game 23: 1110 0000
	.BYTE  $C0 ;Game 24: 1100 0000
	.BYTE  $E9 ;Game 25: 1110 1001
	.BYTE  $E2 ;Game 26: 1110 0010
	.BYTE  $C1 ;Game 27: 1100 0001
; $FF to signify end of game variations.
; Theoretically one could add up to six
; additional variations.
	.BYTE  $FF

	ORG $17FC
	.word $f000 ;          Reset
L17FE  .BYTE  $0F, $11 ;        IRQ - (used as pitch for sound generator)


;-------------------------------------------------------------------------
; Song player stuff

excuseMe

	;DEBUG
;	JMP ConSwitch

	; When the select button is pressed
	; the memory is cleared which takes
	; a bunch of extra cycles, so skip
	; the song player.
    LDA  SWCHB  ; Select button.  ???
	AND  #$02
	BEQ  noPlayer

	jsr songPlayer
noPlayer

	JMP  ConSwitch



;-------------------------------------------------------------------------
; This is called at program startup.
; Init song variables here

songSetup
	lda #105
	sta measure

	JMP  J11A3


	include songplay.h


	ORG $1FFC
	.word $f000 ;          Reset
L1FFE  .BYTE  $0F, $11 ;        IRQ - (used as pitch for sound generator)

;
; Recent changes:
;
; 08/05/96: Added dollar-signs to signify hex numbers.
;           The original, strangely, omitted them.
;           Started update list at end of document.
;           Still have no clue where the joystick code
;           is....
;
; 08/12/96: Figured out some joystick code, now that
;           I understand how they work.  Renamed GAMSHP
;           because it wasn't really "velocity", but
;           really the tank type.  Velocity is now
;           what it should be.
;
; 10/19/96: Cracked the mystery of the joystick-port
;           write.  No, Tim, it's not an LED, it's for
;           disabling the joystick when in game select
;           mode.  Thanks to AlanD for this theory.
;
; 2/21/97:  Added cycle counting to score drawing section.
;           I'm sure Kaplan wasn't this precise, but it
;           is a bit helpful.
;
; 2/26/97:  Changed year of above update to 1997.  :-)
;           Changed a few variable names and made some of
;           my notes a bit clearer.  I'm also naming some
;           of those mysterious JSR's.  Plus, it actually
;           COMPILES with DASM.  Whee!
;
; 8/26/97: Oops.  Turns out Larry Wagner made Combat.  Sorry.



Attachment: combrock.bin
Description: Binary data

Current Thread