From 186aa90685cc27b4506c57cf6d9f40318878e364 Mon Sep 17 00:00:00 2001 From: Mischa Poslawsky Date: Thu, 10 Aug 2000 15:38:44 +0200 Subject: [PATCH] version 0.99 pre1: optimisations, level updates * some optimizations: keycall, menu handling, port nops removed, more SMC, fire handling, fast bullet handling, enemy movement * better "backwards" enemies handling (and implemented in game) --- nemesis.txt | 50 ++- nemesis.z80 | 970 ++++++++++++++++++++++++++-------------------------- 2 files changed, 501 insertions(+), 519 deletions(-) diff --git a/nemesis.txt b/nemesis.txt index 10ac92a..81dbc27 100644 --- a/nemesis.txt +++ b/nemesis.txt @@ -1,42 +1,38 @@ ------------------------------------------------------------------------------ Title : Nemesis - Version : 0.98.77 Beta - Release Date : 7.VII.00 - Filename : nemesis.86p (size 6707B) + Version : 0.99.810 Beta + Release Date : 10.VIII.00 + Filename : nemesis.86p (size 7kB) Author(s) : Shiar Email Address : shiar0@hotmail.com ICQ : #43840958 Web Page : http://www.shiar.org Description : cool arcade-shoot-em-up-game - Where to get this game : www.shiar.org | www.ticalc.org + Where to get this game : www.shiar.org | ticalc.org Other games by author : Worm ->>>>>>> NOTE ON V.98 --------------------------------------------------------- +>>>>>>> NOTE ON V.99 --------------------------------------------------------- - It's been nearly a year since the first version of Nemesis, and over one -half year since my last version. So I figured it's about time to complete -this game. I won't bother you with the endless list of improvements I made; -just go ahead and play the game! + [Under construction] >>>>>>> INTRO TO NEMESIS ----------------------------------------------------- Nemesis is an old arcade-game for many platforms, originally for arcades. I first played Nemesis III for the MSX (1988), but Konami made at least -41 Nemesis-games (named Nemesis=Gradius, Salamander=LifeForce, Parodius) +41 Nemesis-games - named Nemesis=Gradius, Salamander=LifeForce, Parodius - for systems including the Game Boy, (S)NES and Play Station. >>>>>>> THA GAME ------------------------------------------------------------- - Arrow keys : move - 2nd : fire - ALPHA : select powerup - MORE : pause - GRAPH : teacher/boss! (press graph again to resume) - EXIT : exit - F1 : toggle B<>W in main menu, save game at level-screen + ARROWS : move + 2nd : fire + ALPHA : select powerup + MORE : pause (change contrast, toggle B<>W) + GRAPH : teacher/boss! (press graph again to resume) + EXIT : whooo, what does _this_ button do? Collect the pickups enemies leave after they're destroyed to upgrade your ship. The highlighted icon in the score bar (bottom) can be activated by @@ -66,19 +62,13 @@ memory LOCKED! Besides that there shouldn't be any bugs. >>>>>>> CREDITS -------------------------------------------------------------- - SHIAR (me) programming and everything else. SHIAR@MAILROOM.COM - DAVE official betatester (if you need a bug, ask Dave :) - BLACKBELT official betatester - MATTHEW DALE official betatester - JONAH COHEN for teaching me z80, giving advise, testing... - SCABBY gave me Wworm, Derek, and probably some other stuff - CULLEN SAULS exchanging beta MegaMan for beta Nemesis ;) - BRIAN KOROPOFF for solving the left+down bug! - PATRICK DAVIDSON Nemesis was originally based on his Galaxian - KONAMI for writing the original Nemesises and more great games - -and EVERYBODY WHO SENT ME SOMETHING!! (too much to list here) -and everybody I forgot. + Programming/levels/gfx - - - SHIAR + Official betatesters - - - - DAVE -- BLACKBELT -- MATTHEW DALE + Support (advise/ideas/etc) - JONAH -- SCABBY -- BRIAN KOROPOFF -- CULLEN S + Original engine (Galaxian) - PATRICK DAVIDSON + Original Nemesises - - - - - KONAMI + +Also alot of thanks to EVERYBODY WHO SENT ME SOMETHING and everybody I forgot. >>>>>>> RULEZ AND REGULATIONS ------------------------------------------------ diff --git a/nemesis.z80 b/nemesis.z80 index 31cf27c..fed759c 100644 --- a/nemesis.z80 +++ b/nemesis.z80 @@ -7,7 +7,7 @@ ;Description : cool arcade-shoot-em-up-game ;Other games by author : Worm ;This source should only be used for learning practises, do not -;alter it, and certainly do not distribute an altered version!! +;alter it, and certainly never distribute an altered version!! ;&&& marks uncertainties or things to optimize @@ -39,7 +39,6 @@ storepos2 = _asm_exec_ram+7200 ;141 OF 167 9000 BYTES ;---------------------- in-game vars ---------------------------------------- just_fired = storepos ; +0 ;counts how long a blast lasts -menuitem = storepos ; +0 ;used to store menu location hiscorepos = storepos ; +0 ;entering hiscore name ; ;--------YOU x = storepos+1 ; +1 ;your ship's position @@ -48,12 +47,10 @@ firex = y+1 ; +3 ;(1 byte) firey = firex+1 ; +4 ;(1 byte) ; ;--------LEVEL eventleft = storepos+5 ; +5 ;nr. of enemies still to come -nextevent = eventleft+1 ; +6 ;time to next event -level_enemy = nextevent+1 ; +7 ;enemy type +level_enemy = eventleft+1 ; +7 ;enemy type level_info = level_enemy+1 ; +8 ;info (see below) level_move = level_info+1 ; +9 ;= - ; ;--------OBJECTS -spacespace = storepos+19 ;+19 +spacespace = level_move+1 ;+10 groundinfo = spacespace+1 ;+20 groundpos = groundinfo+1 ;+21 $10 ceilingpos = groundpos+16 ;+37 $10 @@ -66,7 +63,7 @@ nrstars2 = 7 starx2 = starx1+(nrstars1*2) ;+69 ; ;--------MULTIPLES your_prevpos = starx2+(nrstars2*2) ;+87 ;save previous positions (32d) -mm = 4 +mm = 4 ;max. number of multiples ;^-----------------------------------<1 ;-120=$78 @@ -95,7 +92,7 @@ lvlenemies = ebullets+(nrebuls*3) .dw Title ;pointer to description (all shells) .dw Icon ;pointer to YAS icon -Title: .db "Nemesis v0.98 by SHIAR",0 +Title: .db "Nemesis v0.99.810 by SHIAR",0 Icon: .db 8,1 ;icon for YAS: width = 1byte; height = 9bytes .db %11100000 ; ███ @@ -105,8 +102,8 @@ Icon: .db 8,1 ;icon for YAS: width = 1byte; height = 9bytes .db %00111110 ; █████ .db %01111000 ; ████ .db %11100000 ; ███ ;recommend 80x50 screen mode - .DB 0 ;clear stupid YAS-line - + .db 0 ;YAS 0.92 compatibility +;43 ;---------------------- init ------------------------------------------------ int_handler: ;new interrupt proc @@ -188,11 +185,9 @@ dispmenu: ld hl,txt_menu2 cal _puts - xor a - ld (menuitem),a - menuloop: - ld a,(menuitem) + ld a,0 ;current menu item (0 or 1); 0 by default +menuitem =$-1 ld h,$01 add a,4 ld l,a @@ -211,38 +206,33 @@ menuloop: ld (_curRow),hl cal _putc - halt \ halt - - cal GET_KEY ;wait for keypress - cp K_UP - jr z,menuchange - cp K_DOWN - jr z,menuchange + cal getsomekeys ;read keys (z if enter/2nd pressed) + jr z,start_tha_freakin_game cp K_EXIT jr z,menuexit cp K_F1 cal z,do_invert - cp K_SECOND - jr z,start_tha_freakin_game - cp K_ENTER + cp K_UP + jr z,menuchange + cp K_DOWN jr nz,menuloop -start_tha_freakin_game: +menuchange: + ld hl,menuitem + ld a,(hl) + xor 1 ;0=1; 1=0 + ld (hl),a ;set new menu item + jr menuloop +start_tha_freakin_game: ld a,(menuitem) dec a cal nz,New_game ;NEW GAME jp samelevel ;CONTINUE: game_main_loop menuexit: - ld hl,0 - ld (your_score),hl - jp game_over - -menuchange: - ld a,(menuitem) - xor 1 - ld (menuitem),a - jr menuloop + ld hl,0 ;reset score + ld (your_score),hl ;(prevents hiscore while never played) + jp game_over ;and go to game over screen do_invert: ;invert screen (b<>w); destr:b psh hl @@ -255,6 +245,15 @@ do_invert: ;invert screen (b<>w); destr:b pop hl ret +getsomekeys: + halt + halt + cal GET_KEY + cp K_SECOND + ret z + cp K_ENTER + ret + ;---------------------------------------------------------------------------- ;---------------------- game loop ------------------------------------------- ;---------------------------------------------------------------------------- @@ -322,14 +321,13 @@ check_firekey: psh hl ;push hl on stack (instead of cal Fire_bullet) jp z,Fire_bullet ;fire smtn (bulletstaillasermultiples+stuff..) pop hl ;no cal to Fire_bullet made, so pop stack - xor a ;no: - ld (just_fired),a ;reset just_fired + ld hl,just_fired ;no: + ld (hl),5 ;able to fire (five turns = laser duration) check_selkey: ld a,%01011111 ;look at first column of keys (ALPHA to STO) - out (1),a ;gimme - nop \ nop ;what's taking you so long - in a,(1) ;at last... our precious keyzzz... + out (1),a + in a,(1) ;our precious keys bit 6,a ;'bout the GRAPH key... cal z,Teacher ;you didn't _press_ it, did you?!? @@ -349,12 +347,12 @@ _gamestuff1: cal Level_event ;insert enemies cal Display_Screen ;display all - ld b,1 -___: - halt ;delay - dnz ___ +delay: + halt ;delay and preserve batteries :) jp game_main_loop ;LOOP ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +;------- weapon ------- + inc_weapdamage: ld a,0 weapincs =$-1 @@ -378,7 +376,41 @@ weapdaminc =$-1 weapdamage =$-1 add a,b ;a=total damage ld (curweapdamage),a ;safe the current damage - cal disp_charge + + +disp_charge: ;display charge bar + ld hl,(59*16)+VIDEO_MEM+3 + ld b,3 +chargebarclr: + dec hl + ld (hl),0 + dnz chargebarclr + + ld a,(weapincs) ;load bar size (0-80) + srl a ;half the size (0-40) + srl a ;again half that size (0-20 pixels) + ld c,a ;psh a + srl a ;/2 + srl a ;/4 + srl a ;/8: don't display last 3 bits of a (later) + jr z,nochargebar ;if a=0 then it would loop 256x so skip it + ld b,a ;loop b=a times +chargebar: ;starting at ($39*16)+VIDEO_MEM + ld (hl),%11111111 ;draw a piece of the bar + inc hl ;next position + dnz chargebar ;loop it b times +nochargebar: + ld a,c ;pop a + and %111 ;display last bits of chargebar + ret z ;if armor=0 then bit = %00000000 (don't disp) + ld b,a ;into B + xor a ;bit = %00000000 +chargebarbit: + scf ;set carry flag + rra ;rotates A right and sets bit 7 (c-flag) + dnz chargebarbit ;repeat B times (so if B=6 then a=%11111100) +chargebarready: ; (an if B=3 then a=%11100000) + ld (hl),a ;draw this last byte ret ;--------------------------- ground ----------------------------------------- @@ -573,10 +605,10 @@ DisplayStars: ;inputs: hl=starx# a=stars# b=nrstars# movestars2: ld ix,starx2 ld a,(stars2) - rlca + rlca ;move bits (star) left ld (stars2),a - ret nc - ld b,nrstars2 + ret nc ;if star didn't went from left to right bit + ld b,nrstars2 ;otherwise move all stars one byte left jr movestars_loop movestars1: @@ -597,7 +629,7 @@ movestars_loop: ld a,l and %00001111 - cp 9 ;(GRAPH_MEM&%00001111)-- = $C9FAand15-1 = $A-1 + cp (dispbuffer&15)-1 ;$C9FAand15-- = 9 jr nz,newstarok cal RandomY @@ -985,65 +1017,58 @@ select6: ;------------------------- fire bullet -------------------------------------- -fire_multiples: - ld hl,(your_prevpos+16);then, fire from multiple position +fire_multiple: psh af dec h ;one up (-2 height: keeps weapons centered) + psh ix ;save ix for next fire cal fireany ;fire from multiple position + pop ix ;saving ix is much faster than recalculating pop af ;number of multiples dec a ;one just displayed - ret z ;return if none left + pop hl ;ret + ret z ;ret2 if none left + jp (hl) ;real ret + +fire_multiples: + ld hl,(your_prevpos+16);then, fire from multiple position + cal fire_multiple ld hl,(your_prevpos+30) - psh af - dec h - cal fireany - pop af - dec a - ret z + cal fire_multiple ld hl,(your_prevpos+44) - psh af - dec h - cal fireany - pop af - dec a - ret z + cal fire_multiple ld hl,(your_prevpos+58) - psh af - dec h - cal fireany - pop af - dec a + cal fire_multiple ;no JP: that messes up the stack ret Fire_bullet: - ld hl,just_fired - ld a,(hl) ;just_fired - cp 5 ;already pressed? - ret z ;return when already pressed (=5) + ld hl,just_fired ;=for how long you may hold fire (2nd) + ld a,(hl) ;a = time left + dec a ;decrease timer + ret z ;may not fire when (just_fired) became 0 + ld (hl),a ;save new decreased value - inc (hl) ;otherwise increase counter (0 to 4 >> 1 to 5) ld a,(your_weapon) ;if you have bullets..... cp maxweapon jr nc,fireOK ;>weapons = laser - ld (hl),5 ;.....then can't fire next turn (go to 5 imm.) - + ld (hl),1 ;bullet may last one turn (just fire 1 bullet) fireOK: + ld a,(your_weapon) ;weapon nr. + ld ix,weapondata+2 + add a,a ;weap*2 + add a,a ; *4 + add a,a ; *8 + ld c,a + ld b,0 ;go to current weapon (bc=a) + add ix,bc ;ix=weapon ptr + ld a,(your_multiples) ;any multiples? and %111 ;nr. of multiples cal nz,fire_multiples ;if >0 then fire them too ld hl,(x) ;fire from ship position (x) fireany: ;HL=(x,y) ld (firex),hl ;set position to fire from - ld a,(your_weapon) - ld ix,weapondata+2-(256*3) - add a,a ;weap*2 - add a,a ; *4 - add a,a ; *8 - ld c,a - ld b,3 ;go to current weapon (bc=a), b=3 :P - add ix,bc - -fire_weapon: ;b=3 + ld b,3 ;or use the proc at fireOK with ld ix,weapondata+2-(256*3) +fire_weapon: psh bc ;save counter ld a,(ix) ;load this weapon cp %11100000 ;%11110000=laser @@ -1064,7 +1089,40 @@ fire_tail: cp %11100000 ;issit laser ret z ;then return xor %11111 ;smart way of going left instead of right :P - jr fire_ybullet ;fire tail bullet and return + ;fire tail bullet +;-----fire BULLETs----- + +fire_ybullet: ;fire bullet type=C dam=(curweapdamage) at (firex/y) + ld c,a ;save bulletType in c + ld hl,ybullets ;check for unused bullet + ld de,4 + ld b,nrybuls +find_ybullet: + ld a,(hl) + or a + jr z,found_ybullet ;0 = no bullet here + add hl,de + dnz find_ybullet ;look next bullet + ret ;none found, return don't fire + +found_ybullet: + ld (hl),c ;use the bullet and set correct bullet-type + inc hl ;@damage + ld (hl),1 ;set bullet damage +curweapdamage =$-1 + ld a,(firex) ;your x-pos + add a,5 ;place bullet in front of you + inc hl ;go to bullet-x + ld (hl),a ;set x + + ld a,(firey) ;your y-pos + add a,(ix+1) ;place bullet at the middle of your ship + inc hl ;go to bullet-y + ld (hl),a ;set y + + xor a + ld (weapincs),a ;reset damage + ret ;-----fire LASER----- @@ -1148,43 +1206,9 @@ nolashit: pop ix ret -;-----fire BULLETs----- - -fire_ybullet: ;fire bullet type=C dam=(curweapdamage) at (firex/y) - ld c,a ;save bulletType in c - ld hl,ybullets ;check for unused bullet - ld de,4 - ld b,nrybuls -find_ybullet: - ld a,(hl) - or a - jr z,found_ybullet ;0 = no bullet here - add hl,de - dnz find_ybullet ;look next bullet - ret ;none found, return don't fire - -found_ybullet: - ld (hl),c ;use the bullet and set correct bullet-type - inc hl ;@damage - ld (hl),1 ;set bullet damage -curweapdamage =$-1 - ld a,(firex) ;your x-pos - add a,5 ;place bullet in front of you - inc hl ;go to bullet-x - ld (hl),a ;set x - - ld a,(firey) ;your y-pos - add a,(ix+1) ;place bullet at the middle of your ship - inc hl ;go to bullet-y - ld (hl),a ;set y - - xor a - ld (weapincs),a ;reset damage - ret - ;------------------------ handle bullets ------------------------------------ -bullet_left: +move_bullet: ld c,a ;c=type and %11111 ;pixels to move add a,(hl) ;a = X + (hl) to the right @@ -1198,6 +1222,7 @@ bullet_left: inc hl ;@y-pos ld a,c cal _shracc ;%11110000->1111 +;Note: a _shracc procedure inside Nemesis itself would be 27 cycles faster srl a ;%1110->111 dec a jr z,bullet_noymove ;1=straight forward @@ -1210,8 +1235,8 @@ bullet_left: bullet_halfdown: ;5=1/2down ld a,(timer) - and 1 - jr z,bullet_noymove + rra ;carry once every other turn + jr c,bullet_noymove bullet_down: ld a,(hl) inc a @@ -1220,8 +1245,8 @@ bullet_down: ld (hl),a bullet_halfup: ld a,(timer) - and 1 - jr z,bullet_noymove + rra ;CF every other turn + jr c,bullet_noymove bullet_up: ld a,(hl) dec a @@ -1232,7 +1257,7 @@ bullet_noymove: ret remove_bullet: - pop hl ;cal bullet_left + pop hl ;cal move_bullet pop hl ;enemy+type ld (hl),0 ;dump this bullet! jr next_ybullet+1 ;+1:skip pop hl at next_ybullet @@ -1241,33 +1266,31 @@ Handle_bullets: ld hl,ybullets ld b,nrybuls scan_bullets: + ld a,(hl) ;@bulletType + or a ;bulletType=0 >> no bullet + jp z,next_ybullet+2 ;skip pops (+2); jP for speed + psh bc ;bullet counter psh hl ;save enemy+type ld (temp1),hl ;needed for check_bullethits - ld a,(hl) ;@bulletType inc hl ;@damage inc hl ;@x - - or a - jp z,next_ybullet ;bulletType=0 >> no bullet - cal bullet_left ;move bullet left + cal move_bullet ;move bullet display_bullet: - psh de ;save de =position dec hl ;@x dec hl ;@damage ld a,(hl) ;bullet damage=size ld hl,bullettable ;pointer to first bullet srl a srl a ;per 4 - ld d,0 - ld e,a ;->16bit (de=a) - add hl,de ;point to correct bullet offset + ld b,0 + ld c,a ;->16bit (de=a) + add hl,bc ;point to correct bullet offset ld a,(hl) ;load bullet offset - ld e,a ;convert to 16bit (d=0) + ld c,a ;convert to 16bit (d=0) ld ix,spr_bullet01 ;first sprite - add ix,de ;add offset (go to correct sprite) - pop de ;saved position + add ix,bc ;add offset (go to correct sprite) ld a,(ix) ;bullet x-size ld (bulletxsize),a ;used at check_bullethits @@ -1280,11 +1303,11 @@ display_bullet: next_ybullet: pop hl ;restore enemy+type - inc hl + pop bc ;b=counter + inc hl ;&&&add hl = faster inc hl inc hl inc hl ;skip type,dam,x,y: next enemy+type - pop bc ;b=counter dnz scan_bullets ;next bullet (loop) ret @@ -1384,11 +1407,11 @@ pickupdone: ;--------------------------- level events ----------------------------------- Level_event: - ld hl,nextevent ;time to next event @@ -1579,34 +1599,31 @@ enemy_bullet: ld d,(hl) ;d=x inc hl ;@y - ld a,b ;restore type - cp %1100 ;is it a normal bullet? (cp = faster than bit) - jr z,ebullet_common ;type %1100: normal bullet - and %111 ;isolate important bits - jr z,ebullet_down ;type %1000: moving down - dec a - jr z,ebullet_up ;type %1001: moving up - ld b,a + dec b + jr z,ebullet_common ;type 1: normal bullet + dec b + jr z,ebullet_down ;type 2: moving down + dec b + jr z,ebullet_up ;type 3: moving up ld a,(timer) - rra - jr c,ebullet_common + rra ;half speed + jr c,ebullet_common ;if bit then normal bullet - ld a,b - dec a - jr z,ebullet_down ;type %1010: moving down 50% - ;type %1011: moving up 50% + dec b + jr z,ebullet_down ;type 4: moving down 50% + ;type 5: moving up 50% ebullet_up: ld a,(hl) dec a - jp m,ebullet_common + jp m,ebullet_common ;y<0 ld (hl),a jr ebullet_common ebullet_down: ld a,(hl) inc a - cp 55 + cp 58-3 jr z,ebullet_common ld (hl),a @@ -1645,7 +1662,7 @@ ebullet_hits: ld b,a ;set damage-amount cal damage_you ;HIT!! remove_ebullet: - pop hl ;hl could be destroyed by damage_you + pop hl ;hl destroyed by damage_you ld (hl),0 ;bullet > unused jr next_bullet+1 ;next bullet (SKIP THE = one byte) @@ -1708,10 +1725,8 @@ enemyonscreenX: jr firing_done ;continue check_enemyfire: - inc hl ;@y - inc hl ;@movetype - inc hl ;@movecount - inc hl ;@firecount + ld bc,4 ;4x inc hl + add hl,bc ;@firecount dec (hl) ;decrease counter till next blast ld a,(hl) ;&&&doesn't seem efficient to me or a ;has it reached zero? @@ -1735,16 +1750,16 @@ next_enemy: dnz handle_enemy ret -remove_enemy: - pop hl - ld (hl),$0000 ;bye bye enemy - jr next_enemy+1 ;continue AFTER pop hl (already done) - exploding_enemy: inc hl ld a,(hl) cp 16 - jr z,remove_enemy ;remove when at last frame + jr nz,keep_enemy ;remove when at last frame +remove_enemy: + pop hl + ld (hl),$0000 ;bye bye enemy + jr next_enemy+1 ;continue AFTER pop hl (already done) +keep_enemy: inc a ld (hl),a ;next frame dec a ;1-16 -> 0-15 @@ -1755,82 +1770,80 @@ exploding_enemy: ;--------------------------- moving enemies --------------------------------- moving_enemy: + dec d ;move left once ld a,(hl) ;how does this enemy move? - bit 7,a ;direction indicator - jr nz,moveright -moveleft: - dec d - jr moveXdone -moveright: - inc d -moveXdone: - res 7,a ;01111111=movetype: and a - ret z ;0 = don't move - dec a - jr z,movetype_updown ;1 = 0 >< up / down - dec a - jr z,movetype_vslow ;2 = .75 >> - dec a - jr z,movetype_slow ;3 = .5 >> - dec a - jr z,movetype_fast ;4 = .5 << - dec a - jr z,movetype_vfast ;5 = 1 << - dec a - jr z,movetype_smart ;6 - dec a - jr z,movetype_lure ;7 = 1 >> move y towards you - dec a - jr z,movetype_slowlure ;8 = 1 >> lure 1/2 speed - dec a -; jr z,movetype_stoplure ;9 = 1 >> slowlure; stop at x=99 -; dec a -; jr z,movetype_fulllure ;10 = x+y towards you 1/2 speed + ret z ;0 = (1<) + ld b,a + ld a,(timer) + dec b + jr z,movetype_updown ;1 = (1<) up / down + dec b + jr z,movetype_vslow ;2 = (.25<) + dec b + jr z,movetype_slow ;3 = (.5<) + dec b + jr z,movetype_fast ;4 = (1.5<) + dec b + jr z,movetype_vfast ;5 = (2<) + + inc d ;speed 0 + dec b + jr z,movetype_smart ;6 = &&& smart + dec b + jr z,movetype_lure ;7 = (0) move y towards you + dec b + jr z,movetype_slowlure ;8 = (0) lure 1/2 speed + dec b + dec b + jr z,movetype_fulllure ;10 = x+y towards you 1/2 speed + dec b + jr z,movetype_right ;11 = (.5>) + dec b + jr z,movetype_fright ;12 = (1>) + +movetype_right: + rra + ret c ;speed 0 50% +movetype_fright: + inc d ;move right one px + ret movetype_fulllure: - ld a,(timer) - and 1 - ret z + rra + ret c ;50% speed cal movetype_lure ld a,(x) cp d - ret c ;move left (already did) + jr c,movetype_vfast ;moves left (again) lure_right: - inc d ;already moved left, so move right -moverightonce: - inc d ;twice (=+1) + inc d ;move right ret movetype_slowlure: - ld a,(timer) - and 1 ;half the time - jr z,moverightonce ;dont move at all (compensate move left +ret) + rra ;half the time + ret c movetype_lure: - ld a,104 + ld a,110 cp d - jr c,dothelurethingy - inc d ;x<106: full stop + jr nc,dothelurethingy + dec d ;x>109: move left dothelurethingy: ld a,(y) cp e - ret z ;don't move if equal + ret z ;don't move vertically if equal jr c,lure_up ;below you then move up lure_down: ;above then move down inc e ret -lure_up: - dec e +lure_up:dec e ret movetype_smart: - inc hl ;hl =@ - ld a,(timer) - and %1111 ; | - ld a,(hl) ;&&& \|/ - jr nz,smartupdate + inc hl ;@movecount + ld a,(hl) inc a -smartupdate: + and %1111 ld (hl),a or a ;reset carry flag @@ -1839,41 +1852,33 @@ smartupdate: jr z,movetype_fast movetype_slow: - ld a,(timer) - and %1 - ret z + rra + ret c + inc d ;don't move + ret movetype_vslow: - ld a,(timer) and %11 ret z - inc d + inc d ;don't move ret movetype_fast: - ld a,(timer) - and %1 - ret z + rra + ret c ;once every other turn movetype_vfast: - dec d ;move left - ret nz ;finished - pop hl ;restore stack (no ret used) - jp remove_enemy ;remove this enemy (off screen) + dec d ;move left twice + ret movetype_updown: - inc hl ;@ + inc hl ;@movecount ld a,(hl) dec a - jr nz,move_updated - add a,128 -move_updated: - ld (hl),a - - or a ;reset carry flag - dec hl ;@ - and %00100000 - ld a,(hl);&&&ld a,e ;load current y-position + and 127 ;range 0..127 + ld (hl),a ;store new movecounter + dec hl ;reset hl to @movetype + and %00100000 ;ZF changes once every 64 turns + ld a,e ;load current y-position jr z,movedown - moveup: dec a ;decrease y-pos (=move up) ret m ;don't move off the screen (y<0) dec e ;save new y-pos @@ -1891,8 +1896,7 @@ Enemies_hit: ld hl,(x) ;e = X, d = Y ld de,$0707 ;add 7 to both d and e add hl,de - ld d,h - ld e,l ;e = X+7, d = Y+7 + ex de,hl ;e = X+7, d = Y+7 ld hl,enemies+1 ld b,nrenemies ;check all 20 enemies @@ -1981,88 +1985,75 @@ check_next: ;--------------------------- story ------------------------------------------ storyPage: - psh hl - cal _clrLCD + psh hl ;hl will be destroyed by _clrLCD + cal _clrLCD ;clear screen pop hl + ld a,(hl) + ld (curline),a ;begin line for special effect storyLine: + ld d,(hl) ;vertical position of text inc hl - ld e,(hl) + ld e,(hl) ;horizontal text-position + ld (_penCol),de ;set position inc hl - ld d,(hl) - ld (_penCol),de - inc hl - cal _vputs + cal _vputs ;display text - ld a,(hl) - dec a - jr z,storyLine + ld a,(hl) ;load next byte + inc hl + or a ;0 means more text + jr z,storyLine ;loop if there is + psh af psh hl ld hl,VIDEO_MEM ;copy text ld de,dispbuffer ;to GRAPH_MEM ld bc,1024 ;entire screen ldir - cal _clrLCD + cal _clrLCD ;clear VIDEO_MEM pop hl - - inc hl - ld a,(hl) - inc hl - ld b,(hl) + pop bc ;last byte (<>0) is lines to SFX psh hl - cal DoSFX - cal _getkey + cal DoSFX ;do special effects + cal _getkey ;wait for a key pop hl ret dostory: cal storyPage ;do some story - inc hl ;look at next hl - ld a,(hl) ;load in a - dec hl ;restory hl + ld a,(hl) ;load next byte in a inc a ;set z-flag if a = $ff jr nz,dostory ;otherwise loop - - ld bc,2+1 ;story ends - add hl,bc ;set hl to beginning of the level + inc hl + inc hl ;set hl to beginning of the level ld (levelp),hl ;set the level-pointer ret ;and return ;--------------------------- SFX -------------------------------------------- -DoSFX: ;in:a=beginLine;b=nrOfLines - ld (curline),a -SFXframe: +DoSFX: ;in:(curline)=beginLine;b=nrOfLines +SFXloop: psh bc ld a,0 ;get line number curline =$-1 inc a ;go to the next line ld (curline),a ;update - ld l,a ld h,0 ;hl=a add hl,hl add hl,hl add hl,hl add hl,hl ;*16 (a pixels down=a*16) + sub 64 ;a=a-64 + neg ;a=64-a (lines from bottom) ld b,h ;save hl for later ld c,l - ld de,VIDEO_MEM ;where to put sfx add hl,de ;go to ymin ex de,hl ;put into de again - - ld hl,dispbuffer - add hl,bc ;hl->logo - - sub 64 ;a=a-64 - neg ;a=64-a (lines from bottom) - -; ld c,a ;c=a=(curline) -; ld a,64 -; sub c ;lines from bottom + ld hl,dispbuffer ;source of original + add hl,bc ;hl->source SFXdisp: ;display this frame on screen ld bc,16 ;one line (=16 bytes, you'd know by now) @@ -2078,7 +2069,7 @@ SFXdelay: dnz SFXdelay ;8x pop bc ;counter - dnz SFXframe + dnz SFXloop ret ;--------------------------- show icon -------------------------------------- @@ -2243,41 +2234,6 @@ armorbarready: ; (an if B=3 then a=%11100000) ld (hl),a ;and just below ret -disp_charge: - ld hl,(59*16)+VIDEO_MEM+3 - ld b,3 -chargebarclr: - dec hl - ld (hl),0 - dnz chargebarclr - - ld a,(weapincs) ;load bar size (0-80) - srl a ;half the size (0-40) - srl a ;again half that size (0-20 pixels) - ld c,a ;psh a - srl a ;/2 - srl a ;/4 - srl a ;/8: don't display last 3 bits of a (later) - jr z,nochargebar ;if a=0 then it would loop 256x so skip it - ld b,a ;loop b=a times -chargebar: ;starting at ($39*16)+VIDEO_MEM - ld (hl),%11111111 ;draw a piece of the bar - inc hl ;next position - dnz chargebar ;loop it b times -nochargebar: - ld a,c ;pop a - and %111 ;display last bits of chargebar - ret z ;if armor=0 then bit = %00000000 (don't disp) - ld b,a ;into B - xor a ;bit = %00000000 -chargebarbit: - scf ;set carry flag - rra ;rotates A right and sets bit 7 (c-flag) - dnz chargebarbit ;repeat B times (so if B=6 then a=%11111100) -chargebarready: ; (an if B=3 then a=%11100000) - ld (hl),a ;draw this last byte - ret - ;--------------------------- proc ------------------------------------------- Random: ;a=c=%10010=forward; <=%01110=backwards) @@ -3410,7 +3376,7 @@ spr_dividerline: txt_email: .db "www.shiar.org ",127 ;title screen .db " shiar0@hotmail.com",0 _txt_email = $3A01 ;$3A1E=just email -txt_about: .db "v0.98.79 ",127," by Shiar",0 ;right behind txt_email +txt_about: .db "v0.99.810 ",127," by Shiar",0 ;right behind txt_email _txt_about = $3321 txt_menu1: .db "NEW GAME",0 txt_menu2: .db "CONTINUE",0 @@ -3431,7 +3397,7 @@ txt_teacherans: .db Lneg,"14.6549373495",0 storehi_start: hiscore .dw 0 ;default hiscore -hiname .db "shiar.98",0 ; " " name +hiname .db "shiar.99",0 ; " " name storehi_end: storesave_start: ;--SAVED GAME-- defs: @@ -3440,7 +3406,7 @@ levelp .dw level01 ;pointer to level data l01 pickuptimer .db 4 ;counts when to place a pickup 4 your_ship .dw spr_ship01 ;your sprite sprs1 your_score .dw 0 ;current score 0 -your_pickup .db 3 ;pickups already picked up 0 +your_pickup .db 5 ;pickups already picked up 0 your_occ .db 0 ;0=normal 1..16=exploding 0 your_inv .db 0 ;invincibility left 0 your_armor .db 12 ;HP left 12 @@ -3458,99 +3424,76 @@ time2invert: .db 0 ;time until b<>w switch (0 at startup) ; @level: [nr.dif.enemies]x [enemy nr] ; [min. enemy frequency] [enemy frequency max.inc] [next lvl] ; [level_info: 0000:damage 0:diagfire 0:ground 0:ceiling 0:?] -; [level_move] [tunnel size] [groundtype] -; [16_ground] [16_ceiling] [stars1] [stars2] +; [level_move] [tunnel size] [groundtype] [stars1] [stars2] ;efrequency must be odd if halfluring! -level00: - .db 0 ;story identifier - .db $21,$1d,"Cosmic year 6716" ,0,0,$1d,$06 - .db $1b,$1d,"STORYLINE COMING SOON" ,0,0,$1d,$06 - .db $09,$19,"STORYLINE COMING SOON" ,0,1 - .db $2e,$21,"**** NEMESIS 86" ,0,1 - .db $52,$36,"by Shiar" ,0,0,$19,$23 - .db $ff ;story end + .db 0 ;storyline ID +level00: ;[y-pos] [x-pos] [text,0] [SFX lines; 0=more text] [-1=end] + .db 25,33,"Imperial ships have",0,0 + .db 31,9,"been sent to intercept you",0,31-25+6,-1 .db 20 ;boss for level01 level01: ;intro-like, just a few enemies to begin with .db 2,6,8 .db 26,70,20,%00010000,0,0,0 - .db 1,2,3,4,5,6,6,5,4,3,4,5,4,5,6,5 - .db 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 .db 1,1 .db 21 level02: ;first wave of enemies; easeey .db 3,6,7,8 .db 20,60,60,%00100000,0,0,0 - .db 1,2,3,4,5,6,6,5,4,3,4,5,4,5,6,5 - .db 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 .db 1,1 .db 22 level03: ;some more enemies .db 4,7,8,9,10 .db 17,40,75,%00110000,0,0,0 - .db 1,2,3,4,5,6,6,5,4,3,4,5,4,5,6,5 - .db 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 .db 1,1 - .db 0,0 ;storyline ID + .db 0 .db 1,1,"Long-Range scanners are ", - .db "showing",0,1 - .db 1,8,"lots of enemy vessels on ", - .db "an intercept",0,1 - .db 1,15,"course.",0,1 - .db 1,24,"I'm changing course to a", - .db " nearby ",0,1 - .db 1,31,"asteroid belt and try to",0,1 - .db 1,38,"lose them inthere.",0,0 - .db 1,38+5,$FF + .db "showing",0,0 + .db 8,1,"lots of enemy vessels ", + .db "advancing fast.",0,8-1+6 + .db 24,1,"I'm changing course to a", + .db " nearby ",0,0 + .db 31,1,"asteroid belt and try to",0,0 + .db 38,1,"lose them inthere.",0,38-24+6,-1 .db 23 -level04: ;light asteroid belt - .db 3,1,2,4 +level04: ;approaching asteroid belt + .db 7,11,11,12,12,13,1,2 .db 12,24,80,%00111000 - .db 2,0,0 - .db 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 ;16 - .db 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 - .db 1,1 + .db 2,0,0,1,1 .db 24 -level05: ;inside asteroid belt - .db 5,1,2,3,4,5 - .db 6,10,180,%01011000 - .db 2,0,0 - .db 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 ;16 - .db 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 - .db 1,1 +level05: ;light asteroid belt + .db 5,11,12,1,2,4 + .db 12,24,80,%00111000 + .db 2,0,0,1,1 .db 25 -level02a: - .db 3,4,5,6 - .db 30,1,40,%01000000 - .db 0,0,0 - .db 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 ;16 - .db 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 - .db 1,1 +level06: ;inside asteroid belt + .db 6,13,1,2,3,4,5 + .db 7,18,180,%01011000 + .db 2,0,0,1,1 - .db 0 + .db 0,1,1,"That's it for now...",0,5,-1 + +endlevel = 6 .db 0 - .db $01,01,"And the storyline conti", - .db "nues.....",0,1 - .db $01,09,"You decide to fly close", - .db " to the",0,1 - .db $01,15,"surface of a nearby pl", - .db "anet =)",0,0,1,20 - .db $FF + .db 1,1,"And the storyline conti", + .db "nues.....",0,5 + .db 9,1,"You decide to fly close", + .db " to the",0,0 + .db 15,1,"surface of a nearby pl", + .db "anet =)",0,15-9+6,-1 .db 26 level03b: - .db 1,$02 + .db 1,2 .db $13,40,$4b,%00100100,0,-5,1 - .db 1,2,3,4,5,6,6,5,4,3,4,5,4,5,6,5 - .db 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 .db 1,1 .db 0 @@ -3563,39 +3506,29 @@ level03b: .db 27 level03a: .db 1,$03 - .db $2d,$3f,%00010110,0,-9,1 - .db 3,2,4,3,2,2,1,1,1,1 ,1,1,21,17,18,20 - .db 1,1,1,1,1,1,1,3,6,12,9,1,21,19,18,18 + .db $2d,$3f,%00110110,0,-9,1 .db -1,-1 ;=%11111111=line .db $07,$08 level04b: .db 1,$04 .db $11,$41,%00100001,0,0,0 - .db 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 - .db 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 .db 1,1 .db $07,$09 level05a: .db 1,$05 .db $11,$45,%00100101,%10,-7,1 - .db 14,12,11,9,10,7,7,5,4,3,4,4,2,3,1,2 - .db 1, 1, 1, 1,1, 1,1,1,1,1,1,1,1,1,1,1 .db 1,1 .db $07,$08 level06c: .db 1,$06 .db $19,$3a,%00100111,0,-4,1 - .db 20,22,18,15,9,1,1,1,1,1,1,1,1,1,1,1 - .db 20,22,18,15,9,1,1,1,1,1,1,1,1,1,1,1 .db 1,1 .db $07,$09 level07: .db 1,$07 .db $09,$ff,%00100001,0,0,0 - .db 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 - .db 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 .db 1,1 ;------------------------------ enemies ------------------------------------- @@ -3605,7 +3538,7 @@ level07: ;appearances: 1=random; 2=lure; 3=halflure ;case movetype: ; 1=updown; 2=1/4x; 3=1/2x; 4=1.5x; 5=2x; 6=smart; 7=y-lure; -; 8=y-lure 1/2x; 9=8 stop at x=99; 10=x+y-lure 1/2x +; 8=y-lure 1/2x; 9=x; 10=x+y-lure 1/2x enemyspecs: ;1-5=asteroids .db 0,%00100110,(spr_enemyA1-spr_enemy00)/2,128,1,0,0,0 @@ -3618,28 +3551,29 @@ enemyspecs: .db 0,%00110010,(spr_enemyE4-spr_enemy00)/2,128,1,3,6,50 ;slow .db 0,%00100110,(spr_enemyE2-spr_enemy00)/2,128,1,0,1,0 .db 0,%00101110,(spr_enemyE3-spr_enemy00)/2,128,3,0,19,39 - .db 0,%00101010,(spr_enemyE5-spr_enemy00)/2,128,3,4,1,0 ;fast -;11=jumping bug (up/down) - .db 0,%00001111,(spr_enemyN3-spr_enemy00)/2,128,2,1,87,5 + .db 0,%00101010,(spr_enemyE5-spr_enemy00)/2,128,3,4,1,0 ;fast +;11-12=backwards + .db 0,%00011110,(spr_enemyB1-spr_enemy00)/2,0,3,11,19,92 + .db 0,%00101110,(spr_enemyB2-spr_enemy00)/2,0,1,12,11,45 + .db 0,%00110110,(spr_enemyB3-spr_enemy00)/2,0,1,11,10,41 ;small - .db 0,%00000011,(spr_enemy00-spr_enemy00)/2,1,0,0,0,0 ;12 - .db 0,%00000011,(spr_enemy00-spr_enemy00)/2,1,0,0,0,0 ;13 - .db 0,%00000011,(spr_enemy00-spr_enemy00)/2,1,0,0,0,0 ;14 + .db 0,%00001111,(spr_enemyN3-spr_enemy00)/2,128,2,1,87,5 .db 0,%00000011,(spr_enemy00-spr_enemy00)/2,1,0,0,0,0 ;15 .db 0,%00000011,(spr_enemy00-spr_enemy00)/2,1,0,0,0,0 ;16 .db 0,%00000011,(spr_enemy00-spr_enemy00)/2,1,0,0,0,0 ;17 .db 0,%00000011,(spr_enemy00-spr_enemy00)/2,1,0,0,0,0 ;18 .db 0,%00000011,(spr_enemy00-spr_enemy00)/2,1,0,0,0,0 ;19 -;20-22=first bosses - .db 1,%00101011,(spr_boss0_1-spr_enemy00)/2,127,1,8,20,12 ;20 - .db 1,%00110011,(spr_boss0_1-spr_enemy00)/2,127,1,8,15,10 ;21 - .db 1,%01001011,(spr_boss0_2-spr_enemy00)/2,127,3,9,10,9 ;22 -;23-24=asteroid bosses - .db 2,%00001011,(spr_boss0_3-spr_enemy00)/2,127,1,10,36,14 - .db 2,%00110011,(spr_boss0_3-spr_enemy00)/2,127,2,10,28,12 -;25-26=big bosses - .db 2,%00000111,(spr_boss0_4-spr_enemy00)/2,127,3,7,18,7 ;25=bigboss1 - .db 2,%01001011,(spr_boss0_5-spr_enemy00)/2,127,3,7,18,7 ;26=bigboss2 +;20-23=first bosses + .db 1,%00101011,(spr_boss2-spr_enemy00)/2,127,1,8,20,12 ;small + .db 1,%00110011,(spr_boss1-spr_enemy00)/2,127,1,8,15,10 + .db 1,%01001011,(spr_boss1-spr_enemy00)/2,127,3,10,10,9 + .db 0,%11111111,(spr_boss3-spr_enemy00)/2,127,3,10,1,4 ;weak+rapidfire +;24-25=asteroid bosses + .db 2,%00001011,(spr_bossA1-spr_enemy00)/2,127,1,10,36,14 + .db 2,%00110011,(spr_bossA1-spr_enemy00)/2,127,2,10,28,12 +;26-27=big bosses + .db 2,%00000111,(spr_boss4-spr_enemy00)/2,127,3,7,18,7 + .db 2,%01001011,(spr_boss5-spr_enemy00)/2,127,3,7,18,7 spr_enemy00: .db 16,8 ;pickup @@ -3744,6 +3678,35 @@ spr_enemyE5: .db %01111000 ; ████ .db %00011100 ; ███ +spr_enemyB1: + .db 6,6 ;solid backwards + .db %11110000 ;████ + .db %00101000 ; █ █ + .db %01010100 ; █ █ █ + .db %01010100 ; █ █ █ + .db %00101000 ; █ █ + .db %11110000 ;████ +spr_enemyB2: + .db 6,7 + .db %11110000 ;████ + .db %01001000 ; █ █ + .db %01110100 ; ███ █ + .db %00100100 ; █ █ + .db %01110100 ; ███ █ + .db %01001000 ; █ █ + .db %11110000 ;████ + .db 0 +spr_enemyB3: + .db 5,7 + .db %11100000 ;███ + .db %01010000 ; █ █ + .db %01111000 ; ████ + .db %01000000 ; █ + .db %01111000 ; ████ + .db %01010000 ; █ █ + .db %11100000 ;███ + .db 0 + spr_enemyG1: .db 8,6 ;G-Type .db %00111111 ; █████ @@ -3777,7 +3740,7 @@ spr_enemyG4: .db %01111000 ; ████ .db %00111111 ; █████ spr_enemyG5: - .db 6,6 ;G lost his head; large window ;) + .db 6,6 .db %01111100 ; █████ .db %10110000 ;█ ██ .db %10111000 ;█ ███ @@ -3785,7 +3748,7 @@ spr_enemyG5: .db %10110000 ;█ ██ .db %01111100 ; █████ spr_enemyG6: - .db 7,6 ;small G-type + .db 7,6 ;small G-type solid .db %00011110 ; ████ .db %01111000 ; ████ .db %11110000 ;████ @@ -3857,8 +3820,8 @@ spr_enemyN3: .db %10111110 ;█ █████ .db 0 -spr_boss0_1: - .db 16,10 ;boss type one..:.......: +spr_boss1: + .db 16,10 ;.......:.......: .db %00000001 ; ██████ ██ .db %00001110 ; ███ █ ███ .db %00110010 ; ██ █ ████ @@ -3881,14 +3844,40 @@ spr_boss0_1: .db %00101110 .db %11111011 .db 0 -spr_boss0_2: - .db 16,10 ;boss type two..:.......: +spr_boss2: + .db 12,12 ;.......:....5..: + .db %00011110 ; ████ + .db %01100001 ; ██ ██ + .db %10110010 ;█ ██ █ ██ + .db %00000101 ; █ ██ █ + .db %00001010 ; █ █ ██ + .db %00011010 ; ██ █ █ █ + .db %00011010 ; ██ █ █ █ + .db %00001010 ; █ █ ██ + .db %00000101 ; █ ██ █ + .db %10110010 ;█ ██ █ ██ + .db %01100001 ; ██ ██ + .db %00011110 ; ████ + .db 11 + .db %00000000 + .db %10000000 + .db %01100000 + .db %10100000 + .db %01100000 + .db %10010000 + .db %10010000 + .db %01100000 + .db %10100000 + .db %01100000 + .db %10000000 +spr_boss3: + .db 16,10 ;.......:.......: .db %11111110 ;███████ .db %00000011 ; ███ ████ .db %00110101 ; ██ █ ████ █ .db %01111010 ; ████ █ █ █ ██ - .db %10001101 ;█ ██ █ ██ ██ - .db %10001101 ;█ ██ █ ██ ██ + .db %10001101 ;█ ██ █ ██ ██ █ + .db %10001101 ;█ ██ █ ██ ██ █ .db %01111010 ; ████ █ █ █ ██ .db %00110101 ; ██ █ ████ █ .db %00000011 ; ███ ████ @@ -3898,12 +3887,12 @@ spr_boss0_2: .db %10001111 .db %11100001 .db %10010110 - .db %01101100 - .db %01101100 + .db %01101101 + .db %01101101 .db %10010110 .db %11100001 .db %10001111 -spr_boss0_3: +spr_bossA1: .db 16,11 ;bigasteroid one .db %00011110 ; ████ .db %01110011 ; ███ ███ @@ -3927,7 +3916,7 @@ spr_boss0_3: .db %11110000 .db %11000000 .db 0 -spr_boss0_4: +spr_boss4: .db 16,18 ;bigboss one : .db %00000000 ; █ █ .db %00000111 ; ███ ███ @@ -3967,7 +3956,7 @@ spr_boss0_4: .db %11010000 .db %01110000 .db %01010000 -spr_boss0_5: +spr_boss5: .db 16,15 ;bigboss two : .db %00001111 ; █████ .db %00111110 ; █████ █████ @@ -4113,6 +4102,9 @@ logo_nemesis: ; 0.99.79 -- 9.VII.00 -- size 6747 ; ; + you can have upto FOUR multiples! (~20 pixels apart) +; * some optimizations: keycall, menu handling, port nops removed, +; more SMC, fire handling, fast bullet handling, enemy movement +; * better "backwards" enemies handling (and implemented in game) ; ; + added - removed * changed # bug fixed -- 2.30.0