├── .gitattributes ├── Build ├── G-Note.bin ├── G-Plane.bin ├── GG-01.asm ├── GG-02.asm ├── PIG-01.asm ├── PIG-02.asm ├── SS-01.asm ├── SS-02.asm ├── SS-03.asm ├── X.bin ├── build_birdstrike.asm └── style_guide.md ├── Clean ├── BIRDS ├── BS_Clean.ssd ├── G-Note.bin ├── G-Plane.bin ├── GG-01.asm ├── GG-02.asm ├── PIG-01.asm ├── PIG-02.asm ├── SS-01.asm ├── SS-03.asm ├── X.bin ├── build.cmd ├── build_birdstrike.asm ├── build_output.asm ├── labels.txt └── notes.todo ├── LICENSE ├── Original ├── $.!BOOT ├── $.!BOOT.INF ├── $.G ├── $.G.INF ├── $.HSTRS ├── $.HSTRS.INF ├── $.KEYS ├── $.KEYS.INF ├── $.OLDSRCE ├── $.OLDSRCE.INF ├── $.OLDSRCE.bas ├── $.PIGSRCE ├── $.PIGSRCE.INF ├── $.PIGSRCE.bas ├── $.S ├── $.S.INF ├── $.S.bas ├── $.X └── $.X.INF ├── README.md └── build_output.asm /.gitattributes: -------------------------------------------------------------------------------- 1 | *.bin linguist-vendored 2 | *.INF linguist-vendored 3 | *.asm linguist-language=Assembly 4 | -------------------------------------------------------------------------------- /Build/G-Note.bin: -------------------------------------------------------------------------------- 1 | <<8888888 8<88888888<88 880<<880,<(((=>><(,( -------------------------------------------------------------------------------- /Build/G-Plane.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qurm/BirdStrike/b13704515ac3996feeacb220ab03b2a1ba6c6869/Build/G-Plane.bin -------------------------------------------------------------------------------- /Build/GG-01.asm: -------------------------------------------------------------------------------- 1 | \ GG.asm converted from parts of $.OLDSRCE BIRD DISK Side 1 2 | \ and missing source "G" obtained from dissassembly of G binary file. 3 | \ (c) Andy Frigaard 1984 to May 2021 4 | \ The GG files were written first (1982-3) baed on $.OLDSRCE and were a playable game with 5 | \ many missing features. The main loop was overwritten and only the subroutines used. 6 | \ There are some later patches in the SS files. 7 | \ This source file is edited down to contain only required elements 8 | \ for a build using beebasm. 9 | \ Contains 10 | \ Draw Musical Stave 11 | 12 | \ I think &.OLDSOURCE is fairly definitive for &286E-&2D09 13 | \ (.mg to the start of the workspace / data areas at the top of the game). 14 | 15 | \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ 16 | \\ dissassembly from G binary 17 | \\ new labels align to Iains 18 | \.drawStave 19 | \ 21EE A0 00 LDY #&00 20 | 21 | \\ Draw one Musical Stave 22 | \\ Called from Draw Musical Staves, Notes, Play Tune 23 | \\ Calls JSR oswrch, using PLOT commands 24 | \\ Inputs: 25 | \\ Constants: 26 | \stave_base_addr = &80.. 27 | 28 | .draw_stave 29 | .stv 30 | { 31 | LDY #&00 32 | .stave_loop1 33 | LDA sl,Y: JSR oswrch 34 | INY: CPY #&09 35 | bne stave_loop1 36 | LDX #&05 37 | .stave_loop2 38 | LDY #&09 39 | .stave_loop3 40 | LDA sl,Y: JSR oswrch 41 | INY: CPY #&15 42 | BNE stave_loop3 43 | DEX 44 | BNE stave_loop2 45 | RTS 46 | .stave_data 47 | .sl 48 | EQUB &12, &00, &04 \ define graphics colour 49 | EQUB &19, &04, &00, &01, &EC, &03 \ PLOT K, X, Y 50 | EQUB &19, &01, &00, &03, &00, &00 \ PLOT K, X, Y 51 | EQUB &19, &00, &00, &fd, &f0, &ff \ PLOT K, X, Y 52 | } -------------------------------------------------------------------------------- /Build/GG-02.asm: -------------------------------------------------------------------------------- 1 | \ GG.asm converted from parts of $.OLDSRCE BIRD DISK Side 1 2 | \ and missing source "G" obtained from dissassembly of G binary file. 3 | \ (c) Andy Frigaard 1984 to May 2021 4 | \ The GG files were written first (1982-3) baed on $.OLDSRCE and were a playable game with 5 | \ many missing features. The main loop was overwritten and only the subroutines used. 6 | \ There are some later patches in the SS files. 7 | \ This source file is edited down to contain only required elements 8 | \ for a build using beebasm. 9 | \ Contains 10 | \ Setup of Sound envelopes, logical colours 11 | \ Move player gun, move bullets, move planes 12 | \ Move bombs,.. 13 | \ Data structures for above, lists, pointers, variables, constants 14 | 15 | 16 | \ I think $.OLDSOURCE is fairly definitive for &286E-&2D09 17 | \ (.mg to the start of the workspace / data areas at the top of the game). 18 | 19 | \ appears at .L281D 20 | \ 281D A9 13 LDA #&13 21 | 22 | \\ Define logical colours palette 23 | \\ Calls oswrch 24 | \\ Input: called with X=#15 to 8 :LDY #7 in setup 25 | \\ Input: called with X=0 Y=0 in gun_hit_display 26 | .D% 27 | .def_log_colour 28 | LDA #&13 29 | JSR oswrch \ Define logical colours OSWRCH &13 and 5 further bytes 30 | TXA 31 | JSR oswrch 32 | TYA 33 | JSR oswrch 34 | LDA #&00 35 | JSR oswrch 36 | JSR oswrch 37 | JMP oswrch 38 | 39 | \\ Define sound envelopes, similar to .env in OLDSRCE 40 | \\ Called from start_game 41 | \\ Calculates LSB of osword 8 call in X based on A at entry, &2D80, .. &2DC0 42 | \\ X = (A * 16) + &70 where 5>=A>0 43 | \\ (Y is not calculated, but should perhaps be something DIV 256) 44 | .E% 45 | .def_envelopes 46 | \envelope_base_addr = &2D80 \ base address &2D80, to &2DCF 47 | LDA no \ 5,4,3,2,1 48 | ASL A: ASL A: ASL A: ASL A \ multiply by 16 49 | ADC #&70 50 | TAX 51 | LDA #&08 \ osword define ENVELOPE, &14 bytes at Y,X addr 52 | LDY #HI(envelope_base_addr) \ &2D 53 | JSR osword 54 | DEC no 55 | BNE def_envelopes 56 | RTS 57 | 58 | .scr \ waits for Vsync? 59 | LDA #&02 60 | STA &FE4E \ Interrupt Enable Register 61 | .scri 62 | BIT &FE4D \ Interrupt Flag Register 63 | BEQ scri \ loop until interrupt 64 | LDA #&82 65 | STA &FE4E \ Interrupt Enable Register 66 | RTS 67 | 68 | \\ Plot score using custom sprites 69 | \\ Input: 70 | \\ A = LSB sprite offset 71 | \\ sf+1 = &1C 72 | \ was .W% \ W%=&285A plots some sprite? 73 | .plot_score 74 | { 75 | STA sf \ store offset lsb 76 | LDY #&0F \ length 16 bytes 77 | .loop 78 | LDA (sf),Y: STA (sd),Y 79 | DEY 80 | BPL loop \L285E 81 | CLC 82 | LDA sd: ADC #&10 83 | STA sd 84 | RTS 85 | } 86 | EQUB 00 87 | 88 | \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ 89 | 90 | 91 | \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ 92 | \\ start from OLDSRCE 93 | \\ then compare with the G binary 94 | 95 | \\ Move players gun 96 | \\ Called from main loop 97 | \\ Updates: Xg (x-coord), gunp (screen memory pos) 98 | \ TODO this has been modified in the released source 99 | \ set to RTS to disable - self-modifying code? SMC - see gun_hit_display routine 100 | \.smc_L286E 101 | \ 286E 60 RTS 102 | \ 286F D3 103 | \ 2870 28 104 | \ JSR gun 105 | .mg 106 | .move_gun 107 | JSR gun 108 | \ RTS: EQUW gun \ address of .gun &28D3 109 | 110 | LDA #&81:LDY #&FF:LDX #&BD \ http://beebwiki.mdfs.net/OSBYTE_%2681 111 | JSR osbyte \ check for "X" move right 112 | INX:BEQ r 113 | DEY:LDX #&9E:JSR osbyte \ check for "Z" move left 114 | INX:BNE gd 115 | .l \ move left 116 | LDX Xg:CPX #1:BEQ gd: \ check limit 117 | DEX:STX Xg:SEC: \ X coord -1 118 | LDA gunp:SBC#8:STA gunp:BCS gd \ screen memory pos -8 119 | DEC gunp+1:BCC gd \ always 120 | .r \ move right 121 | LDX Xg:CPX #71:BEQ gd: \ check right limit 122 | INX:STX Xg:CLC 123 | LDA gunp:ADC #8:STA gunp \ screen memory pos +8 124 | BCC gd 125 | INC gunp+1 126 | .gd 127 | SEC:LDA #0:STA pos:LDY #&24 \ clear pos, Y=base address index 128 | .ch 129 | LDA(gunp),Y:BEQ cop:STA pos \ store in pos 130 | .cop 131 | TYA:SBC #8:TAY:BPL ch \ Y=Y-8 repeat while Y> 0 132 | LDA pos:BEQ plot_gun_sprite \ if pos=0 skip ahead 133 | LDA sc:ORA #&20:STA sc \ sc = score flag - set bit &20, not used by score? 134 | 135 | \\ Gun, plot gun sprite XOR, from gunf,Y to (gunp),Y 136 | \\ MODE 2, single line for player gun 137 | \\ Sprite length cycles 40 bytes 138 | \\ Constants: 139 | \ \ gunf=&2358 (normal) gunf=&1A60 (explosion) 140 | gun_sprite_length=&27 \ &27=40 bytes 141 | .gun 142 | .plot_gun_sprite 143 | .modify_gun_length \ draw the players gun sprite 144 | { 145 | LDY #gun_sprite_length 146 | .gop \ gunf modified to &2358 by .sgun and gun_hit_display 147 | LDA gunf,Y:BEQ gz \ load sprite byte, skip XOR drawing for 0 148 | EOR(gunp),Y 149 | STA(gunp),Y \ XOR draw to screen 150 | .gz 151 | DEY:BPL gop \ repeat until Y<0 152 | RTS 153 | } 154 | 155 | \ table 156 | \ bulst[0] = no of bullets x 4 bytes, 8 => 2 bullets 157 | \ each bullet has 3 bytes 158 | \ bulst[0] = exp Y-coord in pixels 159 | \ bulst[1] = LO addr => sd 160 | \ bulst[2] = HI addr => sd 161 | \ bulst[3] = X-coord in pixels flag 162 | \ bfg zp flag, set to 2 intially, AND with &FE for 163 | 164 | \\ Move player bullets 165 | \\ Called from main loop 166 | \\ Inputs buf is sprite source address 167 | \\ Output: zp sf 168 | 169 | .mb 170 | .move_bullets 171 | { 172 | LDY #0:LDA(bulst),Y:STA no \ load count of bullets into no 173 | LDA buf:STA sf:LDA buf+1:STA sf+1 \ load bullet sprite into sf, sprite from 174 | .ntbu 175 | INY:LDA(bulst),Y:STA exp \ load from bullet list into zero page 176 | INY:LDA(bulst),Y:STA sd 177 | INY:LDA(bulst),Y:STA sd+1:BNE bu1 \ if bulst[2] = 0 then no bullet 178 | INY:LDA #&FE:AND bfg:STA bfg 179 | JMP nxbu 180 | .bu1 181 | INY:JSR plot_bullet_sprite \ XOR undraw plot_bullet_sprite 182 | LDA(bulst),Y:BPL bu2 \ if bulst[3] positive, then continue 183 | .bu7 184 | LDA#0:STA sd+1:BEQ nxbu \alws \ else terminate this bullet, set bulst[2] = 0 185 | .bu2 186 | SEC:LDA#7:AND sd:CMP#5:BMI bu3 \ move 5 bytes/pixels up 187 | LDA sd:SBC#5:STA sd:JMP bu4 \ either 8 bit subract 5, or 188 | .bu3 189 | LDA sd:SBC #&7D:STA sd \ 16 bit subtract &027D, for 1 row 190 | LDA sd+1:SBC#2:STA sd+1 191 | .bu4 192 | SEC:LDA exp:SBC#5:STA exp \ Y-coord - 5 193 | CMP #2:BEQ bu7 \ if exp is 2, then hit top? 194 | JSR plot_bullet_sprite \ draw plot_bullet_sprite 195 | .nxbu 196 | DEY:DEY:DEY 197 | LDA exp:STA(bulst),Y: \ restore from zp to bulst 198 | INY:LDA sd: STA(bulst),Y: 199 | INY:LDA sd+1:STA(bulst),Y: 200 | INY 201 | CPY no:BMI ntbu 202 | RTS 203 | } 204 | 205 | \\ New bullet, nb, player fires? 206 | \\ Called from main loop after Move Bullet 207 | \\ Calls JSR fpat, s5 plot_bullet_sprite 208 | \\ Inputs 209 | \\ Outputs 210 | \\ Sets values for bulst, bfg, sc (score) 211 | .new_bullet 212 | .nb \ first instruction is in G binary file, changed to RTS, &60 in gun_hit_display 213 | LDA #1 214 | \RTS:EQUB &01 \ SMC for LDA #1 215 | BIT bfg \ test can fire again? 216 | BNE nwb0 217 | LDA #&81:LDY#&FF:LDX#&B6 \ TODO changed LDX#&A6 to LDX#&B6 to fix player firing 218 | JSR osbyte \ OSBYTE 129 Read key, keyboard scan for ENTER -74 219 | INX:BEQ nwb1 220 | \ AF 7/6/21 align to published 221 | \ was LDA #&FD:AND bfg:STA bfg 222 | LDA #&00::STA fp0 : RTS \ SMC updates fp0 223 | .nwb0 224 | RTS 225 | 226 | \ AF 7/6/21 align to published 227 | \ was LDA#2:BIT bfg:BNE nwb0:LDY#255 228 | .nwb1 229 | \ LDA #2:BIT bfg 230 | JMP fpat: EQUB bfg \ fpat prior to fp0 above 231 | \\\\\\\\\\\\\\\\ fpat \\\\\\\\\\\\\\\\ 232 | \ LDA fp0:BEQ fp1 \ decrement counter, return if > 0 233 | \ DEC fp0:RTS 234 | \.fp1 235 | \ LDA #18:STA fp0 \ reset counter to 18 236 | \ JMP nwb_patch_return \ &297D 237 | \.fp0 238 | \ EQUB 0 \ modified above 239 | \\\\\\\\\\\\\\\\ end fpat \\\\\\\\\\\\\\\\ 240 | 241 | BNE nwb0 242 | .nwb_patch_return 243 | LDY #&FF 244 | .nwb2 245 | INY:INY:INY:INY 246 | LDA(bulst),Y:BNE nwb2 \ search for unused list entry, bulst[2] = 0 247 | DEY:DEY 248 | LDA #&9D:STA(bulst),Y: \ bulst[0] = 9D is y coord 249 | INY:SEC 250 | LDA gunp:SBC #&6E:STA(bulst),Y \ 16 bit subtract from gunp 251 | STA sd \ Bullet addr is (gunp-&026E) in bulst[1,2] 252 | INY:LDA gunp+1:SBC #2:STA(bulst),Y 253 | STA sd+1: 254 | INY:LDA Xg:CLC:ADC #3:STA(bulst),Y \ Bullet start X coord is (Xg+3) in bulst[3] 255 | JSR plot_bullet_sprite \ plot_bullet_sprite 256 | LDA #3:ORA bfg:STA bfg \ set bfg bit0,1 shows 2 bullets 257 | LDA #1:ORA sc:STA sc 258 | LDA #7:LDY #&2D:LDX #&D0 \ OSWORD - A=7 SOUND command at &2DD0 259 | JMP osword 260 | 261 | \ s5 Sprite/screen memory movement for bombs, bullets? 262 | \ uses EOR plotting, from sf, to st & sd (across 2 MODE 2 rows) 263 | \ called from mbo, Move Bombs, Move player bullets 264 | \ input is zero-page sd, sf address pointers; Y index 265 | \ output is zero-page st, address pointers and mod? 266 | \ Y is preserved 267 | .s5 268 | .plot_bullet_sprite 269 | { 270 | bullet_sprite_length=&05 271 | TYA:PHA: \ save Y 272 | LDY #bullet_sprite_length \ 6 bytes per bomb 273 | CLC: 274 | LDA sd:ADC #&78:STA st: \ add 1 row, &0278 and store in st 275 | LDA sd+1:ADC #2:STA st+1 276 | LDA sd:AND#7:EOR#7:STA mod \ modulo 277 | CMP #5:BPL top \ if all pixels are in top line, go to top 278 | .bot 279 | LDA(sf),Y:EOR(st),Y:STA(st),Y 280 | DEY:CPY mod:BNE bot \ Y-1, loop until = mod 281 | .top 282 | LDA(sf),Y:EOR(sd),Y:STA(sd),Y 283 | DEY:BPL top \ Y-1, loop until 0 284 | PLA:TAY: \ restore Y 285 | RTS 286 | } 287 | 288 | \TODO different to released source - self modified SMC here. 289 | \ .np is a RTS 290 | \ 29F6 60 RTS 291 | \.smc_L29F7 292 | \ 29F7 60 RTS 293 | \ 29F8 72 294 | 295 | \\ New plane, np, STarts a plane flying from the formation 296 | \\ Determines if level is complete if no planes remaining. 297 | \ pflg = plane flag - where init? 298 | .np 299 | LDA pflg \ AF 7/6/21 300 | \ RTS: EQUB pflg \ SMC in gun_hit_display 301 | CMP #01:BPL nw \ if any flag bit set, then RTS 302 | DEC ti:BNE nw \ ti=ti-1, if timer <> 0 then RTS 303 | LDA ti+1:STA ti: \ timer=0 so reset 304 | LDA no:JSR ra2:TAY:SEC 305 | .np2 \ renamed from .n2 306 | SBC #5:BPL np2:TAX 307 | .np3 308 | INY:INX:BNE np3 309 | DEY:LDA(pls),Y:BMI fy:LDY no 310 | .se 311 | DEY:LDA(pls),Y:BMI fy \ Y=Y-1 - if high bit, skip 312 | DEY:DEY:DEY:DEY:BNE se \ Y=Y-4, repeat until zero 313 | LDA #&80:ORA sc:STA sc \ not found, set sc level is complete 314 | RTS 315 | .fy 316 | EOR #&80:STA(pls),Y \ XOR high bit, set is flying 317 | .nw 318 | RTS 319 | 320 | \\ Plane Explosion animation plotting 321 | \\ selects the source sprite into plf, from plane or 322 | \\ from explosion animation 323 | \\ actual plotting is in JSR pp 324 | \explosion_sprite_addr = &1928 \ base for 3 animated sprites &30 long 325 | 326 | .pxp 327 | LDA exp:BEQ nx \ not explosion 328 | 329 | LDX #HI(explosion_sprite_addr):STX plf+1: \ set HI plane sprite to explosion 330 | LDA plf:PHA: 331 | LDA exp:CMP #21:BNE px1 332 | LDA #&40:STA plf: \ set LO plane sprite 333 | JSR pp:JMP px4 334 | .px1 335 | \ TODO align to published, as LDA #&40, was LDX #&0 336 | CMP #12:BNE px2: 337 | LDA #&40:STA plf: \ set LO plane sprite 338 | JSR pp: \TODO - repeats here? no px4 339 | LDA #&80:STA plf: \ set LO plane sprite 340 | JSR pp:JMP px4 341 | .px2 342 | CMP #6:BNE px3: 343 | LDA #&80:STA plf: \ set LO plane sprite 344 | JSR pp 345 | LDA #&C0:STA plf: \ set LO plane sprite 346 | JSR pp:JMP px4 347 | .px3 348 | CMP #1:BNE px4: 349 | LDA #&C0:STA plf: \ set LO plane sprite 350 | JSR pp 351 | .px4 352 | LDA #HI(plane_sprite_addr):STA plf+1 \ restore to plane_sprite_addr 353 | PLA:STA plf:DEC exp 354 | .nx JMP fo+3 355 | \\ End of Plane Explosion plotting 356 | 357 | 358 | \\ Move plane 359 | \\ Logic for random Left/Right and following player 360 | \\ Calls pxp, pp to determine sprite and plot 361 | \\ TODO - not efficient to copy all to zp if not moving this plane 362 | .mp 363 | LDY #0:LDA(pls),Y:STA no:STY pflg \ initial plfg=0 364 | .nxpl 365 | INY:LDA(pls),Y:STA exp \ load plane values to zero page 366 | INY:LDA(pls),Y:STA pos 367 | INY:LDA(pls),Y:STA pos+1 368 | INY:LDA(pls),Y:STA psta 369 | INY:LDA(pls),Y:STA yo 370 | LDA exp:AND #&C0:BNE p0 \ check for bottom screen? 371 | JMP pxp \ un-plot plane, remove prior to move 372 | .p0 373 | LDA psta:BPL p1 374 | JMP pl1 \ psta plane status not active, JMP next plane 375 | .p1 376 | DEC exp 377 | TYA:PHA: 378 | \\ plane hit bullet detection 379 | LDY#0:LDA(bulst),Y:STA sd: 380 | .h 381 | INY:LDA(bulst),Y:SEC:SBC yo:BMI nh:CMP#8:BPL nh 382 | INY:INY:LDA(bulst),Y:BEQ nh+2 383 | INY:LDA(bulst),Y:SEC:SBC psta:BMI nh+3 384 | CMP #7:BPL nh+3 385 | CMP #3:BEQ o: 386 | LDA #&40:ORA sc:STA sc: 387 | ASLA:STA(bulst),Y:BNEnh+3 \always 388 | .o 389 | LDA #25:STA exp: 390 | LDA #&D8:STA(bulst),Y:TAX 391 | LDA #7:LDY #&2D:JSR osword \ OSWORD - A=7 SOUND command at &2DD8 392 | PLA:TAY: 393 | LDA#2:ORA sc:STA sc 394 | JSR pp \ plot plane 395 | JMP pxp 396 | .nh INY:INY:INY: \ plane not hit 397 | CPY sd:BMI h: 398 | PLA:TAY 399 | LDA bofg:AND #&BF:STA bofg 400 | INC pflg:JSR pp:LDA yo:CMP #&AF:BNE hop5 401 | SEC:LDA pos:SBC #&87:STA pos: 402 | LDA pos+1:SBC #&48:STA pos+1 403 | LDA #&C0:STA yo: 404 | \ TODO [note: .nh 3xNOPs caused game exit. Substituting JSR &14D9 caused hang] 405 | \ NOP:NOP:NOP \ replace the JSR 406 | \ JSR h9 \ 22DC, seems to do nothing, RTS. Maybe modified code? 407 | \ bug or typo? 408 | JSR stp6 \ is 14D9 - patched code. 409 | 410 | .hop5 411 | LDA #&3F:AND exp:BNE mid 412 | SEC: 413 | LDA psta:SBC Xg:STA exp 414 | LDA #0:BCS pl3 415 | SEC:RORA 416 | .pl3 417 | RORA:STA sd: 418 | LDA exp:BNE pl5 419 | .pl20 420 | \ JSR &FFFF: \ TODO was this ever correct? FFFF 421 | JSR patch 422 | .pl5 423 | BPL pl4:EOR #&FF:CLC:ADC #1 424 | .pl4 425 | CMP #2:BMI pl6 426 | STA ra3+1:JSR ra2+3 427 | LSR ra3+1 428 | CLC:ADC ra3+1:AND #&3F 429 | .pl6 430 | ORA sd:STA exp 431 | .mid 432 | LDA exp:LDX psta:CPX#1:BPL plnl 433 | ORA #&40:AND #&7F:JMP do 434 | \\ end 435 | 436 | \\ Plane ? 437 | \\ renamed nl to plnl as conflict with note list 438 | .plnl 439 | CPX #72:BMI do+2:ORA #&80:AND #&BF 440 | .do 441 | STA exp:INC yo: 442 | LDA #7:AND pos:CMP #7:BEQ pl2 443 | INC pos:JMP lft 444 | .pl2 445 | CLC 446 | LDA pos:ADC #&79:STA pos \ 16 bit add &0279 to pos - 1 row mode 2? 447 | LDA pos+1:ADC #2:STA pos+1 448 | .lft \ move left? 449 | \LDA exp:ROLA 450 | JMP nlr \TODO was LDA exp:ROLA - now is patched code doing similar?? 451 | \ better plane movement? 452 | 453 | BCC rgt \ exp determines right or left 454 | DEC psta 455 | LDA pos:SBC #8:STA pos:BCS fo \ left pos=pos-8 456 | DEC pos+1 457 | JMP fo 458 | .rgt \ move right? 459 | INC psta:ROLA:BCC fo: 460 | CLC: 461 | LDA pos:ADC#8:STA pos:BCC fo \ right pos=pos+8 462 | INC pos+1 463 | \\ end Plane 464 | 465 | \\ fo plots plane, writes data back to list 466 | \ called from .pxp plane plotting, also labelled F% 467 | \ input Y=? where is Y set? 468 | .fo 469 | JSR pp 470 | DEY:DEY:DEY:DEY 471 | LDA exp:STA(pls),Y \ save back to plane_list 472 | INY:LDA pos:STA(pls),Y 473 | INY:LDA pos+1:STA(pls),Y 474 | INY:LDA psta:STA(pls),Y 475 | INY:LDA yo:STA(pls),Y 476 | .pl1 477 | CPY no:BEQ hop7 478 | JMP nxpl 479 | .hop7 480 | RTS 481 | \\ end fo 482 | 483 | \\ Plane plot .. 484 | \\ sprite plotting using XOR in MODE 2, when sprite 485 | \\ spans 2 lines uses 'top' and 'bottom' loops to write pixels across lines. 486 | \\ Called from start_game, .fo, after plane is plotted 487 | \\ input: 488 | \\ plf plane sprite from address, zero page 489 | \\ Y=? is preserved 490 | \\ used: 491 | \\ st sprite "to" address, zero page 492 | \\ pos to address, zero page 493 | .pp 494 | .plot_plane 495 | { 496 | plane_sprite_length=&3F \ &40 bytes sprite 497 | TYA:PHA 498 | CLC 499 | LDA pos:ADC #&78:STA st \ 16 bit add &0278 to pos - 1 row mode 2? 500 | AND #7:EOR #7:STA mod \6 to 1, XOR low 3 bits, invert, store in mod=&74 501 | LDA pos+1:ADC #2:STA st+1 \59+2=5b 502 | .*modify_plane_sprite_length 503 | LDY #plane_sprite_length \ SMC modified to change sprite length 504 | .plo 505 | LDX #7:CPX mod:BEQ tp \ if mod=7 then goto tp, top, else bottom 506 | 507 | .bt \ bottom 508 | LDA (plf),Y:BEQ bz \ optimisation, skip plotting zero bytes 509 | EOR (st),Y:STA (st),Y \ XOR write to screen 510 | .bz DEY 511 | DEX:CPX mod:BNE bt \ repeat inner loop until X=0 512 | 513 | .tp \ top 514 | LDA (plf),Y:BEQ tz 515 | EOR (pos),Y:STA (pos),Y 516 | .tz DEY 517 | DEX:BPL tp \ repeat inner loop until X=0 518 | TYA:BPL plo \ repeat outer loop until Y=0 519 | PLA:TAY \ exit and restore Y 520 | RTS 521 | } 522 | \\ end pp, Plane plot sprite 523 | 524 | 525 | \ New bombs 526 | .nbo 527 | \ LDA/RTS Gets changed to $A9 (LDA#) by gun_hit_display 528 | LDA #&C0 529 | \ RTS: EQUB &C0 \ TODO align to published. 530 | BIT bofg:BNE nbo4 531 | DEC bofg:BNE nbo4 532 | LDY #255 533 | .nbo2 534 | INY:INY:INY:INY:INY:LDA(pls),Y:BMI nbo2 535 | DEY:DEY:DEY:LDA(pls),Y:AND #&C0:BNE nbo5 536 | INY:INY:INY:JMP nbo2 537 | .nbo5 538 | INY:CLC:LDA(pls),Y:ADC #&9D:STA sd: 539 | INY:LDA(pls),Y:ADC#2:STA sd+1: 540 | JSR plot_bullet_sprite \ XOR remove plot_bullet_sprite 541 | LDY #0 542 | .nbo3 543 | INY:INY:LDA(bost),Y:BNE nbo3 \ find a free bomb slot 544 | LDA sd+1:STA(bost),Y:DEY:LDA sd:STA(bost),Y 545 | LDA inb:STA bofg \ store inb in bofg 546 | .nbo4 547 | LDA #&C0:ORA bofg:STA bofg:RTS 548 | 549 | \ Move bombs 550 | \ bost - bomb slot table 551 | .mbo 552 | LDY #0:LDA(bost),Y:STA no \ load no bombs, zero page 553 | LDA bof:STA sf:LDA bof+1:STA sf+1 \ load sprite locn, zero page 554 | .ntbo 555 | INY:LDA(bost),Y:STA sd: \load bomb into zero page sd 556 | INY:LDA(bost),Y:STA sd+1 557 | BNE bo1: 558 | LDA #&7F:AND bofg:STA bofg:JMP bo7 \ mask bofg, clear top bit 559 | .bo1 560 | JSR plot_bullet_sprite \ undraw plot_bullet_sprite 561 | LDA sd:AND#7:CMP#6:BPL bo2 562 | INC sd:INC sd:LDA sd+1:JMP bo4 \ bottom? 563 | .bo2 564 | CLC:LDA sd:ADC #&7A:STA sd \ add &027A to bomb screen address (n rows?) 565 | LDA sd+1:ADC #2:STA sd+1 566 | .bo4 567 | CMP #&80:BMI bo6: 568 | LDA #0:STA(bost),Y:BEQ bo7 \always \bomb hits bottom? set bost=0 569 | .bo6 570 | JSR plot_bullet_sprite \ re-draw plot_bullet_sprite 571 | DEY:LDA sd:STA(bost),Y: 572 | INY:LDA sd+1:STA(bost),Y \ put back in bomb table 573 | .bo7 574 | CPY no:BMI ntbo \ another bomb? then loop, or exit 575 | RTS 576 | 577 | \ Random number 578 | .ra2 579 | STA ra3+1:SEC:LDA py:AND #&7F: \ IFM - LDA was ra1 580 | .ra3 581 | SBC #&10:BPL ra3:ADC ra3+1: \IFM - SBC#10->SBC#&10 \[note: .ra3 has SBC #0 (disassembly is #&10)] 582 | RTS 583 | 584 | \ this is all zeroed in start_game 2D0A to 2D5E 585 | .bullet_list \ pointer to this in zero page bulst=&8A 586 | EQUB &08 \ contains max no of bullets 8 587 | EQUB &00,&00,&00,&00 \ exp, screen address sd, sd+1 588 | EQUB &00,&00,&00,&00 589 | \ TODO etc how many, 3 or 4 byte entries. 590 | 591 | \TODO OTHER Data here in published - Keys? 592 | .plane_list \ was pls_addr=&2D13 593 | EQUB &1E 594 | EQUB &00,&00,&00,&00,&00,&00,&00,&00 595 | EQUB &00,&00,&00,&00,&00,&00,&00,&00 596 | EQUB &00,&00,&00,&00,&00,&00,&00,&00 597 | EQUB &00,&00,&00,&00,&00,&00,&00,&00 598 | EQUB &00,&00,&00,&00,&00,&00,&00,&00 599 | EQUB &00,&00,&00,&00,&00,&00,&00,&00 600 | EQUB &00,&00,&00 \ padding 601 | \ IFM - L2D47 - sprite pointers? Maybe more? 602 | ORG &2D47 603 | 604 | \.L2D47 605 | .bomb_list \ pointer to this in zero page bost=&8C 606 | EQUB $02,$D6,$00,$00,$00,$00,$00,$00 607 | EQUB $00,$00,$00,$00,$00,$00,$00,$00 608 | EQUB $00,$00,$00,$00,$00,$00,$00,$00 609 | 610 | \.L2D5F 611 | .cloud_sprite_offset_list 612 | EQUB $80,$40,$40,$00,$80,$00,$40,$80 613 | EQUB $00 614 | 615 | .bis \ Pigeon sprite animation pointers (offsets from &1A00/&1B00) 616 | EQUB $88,$A0,$B8,$D0,$E8,$D0,$B8,$88 617 | 618 | .Xg 619 | EQUB $20 \ Player gun X coordinate 620 | .inb 621 | EQUB $D7 622 | .buf \.L2D72 623 | EQUB $00 \ Bullet sprite pointer low byte 624 | EQUB $1A \ Bullet sprite pointer high byte 625 | .bof 626 | EQUB $50 \ Enemy bomb sprite pointer low byte 627 | EQUB $23 \ Enemy bomb sprite pointer high byte 628 | 629 | .sc \ Score Counter flag byte 630 | EQUB $00 631 | \.sc+1 \ Score LSB in BCD, multiplied by 10 in display 632 | EQUB $00 633 | \.sc+2 \ Score MSB in BCD 634 | EQUB $00 635 | 636 | .de \de=&2D79 637 | EQUB $20 638 | .ti \.de+1 639 | EQUB $03 \ timer used to increase difficulty 640 | EQUB $42 \.de+1, ti+1 is a timer default, so when ti is zero is reset to value 641 | 642 | .ba \ ba is Bird Address LSB & 2D7D 643 | EQUB $00 644 | EQUB $00 \ ba+1 is Bird Address MSB set high bit when shot, AND #&80 645 | EQUB $06 \ ba+2 is index for sprite animation, set high bit when shot. 646 | EQUB $00 \ ba+3 X-coord column, set by L<>R direction #76 or #0, then inc/dec by 1 647 | 648 | ORG &2D80 649 | .envelope_base_addr \ IFM - envelope data 650 | EQUB $01,$81,$FD,$00,$00,$28,$00 \ Pigeon 'tweet' 651 | EQUB $00,$3C,$06,$CE,$CE,$3B,$7E 652 | EQUB $00,$00 \ Padding 653 | 654 | EQUB $02,$83,$00,$00,$00,$00,$00 \ Enemy explosion 655 | EQUB $00,$7F,$FF,$FE,$FF,$7E,$78 656 | EQUB $00,$00 657 | 658 | EQUB $03,$86,$FF,$00,$01,$02,$01 \ Player explosion 659 | EQUB $01,$7F,$FF,$FD,$FD,$7E,$78 660 | EQUB $00,$00 661 | 662 | EQUB $04,$81,$FB,$E6,$FE,$10,$01 \ Player fire 663 | EQUB $5A,$7F,$FE,$E2,$9C,$7E,$00 664 | EQUB $00,$00 665 | 666 | EQUB $05,$0A,$00,$00,$00,$01,$0C \ Tune voice 667 | EQUB $00,$7F,$F5,$00,$E2,$7E,$00 668 | EQUB $00,$00 669 | 670 | \ sounds definitions OSWORD 7 parameter block, 671 | \ XY+0..1=channel 672 | \ XY+2..3=volume or envelope 673 | \ XY+4..5=pitch 674 | \ XY+6..7=duration 675 | .sound_bullet \ 2DD0 676 | EQUB $12,$00,$04,$00,$50,$00,$14,$00 \ 677 | .sound_plane_hit \ 2DD8 678 | EQUB $10,$00,$02,$00,$06,$00,$A0,$00 679 | .sound_player_hit \ 2DE0 680 | EQUB $10,$00,$03,$00,$07,$00,$C8,$00 681 | .sound_bonus \ 2DE8 682 | EQUB $13,$00,$01,$00,$B4,$00,$0A,$00 683 | .sound_pigeon \ 2DF0 684 | EQUB $13,$00,$01,$00,$FA,$00,$0A,$00 685 | \ this definition is modified as tune is played 686 | .sound_note \ 2DF8 687 | EQUB &01,&00,&05,&00 688 | .sound_note_volume \ 2DFC 689 | EQUB &49,&00 690 | .sound_note_pitch \ 2DFE 691 | EQUB &0F,&00 692 | -------------------------------------------------------------------------------- /Build/PIG-01.asm: -------------------------------------------------------------------------------- 1 | \ converted from $.PIGSRCE BIRD DISK Side 1 2 | \ (c) Andy Frigaard 1984 to May 2021 3 | \ The PIG files were written later (1983-4) based on $.PIGSRCE and were a playable game with 4 | \ some missing features, a main loop calling routines from OLDSRCE. The main loop was later 5 | \ overwritten and only the subroutines used. 6 | \ This source file is edited down to contain only required elements 7 | \ for a build using beebasm. 8 | \ Contains 9 | \ Plot player gun indicator 10 | 11 | \ ORG = &21B8 \ P% = &21B8 12 | 13 | \\ &2FC0 is in the table/sprite space above .ba 14 | \\picn=&2FC0 \\bug ? typo \\ picn=&1D54 different value in PIGSRCE !! 15 | 16 | \ !Xg=&2F30CF20:!plf=&2F40:!bof=&2F38:!de=&420320 17 | \ ?bfg=2:!bulst=&2D472D0A:?&2D0A=8:?&2D47=20 18 | \ !pls=&2D13:?&2D13=25 19 | 20 | \ Program locations 21 | \ mostly are in the G, PIGSRCE memory space 22 | \ C%=&261A 23 | \ scr=&284A 24 | \w=&285A 25 | \X%=&258D 26 | \R%=&25B8 27 | \V%=&25C9 28 | \lg=&26B0 29 | 30 | \ OLDSRCE uses: !pls=&2D13:?&2D13=25 31 | \ pls_addr = &2D13, now plane_list 32 | 33 | \ AF 6/6/2021 moved to top to align to Iains 34 | \TODO minor differences here in .mini 35 | \ from here appears in G at 2223 36 | 37 | \\ Plot player gun indicator (small sprite, top left) initially 38 | \mini_gun_sprite_addr= &1910 \ temp player gun sprite &1928 or &1910 39 | .mini 40 | .plot_gun_life_indicator 41 | \ LDA #&C0:STA sf:LDA#9:STA sf+1: 42 | LDA #LO(mini_gun_sprite_addr):STA sf 43 | LDA #HI(mini_gun_sprite_addr):STA sf+1 \ IFM - LDA#19->LDA#&19 lives sprite ptr fix 44 | LDA gex+2:STA sd \ initial destination 45 | LDA gex+3:STA sd+1 46 | JMP plot_pigeon_sprite \ share pigeon sprite routine 47 | 48 | \\ from here appears in G at &2238 49 | \\ Player Hit display, also named H% 50 | \\ Called from main loop, after all moves, before score. 51 | .gun_hit_display 52 | .h0 53 | LDA #&20:BIT sc:BNE h1 \ if bit is set then hit, e 54 | LDA gex:BNE h12 55 | .hreturn 56 | RTS \2244 60 RTS 57 | .h1 58 | LDX #0:LDY#7:JSR def_log_colour \ define background as white? temp flash. 59 | LDA #7:LDY #&2D:LDX #&E0:JSR osword \ Sound 60 | LDA #&FF:STA gex \ counter for explosion 61 | LDA #&60:STA nbo:STA np:STA mg:STA nb \ this stores RTS in each routine, disabling them SMC 62 | JSR plot_gun_sprite \ un-draw sprite was .gun 63 | \ AF align to published as LDA #&1A , was LDA #&A 64 | LDA #&1A:STA gun+4:LDA #&10:STA gun+3 \ modify code with sprite source as &1A10 65 | JMP plot_gun_sprite \ re-draw sprite was .gun, exit. 66 | .h12 67 | DEC gex:LDA gex:CMP #254:BNE h3 \ gex, gun explosion, during which does not move etc 68 | LDX #0:LDY #0:JMP def_log_colour \ define background as white? temp flash. 69 | .h3 70 | CMP #&DC:BNE h4:JSR plot_gun_sprite \ show next different sprite offset, animation. 71 | LDA #&38:STA gun+3:JMP plot_gun_sprite 72 | .h4 73 | CMP #&8C:BNE h5:JSR plot_gun_sprite \ show next different sprite offset, animation. 74 | LDA #&60:STA gun+3:JMP plot_gun_sprite 75 | .h5 \ 22A7 C9 01 CMP #&01 76 | CMP #1:BNE hreturn: \ final counter = 1, then 77 | \ TODO differences with Ians source added lines 78 | DEC gex+1 \ &1D56 \ dec and check player lives >0 79 | BNE h5a \ added &22B3 80 | JMP game_over \ gov \ &14AE \ added 81 | .h5a 82 | JSR plot_gun_sprite 83 | JSR sgun \ added 84 | 85 | LDY plane_list \ process the plane list and if any have exp = C0 then un-draw 86 | .h6 87 | LDA(pls),Y:CMP #&C0:BNE h8 88 | DEY:LDA(pls),Y:BPL h9 89 | EOR #&80:STA(pls),Y 90 | DEY:LDA(pls),Y:STA pos+1 91 | DEY:LDA(pls),Y:STA pos 92 | JSR plot_plane 93 | JMP h10 94 | .h8 DEY: 95 | .h9 DEY:DEY: 96 | .h10 DEY:DEY:BNE h6 97 | .h7 \ modify these routines, replacing RTS with the correct opcode 98 | LDA #&20:STA mg \ #&20 = JSR opcode 99 | LDA #&A5:STA np \ #&A5 = LDA ZP opcode 100 | LDA #&A9:STA nbo:STA nb \ #&A9 = LDA# opcode 101 | \ TODO differences with Ians source 102 | \\ differences to G dissasm 103 | \ 22F4 CE 56 1D DEC &1D56 104 | \ 22F7 F0 0F BEQ &2308 105 | \ AF 6/6/2021 removed this line 106 | \ DEC gex+1:BEQ govX \ renamed govX but .gov is in SS, so cannot BEQ that far 107 | \ is this realy used? 108 | SEC: 109 | LDA gex+2:SBC #&18 \ set sprite screen position one left; was SBC#&20 110 | \ AF 6/6/2021 changed to JMP, was :JSR mini 111 | STA gex+2:JMP mini 112 | 113 | \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ 114 | \\ section is overwritten with data .nl, .tl, etc up to B% 115 | \ AF 6/6/2021 removed this line 116 | \ JMP sgun 117 | 118 | \ AF 6/6/2021 removed this line 119 | \.govX 120 | \ PLA:PLA:RTS 121 | 122 | \ from here appears in G at &2223 123 | \ ie different order 124 | \ AF 6/6/2021 moved to top 125 | \ .mini 126 | \ LDA #&C0:STA sf:LDA#9:STA sf+1: 127 | \ LDA gex+2:STA sd: 128 | \ LDA gex+3:STA sd+1 129 | \ JMP pb 130 | 131 | \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ 132 | \ also in SS.asm 133 | \ PIG.asm:56: error: Branch out of range. 134 | \ (Branch distance is -3411 bytes; 3283 more than the maximum -128.) 135 | \ renamed stp4 tp stp4b 136 | \ AF 6/6/2021 removed this line 137 | \ now branch to hreturn instead 138 | \.stp4b RTS 139 | \.stp6 140 | \ LDA gex:BEQ stp4:LDA psta:EOR #&80:STA psta 141 | \ PLA:PLA:JMP fo+3 142 | 143 | -------------------------------------------------------------------------------- /Build/PIG-02.asm: -------------------------------------------------------------------------------- 1 | \ converted from $.PIGSRCE BIRD DISK Side 1 2 | \ (c) Andy Frigaard 1984 to May 2021 3 | \ The PIG files were written later (1983-4) based on $.PIGSRCE and were a playable game with 4 | \ some missing features, a main loop calling routines from OLDSRCE. The main loop was later 5 | \ overwritten and only the subroutines used. 6 | \ This source file is edited down to contain only required elements 7 | \ for a build using beebasm. 8 | \ Contains 9 | \ Note, Tune data lists. 10 | \ Pigeon/bird initialise and move 11 | \ Plane hit animation 12 | \ Clouds and background scenery drawing and data 13 | 14 | 15 | \ 15/6/21 now includes background scenery data as EQUB (was in G-Scene.bin) 16 | 17 | 18 | \ Note list and Tune list source of music. 19 | \ nl=&2382 \ Note list &30 bytes, zero-terminated lists, 13,14,11,8 20 | \ tl=&23B2 \ Tune List pairs zero-terminated lists, pitch, duration, 16, 16, 16, 12, 8, 16, 1 21 | .nl 22 | EQUB $0D,$4A,$18,$8C,$8E,$1C,$8A,$84 23 | EQUB $14,$82,$20,$44,$05,$00,$48,$18 24 | EQUB $86,$84,$14,$86,$84,$14,$88,$2A 25 | EQUB $4E,$05,$00,$4A,$18,$8C,$8E,$1C 26 | EQUB $8A,$84,$14,$82,$20,$44,$00,$44 27 | EQUB $42,$42,$44,$46,$24,$14,$05,$00 28 | .tl 29 | \ Start of level / bonus tunes 30 | EQUB $65,$17,$5D,$05,$59,$0A,$65,$05 31 | EQUB $79,$0A,$81,$05,$89,$1E,$79,$1E 32 | EQUB $00,$6D,$17,$75,$05,$79,$0A,$75 33 | EQUB $05,$79,$0A,$6D,$05,$65,$1E,$59 34 | EQUB $1E,$00,$65,$17,$5D,$05,$59,$0A 35 | EQUB $65,$05,$79,$0A,$81,$05,$89,$1E 36 | EQUB $79,$0F,$00,$79,$0F,$81,$0F,$81 37 | EQUB $0F,$79,$0F,$75,$0F,$79,$1E,$00 38 | EQUB $59,$05,$59,$05,$59,$05,$49,$0F 39 | EQUB $00,$41,$05,$35,$0A,$39,$05,$3D 40 | EQUB $05,$41,$05,$65,$0A,$65,$0A,$55 41 | EQUB $14,$00,$14,$00 42 | 43 | \ ORG &240E 44 | \ from here appears in G at &240E 45 | \ also as B% 46 | 47 | \\ Pigeon, Move Bird 48 | \\ called from main loop 49 | \ &1A00 Bird Sprites, Flying Left? L=>R, on single page 50 | \ &1B00 Bird Sprites, Flying Right? R=>L, on single page 51 | \ bis is list of 7 Pigeon sprite animation pointers (offsets from &1A00/&1B00) 52 | \ EQUB $88,$A0,$B8,$D0,$E8,$D0,$B8,$88 53 | \ ba is Bird Address LSB & 2D7D 54 | \ ba+1 is Bird Address MSB set high bit when shot, AND #&80 55 | \ ba+2 is index for sprite animation, set high bit when shot. 56 | \ ba+3 X-coord column, set by L<>R direction #76 or #0, then inc/dec by 1 57 | \ py is pigeon Y-coord , multiple of 16 58 | \ picn pigeon counter, increment for each new one, used to alternate sides 59 | .pg 60 | \ TODO - Released source LDA #&1B (was &0B) - source of bird sprite? 61 | LDA #&1B:STA sf+1: 62 | LDA ba+1:BNE pgb0 \ Check if Bird is in flight, MSB <> 0 63 | LDA #&42:BIT sc:BEQ ep \ check Score byte flag 64 | 65 | \ TODO - BIT with picn = &1D54 66 | \ 2420 2C 54 1D BIT &1D54 67 | \ picn is 02FC in released - this was a possible bug 68 | LDA #02:BIT picn:BEQ pgl \ if pigeon counter is even, then fly L=>R 69 | 70 | \ Initialise Flying Right R=>F 71 | \ TODO - Released source LDA #&1B (was &0B) 72 | .pig_init_right 73 | LDA #&1B:STA sf+1:STA pg+1: 74 | LDA #&68:STA ba:STA sd: 75 | LDA #0:STA xps+1: \ set X-coord limit column 0, SMC modifies below 76 | LDA #76:STA ba+3 \ set X-coord var column=76 77 | LDA #&4B:STA b5-2:BNE b3 \ A=MSB of bird screen address SMC modifies #&49 or #&4B 78 | .pgl 79 | .pig_init_left 80 | \ Initialise Flying Left L=>R 81 | \ TODO - Released source LDA #&1A (was &0A) 82 | LDA #&1A:STA sf+1:STA pg+1 83 | LDA #0:STA ba:STA sd: 84 | STA ba+3 \ set X-coord var column=0 85 | LDA #76:STA xps+1 \ set X-coord limit column 76, SMC modifies below 86 | LDA #&49:STA b5-2 \ A=MSB of bird screen address SMC modifies #&49 or #&4B 87 | 88 | \ Initialise common Flying Left or Right 89 | .b3 90 | LDA #0:STA py \ new pigeon, Y-coord = 0 91 | INC picn \ inc pigeon counter 92 | 93 | LDA #7:AND ra1:TAX \ get random [0-7] in X 94 | \ TODO - Released source LDA #&4B 95 | LDA #&4B:CLC \SMC modified above #&49 or #&4B was initial &4B 96 | .b5 97 | ADC #5:TAY \ preserve A+5 in Y 98 | LDA py:ADC #16:STA py \ add 16, random times => random pigeon Y coord 99 | TYA \ recover A 100 | DEX:BPL b5 \ repeat X (random 0-7) times 101 | STA ba+1:STA sd+1 \ store MSB of bird address 102 | LDX #2:STX ba+2 \ store initial sprite offset value, 2 103 | LDA bis,X:STA sf \ select Sprite offset from "bis" table 104 | JMP pb \ do initial plotBirdSprite 105 | .ep 106 | RTS 107 | \ End Pigeon Initialise 108 | 109 | 110 | \ After intialisation, process bird, move, check hits. 111 | \ so renamed b0 to pgb0, another bo b1 in S.asm, different purpose 112 | .pgb0 113 | LDA ba:STA sd: \ copy Bird address to zero page sd 114 | LDA ba+1:STA sd+1:BPL pgb1 \ if high bit clear, then pigeon not hit, so branch 115 | 116 | DEC ba+2:BNE ep \ dec index for animation, point to next sprite 117 | \ why ep - maybe page boundary .x too far? 118 | EOR #&80:STA sd+1 \ fix sd+1 to high bit is clear 119 | 120 | \ TODO - Released source LDA #&10, was LDA #0, line order changed. 121 | \LDA #&10:STA ba+1 122 | \LDA #&10:ORA sc:STA sc 123 | 124 | LDA #&10:ORA sc:STA sc \ set Score byte flag 125 | LDA #&00:STA ba+1 \ clear bird address for next cycle 126 | BEQ bx \ go to plot the dead pigeon sprite 127 | 128 | \ so renamed b1 to pgb1 129 | .pgb1 130 | LDA ba+2:AND #&7F:TAX 131 | LDA bis,X:STA sf \ select Sprite offset from "bis" table 132 | LDY #0:LDA(bulst),Y:STA no: 133 | 134 | \ renamed h to pgh 135 | .pgh \ check pigeon is hit? 136 | INY:LDA(bulst),Y:SEC:SBC py:BMI pgnh 137 | CMP #7:BPL pgnh 138 | INY:INY:LDA(bulst),Y:BEQ pgnh+2 139 | INY:LDA(bulst),Y:SEC:SBC ba+3:BMI pgnh+3 140 | CMP #3:BPL pgnh+3 141 | LDA #&E8:STA(bulst),Y:TAX: 142 | LDA #7:LDY #&2D:JSR &FFF1 \ Sound 143 | LDA #&10:STA ba+2: \ store sprite offset value, 16 - dead pigeon? 144 | LDA #&80:ORA ba+1:STA ba+1 \ set address high bit for dead. 145 | JSR pb \ do plotBirdSprite & RTS 146 | .bx 147 | \ TODO - Released source LDA #&1B, was LDA #&B 148 | LDA #&1B:STA sf+1: 149 | LDA #&70:STA sf:JMP pb \ do plotBirdSprite & RTS 150 | .b9 151 | LDA #4:ORA sc:STA sc \ set Score byte flag 152 | LDA #0:STA ba+1 153 | .x 154 | RTS 155 | \ so renamed nh to pgnh 156 | .pgnh \ pigeon not hit 157 | INY:INY:INY: 158 | CPY no:BMI pgh \ loop again to check next bullet hit 159 | LDA #&80:EOR ba+2 \ toggle high bit for alternate cycles 160 | STA ba+2:BMI x \ skip and exit 1 in 2 cyles 161 | 162 | JSR pb \ Remove using XOR, do plotBirdSprite 163 | LDA ba+3 \ pigeon, get X-coord 164 | .xps 165 | \TODO - Released source CMP #00, was CMP #76 &4C 166 | CMP #00:BEQ b9 \ if pigeon at left/right of screen SMC 00 or 76 167 | AND #31:BNE b6 168 | LDA #7:LDY #&2D:LDX #&F0:JSR osword \ OSWORD - A=7 SOUND command at &2DF0 169 | .b6 170 | LDX ba+2:DEX:BPL b7 \ dec sprite animation offset value 171 | LDX #7 \ if=0, reset sprite animation index to 7 172 | .b7 173 | STX ba+2 174 | LDA bis,X:STA sf \ select Sprite offset from "bis" table 175 | LDA xps+1:BEQ b10 176 | \ moving L->R 177 | INC ba+3:CLC \ inc x-coord 178 | 179 | LDA ba:ADC #8:STA ba \ move right one pixel, 8 bytes 180 | STA sd:BCC pb 181 | INC ba+1:INC sd+1 182 | JMP pb \ do plotBirdSprite & RTS 183 | .b10 \ moving R->L 184 | DEC ba+3 \ dec x-coord 185 | SEC: LDA ba:SBC #8 \ move left one pixel, 8 bytes 186 | STA ba:STA sd:BCS pb 187 | DEC ba+1:DEC sd+1 \ pass through to plotBirdSprite 188 | 189 | \\ pb Plot Bird, draws bird sprites on screen 190 | \\ XOR plotting loop for &17 24 bytes 191 | \\ Inputs: (set above) 192 | \\ sf = sprite from address 193 | \\ sd = sprite destination address 194 | .plot_pigeon_sprite 195 | .pb 196 | { 197 | LDY #&17 198 | .b8 \ XOR plotting loop for &17 24 bytes 199 | LDA(sf),Y:EOR(sd),Y:STA(sd),Y 200 | DEY:BPL b8 201 | RTS 202 | } 203 | 204 | \\ PIG-02.asm below based on 205 | \\ missing source "G" obtained from dissassembly of G binary file 206 | \\ does background, line graphics. 207 | \\ Andy Frigaard May 2021 208 | \\ labels unknown - set to ddu1, ddu2, etc 209 | 210 | \\ Plane is hit 211 | \\ Called from sor, score routine 212 | \\ Inputs: (set above) 213 | \\ sf = sprite from address 214 | \\ sd = sprite destination address 215 | \\ Constants: 216 | plane_table = &1D40 \ in X.bin file 217 | plane_kill_count = &1D5B 218 | \ gex, gun explosion is gex=&1D55 and gex+1=&1D56 219 | \ &1D40: 31 7A D9 7C C9 77 12 7A C8 7C BA 77 51 7A B8 7C 1zY|Iw.zH|:wQz8| 220 | \ &1D50: 20 7A 42 7A 00 00 00 00 00 00 00 00 00 00 00 00 221 | \ also X% X%=&258D 222 | .ddu1 223 | .plane_hit \ X%=&258D 224 | LDY plane_kill_count \&1D5B \ plane kill counter 225 | CPY #&09 226 | BPL ddu3 \ if > 9 then exit routine &25B7 227 | LDA plane_table,Y: STA sd \ setup zp destination 228 | INY 229 | LDA plane_table,Y: STA sd+1 230 | INY 231 | STY plane_kill_count \&1D5B 232 | 233 | \ write #&55 to 5 234 | LDY #&04 \ loop 5 cycles 235 | LDA #&55 236 | .ddu2 237 | STA (sd),Y \ write (sd),4 (sd),3... 238 | DEY: BPL ddu2 \ 239 | 240 | \ write to (sd),9 (sd),1 241 | LDY #&09 242 | ASL A 243 | STA (sd),Y 244 | LDY #&01 245 | LDA #&FF 246 | STA (sd),Y 247 | .ddu3 248 | RTS 249 | \.L25B8 250 | 251 | \\ Random generator, was R% 252 | \\ Called from smain loop after vsync 253 | \\ Inputs: 254 | \\ ra, ra+1,ra+2 = zp address 255 | .random1 \ psuedo "random" number generator 256 | LDA ra1 257 | AND #&48 258 | ADC #&38 259 | ASL A: ASL A 260 | ROL ra1+2 261 | ROL ra1+1 262 | ROL ra1 263 | LDA ra1 264 | RTS 265 | 266 | \\ start draw_backgnd_art 267 | \\ reads from a table of VDU commands and parameters, 268 | \\ GCOL, PLOT, etc 269 | \\ then uses pp to draw scenry sprites. 270 | \\ Constants: 271 | \ modify_plane_sprite_length = &2C1E \ SMC length defined in pp routine. 272 | \ backgnd_sprite_addr_table = &27C3 \ part of scenery_line_art 273 | .draw_backgnd_art 274 | { 275 | LDY #&00 276 | .draw_line_art_loop 277 | LDA &26B0,Y: JSR oswrch \&FFEE 278 | INY 279 | BNE draw_line_art_loop \ loop 256 times 280 | 281 | \\ this uses the pp plane sprite routine and modifies that to change 282 | \\ the byte counter to LDA #&1F: STA &2C1E 283 | LDA plf: STA sf \ initialise zp locations 284 | LDA plf+1: STA sf+1 285 | LDA #&1F: STA modify_plane_sprite_length+1 \&2C1E 286 | LDA #%11100000: STA no \ store &E0 %11100000 in temp zp 287 | LDY #&00 288 | \.L25E7 289 | 290 | \ loop loads table of values that are source and 291 | \ destination sprite addresses, writes to zp, runs JSR pp. 292 | \ BIT sets the Z flag as though the value in the address tested were ANDed with the accumulator. The N and V flags are set to match bits 7 and 6 respectively in the value stored at the tested address. 293 | .draw_backgnd_sprite_loop 294 | INY: LDX &27C3,Y \ address LO; start Y=1 295 | INY: LDA &27C3,Y \ address HI 296 | BIT no: BNE skip1 \ use BIT to AND with A => all screen address 297 | STA plf+1: STX plf \ store source addr for sprite 298 | INY: LDX &27C3,Y \ use A & X to move 2 bytes per loop 299 | INY: LDA &27C3,Y 300 | .skip1 301 | STX pos \ store destination addr for 'top' row MODE 2, assumes sprite is on one row only 302 | STA pos+1 303 | JSR pp \ &2C08 plot plane sprites 304 | CPY &27C3 \ Check Y is < #&58, length of list 305 | BMI draw_backgnd_sprite_loop \ &25E7 306 | \ restore default settings for pp plane plot 307 | LDA #&3F: STA modify_plane_sprite_length+1 \&2C1E 308 | LDA sf: STA plf 309 | LDA sf+1: STA plf+1 310 | RTS 311 | } 312 | BRK \filler byte 313 | 314 | \\ plot_clouds draws clouds 315 | \\ Clouds are made up of 3 sections, upper, mid, lower. 316 | \ cloud_sprite_offset_list=&2D5F \ cloud sprite offset lookup list in GG-02 317 | \.L261A, was C% 318 | \\ Constants: 319 | cloud_mid_dest_addr = &4400 320 | cloud_sprite_addr= &2EE0 \ cloud sprite is &2E00 + 256what is this address? 321 | cloud_lower_dest_addr = &4900 \ source address in screen memory 322 | cloud_upper_dest_addr = &4180 \ 4180, 4980, 5180, 5980 .. destination address in screen memory 323 | .plot_clouds 324 | { 325 | LDA #HI(cloud_mid_dest_addr) 326 | STA pos+1 \ initialise destination zp = cloud_dest_addr 327 | LDA #&FF 328 | LDX #&05 329 | \ fill mid section white outer loop 330 | .mid_outer_loop 331 | \ fill mid section white inner loop 332 | LDY #LO(cloud_mid_dest_addr): STY pos \ Y=#&00 333 | .mid_inner_loop 334 | STA (pos),Y \ set to white &FF 335 | INY: BNE mid_inner_loop \ repeat 256 times 336 | INC pos+1 337 | DEX: BNE mid_outer_loop \ repeat 5 times 338 | \ end mid section inner, outer loop 339 | 340 | LDY #&1F \ counter, &20 cycles 341 | .cloud_loop2 342 | LDA cloud_sprite_addr,Y: STA (pos),Y \ initialise destination addr zp 343 | DEY: BPL cloud_loop2 344 | LDA #HI(cloud_sprite_addr) 345 | STA psta+1 \ psta is &2Exx, x = $80,$40,$40,$00,... 346 | LDA #&20: STA pos 347 | 348 | \ plot cloud sprite outer X loop, 8 cycles 349 | LDX #&08 \ offset from cloud_sprite_base_addr 350 | .next_cloud_sprite 351 | LDA cloud_sprite_offset_list,X 352 | STA psta \ setup zp address pointer, $80,$40,$40,$00,... 353 | 354 | \ plot cloud sprite inner Y loop, &40 bytes 355 | LDY #&3F 356 | .next_cloud_byte 357 | LDA (psta),Y 358 | STA (pos),Y 359 | DEY 360 | BPL next_cloud_byte \ repeat inner Y loop 361 | 362 | CLC \ add &40 to destination address 363 | LDA pos: ADC #&40: STA pos: BCC skip1 364 | INC pos+1 365 | .skip1 366 | DEX 367 | BPL next_cloud_sprite \ repeat inner Y loop 368 | \ end plot cloud sprite loops 369 | 370 | 371 | \ plot cloud ?? Y loop, &20,32 bytes 372 | LDY #&1F 373 | .loop32 374 | LDA &2EC0,Y: STA (pos),Y 375 | DEY: BPL loop32 376 | 377 | \ plot cloud ?? Y loop 256, X loop 8 cycles 378 | \\ copies from lower cloud to upper cloud, mirror image plot 379 | .mirror_loop_1 380 | LDY #&00 381 | .mirror_loop_2 382 | LDX #&07 383 | .mirror_loop_3 384 | .modify_lower_dest_addr 385 | LDA cloud_lower_dest_addr,Y \ self modifying SMC below, screen memory location &4900 386 | .modify_upper_dest_addr 387 | STA cloud_upper_dest_addr,X \ address modified SMC on each loop &4180 388 | INY 389 | DEX: BPL mirror_loop_3 390 | CLC \ 16 bit add 08 to ddu17+1 391 | LDA modify_upper_dest_addr+1: ADC #&08: 392 | STA modify_upper_dest_addr+1 \ 16 bit add &0800 self modifying SMC 393 | BCC skip2 394 | INC modify_upper_dest_addr+2 395 | .skip2 396 | CPY #&80 397 | BNE mirror_loop_2 398 | LDA modify_lower_dest_addr+1 \ load HI(cloud_lower_dest_addr) 399 | EOR #&80 \ XOR high bit 400 | STA modify_lower_dest_addr+1 \ self modifying SMC, write HI(cloud_lower_dest_addr) 401 | BMI skip3 402 | INC modify_lower_dest_addr+2 \ &2670 403 | .skip3 404 | \ check termination when matching MSB of cloud_mid_dest_addr 405 | LDA #HI(cloud_mid_dest_addr) \#&44 406 | CMP modify_upper_dest_addr+2 407 | BNE mirror_loop_1 408 | 409 | \\ restore the modified addressses for use in the next game level/redraw. 410 | STY modify_upper_dest_addr+1 411 | INX 412 | STX modify_lower_dest_addr+1 \ self modifying SMC 413 | LDA #HI(cloud_lower_dest_addr) \#&49 414 | STA modify_lower_dest_addr+2 \ self modifying SMC 415 | LDA #HI(cloud_upper_dest_addr) \#&41 416 | STA modify_upper_dest_addr+2 \ self modifying SMC 417 | RTS 418 | } 419 | \\ Background data for scenery, background sprite locations 420 | \\ starts at .sceneryLineArt 421 | \\ mostly VDU commands. 422 | \\ 26B0 to 281D was in G-Scene.bin file 423 | .scenery_line_art 424 | \ Define graphics colour (GCOL a,n) 425 | EQUB &12, &00, &06 \ cyan 426 | \ PLOT K,x,y 427 | EQUB &19, &04, &00, &00, &13, &00 428 | EQUB &19, &05, &04, &01, &17, &00 429 | EQUB &19, &05, &2C, &01, &3C, &00 430 | EQUB &19, &04, &7E, &04, &3E, &00 431 | EQUB &19, &05, &1A, &04, &20, &00 432 | EQUB &19, &05, &84, &03, &20, &00 433 | EQUB &19, &05, &52, &03, &28, &00 434 | EQUB &19, &05, &20, &03, &38, &00 435 | EQUB &19, &05, &16, &03, &46, &00 436 | EQUB &19, &05, &16, &03, &52, &00 437 | EQUB &19, &05, &20, &03, &60, &00 438 | EQUB &19, &05, &52, &03, &74, &00 439 | EQUB &19, &05, &BB, &03, &7C, &00 440 | EQUB &19, &04, &7E, &04, &42, &00 441 | EQUB &19, &15, &1A, &04, &24, &00 442 | EQUB &19, &15, &84, &03, &24, &00 443 | EQUB &19, &15, &52, &03, &2C, &00 444 | EQUB &19, &15, &20, &03, &3C, &00 445 | EQUB &19, &04, &20, &03, &64, &00 446 | EQUB &19, &15, &52, &03, &78, &00 447 | EQUB &19, &15, &BB, &03, &80, &00 448 | \ Define graphics colour (GCOL a,n) 449 | EQUB &12, &00, &02 \ green 450 | \ PLOT K,x,y 451 | EQUB &19, &04, &00, &05, &17, &00 452 | EQUB &19, &05, &C4, &04, &28, &00 453 | EQUB &19, &04, &E2, &04, &1C, &00 454 | EQUB &19, &05, &DE, &03, &38, &00 455 | EQUB &19, &04, &80, &02, &82, &00 456 | EQUB &19, &05, &48, &03, &0E, &01 457 | EQUB &19, &05, &AC, &03, &45, &01 458 | EQUB &19, &05, &1A, &04, &4A, &01 459 | EQUB &19, &05, &00, &05, &AE, &01 460 | EQUB &19, &04, &2C, &01, &C8, &00 461 | EQUB &19, &05, &8A, &02, &40, &01 462 | EQUB &19, &05, &3E, &03, &04, &01 463 | EQUB &19, &04, &F4, &01, &64, &00 464 | EQUB &19, &05, &FA, &00, &DC, &00 465 | EQUB &19, &05, &8C, &00, &54, &01 466 | EQUB &19, &05, &00, &00, &68, &01 467 | \ Define graphics colour (GCOL a,n) 468 | EQUB &12, &00, &04 \ blue 469 | \ PLOT K,x,y 470 | EQUB &19, &04, &9E, &02, &96, &00 471 | EQUB &19, &15, &F4, &01, &78, &00 472 | EQUB &19, &05, &58, &02, &64, &00 473 | EQUB &19, &05, &90, &01, &5A, &00 474 | EQUB &00 \ 256 bytes 475 | \ TODO - what is this list? still in use? 27b0 476 | EQUB &7D, &2D, &20, &13, &28, &A9, &09, &85, &83, &A9, &F0, &85, &82, &4C, &13, &28, &A9, &00, &8D 477 | \.L27C3 478 | .backgnd_sprite_addr_table 479 | EQUB &58 \ first is length of list, 88 bytes, 44 words 480 | EQUW &1CA0 \ sprite source addr 481 | EQUW &7393, &7149, &7660, &7599, &7344, &78C9, &76B4 \ destination addrs 482 | EQUW &1CC0 \ next sprite source addr, ... 483 | EQUW &7613, &7893, &73C9, &7649, &78E0, &7844, &75C4 \ destination addrs 484 | EQUW &1CE0 485 | EQUW &7B13, &7B4A, &7B60, &7AC4 486 | EQUW &1D00 487 | EQUW &78B0, &7820, &785C 488 | EQUW &1D20 489 | EQUW &7800, &7688 490 | EQUW &1D60 491 | EQUW &7060 492 | EQUW &1D80 493 | EQUW &72E0, &7560, &77E0, &7A80, &7AA0, &7ADC 494 | EQUW &1DA0 495 | EQUw &7A60, &7B30 496 | EQUW &1DC0 497 | EQUW &7908 498 | EQUW &1DE0 499 | EQUw &7928 500 | EQUB &00 -------------------------------------------------------------------------------- /Build/SS-01.asm: -------------------------------------------------------------------------------- 1 | \ converted from $.S BIRD DISK Side 1 2 | \ (c) Andy Frigaard 1984 to May 2021 3 | \ The SS files were written last (1984) and refer to earlier subroutines in PIG, GG files. 4 | \ This source file is edited down to contain only required elements 5 | \ for a build using beebasm. 6 | \ Contains 7 | \ Main loop keyboard handling 8 | \ Patches that modify or are called by earlier code. 9 | \ Bonus routines 10 | \ Game entry screen, logo, high score in MODE 7 teletext data 11 | 12 | \ ORG $1400 \ "P%" as per the original source 13 | 14 | \ AF: Last few chars of this string may have been used for padding to adjust some location 15 | EQUS "Thanks David,Ian,Martin,Mum,Dad,Susi C" 16 | 17 | \\ Check Key presses for user input 18 | \\ Called from main loop after all screen routines 19 | \\ Calls JSR key, OSBYTE 20 | \\ Note this writes OSWORD vector at &20C, turning sound on and off. 21 | \\ checking for R, S, Q on keyboard 22 | .check_key_press 23 | .opt 24 | { 25 | .checkQkey 26 | LDX #&EF:JSR key:BNE op1 \ EF=-17 INKEY Q, Quiet 27 | LDA #LO(mute):STA &20C \ rewrite OSWORD vector to below .mute 28 | LDA #HI(mute):STA &20D 29 | .op1 30 | .checkSkey 31 | LDX #&AE:JSR key:BNE op2 \ AE=-82 INKEY S, Sound 32 | LDA soun:STA &20C: 33 | LDA soun+1:STA &20D 34 | .op2 35 | .checkRkey 36 | LDX #&CC:JSR key:BNE op5 \ CC=-52 INKEY R, Rest 37 | .op3 38 | LDA #&81:LDY #1:LDX #0:JSR osbyte: \OSBYTE 129 Read key, scan for 1s, keyboard scan for X (value?) 39 | BCS op3: \If Carry is set, no key, loop 40 | CPX #82: \82 = R 41 | BEQ op3 \If R pressed, loop, else RTS 42 | .op5 43 | .checkKeyComplete 44 | RTS 45 | 46 | .mute \ OSWORD vector points here when Q/mute 47 | CMP #07:BEQ op5 \ exit if OSWORD &07 48 | .mu1 49 | JMP(soun) 50 | } 51 | \TODO move this to a memory location, is populated on game startup 52 | .soun \ OSWORD vector restored from here 53 | EQUW &E7EB 54 | 55 | \\ End of Check Key presses for user input 56 | 57 | \\ Check Plane right bounds, do movement? 58 | \\ Called from Plane function - as a patch? 59 | \\ TODO relocate this to the Plane routing 60 | \\ Calls JSR fo (plane plotting) 61 | .nlr \ Move enemy / check left bound 62 | { 63 | LDA tog:BEQ enlr:LDA exp:BPL rt 64 | DEC psta:SEC:LDA pos:SBC#8:STA pos:BCS enlr 65 | DEC pos+1:JMP enlr 66 | .rt \ Check right bound 67 | INC psta:CLC 68 | LDA pos:ADC #8:STA pos 69 | BCC enlr 70 | INC pos+1 71 | .enlr 72 | LDA #01:EOR tog:STA tog 73 | JMP fo \ plane plotting 74 | .tog EQUB 0 \ toggle byte, 0/1 75 | } 76 | 77 | 78 | \\ fpat - Fire patch - bullet counter? 79 | \\ Called from New bullet, nb, player fires, added afterwards? 80 | \\ TODO relocate this to the New bullet GG-02; create new counter addr for fp0 81 | \\ Calls 82 | \\ Inputs 83 | \\ Outputs 84 | \\ Sets values for fp0 counter 85 | .fpat 86 | { 87 | LDA fp0:BEQ fp1 \ decrement counter, return if > 0 88 | DEC fp0:RTS 89 | .fp1 90 | LDA #18:STA fp0 \ reset counter to 18 91 | JMP nwb_patch_return \ &297D 92 | } 93 | .fp0 94 | EQUB 0 \ modified above 95 | \\ End of fpat - Fire patch 96 | 97 | \\ game_over - Display GAME OVER message, and 98 | \\ Called from gun_hit_display, after last player killed. 99 | \\ Calls newgame 100 | \\ Inputs 101 | \\ Outputs 102 | .game_over 103 | { 104 | .gov 105 | PLA:PLA \ pull stack, will not return to calling routine 106 | LDY#255 107 | .gov1 \ Spell out GAME OVER slowly, delay between characters 108 | INY:LDA #10:JSR delay \ delay for 10x20 = 200ms 109 | LDA gov2,Y:JSR oswrch \ 'R' is last character 110 | CMP #82: BNE gov1 \ loop through 111 | LDA #150:JSR delay 112 | JMP newgame 113 | 114 | .gov2 115 | EQUB &1F, &05, &0F \ oswrch, move cursor to &05, &0F, COL 1 116 | EQUB &11, &01 \ oswrch, set COL 1 117 | \EQUD &110F051F 118 | \EQUB 1: 119 | EQUS "GAME OVER" 120 | } 121 | \\ End of game_over - Display GAME OVER message 122 | 123 | 124 | \\ Move plane patch or additional logic 125 | \\ Called from Move plane see PIG-01 126 | \\ TODO Move this into calling routine 127 | .stp4 128 | RTS 129 | .stp6 130 | LDA gex:BEQ stp4 131 | LDA psta:EOR #&80:STA psta:INC exp \ bug! old source check for bounds? 132 | PLA:PLA \ pull return address from stack 133 | JMP fo+3 134 | \\ End of 135 | 136 | \\ Scoring - check for extra player 137 | \\ Called from: Calculate the Score 138 | \\ TODO - monitor use of exg3 location/flag, move to variable 139 | .extra_player_check 140 | .exg 141 | { 142 | LDA #1:BIT exg3:BNE exg1 143 | LDY sc+2:CPY #5:BMI exg2 144 | ORA exg3:STA exg3:JSR exg4 145 | .exg1 146 | LDA #2:BIT exg3:BNE exg2 147 | LDY sc+2:CPY #&10:BMI exg2 \ if score over 10000? 148 | ORA exg3:STA exg3:JMP exg4 \ then store in exg3 149 | .exg2 150 | RTS: 151 | .*exg3 152 | EQUB 0 153 | .exg4 154 | JSR mini 155 | LDA #220:STA &2DFC 156 | LDX #&F8:LDY#&2D:LDA#7:JSR osword \ OSWORD - A=7 SOUND command at &2DF8 157 | INC gex+1:CLC 158 | LDA gex+2:ADC #&18 \ set sprite screen position one right 159 | STA gex+2:BCC exg5 160 | INC gex+3 161 | .exg5 162 | RTS 163 | } 164 | \\ End of Scoring - check for extra player 165 | 166 | 167 | \\ Bonus routine 168 | \\ Bonus completed, reward by playing the tune 169 | \\ Called from 170 | .bon 171 | LDA fc:AND #3:BNE bon0 \ load frame/level counter, if 0,4,8,.. 172 | LDA #15:JSR delay \ then pause, delay for 15x20 = 300ms 173 | JSR stmv:JMP bon11 \ do stmv , draw tune, then play tune. 174 | .bon0 \ Choose tune, based on frame counter, play tune 175 | JSR cht:JSR tune 176 | .bon11 177 | JSR wbmsg:LDY #75: 178 | .bon1 179 | SED:CLC: 180 | LDA sc+1:ADC#2:STA sc+1:LDA sc+2:ADC#0:STA sc+2 \ Add 2 to score 181 | CLD 182 | LDA #2:JSR delay \ then delay for 2x20 = 40ms 183 | TYA:PHA:LDX#&E8:LDY#&2D:LDA#7:JSR osword: \OSWORD - A=7 SOUND command at &2DF8 184 | JSR score_update_screen \ display score 185 | PLA:TAY:DEY:BNE bon1 186 | INC bsou 187 | LDX #LO(bsou):LDY#HI(bsou) \sound defined below 188 | LDA#7:JSR osword \OSWORD - A=7 SOUND command at bsou 189 | DEC bsou 190 | LDA #&80:ORA sc:STA sc \ set score flag 191 | RTS 192 | 193 | \Write Bonus message 194 | .wbmsg 195 | LDY #0: 196 | .wb1 197 | LDA bmsg,Y:JSR &FFEE: \ iterate through 0 to 10 char 198 | INY:CPY #11:BNE wb1: RTS 199 | .bmsg 200 | EQUD &071F0611: EQUB &F \ Mode 7, Cyan text, centred 201 | EQUS "BONUS!" \ message 202 | \ Bonus Sound definition for OSWORD 7, SOUND call 203 | \ parameter block, 8 bytes 204 | \ SOUND &0012, &FFFF, 0, 0 205 | .bsou 206 | EQUD &FFFF0012 207 | EQUD 0 208 | EQUB &FF \padding added AF 7/6/21 to align to published 209 | 210 | 211 | \\ Start of HSTRS file, MODE 7 bytes 212 | \\ 213 | \\ nbk Name parameter Block for OSWORD call to read user name 214 | .nbk \=&15C0 \EQUB $B4,$16,$08,$20,$7F 215 | EQUB &B4, &16, &08, &20, &7F 216 | \\ High Score, 3 bytes, Initially 0200 00 217 | .hs \=&15C5 218 | EQUB &00, &00, &02 219 | \\ Mode 7 title screen 220 | .m7 \=&15C8 221 | EQUB &16, &07, &17, &00, &0A, &20, &00, &00 222 | EQUB &00, &00, &00, &00 223 | \\ Bird Strike logo, in teletext characters 224 | \\ Copyright, High score etc 225 | .bsk \=&15D4: 226 | EQUB &9A, &94, &68, &3F, &6F, &34, &20, &20, &20, &20, &20, &20 227 | EQUB &20, &20, &FF, &20, &20, &5F, &7E, &2F, &6D, &20, &78, &20, &20, &20, &20, &20 228 | EQUB &20, &20, &7E, &0D, &9A, &96, &6A, &7D, &7E, &25, &20, &2F, &20, &30, &20, &20 229 | EQUB &20, &20, &FF, &20, &20, &6A, &7D, &70, &30, &20, &FF, &2C, &20, &30, &20, &20 230 | EQUB &2F, &20, &FF, &5F, &3E, &0D, &9A, &94, &6A, &3F, &60, &6F, &34, &FF, &20, &FF 231 | EQUB &2F, &21, &78, &2F, &FF, &20, &20, &20, &60, &60, &FF, &20, &FF, &20, &20, &FF 232 | EQUB &2F, &21, &FF, &20, &FF, &6F, &30, &20, &7E, &7B, &34, &0D, &9A, &96, &2A, &7D 233 | EQUB &70, &7E, &25, &6F, &30, &FF, &20, &20, &6F, &7C, &3F, &20, &20, &2A, &7C, &7E 234 | EQUB &27, &20, &6F, &74, &30, &FF, &20, &20, &6F, &30, &FF, &20, &2B, &34, &6D, &78 235 | EQUB &24, &1F, &05, &05, &82, &46, &49, &52, &45, &46, &4C, &59, &20, &28, &63, &29 236 | EQUB &20, &41, &6E, &64, &72, &65, &77, &20, &46, &72, &69, &67, &61, &61, &72, &64 237 | EQUB &0D, &1F, &0B, &08, &8D, &83, &48, &69, &67, &68, &20, &53, &63, &6F, &72, &65 238 | EQUB &1F, &0B, &09, &8D, &83, &48, &69, &67, &68, &20, &53, &63, &6F, &72, &65, &00 239 | \\ dots .... string 240 | .dts \=&16A0 241 | .dots_str 242 | EQUB &1F, &0B, &0B, &2E, &2E, &2E, &2E, &2E, &2E, &2E, &2E, &2E, &2E, &2E, &2E, &2E 243 | EQUB &00, &1F, &19, &0B 244 | \\ High score Name string - rewritable 245 | .nam \=&16B4: 246 | EQUB &61, &6E, &64, &72, &65, &77, &20, &20, &00 247 | \\ Instructions strings 248 | .ints \=&16BD 249 | .instructions_str 250 | EQUB &1F, &0E, &0E 251 | EQUB &8D, &83, &4B, &65, &79, &73, &1F, &0E, &0F, &8D, &83, &4B, &65, &79, &73, &1F 252 | EQUB &06, &11, &86, &5A, &20, &2E, &2E, &2E, &2E, &2E, &2E, &2E, &2E, &2E, &2E, &2E 253 | EQUB &2E, &20, &6D, &6F, &76, &65, &20, &6C, &65, &66, &74, &1F, &06, &12, &86, &58 254 | EQUB &20, &2E, &2E, &2E, &2E, &2E, &2E, &2E, &2E, &2E, &2E, &2E, &20, &6D, &6F, &76 255 | EQUB &65, &20, &72, &69, &67, &68, &74, &1F, &06, &13, &86, &52, &45, &54, &55, &52 256 | EQUB &4E, &20, &2E, &2E, &2E, &2E, &2E, &2E, &2E, &2E, &2E, &2E, &2E, &20, &73, &68 257 | EQUB &6F, &6F, &74, &1F, &06, &14, &86, &53, &2F, &51, &20, &2E, &2E, &2E, &2E, &2E 258 | EQUB &2E, &2E, &20, &73, &6F, &75, &6E, &64, &20, &6F, &6E, &2F, &6F, &66, &66, &1F 259 | EQUB &06, &15, &86, &52, &20, &2E, &2E, &2E, &2E, &2E, &2E, &2E, &2E, &2E, &2E, &2E 260 | EQUB &2E, &2E, &2E, &2E, &2E, &2E, &20, &72, &65, &73, &74, &00 261 | \ Press space to play string 262 | .sps \=&175C 263 | EQUB &1F, &07, &18, &81 264 | EQUB &88, &50, &72, &65, &73, &73, &20, &73, &70, &61, &63, &65, &20, &74, &6F, &20 265 | EQUB &70, &6C, &61, &79, &2E, &00 266 | \ end of HSTRS 267 | .end_SS_01 268 | PRINT ".end_SS_01 = ", ~end_SS_01 -------------------------------------------------------------------------------- /Build/SS-02.asm: -------------------------------------------------------------------------------- 1 | \ converted from $.S BIRD DISK Side 1 2 | \ (c) Andy Frigaard 1984 to May 2021 3 | \ The SS files were written last and refer to earlier subroutines in PIG, GG files 4 | \ This source file is edited down to contain only required elements 5 | \ for a build using beebasm. 6 | \ Contains 7 | \ Musical stave display 8 | \ Game end, check high score 9 | \ Display of logo, high score in MODE 7 10 | \ source from 1778 to 18FE 11 | 12 | \ ORG $1778 \ "P%" as per the original source 13 | 14 | \\ Draw Musical Staves, Notes, Play Tune 15 | \\ Called from Bonus routine, SS-01 16 | \\ Calls JSR stv in GG-01 17 | \\ Inputs: 18 | \\ stm = ?? 19 | \\ Constants: 20 | \stave_base_addr = &80.. 21 | .stmv 22 | LDY #10 \ set offset 10 23 | .stm4 24 | LDA stm10,Y: JSR oswrch \ OSWRCH Write character stm10,Y 25 | DEY:BPL stm4 \ branch if positive, loop 26 | \self modifying code 27 | LDA #&80:STA stm2+1: 28 | LDA #0:STA stm3+1: 29 | LDA #4:STA no \ draw 4 staves, store counter 30 | .stm1 31 | LDA #29:JSR oswrch: \ Define graphics origin 32 | LDA #0:JSR oswrch:JSR oswrch \ 0, 0 33 | SEC \set Carry 34 | \ Subtract memory from accumulator with carry A,C=A-M-(1-C) 35 | .stm2 36 | LDA #0:SBC #&80:STA stm2+1 \ modified above 37 | PHP:JSR oswrch \ graphics origin parameter 38 | PLP 39 | .stm3 40 | LDA #0:SBC #0:STA stm3+1 41 | JSR oswrch \ graphics origin parameter 42 | JSR stv \ Draw one stave, loop 4 times 43 | DEC no:BNE stm1 \ loop 4,3,2,1 44 | 45 | \ draw notes, play tune 46 | .stm5 LDA fc:STA tm 47 | LDA #0:STA fc: 48 | LDA #&26:STA tm+4: 49 | LDA #&88:STA tm+3 50 | .stm6 51 | CLC: 52 | LDA tm+3:STA not: 53 | LDA tm+4:ADC #&A:STA tm+4: 54 | STA not+1: 55 | JSR cht: 56 | STX nl:INC fc 57 | .stm8 JSR nxno:BNE stm8:JSR cht:JSR tune 58 | LDA #60:JSR delay \ delay for 60x20 = 1200ms 59 | LDA fc:CMP #4:BNE stm6: 60 | LDA tm:STA fc: 61 | LDA #26:JMP oswrch \JMP to OSWRCH, so will RTS to calling code 62 | .stm10 \static bytes 4+4+2+1 = 11 bytes 63 | EQUD &04FF0310:EQUD &000F020F:EQUW &18F0:EQUB 26 64 | \\ End Draw Musical Staves, Notes, Play Tune 65 | 66 | 67 | \\ Game End routine 68 | \\ Display title screen in MODE 7, High Score etc 69 | \\ Called from newgame 70 | \\ uses strings dots_str, instructions_str defined in SS-01 71 | .gend 72 | { 73 | LDA #0:STA hs: \ set hs to 0 74 | LDA sc+2:CMP hs+2:BCC ge1 \ Compare High score MSB 75 | BNE ge0 76 | LDA sc+1:CMP hs+1:BCC ge1 \ Compare High score MSB 77 | .ge0 78 | LDA sc+1:STA hs+1: \ Update High score with player score LSB, MSB 79 | LDA sc+2:STA hs+2: 80 | DEC hs \ Set hs to &FF 81 | .ge1 82 | LDA #22:JSR oswrch \ OSWRCH Change to screen MODE 7 (Teletext) 83 | LDA #7: JSR oswrch 84 | LDX #(bsk AND255):LDY#(bsk DIV256):JSR wrs 85 | LDA #31:JSR oswrch: \ move cursor to 5,11 86 | LDA #5:JSR oswrch: 87 | LDA #11:JSR oswrch 88 | LDA hs+2:JSR whs \ write high score 89 | LDA hs+1:JSR whs 90 | LDA #48:JSR oswrch 91 | 92 | \LDX #(dts AND 255): LDY#(dts DIV 256):JSR wrs 93 | \LDX #(ints AND 255):LDY#(ints DIV 256):JSR wrs 94 | LDX #LO(dots_str): LDY#HI(dots_str):JSR wrs 95 | LDX #LO(instructions_str):LDY#HI(instructions_str):JSR wrs 96 | LDA #31:JSR oswrch \ move cursor to 26, 11 97 | LDA #26:JSR oswrch 98 | LDA #11:JSR oswrch 99 | LDA hs:BEQ ge3 \ if high score, then user may enter name 100 | LDA #21:LDX #0:JSR osbyte \ OSBYTE 21 X=0 Keyboard buffer emptied \ flush 101 | \ User can enter high score name. 102 | TXA 103 | LDX#LO(nbk):LDY#HI(nbk):JSR osword: \OSWORD - A=0 Read from keyboard to nbk 104 | JMP ge7 105 | 106 | .ge3 \ display existing high score name 107 | LDY #&FF 108 | .ge6 109 | INY:LDA nam,Y:JSR &FFE3 \ iterate through 32 chars in nam, OSASCI 110 | CMP #32:BPL ge6 111 | 112 | .ge7 113 | LDY #2: 114 | .ge5 115 | LDA m7,Y:JSR oswrch \ iterate through 2 to 13 chars in m7, OSCASCI 116 | INY:CPY #13:BNE ge5 117 | LDA #100:JSR delay \ delay for 100x20 = 2000ms 118 | 119 | .*space 120 | LDA #26:JSR oswrch \ OWSRCH, 26 restore default viewport? 121 | \LDX #(sps AND 255):LDY #(sps DIV 256):JSR wrs 122 | LDX #LO(sps):LDY #HI(sps):JSR wrs \ write string 123 | .ge4 124 | LDX #&9D:JSR key \ wait for space bar, loop 125 | BNE ge4 126 | RTS 127 | } 128 | \\ End of Game End routine 129 | 130 | 131 | \\ Write High Score 132 | \\ Called from Game End routine above 133 | .whs 134 | { 135 | PHA: LSRA:LSRA:LSRA:LSRA \ Push A, multiply x 16 136 | CLC:ADC #&30:JSR &FFE3 \ add &30, call OSASCI, write line feed 137 | PLA: AND #&F:CLC:ADC #&30 \ Pull A, mask 4 high bits, add &30 138 | JMP &FFE3 \ call OSASCI/OSWRCH and RTS to calling code 139 | } 140 | \\ End of Write High Score 141 | 142 | \\ Write String to OSASCI, zero terminated string 143 | \\ called with dts, ints, sps address 144 | \\ input X=low byte, Y=high byte of dts address 145 | .wrs 146 | .write_string 147 | { 148 | STX modify_string_addr+1 \ store parameter values direct, modifying code, SMC 149 | STY modify_string_addr+2 150 | LDY #&FF 151 | .wr1 152 | INY 153 | .modify_string_addr 154 | LDA dots_str,Y: JSR &FFE3 \ iterate through supplied table, calling OSASCI line feed 155 | CMP #0:BNE wr1 \ terminates when A=0 156 | RTS 157 | } 158 | \todo published source has more code here.. patch by FB? 159 | \ IFM - This seems to be a (final) attempt to trip up a would-be 160 | \ pirate! ?&5D is set to 1 by the second Firebird loading/decryption 161 | \ routine just before it launches the game at &1E00. 162 | \ If ?&5D<>1 before this (eg if you've loaded the game by other 163 | \ means), the code enters an infinite loop at &1907 164 | \ 165 | \ Note: The disc version that has been in circulation for many years 166 | \ achieves this by copying 160 bytes of data from &1200 to page zero 167 | \ via a routine at &1300. This routine also restores a couple of 168 | \ vectors (WRCH and EVNT) used by the FB game-loading music. In the 169 | \ original these are restored by the decryption routine. 170 | \ 171 | \18fe: pha 172 | \18ff: lda $5d 173 | \1901: cmp #$01 174 | \1903: bne L1907 175 | \1905: pla 176 | \1906: rts 177 | \1907: L1907 jmp L1907 178 | -------------------------------------------------------------------------------- /Build/SS-03.asm: -------------------------------------------------------------------------------- 1 | \ converted from $.S BIRD DISK Side 1 2 | \ (c) Andy Frigaard 1984 to May 2021 3 | \ The SS files were written last and refer to earlier subroutines in PIG, GG files 4 | \ This source file is edited down to contain only required elements 5 | \ for a build using beebasm. 6 | \ Contains 7 | \ Main loop & startup routines 8 | \ Score handling and display 9 | \ Musical routines and tune display 10 | 11 | 12 | \ org $1E00 \ "P%" as per the original source 13 | \\ Game entry point here 14 | .game 15 | \ Set Escape Disabled 16 | LDA #200:LDX #03:LDY #0:JSR osbyte \OSBYTE &C8 (200) *FX 200 Read/write ESCAPE, BREAK 17 | JSR space 18 | \ TODO source was missing these 4 line 19 | \ Added AF 6/6/2021 20 | LDX #&01: LDA #&04: LDY #&00 21 | JSR osbyte \ OSBYTE 04 Disable cursor editing, X=1 22 | LDA &20C:STA soun: \ save OSWORD vector to .soun 23 | LDA &20D:STA soun+1 24 | 25 | .newgame 26 | JSR gend \ display title screen 27 | JSR start_game \ Start - after spacebar, start new game 28 | 29 | \\ Game main loop 30 | \\ run, until ESC pressed 31 | .GO 32 | JSR random1 \ update "random" numbers for use later R% 33 | JSR scr \ wait for vsync timing 34 | JSR mp \ Move planes, mp 35 | JSR np \ New plane, np 36 | LDA #&00+(1EOR7):STA &FE21 37 | JSR mg \ Move gun, mg, player moves?m 38 | LDA #&00+(0EOR7):STA &FE21 39 | JSR mb \ Move bullet 40 | JSR nb \ New bullet, nb, player fires? 41 | JSR mbo \ Move bombs 42 | JSR nbo \ New bombs nbo 43 | JSR pg \ Move bird, was B% 44 | JSR gun_hit_display \ Player Hit processing, was H% 45 | JSR sor \ gravestones, score? 46 | JSR check_key_press \ keyboard inputs, was opt 47 | 48 | \ TODO - commented 2 lines out to align to Iains disassembly 49 | \ LDX #&8F:JSR key:BNE GO: \ Check if ESC not pressed, then loop to .GO 50 | \ Set Escape Enabled, Jump out and end. 51 | \ LDA #200:LDY #0:JMP osbyte \ OSBYTE Escape key 52 | \ TODO - add 1 line to align to Iains disassembly 53 | JMP GO 54 | 55 | EQUS "(c)A.E.Frigaard 1984 Hello!" 56 | 57 | \\ Start new game, was .S% 58 | \\ Intialise variables, setup screem 59 | \\ Called for every new game 60 | .start_game 61 | LDA #5:STA no:JSR def_envelopes \ Store 5 at counter, call define envelope E% 62 | LDA #&49:JSR tune \ play starting tune 63 | LDA #22:JSR oswrch \ select MODE 2 via OSWRCH 64 | LDA #2:JSR oswrch 65 | \ intialise to zero counters, scores 66 | LDA #0:STA exg3:STA cnt:STA fc:STA picn:STA gex:STA sc+1:STA sc+2:STA plf:CLC 67 | LDA #32:STA de 68 | LDA #3:STA ti \ ti=de+1 initial timer value 69 | LDA #42:STA ti+1 \ default timer value was de+2: 70 | LDA #2:STA bfg:LDA #&2D:STA bulst+1:STA bost+1:STA pls+1 71 | LDA #&47:STA bost:LDA #&A:STA bulst:LDA #&13:STA pls 72 | 73 | \\ Setup screen colours - load palette 74 | LDX #15:LDY #7 75 | .co1 76 | JSR def_log_colour \ JSR call 8 times, decrementing X, was D% 77 | DEX: CPX #7:BNE co1 78 | \ a9 13 20 ee ff 8a 20 ee ff 98 20 ee ff a9 20 20 ee ff 20 ee ff 4c ee ff a5 70 79 | 80 | STX ra1 \ save X 7 in ra1 81 | 82 | LDA #player_live_init:STA gex+1 \\ player lives, 3 83 | LDA #&2F:STA plf+1 84 | LDA #&F0:STA inb \\ flag 1111 0000 85 | LDA #0:STA tm+1 86 | 87 | \\ Begin Level (next frame) 88 | \\ TO DO - Iains fix here 89 | \ de=&2D79 initialised with !de=&400314 (3 bytes, ti=&40) 90 | .bf 91 | JSR cht \ call Change Tune, returns A=? X=? 92 | STX nl:INC fc: \ increment frame counter, game level 93 | LDA de:CMP #15:BMI b0: \ if de, difficulty < 15, go .b0 (branch if minus) 94 | LDA fc:AND #1:BEQ b0 \ else if level is odd (1,3,5) 95 | DEC de:DEC de: \ then decrement x 2 de 96 | DEC inb \ and decrement inb 97 | .b0 98 | INC tm+1:INC tm+1: \ inc x 2 tm+1, this is default timer. 99 | LDA #12:JSR oswrch \ OSWRCH clear the screen 100 | LDA #154:LDX #20:JSR osbyte \ OSBYTE Write to video ULA control register and OS copy 101 | JSR plot_clouds \ Draw the clouds, was C% 102 | JSR draw_backgnd_art \ Draw the vector art, V% 103 | JSR stv: \ Draw the musical stave, stv? 104 | JSR score_update_screen \ Write the score to screen 105 | 106 | LDA #0:STA plane_kill_count: 107 | STA sc:STA ba+1 108 | \ &54 bytes covers bullet_list is 7, plane_list, bomb_list 109 | LDY cloud_sprite_offset_list-bullet_list 110 | \ LDY #&5C \ originally &54 111 | .b1 112 | STA bullet_list,Y: DEY: BNE b1 \ clear &54 bytes at &2D0A (bullet_list set to 0) 113 | LDA tm+1:STA bomb_list \ allow up to 2? bombs 114 | LDA #8:STA bullet_list \ allow up to 2 (x 4 byte) bullets 115 | LDA #30:STA plane_list \ allow up to 30 planes! 116 | note_screen_addr = &3088 117 | gun_screen_addr = &3288 118 | LDA #&30:STA not+1 119 | LDA #&88:STA not 120 | LDA #&80:STA gex+2 121 | LDA #&32:STA gex+3: 122 | 123 | \\ draw initial player gun indicators 124 | LDX gex+1 \ number of player guns 125 | .pmi 126 | JSR mini \ draw mini gun indicator top left 127 | CLC 128 | LDA gex+2:ADC #&18:STA gex+2 129 | DEX:BNE pmi \ loop for no of guns 130 | 131 | \\ draw initial planes 132 | \\ plane_list like this, 4 bytes per plane 133 | \ 81, LO, HI, ?, ? 134 | \ exp, pos, pos+1, psta, yo 135 | \ 42 9A 39 43 CA \this is flying near top 136 | \ 41 39 5F 47 41 \this is flying mid right 137 | \ 81 A8 3A 95 D0 138 | \ 81 F8 3A 9F D0 139 | \ 81 48 3B A9 D0 140 | \ 81 98 3B B3 D0 141 | \ 81 E8 3B BD D0 142 | plane_screen_addr = &3A81 \ TODO - this is not an address 143 | LDA #HI(plane_screen_addr):STA sd+1 \ sd not used in intialisation 144 | LDA #LO(plane_screen_addr):STA sf \ odd, uses sf as a temp workspace 145 | LDX#1:LDY#8 146 | .pp1 \TODO use of sf seems incomplete? inspect list? 147 | LDA #LO(plane_screen_addr) \ #&81 148 | STA plane_list,X \ LO address element 1 149 | INX:TYA \ Y = 8, copy to A 150 | CLC 151 | ADC #&50:STA plane_list,X \ add 8+50, &58, LO address=element 2 152 | TAY:INX \ y=&58 , Y is temp store A during loop 153 | LDA sd+1:ADC #0 \ add 16 bit carry 154 | STA plane_list,X: STA sd+1 \ HI address=element 3 155 | CLC:INX 156 | LDA sf:ADC #10 157 | STA sf:STA plane_list,X \ 81, 95, 9F, A9, B3, BD = element 4 158 | INX 159 | LDA #&D0:STA plane_list,X \ D0 - sort of flag, sprite offset? 160 | INX:CPX #31:BMI pp1 \ loop 6 times, X inc 5 each cycle 161 | 162 | LDY #0 163 | LDA (pls),Y:STA no \ plane_list, 0 is &1E,30 = 6 planes, 5 bytes 164 | .slop 165 | INY: 166 | INY:LDA (pls),Y:STA pos \ zp plane pointer to plane_list, screen address 167 | INY:LDA (pls),Y:STA pos+1 168 | JSR pp \ plots initial plane, 6 times 169 | INY:INY:CPY no:BMI slop 170 | JSR h7 171 | 172 | \ gun_sprite_addr = &2358 173 | gun_init_screen_addr = &7E90 174 | .sgun \ Setup gun, initial screen position etc 175 | .player_gun_initialise 176 | LDA #32: STA Xg: \ Gun X position 177 | LDA #HI(gun_init_screen_addr):STA gunp+1: \ Gun position address MSB 178 | LDA #LO(gun_init_screen_addr):STA gunp: \ Gun position address LSB 179 | LDA #HI(gun_sprite_addr):STA gun+4: \ Modify Gun sprite address MSB 180 | LDA #LO(gun_sprite_addr):STA gun+3: \ Modify Gun sprite address LSB 181 | JSR gun: \ .gun in OLDSRCE, is modified by above lines. 182 | 183 | LDA #&40:JMP tune \play tune &40 184 | 185 | \\ Calculate the Score 186 | \\ Input: 187 | \ sc is a bitwise flag showing the events that have occurred in this last cycle 188 | \ sc = &01 : Unused? Set in nb, when firing bullet 189 | \ sc = &02 : Plane killed / +15(0) points 190 | \ sc = &10 : Pigeon killed (note added to stave / +10(0) points) 191 | \ sc = &20 : Unused? Set in mg, move_gun 192 | \ sc = &40 : Plane Wing has been hit (pigeon release / +1(0) points) 193 | \ sc = &80 : Level is complete (load next level / +0 points) 194 | \ sc+1 195 | \ sc+2 196 | .sor 197 | LDA sc:BEQ score_update_screen \ if zero, no score events 198 | SED \ decimal scoring 199 | AND #2:BEQ s1 \ bit 1 not set 200 | CLC:LDA #&15 \ score for plane 15 => 150 201 | ADC sc+1:STA sc+1 \ 16 bit add dec 15 to sc+1 202 | LDA sc+2:ADC #0:STA sc+2 203 | JSR plane_hit \ was X% 204 | 205 | .s1 \ 1FFE A9 40 LDA #&40 206 | LDA #&40:BIT sc:BEQ s4 \ bit 6 not set 207 | CLC:LDA #1 208 | .wng \ score for plane wing 1 => 10 209 | ADC sc+1:STA sc+1: \ 16 bit add dec 1 to sc+1 210 | LDA sc+2:ADC #0:STA sc+2 211 | CLD 212 | LDX #LO(bsou):LDY#HI(bsou) 213 | LDA #7:JSR osword \OSWORD - A=7 SOUND command at bsou 214 | SED 215 | 216 | .s4 217 | LDA #&10:BIT sc:BEQ s2 218 | CLC:LDA #10 219 | .pig \ score for pigeon 10 => 100 220 | ADC sc+1:STA sc+1 \ 16 bit add dec 10 to sc+1 221 | LDA sc+2:ADC#0:STA sc+2 222 | CLD: 223 | JSR nxno:BNE s2 \ add next Note, check bonus? 224 | JSR bon \ do bonus 225 | 226 | .s2 227 | CLD:JSR exg \ check for extra player? 228 | LDA sc:BPL s3 229 | JMP ef 230 | .s3 231 | LDA #0:STA sc \ clear score byte for next cycle 232 | RTS 233 | \ sor end 234 | 235 | \\ Writes the score to screen 236 | \\ calls plot_score with A=Sprite offset 237 | \\ each call to plot_score increases SD address for next digit 238 | score_sprite_base=&1C00 239 | score_sprite_dest=&34B0 240 | .s7 241 | .score_update_screen 242 | LDA #HI(score_sprite_dest):STA sd+1: 243 | LDA #LO(score_sprite_dest):STA sd: 244 | LDA #HI(score_sprite_base):STA sf+1: 245 | \ NNxxx digits 246 | LDA #&F0:AND sc+2:JSR plot_score 247 | LDA #&F:AND sc+2:ASLA:ASLA:ASLA:ASLA:JSR plot_score 248 | \ xxNNx digits 249 | LDA #&F0:AND sc+1:JSR plot_score 250 | LDA #&F:AND sc+1:ASLA:ASLA:ASLA:ASLA:JSR plot_score 251 | \ xxxxN final digit, always 0 252 | LDA #0:JMP plot_score 253 | 254 | 255 | \\ Delay timer routine, uses vsync 20ms delay 256 | \\ input in A=n, Y preserved, n x 20ms delay 257 | \\ output original Y (also in A) 258 | .delay 259 | STA tm+2 \store counter in tm+2 260 | TYA:PHA \save Y 261 | .del1 262 | JSR scr \vsync 20ms delay 263 | DEC tm+2:BNE del1 \iterate until zero 264 | PLA:TAY:RTS \restore Y, return 265 | \\ end delay 266 | 267 | 268 | \\ Next level setup 269 | \\ Called from score routine 270 | \\ Calls 271 | .next_level 272 | .ef 273 | LDA #0:STA sc \ clear score byte for next cycle 274 | CLC: 275 | LDA plf: ADC#&40:STA plf \ plf = next plane from sprite address 276 | LDA #100:JSR delay: \ pause 277 | JMP bf \ play next frame/level 278 | \\ End of Next level setup 279 | 280 | 281 | \\ Choose Tune, Change Tune parameters in A, X 282 | \\ input fc parameters 283 | \\ output in A, X to control tune pointers? 284 | .cht 285 | LDA #3:AND fc:TAX:BNE ct1 \ if frame counter is 0, 4, 8 286 | LDA #&33:RTS \ then return A=&33, X=fc 287 | .ct1 \TODO - A, X mixed up here? 288 | DEX:BNE ct2 \ else if frame counter 1 289 | TXA:LDX#13:RTS \ then return A=fc-1, X=13 290 | .ct2 291 | DEX:BNE ct3 \ else if frame counter 2 292 | LDA #17:LDX #26:RTS \ then return A=17, X=26 293 | .ct3 294 | LDA#34:LDX#38 \ else fc 3, then return A=34, X=38 295 | RTS 296 | \\ End of Choose Tune 297 | 298 | 299 | \\ Patch for Move Plane - improved randomness 300 | \\ Called from mp 301 | \\ TODO move into mp routine 302 | .patch 303 | LDA ra1:BPL patch2: 304 | LDA sd:EOR #&C0:STA sd \ XOR top bit of address 305 | .patch2 306 | LDA de \dirn when above 307 | RTS 308 | \\ End of Patch for Move Plane 309 | 310 | 311 | \\ Plot Next Note 312 | \\ Calls pno, plot_note 313 | \ uses .nl lookup table 314 | \ nl,0 used for pointer to next note 315 | \ nl,Y used for .. 316 | .nxno 317 | INC nl:LDY nl \ inc note pointer 318 | LDA nl,Y:STA no 319 | AND #&E: 320 | CMP #8:BPL n1 321 | CLC:ADC not:STA sd 322 | LDA #0:BEQ n2 \ always 323 | .n1 324 | CLC:ADC not:ADC #&78:STA sd \ 16 bit add &0278, next row 325 | LDA #2 326 | .n2 327 | ADC not+1:STA sd+1 \ store sprite destination 328 | LDA #HI(note_sprite_addr) \ &23 329 | STA sf+1 330 | JSR chnot 331 | CLC 332 | LDA not:ADC #&20:STA not \ add &20 to sprite from 333 | BCC n3 334 | INC not+1 335 | .n3 336 | JSR pno \ plot_note 337 | CLC 338 | LDA sd:ADC#8:STA sd \ 16 bit add 8 to sprite destination 339 | BCC n4: 340 | INC sd+1 341 | .n4 342 | CLC 343 | LDA sf:ADC #8:STA sf \ 16 bit add 8 to sprite from 344 | BCC n5 345 | INC sf+1 346 | .n5 347 | JSR pno \ plot_note 348 | INY:LDA nl,Y 349 | RTS 350 | 351 | 352 | \\ Choose Note sprite to display 353 | \\ 2300 start of notes sprites to last 2340 354 | \\ Shift A, compare with "no" bitwise 355 | \\ find the case based on bit set in "no" 356 | .chnot 357 | LDA #&80:BIT no:BEQ c1 \ A = b1000 0000, set sf=&2300 358 | LDA #0:STA sf:RTS 359 | .c1 360 | LSRA: BIT no:BEQ c2 \ A = b0100 0000, set sf=&2310 361 | LDA #&10:STA sf:RTS 362 | .c2 363 | LSRA: BIT no:BEQ c3 \ A = b0010 0000, set sf=&2320 364 | LDA #&20:STA sf:RTS 365 | .c3 366 | LSRA: BIT no:BEQ c4 \ A = b0001 0000, set sf=&2330 367 | LDA #&30:STA sf:RTS 368 | .c4 369 | LDA #1:BIT no:BEQ c5 \ A = b0000 1000, set sf=&2340 370 | LDA #&40:STA sf 371 | .c5 372 | RTS 373 | 374 | \\ plot note on stave 375 | \\ uses ORA plotting, not XOR, to ensure colours are true. 376 | .pno TYA:PHA:LDY #7 377 | CLC:LDA sd:ADC #&78:STA st: 378 | LDA sd+1:ADC #2:STA st+1 379 | LDA sd:AND #7:EOR #7:STA mod 380 | CMP #7:BPL pntop 381 | .pnbot \ renamed bot to pnbot 382 | LDA(sf),Y:ORA(st),Y:STA(st),Y 383 | DEY:CPY mod:BNE pnbot 384 | .pntop 385 | LDA(sf),Y:ORA(sd),Y:STA(sd),Y 386 | DEY:BPL pntop 387 | PLA:TAY:RTS 388 | 389 | \\ Play the tune, pass in a parameter A, return X as 0 if pressed 390 | \\ Player can press space/any key to cut short the tune and continue play. 391 | \\ input A is Note, no, pointer to the tl (tune list) table 392 | \\ for example: &40 393 | \\ &2DF8 is start of OSWORD 7 parameter block, with these defaults: 394 | \\.L2DF8 EQUB $01,$00 395 | \\.L2DFA EQUB $05,$00 \OSWORD docs say &FF for MSBsound 396 | \\.L2DFC EQUB $49,$00 397 | \\.L2DFE EQUB $0F,$00 398 | \\ only update these: 2DFC = Pitch LSB, 2DFE = duration LSB 399 | .playTune 400 | .tune 401 | STA no: 402 | \ iterate through tl, Tune List, LDA tl,Y until zero value terminator 403 | \ no is the note counter, pointer to the tl (tune list) table 404 | .t1 405 | LDY no:LDA tl,Y: BEQ t3 \ get next note, 406 | STA sound_note_volume:INY: 407 | LDA tl,Y:STA sound_note_pitch \ store tune in OSWORD 7 parameter block 408 | LDX #LO(sound_note):LDY #HI(sound_note) 409 | LDA #7:JSR osword \ OSWORD - A=7 SOUND command at &2DF8 410 | INC no:INC no:JMP t1 \ increment Y + 2, loop 411 | 412 | .t3 \ loop get sound, until Sound channel is clear? < 15 413 | LDA #&80:LDX #250:JSR osbyte \ OSBYTE 128 Get Sound Channel 1 buffer status in Y 414 | CPX #15:BMI t3 \ X contains spaces in sound buffer, loop until buffer is empty 415 | RTS \ then tune has played, can return. 416 | 417 | \\ Keyboard scan - check for key press 418 | \\ input X = negative INKEY value, Y set to FF 419 | \\ output X = X and Y contain &FF if the key being scanned is pressed. 420 | .keyboardScan 421 | .key 422 | LDA #&81:LDY #&FF:JSR osbyte \ OSBYTE 129 Read key, keyboard scan for X (value?) 423 | INX:RTS \ X is &FF is pressed, so INX to 0, return 424 | INX:RTS \ AF 7/6/21 added padding to align diffs, dead code 425 | \ ]:VDU11:PRINT~P%;: 426 | \ P%=&1778: 427 | \ [OPTZ 428 | -------------------------------------------------------------------------------- /Build/X.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qurm/BirdStrike/b13704515ac3996feeacb220ab03b2a1ba6c6869/Build/X.bin -------------------------------------------------------------------------------- /Build/build_birdstrike.asm: -------------------------------------------------------------------------------- 1 | \ This is the master file used to build from source BIRD DISK Side 1 2 | \ Andy Frigaard May 2021 3 | \ Other files are largely in the same format as original 4 | \ with same structure, more labels, more comments. 5 | \ 6 | \ S source file contains 7 | \ main game loop, and functions for 8 | \ drawing & playing tunes 9 | \ game over, high score entry etc 10 | \ See PIG (PIGSRCE) 11 | \ See GG (OLDSRCE) for the core game, moving sprites, etc. 12 | \ 13 | \ INCLUDE "filename" 14 | \ Includes the specified source file in the code at this point. 15 | \ INCBIN "filename" 16 | \ Includes the specified binary file in the object code at this point. 17 | 18 | \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ 19 | \ Build instructions, assume that Beebasm is in the folder specified. 20 | \ Each option produces output as per the Beebasm options. 21 | \ beebasm -i build_birdstrike.asm 22 | \ ..\beebasm-1.09\beebasm -i build_birdstrike.asm 23 | \ ..\beebasm-1.09\beebasm.exe -vc -i build_birdstrike.asm -v > build_output.asm 24 | \ ..\beebasm-1.09\beebasm.exe -vc -i build_birdstrike.asm -d >labels.txt 25 | \ ..\beebasm-1.09\beebasm -i build_birdstrike.asm -do BS1v1.ssd -boot BIRDS 26 | \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ 27 | 28 | 29 | WORDvA = $020C \ WRCH vector A 30 | WORDvB = $020D \ WRCH vector B 31 | 32 | WRCHvA = $020E \ WRCH vector A 33 | WRCHvB = $020F \ WRCH vector B 34 | 35 | EVNTvA = $0220 \ EVNT vector A 36 | EVNTvB = $0221 \ EVNT vector B 37 | 38 | LFE4D = $FE4D \ Interrupt Flag Register 39 | LFE4E = $FE4E \ Interrupt Enable Register 40 | SysViaRegB = &FE40 41 | SysViaDDRA = &FE43 42 | SysViaIFR = &FE4D 43 | SysViaIER = &FE4E 44 | SysViaRegA = &FE4F 45 | 46 | vector_table_low_byte = $FFB7 \ Vector table address low byte 47 | vector_table_high_byte = $FFB8 \ Vector table address high byte 48 | 49 | osasci = $FFE3 \ OSASCI 50 | oswrch = $FFEE \ OSWRCH 51 | osword = $FFF1 \ OSWORD 52 | osbyte = $FFF4 \ OSBYTE 53 | 54 | \ Zero Page locations 55 | no=&70: \ number used in bombs too - generic counter 56 | \ Flags are used bit-wise 57 | bfg = &71 \ bird flag , set to 2 intially 58 | pfg = &72 \ plane flag ? 59 | pflg=&72 \ used in OLDSRCE 60 | bofg = &73 \ bomb flag (from OLDSRCE) 61 | mod=&74: 62 | pls=&75 \ plane pointer to plane_list, screen address 63 | \ OLDSRCE uses: !pls=&2D13:?&2D13=25 64 | exp=&77: \ plane list 1st element 65 | pos=&78: \ temp position, used in .mg (move gun), pp plot plane address 66 | psta=&7A: \ plane list 4th element 67 | yo=&7B \ plane list 5th element 68 | py=&7C 69 | ra1=&7D \ random IFM - fix pigeon height bug \ different in OLDSRCE ra1=&7C TODO ONLY used in few places 70 | 71 | sd=&80 \ used for sprite indirect address, bomb, bullet 72 | sf=&82 \ sprite "from" address 73 | st=&84 \ sprite "to" address 74 | gunp=&86 \ gun position 75 | plf=&88 \ plane sprite "from" address 76 | bulst=&8A \ bullet start/list as are multiple &2d0A in GG-02 77 | \ ?bfg=2:!bulst=&2D472D0A:?&2D0A=8:?&2D47=20 78 | bost=&8C \ bomb start/list as are multiple 79 | cnt=&8E \ counter for? 80 | 81 | \ Sprites memory locations - now defined in constants in source 82 | \ $.X is loaded at &1900 (scenery sprites etc - not clouds/enemies) 83 | \ $.X 001900 001900 000500 &1900 + &0500 = &1E00 84 | 85 | tm=&1A08 \ tm+1 used for number of active 'bomb slots' 86 | \ memory overwrites begin at ?(tm+1)>19 (ish). 87 | \ tm+2 used for vsync timing counter 88 | \ gunf=&2F00 \ used in .gun, value is modified by .sgun 89 | gunf=&1A60 90 | 91 | gex=&1D55 \ gun explosion timer, used in gun_hit_display to show correct sprite 92 | \ gex+1 is current no of lives 93 | \ gex +2,3 is LO,HI screen address for mini gun indicator 94 | player_live_init = 3 95 | \ TODO picn different in PIG and SS, using SS as more recent 96 | picn=&1D54: \ different value in PIGSRCE !! 97 | not=&1D59: \ note sprite origin ? 98 | fc=&1D5C 99 | 100 | \ $.G is loaded at &21EE (Stave-drawing onwards) (built with PIGSRCE?) 101 | \ $.G 0021EE 0021EE 000E12 102 | \ &21EE + &0E12 = $3000 (start of MODE 2 screen video RAM) 103 | 104 | \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ 105 | \nl=&2382 \ Note list &30 bytes, zero-terminated lists, 13,14,11,8 106 | \tl=&23B2 \ Tune List pairs zero-terminated lists, pitch, duration, 16, 16, 16, 12, 8, 16, 1 107 | \B%=&240E: \ code, same as pg in GG.asm 108 | \pb=&2581: 109 | \X%=&258D: 110 | \R%=&25B8: 111 | \V%=&25C9 112 | \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ 113 | 114 | \ Program locations 115 | \ mostly in the G, PIGSRCE memory space, now defined in GG-02 source 116 | \bis=&2D68 117 | \Xg=&2D70 118 | \inb=&2D71 119 | \buf=&2D72 120 | \bof=&2D74 121 | \sc=&2D76 \ used by .mg, move gun 122 | \de=&2D79 \ initialised with !de=&400314 (3 bytes, ti=&40) 123 | \ti=&2D7A 124 | \ba=&2D7C 125 | 126 | \ TODO gex different in PIG and SS, using SS as more recent 127 | \ gex=&2F28 128 | 129 | \ direct setting of RAM - not in beebasm 130 | \ !gunp=&7E90:!Xg=&2F30C720:!plf=&2F40:!bof=&2F38:!de=&400314 131 | \ ?bfg=2:!bulst=&2D472D0A:?&2D0A=8:?&2D47=20 132 | \ !pls=&2D13:?&2D13=25 133 | 134 | 135 | ORG &1400 136 | \ 1400 to 15BE 137 | INCLUDE "SS-01.asm" 138 | \ with HSTRS data to &1776 139 | 140 | \ ORG &15C0 141 | \ INCBIN "HSTRS.bin" \ MODE 7 High score and Keys, Space to start. 142 | \ derived from $.HSTRS source binary 143 | \ now included in SS-01 144 | 145 | ORG &1778 146 | \ 1778 to 18FE 147 | INCLUDE "SS-02.asm" 148 | \ to combine with SS-01 149 | 150 | ORG &1900 151 | INCBIN "X.bin" \ sprite, data, variables file &1900 to &1E00, &500 bytes 152 | \ pigeon/score font/scenery/player sprites 153 | \ derived from $.X source binary 154 | 155 | ORG &1E00 156 | \ 1E00 to 21DD - some space above 157 | INCLUDE "SS-03.asm" 158 | \ when combined with below files goes to 22EF 159 | 160 | 161 | \ORG &27F5 \ P%=&27F5 162 | ORG &21EE \ align to released source 163 | INCLUDE "GG-01.asm" \ derived from $.G source binary 164 | \ 21EE to 2222 165 | \ draw_stave only, very short 166 | 167 | 168 | ORG &2223 169 | INCLUDE "PIG-01.asm" 170 | \ 2223 to 22FF very short 171 | \ starts at .mini 172 | \ and has gun_hit_display 173 | 174 | \no space here - assembles up to 22FF 175 | 176 | ORG &2300 177 | note_sprite_addr=&2300 178 | bomb_sprite_addr=&2350 179 | gun_sprite_addr=&2358 \ (normal) gunf=&1A60 (explosion) 180 | INCBIN "G-Note.bin" \ sprite and data file &2300 to &2380, &80 bytes 181 | \ Notes, bomb, gun sprites 182 | \ derived from $.G source binary 183 | \unused 2380 from 2382 is note list, .nl 184 | \TODO this is very small, can relocate 185 | 186 | \ ORG &240E 187 | ORG &2382 188 | INCLUDE "PIG-02.asm" 189 | \ starts with .nl, .tl at 2382 190 | \ starts at .pg to .b8 + 191 | \ 240E to 258C 192 | \ new code to 26AE 193 | \ Background scenery, graphics, lines, tables to 281C 194 | 195 | ORG &281D 196 | INCLUDE "GG-02.asm" 197 | \ starts at .def_log_colour 198 | \ 281D to 2D09 199 | \ data, lists, sound tables 2D09 to 2E00 200 | 201 | 202 | ORG &2E00 203 | INCBIN "G-Plane.bin" \ sprite and data file &2E00 to &3000, &200 bytes 204 | \ cloud, plane sprites 205 | \ derived from $.G source binary 206 | 207 | \ SAVE "filename", start, end [, exec [, reload] ] 208 | SAVE "BIRDS", &1400, &3000, &1E00 209 | -------------------------------------------------------------------------------- /Build/style_guide.md: -------------------------------------------------------------------------------- 1 | 2 | ## Style Guide 3 | 4 | Assembler comments and layout to conform to beebasm standards 5 | 6 | Comments start with backslash '\\' 7 | 8 | Subroutine header 9 | ``` 10 | \\ plot_clouds draws clouds 11 | \\ Clouds are made up of 3 sections, upper, mid, lower. 12 | \\ Inputs: (set above) 13 | \\ sf = sprite from address 14 | \\ sd = sprite destination address 15 | \\ Constants: 16 | cloud_mid_dest_addr = &4400 17 | cloud_sprite_addr= &2EE0 \ cloud sprite is &2E00 + 256 18 | cloud_lower_dest_addr = &4900 \ source address in screen memory 19 | ``` 20 | 21 | ### Constants, Labels 22 | 23 | Defined addresses or constants, where destination cannot be a label. 24 | ``` 25 | gun_sprite_addr= &1910 26 | ... 27 | LDA #LO(gun_sprite_addr):STA sf 28 | ``` 29 | 30 | Labels within function/subroutine, local loop destinations are in left column. Code is indented: 31 | 32 | ``` 33 | .function_action_attribute 34 | 35 | \ Initialise Flying Right R=>F 36 | .pig_init_right 37 | 38 | ... 39 | 40 | .mirror_loop_1 41 | LDY #&00 42 | .mirror_loop_2 43 | LDX #&07 44 | 45 | ``` 46 | use additional .modify_ labels where code is modified 47 | ```asm 48 | .modify_lower_dest_addr 49 | LDA cloud_lower_dest_addr,Y \ self modifying SMC 50 | ... 51 | INC modify_lower_dest_addr+2 52 | ``` 53 | 54 | Use local label for short internal branch, 55 | indent skipped lines. Local scope is defined by `{... }`. 56 | ``` 57 | { 58 | BMI skip3 59 | INC modify_lower_dest_addr+2 \ &2670 60 | .skip3 61 | } 62 | ``` -------------------------------------------------------------------------------- /Clean/BIRDS: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qurm/BirdStrike/b13704515ac3996feeacb220ab03b2a1ba6c6869/Clean/BIRDS -------------------------------------------------------------------------------- /Clean/BS_Clean.ssd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qurm/BirdStrike/b13704515ac3996feeacb220ab03b2a1ba6c6869/Clean/BS_Clean.ssd -------------------------------------------------------------------------------- /Clean/G-Note.bin: -------------------------------------------------------------------------------- 1 | <<8888888 8<88888888<88 880<<880,<(((=>><(,( -------------------------------------------------------------------------------- /Clean/G-Plane.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qurm/BirdStrike/b13704515ac3996feeacb220ab03b2a1ba6c6869/Clean/G-Plane.bin -------------------------------------------------------------------------------- /Clean/GG-01.asm: -------------------------------------------------------------------------------- 1 | \ GG.asm converted from parts of $.OLDSRCE BIRD DISK Side 1 2 | \ and missing source "G" obtained from dissassembly of G binary file. 3 | \ (c) Andy Frigaard 1984 to May 2021 4 | \ The GG files were written first (1982-3) baed on $.OLDSRCE and were a playable game with 5 | \ many missing features. The main loop was overwritten and only the subroutines used. 6 | \ There are some later patches in the SS files. 7 | \ This source file is edited down to contain only required elements 8 | \ for a build using beebasm. 9 | \ Contains 10 | \ Draw Musical Stave 11 | 12 | \ I think &.OLDSOURCE is fairly definitive for &286E-&2D09 13 | \ (.mg to the start of the workspace / data areas at the top of the game). 14 | 15 | .start_GG_01 16 | PRINT ".start_GG_01 = ", ~start_GG_01 17 | 18 | \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ 19 | \\ dissassembly from G binary 20 | \\ new labels align to Iains 21 | \.drawStave 22 | \ 21EE A0 00 LDY #&00 23 | 24 | \\ Draw one Musical Stave 25 | \\ Called from Draw Musical Staves, Notes, Play Tune 26 | \\ Calls JSR oswrch, using PLOT commands 27 | \\ Inputs: 28 | \\ Constants: 29 | \stave_base_addr = &80.. 30 | 31 | .draw_stave 32 | .stv 33 | { 34 | LDY #&00 35 | .stave_loop1 36 | LDA sl,Y: JSR oswrch 37 | INY: CPY #&09 38 | bne stave_loop1 39 | LDX #&05 40 | .stave_loop2 41 | LDY #&09 42 | .stave_loop3 43 | LDA sl,Y: JSR oswrch 44 | INY: CPY #&15 45 | BNE stave_loop3 46 | DEX 47 | BNE stave_loop2 48 | RTS 49 | .stave_data 50 | .sl 51 | EQUB &12, &00, &04 \ define graphics colour 52 | EQUB &19, &04, &00, &01, &EC, &03 \ PLOT K, X, Y 53 | EQUB &19, &01, &00, &03, &00, &00 \ PLOT K, X, Y 54 | EQUB &19, &00, &00, &fd, &f0, &ff \ PLOT K, X, Y 55 | } 56 | 57 | 58 | \\ Notes, bomb, gun sprites 59 | \\ derived from $.G source binary 60 | \\note_sprite_addr=&2000 61 | \\bomb_sprite_addr=&2050 62 | \\gun_sprite_addr=&2058 \ (normal) gunf=&1A60 (explosion) 63 | 64 | \ align to page 65 | \\ equivalent of INCBIN "G-Note.bin" \ sprite and data file originally at &2300 to &2380, &80 bytes 66 | \ORG &2000 67 | ALIGN &100 68 | 69 | .note_sprite_addr 70 | EQUB &00,&00,&00,&00,&00,&14,&3C,&3C,&38,&38,&38,&38,&38,&38,&38,&20 71 | EQUB &00,&00,&00,&00,&00,&14,&38,&3C,&38,&38,&38,&38,&38,&38,&38,&00 72 | EQUB &00,&00,&00,&00,&00,&14,&38,&3C,&00,&00,&00,&00,&00,&38,&38,&20 73 | EQUB &00,&00,&00,&00,&00,&38,&38,&30,&00,&00,&00,&00,&00,&00,&00,&00 74 | EQUB &00,&00,&00,&00,&00,&3C,&3C,&10,&00,&00,&00,&00,&00,&38,&38,&30 75 | .bomb_sprite_addr 76 | EQUB &01,&04,&04,&01,&01,&01,&00,&00 77 | .gun_sprite_addr 78 | EQUB &00,&04,&04,&04,&2C,&04,&04,&04 79 | EQUB &00,&00,&00,&14,&3C,&14,&14,&00,&28,&28,&28,&3D,&3E,&3E,&3C,&28 80 | EQUB &00,&04,&04,&04,&2C,&04,&04,&04,&00,&00,&00,&00,&28,&00,&00,&00 81 | 82 | .end_GG_01 83 | PRINT ".end_GG-01 = ", ~end_GG_01 -------------------------------------------------------------------------------- /Clean/PIG-01.asm: -------------------------------------------------------------------------------- 1 | \ converted from $.PIGSRCE BIRD DISK Side 1 2 | \ (c) Andy Frigaard 1984 to May 2021 3 | \ The PIG files were written later (1983-4) based on $.PIGSRCE and were a playable game with 4 | \ some missing features, a main loop calling routines from OLDSRCE. The main loop was later 5 | \ overwritten and only the subroutines used. 6 | \ This source file is edited down to contain only required elements 7 | \ for a build using beebasm. 8 | \ Contains 9 | \ Plot player gun indicator 10 | 11 | \ ORG = &21B8 \ P% = &21B8 12 | 13 | \ AF 6/6/2021 moved to top to align to Iains 14 | \TODO minor differences here in .mini 15 | \ from here appears in G at 2223 16 | 17 | \\ Plot player gun indicator (small sprite, top left) initially 18 | \mini_gun_sprite_addr= &1910 \ temp player gun sprite &1928 or &1910 19 | .mini 20 | .plot_gun_life_indicator 21 | \ LDA #&C0:STA sf:LDA#9:STA sf+1: 22 | LDA #LO(mini_gun_sprite_addr):STA sf 23 | LDA #HI(mini_gun_sprite_addr):STA sf+1 \ IFM - LDA#19->LDA#&19 lives sprite ptr fix 24 | LDA gex+2:STA sd \ initial destination 25 | LDA gex+3:STA sd+1 26 | JMP plot_pigeon_sprite \ share pigeon sprite routine 27 | 28 | \\ from here appears in G at &2238 29 | \\ Player Hit display, also named H% 30 | \\ Called from main loop, after all moves, before score. 31 | .gun_hit_display 32 | .h0 33 | LDA #&20:BIT sc:BNE h1 \ if bit is set then gun just hit in move_gun 34 | LDA gex:BNE h12 \ else gex counts down from &FF to zero 35 | .hreturn 36 | RTS 37 | .h1 \ player is hit 38 | LDX #0:LDY#7:JSR def_log_colour \ define background as white? temp flash. 39 | LDA #7:LDY #HI(sound_player_hit):LDX #LO(sound_player_hit):JSR osword \ Sound sound_player_hit 40 | LDA #&FF:STA gex \ counter for explosion 41 | LDA #&60:STA np:STA mg 42 | STA nb: STA new_bomb \ this stores RTS in each routine, disabling them SMC 43 | JSR plot_gun_sprite \ un-draw sprite was .gun 44 | \ AF align to published as LDA #&1A , was LDA #&A 45 | LDA #HI(other_sprite_addr):STA gun+4 46 | LDA #LO(other_sprite_addr):STA gun+3 \ modify code with sprite source as &1A10, gun_sprite_addr 47 | JMP plot_gun_sprite \ re-draw sprite was .gun, exit. 48 | .h12 49 | DEC gex:LDA gex:CMP #254:BNE h3 \ gex, gun explosion, during which does not move etc 50 | LDX #0:LDY #0:JMP def_log_colour \ re-define normal background (was temp flash). 51 | .h3 52 | CMP #&DC:BNE h4:JSR plot_gun_sprite \ show next different sprite offset, animation. 53 | LDA #&38:STA gun+3:JMP plot_gun_sprite 54 | .h4 55 | CMP #&8C:BNE h5:JSR plot_gun_sprite \ show next different sprite offset, animation. 56 | LDA #&60:STA gun+3:JMP plot_gun_sprite 57 | .h5 \ 22A7 C9 01 CMP #&01 58 | CMP #1:BNE hreturn: \ final counter = 1, then 59 | \ TODO differences with Ians source added lines 60 | DEC gex+1 \ &1D56 \ dec and check player lives >0 61 | BNE h5a \ added &22B3 62 | JMP game_over \ gov \ &14AE \ added 63 | .h5a 64 | JSR plot_gun_sprite 65 | JSR sgun \ added 66 | 67 | LDY plane_list \ process the plane list and if any have exp = C0 then un-draw 68 | .h6 69 | LDA(pls),Y:CMP #&C0:BNE h8 70 | DEY:LDA(pls),Y:BPL h9 71 | EOR #&80:STA(pls),Y 72 | DEY:LDA(pls),Y:STA pos+1 73 | DEY:LDA(pls),Y:STA pos 74 | JSR plot_plane 75 | JMP h10 76 | .h8 DEY: 77 | .h9 DEY:DEY: 78 | .h10 DEY:DEY:BNE h6 79 | .h7 \ modify these routines, replacing RTS with the NOP opcode, &EA 80 | LDA #&EA:STA nb:STA np :STA mg: STA new_bomb 81 | 82 | \ AF 6/6/2021 removed this line 83 | \ DEC gex+1:BEQ govX \ renamed govX but .gov is in SS, so cannot BEQ that far 84 | \ is this realy used? 85 | SEC: 86 | LDA gex+2:SBC #&18 \ set sprite screen position one left; was SBC#&20 87 | \ AF 6/6/2021 changed to JMP, was :JSR mini 88 | STA gex+2:JMP mini 89 | 90 | .end_PIG_01 91 | PRINT ".end_PIG-01 = ", ~end_PIG_01 92 | 93 | \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ 94 | \\ section is overwritten with data .nl, .tl, etc up to B% 95 | \ AF 6/6/2021 removed this line 96 | \ JMP sgun 97 | 98 | \ AF 6/6/2021 removed this line 99 | \.govX 100 | \ PLA:PLA:RTS 101 | 102 | \ from here appears in G at &2223 103 | \ ie different order 104 | \ AF 6/6/2021 moved to top 105 | \ .mini 106 | \ LDA #&C0:STA sf:LDA#9:STA sf+1: 107 | \ LDA gex+2:STA sd: 108 | \ LDA gex+3:STA sd+1 109 | \ JMP pb 110 | 111 | \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ 112 | \ also in SS.asm 113 | \ PIG.asm:56: error: Branch out of range. 114 | \ (Branch distance is -3411 bytes; 3283 more than the maximum -128.) 115 | \ renamed stp4 tp stp4b 116 | \ AF 6/6/2021 removed this line 117 | \ now branch to hreturn instead 118 | \.stp4b RTS 119 | \.stp6 120 | \ LDA gex:BEQ stp4:LDA psta:EOR #&80:STA psta 121 | \ PLA:PLA:JMP fo+3 122 | 123 | -------------------------------------------------------------------------------- /Clean/PIG-02.asm: -------------------------------------------------------------------------------- 1 | \ converted from $.PIGSRCE BIRD DISK Side 1 2 | \ (c) Andy Frigaard 1984 to May 2021 3 | \ The PIG files were written later (1983-4) based on $.PIGSRCE and were a playable game with 4 | \ some missing features, a main loop calling routines from OLDSRCE. The main loop was later 5 | \ overwritten and only the subroutines used. 6 | \ This source file is edited down to contain only required elements 7 | \ for a build using beebasm. 8 | \ Contains 9 | \ Note, Tune data lists. 10 | \ Pigeon/bird initialise and move 11 | \ Plane hit animation 12 | \ Clouds and background scenery drawing and data 13 | 14 | 15 | \ 15/6/21 now includes background scenery data as EQUB (was in G-Scene.bin) 16 | .start_PIG_02 17 | PRINT ".start_PIG_02 = ", ~start_PIG_02 18 | 19 | \ Note list and Tune list source of music. 20 | \ nl=&2382 \ Note list &30 bytes, zero-terminated lists, 13,14,11,8 21 | \ tl=&23B2 \ Tune List pairs zero-terminated lists, pitch, duration, 16, 16, 16, 12, 8, 16, 1 22 | .nl 23 | EQUB $0D,$4A,$18,$8C,$8E,$1C,$8A,$84 24 | EQUB $14,$82,$20,$44,$05,$00,$48,$18 25 | EQUB $86,$84,$14,$86,$84,$14,$88,$2A 26 | EQUB $4E,$05,$00,$4A,$18,$8C,$8E,$1C 27 | EQUB $8A,$84,$14,$82,$20,$44,$00,$44 28 | EQUB $42,$42,$44,$46,$24,$14,$05,$00 29 | .tl 30 | \ Start of level / bonus tunes 31 | EQUB $65,$17,$5D,$05,$59,$0A,$65,$05 32 | EQUB $79,$0A,$81,$05,$89,$1E,$79,$1E 33 | EQUB $00,$6D,$17,$75,$05,$79,$0A,$75 34 | EQUB $05,$79,$0A,$6D,$05,$65,$1E,$59 35 | EQUB $1E,$00,$65,$17,$5D,$05,$59,$0A 36 | EQUB $65,$05,$79,$0A,$81,$05,$89,$1E 37 | EQUB $79,$0F,$00,$79,$0F,$81,$0F,$81 38 | EQUB $0F,$79,$0F,$75,$0F,$79,$1E,$00 39 | EQUB $59,$05,$59,$05,$59,$05,$49,$0F 40 | EQUB $00,$41,$05,$35,$0A,$39,$05,$3D 41 | EQUB $05,$41,$05,$65,$0A,$65,$0A,$55 42 | EQUB $14,$00,$14,$00 43 | 44 | \ ORG &240E 45 | \ from here appears in G at &240E 46 | \ also as B% 47 | 48 | \\ Pigeon, Move Bird 49 | \\ called from main loop 50 | \ &1A00 Bird Sprites, Flying Left? L=>R, on single page 51 | \ &1B00 Bird Sprites, Flying Right? R=>L, on single page 52 | \ bis is list of 7 Pigeon sprite animation pointers (offsets from &1A00/&1B00) 53 | \ EQUB $88,$A0,$B8,$D0,$E8,$D0,$B8,$88 54 | \ ba is Bird Address LSB & 2D7D 55 | \ ba+1 is Bird Address MSB set high bit when shot, AND #&80 56 | \ ba+2 is index for sprite animation, set high bit when shot. 57 | \ ba+3 X-coord column, set by L<>R direction #76 or #0, then inc/dec by 1 58 | \ py is pigeon Y-coord , multiple of 16 59 | \ picn pigeon counter, increment for each new one, used to alternate sides 60 | .pg 61 | \ TODO - Released source LDA #&1B (was &0B) - source of bird sprite? 62 | LDA #HI(pigr_sprite_addr):STA sf+1 63 | LDA ba+1:BNE pgb0 \ Check if Bird is in flight, MSB <> 0 64 | LDA #&42:BIT sc:BEQ ep \ check Score byte flag 65 | 66 | \ TODO - BIT with picn = &1D54 67 | \ 2420 2C 54 1D BIT &1D54 68 | \ picn is 02FC in released - this was a possible bug 69 | LDA #02:BIT picn:BEQ pgl \ if pigeon counter is even, then fly L=>R 70 | 71 | \ Initialise Flying Right R=>F 72 | \ TODO - Released source LDA #&1B (was &0B) 73 | .pig_init_right 74 | LDA #HI(pigr_sprite_addr):STA sf+1:STA pg+1: 75 | LDA #&68:STA ba:STA sd: 76 | LDA #0:STA xps+1: \ set X-coord limit column 0, SMC modifies below 77 | LDA #76:STA ba+3 \ set X-coord var column=76 78 | LDA #&4B:STA b5-2:BNE b3 \ A=MSB of bird screen address SMC modifies #&49 or #&4B 79 | .pgl 80 | .pig_init_left 81 | \ Initialise Flying Left L=>R 82 | \ TODO - Released source LDA #&1A (was &0A) 83 | LDA #HI(pigl_sprite_addr):STA sf+1:STA pg+1 84 | LDA #0:STA ba:STA sd: 85 | STA ba+3 \ set X-coord var column=0 86 | LDA #76:STA xps+1 \ set X-coord limit column 76, SMC modifies below 87 | LDA #&49:STA b5-2 \ A=MSB of bird screen address SMC modifies #&49 or #&4B 88 | 89 | \ Initialise common Flying Left or Right 90 | .b3 91 | LDA #0:STA py \ new pigeon, Y-coord = 0 92 | INC picn \ inc pigeon counter 93 | 94 | LDA #7:AND ra1:TAX \ get random [0-7] in X 95 | \ TODO - Released source LDA #&4B 96 | LDA #&4B:CLC \SMC modified above #&49 or #&4B was initial &4B 97 | .b5 98 | ADC #5:TAY \ preserve A+5 in Y 99 | LDA py:ADC #16:STA py \ add 16, random times => random pigeon Y coord 100 | TYA \ recover A 101 | DEX:BPL b5 \ repeat X (random 0-7) times 102 | STA ba+1:STA sd+1 \ store MSB of bird address 103 | LDX #2:STX ba+2 \ store initial sprite offset value, 2 104 | LDA bis,X:STA sf \ select Sprite offset from "bis" table 105 | JMP pb \ do initial plotBirdSprite 106 | .ep 107 | RTS 108 | \ End Pigeon Initialise 109 | 110 | 111 | \ After intialisation, process bird, move, check hits. 112 | \ so renamed b0 to pgb0, another bo b1 in S.asm, different purpose 113 | .pgb0 114 | LDA ba:STA sd: \ copy Bird address to zero page sd 115 | LDA ba+1:STA sd+1:BPL pgb1 \ if high bit clear, then pigeon not hit, so branch 116 | 117 | DEC ba+2:BNE ep \ dec index for animation, point to next sprite 118 | \ why ep - maybe page boundary .x too far? 119 | EOR #&80:STA sd+1 \ fix sd+1 to high bit is clear 120 | 121 | \ TODO - Released source LDA #&10, was LDA #0, line order changed. 122 | \LDA #&10:STA ba+1 123 | \LDA #&10:ORA sc:STA sc 124 | 125 | LDA #&10:ORA sc:STA sc \ set Score byte flag 126 | LDA #&00:STA ba+1 \ clear bird address for next cycle 127 | BEQ bx \ go to plot the dead pigeon sprite 128 | 129 | \ so renamed b1 to pgb1 130 | .pgb1 131 | LDA ba+2:AND #&7F:TAX 132 | LDA bis,X:STA sf \ select Sprite offset from "bis" table 133 | LDY #0:LDA(bulst),Y:STA no: 134 | 135 | \ renamed h to pgh 136 | .pgh \ check pigeon is hit? 137 | INY:LDA(bulst),Y:SEC:SBC py:BMI pgnh 138 | CMP #7:BPL pgnh 139 | INY:INY:LDA(bulst),Y:BEQ pgnh+2 140 | INY:LDA(bulst),Y:SEC:SBC ba+3:BMI pgnh+3 141 | CMP #3:BPL pgnh+3 142 | LDA #&E8:STA(bulst),Y:TAX: 143 | LDA #7:LDY #&2D:JSR &FFF1 \ Sound 144 | LDA #&10:STA ba+2: \ store sprite offset value, 16 - dead pigeon? 145 | LDA #&80:ORA ba+1:STA ba+1 \ set address high bit for dead. 146 | JSR pb \ do plotBirdSprite & RTS 147 | .bx 148 | \ TODO - Released source LDA #&1B, was LDA #&B 149 | LDA #HI(pigr_sprite_addr):STA sf+1: 150 | LDA #&70:STA sf:JMP pb \ do plotBirdSprite & RTS 151 | .b9 152 | LDA #4:ORA sc:STA sc \ set Score byte flag 153 | LDA #0:STA ba+1 154 | .x 155 | RTS 156 | \ so renamed nh to pgnh 157 | .pgnh \ pigeon not hit 158 | INY:INY:INY: 159 | CPY no:BMI pgh \ loop again to check next bullet hit 160 | LDA #&80:EOR ba+2 \ toggle high bit for alternate cycles 161 | STA ba+2:BMI x \ skip and exit 1 in 2 cyles 162 | 163 | JSR pb \ Remove using XOR, do plotBirdSprite 164 | LDA ba+3 \ pigeon, get X-coord 165 | .xps 166 | \TODO - Released source CMP #00, was CMP #76 &4C 167 | CMP #00:BEQ b9 \ if pigeon at left/right of screen SMC 00 or 76 168 | AND #31:BNE b6 169 | LDA #7:LDY #&2D:LDX #&F0:JSR osword \ OSWORD - A=7 SOUND command at &2DF0 170 | .b6 171 | LDX ba+2:DEX:BPL b7 \ dec sprite animation offset value 172 | LDX #7 \ if=0, reset sprite animation index to 7 173 | .b7 174 | STX ba+2 175 | LDA bis,X:STA sf \ select Sprite offset from "bis" table 176 | LDA xps+1:BEQ b10 177 | \ moving L->R 178 | INC ba+3:CLC \ inc x-coord 179 | 180 | LDA ba:ADC #8:STA ba \ move right one pixel, 8 bytes 181 | STA sd:BCC pb 182 | INC ba+1:INC sd+1 183 | JMP pb \ do plotBirdSprite & RTS 184 | .b10 \ moving R->L 185 | DEC ba+3 \ dec x-coord 186 | SEC: LDA ba:SBC #8 \ move left one pixel, 8 bytes 187 | STA ba:STA sd:BCS pb 188 | DEC ba+1:DEC sd+1 \ pass through to plotBirdSprite 189 | 190 | \\ pb Plot Bird, draws bird sprites on screen 191 | \\ XOR plotting loop for &17 24 bytes, on single MODE 2 line 192 | \\ Also called by plot_gun_life_indicator, top left. 193 | \\ Inputs: (set above) 194 | \\ sf = sprite from address 195 | \\ sd = sprite destination address 196 | .plot_pigeon_sprite 197 | .pb 198 | { 199 | LDY #&17 200 | .b8 \ XOR plotting loop for &17 24 bytes 201 | LDA(sf),Y:EOR(sd),Y:STA(sd),Y 202 | DEY:BPL b8 203 | RTS 204 | } 205 | 206 | \\ PIG-02.asm below based on 207 | \\ missing source "G" obtained from dissassembly of G binary file 208 | \\ does background, line graphics. 209 | \\ Andy Frigaard May 2021 210 | \\ labels unknown - set to ddu1, ddu2, etc 211 | 212 | \\ Plane is hit 213 | \\ Called from sor, score routine 214 | \\ Inputs: (set above) 215 | \\ sf = sprite from address 216 | \\ sd = sprite destination address 217 | \\ Constants: 218 | 219 | \ gex, gun explosion is gex=&1D55 and gex+1=&1D56 220 | \ plane_table (in X.bin): 221 | \ &1D40: 31 7A D9 7C C9 77 12 7A C8 7C BA 77 51 7A B8 7C 1zY|Iw.zH|:wQz8| 222 | \ &1D50: 20 7A 42 7A 00 00 00 00 00 00 00 00 00 00 00 00 223 | \ also X% X%=&258D 224 | .ddu1 225 | .plane_hit \ X%=&258D 226 | LDY plane_kill_count \&1D5B \ plane kill counter 227 | CPY #&09 228 | BPL ddu3 \ if > 9 then exit routine &25B7 229 | LDA plane_table,Y: STA sd \ setup zp destination 230 | INY 231 | LDA plane_table,Y: STA sd+1 232 | INY 233 | STY plane_kill_count \&1D5B 234 | 235 | \ write #&55 to 5 236 | LDY #&04 \ loop 5 cycles 237 | LDA #&55 238 | .ddu2 239 | STA (sd),Y \ write (sd),4 (sd),3... 240 | DEY: BPL ddu2 \ 241 | 242 | \ write to (sd),9 (sd),1 243 | LDY #&09 244 | ASL A 245 | STA (sd),Y 246 | LDY #&01 247 | LDA #&FF 248 | STA (sd),Y 249 | .ddu3 250 | RTS 251 | \.L25B8 252 | 253 | \\ Random generator, was R% 254 | \\ Called from smain loop after vsync 255 | \\ Inputs: 256 | \\ ra, ra+1,ra+2 = zp address 257 | .random1 \ psuedo "random" number generator 258 | LDA ra1 259 | AND #&48 260 | ADC #&38 261 | ASL A: ASL A 262 | ROL ra1+2 263 | ROL ra1+1 264 | ROL ra1 265 | LDA ra1 266 | RTS 267 | 268 | \\ start draw_backgnd_art 269 | \\ reads from a table of VDU commands and parameters, 270 | \\ GCOL, PLOT, etc 271 | \\ then uses pp to draw scenry sprites. 272 | \\ Constants: 273 | \ modify_plane_sprite_length = &2C1E \ SMC length defined in pp routine. 274 | \ backgnd_sprite_addr_table = &27C3 \ part of scenery_line_art 275 | .draw_backgnd_art 276 | { 277 | LDY #&00 278 | .draw_line_art_loop 279 | LDA scenery_line_art,Y: JSR oswrch \&FFEE 280 | INY 281 | BNE draw_line_art_loop \ loop 256 times 282 | 283 | \\ this uses the pp plane sprite routine and modifies that to change 284 | \\ the byte counter to LDA #&1F: STA &2C1E 285 | LDA plf: STA sf \ initialise zp locations 286 | LDA plf+1: STA sf+1 287 | LDA #&1F: STA modify_plane_sprite_length+1 \&2C1E 288 | LDA #%11000000: STA no \ store &E0 %11100000 in temp zp 289 | LDY #&00 290 | \.L25E7 291 | 292 | \ loop loads table of values that are source and 293 | \ destination sprite addresses, writes to zp, runs JSR pp. 294 | \ assumes that source addresses are < &3000, destinations are > &3000, tested with BIT #%11000000 295 | \ BIT sets the Z flag as though the value in the address tested were ANDed with the accumulator. 296 | \ The N and V flags are set to match bits 7 and 6 respectively in the value stored at the tested address. 297 | .draw_backgnd_sprite_loop 298 | INY: LDX backgnd_sprite_addr_table,Y \ address LO; start Y=1 299 | INY: LDA backgnd_sprite_addr_table,Y \ address HI 300 | BIT no: BNE skip1 \ use BIT to AND with A => all screen address 301 | STA plf+1: STX plf \ store source addr for sprite 302 | INY: LDX backgnd_sprite_addr_table,Y \ use A & X to move 2 bytes per loop 303 | INY: LDA backgnd_sprite_addr_table,Y 304 | .skip1 305 | STX pos \ store destination addr for 'top' row MODE 2, assumes sprite is on one row only 306 | STA pos+1 307 | JSR pp \ &2C08 plot plane sprites 308 | CPY backgnd_sprite_addr_table \ Check Y is < #&58, length of list 309 | BMI draw_backgnd_sprite_loop \ &25E7 310 | \ restore default settings for pp plane plot 311 | LDA #&3F: STA modify_plane_sprite_length+1 \&2C1E 312 | LDA sf: STA plf 313 | LDA sf+1: STA plf+1 314 | RTS 315 | } 316 | BRK \filler byte 317 | 318 | \\ plot_clouds draws clouds 319 | \\ Clouds are made up of 3 sections, upper, mid, lower. 320 | \ cloud_sprite_offset_list=&2D5F \ cloud sprite offset lookup list in GG-02 321 | \.L261A, was C% 322 | \\ Constants: 323 | cloud_mid_dest_addr = &4400 324 | cloud_sprite_addr= &2EE0 \ cloud sprite is &2E00 + 256what is this address? 325 | cloud_lower_dest_addr = &4900 \ source address in screen memory 326 | cloud_upper_dest_addr = &4180 \ 4180, 4980, 5180, 5980 .. destination address in screen memory 327 | .plot_clouds 328 | { 329 | LDA #HI(cloud_mid_dest_addr) 330 | STA pos+1 \ initialise destination zp = cloud_dest_addr 331 | LDA #&FF 332 | LDX #&05 333 | \ fill mid section white outer loop 334 | .mid_outer_loop 335 | \ fill mid section white inner loop 336 | LDY #LO(cloud_mid_dest_addr): STY pos \ Y=#&00 337 | .mid_inner_loop 338 | STA (pos),Y \ set to white &FF 339 | INY: BNE mid_inner_loop \ repeat 256 times 340 | INC pos+1 341 | DEX: BNE mid_outer_loop \ repeat 5 times 342 | \ end mid section inner, outer loop 343 | 344 | LDY #&1F \ counter, &20 cycles 345 | .cloud_loop2 346 | LDA cloud_sprite_addr,Y: STA (pos),Y \ initialise destination addr zp 347 | DEY: BPL cloud_loop2 348 | LDA #HI(cloud_sprite_addr) 349 | STA psta+1 \ psta is &2Exx, x = $80,$40,$40,$00,... 350 | LDA #&20: STA pos 351 | 352 | \ plot cloud sprite outer X loop, 8 cycles 353 | LDX #&08 \ offset from cloud_sprite_base_addr 354 | .next_cloud_sprite 355 | LDA cloud_sprite_offset_list,X 356 | STA psta \ setup zp address pointer, $80,$40,$40,$00,... 357 | 358 | \ plot cloud sprite inner Y loop, &40 bytes 359 | LDY #&3F 360 | .next_cloud_byte 361 | LDA (psta),Y 362 | STA (pos),Y 363 | DEY 364 | BPL next_cloud_byte \ repeat inner Y loop 365 | 366 | CLC \ add &40 to destination address 367 | LDA pos: ADC #&40: STA pos: BCC skip1 368 | INC pos+1 369 | .skip1 370 | DEX 371 | BPL next_cloud_sprite \ repeat inner Y loop 372 | \ end plot cloud sprite loops 373 | 374 | 375 | \ plot cloud ?? Y loop, &20,32 bytes 376 | LDY #&1F 377 | .loop32 378 | LDA &2EC0,Y: STA (pos),Y 379 | DEY: BPL loop32 380 | 381 | \ plot cloud ?? Y loop 256, X loop 8 cycles 382 | \\ copies from lower cloud to upper cloud, mirror image plot 383 | .mirror_loop_1 384 | LDY #&00 385 | .mirror_loop_2 386 | LDX #&07 387 | .mirror_loop_3 388 | .modify_lower_dest_addr 389 | LDA cloud_lower_dest_addr,Y \ self modifying SMC below, screen memory location &4900 390 | .modify_upper_dest_addr 391 | STA cloud_upper_dest_addr,X \ address modified SMC on each loop &4180 392 | INY 393 | DEX: BPL mirror_loop_3 394 | CLC \ 16 bit add 08 to ddu17+1 395 | LDA modify_upper_dest_addr+1: ADC #&08: 396 | STA modify_upper_dest_addr+1 \ 16 bit add &0800 self modifying SMC 397 | BCC skip2 398 | INC modify_upper_dest_addr+2 399 | .skip2 400 | CPY #&80 401 | BNE mirror_loop_2 402 | LDA modify_lower_dest_addr+1 \ load HI(cloud_lower_dest_addr) 403 | EOR #&80 \ XOR high bit 404 | STA modify_lower_dest_addr+1 \ self modifying SMC, write HI(cloud_lower_dest_addr) 405 | BMI skip3 406 | INC modify_lower_dest_addr+2 \ &2670 407 | .skip3 408 | \ check termination when matching MSB of cloud_mid_dest_addr 409 | LDA #HI(cloud_mid_dest_addr) \#&44 410 | CMP modify_upper_dest_addr+2 411 | BNE mirror_loop_1 412 | 413 | \\ restore the modified addressses for use in the next game level/redraw. 414 | STY modify_upper_dest_addr+1 415 | INX 416 | STX modify_lower_dest_addr+1 \ self modifying SMC 417 | LDA #HI(cloud_lower_dest_addr) \#&49 418 | STA modify_lower_dest_addr+2 \ self modifying SMC 419 | LDA #HI(cloud_upper_dest_addr) \#&41 420 | STA modify_upper_dest_addr+2 \ self modifying SMC 421 | RTS 422 | } 423 | \\ Background data for scenery, background sprite locations 424 | \\ starts at .sceneryLineArt 425 | \\ mostly VDU commands. 426 | \\ 26B0 to 281D was in G-Scene.bin file 427 | .scenery_line_art 428 | \ Define graphics colour (GCOL a,n) 429 | EQUB &12, &00, &06 \ cyan 430 | \ PLOT K,x,y 431 | EQUB &19, &04, &00, &00, &13, &00 432 | EQUB &19, &05, &04, &01, &17, &00 433 | EQUB &19, &05, &2C, &01, &3C, &00 434 | EQUB &19, &04, &7E, &04, &3E, &00 435 | EQUB &19, &05, &1A, &04, &20, &00 436 | EQUB &19, &05, &84, &03, &20, &00 437 | EQUB &19, &05, &52, &03, &28, &00 438 | EQUB &19, &05, &20, &03, &38, &00 439 | EQUB &19, &05, &16, &03, &46, &00 440 | EQUB &19, &05, &16, &03, &52, &00 441 | EQUB &19, &05, &20, &03, &60, &00 442 | EQUB &19, &05, &52, &03, &74, &00 443 | EQUB &19, &05, &BB, &03, &7C, &00 444 | EQUB &19, &04, &7E, &04, &42, &00 445 | EQUB &19, &15, &1A, &04, &24, &00 446 | EQUB &19, &15, &84, &03, &24, &00 447 | EQUB &19, &15, &52, &03, &2C, &00 448 | EQUB &19, &15, &20, &03, &3C, &00 449 | EQUB &19, &04, &20, &03, &64, &00 450 | EQUB &19, &15, &52, &03, &78, &00 451 | EQUB &19, &15, &BB, &03, &80, &00 452 | \ Define graphics colour (GCOL a,n) 453 | EQUB &12, &00, &02 \ green 454 | \ PLOT K,x,y 455 | EQUB &19, &04, &00, &05, &17, &00 456 | EQUB &19, &05, &C4, &04, &28, &00 457 | EQUB &19, &04, &E2, &04, &1C, &00 458 | EQUB &19, &05, &DE, &03, &38, &00 459 | EQUB &19, &04, &80, &02, &82, &00 460 | EQUB &19, &05, &48, &03, &0E, &01 461 | EQUB &19, &05, &AC, &03, &45, &01 462 | EQUB &19, &05, &1A, &04, &4A, &01 463 | EQUB &19, &05, &00, &05, &AE, &01 464 | EQUB &19, &04, &2C, &01, &C8, &00 465 | EQUB &19, &05, &8A, &02, &40, &01 466 | EQUB &19, &05, &3E, &03, &04, &01 467 | EQUB &19, &04, &F4, &01, &64, &00 468 | EQUB &19, &05, &FA, &00, &DC, &00 469 | EQUB &19, &05, &8C, &00, &54, &01 470 | EQUB &19, &05, &00, &00, &68, &01 471 | \ Define graphics colour (GCOL a,n) 472 | EQUB &12, &00, &04 \ blue 473 | \ PLOT K,x,y 474 | EQUB &19, &04, &9E, &02, &96, &00 475 | EQUB &19, &15, &F4, &01, &78, &00 476 | EQUB &19, &05, &58, &02, &64, &00 477 | EQUB &19, &05, &90, &01, &5A, &00 478 | EQUB &00 \ 256 bytes 479 | \ TODO - what is this list? still in use? 27b0 480 | EQUB &7D, &2D, &20, &13, &28, &A9, &09, &85, &83, &A9, &F0, &85, &82, &4C, &13, &28, &A9, &00, &8D 481 | \.L27C3 482 | 483 | .backgnd_sprite_addr_table 484 | EQUB &58 \ first is length of list, 88 bytes, 44 words 485 | EQUW X_base_addr + &3A0 \ sprite source addr, tree tops 486 | EQUW &7393, &7149, &7660, &7599, &7344, &78C9, &76B4 \ destination addrs 487 | EQUW X_base_addr + &3C0 \ next sprite source addr, tree mid 488 | EQUW &7613, &7893, &73C9, &7649, &78E0, &7844, &75C4 \ destination addrs 489 | EQUW X_base_addr + &3E0 \&1CE0 tree base 490 | EQUW &7B13, &7B4A, &7B60, &7AC4 491 | EQUW X_base_addr + &400 \&1D00 roof 492 | EQUW &78B0, &7820, &785C 493 | EQUW X_base_addr + &420 \&1D20 damaged roof 494 | EQUW &7800, &7688 495 | EQUW X_base_addr + &460 \&1D60 church clock 496 | EQUW &7060 497 | EQUW X_base_addr + &480 \&1D80 church wall 498 | EQUW &72E0, &7560, &77E0, &7A80, &7AA0, &7ADC 499 | EQUW X_base_addr + &4A0 \&1DA0 church door 500 | EQUw &7A60, &7B30 501 | EQUW X_base_addr + &4C0 \&1DC0 house 502 | EQUW &7908 503 | EQUW X_base_addr + &4E0 \&1DE0 house ruin 504 | EQUw &7928 505 | EQUB &00 506 | 507 | .end_PIG_02 508 | PRINT ".end_PIG-02 = ", ~end_PIG_02 509 | -------------------------------------------------------------------------------- /Clean/SS-01.asm: -------------------------------------------------------------------------------- 1 | \ converted from $.S BIRD DISK Side 1 2 | \ (c) Andy Frigaard 1984 to May 2021 3 | \ The SS files were written last (1984) and refer to earlier subroutines in PIG, GG files. 4 | \ This source file is edited down to contain only required elements 5 | \ for a build using beebasm. 6 | \ Contains 7 | \ Main loop keyboard handling 8 | \ Patches that modify or are called by earlier code. 9 | \ Bonus routines 10 | \ Game entry screen, logo, high score in MODE 7 teletext data 11 | 12 | \ ORG $1400 \ "P%" as per the original source 13 | .start_SS_01 14 | PRINT ".start_SS_01 = ", ~start_SS_01 15 | \ AF: Last few chars of this string may have been used for padding to adjust some location 16 | EQUS "Thanks David,Ian,Martin,Mum,Dad,Susi C" 17 | 18 | \\ game_over - Display GAME OVER message, and 19 | \\ Called from gun_hit_display, after last player killed. 20 | \\ Calls newgame 21 | \\ Inputs 22 | \\ Outputs 23 | .game_over 24 | .gov 25 | { 26 | PLA:PLA \ pull stack, will not return to calling routine 27 | LDY#255 28 | .gov1 \ Spell out GAME OVER slowly, delay between characters 29 | INY:LDA #10:JSR delay \ delay for 10x20 = 200ms 30 | LDA gov2,Y:JSR oswrch \ 'R' is last character 31 | CMP #82: BNE gov1 \ loop through 32 | LDA #150:JSR delay 33 | JMP newgame 34 | 35 | .gov2 36 | EQUB &1F, &05, &0F \ oswrch, move cursor to &05, &0F, COL 1 37 | EQUB &11, &01 \ oswrch, set COL 1 38 | EQUS "GAME OVER" 39 | } 40 | \\ End of game_over - Display GAME OVER message 41 | 42 | 43 | \\ Bonus routine 44 | \\ Bonus completed, reward by playing the tune 45 | \\ Called from score sor in SS-03 46 | .bon 47 | { 48 | LDA fc:AND #3:BNE play_short \ load frame/level counter, if 4,8,12.. major bonus 49 | LDA #15:JSR delay \ then pause, delay for 15x20 = 300ms 50 | JSR stmv:JMP play_full \ do stmv , draw tune, then play full tune. 51 | .play_short \ Choose tune, based on frame counter, play 1 part tune 52 | JSR cht:JSR tune 53 | .play_full \ full 4 part tune 54 | JSR wbmsg: 55 | LDY #75 \ 75 x 20 = 1500 bonus 56 | .bonus_loop \ slowly increment score 57 | SED:CLC 58 | LDA sc+1:ADC#2:STA sc+1 59 | LDA sc+2:ADC#0:STA sc+2 \ Add 2 to score 60 | CLD 61 | LDA #2:JSR delay \ then delay for 2x20 = 40ms 62 | TYA:PHA 63 | LDX #LO(sound_bonus):LDY#HI(sound_bonus) 64 | LDA #7:JSR osword \ OSWORD - A=7 SOUND command at &2DF8 65 | JSR score_update_screen \ display score 66 | PLA:TAY:DEY:BNE bonus_loop 67 | 68 | INC bsou \ why? byte 1 from &FF to 00 69 | LDX #LO(bsou):LDY #HI(bsou) \ sound defined below 70 | LDA #7:JSR osword \ OSWORD - A=7 SOUND command at bsou 71 | DEC bsou 72 | LDA #&80:ORA sc:STA sc \ set score flag for next level 73 | RTS 74 | } 75 | 76 | \\ Write Bonus message 77 | .wbmsg 78 | { 79 | LDY #0: 80 | .wb1 81 | LDA bmsg,Y:JSR &FFEE: \ iterate through 0 to 10 char 82 | INY:CPY #11:BNE wb1: RTS 83 | .bmsg 84 | EQUD &071F0611: EQUB &F \ Mode 7, Cyan text, centred 85 | EQUS "BONUS!" \ message 86 | } 87 | 88 | \\ Start of HSTRS file, MODE 7 bytes 89 | \\ TODO - can copy all this to a low page on load. 90 | \\ nbk Name parameter Block for OSWORD call to read user name 91 | .nbk \=&15C0 \EQUB $B4,$16,$08,$20,$7F 92 | EQUB &B4, &16, &08, &20, &7F 93 | \\ High Score, 3 bytes, Initially 0200 00 94 | .hs \=&15C5 95 | EQUB &00, &01, &00 96 | \\ Mode 7 title screen 97 | .m7 \=&15C8 98 | EQUB &16, &07, &17, &00, &0A, &20, &00, &00 99 | EQUB &00, &00, &00, &00 100 | \\ Bird Strike logo, in teletext characters 101 | \\ Copyright, High score etc 102 | .bsk \=&15D4: 103 | EQUB &9A, &94, &68, &3F, &6F, &34, &20, &20, &20, &20, &20, &20 104 | EQUB &20, &20, &FF, &20, &20, &5F, &7E, &2F, &6D, &20, &78, &20, &20, &20, &20, &20 105 | EQUB &20, &20, &7E, &0D, &9A, &96, &6A, &7D, &7E, &25, &20, &2F, &20, &30, &20, &20 106 | EQUB &20, &20, &FF, &20, &20, &6A, &7D, &70, &30, &20, &FF, &2C, &20, &30, &20, &20 107 | EQUB &2F, &20, &FF, &5F, &3E, &0D, &9A, &94, &6A, &3F, &60, &6F, &34, &FF, &20, &FF 108 | EQUB &2F, &21, &78, &2F, &FF, &20, &20, &20, &60, &60, &FF, &20, &FF, &20, &20, &FF 109 | EQUB &2F, &21, &FF, &20, &FF, &6F, &30, &20, &7E, &7B, &34, &0D, &9A, &96, &2A, &7D 110 | EQUB &70, &7E, &25, &6F, &30, &FF, &20, &20, &6F, &7C, &3F, &20, &20, &2A, &7C, &7E 111 | EQUB &27, &20, &6F, &74, &30, &FF, &20, &20, &6F, &30, &FF, &20, &2B, &34, &6D, &78 112 | EQUB &24, &1F, &05, &05, &82, &46, &49, &52, &45, &46, &4C, &59, &20, &28, &63, &29 113 | EQUB &20, &41, &6E, &64, &72, &65, &77, &20, &46, &72, &69, &67, &61, &61, &72, &64 114 | EQUB &0D, &1F, &0B, &08, &8D, &83, &48, &69, &67, &68, &20, &53, &63, &6F, &72, &65 115 | EQUB &1F, &0B, &09, &8D, &83, &48, &69, &67, &68, &20, &53, &63, &6F, &72, &65, &00 116 | \\ dots .... string 117 | .dts \=&16A0 118 | .dots_str 119 | EQUB &1F, &0B, &0B, &2E, &2E, &2E, &2E, &2E, &2E, &2E, &2E, &2E, &2E, &2E, &2E, &2E 120 | EQUB &00, &1F, &19, &0B 121 | \\ High score Name string - rewritable 122 | .nam \=&16B4: 123 | EQUB &61, &6E, &64, &72, &65, &77, &20, &20, &00 124 | \\ Instructions strings 125 | .ints \=&16BD 126 | .instructions_str 127 | EQUB &1F, &0E, &0E 128 | EQUB &8D, &83, &4B, &65, &79, &73, &1F, &0E, &0F, &8D, &83, &4B, &65, &79, &73, &1F 129 | EQUB &06, &11, &86, &5A, &20, &2E, &2E, &2E, &2E, &2E, &2E, &2E, &2E, &2E, &2E, &2E 130 | EQUB &2E, &20, &6D, &6F, &76, &65, &20, &6C, &65, &66, &74, &1F, &06, &12, &86, &58 131 | EQUB &20, &2E, &2E, &2E, &2E, &2E, &2E, &2E, &2E, &2E, &2E, &2E, &20, &6D, &6F, &76 132 | EQUB &65, &20, &72, &69, &67, &68, &74, &1F, &06, &13, &86, &52, &45, &54, &55, &52 133 | EQUB &4E, &20, &2E, &2E, &2E, &2E, &2E, &2E, &2E, &2E, &2E, &2E, &2E, &20, &73, &68 134 | EQUB &6F, &6F, &74, &1F, &06, &14, &86, &53, &2F, &51, &20, &2E, &2E, &2E, &2E, &2E 135 | EQUB &2E, &2E, &20, &73, &6F, &75, &6E, &64, &20, &6F, &6E, &2F, &6F, &66, &66, &1F 136 | EQUB &06, &15, &86, &52, &20, &2E, &2E, &2E, &2E, &2E, &2E, &2E, &2E, &2E, &2E, &2E 137 | EQUB &2E, &2E, &2E, &2E, &2E, &2E, &20, &72, &65, &73, &74, &00 138 | \ Press space to play string 139 | .sps \=&175C 140 | EQUB &1F, &07, &18, &81 141 | EQUB &88, &50, &72, &65, &73, &73, &20, &73, &70, &61, &63, &65, &20, &74, &6F, &20 142 | EQUB &70, &6C, &61, &79, &2E, &00 143 | \ end of HSTRS 144 | 145 | \\ Start of SS-02 lines. 146 | \\ Was at ORG $1778 147 | 148 | \\ Draw Musical Staves, Notes, Play Tune 149 | \\ Called from Bonus routine, SS-01 150 | \\ Calls JSR stv in GG-01 151 | \\ Inputs: 152 | \\ stm = ?? 153 | \\ Constants: 154 | \stave_base_addr = &80.. 155 | \TODO - appears to modify fc temporarily, maybe fc used in subroutines. 156 | stave_base_addr = &2688 \Adds 0A, so &3088, 3A88,... 157 | .stmv 158 | LDY #10 \ set offset 10 159 | .stm4 160 | LDA stm10,Y: JSR oswrch \ OSWRCH Write character stm10,Y 161 | DEY:BPL stm4 \ branch if positive, loop 162 | \self modifying code 163 | LDA #&80:STA stm2+1: 164 | LDA #0:STA stm3+1: 165 | LDA #4:STA no \ draw 4 staves, store counter 166 | .stm1 167 | LDA #29:JSR oswrch: \ Define graphics origin 168 | LDA #0:JSR oswrch:JSR oswrch \ 0, 0 169 | SEC \set Carry 170 | \ Subtract memory from accumulator with carry A,C=A-M-(1-C) 171 | .stm2 172 | LDA #0:SBC #&80:STA stm2+1 \ modified above 173 | PHP:JSR oswrch \ graphics origin parameter 174 | PLP 175 | .stm3 176 | LDA #0:SBC #0:STA stm3+1 177 | JSR oswrch \ graphics origin parameter 178 | JSR stv \ Draw one stave, loop 4 times 179 | DEC no:BNE stm1 \ loop 4,3,2,1 180 | 181 | \ draw notes, play tune 182 | .stm5 LDA fc:STA tm \ save fc in temp 183 | LDA #0:STA fc: \ initial fc=0, INC below to 1 184 | LDA #LO(stave_base_addr):STA tm+3 185 | LDA #HI(stave_base_addr):STA tm+4 186 | .stm6 187 | CLC: 188 | LDA tm+3:STA not \not = X_base_addr + &459 \ note sprite origin , not+1 189 | LDA tm+4:ADC #&A:STA tm+4 190 | STA not+1 191 | JSR cht 192 | STX nl:INC fc 193 | .stm8 194 | JSR nxno:BNE stm8:JSR cht:JSR tune 195 | LDA #60:JSR delay \ delay for 60x20 = 1200ms 196 | LDA fc:CMP #4:BNE stm6 \ loop for 4 levels 197 | LDA tm:STA fc: \ restore fc 198 | LDA #26:JMP oswrch \JMP to OSWRCH, so will RTS to calling code 199 | .stm10 \static bytes 4+4+2+1 = 11 bytes 200 | EQUD &04FF0310: 201 | EQUD &000F020F: 202 | EQUW &18F0: 203 | EQUB 26 204 | \\ End Draw Musical Staves, Notes, Play Tune 205 | 206 | 207 | \\ Game End routine 208 | \\ Display title screen in MODE 7, High Score etc 209 | \\ Called from newgame 210 | \\ uses strings dots_str, instructions_str defined in SS-01 211 | .gend 212 | { 213 | LDA #0:STA hs: \ set hs to 0 214 | LDA sc+2:CMP hs+2:BCC ge1 \ Compare High score MSB 215 | BNE ge0 216 | LDA sc+1:CMP hs+1:BCC ge1 \ Compare High score MSB 217 | .ge0 218 | LDA sc+1:STA hs+1: \ Update High score with player score LSB, MSB 219 | LDA sc+2:STA hs+2: 220 | DEC hs \ Set hs to &FF 221 | .ge1 222 | LDA #22:JSR oswrch \ OSWRCH Change to screen MODE 7 (Teletext) 223 | LDA #7: JSR oswrch 224 | LDX #(bsk AND255):LDY#(bsk DIV256):JSR wrs 225 | LDA #31:JSR oswrch: \ move cursor to 5,11 226 | LDA #5:JSR oswrch: 227 | LDA #11:JSR oswrch 228 | LDA hs+2:JSR whs \ write high score 229 | LDA hs+1:JSR whs 230 | LDA #48:JSR oswrch 231 | 232 | LDX #LO(dots_str): LDY#HI(dots_str):JSR wrs 233 | LDX #LO(instructions_str):LDY#HI(instructions_str):JSR wrs 234 | LDA #31:JSR oswrch \ move cursor to 26, 11 235 | LDA #26:JSR oswrch 236 | LDA #11:JSR oswrch 237 | LDA hs:BEQ ge3 \ if high score, then user may enter name 238 | LDA #21:LDX #0:JSR osbyte \ OSBYTE 21 X=0 Keyboard buffer emptied \ flush 239 | \ User can enter high score name. 240 | TXA 241 | LDX#LO(nbk):LDY#HI(nbk):JSR osword: \OSWORD - A=0 Read from keyboard to nbk 242 | JMP ge7 243 | 244 | .ge3 \ display existing high score name 245 | LDY #&FF 246 | .ge6 247 | INY:LDA nam,Y:JSR &FFE3 \ iterate through 32 chars in nam, OSASCI 248 | CMP #32:BPL ge6 249 | 250 | .ge7 251 | LDY #2: 252 | .ge5 253 | LDA m7,Y:JSR oswrch \ iterate through 2 to 13 chars in m7, OSCASCI 254 | INY:CPY #13:BNE ge5 255 | LDA #100:JSR delay \ delay for 100x20 = 2000ms 256 | 257 | .*space 258 | LDA #26:JSR oswrch \ OWSRCH, 26 restore default viewport? 259 | \LDX #(sps AND 255):LDY #(sps DIV 256):JSR wrs 260 | LDX #LO(sps):LDY #HI(sps):JSR wrs \ write string 261 | .ge4 262 | LDX #&9D:JSR key \ wait for space bar, loop 263 | BNE ge4 264 | RTS 265 | } 266 | \\ End of Game End routine 267 | 268 | 269 | \\ Write High Score 270 | \\ Called from Game End routine above 271 | .whs 272 | { 273 | PHA: LSRA:LSRA:LSRA:LSRA \ Push A, BCD number, divide x 16 to move to low nibble 274 | CLC:ADC #&30:JSR &FFE3 \ add &30 to make ASCII, call OSASCI, write line feed 275 | PLA: AND #&F:CLC:ADC #&30 \ Pull A, mask 4 high bits, add &30 276 | JMP &FFE3 \ call OSASCI/OSWRCH and RTS to calling code 277 | } 278 | \\ End of Write High Score 279 | 280 | \\ Write String to OSASCI, zero terminated string 281 | \\ called with dts, ints, sps address 282 | \\ input X=low byte, Y=high byte of dts address 283 | .wrs 284 | .write_string 285 | { 286 | STX modify_string_addr+1 \ store parameter values direct, modifying code, SMC 287 | STY modify_string_addr+2 288 | LDY #&FF 289 | .wr1 290 | INY 291 | .modify_string_addr 292 | LDA dots_str,Y: JSR &FFE3 \ iterate through supplied table, calling OSASCI line feed 293 | CMP #0:BNE wr1 \ terminates when A=0 294 | RTS 295 | } 296 | .end_SS_01 297 | PRINT ".end_SS_01 = ", ~end_SS_01 -------------------------------------------------------------------------------- /Clean/SS-03.asm: -------------------------------------------------------------------------------- 1 | \ converted from $.S BIRD DISK Side 1 2 | \ (c) Andy Frigaard 1984 to May 2021 3 | \ The SS files were written last and refer to earlier subroutines in PIG, GG files 4 | \ This source file is edited down to contain only required elements 5 | \ for a build using beebasm. 6 | \ Contains 7 | \ Main loop & startup routines 8 | \ Score handling and display 9 | \ Musical routines and tune display 10 | \\ AF 29/6/21 New level intialisation uses lookup table avoids Iains unbounded 11 | \\ bug on high levels. Allows more flexible difficulty model. 12 | 13 | 14 | \ org $1E00 \ "P%" as per the original source 15 | .start_SS_03 16 | PRINT ".start_SS_03 = ", ~start_SS_03 17 | \\ Game entry point here 18 | .game 19 | \ Close the open boot file, required if loading over DFS workspace at &1100 20 | \ https://stardot.org.uk/forums/viewtopic.php?f=74&t=23054&p=329177&hilit=close%230#p329177 21 | LDA #0:TAY:JSR osfind 22 | 23 | \ Set Escape Disabled 24 | LDA #200:LDX #03:LDY #0:JSR osbyte \OSBYTE &C8 (200) *FX 200 Read/write ESCAPE, BREAK 25 | JSR space 26 | \ source was missing these 4 line 27 | \ Added AF 6/6/2021 28 | LDX #&01: LDA #&04: LDY #&00 29 | JSR osbyte \ OSBYTE 04 Disable cursor editing, X=1 30 | LDA WORDvA :STA soun: \ save OSWORD vector to .soun, &020C 31 | LDA WORDvB :STA soun+1 32 | 33 | .newgame 34 | JSR gend \ display title screen 35 | JSR start_game \ Start - after spacebar, start new game 36 | 37 | \\ Game main loop 38 | \\ run, until ESC pressed 39 | \\ the order of these can be important as flags are passed in the score byte 40 | .GO 41 | JSR random1 \ update "random" numbers for use later R% 42 | JSR scr \ wait for vsync timing 43 | \ LDA #&00+(1 EOR 7):STA &FE21 \show red indicator for start sprite drawing 44 | JSR mp \ Move planes, mp 45 | JSR np \ New plane, np 46 | 47 | JSR mg \ Move gun, mg, player moves?m 48 | JSR mb \ Move bullet 49 | JSR nb \ New bullet, nb, player fires? 50 | JSR move_bombs \ Move bombs 51 | JSR new_bomb \ New bombs nbo 52 | \ LDA #&00+(0 EOR 7):STA &FE21 \clear red indicator for end sprite drawing 53 | JSR pg \ Move bird, was B% 54 | JSR gun_hit_display \ Player Hit processing, was H% 55 | JSR sor \ gravestones, score? 56 | JSR check_key_press \ keyboard inputs, was opt 57 | 58 | JMP GO 59 | 60 | EQUS "(c)A.E.Frigaard 1984 Hello!" 61 | 62 | \\ Define lists for any parameters changing over 8 levels 63 | \\ Must have values as multiples shown 64 | \\ Used in .. uses Level 8 for all subsequent 65 | 66 | .level_de \ delta tracking, was -2 on odd levels originally 67 | \\ values near 0 are perfect tracking of player by the plane 68 | EQUB 32, 30, 28, 26, 24, 22, 20, 18 69 | \EQUB 32, 30, 28, 28, 26, 26, 24, 24 70 | 71 | .level_bullet_count \ allow up to 4 x 4 byte bullets - must modify list length too, 6,10, 8? 72 | \original game starts with 2 bullets 73 | EQUB 8, 8, 10, 12, 14, 16, 16, 16 74 | 75 | .level_bullet_interval \ this is set in new_bullet as 18, modified from this list, each level. 76 | EQUB 12, 10, 08, 08, 08, 08, 08, 08 77 | 78 | .level_bomb_count \ allow up to 7 x 2 byte bombs (16 byte space in zp) 79 | EQUB 4, 6, 8, 10, 12, 12, 12, 12 \ max 14 bytes in table 80 | 81 | .level_bomb_interval \ bits 6,7 set bits 0-5 are counter, so &C0 + timer 82 | EQUB &2F,&27,&1F,&17,&0F,&0F,&0F,&0F 83 | \timer=0F => room for 6 to 7 on screen at rate 3 84 | \timer=1C => room for 4 on screen; rate 3 will need to fall faster too. 85 | .level_bomb_rate \ bits 6,7 set bits 0-5 are counter, so &C0 + timer 86 | EQUB 03,03,03,03,04,04,04,04 87 | 88 | \\ Start new game, was .S% 89 | \\ Intialise variables, setup screem 90 | \\ Called for every new game (not each level) 91 | .start_game 92 | LDA #5:STA no:JSR def_envelopes \ Store 5 at counter, call define envelope E% 93 | LDA #&49:JSR tune \ play starting tune 94 | LDA #22:JSR oswrch \ select MODE 2 via OSWRCH 95 | LDA #2:JSR oswrch 96 | \ intialise to zero counters, scores 97 | LDA #0:STA exg3:STA cnt:STA fc:STA picn:STA gex:STA sc+1:STA sc+2:STA plf: 98 | \make this a loop TODO 99 | STA b_addr: STA b_addr+1:STA b_addr+2:STA b_addr+3:STA b_addr+4:STA b_addr+5 \AF July TODO full length 100 | CLC 101 | \LDA #32:STA de 102 | LDA #3:STA ti \ ti=de+1 initial timer value first plane to fly 103 | LDA #42:STA ti+1 \ default timer value was de+2, subsequent timer 104 | LDA #2:STA bfg 105 | 106 | LDA #LO(bullet_list):STA bulst 107 | LDA #HI(bullet_list):STA bulst+1 108 | \LDA #LO(bomb_addr):STA bost \todo no longer used, now table is in ZP 109 | \LDA #HI(bomb_addr):STA bost+1 110 | LDA #LO(plane_list):STA pls 111 | LDA #HI(plane_list):STA pls+1 112 | 113 | \\ Setup screen colours - load palette 114 | LDX #15:LDY #7 115 | .co1 116 | .colour_loop 117 | JSR def_log_colour \ JSR call 8 times, decrementing X, was D% 118 | DEX: CPX #7:BNE colour_loop 119 | 120 | STX ra1 \ save X 7 in ra1 121 | LDA #1: STA player_dies+1 \\ god-mode, player_dies=0, false 122 | LDA #player_live_init:STA gex+1 \\ player lives, 3 123 | LDA #HI(plane_sprite_addr):STA plf+1 \ LO addresses set per game frame 124 | 125 | \\ new level intialisation AF 29/6/21 126 | \\ not reqd 127 | \LDA #&F0:STA inb \\ flag 1111 0000 128 | \LDA #0:STA tm+1 \\ used for bomb list counter start (0),2,3 AF try 2 129 | 130 | \\ init, L1, L2, L3, .. 131 | \\ de 32, 30, 30, 28 \ -2 on odd levels 132 | \\ ti 03 133 | \\ ti+1 42 134 | \\ bfg? 02 135 | \\ tm 136 | \\ tm+1 0, 2, 2, 4, 4 \bomb list counter start 137 | \\ ra? 138 | \\ tune 139 | \\ fc 00, 01, 02, 03 140 | \\ inb &F0,&EF,&EF,&EE,&EE, 141 | \\ gex+1 03 \player lives, no change 142 | 143 | 144 | \\ Begin Level (next frame) 145 | .bf 146 | .begin_level 147 | { 148 | JSR cht \ call Change Tune, returns A=? X=? 149 | STX nl:INC fc: \ increment frame counter, game level X=7?? 150 | \LDA de:CMP #15:BMI b0: \ if de, difficulty < 15, go .b0 (branch if minus) 151 | \LDA fc:AND #1:BEQ b0 \ else if level is odd (1,3,5) 152 | \DEC de:DEC de: \ then decrement x 2 de 153 | \DEC inb \ and decrement inb 154 | \.b0 \ IainFM: I also moved the .b0 label in SS-03.asm. That seems to have cured the bug, although I've not tested it to destruction yet! 155 | \INC tm+1:INC tm+1: \ inc x 2 tm+1, this is default timer? Add 2 more bomb per level? 156 | \TODO check bounds, also only two bombs shown on level 1 even with 4 157 | 158 | \ initialise lists by clearing to zero 159 | \ &54 bytes covers bullet_list, plane_list, bomb_list - can extend this: 160 | \ LDY #cloud_sprite_offset_list - bullet_list -1 161 | LDY #last_list - bullet_list -1 162 | 163 | LDA#0 164 | .clear_bullet_list 165 | STA bullet_list,Y: DEY: BPL clear_bullet_list \ clear &54 bytes at &2D0A (bullet_list set to 0) 166 | LDY #&1F 167 | .clear_bomb_list 168 | STA bomb_count,Y:DEY:BPL clear_bomb_list \ clear &50 to &06F 169 | .b0 170 | LDA #12:JSR oswrch \ OSWRCH clear the screen 171 | LDA #154:LDX #20:JSR osbyte \ OSBYTE Write to video ULA control register and OS copy 172 | JSR plot_clouds \ Draw the clouds, was C% 173 | JSR draw_backgnd_art \ Draw the vector art, V% 174 | JSR stv \ Draw the musical stave, stv? 175 | JSR score_update_screen \ Write the score to screen 176 | 177 | LDA #0:STA plane_kill_count: 178 | STA sc:STA ba+1 179 | 180 | \\ new level intialisation AF 29/6/21 181 | LDY fc: DEY \ zero based , first level=0 182 | \TODO cap the level at 8 ADN#7 183 | LDA level_de,Y: STA de 184 | LDA level_bomb_interval,Y: ORA#&C0 \set bits 6,7 185 | STA inb: \ LDA#&3F: 186 | STA bofg \AF July initiliase? 187 | SEC 188 | LDA level_bomb_count,Y: SBC #2 \ allow up to N bombsm store N-2, as loops are zero-based 189 | \STA tm+1: \LDA tm+1: 190 | STA bomb_max_count 191 | LDA level_bomb_rate,Y: 192 | STA bomb_vert_rate:CLC:ADC#&78:STA bomb_vert_LO 193 | EOR #7: AND#7:TAX:INX:STX bomb_vert_newline \ 194 | 195 | LDA level_bullet_count,Y 196 | STA bullet_list \ allow up to 4 x 4 byte bullets - must modify list length too, 6,10, 8? 197 | LDA level_bullet_interval,Y 198 | STA bullet_interval+1 \ SMC sets immediate LDA in new_bullet 199 | LDA #30: \ TEST set to 10, 2 planes 200 | STA plane_list \ allow up to 6 x 5 byte planes AF TEST was 30 201 | 202 | note_screen_addr = &3088 203 | gun_screen_addr = &3280 \ or 3288? 204 | LDA #LO(note_screen_addr):STA not 205 | LDA #HI(note_screen_addr):STA not+1 206 | LDA #LO(gun_screen_addr):STA gex+2 \TO do - more related init below? is this needed? 207 | LDA #HI(gun_screen_addr):STA gex+3: 208 | 209 | \\ draw initial player gun indicators 210 | LDX gex+1 \ number of player guns 211 | .pmi 212 | JSR mini \ draw mini gun indicator top left 213 | CLC 214 | LDA gex+2:ADC #&18:STA gex+2 215 | DEX:BNE pmi \ loop for no of guns 216 | 217 | \\ draw initial planes 218 | plane_screen_addr = &3A81 \ TODO - this is not an address 219 | LDA #HI(plane_screen_addr):STA sd+1 \ sd not used in intialisation 220 | LDA #LO(plane_screen_addr):STA sf \ odd, uses sf as a temp workspace 221 | LDX#1:LDY#8 222 | .pp1 \TODO use of sf seems incomplete? inspect list? 223 | LDA #LO(plane_screen_addr) \ #&81 224 | STA plane_list,X \ LO address element 1 225 | INX:TYA \ Y = 8, copy to A 226 | CLC 227 | ADC #&50:STA plane_list,X \ add 8+50, &58, LO address=element 2 228 | TAY:INX \ y=&58 , Y is temp store A during loop 229 | LDA sd+1:ADC #0 \ add 16 bit carry 230 | STA plane_list,X: STA sd+1 \ HI address=element 3 231 | CLC:INX 232 | LDA sf:ADC #10 \ each plane is &50 bytes, 10 X-coord apart 233 | STA sf:STA plane_list,X \ 81, 95, 9F, A9, B3, BD = element 4 psta 234 | INX 235 | LDA #&D0:STA plane_list,X \ y-coord? &D0 - sort of flag, sprite offset? 236 | \TODO use BCC compare with 30, use bullet_list 237 | INX:CPX #31:BMI pp1 \ loop 6 times, X inc 5 each cycle 238 | \INX:CPX #16:BMI pp1 \ loop 6 times, X inc 5 each cycle AF TEST 239 | 240 | \ for future use - simplified plane list setup 241 | \LDX #0 242 | \LDA #LO(plane_screen_addr):STA sf \ &81, uses sf as a temp workspace 243 | \CLC 244 | \.plane_setup_loop 245 | \ LDA sf:ADC #10 \ each plane is &50 bytes, 10 X-coord apart 246 | \ STA sf:STA plX,X \ 81, 95, 9F, A9, B3, BD = element 4 psta 247 | \ INX 248 | \ CPX #6: BCC plane_setup_loop 249 | 250 | LDY #0 251 | LDA (pls),Y:STA no \ plane_list, 0 is &1E,30 = 6 planes, 5 bytes 252 | .slop 253 | INY: 254 | INY:LDA (pls),Y:STA pos \ zp plane pointer to plane_list, screen address 255 | INY:LDA (pls),Y:STA pos+1 256 | JSR pp \ plots initial plane, 6 times 257 | INY:INY:CPY no:BMI slop 258 | JSR h7 259 | } 260 | \\ end of begin_level 261 | 262 | gun_init_screen_addr = &7E90 263 | .sgun \ Setup gun, initial screen position etc 264 | .player_gun_initialise 265 | LDA #32: STA Xg: \ Gun X position 266 | LDA #HI(gun_init_screen_addr):STA gunp+1: \ Gun position address MSB 267 | LDA #LO(gun_init_screen_addr):STA gunp: \ Gun position address LSB 268 | LDA #HI(gun_sprite_addr):STA gun+4: \ Modify Gun sprite address MSB 269 | LDA #LO(gun_sprite_addr):STA gun+3: \ Modify Gun sprite address LSB 270 | JSR gun: \ .gun in OLDSRCE, is modified by above lines. 271 | 272 | LDA #&40:JMP tune \play tune &40 273 | 274 | \\ Calculate the Score 275 | \\ Input: 276 | \ sc is a bitwise flag showing the events that have occurred in this last cycle 277 | \ sc = &01 : Unused? Set in nb, when firing bullet 278 | \ sc = &02 : Plane killed / +15(0) points 279 | \ sc = &10 : Pigeon killed (note added to stave / +10(0) points) 280 | \ sc = &20 : Set in mg, move_gun when hit, detected in gun_hit_display before .sor 281 | \ sc = &40 : Plane Wing has been hit (pigeon release / +1(0) points) 282 | \ sc = &80 : Level is complete (load next level / +0 points); set in bonsu and new_plane 283 | \ Output: 284 | \ sc is cleared = 0 285 | \ sc+1 increased 286 | \ sc+2 increased 287 | .end_frame 288 | EQUB 0 \ if set to 1, then frame end, do last cycle to clear sprites (bullet, bomb) 289 | .score_exit 290 | RTS 291 | .sor 292 | { 293 | \LDA sc:BEQ score_update_screen \ if zero, no score events 294 | LDA sc:BEQ score_exit \ if zero, no score events, so exit 295 | SED \ decimal scoring 296 | AND #2:BEQ s1 \ bit 1 not set 297 | CLC:LDA #&15 \ score for plane 15 => 150 298 | ADC sc+1:STA sc+1 \ 16 bit add dec 15 to sc+1 299 | LDA sc+2:ADC #0:STA sc+2 300 | JSR plane_hit \ was X% 301 | 302 | .s1 303 | LDA #&40:BIT sc:BEQ s4 \ bit 6 not set 304 | CLC:LDA #1 305 | .wng \ score for plane wing 1 => 10 306 | ADC sc+1:STA sc+1: \ 16 bit add dec 1 to sc+1 307 | LDA sc+2:ADC #0:STA sc+2 308 | CLD 309 | LDX #LO(bsou):LDY#HI(bsou) 310 | LDA #7:JSR osword \OSWORD - A=7 SOUND command at bsou 311 | SED 312 | 313 | .s4 314 | LDA #&10:BIT sc:BEQ s2 315 | CLC:LDA #10 316 | .pig \ score for pigeon 10 => 100 317 | ADC sc+1:STA sc+1 \ 16 bit add dec 10 to sc+1 318 | LDA sc+2:ADC#0:STA sc+2 319 | CLD: 320 | JSR nxno:BNE s2 \ add next Note, check bonus? 321 | JSR bon \ do bonus - will set score flag for next level 322 | 323 | .s2 324 | CLD:JSR exg \ check for extra player? 325 | LDA sc:BPL s3 \ BIT 7 is set, end of level TODO - clean up bullets 326 | LDA end_frame: BNE end_level \ first pass end_frame=0, so set to &80 and do next cycle 327 | LDA #&80: STA end_frame: STA sc 328 | \RTS \ TODO bug exit and allow one more cycle to clean-up sprites. 329 | JMP s3 330 | .end_level 331 | LDA#0: STA sc: STA end_frame \ second pass, clear sc and go to next_level 332 | JMP next_level 333 | .s3 334 | LDA #0:STA sc \ clear score byte for next cycle 335 | \ fall through to display score 336 | \ RTS 337 | } 338 | \\ sor end 339 | 340 | \\ Writes the score to screen 341 | \\ calls plot_score with A=Sprite offset 342 | \\ each call to plot_score increases SD address for next digit 343 | score_sprite_dest=&34B0 344 | .s7 345 | .score_update_screen 346 | { 347 | LDA #HI(score_sprite_dest):STA sd+1: 348 | LDA #LO(score_sprite_dest):STA sd: 349 | LDA #HI(score_sprite_base):STA sf+1: 350 | \ NNxxx digits 351 | LDA #&F0:AND sc+2:JSR plot_score 352 | LDA #&F:AND sc+2:ASLA:ASLA:ASLA:ASLA:JSR plot_score 353 | \ xxNNx digits 354 | LDA #&F0:AND sc+1:JSR plot_score 355 | LDA #&F:AND sc+1:ASLA:ASLA:ASLA:ASLA:JSR plot_score 356 | \ xxxxN final digit, always 0 357 | LDA #0:JMP plot_score 358 | } 359 | \\ Scoring - check for extra player 360 | \\ Called from: Calculate the Score 361 | \\ routine was moved from SS-01 to go with score routines here 362 | \\ TODO - monitor use of exg3 location/flag, move to variable 363 | .extra_player_check 364 | .exg 365 | { 366 | LDA #1:BIT exg3:BNE exg1 367 | LDY sc+2:CPY #5:BMI exg2 368 | ORA exg3:STA exg3:JSR exg4 369 | .exg1 370 | LDA #2:BIT exg3:BNE exg2 371 | LDY sc+2:CPY #&10:BMI exg2 \ if score over 10000? 372 | ORA exg3:STA exg3:JMP exg4 \ then store in exg3 373 | .exg2 374 | RTS: 375 | .*exg3 376 | EQUB 0 377 | .exg4 378 | JSR mini 379 | LDA #220:STA sound_note_volume \ &2DFC 380 | LDX #LO(sound_note):LDY#HI(sound_note) 381 | LDA#7:JSR osword \ OSWORD - A=7 SOUND command at &2DF8 382 | INC gex+1:CLC 383 | LDA gex+2:ADC #&18 \ set sprite screen position one right 384 | STA gex+2:BCC exg5 385 | INC gex+3 386 | .exg5 387 | RTS 388 | } 389 | \\ End of Scoring - check for extra player 390 | 391 | 392 | \\ Delay timer routine, uses vsync 20ms delay 393 | \\ input in A=n, Y preserved, n x 20ms delay 394 | \\ output original Y (also in A) 395 | .delay 396 | STA tm+2 \store counter in tm+2 397 | TYA:PHA \save Y 398 | .del1 399 | JSR scr \vsync 20ms delay 400 | DEC tm+2:BNE del1 \iterate until zero 401 | PLA:TAY:RTS \restore Y, return 402 | \\ end delay 403 | 404 | 405 | \\ Next level setup 406 | \\ Called from score routine 407 | \\ Calls delay 408 | .next_level 409 | .ef 410 | \LDA #0:STA sc \ clear score byte for next cycle 411 | CLC 412 | LDA plf: ADC#&40:STA plf \ plf = next plane from sprite address 413 | LDA #100:JSR delay: \ pause 414 | JMP begin_level \ play next frame/level 415 | \\ End of Next level setup 416 | 417 | 418 | \\ Choose Tune, Change Tune parameters in A, X 419 | \\ input fc parameters 420 | \\ output in A, X to control tune pointers? 421 | .cht 422 | LDA #3:AND fc:TAX:BNE ct1 \ if frame counter is 0, 4, 8 423 | LDA #&33:RTS \ then return A=&33, X=fc 424 | .ct1 \TODO - A, X mixed up here? 425 | DEX:BNE ct2 \ else if frame counter 1 426 | TXA:LDX#13:RTS \ then return A=fc-1, X=13 427 | .ct2 428 | DEX:BNE ct3 \ else if frame counter 2 429 | LDA #17:LDX #26:RTS \ then return A=17, X=26 430 | .ct3 431 | LDA#34:LDX#38 \ else fc 3, then return A=34, X=38 432 | RTS 433 | \\ End of Choose Tune 434 | 435 | \\ Plot Next Note 436 | \\ Calls pno, plot_note 437 | \ uses .nl lookup table 438 | \ nl,0 used for pointer to next note 439 | \ nl,Y used for .. 440 | .nxno 441 | INC nl:LDY nl \ inc note pointer 442 | LDA nl,Y:STA no 443 | AND #&E: 444 | CMP #8:BPL n1 445 | CLC:ADC not:STA sd 446 | LDA #0:BEQ n2 \ always 447 | .n1 448 | CLC:ADC not:ADC #&78:STA sd \ 16 bit add &0278, next row 449 | LDA #2 450 | .n2 451 | ADC not+1:STA sd+1 \ store sprite destination 452 | LDA #HI(note_sprite_addr) \ &23 453 | STA sf+1 454 | JSR chnot 455 | CLC 456 | LDA not:ADC #&20:STA not \ add &20 to sprite from 457 | BCC n3 458 | INC not+1 459 | .n3 460 | JSR pno \ plot_note 461 | CLC 462 | LDA sd:ADC#8:STA sd \ 16 bit add 8 to sprite destination 463 | BCC n4: 464 | INC sd+1 465 | .n4 466 | CLC 467 | LDA sf:ADC #8:STA sf \ 16 bit add 8 to sprite from 468 | BCC n5 469 | INC sf+1 470 | .n5 471 | JSR pno \ plot_note 472 | INY:LDA nl,Y 473 | RTS 474 | 475 | 476 | \\ Choose Note sprite to display 477 | \\ 2300 start of notes sprites to last 2340 478 | \\ Shift A, compare with "no" bitwise 479 | \\ find the case based on bit set in "no" 480 | .chnot 481 | LDA #&80:BIT no:BEQ c1 \ A = b1000 0000, set sf=&2300 482 | LDA #0:STA sf:RTS 483 | .c1 484 | LSRA: BIT no:BEQ c2 \ A = b0100 0000, set sf=&2310 485 | LDA #&10:STA sf:RTS 486 | .c2 487 | LSRA: BIT no:BEQ c3 \ A = b0010 0000, set sf=&2320 488 | LDA #&20:STA sf:RTS 489 | .c3 490 | LSRA: BIT no:BEQ c4 \ A = b0001 0000, set sf=&2330 491 | LDA #&30:STA sf:RTS 492 | .c4 493 | LDA #1:BIT no:BEQ c5 \ A = b0000 1000, set sf=&2340 494 | LDA #&40:STA sf 495 | .c5 496 | RTS 497 | 498 | \\ plot note on stave 499 | \\ uses ORA plotting, not XOR, to ensure colours are true. 500 | .pno TYA:PHA:LDY #7 501 | CLC:LDA sd:ADC #&78:STA st: 502 | LDA sd+1:ADC #2:STA st+1 503 | LDA sd:AND #7:EOR #7:STA mod 504 | CMP #7:BPL pntop 505 | .pnbot \ renamed bot to pnbot 506 | LDA(sf),Y:ORA(st),Y:STA(st),Y 507 | DEY:CPY mod:BNE pnbot 508 | .pntop 509 | LDA(sf),Y:ORA(sd),Y:STA(sd),Y 510 | DEY:BPL pntop 511 | PLA:TAY:RTS 512 | 513 | \\ Play the tune, pass in a parameter A, return X as 0 if pressed 514 | \\ Player can press space/any key to cut short the tune and continue play. 515 | \\ input A is Note, no, pointer to the tl (tune list) table 516 | \\ for example: &40 517 | \\ &2DF8 is start of OSWORD 7 parameter block, with these defaults: 518 | \\.L2DF8 EQUB $01,$00 519 | \\.L2DFA EQUB $05,$00 \OSWORD docs say &FF for MSBsound 520 | \\.L2DFC EQUB $49,$00 521 | \\.L2DFE EQUB $0F,$00 522 | \\ only update these: 2DFC = Pitch LSB, 2DFE = duration LSB 523 | .playTune 524 | .tune 525 | STA no: 526 | \ iterate through tl, Tune List, LDA tl,Y until zero value terminator 527 | \ no is the note counter, pointer to the tl (tune list) table 528 | .t1 529 | LDY no:LDA tl,Y: BEQ t3 \ get next note, 530 | STA sound_note_volume:INY: 531 | LDA tl,Y:STA sound_note_pitch \ store tune in OSWORD 7 parameter block 532 | LDX #LO(sound_note):LDY #HI(sound_note) 533 | LDA #7:JSR osword \ OSWORD - A=7 SOUND command at &2DF8 534 | INC no:INC no:JMP t1 \ increment Y + 2, loop 535 | 536 | \\ Profiler shows this loop is fairly heavy cycle count 537 | \\ TODO - any better way to wait for sound? Game is idle anyway? 538 | .t3 \ loop get sound, until Sound channel is clear? < 15 539 | LDA #&80:LDX #250:JSR osbyte \ OSBYTE 128 Get Sound Channel 1 buffer status in Y 540 | CPX #15:BMI t3 \ X contains spaces in sound buffer, loop until buffer is empty 541 | RTS \ then tune has played, can return. 542 | 543 | \\ Keyboard scan - check for key press, passed in X 544 | \\ Called from check_key_press below 545 | \\ input X = negative INKEY value, Y set to FF 546 | \\ output X = X and Y contain &FF if the key being scanned is pressed. 547 | .keyboardScan 548 | .key 549 | LDA #&81:LDY #&FF:JSR osbyte \ OSBYTE 129 Read key, keyboard scan for X (value?) 550 | INX:RTS \ X is &FF if pressed, so INX to 0, return 551 | \ X is 00 if not pressed 552 | 553 | \\ Check Key presses for user input 554 | \\ Called from main loop after all screen routines, moved from SS-01 555 | \\ Calls JSR key, OSBYTE 556 | \\ Note this writes OSWORD vector at &20C, turning sound on and off. 557 | \\ checking for R, S, Q on keyboard 558 | .check_key_press 559 | 560 | { 561 | \ DEC keycounter \ optimise - check key every N cycles 562 | \ BNE checkKeyComplete 563 | \ LDA #5:STA keycounter 564 | .checkQkey 565 | LDX #&EF:JSR key:BNE checkSkey \ EF=-17 INKEY Q, Quiet 566 | LDA #LO(mute):STA WORDvA \&20C \ rewrite OSWORD vector to below .mute 567 | LDA #HI(mute):STA WORDvB \&20D 568 | 569 | .checkSkey 570 | LDX #&AE:JSR key:BNE checkRkey \ AE=-82 INKEY S, Sound 571 | LDA soun:STA WORDvA \&20C 572 | LDA soun+1:STA WORDvB \&20D 573 | 574 | .checkRkey 575 | LDX #&CC:JSR key:BNE checkKeyComplete \ CC=-52 INKEY R, Rest 576 | \\ http://www.retrosoftware.co.uk/wiki/index.php?title=Reading_the_keyboard_by_direct_hardware_access 577 | \\LDA #&7F:STA &FE43 578 | \\SEI 579 | \\LDA #&0F:STA &FE42 \ allow write to addressable latch 580 | \\LDA #&03:STA &FE40 \ set bit 3 to 0 581 | .op3 582 | \\LDA #51:STA &FE4F:LDA &FE4F \ N flag = whether 'R' pressed 583 | \\BMI op5 584 | \\JMP op3 585 | LDA #&81:LDY #1:LDX #255:JSR osbyte \ OSBYTE 129 Read key, scan for 255cs, keyboard scan for X (value?) 586 | \\ TODO - bug does not return form this. 587 | 588 | BCS op3: \ If Carry is set, no key, loop 589 | CPX #82: \ Carry clear, X=character, 82 = R 590 | BEQ op3 \ If R pressed, loop, else RTS 591 | 592 | .op5 593 | \\CLI 594 | .checkKeyComplete 595 | RTS 596 | 597 | .keycounter 598 | EQUB 1 599 | .mute \ OSWORD vector points here when Q/mute 600 | CMP #07:BEQ op5 \ exit if OSWORD &07 601 | .mu1 602 | JMP(soun) 603 | } 604 | \TODO move this to a ZP memory location, is populated on game startup 605 | .soun \ OSWORD vector restored from here 606 | EQUW &E7EB 607 | \\ End of Check Key presses for user input 608 | 609 | 610 | .end_SS_03 611 | PRINT ".end_SS_03 = ", ~end_SS_03 612 | -------------------------------------------------------------------------------- /Clean/X.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qurm/BirdStrike/b13704515ac3996feeacb220ab03b2a1ba6c6869/Clean/X.bin -------------------------------------------------------------------------------- /Clean/build.cmd: -------------------------------------------------------------------------------- 1 | ..\..\beebasm-1.09\beebasm -i build_birdstrike.asm -do BS_Clean.ssd -boot BIRDS 2 | ..\..\beebasm-1.09\beebasm.exe -vc -i build_birdstrike.asm -v > build_output.asm 3 | ..\..\beebasm-1.09\beebasm.exe -vc -i build_birdstrike.asm -d >labels.txt 4 | copy BS_Clean.ssd C:\workspace\BBC\jsbeeb\discs -------------------------------------------------------------------------------- /Clean/build_birdstrike.asm: -------------------------------------------------------------------------------- 1 | \ This is the master file used to build from source BIRD DISK Side 1 2 | \ Andy Frigaard May 2021 3 | \ Other files are largely in the same format as original 4 | \ with same structure, more labels, more comments. 5 | \ 6 | \ S source file contains 7 | \ main game loop, and functions for 8 | \ drawing & playing tunes 9 | \ game over, high score entry etc 10 | \ See PIG (PIGSRCE) 11 | \ See GG (OLDSRCE) for the core game, moving sprites, etc. 12 | \ 13 | \ INCLUDE "filename" 14 | \ Includes the specified source file in the code at this point. 15 | \ INCBIN "filename" 16 | \ Includes the specified binary file in the object code at this point. 17 | 18 | \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ 19 | \ Build instructions, assume that Beebasm is in the folder specified. 20 | \ Each option produces output as per the Beebasm options. 21 | \ beebasm -i build_birdstrike.asm 22 | \ ..\..\beebasm-1.09\beebasm -i build_birdstrike.asm 23 | \ ..\..\beebasm-1.09\beebasm.exe -vc -i build_birdstrike.asm -v > build_output.asm 24 | \ ..\..\beebasm-1.09\beebasm.exe -vc -i build_birdstrike.asm -d >labels.txt 25 | \ ..\..\beebasm-1.09\beebasm -i build_birdstrike.asm -do BS_Clean.ssd -boot BIRDS 26 | \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ 27 | 28 | 29 | WORDvA = $020C \ WORD vector A 30 | WORDvB = $020D \ WORD vector B 31 | 32 | WRCHvA = $020E \ WRCH vector A 33 | WRCHvB = $020F \ WRCH vector B 34 | 35 | EVNTvA = $0220 \ EVNT vector A 36 | EVNTvB = $0221 \ EVNT vector B 37 | 38 | \\ #FE40-5F is the 6522 System VIA 39 | SysViaRegB = &FE40 40 | SysViaDDRA = &FE43 41 | SysViaIFR = &FE4D \ Interrupt Flag Register 42 | SysViaIER = &FE4E \ Interrupt Enable Register 43 | SysViaRegA = &FE4F 44 | 45 | vector_table_low_byte = $FFB7 \ Vector table address low byte 46 | vector_table_high_byte = $FFB8 \ Vector table address high byte 47 | 48 | osfind = &FFCE \ OSFIND 49 | osasci = $FFE3 \ OSASCI 50 | oswrch = $FFEE \ OSWRCH 51 | osword = $FFF1 \ OSWORD 52 | osbyte = $FFF4 \ OSBYTE 53 | 54 | ; physical colours 55 | black = 0 56 | red = 1 57 | green = 2 58 | yellow = 3 59 | blue = 4 60 | magenta = 5 61 | cyan = 6 62 | white = 7 63 | 64 | black_r = %00000000 65 | red_r = %00000001 66 | green_r = %00000100 67 | yellow_r = %00000101 68 | blue_r = %00010000 69 | magenta_r = %00010001 70 | cyan_r = %00010100 71 | white_r = %00010101 72 | white_l = %00101010 73 | 74 | \ Zero Page locations 75 | no=&70: \ number used in bombs too - generic counter 76 | \ Flags are used bit-wise 77 | bfg = &71 \ bullet flag , set to 2 intially 78 | pfg = &72 \ plane flag ? 79 | pflg=&72 \ used in OLDSRCE 80 | bofg = &73 \ bomb flag (from OLDSRCE) 81 | mod=&74: 82 | pls=&75 \ plane pointer to plane_list, screen address 83 | \ OLDSRCE uses: !pls=&2D13:?&2D13=25 84 | exp=&77: \ plane list 1st element 85 | pos=&78: \ temp position, used in .mg (move gun), pp plot plane address 86 | psta=&7A: \ plane list 4th element 87 | yo=&7B \ plane list 5th element 88 | py=&7C 89 | ra1=&7D \ random IFM - fix pigeon height bug \ different in OLDSRCE ra1=&7C TODO ONLY used in few places 90 | 91 | sd=&80 \ used for sprite indirect address, bomb, bullet 92 | sf=&82 \ sprite "from" address 93 | st=&84 \ sprite "to" address 94 | gunp=&86 \ gun position 95 | plf=&88 \ plane sprite "from" address 96 | bulst=&8A \ bullet start/list as are multiple &2d0A in GG-02 97 | \ ?bfg=2:!bulst=&2D472D0A:?&2D0A=8:?&2D47=20 98 | bost=&8C \ bomb start/list as are multiple 99 | cnt=&8E \ counter for? 100 | 101 | bomb_count=&50 \AF 3/7/2021 current no of bomb, 0 is none, up to max bomb_list[0] 102 | bomb_max_count=&51 \AF 3/7/2021 \list 103 | \bomb_addr=&51 \AF 3/7/2021 \list 104 | b_addr=&52 \AF 3/7/2021 \list 105 | b_lower_addr=&62 \AF 3/7/2021 106 | \ Sprites memory locations - now defined in constants in source 107 | \ $.X is loaded at &1900 (scenery sprites etc - not clouds/enemies) 108 | \ $.X 001900 001900 000500 &1900 + &0500 = &1E00 109 | 110 | X_base_addr = &2200 111 | explosion_sprite_addr = X_base_addr + &040 \ base for 3 animated plane expl sprites &30 long 112 | mini_gun_sprite_addr= X_base_addr + &010 \ temp player gun sprite &1928 or &1910 113 | 114 | bullet_sprite_addr = X_base_addr + &100 \bullet simple sprite 115 | other_sprite_addr = X_base_addr + &110 \ animated gun explosion, 3 x &28 = &78 116 | pigl_sprite_addr = X_base_addr + &100 \ Bird Sprites, Flying Left? L=>R, on single page 117 | pigr_sprite_addr = X_base_addr + &200 \ &1B00 \ Bird Sprites, Flying Right? R=>L, on single page 118 | \ bird each is &18 bytes, 5 images = &78 119 | \ offsets are $88,$A0,$B8,$D0,$E8 so next free is 1F0 120 | \ dead bird sprite at &270 121 | \ 200 to 270 appear unused. 122 | 123 | \ this is all zeroed in start_game ( was 2D0A to 2D5E) 124 | \ AF 27/6/2021 added 2 more entries, 8 bytes total 17 125 | \ pointer to this in zero page bulst=&8A 126 | \ TODO this could relocate to a low page, &D00 127 | bullet_list = X_base_addr + &200 \ 1 and 4 x 4 = 17 128 | plane_list = X_base_addr + &211 \ 1 and 10 x 5 = 51 129 | last_list = X_base_addr + &244 130 | 131 | tm=X_base_addr + &108 \ tm used in stmv as temp store of fc 132 | \ tm+1 used for number of active 'bomb slots' 133 | \ memory overwrites begin at ?(tm+1)>19 (ish). 134 | \ tm+2 used for vsync timing counter 135 | \ gunf=&2F00 \ used in .gun, value is modified by .sgun 136 | gunf=X_base_addr + &160 137 | 138 | score_sprite_base= X_base_addr + &300 \300 to 3A0 139 | \ see backgnd_sprite_addr_table 3A0 to 4FF, except 440 to 460 used below 140 | \ pre-populated 141 | plane_table = X_base_addr + &440 \ 440 to 453 in X.bin file, used in PIG-02 plane_hit 142 | \ zero initial values 454 to 45F 143 | picn=X_base_addr + &454 \ different value in PIGSRCE !! 144 | gex=X_base_addr + &455 \ gun explosion timer, used in gun_hit_display to show correct sprite 145 | \ gex+1 is current no of lives 146 | \ gex+2,3 is LO,HI screen address for mini gun indicator 147 | not = X_base_addr + &459 \ note sprite origin , not+1 148 | plane_kill_count = X_base_addr + &45B 149 | fc = X_base_addr + &45C 150 | \ 460 to churhs a similar. 151 | 152 | player_live_init = 3 153 | 154 | \\PRINT ".picn = ", ~picn 155 | 156 | 157 | ORG &1200 158 | 159 | 160 | INCLUDE "SS-01.asm" 161 | \ with HSTRS data to &1776 162 | \ MODE 7 High score and Keys, Space to start. 163 | \ derived from $.HSTRS source binary 164 | 165 | \ ORG &1E00 166 | \ &15FD to &19DD 167 | INCLUDE "SS-03.asm" 168 | \ has entry point .game 169 | 170 | \ ORG &2223 171 | INCLUDE "PIG-01.asm" 172 | \ was 2223 to 22FF very short 173 | \ new &19DD to &1ABA 174 | \ starts at .mini 175 | \ and has gun_hit_display 176 | 177 | \ ORG &2382 178 | INCLUDE "PIG-02.asm" 179 | \ starts with .nl, .tl at 2382 180 | \ starts at .pg to .b8 + 181 | \ 240E to 258C 182 | \ new code to 26AE 183 | \ Background scenery, graphics, lines, tables to 281C 184 | 185 | \ORG &21EE \ align to released source 186 | INCLUDE "GG-01.asm" \ derived from $.G source binary 187 | \ was 21EE to 2222 188 | \ new to &1AEF 189 | \ draw_stave only, very short 190 | \ Notes, bomb, gun sprites 191 | \ ORG &2000 within 192 | \ was INCBIN "G-Note.bin" \ sprite and data file &2300 to &2380, &80 bytes 193 | 194 | \\.end_G_Note 195 | \\PRINT ".end_G_Note = ", ~end_G_Note 196 | 197 | 198 | PRINT "X_base_addr = ", ~X_base_addr 199 | \ORG &1900 200 | ORG X_base_addr 201 | .start_X 202 | PRINT ".start_X = ", ~start_X 203 | INCBIN "X.bin" \ sprite, data, variables file &1900 to &1E00, &500 bytes 204 | \ pigeon/score font/scenery/player sprites 205 | \ derived from $.X source binary 206 | .end_X 207 | PRINT ".end_X = ", ~end_X 208 | 209 | 210 | \ ORG &281D 211 | \ ORG &2600 212 | \ ALIGN &100 213 | INCLUDE "GG-02.asm" 214 | \ starts at .def_log_colour 215 | \ 281D to 2D09 216 | \ data, lists, sound tables 2D09 to 2E00 217 | 218 | 219 | ORG &2E00 220 | plane_sprite_addr = &2F00 \ base for 4 levels of plane 221 | INCBIN "G-Plane.bin" \ sprite and data file &2E00 to &3000, &200 bytes 222 | \ cloud, plane sprites 223 | \ derived from $.G source binary 224 | 225 | \ SAVE "filename", start, end [, exec [, reload] ] 226 | \ SAVE "BIRDS", start_SS_01, &3000, &1E00 227 | SAVE "BIRDS", start_SS_01, &3000, game 228 | -------------------------------------------------------------------------------- /Clean/labels.txt: -------------------------------------------------------------------------------- 1 | .start_SS_01 = &1200 2 | .end_SS_01 = &1606 3 | .start_SS_03 = &1606 4 | .end_SS_03 = &1ADF 5 | .end_PIG-01 = &1BB8 6 | .start_PIG_02 = &1BB8 7 | .end_PIG-02 = &2053 8 | .start_GG_01 = &2053 9 | .end_GG-01 = &2180 10 | X_base_addr = &2200 11 | .start_X = &2200 12 | .end_X = &2700 13 | .start_GG_02 = &2700 14 | .end_GG_02_code = &2C8F 15 | .start_GG_02_data = &2D56 16 | .end_GG-02 = &2E00 17 | [{'D%':9984L,'E%':10008L,'GO':5683L,'Xg':11686L,'b10':7586L,'b3':7317L,'b5':7332L,'b6':7541L,'b7':7549L,'b9':7487L,'ba':11633L,'backgnd_sprite_addr_table':8185L,'begin_level':5927L,'bf':5927L,'bis':11619L,'bof':11670L,'bomb_sprite_addr':8528L,'bomb_vert_HI':11609L,'bomb_vert_LO':11608L,'bomb_vert_newline':11607L,'bomb_vert_rate':11606L,'bon':4688L,'bsk':4829L,'bsou':11720L,'buf':11654L,'bullet_interval':10344L,'bx':7476L,'c1':6661L,'c2':6671L,'c3':6681L,'c4':6691L,'c5':6701L,'check_key_press':6810L,'check_plane_collision':10629L,'chnot':6650L,'cht':6523L,'cloud_sprite_offset_list':11610L,'co1':5903L,'colour_loop':5903L,'ct1':6534L,'ct2':6541L,'ct3':6549L,'ddu1':7619L,'ddu2':7645L,'ddu3':7661L,'de':11630L,'def_envelopes':10008L,'def_log_colour':9984L,'del1':6497L,'delay':6492L,'dots_str':5033L,'draw_backgnd_art':7679L,'draw_stave':8275L,'dts':5033L,'ef':6508L,'end_GG_01':8576L,'end_GG_02':11776L,'end_GG_02_code':11407L,'end_PIG_01':7096L,'end_PIG_02':8275L,'end_SS_01':5638L,'end_SS_03':6879L,'end_X':9984L,'end_frame':6211L,'envelope_base_addr':11640L,'ep':7363L,'exg':6409L,'exg3':6456L,'extra_player_check':6409L,'game':5638L,'game_over':4646L,'gend':5408L,'gov':4646L,'gun':10171L,'gun_hit_display':6900L,'gun_sprite_addr':8536L,'h0':6900L,'h1':6913L,'h10':7066L,'h12':6964L,'h3':6981L,'h4':6996L,'h5':7011L,'h5a':7023L,'h6':7032L,'h7':7070L,'h8':7063L,'h9':7064L,'hreturn':6912L,'hs':4814L,'inb':11687L,'instructions_str':5062L,'ints':5062L,'key':6801L,'keyboardScan':6801L,'level_bomb_count':5786L,'level_bomb_interval':5794L,'level_bomb_rate':5802L,'level_bullet_count':5770L,'level_bullet_interval':5778L,'level_de':5762L,'m7':4817L,'mb':10186L,'mg':10065L,'mini':6879L,'modify_gun_length':10171L,'modify_plane_sprite_length':11066L,'move_bombs':11264L,'move_bullets':10186L,'move_gun':10065L,'move_planes':10723L,'mp':10723L,'n1':6581L,'n2':6591L,'n3':6617L,'n4':6631L,'n5':6642L,'nam':5053L,'nb':10315L,'nbk':4809L,'new_bomb':11106L,'new_bullet':10315L,'new_plane':10471L,'newgame':5677L,'next_level':6508L,'nl':7096L,'note_sprite_addr':8448L,'np':10471L,'nxno':6554L,'pb':7607L,'pg':7236L,'pgb0':7364L,'pgb1':7400L,'pgh':7417L,'pgl':7290L,'pgnh':7501L,'pig_init_left':7290L,'pig_init_right':7259L,'plane_hit':7619L,'playTune':6754L,'player_dies':10136L,'player_gun_initialise':6180L,'plot_bomb':11230L,'plot_bomb_lower1':11243L,'plot_bomb_lower2':11247L,'plot_bomb_mod':11250L,'plot_bomb_upper1':11254L,'plot_bomb_upper2':11258L,'plot_clouds':7760L,'plot_fast_bullet_sprite':10418L,'plot_gun_life_indicator':6879L,'plot_gun_sprite':10171L,'plot_pigeon_sprite':7607L,'plot_plane':11041L,'plot_score':10045L,'pnbot':6731L,'pno':6702L,'pntop':6742L,'pp':11041L,'pxp':10537L,'ra2':11391L,'ra3':11399L,'random1':7662L,'s7':6352L,'save_plane':10996L,'sc':11627L,'scenery_line_art':7910L,'score_exit':6212L,'score_update_screen':6352L,'scr':10029L,'scri':10034L,'sgun':6180L,'sor':6213L,'soun':6877L,'sound_bonus':11752L,'sound_bsou':11720L,'sound_bullet':11728L,'sound_note':11768L,'sound_note_pitch':11774L,'sound_note_volume':11772L,'sound_pigeon':11760L,'sound_plane_hit':11736L,'sound_player_hit':11744L,'space':5578L,'sps':5221L,'start_GG_01':8275L,'start_GG_02':9984L,'start_GG_02_data':11606L,'start_PIG_02':7096L,'start_SS_01':4608L,'start_SS_03':5638L,'start_X':8704L,'start_game':5810L,'stm1':5272L,'stm10':5397L,'stm2':5286L,'stm3':5298L,'stm4':5249L,'stm5':5315L,'stm6':5336L,'stm8':5363L,'stmv':5247L,'stv':8275L,'t1':6756L,'t3':6789L,'ti':11631L,'tl':7144L,'tune':6754L,'wbmsg':4784L,'whs':5598L,'write_string':5618L,'wrs':5618L,'x':7500L,'xps':7524L}] 18 | -------------------------------------------------------------------------------- /Clean/notes.todo: -------------------------------------------------------------------------------- 1 | # Clean Version 2 | Clean-up: 3 | ✔ Change buggy level incrementing to a table model - more transparent, better to tune. @done(21-06-30 11:41) 4 | ✔ Consolidate sound defintions etc @done(21-06-30 12:25) 5 | ☐ Flags for ass build to move through levels faster (less planes) 6 | ✔ Flag for god-mode similar to aid testing, experimentation @started(21-07-06 22:57) @done(21-07-14 19:43) @lasted(1w20h46m10s) 7 | ☐ Check use of CMP, better use of BCC, BCS for unsigned comparisons 8 | ☐ Add bounds checks on all list scans > needs max size? 9 | ☐ Analyse X.bin, extract code/tables into source files. @started(21-07-25 18:35) 10 | ☐ Working lists dont need to be in source - create in unused page on start &400?. 11 | ✔ bug when bullets left on screen at bonus end frame @done(21-07-11 18:46) 12 | 13 | Foundation: 14 | Simplify and improve performance to allow for new features 15 | ☐ List/counter pattern for multiple sprites (max/actual count, interval, empty slot) 16 | ✔ Rework bomb code to allow > 2 bombs and incremental changes @done(21-07-06 20:27) 17 | ✔ Rework bomb code to allow incremental changes in speed by level @done(21-07-06 22:57) 18 | need to reset cleanly beteen levels - some in progress 19 | ☐ Rework bomb code to allow physics, changes in speed, drift. 20 | ✔ Optimise bullet/bomb sprite to unroll, use EOR#, .. @done(21-07-06 22:58) 21 | ☐ Use of ZP for selected lists, flags (bullet/bomb) @started(21-07-06 22:57) 22 | ☐ Use of dedicated ZP locations so not reloaded each cycle. @started(21-07-06 22:57) 23 | ☐ Move plane - optimise, allow for multiple planes, plane flag @started(21-07-11 18:47) 24 | 25 | 26 | Features: 27 | ☐ Night mode levels - hide some plane features, spotlights? moon, stars 28 | ☐ Cloud movement - re-draw boundaries in black to give impression of movement. 29 | ☐ Cloud enhancement - more, multiples clouds to hide planes etc. 30 | ☐ Bird movement - more complexity, rise/fall 31 | ☐ Plane - show smoke as indicator of winged; change pattern; clear at bottom. 32 | ☐ Plane - more homing behaviour - dive bomb, ascend / descend with physics. 33 | ☐ Other special flying feature, similar to pigeon, to drive power-up, score. biplane, or friend + enemy biplanes, balloon 34 | ☐ Some form of power-up (more bullets, faster bullets) for player. 35 | ☐ Protective shield as power-up (in trench) 36 | ☐ Church crosses are retained from level to level. 37 | ☐ Scenery some animation? Flowing stream. 38 | 39 | 40 | Code Efficiency: 41 | Profiling to show what instructions are run 42 | https://stardot.org.uk/forums/viewtopic.php?f=4&t=21875&p=310100&hilit=code+profiler&sid=ec9fc8d99d722804f6bb6a7009c93151#p310100 43 | 44 | ✔ Score is writing 5 sprites each cycle - only needed on change. @done(21-06-30 20:41) 45 | ☐ gun position is XOR plotting each cycle - only needed on move. Needs changes to collision detection 46 | ☐ plot_plane loop high - large sprite, always moving or waste?. 47 | ☐ keyboardScan loop high - always moving or waste?. 48 | ☐ tune t3 loop high - seems odd waste?. 49 | ☐ plot_pigeon_sprite - loop high - large sprite waste?. 50 | 51 | 52 | Top routines 53 | Based on 8/82021 profiler 54 | 55 | scr loop 56 | 0x2632 BIT abs 10959490 4843922 0.441984253 57 | 0x2635 BEQ branch 10959145 6889799 0.62868034 58 | 59 | plot_gun_sprite 60 | plotting every cycle, as collision detection is based on reading screen 61 | 0x26bd LDA abs,y 258353 1036702 4.012734514 62 | 0x26c0 BEQ branch 258334 601941 2.33008818 63 | 0x26c2 EOR (),y 174388 4293855962 24622.42793 64 | 0x26c4 STA (),y 174385 1049046 6.015689423 65 | 0x26c6 DEY 258339 4291485550 16611.83774 66 | 0x26c7 BPL branch 258355 769855 2.979833949 67 | 68 | 69 | plot_plane top 70 | large sprite so many cycles 71 | BEQ branch skips about 45% bytes, takes 2.4c saves 45% of 11c - OK 72 | A branch not taken requires two machine cycles. Add one if the branch is taken 73 | 0x2a80 CPX zp 174735 4293491605 24571.44593 74 | 0x2a82 BNE branch 174733 4293447868 24571.47687 75 | 0x2a84 LDA (),y 224863 4294091917 19096.4806 76 | 0x2a86 BEQ branch 224853 550487 2.448208385 77 | 0x2a88 EOR (),y 124201 634534 5.108928269 78 | 0x2a8a STA (),y 124190 745346 6.001658749 79 | 0x2a8c DEY 224857 449880 2.000738247 80 | 0x2a8d DEX 224870 4291417207 19083.99167 81 | 0x2a8e BPL branch 224865 624804 2.778573811 82 | 83 | plot_plane bottom 84 | 0x2a76 LDA (),y 174736 4293841257 24573.30634 85 | 0x2a78 BEQ branch 174728 417509 2.389479648 86 | 0x2a7a EOR (),y 106782 4291516426 40189.51158 87 | 0x2a7c STA (),y 106776 640827 6.001601483 88 | 0x2a7e DEY 174734 349601 2.000761157 89 | 0x2a7f DEX 174733 349586 2.000686762 90 | 91 | keyboardScan 92 | could reduce? alternate cycles? 93 | 0x195a LDA imm 67233 104422 1.553136109 94 | 0x195c LDY imm 67237 104498 1.554174041 95 | 0x195e JSR abs 67238 313203 4.65812487 96 | 0x1961 INX 67239 104426 1.553057006 97 | 0x1962 RTS 67240 313296 4.659369423 98 | 99 | ge4 wait for press space at game start/end 100 | 0x14d6 LDX imm 57549 85064 1.478114303 101 | 0x14d8 JSR abs 57552 255108 4.43265221 102 | 0x14db BNE branch 57551 127540 2.216121353 103 | 104 | plot_bullet_sprite 105 | can change to immediate EOR with fixed value 106 | 0x27e1 LDA (),y 31236 156377 5.006306825 107 | 0x27e3 EOR (),y 31235 156316 5.004514167 108 | 0x27e5 STA (),y 31236 187629 6.006819055 109 | 0x27e7 DEY 31236 62500 2.000896402 110 | 0x27e8 BPL branch 31238 86883 2.781324028 111 | 112 | 113 | 0x194e LDA imm 29570 59189 2.001657085 114 | 0x1950 LDX imm 29570 59188 2.001623267 115 | 0x1952 JSR abs 29569 177539 6.0042274 116 | 0x1955 CPX imm 29567 59155 2.000710251 117 | 0x1957 BMI branch 29570 88757 3.001589449 118 | 119 | 120 | LDA (LoaD Accumulator) 121 | Affects Flags: N Z 122 | 123 | MODE SYNTAX HEX LEN TIM 124 | Immediate LDA #$44 $A9 2 2 125 | Zero Page LDA $44 $A5 2 3 126 | Zero Page,X LDA $44,X $B5 2 4 127 | Absolute LDA $4400 $AD 3 4 128 | Absolute,X LDA $4400,X $BD 3 4+ 129 | Absolute,Y LDA $4400,Y $B9 3 4+ 130 | Indirect,X LDA ($44,X) $A1 2 6 131 | Indirect,Y LDA ($44),Y $B1 2 5+ 132 | 133 | + add 1 cycle if page boundary crossed 134 | 135 | PRofiler features 136 | count reads and writes to 137 | - program space 138 | - data space 139 | - zero page 140 | - stack 141 | 142 | Display - any charts lib 143 | - Heatmap 16x16, or scatter plot 144 | - tree/ node map 145 | chart.js - open, popular 146 | D3 Data Driven Documents. - related to dom data. Other libs built on this. 147 | Plotly - built on D3 - needs dom? 148 | Google charts - HTML5 149 | 150 | Characterise by op-code 151 | Heatmap 16x16 152 | 153 | pc instruction count cycles 154 | 2632 BIT abs 1069227 1069840 155 | 2635 BEQ branch 1069152 1782302 156 | 2641 LDA (),y 24000 23507 157 | 2643 STA (),y 24000 40006 158 | 2645 DEY 24000 48000 159 | 2646 BPL branch 24000 16016 160 | 26b9 LDA abs,y 23994 23811 161 | 26bc BEQ branch 23997 32018 162 | 26be EOR (),y 16200 10808 163 | 26c0 STA (),y 16194 26993 164 | 26c2 DEY 23994 40208 165 | 26c3 BPL branch 23997 4290983314 166 | 2a72 LDA (),y 16872 15488 167 | 2a74 BEQ branch 16872 28120 168 | 2a78 STA (),y 10320 17640 169 | 2a7a DEY 16869 27186 170 | 2a7b DEX 16872 11254 171 | 2a7c CPX zp 16869 11246 172 | 2a7e BNE branch 16872 16874 173 | 2a80 LDA (),y 21144 19760 174 | 2a82 BEQ branch 21144 35240 175 | 2a86 STA (),y 11658 19651 176 | 2a88 DEY 21144 32802 177 | 2a89 DEX 21144 14096 178 | 2a8a BPL branch 21144 14096 179 | -------------------------------------------------------------------------------- /Original/$.!BOOT: -------------------------------------------------------------------------------- 1 | PAGE=&3000 *L.X *L.G CH."KEYS" LOAD"S" *L.HSTRS -------------------------------------------------------------------------------- /Original/$.!BOOT.INF: -------------------------------------------------------------------------------- 1 | $.!BOOT 000000 000000 000030 2 | -------------------------------------------------------------------------------- /Original/$.G: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qurm/BirdStrike/b13704515ac3996feeacb220ab03b2a1ba6c6869/Original/$.G -------------------------------------------------------------------------------- /Original/$.G.INF: -------------------------------------------------------------------------------- 1 | $.G 0021EE 0021EE 000E12 2 | -------------------------------------------------------------------------------- /Original/$.HSTRS: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qurm/BirdStrike/b13704515ac3996feeacb220ab03b2a1ba6c6869/Original/$.HSTRS -------------------------------------------------------------------------------- /Original/$.HSTRS.INF: -------------------------------------------------------------------------------- 1 | $.HSTRS 0015C0 000000 0001B6 2 | -------------------------------------------------------------------------------- /Original/$.KEYS: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qurm/BirdStrike/b13704515ac3996feeacb220ab03b2a1ba6c6869/Original/$.KEYS -------------------------------------------------------------------------------- /Original/$.KEYS.INF: -------------------------------------------------------------------------------- 1 | $.KEYS FF1900 FF8023 0000E0 2 | -------------------------------------------------------------------------------- /Original/$.OLDSRCE: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qurm/BirdStrike/b13704515ac3996feeacb220ab03b2a1ba6c6869/Original/$.OLDSRCE -------------------------------------------------------------------------------- /Original/$.OLDSRCE.INF: -------------------------------------------------------------------------------- 1 | $.OLDSRCE FF3000 FF8023 00170D 2 | -------------------------------------------------------------------------------- /Original/$.OLDSRCE.bas: -------------------------------------------------------------------------------- 1 | 100 HIMEM=&27D0:PROCI 2 | 120 FORZ=0TO2STEP2:P%=&27F5 3 | 140 [OPTZ 4 | 150 JSRsetup 5 | 160 .GO JSRscr 6 | 170 JSRmp:JSRnp 7 | 180 JSRmg 8 | 190 JSRmb:JSRnb 9 | 200 JSRmbo:JSRnbo:JSRra0 10 | 210 LDA#&81:LDY#&FF:LDX#&8F:JSR&FFF4:INX:BNEGO:RTS 11 | 215 .h9 RTS 12 | 220 .scr LDA#19:JMP&FFF4 13 | 230 .ra0 LDAra1:AND#&48:ADC#&38:ASLA:ASLA:ROLra1+2:ROLra1+1:ROLra1:LDAra1:RTS 14 | 242 .setup LDY#0:LDA(pls),Y:STAno 15 | 243 .slop INY:INY:LDA(pls),Y:STApos:INY:LDA(pls),Y:STApos+1 16 | 244 JSRpp:INY:INY:CPYno:BMIslop:JSRgun:CLC:LDA#3:STAexp 17 | 245 .env LDAexp:ASLA:ASLA:ASLA:ASLA:ADC#&80:TAX:LDA#8:LDY#&2D:JSR&FFF1:DECexp:BPLenv:RTS 18 | 246 19 | 260 .mg JSRgun:LDA#&81:LDY#&FF:LDX#&BD:JSR&FFF4 20 | 270 INX:BEQr 21 | 280 DEY:LDX#&9E:JSR&FFF4 22 | 290 INX:BNEgd 23 | 300 .l LDXXg:CPX#1:BEQgd:DEX:STXXg:SEC:LDAgunp:SBC#8:STAgunp:BCSgd:DECgunp+1:BCCgd\always 24 | 320 .r LDXXg:CPX#71:BEQgd:INX:STXXg:CLC:LDAgunp:ADC#8:STAgunp:BCCgd:INCgunp+1 25 | 340 .gd SEC:LDA#0:STApos:LDY#&24:.ch LDA(gunp),Y:BEQcop:STApos:.cop TYA:SBC#8:TAY:BPLch:LDApos:BEQgun:LDAsc:ORA#&20:STAsc 26 | 350 .gun LDY#&27:.gop LDAgunf,Y:BEQgz:EOR(gunp),Y:STA(gunp),Y:.gz DEY:BPLgop:RTS 27 | 370 .mb LDY#0:LDA(bulst),Y:STAno:LDAbuf:STAsf:LDAbuf+1:STAsf+1 28 | 380 .ntbu INY:LDA(bulst),Y:STAexp:INY:LDA(bulst),Y:STAsd:INY:LDA(bulst),Y:STAsd+1:BNEbu1 29 | 390 INY:LDA#&FE:ANDbfg:STAbfg:JMPnxbu 30 | 400 .bu1 INY:JSRs5:LDA(bulst),Y:BPLbu2 31 | 420 .bu7 LDA#0:STAsd+1:BEQnxbu\alws 32 | 430 .bu2 SEC:LDA#7:ANDsd:CMP#5:BMIbu3:LDAsd:SBC#5:STAsd:JMPbu4 33 | 440 .bu3 LDAsd:SBC#&7D:STAsd:LDAsd+1:SBC#2:STAsd+1 34 | 450 .bu4 SEC:LDAexp:SBC#5:STAexp:CMP#2:BEQbu7:JSRs5 35 | 490 .nxbu DEY:DEY:DEY:LDAexp:STA(bulst),Y:INY:LDAsd:STA(bulst),Y:INY:LDAsd+1:STA(bulst),Y:INY 36 | 500 CPYno:BMIntbu:RTS 37 | 510 38 | 520 .nb LDA#1:BITbfg:BNEnwb0:LDA#&81:LDY#&FF:LDX#&A6:JSR&FFF4:INX:BEQnwb1 39 | 540 LDA#&FD:ANDbfg:STAbfg:.nwb0 RTS 40 | 550 .nwb1 LDA#2:BITbfg:BNEnwb0:LDY#255 41 | 570 .nwb2 INY:INY:INY:INY:LDA(bulst),Y:BNEnwb2:DEY:DEY:LDA#&9D:STA(bulst),Y:INY:SEC:LDAgunp:SBC#&6E:STA(bulst),Y:STAsd 42 | 580 INY:LDAgunp+1:SBC#2:STA(bulst),Y:STAsd+1:INY:LDAXg:CLC:ADC#3:STA(bulst),Y:JSRs5:LDA#3:ORAbfg:STAbfg:LDA#1:ORAsc:STAsc 43 | 585 LDA#7:LDY#&2D:LDX#&D0:JMP&FFF1 44 | 590 45 | 600 .s5 TYA:PHA:LDY#5 46 | 605 CLC:LDAsd:ADC#&78:STAst:LDAsd+1:ADC#2:STAst+1 47 | 610 LDAsd:AND#7:EOR#7:STAmod:CMP#5:BPLtop 48 | 630 .bot LDA(sf),Y:EOR(st),Y:STA(st),Y:DEY:CPYmod:BNEbot 49 | 640 .top LDA(sf),Y:EOR(sd),Y:STA(sd),Y:DEY:BPLtop 50 | 650 PLA:TAY:RTS 51 | 660 .np LDApflg:CMP#1:BPLnw:DECti:BNEnw:LDAti+1:STAti:LDAno:JSRra2:TAY:SEC:.n2 SBC#5:BPLn2:TAX 52 | 662 .n3 INY:INX:BNEn3:DEY:LDA(pls),Y:BMIfy:LDYno 53 | 665 .se DEY:LDA(pls),Y:BMIfy:DEY:DEY:DEY:DEY:BNEse:LDA#&80:ORAsc:STAsc:RTS:.fy EOR#&80:STA(pls),Y 54 | 669 .nw RTS 55 | 680 .pxp LDAexp:BEQnx:LDX#&9:STXplf+1:LDAplf:PHA:LDAexp:CMP#21:BNEpx1:LDA#0:STAplf:JSRpp:JMPpx4 56 | 682 .px1 CMP#12:BNEpx2:LDA#0:STAplf:JSRpp:LDA#&40:STAplf:JSRpp:JMPpx4 57 | 684 .px2 CMP#6:BNEpx3:LDA#&40:STAplf:JSRpp:LDA#&80:STAplf:JSRpp:JMPpx4 58 | 686 .px3 CMP#1:BNEpx4:LDA#&80:STAplf:JSRpp 59 | 688 .px4 LDA#&2F:STAplf+1:PLA:STAplf:DECexp:.nx JMPfo+3 60 | 720 .mp LDY#0:LDA(pls),Y:STAno:STYpflg 61 | 730 .nxpl INY:LDA(pls),Y:STAexp:INY:LDA(pls),Y:STApos:INY:LDA(pls),Y:STApos+1:INY:LDA(pls),Y:STApsta:INY:LDA(pls),Y:STAyo 62 | 740 LDAexp:AND#&C0:BNEp0:JMPpxp:.p0 LDApsta:BPLp1:JMPpl1:.p1 DECexp 63 | 760 TYA:PHA:LDY#0:LDA(bulst),Y:STAsd:.h INY:LDA(bulst),Y:SEC:SBCyo:BMInh:CMP#8:BPLnh:INY:INY:LDA(bulst),Y:BEQnh+2:INY:LDA(bulst),Y:SEC:SBCpsta:BMInh+3:CMP#7:BPLnh+3 64 | 765 CMP#3:BEQo:LDA#&40:ORAsc:STAsc:ASLA:STA(bulst),Y:BNEnh+3\always 65 | 768 .o LDA#25:STAexp:LDA#&D8:STA(bulst),Y:TAX:LDA#7:LDY#&2D:JSR&FFF1:PLA:TAY:LDA#2:ORAsc:STAsc:JSRpp:JMPpxp 66 | 770 .nh INY:INY:INY:CPYsd:BMIh:PLA:TAY 67 | 790 LDAbofg:AND#&BF:STAbofg 68 | 800 INCpflg:JSRpp:LDAyo:CMP#&AF:BNEhop5:SEC:LDApos:SBC#&87:STApos:LDApos+1:SBC#&48:STApos+1:LDA#&C0:STAyo:JSRh9 69 | 810 .hop5 LDA#&3F:ANDexp:BNEmid 70 | 840 SEC:LDApsta:SBCXg:STAexp:LDA#0:BCSpl3:SEC:RORA:.pl3 RORA:STAsd:LDAexp:BNEpl5:.pl20 JSR&FFFF:.pl5 BPLpl4:EOR#&FF:CLC:ADC#1 71 | 845 .pl4 CMP#2:BMIpl6:STAra3+1:JSRra2+3:LSRra3+1:CLC:ADCra3+1:AND#&3F:.pl6 ORAsd:STAexp 72 | 850 .mid LDAexp:LDXpsta:CPX#1:BPLnl:ORA#&40:AND#&7F:JMPdo:.nl CPX#72:BMIdo+2:ORA#&80:AND#&BF 73 | 860 .do STAexp:INCyo:LDA#7:ANDpos:CMP#7:BEQpl2:INCpos:JMPlft:.pl2 CLC:LDApos:ADC#&79:STApos:LDApos+1:ADC#2:STApos+1 74 | 870 .lft LDAexp:ROLA:BCCrgt:DECpsta:LDApos:SBC#8:STApos:BCSfo:DECpos+1:JMPfo 75 | 880 .rgt INCpsta:ROLA:BCCfo:CLC:LDApos:ADC#8:STApos:BCCfo:INCpos+1 76 | 890 .fo JSRpp:DEY:DEY:DEY:DEY:LDAexp:STA(pls),Y:INY:LDApos:STA(pls),Y:INY:LDApos+1:STA(pls),Y:INY:LDApsta:STA(pls),Y:INY:LDAyo:STA(pls),Y 77 | 900 .pl1 CPYno:BEQhop7:JMPnxpl:.hop7 RTS 78 | 920 .pp TYA:PHA:CLC:LDApos:ADC#&78:STAst:AND#7:EOR#7:STAmod 79 | 930 LDApos+1:ADC#2:STAst+1:LDY#&3F 80 | 940 .plo LDX#7:CPXmod:BEQtp 81 | 950 .bt LDA(plf),Y:BEQbz:EOR(st),Y:STA(st),Y:.bz DEY:DEX:CPXmod:BNEbt 82 | 960 .tp LDA(plf),Y:BEQtz:EOR(pos),Y:STA(pos),Y:.tz DEY:DEX:BPLtp:TYA:BPLplo 83 | 970 PLA:TAY:RTS 84 | 971 85 | 990 .nbo LDA#&C0:BITbofg:BNEnbo4:DECbofg:BNEnbo4:LDY#255 86 | 1010 .nbo2 INY:INY:INY:INY:INY:LDA(pls),Y:BMInbo2 87 | 1020 DEY:DEY:DEY:LDA(pls),Y:AND#&C0:BNEnbo5:INY:INY:INY:JMPnbo2 88 | 1025 .nbo5 INY:CLC:LDA(pls),Y:ADC#&9D:STAsd:INY:LDA(pls),Y:ADC#2:STAsd+1:JSRs5:LDY#0 89 | 1030 .nbo3 INY:INY:LDA(bost),Y:BNEnbo3 90 | 1040 LDAsd+1:STA(bost),Y:DEY:LDAsd:STA(bost),Y:LDAinb:STAbofg 91 | 1050 .nbo4 LDA#&C0:ORAbofg:STAbofg:RTS 92 | 1060 93 | 1070 .mbo LDY#0:LDA(bost),Y:STAno:LDAbof:STAsf:LDAbof+1:STAsf+1 94 | 1080 .ntbo INY:LDA(bost),Y:STAsd:INY:LDA(bost),Y:STAsd+1 95 | 1090 BNEbo1:LDA#&7F:ANDbofg:STAbofg:JMPbo7 96 | 1100 .bo1 JSRs5:LDAsd:AND#7:CMP#6:BPLbo2:INCsd:INCsd:LDAsd+1:JMPbo4 97 | 1110 .bo2 CLC:LDAsd:ADC#&7A:STAsd:LDAsd+1:ADC#2:STAsd+1 98 | 1130 .bo4 CMP#&80:BMIbo6:LDA#0:STA(bost),Y:BEQbo7\always 99 | 1140 .bo6 JSRs5:DEY:LDAsd:STA(bost),Y:INY:LDAsd+1:STA(bost),Y 100 | 1150 .bo7 CPYno:BMIntbo:RTS 101 | 1160 .ra2 STAra3+1:SEC:LDAra1:AND#&7F:.ra3 SBC#0:BPLra3:ADCra3+1:RTS 102 | 1240 ]:NEXT:VDU11:PRINT~P%:END 103 | 1260 DEFPROCI 104 | 1270 FORA%=&2D00TO&2D7F:?A%=0:NEXT 105 | 1280 bfg=&71:pflg=&72:bofg=&73:mod=&74 106 | 1300 sd=&80:sf=&82:st=&84 107 | 1310 Xg=&2D70:gunp=&86:gunf=&2F00 108 | 1320 bulst=&8A:buf=&2D72:no=&70 109 | 1330 pls=&75:exp=&77:pos=&78:psta=&7A:yo=&7B:ra1=&7C:plf=&88 110 | 1340 de=&2D79:ti=&2D7A:sc=&2D76:bof=&2D74:inb=&2D71:bost=&8C 111 | 1350 !gunp=&7E90:!Xg=&2F30C720:!plf=&2F40:!bof=&2F38:!de=&400314 112 | 1360 ?bfg=2:!bulst=&2D472D0A:?&2D0A=8:?&2D47=20 113 | 1370 !pls=&2D13:?&2D13=25 114 | 1380 FORA%=0TO30STEP5:A%?&2D14=&81:A%!&2D15=&3A58+16*A% 115 | 1390 A%?&2D17=&80+11+2*A%:A%?&2D18=&D0:NEXT 116 | 1410 ENDPROC 117 | -------------------------------------------------------------------------------- /Original/$.PIGSRCE: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qurm/BirdStrike/b13704515ac3996feeacb220ab03b2a1ba6c6869/Original/$.PIGSRCE -------------------------------------------------------------------------------- /Original/$.PIGSRCE.INF: -------------------------------------------------------------------------------- 1 | $.PIGSRCE FF1900 FF8023 001015 2 | -------------------------------------------------------------------------------- /Original/$.PIGSRCE.bas: -------------------------------------------------------------------------------- 1 | 100 HIMEM=&21B8:PROCI 2 | 110 FORZ=0TO2STEP2:P%=HIMEM 3 | 120 [OPTZ:.Q% JSRS% 4 | 130 .GO JSRR%:JSRscr 5 | 140 JSRmp:JSRnp:JSRmg 6 | 150 JSRmb:JSRnb:JSRmbo:JSRnbo:JSRpg 7 | 160 JSRh0:JSRsor:LDA#&81:LDY#&FF:LDX#&8F:JSR&FFF4:INX:BNEGO:RTS 8 | 170 .S% LDA#0:STApicn:STAgex:STAba+1:STA&2F37:STAsc:STAsc+1:STAsc+2:JSRC%:JSRV%:CLC:LDA#4:STAno:JSRE% 9 | 180 LDA#&80:STAgex+2:LDA#&32:STAgex+3:LDX#4:STXgex+1:DEX:.pmi JSRmini:CLC:LDAgex+2:ADC#&20:STAgex+2:DEX:BNEpmi 10 | 190 .col LDX#15:LDY#7:.co1 JSRD%:DEX:CPX#7:BNEco1:STXra1 11 | 200 .ppos LDA#&3A:STA&81:LDA#&81:STA&82:LDX#1:LDY#8 12 | 210 .pp1 LDA#&81:STA!pls,X:INX:TYA:CLC:ADC#&50:STA!pls,X:TAY:INX:LDA&81:ADC#0:STA!pls,X:STA&81:CLC:INX:LDA&82:ADC#10:STA&82:STA!pls,X 13 | 220 INX:LDA#&D0:STA!pls,X:INX:CPX#31:BMIpp1:LDY#0:LDA(pls),Y:STAno 14 | 230 .slop INY:INY:LDA(pls),Y:STApos:INY:LDA(pls),Y:STApos+1 15 | 240 JSRpp:INY:INY:CPYno:BMIslop 16 | 250 JMPh7:.sgun LDA#32:STAXg:LDA#&7E:STAgunp+1:LDA#&90:STAgunp:LDA#&2F:STAgun+4:LDA#0:STAgun+3:JMPgun 17 | 260 18 | 270 .h0 LDA#&20:BITsc:BNEh1:LDAgex:BNEh12:RTS 19 | 280 .h1 LDX#0:LDY#7:JSRD%:LDA#7:LDY#&2D:LDX#&E0:JSR&FFF1:LDA#255:STAgex:LDA#&60:STAnbo:STAnp:STAmg:STAnb 20 | 290 JSRgun:LDA#&A:STAgun+4:LDA#&10:STAgun+3:JMPgun 21 | 300 .h12 DECgex:LDAgex:CMP#254:BNEh3:LDX#0:LDY#0:JMPD% 22 | 310 .h3 CMP#220:BNEh4:JSRgun:LDA#&38:STAgun+3:JMPgun 23 | 320 .h4 CMP#140:BNEh5:JSRgun:LDA#&60:STAgun+3:JMPgun 24 | 330 .h5 CMP#1:BNEstp4:JSRgun:LDY!pls 25 | 340 .h6 LDA(pls),Y:CMP#&C0:BNEh8:DEY:LDA(pls),Y:BPLh9:EOR#&80:STA(pls),Y:DEY:LDA(pls),Y:STApos+1:DEY:LDA(pls),Y:STApos:JSRpp:JMPh10 26 | 350 .h8 DEY:.h9 DEY:DEY:.h10 DEY:DEY:BNEh6 27 | 360 .h7 LDA#&20:STAmg:LDA#&A5:STAnp:LDA#&A9:STAnbo:STAnb:DECgex+1:BEQgov:SEC:LDAgex+2:SBC#&20:STAgex+2:JSRmini:JMPsgun 28 | 370 .gov PLA:PLA:RTS 29 | 380 .mini LDA#&C0:STAsf:LDA#9:STAsf+1:LDAgex+2:STAsd:LDAgex+3:STAsd+1:JMPpb 30 | 390 .stp4 RTS 31 | 400 .stp6 LDAgex:BEQstp4:LDApsta:EOR#&80:STApsta:PLA:PLA:JMPfo+3 32 | 410 33 | 420 .sor LDAsc:BEQs7:SED:AND#2:BEQs1:CLC:LDA#5\pl:ADCsc+1:STAsc+1:LDAsc+2:ADC#0:STAsc+2:JSRX% 34 | 430 .s1 LDA#&10:BITsc:BEQs2:CLC:LDA#10\pig:ADCsc+1:STAsc+1:LDAsc+2:ADC#0:STAsc+2 35 | 440 .s2 CLD:LDA#0:STAsc:RTS 36 | 450 .s7 LDA#&33:STAsd+1:LDA#&90:STAsd:LDA#&C:STAsf+1:LDA#&F0:ANDsc+2:JSRw:LDA#&F:ANDsc+2:ASLA:ASLA:ASLA:ASLA:JSRw 37 | 460 LDA#&F0:ANDsc+1:JSRw:LDA#&F:ANDsc+1:ASLA:ASLA:ASLA:ASLA:JMPw 38 | 470 .pg LDA#&B:STAsf+1:LDAba+1:BNEb0:LDA#&42:BITsc:BEQep 39 | 480 LDA#2:BITpicn:BEQpgl 40 | 490 LDA#&B:STAsf+1:STApg+1:LDA#&68:STAba:STAsd:LDA#0:STAxps+1:LDA#76:STAba+3:LDA#&4B:STAb5-2:BNEb3 41 | 500 .pgl LDA#&A:STAsf+1:STApg+1:LDA#0:STAba:STAsd:STAba+3:LDA#76:STAxps+1:LDA#&49:STAb5-2 42 | 510 .b3 LDA#0:STApy:INCpicn 43 | 520 LDA#7:ANDra1:TAX:LDA#&49:CLC:.b5 ADC#5:TAY:LDApy:ADC#16:STApy:TYA:DEX:BPLb5:STAba+1:STAsd+1:LDX#2:STXba+2:LDAbis,X:STAsf:JMPpb:.ep RTS 44 | 530 .b0 LDAba:STAsd:LDAba+1:STAsd+1:BPLb1:DECba+2:BNEep:EOR#&80:STAsd+1:LDA#0:STAba+1:LDA#&10:ORAsc:STAsc:BEQbx:.b1 LDAba+2:AND#&7F:TAX:LDAbis,X:STAsf:LDY#0:LDA(bulst),Y:STAno:.h INY:LDA(bulst),Y:SEC:SBCpy:BMInh:CMP#7:BPLnh 45 | 540 INY:INY:LDA(bulst),Y:BEQnh+2:INY:LDA(bulst),Y:SEC:SBCba+3:BMInh+3:CMP#3:BPLnh+3:LDA#&E8:STA(bulst),Y:TAX:LDA#7:LDY#&2D:JSR&FFF1:LDA#&10:STAba+2:LDA#&80:ORAba+1:STAba+1:JSRpb 46 | 550 .bx LDA#&B:STAsf+1:LDA#&70:STAsf:JMPpb:.b9 LDA#4:ORAsc:STAsc:LDA#0:STAba+1:.x RTS 47 | 560 .nh INY:INY:INY:CPYno:BMIh:LDA#&80:EORba+2:STAba+2:BMIx:JSRpb:LDAba+3:.xps CMP#76:BEQb9:AND#31:BNEb6:LDA#7:LDY#&2D:LDX#&F0:JSR&FFF1 48 | 570 .b6 LDXba+2:DEX:BPLb7:LDX#7:.b7 STXba+2:LDAbis,X:STAsf:LDAxps+1:BEQb10:INCba+3:CLC:LDAba:ADC#8:STAba:STAsd:BCCpb:INCba+1:INCsd+1:JMPpb 49 | 580 .b10 DECba+3:SEC:LDAba:SBC#8:STAba:STAsd:BCSpb:DECba+1:DECsd+1 50 | 590 .pb LDY#&17:.b8 LDA(sf),Y:EOR(sd),Y:STA(sd),Y:DEY:BPLb8:RTS 51 | 600 ]:NEXT:VDU11:PRINT~P% 52 | 610 !&2B4A=!&2B4A AND &FFFF0000 OR stp6:END 53 | 620 DEFPROCI 54 | 630 !&2D5F=&00404080:!&2D63=&80400080:?&2D67=0 55 | 640 FORA%=&2D0ATO&2D5E:?A%=0:NEXT 56 | 650 bfg=&71:pfg=&72:Xg=&2D70:gunp=&86:bis=&2D68:ba=&2D7C 57 | 660 py=&7C:ra1=&7D:sd=&80:sf=&82:bulst=&8A:buf=&2D72:no=&70 58 | 670 vs=&27C3:lg=&26B0:plf=&88:pls=&75:pos=&78:psta=&7A:bost=&8C 59 | 680 de=&2D79:ti=&2D7A:sc=&2D76:bof=&2D74:inb=&2D71:gex=&2F28:picn=&2FC 60 | 690 !Xg=&2F30CF20:!plf=&2F40:!bof=&2F38:!de=&420320 61 | 700 ?bfg=2:!bulst=&2D472D0A:?&2D0A=8:?&2D47=20 62 | 710 !pls=&2D13:?&2D13=25 63 | 720 mg=&286E:gun=&28D3:mb=&28E2:nb=&295E 64 | 730 np=&29F7:mp=&2A94:fo=&2BE1:pp=&2C08:nbo=&2C45:mbo=&2C98 65 | 740 C%=&261A:D%=&281D:E%=&2835:scr=&284A:w=&285A 66 | 750 X%=&258D:R%=&25B8:V%=&25C9 67 | 760 ENDPROC 68 | -------------------------------------------------------------------------------- /Original/$.S: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qurm/BirdStrike/b13704515ac3996feeacb220ab03b2a1ba6c6869/Original/$.S -------------------------------------------------------------------------------- /Original/$.S.INF: -------------------------------------------------------------------------------- 1 | $.S FF3000 FF8023 001DCA 2 | -------------------------------------------------------------------------------- /Original/$.S.bas: -------------------------------------------------------------------------------- 1 | 100 PROCI:HIMEM=&5800 2 | 110 FORZ=0TO2STEP2:P%=&1E00 3 | 120 [OPTZ:.Q% LDA#200:LDX#1:LDY#0:JSR&FFF4:JSRspace:LDA&20C:STAsoun:LDA&20D:STAsoun+1 4 | 125 .newgame JSRgend:JSRS% 5 | 130 .GO JSRR%:JSRscr 6 | 140 JSRmp:JSRnp:JSRmg 7 | 150 JSRmb:JSRnb:JSRmbo:JSRnbo:JSRB% 8 | 160 JSRH%:JSRsor:JSRopt:LDX#&8F:JSRkey:BNEGO:LDA#200:LDY#0:JMP&FFF4 9 | 170 EQUS"(c)A.E.Frigaard 1984 Hello!" 10 | 180 .S% LDA#5:STAno:JSRE%:LDA#&49:JSRtune:LDA#22:JSR&FFEE:LDA#2:JSR&FFEE:LDA#0:STAexg3:STAcnt:STAfc:STApicn:STAgex:STAsc+1:STAsc+2:STAplf:CLC 11 | 190 LDA#32:STAde:LDA#3:STAde+1:LDA#42:STAde+2:LDA#2:STAbfg:LDA#&2D:STAbulst+1:STAbost+1:STApls+1 12 | 200 LDA#&47:STAbost:LDA#&A:STAbulst:LDA#&13:STApls 13 | 210 LDX#15:LDY#7:.co1 JSRD%:DEX:CPX#7:BNEco1:STXra1:LDA#3:STAgex+1:LDA#&2F:STAplf+1:LDA#&F0:STAinb:LDA#0:STAtm+1 14 | 220 .bf JSRcht:STXnl:INCfc:LDAde:CMP#15:BMIb0:LDAfc:AND#1:BEQb0:DECde:DECde:DECinb 15 | 230 .b0 INCtm+1:INCtm+1:LDA#12:JSR&FFEE:LDA#154:LDX#20:JSR&FFF4:JSRC%:JSRV%:JSRstv:JSRs7:LDA#0:STA&1D5B:STAsc:STAba+1:LDY#&54:.b1 STA&2D0A,Y:DEY:BNEb1 16 | 240 LDAtm+1:STA&2D47:LDA#6:STA&2D0A:LDA#30:STA&2D13:LDA#&30:STAnot+1:LDA#&88:STAnot 17 | 250 LDA#&80:STAgex+2:LDA#&32:STAgex+3:LDXgex+1:.pmi JSRmini:CLC:LDAgex+2:ADC#&18:STAgex+2:DEX:BNEpmi 18 | 260 LDA#&3A:STA&81:LDA#&81:STA&82:LDX#1:LDY#8 19 | 270 .pp1 LDA#&81:STA!pls,X:INX:TYA:CLC:ADC#&50:STA!pls,X:TAY:INX:LDA&81:ADC#0:STA!pls,X:STA&81:CLC:INX:LDA&82:ADC#10:STA&82:STA!pls,X 20 | 280 INX:LDA#&D0:STA!pls,X:INX:CPX#31:BMIpp1:LDY#0:LDA(pls),Y:STAno 21 | 290 .slop INY:INY:LDA(pls),Y:STApos:INY:LDA(pls),Y:STApos+1 22 | 300 JSRpp:INY:INY:CPYno:BMIslop 23 | 310 JSRh7:.sgun LDA#32:STAXg:LDA#&7E:STAgunp+1:LDA#&90:STAgunp:LDA#&23:STAgun+4:LDA#&58:STAgun+3:JSRgun:LDA#&40:JMPtune 24 | 320 .sor LDAsc:BEQs7:SED:AND#2:BEQs1:CLC:LDA#&15\pl:ADCsc+1:STAsc+1:LDAsc+2:ADC#0:STAsc+2:JSRX% 25 | 330 .s1 LDA#&40:BITsc:BEQs4:CLC:LDA#1 \wng:ADCsc+1:STAsc+1:LDAsc+2:ADC#0:STAsc+2 26 | 340 CLD:LDX#(bsou AND255):LDY#(bsou DIV256):LDA#7:JSR&FFF1:SED 27 | 350 .s4 LDA#&10:BITsc:BEQs2:CLC:LDA#10\pig:ADCsc+1:STAsc+1:LDAsc+2:ADC#0:STAsc+2:CLD:JSRnxno:BNEs2:JSRbon 28 | 360 .s2 CLD:JSRexg:LDAsc:BPLs3:JMPef:.s3 LDA#0:STAsc:RTS \sor 29 | 370 .s7 LDA#&34:STAsd+1:LDA#&B0:STAsd:LDA#&1C:STAsf+1:LDA#&F0:ANDsc+2:JSRW%:LDA#&F:ANDsc+2:ASLA:ASLA:ASLA:ASLA:JSRW% 30 | 380 LDA#&F0:ANDsc+1:JSRW%:LDA#&F:ANDsc+1:ASLA:ASLA:ASLA:ASLA:JSRW%:LDA#0:JMPW% 31 | 390 .delay STAtm+2:TYA:PHA:.del1 JSRscr:DECtm+2:BNEdel1:PLA:TAY:RTS 32 | 400 .ef LDA#0:STAsc:CLC:LDAplf:ADC#&40:STAplf:LDA#100:JSRdelay:JMPbf 33 | 410 .cht LDA#3:ANDfc:TAX:BNEct1:LDA#&33:RTS:.ct1 DEX:BNEct2:TXA:LDX#13:RTS 34 | 420 .ct2 DEX:BNEct3:LDA#17:LDX#26:RTS:.ct3 LDA#34:LDX#38:RTS 35 | 430 .patch LDAra1:BPLpatch2:LDAsd:EOR#&C0:STAsd:.patch2 LDAde:RTS \dirn when above 36 | 440 37 | 450 .nxno INCnl:LDYnl:LDAnl,Y:STAno:AND#&E:CMP#8:BPLn1:CLC:ADCnot:STAsd:LDA#0:BEQn2 38 | 460 .n1 CLC:ADCnot:ADC#&78:STAsd:LDA#2 39 | 470 .n2 ADCnot+1:STAsd+1:LDA#&23:STAsf+1:JSRchnot 40 | 480 CLC:LDAnot:ADC#&20:STAnot:BCCn3:INCnot+1 41 | 490 .n3 JSRpno:CLC:LDAsd:ADC#8:STAsd:BCCn4:INCsd+1 42 | 500 .n4 CLC:LDAsf:ADC#8:STAsf:BCCn5:INCsf+1 43 | 510 .n5 JSRpno:INY:LDAnl,Y:RTS 44 | 520 .chnot LDA#&80:BITno:BEQc1:LDA#0:STAsf:RTS 45 | 530 .c1 LSRA:BITno:BEQc2:LDA#&10:STAsf:RTS:.c2 LSRA:BITno:BEQc3:LDA#&20:STAsf:RTS 46 | 540 .c3 LSRA:BITno:BEQc4:LDA#&30:STAsf:RTS:.c4 LDA#1:BITno:BEQc5:LDA#&40:STAsf:.c5 RTS 47 | 550 .pno TYA:PHA:LDY#7 48 | 560 CLC:LDAsd:ADC#&78:STAst:LDAsd+1:ADC#2:STAst+1 49 | 570 LDAsd:AND#7:EOR#7:STAmod:CMP#7:BPLtop 50 | 580 .bot LDA(sf),Y:ORA(st),Y:STA(st),Y:DEY:CPYmod:BNEbot 51 | 590 .top LDA(sf),Y:ORA(sd),Y:STA(sd),Y:DEY:BPLtop 52 | 600 PLA:TAY:RTS 53 | 610 .tune STAno:.t1 LDYno:LDAtl,Y:BEQt3:STA&2DFC:INY:LDAtl,Y:STA&2DFE 54 | 620 LDX#&F8:LDY#&2D:LDA#7:JSR&FFF1:INCno:INCno:JMPt1 55 | 630 .t3 LDA#&80:LDX#250:JSR&FFF4:CPX#15:BMIt3:RTS 56 | 635 .key LDA#&81:LDY#&FF:JSR&FFF4:INX:RTS 57 | 640 58 | 650 ]:VDU11:PRINT~P%;:P%=&1778:[OPTZ 59 | 660 .stmv LDY#10:.stm4 LDAstm10,Y:JSR&FFEE:DEY:BPLstm4 60 | 670 LDA#&80:STAstm2+1:LDA#0:STAstm3+1:LDA#4:STAno:.stm1 LDA#29:JSR&FFEE:LDA#0:JSR&FFEE:JSR&FFEE:SEC 61 | 680 .stm2 LDA#0:SBC#&80:STAstm2+1:PHP:JSR&FFEE:PLP:.stm3 LDA#0:SBC#0:STAstm3+1:JSR&FFEE:JSRstv:DECno:BNEstm1 62 | 690 63 | 700 .stm5 LDAfc:STAtm 64 | 710 LDA#0:STAfc:LDA#&26:STAtm+4:LDA#&88:STAtm+3 65 | 720 .stm6 CLC:LDAtm+3:STAnot:LDAtm+4:ADC#&A:STAtm+4:STAnot+1:JSRcht:STXnl:INCfc 66 | 730 .stm8 JSRnxno:BNEstm8:JSRcht:JSRtune 67 | 740 LDA#60:JSRdelay 68 | 750 LDAfc:CMP#4:BNEstm6:LDAtm:STAfc:LDA#26:JMP&FFEE 69 | 760 .stm10 EQUD&4FF0310:EQUD&F020F:EQUW&18F0:EQUB26 70 | 770 71 | 780 .gend LDA#0:STAhs:LDAsc+2:CMPhs+2:BCCge1:BNEge0:LDAsc+1:CMPhs+1:BCCge1 72 | 790 .ge0 LDAsc+1:STAhs+1:LDAsc+2:STAhs+2:DEChs 73 | 800 .ge1 LDA#22:JSR&FFEE:LDA#7:JSR&FFEE 74 | 810 LDX#(bsk AND255):LDY#(bsk DIV256):JSRwrs 75 | 820 LDA#31:JSR&FFEE:LDA#5:JSR&FFEE:LDA#11:JSR&FFEE 76 | 830 LDAhs+2:JSRwhs:LDAhs+1:JSRwhs:LDA#48:JSR&FFEE 77 | 840 LDX#(dts AND255):LDY#(dts DIV256):JSRwrs 78 | 850 LDX#(ints AND255):LDY#(ints DIV256):JSRwrs 79 | 860 LDA#31:JSR&FFEE:LDA#26:JSR&FFEE:LDA#11:JSR&FFEE 80 | 870 LDAhs:BEQge3 81 | 880 LDA#21:LDX#0:JSR&FFF4 \ flush 82 | 890 TXA:LDX#(nbk AND255):LDY#(nbk DIV256):JSR&FFF1:JMPge7 83 | 900 .ge3 LDY#&FF:.ge6 INY:LDAnam,Y:JSR&FFE3:CMP#32:BPLge6 84 | 910 .ge7 LDY#2:.ge5 LDAm7,Y:JSR&FFEE:INY:CPY#13:BNE ge5 85 | 920 LDA#100:JSRdelay 86 | 930 .space LDA#26:JSR&FFEE:LDX#(sps AND255):LDY#(sps DIV256):JSRwrs 87 | 940 .ge4 LDX#&9D:JSRkey:BNEge4:RTS 88 | 950 .whs PHA:LSRA:LSRA:LSRA:LSRA:CLC:ADC#&30:JSR&FFE3:PLA:AND#&F:CLC:ADC#&30:JMP&FFE3 89 | 960 .wrs STXwr1+2:STYwr1+3:LDY#&FF:.wr1 INY:LDAdts,Y:JSR&FFE3:CMP#0:BNEwr1:RTS 90 | 970 ]:PRINT~P%;:P%=&1400:[OPTZ 91 | 980 92 | 981 EQUS"Thanks David,Ian,Martin,Mum,Dad,Susi C" 93 | 990 .opt LDX#&EF:JSRkey:BNEop1:LDA#(mute MOD256):STA&20C:LDA#(mute DIV256):STA&20D 94 | 1000 .op1 LDX#&AE:JSRkey:BNEop2:LDAsoun:STA&20C:LDAsoun+1:STA&20D 95 | 1010 .op2 LDX#&CC:JSRkey:BNEop5:.op3 LDA#&81:LDY#1:LDX#0:JSR&FFF4:BCSop3:CPX#82:BEQop3 96 | 1020 .op5 RTS 97 | 1030 98 | 1034 .mute CMP#7:BEQop5:.mu1 JMP(soun) 99 | 1035 .soun EQUW&E7EB 100 | 1039 101 | 1040 .nlr LDAtog:BEQenlr:LDAexp:BPLrt:DECpsta:SEC:LDApos:SBC#8:STApos:BCSenlr:DECpos+1:JMPenlr 102 | 1050 .rt INCpsta:CLC:LDApos:ADC#8:STApos:BCCenlr:INCpos+1 103 | 1060 .enlr LDA#1:EORtog:STAtog:JMP&2BE1 104 | 1070 .tog EQUB0 105 | 1071 106 | 1072 .fpat LDAfp0:BEQfp1:DECfp0:RTS 107 | 1075 .fp1 LDA#18:STAfp0:JMP&297D 108 | 1076 .fp0 EQUB 0 109 | 1080 110 | 1090 .gov PLA:PLA 111 | 1100 LDY#255:.gov1 INY:LDA#10:JSRdelay:LDAgov2,Y:JSR&FFEE:CMP#82 \R:BNEgov1 112 | 1110 LDA#150:JSRdelay:JMPnewgame 113 | 1120 .gov2 EQUD&110F051F:EQUB1:EQUS"GAME OVER" 114 | 1130 .stp4 RTS 115 | 1140 .stp6 LDAgex:BEQstp4:LDApsta:EOR#&80:STApsta:INC exp \bug!:PLA:PLA:JMPF%+3 116 | 1150 .exg LDA#1:BITexg3:BNEexg1:LDYsc+2:CPY#5:BMIexg2:ORAexg3:STAexg3:JSRexg4 117 | 1160 .exg1 LDA#2:BITexg3:BNEexg2:LDYsc+2:CPY#&10:BMIexg2:ORAexg3:STAexg3:JMPexg4 118 | 1170 .exg2 RTS:.exg3 EQUB0 119 | 1180 .exg4 JSRmini:LDA#220:STA&2DFC:LDX#&F8:LDY#&2D:LDA#7:JSR&FFF1 120 | 1190 INCgex+1:CLC:LDAgex+2:ADC#&18:STAgex+2:BCCexg5:INCgex+3:.exg5 RTS 121 | 1195 122 | 1200 .bon LDAfc:AND#3:BNEbon0:LDA#15:JSRdelay:JSRstmv:JMPbon11:.bon0 JSRcht:JSRtune 123 | 1205 .bon11 JSRwbmsg:LDY#75:.bon1 SED:CLC:LDAsc+1:ADC#2:STAsc+1:LDAsc+2:ADC#0:STAsc+2 124 | 1210 CLD:LDA#2:JSRdelay:TYA:PHA:LDX#&E8:LDY#&2D:LDA#7:JSR&FFF1:JSRs7:PLA:TAY:DEY:BNEbon1 125 | 1220 INCbsou:LDX#(bsou AND255):LDY#(bsou DIV256):LDA#7:JSR&FFF1:DECbsou 126 | 1230 LDA#&80:ORAsc:STAsc:RTS 127 | 1240 .wbmsg LDY#0:.wb1 LDAbmsg,Y:JSR&FFEE:INY:CPY#11:BNEwb1:RTS 128 | 1250 .bmsg EQUD&71F0611:EQUB&F:EQUS"BONUS!" 129 | 1260 .bsou EQUD&FFFF0012:EQUD0 130 | 1261 ]:PRINT~P%,;:P%=&2970:[OPTZ 131 | 1263 LDA#0:STAfp0:RTS:RTS:JMPfpat 132 | 1270 ]:PRINT~P%:VDU11:NEXT:M%=&FFFF0000:!&2B4A=!&2B4A AND M% OR stp6 133 | 1280 !&2B68=!&2B68 ANDM% OR patch:!&22B7=!&22B7 ANDM%OR sgun:!&22B1=!&22B1 ANDM%OR gov 134 | 1290 !&2BBE=!&2BBE ANDM% ORnlr:?&2BBD=&4C:END 135 | 1300 DEFPROCI 136 | 1310 bfg=&71:pfg=&72:mod=&74:exp=&77:Xg=&2D70:inb=&2D71:gunp=&86:ba=&2D7C:ra1=&7D:sd=&80:sf=&82:st=&84 137 | 1320 bulst=&8A:buf=&2D72:no=&70:plf=&88:pls=&75:pos=&78:psta=&7A:bost=&8C:cnt=&8E 138 | 1330 sc=&2D76:bof=&2D74:de=&2D79:tm=&1A08:gex=&1D55:picn=&1D54:not=&1D59:fc=&1D5C 139 | 1340 mg=&286E:gun=&28D3:mb=&28E2:nb=&295E 140 | 1350 np=&29F7:mp=&2A94:F%=&2BE1:pp=&2C08:nbo=&2C45:mbo=&2C98 141 | 1360 C%=&261A:D%=&281D:E%=&2835:scr=&284A:W%=&285A 142 | 1370 nl=&2382:tl=&23B2:B%=&240E:pb=&2581:X%=&258D:R%=&25B8:V%=&25C9 143 | 1380 stv=&21EE:sl=&220E:mini=&2223:H%=&2238:h7=&22E2 144 | 1390 nbk=&15C0:hs=&15C5:m7=&15C8:bsk=&15D4:dts=&16A0 145 | 1400 nam=&16B4:ints=&16BD:sps=&175C 146 | 1410 ENDPROC 147 | -------------------------------------------------------------------------------- /Original/$.X: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qurm/BirdStrike/b13704515ac3996feeacb220ab03b2a1ba6c6869/Original/$.X -------------------------------------------------------------------------------- /Original/$.X.INF: -------------------------------------------------------------------------------- 1 | $.X 001900 001900 000500 2 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # BS2021 2 | Bird Strike is a video game for the BBC Micro written by Andy Frigaard and published in 1984 in the UK by [FireBird](https://en.wikipedia.org/wiki/Telecomsoft#Firebird) software. This is a release in 2021 of the original source code. 3 | 4 | 5 | It can be played online in the JSBeeb emulator here [ http://www.bbcmicro.co.uk](http://www.bbcmicro.co.uk/index.php?rt_R=&rt_B=&rt_M=&rt_P=&rt_U=&rt_W=&rt_L=&search=bird+Strike&on_T=on&on_Y=on&on_P=on&on_A=on&on_G=on&on_S=on&on_Z=on&on_C=on&sort=b) 6 | 7 | 8 | ## Original source folder 9 | Contains the files in the BBC file format recovered from a 5.25" disk backup from 1984. 10 | 11 | These are a mix of BBC BASIC Assembler source code and some binary files containing graphics, sprites and data tables. The three BASIC files are also copied and renamed as `.bas` in a text file format. The original files are in the BBC BASIC format with tokenised line numbers. 12 | 13 | Small sections of source code were only present in binary format and may later be recovered from the original tapes. These have been reconstructed from disassembly. 14 | 15 | The source is hard to read in the original BASIC/Assembler files. 16 | There are minimal comments and typically 2 or 3 character labels. Working memory was very limited and the shortest possible files allowed for source and assembled code to both be held in RAM. The game development started using the cassette tape file system and only the later files were developed on disk. Over the period I may have lost some of the earlier source, or just been unable to keep editing it all with limited space, so there are various patches and modifications to the older routines. 17 | 18 | 19 | ## Buildable source 20 | The Build folder has an alternative current (2021) version of the source files that can be built using Beebasm to produce a bootable disk image for use on the Beebem emulator or real BBC Micro. 21 | 22 | There are minor differences to the original source, mostly explained. There are extensive explanations, comments, labels, & named constants, but no fixes or changes to the code. It will build a byte-for-byte binary that is the same as the published tape version without the copy protection and tape file loader (which had music & instructions). 23 | 24 | Multiple asm files are used, each built at a specific address. This is because the original game has areas of binary data (graphics, sprites, data tables) interspersed with the code. 25 | 26 | There are a large number of self-modifying code routines and patches applied to earlier code that make direct reference to specific memory locations. For this reason the files need to be built and run at those memory locations. 27 | 28 | ### How to build 29 | All the required files are in the Build folder only. 30 | 31 | The main build file is `build_birdstrike.asm` that links all the source and binary files. This declares all the constants, variables and determines the locations at which each component is assembled or loaded. It does contain some build instructions, for example, for a basic assembly : `beebasm -i build_birdstrike.asm ` 32 | 33 | 34 | ## Clean source 35 | The Clean folder has an improved current (2021) version of the source files. This is very much the same game, but has many source code changes, and further comments. These changes include making the code relocatable, more use of zero-page, simplifying the source by merging patches into the original code, better labels, and making routines more flexible. 36 | 37 | The code to change from level to level was re-written to fix some bugs, and simplified to use a table of parameters that change (such as number of bombs, bullets, speed). This means that these parameters can be easily changed and the game can be easily adjusted and tuned to increase difficulty & challenges. 38 | 39 | The game was run in a profiler to identify inefficient & heavily used code, and some optimisations applied. 40 | 41 | This is the best version for any further development, or for learning how the code works. As it is largely all relocatable, changes can be made without side-effects. Also much more of the code uses variables rather than hard-coded parameters (e.g. no & rate of bullets). 42 | 43 | ## Credits 44 | Huge thanks to Iain McLaren whose work to disassemble and debug the original game inspired me to start this work. His assistance and encouragement to recover the source from my old disks motivated me to spend time rediscovering, commenting and publishing the code after a 37 year gap! 45 | 46 | Also to the Stardot community https://stardot.org.uk/forums/index.php, who are friendly, helpful and extemely knowledgeable! 47 | 48 | ## List of files 49 | ### Original 50 | 51 | ### Build 52 | 53 | 54 | 55 | 56 | -------------------------------------------------------------------------------- /build_output.asm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qurm/BirdStrike/b13704515ac3996feeacb220ab03b2a1ba6c6869/build_output.asm --------------------------------------------------------------------------------