Atari Vcs 2600 River Raid Labeled Assembler Source Code

  • Uploaded by: AlainleGuirec
  • 0
  • 0
  • October 2019
  • PDF

This document was uploaded by user and they confirmed that they have the permission to share it. If you are author or own the copyright of this book, please report to us by using this DMCA report form. Report DMCA


Overview

Download & View Atari Vcs 2600 River Raid Labeled Assembler Source Code as PDF for free.

More details

  • Words: 16,039
  • Pages: 65
; *** R I V E R R A I D *** ; Copyright 1982 Activision ; Designer: Carol Shaw ; Analyzed, labeled and commented ; by Thomas Jentzsch (JTZ) ; Last Update: 13.08.2001 (v0.9) ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ;

Section generation: The river is divided into sections which are generated by random. The random number generator can generate 57337 different sections. Each section is divided into 16 blocks. The last block is the bridge. For each other block a random Id is generated, which defines the shape of the river. The river is randomly generated with or without islands. Each block is 32 lines high and is divided into two parts. Those parts are neccessary for the bridge only, because it is smaller than a whole block.

; ; ; ; ; ; ; ; ; ;

Misc: - There are no score variables, the score is stored and changed directly in the display pointers! - The are no variables to store the x-positions of the objects, all calculations are done directly with the position values. (There aren't any BCD calculations in this code!) - All variables for the players are swapped, when the players change. - The game speeds aren't adjusted for PAL, the PAL game run's about 16% slower. (This seems to be true for most PAL conversions.) - ...

All objects are also randomly generated. There is one object in each block. First the game randomly selects if a fuel tank, an enemy object (ship, plane or helicopter) or a house should be generated. Then a starting x-position is defined and finally the direction (left/right) of the object is set. The ships and helicopters start patroling also randomly. Kernel: The main display is 160 lines tall. Below is the state display (score, fuel, lives and copyright). The kernel displays five or six of the section blocks. When a block leaves the display, it is replaced on the fly by a new generated one. It's basically a two line kernel, which is repeated twelve times. After that, there is code for eight more lines, where the block is iterated and all new parameter are set. (12 * 2 + 8 = 32!) The parameters for each block are: - a pointer to the current playfield pattern - a flag for a bright or dark green playfield - two pointers for the current object, the data is displayed interlaced, this gives in a single line resolution here - a color pointer for the object - x-positioning values for the object - some flags for the object (size, reflection...) All collisons are checked for each displayed block and only the hardware collision registers are used for that (no software calculations).

processor 6502 include vcs.h ;===============================================================================

; A S S E M B L E R - S W I T C H E S ;=============================================================================== FILL_OPT SCREENSAVER TRAINER NTSC

= = = =

1 1 0 1

; ; ; ;

fill optimized bytes with NOPs compile with screensaver code enable training mode compile for NTSC

;=============================================================================== ; C O N S T A N T S ;=============================================================================== ; initial values for the random number generator: SEED_LO = $14 ; change "to go, where no one has gone before" :) SEED_HI = $A8 ; color constants: BLACK = $00 GREY = $06 ORANGE = $2A IF NTSC YELLOW = $1C RED = $48 BLUE = $84 CYAN = $B0 GREEN = $D2 ELSE YELLOW = $2C RED = $68 BLUE = $B4 CYAN = $70 GREEN = $52 ENDIF DARK_RED = RED LIGHT_GREEN = GREEN BROWN = YELLOW LIGHT_GREY = GREY DARK_BLUE = BLUE

+ + -

$6 $8 $C $6 $4

; main game constants: NUM_BLOCKS = 6 SECTION_BLOCKS = 16 BLOCK_PARTS = 2 BLOCK_SIZE = 32 NUM_LINES = 160 MAX_LEVEL = 48 DIGIT_H JET_Y MIN_MISSILE MAX_MISSILE MISSILE_SPEED ROAD_HEIGHT INTRO_SCROLL

= = = = = = =

8 19 JET_Y-6 NUM_LINES+1 6 13 48

SWITCH_PAGE_ID

= 9

; ; ; ; ; ;

max. number of block on screen number of blocks/stage each block has two parts number of lines/block number of lines in main kernel number of difficulty levels

; height of the score digits ; fixed y-position for jet ; starting position of player missile ; y-speed of the jet missile ; number of lines for road ; counter for scrolling into new game ; first pattern id with data on different page

; constants for ID_EXPLOSION0 ID_EXPLOSION1 ID_EXPLOSION2 ID_EXPLOSION3 ID_PLANE ID_HELI0 ID_HELI1 ID_SHIP ID_BRIDGE ID_HOUSE ID_FUEL

shape-ids: = 0 = 1 = 2 = 3 = 4 = 5 = 6 = 7 = 8 = 9 = 10

; used for explosion end

; flags for blockLst: PF1_PAGE_FLAG = %00000001 PF2_PAGE_FLAG = %00000010 PF_COLOR_FLAG = %00000100 PATROL_FLAG = %00010000 PF_COLLIDE_FLAG = %00100000 ENEMY_MOVE_FLAG = %01000000 PF_ROAD_FLAG = %10000000

; ; ; ; ; ; ;

; flags for State1Lst: DIRECTION_FLAG = %00001000 FINE_MASK = %11110000 NUSIZ_MASK = %00000111

; move direction of object ; mask bits for HMxy ; mask bits for NUSIx

; flags for PF_State: ISLAND_FLAG = %10000000 CHANGE_FLAG = %01000000 might be wrong)

pattern for PF1 in page $FC or $FD pattern for PF1 in page $FC or $FD bright or dark green PF enemy is patroling (change directions) enemy collided with playfield enemy is moving display road and bridge

; island displayed in block ; begin or end of island (JTZ: this interpretation

; joystick bits: MOVE_RIGHT = %00001000 MOVE_LEFT = %00000100 MOVE_DOWN = %00000010 MOVE_UP = %00000001 ; values for ENAxy: DISABLE = %00 ENABLE = %10

; value for enabling a missile

; values for NUSIZx: TWO_COPIES = %001 THREE_COPIES = %011 DOUBLE_SIZE = %101 QUAD_SIZE = %111 ; mask for SWCHB: BW_MASK = %1000

; black and white bit

;=============================================================================== ; Z P - V A R I A B L E S ;=============================================================================== gameVariation gameDelay

= $80 = $81

; ;

one or two player game delay before gameVariation changes

frameCnt = random = start of ship and joystick = IF SCREENSAVER SS_XOR = (0/$01..$ff) SS_Mask = ($ff/$f7) ENDIF dXSpeed = prevPF1PatId = previous block PF_State = sectionEnd = blockOffset = posYLo = bridgeExplode =

$82 ; $83 ; helicopter, sound) $84 ;

simple frame counter 8 bit random number (used for:

$85

;

change colors in screensaver mode

$86

;

darker colors in screensaver mode

$87 $88

; ;

x-acceleration playfield pattern Id of the

$89 $8A $8B $8C $8D

; ; ; ; ;

io000000 0 = end of section offset into first displayed block low value of blockOffset counter for bridge explosion

saved joystick value (?000rldu)

; the next 36 bytes are used to save all variables for six blocks: ;--------------------------------------blockLst = $8E ; ..$93 flags for block definition blockLstEnd = blockLst+NUM_BLOCKS-1 ;--------------------------------------XPos1Lst = $94 ; ..$99 coarse value for x-positioning of object XPos1LstEnd = XPos1Lst+NUM_BLOCKS-1 ;--------------------------------------State1Lst = $9A ; ..$9F bit 0..2 = NUSIZ1, bit 3 = REFP1, 4..7 = fine move State1LstEnd = State1Lst+NUM_BLOCKS-1 ;--------------------------------------Shape1IdLst = $A0 ;.. $A5 ids for object Shape1IdLstEnd = Shape1IdLst+NUM_BLOCKS-1 ;--------------------------------------PF1Lst = $A6 ; ..$AB low pointer for PF1 data PF1LstEnd = PF1Lst+NUM_BLOCKS-1 ;--------------------------------------PF2Lst = $AC ; ..$B1 low pointer for PF2 data PF2LstEnd = PF2Lst+NUM_BLOCKS-1 ;--------------------------------------; end of block variables missileY = $B2 ; y-position of player missile playerX = $B3 ; x-position of player jet speedX = $B4 ; x-speed of player jet speedY = $B5 ; y-speed of play jet blockPart = $B6 ; 1/2 (used for bridge) fuelHi = $B7 ; high value of fuel (displayed) fuelLo = $B8 ; low value of fuel sectionBlock = $B9 ; number of block in current section (16..1) shapePtr0 = $BA ; ..$BB pointer to the shape for the player jet PF1PatId = $BC ; playfield pattern Id for the new generated block ;--------------------------------------player1State = $BD ; ..$C1 level = player1State ; difficulty level for current

player (1..48) randomLoSave = player1State+1; begin of level randomHiSave = player1State+2; livesPtr = player1State+3; ..$C1 ;--------------------------------------player2State = $C2 ; ..$C5 livesPtr2 = player2State+3; here, because it's const ;--------------------------------------gameMode = $C6 ; = scroll into game shapePtr1a = $C7 ; ..$C8 shapePtr1b = $C9 ; ..$CA colorPtr = $CB ; ..$CC scorePtr1 = $CD ; ..$D8 current player PF1Ptr = $D9 ; ..$DA PF2Ptr = $DB ; ..$DC ;--------------------------------------scorePtr2 = $DD ; ..$E7 other player ; the constant hi-pointers are temporary used: blockNum = scorePtr2+1 ; reflect0 = scorePtr2+3 ; reflection hitEnemyIdx = scorePtr2+5 ; missile PFCrashFlag = scorePtr2+7 ; missileFlag = scorePtr2+9 ; ;--------------------------------------collidedEnemy = $E8 ; randomLo = $E9 ; randomHi = $EA randomLoSave2 = $EB ; current player randomHiSave2 = $EC temp2 = $ED ; roadBlock = temp2 ; PFcolor = $EE ; valleyWidth = PFcolor ; first levels (6/0) playerColor = $EF ; stateBKColor = $F0 ; statePFColor = $F1 ; temp = $F2 ; diffPF = temp ; ids zero1 = $f3 ; player = $F4 ; missileX = $F5 ; zero2 = $F6 ; IF SCREENSAVER SS_Delay = $F7 ; ENDIF sound0Id = $F8 ; sound0Cnt = $F9 bridgeSound = $FA ;

saved random generator values for

the high pointer is not saved 0 = running; -1 = game over; 1..48

12 bytes for the score display of

12 bytes for the score display of current block in kernel flag for GRP0 (player jet) index of enemy that was hit by jet crashed into playfield $ff means: missile enabled jet collided with enemy (id) current number generator values saved number generator values for

bit 7 = 1: road in block color of river banks define minimum width of valley in YELLOW/BLACK GREY (const!) YELLOW+2 (const!) main temporary variable difference between to PF pattern always zero! 0/1 x-position of player missile always zero! screensaver delay

bridge is exploding

missileSound temp3 blockLine kernel maxId lineNum

= $FB = $FC = temp3 = temp3 = $FD

;

missile fired

;

current displayed line of block in

;

counter for kernel lines

;=============================================================================== ; M A C R O S ;=============================================================================== MAC FILL_NOP IF FILL_OPT REPEAT {1} NOP REPEND ENDIF ENDM ;=============================================================================== ; R O M - C O D E (Part 1) ;=============================================================================== ORG $F000 START:

SEI CLD LDX

Reset:

LDA .loopClear: STA TXS INX BNE JSR LDA LDX JSR LDX JSR LDA BNE INC STA LDA STA MainLoop: LDX LDA LSR LSR LSR CLC

#0

; 2 ; 2 ; 2

#0

; 2

$00,X

; ; ; .loopClear ; SetScorePtrs ; #>Zero ; #12-1 ; SetScorePtr1 ; #colorPtr+1-PF1Lst; GameInit ; random ; MainLoop ; random ; livesPtr ; #
4 2 2 2 6 2 2 6 2 6 3 2 5 3 2 3

#4 fuelHi

2 3 2 2 2 2

; ; ; ; ; ;

set high-pointers to $FB #38

= 0!

offset ball

ADC JSR

#69 SetPosX

; 2 ; 6

position ball for fuel display

; *** prepare everything for the main kernel: *** ; set all color registers (and NUSIZ1 = 0) INX ; 2 x = 5! .loopSetColors: LDA ColorTab,X ; 4 IF SCREENSAVER EOR SS_XOR ; 3 AND SS_Mask ; 3 ELSE FILL_NOP 4 ENDIF STA PFcolor,X ; 4 STA NUSIZ1,X ; 4 DEX ; 2 BPL .loopSetColors ; 2 TAY ; 2 y = 0! LDA scorePtr1+10 ; 3 CMP #
temp NUSIZ0 playerX reflect0 REFP0 .noReflect

SetPosX

; ; ; ; ; ; ; ;

2 3 3 3 3 3 2 2

; 2 ; 6 ; 2

flicker background red

x = 0!

adjust x-pos x-position player jet

STX

CTRLPF

; 3

reflect playfield

STX

VDELP1

; 3

enable vertical delay for player 1

; set size, reflect and postion for top enemy object; LDY XPos1Lst +NUM_BLOCKS-1; 3 LDA State1Lst+NUM_BLOCKS-1; 3 STA NUSIZ1 ; 3 STA REFP1 ; 3 JSR SetPosX2 ; 6 position top enemy object ; x-position missile: INX LDA missileX JSR SetPosX JSR STY

DoHMove PF0

; clear collsion variables: STY hitEnemyIdx STY PFCrashFlag STY missileFlag STY collidedEnemy

; 2 ; 3 ; 6

position missile

; 6 ; 3

enable complete PF0 (y=$ff)

; ; ; ;

3 3 3 3

; set variables for top block: LDX #NUM_BLOCKS-1 ; 2 JSR SetPFxPtr ; 6 LDA blockOffset ; 3 CMP #3 ; 2 BCS .skipDex ; 2 DEX ; 2 .skipDex: STX blockNum ; 3 LDY Shape1IdLst,X ; 4 LDX shapePtr1aTab,Y ; 4 STX shapePtr1a ; 3 LDX shapePtr1bTab,Y ; 4 STX shapePtr1b ; 3 LDX ColorPtrTab,Y ; 4 STX colorPtr ; 3 STA CXCLR ; 3 STA HMCLR ; 3 ; calculate offset into first block: TAX ; 2 SEC ; 2 SBC #1 ; 2 AND #$1F ; 2 STA blockLine ; 3 LSR blockLine ; 5 CMP #26 ; 2 BCC lowOffset ; 2 SBC #22 ; 2 BNE endOffset ; 2 lowOffset: CMP BCC

#4 endOffset

; 2 ; 2

top block just started? no, skip yes, start at block 4

clear all collison registers

0..15

AND ORA endOffset:

#%01 #%10

; set entrypoint into kernel: TAY LDA JmpHiTab,Y PHA LDA JmpLoTab,Y PHA

; 2 ; 2

; ; ; ; ;

2 4 3 4 3

; prepare graphics for first line of kernel: TXA ; 2 LSR ; 2 TAY ; 2 LDA (shapePtr1a),Y ; 5 BCC .evenLine ; 2 LDA (shapePtr1b),Y ; 5 .evenLine: CPX #26 ; 2 BCS .noShape ; 2 CPX #3 ; 2 BCC .noShape ; 2 STA GRP1 ; 3 row LDA #0 ; 2 STA GRP0 ; 3 .noShape: LDA (PF1Ptr),Y ; 5 STA PF1 ; 3 LDA (PF2Ptr),Y ; 5 STA PF2 ; 3 LDA (colorPtr),Y ; 5 IF SCREENSAVER EOR SS_XOR ; 3 AND SS_Mask ; 3 ELSE FILL_NOP 4 ENDIF STA COLUP1 ; 3 LDX blockNum ; 3 LDA blockLst,X ; 4 STA roadBlock ; 3 AND #PF_COLOR_FLAG ; 2 ORA #GREEN ; 2 IF SCREENSAVER EOR SS_XOR ; 3 AND SS_Mask ; 3 ELSE FILL_NOP 4 ENDIF STA PFcolor ; 3 BIT blockLstEnd ; 3 BPL .noRoad ; 2 CPY #ROAD_HEIGHT ; 2 BCS .noRoad ; 2 LDA RoadColorTab,Y ; 4 IF SCREENSAVER

even blockOffset! blockoffset >= 26? yes, skip enemy shape blockoffset < 3? yes, skip enemy shape no, display enemy shape in first VDELP1!

save road-state

road in first block? no, use green color offset inside road? no, use green color yes, use road colors

ELSE

EOR AND

SS_XOR SS_Mask

FILL_NOP 4 ENDIF .noRoad: STA COLUPF LDY #NUM_LINES STY lineNum .waitTim: LDA INTIM BNE .waitTim STA WSYNC STA HMOVE STA VBLANK RTS

; 3 ; 3

; 3 ; 2 ; 3 ; ; ; ; ; ;

4 2 3 3 3 6

jump into kernel!

; *** main display kernel: *** DisplayKernel SUBROUTINE ; first some external code to save cycles in the kernel: JmpPoint2: ;12 INC lineNum ; 5 LDY blockLine ; 3 BPL enterKernel2 ; 3 .skipJet0: LDX BEQ

zero2 .contJet0

; 3 ; 3

.noRoad: LDA JMP

PFcolor .contPFColor

; 3 ; 3

.doJet0a: LDA (shapePtr0),Y TAX LDA #$00 .loopKernel1: BEQ .contJet0a from .doJet0a BNE .contKernel1 from .loopkernel1

; ; ; ; ;

5 2 2

load 0 with exactly 3 cylces

@19

2

this jump is taken when comming

; 3

this jump is taken when comming

IF SCREENSAVER = 0 FILL_NOP 1 ENDIF JmpPoint3: ;12 JSR Wait12 ;12 .contKernel1: NOP ; 2 @26 ;-------------------------------------; even line: ; - ... ; - draw player jet ; - load new P1 shape

; *** here starts the main kernel loop: *** .loopKernel: ; CPY #JET_Y ; 2 BCS .skipJet0 ; 2 LDA (shapePtr0),Y ; 5 TAX ; 2 .contJet0: LDY blockLine ; 3 BIT roadBlock ; 3 BPL .noRoad ; 2 LDA RoadColorTab,Y ; 4 IF SCREENSAVER EOR SS_XOR ; 3 .contPFColor: AND SS_Mask ; 3 ELSE FILL_NOP 2 .contPFColor: FILL_NOP 1 ENDIF STA.w temp ; 4 LDA (shapePtr1b),Y ; 5 STA GRP1 ; 3 LDA (PF1Ptr),Y ; 5 STA PF1 ; 3 @75 ;-------------------------------------; new line starts here! ; odd line: ; - set PF color ; - set P1 color ; - change PF STA HMOVE ; 3 STX GRP0 ; 3 @2 LDA temp ; 3 STA COLUPF ; 3 @8 LDA (colorPtr),Y ; 5 IF SCREENSAVER EOR SS_XOR ; 3 AND SS_Mask ; 3 ELSE FILL_NOP 4 ENDIF STA COLUP1 ; 3 @22 LDA (PF2Ptr),Y ; 5 STA PF2 ; 3 @30 enterKernel2: LDA (shapePtr1a),Y ; 5 STA GRP1 ; 3 LDY lineNum ; 3 DEY ; 2 BEQ .exitKernel2 ; 2 CPY #JET_Y ; 2 BCC .doJet0a ; 2 TYA ; 2 SBC missileY ; 3 AND #$F8 ; 2 BNE .skipEnable0 ; 2 LDA #ENABLE ; 2

draw player jet? no, skip yes, load data.. ..into x road displayed? no, normal PF color yes, load road colors

time doesn't matter (VDELP1!)

this also updates GRP1

time doesn't matter (VDELP1!)

.skipEnable0: LDX #$00 ; 2 .contJet0a: DEY ; 2 STY lineNum ; 3 STA WSYNC ; 3 ;-------------------------------------; even line: ; - en-/disable missile ; - update P0 and P1 graphics ; - decrease block-line ; - ... STA HMOVE ; 3 STA ENAM0 ; 3 STX GRP0 ; 3 @6 BEQ .exitKernel2 ; 2 DEC blockLine ; 5 BNE .loopKernel1 ; 2

this also updates GRP1

;*** start of next block (requires eight extra kernel lines): *** ; new block, line 1 ; - dec block-number ; - set new road-state ; - get new PF color ; - set new shape-pointer 1a DEC blockNum ; 5 JmpPoint1: LDX blockNum ; 3 BMI LF202 ; 2 LDA blockLst,X ; 4 save road-state STA roadBlock ; 3 AND #PF_COLOR_FLAG ; 2 bright or dark.. ORA #GREEN ; 2 ..green IF SCREENSAVER EOR SS_XOR ; 3 AND SS_Mask ; 3 ELSE FILL_NOP 4 ENDIF STA PFcolor ; 3 LDA Shape1IdLst,X ; 4 set TAX ; 2 shape-pointer LDA shapePtr1aTab,X ; 4 for the STA shapePtr1a ; 3 next enemy LF1CE: LDA #$00 ; 2 STA GRP1 ; 3 CPY #JET_Y ; 2 STA WSYNC ; 3 ;-------------------------------------; new block, line 2 ; x = shape-id ; - set jet ; - set PF ; - set new shape-pointer 1b ; - set new color-pointer STA HMOVE ; 3 BCS .skipJet1 ; 2

LDA .skipJet1: STA LDY pattern LDA STA LDA STA LDY DEY .exitKernel2: BEQ LDA STA LDA STA JmpPoint0: CPY BCS LDA TAX LDA BEQ LF202: INX BEQ JmpPoint9: NOP SEC BCS

(shapePtr0),Y

; 5

GRP0 #0

; 3 ; 2

(PF1Ptr),Y PF1 (PF2Ptr),Y PF2 lineNum

; ; ; ; ; ;

5 3 5 3 3 2

.exitKernel1 shapePtr1bTab,X shapePtr1b ColorPtrTab,X colorPtr

; ; ; ; ;

2 4 3 4 3

#JET_Y .skipJet2 (shapePtr0),Y #DISABLE .contJet2

; ; ; ; ; ;

2 2 5 2 2 3

LF1CE

; 2 ; 2

.enterKernel9

; 2 ; 2 ; 3

.skipJet2: TYA ; 2 SBC missileY ; 3 AND #$F8 ; 2 BNE .skipEnable1 ; 2 LDA #ENABLE ; 2 .skipEnable1: LDX #$00 ; 2 .contJet2: STA WSYNC ; 3 ;-------------------------------------; new block, line 3 ; - en-/disabvle missile ; - set jet ; - set new PF pointers STA HMOVE ; 3 STA ENAM0 ; 3 STX GRP0 ; 3 DEY ; 2 STY lineNum ; 3 .exitKernel1: BEQ .exitKernel ; 2 LDX blockNum ; 3 .enterKernel9: JSR SetPFxPtr ;50 LDA PFcolor ; 3

display last line of playfield

CPY #JET_Y ; 2 NOP ; 2 @76 ;-------------------------------------; new block, line 4 ; - set new PF color ; - set PF ; - load fine movement STA HMOVE ; 3 STA COLUPF ; 3 BCS .skipJet3 ; 2 LDA (shapePtr0),Y ; 5 STA GRP0 ; 3 .skipJet3: LDY #SECTION_BLOCKS-1 ; 2 LDA (PF1Ptr),Y ; 5 STA PF1 ; 3 LDA (PF2Ptr),Y ; 5 STA PF2 ; 3 DEC lineNum ; 5 BEQ .exitKernel ; 2 JmpPoint8: LDA State1Lst,X ; 4 STA temp ; 3 LDY lineNum ; 3 CPY #JET_Y ; 2 BCC .skipJet4 ; 2 TYA ; 2 SBC missileY ; 3 AND #$F8 ; 2 BNE .skipEnable2 ; 2 LDA #ENABLE ; 2 .skipEnable2: LDY #0 ; 2 .contJet4: STA WSYNC ; 3 ;-------------------------------------; new block, line 5 ; - en-/disable missile ; - set jet ; - position new shape STA HMOVE ; 3 STA ENAM0 ; 3 STY GRP0 ; 3 ; position player 1: LDA XPos1Lst,X ; 4 BEQ .posVeryLeft ; 2 TAX ; 2 CPX #7 ; 2 BCS .posRight ; 2 .waitLeft: DEX ; 2 BNE .waitLeft ; 2 STA RESP1 ; 3 .contLeft: DEC lineNum ; 5 LDY lineNum ; 3 BNE .contPos ; 2 .exitKernel:

put fine move-value into temp

load coarse move-value

JMP .posVeryLeft: NOP NOP LDA STA STA BNE .skipJet4: LDA TAY LDA BEQ

DisplayState

; 3

#$60 RESP1 HMP1 .contLeft

; ; ; ; ; ;

2 2 2 3 3 2

; ; ; ;

5 2 2 2

(shapePtr0),Y #$00 .contJet4

.posRight: SBC #4 ; 2 TAX ; 2 DEC lineNum ; 5 LDY lineNum ; 3 BEQ .exitKernel ; 2 .waitRight: DEX ; 2 BPL .waitRight ; 2 STA RESP1 ; 3 JmpPoint7: .contPos: STA WSYNC ; 3 ;-------------------------------------; new block, line 6 STA HMOVE ; 3 CPY #JET_Y ; 2 BCS .skipJet5 ; 2 LDA (shapePtr0),Y ; 5 STA GRP0 ; 3 .skipJet5: LDY #SECTION_BLOCKS-2 ; 2 LDA (PF1Ptr),Y ; 5 STA PF1 ; 3 LDA (PF2Ptr),Y ; 5 STA PF2 ; 3 LDY lineNum ; 3 DEY ; 2 BEQ .exitKernel ; 2 LDX blockNum ; 3 LDA temp ; 3 STA HMP1 ; 3 JmpPoint6: LDA #[BLOCK_SIZE-8]/2 ; 2 STA blockLine ; 3 TYA ; 2 SEC ; 2 SBC missileY ; 3 AND #$F8 ; 2 BNE .skipEnable3 ; 2 LDA #ENABLE ; 2 .skipEnable3:

exit the kernel

CPY #JET_Y ; 2 STA WSYNC ; 3 ;-------------------------------------; new block, line 7 STA HMOVE ; 3 STA ENAM0 ; 3 BCS .skipJet6 ; 2 LDA (shapePtr0),Y ; 5 STA GRP0 ; 3 .skipJet6: LDA State1Lst,X ; 4 STA NUSIZ1 ; 3 STA REFP1 ; 3 DEY ; 2 STY lineNum ; 3 BEQ DisplayState ; 2 STA HMCLR ; 3 ; check collisions: ; (the collsion check between jet or missile and playfield aren't ; really neccessary for each block, but the collison registers ; are cleared after each block) INX ; 2 BIT CXM0P-$30 ; 3 player missile hit enemy? BPL .notHit ; 2 STX hitEnemyIdx ; 3 save block number .notHit: IF TRAINER BIT zero1 ELSE BIT CXP0FB-$30 ; 3 jet hit PF? ENDIF BPL .noPFCrash ; 2 STX PFCrashFlag ; 3 .noPFCrash: IF TRAINER BIT zero1 ELSE BIT CXM0FB-$30 ; 3 player missile hit PF? ENDIF BPL .notHitPF ; 2 STX missileFlag ; 3 .notHitPF: IF TRAINER BIT zero1 ELSE BIT CXPPMM-$30 ; 3 jet crashed into enemy? ENDIF BPL .noCrash ; 2 STX collidedEnemy ; 3 save block number .noCrash: .enterKernel5: ;-------------------------------------; new block, line 8 STA WSYNC ; 3 STA HMOVE ; 3 CPY #JET_Y ; 2

BCS LDA STA .skipJet7: LDY LDA STA LDA STA LDY DEY BEQ BIT BPL LDA ORA STA .notEnemyPF: STA

.skipJet7 (shapePtr0),Y GRP0

; 2 ; 5 ; 3

#SECTION_BLOCKS-3 (PF1Ptr),Y PF1 (PF2Ptr),Y PF2 lineNum DisplayState CXP1FB-$30 .notEnemyPF blockLst,X #PF_COLLIDE_FLAG blockLst,X

; ; ; ; ; ; ; ; ; ; ; ; ;

CXCLR

; 3

2 5 3 5 3 3 2 2 3 2 4 2 4

.enterKernel4: TYA ; 2 SEC ; 2 SBC missileY ; 3 AND #$F8 ; 2 BNE .skipEnable4 ; 2 LDA #ENABLE ; 2 .skipEnable4: CPY #JET_Y ; 2 STA WSYNC ; 3 ;-------------------------------------; new block, line 9 (= begin of even line) STA HMOVE ; 3 STA ENAM0 ; 3 BCS .skipJet8 ; 2 LDA (shapePtr0),Y ; 5 STA GRP0 ; 3 .contJet8: DEY ; 2 STY lineNum ; 3 BEQ DisplayState ; 2 JMP .loopKernel ; 3 @26 JmpPoint5: LDA STA BNE

#[BLOCK_SIZE-8]/2 ; 2 blockLine ; 3 .enterKernel5 ; 3

JmpPoint4: LDA STA BNE

#[BLOCK_SIZE-8]/2 ; 2 blockLine ; 3 .enterKernel4 ; 3

.skipJet8: NOP NOP BCS

; ; 2 ; 2 ; 3

.contJet8

enemy hit PF? no, skip yes, set collision flag clear all collison registers

exit the kernel

12

waste some time

DisplayState SUBROUTINE ; finish display kernel: STA WSYNC STA HMOVE LDY #$00 STY GRP1 STY GRP0 LDA zero1 wastes a variable!) STA COLUBK STY PF0 STY PF1 STY PF2 STY REFP0 STY REFP1 STY reflect0 ; prepare state display: LDA #$11 also for HMP0! STA RESP0 STA RESP1 STA CTRLPF STA HMP0 LDA #$20 STA HMP1 LDA playerColor JSR SetColPx LDA stateBKColor STA COLUBK LDA #THREE_COPIES STA NUSIZ0 STA NUSIZ1 LDA statePFColor STA COLUPF LDY #$07 STY VDELP0 STY lineNum STA HMCLR ; display score: .loopScore: LDA (scorePtr1+8),Y TAX LDA (scorePtr1+10),Y STA WSYNC STA HMOVE STY temp2 STA temp LDA (scorePtr1),Y STA GRP0 LDA (scorePtr1+2),Y STA GRP1 LDA (scorePtr1+4),Y STA GRP0 LDA (scorePtr1+6),Y LDY temp STA GRP1 STX GRP0 STY GRP1

; ; ; ; ; ;

3 3 2 3 3 3

; ; ; ; ; ; ;

3 3 3 3 3 3 3

; 2 ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ;

3 3 3 3 2 3 3 6 3 3 2 3 3 3 3 2 3 3 3

; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ;

5 2 5 3 3 3 3 5 3 5 3 5 3 5 3 3 3 3

waste one extra cylce (but also

reflect PF, 2 pixel ball width,

STA LDY DEY BPL

GRP0 temp2 .loopScore

LDA zero1 JSR FinishDigits ; display fuel: .loopFuel: STY temp2 LDA FuelTab4,Y LDX FuelTab3,Y STA WSYNC STA HMOVE STA temp NOP LDA #$00 STA GRP0 LDA ENABLTab,Y STA ENABL LDA FuelTab0,Y STA GRP1 LDA FuelTab1,Y STA GRP0 LDA FuelTab2,Y LDY temp STA GRP1 STX GRP0 STY GRP1 STA GRP0 LDY temp2 DEY BPL .loopFuel LDA JSR INY CLC LDX INX BNE LDA STA

playerColor FinishDigits gameMode .noGame #<Space livesPtr

; animate copyright message: LDA frameCnt LSR LSR LSR CMP #20 BCS .ok CMP #12 .noGame: LDY #7 BCC .ok SBC #4 TAY .ok:

; ; ; ;

3 3 2 2

; 3 ; 6

a = 0 (BLACK) y = 14

; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ;

3 4 4 3 3 3 2 2 3 4 3 4 3 4 3 4 3 3 3 3 3 3 2 2

line counter

; ; ; ; ; ; ; ; ;

3 6 2 2 3 2 2 2 3

; ; ; ; ; ; ;

3 2 2 2 2 2 2

; ; ; ;

2 2 2 2

y=15

STY temp3 ; display lives and copyright: .loopCopyright: LDY temp3 LDA Copyright5,Y STA temp STA WSYNC STA HMOVE LDX Copyright4,Y LDA (livesPtr),Y STA GRP0 DEC temp3 LDA Copyright1,Y STA GRP1 LDA Copyright2,Y STA GRP0 LDA Copyright3,Y LDY temp STA GRP1 STX GRP0 STY GRP1 STA GRP0 DEC lineNum BPL .loopCopyright

; 3 ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ;

3 4 3 3 3 4 5 3 5 4 3 4 3 4 3 3 3 3 3 5 2

STA STA LDX STX STX STX LDA CMP BCC INX .skipInx:

; ; ; ; ; ; ; ; ; ;

3 3 2 3 3 3 3 2 2 2

WSYNC HMOVE #$00 VDELP0 GRP1 GRP0 blockOffset #BLOCK_SIZE-6 .skipInx

copyright scroll offset

; check collisions for the last displayed block: BIT CXM0P-$30 ; 3 player missile hit enemy? BPL .notHit2 ; 2 STX hitEnemyIdx ; 3 save block number .notHit2: IF TRAINER BIT zero1 ELSE BIT CXP0FB-$30 ; 3 jet hit PF? ENDIF BPL .noPFCrash2 ; 2 STX PFCrashFlag ; 3 .noPFCrash2: BIT CXM0FB-$30 ; 3 player missile hit PF? BPL .notHitPF2 ; 2 STX missileFlag ; 3 .notHitPF2: IF NTSC LDA ELSE

#29

; 2

LDA ENDIF

LDY STA STA STY

BIT BPL LDA ORA STA .notEnemyPF2: IF TRAINER LDA ELSE BIT ENDIF BPL STX .noCrash2:

#58

; 2

#%10000010 WSYNC TIM64T VBLANK

; ; ; ;

2 3 4 3

CXP1FB-$30 .notEnemyPF2 blockLst,X #PF_COLLIDE_FLAG blockLst,X

; ; ; ; ;

3 2 4 2 4

enemy hit PF?

zero1 CXPPMM-$30

; 3

jet crashed into enemy?

.noCrash2 collidedEnemy

; 2 ; 3

save block number

; *** update framecounter, check for screensaver: *** DEC frameCnt ; 5 BNE .skipSS_Delay ; 2 LDX gameMode ; 3 INX ; 2 BNE .skipInit ; 2 JSR SwapPlayers ; 6 .skipInit: IF SCREENSAVER INC SS_Delay ; 5 BNE .skipSS_Delay ; 2 SEC ; 2 ROR SS_Delay ; 5 ELSE FILL_NOP 4 ENDIF .skipSS_Delay: IF SCREENSAVER LDY #$FF ; 2 LDA SWCHB ; 4 AND #BW_MASK ; 2 black and white? BNE .colorMode ; 2 no, color mode LDY #$0F ; 2 yes, mask out high nibble .colorMode: TYA ; 2 LDY #$00 ; 2 BIT SS_Delay ; 3 BPL .noScreenSaver ; 2 AND #$F7 ; 2 LDY SS_Delay ; 3 .noScreenSaver: STY SS_XOR ; 3 ASL SS_XOR ; 5 STA SS_Mask ; 3 ELSE FILL_NOP 28

ENDIF ; *** randomly start movement of enemies: *** LDA random ; 3 ASL ; 2 ASL ; 2 ASL ; 2 EOR random ; 3 ASL ; 2 ROL random ; 5 LDA frameCnt ; 3 AND #$0F ; 2 BNE .skipStartMove ; 2 LDA random ; 3 AND #$07 ; 2 CMP #5 ; 2 enemies BCC .inBound ; 2 SBC #5 ; 2 three enemies .inBound: TAX ; 2 LDA blockLst,X ; 4 ORA #ENEMY_MOVE_FLAG ; 2 STA blockLst,X ; 4 .skipStartMove: ;*** animate and move the enemy LDX #NUM_BLOCKS-1 .loopEnemies: ; animate some enemies: LDY Shape1IdLst,X CPY #ID_SHIP and fuel BCS .skipAnimate LDA #$01 CPY #ID_PLANE helicopter BCS .fastAnimation LDA #$0F 16th frame) .fastAnimation: AND frameCnt BNE .skipAnimate LDA AnimateIdTab,Y STA Shape1IdLst,X TAY .skipAnimate:

every 16th frame

start one of the first five doubled chances for the first

start movement of enemy

objects: *** ; 2 ; 4 ; 2

don't animate ship, bridge, house

; 2 ; 2 ; 2

every 2nd frame fast animate plane (not done) and

; 2 ; 2

slow animate explosions (every

; ; ; ; ;

3 2 4 4 2

; check for move and direction change: LDA gameMode ; 3 BNE .skipMoveEnemy ; 2 LDA level ; 3 LSR ; 2 BEQ .skipMoveEnemy ; 2 CPY #ID_PLANE ; 2 frame BEQ .xMoveEnemy ; 2

first level? yes, don't move move plane in same direction every

frame

BCC CPY BCS LDA ROR BCS

.skipMoveEnemy #ID_BRIDGE .skipMoveEnemy frameCnt

LDA ASL BPL ASL BPL ASL BMI LDA EOR STA LDA ORA BNE

blockLst,X

.skipMoveEnemy

.skipMoveEnemy .noPFCollision .xMoveEnemy State1Lst,X #DIRECTION_FLAG State1Lst,X blockLst,X #PATROL_FLAG .endChangeDir

.noPFCollision: LDA blockLst,X AND #~PATROL_FLAG temporary) .endChangeDir: STA blockLst,X

; ; ; ; ; ;

2 2 2 3 2 2

; ; ; ; ; ; ; ; ; ; ; ; ;

4 2 2 2 2 2 2 4 2 4 4 2 2

; 4 ; 2

don't move bridge, house and fuel

move helicopter and ship every 2nd enemy moving? no, skip move enemy collided with PF? no, skip patroling enemy? no, skip swap direction switch enemy move direction (re)enable patrol mode

disable patrol mode (only

; 4

; move enemy one pixel left or right: ; (no real position variables, the code is working ; directly with the positioning values) .xMoveEnemy: LDY XPos1Lst,X ; 4 LDA State1Lst,X ; 4 LSR ; 2 LSR ; 2 LSR ; 2 LSR ; 2 EOR #$07 ; 2 BCS .xMoveLeft ; 2 moving left! ADC #1 ; 2 CMP #15 ; 2 BCC .skipRightIny ; 2 SBC #15 ; 2 INY ; 2 .skipRightIny: CPY #10 ; 2 BCC .contMoveX ; 2 CMP #10 ; 2 >= 160? BCC .contMoveX ; 2 no, continue LDY #0 ; 2 yes,.. TYA ; 2 ..move shape (plane).. BEQ .contMoveX ; 2 ..to the very left (0) .xMoveLeft: SBC BCS ADC

#1 .contMoveX2 #15

; 2 ; 2 ; 2

DEY BPL .contMoveX LDY #10 LDA #9 .contMoveX: STY XPos1Lst,X .contMoveX2: EOR #$07 JSR Mult16 EOR State1Lst,X AND #FINE_MASK EOR State1Lst,X STA State1Lst,X .skipMoveEnemy: ; clear PF-collision: LDA blockLst,X AND #~PF_COLLIDE_FLAG STA blockLst,X DEX BMI .exitLoopEnemies JMP .loopEnemies .exitLoopEnemies: ; *** read joystick: *** LDA SWCHA LDX player BEQ .player1 JSR Mult16 .player1: AND #$F0 TAX LDY #4 .loopBits: ROL ROL joystick nibble!) DEY BNE .loopBits

; ; ; ;

2 2 2 2

; 4 ; ; ; ; ; ;

2 6 4 2 4 4

; ; ; ; ; ;

4 2 4 2 2 3

; ; ; ;

4 3 2 6

< 0? no, continue yes, move shape (plane).. ..to the very right (159) store coarse value here

#$F0 OR fine value into here

; 2 ; 2 ; 2

mask out other player joystick

; 2 ; 5

roll new 4 bits into joystick (old 4 bits got into upper

; 2 ; 2

CPX #$F0 BNE .joystickMoved LDX player LDA INPT4-$30,X BMI .noFire .joystickMoved:

; ; ; ; ;

2 2 3 4 2

LDA gameMode CMP #INTRO_SCROLL BNE .skipRestart LDA #64 STA speedY STY gameMode .skipRestart: IF SCREENSAVER STY SS_Delay ELSE FILL_NOP 2

; ; ; ; ; ;

3 2 2 2 3 3

; 3

restart new game y=0! y=0!

ENDIF .noFire: LDX gameMode BEQ .checkCollisions BMI .gameOver CPX #INTRO_SCROLL+1 BCC .doSoundJmp BNE .startGame game ; decrease lives: LDA livesPtr BEQ .finishGame SBC #DIGIT_H BNE LF5B5 LDA #<Space+1 LF5B5: CMP #<MaxOut BNE LF5BB LDA #
; ; ; ; ; ;

3 2 2 2 2 2

; ; ; ; ; ; ; ; ;

3 2 2 2 2 2 2 2 3

; 5 ; 2

.doSoundJmp gameMode .doSoundJmp shapePtr0 livesPtr2 #
; ; ; ; ; ; ; ; ;

2 2 5 2 3 3 2 2 6

livesPtr #
; 3 ; 2 ; 2

FinishGame .doSoundJmp

; 6 ; 2

#shapePtr0+2-PF1Lst;2 GameInit ; 6 ; 2 #PF_ROAD_FLAG ; 2 blockLstEnd ; 3 randomLoSave ; 3 randomLo ; 3 randomHiSave ; 3 randomHi ; 3 DoSound

.checkCollisions: LDX collidedEnemy BMI .endCollisions LDA Shape1IdLst,X

game running game is over scrolling into new game/life? yes, skip decrease no, finished scrolling, start new

zero!

score overflow? reset lives to 3 start game

other player still alive? no, skip swap

current player still alive? yes, continue

#22

load.. ..random variables.. ..with saved.. ..player variables

; 3 ; 3 ; 2 ; 4

collided with enemy? no, skip

CMP BCC CMP helicopter? BCC BNE INC .noBridge: LDY LDA JSR LDX LDA JMP .refuel: LDA ADC LDX BCC LDA STA LDX .notFull: STA CPX BEQ STX LDA STA

#ID_PLANE .endCollisions #ID_BRIDGE

; 2 ; 2 ; 2

.noBridge .refuel sectionEnd

; 2 ; 2 ; 5

#$1F #1 LooseJet collidedEnemy #ID_EXPLOSION2 .contJetExplosion

; ; ; ; ; ;

2 2 6 3 2 3

fuelHi #$01 #4 .notFull #$FF fuelLo #3

; ; ; ; ; ; ;

3 2 2 2 2 3 2

fuelHi sound0Id .endCollisions sound0Id #$08 sound0Cnt

; ; ; ; ; ;

3 3 2 3 2 3

.endCollisions: LDX PFCrashFlag BMI .skipCrash .maxedOut: LDY #$1F LDA #1 .looseJet: JSR LooseJet BNE .doSoundJmp

collided with explosion? no, skip collided with ship, plane or yes, do collision no, collided with fuel! no, collided with bridge! load some sound values sound id = 1 start explosion

sound id = 4

sound id = 3

; 3 ; 2

jet crashed? no, skip

; 2 ; 2

sound id = 1

; 6 ; 2

.skipCrash: ; decrease fuel: LDA fuelLo SEC IF TRAINER SBC #0 ELSE SBC #$20 ENDIF BCS .skipDecHi LDY fuelHi BNE .fuelOk LDA #2 LDY #$23 JMP .looseJet

; 3 ; 2

; 2 ; ; ; ; ; ;

2 3 2 2 2 3

sound id = 2 out of fuel!

.fuelOk: DEC .skipDecHi: STA

fuelHi

; 5

fuelLo

; 3

; *** move jet left or right: *** LDA joystick ; 3 TAY ; 2 AND #MOVE_LEFT|MOVE_RIGHT; 2 EOR #MOVE_LEFT|MOVE_RIGHT; 2 BNE .leftRight ; 2 STA dXSpeed ; 3 STA speedX ; 3 LDX #<JetStraight-1 ; 2 BNE .setPtr0 ; 2 .leftRight: LDA CLC ADC BCS STA .maxChange: LDX TYA AND STA BEQ BCS LDA SEC SBC BCS .maxChange2: DEC BNE

dXSpeed

; ; ; ; ;

3 2 2 2 3

dXSpeed .setXSpeed

; ; ; ; ; ; ; ; ; ;

2 2 2 3 2 2 3 2 3 2

playerX .setXSpeed

; 5 ; 2

#8 .maxChange dXSpeed #<JetMove-1 #MOVE_RIGHT reflect0 .moveRight .maxChange2 speedX

.moveRight: BCS .maxChange3 ; 2 LDA speedX ; 3 BIT joystick ; 3 BPL .wasRight ; 2 LDA #-1 ; 2 the left (JTZ: what's that good for?) .wasRight: ADC dXSpeed ; 3 BCC .setXSpeed ; 2 .maxChange3: INC playerX ; 5 .setXSpeed: STA speedX ; 3 .setPtr0: STX shapePtr0 ; 3 ; change jet speed: LDX speedY TYA LSR

; 3 ; 2 ; 2

jet is flying straight

increase the x speed change

moved right before? yes, skip bo, move the jet very slowly to

BCS .incSpeed: TXA ADC BCC BCS .noMoveUp: LSR BCC TXA ASL BCC BEQ .noMoveDown: TXA CMP BCC SBC .changeSpeed: STA .skipChange:

.noMoveUp

; 2

#2 .changeSpeed .skipChange

; ; ; ;

2 2 2 2

.incSpeed .skipChange

; ; ; ; ; ;

2 2 2 2 2 2

#$41 .skipChange #2

; ; ; ;

2 2 2 2

speedY

; 3

.noMoveDown

LDX hitEnemyIdx BMI .skipCollisions LDY Shape1IdLst,X CPY #ID_PLANE BCC .skipCollisions LDA #ID_EXPLOSION1 .contJetExplosion: LDY Shape1IdLst,X STA Shape1IdLst,X LDA #23 STA bridgeSound CPY #ID_BRIDGE BNE .skipBridge STA bridgeExplode LDA #$E0|TWO_COPIES copies close) STA State1Lst,X LDA #4 STA XPos1Lst,X INC sectionEnd .skipBridge: ; increase score: LDX #8 LDA ScoreTab,Y BPL .loopSetPtr1 AND #$7F LDX scorePtr1+8 CPX #<Space BNE .noSpace LDX #
; ; ; ; ; ;

3 2 4 2 2 2

; ; ; ; ; ; ; ;

4 4 2 3 2 2 3 2

; ; ; ;

4 2 4 5

; ; ; ; ; ; ; ; ;

2 4 2 2 3 2 2 2 3

; 2

minimal speed? yes, skip slow down

object hit? no, skip enemy objects? no, explosions start explosion animation

start bridge explosion set fixed position and size (two coarse positiong value new section has been started

add 10s add n*100 points

replace Space.. ..with Zero add 100s

.loopSetPtr1: PHA CPX #2 BNE .notLivePtr ; check for bonus life: LDA livesPtr CMP #
; 3 ; 2 ; 2 ; ; ; ; ;

3 2 2 2 2

life pointer

CF=1!

; 2 ; 3 ; ; ; ; ;

4 2 2 2 4

; ; ; ; ; ; ; ; ; ; ;

4 2 4 2 2 2 4 2 2 2 2

point to '0'

exit loop

; more than 999990 points, set score to !!!!!!, game over: LDA #<MaxOut ; 2 LDX #12-2 ; 2 JSR SetScorePtr1 ; 6 LDA #
; 4 ; 2 ; 2

; *** move or fire missiles: *** LDA missileFlag ; 3 BPL .noMissile ; 2 LDA missileY ; 3 CMP #MAX_MISSILE+1 ; 2 BCS .checkFire ; 2 ADC #MISSILE_SPEED ; 2 TAX ; 2 LDA SWCHB ; 4 LDY player ; 3

disable missile

y-move missile read difficulty

BNE ASL .player1a: TAY BPL BMI

.player1a

.guidedMissile .directMissile

.checkFire: LDX player LDA INPT4-$30,X BMI .noMissile LDX #$0F STX missileSound LDX #MIN_MISSILE .guidedMissile: LDA playerX CLC ADC #$05 STA missileX .directMissile: STX missileY

; 2 ; 2 ; 2 ; 2 ; 2 ; ; ; ; ; ;

3 4 2 2 3 2

; ; ; ;

3 2 2 3

; 3

; *** sound routines: *** ; TODO: analyze, labels, comments DoSound: ; start with channel 0: LDY #$1C ; LDA sound0Cnt ; LDX sound0Id ; BEQ LF789 ; DEX ; BEQ LF770 ; LDY #$0F ; CPX #$02 ; BCS LF776 ; LDY #$08 ; LF770: LSR ; TAX ; LDA #$08 ; BNE LF77D ;

2 3 3 2 2 2 2 2 2 2 2 2 2 2

LF776: BEQ LDY LF77A: TAX LDA LF77D: DEC BNE PHA LDA STA PLA BPL

.setAud0

; ; ; ; ; ; ; ; ; ; ;

2 2 2 2 5 2 3 2 3 4 2

; low fuel sound: LF789: LDA gameMode BNE .mute0 LDA fuelHi CMP #$40

; ; ; ;

3 2 3 2

LF77A #$1F #$04 sound0Cnt .setAud0 #0 sound0Id

white noise

high pure tone

stop sound0

game running? no, quiet (x=0)

BCS LDY BNE LDY .contSound0: DEY STY LDX STX CMP BCS ROL ROL ROL ROL EOR ADC BNE

.jetSound sound0Cnt .contSound0 #$3F

LF7B0: CPY BCC TYA LSR .loadAud0: TAY LDA LDX BNE

#$1C .jetSound

sound0Cnt fuelLo temp #$04 LF7B0 temp temp #$FF #$20 .loadAud0

#$0C #$0F .setAud0

; ; ; ;

2 3 2 2

; ; ; ; ; ; ; ; ; ; ; ; ;

2 3 3 3 2 2 5 2 5 2 2 2 2

; ; ; ;

2 2 2 2

; ; ; ;

2 2 2 2

; make some noise, depending on jet speed: .jetSound: LDA speedY ; 3 LSR ; 2 LSR ; 2 LSR ; 2 LSR ; 2 EOR #$FF ; 2 SEC ; 2 ADC #$1F ; 2 TAY ; 2 LDA joystick ; 3 position AND #MOVE_UP|MOVE_DOWN; 2 TAX ; 2 LDA VolumeTab,X ; 4 TAX ; 2 LDA #$08 ; 2 .setAud0: STA AUDC0 ; 3 STY AUDF0 ; 3 .mute0: STX AUDV0 ; 3 ; continue with channel 1: ; (missile fire or bridge explosion) LDA missileSound ; 3 BEQ .noMissileSound ; 2 DEC missileSound ; 5

frequency depends on y-speed

volume depends on joystick

white noise

LDX priority BNE EOR SEC ADC LDY LDX BNE

bridgeSound

; 3

.doBridge #$FF

; ; ; ; ; ; ;

#$1C #$0C #$08 .setAud1

.noMissileSound: LDX bridgeSound BEQ .skipSound1 ; let the bridge explode: .doBridge: DEC bridgeSound TXA LSR CLC ADC #$04 TAX LDA random ORA #$18 LDY #$08 .setAud1: STA AUDF1 STY AUDC1 .skipSound1: STX AUDV1 ; start next frame: .waitTim: LDA INTIM BNE .waitTim LDY #$82 STY WSYNC STY VSYNC STY WSYNC STY WSYNC STY WSYNC STA VSYNC IF NTSC LDA #43 ELSE LDA #73 ENDIF STA TIM64T ; *** check switches: *** LDA SWCHB LSR BCS .noReset LDA gameVariation STA player LDX #$F7 JMP Reset .noReset:

2 2 2 2 2 2 2

bridge exposion has higher

medium pure tone

; 3 ; 2 ; ; ; ; ; ; ; ; ;

5 2 2 2 2 2 3 2 2

countdown volume

random frequency

; 3 ; 3 ; 3

; ; ; ; ; ; ; ; ;

4 2 2 3 3 3 3 3 3

; 2 ; 2 ; 4 ; ; ; ; ; ; ;

4 2 2 3 3 2 3

RESET was pressed

LSR BCS .noSelect DEC gameDelay BPL .skipSelect LDA gameVariation EOR #$01 STA gameVariation IF SCREENSAVER STA SS_Delay ELSE FILL_NOP 2 ENDIF STA player ASL ASL ASL ADC #DIGIT_H JSR SetScorePtrs JSR FinishGame LDY #$1E .noSelect: STY gameDelay .skipSelect: LDA BMI CMP BNE LDA STA .mainLoopJmp: JMP

; ; ; ; ; ; ;

2 2 5 2 3 2 3

SELECT was pressed toggle game (one or two player)

; 3

; ; ; ; ; ; ; ;

3 2 2 2 2 6 6 2

; 3

gameMode .mainLoopJmp #INTRO_SCROLL .setBlockVars #<JetStraight-1 shapePtr0

; ; ; ; ; ;

3 2 2 2 2 3

MainLoop

; 3

; check, if a new block is neccessary: .setBlockVars: LDA #3-1 ; 2 max. speed = 3 lines/frame STA blockNum ; 3 .loopNext: DEC blockNum ; 5 BMI .mainLoopJmp ; 2 LDA speedY ; 3 CMP #$FE ; 2 BCS .incOffset ; 2 ADC posYLo ; 3 STA posYLo ; 3 BCC .loopNext ; 2 .incOffset: INC blockOffset ; 5 LDA blockOffset ; 3 CMP #BLOCK_SIZE ; 2 BCC .loopNext ; 2 ; *** it#s time to create a new block: *** LDX #0 ; 2 STX blockOffset ; 3 LDY #NUM_BLOCKS ; 2 STY temp ; 3

scrolling into game no, generate new blocks yes, set.. ..jet data pointer.. .. and continue with main loop

add speedY*3 to blockOffset ->

maximum speed? yes, increase offset

move 6 blocks

LDA level CMP #5 BCC .firstLevels LDY #0 .firstLevels: STY valleyWidth limited widths

; ; ; ;

3 2 2 2

; 3

first four levels? yes, prevent small valley no, allow all widths of valley 0 = all widths allowed, 6 =

; first move the other blocks, to make space for the new one: .loopBlocks: ; LDY #5 ; 2 move 5 bytes .loopMoveBlock: LDA blockLst+1,X ; 4 STA blockLst,X ; 4 INX ; 2 DEY ; 2 BNE .loopMoveBlock ; 2 INX ; 2 skip one entry DEC temp ; 5 BNE .loopBlocks ; 2 STY State1LstEnd LDA blockLstEnd PF_COLOR_FLAG) AND #PF_COLOR_FLAG STA blockLstEnd LDX PF1PatId STX prevPF1PatId

; 3 ; 3 ; ; ; ;

2 3 3 3

DEC BEQ LDX DEX section? BNE

blockPart .nextBlock sectionBlock

; ; ; ;

5 2 3 2

.notLast

; 2

y=0! clear variable (except

copy previous PF pattern id second part of block? yes, next block first part of last block of no, continue part

; the last block of a section has to be a road with bridge: STX sectionEnd ; 3 yes, end of current section LDA level ; 3 LSR ; 2 straight current level? LDA #PF_ROAD_FLAG ; 2 BCS .isStraight ; 2 yes, dark green in NEXT level LDA #PF_ROAD_FLAG|PF_COLOR_FLAG; 2 no, lighter green in NEXT level .isStraight: STA blockLstEnd ; 3 .notLast: JSR NextRandom16 ; 6 new random number for next part of block JMP .nextBlockPart ; 3 ; continue with a 'normal' block: .nextBlock: DEC sectionBlock ; BNE .contSection ; JSR SaveSection ; LDX #SECTION_BLOCKS ; STX sectionBlock ; .contSection:

5 2 6 2 3

last block of section? no, continue yes, save variables.. ..and got next level

bridge)

JSR LDX DEX BNE STX LDA

NextRandom16 sectionBlock .notLastBlock PF_State #12

; ; ; ; ; ;

BNE

.setPF1Id

; 3

.notLastBlock: LDA level LSR LDA #7 BCS .setPF1Id LDA PF_State DEX BNE .notLastButOne

; ; ; ; ; ; ;

6 3 2 2 3 2

3 2 2 2 3 2 2

; finish island before end of section: CMP #ISLAND_FLAG|CHANGE_FLAG; 2 BEQ .isSetBoth ; 2 island) BNE .clearBoth ; 3 step to finish island)

new random number for next block last block of section? no, skip yes, PF-State = static pattern-id for last block (with

straight level? pattern-id for straight block yes, set last but one block of section? no, skip both flags set? yes, 11 -> 10 (1. step to finish no, static PF and no island (2.

; change PF_State bits 7 & 6: ; 00 -> 01/00 static -> changing or static ; 01 -> 11 changing -> island & changing ; 10 -> 00 island & static -> static (JTZ: ???) ; 11 -> 10/11 island & changing -> island & changing or static .notLastButOne: ASL ; 2 EOR PF_State ; 3 CHANGE_FLAG != ISLAND_FLAG? BMI .updateFlags ; 2 yes, change flags LDA randomLo ; 3 randomly change state? AND #%00110000 ; 2 BNE .skipFlags ; 2 no, don't change state (75%) .isSetBoth: LDA PF_State ; 3 AND #ISLAND_FLAG ; 2 ISLAND_FLAG set? BNE .isIsland ; 2 yes, clear CHANGE_FLAG ORA #CHANGE_FLAG ; 2 no, set CHANGE_FLAG .isIsland: STA PF_State ; 3 LDA #0 ; 2 BEQ .setPF1Id ; 3 .updateFlags: ; change flags: 01 -> 11, 10 -> 00 LDA #ISLAND_FLAG|CHANGE_FLAG; 2 BIT PF_State ; 3 BVS .setBoth ; 2 .clearBoth: LDA #0 ; 2 .setBoth: STA PF_State ; 3 .skipFlags:

CHANGE_FLAG set? yes, set ISLAND_FLAG no, clear both flags

; create new random PF id: ; (JTZ: I'm not 100% sure, that I understand everything completely) LDY #14 ; 2 y = 14 LDA randomLo ; 3 AND #$0F ; 2 CMP #2 ; 2 BCS .minOk ; 2 ADC #2 ; 2 minimum = 2 .minOk: ; a = 2..15 BIT PF_State ; 3 ISLAND_FLAG set? BPL .skipDey ; 2 no, skip DEY ; 2 y = 13 .skipDey: LDX valleyWidth ; 3 all widths allowed? BEQ .allWidths ; 2 yes, skip limit LDY #8 ; 2 y = 8 .allWidths: STY temp ; 3 save max. allowed id CMP temp ; 3 random id < max. id? BCC .setPF1Id ; 2 yes, skip LDA temp ; 3 no, use max. id .setPF1Id: STA PF1PatId ; 3 a = 2..8 or 2..13/14 LDY #BLOCK_PARTS ; 2 reset blockPart STY blockPart ; 3 .nextBlockPart: LDA prevPF1PatId TAX SEC SBC PF1PatId STA diffPF two blocks BCS .biggerPrev ; new id is bigger: INC diffPF CPX #SWITCH_PAGE_ID-1 LDX PF1PatId BCS .prevBigId CPX #SWITCH_PAGE_ID BCC .page1Id LDA #-1 ADC prevPF1PatId BPL .prevId

; ; ; ; ;

3 2 2 3 3

store the difference between the

; 2 ; ; ; ; ; ; ; ; ;

; old id is bigger or equal: .biggerPrev: BEQ .equalId ; DEC diffPF ; .equalId: CPX #SWITCH_PAGE_ID ; BCS .page0Id ; ; not enough space for an island: .page1Id: JSR GetPageFlag ; JSR LoadPFPattern ; STA PF1LstEnd ; LDA #0 ;

5 2 3 2 2 2 2 3 3

2 5

CF=1! (JTZ: what's that good for?)

-1

2 2 6 6 3 2

a = 0/1

STA BEQ

PF2LstEnd .contPage1

; enough space for an island in .page0Id: LDA PF1PatId CMP #SWITCH_PAGE_ID-1 BCS .prevBigId ; enough space for an island in LDA #14+1 SBC PF1PatId BCS .prevId .prevBigId: LDA .prevId: STA JSR SEC ROL JSR .contPage1: BIT BPL LDA LDX STA STX .skipSwapPF: BIT BPL LDA STA LDY LDA JMP

; 3 ; 3 previous block: ; 3 ; 2 ; 2 both blocks: ; 2 ; 3 ; 3

CF=0! negate id (inverts pattern)

#PF1_PAGE_FLAG|PF2_PAGE_FLAG|PF_COLOR_FLAG; 2 PF1LstEnd GetPageFlag LoadPFPattern

; ; ; ; ;

3 6 2 2 6

PF_State .skipSwapPF PF1LstEnd PF2LstEnd PF2LstEnd PF1LstEnd

; ; ; ; ; ;

3 2 3 3 3 3

ISLAND_FLAG set? no, don't swap

blockLstEnd .skipRoad #QUAD_SIZE State1LstEnd #ID_BRIDGE #63 .endNewShape

; ; ; ; ; ; ;

3 2 2 3 2 2 3

PF_ROAD_FLAG set? no, skip yes, create road block quad size bridge

a = 1/3

x-position

.skipRoad: ; *** create new objects: *** LDY #ID_FUEL ; 2 LDA sectionBlock ; 3 CLC ; 2 ADC blockPart ; 3 CMP #SECTION_BLOCKS+BLOCK_PARTS; 2 no enemies at first part of first block of section BCS .newHouse ; 2 ; create more enemies and less fuel in higher difficulty levels: LDA #64 ; 2 SBC level ; 3 1..48 (CF=0!) ASL ; 2 a = 124..30 CMP randomHi ; 3 BCC .newEnemy ; 2 ~48%..88% -> more enemies, less fuel and houses BIT randomLo ; 3 BVC .newFuel ; 2 ~24%.. 6% -> less fuel ; no enemy or fuel, create new house instead: .newHouse: DEY ; 2 y=ID_HOUSE

LDX PF1PatId ; 3 CPX prevPF1PatId ; 3 BCC .currentSmaller ; 2 LDX prevPF1PatId ; 3 .currentSmaller: ; x = smaller id LDA #DOUBLE_SIZE ; 2 house is double sized STA State1LstEnd ; 3 LDA level ; 3 LSR ; 2 BCC .notStraight ; 2 ; create random x-position for house in straight section: LDA randomLo ; 3 AND #$1F ; 2 ADC #8 ; 2 CMP #25 ; 2 random position fits in left bank? BCC .setShapeDir ; 2 yes, ok ADC #92 ; 2 no, position house on right bank BNE .setShapeDir ; 3 ; position house in non-straight section: .notStraight: LDA ShapePosTab,X ; 4 BIT PF_State ; 3 BPL .setShapeDir ; 2 CPX #0 ; 2 BEQ .setShapeDir ; 2 LDA #71 ; 2 island BNE .setShapeDir ; 3 ; create new ship, helicopter or plane: .newEnemy: LDA #%111 ; 2 LDX level ; 3 CPX #3 ; 2 BCS .withPlanes ; 2 LDA #%001 ; 2 helicopter .withPlanes: AND randomHi ; 3 TAX ; 2 LDY EnemyIdTab,X ; 4 .newFuel: CPY #ID_SHIP ; 2 BNE .noShip ; 2 LDA #DOUBLE_SIZE ; 2 STA State1LstEnd ; 3 .noShip: LDA PF1PatId ; 3 CMP prevPF1PatId ; 3 BNE .newId ; 2 ; position object in straight blocks: STA maxId ; 3 LDA level ; 3 LSR ; 2 BCC .notStraight2 ; 2 ; position object in straight section: LDA #106 ; 2

x-pos based on PF1 id ISLAND_FLAG set? no, skip PF id = 0? no, skip fixed position for a house on

enemy planes start at level three limit first levels to ship and create random enemy object

doublesize

new pat-id = previous pat-id? no,

LDX State1LstEnd BEQ .isShip LDA #97 .isShip: SBC valleyWidth first four levels, river bank STA temp LDA randomLo AND #$3F ADC #45 ADC valleyWidth four levels (s.a.) CMP temp BCC .setShapeDir LDA temp .setShapeDir: ; make random direction for new BIT randomLo BMI .invertDirection BPL .endNewShape .newId:

BCS .currentBigger LDA prevPF1PatId .currentBigger: STA maxId

; 3 ; 2 ; 2

ship? (doublesize) yes, position more right no, position more left

; 3

decrease maximum position (-6) in

; ; ; ; ; ;

this avoids positioning near the 3 3 2 2 3

; 3 ; 2 ; 3

store maximum position

increase random position in first random position < maximum? yes, ok no, position = maximum

shape: ; 3 ; 2 ; 3 ; 2 ; 3 ; 3

; position object in non-straight .notStraight2: ; check, if there is enough space LDX #13 ; BIT PF_State ; BPL .contPage12 ; LDX #10 ; .contPage12: CPX maxId ; BCS .spaceOk ; TYA ; SBC #ID_SHIP-1 ; BNE .spaceOk ; STA State1LstEnd ; DEY ; .spaceOk: LDA maxId ; ASL ; ASL ; BEQ .posSomewhere ; BIT PF_State ; BPL .posSomewhere ; ; position object outside: EOR #$FF ; ADC #81 ; BIT randomLo ; BPL .skipNeg ; EOR #$FF ; ADC #160 ;

maxId cointains max(prevId, newId)

section: for new object: 2 PF id 3 ISLAND_FLAG set? 2 no, skip 2 yes, lower PF id 3 2 2 2 2 3 2

new enemy is a ship? no, skip yes, change.. ..ship into helicopter

3 2 2 2 3 2

ISLAND_FLAG set? no, position somewhere

2 2 3 2 2 2

BNE

.contPos

; position object somewhere: .posSomewhere: ADC #16 BIT randomLo BMI .doNeg .contPos: CLC ADC #2 ADC valleyWidth levels BNE .endNewShape

; 3

; 2 ; 3 ; 2 ; 2 ; 2 ; 3

keep space to river bank in first

; 3

.doNeg: EOR #$FF ADC #160+1 .skipNeg: CPY #ID_FUEL SBC #9 SBC valleyWidth levels LDX State1LstEnd BEQ .invertDirection SBC #10 .invertDirection: CPY #ID_FUEL BEQ .endNewShape PHA LDA State1LstEnd ORA #DIRECTION_FLAG STA State1LstEnd PLA .endNewShape: STY Shape1IdLstEnd JSR CalcPosX STY XPos1LstEnd ORA State1LstEnd STA State1LstEnd JMP .loopNext

; 2 ; 2 ; 2 ; 2 ; 3

position fuel 1 pixel more right

; 3 ; 2 ; 2

double sized object? (ship, house) no, skip yes, move 10 pixels left

; ; ; ; ; ; ;

2 2 3 3 2 3 4

fuel? yes, has constant direction

; ; ; ; ; ;

3 6 3 3 3 3

save id of new object

keep space to river bank in first

set direction flag

save coarse x-positioning value save fine x-positioning value

; ****************************** end of main loop ****************************** GameInit SUBROUTINE ; Input: x (= 22/38, number of initialized variables) ; initializes some variables for new game: .initLoop: LDA InitTab,X ; 4 STA PF1Lst,X ; 4 DEX ; 2 BPL .initLoop ; 2 ; clear some variables for new game: LDA #0 ; 2 LDX #30 ; 2 .loopClear: STA dXSpeed,X ; 4

DEX BPL LDX LDY LDA LSR BCC LDY current level .loopSet: STY DEX BPL RTS

.loopClear

; 2 ; 2

#NUM_BLOCKS-1 #PF1_PAGE_FLAG level

; 2 ; 2 ; 3 ; 2 .loopSet ; 2 #PF1_PAGE_FLAG|PF_COLOR_FLAG; 2 blockLst,X .loopSet

IF NTSC LoadPFPattern SUBROUTINE BIT PF_State BPL .contPage1 TAY table LDA PageFlagTab,Y .contPage1: ORA blockLstEnd STA blockLstEnd LDA BankPtrTab,X CLC ADC diffPF and prev PF id STA PF2LstEnd RTS ELSE FinishDigits SUBROUTINE INY STA WSYNC STA HMOVE STY GRP1 STY GRP0 STY GRP1 LDY #14 SetColPx: STA COLUP0 STA COLUP1 DoHMove: STA WSYNC STA HMOVE RTS ENDIF

; ; ; ;

straight level? no, skip yes, set brighter green in

4 2 2 6

; 3 ; 2 ; 2

ISLAND_FLAG set? no, set current page-flag yes, read new page-flag from

; 4 ; ; ; ; ;

3 3 4 2 3

load a pattern for the river bank adjust with difference between new

; 3 ; 6 ; ; ; ; ; ; ;

2 3 3 3 3 3 2

load line counter

; 3 ; 3 ; 3 ; 3 ; 6

NextRandom16 SUBROUTINE ; implements a 16 bit LFSR which generates a new random number: LDA randomHi ; 3 ASL ; 2 ASL ; 2 ASL ; 2 EOR randomHi ; 3 ASL ; 2

ROL randomLo ; 5 ROL randomHi ; 5 ; (JTZ: randomHi is very random, randomLo is NOT when more than one bit is used, ; because: randomLo[x+1] = randomLo[x]*2 + 0/1, but randomLo is used more often, ; randomHi only for new enemy and which. This could make the game a bit predictable.) RTS ; 6 SaveSection SUBROUTINE ; called at the start of a new section, increases difficulty level ; and saves random variables to be able to restart this section LDX level ; 3 limit level to 48 CPX #MAX_LEVEL ; 2 BCC .notMax ; 2 LDX #MAX_LEVEL-2 ; 2 go back to 47 .notMax: LDA randomLoSave ; 3 STA randomLoSave2 ; 3 LDA randomHiSave ; 3 STA randomHiSave2 ; 3 LDA randomLo ; 3 STA randomLoSave ; 3 LDA randomHi ; 3 STA randomHiSave ; 3 INX ; 2 STX level ; 3 1..48 RTS ; 6 SetPosX SUBROUTINE ; calculates the values and positions objects: JSR CalcPosX ; 6 SetPosX2: STA HMP0,X ; 4 INY ; 2 INY ; 2 INY ; 2 STA WSYNC ; 3 .waitPos: DEY ; 2 BPL .waitPos ; 2 STA RESP0,X ; 4 RTS ; 6 ;=============================================================================== ; R O M - T A B L E S (Part 1) ;=============================================================================== align 256 Zero: .byte .byte .byte .byte .byte .byte .byte

$3C $66 $66 $66 $66 $66 $66

; ; ; ; ; ; ;

| | | | | | |

XXXX XX XX XX XX XX XX XX XX XX XX XX XX

| $FB00 | | | | | |

One:

Two:

Three:

Four:

Five:

Six:

Seven:

.byte $3C ; |

XXXX

|

.byte .byte .byte .byte .byte .byte .byte .byte

$3C $18 $18 $18 $18 $18 $38 $18

; ; ; ; ; ; ; ;

| | | | | | | |

XXXX XX XX XX XX XX XXX XX

| | | | | | | |

.byte .byte .byte .byte .byte .byte .byte .byte

$7E $60 $60 $3C $06 $06 $46 $3C

; ; ; ; ; ; ; ;

| | | | | | | |

XXXXXX XX XX XXXX XX XX X XX XXXX

| | | | | | | |

.byte .byte .byte .byte .byte .byte .byte .byte

$3C $46 $06 $0C $0C $06 $46 $3C

; ; ; ; ; ; ; ;

| XXXX | X XX | XX | XX | XX | XX | X XX | XXXX

| | | | | | | |

.byte .byte .byte .byte .byte .byte .byte .byte

$0C $0C $0C $7E $4C $2C $1C $0C

; ; ; ; ; ; ; ;

| XX | | XX | | XX | | XXXXXX | | X XX | | X XX | | XXX | | XX |

.byte .byte .byte .byte .byte .byte .byte .byte

$7C $46 $06 $06 $7C $60 $60 $7E

; ; ; ; ; ; ; ;

| | | | | | | |

XXXXX X XX XX XX XXXXX XX XX XXXXXX

| | | | | | | |

.byte .byte .byte .byte .byte .byte .byte .byte

$3C $66 $66 $66 $7C $60 $62 $3C

; ; ; ; ; ; ; ;

| | | | | | | |

XXXX XX XX XX XX XX XX XXXXX XX XX X XXXX

| | | | | | | |

XX XX

| |

.byte $18 ; | .byte $18 ; |

Eight:

Nine:

MaxOut:

Space:

.byte .byte .byte .byte .byte .byte

$18 $18 $0C $06 $42 $7E

; ; ; ; ; ;

| XX | XX | XX | XX | X X | XXXXXX

| | | | | |

.byte .byte .byte .byte .byte .byte .byte .byte

$3C $66 $66 $3C $3C $66 $66 $3C

; ; ; ; ; ; ; ;

| | | | | | | |

XXXX XX XX XX XX XXXX XXXX XX XX XX XX XXXX

| | | | | | | |

.byte .byte .byte .byte .byte .byte .byte .byte

$3C $46 $06 $3E $66 $66 $66 $3C

; ; ; ; ; ; ; ;

| | | | | | | |

XXXX XX XX XXXXX XX XX XX XX XX XX XXXX

| | | | | | | |

.byte .byte .byte .byte .byte .byte .byte .byte

$18 $18 $00 $18 $18 $18 $18 $18

; ; ; ; ; ; ; ;

| | | | | | | |

XX XX

| | | | | | | |

.byte Copyright0: .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte Copyright1: .byte .byte .byte .byte .byte .byte

$00 ; |

X

XX XX XX XX XX

|

$00 $00 $00 $00 $00 $00 $00 $00 $00 $F7 $95 $87 $80 $90 $F0

; ; ; ; ; ; ; ; ; ; ; ; ; ; ;

| | | | | | | | | | | | | | | | | | |XXXX XXX| |X X X X| |X XXX| |X | |X X | |XXXX |

$00 $00 $00 $00 $00 $00

; ; ; ; ; ;

| | | | | |

| | | | | |

.byte .byte .byte .byte .byte .byte .byte .byte .byte .byte Copyright2: .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte Copyright3: .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte Copyright4: .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte

$00 $00 $47 $41 $77 $55 $75 $00 $00 $00

; ; ; ; ; ; ; ; ; ;

| | | | | | | | | |

| | X XXX| X X| XXX XXX| X X X X| XXX X X| | | |

$AD $A9 $E9 $A9 $ED $41 $0F $00 $03 $00 $4B $4A $6B $00 $08 $00

; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ;

|X X |X X |XXX |X X |XXX | X | | | | | X | X | XX | | |

$50 $58 $5C $56 $53 $11 $F0 $00 $80 $80 $AA $AA $BA $22 $27 $02

; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ;

| X X | | X XX | | X XXX | | X X XX | | X X XX| | X X| |XXXX | | | |X | |X | |X X X X | |X X X X | |X XXX X | | X X | | X XXX| | X |

$BA $8A $BA $A2 $3A $80 $FE $00 $00 $00 $11 $11 $17

; ; ; ; ; ; ; ; ; ; ; ; ;

|X XXX X | |X X X | |X XXX X | |X X X | | XXX X | |X | |XXXXXXX | | | | | | | | X X| | X X| | X XXX|

XX X X X XX

X| X| X| X| X| X| XXXX| | XX| | X XX| X X | X XX| | X | |

.byte .byte .byte Copyright5: .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte

$15 ; | $17 ; | $00 ; | $E9 $AB $AF $AD $E9 $00 $00 $00 $00 $00 $77 $54 $77 $51 $77

; ; ; ; ; ; ; ; ; ; ; ; ; ; ;

X X X| X XXX| |

|XXX X X| |X X X XX| |X X XXXX| |X X XX X| |XXX X X| | | | | | | | | | | | XXX XXX| | X X X | | XXX XXX| | X X X| | XXX XXX|

PageFlagTab: .byte 0, PF2_PAGE_FLAG, PF1_PAGE_FLAG, PF1_PAGE_FLAG|PF2_PAGE_FLAG PF1_PAGE_FLAG unused! shapePtr1bTab: .byte <Explosion0-1, <Explosion1B-1, <Explosion2B-1, <Explosion1B-1 .byte PFPat0 ; 2 STA PF1Ptr+1 ; 3 LDA STA LDA LSR AND ORA STA RTS

PF2Lst,X PF2Ptr blockLst,X

; ; ; ; #PF2_PAGE_FLAG>>1 ; #>PFPat0 ; PF2Ptr+1 ; ;

4 3 4 2 2 2 3 6 = 44

;=============================================================================== ; R O M - T A B L E S (Part 2)

;

;=============================================================================== ; high addresses of entry points into kernel: JmpHiTab: .byte >[JmpPoint0-1], >[JmpPoint1-1], >[JmpPoint2-1], >[JmpPoint3-1], >[JmpPoint4-1] .byte >[JmpPoint5-1], >[JmpPoint6-1], >[JmpPoint7-1], >[JmpPoint8-1], >[JmpPoint9-1] ; used to animate explosions and helicopter: AnimateIdTab: .byte 0 ; .byte ID_EXPLOSION2 ; start of explosion sequence .byte ID_EXPLOSION3 ; .byte ID_EXPLOSION0 ; end explosion with 0 .byte ID_PLANE ; no animation for plane .byte ID_HELI1 ; switch between.. .byte ID_HELI0 ; ..ID_HELI0 and ID_HELI1 ; these are the patterns, that are used to define the playfield: PFPat0: .byte $00 ; | | $FC00 .byte $00 ; | | .byte $00 ; | | .byte $00 ; | | .byte $00 ; | | .byte $00 ; | | .byte $00 ; | | .byte $00 ; | | .byte $00 ; | | .byte $00 ; | | .byte $00 ; | | .byte $00 ; | | .byte $00 ; | | .byte $00 ; | | .byte $00 ; | | .byte $00 ; | | .byte $00 ; | | .byte $00 ; | | .byte $00 ; | | .byte $01 ; | X| .byte $03 ; | XX| .byte $07 ; | XXX| .byte $0F ; | XXXX| .byte $1F ; | XXXXX| PFPat14: .byte $3F ; | XXXXXX| .byte $3F ; | XXXXXX| .byte $3F ; | XXXXXX| .byte $3F ; | XXXXXX| .byte $3F ; | XXXXXX| .byte $3F ; | XXXXXX| .byte $3F ; | XXXXXX| .byte $3F ; | XXXXXX| .byte $3F ; | XXXXXX| .byte $3F ; | XXXXXX| .byte $3F ; | XXXXXX| .byte $3F ; | XXXXXX|

.byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte PFPat13: .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte PFPat12: .byte .byte .byte .byte

$3F $3F $3F $3F $1F $0F $07 $03 $01 $00 $00 $00 $00 $00 $00 $00 $00 $01 $03 $07 $0F

; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ;

| | | | | | | | | | | | | | | | | | | | |

XXXXXX| XXXXXX| XXXXXX| XXXXXX| XXXXX| XXXX| XXX| XX| X| | | | | | | | | X| XX| XXX| XXXX|

$1F $1F $1F $1F $1F $1F $1F $1F $1f $1F $1F $1F $1F $1F $1F $1F $0F $07 $03 $01 $00 $00 $00 $00 $00 $00 $00 $00 $01 $03 $07

; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ;

| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |

XXXXX| XXXXX| XXXXX| XXXXX| XXXXX| XXXXX| XXXXX| XXXXX| XXXXX| XXXXX| XXXXX| XXXXX| XXXXX| XXXXX| XXXXX| XXXXX| XXXX| XXX| XX| X| | | | | | | | | X| XX| XXX|

$0F $0F $0F $0F

; ; ; ;

| | | |

XXXX| XXXX| XXXX| XXXX|

.byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte PFPat11: .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte PFPat10: .byte .byte .byte .byte

$0F $0F $0F $0F $0F $0F $0F $0F $0F $0F $0F $0F $07 $03 $01 $00 $00 $00 $00 $00 $00 $00 $00 $01 $03

; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ;

| | | | | | | | | | | | | | | | | | | | | | | | |

XXXX| XXXX| XXXX| XXXX| XXXX| XXXX| XXXX| XXXX| XXXX| XXXX| XXXX| XXXX| XXX| XX| X| | | | | | | | | X| XX|

$07 $07 $07 $07 $07 $07 $07 $07 $07 $07 $07 $07 $07 $07 $07 $07 $03 $01 $00 $00 $00 $00 $00 $00 $00 $00 $01

; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ;

| | | | | | | | | | | | | | | | | | | | | | | | | | |

XXX| XXX| XXX| XXX| XXX| XXX| XXX| XXX| XXX| XXX| XXX| XXX| XXX| XXX| XXX| XXX| XX| X| | | | | | | | | X|

$03 $03 $03 $03

; ; ; ;

| | | |

XX| XX| XX| XX|

.byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte

$03 $03 $03 $03 $03 $03 $03 $03 $03 $03 $03 $03 $01 $00 $00 $00 $00 $00 $00 $00 $00

; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ;

| | | | | | | | | | | | | | | | | | | | |

XX| XX| XX| XX| XX| XX| XX| XX| XX| XX| XX| XX| X| | | | | | | | |

.byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte JetStraight: .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte

$01 $01 $01 $01 $01 $01 $01 $01 $01 $01 $01 $01 $01 $01 $01 $01 $00 $00 $00

; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ;

| | | | | | | | | | | | | | | | | | |

X| X| X| X| X| X| X| X| X| X| X| X| X| X| X| X| | | |

$00 $00 $00 $00 $00 $2A $3E $1C $08 $49 $6B $7F $7F $3E $1C $08

; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ;

| | | | | | | | | | | | | | | |

| | | | | X X X | XXXXX | XXX | X | X X X| XX X XX| XXXXXXX| XXXXXXX| XXXXX | XXX | X |

PFPat9:

.byte .byte JetMove: .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte JetExplode: .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte

$08 ; | $08 ; |

X X

| |

X X XXX XXXX XX X X X X XXX XXXXX XXXXX XXXX XX X X X

| | | | | | | | | | | | | | | | | |

$00 $00 $00 $00 $02 $2E $3C $18 $08 $0A $2E $3E $3E $3C $18 $08 $08 $08

; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ;

| | | | | | | | | | | | | | | | | |

$00 $00 $00 $00 $00 $02 $08 $10 $00 $40 $08 $21 $44 $10 $04 $08 $00

; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ;

| | | | | | | | | | | X | | X | | X | | | | X | | X | | X X| | X X | | X | | X | | X | | |

; low pointers to the patterns for the river bank: BankPtrTab: ; $FCF1 .byte
PFPat8:

.byte .byte .byte .byte .byte .byte .byte

$80 $C0 $E0 $F0 $F8 $FC $FE

; ; ; ; ; ; ;

|X |XX |XXX |XXXX |XXXXX |XXXXXX |XXXXXXX

| $FD00 | | | | | |

.byte $FF ; |XXXXXXXX|

PFPat7:

PFPat6:

.byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte

$FF $FF $FF $FF $FF $FF $FF $FF $FF $FF $FF $FF $FF $FF $FF $FE $FC $F8 $F0 $E0 $C0 $80 $C0 $E0 $F0 $F8 $FC

; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ;

|XXXXXXXX| |XXXXXXXX| |XXXXXXXX| |XXXXXXXX| |XXXXXXXX| |XXXXXXXX| |XXXXXXXX| |XXXXXXXX| |XXXXXXXX| |XXXXXXXX| |XXXXXXXX| |XXXXXXXX| |XXXXXXXX| |XXXXXXXX| |XXXXXXXX| |XXXXXXX | |XXXXXX | |XXXXX | |XXXX | |XXX | |XX | |X | |XX | |XXX | |XXXX | |XXXXX | |XXXXXX |

.byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte

$FE $FE $FE $FE $FE $FE $FE $FE $FE $FE $FE $FE $FE $FE $FE $FE $FC $F8 $F0 $E0 $C0 $80 $C0 $E0 $F0 $F8

; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ;

|XXXXXXX |XXXXXXX |XXXXXXX |XXXXXXX |XXXXXXX |XXXXXXX |XXXXXXX |XXXXXXX |XXXXXXX |XXXXXXX |XXXXXXX |XXXXXXX |XXXXXXX |XXXXXXX |XXXXXXX |XXXXXXX |XXXXXX |XXXXX |XXXX |XXX |XX |X |XX |XXX |XXXX |XXXXX

.byte $FC ; |XXXXXX .byte $FC ; |XXXXXX .byte $FC ; |XXXXXX

| | | | | | | | | | | | | | | | | | | | | | | | | | | | |

PFPat5:

PFPat4:

.byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte

$FC $FC $FC $FC $FC $FC $FC $FC $FC $FC $FC $FC $FC $F8 $F0 $E0 $C0 $80 $C0 $E0 $F0

; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ;

|XXXXXX |XXXXXX |XXXXXX |XXXXXX |XXXXXX |XXXXXX |XXXXXX |XXXXXX |XXXXXX |XXXXXX |XXXXXX |XXXXXX |XXXXXX |XXXXX |XXXX |XXX |XX |X |XX |XXX |XXXX

| | | | | | | | | | | | | | | | | | | | |

.byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte

$F8 $F8 $F8 $F8 $F8 $F8 $F8 $F8 $F8 $F8 $F8 $F8 $F8 $F8 $F8 $F8 $F0 $E0 $C0 $80 $C0 $E0

; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ;

|XXXXX |XXXXX |XXXXX |XXXXX |XXXXX |XXXXX |XXXXX |XXXXX |XXXXX |XXXXX |XXXXX |XXXXX |XXXXX |XXXXX |XXXXX |XXXXX |XXXX |XXX |XX |X |XX |XXX

| | | | | | | | | | | | | | | | | | | | | |

.byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte

$F0 $F0 $F0 $F0 $F0 $F0 $F0 $F0 $F0 $F0 $F0 $F0 $F0

; ; ; ; ; ; ; ; ; ; ; ; ;

|XXXX |XXXX |XXXX |XXXX |XXXX |XXXX |XXXX |XXXX |XXXX |XXXX |XXXX |XXXX |XXXX

| | | | | | | | | | | | |

PFPat3:

PFPat2:

PFPat1:

.byte .byte .byte .byte .byte .byte .byte

$F0 $F0 $F0 $E0 $C0 $80 $C0

; ; ; ; ; ; ;

|XXXX |XXXX |XXXX |XXX |XX |X |XX

| | | | | | |

.byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte

$E0 $E0 $E0 $E0 $E0 $E0 $E0 $E0 $E0 $E0 $E0 $E0 $E0 $E0 $E0 $E0 $C0 $80

; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ;

|XXX |XXX |XXX |XXX |XXX |XXX |XXX |XXX |XXX |XXX |XXX |XXX |XXX |XXX |XXX |XXX |XX |X

| | | | | | | | | | | | | | | | | |

.byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte

$C0 $C0 $C0 $C0 $C0 $C0 $C0 $C0 $C0 $C0 $C0 $C0 $C0 $C0 $C0 $C0

; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ;

|XX |XX |XX |XX |XX |XX |XX |XX |XX |XX |XX |XX |XX |XX |XX |XX

| | | | | | | | | | | | | | | |

.byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte

$80 $80 $80 $80 $80 $80 $80 $80 $80 $80 $80 $80 $80 $80

; ; ; ; ; ; ; ; ; ; ; ; ; ;

|X |X |X |X |X |X |X |X |X |X |X |X |X |X

| | | | | | | | | | | | | |

.byte $80 ; |X .byte $80 ; |X

| |

InitTab: ; $FDB1 .ds 6, PFPat0 .byte 12 .byte 1 .byte SEED_LO, SEED_HI .byte <Space, >Space .byte 1, SEED_LO, SEED_HI, <Space randomLoSave, randomHiSave, livesPtr) .byte $80 .byte FuelA .byte FuelB .byte <ShipCol-3, >ShipCol

; ; ; ; ; ; ; ; ; ; ; ; ; ; ;

PF1Lst PF2Lst missileY playerX speedX speedY

; ; ; ;

gameMode shapePtr1a shapePtr1b colorPtr

fuelHi, fuelLo sectionBlock shapePtr0 ;22 PF1PatId level randomLoSave, randomHiSave livesPtr player2State (level,

;=============================================================================== ; R O M - C O D E (Part 3) ;=============================================================================== CalcPosX SUBROUTINE ; calculates values for x-positioning: ; Input: ; - a = x-position ; Return: ; - y = coarse value for delay loop ; - a = fine value for HMxy TAY ; 2 INY ; 2 TYA ; 2 AND #$0F ; 2 STA temp2 ; 3 TYA ; 2 LSR ; 2 LSR ; 2 LSR ; 2 LSR ; 2 TAY ; 2 CLC ; 2 ADC temp2 ; 3 CMP #$0F ; 2 BCC .skipIny ; 2 SBC #$0F ; 2 INY ; 2 .skipIny: EOR #$07 ; 2 Mult16: ASL ; 2

Wait12:

ASL ASL ASL

; 2 ; 2 ; 2

RTS

; 6

;=============================================================================== ; R O M - T A B L E S (Part 3) ;=============================================================================== ; low addresses of entry points into kernel: JmpLoTab: .byte <[JmpPoint0-1] .byte <[JmpPoint1-1] .byte <[JmpPoint2-1] .byte <[JmpPoint3-1] .byte <[JmpPoint4-1] .byte <[JmpPoint5-1] .byte <[JmpPoint6-1] .byte <[JmpPoint7-1] .byte <[JmpPoint8-1] .byte <[JmpPoint9-1] align 256 FuelTab0: .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte FuelTab1: .byte Explosion0: .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte

$7F $40 $4F $48 $48 $4E $48 $48 $4F $40 $40 $4C $4C $4C $7F

; ; ; ; ; ; ; ; ; ; ; ; ; ; ;

| | | | | | | | | | | | | | |

XXXXXXX| $FE00 X | X XXXX| X X | X X | X XXX | X X | X X | X XXXX| X | X | X XX | X XX | X XX | XXXXXXX|

$FF ; |XXXXXXXX| $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00

; ; ; ; ; ; ; ; ; ; ; ;

| | | | | | | | | | | |

| | | | | | | | | | | |

.byte FuelTab2: .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte FuelTab3: .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte FuelTab4: .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte

$00 ; |

|

$FF $00 $03 $C2 $63 $30 $1B $EC $46 $43 $C1 $48 $08 $08

; ; ; ; ; ; ; ; ; ; ; ; ; ;

|XXXXXXXX| | | | XX| |XX X | | XX XX| | XX | | XX XX| |XXX XX | | X XX | | X XX| |XX X| | X X | | X | | X |

$FF $00 $80 $00 $80 $80 $80 $00 $00 $00 $80 $00 $00 $00

; ; ; ; ; ; ; ; ; ; ; ; ; ;

|XXXXXXXX| | | |X | | | |X | |X | |X | | | | | | | |X | | | | | | |

$FF $01 $81 $81 $81 $E1 $81 $81 $F1 $01 $01 $19 $19 $19 $FF

; ; ; ; ; ; ; ; ; ; ; ; ; ; ;

|XXXXXXXX| | X| |X X| |X X| |X X| |XXX X| |X X| |X X| |XXXX X| | X| | X| | XX X| | XX X| | XX X| |XXXXXXXX|

; used to en- or disable ball in fuel display: ENABLTab: .byte DISABLE .byte ENABLE, ENABLE, ENABLE, ENABLE, ENABLE, ENABLE, ENABLE, ENABLE, ENABLE, ENABLE ; the scores to the enemy objects (bit 7 = 0: *10, = 1: *100): ScoreTab: .byte 0, 0, 0, 0 ; EXPLOSIONS .byte DIGIT_H * 1 | $80 ; PLANE 100

.byte .byte .byte .byte .byte .byte

DIGIT_H DIGIT_H DIGIT_H DIGIT_H 0 DIGIT_H

* * * *

6 6 3 5 |$80

* 8

; ; ; ; ; ;

HELI HELI SHIP BRIDGE HOUSE FUEL

; the data is stored for interlaced display: FuelA: .byte $FE ; |XXXXXXX | .byte $DE ; |XX XXXX | .byte $DE ; |XX XXXX | .byte $FE ; |XXXXXXX | .byte $DE ; |XX XXXX | .byte $DE ; |XX XXXX | .byte $FE ; |XXXXXXX | .byte $D6 ; |XX X XX | .byte $D6 ; |XX X XX | .byte $DE ; |XX XXXX | .byte $CE ; |XX XXX | FuelB: .byte $C6 ; |XX XX | .byte $DE ; |XX XXXX | .byte $DE ; |XX XXXX | .byte $C6 ; |XX XX | .byte $CE ; |XX XXX | .byte $C6 ; |XX XX | .byte $C6 ; |XX XX | .byte $D6 ; |XX X XX | .byte .byte .byte .byte BridgeA: .byte BridgeB: .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte ShipB: .byte .byte .byte .byte .byte .byte .byte PlaneA: .byte

$FE $DE $DE $7C

; ; ; ;

|XXXXXXX |XX XXXX |XX XXXX | XXXXX

$42 ; | X

| | | |

X |

$FF $FF $FF $FF $FF $FF $FF $FF $FF $FF $42

; ; ; ; ; ; ; ; ; ; ;

|XXXXXXXX| |XXXXXXXX| |XXXXXXXX| |XXXXXXXX| |XXXXXXXX| |XXXXXXXX| |XXXXXXXX| |XXXXXXXX| |XXXXXXXX| |XXXXXXXX| | X X |

$00 $00 $00 $FC $FF $30 $10

; ; ; ; ; ; ;

| | | | | | |XXXXXX | |XXXXXXXX| | XX | | X |

$00 ; |

|

60 60 30 500 80

Heli1B:

Heli0A:

ShipA:

PlaneB:

Heli1A:

Heli0B:

.byte .byte .byte .byte .byte .byte .byte .byte

$00 $00 $00 $00 $30 $4F $C6 $00

; ; ; ; ; ; ; ;

| | | | | | | | | XX | | X XXXX| |XX XX | | |

.byte .byte .byte .byte .byte .byte .byte .byte

$00 $00 $00 $0E $8E $FF $0E $07

; ; ; ; ; ; ; ;

| | | | | | | XXX | |X XXX | |XXXXXXXX| | XXX | | XXX|

.byte .byte .byte .byte .byte .byte .byte .byte .byte

$00 $00 $00 $00 $04 $FF $9F $04 $07

; ; ; ; ; ; ; ; ;

| | | | | | | | | X | |XXXXXXXX| |X XXXXX| | X | | XXX|

.byte .byte .byte .byte .byte .byte .byte

$00 $00 $00 $7C $FE $78 $10

; ; ; ; ; ; ;

| | | | XXXXX |XXXXXXX | XXXX | X

.byte .byte .byte .byte .byte .byte .byte .byte

$00 $00 $00 $00 $00 $38 $FF $80

; ; ; ; ; ; ; ;

| | | | | | | | | | | XXX | |XXXXXXXX| |X |

.byte .byte .byte .byte .byte .byte .byte .byte .byte

$00 $00 $00 $00 $04 $FF $9F $04 $1C

; ; ; ; ; ; ; ; ;

| | | | | | | | | X | |XXXXXXXX| |X XXXXX| | X | | XXX |

.byte $00 ; | .byte $00 ; | .byte $00 ; |

| | | | | | |

| | |

.byte .byte .byte .byte .byte Explosion1B: .byte .byte .byte .byte .byte .byte .byte .byte Explosion1A: .byte .byte .byte .byte .byte .byte .byte .byte .byte Explosion2B: .byte .byte .byte .byte .byte .byte .byte .byte .byte Explosion2A: .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte HouseB: .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte

$0E $8E $FF $0E $1C

; ; ; ; ;

| XXX | |X XXX | |XXXXXXXX| | XXX | | XXX |

$00 $00 $00 $00 $10 $20 $40 $10

; ; ; ; ; ; ; ;

| | | | | X | X | X | X

$00 $00 $00 $00 $04 $02 $08 $04 $00

; ; ; ; ; ; ; ; ;

| | | | | | | | |

$00 $00 $00 $20 $02 $41 $20 $02 $04

; ; ; ; ; ; ; ; ;

| | | | X | | X | X | |

$00 $00 $00 $04 $88 $10 $04 $80 $10 $00 $00

; ; ; ; ; ; ; ; ; ; ;

| | | | |X | | |X | | |

$00 $04 $1F $0E $04 $04 $00 $AA $FE $7C $00

; ; ; ; ; ; ; ; ; ; ;

| | | X | | XXXXX| | XXX | | X | | X | | | |X X X X | |XXXXXXX | | XXXXX | | |

| | | | | | | | | | | | X | X | X | X | | | | | | X | X| | X | X |

X X X X X

| | | | | | | | | | |

HouseA: .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte

$00 $04 $0E $1F $0E $04 $00 $FE $AA $FE $38 $00 $00 $00

; ; ; ; ; ; ; ; ; ; ; ; ; ;

| | | X | | XXX | | XXXXX| | XXX | | X | | | |XXXXXXX | |X X X X | |XXXXXXX | | XXX | | | | | | |

;=============================================================================== ; R O M - C O D E (Part 4) ;=============================================================================== GetPageFlag SUBROUTINE ; get bit 0 of the page for the TXA BEQ .exit LDA #%0 CPX #SWITCH_PAGE_ID BCS .exit LDA #%1 .exit: RTS SetScorePtrs SUBROUTINE STA scorePtr1+10 STA scorePtr2+10

playfield data: ;2 ;2 ;2 ;2 PF id < 9 ;2 no, read data from page $FC ;2 yes, read data from page $FD ;6 ;3 ;3

; let score-pointers point to 'Space' to avoid leading zeros: LDA #<Space ;2 LDX #8 ;2 .loopScorePtr2: STA scorePtr2,X ;4 DEX ;2 DEX ;2 BPL .loopScorePtr2 ;2 LDX #8 SetScorePtr1: STA scorePtr1,X DEX DEX BPL SetScorePtr1 RTS

;2 ;4 ;2 ;2 ;2 ;6

;=============================================================================== ; R O M - T A B L E S (Part 4) ;===============================================================================

ColorPtrTab: .byte colors) .byte .byte .byte .byte .byte .byte .byte .byte .byte .byte

$49

; explosion 0

(no extra data for explosion

$2A $66 $2A
; ; ; ; ; ; ; ; ; ;

(one byte shared!) (=$37)

explosion 1 explosion 2 explosion 3 plane helicopter helicopter ship bridge house fuel

HouseCol: .byte BROWN, LIGHT_GREEN, LIGHT_GREEN, LIGHT_GREEN, LIGHT_GREEN .byte BLACK, LIGHT_GREY, LIGHT_GREY, BLACK, BLACK FuelCol: .byte LIGHT_GREY, LIGHT_GREY, LIGHT_GREY, RED, RED, RED .byte LIGHT_GREY, LIGHT_GREY, LIGHT_GREY, RED, RED, RED HelicopterCol: .byte CYAN, CYAN, DARK_BLUE, CYAN, ORANGE, ORANGE IF NTSC PlaneCol: .byte $AC, $9C, $8C ShipCol: .byte $A8, $32, BLACK, BLACK BridgeCol: .byte $20, $14, $12, $14, $12, $18, $12, $14, $12, $14, $20 ELSE PlaneCol: .byte $BC, $BC, $9C ShipCol: .byte $98, $42, BLACK, BLACK BridgeCol: .byte $20, $24, $22, $24, $22, $28, $22, $24, $22, $24, $20 .byte $B4 ; unused ENDIF ;=============================================================================== ; R O M - C O D E (Part 5) ;=============================================================================== LooseJet SUBROUTINE ; called when player looses a life: STY sound0Cnt ; 3 STA sound0Id ; 3 LDA blockLst ; 3 EOR blockLstEnd ; 3 AND #PF_COLOR_FLAG ; 2 BEQ .skipRestartLevel ; 2 LDA sectionEnd ; 3 BEQ .isEnd ; 2 BIT blockLstEnd ; 3 BPL .skipRestartLevel ; 2 JSR SaveSection ; 6 BNE .skipRestartLevel ; 3

dark section? yes, skip end of section? yes, check restart of level road in new block? no, skip yes, goto next section

.isEnd:

BIT blockLstEnd BMI .skipRestartLevel ; restart level: LDX level DEX CPX #MAX_LEVEL-2 BNE .skipLimit LDX #MAX_LEVEL .skipLimit: STX level LDA randomLoSave2 STA randomLoSave LDA randomHiSave2 STA randomHiSave .skipRestartLevel: LDA #<JetExplode-1 STA shapePtr0 .contFinish: STA gameMode LDA #NUM_LINES+20 STA missileY RTS FinishGame: ; called when LDA STA BNE

; 3 ; 2

PF_ROAD_FLAG set? yes, skip restart level

; ; ; ; ;

3 2 2 2 2

limit level to 48

; ; ; ; ;

3 3 3 3 3

; 2 ; 3 ; ; ; ;

3 2 3 6

the the game is not running: #$FF ; 2 frameCnt ; 3 .contFinish ; 3

IF NTSC FinishDigits SUBROUTINE INY STA WSYNC STA HMOVE STY GRP1 STY GRP0 STY GRP1 LDY #14 SetColPx: STA COLUP0 STA COLUP1 DoHMove: STA WSYNC STA HMOVE RTS ELSE LoadPFPattern SUBROUTINE BIT PF_State BPL .contPage1 TAY table LDA PageFlagTab,Y .contPage1: ORA blockLstEnd STA blockLstEnd LDA BankPtrTab,X

retrieve saved random values

; ; ; ; ; ; ;

2 3 3 3 3 3 2

disable missile

disable al animations

load line counter

; 3 ; 3 ; 3 ; 3 ; 6 ; 3 ; 2 ; 2 ; 4 ; 3 ; 3 ; 4

ISLAND_FLAG set? no, set current page-flag yes, read new page-flag from

CLC ADC diffPF and prev PF id STA PF2LstEnd RTS ENDIF

; 2 ; 3

adjust with difference between new

; 3 ; 6

;=============================================================================== ; R O M - T A B L E S (Part 5) ;=============================================================================== RoadColorTab: .byte $04, $04, $08, $08, $08, $08, YELLOW, $08, $08, $08, $08 ; next two bytes are shared VolumeTab: .byte $04, $04 ; next byte ($07) is shared EnemyIdTab: .byte ID_SHIP, ID_HELI0, ID_SHIP, ID_HELI0, ID_PLANE, ID_SHIP, ID_HELI0, ID_HELI0 shapePtr1aTab: .byte <Explosion0-1, <Explosion1A-1, <Explosion2A-1, <Explosion1A-1 .byte
#3

;2

player1State,X player2State,X player2State,X player1State,X .loopSwap0

;4 ;4 ;4 ;4 ;2 ;2

LDX .loopSwap1: LDA LDY STA STY DEX DEX BPL .skipSwap:

#12-2

;2

scorePtr1,X scorePtr2,X scorePtr2,X scorePtr1,X

;4 ;4 ;4 ;4 ;2 ;2 ;2

.loopSwap1

RTS

;6

;=============================================================================== ; R O M - T A B L E S (Part 6) ;=============================================================================== ColorTab: .byte 0, YELLOW, GREY, YELLOW+2, BLUE .word START .word 0

Related Documents


More Documents from ""