wudsn-ide/com.wudsn.ide.ref/ASM/Atari2600/DASM/minidig/disassembly/CosmicArk.asm
2018-12-30 16:52:33 +01:00

3421 lines
120 KiB
NASM
Raw Blame History

; *** C O S M I C A R K ***
; Copyright 1982 Imagic
; Designer: Rob Fulop
; Analyzed, labeled and commented
; by Thomas Jentzsch (JTZ)
; Last Update: 23.04.2002 (v0.9)
; PAL conversion notes:
; Cosmic Ark is the first game I disassembled, where the PAL conversion has
; adjusted game speeds. This was possible, because the game uses fractional
; addition techniques (see Stella Programmer's Guide, page 16). Nearly all
; speeds have been adjusted, so that the game should have the same speeds for
; NTSC and PAL. Due to the rather complex meteror speeds and a little flaw in
; the code, this doesn't work 100% perfect there.
; Misc:
; - The code is not very heavily optimized and there are a few a bit weird code
; sequences. However, this is probably just the case because optimization was
; not necessary. The general code looks very straightforward and readable.
; - It looks like the game was planned to have a *non*-cooperative 2 player
; mode. The duplicated score variables and the code for changing both scores
; (AddScore) are still there.
; - The game uses a *lot* of status flags. Therefore I'm not always sure, that
; I recognized them correctly.
TIMINT = $285
processor 6502
include vcs.h
;===============================================================================
; A S S E M B L E R - S W I T C H E S
;===============================================================================
NTSC = 1 ; compiling for NTSC of PAL mode
OPTIMIZE = 0 ; enable some possible size optimizations
FILL_OPT = 1 ; fill the optimized space with NOPs
;===============================================================================
; C O N S T A N T S
;===============================================================================
;general constants:
SCREEN_WIDTH = 160
NUM_DIGITS = 6 ; number of score digits (48 pixel routine)
;values for missiles and ball:
DISABLE = %00
ENABLE = %10
;values for joystick:
NO_DIR = %1111
UP_DIR = %1110
DOWN_DIR = %1101
LEFT_DIR = %1011
RIGHT_DIR = %0111
;values for NUSIZx:
ONE_COPY = %000
TWO_COPIES = %001
TWO_COPIES_WIDE = %010
THREE_COPIES = %011
DOUBLE_SIZE = %101
THREE_COPIES_MED = %110
QUAD_SIZE = %111
MS_SIZE1 = %000000
MS_SIZE2 = %010000
MS_SIZE4 = %100000
MS_SIZE8 = %110000
;color values:
BLACK = $00
WHITE = $0e
IF NTSC
BROWN = $28
ORANGE = $38
RED = $48
MAGENTA = $58
MAGENTA2 = $68
BLUE = $88
BLUE2 = $98
CYAN = $a8
GREEN = $c8
GREEN2 = $d8
ORANGE_GREEN = $e8
OCHRE = $f8
ELSE
BROWN = $48
ORANGE = $48
RED = $68
MAGENTA = $88
MAGENTA2 = $c8
BLUE = $b8
BLUE2 = $d8
CYAN = $98
GREEN = $58
GREEN2 = $38
ORANGE_GREEN = $28
OCHRE = $48
ENDIF
RED_BROWN = $44 ; NTSC = PAL!
;various constants:
NUM_STARCOLUMS = 18 ; number of star columns
NUM_GAMES = 6 ; number of game variations (1..6)
ADVANCED_GAME = 4 ; advanced games start here (4..6)
NUM_BEASTIES = 7 ; number of different beasties
MAX_FUEL = 48 ; maximum fuel units
ARK_HEIGHT = 19
MAX_SCROLL = 10 ; number of lines the planet surface scrolls
DIGIT_HEIGHT = 10
KERNEL_HEIGHT = 184
ID_P0 = 0
ID_SHUTTLE = ID_P0+1
ID_STARS = ID_SHUTTLE+1
;values for shotDir:
NO_SHOT = 0
SHOT_LEFT = 1
SHOT_RIGHT = 2
SHOT_UP = 3
SHOT_DOWN = 4
;values for meteorDir (identical to shotDir):
NO_METEOR = 0
METEOR_LEFT = 1
METEOR_RIGHT = 2
METEOR_UP = 3
METEOR_DOWN = 4
;flags for status:
SHUTTLE_MODE = %10000000
ON_PLANET = %01000000
ARK_UPDOWN = %00100000
NO_METEORS = %00010000
GAME_OVER = %00001000 ; this flag is set, while the last Ark is destroyed
;values for gameStatus:
RUNNING = %10000000
START_MODE = %01000000
SHOW_GAMENUM = %00100000
;flags for gameFlags:
ONE_PLAYER = %00000000
TWO_PLAYERS = %01000000
METEOR_GAME = %10000000
;values for defenseStatus:
FIREING = %10000000
DIR_UP = %01000000
ACTIVE = %00100000
;values for beamStatus:
BEAM_BEASTIE = %10000000
DROP_BEASTIE = %01000000
;values beastie?Status:
BEASTIE_LEFT = %10000000
BEASTIE_FREE = %01000000
;values for channel0Sound:
ARK_SOUND = %10000000 ; played while the Ark moves up and down
SHOT_SOUND = %01000000
CAPTURED_SOUND = %00100000 ; the short "blip" when a beastie is captured
;values for channel1Sound:
METEOR_SOUND = %10000000
SHUTTLE_SOUND = %01000000
BEAM_SOUND = %00100000
;===============================================================================
; Z P - V A R I A B L E S
;===============================================================================
xPosLst = $80 ; ..$84
xPosP0 = xPosLst ; x-position of rescure shuttle (P0)
xPosMeteor = xPosLst+1 ; x-position of meteor and escape shuttle (P1)
xPosStars = xPosLst+2 ; starting x-position of stars (M0)
xPosShotBeam = xPosLst+3 ; x-position of players shot and beastie in tractor beam (M1)
xPosBeam = xPosLst+4 ; x-position of tractor beam (BL)
starColumn = $85 ; current star effect column counter
unused1 = $86
arkPatLst = $87 ; ..$99 pattern of the Ark (19 lines)
yPosShot = $9a ; y-position of players shot
unused2 = $9b
shotDir = $9c ; direction of players shot (0=disabled, 1..4)
yPosMeteor = $9d ; y-position of meteor
meteorDir = $9e ; direction of meteor (0=disabled, 1..4)
meteorPtr = $9f ; ..$a0 kernel pointer to meteor graphics (and escape shuttle)
level = $a1 ; increased after each successful planet
arkHitCnt = $a2 ; counter for disappearing Ark
yPosShuttle = $a3 ; y-position of rescue shuttle
;---------------------------------------
;sound variables:
channel0Sound = $a4 ; flags for sounds of channel 0
channel1Sound = $a5 ; flags for sounds of channel 1
channel0Time = $a6 ; delay time for channel 0 (used to modify sounds)
channel1Time = $a7 ; the same for for channel 1
;---------------------------------------
beastie0Status = $a8 ; status of the beastie 0 (free/captured and running direction)
beastie1Status = $a9 ; the same for beastie 1
numBeasties = $aa ; number of captured beasties
explosionCnt = $ab ; counter for shuttle explosion (0 = no explosion)
gameOver = $ac ; != 0 -> game over
fuel = $ad ; fuel units (0..48)
;---------------------------------------
;score variables:
scoreHi = $ae ; ..$af one variable was planed for each player, but only the first is used
scoreMid = $b0 ; ..$b1
scoreLow = $b2 ; ..$b3
;---------------------------------------
frameCnt = $b4 ; ..$b5 high value only used for screen saver delay
tempVar = $b6 ; temporary multi purpose variable
tempVar2 = $b7 ; another one
status = $b8 ; some status flags
surfaceScroll = $b9 ; used for scrolling up the planet surface
numMeteors = $ba ; number of remaining non wavering meteors in wave
selectDelay = $bb ; delay for SELECT switch
gameNum = $bc ; current game variation (1..6)
digitPtr = $bd ; ..$c8 12 pointers for displaying score, fuel and copyright
yPosArk = $c9 ; y-position of Cosmic Ark
arkAppearCnt = $ca ; used to make Ark appear on top of screen
joyDir = $cb ; last joystick direction
random = $cc ; random number generator (used for meteors, beastie "AI" and hit Ark)
shuttlePtr = $cd ; ..$ce kernel pointer to shuttle graphics
xPosShuttle = $cf ; x-position of rescue shuttle
saveHMStars = $d0 ; remember HMOVE value of stars
;---------------------------------------
;fractional addition variables:
meteorPosLo = $d1 ; some low variables for fractional addition
yPosShuttleLo = $d2 ; (see Stella Programmer's Guide, page 16)
xPosShuttleLo = $d3
;---------------------------------------
xPosBeastie0 = $d4 ; x-position of beastie 0
xPosBeastie1 = $d5 ; x-position of beastie 1
yPosBeam = $d6 ; top position of tractor beam (0 or yPosShuttle)
speedHi = $d7 ; current meteor speed
;---------------------------------------
;another fractional addition variable:
speedLo = $d8
;---------------------------------------
yPosDefense = $d9 ; y-position of planet defense system
defenseStatus = $da ; %FDAxxxxx: Fireing, Direction, Active
yBeamedBeastie = $db ; y-position of beamed beastie
beamStatus = $dc ; status of tractor beam (enabled, dropping a beastie)
gameStatus = $dd ; some more status flags
beastiePtr = $de ; ..$df kernel pointer to beastie graphics
planetTime = $e0 ; time on planet
defenseDelay = $e1 ; delay until next defense fire
;---------------------------------------
;difficulty variables:
initSpeedHi = $e2 ; initial high meteor speed
initSpeedLo = $e3 ; initial low meteor speed
shutteSpeedLo = $e4 ; shuttle speed
alertTime = $e5 ; delay time until bombardment alert
defenseFreq = $e6 ; frequency of defense fire
levelMeteors = $e7 ; meteors per wave
;---------------------------------------
alertCnt = $e8 ; countdown for bombardment alert
beastieId = $e9 ; beastie on current planet
shuttleColor = $ea ; shuttle color, changes every 4th planet
oldNumBeasties = $eb ; number of beasties at start of planet
gameFlags = $ec ; again some more status flags
fireButton = $ed ; remembers fire button bit
waveringFlag = $ee ; used for wavering meteors
waveringCnt = $ef ; used for wavering meteors
P1SpaceCol = $f0 ; color for meteors and escape shuttle
numWaverings = $f1 ; maximum number of wavering meteors in wave
colorMask = $f2 ; used to darken the score display after ~18 minutes
;===============================================================================
; 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
;===============================================================================
ORG $1000
StartKernel SUBROUTINE
;*** start of the display kernel ***
ldx #$04 ; 2 position all five objects
.loopSetPos:
lda xPosLst,x ; 4
jsr SetPosX ; 6
dex ; 2
bpl .loopSetPos ; 2<>
lda status ; 3
and #GAME_OVER ; 2 game over?
beq .skip ; 2<> no, skip
; JTZ: I don't know what this code is useful for. It only causes
; some distortions at the top of the screen when the game is over.
lda frameCnt ; 3 yes, do something
and #$07 ; 2
tay ; 2
lda NuSiz0Tab,y ; 4
.skip:
sta NUSIZ0 ; 3
.waitTim:
bit TIMINT ; 4
bpl .waitTim ; 2<>
sta WSYNC ; 3
;------------------------------
ldx #ID_STARS ; 2 position stars
lda xPosLst,x ; 4
jsr SetPosX ; 6
sta saveHMStars ; 3
sta WSYNC ; 3
;------------------------------
sta HMOVE ; 3
jsr TimeStarTrick ;18 a = $60 = -6
sta HMM0 ; 3 @24 to early! (Cosmic Ark stars trick)
lda #BLACK ; 2 space background
bit status ; 3 space or planet?
bvc .inSpace ; 2<> space, skip
lda #CYAN-8 ; 2 planet background
.inSpace:
sta COLUBK ; 3
sta WSYNC ; 3
;------------------------------
sta VBLANK ; 3
sta HMCLR ; 3
sta REFP0 ; 3 disable reflection
sta REFP1 ; 3
sta CXCLR ; 3
IF NTSC
lda #ENABLE ; 2
ELSE
lda SWCHB ; 4 disable stars with B/W switch (PAL only!)
lsr ; 2
lsr ; 2
ENDIF
sta ENAM0 ; 3 enable missile 0
lda P1SpaceCol ; 3
sta COLUP1 ; 3
lda #%10101 ; 2
sta CTRLPF ; 3 PF reflection & priority, BL size = 2
sta REFP1 ; 3 disable P1 reflection (again?)
IF NTSC
ldx #KERNEL_HEIGHT ; 2 number of kernel lines
ELSE
ldx #KERNEL_HEIGHT+5 ; 2 5 more lines in PAL kernel -> Ark appears a bit below top
ENDIF
.loopTopKernel:
stx WSYNC ; 3
;------------------------------
txa ; 2 check meteor
sec ; 2
sbc yPosMeteor ; 3
tay ; 2
and #$f8 ; 2 at meteor position?
bne .noMeteor0 ; 2<> no, draw blank
lda (meteorPtr),y ; 5 yes, draw meteor
jmp .contMeteor0 ; 3
.noMeteor0:
lda #0 ; 2
.contMeteor0:
sta GRP1 ; 3
txa ; 2 change star color
eor frameCnt ; 3
sta COLUP0 ; 3
ldy #ENABLE-1 ; 2 -> disable shot
txa ; 2 check shot
sec ; 2
sbc yPosShot ; 3
and #$f8 ; 2
bne .disableShot ; 2<>
iny ; 2 -> enable shot
.disableShot:
sty ENAM1 ; 3
dex ; 2
cpx yPosArk ; 3 at Ark position?
bne .loopTopKernel ; 2<> no, loop
lda #ARK_HEIGHT-1 ; 2 19 lines with Ark
sta tempVar ; 3
.loopArkKernel:
sta WSYNC ; 3
;------------------------------
ldy tempVar ; 3 draw Ark
lda arkPatLst,y ; 4
sta PF2 ; 3
lda ArkColTab,y ; 4
sta COLUPF ; 3
txa ; 2 change star color
eor frameCnt ; 3
sta COLUP0 ; 3
;draw meteor:
txa ; 2 check meteor
sec ; 2
sbc yPosMeteor ; 3
tay ; 2
and #$f8 ; 2
bne .noMeteor1 ; 2<>
lda (meteorPtr),y ; 5
jmp .contMeteor1 ; 3
.noMeteor1:
lda #0 ; 2
.contMeteor1:
sta GRP1 ; 3
ldy #ENABLE-1 ; 2 -> disable shot
cpx yPosShot ; 3 check shot
bne .disableShot1 ; 2<>
iny ; 2 -> enable shot
.disableShot1:
sty ENAM1 ; 3
dex ; 2
dec tempVar ; 5 Ark completely drawn?
bpl .loopArkKernel ; 2<> no, loop
sta WSYNC ; 3
;------------------------------
lda CXP1FB-$30 ; 3 check for meteor collisons
pha ; 3 save on stack
bit status ; 3 on planet?
bvs .onPlanet ; 2<> yes, draw rescue shuttle
jmp LowerKernel ; 3 no, draw meteor
.onPlanet:
lda saveHMStars ; 3 move stars
sta HMM0 ; 3
lda xPosShuttle ; 3 position rescue shuttle
stx tempVar2 ; 3
ldx #ID_SHUTTLE ; 2
jsr SetPosX ; 6 this causes the lower line of the Ark
sta WSYNC ; 3 to be displayed some extra lines
;------------------------------
sta HMOVE ; 3
jsr TimeStarTrick ;18 a = $60 = -6
sta HMM0 ; 3 @24 to early! (Cosmic Ark stars trick)
lda #MS_SIZE2 ; 2
sta NUSIZ1 ; 3
lda tempVar2 ; 3
sec ; 2
sbc #$03 ; 2
tax ; 2
lda shuttleColor ; 3 color shuttle
sta COLUP1 ; 3
lda #0 ; 2
sta WSYNC ; 3
;------------------------------
sta PF2 ; 3
beq .enterPlanetKernel;3+1
.loopPlanetKernel:
sta WSYNC ; 3
;------------------------------
sta GRP1 ; 3
cpx yPosDefense ; 3
beq .checkDefense ; 2<>
bcc .drawMast ; 2<>+1
bcs .endDefense ; 3+1
.checkDefense:
lda #$30 ; 2
bit defenseStatus ; 3 defense fireing?
bpl .drawTop ; 2<> no, draw top of mast
lda #$ff ; 2 yes, draw whole line
sta PF0 ; 3
sta PF1 ; 3
sta PF2 ; 3
bne .endDefense ; 3
.drawMast:
lda #$10 ; 2 draw top of mast
.drawTop:
sta PF0 ; 3
lda #$00 ; 2
sta PF1 ; 3
sta PF2 ; 3
.endDefense:
ldy #ENABLE ; 2 check tractor beam
cpx yPosBeam ; 3
bcc .enableBeam ; 2<>
dey ; 2
.enableBeam:
sty ENABL ; 3
.enterPlanetKernel:
;draw shuttle:
txa ; 2 check shuttle
sec ; 2
sbc yPosShuttle ; 3
tay ; 2
and #$f8 ; 2
bne .disableShuttle0 ; 2<>
lda (shuttlePtr),y ; 5
jmp .contShuttle0 ; 3
.disableShuttle0:
lda #0 ; 2
.contShuttle0:
dex ; 2
cpx #19 ; 2
beq .bottomKernel ; 2<>
sta WSYNC ; 3
;------------------------------
sta GRP1 ; 3
txa ; 2 change star color
eor frameCnt ; 3
sta COLUP0 ; 3
ldy #ENABLE-1 ; 2 check beastie in tractor beam
txa ; 2
sec ; 2
sbc yBeamedBeastie ; 3
and #$f8 ; 2
bne .disableBeam ; 2<>
iny ; 2 enable beastie in tractor beam
.disableBeam:
sty ENAM1 ; 3
txa ; 2 check shuttle
sec ; 2
sbc yPosShuttle ; 3
tay ; 2
and #$f8 ; 2
bne .disableShuttle1 ; 2<>
lda (shuttlePtr),y ; 5
jmp .contShuttle1 ; 3
.disableShuttle1:
lda #0 ; 2
.contShuttle1:
dex ; 2
cpx #19 ; 2
bne .loopPlanetKernel; 2<>+1
beq .bottomKernel ; 3
LowerKernel:
lda #0 ; 2
sta WSYNC ; 3
;------------------------------
sta PF2 ; 3
.loopLowerKernel:
sta WSYNC ; 3
;------------------------------
txa ; 2 check meteor
sec ; 2
sbc yPosMeteor ; 3
tay ; 2
and #$f8 ; 2
bne .noMeteor ; 2<>
lda (meteorPtr),y ; 5
jmp .contMeteor ; 3
.noMeteor:
lda #$00 ; 2
.contMeteor:
sta GRP1 ; 3
txa ; 2 change star color
eor frameCnt ; 3
sta COLUP0 ; 3
ldy #ENABLE-1 ; 2 -> disable shot
txa ; 2 check shot
sec ; 2
sbc yPosShot ; 3
and #$f8 ; 2
bne .disableShot2 ; 2<>
iny ; 2 -> enable shot
.disableShot2:
sty ENAM1 ; 3
dex ; 2
cpx #21 ; 2
bne .loopLowerKernel ; 2<>
.bottomKernel:
lda #0 ; 2 disable stars
sta ENAM0 ; 3
sta GRP1 ; 3
bit status ; 3
bvs .onPlanet1 ; 2<> on planet
sta ENAM1 ; 3
sta WSYNC ; 3
jmp .drawScore ; 3
.onPlanet1:
ldx #ID_P0 ; 2 position beastie 0
lda xPosBeastie0 ; 3
jsr SetPosX ; 6
sta WSYNC ; 3
;------------------------------
inx ; 2 position beastie 1
lda xPosBeastie1 ; 3
jsr SetPosX ; 6
sta WSYNC ; 3
;------------------------------
sta HMOVE ; 3
lda #MS_SIZE2 ; 2
sta NUSIZ0 ; 3
sta NUSIZ1 ; 3
lda #BROWN+6 ; 2 set beastie color
sta COLUP0 ; 3
sta COLUP1 ; 3
ldy #%10001 ; 2 PF reflection, BL size = 2
sty CTRLPF ; 3
ldy #$08 ; 2
bit beastie0Status ; 3 beastie 0 moving right?
bmi .reflect0 ; 2<> yes, reflect graphics
dey ; 2
.reflect0:
sty REFP0 ; 3
ldy #$08 ; 2
bit beastie1Status ; 3 beastie 1 moving right?
bmi .reflect1 ; 2<> yes, reflect graphics
dey ; 2
.reflect1:
sty REFP1 ; 3
;scroll surface up/down:
ldx #MAX_SCROLL ; 2
ldy level ; 3
lda PlanetColTab,y ; 4
sta tempVar ; 3
ldy surfaceScroll ; 3
.loopWait:
dey ; 2 wait for planet surface
bmi .drawSurface ; 2<>
sta WSYNC ; 3
;------------------------------
dex ; 2
bne .loopWait ; 2<>
beq .endSurface ; 3+1
.drawSurface:
ldy #DISABLE ; 2
sty ENAM1 ; 3
.loopSurface:
sta WSYNC ; 3
;------------------------------
lda tempVar ; 3 draw surface of planet
ora LumTab,y ; 4
sta COLUPF ; 3
lda PlanetPF0Tab,y ; 4
sta PF0 ; 3
lda PlanetPF1Tab,y ; 4
sta PF1 ; 3
lda PlanetPF2Tab,y ; 4
sta PF2 ; 3
lda (beastiePtr),y ; 5
bit beastie0Status ; 3 beastie 0 captured?
bvc .captured0 ; 2<> yes, skip draw
sta GRP0 ; 3
.captured0:
bit beastie1Status ; 3 beastie 1 captured?
bvc .captured1 ; 2<> yes, skip draw
sta GRP1 ; 3
.captured1:
iny ; 2
dex ; 2
bne .loopSurface ; 2<>+1
.endSurface:
lda tempVar ; 3
sta COLUBK ; 3
jmp .exitKernel ; 3
.drawScore:
lda #BROWN+4 ; 2 set score color
and colorMask ; 3
sta COLUP1 ; 3
sta COLUP0 ; 3
lda #BLUE+4 ; 2 set frame color
and colorMask ; 3
sta COLUPF ; 3
lda #%01 ; 2 enable PF reflection
sta CTRLPF ; 3
lda #THREE_COPIES ; 2
sta NUSIZ0 ; 3
sta NUSIZ1 ; 3
ldy #5 ; 2
sta WSYNC ; 3
;------------------------------
lda #$ff ; 2 draw top of frame around digits
sta PF2 ; 3
;position score sprites:
.delayPos:
dey ; 2
bpl .delayPos ; 2<>
nop ; 2
sta RESP0 ; 3
sta RESP1 ; 3
lda #$f0 ; 2
sta HMP0 ; 3
ldx #$00 ; 2
stx HMP1 ; 3
inx ; 2
stx VDELP0 ; 3
stx VDELP1 ; 3
sta WSYNC ; 3
sta HMOVE ; 3
stx PF2 ; 3
sta WSYNC ; 3
;------------------------------
;draw score:
lda #DIGIT_HEIGHT-1 ; 2 48 pixel routine
sta tempVar2 ; 3
.digitLoop:
ldy tempVar2 ; 3
lda (digitPtr),y ; 5
sta GRP0 ; 3
sta WSYNC ; 3
;------------------------------
lda (digitPtr+2),y ; 5
sta GRP1 ; 3
lda (digitPtr+4),y ; 5
sta GRP0 ; 3
lda (digitPtr+6),y ; 5
sta tempVar ; 3
lda (digitPtr+8),y ; 5
tax ; 2
lda (digitPtr+10),y ; 5
tay ; 2
lda tempVar ; 3
sta GRP1 ; 3
stx GRP0 ; 3
sty GRP1 ; 3
sty GRP0 ; 3
dec tempVar2 ; 5
bpl .digitLoop ; 2<>
ldx #$00 ; 2
sta WSYNC ; 3
;------------------------------
stx GRP0 ; 3
stx GRP1 ; 3
;fuel bar:
lda fuel ; 3 convert fuel into bar
and #$07 ; 2
sta tempVar ; 3
lda fuel ; 3
lsr ; 2
lsr ; 2
lsr ; 2
tay ; 2
beq .skipFull ; 2<>
lda #<FuelBarTab+8 ; 2 full bar
.loopFullBar:
sta digitPtr,x ; 4
inx ; 2
inx ; 2
dey ; 2
bne .loopFullBar ; 2<>
.skipFull:
lda #<FuelBarTab ; 2 empty bar
clc ; 2
adc tempVar ; 3
sta digitPtr,x ; 4
inx ; 2
inx ; 2
lda #<FuelBarTab ; 2
.loopEmptyBar:
cpx #NUM_DIGITS*2 ; 2
beq .exitEmptyLoop ; 2<>
sta digitPtr,x ; 4
inx ; 2
inx ; 2
bne .loopEmptyBar ; 3
.exitEmptyLoop:
;draw fuel bar:
lda #RED_BROWN ; 2
sta COLUP0 ; 3
sta COLUP1 ; 3
lda #2 ; 2
sta tempVar2 ; 3
.fuelBarLoop:
ldy #$00 ; 2
lda (digitPtr),y ; 5
sta GRP0 ; 3
sta WSYNC ; 3
;------------------------------
lda (digitPtr+2),y ; 5
sta GRP1 ; 3
lda (digitPtr+4),y ; 5
sta GRP0 ; 3
lda (digitPtr+6),y ; 5
sta tempVar ; 3
lda (digitPtr+8),y ; 5
tax ; 2
lda (digitPtr+10),y ; 5
tay ; 2
lda tempVar ; 3
sta GRP1 ; 3
stx GRP0 ; 3
sty GRP1 ; 3
sty GRP0 ; 3
dec tempVar2 ; 5
bpl .fuelBarLoop ; 2<>
.exitKernel:
ldx #0 ; 2
sta WSYNC ; 3
;------------------------------
stx GRP0 ; 3
stx GRP1 ; 3
stx GRP0 ; 3
sta WSYNC ; 3
;------------------------------
stx PF0 ; 3
stx PF1 ; 3
stx ENABL ; 3
stx VDELP0 ; 3
stx VDELP1 ; 3
bit status ; 3
bvs .onPlanet2 ; 2<>
lda #$ff ; 2 draw bottom of frame around digits
sta PF2 ; 3
.onPlanet2:
sta WSYNC ; 3
;------------------------------
stx PF2 ; 3
jmp OverScan ; 3
SetPosX SUBROUTINE
;*** position object[X] horizontaly ***
sta tempVar ; 3
inc tempVar ; 5
cpx #$02 ; 2
bcc .isPlayer ; 2<>
inc tempVar ; 5
.isPlayer:
lda tempVar ; 3
pha ; 3
lsr ; 2
lsr ; 2
lsr ; 2
lsr ; 2
sta tempVar ; 3
tay ; 2
pla ; 4
and #$0f ; 2
clc ; 2
adc tempVar ; 3
cmp #$0f ; 2
bcc .ok ; 2<>
sbc #$0f ; 2
iny ; 2
.ok:
sec ; 2
sbc #$08 ; 2
eor #$ff ; 2
sta WSYNC ; 3
;------------------------------
asl ; 2
asl ; 2
asl ; 2
asl ; 2
sta HMP0,x ; 4
.wait:
dey ; 2
bpl .wait ; 2<>
sta tempVar ; 3
sta RESP0,x ; 4
sta WSYNC ; 3
;------------------------------
rts ; 6
START:
sei ; 2
cld ; 2
ldx #$ff ; 2
txs ; 2
inx ; 2
txa ; 2
.clearLoop:
sta $00,x ; 4
inx ; 2
bne .clearLoop ; 2<>
dec colorMask ; 5 = $ff (disable screen saver)
;set high digit pointers:
lda #>Zero ; 2
ldx #NUM_DIGITS*2-1 ; 2
.setHighLoop:
sta digitPtr,x ; 4
dex ; 2
dex ; 2
bpl .setHighLoop ; 2<>
lda #1 ; 2
sta status ; 3
sta random ; 3 initialize random number generator
sta gameNum ; 3 start with game #1
lda #>Shuttle0 ; 2 set high pointers
sta shuttlePtr+1 ; 3
lda #>Beastie0 ; 2
sta beastiePtr+1 ; 3
lda #2 ; 2
sta numMeteors ; 3
jsr StartArkDown ; 6 start Ark
jsr InitGameVars ; 6
MainLoop:
lda #$02 ; 2 start with vertical sync
sta VBLANK ; 3
sta WSYNC ; 3
sta VSYNC ; 3
sta WSYNC ; 3
sta WSYNC ; 3
sta WSYNC ; 3
lda #$00 ; 2
sta VSYNC ; 3
IF NTSC
lda #44 ; 2
ELSE
lda #73 ; 2
ENDIF
sta TIM64T ; 4
;increase frame counter, enable screen saver:
inc frameCnt ; 5
bne .skip_SS ; 2<>
inc frameCnt+1 ; 5
bne .skip_SS ; 2<>
bit gameStatus ; 3 status of game?
bvs .activate_SS ; 2<> in start mode, activate screen saver
bmi .skip_SS ; 2<> running!
.activate_SS:
lda #$f3 ; 2 enable screen saver
sta colorMask ; 3
.skip_SS:
lda random ; 3 generate next random number
asl ; 2
eor random ; 3
asl ; 2
asl ; 2
rol random ; 5
bit gameStatus ; 3 game status?
bvs .checkFire ; 2<> start mode, check fire button
bmi .checkSwitches ; 2<> game running, don't check fire!
.checkFire:
lda INPT4-$30 ; 3 fire pressed?
bpl .doReset ; 2<> yes, reset
.checkSwitches:
lda SWCHB ; 4 avoid repeating RESETs
ror status ; 5 RESET presed before
bcs .noOldReset ; 2<> no, skip
lsr ; 2 RESET pressed?
bcs .doReset ; 2<> no, skip
rol ; 2
.noOldReset:
lsr ; 2
rol status ; 5 bit 0 = RESET
lsr ; 2 SELECT pressed?
bit selectDelay ; 3
bcc .select ; 2<> yes, start a new game
rol selectDelay ; 5 no, debounce delay (very clever)
bne .skipSwitches ; 3+1
.select:
bpl .skipSelect ; 2<>
lda gameStatus ; 3 enable "start mode" and "show game number"
ora #START_MODE|SHOW_GAMENUM; 2
sta gameStatus ; 3
jsr InitGame ; 6
.endDelay:
lda frameCnt ; 3 remember framecounter of current SELECT
and #$1f ; 2
sta selectDelay ; 3
inc gameNum ; 5 increase game number
lda gameNum ; 3
cmp #NUM_GAMES+1 ; 2 maximum game number?
bne .endSwitches ; 2<> no, skip
lda #1 ; 2 yes, reset game number
sta gameNum ; 3
bne .endSwitches ; 3
.skipSelect:
lda selectDelay ; 3 32 frames since last valid SELECT?
eor frameCnt ; 3
and #$1f ; 2
beq .endDelay ; 2<> yes, increase game number
.endSwitches:
jmp .endUpdateGame ; 3
.doReset:
;start a new game:
ldy gameNum ; 3
lda GameFlagsTab,y ; 4
sta gameFlags ; 3
lda #$ff ; 2 disable screen saver
sta colorMask ; 3
ldx #RUNNING ; 2 game is running
stx gameStatus ; 3
jsr InitGame ; 6
jsr StartArkDown ; 6
jsr InitGameVars ; 6
jsr InitLevel ; 6
lda #MAX_FUEL-8 ; 2 set initial fuel
sta fuel ; 3
.skipSwitches:
lda gameStatus ; 3 selecting a game?
and #SHOW_GAMENUM ; 2
beq .updateGameVars ; 2<> no,
jmp .endUpdateGame ; 3 yes, the game is not running
GameFlagsTab:
.byte 0 ; unused
.byte ONE_PLAYER
.byte METEOR_GAME
.byte TWO_PLAYERS
.byte ONE_PLAYER
.byte METEOR_GAME
.byte TWO_PLAYERS
.updateGameVars:
;*** begin of update game variables: ***
lda status ; 3
and #ARK_UPDOWN ; 2 Ark moving up?
beq .skipBonus ; 2<> no,
inc yPosArk ; 5 yes, increase Ark's y-position
bit status ; 3 in space?
bvc .noScroll ; 2<> yes, don't scroll down planet
lda frameCnt ; 3
and #$07 ; 2 scroll every 8th frame
bne .noScroll ; 2<>
lda surfaceScroll ; 3
cmp #MAX_SCROLL ; 2 scrolled up completely?
beq .noScroll ; 2<> yes, skip
inc surfaceScroll ; 5 no, scroll up
.noScroll:
lda yPosArk ; 3
cmp #KERNEL_HEIGHT-1 ; 2 Ark at top of screen?
bne .skipBonus ; 2<> no, continue current section
lda status ; 3
and #$cf ; 2 disable meteors
bit gameFlags ; 3 meteor game?
bpl .normalGame ; 2<> no, skip
sta status ; 3 yes, meteor stage
inc level ; 5
jsr NextLevel ; 6
jmp .contSection ; 3
.normalGame:
eor #ON_PLANET ; 2 toggle section type
sta status ; 3
bit status ; 3 in space?
bvc .contSection ; 2<> yes, with meteors
ora #NO_METEORS ; 2 no, stop meteors
sta status ; 3
.contSection:
lda #ARK_HEIGHT*2 ; 2
sta arkAppearCnt ; 3
bit status ; 3 now on planet?
bvs .skipBonus ; 2<> yes, no bonus
lda numBeasties ; 3
cmp #2 ; 2 all beasties captured?
bcc .skipNextLevel ; 2<> no, skip
inc level ; 5 yes, goto next level
lda #0 ; 2 reset number of captured beasties
sta numBeasties ; 3
tay ; 2 Y is always 0!
ldx #$10 ; 2 +1000 points bonus
jsr AddScore ; 6
jsr NextLevel ; 6
.skipNextLevel:
jsr InitLevel ; 6
.skipBonus:
lda arkAppearCnt ; 3 Ark appearing?
beq .inSpace1 ; 2<> no,
bmi .inSpace1 ; 2<> no,
lsr ; 2
cmp #ARK_HEIGHT ; 2 Ark completely on screen?
bcs .arkComplete ; 2<> yes, move down
tay ; 2
ldx ArkAppearTab,y ; 4 copy one more Ark pattern line...
lda ArkPatTab,x ; 4 ...into the RAM buffer
sta arkPatLst,x ; 4
IF OPTIMIZE
bcc .contAppear ; 3
FILL_NOP 1
ELSE
jmp .contAppear ; 3
ENDIF
.arkComplete:
dec yPosArk ; 5
bit status ; 3 on planet
bvc .inSpace0 ; 2<> no, skip
lda frameCnt ; 3 yes, scroll planet surface...
and #$07 ; 2 ...every 8th frame
bne .inSpace0 ; 2<>
lda surfaceScroll ; 3
beq .inSpace0 ; 2<>
dec surfaceScroll ; 5
.inSpace0:
lda yPosArk ; 3
cmp #104 ; 2
bne .contAppear ; 2<>
lda #$80 ; 2 stop moving down Ark
sta arkAppearCnt ; 3
lda #0 ; 2
sta channel0Sound ; 3 disable all sounds in channel 0
bit status ; 3
bvc .inSpace1 ; 2<>
lda #SCREEN_WIDTH/2-4; 2
sta xPosShuttle ; 3
lda #86 ; 2
sta yPosShuttle ; 3
bne .inSpace1 ; 3
.contAppear:
inc arkAppearCnt ; 5
.inSpace1:
lda explosionCnt ; 3 shuttle exploding?
beq .noExplosion ; 2<> no, skip
and #$f8 ; 2 yes, animate explosions
clc ; 2
adc #<Explosion0 ; 2
tay ; 2
dec explosionCnt ; 5 explosion finished
bne .setShuttlePtr ; 2<>+1 no, continue
lda #SCREEN_WIDTH/2-4; 2 yes, position shuttle inside Ark
sta xPosShuttle ; 3
lda #86 ; 2
sta yPosShuttle ; 3
rol status ; 5 disable shuttle mode
clc ; 2
ror status ; 5
lda numBeasties ; 3 any beasties captured?
beq .setShuttlePtr ; 2<>+1 no, skip
jsr ReleaseBeastie ; 6 yes, release one and...
dec numBeasties ; 5 ...decrease number
.noExplosion:
ldy #<Shuttle0 ; 2 animate shuttle
lda frameCnt ; 3
and #$02 ; 2
beq .setShuttlePtr ; 2<>+1
ldy #<Shuttle1 ; 2
.setShuttlePtr:
sty shuttlePtr ; 3
lda arkAppearCnt ; 3 Ark moving down?
bpl .skipNew ; 2<> yes, skip new meteor
lda meteorDir ; 3 meteor on screen
bne .skipNew ; 2<> yes, skip
jsr NewMeteor ; 6 no, create new meteor
.skipNew:
;*** move meteor ***
ldy meteorDir ; 3 meteor displayed?
beq .endMoveMeteor ; 2<> no ,skip moving
;calculate current meteor speed:
ldx speedHi ; 3 slow down meteor
lda meteorPosLo ; 3
clc ; 2
adc speedLo ; 3
sta meteorPosLo ; 3
bcc .skipOverflow ; 2<>
inx ; 2
.skipOverflow:
stx tempVar ; 3 current result speed in pixel
;decrese meteor speed:
lda speedLo ; 3
cmp #128 ; 2 minimum speed >= 128? (= 1/2 pixel/frame)
; (not adjusted for PAL!)
; JTZ: The code doesn't perfectly limit the minimum meteor speed to
; 128 (NTSC:128-24, PAL: 128-32), therefore sometimes in the lower
; levels the meteors can be *slower* than in the previous one.
; This also causes some speed differences in the PAL conversion. ;
;
bcs .decSpeed ; 2<> yes, decrease
lda speedHi ; 3
beq .endDecSpeed ; 2<>
.decSpeed:
lda speedLo ; 3 reduce the meteor speed
sec ; 2
IF OPTIMIZE
sbc SpeedDecTab-1,y ; 4 horizontal meteors slow down much faster than vertical ones
ELSE
sbc SpeedDecTab,y ; 4 horizontal meteors slow down much faster than vertical ones
ENDIF
sta speedLo ; 3
bcs .endDecSpeed ; 2<>
dec speedHi ; 5
.endDecSpeed:
;move the meteor:
ldx #0 ; 2 "not wavering" value
bit waveringFlag ; 3 meteor wavering
bpl .notWavering0 ; 2<> no, skip
lda waveringCnt ; 3
and #$07 ; 2
tax ; 2
lda WaveringTab,x ; 4
tax ; 2
inc waveringCnt ; 5 continue wavering
.notWavering0:
cpy #METEOR_LEFT ; 2 check direction of meteor
beq .meteorLeft ; 2<>
cpy #METEOR_RIGHT ; 2
beq .meteorRight ; 2<>
cpy #METEOR_UP ; 2
beq .meteorUp ; 2<>
lda yPosMeteor ; 3 meteor moves down
clc ; 2
adc tempVar ; 3
bne .contMeteorDown ; 3
.meteorUp:
lda yPosMeteor ; 3 meteor moves up
sec ; 2
sbc tempVar ; 3
.contMeteorDown:
sta yPosMeteor ; 3
txa ; 2 add wavering value
clc ; 2
adc xPosMeteor ; 3
sta xPosMeteor ; 3
bne .endMoveMeteor ; 3
.meteorLeft:
lda xPosMeteor ; 3 meteor moves left
clc ; 2
adc tempVar ; 3
bne .contMeteorLeft ; 3
.meteorRight:
lda xPosMeteor ; 3 meteor move right
sec ; 2
sbc tempVar ; 3
.contMeteorLeft:
sta xPosMeteor ; 3
txa ; 2 add wavering value
clc ; 2
adc yPosMeteor ; 3
sta yPosMeteor ; 3
.endMoveMeteor:
ldy #0 ; 2 disable beam (might be enabled again later)
sty yPosBeam ; 3
bit status ; 3
bpl .skipBeam ; 2<>
lda explosionCnt ; 3 shuttle exploding?
bne .skipFire ; 2<> yes, skip fire button
jsr GetPlayer ; 6 get number of current player
lda INPT4-$30,x ; 4 fire button pressed?
sta fireButton ; 3
bpl .beamFire ; 2<> yes, check for beaming
.skipFire:
lda channel1Sound ; 3 disable beam sound
and ~#BEAM_SOUND ; 2
sta channel1Sound ; 3
lda beamStatus ; 3 currently beaming?
bpl .skipBeam ; 2<> no, skip
lda #DROP_BEASTIE ; 2 yes, drop beastie
sta beamStatus ; 3
bne .skipBeam ; 3
.beamFire:
lda yPosShuttle ; 3
cmp #78 ; 2 shuttle in Ark?
bcs .skipBeam ; 2<> yes, skip beaming
lda channel1Sound ; 3
and ~#SHUTTLE_SOUND ; 2 disable shuttle sound...
ora #BEAM_SOUND ; 2 ...and enable beam sound
sta channel1Sound ; 3
lda frameCnt ; 3
lsr ; 2
bcc .endJoyStick ; 2<>
lda xPosShuttle ; 3 calc position of tractor beam
clc ; 2
adc #$03 ; 2
sta xPosBeam ; 3
ldy yPosShuttle ; 3
sty yPosBeam ; 3 (re)enable tractor beam
cpy #$00 ; 2
bne .endJoyStick ; 2<>
.skipBeam:
lda arkAppearCnt ; 3 Ark at final position?
bmi .checkJoystick ; 2<> yes, check joystick
.endJoyStick:
jmp .skipRight ; 3
.checkJoystick:
bit gameStatus ; 3 game running
bpl .endJoyStick ; 2<> no, skip joystick direction checks
jsr GetPlayer ; 6
lda SWCHA ; 4
cpx #1 ; 2 player 1 ?
beq .player1 ; 2<> yes, skip shifts
lsr ; 2
lsr ; 2
lsr ; 2
lsr ; 2
.player1:
and #%1111 ; 2
bit status ; 3
bmi .skipShot ; 2<>+1
bvs .onPlanet ; 2<>
ldy fuel ; 3 no fuel?
beq .endJoyStick ; 2<> yes, skip fire
.onPlanet:
cmp joyDir ; 3 new dir = old dir?
beq .endJoyStick ; 2<> yes, don't shot
sta joyDir ; 3
cmp #LEFT_DIR ; 2
beq .leftDir ; 2<>+1
cmp #RIGHT_DIR ; 2
beq .rightDir ; 2<>+1
cmp #UP_DIR ; 2
beq .upDir ; 2<>+1
cmp #DOWN_DIR ; 2
beq .downDir ; 2<>+1
.endJoyStickJMP:
bne .endJoyStick ; 3+1
.upDir:
lda #96 ; 2
sta yPosShot ; 3
lda #SHOT_UP ; 2
.contDown:
sta shotDir ; 3
lda #SCREEN_WIDTH/2 ; 2
sta xPosShotBeam ; 3
bne .endDir ; 3
.downDir:
bit status ; 3 shooting down on planet not allowed
bvc .inSpace4 ; 2<>
rol status ; 5 enable shuttle mode instead
sec ; 2
ror status ; 5
bne .skipShot ; 3
.inSpace4:
lda #92 ; 2
sta yPosShot ; 3
lda #SHOT_DOWN ; 2
bne .contDown ; 3
.leftDir:
lda #SCREEN_WIDTH/2-8; 2
sta xPosShotBeam ; 3
lda #SHOT_LEFT ; 2
.contRight:
sta shotDir ; 3
lda #96 ; 2
sta yPosShot ; 3
.endDir:
lda channel0Sound ; 3 enable shot sound
ora #SHOT_SOUND ; 2
sta channel0Sound ; 3
bit status ; 3 on planet
bvs .onPlanet1 ; 2<> yes, skip
dec fuel ; 5 no, reduce energy
.onPlanet1:
lda #6 ; 2 set shot sound time
sta channel0Time ; 3
bne .endJoyStickJMP ; 3+1
.rightDir:
lda #SCREEN_WIDTH/2+8; 2
sta xPosShotBeam ; 3
lda #SHOT_RIGHT ; 2
bne .contRight ; 3
.skipShot:
ldx explosionCnt ; 3 shuttle exploding?
beq .noExplosion1 ; 2<> no, skip
lda #NO_DIR ; 2 disable joystick
.noExplosion1:
sta tempVar ; 3 remember joystick value
tay ; 2
lda channel1Sound ; 3
and ~#SHUTTLE_SOUND ; 2 disable shuttle sound
cpy #NO_DIR ; 2 joystick moved?
beq .notMoved ; 2<> no, keep shuttle sound disabled
ora #SHUTTLE_SOUND ; 2 enable shuttle sound again
.notMoved:
sta channel1Sound ; 3
lsr tempVar ; 5 joystick moved up?
bcs .endUpDir ; 2<> no
lda yPosShuttleLo ; 3 move shuttle up
adc shutteSpeedLo ; 3
sta yPosShuttleLo ; 3
bcc .endUpDir ; 2<>
lda yPosShuttle ; 3
cmp #77 ; 2 shuttle right below Ark?
bcc .lowShuttle ; 2<> no, lower
lda xPosShuttle ; 3
cmp #SCREEN_WIDTH/2-5; 2 shuttle horizontally at middle of Ark?
bcc .endUpDir ; 2<> no, to far left
cmp #SCREEN_WIDTH/2-2; 2
bcs .endUpDir ; 2<> no, to far right
.lowShuttle:
inc yPosShuttle ; 5
lda yPosShuttle ; 3
cmp #86 ; 2 shuttle inside Ark?
bne .endUpDir ; 2<> no, skip
;shuttle returns into Ark:
lda status ; 3 disable shuttle mode
and ~#SHUTTLE_MODE ; 2
sta status ; 3
lda channel1Sound ; 3
and ~#SHUTTLE_SOUND ; 2 disable shuttle sound
sta channel1Sound ; 3
lda numBeasties ; 3
cmp #2 ; 2 both beasties captured?
bcc .endUpDir ; 2<> no, skip
;both beasties rescued at once before alert gives full fuel:
lda alertCnt ; 3 alert started?
bne .endUpDir ; 2<> yes, don't start Ark
lda meteorDir ; 3 meteor on screen?
bne .endUpDir ; 2<> yes, don't start Ark
lda oldNumBeasties ; 3 no beasties captured before?
bne .skipMaxFuel ; 2<> no, skip max. fuel
lda #MAX_FUEL-1 ; 2 gain maximum fuel
sta fuel ; 3
.skipMaxFuel:
jsr StartArkUp ; 6
.endUpDir:
lsr tempVar ; 5 joystick moved down?
bcs .skipDown ; 2<> no, skip down
lda yPosShuttleLo ; 3
adc shutteSpeedLo ; 3
sta yPosShuttleLo ; 3
bcc .skipDown ; 2<>
lda yPosShuttle ; 3
cmp #22 ; 2 shuttle at lowest position?
bcc .skipDown ; 2<> yes, skip
dec yPosShuttle ; 5 no, move further down
.skipDown:
lda yPosShuttle ; 3
cmp #78 ; 2 shuttle moving into Ark?
bcs .skipRight ; 2<> yes, skip left and right
lsr tempVar ; 5 joystick moved left?
bcs .skipLeft ; 2<> no, skip left
lda xPosShuttle ; 3
cmp #1 ; 2 shuttle at left border?
beq .skipLeft ; 2<> yes, skip move left
;*** move the shuttle: ***
;the lower registers are used to allow fine speed adjustments
;they are always added, even if the player moves left or down!
lda xPosShuttleLo ; 3
adc shutteSpeedLo ; 3
sta xPosShuttleLo ; 3
bcc .skipLeft ; 2<>
dec xPosShuttle ; 5
.skipLeft:
lsr tempVar ; 5 joystick moved right?
bcs .skipRight ; 2<> no, skip right
lda xPosShuttle ; 3
cmp #SCREEN_WIDTH-10 ; 2 shuttle at right border?
beq .skipRight ; 2<> yes, skip right
lda xPosShuttleLo ; 3
adc shutteSpeedLo ; 3
sta xPosShuttleLo ; 3
bcc .skipRight ; 2<>
inc xPosShuttle ; 5
.skipRight:
;process shot:
ldx #MS_SIZE1 ; 2 small missile size
lda shotDir ; 3
beq .contShot ; 2<>+1
cmp #SHOT_LEFT ; 2
beq .shotLeft ; 2<>+1
cmp #SHOT_RIGHT ; 2
beq .shotRight ; 2<>+1
ldx #MS_SIZE1 ; 2
cmp #SHOT_UP ; 2
beq .shotUp ; 2<>+1
cmp #SHOT_DOWN ; 2
bne .contShot ; 2<>
lda yPosShot ; 3 move shot down
sec ; 2
sbc #8 ; 2
sta yPosShot ; 3 shot at bottom of screen?
bmi .disableShot ; 2<> yes, disable
bpl .contShot ; 3
.shotUp:
lda yPosShot ; 3 move shot up
clc ; 2
adc #8 ; 2
sta yPosShot ; 3
cmp #192 ; 2 shot at top of screen?
bcs .disableShot ; 2<> yes, disable
bcc .contShot ; 3
.shotLeft:
ldx #MS_SIZE8 ; 2 wide missile size
lda xPosShotBeam ; 3 move shot left
sec ; 2
sbc #8 ; 2
sta xPosShotBeam ; 3 shot at left border?
bpl .contShot ; 2<> yes, disable
.disableShot:
ldx #0 ; 2
stx shotDir ; 3
stx yPosShot ; 3
beq .contShot ; 3
.shotRight:
ldx #MS_SIZE8 ; 2 wide missile
lda xPosShotBeam ; 3 move shot right
clc ; 2
adc #8 ; 2
sta xPosShotBeam ; 3
cmp #SCREEN_WIDTH ; 2 shot at right border?
bcs .disableShot ; 2<> yes, disable
.contShot:
stx NUSIZ1 ; 3
;animate center line of Ark:
lda arkHitCnt ; 3 Ark hit?
bne .skipAnimate ; 2<> yes, skip center animation
lda arkPatLst+9 ; 3
beq .skipAnimate ; 2<>
lda frameCnt ; 3 progress animation every 8th frame
and #$07 ; 2
tay ; 2
lda AnimateTab,y ; 4
sta arkPatLst+9 ; 3
.skipAnimate:
lda arkHitCnt ; 3
bne .noBottomCenter ; 2<>
ldx #$fe ; 2 small Ark pattern
lda alertCnt ; 3
beq .noAlert ; 2<>
and #$10 ; 2 Ark changes width during alert
beq .smallArk ; 2<>
bne .wideArk ; 3
.noAlert:
bit SWCHB ; 4 P0 difficutly
bvc .smallArk ; 2<> B(eginner), skip
.wideArk:
ldx #$ff ; 2 A(dvanced), make center of Ark wider
.smallArk:
lda arkPatLst+7 ; 3 top center
beq .noTopCenter ; 2<>
stx arkPatLst+7 ; 3
.noTopCenter:
lda arkPatLst+11 ; 3 bottom center
beq .noBottomCenter ; 2<>
stx arkPatLst+11 ; 3
.noBottomCenter:
lda status ; 3
and #GAME_OVER ; 2 game over?
beq .skipStartEscape ; 2<> no, skip
lda arkHitCnt ; 3
cmp #1 ; 2 Ark disappeared completely?
bne .skipStartEscape ; 2<> no, skip
;game over, show escape shuttle:
lda #>Shuttle0 ; 2 draw shuttle instead of meteor
sta meteorPtr+1 ; 3
lda #SCREEN_WIDTH/2 ; 2 position shuttle at center of screen
sta xPosMeteor ; 3
lda #80 ; 2
sta yPosMeteor ; 3
lda #GREEN2+6 ; 2
sta P1SpaceCol ; 3
lda #$30 ; 2 escape shuttle starts moving left
sta speedLo ; 3
lda #$fb ; 2
sta speedHi ; 3
lda #SHUTTLE_SOUND ; 2 enable shuttle sound
sta channel1Sound ; 3
lda #$ff ; 2 set game over flag
sta gameOver ; 3
.skipStartEscape:
lda gameOver ; 3 game over
beq .endMoveShuttle ; 2<> no, skip
;move the escape shuttle:
lda speedLo ; 3 change shuttle speed
clc ; 2
adc #$30 ; 2
sta speedLo ; 3
bcc .skipIncHi ; 2<>
inc speedHi ; 5
.skipIncHi:
lda speedHi ; 3 shuttle moving right?
bmi .skipEscapeDown ; 2<> no, skip
dec yPosMeteor ; 5 yes, move shuttle down
.skipEscapeDown:
lda meteorPosLo ; 3
clc ; 2
adc speedLo ; 3
sta meteorPosLo ; 3
lda xPosMeteor ; 3
adc speedHi ; 3
cmp #SCREEN_WIDTH-4 ; 2 shuttle at right border?
bcs .disableShuttle ; 2<> yes, disable escape shuttle
sta xPosMeteor ; 3 no, continue moving
IF OPTIMIZE
bcc .endMoveShuttle ; 3
FILL_NOP 1
ELSE
jmp .endMoveShuttle ; 3
ENDIF
.disableShuttle:
lda #0 ; 2 disable game over flag
sta gameOver ; 3
sta yPosMeteor ; 3
sta channel1Sound ; 3 disable all sounds in channel 1
lda #RUNNING|START_MODE; 2 game status = running in start mode
sta gameStatus ; 3
lda status ; 3 status = no shuttle and in space
and ~#[SHUTTLE_MODE|ON_PLANET]; 2
sta status ; 3
lda scoreLow ; 3 show game number - 1 at last score digit
and #$f0 ; 2
sta tempVar ; 3
ldx gameNum ; 3
dex ; 2
txa ; 2
ora tempVar ; 3
sta scoreLow ; 3
.endMoveShuttle:
lda gameOver ; 3 game over?
beq .setMeteorPtr ; 2<> no, show meteors
ldy #<Shuttle0 ; 2 yes, show escape shuttle
lda frameCnt ; 3 animate escape shuttle every 2nd frame
and #$02 ; 2
bne .show0 ; 2<>
ldy #<Shuttle1 ; 2
.show0:
sty meteorPtr ; 3
IF OPTIMIZE
bne .endUpdateGame ; 3
FILL_NOP 1
ELSE
jmp .endUpdateGame ; 3
ENDIF
.setMeteorPtr:
lda frameCnt ; 3 animate meteor
and #<Meteor3 ; 2 every 8th frame
sta meteorPtr ; 3
lda #>Meteor0 ; 2
sta meteorPtr+1 ; 3
.endUpdateGame:
;flicker the stars:
ldy starColumn ; 3 move flickering stars
lda frameCnt ; 3
and #$07 ; 2
bne .skipFlicker ; 2<>
iny ; 2
cpy #NUM_STARCOLUMS ; 2
bne .skipFlicker ; 2<>
ldy #0 ; 2 reset position
.skipFlicker:
sty starColumn ; 3
lda xPosStarsTab,y ; 4 set star columns position
sta xPosStars ; 3
;show game number, copyright or scores:
ldx #$00 ; 2
lda gameStatus ; 3
and #SHOW_GAMENUM ; 2 show game number?
beq .setScorePtr ; 2<> no, display score
txa ; 2 show leading blanks
jsr SetDigitLowPtr ; 6
lda gameNum ; 3
jsr SetDigitLowPtr ; 6
lda #$aa ; 2 show trailing blanks (10,10)
jsr SetDigitLowPtr ; 6
IF OPTIMIZE
bne .endSetDigitPtr ; 3
FILL_NOP 1
ELSE
jmp .endSetDigitPtr ; 3
ENDIF
.setScorePtr:
bit gameStatus ; 3 game running?
bpl .setCopyRightPtr ; 2<> no, show copyright
lda scoreHi ; 3 yes, show score
jsr SetDigitLowPtr ; 6
lda scoreMid ; 3
jsr SetDigitLowPtr ; 6
lda scoreLow ; 3
jsr SetDigitLowPtr ; 6
.endSetDigitPtr:
; replace leading zeros with blanks:
ldx #0 ; 2
.loopBlanks:
lda digitPtr,x ; 4 digit != 0?
bne .endDigitPtr ; 2<> yes, exit
lda #<Blank ; 2
sta digitPtr,x ; 4
inx ; 2
inx ; 2
cpx #NUM_DIGITS*2-2 ; 2
bne .loopBlanks ; 2<>
beq .endDigitPtr ; 3
.setCopyRightPtr:
lda #<Copyright5 ; 2
ldx #NUM_DIGITS*2-2 ; 2
.loopCopyright:
sta digitPtr,x ; 4
sec ; 2
sbc #DIGIT_HEIGHT ; 2 -10
dex ; 2
dex ; 2
bpl .loopCopyright ; 2<>
.endDigitPtr:
jmp StartKernel ; 3
OverScan SUBROUTINE
;*** end of display kernel, start of overscan area ***
IF NTSC
lda #35 ; 2
ELSE
lda #59 ; 2
ENDIF
sta TIM64T ; 4
pla ; 4 save Ark/meteor collisions...
sta tempVar ; 3 ...in tempVar
;check beam/beastie collisions:
lda beamStatus ; 3 currently beaming a beastie?
bmi .skipCheckColl ; 2<> yes, skip check collisions
ldx #0 ; 2
bit CXP0FB-$30 ; 3 beastie 0 hit by beam?
bvs .startBeam ; 2<> yes, start beaming
inx ; 2
bit CXP1FB-$30 ; 3 beastie 1 hit by beam?
bvc .skipStartBeam ; 2<> yes, skip start beaming
.startBeam:
sta beastie0Status,x ; 4 = %0xxxxxxx
lda #BEAM_BEASTIE ; 2
sta beamStatus ; 3
lda #6 ; 2
sta yBeamedBeastie ; 3 start beaming up beastie
lda xPosShuttle ; 3
clc ; 2
adc #3 ; 2
sta xPosShotBeam ; 3
.skipStartBeam:
bit CXM1P-$30 ; 3 meteor hit by shot?
bvs .meteorHit ; 2<> yes, disable meteor
.skipCheckColl:
lda tempVar ; 3 Ark / meteor collision?
bpl .noCollision ; 2<> no, skip
;Ark was hit by meteor:
lda #0 ; 2
sta arkAppearCnt ; 3
sta yPosShuttle ; 3
sta channel0Sound ; 3 disable all sounds
sta channel1Sound ; 3
sta yBeamedBeastie ; 3 clear beastie beam position
sta beamStatus ; 3
lda status ; 3 disable shuttle mode
and ~#SHUTTLE_MODE ; 2
sta status ; 3
lda #$c0 ; 2
sta arkHitCnt ; 3
bit gameStatus ; 3 game running?
bpl .disableMeteor ; 2<>+1 no,
lda fuel ; 3 yes, decrease fuel
sec ; 2
sbc #10 ; 2
sta fuel ; 3
bcs .disableMeteor ; 2<>+1
lda #0 ; 2 out of energy
sta fuel ; 3
lda status ; 3 game is over
ora #GAME_OVER ; 2
sta status ; 3
bne .disableMeteor ; 3+1
.noCollision:
lda status ; 3 shuttle mode and...
and defenseStatus ; 3 ...defense fireing?
bpl .dropBeastie ; 2<>+1 no, skip
lda yPosShuttle ; 3 yes, check for defense hit at shuttle
cmp yPosDefense ; 3
bcs .dropBeastie ; 2<>+1 no, shuttle to high
adc #5 ; 2
cmp yPosDefense ; 3
bcc .dropBeastie ; 2<>+1 no, shuttle to low
lda explosionCnt ; 3 shuttle already exploding?
bne .dropBeastie ; 2<>+1 no, skip
lda #23 ; 2 yes, start shuttle explosion
sta explosionCnt ; 3
bne .dropBeastie ; 3+1
.meteorHit:
ldy #0 ; 2 disable meteor
sty yPosShot ; 3
sty shotDir ; 3
sty channel1Time ; 3
ldx #0 ; 2
lda #$10 ; 2 +10 points
bit waveringFlag ; 3 wavering meteor?
bpl .notWavering1 ; 2<> no, skip
lda #$30 ; 2 +30 points
.notWavering1:
jsr AddScore ; 6
lda fuel ; 3 get fuel back
cmp #MAX_FUEL-1 ; 2
beq .skipRefuel ; 2<>
inc fuel ; 5
.skipRefuel:
bit gameFlags ; 3 meteor game?
bpl .skipRefuel2 ; 2<> no, skip
lda fuel ; 3 yes, get fuel back twice
cmp #MAX_FUEL-1 ; 2
beq .skipRefuel2 ; 2<>
inc fuel ; 5
.skipRefuel2:
lda channel0Sound ; 3 disable shot sound
and ~#SHOT_SOUND ; 2
sta channel0Sound ; 3
.disableMeteor:
lda #0 ; 2 disable meteor
sta meteorDir ; 3
sta yPosMeteor ; 3
.dropBeastie:
;drop beamed beastie:
bit beamStatus ; 3 beastie dropped?
bvc .skipDrop ; 2<> no, skip
lda yBeamedBeastie ; 3 beastie falls down
sec ; 2
sbc #4 ; 2
sta yBeamedBeastie ; 3
cmp #6 ; 2 beam position back at bottom?
bcs .endBeaming ; 2<> no, skip
jsr ReleaseBeastie ; 6 yes, release beastie
lda #0 ; 2
sta beamStatus ; 3
sta yBeamedBeastie ; 3 disable beam position
.skipDrop:
bit beamStatus ; 3 beaming a beastie?
bpl .endBeaming ; 2<> no, skip
lda frameCnt ; 3 yes, beam up the beastie
lsr ; 2
bcc .endBeaming ; 2<>
inc yBeamedBeastie ; 5
lda yBeamedBeastie ; 3
cmp yPosShuttle ; 3 beastie beam at shuttle?
bne .endBeaming ; 2<> no, skip
lda #0 ; 2 yes, captured!
sta beamStatus ; 3
sta yBeamedBeastie ; 3
lda #15 ; 2 set captured sound time
sta channel0Time ; 3
lda channel0Sound ; 3 enable beastie captured sound
ora #CAPTURED_SOUND ; 2
sta channel0Sound ; 3
inc numBeasties ; 5 increase number of captured beasties
.endBeaming:
lda arkHitCnt ; 3
IF OPTIMIZE
beq .contNormal ; 3
FILL_NOP 3
ELSE
bne .disappearArk ; 2<>
jmp .contNormal ; 3
ENDIF
.disappearArk:
cmp #151 ; 2 Ark completely disappeared?
bcs .disappeared ; 2<> yes, skip
lsr ; 2
lsr ; 2
lsr ; 2
tay ; 2
ldx ArkAppearTab,y ; 4
lda #0 ; 2 clear one whole line of Ark
sta arkPatLst,x ; 4
.disappeared:
;randomly flicker remaining Ark lines:
lda frameCnt ; 3
and #$03 ; 2 every 4th frame
bne .skipClear ; 2<>
ldx #ARK_HEIGHT-1 ; 2
ldy random ; 3
.loopClear:
lda arkPatLst,x ; 4 line already cleared?
beq .skipLine ; 2<> yes, skip line
lda StartKernel,y ; 4 use random ROM-code to make Ark disappear
bne .notZero ; 2<>
tya ; 2
.notZero:
and ArkPatTab,x ; 4 clear random bits in all lines
sta arkPatLst,x ; 4
iny ; 2 next byte of code
.skipLine:
dex ; 2 next line
bpl .loopClear ; 2<>
.skipClear:
dec arkHitCnt ; 5 Ark completely disappeared?
bne .contNormal ; 2<> no, continue
lda status ; 3
and #GAME_OVER ; 2 game over?
beq .contGame ; 2<> no, continue
lda status ; 3 yes, new status: in space and shuttle mode disabled
and ~#[SHUTTLE_MODE|ON_PLANET]; 2
sta status ; 3
lda #0 ; 2 disable all sounds of channel 0
sta channel0Sound ; 3
sta frameCnt+1 ; 3 reset screen saver counter
beq .contGameOver ; 3
.contGame:
bit gameStatus ; 3 game running?
bpl .skipRepeatLevel ; 2<> no, toggle section in demo mode
bit status ; 3
bvc .inSpace ; 2<>
lda #0 ; 2 reset number of captured beasties
sta numBeasties ; 3
lda levelMeteors ; 3 init number of normal meteors
sta numMeteors ; 3
bne .contArkHit ; 3
.inSpace:
lda numMeteors ; 3 add two more normal meteors to current wave
clc ; 2 (the missed plus a penalty)
adc #2 ; 2
sta numMeteors ; 3
.contArkHit:
lda status ; 3 new status: in space and shuttle mode disabled
and ~#[SHUTTLE_MODE|ON_PLANET]; 2
sta status ; 3
jsr InitLevel2 ; 6 init without reseting number of meteors
IF OPTIMIZE
bne .skipToggle ; 3
FILL_NOP 1
ELSE
jmp .skipToggle ; 3
ENDIF
.skipRepeatLevel:
lda status ; 3 toggle section (planet <-> space)
eor #ON_PLANET ; 2
sta status ; 3
jsr InitLevel ; 6 (re)init the current level
.skipToggle:
jsr StartArkDown ; 6
.contGameOver:
lda status ; 3 disable GAME_OVER flag
and ~#GAME_OVER ; 2
sta status ; 3
.contNormal:
bit status ; 3 on planet?
bvs .doPlanet ; 2<> yes, process planet
jmp .skipDefense ; 3
.doPlanet:
lda frameCnt ; 3
and #$07 ; 2
bne .endActivate ; 2<>+1
inc planetTime ; 5
lda planetTime ; 3
cmp alertTime ; 3 alert time reached?
bne .skipAlertStart ; 2<> no, skip
lda status ; 3 yes, enable alert
and #ARK_UPDOWN ; 2 Ark already moving up?
bne .skipAlertStart ; 2<> yes, skip start countdown
lda #$ff ; 2 no, start alert countdown
sta alertCnt ; 3
.skipAlertStart:
lda defenseStatus ; 3
and #ACTIVE ; 2
bne .endActivate ; 2<>+1
lda level ; 3
cmp #1 ; 2 first level?
bcc .endActivate ; 2<>+1 yes, no defense system
lda #16 ; 2 no, activate defense system...
cmp planetTime ; 3 ...after 8*16 frames (~2 sec.)
bne .endActivate ; 2<>
lda #ACTIVE|DIR_UP ; 2 activate and move up
sta defenseStatus ; 3
.endActivate:
;set beastie pattern pointer:
lda beastieId ; 3
asl ; 2
tay ; 2
lda frameCnt ; 3
and #$04 ; 2 change beastie pattern every 4th frame
bne .firstAnimation ; 2<>
iny ; 2
.firstAnimation:
tya ; 2
jsr Mult10 ; 6
clc ; 2
adc #<Beastie0 ; 2
sta beastiePtr ; 3
lda frameCnt ; 3 move only one beastie / frame
and #$01 ; 2
tax ; 2
lda beastie0Status,x ; 4 beastie runs left?
bpl .runLeft ; 2<> yes, move left
lda xPosBeastie0,x ; 4
beq .negDir ; 2<>
dec xPosBeastie0,x ; 6
;beastie "AI" (they stay away from enabled tractor beam):
lda fireButton ; 3 beam enabled?
bmi .noBeam ; 2<> no, skip
lda xPosBeam ; 3 yes, let beastie stay away from beam
clc ; 2
adc #$03 ; 2
cmp xPosBeastie0,x ; 4 beastie close to beam?
beq .negDir ; 2<> yes, run away!
bne .noBeam ; 3 no, change direction randomly
.runLeft:
lda xPosBeastie0,x ; 4
cmp #SCREEN_WIDTH-5 ; 2
beq .negDir ; 2<>
inc xPosBeastie0,x ; 6
;beastie "AI" repeated:
lda INPT4-$30 ; 3 beam enabled?
bmi .noBeam ; 2<> no, skip
lda xPosBeastie0,x ; 4 yes, let beastie stay away from beam
clc ; 2
adc #$07 ; 2
cmp xPosBeam ; 3 beastie close to beam?
beq .negDir ; 2<> yes, run away!
.noBeam:
lda random ; 3 no, change direction randomly
and #$07 ; 2 change direction?
bne .skipNegDir ; 2<> no skip
.negDir:
lda beastie0Status,x ; 4 reverse beastie direction
eor #BEASTIE_LEFT ; 2
sta beastie0Status,x ; 4
.skipNegDir:
lda defenseStatus ; 3
and #ACTIVE ; 2 defense system activated?
beq .skipDefense ; 2<> no, skip
lda frameCnt ; 3
and #$03 ; 2
bne .endMove ; 2<>
bit defenseStatus ; 3 defense moves up or down
bvc .moveDown ; 2<> down
inc yPosDefense ; 5
inc yPosDefense ; 5
lda yPosDefense ; 3
cmp #80 ; 2 defense at top position
bne .endMove ; 2<> no, skip
.reverseDir:
lda defenseStatus ; 3 reverse defense system direction
eor #DIR_UP ; 2
sta defenseStatus ; 3
jmp .endMove ; 3
.moveDown:
dec yPosDefense ; 5
dec yPosDefense ; 5
lda yPosDefense ; 3
cmp #22 ; 2 defense at bottom position?
beq .reverseDir ; 2<> yes, reverse direction
.endMove:
inc defenseDelay ; 5
rol defenseStatus ; 5
ldx yPosDefense ; 3
cpx #22 ; 2 defense system at bottom position?
bcc .atBottom ; 2<> yes, reset delay (don't fire)
lda defenseDelay ; 3
cmp defenseFreq ; 3 next defense fire?
clc ; 2 flag disable fire
bne .noFire ; 2<> no, disable
sec ; 2 flag enable fire
.atBottom:
lda #0 ; 2 reset fire delay
sta defenseDelay ; 3
.noFire:
ror defenseStatus ; 5 set defense fire status
.skipDefense:
;*** play sounds of channel 0: ***
ldy #$00 ; 2
bit gameStatus ; 3 game running?
bmi .useChannel1 ; 2<> yes, make some noise
jmp .setAudio1 ; 3 no, silence
.alertSound:
ldy #$08 ; 2 enable alert sound
and #$10 ; 2
bne .soundOn ; 2<>
ldy #$00 ; 2 disable alert sound
.soundOn:
ldx #$18 ; 2
dec alertCnt ; 5 alert over?
bne .contAlert ; 2<> no, skip
lda status ; 3 yes, start bombardment
and ~#NO_METEORS ; 2
sta status ; 3
lda #1 ; 2 only one meteor
sta numMeteors ; 3
.contAlert:
lda #1 ; 2
bne .setAudio0JMP ; 3
.useChannel1:
lda arkHitCnt ; 3 Ark hit?
bne .arkHitSound ; 2<>+1 yes, play hit sound
lda alertCnt ; 3 alert enabled?
bne .alertSound ; 2<> yes, play alert sound
lda channel0Sound ; 3
asl ; 2 Ark sound enabled?
bcs .arkSound ; 2<>+1 yes, play Ark sound
asl ; 2 shot enabled?
bcs .shotSound ; 2<>+1 yes, play shot sound
asl ; 2 captured sound enabed
bcs .capturedSound ; 2<> yes, play captured sound
lda explosionCnt ; 3 shuttle explosion?
bne .explosionSound ; 2<> yes, play explosion sound
bit defenseStatus ; 3 defense fireing?
bpl .setAudio0JMP ; 2<> no, no sound
;defense fire sound:
ldy #$0e ; 2
lda #$08 ; 2
ldx #$01 ; 2
.setAudio0JMP:
jmp .setAudio0 ; 3
.explosionSound:
tax ; 2
lsr ; 2
tay ; 2
lda #$0c ; 2
bne .setAudio0JMP ; 3
.capturedSound:
ldy channel0Time ; 3
ldx channel0Time ; 3
dec channel0Time ; 5
bpl .contCaptSound ; 2<>
lda channel0Sound ; 3 disable beastie captured sound
and ~#CAPTURED_SOUND ; 2
sta channel0Sound ; 3
.contCaptSound:
lda #$04 ; 2
bne .setAudio0JMP ; 3+1
.arkHitSound:
lsr ; 2
lsr ; 2
lsr ; 2
lsr ; 2
tay ; 2
ldx #$03 ; 2
lda frameCnt ; 3
lsr ; 2
bcc .highFreq ; 2<>
ldx #$08 ; 2 lower frequency
.highFreq:
lda #$01 ; 2
bne .setAudio0JMP ; 3+1
.shotSound:
lda #8 ; 2 set frequency of shot
sec ; 2
sbc channel0Time ; 3
tax ; 2
ldy channel0Time ; 3
lda ShotVolTab,y ; 4 set volume of shot
tay ; 2
lda #$01 ; 2
dec channel0Time ; 5
bpl .contShotSound ; 2<>
lda channel0Sound ; 3 disable shot sound
and ~#SHOT_SOUND ; 2
sta channel0Sound ; 3
.contShotSound:
jmp .setAudio0 ; 3
ShotVolTab:
.byte $00, $04, $08, $0c, $08, $04, $02
.arkSound:
lda arkAppearCnt ; 3 Ark appearing?
beq .skipAppearSound ; 2<> no, skip
lsr ; 2
cmp #ARK_HEIGHT ; 2
bcs .skipAppearSound ; 2<>
lsr ; 2 increase volume
tay ; 2
ldx #$10 ; 2 change frequency every 2nd frame
lda frameCnt ; 3
lsr ; 2
bcc .skipLowFreq ; 2<>
ldx #$18 ; 2
.skipLowFreq:
lda #$04 ; 2
bne .setAudio0 ; 3
.skipAppearSound:
ldx #$08 ; 2 change frequency every 4th frame
lda frameCnt ; 3
lsr ; 2
lsr ; 2
bcc .skipMedFreq ; 2<>
ldx #$10 ; 2
.skipMedFreq:
lda #$0c ; 2
ldy #$08 ; 2
IF OPTIMIZE
FILL_NOP 2
ELSE
bne .setAudio0 ; 3 really weird and superfluos code! :-)
ENDIF
.setAudio0:
sty AUDV0 ; 3
stx AUDF0 ; 3
sta AUDC0 ; 3
;*** play sounds of channel 1: ***
ldy #$00 ; 2
lda channel1Sound ; 3
asl ; 2
bcs .meteorSound ; 2<>
asl ; 2
bcs .shuttleSound ; 2<>
asl ; 2
IF OPTIMIZE
bcc .setAudio1 ; 2<>
FILL_NOP 3
ELSE
bcs .beamSound ; 2<>
jmp .setAudio1 ; 3
ENDIF
.beamSound:
ldy #$08 ; 2
ldx #$10 ; 2
bit beamStatus ; 3 beaming a beastie
bpl .lowBeamFreq ; 2<> no, skip
ldx #$04 ; 2 yes, higher frequency
.lowBeamFreq:
lda frameCnt ; 3
and #$01 ; 2
bne .skipLowerFreq ; 2<>
inx ; 2
.skipLowerFreq:
lda #$04 ; 2
bne .setAudio1 ; 3
.shuttleSound:
ldy #$00 ; 2 silence
lda frameCnt ; 3
and #$02 ; 2
beq .noShuttleSound ; 2<>
ldy #$08 ; 2
.noShuttleSound:
ldx #$08 ; 2
lda #$04 ; 2
bne .setAudio1 ; 3
.meteorSound:
lda #16 ; 2 increase meteor sound volume
sec ; 2
sbc channel1Time ; 3
tay ; 2
ldx numMeteors ; 3 link frequency to number of remaining meteors
dec channel1Time ; 5
bpl .contMeteor ; 2<>
lda channel1Sound ; 3 disable general meteor sound
and ~#METEOR_SOUND ; 2
sta channel1Sound ; 3
.contMeteor:
lda #$08 ; 2 enable wavering sound
bit waveringFlag ; 3
bpl .notWavering2 ; 2<>
lda frameCnt ; 3
and #$02 ; 2
bne .noSilence ; 2<>
ldy #$00 ; 2 disable wavering sound
.noSilence:
lda #$0c ; 2
.notWavering2:
cpx #$00 ; 2 any more meteors or...
bne .setAudio1 ; 2<> yes, skip
ldx numWaverings ; 3 ...any more wavering meteors?
IF OPTIMIZE
FILL_NOP 2
ELSE
cpx #0 ; 2 very weird!
ENDIF
bne .setAudio1 ; 2<> yes, skip
ldy channel1Time ; 3 no, ping at the end of wave
iny ; 2
ldx #$02 ; 2
lda #$0c ; 2
.setAudio1:
sty AUDV1 ; 3
stx AUDF1 ; 3
sta AUDC1 ; 3
;*** wait until end of overscan: ***
.waitTim:
bit TIMINT ; 4
bpl .waitTim ; 2<>
jmp MainLoop ; 3
TimeStarTrick SUBROUTINE
;*** waits some time and loads HMM0 value ***
nop ; 2
nop ; 2
lda #$60 ; 2
rts ; 6
InitGame SUBROUTINE
;*** clears a lot of variables ***
lda #$01 ; 2
sta status ; 3
ldx #$80 ; 2
lda #$00 ; 2
.loopClear:
sta $00,x ; 4
inx ; 2
cpx #<frameCnt ; 2
bne .loopClear ; 2<>
rts ; 6
GetPlayer SUBROUTINE
;*** returns the current player ***
ldx #0 ; 2 player 0
bit gameFlags ; 3 2-player game?
bvc .player0 ; 2<> no, skip
lda status ; 3 planet or space?
asl ; 2
eor SWCHB ; 4
bpl .player0 ; 2<>
inx ; 2 player 1
.player0:
rts ; 6
InitLevel SUBROUTINE
;*** initialize the current level ***
lda levelMeteors ; 3
sta numMeteors ; 3
InitLevel2:
lda #DIR_UP ; 2 defense system starts with moving up
sta defenseStatus ; 3
sta beastie0Status ; 3 enable first beastie, moves right
lda #BEASTIE_LEFT|BEASTIE_FREE; 2
sta beastie1Status ; 3 enable second beastie, moves left
lda level ; 3 set number of wavering meteors
lsr ; 2
sta numWaverings ; 3
.limitId:
cmp #NUM_BEASTIES ; 2 limit beastie id to 0..6
bcc .setId ; 2<>
sbc #NUM_BEASTIES ; 2
bcs .limitId ; 3
.setId:
sta beastieId ; 3
lda #0 ; 2
sta xPosBeastie0 ; 3
sta planetTime ; 3
sta defenseDelay ; 3
sta yPosDefense ; 3
sta yPosShuttle ; 3
sta channel1Sound ; 3
ldx numBeasties ; 3 no breastie already captured?
stx oldNumBeasties ; 3
beq .bothBeasties ; 2<> yes, show both
sta beastie1Status ; 3 no, disable second beastie
.bothBeasties:
lda #SCREEN_WIDTH-5 ; 2
sta xPosBeastie1 ; 3
rts ; 6
ReleaseBeastie SUBROUTINE
ldx #0 ; 2
bit beastie0Status ; 3 beastie 0 captured?
bvc .release0 ; 2<> yes, release
inx ; 2 release beastie 1
.release0:
lda beastie0Status,x ; 4
ora #BEASTIE_FREE ; 2 reset captured flag
sta beastie0Status,x ; 4
lda xPosShotBeam ; 3 release at old beam position
sta xPosBeastie0,x ; 4
rts ; 6
NewMeteor SUBROUTINE
;*** randomly create new meteors ***
ldy #NO_METEOR ; 2
lda status ; 3
and #NO_METEORS ; 2 meteors disabled?
IF OPTIMIZE
bne .skipNew ; 2<> yes, skip new
FILL_NOP 3
ELSE
beq .makeNew ; 2<> no, create new meteor
jmp .skipNew ; 3 yes, skip new
ENDIF
.makeNew:
lda random ; 3 randomly decide for wavering meteors
and #%00001100 ; 2 wavering? (~25% chance)
bne .noWavering ; 2<> no, skip
lda numWaverings ; 3 any more wavering meteors?
beq .noWavering ; 2<> no, skip
.createWavering:
dec numWaverings ; 5
lda #2 ; 2
sta waveringCnt ; 3
lda #RED+6 ; 2
sta P1SpaceCol ; 3
lda waveringFlag ; 3
ora #$80 ; 2 wavering meteor
bne .setWavering ; 3
.noWavering:
lda numMeteors ; 3 any more meteors?
bne .createNormal ; 2<> yes, create normal meteor
lda numWaverings ; 3 any more wavering meteors?
bne .createWavering ; 2<> yes, create wavering meteor
ldy #0 ; 2 no, disable meteors
sty yPosMeteor ; 3
sty meteorDir ; 3
IF OPTIMIZE
beq StartArkUp ; 3
FILL_NOP 1
ELSE
jmp StartArkUp ; 3
ENDIF
.createNormal:
dec numMeteors ; 5
lda #BLUE+6 ; 2
sta P1SpaceCol ; 3
lda waveringFlag ; 3
and #$7f ; 2 normal meteor
.setWavering:
sta waveringFlag ; 3
lda random ; 3 random new meteor direction
and #$03 ; 2
tay ; 2
bit status ; 3
bvc .inSpace ; 2<>
cpy #METEOR_DOWN-1 ; 2 meteor from down?
bne .inSpace ; 2<>
dey ; 2 change to up
.inSpace:
lda YPosMeteorTab,y ; 4 set meteor position
sta yPosMeteor ; 3
lda XPosMeteorTab,y ; 4
sta xPosMeteor ; 3
lda initSpeedHi ; 3 inititialize meteor speed
sta speedHi ; 3
lda initSpeedLo ; 3
sta speedLo ; 3
rol channel1Sound ; 5 enable meteor sound
sec ; 2
ror channel1Sound ; 5
lda #16 ; 2 set meteor sound time
sta channel1Time ; 3
iny ; 2
.skipNew:
sty meteorDir ; 3
rts ; 6
StartArkUp SUBROUTINE
;*** Ark starts moving up ***
lda status ; 3 set status: Ark is moving up
ora #ARK_UPDOWN ; 2
sta status ; 3
lda channel0Sound ; 3 enable Ark sound
ora #ARK_SOUND ; 2
sta channel0Sound ; 3
;gain 10 fuel units for each new captured beastie:
lda numBeasties ; 3 subtract old number of captured
sec ; 2 beasties from current
sbc oldNumBeasties ; 3
tax ; 2
lda #0 ; 2
sta arkAppearCnt ; 3
sta yPosShuttle ; 3 disable shuttle
sta defenseStatus ; 3 disable defense
sta yPosDefense ; 3
.loopRefuel:
dex ; 2
bmi .refuel ; 2<>
clc ; 2
adc #10 ; 2
bne .loopRefuel ; 3
.refuel:
clc ; 2
adc fuel ; 3
cmp #MAX_FUEL ; 2 limit fuel to 48 units
bcc .skipMaxFuel ; 2<>
lda #MAX_FUEL-1 ; 2
.skipMaxFuel:
sta fuel ; 3
rts ; 6
AddScore SUBROUTINE
;*** adds A/X (lo/hi) to score of player in Y ***
; JTZ: Actually Y is allways zero, but they might originally have
; had planed a non cooperative 2 player game too.
sed ; 2
clc ; 2
adc scoreLow,y ; 4
sta scoreLow,y ; 5
txa ; 2
IF OPTIMIZE
FILL_NOP 2
adc #$00 ; 2
ELSE
bcc .skipMidC ; 2<> very weird!
adc #$00 ; 2
ENDIF
.skipMidC:
clc ; 2
adc scoreMid,y ; 4
sta scoreMid,y ; 5
lda #$00 ; 2
IF OPTIMIZE
FILL_NOP 4
ELSE
bcc .skipHiC ; 2<> very weird!
adc #$00 ; 2
ENDIF
.skipHiC:
adc scoreHi,y ; 4
sta scoreHi,y ; 5
cld ; 2
rts ; 6
StartArkDown SUBROUTINE
;*** Ark starts moving down ***
lda #KERNEL_HEIGHT-1 ; 2 start Ark at top of screen
sta yPosArk ; 3
lda #64 ; 2
sta xPosBeam ; 3
lda #MAX_SCROLL ; 2 make surface invisible (scrolls up)
sta surfaceScroll ; 3
lda #1 ; 2 start appearance of Ark
sta arkAppearCnt ; 3
lda channel0Sound ; 3 enable Ark sound
ora #ARK_SOUND ; 2
sta channel0Sound ; 3
rts ; 6
SetDigitLowPtr SUBROUTINE
;*** sets low pointers for the 48 pixel routine ***
sta tempVar2 ; 3
lsr ; 2
lsr ; 2
lsr ; 2
lsr ; 2
jsr Mult10 ; 6
sta digitPtr,x ; 4
inx ; 2
inx ; 2
lda tempVar2 ; 3
and #$0f ; 2
jsr Mult10 ; 6
sta digitPtr,x ; 4
inx ; 2
inx ; 2
rts ; 6
Mult10 SUBROUTINE
;*** multiply A with 10 ***
asl ; 2
sta tempVar ; 3
asl ; 2
asl ; 2
clc ; 2
adc tempVar ; 3
rts ; 6
InitGameVars SUBROUTINE
;*** init game speed variables ***
;The most important game speed parameters are adjusted here (and at some other
; places in code), so that NTSC and PAL games have about the same speed
;BTW: Simulating the speed through several levels showed some *significant*
; differences in the necessary reaction times in some lower levels. That's
; because not all values could be perfectly adjusted!
lda gameNum ; 3
cmp #ADVANCED_GAME ; 2 advanced game?
;set initial meteor speed:
; normal : 624 (PAL: 624*6/5 = 748)
; advanced: 752 (PAL: 752*6/5 =~902)
lda #2 ; 2
sta initSpeedHi ; 3
IF NTSC
lda #112 ; 2 normal speed
ELSE
lda #236 ; 2
ENDIF
bcc .normalGame1 ; 2<> skip, if normal game
IF NTSC
lda #240 ; 2 fast NTSC speed (~level 9)
ELSE
inc initSpeedHi ; 5 fast PAL speed (~level 9)
lda #134 ; 2
ENDIF
.normalGame1:
sta initSpeedLo ; 3
;set initial shuttle speed:
; normal : 128 (PAL: 128*6/5 =~152)
; advanced: 224 (PAL: 232)
IF NTSC
lda #128 ; 2
ELSE
lda #152 ; 2
ENDIF
bcc .normalGame2 ; 2<> skip, if normal game
IF NTSC
lda #224 ; 2 high speed (~level 13)
ELSE
lda #232 ; 2 high speed (~level 11)
ENDIF
.normalGame2:
sta shutteSpeedLo ; 3
;set initial defense fireing frequency:
; normal : 112 (PAL: 112*5/6 =~96)
; advanded: 16 (PAL too!)
IF NTSC
lda #112 ; 2 about every 2 seconds
ELSE
lda #96 ; 2
ENDIF
bcc .normalGame3 ; 2<> skip, if normal game
lda #16 ; 2 about every 0.3 seconds (not PAL adjusted)
.normalGame3:
sta defenseFreq ; 3
;set initial time until alert starts:
; normal : 112 (PAL: 112*5/6 =~93)
; advanced: 64 (PAL: 64*5/6 =~53)
IF NTSC
lda #112 ; 2 ~15 seconds
ELSE
lda #93 ; 2
ENDIF
bcc .normalGame4 ; 2<> skip, if normal game
IF NTSC
lda #64 ; 2 ~8.5 seconds (~level 13)
ELSE
lda #53 ; 2 PAL (~level 11)
ENDIF
.normalGame4:
sta alertTime ; 3
;set initial meteors / wave:
lda #8 ; 2
bcc .normalGame5 ; 2<> skip, if normal game
lda #20 ; 2
.normalGame5:
sta levelMeteors ; 3
;set shuttle color:
lda shuttleColorTab ; 4
sta shuttleColor ; 3
rts ; 6
NextLevel SUBROUTINE
;*** increase the game speeds ***
lda level ; 3
and #$03 ; 2 time to change color and shuttle speed?
bne .skipSpeedUp ; 2<> no, skip
;change shuttle color:
lda level ; 3 every 4th planet
lsr ; 2
lsr ; 2
and #$03 ; 2
tay ; 2
lda shuttleColorTab,y; 4
sta shuttleColor ; 3
;increase speed of rescue shuttle:
lda shutteSpeedLo ; 3 every 4th planet (= 2nd planet)
clc ; 2
adc #8 ; 2 not PAL adjusted (8*50/60 = ~6.7)
bcs .skipSpeedUp ; 2<>
sta shutteSpeedLo ; 3
.skipSpeedUp:
;increase defense fireing frequency:
lda defenseFreq ; 3 every planet
sec ; 2
sbc #8 ; 2 not PAL adjusted (8*50/60 = ~6.7)
beq .skipInc ; 2<>
sta defenseFreq ; 3
.skipInc:
;increase number of meteors for next level:
lda levelMeteors ; 3
cmp #30 ; 2 maximum number (30)?
beq .skipIncNum ; 2<> no, skip increase
inc levelMeteors ; 5 yes, one more meteorid
.skipIncNum:
;increase speed of meteors for next level:
lda initSpeedLo ; 3
clc ; 2
IF NTSC
adc #16 ; 2
ELSE
adc #19 ; 2 PAL adjusted value
ENDIF
sta initSpeedLo ; 3
bcc .skipIncHi ; 2<>
inc initSpeedHi ; 5
.skipIncHi:
;decrease time until bombardment alert:
lda alertTime ; 3
IF NTSC
cmp #48 ; 2 0.8 seconds minimum alert time
beq .skipDecTime ; 2<>
ELSE
cmp #39 ; 2 PAL adjusted value
bcc .skipDecTime ; 2<>
ENDIF
sec ; 2
sbc #4 ; 2 not PAL adjusted (4*50/60 = ~3.3)
sta alertTime ; 3
.skipDecTime:
rts ; 6
;===============================================================================
; R O M - T A B L E S
;===============================================================================
shuttleColorTab: ; rescue shuttle colors
.byte GREEN2+6
.byte BLUE+6
.byte RED+6
.byte BROWN+6
WaveringTab:
.byte -1, -1, -1, -1
.byte 1, 1, 1, 1
IF OPTIMIZE
FILL_NOP 1
IF NTSC
FILL_NOP 5
ENDIF
ELSE
.byte -1 ;unused
IF NTSC
.byte -1, -1, -1, -1, -1 ;unused
ENDIF
ENDIF
AnimateTab:
.byte %11111100 ; |XXXXXX |
.byte %11111000 ; |XXXXX |
.byte %11110100 ; |XXXX X |
.byte %11101100 ; |XXX XX |
.byte %11011100 ; |XX XXX |
.byte %10111100 ; |X XXXX |
.byte %01111100 ; | XXXXX |
.byte %11111100 ; |XXXXXX |
Shuttle0:
.byte %00000000 ; | |
.byte %00011000 ; | XX |
.byte %11111111 ; |XXXXXXXX|
.byte %01110000 ; | XXX |
.byte %11111111 ; |XXXXXXXX|
.byte %00011000 ; | XX |
.byte %00000000 ; | |
.byte %00000000 ; | |
Shuttle1:
.byte %00000000 ; | |
.byte %00011000 ; | XX |
.byte %11111111 ; |XXXXXXXX|
.byte %00001110 ; | XXX |
.byte %11111111 ; |XXXXXXXX|
.byte %00011000 ; | XX |
.byte %00000000 ; | |
.byte %00000000 ; | |
Explosion0:
.byte %00000000 ; | |
.byte %00100000 ; | X |
.byte %00000100 ; | X |
.byte %10000001 ; |X X|
.byte %00000000 ; | |
.byte %00100000 ; | X |
.byte %00001000 ; | X |
.byte %10000001 ; |X X|
Explosion1:
.byte %01000010 ; | X X |
.byte %00000000 ; | |
.byte %00010000 ; | X |
.byte %01001010 ; | X X X |
.byte %00010000 ; | X |
.byte %00001000 ; | X |
.byte %01000010 ; | X X |
.byte %00100100 ; | X X |
Explosion2:
.byte %00011000 ; | XX |
.byte %10100101 ; |X X X X|
.byte %00000000 ; | |
.byte %10100101 ; |X X X X|
.byte %00000000 ; | |
.byte %10100101 ; |X X X X|
.byte %00011000 ; | XX |
.byte %00000000 ; | |
align 256
Meteor0:
.byte %00000000 ; | |
.byte %00111100 ; | XXXX |
.byte %01111110 ; | XXXXXX |
.byte %01101111 ; | XX XXXX|
.byte %01011111 ; | X XXXXX|
.byte %00111010 ; | XXX X |
.byte %00011110 ; | XXXX |
.byte %00001100 ; | XX |
Meteor1:
.byte %00000000 ; | |
.byte %00011100 ; | XXX |
.byte %00101110 ; | X XXX |
.byte %01110110 ; | XXX XX |
.byte %11111110 ; |XXXXXXX |
.byte %11011110 ; |XX XXXX |
.byte %01111100 ; | XXXXX |
.byte %00011000 ; | XX |
Meteor2:
.byte %00110000 ; | XX |
.byte %01111000 ; | XXXX |
.byte %01011100 ; | X XXX |
.byte %11111010 ; |XXXXX X |
.byte %11110110 ; |XXXX XX |
.byte %01111110 ; | XXXXXX |
.byte %00111100 ; | XXXX |
.byte %00000000 ; | |
Meteor3:
.byte %00011000 ; | XX |
.byte %00111110 ; | XXXXX |
.byte %01111000 ; | XXXX |
.byte %01111111 ; | XXXXXXX|
.byte %01101110 ; | XX XXX |
.byte %01110100 ; | XXX X |
.byte %00111000 ; | XXX |
.byte %00000000 ; | |
.byte %00010001 ; | X X| $1e20 unused
.byte %00100001 ; | X X|
.byte %00100010 ; | X X |
.byte %00110011 ; | XX XX|
LumTab:
;luminance of planet surface lines:
.byte $0c
.byte $0c
.byte $0c
.byte $0c
.byte $0c
.byte $0a
.byte $08
.byte $06
.byte $04
.byte $02
ArkAppearTab:
;row order in which the Ark appears on top of screen:
.byte 9, 8,10, 7,11, 6,12, 5,13, 4,14, 3,15, 2,16, 1,17, 0,18
YPosMeteorTab:
;y-starting position of a meteor:
.byte 91, 91,192, 0
XPosMeteorTab:
;x-starting position of a meteor:
.byte 0,152, 76, 76
PlanetColTab:
;colors of the planet surfaces:
.byte GREEN-8
.byte BROWN-8
.byte MAGENTA-8
.byte BLUE-8
.byte OCHRE-8
.byte CYAN-8
.byte GREEN
.byte ORANGE_GREEN-4
.byte OCHRE-8
.byte RED_BROWN
.byte BLUE
.byte MAGENTA2-4
.byte ORANGE-8
.byte MAGENTA-8
.byte BLUE2-8
.byte BLACK
xPosStarsTab:
.byte 13, 28, 43, 58, 73, 88,103,118,133
.byte 148,133,118,103, 88, 73, 58, 43, 28
NuSiz0Tab:
.byte MS_SIZE1|ONE_COPY
.byte MS_SIZE1|TWO_COPIES_WIDE
.byte MS_SIZE1|THREE_COPIES
.byte MS_SIZE2|TWO_COPIES_WIDE
.byte MS_SIZE2|THREE_COPIES
.byte MS_SIZE4|THREE_COPIES
.byte MS_SIZE8|TWO_COPIES_WIDE
.byte MS_SIZE8|THREE_COPIES
;two patterns for each beastie:
Beastie0:
.byte %00000000 ; | |
.byte %00111000 ; | XXX |
.byte %00101000 ; | X X |
.byte %00101000 ; | X X |
.byte %00111000 ; | XXX |
.byte %00001000 ; | X |
.byte %00111000 ; | XXX |
.byte %00100000 ; | X |
.byte %00111000 ; | XXX |
.byte %00000000 ; | |
.byte %00000000 ; | |
.byte %00000000 ; | |
.byte %00000000 ; | |
.byte %00111000 ; | XXX |
.byte %00101000 ; | X X |
.byte %00111000 ; | XXX |
.byte %00101000 ; | X X |
.byte %00111000 ; | XXX |
.byte %00111000 ; | XXX |
.byte %00000000 ; | |
.byte %00000000 ; | |
.byte %00000000 ; | |
.byte %00000000 ; | |
.byte %00111000 ; | XXX |
.byte %00010000 ; | X |
.byte %00010000 ; | X |
.byte %00111000 ; | XXX |
.byte %00101000 ; | X X |
.byte %00001000 ; | X |
.byte %00001000 ; | X |
.byte %00000000 ; | |
.byte %00000000 ; | |
.byte %00000000 ; | |
.byte %00000000 ; | |
.byte %00111000 ; | XXX |
.byte %00010000 ; | X |
.byte %00111000 ; | XXX |
.byte %00101000 ; | X X |
.byte %00100000 ; | X |
.byte %00100000 ; | X |
.byte %00000000 ; | |
.byte %00000000 ; | |
.byte %00000000 ; | |
.byte %00000000 ; | |
.byte %00000000 ; | |
.byte %00001000 ; | X |
.byte %01001100 ; | X XX |
.byte %00111000 ; | XXX |
.byte %01000100 ; | X X |
.byte %00000000 ; | |
.byte %00000000 ; | |
.byte %00000000 ; | |
.byte %00000000 ; | |
.byte %00000000 ; | |
.byte %00000000 ; | |
.byte %00001000 ; | X |
.byte %00001100 ; | XX |
.byte %01111000 ; | XXXX |
.byte %00101000 ; | X X |
.byte %00000000 ; | |
.byte %00000000 ; | |
.byte %00001000 ; | X |
.byte %00010100 ; | X X |
.byte %00011000 ; | XX |
.byte %00011100 ; | XXX |
.byte %00010000 ; | X |
.byte %00010000 ; | X |
.byte %00010000 ; | X |
.byte %00100000 ; | X |
.byte %00000000 ; | |
.byte %00000000 ; | |
.byte %00000000 ; | |
.byte %00001000 ; | X |
.byte %00010100 ; | X X |
.byte %00011000 ; | XX |
.byte %00011100 ; | XXX |
.byte %00010000 ; | X |
.byte %00001000 ; | X |
.byte %00000000 ; | |
.byte %00000000 ; | |
.byte %00100100 ; | X X |
.byte %00100100 ; | X X |
.byte %00011000 ; | XX |
.byte %00000000 ; | |
.byte %00000000 ; | |
.byte %00000000 ; | |
.byte %00000000 ; | |
.byte %00000000 ; | |
.byte %00000000 ; | |
.byte %00000000 ; | |
.byte %00000000 ; | |
.byte %00011000 ; | XX |
.byte %00100100 ; | X X |
.byte %00000000 ; | |
.byte %00000000 ; | |
.byte %00000000 ; | |
.byte %00000000 ; | |
.byte %00000000 ; | |
.byte %00000000 ; | |
.byte %00000000 ; | |
.byte %00000000 ; | |
.byte %00000000 ; | |
.byte %00011000 ; | XX |
.byte %00111100 ; | XXXX |
.byte %00011000 ; | XX |
.byte %00111100 ; | XXXX |
.byte %00111100 ; | XXXX |
.byte %00001100 ; | XX |
.byte %00000100 ; | X |
.byte %00000000 ; | |
.byte %00000000 ; | |
.byte %00000000 ; | |
.byte %00011000 ; | XX |
.byte %00111100 ; | XXXX |
.byte %00100100 ; | X X |
.byte %00111100 ; | XXXX |
.byte %00111100 ; | XXXX |
.byte %00110000 ; | XX |
.byte %00100000 ; | X |
.byte %00000000 ; | |
.byte %00000000 ; | |
.byte %00000000 ; | |
.byte %00000000 ; | |
.byte %00011000 ; | XX |
.byte %00110000 ; | XX |
.byte %00100000 ; | X |
.byte %00110000 ; | XX |
.byte %00011000 ; | XX |
.byte %00000000 ; | |
.byte %00000000 ; | |
.byte %00000000 ; | |
.byte %00000000 ; | |
.byte %00000000 ; | |
.byte %00011000 ; | XX |
.byte %00111100 ; | XXXX |
.byte %00100000 ; | X |
.byte %00111100 ; | XXXX |
.byte %00011000 ; | XX |
.byte %00000000 ; | |
.byte %00000000 ; | |
align 256, 0
Zero:
.byte %00000000 ; | |
.byte %00111110 ; | XXXXX |
.byte %00100110 ; | X XX |
.byte %00100110 ; | X XX |
.byte %00100110 ; | X XX |
.byte %00100110 ; | X XX |
.byte %00100110 ; | X XX |
.byte %00100010 ; | X X |
.byte %00100010 ; | X X |
.byte %00111110 ; | XXXXX |
One:
.byte %00000000 ; | |
.byte %00011000 ; | XX |
.byte %00011000 ; | XX |
.byte %00011000 ; | XX |
.byte %00011000 ; | XX |
.byte %00011000 ; | XX |
.byte %00001000 ; | X |
.byte %00001000 ; | X |
.byte %00001000 ; | X |
.byte %00001000 ; | X |
Two:
.byte %00000000 ; | |
.byte %01111110 ; | XXXXXX |
.byte %01100000 ; | XX |
.byte %01100000 ; | XX |
.byte %01100000 ; | XX |
.byte %01111110 ; | XXXXXX |
.byte %00000010 ; | X |
.byte %00000010 ; | X |
.byte %01000010 ; | X X |
.byte %01111110 ; | XXXXXX |
Three:
.byte %00000000 ; | |
.byte %01111110 ; | XXXXXX |
.byte %01000110 ; | X XX |
.byte %01000110 ; | X XX |
.byte %00000110 ; | XX |
.byte %00000110 ; | XX |
.byte %00111100 ; | XXXX |
.byte %00000100 ; | X |
.byte %01000100 ; | X X |
.byte %01111100 ; | XXXXX |
Four:
.byte %00000000 ; | |
.byte %00001100 ; | XX |
.byte %00001100 ; | XX |
.byte %00001100 ; | XX |
.byte %01111110 ; | XXXXXX |
.byte %01000100 ; | X X |
.byte %01000100 ; | X X |
.byte %01000100 ; | X X |
.byte %01000100 ; | X X |
.byte %01000100 ; | X X |
Five:
.byte %00000000 ; | |
.byte %01111110 ; | XXXXXX |
.byte %01000110 ; | X XX |
.byte %01000110 ; | X XX |
.byte %00000110 ; | XX |
.byte %00000110 ; | XX |
.byte %01111110 ; | XXXXXX |
.byte %01000000 ; | X |
.byte %01000000 ; | X |
.byte %01111110 ; | XXXXXX |
Six:
.byte %00000000 ; | |
.byte %01111110 ; | XXXXXX |
.byte %01000110 ; | X XX |
.byte %01000110 ; | X XX |
.byte %01000110 ; | X XX |
.byte %01111110 ; | XXXXXX |
.byte %01000000 ; | X |
.byte %01000000 ; | X |
.byte %01000010 ; | X X |
.byte %01111110 ; | XXXXXX |
Seven:
.byte %00000000 ; | |
.byte %00000110 ; | XX |
.byte %00000110 ; | XX |
.byte %00000110 ; | XX |
.byte %00000110 ; | XX |
.byte %00000110 ; | XX |
.byte %00000110 ; | XX |
.byte %00000110 ; | XX |
.byte %00000010 ; | X |
.byte %00111110 ; | XXXXX |
Eight:
.byte %00000000 ; | |
.byte %01111110 ; | XXXXXX |
.byte %01000110 ; | X XX |
.byte %01000110 ; | X XX |
.byte %01000110 ; | X XX |
.byte %01100110 ; | XX XX |
.byte %00111100 ; | XXXX |
.byte %00100100 ; | X X |
.byte %00100100 ; | X X |
.byte %00111100 ; | XXXX |
Nine:
.byte %00000000 ; | |
.byte %00000110 ; | XX |
.byte %00000110 ; | XX |
.byte %00000110 ; | XX |
.byte %00000110 ; | XX |
.byte %00111110 ; | XXXXX |
.byte %00100010 ; | X X |
.byte %00100010 ; | X X |
.byte %00100010 ; | X X |
.byte %00111110 ; | XXXXX |
Blank:
.byte %00000000 ; | |
.byte %00000000 ; | |
.byte %00000000 ; | |
.byte %00000000 ; | |
.byte %00000000 ; | |
.byte %00000000 ; | |
.byte %00000000 ; | |
.byte %00000000 ; | |
.byte %00000000 ; | |
.byte %00000000 ; | |
Copyright0:
.byte %00000000 ; | |
.byte %00000000 ; | |
.byte %10001011 ; |X X XX|
.byte %10001010 ; |X X X |
.byte %10001010 ; |X X X |
.byte %10111011 ; |X XXX XX|
.byte %10101010 ; |X X X X |
.byte %10111011 ; |X XXX XX|
.byte %00000000 ; | |
.byte %00000000 ; | |
Copyright1:
.byte %00000000 ; | |
.byte %00000000 ; | |
.byte %10111000 ; |X XXX |
.byte %10100001 ; |X X X|
.byte %10100001 ; |X X X|
.byte %10111001 ; |X XXX X|
.byte %10001001 ; |X X X|
.byte %10111000 ; |X XXX |
.byte %00000000 ; | |
.byte %00000000 ; | |
Copyright2:
.byte %01110000 ; | XXX |
.byte %10001000 ; |X X |
.byte %10001000 ; |X X |
.byte %00100100 ; | X X |
.byte %01000100 ; | X X |
.byte %01000100 ; | X X |
.byte %00100100 ; | X X |
.byte %10001000 ; |X X |
.byte %10001000 ; |X X |
.byte %01110000 ; | XXX |
Copyright3:
.byte %00000000 ; | |
.byte %10101010 ; |X X X X |
.byte %10101010 ; |X X X X |
.byte %10101010 ; |X X X X |
.byte %10101010 ; |X X X X |
.byte %10101010 ; |X X X X |
.byte %10101010 ; |X X X X |
.byte %10101010 ; |X X X X |
.byte %10010100 ; |X X X |
.byte %00000000 ; | |
Copyright4:
.byte %00000000 ; | |
.byte %10010011 ; |X X XX|
.byte %10010100 ; |X X X |
.byte %10010100 ; |X X X |
.byte %11110101 ; |XXXX X X|
.byte %10010100 ; |X X X |
.byte %10010100 ; |X X X |
.byte %10010100 ; |X X X |
.byte %01100011 ; | XX XX|
.byte %00000000 ; | |
Copyright5:
.byte %00000000 ; | |
.byte %00100110 ; | X XX |
.byte %10101001 ; |X X X X|
.byte %10101000 ; |X X X |
.byte %10101000 ; |X X X |
.byte %00101000 ; | X X |
.byte %00101000 ; | X X |
.byte %10101001 ; |X X X X|
.byte %00100110 ; | X XX |
.byte %00000000 ; | |
FuelBarTab:
.byte %00000000 ; | |
.byte %10000000 ; |X |
.byte %11000000 ; |XX |
.byte %11100000 ; |XXX |
.byte %11110000 ; |XXXX |
.byte %11111000 ; |XXXXX |
.byte %11111100 ; |XXXXXX |
.byte %11111110 ; |XXXXXXX |
.byte %11111111 ; |XXXXXXXX|
ArkPatTab:
.byte %10000000 ; |X |
.byte %11000000 ; |XX |
.byte %11100000 ; |XXX |
.byte %11110000 ; |XXXX |
.byte %11111000 ; |XXXXX |
.byte %11111100 ; |XXXXXX |
.byte %11111110 ; |XXXXXXX |
.byte %11111111 ; |XXXXXXXX|
.byte %11111110 ; |XXXXXXX |
.byte %11111100 ; |XXXXXX |
.byte %11111110 ; |XXXXXXX |
.byte %11111111 ; |XXXXXXXX|
.byte %11111110 ; |XXXXXXX |
.byte %11111100 ; |XXXXXX |
.byte %11111000 ; |XXXXX |
.byte %11110000 ; |XXXX |
.byte %11100000 ; |XXX |
.byte %11000000 ; |XX |
.byte %10000000 ; |X |
ArkColTab:
.byte RED+6
.byte RED+4
.byte RED+2
.byte RED
.byte RED_BROWN+2
.byte RED_BROWN
.byte RED_BROWN-2
.byte RED+6
.byte RED_BROWN-2
.byte WHITE
.byte RED_BROWN-2
.byte RED+6
.byte RED_BROWN-2
.byte RED_BROWN
.byte RED_BROWN+2
.byte RED
.byte RED+2
.byte RED+4
.byte RED+6
;pattern for the palnet surface:
PlanetPF0Tab:
.byte %00010000 ; | X |
.byte %00010000 ; | X |
.byte %00010000 ; | X |
.byte %00010000 ; | X |
.byte %00010000 ; | X |
.byte %00010000 ; | X |
.byte %00110000 ; | XX |
.byte %11111111 ; |XXXXXXXX|
.byte %11111111 ; |XXXXXXXX|
.byte %11111111 ; |XXXXXXXX|
PlanetPF1Tab:
.byte %00000000 ; | |
.byte %00000000 ; | |
.byte %00000000 ; | |
.byte %00000000 ; | |
.byte %00000000 ; | |
.byte %00110000 ; | XX |
.byte %01111001 ; | XXXX X|
.byte %11111111 ; |XXXXXXXX|
.byte %11111111 ; |XXXXXXXX|
.byte %11111111 ; |XXXXXXXX|
PlanetPF2Tab:
.byte %00000000 ; | |
.byte %00000000 ; | |
.byte %00000000 ; | |
.byte %00000000 ; | |
.byte %10000000 ; |X |
.byte %11000000 ; |XX |
.byte %11110011 ; |XXXX XX|
.byte %11111111 ; |XXXXXXXX|
.byte %11111111 ; |XXXXXXXX|
.byte %11111111 ; |XXXXXXXX|
SpeedDecTab:
;meteor slowdown values, one for each direction:
IF OPTIMIZE
FILL_NOP 1
ELSE
.byte 0 ; unsued
ENDIF
IF NTSC
.byte 24, 24, 8, 8
ELSE
.byte 32, 32, 14, 14 ; PAL adjusted speed difference
ENDIF
ORG $1ffc
.word START, START