💾 Archived View for uscoffings.net › retro-computing › software › 6502 › nbcombat.asm captured on 2024-08-18 at 21:36:17.

View Raw

More Information

⬅️ Previous capture (2022-07-16)

🚧 View Differences

-=-=-=-=-=-=-

; 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


	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  J11A3
MLOOP   JSR  NWSCR ;            $1014
	JSR  ConSwitch
	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  AUDV0,X  ;Sound effects.  BOOOM!
	LDA  #$08
	STA  AUDC0,X
	LDA  L17FE,X
	STA  AUDF0,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  AUDC0,X
	LDA  #$07
	STA  AUDV0,X
	LDA  $9B,X  
	STA  AUDF0,X
	RTS  
	;Ambient sound.
B1421   LDY  GAMSHP
	LDA  SNDV,Y
	AND  $88   ;$88 affects sound too? wow.
		   ;Perhaps speed too
	STA  AUDV0,X ;see how it affects volume?
	LDA  SNDC,Y
	STA  AUDC0,X
	CLC  
	LDA  #$00
B1432   DEY  
	BMI  B1439
	ADC  #$0C
	BPL  B1432
B1439   ADC  $8B,X
	TAY  
	TXA  
	ASL   
	ADC  SNDP,Y
	STA  AUDF0,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  AUDV0,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)

;
; 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.