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