├── gfx ├── bird.png ├── crab.png ├── door.bin ├── fish.png ├── gogr.png ├── hero.png ├── note.bin ├── bear2.png ├── crawl.bin ├── loader.kla ├── shell.png ├── shore.kla ├── stars.gpx ├── stars.imap ├── credits.map ├── credits.scr ├── darkbear.png ├── desktop.ini ├── fish_icon.png ├── logo_bars.bin ├── logo_top.png ├── platform0.gpx ├── platform0.png ├── platform1.gpx ├── platform1.png ├── degree_icon.png ├── platform0.imap ├── platform1.imap ├── shoredark2.kla ├── digits_shadow.png ├── platform0.iscr ├── stars.iscr └── platform1.iscr ├── sfx ├── bear.ins ├── bear.snd ├── jump.ins ├── jump.snd ├── bonus.ins ├── bonus.snd ├── eating.ins ├── eating.snd ├── igloo.ins ├── igloo.snd ├── splash.ins ├── splash.snd ├── landing.ins └── landing.snd ├── .gitattributes ├── release ├── fb.gif ├── frostbite.prg └── MANUAL.txt ├── sid ├── Frostbite_C64.sid └── Frostbite_C64.sng ├── README.md └── src ├── sfx.asm ├── hero.asm ├── misc.asm ├── notes.asm ├── splash.asm ├── hud.asm ├── controls.asm ├── environment.asm ├── enemies.asm └── game.asm /gfx/bird.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tonysavon/Frostbite-C64/HEAD/gfx/bird.png -------------------------------------------------------------------------------- /gfx/crab.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tonysavon/Frostbite-C64/HEAD/gfx/crab.png -------------------------------------------------------------------------------- /gfx/door.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tonysavon/Frostbite-C64/HEAD/gfx/door.bin -------------------------------------------------------------------------------- /gfx/fish.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tonysavon/Frostbite-C64/HEAD/gfx/fish.png -------------------------------------------------------------------------------- /gfx/gogr.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tonysavon/Frostbite-C64/HEAD/gfx/gogr.png -------------------------------------------------------------------------------- /gfx/hero.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tonysavon/Frostbite-C64/HEAD/gfx/hero.png -------------------------------------------------------------------------------- /gfx/note.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tonysavon/Frostbite-C64/HEAD/gfx/note.bin -------------------------------------------------------------------------------- /sfx/bear.ins: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tonysavon/Frostbite-C64/HEAD/sfx/bear.ins -------------------------------------------------------------------------------- /sfx/bear.snd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tonysavon/Frostbite-C64/HEAD/sfx/bear.snd -------------------------------------------------------------------------------- /sfx/jump.ins: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tonysavon/Frostbite-C64/HEAD/sfx/jump.ins -------------------------------------------------------------------------------- /sfx/jump.snd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tonysavon/Frostbite-C64/HEAD/sfx/jump.snd -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /gfx/bear2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tonysavon/Frostbite-C64/HEAD/gfx/bear2.png -------------------------------------------------------------------------------- /gfx/crawl.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tonysavon/Frostbite-C64/HEAD/gfx/crawl.bin -------------------------------------------------------------------------------- /gfx/loader.kla: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tonysavon/Frostbite-C64/HEAD/gfx/loader.kla -------------------------------------------------------------------------------- /gfx/shell.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tonysavon/Frostbite-C64/HEAD/gfx/shell.png -------------------------------------------------------------------------------- /gfx/shore.kla: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tonysavon/Frostbite-C64/HEAD/gfx/shore.kla -------------------------------------------------------------------------------- /gfx/stars.gpx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tonysavon/Frostbite-C64/HEAD/gfx/stars.gpx -------------------------------------------------------------------------------- /gfx/stars.imap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tonysavon/Frostbite-C64/HEAD/gfx/stars.imap -------------------------------------------------------------------------------- /release/fb.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tonysavon/Frostbite-C64/HEAD/release/fb.gif -------------------------------------------------------------------------------- /sfx/bonus.ins: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tonysavon/Frostbite-C64/HEAD/sfx/bonus.ins -------------------------------------------------------------------------------- /sfx/bonus.snd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tonysavon/Frostbite-C64/HEAD/sfx/bonus.snd -------------------------------------------------------------------------------- /sfx/eating.ins: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tonysavon/Frostbite-C64/HEAD/sfx/eating.ins -------------------------------------------------------------------------------- /sfx/eating.snd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tonysavon/Frostbite-C64/HEAD/sfx/eating.snd -------------------------------------------------------------------------------- /sfx/igloo.ins: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tonysavon/Frostbite-C64/HEAD/sfx/igloo.ins -------------------------------------------------------------------------------- /sfx/igloo.snd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tonysavon/Frostbite-C64/HEAD/sfx/igloo.snd -------------------------------------------------------------------------------- /sfx/splash.ins: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tonysavon/Frostbite-C64/HEAD/sfx/splash.ins -------------------------------------------------------------------------------- /sfx/splash.snd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tonysavon/Frostbite-C64/HEAD/sfx/splash.snd -------------------------------------------------------------------------------- /gfx/credits.map: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tonysavon/Frostbite-C64/HEAD/gfx/credits.map -------------------------------------------------------------------------------- /gfx/credits.scr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tonysavon/Frostbite-C64/HEAD/gfx/credits.scr -------------------------------------------------------------------------------- /gfx/darkbear.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tonysavon/Frostbite-C64/HEAD/gfx/darkbear.png -------------------------------------------------------------------------------- /gfx/desktop.ini: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tonysavon/Frostbite-C64/HEAD/gfx/desktop.ini -------------------------------------------------------------------------------- /gfx/fish_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tonysavon/Frostbite-C64/HEAD/gfx/fish_icon.png -------------------------------------------------------------------------------- /gfx/logo_bars.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tonysavon/Frostbite-C64/HEAD/gfx/logo_bars.bin -------------------------------------------------------------------------------- /gfx/logo_top.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tonysavon/Frostbite-C64/HEAD/gfx/logo_top.png -------------------------------------------------------------------------------- /gfx/platform0.gpx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tonysavon/Frostbite-C64/HEAD/gfx/platform0.gpx -------------------------------------------------------------------------------- /gfx/platform0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tonysavon/Frostbite-C64/HEAD/gfx/platform0.png -------------------------------------------------------------------------------- /gfx/platform1.gpx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tonysavon/Frostbite-C64/HEAD/gfx/platform1.gpx -------------------------------------------------------------------------------- /gfx/platform1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tonysavon/Frostbite-C64/HEAD/gfx/platform1.png -------------------------------------------------------------------------------- /sfx/landing.ins: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tonysavon/Frostbite-C64/HEAD/sfx/landing.ins -------------------------------------------------------------------------------- /sfx/landing.snd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tonysavon/Frostbite-C64/HEAD/sfx/landing.snd -------------------------------------------------------------------------------- /gfx/degree_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tonysavon/Frostbite-C64/HEAD/gfx/degree_icon.png -------------------------------------------------------------------------------- /gfx/platform0.imap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tonysavon/Frostbite-C64/HEAD/gfx/platform0.imap -------------------------------------------------------------------------------- /gfx/platform1.imap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tonysavon/Frostbite-C64/HEAD/gfx/platform1.imap -------------------------------------------------------------------------------- /gfx/shoredark2.kla: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tonysavon/Frostbite-C64/HEAD/gfx/shoredark2.kla -------------------------------------------------------------------------------- /gfx/digits_shadow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tonysavon/Frostbite-C64/HEAD/gfx/digits_shadow.png -------------------------------------------------------------------------------- /release/frostbite.prg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tonysavon/Frostbite-C64/HEAD/release/frostbite.prg -------------------------------------------------------------------------------- /sid/Frostbite_C64.sid: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tonysavon/Frostbite-C64/HEAD/sid/Frostbite_C64.sid -------------------------------------------------------------------------------- /sid/Frostbite_C64.sng: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tonysavon/Frostbite-C64/HEAD/sid/Frostbite_C64.sng -------------------------------------------------------------------------------- /gfx/platform0.iscr: -------------------------------------------------------------------------------- 1 |  2 |  3 |  4 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Frostbite-C64 2 | A Commodore 64 port of Activision's Frostbite. https://csdb.dk/release/?id=183742 3 | -------------------------------------------------------------------------------- /gfx/stars.iscr: -------------------------------------------------------------------------------- 1 |     2 |               3 | ! -------------------------------------------------------------------------------- /gfx/platform1.iscr: -------------------------------------------------------------------------------- 1 |      2 |   3 |   4 |      5 |   6 |   7 |          !!! "#$ "#$ "#$ %&'(%&'(%&'( "#)* "#)* "#)* +,-./&'(+,-./&'(+,-./&'( 012* 012* 012* +,-.3456+,-.3456+,-.3456 01789:;01789:;01789:; <=>456<=>456<=>456 ?@89:;?@89:;?@89:; <=AB<=AB<=AB ? C 8 | ? C 9 | ? C 10 | -------------------------------------------------------------------------------- /src/sfx.asm: -------------------------------------------------------------------------------- 1 | .macro sfx(sfx_id) 2 | { 3 | ldx #sfx_id 4 | jsr sfx_play 5 | } 6 | 7 | 8 | set_sfx_routine: 9 | { 10 | lda music_on 11 | bne !on+ 12 | 13 | lda #play_no_music 17 | sta sfx_play.sfx_routine + 2 18 | rts 19 | 20 | !on: 21 | lda #play_with_music 25 | sta sfx_play.sfx_routine + 2 26 | rts 27 | } 28 | 29 | sfx_play: 30 | { 31 | sfx_routine: 32 | jmp play_with_music 33 | } 34 | 35 | 36 | //when sid is not playing, we can use any of the channels to play effects 37 | play_no_music: 38 | { 39 | 40 | lda wavetable_l,x 41 | ldy wavetable_h,x 42 | ldx channel 43 | dex 44 | bpl !skp+ 45 | ldx #2 46 | !skp: 47 | stx channel 48 | pha 49 | lda times7,x 50 | tax 51 | pla 52 | jmp sid.init + 6 53 | 54 | channel: 55 | .byte 2 56 | times7: 57 | .fill 3, 7 * i 58 | } 59 | 60 | 61 | play_with_music: 62 | { 63 | lda wavetable_l,x 64 | ldy wavetable_h,x 65 | ldx #7 * 2 66 | jmp sid.init + 6 67 | rts 68 | } 69 | 70 | 71 | // Only 7 different effects, but let's make them count :-) 72 | .label SFX_LANDING = 0 73 | .label SFX_JUMP = 1 74 | .label SFX_IGLOO = 2 75 | .label SFX_BONUS = 3 76 | .label SFX_FISH = 4 77 | .label SFX_SPLASH = 5 78 | .label SFX_BEAR = 6 79 | 80 | sfx_jump: 81 | .import binary "../sfx/jump.snd" 82 | 83 | 84 | sfx_igloo: 85 | .import binary "../sfx/igloo.snd" 86 | 87 | 88 | sfx_bonus: 89 | .import binary "../sfx/bonus.snd" 90 | 91 | 92 | sfx_fish: 93 | .import binary "../sfx/eating.snd" 94 | 95 | 96 | sfx_landing: 97 | .import binary "../sfx/landing.snd" 98 | 99 | 100 | sfx_splash: 101 | .import binary "../sfx/splash.snd" 102 | 103 | sfx_bear: 104 | .import binary "../sfx/bear.snd" 105 | 106 | 107 | wavetable_l: 108 | .byte sfx_landing, >sfx_jump, >sfx_igloo, >sfx_bonus, >sfx_fish, >sfx_splash, >sfx_bear 112 | -------------------------------------------------------------------------------- /src/hero.asm: -------------------------------------------------------------------------------- 1 | .label STATUS_MOVING = %00000001 2 | .label STATUS_DIRECTION = %00000010 3 | .label STATUS_JUMPING = %00000100 4 | .label STATUS_YDIRECTION = %00001000 5 | .label STATUS_STUCK = %00010000 6 | .label STATUS_SAFESPOT = %00100000 7 | .label STATUS_CLEARED_SLAB = %01000000 8 | 9 | 10 | hero: 11 | { 12 | init: 13 | lda #0 14 | sta herox 15 | lda #10 16 | sta herox + 1 17 | 18 | lda #0 19 | sta herolane 20 | 21 | sta jumpclock 22 | 23 | 24 | lda #0 25 | sta herostatus 26 | 27 | lda #[hero_sprites & $3fff] / 64 28 | sta herof 29 | 30 | lda #[hero_sprites & $3fff] / 64 + 7 31 | sta herof + 1 32 | 33 | lda #[hero_sprites & $3fff] / 64 + 14 34 | sta herof + 2 35 | 36 | lda #7 37 | sta heroc 38 | lda #8 39 | sta heroc + 1 40 | lda #10 41 | sta heroc + 2 42 | 43 | rts 44 | 45 | update: 46 | lda herostatus 47 | and #STATUS_JUMPING 48 | beq !nojump+ 49 | 50 | ldx #[hero_sprites & $3fff] / 64 + 6 51 | lda jumpclock 52 | cmp #16 53 | bcc !skp+ 54 | ldx #[hero_sprites & $3fff] / 64 + 0 55 | !skp: 56 | jmp !flipandstore+ 57 | 58 | 59 | !nojump: 60 | lda #STATUS_MOVING 61 | bit herostatus 62 | beq !still+ 63 | 64 | !walking: 65 | lda controls.walkframe 66 | lsr 67 | lsr 68 | lsr 69 | lsr 70 | lsr //32 71 | clc 72 | adc #[hero_sprites & $3fff] / 64 73 | tax 74 | jmp !flipandstore+ 75 | 76 | !still: 77 | ldx #[hero_sprites & $3fff] / 64 78 | jmp !flipandstore+ 79 | 80 | 81 | !flipandstore: 82 | lda #STATUS_DIRECTION 83 | bit herostatus 84 | beq !store+ 85 | txa 86 | clc 87 | adc #7*3 88 | tax 89 | 90 | !store: 91 | txa 92 | sta herof 93 | clc 94 | adc #7 95 | sta herof + 1 96 | adc #7 97 | sta herof + 2 98 | rts 99 | } 100 | 101 | .var trajectory = List() 102 | .for (var i = 0; i < 24; i++) 103 | .eval trajectory.add(36.0 * sin (((PI / 1.4) * i) / 24.0)) 104 | 105 | jump_trajectory_up: 106 | .fill 24, trajectory.get(i) 107 | 108 | jump_trajectory_down: 109 | .fill 24, trajectory.get(23-i) - 32 110 | 111 | 112 | hero_y_offset: 113 | .fill 5, 92 + 32 * i -------------------------------------------------------------------------------- /src/misc.asm: -------------------------------------------------------------------------------- 1 | //blits a number of half pages from src to dst 2 | .macro blithp(src,dst,n) 3 | { 4 | ldx #127 5 | !: 6 | .for (var i = 0; i < n; i++) 7 | { 8 | lda src + 128 * i,x 9 | sta dst + 128 * i,x 10 | } 11 | dex 12 | .if (n < 20) 13 | { 14 | bpl !- 15 | } 16 | else //prevent branch distance error 17 | { 18 | bmi !+ 19 | jmp !- 20 | !: 21 | } 22 | 23 | } 24 | 25 | 26 | //32 bit random number generator 27 | random_: 28 | { 29 | asl random 30 | rol random+1 31 | rol random+2 32 | rol random+3 33 | bcc nofeedback 34 | lda random 35 | eor #$b7 36 | sta random 37 | lda random+1 38 | eor #$1d 39 | sta random+1 40 | lda random+2 41 | eor #$c1 42 | sta random+2 43 | lda random+3 44 | eor #$04 45 | sta random+3 46 | nofeedback: 47 | rts 48 | 49 | random: .byte $ff,$ff,$ff,$ff 50 | } 51 | 52 | 53 | // Waits fire button full press-depress cycle 54 | waitbutton: 55 | { 56 | !: jsr vsync 57 | 58 | lda $dc00 59 | and #%00010000 60 | bne !- 61 | 62 | 63 | !: jsr vsync 64 | 65 | lda $dc00 66 | and #%00010000 67 | beq !- 68 | 69 | rts 70 | } 71 | 72 | vsync: 73 | { 74 | bit $d011 75 | bmi *-3 76 | bit $d011 77 | bpl *-3 78 | rts 79 | } 80 | 81 | framevsync: 82 | { 83 | 84 | !: lda frameflag 85 | beq !- 86 | lda #0 87 | sta frameflag 88 | rts 89 | } 90 | 91 | erase_sid: 92 | { 93 | ldx #$1f 94 | lda #0 95 | !: sta $d400,x 96 | dex 97 | bpl !- 98 | rts 99 | } 100 | 101 | // Flips a sprite horizontally 102 | // https://codebase64.org/doku.php?id=base:sprite_mirror 103 | 104 | .macro flipspr(src,dst) 105 | { 106 | lda #src 109 | sta mirror_sprite.src1 + 2 110 | 111 | lda #dst 114 | sta mirror_sprite.dst1 + 2 115 | jsr mirror_sprite 116 | } 117 | 118 | 119 | mirror_sprite: 120 | { 121 | //initialization 122 | ldy mirror_sprite.src1 + 1 123 | iny 124 | sty mirror_sprite.src2 + 1 125 | iny 126 | sty mirror_sprite.src3 + 1 127 | 128 | ldy mirror_sprite.dst1 + 1 129 | iny 130 | sty mirror_sprite.dst2 + 1 131 | iny 132 | sty mirror_sprite.dst3 + 1 133 | 134 | ldy mirror_sprite.src1 + 2 135 | sty mirror_sprite.src2 + 2 136 | sty mirror_sprite.src3 + 2 137 | 138 | ldy mirror_sprite.dst1 + 2 139 | sty mirror_sprite.dst2 + 2 140 | sty mirror_sprite.dst3 + 2 141 | 142 | 143 | 144 | 145 | ldx #$3c //bottom left byte offset 146 | !: 147 | 148 | src1: ldy $e000,x 149 | lda sprmir,y 150 | src3: ldy $e002,x 151 | dst3: sta $e002,x 152 | lda sprmir,y 153 | dst1: sta $e000,x 154 | 155 | src2: ldy $e001,x 156 | lda sprmir,y 157 | dst2: sta $e001,x 158 | 159 | txa 160 | axs #$03 //dex * 3. We save 2 cycles. 161 | 162 | bpl !- 163 | 164 | rts 165 | } 166 | 167 | // The following table is for multicolor sprites. Changes for hires sprites are trivial. 168 | sprmir: 169 | .fill 256, ((i & %00000011) << 6) | ((i & %00001100) << 2) | ((i & %00110000) >> 2) | ((i & %11000000) >> 6) 170 | 171 | -------------------------------------------------------------------------------- /src/notes.asm: -------------------------------------------------------------------------------- 1 | 2 | // Some random notes from the Reverse engineering process of the original game 3 | // There's MUCH more, but most of the stuff I RE-ed has been put down in code straight away 4 | 5 | /* 6 | Night and day last 4 levels each 7 | 8 | level 0-3 is day 9 | 4-7 is night 10 | 8-11 is day 11 | and so on 12 | 13 | Enemies are one per lane for the first levels 14 | Then they go like 15 | 1,2,2,3 enemies for the first, second, third, fourth level of each lane 16 | 17 | Hero walk speed is constant and does not depend on the level 18 | 19 | Slab speed increases at every level 20 | 21 | hero jump speed is always higher than slab scroll speed. Check code for the actual function. 22 | 23 | For the firstlevel a slab transition takes ~1152 frames. Roughly 3 seconds on PAL. 24 | which means 3.6 frames for a single pixel scroll. 25 | initial speed must be %00001000 26 | at level 16, slabs are 4 times faster, which gives us an indication of the speed function. 27 | 28 | speed = %00001000 * (level / 4) 29 | 30 | We don't want the speed to be higher than 1 char per second for char objects in the screen, 31 | so the enemies top speed will be %11111111 which means that the slab top speed must be capped 32 | to %11000000. Which means that speed is only increasing for 48 levels, then it must settle. 33 | Looking at the original code, this seems to be the case there as well. 34 | 35 | Finally, these numbers have to be adjusted for the higher pixel density of the Commodore 64, 36 | in order to preserve exactly the same "feeling" of the original. 37 | The resulting speed-tables are in the code. 38 | 39 | Animated slab are animated at constant speed, regardless of the scroll speed. 40 | A complete animation looop 0..8..1 lasts exactly 256 frames. 41 | 42 | 43 | The safe spot: 44 | it's the left end side of the shore. It only works if you jump STRAIGHT UP from the first lane. 45 | This is a noticeable case of a bug turned into feature. Frostbite behaves like that because 46 | the shore and the lanes have a slightly different X-range. 47 | when jumping from the first lane to the shore you can therefore jump to an x-offset position 48 | you'd not be normally entitled to walk to, coming from a shore. 49 | This "bug" is not there in the C64 version, because of the different control logic, so I had to 50 | "implement" it. The hero status byte has a special STATUS_SAFESPOT flag that indicates that the 51 | hero is standing on the safe spot, which activates the code to simulate the bug. 52 | 53 | Enemies: 54 | starting from level 6 (second night stage) crabs and shells do pauses. They pause for 64 frames 55 | and then go for 64 frames, in turns. All shells pause when the crab moves and vice-versa 56 | 57 | 58 | This is the number of enemies per lane according to the level 59 | 60 | 01: 1 61 | 02: 2 62 | 03: 2 63 | 04: 1 64 | 05: 1 65 | 06: 2 66 | 07: 2 67 | 08: 3 68 | 09: 1 69 | 10: 2 70 | 11: 2 71 | 12: 3 72 | 13: 1 73 | 14: 2 74 | 15: 2 75 | 16: 3 76 | 77 | 78 | so it's 1,2,2,1 for the first block of 4 levels, and then it goes 1,2,2,3 forever. 79 | 80 | 81 | slab type: 0 = regular, 1 = cracking, 2 = long 82 | 83 | 01: 0 84 | 02: 2 85 | 03: 0 86 | 04: 2 87 | 05: 0 88 | 06: 1 89 | 07: 0 90 | 08: 1 91 | 09: 0 92 | 10: 1 93 | 11: 0 94 | 12: 1 95 | 13: 0 96 | 14: 1 97 | 15: 0 98 | 16: 1 99 | 17: 0 100 | 18: 1 101 | 19: 0 102 | 20: 1 103 | 104 | so it's 0,2,0,2 and then it's 0,1 forever 105 | 106 | -------------------------------------------------------------------------------- /src/splash.asm: -------------------------------------------------------------------------------- 1 | showpic: 2 | { 3 | jsr vsync 4 | lda #$0b 5 | sta $d011 6 | 7 | lda #$00 8 | sta $d020 9 | lda #$01 10 | sta $d021 11 | 12 | lda #$00 13 | sta $dd00 14 | lda #%10000000 15 | sta $d018 16 | lda #$d8 17 | sta $d016 18 | 19 | ldx #0 20 | !: 21 | .for (var i = 0; i < 4; i++) 22 | { 23 | lda $b800 + $100 * i,x 24 | sta $d800 + $100 * i,x 25 | } 26 | inx 27 | bne !- 28 | 29 | jsr vsync 30 | lda #$3b 31 | sta $d011 32 | 33 | rts 34 | } 35 | 36 | 37 | splash: 38 | { 39 | lda #0 40 | jsr sid.init 41 | 42 | sei 43 | 44 | lda #0 45 | sta $d021 46 | sta $d015 47 | sta button 48 | 49 | lda #$0f 50 | sta $d418 51 | 52 | ldx #39 53 | !: lda #0 54 | sta $d800 + 16 * 40,x 55 | lda #$0f 56 | .for (var i = 0; i < 8; i++) 57 | sta $d800 + (17 + i) * 40,x 58 | dex 59 | bpl !- 60 | 61 | lda #$c8 62 | sta $d016 63 | 64 | loop: 65 | 66 | jsr vsync 67 | jsr random_ 68 | jsr sid.play 69 | 70 | lda #1 71 | sta $dd00 72 | lda #%11011000 73 | sta $d018 74 | lda #$3b 75 | sta $d011 76 | 77 | lda #180 78 | !: cmp $d012 79 | bcs !- 80 | 81 | lda #3 82 | sta $dd00 83 | lda #$1b 84 | sta $d011 85 | lda #%11010110 86 | sta $d018 87 | 88 | lda $dc00 89 | sta joy 90 | 91 | jsr select_level 92 | 93 | 94 | lda button 95 | cmp #2 96 | bcs !exit+ 97 | cmp #0 98 | beq waitrelease 99 | cmp #1 100 | bne !next+ 101 | beq waitpush 102 | 103 | !next: 104 | 105 | jmp loop 106 | 107 | 108 | !exit: 109 | lda #1 110 | jsr sid.init 111 | rts 112 | 113 | waitpush: 114 | lda #%00010000 115 | bit joy 116 | bne !skp+ 117 | inc button 118 | !skp: 119 | jmp loop 120 | 121 | waitrelease: 122 | lda #%00010000 123 | bit joy 124 | beq !skp+ 125 | inc button 126 | !skp: 127 | jmp loop 128 | 129 | 130 | select_level: 131 | { 132 | //print the level anyway 133 | ldx #'0' 134 | lda menulevel 135 | cmp #10 136 | bcc !singledigit+ 137 | sbc #10 138 | ldx #'1' 139 | clc 140 | !singledigit: 141 | adc #'0' 142 | sta $3400 + 23 * 40 + 38 143 | stx $3400 + 23 * 40 + 37 144 | 145 | lda menulevel 146 | sec 147 | sbc #1 148 | lsr 149 | lsr 150 | tax 151 | lda dcol,x 152 | sta $d800 + 23 * 40 + 38 153 | sta $d800 + 23 * 40 + 37 154 | 155 | lda jtimer 156 | beq !skp+ 157 | 158 | dec jtimer 159 | 160 | rts 161 | 162 | !skp: 163 | 164 | lda #%00000001 165 | bit joy 166 | beq !incl+ 167 | asl 168 | bit joy 169 | beq !decl+ 170 | rts 171 | 172 | !incl: 173 | 174 | lda menulevel 175 | cmp #16 176 | bcs !done+ 177 | inc menulevel 178 | lda #10 179 | sta jtimer 180 | !done: 181 | rts 182 | 183 | !decl: 184 | lda menulevel 185 | cmp #2 186 | bcc !done- 187 | dec menulevel 188 | lda #10 189 | sta jtimer 190 | rts 191 | 192 | 193 | 194 | } 195 | 196 | button: 197 | .byte 0 198 | joy: 199 | .byte 0 200 | jtimer: 201 | .byte 0 202 | 203 | dcol: 204 | .byte 13,7,8,2 205 | } 206 | 207 | -------------------------------------------------------------------------------- /src/hud.asm: -------------------------------------------------------------------------------- 1 | hud_init: 2 | { 3 | 4 | jsr color_hud_area 5 | 6 | lda #DEGREECHAR 7 | sta scrn + 40 + 22 8 | 9 | lda level 10 | cmp #20 11 | bcc !skp+ 12 | 13 | lda #FISHCHARS 14 | sta scrn + 40 + 10 15 | lda #FISHCHARS + 1 16 | sta scrn + 40 + 11 17 | 18 | 19 | !skp: 20 | 21 | jsr timer.update 22 | 23 | jsr put_lives 24 | jmp put_score 25 | 26 | rts 27 | 28 | 29 | 30 | } 31 | 32 | // We have a separate jsr for this, because it's not only used by the initializer 33 | color_hud_area: 34 | { 35 | 36 | 37 | lda #1 38 | ldx #39 39 | !: 40 | sta $d800,x 41 | sta $d800 + 40,x 42 | sta $d800 + 80,x 43 | dex 44 | bpl !- 45 | 46 | lda #9 47 | //time 48 | sta $d800 + 40 + 18 49 | sta $d800 + 40 + 19 50 | sta $d800 + 40 + 20 51 | sta $d800 + 40 + 21 52 | //degree 53 | sta $d800 + 40 + 22 54 | 55 | //lives 56 | sta $d800 + 40 + 6 57 | sta $d800 + 40 + 7 58 | 59 | //fish 60 | sta $d800 + 40 + 10 61 | sta $d800 + 40 + 11 62 | 63 | ldx #13 64 | !: sta $d800 + 40 + 24,x 65 | dex 66 | bpl !- 67 | 68 | //if it's day, erase the stars. otherwise draw them 69 | lda level 70 | sec 71 | sbc #1 72 | and #4 73 | beq !day+ 74 | 75 | //night 76 | ldx #119 77 | !: lda starmap,x 78 | beq !skp+ 79 | sta scrn,x 80 | !skp: 81 | dex 82 | bpl !- 83 | 84 | jmp !next+ 85 | 86 | 87 | !day: 88 | lda #0 89 | ldx #119 90 | !: ldy starmap,x 91 | beq !skp+ 92 | sta scrn,x 93 | !skp: 94 | dex 95 | bpl !- 96 | !next: 97 | rts 98 | } 99 | 100 | // Adds A * 100 to the score, so 100 to 900 in steps of 100 101 | add_score_xx: 102 | { 103 | ldx #3 104 | jmp add_score_x.opt 105 | } 106 | 107 | // Adds A * 10 to the score, so 10 to 90 in steps of 10. 108 | add_score_x: 109 | { 110 | ldx #4 111 | opt: ldy #0 //flag for extralives 112 | !: clc 113 | adc score,x 114 | sta score,x 115 | cmp #$0a 116 | bcc !done+ 117 | sbc #$0a 118 | sta score,x 119 | lda #1 120 | cpx #2 121 | bne !skp+ 122 | 123 | iny 124 | 125 | !skp: 126 | dex 127 | bpl !- 128 | //overflow! 129 | lda #9 130 | sta score 131 | sta score + 1 132 | sta score + 2 133 | sta score + 3 134 | sta score + 4 135 | sta score + 5 136 | 137 | jsr put_score 138 | jmp game_over //this is the good gameover! 139 | 140 | !done: 141 | 142 | cpy #0 143 | beq !skp+ 144 | 145 | lda lives 146 | cmp #10 147 | bcs !skp+ 148 | inc lives 149 | jsr put_lives 150 | !skp: 151 | //jmp put_score //it's up next anyway 152 | } 153 | 154 | 155 | put_score: 156 | { 157 | 158 | ldx #0 159 | ldy #0 160 | 161 | !: 162 | lda score,x 163 | asl //also clears carry, because score digits are < 128 164 | adc #1 165 | sta scrn + 40 + 2 + 24,y 166 | iny 167 | adc #1 168 | sta scrn + 40 + 2 + 24,y 169 | iny 170 | inx 171 | cpx #6 //this will also clear the carry 172 | bne !- 173 | 174 | rts 175 | 176 | } 177 | 178 | 179 | put_lives: 180 | { 181 | 182 | lda lives 183 | asl 184 | sec 185 | sbc #1 186 | sta scrn + 40 + 6 187 | clc 188 | adc #1 189 | sta scrn + 40 + 7 190 | rts 191 | } 192 | 193 | 194 | timer: 195 | { 196 | init: 197 | lda #49 198 | sta timer_value + 2 199 | lda #5 200 | sta timer_value + 1 201 | lda #4 202 | sta timer_value + 0 203 | 204 | rts 205 | 206 | tick: 207 | lda timer_value 208 | bpl !skp+ 209 | rts 210 | 211 | !skp: 212 | 213 | dec timer_value + 2 214 | bmi !underflow+ 215 | 216 | lda timer_value 217 | bne !skp+ 218 | 219 | //if less than 10 seconds, we must blink 220 | lda timer_value + 2 221 | and #31 222 | tax 223 | lda mcgradient,x 224 | sta $d800 + 40 + 18 225 | sta $d800 + 40 + 19 226 | sta $d800 + 40 + 20 227 | sta $d800 + 40 + 21 228 | rts 229 | 230 | !underflow: 231 | lda #49 232 | sta timer_value + 2 233 | 234 | dec timer_value + 1 235 | bpl update 236 | 237 | lda #9 238 | sta timer_value + 1 239 | dec timer_value + 0 240 | bpl update 241 | 242 | // timer_value <0 means time is up. We check this elsewhere, we just don't update the screen 243 | 244 | !skp: 245 | rts 246 | 247 | update: 248 | 249 | lda timer_value 250 | bpl !skp+ 251 | 252 | lda #0 253 | sta timer_value + 1 254 | !skp: 255 | asl //clears the carry as this is < 128 256 | adc #1 257 | sta scrn + 40 + 18 258 | adc #1 259 | sta scrn + 40 + 19 260 | 261 | lda timer_value + 1 262 | asl //clears the carry as this is < 128 263 | adc #1 264 | sta scrn + 40 + 20 265 | adc #1 266 | sta scrn + 40 + 21 267 | 268 | rts 269 | 270 | 271 | .const mcgradientlist = List().add($00+8, $02+8, $04+8,$04+4, $05+8,$05+8, $03+8,$03+8,$03+8, $07+8,$07+8,$07+8,$07+8, $01+8,$01+8,$01+8,$01+8) 272 | mcgradient: 273 | 274 | .fill 15,mcgradientlist.get(15-i) 275 | .fill 17,mcgradientlist.get(i) 276 | } 277 | -------------------------------------------------------------------------------- /src/controls.asm: -------------------------------------------------------------------------------- 1 | controls: 2 | { 3 | 4 | lda $dc00 5 | 6 | sta controls.backup 7 | 8 | lda #STATUS_STUCK 9 | bit herostatus 10 | beq !canmove+ 11 | 12 | //the hero is stuck. the enemy move part has already moved it, 13 | //so let's just switch to the check boundaries status 14 | jmp !check_boundaries+ 15 | 16 | 17 | !canmove: 18 | lda controls.backup 19 | jsr readjoy 20 | 21 | //fist thing, check fire 22 | bcs !clearfire+ 23 | 24 | //fire. 25 | 26 | lda firebusy 27 | bne !nofire+ 28 | 29 | lda #1 30 | sta firebusy 31 | 32 | lda herostatus 33 | and #STATUS_JUMPING 34 | bne !nofire+ 35 | 36 | lda herolane 37 | beq !nofire+ 38 | 39 | //reverse the flow of the current slab 40 | 41 | tax 42 | dex 43 | lda #0 44 | sta environment.slablane.status,x 45 | lda environment.slablane.direction,x 46 | eor #1 47 | sta environment.slablane.direction,x 48 | 49 | lda igloo_size 50 | cmp #16 51 | beq !skp+ 52 | jsr environment.break_igloo 53 | 54 | !skp: 55 | jmp !next+ 56 | 57 | !clearfire: 58 | lda #0 59 | sta firebusy 60 | 61 | !nofire: 62 | cpy #0 63 | beq !testx+ 64 | 65 | 66 | lda #STATUS_JUMPING 67 | bit herostatus 68 | bne !testx+ 69 | 70 | 71 | //lda herostatus 72 | //ora #STATUS_JUMPING 73 | //sta herostatus 74 | lda #$00 75 | sta jumpclock 76 | 77 | cpy #$ff 78 | beq !up+ 79 | 80 | !down: 81 | lda herolane 82 | cmp #4 83 | beq !testx+ 84 | 85 | lda herostatus 86 | 87 | ora #STATUS_JUMPING 88 | 89 | and #$ff - STATUS_YDIRECTION - STATUS_SAFESPOT 90 | sta herostatus 91 | 92 | stx svx + 1 93 | :sfx(SFX_JUMP) 94 | 95 | jmp svx 96 | //jmp !testx+ 97 | 98 | !up: 99 | lda herolane 100 | beq !testx+ 101 | 102 | lda herostatus 103 | ora #STATUS_YDIRECTION | STATUS_JUMPING 104 | sta herostatus 105 | 106 | stx svx + 1 107 | :sfx(SFX_JUMP) 108 | 109 | //jmp !testx+ 110 | 111 | svx: ldx #0 112 | !testx: 113 | //if we are in safespot, we can only move vertically 114 | lda #STATUS_SAFESPOT 115 | bit herostatus 116 | beq !skp+ 117 | jmp !no_horizontal_movement+ 118 | !skp: 119 | cpx #0 120 | bne !skp+ 121 | lda herostatus 122 | and #$ff - STATUS_MOVING 123 | sta herostatus 124 | lda #0 125 | sta walkframe 126 | jmp !no_horizontal_movement+ 127 | !skp: 128 | lda herostatus 129 | ora #STATUS_MOVING 130 | sta herostatus 131 | 132 | lda walkspeed 133 | sta p0tmp 134 | 135 | lda #STATUS_JUMPING 136 | bit herostatus 137 | beq !skp+ 138 | 139 | lda jumpspeed 140 | sta p0tmp 141 | 142 | !skp: 143 | cpx #1 144 | beq !right+ 145 | //left 146 | lda herostatus 147 | ora #STATUS_DIRECTION 148 | sta herostatus 149 | 150 | lda herox 151 | sec 152 | sbc p0tmp //walkspeed 153 | sta herox 154 | lda herox + 1 155 | sbc #0 156 | sta herox + 1 157 | 158 | jmp !wf+ 159 | 160 | !right: 161 | lda herostatus 162 | and #$ff - STATUS_DIRECTION 163 | sta herostatus 164 | 165 | lda herox 166 | clc 167 | adc p0tmp //walkspeed 168 | sta herox 169 | lda herox + 1 170 | adc #0 171 | sta herox + 1 172 | 173 | !wf: 174 | 175 | lda walkspeed 176 | lsr 177 | lsr 178 | lsr // /8 179 | clc 180 | adc walkframe 181 | sta walkframe 182 | 183 | cmp #5*32 184 | bcc !next+ 185 | lda #0 186 | sta walkframe 187 | 188 | 189 | jmp !next+ 190 | 191 | !no_horizontal_movement: 192 | !next: 193 | 194 | 195 | 196 | //refine boundaries etc 197 | lda #STATUS_JUMPING 198 | bit herostatus 199 | beq !next+ 200 | 201 | inc jumpclock 202 | lda jumpclock 203 | cmp #24 204 | bne !next+ 205 | 206 | lda herostatus 207 | and #$ff - STATUS_JUMPING 208 | sta herostatus 209 | 210 | and #STATUS_YDIRECTION 211 | beq !down+ 212 | //up 213 | dec herolane 214 | beq !testsafespot+ //!next+ 215 | jmp !opt+ 216 | 217 | !testsafespot: 218 | lda herox 219 | clc 220 | adc #%01000000 221 | lda herox + 1 222 | adc #0 223 | 224 | bne !next+ 225 | 226 | lda #%11000000 227 | sta herox 228 | lda #0 229 | sta herox + 1 230 | lda herostatus 231 | and #$ff - STATUS_DIRECTION - STATUS_MOVING 232 | ora #STATUS_SAFESPOT 233 | sta herostatus 234 | jmp !next+ 235 | 236 | !down: 237 | inc herolane 238 | !opt: 239 | ldx herolane 240 | dex 241 | 242 | //align the subpixel amounts, so we don't "slide" 243 | lda environment.slablane.offset_l,x 244 | and #%00011111 245 | sta p0tmp + 3 246 | lda herox 247 | and #%11100000 248 | ora p0tmp + 3 249 | sta herox 250 | 251 | 252 | 253 | lda environment.slablane.status,x 254 | bne !next+ 255 | 256 | //we can potentially build the igloo and assign some score 257 | //but we can't do it here, because the player might have landed in the water 258 | //so let's assign this to a variable 259 | 260 | lda #STATUS_CLEARED_SLAB 261 | ora herostatus 262 | sta herostatus 263 | stx environment.slabcleared 264 | 265 | !next: 266 | 267 | !check_boundaries: 268 | 269 | lda #STATUS_SAFESPOT 270 | bit herostatus 271 | bne !dontcheck+ 272 | 273 | lda #0 274 | sta p0tmp 275 | 276 | lda herolane 277 | bne !skp+ 278 | lda #1 279 | sta p0tmp 280 | 281 | !skp: 282 | lda herox + 0 283 | sec 284 | sbc #%10000000 285 | lda herox + 1 286 | sbc #0 287 | 288 | cmp p0tmp 289 | bpl !ok+ 290 | 291 | lda #%10000000 292 | sta herox 293 | lda p0tmp 294 | sta herox + 1 295 | 296 | !ok: 297 | cmp #37 298 | bcc !ok+ 299 | lda #37 300 | sta herox + 1 301 | lda #0 302 | sta herox 303 | !ok: 304 | !dontcheck: 305 | rts 306 | 307 | 308 | firebusy: 309 | .byte 0 310 | walkframe: 311 | .byte 0 312 | backup: 313 | .byte 0 314 | } 315 | 316 | readjoy: 317 | { 318 | 319 | djrrb: ldy #0 320 | ldx #0 321 | lsr 322 | bcs djr0 323 | dey 324 | djr0: lsr 325 | bcs djr1 326 | iny 327 | djr1: lsr 328 | bcs djr2 329 | dex 330 | djr2: lsr 331 | bcs djr3 332 | inx 333 | djr3: lsr 334 | rts 335 | } -------------------------------------------------------------------------------- /release/MANUAL.txt: -------------------------------------------------------------------------------- 1 | 2 | Frostbite - Commodore 64 3 | ---------------------------------------------------------------------------- 4 | 5 | Coded by Antonio Savona 6 | Gfx by Steven Day 7 | Music and sfx by Saul Cross 8 | 9 | Special thanks to Carlos Bragatto for testing 10 | ---------------------------------------------------------------------------- 11 | 12 | Frostbite Bailey's (TM) 13 | ARCTIC ARCHITECT'S HANDBOOK 14 | 15 | Activision (R) 16 | 17 | 18 | The object of the game is to help Frostbite Bailey (TM) build igloos 19 | by jumping on floating blocks of ice. Be careful to avoid these 20 | deadly hazards: clams, snowgeese, Alaskan king crab, grizzly polar 21 | bears, and the rapidly dropping temperature. 22 | 23 | 24 | FROSTBITE (TM) CONTROLS 25 | 1. In main menu, push the Joystick up/down to select starting level 26 | 27 | 2. Push fire button to start playing 28 | 29 | 3. in game, press left arrow key to toggle MUSIC ON/OFF 30 | 31 | 4. in game, press space bar to toggle PAUSE ON/OFF 32 | 33 | 34 | FROSTBITE (TM) BASICS 35 | 36 | 1. Hook up your Commodore 64. Follow manufacturer's instructions. 37 | 38 | 2. With power OFF, plug in game cartridge. 39 | 40 | 3. Turn power ON. If no picture appears, check connection of your game 41 | system to TV, then repeat steps 1-3. 42 | 43 | 4. Plug in the Joystick Controller in Port 2 (Port 1 is not used). 44 | 45 | 5. The Joystick Controller is held with the fire button in the upper 46 | left position. 47 | 48 | * To move Frostbite Bailey left or right, move Joystick left or 49 | right. 50 | 51 | * He'll move up when you push the Joystick forward, and move down 52 | when you pull it back. 53 | 54 | * To reverse the direction of the ice floe [sic] you are standing 55 | on, press the fire button. But remember, each time you do, your 56 | igloo will lose a block, unless its completely built. 57 | 58 | 6. To begin a new game, press Fire button. The ice will start to 59 | move and Frostbite can start jumping. 60 | 61 | 7. Reserves. You begin the game with one active Frostbite Bailey 62 | (TM) and three on reserve. With each increase of 10,000 points, 63 | a bonus Frostbite is added to your reserves (up to a maximum of 64 | nine). 65 | 66 | 8. Frostbite gets lost each time he falls into the Arctic Sea, gets 67 | chased away by a Polar Grizzly, or gets caught outside when the 68 | temperature drops to zero. 69 | 70 | 71 | IGLOO CONSTRUCTION 72 | 73 | Building Codes. Each time Frostbite Bailey (TM) jumps onto a white 74 | ice floe, a "block" is added to the igloo. Once jumped upon, the 75 | white ice turns blue. It can still be jumped on, but it won't add 76 | points to your score or blocks to your igloo. When all four rows are 77 | blue, they turn white again. The igloo is complete when the door 78 | appears. Frostbite may then jump into it. 79 | 80 | Work Hazards. Avoid contact with Alaskan King Crabs, snow geese, and 81 | killer clams, as they will push Frostbite Bailey into the fatal 82 | Arctic Sea. The Polar Grizzlies come out of hibernation at level 4 83 | and, upon contact, will chase Frostbite right off-screen. 84 | 85 | 86 | SPECIAL FEATURES OF FROSTBITE 87 | 88 | Fresh Fish swim by regularly. They are Frostbite's only food, and, 89 | as such, are also additives to your score. Catch 'em if you can. 90 | 91 | Night and Day. Frostbite works the day shift and the night shift. 92 | He must build four igloos per shift. 93 | 94 | A Magic Fish will appear near your score when you've racked up a 95 | certain high number of points. Watch for it! 96 | 97 | 98 | SCORING 99 | 100 | Points For 101 | Level Points per Iceblock Entering Igloo 102 | --------------------------------------------------------------------- 103 | 1 10 160 104 | 2 20 320 105 | 3 30 480 106 | 4 40 640 107 | 5 50 800 108 | 6 60 960 109 | 7 70 1120 110 | 8 80 1280 111 | 9 90 1440 112 | 113 | Scoring remains constant after the ninth level. 114 | 115 | * Fish are worth 200 points each. 116 | 117 | * Also, each degree remaining when Frostbite Bailey (TM) enters his 118 | igloo will add points to your score as follows: 119 | 120 | 10 * Degree * Level Number 121 | 122 | 123 | JOIN THE "ARCTIC ARCHITECTS" 124 | 125 | Getting into any builder's association requires paying your dues. 126 | Score 40,000 points or more, and we'll figure you paid yours. If you 127 | find the magic fish, we'll be really impressed! Send us a photo of 128 | the TV screen showing your qualifying score, along with your 129 | name and address, and we'll send you the official Arctic Architects 130 | emblem. Be sure to write the name "Frostbite" and your score on the 131 | bottom corner of the envelope. 132 | 133 | 134 | LIFE AT THE TOP OF THE WORLD 135 | 136 | The Arctic probably ranks as the area least chosen by homebuyers, and 137 | most of us know little, if anything, about this amazing land. Yet, 138 | the Arctic has been home to some of the happiest and healthiest 139 | members of humankind for thousands of years--the Eskimos! 140 | 141 | Traditional Eskimos believe that nature's gift belong to everyone. 142 | There is no private property except for tools and clothes. 143 | Everything else is shared--not only with community members, but with 144 | any stranger that travels by! 145 | 146 | It is only while traveling that Eskimos live in their famous snow 147 | houses. All houses are called "igloos" whether they are made of 148 | wood, fur, mud, or snow. The snow variety can be built in about one 149 | hour. Here's how: 150 | 151 | A knife with a long, wife blade is used to cut snow into blocks 152 | measuring 36" x 18" x 6". These are piled in a continuous spiral. 153 | 154 | The entrance is a tunnel under the snow or, when the ground is 155 | frozen, a long hall, above-ground. This keeps out the cold wind, and 156 | keeps the warm air inside. A hole is made in the roof for 157 | ventilation. 158 | 159 | There are fascinating things to learn from our Arctic sisters and 160 | brothers. Find out more at your library. 161 | 162 | 163 | HOW TO BECOME AN ARCTIC ARCHITECT 164 | 165 | Tips from Steve Cartwright, designer of Frostbite (TM) 166 | 167 | /Steve Cartwright is an Activision senior designer. His prolific 168 | talents have already brought you Barnstorming (TM), Megamania (TM), 169 | Seaquest (TM), and Plaque Attack (TM). Aside from video games, Steve 170 | enjoys motorcycle touring and photography./ 171 | 172 | "Here are my favorite tips for high scoring: 173 | 174 | "Learn to use the fire button sparingly. The best time to use it is 175 | to 'fake out' the bear by drawing him to the middle of the screen and 176 | quickly changing direction. 177 | 178 | "Don't be greedy with the fish. Get them if they come by. However, 179 | going out of your way often uses too much time. 180 | 181 | "Another thing: You can move Frostbite Bailey in mid-air and, at the 182 | higher levels, you can really hook him around. Check out just how 183 | far he'll go. 184 | 185 | "Notice that hazards only get you when both feet are planted. 186 | Therefore, it's possible to jump 'around' hazards since they can't 187 | hurt you in mid-air. 188 | 189 | "Now here's a secret tip I've decided to share: If you jump up onto 190 | the extreme left of the shore, the bear can't get you. It's 191 | Frostbite's emergency hide-out. 192 | 193 | "Now that you know the inside scoop, I'm expecting some really high 194 | scores. But don't stay on the ice too long: You can't write when 195 | your hands are cold. And, at the very least, I'm expecting a 196 | postcard." 197 | 198 | Steve Cartwright 199 | 200 | 201 | 202 | Let us get to know you! If you have questions or comments about our 203 | games or clubs, or want to be added to our mailing list, drop us a 204 | note or call the "Game Hotline" toll-free at 800-633-GAME. In 205 | California, please call 415-940-6044/5. (Note: These numbers 206 | probably don't work anymore, so don't call them. They are here for 207 | historical reasons only.) 208 | 209 | Activision, Inc., Drawer No. 7287, Mountain View, CA 94039 210 | 211 | Atari (R), 2600 (TM), and Video Computer System (TM) are trademarks 212 | of ATARI, Inc. 213 | 214 | (C) 1983 Activision (R) AX-031-03 Printed in the U.S.A. -------------------------------------------------------------------------------- /src/environment.asm: -------------------------------------------------------------------------------- 1 | environment: 2 | { 3 | init: 4 | { 5 | 6 | ldx #3 7 | !: jsr enemies.clear_enemylane 8 | dex 9 | bpl !- 10 | 11 | lda #0 12 | sta igloo_size 13 | 14 | lda mustredraw 15 | bne !skp+ 16 | jmp !noredraw+ 17 | 18 | !skp: 19 | 20 | jsr vsync 21 | and #$0b 22 | sta $d011 23 | 24 | lda level 25 | sec 26 | sbc #1 27 | and #4 28 | bne !night+ 29 | jmp !day+ 30 | 31 | !night: 32 | 33 | 34 | blithp(src_night_data,target_scenery_data,21) 35 | 36 | lda #0 37 | sta irq_top.skycolor + 1 38 | 39 | lda #$00 40 | 41 | sta irq_movetobmp.pondcolor + 1 42 | 43 | jmp !next+ 44 | 45 | !day: 46 | 47 | blithp(src_day_data,target_scenery_data,21) 48 | 49 | lda #14 50 | sta irq_top.skycolor + 1 51 | 52 | lda #$06 53 | sta irq_movetobmp.pondcolor + 1 54 | //jmp !next+ 55 | 56 | !next: 57 | 58 | ldx #240 59 | !: lda shorecolordata -1,x 60 | sta $d800 + 3 * 40 -1,x 61 | lda shorescreendata -1,x 62 | sta scrn + 3 * 40 -1,x 63 | dex 64 | bne !- 65 | 66 | :blithp(shorebitmapdata, $6000 + 320 * 3,15) 67 | 68 | jsr vsync 69 | lda #$1b 70 | sta $d011 71 | 72 | !noredraw: 73 | 74 | 75 | rts 76 | } 77 | 78 | 79 | 80 | update: 81 | { 82 | jsr moveslabs 83 | 84 | //check if the hero is standing on a slab and move him accordingly, unless it's stuck. 85 | lda #STATUS_STUCK | STATUS_JUMPING 86 | bit herostatus 87 | bne !next+ 88 | 89 | ldx herolane 90 | beq !next+ //don't move when on the shore 91 | 92 | dex 93 | lda slablane.direction,x 94 | beq !right+ 95 | lda herox 96 | sec 97 | sbc slablane.speed 98 | sta herox 99 | lda herox + 1 100 | sbc #0 101 | sta herox + 1 102 | jmp !next+ 103 | 104 | !right: 105 | lda herox 106 | clc 107 | adc slablane.speed 108 | sta herox 109 | lda herox + 1 110 | adc #0 111 | sta herox + 1 112 | 113 | !next: 114 | rts 115 | } 116 | 117 | 118 | //decrease igloo size by one unit 119 | break_igloo: 120 | { 121 | ldx igloo_size 122 | beq !done+ 123 | dex 124 | stx igloo_size 125 | 126 | lda brick_offset.hi,x 127 | sta p0tmp + 1 128 | lda brick_offset.lo,x 129 | sta p0tmp 130 | 131 | clc 132 | adc #<[shorebitmapdata - ($6000 + 3 * 320)] 133 | sta p0tmp + 2 134 | lda p0tmp + 1 135 | adc #>[shorebitmapdata - ($6000 + 3 * 320)] 136 | sta p0tmp + 3 137 | 138 | lda brick_size,x 139 | sta p0tmp + 4 140 | 141 | ldy brick_parity,x 142 | 143 | !: 144 | .for (var i = 0; i < 4; i++) 145 | { 146 | lda (p0tmp + 2),y 147 | sta (p0tmp),y 148 | iny 149 | } 150 | 151 | iny 152 | iny 153 | iny 154 | iny 155 | 156 | dec p0tmp + 4 157 | bne !- 158 | 159 | !skp: 160 | !done: 161 | rts 162 | 163 | 164 | } 165 | 166 | 167 | //grows igloo by one unit 168 | build_igloo: 169 | { 170 | ldx igloo_size 171 | cpx #15 172 | 173 | bcs !done+ 174 | 175 | lda brick_offset.lo,x 176 | sta p0tmp 177 | lda brick_offset.hi,x 178 | sta p0tmp + 1 179 | //(p0tmp) destination offset on screen 180 | lda brick_size,x 181 | sta p0tmp + 2 182 | 183 | ldy brick_parity,x 184 | 185 | !: 186 | .for (var i = 0; i < 4; i++) 187 | { 188 | lda brick_pattern,y 189 | sta (p0tmp),y 190 | //inx 191 | iny 192 | } 193 | 194 | iny 195 | iny 196 | iny 197 | iny 198 | 199 | dec p0tmp + 2 200 | bne !- 201 | 202 | !skp: 203 | !done: 204 | rts 205 | } 206 | 207 | .var bolist = List().add( 208 | $6000 + 28 * 8 + 5 * 320, 209 | $6000 + 30 * 8 + 5 * 320, 210 | $6000 + 32 * 8 + 5 * 320, 211 | $6000 + 34 * 8 + 5 * 320, 212 | 213 | $6000 + 28 * 8 + 5 * 320, 214 | $6000 + 30 * 8 + 5 * 320, 215 | $6000 + 32 * 8 + 5 * 320, 216 | $6000 + 34 * 8 + 5 * 320, 217 | 218 | $6000 + 28 * 8 + 4 * 320, 219 | $6000 + 30 * 8 + 4 * 320, 220 | $6000 + 32 * 8 + 4 * 320, 221 | $6000 + 34 * 8 + 4 * 320, 222 | 223 | $6000 + 29 * 8 + 4 * 320, 224 | $6000 + 32 * 8 + 4 * 320, 225 | 226 | $6000 + 30 * 8 + 3 * 320 227 | ) 228 | 229 | 230 | brick_offset: 231 | .lohifill bolist.size(),bolist.get(i) 232 | 233 | brick_size: 234 | .fill 12,2 235 | .byte 3,3 236 | .byte 4 237 | 238 | brick_parity: 239 | .byte 4,4,4,4, 0,0,0,0, 4,4,4,4, 0,0, 4 240 | 241 | moveslabs: 242 | { 243 | lda slablane.resetclock 244 | beq !skp+ 245 | 246 | dec slablane.resetclock 247 | bne !skp+ 248 | 249 | lda slablane.status + 0 250 | and slablane.status + 1 251 | and slablane.status + 2 252 | and slablane.status + 3 253 | 254 | beq !skp+ 255 | 256 | lda igloo_size 257 | cmp #16 258 | beq !skp+ 259 | 260 | lda #0 261 | sta slablane.status + 0 262 | sta slablane.status + 1 263 | sta slablane.status + 2 264 | sta slablane.status + 3 265 | 266 | 267 | !skp: 268 | 269 | ldx #0 //counter on slabs 270 | !sloop: 271 | 272 | lda slablane.direction,x 273 | beq !right+ 274 | 275 | //left 276 | lda slablane.offset_l,x 277 | clc 278 | adc slablane.speed 279 | sta slablane.offset_l,x 280 | bcc !next+ 281 | 282 | inc slablane.offset_h,x 283 | lda slablane.offset_h,x 284 | cmp #40 285 | bcc !skp+ 286 | sbc #40 287 | sta slablane.offset_h,x 288 | 289 | !skp: 290 | jsr redraw_slab 291 | jmp !next+ 292 | 293 | !right: 294 | lda slablane.offset_l,x 295 | sec 296 | sbc slablane.speed 297 | sta slablane.offset_l,x 298 | bcs !next+ 299 | 300 | dec slablane.offset_h,x 301 | bpl !skp+ 302 | lda #39 303 | sta slablane.offset_h,x 304 | 305 | !skp: 306 | jsr redraw_slab 307 | //jmp !next+ 308 | 309 | !next: 310 | inx 311 | cpx #4 312 | bne !sloop- 313 | 314 | rts 315 | 316 | } 317 | 318 | //draws lane x. x must be preserved 319 | redraw_slab: 320 | { 321 | lda dest_off.lo,x 322 | sta dest0 + 1 323 | lda dest_off.hi,x 324 | sta dest0 + 2 325 | 326 | lda dest0 + 1 327 | clc 328 | adc #40 329 | sta dest1 + 1 330 | lda dest0 + 2 331 | adc #0 332 | sta dest1 + 2 333 | 334 | //check the source 335 | lda slabtype 336 | bne !t1+ 337 | 338 | lda #slab0map0 342 | sta src0h + 1 343 | 344 | lda #slab0map1 348 | sta src1h + 1 349 | 350 | jmp !nxt+ 351 | 352 | !t1: 353 | 354 | cmp #1 355 | bne !t2+ 356 | 357 | 358 | lda clock 359 | lsr 360 | lsr 361 | lsr 362 | lsr //0..15 363 | 364 | tay 365 | lda pingpongslab1map0.lo,y 366 | sta src0l + 1 367 | lda pingpongslab1map0.hi,y 368 | sta src0h + 1 369 | 370 | lda pingpongslab1map1.lo,y 371 | sta src1l + 1 372 | lda pingpongslab1map1.hi,y 373 | sta src1h + 1 374 | jmp !nxt+ 375 | 376 | !t2: 377 | lda #<[slab1map0 + 80 * 7] 378 | sta src0l + 1 379 | 380 | lda #>[slab1map0 + 80 * 7] 381 | sta src0h + 1 382 | 383 | lda #<[slab1map1 + 80 * 7] 384 | sta src1l + 1 385 | 386 | lda #>[slab1map1 + 80 * 7] 387 | sta src1h + 1 388 | 389 | jmp !nxt+ 390 | 391 | !nxt: 392 | lda slablane.offset_h,x 393 | clc 394 | src0l: adc #slab0map0 397 | adc #0 398 | sta src0 + 2 399 | 400 | lda slablane.offset_h,x 401 | clc 402 | src1l: adc #slab0map1 405 | adc #0 406 | sta src1 + 2 407 | 408 | ldy #39 409 | src0: lda slab0map0,y 410 | dest0: sta scrn + 8 * 40,y 411 | 412 | src1: lda slab0map1,y 413 | dest1: sta scrn + 9 * 40,y 414 | 415 | dey 416 | bpl src0 417 | 418 | rts 419 | 420 | dest_off: 421 | .lohifill 4, scrn + 11 * 40 + i * 160 422 | 423 | .const pp = List().add(0,1,2,3,4,5,6,7,8,7,6,5,4,3,2,1) 424 | 425 | pingpongslab1map0: 426 | .lohifill 16, slab1map0 + 80 * pp.get(i) 427 | 428 | pingpongslab1map1: 429 | .lohifill 16, slab1map1 + 80 * pp.get(i) 430 | 431 | } 432 | 433 | slabcolor0: 434 | //d022 435 | .byte 3 436 | .byte 14 437 | slabcolor1: 438 | .byte 1 439 | .byte 3 440 | 441 | 442 | slabtype: 443 | .byte 0 444 | 445 | slabcleared: 446 | .byte 0 447 | slablane: 448 | { 449 | offset_l: //in subchars 450 | .byte 0,0,0,0 451 | offset_h: //in chars 452 | .byte 0,0,0,0 453 | 454 | direction: 455 | .byte 0,1,0,1 456 | 457 | status: 458 | .byte 0,0,0,0 //0 = clear, 1 = reversed 459 | 460 | speed: 461 | .byte 0 462 | 463 | resetclock: 464 | .byte 0 465 | } 466 | 467 | } -------------------------------------------------------------------------------- /src/enemies.asm: -------------------------------------------------------------------------------- 1 | enemies: 2 | { 3 | 4 | plot_frame: 5 | { ldy #31 6 | !: 7 | src: lda enemybmp0r,y 8 | dst: sta enemy0,y 9 | dey 10 | bpl !- 11 | 12 | rts 13 | } 14 | 15 | //load x with lane 16 | 17 | deploy: 18 | 19 | 20 | //select enemy type. Levels 1 and 2 it's only fish or birds. 21 | //from level 2 onwards it's all of them 22 | 23 | lda random_.random,x 24 | and #%00011100 //this generates a random enemy type 0-3 (bit 3-4) and a random direction (bit2) 25 | ldy level 26 | cpy #3 27 | bcs !all+ 28 | and #%00010100 //if level is 1 or 2, only birds (enemy type 0) and fishes (enemy type 2) are allowed 29 | !all: 30 | clc 31 | adc #ENEMY0CHARS 32 | sta enemylane.type,x 33 | lsr 34 | lsr 35 | lsr 36 | lda #0 37 | rol 38 | sta enemylane.direction,x 39 | 40 | ldy enemylane.enemiesperlane 41 | 42 | lda enemylane.direction,x 43 | beq !r+ 44 | 45 | //if we are going left, we start from 64 - 8 - 4 = 52 46 | lda random_.random,x 47 | anc #%00000011 48 | adc #52 49 | jmp !str+ 50 | //right, we start from -12 51 | !r: 52 | lda random_.random,x 53 | anc #%00000011 54 | adc #-12 55 | 56 | !str: 57 | //lda #20 //p0tmp + 3 58 | sta enemylane.offset_h0,x 59 | 60 | clc 61 | 62 | adc #4 63 | sta enemylane.offset_h2,x 64 | 65 | adc #4 66 | sta enemylane.offset_h1,x 67 | 68 | lda #0 69 | sta enemylane.enemy1_active,x 70 | sta enemylane.enemy2_active,x 71 | 72 | lda #1 73 | sta enemylane.enemy0_active,x 74 | dey 75 | beq !next+ 76 | sta enemylane.enemy1_active,x 77 | 78 | dey 79 | beq !next+ 80 | sta enemylane.enemy2_active,x 81 | 82 | !next: 83 | 84 | rts 85 | 86 | 87 | update: 88 | { 89 | jsr movelanes 90 | 91 | 92 | //if the enemy is stuck, we also move the enemy accordingly 93 | 94 | lda #STATUS_STUCK 95 | bit herostatus 96 | beq !next+ 97 | 98 | ldx herolane 99 | dex 100 | 101 | lda enemylane.moved,x 102 | beq !next+ 103 | 104 | lda enemylane.direction,x 105 | beq !right+ 106 | lda herox 107 | sec 108 | sbc enemylane.speed 109 | sta herox 110 | lda herox + 1 111 | sbc #0 112 | sta herox + 1 113 | jmp !next+ 114 | 115 | !right: 116 | lda herox 117 | clc 118 | adc enemylane.speed 119 | sta herox 120 | lda herox + 1 121 | adc #0 122 | sta herox + 1 123 | 124 | 125 | !next: 126 | lda clock 127 | 128 | and #%00000111 129 | bne !next+ 130 | 131 | //animate the bird right 132 | lda enemyclock0 133 | and #%00001000 134 | asl 135 | asl 136 | adc #enemybmp0r 139 | adc #0 140 | sta plot_frame.src + 2 141 | 142 | lda #enemy0 145 | sta plot_frame.dst + 2 146 | jsr plot_frame 147 | jmp !incandexit+ 148 | 149 | !next: 150 | cmp #1 151 | bne !next+ 152 | //animate the bird left 153 | lda enemyclock0 154 | and #%00001000 155 | asl 156 | asl 157 | adc #enemybmp0l 160 | adc #0 161 | sta plot_frame.src + 2 162 | 163 | lda #<[enemy0 + 32] 164 | sta plot_frame.dst + 1 165 | lda #>[enemy0 + 32] 166 | sta plot_frame.dst + 2 167 | jsr plot_frame 168 | jmp !incandexit+ 169 | 170 | 171 | 172 | !next: 173 | cmp #2 174 | bne !next+ 175 | 176 | //animate the crab right 177 | lda enemyclock1 178 | and #%11111000 179 | asl 180 | asl 181 | sta p0tmp 182 | lda #0 183 | rol 184 | sta p0tmp + 1 185 | 186 | clc 187 | lda p0tmp 188 | adc #enemybmp1r 191 | adc p0tmp + 1 192 | sta plot_frame.src + 2 193 | 194 | lda #enemy1 197 | sta plot_frame.dst + 2 198 | jsr plot_frame 199 | jmp !incandexit+ 200 | 201 | !next: 202 | cmp #3 203 | bne !next+ 204 | //animate the crab left. No specific animation at the moment, so we use the right frame to plot to the left chars 205 | 206 | lda enemyclock1 207 | and #%11111000 208 | asl 209 | asl 210 | sta p0tmp 211 | lda #0 212 | rol 213 | sta p0tmp + 1 214 | 215 | clc 216 | lda p0tmp 217 | adc #enemybmp1r 220 | adc p0tmp + 1 221 | sta plot_frame.src + 2 222 | 223 | lda #<[enemy1 + 32] 224 | sta plot_frame.dst + 1 225 | lda #>[enemy1 + 32] 226 | sta plot_frame.dst + 2 227 | jsr plot_frame 228 | 229 | jmp !incandexit+ 230 | 231 | 232 | !next: 233 | cmp #4 234 | bne !next+ 235 | 236 | //animate the fish right 237 | lda enemyclock1 238 | and #%11111000 239 | asl 240 | asl 241 | sta p0tmp 242 | lda #0 243 | rol 244 | sta p0tmp + 1 245 | 246 | clc 247 | lda p0tmp 248 | adc #enemybmp2r 251 | adc p0tmp + 1 252 | sta plot_frame.src + 2 253 | 254 | lda #enemy2 257 | sta plot_frame.dst + 2 258 | jsr plot_frame 259 | jmp !incandexit+ 260 | 261 | !next: 262 | cmp #5 263 | bne !next+ 264 | //animate the fish left. 265 | 266 | lda enemyclock1 267 | and #%11111000 268 | asl 269 | asl 270 | sta p0tmp 271 | lda #0 272 | rol 273 | sta p0tmp + 1 274 | 275 | clc 276 | lda p0tmp 277 | adc #enemybmp2l 280 | adc p0tmp + 1 281 | sta plot_frame.src + 2 282 | 283 | lda #<[enemy2 + 32] 284 | sta plot_frame.dst + 1 285 | lda #>[enemy2 + 32] 286 | sta plot_frame.dst + 2 287 | jsr plot_frame 288 | 289 | jmp !incandexit+ 290 | 291 | !next: 292 | 293 | cmp #6 294 | bne !next+ 295 | 296 | //animate the shell right 297 | lda enemyclock1 298 | and #%11111000 299 | asl 300 | asl 301 | sta p0tmp 302 | lda #0 303 | rol 304 | sta p0tmp + 1 305 | 306 | clc 307 | lda p0tmp 308 | adc #enemybmp3r 311 | adc p0tmp + 1 312 | sta plot_frame.src + 2 313 | 314 | lda #enemy3 317 | sta plot_frame.dst + 2 318 | jsr plot_frame 319 | jmp !incandexit+ 320 | 321 | !next: 322 | cmp #7 323 | bne !next+ 324 | //animate the shell left. same frames of the shell right 325 | 326 | lda enemyclock1 327 | and #%11111000 328 | asl 329 | asl 330 | sta p0tmp 331 | lda #0 332 | rol 333 | sta p0tmp + 1 334 | 335 | clc 336 | lda p0tmp 337 | adc #enemybmp3r 340 | adc p0tmp + 1 341 | sta plot_frame.src + 2 342 | 343 | lda #<[enemy3 + 32] 344 | sta plot_frame.dst + 1 345 | lda #>[enemy3 + 32] 346 | sta plot_frame.dst + 2 347 | jsr plot_frame 348 | 349 | jmp !incandexit+ 350 | 351 | 352 | !next: 353 | 354 | !incandexit: 355 | 356 | inc enemyclock0 357 | lda enemyclock0 358 | cmp #8 * 2 359 | bne !skp+ 360 | 361 | lda #0 362 | sta enemyclock0 363 | 364 | !skp: 365 | 366 | inc enemyclock1 367 | lda enemyclock1 368 | cmp #8 * 10 369 | bne !skp+ 370 | 371 | lda #0 372 | sta enemyclock1 373 | 374 | !skp: 375 | 376 | rts 377 | } 378 | 379 | 380 | movelanes: 381 | { 382 | 383 | ldx #0 //counter on enemylanes 384 | 385 | !sloop: 386 | lda #0 387 | sta enemylane.moved,x 388 | //if it's crab or shell, and we are on level 6+, then they alternate on/off every 64 frames. See notes.asm 389 | 390 | lda level 391 | cmp #6 392 | bcc !domove+ 393 | 394 | lda enemylane.type,x 395 | cmp #ENEMY1CHARS 396 | bcc !domove+ 397 | cmp #ENEMY2CHARS 398 | bcc !crab+ 399 | cmp #ENEMY3CHARS 400 | bcc !domove+ 401 | 402 | //it's a shell 403 | 404 | !shell: 405 | lda clock 406 | and #64 407 | beq !domove+ 408 | jmp !next+ 409 | !crab: 410 | lda clock 411 | and #64 412 | bne !domove+ 413 | jmp !next+ 414 | 415 | !domove: 416 | lda #1 417 | sta enemylane.moved,x 418 | 419 | lda enemylane.direction,x 420 | bne !left+ 421 | 422 | //right 423 | lda enemylane.offset_l,x 424 | clc 425 | adc enemylane.speed 426 | sta enemylane.offset_l,x 427 | bcc !next+ 428 | 429 | inc enemylane.offset_h0,x 430 | 431 | lda enemylane.offset_h0,x 432 | cmp #52 433 | bmi !skp+ 434 | //if the leftmost enemy offsets, we respawn 435 | 436 | jsr deploy 437 | jmp !next+ 438 | !skp: 439 | inc enemylane.offset_h1,x 440 | 441 | 442 | inc enemylane.offset_h2,x 443 | 444 | jsr redraw_enemylane 445 | jmp !next+ 446 | 447 | !left: 448 | lda enemylane.offset_l,x 449 | sec 450 | sbc enemylane.speed 451 | sta enemylane.offset_l,x 452 | bcs !next+ 453 | 454 | lda #$fe 455 | dcp enemylane.offset_h0,x 456 | bne !skp+ 457 | lda #63 458 | sta enemylane.offset_h0,x 459 | 460 | !skp: 461 | lda #$fe 462 | dcp enemylane.offset_h1,x 463 | bne !skp+ 464 | //lda #63 465 | //sta enemylane.offset_h1,x 466 | //if the rightmost enemy undeflows, we respawn 467 | jsr deploy 468 | jmp !next+ 469 | 470 | !skp: 471 | lda #$fe 472 | dcp enemylane.offset_h2,x 473 | bne !skp+ 474 | lda #63 475 | sta enemylane.offset_h2,x 476 | 477 | !skp: 478 | 479 | jsr redraw_enemylane 480 | 481 | 482 | !next: 483 | 484 | inx 485 | cpx #4 486 | beq !done+ 487 | jmp !sloop- 488 | !done: 489 | rts 490 | } 491 | 492 | //load x with the lane number 493 | 494 | clear_enemylane: 495 | { 496 | lda enemylane_dest_off.lo,x 497 | sta clr + 1 498 | lda enemylane_dest_off.hi,x 499 | sta clr + 2 500 | 501 | lda #0 502 | 503 | ldy #79 504 | 505 | clr: sta scrn + 9 * 40,y 506 | dey 507 | bpl clr 508 | rts 509 | } 510 | 511 | //load x with lane, x must be preserved 512 | 513 | redraw_enemylane: 514 | { 515 | 516 | jsr clear_enemylane 517 | 518 | 519 | lda enemylane.enemy0_active,x 520 | bne !active+ 521 | jmp !next_enemy+ 522 | !active: 523 | lda enemylane_dest_off.lo,x 524 | sta p0tmp 525 | lda enemylane_dest_off.hi,x 526 | sta p0tmp + 1 527 | 528 | lda enemylane.type,x 529 | 530 | ldy enemylane.offset_h0,x 531 | bmi !skp+ 532 | 533 | cpy #39 534 | bcs !next_enemy+ 535 | sta (p0tmp),y 536 | !skp: 537 | 538 | clc 539 | adc #1 540 | iny 541 | bmi !skp+ 542 | cpy #39 543 | bcs !skp+ 544 | sta (p0tmp),y 545 | !skp: 546 | pha 547 | lda p0tmp 548 | clc 549 | adc #40 550 | sta p0tmp 551 | lda p0tmp + 1 552 | adc #0 553 | sta p0tmp + 1 554 | pla 555 | clc 556 | adc #1 557 | dey 558 | bmi !skp+ 559 | 560 | sta (p0tmp),y 561 | !skp: 562 | clc 563 | adc #1 564 | iny 565 | bmi !skp+ 566 | sta (p0tmp),y 567 | !skp: 568 | 569 | !next_enemy: 570 | 571 | 572 | 573 | lda enemylane.enemy1_active,x 574 | bne !active+ 575 | jmp !next_enemy+ 576 | !active: 577 | lda enemylane_dest_off.lo,x 578 | sta p0tmp 579 | lda enemylane_dest_off.hi,x 580 | sta p0tmp + 1 581 | 582 | lda enemylane.type,x 583 | 584 | ldy enemylane.offset_h1,x 585 | bmi !skp+ 586 | 587 | cpy #39 588 | bcs !next_enemy+ 589 | sta (p0tmp),y 590 | !skp: 591 | clc 592 | adc #1 593 | iny 594 | bmi !skp+ 595 | 596 | sta (p0tmp),y 597 | !skp: 598 | pha 599 | lda p0tmp 600 | clc 601 | adc #40 602 | sta p0tmp 603 | lda p0tmp + 1 604 | adc #0 605 | sta p0tmp + 1 606 | pla 607 | clc 608 | adc #1 609 | dey 610 | bmi !skp+ 611 | 612 | sta (p0tmp),y 613 | !skp: 614 | clc 615 | adc #1 616 | iny 617 | bmi !skp+ 618 | sta (p0tmp),y 619 | !skp: 620 | 621 | !next_enemy: 622 | 623 | 624 | 625 | 626 | 627 | lda enemylane.enemy2_active,x 628 | bne !active+ 629 | jmp !next_enemy+ 630 | !active: 631 | lda enemylane_dest_off.lo,x 632 | sta p0tmp 633 | lda enemylane_dest_off.hi,x 634 | sta p0tmp + 1 635 | 636 | lda enemylane.type,x 637 | 638 | ldy enemylane.offset_h2,x 639 | bmi !skp+ 640 | 641 | cpy #39 642 | bcs !next_enemy+ 643 | sta (p0tmp),y 644 | !skp: 645 | clc 646 | adc #1 647 | iny 648 | bmi !skp+ 649 | sta (p0tmp),y 650 | !skp: 651 | pha 652 | lda p0tmp 653 | clc 654 | adc #40 655 | sta p0tmp 656 | lda p0tmp + 1 657 | adc #0 658 | sta p0tmp + 1 659 | pla 660 | clc 661 | adc #1 662 | dey 663 | bmi !skp+ 664 | 665 | sta (p0tmp),y 666 | !skp: 667 | clc 668 | adc #1 669 | iny 670 | bmi !skp+ 671 | sta (p0tmp),y 672 | !skp: 673 | 674 | !next_enemy: 675 | 676 | 677 | rts 678 | } 679 | 680 | enemylane_dest_off: 681 | .lohifill 4, scrn + 9 * 40 + i * 160 682 | 683 | enemylane: 684 | { 685 | offset_l: //in subchars 686 | .byte 0,0,0,0 687 | 688 | offset_h0: //in chars 689 | .byte 0,0,0,0 690 | 691 | offset_h1: //for the second enemy. low byte is shared with the others 692 | .byte 0,0,0,0 693 | 694 | offset_h2: //for the third enemy. low byte is shared with the others 695 | .byte 0,0,0,0 696 | 697 | enemy0_active: 698 | .byte 0,0,0,0 699 | 700 | enemy1_active: 701 | .byte 0,0,0,0 702 | 703 | enemy2_active: 704 | .byte 0,0,0,0 705 | 706 | direction: 707 | .byte 0,0,0,0 708 | 709 | moved: 710 | .byte 0,0,0,0 //reports that a movement took place. for crab and shell enemies it's possible to take "pauses". In that case this is zero. 711 | //otherwise it's 1. When the hero is stuck, this is used to implement dragging to death 712 | type: 713 | .byte 0,0,0,0 //0 = bird, 1 = crab, 2 = fish, 3 = shell 714 | 715 | speed: 716 | .byte %00100000 717 | enemiesperlane: 718 | .byte 1 719 | } 720 | 721 | 722 | enemycolor0: 723 | .byte 00, 02, 05, 08 724 | enemycolor1: 725 | .byte 08, 10, 13, 07 726 | 727 | enemyclock0: //for 2 frames 728 | .byte 0 729 | enemyclock1: 730 | .byte 0 //for 10 frames 731 | 732 | 733 | 734 | 735 | } 736 | 737 | //the bear switchs direction at a specific point in time, apparently every 64 frames, regardless of the speed 738 | bear: 739 | { 740 | deploy: 741 | lda #1 742 | sta active 743 | lda #32 744 | sta xpos + 1 745 | lda #0 746 | sta xpos + 0 747 | 748 | lda #[bear_sprites & $3fff] / 64 + 24 749 | sta bearf 750 | 751 | lda #1 752 | sta direction 753 | 754 | lda #0 755 | sta stepframe 756 | 757 | rts 758 | 759 | off: 760 | lda #0 761 | sta active 762 | rts 763 | 764 | update: 765 | 766 | lda direction 767 | beq !right+ 768 | 769 | 770 | //left: 771 | //first, check if we can go 772 | lda xpos + 1 773 | cmp #3 774 | bcc !next+ 775 | 776 | lda xpos 777 | sec 778 | sbc speed 779 | sta xpos 780 | lda xpos + 1 781 | sbc #0 782 | sta xpos + 1 783 | 784 | jmp !opt+ 785 | !right: 786 | 787 | lda xpos + 1 788 | cmp #34 789 | bcs !next+ 790 | 791 | lda xpos 792 | clc 793 | adc speed 794 | sta xpos 795 | lda xpos + 1 796 | adc #0 797 | sta xpos + 1 798 | !opt: 799 | 800 | lda speed 801 | lsr 802 | lsr 803 | clc 804 | adc stepframe 805 | 806 | cmp #%11000000 //6 << 807 | 808 | bcc !skp+ 809 | 810 | lda #0 811 | !skp: 812 | sta stepframe 813 | 814 | lsr 815 | lsr 816 | lsr 817 | //lsr 818 | //lsr 819 | and #%11111100 820 | 821 | clc 822 | adc #[bear_sprites & $3fff] / 64 823 | sta bearf 824 | 825 | lda direction 826 | beq !skp+ 827 | 828 | lda bearf 829 | adc #24 830 | sta bearf 831 | 832 | !skp: 833 | 834 | !next: 835 | 836 | //check if we must change direction 837 | lda clock 838 | and #63 839 | 840 | bne !next+ 841 | 842 | //our chance to change direction 843 | 844 | lda xpos + 1 845 | clc 846 | adc #1 847 | cmp herox + 1 848 | 849 | bcc !right+ 850 | 851 | //left 852 | lda #1 853 | jmp !opt+ 854 | 855 | !right: 856 | lda #0 857 | !opt: 858 | sta direction 859 | 860 | !next: 861 | 862 | 863 | 864 | !next: 865 | rts 866 | 867 | active: 868 | .byte 0 869 | speed: 870 | .byte 0 871 | direction: 872 | .byte 0 873 | 874 | stepframe: 875 | .byte 0 876 | 877 | xpos: 878 | .byte 0,0 879 | flipping: // this is a counter 880 | .byte 0 881 | } -------------------------------------------------------------------------------- /src/game.asm: -------------------------------------------------------------------------------- 1 | .const p0start = $02 2 | .var p0current = p0start 3 | .function reservep0(n) 4 | { 5 | .var result = p0current 6 | .eval p0current = p0current + n 7 | .return result 8 | } 9 | 10 | .const sid = LoadSid("..\sid\Frostbite_C64.sid") 11 | .pc = $2a00 "sid" 12 | .fill sid.size,sid.getData(i) 13 | 14 | .label loaderbitmap = $c000 15 | 16 | .const KOALA_TEMPLATE = "C64FILE, Bitmap=$0000, ScreenRam=$1f40, ColorRam=$2328, BackgroundColor = $2710" 17 | .var kla = LoadBinary("../gfx/loader.kla", KOALA_TEMPLATE) 18 | 19 | .var shorekla = LoadBinary("../gfx/shore.kla", KOALA_TEMPLATE) 20 | .var shorekla2 = LoadBinary("../gfx/shoredark2.kla", KOALA_TEMPLATE) 21 | 22 | .const menulevel = reservep0(1) 23 | .const messagemode = reservep0(1) 24 | .const music_on = reservep0(1) 25 | .const key_clock = reservep0(1) 26 | .const hud_clock = reservep0(1) 27 | 28 | .const herox = reservep0(2) //subchars + chars 29 | .const heroy = reservep0(1) //pixels. temporary variable, doesn't really always keep hero y 30 | .const herof = reservep0(3) //hero frame, one per hw sprite. We could use only one, but this pushes calculations outside of the irq and makes implementation of sequences easier 31 | .const heroc = reservep0(3) //same 32 | .const herostatus = reservep0(1) 33 | .const herolane = reservep0(1) //0-5 0 = shore 34 | 35 | .const jumpclock = reservep0(1) 36 | 37 | .const jumpspeed = reservep0(1) 38 | .const walkspeed = reservep0(1) 39 | 40 | .const lives = reservep0(1) 41 | .const level = reservep0(1) 42 | 43 | .const igloo_size = reservep0(1) 44 | 45 | .const bearf = reservep0(1) //bear frame. In this case, we just use one pointer for the top-lef sprites. the remaining frames will be +1.. +3 46 | .const bearc = reservep0(2) //bear colors 47 | 48 | 49 | .const score = reservep0(6) 50 | .const timer_value = reservep0(3) //2 digits, plus frames of time unit. One time unit both on the A8 and vcs version is exactly 128 frames 51 | //this is big-endian, unlike the other multi-byte values 52 | .const clock = reservep0(1) 53 | .const frameflag = reservep0(1) 54 | 55 | .const ghostd01f = reservep0(1) 56 | .const mustredraw = reservep0(1) //sometimes we don't need to redraw the screen upon starting a new level. 57 | //Screen must only be redrawn when starting a new game or moving between night and day or viceversa 58 | 59 | .var p0tmp = reservep0(8) 60 | 61 | .var sprtmp = reservep0(1) 62 | 63 | .const scrn = $4000 64 | 65 | .macro setirq(addr,line) 66 | { 67 | lda #addr 70 | sta $ffff 71 | lda #line 72 | sta $d012 73 | } 74 | 75 | 76 | 77 | .pc = $0801 78 | :BasicUpstart($0820) 79 | 80 | 81 | .pc = $0820 "main" 82 | 83 | sei 84 | lda #$35 85 | sta $01 86 | 87 | jsr showpic 88 | 89 | jsr waitbutton 90 | 91 | lda #$0b 92 | sta $d011 93 | 94 | lda #$01 95 | sta menulevel 96 | 97 | splashloop: 98 | jsr splash 99 | 100 | lda menulevel 101 | 102 | sta level 103 | 104 | jsr vsync 105 | lda #$0b 106 | sta $d011 107 | 108 | lda #1 109 | sta mustredraw 110 | 111 | jsr init_screen_mode 112 | 113 | jsr init_game 114 | 115 | jsr clear_irq 116 | 117 | :setirq(irq_top, 8) 118 | lda #$1b 119 | sta $d011 120 | 121 | 122 | cli 123 | 124 | levelloop: 125 | jsr bear.off 126 | 127 | jsr environment.init 128 | 129 | 130 | lifeloop: 131 | jsr init_level //also sets speed and slab offset 132 | 133 | ldx #3 134 | !: jsr enemies.clear_enemylane 135 | jsr enemies.deploy 136 | dex 137 | bpl !- 138 | 139 | 140 | lda level 141 | cmp #3 142 | bcs !bear+ 143 | jmp !nobear+ 144 | !bear: 145 | sbc #1 146 | and #4 147 | beq !day+ 148 | jmp !night+ 149 | 150 | !day: 151 | 152 | :blithp(src_day_bear,bear_sprites,12) 153 | lda #7 154 | sta bearc 155 | lda #1 156 | sta bearc + 1 157 | jmp !dep+ 158 | !night: 159 | 160 | :blithp(src_night_bear,bear_sprites,12) 161 | lda #$0c 162 | sta bearc 163 | lda #$0b 164 | sta bearc + 1 165 | 166 | !dep: 167 | 168 | .for (var layer = 0; layer < 2; layer++) 169 | .for (var frame = 0; frame < 6; frame++) 170 | .for (var halve = 0; halve < 2; halve++) 171 | :flipspr(bear_sprites + layer * 6 * 128 + frame * 128 + halve * 64, bear_sprites + 12 * 128 + layer * 6 * 128 + frame * 128 + (1-halve) * 64) 172 | 173 | jsr bear.deploy 174 | 175 | !nobear: 176 | 177 | jsr timer.init 178 | jsr hero.init 179 | jsr hud_init 180 | 181 | 182 | jsr get_ready 183 | 184 | gameloop: 185 | jsr framevsync 186 | 187 | jmp test_game_events //this could break the loop, so we jmp. 188 | return_from_test_game_events: 189 | jsr controls 190 | jsr environment.update 191 | jsr enemies.update 192 | jsr bear.update 193 | 194 | jsr hero.update 195 | jsr timer.tick 196 | 197 | inc clock 198 | jmp gameloop 199 | 200 | 201 | 202 | .macro test_object_collision(enemy0_active, offset_h0) 203 | { 204 | lda enemy0_active,x 205 | beq !en1+ 206 | ldy offset_h0,x 207 | cpy herox + 1 208 | beq !hit+ 209 | dey 210 | cpy herox + 1 211 | beq !hit+ 212 | jmp !en1+ 213 | !hit: 214 | lda enemies.enemylane.type,x 215 | cmp #ENEMY2CHARS //fish 216 | beq !fish+ 217 | cmp #ENEMY2CHARS + 4 218 | beq !fish+ 219 | !deadlyenemy: 220 | 221 | lda herostatus 222 | ora #STATUS_STUCK 223 | sta herostatus 224 | ldx #$ff 225 | jmp !en1+ 226 | 227 | !fish: 228 | 229 | lda #0 230 | sta enemy0_active,x 231 | jsr enemies.redraw_enemylane 232 | lda #2 233 | jsr add_score_xx 234 | 235 | :sfx(SFX_FISH) 236 | 237 | ldx #$ff //signal exit 238 | !en1: 239 | } 240 | 241 | 242 | test_game_events: 243 | { 244 | 245 | //additional controls 246 | lda key_clock 247 | beq !skp+ 248 | dec key_clock 249 | !skp: 250 | 251 | lda hud_clock 252 | beq !skp+ 253 | 254 | dec hud_clock 255 | bne !skp+ 256 | 257 | lda #[empty_sprite & $3fff] / 64 258 | sta irq_top.note_sprf + 1 259 | 260 | !skp: 261 | 262 | //check keypress for various things, such as pause or music on/off 263 | lda $dc01 264 | cmp #239 265 | bne !skp+ 266 | 267 | jsr pause 268 | lda #255 269 | 270 | !skp: 271 | 272 | cmp #253 273 | bne !skp+ 274 | 275 | jsr toggle_music 276 | 277 | 278 | !skp: 279 | 280 | 281 | //test if level complete 282 | //for a level to be complete, we need igloo_size = 16, hero_lane = 0 and a certain x position 283 | !next: 284 | lda igloo_size 285 | cmp #16 286 | bne !next+ 287 | 288 | lda herolane 289 | bne !next+ 290 | 291 | lda herox + 1 292 | cmp #30 293 | bne !next+ 294 | 295 | lda #STATUS_JUMPING 296 | bit herostatus 297 | bne !next+ 298 | 299 | lda controls.backup 300 | and #%00000001 301 | bne !next+ 302 | 303 | //level up! 304 | jmp end_of_level_sequence 305 | 306 | !next: 307 | //various deadly scenarios 308 | //1. tst if we are in the water 309 | 310 | lda #STATUS_JUMPING 311 | bit herostatus 312 | beq !nojmp+ 313 | jmp !next+ 314 | !nojmp: 315 | ldx herolane 316 | bne !noshore+ 317 | jmp !next+ 318 | !noshore: 319 | dex 320 | 321 | 322 | lda ghostd01f 323 | and #%10000000 324 | bne !nodrown+ 325 | 326 | jmp death_by_drowning 327 | 328 | !nodrown: 329 | // test if we hit an object 330 | 331 | :test_object_collision(enemies.enemylane.enemy0_active, enemies.enemylane.offset_h0) 332 | cpx #$ff 333 | bne !skp+ 334 | jmp !next+ 335 | !skp: 336 | :test_object_collision(enemies.enemylane.enemy1_active, enemies.enemylane.offset_h1) 337 | cpx #$ff 338 | bne !skp+ 339 | jmp !next+ 340 | !skp: 341 | :test_object_collision(enemies.enemylane.enemy2_active, enemies.enemylane.offset_h2) 342 | //cpx #$ff 343 | //bne !skp+ 344 | //jmp !next+ 345 | 346 | //2second death scenario: time out 347 | !next: 348 | lda timer_value 349 | bpl !next+ 350 | 351 | jmp frozen_to_death 352 | 353 | !next: 354 | 355 | //third and last death scenario: Bear 356 | lda bear.active 357 | beq !next+ 358 | 359 | lda herolane 360 | bne !next+ 361 | 362 | lda #STATUS_JUMPING 363 | bit herostatus 364 | bne !next+ 365 | 366 | lda herox 367 | clc 368 | adc #%10000000 369 | lda herox + 1 370 | adc #0 371 | cmp bear.xpos + 1 372 | bmi !next+ 373 | 374 | lda herox + 1 375 | sec 376 | sbc #4 377 | cmp bear.xpos + 1 378 | bpl !next+ 379 | 380 | jmp death_by_bear 381 | 382 | //test if a we cleared a slab, as report 383 | !next: 384 | lda #STATUS_CLEARED_SLAB 385 | bit herostatus 386 | beq !next+ 387 | 388 | ldx environment.slabcleared 389 | 390 | lda #1 391 | sta environment.slablane.status,x 392 | 393 | lda igloo_size 394 | cmp #16 395 | beq !skip_score+ 396 | 397 | lda level 398 | cmp #9 399 | bcc !skp+ 400 | lda #9 401 | 402 | !skp: 403 | jsr add_score_x 404 | 405 | jsr environment.build_igloo 406 | inc igloo_size 407 | 408 | lda #16 409 | sta environment.slablane.resetclock 410 | !skip_score: 411 | lda #$FF - STATUS_CLEARED_SLAB 412 | and herostatus 413 | sta herostatus 414 | 415 | lda music_on 416 | bne !skp+ //this effect can't be played if music on as it kills the jump effect 417 | :sfx(SFX_LANDING) 418 | !skp: 419 | 420 | !next: 421 | 422 | jmp return_from_test_game_events 423 | } 424 | 425 | 426 | game_over: 427 | { 428 | 429 | lda #4 //end jingle 430 | jsr sid.init 431 | 432 | lda #0 433 | sta heroy 434 | sta herolane 435 | sta herostatus 436 | 437 | lda #[empty_sprite & $3fff] / 64 438 | sta herof 439 | sta herof + 1 440 | sta herof + 2 441 | 442 | 443 | lda #1 444 | sta messagemode 445 | !l: 446 | jsr environment.update 447 | jsr enemies.update 448 | jsr bear.update 449 | 450 | jsr vsync 451 | inc clock 452 | lda #%00010000 453 | bit $dc00 454 | bne !l- 455 | 456 | jmp splashloop 457 | 458 | } 459 | 460 | get_ready: 461 | { 462 | lda #2 463 | sta messagemode 464 | ldx #96 465 | !: jsr wait_frames 466 | 467 | lda #0 468 | sta messagemode 469 | rts 470 | 471 | } 472 | 473 | death_by_bear: 474 | { 475 | 476 | lda clock 477 | and #%11111110 478 | sta clock //prevents bear from switching direction 479 | 480 | lda bear.speed 481 | sta savesp + 1 482 | 483 | 484 | lda #%00111000 485 | sta bear.speed 486 | 487 | ldx bear.xpos + 1 488 | inx 489 | cpx herox + 1 490 | 491 | bcc !chase_right+ 492 | 493 | //chase left 494 | lda #STATUS_MOVING | STATUS_DIRECTION 495 | sta herostatus 496 | 497 | lda #1 498 | sta bear.direction 499 | 500 | !: 501 | jsr bear.update 502 | jsr hero.update 503 | 504 | lda controls.walkframe 505 | clc 506 | adc #8 507 | cmp #5*32 508 | bcc !skp+ 509 | lda #0 510 | !skp: 511 | sta controls.walkframe 512 | 513 | lda herox 514 | sec 515 | sbc #%01000000 516 | sta herox 517 | lda herox + 1 518 | sbc #0 519 | sta herox + 1 520 | cmp #$fd 521 | beq !done+ 522 | 523 | jsr framevsync 524 | inc clock 525 | lda clock 526 | and #$7 527 | bne !skp+ 528 | :sfx(SFX_BEAR) 529 | !skp: 530 | jmp !- 531 | 532 | !chase_right: 533 | 534 | //chase right 535 | lda #STATUS_MOVING 536 | sta herostatus 537 | 538 | lda #0 539 | sta bear.direction 540 | 541 | !: 542 | jsr bear.update 543 | jsr hero.update 544 | 545 | lda controls.walkframe 546 | clc 547 | adc #8 548 | cmp #5*32 549 | bcc !skp+ 550 | lda #0 551 | !skp: 552 | sta controls.walkframe 553 | 554 | lda herox 555 | clc 556 | adc #%01000000 557 | sta herox 558 | lda herox + 1 559 | adc #0 560 | sta herox + 1 561 | cmp #39 562 | beq !done+ 563 | 564 | jsr framevsync 565 | inc clock 566 | lda clock 567 | and #$7 568 | bne !skp+ 569 | :sfx(SFX_BEAR) 570 | !skp: 571 | jmp !- 572 | 573 | 574 | 575 | !done: 576 | savesp: lda #0 577 | sta bear.speed 578 | 579 | jmp death 580 | 581 | .byte clock 582 | } 583 | 584 | death_by_drowning: 585 | { 586 | //:B2_DECRUNCH(drown_sprites_src) 587 | 588 | :blithp(src_drown_sprites,drown_sprites,3) 589 | lda #[drown_sprites & $3fff] / 64 590 | sta herof 591 | lda #[drown_sprites & $3fff] / 64 + 2 592 | sta herof + 1 593 | lda #[drown_sprites & $3fff] / 64 + 4 594 | sta herof + 2 595 | 596 | :sfx(SFX_SPLASH) 597 | 598 | ldy #20 599 | !l: 600 | ldx #4 601 | jsr wait_frames 602 | jsr d_shift 603 | 604 | inc herof 605 | inc herof + 1 606 | inc herof + 2 607 | ldx #4 608 | jsr wait_frames 609 | jsr d_shift 610 | 611 | 612 | dec herof 613 | dec herof + 1 614 | dec herof + 2 615 | 616 | dey 617 | beq !done+ 618 | jmp !l- 619 | 620 | !done: 621 | jmp death 622 | 623 | 624 | d_shift: 625 | ldx #57 626 | !: 627 | .for (var i = 0; i < 6; i ++) 628 | { 629 | lda 64 * i + drown_sprites + 0,x 630 | sta 64 * i + drown_sprites + 3,x 631 | lda 64 * i + drown_sprites + 1,x 632 | sta 64 * i + drown_sprites + 4,x 633 | lda 64 * i + drown_sprites + 2,x 634 | sta 64 * i + drown_sprites + 5,x 635 | } 636 | 637 | dex 638 | dex 639 | dex 640 | bpl !- 641 | rts 642 | } 643 | 644 | frozen_to_death: 645 | { 646 | lda #6 647 | sta heroc 648 | lda #14 649 | sta heroc + 1 650 | lda #3 651 | sta heroc + 2 652 | 653 | ldx #32 654 | jsr wait_frames 655 | 656 | jmp death 657 | 658 | } 659 | 660 | death: 661 | { 662 | dec lives 663 | 664 | ldx #32 665 | jsr wait_frames 666 | 667 | lda lives 668 | beq !go+ 669 | 670 | lda #$02 671 | ldx music_on 672 | bne !skp+ 673 | lda #$03 674 | !skp: 675 | jsr sid.init 676 | !noinit: 677 | jmp lifeloop 678 | 679 | !go: jmp game_over 680 | } 681 | 682 | end_of_level_sequence: 683 | { 684 | //first thing, lets center the player 685 | lda #%10000000 - 1 686 | sta herox 687 | 688 | lda #[crawl_sprites & $3fff] / 64 689 | sta herof + 1 690 | 691 | lda #[empty_sprite & $3fff] / 64 692 | sta herof 693 | sta herof + 2 694 | 695 | 696 | //color time white 697 | jsr color_hud_area 698 | 699 | :sfx(SFX_JUMP) 700 | 701 | !: 702 | ldx #8 703 | jsr wait_frames 704 | inc herof + 1 705 | lda herof + 1 706 | cmp #[crawl_sprites & $3fff] / 64 + 7 707 | bne !- 708 | 709 | lda #[empty_sprite & $3fff] / 64 710 | sta herof + 1 711 | 712 | lda level 713 | cmp #10 714 | bcc !ok+ 715 | lda #9 716 | !ok: 717 | sta igscr + 1 718 | sta tmscr + 1 719 | jsr add_score_x 720 | ldx #6 721 | jsr wait_frames 722 | 723 | 724 | !: jsr environment.break_igloo 725 | 726 | :sfx(SFX_IGLOO) 727 | 728 | igscr: lda #$00 729 | jsr add_score_x 730 | 731 | ldx #6 732 | jsr wait_frames 733 | lda igloo_size 734 | bne !- 735 | 736 | //now add score for the remaining time 737 | lda timer_value 738 | bmi !next+ 739 | !: 740 | lda timer_value 741 | ora timer_value + 1 742 | beq !next+ 743 | 744 | :sfx(SFX_BONUS) 745 | 746 | tmscr: lda #0 747 | jsr add_score_x 748 | 749 | dec timer_value + 1 750 | bpl !upd+ 751 | lda #9 752 | sta timer_value + 1 753 | dec timer_value 754 | 755 | !upd: 756 | jsr timer.update 757 | 758 | ldx #5 759 | jsr wait_frames 760 | 761 | jmp !- 762 | 763 | !next: 764 | inc level 765 | 766 | ldx #0 767 | 768 | lda level 769 | sec 770 | sbc #1 771 | and #3 772 | bne !skp+ 773 | inx 774 | !skp: 775 | stx mustredraw 776 | jmp levelloop 777 | } 778 | 779 | init_game: 780 | { 781 | 782 | lda #4 783 | sta lives 784 | 785 | lda #0 786 | 787 | sta messagemode 788 | sta frameflag 789 | 790 | ldx #5 791 | !: sta score,x 792 | dex 793 | bpl !- 794 | 795 | lda #0 796 | sta key_clock 797 | 798 | lda #127 799 | sta hud_clock 800 | 801 | lda #[note_sprites & $3fff] / 64 + 0 802 | sta irq_top.note_sprf + 1 803 | 804 | lda #1 805 | sta music_on 806 | 807 | jsr set_sfx_routine 808 | 809 | lda #2 810 | jsr sid.init 811 | 812 | rts 813 | } 814 | 815 | 816 | init_level: 817 | { 818 | 819 | jsr bear.off 820 | 821 | ldx level 822 | dex 823 | cpx #48 824 | bcc !skp+ 825 | 826 | ldx #47 827 | 828 | !skp: 829 | 830 | lda jumpspeed_table,x 831 | sta jumpspeed 832 | 833 | lda enemyspeed_table,x 834 | sta enemies.enemylane.speed 835 | 836 | sta bear.speed 837 | 838 | lda slabspeed_table,x 839 | sta environment.slablane.speed 840 | 841 | 842 | 843 | lda #%00110000 844 | sta walkspeed 845 | 846 | lda #%00000000 847 | sta environment.slablane.offset_l + 0 848 | lda #%01000000 849 | sta environment.slablane.offset_l + 1 850 | lda #%10000000 851 | sta environment.slablane.offset_l + 2 852 | lda #%11000000 853 | sta environment.slablane.offset_l + 3 854 | 855 | lda #24 856 | sta environment.slablane.offset_h + 0 857 | sta environment.slablane.offset_h + 2 858 | 859 | lda #0 860 | sta environment.slablane.offset_h + 1 861 | sta environment.slablane.offset_h + 3 862 | 863 | lda #0 864 | ldx #3 865 | !: 866 | sta environment.slablane.status,x 867 | dex 868 | bpl !- 869 | 870 | lda #1 871 | sta environment.slablane.direction + 0 872 | sta environment.slablane.direction + 2 873 | lda #0 874 | sta environment.slablane.direction + 1 875 | sta environment.slablane.direction + 3 876 | 877 | lda level 878 | cmp #4 879 | bne !skp+ 880 | //1,2,2,1 1,2,2,3... check notes 881 | lda #1 882 | jmp !str+ 883 | !skp: 884 | sec 885 | sbc #1 886 | and #3 887 | tax 888 | 889 | lda enemiesn_table,x 890 | 891 | !str: 892 | sta enemies.enemylane.enemiesperlane 893 | 894 | 895 | lda level 896 | sec 897 | sbc #1 898 | 899 | and #1 900 | 901 | ldx level 902 | cpx #5 903 | bcs !str+ 904 | 905 | asl 906 | 907 | !str: 908 | sta environment.slabtype 909 | 910 | ldx #3 911 | !: jsr environment.redraw_slab 912 | dex 913 | bpl !- 914 | 915 | rts 916 | 917 | 918 | // Speed table for various actors in the game. 919 | // Speed doesn't increse after level 48 (but good luck getting there!) 920 | slabspeed_table: 921 | .fill 48 , %00001000 * (i / 4.0 + 1.0) 922 | 923 | jumpspeed_table: 924 | .fill 48 , %00001000 * (i / 4.0 + 2.0) * 1.6 925 | 926 | enemyspeed_table: 927 | .fill 48 , %00001000 * (i / 4.0 + 1.0) * 1.5 928 | 929 | // Number of enemies per row, per level. 930 | enemiesn_table: 931 | .byte 1,2,2,3 932 | } 933 | 934 | .import source "environment.asm" 935 | .import source "hero.asm" 936 | .import source "controls.asm" 937 | .import source "hud.asm" 938 | .import source "enemies.asm" 939 | .import source "misc.asm" 940 | .import source "splash.asm" 941 | .import source "sfx.asm" 942 | 943 | 944 | init_screen_mode: 945 | { 946 | lda #$02 947 | sta $dd00 948 | lda #%00001110 //screen at $4000, chars at $7800 949 | sta $d018 950 | lda #$06 951 | sta $d021 952 | lda #$00 953 | sta $d020 954 | lda #$d0 955 | sta $d016 956 | 957 | 958 | ldx #0 959 | 960 | !: lda #9 + 0 961 | sta $d800,x 962 | sta $d900,x 963 | sta $da00,x 964 | sta $db00,x 965 | lda #0 966 | sta scrn + $000,x 967 | sta scrn + $100,x 968 | sta scrn + $200,x 969 | sta scrn + $300,x 970 | 971 | inx 972 | bne !- 973 | 974 | rts 975 | } 976 | 977 | 978 | .macro irq_enemy_x(n) 979 | { 980 | lda enemies.enemylane.type + n 981 | sec 982 | sbc #ENEMY0CHARS 983 | lsr 984 | lsr 985 | lsr 986 | tax 987 | 988 | lda enemies.enemycolor0,x 989 | sta $d022 990 | lda enemies.enemycolor1,x 991 | sta $d023 992 | 993 | !scroll: 994 | lda enemies.enemylane.offset_l + n 995 | lsr 996 | lsr 997 | lsr 998 | lsr 999 | lsr 1000 | 1001 | //eor #%111 1002 | ora #$d0 1003 | sta $d016 1004 | } 1005 | 1006 | .macro irq_slab_x(n) 1007 | { 1008 | ldx environment.slablane.status + n 1009 | 1010 | lda environment.slabcolor0,x 1011 | sta $d022 1012 | lda environment.slabcolor1,x 1013 | sta $d023 1014 | 1015 | 1016 | !scroll: 1017 | lda environment.slablane.offset_l + n 1018 | lsr 1019 | lsr 1020 | lsr 1021 | lsr 1022 | lsr 1023 | 1024 | eor #%111 1025 | ora #$d0 1026 | sta $d016 1027 | } 1028 | 1029 | 1030 | // Irq-split handlers 1031 | // They mostly handle bg and mc color change and the scroll for the enemies and slabs lanes 1032 | // This game is quite raster-split intensive 1033 | 1034 | 1035 | // Sets HUD sprits and plays music 1036 | irq_top: 1037 | { 1038 | sta savea + 1 1039 | stx savex + 1 1040 | sty savey + 1 1041 | 1042 | jsr random_ 1043 | 1044 | 1045 | skycolor: lda #$0e 1046 | sta $d021 1047 | 1048 | lda #$d0 1049 | sta $d016 //reset screen 1050 | 1051 | 1052 | jsr sid.play 1053 | 1054 | lda #$00 1055 | sta $d022 1056 | lda #$00 1057 | sta $d023 1058 | 1059 | lda #$ff 1060 | sta $d01c 1061 | 1062 | lda #$00 1063 | sta $d025 1064 | lda #$0f 1065 | sta $d026 1066 | 1067 | lda #%00001111 1068 | sta $d015 1069 | lda #0 1070 | sta $d010 1071 | 1072 | 1073 | lda #48 1074 | sta $d001 1075 | sta $d003 1076 | sta $d005 1077 | sta $d007 1078 | 1079 | lda #36 1080 | 1081 | sta $d000 1082 | sta $d002 1083 | sta $d004 1084 | 1085 | lda #132 1086 | sta $d006 1087 | 1088 | 1089 | lda #[hud_lives & $3fff] / 64 + 0 1090 | sta scrn + $3f8 + 0 1091 | lda #[hud_lives & $3fff] / 64 + 1 1092 | sta scrn + $3f8 + 1 1093 | lda #[hud_lives & $3fff] / 64 + 2 1094 | sta scrn + $3f8 + 2 1095 | 1096 | note_sprf: 1097 | lda #[note_sprites & $3fff] / 64 1098 | sta scrn + $3f8 + 3 1099 | 1100 | lda #7 1101 | sta $d027 1102 | lda #8 1103 | sta $d027 + 1 1104 | lda #10 1105 | sta $d027 + 2 1106 | 1107 | lda #2 1108 | sta $d027 + 3 1109 | 1110 | 1111 | lsr $d019 1112 | :setirq(irq_movetobmp, 51 + 19 - 3) 1113 | savea: lda #$00 1114 | savex: ldx #$00 1115 | savey: ldy #$00 1116 | 1117 | rti 1118 | } 1119 | 1120 | 1121 | // Switches to BMP mode for the shore 1122 | // Places game sprites 1123 | // Draws $d021 rasterbars for the sky effect 1124 | 1125 | irq_movetobmp: 1126 | { 1127 | 1128 | sta savea + 1 1129 | stx savex + 1 1130 | sty savey + 1 1131 | 1132 | lda #%11111111 1133 | sta $d01c 1134 | 1135 | lda #%00000111 //hero always on 1136 | sta $d015 1137 | 1138 | lda #%10000000 1139 | sta $d010 1140 | 1141 | 1142 | //igloo door 1143 | 1144 | lda igloo_size 1145 | cmp #16 1146 | bne !skp+ 1147 | 1148 | lda #%10000111 1149 | sta $d015 1150 | 1151 | !skp: 1152 | 1153 | lda #[door_sprite & $3fff] / 64 1154 | sta scrn + $3f8 + 7 // door 1155 | 1156 | lda #16 1157 | sta $d000 + 7 * 2 1158 | lda #86 1159 | sta $d001 + 7 * 2 1160 | 1161 | lda $d011 1162 | ora #$28 1163 | //lda #$3b 1164 | sta $d011 //bitmap mode, plus restore border 1165 | lda #%00001000 1166 | sta $d018 1167 | 1168 | 1169 | lda level 1170 | sec 1171 | sbc #1 1172 | and #4 1173 | bne !night+ 1174 | 1175 | //day 1176 | lda #0 1177 | sta $d027 + 7 1178 | jmp !bear+ 1179 | 1180 | !night: 1181 | ldx #2 1182 | lda random_.random 1183 | and #%00001111 1184 | beq !skp+ 1185 | ldx #7 1186 | !skp: 1187 | stx $d027 + 7 1188 | !bear: 1189 | //bear 1190 | lda bear.active 1191 | beq !skp+ //no bear 1192 | 1193 | lda $d015 1194 | ora #%01111000 1195 | sta $d015 1196 | 1197 | ldx bearf 1198 | stx scrn + $3f8 + 3 1199 | inx 1200 | stx scrn + $3f8 + 4 1201 | inx 1202 | stx scrn + $3f8 + 5 1203 | inx 1204 | stx scrn + $3f8 + 6 1205 | 1206 | lda bearc //#7 //0c 1207 | sta $d027 + 3 1208 | sta $d027 + 4 1209 | 1210 | lda bearc + 1 //#1 //0b 1211 | sta $d027 + 5 1212 | sta $d027 + 6 1213 | 1214 | lda bear.xpos 1215 | clc 1216 | adc #0 1217 | sta sprtmp 1218 | lda bear.xpos + 1 1219 | adc #3 //3 chars = 24 pixels, which is left border size 1220 | 1221 | asl sprtmp 1222 | rol 1223 | asl sprtmp 1224 | rol 1225 | asl sprtmp 1226 | rol 1227 | 1228 | sta $d000 + 3 * 2 1229 | sta $d000 + 5 * 2 1230 | 1231 | lda #0 1232 | sta sprtmp 1233 | 1234 | bcc !noov+ 1235 | lda $d010 1236 | ora #%00101000 1237 | sta $d010 1238 | 1239 | lda #1 1240 | sta sprtmp 1241 | !noov: 1242 | 1243 | lda $d000 + 3 * 2 1244 | clc 1245 | adc #24 1246 | sta $d000 + 4 * 2 1247 | sta $d000 + 6 * 2 1248 | 1249 | lda sprtmp 1250 | adc #0 1251 | beq !noov+ 1252 | 1253 | lda $d010 1254 | ora #%01010000 1255 | sta $d010 1256 | !noov: 1257 | 1258 | lda #96 1259 | sta $d001 + 3 * 2 1260 | sta $d001 + 4 * 2 1261 | sta $d001 + 5 * 2 1262 | sta $d001 + 6 * 2 1263 | 1264 | !skp: 1265 | //hero 1266 | lda heroc //#7 1267 | sta $d027 + 0 1268 | lda heroc + 1 //#8 1269 | sta $d027 + 1 1270 | lda heroc + 2 //#10 1271 | sta $d027 + 2 1272 | 1273 | 1274 | 1275 | lda herox 1276 | clc 1277 | adc #0 1278 | sta sprtmp 1279 | lda herox + 1 1280 | adc #3 //3 chars = 24 pixels, which is left border size 1281 | 1282 | asl sprtmp 1283 | rol 1284 | asl sprtmp 1285 | rol 1286 | asl sprtmp 1287 | rol 1288 | 1289 | sta $d000 1290 | sta $d002 1291 | sta $d004 1292 | 1293 | bcc !skp+ 1294 | lda $d010 1295 | ora #%00000111 1296 | sta $d010 1297 | 1298 | !skp: 1299 | 1300 | //clc 1301 | 1302 | lda herof 1303 | sta scrn + $3f8 + 0 1304 | 1305 | lda herof + 1 //adc #9 1306 | sta scrn + $3f8 + 1 1307 | 1308 | lda herof + 2 //adc #9 1309 | sta scrn + $3f8 + 2 1310 | 1311 | 1312 | ldx herolane 1313 | lda hero_y_offset,x 1314 | 1315 | sta heroy //temporary value 1316 | 1317 | lda #STATUS_JUMPING 1318 | bit herostatus 1319 | beq !skp+ 1320 | 1321 | ldx jumpclock 1322 | 1323 | lda #STATUS_YDIRECTION 1324 | bit herostatus 1325 | beq !jumpdown+ 1326 | 1327 | lda heroy 1328 | sec 1329 | sbc jump_trajectory_up,x 1330 | //sta heroy 1331 | jmp !str+ 1332 | !jumpdown: 1333 | 1334 | lda heroy 1335 | sec 1336 | sbc jump_trajectory_down,x 1337 | jmp !str+ 1338 | !skp: 1339 | 1340 | lda heroy 1341 | !str: 1342 | sta $d001 1343 | sta $d003 1344 | sta $d005 1345 | 1346 | 1347 | // gradient for the sky rasterbars 1348 | 1349 | 1350 | lda #51 + 25 - 1 1351 | !: cmp $d012 1352 | bcs !- 1353 | 1354 | 1355 | lda gradient_frame 1356 | and #%11110000 1357 | tay 1358 | 1359 | .for (var i = 0; i < 12; i++) 1360 | { 1361 | 1362 | .if (((i + 1 + 51 + 25) & 7) == %011) //badline 1363 | { 1364 | ldx gradient,y 1365 | 1366 | .fill 21, $ea //nop 1367 | iny 1368 | stx $d021 1369 | } 1370 | else 1371 | { 1372 | ldx gradient,y 1373 | iny 1374 | lda $d012 1375 | !: cmp $d012 1376 | beq !- 1377 | stx $d021 1378 | } 1379 | } 1380 | 1381 | lda gradient_frame 1382 | clc 1383 | adc #2 1384 | cmp #6 * 16 1385 | bcc !skp+ 1386 | lda #0 1387 | !skp: 1388 | sta gradient_frame 1389 | 1390 | !skp: 1391 | 1392 | pondcolor: lda #$06 1393 | sta $d021 1394 | 1395 | lsr $d019 1396 | :setirq(irq_sea, 51 + 72 - 3) 1397 | savea: lda #$00 1398 | savex: ldx #$00 1399 | savey: ldy #$00 1400 | rti 1401 | 1402 | gradient_frame: 1403 | .byte 0 1404 | } 1405 | 1406 | 1407 | 1408 | // Back to charmode 1409 | // Places the collision sprite. 1410 | // We can't use regular collision with the main sprite(s) to understand whether the hero is standing on something 1411 | // because the pseudo-3d nature of ice blocks. 1412 | // Bounding box approach is also not viable, because of the way the slabs animate. 1413 | // But pixel-perfect accuracy is required here, we use a fourth invisible sprite which has the same color of the sea 1414 | // and a lower priority than chars. This sprite has the shape of an imaginary poligon in the same pseudo-3d of 1415 | // the ice blocks. Something like this: 1416 | // 1417 | // ******* 1418 | // ******* 1419 | // ******* 1420 | // 1421 | // Despite its invisible nature, this sprite will still trigger HW collision detection. 1422 | 1423 | irq_sea: 1424 | { 1425 | sta savea + 1 1426 | stx savex + 1 1427 | 1428 | lda #$06 1429 | sta $d021 1430 | 1431 | lda herolane 1432 | beq !skp+ 1433 | 1434 | lda #STATUS_JUMPING 1435 | bit herostatus 1436 | bne !skp+ 1437 | 1438 | //place the collision sprite 1439 | //first, clear the $d01f flag 1440 | bit $d01f 1441 | lda #[collision_sprite & $3fff] / 64 1442 | sta scrn + $3f8 + 7 1443 | lda $d000 1444 | sta $d000 + 7 * 2 1445 | ldx $d001 1446 | //inx 1447 | stx $d001 + 7 * 2 1448 | lda $d010 1449 | and #%01111111 1450 | sta $d010 1451 | lsr 1452 | bcc !nof+ 1453 | lda $d010 1454 | ora #%10000000 1455 | sta $d010 1456 | 1457 | !nof: 1458 | lda #%10000111 1459 | sta $d015 1460 | lda #%10000000 1461 | sta $d01b 1462 | lda #%01111111 1463 | sta $d01c 1464 | lda #$06 1465 | sta $d027 + 7 1466 | 1467 | !skp: 1468 | 1469 | lda #51 + 72 1470 | !: cmp $d012 1471 | bcs !- 1472 | 1473 | lda #%00001110 1474 | sta $d018 1475 | 1476 | lda $d011 1477 | and #$ff - $20 1478 | //lda #$1b 1479 | sta $d011 1480 | 1481 | :irq_enemy_x(0) 1482 | 1483 | lda messagemode 1484 | bne !msg+ 1485 | 1486 | jmp !skp+ 1487 | 1488 | !msg: 1489 | ldx #152 1490 | 1491 | .for (var i = 0; i < 8; i++) 1492 | { 1493 | lda #87 + 24 * i 1494 | stx $d001 + i * 2 1495 | } 1496 | 1497 | 1498 | lda #3 1499 | .for (var i = 0; i < 8; i++) 1500 | { 1501 | sta $d027 + i 1502 | } 1503 | 1504 | lda messagemode 1505 | 1506 | asl 1507 | asl 1508 | asl 1509 | 1510 | adc #[gogr_sprites & $3fff] / 64 -8 + 7 1511 | ldx #7 1512 | sec 1513 | !: sta scrn + $3f8 , x 1514 | sbc #1 1515 | dex 1516 | bpl !- 1517 | 1518 | lda #0 1519 | sta $d010 1520 | lda #$ff 1521 | sta $d015 1522 | 1523 | lda #1 1524 | sta $d025 1525 | lda #14 1526 | sta $d026 1527 | 1528 | 1529 | .var xoff = 103 1530 | 1531 | lda messagemode 1532 | cmp #1 1533 | beq !go+ 1534 | 1535 | //get ready 1536 | .for (var i = 0; i < 3; i++) 1537 | { 1538 | lda #xoff 1539 | sta $d000 + i * 2 1540 | .eval xoff = xoff + 20 1541 | } 1542 | .eval xoff = xoff + 12 1543 | 1544 | .for (var i = 3; i < 8; i++) 1545 | { 1546 | lda #xoff 1547 | sta $d000 + i * 2 1548 | .eval xoff = xoff + 20 1549 | } 1550 | jmp !skp+ 1551 | 1552 | !go: 1553 | //get ready 1554 | .eval xoff = 103 1555 | .for (var i = 0; i < 4; i++) 1556 | { 1557 | lda #xoff 1558 | sta $d000 + i * 2 1559 | .eval xoff = xoff + 20 1560 | } 1561 | .eval xoff = xoff + 12 1562 | 1563 | .for (var i = 4; i < 8; i++) 1564 | { 1565 | lda #xoff 1566 | sta $d000 + i * 2 1567 | .eval xoff = xoff + 20 1568 | } 1569 | !skp: 1570 | lsr $d019 1571 | :setirq(irq_slab_0, 51 + 88 + 32 * 0) 1572 | savea: lda #$00 1573 | savex: ldx #$00 1574 | rti 1575 | } 1576 | 1577 | irq_slab_0: 1578 | { 1579 | sta savea + 1 1580 | stx savex + 1 1581 | 1582 | :irq_slab_x(0) 1583 | 1584 | lsr $d019 1585 | :setirq(irq_enemy_1, 51 + 88 + 32 * 0 + 16) 1586 | 1587 | savea: lda #$00 1588 | savex: ldx #$00 1589 | 1590 | rti 1591 | } 1592 | 1593 | irq_enemy_1: 1594 | { 1595 | sta savea + 1 1596 | stx savex + 1 1597 | 1598 | :irq_enemy_x(1) 1599 | 1600 | lsr $d019 1601 | :setirq(irq_slab_1, 51 + 88 + 32 * 1) 1602 | 1603 | savea: lda #$00 1604 | savex: ldx #$00 1605 | 1606 | rti 1607 | } 1608 | 1609 | irq_slab_1: 1610 | { 1611 | sta savea + 1 1612 | stx savex + 1 1613 | :irq_slab_x(1) 1614 | lsr $d019 1615 | :setirq(irq_enemy_2, 51 + 88 + 32 * 1 + 16) 1616 | 1617 | savea: lda #$00 1618 | savex: ldx #$00 1619 | 1620 | rti 1621 | } 1622 | 1623 | irq_enemy_2: 1624 | { 1625 | sta savea + 1 1626 | stx savex + 1 1627 | 1628 | :irq_enemy_x(2) 1629 | 1630 | lsr $d019 1631 | :setirq(irq_slab_2, 51 + 88 + 32 * 2) 1632 | 1633 | savea: lda #$00 1634 | savex: ldx #$00 1635 | 1636 | rti 1637 | } 1638 | 1639 | irq_slab_2: 1640 | { 1641 | sta savea + 1 1642 | stx savex + 1 1643 | :irq_slab_x(2) 1644 | lsr $d019 1645 | :setirq(irq_enemy_3, 51 + 88 + 32 * 2 + 16) 1646 | 1647 | savea: lda #$00 1648 | savex: ldx #$00 1649 | 1650 | rti 1651 | } 1652 | 1653 | irq_enemy_3: 1654 | { 1655 | sta savea + 1 1656 | stx savex + 1 1657 | 1658 | :irq_enemy_x(3) 1659 | 1660 | lsr $d019 1661 | :setirq(irq_slab_3, 51 + 88 + 32 * 3) 1662 | 1663 | savea: lda #$00 1664 | savex: ldx #$00 1665 | 1666 | rti 1667 | } 1668 | 1669 | irq_slab_3: 1670 | { 1671 | sta savea + 1 1672 | stx savex + 1 1673 | :irq_slab_x(3) 1674 | 1675 | lsr $d019 1676 | :setirq(irq_logo, $f9) 1677 | savea: lda #$00 1678 | savex: ldx #$00 1679 | 1680 | rti 1681 | } 1682 | 1683 | // Opens bottom border and places the activision logo, which is made of several sprites 1684 | 1685 | irq_logo: 1686 | { 1687 | sta savea + 1 1688 | stx savex + 1 1689 | 1690 | lda #1 1691 | sta frameflag //display has been drawn 1692 | 1693 | lda $d01f 1694 | sta ghostd01f //save the spr-bg collision register 1695 | 1696 | lda #$00 1697 | sta $d01b //restore priority 1698 | 1699 | lda $d011 1700 | and #$ff - 8 - $80 1701 | //lda #$13 1702 | sta $d011 //border off 1703 | 1704 | lda #$ff 1705 | sta $d015 1706 | 1707 | //place logo at $ff 1708 | lda #%00001000 1709 | sta $d01c 1710 | 1711 | lda #$0 1712 | sta $d010 1713 | 1714 | lda #[logo_bars & $3fff] / 64 1715 | sta scrn + $3f8 + 3 1716 | lda #[logo_bars & $3fff] / 64 + 1 1717 | sta scrn + $3f8 + 4 1718 | lda #[logo_bars & $3fff] / 64 + 2 1719 | sta scrn + $3f8 + 5 1720 | lda #[logo_bars & $3fff] / 64 + 3 1721 | sta scrn + $3f8 + 6 1722 | 1723 | ldx #1 1724 | 1725 | .for (var i = 0; i < 3; i++) 1726 | { 1727 | lda #[logo_sprites & $3fff] / 64 + i 1728 | sta scrn + $3f8 + i 1729 | stx $d027 + i 1730 | } 1731 | 1732 | lda #2 1733 | sta $d027 + 3 1734 | lda #8 1735 | sta $d025 1736 | lda #7 1737 | sta $d026 1738 | lda #5 1739 | sta $d027 + 4 1740 | lda #3 1741 | sta $d027 + 5 1742 | lda #6 1743 | sta $d027 + 6 1744 | 1745 | 1746 | lda #$ff 1747 | .for (var i = 0; i < 7; i++) 1748 | sta $d001 + i * 2 1749 | 1750 | .for (var i = 0; i < 3; i++) 1751 | { 1752 | lda #24 + 160 - 36 + 24 * i 1753 | sta $d000 + i * 2 1754 | } 1755 | 1756 | 1757 | lda #24 + 160 - 36 - 8 1758 | sta $d000 + 3 * 2 1759 | sta $d000 + 4 * 2 1760 | sta $d000 + 5 * 2 1761 | sta $d000 + 6 * 2 1762 | 1763 | 1764 | 1765 | lsr $d019 1766 | :setirq(irq_top, 8) 1767 | 1768 | savea: lda #$00 1769 | savex: ldx #$00 1770 | 1771 | rti 1772 | } 1773 | 1774 | // Switches music on or off, sets the SFX handler accordingly 1775 | toggle_music: 1776 | { 1777 | 1778 | lda key_clock 1779 | beq !skp+ 1780 | rts 1781 | 1782 | !skp: 1783 | 1784 | lda #$3f 1785 | sta key_clock 1786 | 1787 | jsr erase_sid 1788 | 1789 | 1790 | lda music_on 1791 | beq !switch_on+ 1792 | 1793 | //switch off 1794 | 1795 | lda #0 1796 | sta music_on 1797 | 1798 | lda #5 //mute tune 1799 | jsr sid.init 1800 | 1801 | lda #[note_sprites & $3fff] / 64 + 1 // crossed note 1802 | 1803 | jmp !next+ 1804 | !switch_on: 1805 | 1806 | lda #1 1807 | sta music_on 1808 | 1809 | lda #$0f 1810 | sta $d418 1811 | 1812 | lda #1 //music on, no level-start 1813 | jsr sid.init 1814 | 1815 | lda #[note_sprites & $3fff] / 64 //full note 1816 | 1817 | !next: 1818 | sta irq_top.note_sprf + 1 1819 | lda #127 1820 | sta hud_clock 1821 | 1822 | jsr set_sfx_routine 1823 | rts 1824 | 1825 | } 1826 | 1827 | 1828 | pause: 1829 | { 1830 | !: jsr framevsync 1831 | lda $dc01 1832 | cmp #239 1833 | beq !- 1834 | 1835 | !: jsr framevsync 1836 | lda $dc01 1837 | cmp #239 1838 | bne !- 1839 | 1840 | !: jsr framevsync 1841 | lda $dc01 1842 | cmp #239 1843 | beq !- 1844 | 1845 | rts 1846 | } 1847 | 1848 | clear_irq: 1849 | { 1850 | lda #$7f //CIA interrupt off 1851 | sta $dc0d 1852 | sta $dd0d 1853 | lda $dc0d 1854 | lda $dd0d 1855 | 1856 | lda #$01 //Raster interrupt on 1857 | sta $d01a 1858 | lsr $d019 1859 | rts 1860 | } 1861 | 1862 | 1863 | wait_frames: 1864 | { 1865 | !: jsr vsync 1866 | dex 1867 | bne !- 1868 | rts 1869 | } 1870 | 1871 | .macro LoadSprite(pic,x0,y0,bg,col1,col2,col3) 1872 | { 1873 | .var p = LoadPicture(pic,List().add(bg,col1,col2,col3)) //bg,mc1,spritecolor,mc2 1874 | .for (var y = y0; y < y0 + 21; y++) 1875 | .for (var x = x0; x < x0 + 3; x++) 1876 | .byte p.getMulticolorByte(x,y) 1877 | .byte col1 1878 | } 1879 | 1880 | .pc = $4400 "sprites" 1881 | hero_sprites: 1882 | .for (var s = 0; s < 7; s++) 1883 | :LoadSprite("..\gfx\hero.png", 3 * s, 0, $ffffff,$000000,$D5DF7C,$b3b3b3) 1884 | 1885 | .for (var s = 0; s < 7; s++) 1886 | :LoadSprite("..\gfx\hero.png", 3 * s, 0, $ffffff,$000001,$99692D,$b3b3b1) 1887 | 1888 | .for (var s = 0; s < 7; s++) 1889 | :LoadSprite("..\gfx\hero.png", 3 * s, 0, $ffffff,$000001,$C18178,$b3b3b1) 1890 | 1891 | //mirror 1892 | .for (var s = 8; s >= 2; s--) 1893 | :LoadSprite("..\gfx\hero.png", 3 * s, 24, $ffffff,$000000,$D5DF7C,$b3b3b3) 1894 | 1895 | .for (var s = 8; s >= 2; s--) 1896 | :LoadSprite("..\gfx\hero.png", 3 * s, 24, $ffffff,$000001,$99692D,$b3b3b1) 1897 | 1898 | .for (var s = 8; s >= 2; s--) 1899 | :LoadSprite("..\gfx\hero.png", 3 * s, 24, $ffffff,$000001,$C18178,$b3b3b1) 1900 | 1901 | 1902 | crawl_sprites: 1903 | .import binary "..\gfx\crawl.bin" 1904 | 1905 | //empty frames, for the source sprites to be copied 1906 | drown_sprites: 1907 | .fill 6 * 64 , 0 1908 | 1909 | collision_sprite: 1910 | .fill 57,0 1911 | 1912 | .byte %00000011,%11111111,%11000000 1913 | .byte %00000111,%11111111,%11100000 1914 | .byte 0 1915 | 1916 | 1917 | empty_sprite: 1918 | .fill 64,0 1919 | 1920 | door_sprite: 1921 | .import binary "..\gfx\door.bin" 1922 | 1923 | 1924 | hud_lives: 1925 | :LoadSprite("..\gfx\hero.png", 0, 48, $ffffff,$000000,$D5DF7C,$b3b3b3) 1926 | 1927 | :LoadSprite("..\gfx\hero.png", 0, 48, $ffffff,$000001,$99692D,$b3b3b1) 1928 | 1929 | :LoadSprite("..\gfx\hero.png", 0, 48, $ffffff,$000001,$C18178,$b3b3b1) 1930 | 1931 | 1932 | note_sprites: 1933 | .import binary "..\gfx\note.bin" 1934 | 1935 | // 4 sprites for each bear frame. 1936 | // walk pattern is 6 frames 1937 | // total: 48 sprites 1938 | // We don't really place the sprites here, we just "allocate" memory for them. 1939 | // Sprite data will be blitted when needed 1940 | bear_sprites: 1941 | .fill 6*8*64,0 1942 | 1943 | 1944 | .pc = $6d00 "more sprites" 1945 | logo_bars: 1946 | .import binary "..\gfx\logo_bars.bin" 1947 | 1948 | logo_sprites: 1949 | 1950 | .var logopic = LoadPicture("..\gfx\logo_top.png",List().add($000000, $ffffff)) // bg,color 1951 | .for (var s = 0; s < 3; s++) 1952 | { 1953 | .for (var y=0; y<21; y++) 1954 | .for (var x=0; x<3; x++) 1955 | .byte logopic.getSinglecolorByte(x + s * 3,y) 1956 | .byte 0 1957 | } 1958 | 1959 | // Game Over and Get Ready Sprites. 1960 | // Some chars duplicated, but who cares? Cruncher will take care of that 1961 | gogr_sprites: 1962 | .for (var y = 0; y < 2; y++) 1963 | .for(var x = 0; x < 8; x++) 1964 | :LoadSprite("..\gfx\gogr.png", x * 3, 21 * y, $3E31A2, $FFFFFF, $7ABFC7,$7C70DA) 1965 | 1966 | 1967 | // Allocate memory for the shore bitmap 1968 | .pc = $6000 "bitmap" 1969 | .fill 9 * 320, 0 1970 | 1971 | .fill 1 * 320, 0 //margin for switching mode 1972 | 1973 | .pc = $7800 "chars" 1974 | chars: 1975 | 1976 | //empychar 1977 | .fill 8,0 1978 | 1979 | //digits 1980 | digits: 1981 | .const digitpic = LoadPicture("..\gfx\digits_shadow.png", List().add($0000ff,$000000,$000001,$ffffff)) // bg,mc1,charcolor,mc2 1982 | .for (var c = 0; c < 20; c++) 1983 | .for (var b = 0; b < 8; b++) 1984 | .byte digitpic.getMulticolorByte(c,b) 1985 | 1986 | .label DEGREECHAR = (* - chars) / 8 1987 | .const degreepic = LoadPicture("..\gfx\degree_icon.png", List().add($0000ff,$000000,$000001,$ffffff)) // bg,mc1,mc2,charcolor 1988 | .for (var b = 0; b < 8; b++) 1989 | .byte degreepic.getMulticolorByte(0,b) 1990 | 1991 | 1992 | .label FISHCHARS = (* - chars) / 8 1993 | .const fishpic = LoadPicture("..\gfx\fish_icon.png", List().add($0000ff,$000000,$000001,$ffffff)) // bg,mc1,charcolor,mc2 1994 | .for (var c = 0; c < 2; c++) 1995 | .for (var b = 0; b < 8; b++) 1996 | .byte fishpic.getMulticolorByte(c,b) 1997 | 1998 | .label STARCHARS = (* - chars) / 8 1999 | starchars: 2000 | .const stc_ = LoadBinary("..\gfx\stars.imap") 2001 | //unfortunately, for charmaps larger than 32 chars, pixcen decides to assign the empty char to char 32 ($20). 2002 | //We want it to be zero, therefore we need to swap char 0 and 32 2003 | .var stc = List() 2004 | .for (var i = 0; i < stc_.getSize(); i++) 2005 | .eval stc.add(stc_.get(i)) 2006 | 2007 | .for (var i = 0; i < 8; i++) 2008 | { 2009 | .eval stc.set(i + 32 * 8,stc.get(i)) 2010 | .eval stc.set(i , 0) 2011 | } 2012 | 2013 | .fill stc.size() - 8, stc.get(i + 8) 2014 | 2015 | 2016 | .align 64 // 8 char (64 bytes) aligned. 2017 | 2018 | .label ENEMY0CHARS = (* - chars) / 8 2019 | enemy0: //bird 2020 | .fill 32,0 2021 | .fill 32,0 //left 2022 | 2023 | .label ENEMY1CHARS = (* - chars) / 8 2024 | enemy1: //crab 2025 | .fill 32,0 2026 | .fill 32,0 //left 2027 | 2028 | .label ENEMY2CHARS = (* - chars) / 8 2029 | enemy2: //fish 2030 | .fill 32,0 2031 | .fill 32,0 //left 2032 | 2033 | .label ENEMY3CHARS = (* - chars) / 8 2034 | enemy3: //shell 2035 | .fill 32,0 2036 | .fill 32,0 //left 2037 | 2038 | 2039 | slab0chars: 2040 | .const s0c = LoadBinary("..\gfx\platform0.imap") 2041 | .fill s0c.getSize() - 8, s0c.get(i + 8) 2042 | 2043 | slab1chars: 2044 | .const s1c_ = LoadBinary("..\gfx\platform1.imap") 2045 | 2046 | //unfortunately, for charmaps larger than 32 chars, pixcen decides to assign the empty char to char 32 ($20). we want it to be zero. 2047 | //therefore we need to swap char 0 and 32 2048 | .var s1c = List() 2049 | .for (var i = 0; i < s1c_.getSize(); i++) 2050 | .eval s1c.add(s1c_.get(i)) 2051 | 2052 | .for (var i = 0; i < 8; i++) 2053 | { 2054 | .eval s1c.set(i + 32 * 8,s1c.get(i)) 2055 | .eval s1c.set(i , 0) 2056 | } 2057 | 2058 | .fill s1c.size() - 8, s1c.get(i + 8) 2059 | 2060 | //ghost byte of vic bank $4000-$7fff. This must be $ff for open border color to be black 2061 | .pc = $7fff 2062 | .byte $ff 2063 | 2064 | .pc = $8000 "slab maps" 2065 | slab0map: 2066 | .const s0m = LoadBinary("..\gfx\platform0.iscr") 2067 | slab0map0: 2068 | .fill 40, s0m.get(i) == 0 ? 0 : s0m.get(i) -1 + (slab0chars-chars) / 8 2069 | .fill 40, s0m.get(i) == 0 ? 0 : s0m.get(i) -1 + (slab0chars-chars) / 8 2070 | slab0map1: 2071 | .fill 40, s0m.get(i + 40) == 0 ? 0 : s0m.get(i + 40) -1 + (slab0chars-chars) / 8 2072 | .fill 40, s0m.get(i + 40) == 0 ? 0 : s0m.get(i + 40) -1 + (slab0chars-chars) / 8 2073 | 2074 | 2075 | //we need to swap references to char 0 and 32. 2076 | .const s1m_ = LoadBinary("..\gfx\platform1.iscr") 2077 | .var s1m = List() 2078 | .for (var i = 0; i < s1m_.getSize(); i++) 2079 | .eval s1m.add(s1m_.uget(i) == 0 ? 32 : s1m_.uget(i) == 32 ? 0 : s1m_.uget(i)) 2080 | 2081 | //and now we have 9 frames for each of the charlines. 2082 | slab1map0: 2083 | .for (var frame = 0; frame < 9; frame++) 2084 | .for (var r = 0; r < 2; r++) 2085 | .fill 40, s1m.get(i + 0 + 80 * frame) == 0 ? 0 : s1m.get(i + 0 + 80 * frame) -1 + (slab1chars-chars) / 8 2086 | slab1map1: 2087 | .for (var frame = 0; frame < 9; frame++) 2088 | .for (var r = 0; r < 2; r++) 2089 | .fill 40, s1m.get(i + 40 + 80 * frame) == 0 ? 0 : s1m.get(i + 40 + 80 * frame) -1 + (slab1chars-chars) / 8 2090 | 2091 | 2092 | .pc = * "starmap" 2093 | 2094 | starmap: 2095 | //we need to swap references to char 0 and 32. 2096 | .const stm_ = LoadBinary("..\gfx\stars.iscr") 2097 | .var stm = List() 2098 | .for (var i = 0; i < stm_.getSize(); i++) 2099 | .eval stm.add(stm_.uget(i) == 0 ? 32 : stm_.uget(i) == 32 ? 0 : stm_.uget(i)) 2100 | 2101 | .fill stm.size(),stm.get(i) == 0 ? 0 : stm.get(i) - 1 + (starchars - chars) / 8 2102 | 2103 | 2104 | .label target_scenery_data = loaderbitmap 2105 | 2106 | .label brick_pattern = target_scenery_data 2107 | 2108 | .label shorecolordata = brick_pattern + 8*4 2109 | 2110 | .label shorescreendata = shorecolordata + 6*40 2111 | 2112 | .label shorebitmapdata = shorescreendata + 6*40 2113 | 2114 | .label gradient = shorebitmapdata + 6 * 320 2115 | 2116 | 2117 | .align 16 2118 | .pc = * "source scenery data" 2119 | src_day_data: 2120 | { 2121 | // .pc = brick_pattern 2122 | .fill 8*4, shorekla.getBitmap(9 * 320 + i) 2123 | 2124 | // .pc = shorecolordata 2125 | .fill 6 * 40, shorekla.getColorRam(i) 2126 | 2127 | // .pc = shorescreendata 2128 | .fill 6 * 40, shorekla.getScreenRam(i) 2129 | 2130 | // .pc = shorebitmapdata 2131 | .fill 6 * 320, shorekla.getBitmap(i) 2132 | 2133 | // .pc = gradient 2134 | .byte 04,04,14,14,10,10,03,03,07,07,01 2135 | .align 16 2136 | 2137 | .byte 04,14,10,14,10,10,03,03,07,07,01 2138 | .align 16 2139 | 2140 | .byte 04,14,10,14,10,03,10,07,07,07,01 2141 | .align 16 2142 | 2143 | .byte 04,14,10,14,10,03,10,07,01,07,01 2144 | .align 16 2145 | 2146 | .byte 04,04,14,14,10,03,10,07,01,07,01 2147 | .align 16 2148 | 2149 | .byte 04,04,14,14,10,10,03,03,01,07,01 2150 | .align 16 2151 | } 2152 | 2153 | src_night_data: 2154 | { 2155 | // .pc = brick_pattern 2156 | .fill 8*4, shorekla2.getBitmap(9 * 320 + i) 2157 | 2158 | // .pc = shorecolordata 2159 | .fill 6 * 40, shorekla2.getColorRam(i) 2160 | 2161 | // .pc = shorescreendata 2162 | .fill 6 * 40, shorekla2.getScreenRam(i) 2163 | 2164 | // .pc = shorebitmapdata 2165 | .fill 6 * 320, shorekla2.getBitmap(i) 2166 | 2167 | //.pc = gradient 2168 | .byte 06,00,06,04,06,04,14,10,03,07,01 2169 | .align 16 2170 | 2171 | .byte 06,04,06,04,14,04,14,10,03,07,01 2172 | .align 16 2173 | 2174 | .byte 06,04,06,04,14,10,03,10,03,07,01 2175 | .align 16 2176 | 2177 | .byte 06,04,06,04,14,10,03,07,01,07,01 2178 | .align 16 2179 | 2180 | .byte 06,00,06,04,14,10,03,07,01,07,01 2181 | .align 16 2182 | 2183 | .byte 06,00,06,04,06,14,03,10,01,07,01 2184 | .align 16 2185 | } 2186 | 2187 | 2188 | .pc = $f180 "enemy frame data" 2189 | .macro loadframes(file,n,row,colors) 2190 | { 2191 | .var pic = LoadPicture(file,colors) 2192 | .for (var frame = 0; frame < n; frame++) 2193 | .for (var cy = 0; cy < 2; cy++) 2194 | .for (var x = 0; x < 2; x++) 2195 | .for (var y = 0; y < 8; y++) 2196 | .byte pic.getMulticolorByte(frame * 2 + x, row * 16 + cy * 8 + y) 2197 | } 2198 | 2199 | //bird 2200 | enemybmp0r: 2201 | :loadframes("..\gfx\bird.png",2,0,List().add($483AAA,$000000,$99692D,$ffffff)) 2202 | enemybmp0l: 2203 | :loadframes("..\gfx\bird.png",2,1,List().add($483AAA,$000000,$99692D,$ffffff)) 2204 | 2205 | //crab 2206 | enemybmp1r: 2207 | :loadframes("..\gfx\crab.png",10,0,List().add($483AAA,$924A40,$C18178,$ffffff)) 2208 | 2209 | //fish 2210 | enemybmp2r: 2211 | :loadframes("..\gfx\fish.png",10,0,List().add($483AAA,$72B14B,$B3EC91,$ffffff)) 2212 | enemybmp2l: 2213 | :loadframes("..\gfx\fish.png",10,1,List().add($483AAA,$72B14B,$B3EC91,$ffffff)) 2214 | 2215 | //shell 2216 | enemybmp3r: 2217 | :loadframes("..\gfx\shell.png",10,0,List().add($483AAA,$99692D,$D5DF7C,$ffffff)) 2218 | 2219 | 2220 | 2221 | .pc = $e400 "bear sprites" 2222 | src_day_bear: 2223 | { 2224 | 2225 | //right 2226 | .for (var s = 0; s < 6; s++) 2227 | { 2228 | :LoadSprite("..\gfx\bear2.png", 6 * s, 8 + 24, $483AAA, $000001, $D5DF7C,$000002) 2229 | :LoadSprite("..\gfx\bear2.png", 6 * s + 3, 8 + 24, $483AAA, $000000, $D5DF7C,$000002) 2230 | 2231 | :LoadSprite("..\gfx\bear2.png", 6 * s, 8 + 24, $483AAA, $000000, $ffffff,$b3b3b3) 2232 | :LoadSprite("..\gfx\bear2.png", 6 * s + 3, 8 + 24, $483AAA, $000000, $ffffff,$b3b3b3) 2233 | } 2234 | 2235 | // we don't store left-facing sprites. We can just compute them by mirroring the previous set 2236 | 2237 | /* 2238 | //left 2239 | .for (var s = 0; s < 6; s++) 2240 | { 2241 | :LoadSprite("..\gfx\bear2.png", 6 * s, 8, $483AAA, $000001, $D5DF7C,$000002) 2242 | :LoadSprite("..\gfx\bear2.png", 6 * s + 3, 8, $483AAA, $000000, $D5DF7C,$000002) 2243 | 2244 | :LoadSprite("..\gfx\bear2.png", 6 * s, 8, $483AAA, $000000, $ffffff,$b3b3b3) 2245 | :LoadSprite("..\gfx\bear2.png", 6 * s + 3, 8, $483AAA, $000000, $ffffff,$b3b3b3) 2246 | } 2247 | */ 2248 | } 2249 | 2250 | src_night_bear: 2251 | { 2252 | //right 2253 | .for (var s = 0; s < 6; s++) 2254 | { 2255 | :LoadSprite("..\gfx\darkbear.png", 6 * s, 8 + 24, $483AAA, $000001, $8A8A8A,$000002) 2256 | :LoadSprite("..\gfx\darkbear.png", 6 * s + 3, 8 + 24, $483AAA, $000000, $8A8A8A,$000002) 2257 | 2258 | :LoadSprite("..\gfx\darkbear.png", 6 * s, 8 + 24, $483AAA, $000000, $606060,$b3b3b3) 2259 | :LoadSprite("..\gfx\darkbear.png", 6 * s + 3, 8 + 24, $483AAA, $000000, $606060,$b3b3b3) 2260 | } 2261 | 2262 | /* 2263 | //left 2264 | .for (var s = 0; s < 6; s++) 2265 | { 2266 | :LoadSprite("..\gfx\darkbear.png", 6 * s, 8, $483AAA, $000001, $8A8A8A,$000002) 2267 | :LoadSprite("..\gfx\darkbear.png", 6 * s + 3, 8, $483AAA, $000000, $8A8A8A,$000002) 2268 | 2269 | :LoadSprite("..\gfx\darkbear.png", 6 * s, 8, $483AAA, $000000, $606060,$b3b3b3) 2270 | :LoadSprite("..\gfx\darkbear.png", 6 * s + 3, 8, $483AAA, $000000, $606060,$b3b3b3) 2271 | } 2272 | */ 2273 | } 2274 | 2275 | 2276 | src_drown_sprites: 2277 | { 2278 | .for (var s = 7; s < 9; s++) 2279 | :LoadSprite("..\gfx\hero.png", 3 * s, 0, $ffffff,$000000,$D5DF7C,$b3b3b3) 2280 | 2281 | .for (var s = 7; s < 9; s++) 2282 | :LoadSprite("..\gfx\hero.png", 3 * s, 0, $ffffff,$000001,$99692D,$b3b3b1) 2283 | 2284 | .for (var s = 7; s < 9; s++) 2285 | :LoadSprite("..\gfx\hero.png", 3 * s, 0, $ffffff,$000001,$C18178,$b3b3b1) 2286 | } 2287 | 2288 | 2289 | .pc = $3400 + 40 * 17 "credits" 2290 | 2291 | .text " Adaptation by " 2292 | .text " " 2293 | .text " A. Savona : Code " 2294 | .text " S. Day : Graphics " 2295 | .text " S. Cross : Music, Sfx " 2296 | .text " " 2297 | 2298 | .text "Joystick up / down : Selects level - " 2299 | .text " Fire button : Starts game " 2300 | 2301 | .pc = $b400 "splash screen scr" 2302 | .import binary "..\gfx\credits.scr" 2303 | .pc = $a000 "splash screen map" 2304 | .const scm = LoadBinary("..\gfx\credits.map") 2305 | .fill 16 * 320, scm.get(i) 2306 | 2307 | 2308 | .pc = loaderbitmap "loader bmp" 2309 | .fill 8000, kla.getBitmap(i) 2310 | .pc = $b800 "loader col" 2311 | .fill 1000, kla.getColorRam(i) 2312 | .pc = $e000 "loader scr" 2313 | .fill 1000, kla.getScreenRam(i) 2314 | --------------------------------------------------------------------------------