; Space Invaders ; Disassembly comments by Chris Cantrell 2010 ; See http://www.computerarcheology.com for discussion. ; It is never completely finished! ; TODO Look at the various versions of the ROMs and see what's different ; TODO Check all X/Y references and make Xr/Yr or Xn/Yn ;##- ;##- Machine info ;##- ;##$ CPU 8080 as Z80 ;##$ PrintSpacing 12 25 ;##$ OriginalBinary invaders.h+invaders.g+invaders.f+invaders.e ;##- ;##$ ROM 0000-1FFF ;##$ RAM 2000-3FFF ;##- Screen from 2400 to 3FFF ;##- ;##- ;##- Menu structure for CodeToWeb HTML generator ;##- ;##Menu 2 "Game Info" ;##MenuLink RAM "RAM usage" ;##MenuLink Hardware "Hardware/machine info" ;##- ;##Menu 3 "Code" ;##MenuLink CodeBug1 "Bug in the code" ;##MenuLink CheckHiddenMes "Hidden message Easter egg" ;##MenuLink Reset "Program Entry" ;##MenuLink ScanLine96 "ISR called at mid-screen update" ;##MenuLink ScanLine224 "ISR called at end-screen update" ;##MenuLink RunGameObjs "Run all game objects" ;##MenuLink GameObj0 "Move/draw the player" ;##MenuLink GameObj1 "Move/draw the player shot" ;##MenuLink GameObj2 "Allien rolling-shot (targets player)" ;##MenuLink GameObj3 "Alien plunger-shot" ;##MenuLink GameObj4 "Flying Saucer OR squiggly shot" ;##MenuLink NewGame "Start of a new game" ;##MenuLink DrawShiftedSprite "Draw a shifted sprite" ;##MenuLink EraseShifted "Erase a shifted sprite" ;##MenuLink CheckHandleTilt "Check/handle TILT" ;##- ;##Menu 2 "Data" ;##MenuLink DemoCommands "Demo movement commands" ;##MenuLink AShotReloadRate "Alien shot rate map values" ;##MenuLink AReloadScoreTab "Alien shot rate map keys" ;##MenuLink ColFireTable "'Column Firing' table" ;##MenuLink SaucerScrTab "Saucer score table" ;##MenuLink SaucSoreStr "Saucer score strings" ;##MenuLink AlienScores "Alien score per type" ;##MenuLink AlienStartTable "Alien starting coordinate table" ;##MenuLink AlienScoreTable "Printing info for alien score" ;##MenuLink CreditTable "Printing info for credits" ;##- ;##Menu 2 "Images" ;##MenuLink PlayerShotSpr "Player shot (1 image)" ;##MenuLink SquiglyShot "'Squiggly' alien shot" ;##MenuLink PlungerShot "'Plunger' alien shot" ;##MenuLink RollShot "'Rolling' alien shot" ;##MenuLink ShotExploding "Player shot exploding (1 image)" ;##MenuLink ShieldImage "Player Shield" ;##MenuLink AlienSprA "Aliens (2 images each) 1st picture" ;##MenuLink AlienSprB "Aliens (2 images each) 2nd picture" ;##MenuLink PlayerSprite "Player sprite (2 images)" ;##MenuLink SpriteSaucer "Flying saucer (1 image)" ;##MenuLink PlrBlowupSprites "Player exploding (2 images)" ;##MenuLink AShotExplo "Alien shot exploding (1 image)" ;##MenuLink AlienExplode "Alien exploding (1 image)" ;##MenuLink SpriteSaucerExp "Saucer exploding (1 image)" ;##MenuLink AlienSprCYA "Alien pulling upside down Y (1st of 2)" ;##MenuLink AlienSprCYB "Alien pulling upside down Y (2nd of 2)" ;##MenuLink AlienSprCA "Alien pushing Y (1st of 2)" ;##MenuLink AlienSprCB "Alien pushing Y (2nd of 2)" ;##MenuLink Characters "Character font (8x8 * 64 characters)" ;##- ;##Menu 2 "Messages" ;##MenuLink MessageInvaders "'SPACE INVADERS'" ;##MenuLink MessageCoin "'INSERT COIN'" ;##MenuLink MessagePush "'PUSH '" ;##MenuLink MessagePlayUY "'PLAy' with upside down Y" ;##MenuLink MessagePlayY "'PLAY' with normal Y" ;##MenuLink Message1Only "'ONLY 1PLAYER BUTTON '" ;##MenuLink MessageB1or2 "'1 OR 2PLAYERS BUTTON'" ;##MenuLink MessageP1or2 "'<1 OR 2 PLAYERS> '" ;##MenuLink MessageAdv "'*SCORE ADVANCE TABLE*'" ;##MenuLink MessageMyst "'=? MYSTERY'" ;##MenuLink Message10Pts "'=10 POINTS'" ;##MenuLink Message20Pts "'=20 POINTS'" ;##MenuLink Message30Pts "'=30 POINTS'" ;##MenuLink MessageCredit "'CREDIT '" ;##MenuLink Message1Coin "'*1 PLAYER 1 COIN '" ;##MenuLink Message2Coins "'*2 PLAYERS 2 COINS'" ;##MenuLink MessageTilt "'TILT'" ;##MenuLink MesssageP1 "'PLAY PLAYER<1>'" ;##MenuLink MessageGOver "'GAME OVER PLAYER< >'" ;##MenuLink MessageScore "' SCORE<1> HI-SCORE SCORE<2>'" ;##MenuLink MessageTaito "'*TAITO CORPORATION*'" ;##MenuLink MessageCorp "'*TAITO COP*'" ; A word on coordinates. Sometimes the code is easier to understand in the context of the screen ; in standard (no rotated) position. The comments will refer to Xn (X not-rotated) and Yn. Sometimes ; the code is easier to understand in the context of the rotated screen. The comments will ; refer to Xr (X rotated) and Yr. ; ; Some of the early comments in this dig may switch back and forth without the "r/n" notation. Be suspect ; of those. ;##RAM ;##+2000 waitOnDraw (1B00:01) Cleared by alien-draw and set by next-alien. This ensures no alien gets missed while drawing. @ >0137 <0146 >0176 ; +2001 unused2001 (1B01:00) ;##+2002 alienIsExploding (1B02:00) Not-0 if an alien is exploding, 0 if not exploting @ <0103 >0426 <14EA >154B ;##+2003 expAlienTimer (1B03:10) Time (ISR ticks) left in alien-explosion @ >152C <153B >153B ;##+2004 alienRow (1B04:00) Row number of current alien (cursor) @ <0119 >0171 ;##+2005 alienFrame (1B05:00) Animation frame number (0 or 1) for current alien (cursor) @ <011B <01B4 >01B8 ;##+2006 alienCurIndex (1B06:00) Alien cursor index (from 0 to 54) @ <0109 <014F >0160 >01A8 ;##+2007 refAlienDYr (1B07:00) Reference alien delta Yr @ <01AB >01AC >15B3 ;##+2008 refAlienDXr (1B08:02) Reference alien deltaXr @ >00C8 <01DA <0878 >15AD ;##+2009 refAlienYr (1B09:78) Reference alien Yr coordinate @ >00B9 <0180 <01DD >01DE <087C <0913 <14F8 <1562 ;##+200A refAlienXr (1B0A:38) Reference alien Xr coordinate @ >00B9 <0182 <01E1 >01E2 <087C <156F ;##+200B alienPosLSB (1B0B:78) Alien cursor bit pos (LSB) @ >00BC <012E >0167 ;##+200C alienPosMSB (1B0C:38) Alien cursor bit pos (MSB) @ >00BC <012E >0167 ;##+200D rackDirection (1B0D:00) Value 0 if rack is moving right or 1 if rack is moving left @ >00D3 <1597 >15A9 ;##+200E rackDownDelta (1B0E:F8) Constant value of alien rack dropping after bumping screen edge @ <15B0 ; +200F unused200F (1B0F:00) ; GameObject0 (Move/draw the player) ; ;##+2010 obj0TimerMSB (1B10:00) @ <024B >0280 <1621 ;##+2011 obj0TimerLSB (1B11:80) Wait 128 interrupts (about 2 secs) before player task starts @ <0255 >027E >0319 <1623 ;##+2012 obj0TimerExtra (1B12:00) @ <025D >037D ;##+2013 obj0HanlderLSB (1B13:8E) @ <0263 ;##+2014 oBJ0HanlderMSB (1B14:02) Player handler code at 028E @ <0265 ; ;##+2015 playerAlive (1B15:FF) Player is alive (FF=alive). Toggles between 0 and 1 for blow-up images. @ <0290 >039E >060F <0A59 <1618 *16EB ;##+2016 expAnimateTimer (1B16:05) Time till next blow-up sprite change (reloaded to 5) @ <0297 >0297 >02A7 ;##+2017 expAnimateCnt (1B17:0C) Number of changes left in blow-up sequence @ <02AA >02AA ;##+2018 plyrSprPicL (1B18:60) Player sprite descriptor ... picture LSB @ >03AA <1A3B ;##+2019 plyrSprPicM (1B19:1C) Player sprite descriptor ... picture MSB @ >03AA <1A3D ;##+201A playerYr (1B1A:20) Player sprite descriptor ... location LSB @ <02AE <1A3F ;##+201B playerXr (1B1B:30) Player sprite descriptor ... location MSB @ <02AE <034A >0388 >0395 <03FC <061B <1A41 ;##+201C plyrSprSiz (1B1C:10) Player sprite descriptor ... size of sprite @ <1A43 ;##+201D nextDemoCmd (1B1D:01) Next movement command for demo @ <0355 >1667 ;##+201E hidMessSeq (1B1E:00) Set to 1 after 1st of 2 sequences are entered for hidden-message display @ <199A *19A9 ; +201F unused201F (1B1F:00) Appears to be unused ; GameObject1 (Move/draw the player shot) ; ;##+2020 obj1TimerMSB (1B20:00) @ <024B ;##+2021 obj1TimerLSB (1B21:00) @ <0255 ;##+2022 obj1TimerExtra (1B22:00) All 0's ... run immediately @ <025D ;##+2023 obj1HandlerLSB (1B23:BB) @ <0263 ;##+2024 obj1HandlerMSB (1B24:03) Shot handler code at 03BB @ <0265 ; ;##+2025 plyrShotStatus (1B25:00) 0 if available, 1 if just initiated, 2 moving normally, 3 hit something besides alien, 5 if alien explosion is in progress, 4 if alien has exploded (remove from active duty) @ <03C4 >03FB >0B80 <14D8 >1514 >1532 >1547 <1626 >1641 >1655 <172C ;##+2026 blowUpTimer (1B26:10) Sprite blow-up timer @ <03D7 >03D7 <03DB ;##+2027 obj1ImageLSB (1B27:90) @ <03E8 >03E8 <1A3B ;##+2028 obj1ImageMSB (1B28:1C) Sprite image at 1C90 (just one byte) @ <1A3D ;##+2029 obj1CoorYr (1B29:28) Player shot Y coordinate @ <03EB >03EB <03EC >03EC >041B <14E1 <1A3F ;##+202A obj1CoorXr (1B2A:30) Player shot X coordinate @ <03EE >03EE <03EF >03EF <03F0 >03F0 >0401 <1508 <1A0A <1A41 ;##+202B obj1ImageSize (1B2B:01) Size of shot image (just one byte) @ >03F2 <1A43 ;##+202C shotDeltaX (1B2C:04) Shot's delta X @ <0416 ;##+202D fireBounce (1B2D:00) 1 if button has been handled but remains down @ <1632 >1644 >164E ; +202E unused202E (1B2E:FF) ; +202F unused202F (1B2F:FF) ; GameObject2 (Alien rolling-shot) ; ;##+2030 obj2TimerMSB (1B30:00) @ <024B ;##+2031 obj2TimerLSB (1B31:00) @ <0255 ;##+2032 obj2TimerExtra (1B32:02) GO-3 runs when this is 1. GO-4 runs when this is 2. (copied to 2080 in game loop)@ <0072 <025D <0288 >0288 >047A ;##+2033 obj2HandlerLSB (1B33:76) @ <0263 ;##+2034 obj2HandlerMSB (1B34:04) Handler code at 0476 @ <0265 ;Rolling-alien-shot data structure ;##+2035 rolShotStatus (1B35:00) ;##+2036 rolShotStepCnt (1B36:00) @ <04CA <051D ;##+2037 rolShotTrack (1B37:00) A 0 means this shot tracks the player ;##+2038 rolShotCFirLSB (1B38:00) Pointer to column-firing table LSB (not used for targeting) @ <047D >0486 ;##+2039 rolShotCFirMSB (1B39:00) Pointer to column-firing table MSB (not used for MSB counter @ <047D >0486 ;##+203A rolShotBlowCnt (1B3A:04) ;##+203B rolShotImageLSB (1B3B:EE) ;##+203C rolShotImageMSB (1B3C:1C) ;##+203D rolShotYr (1B3D:00) ;##+203E rolShotXr (1B3E:00) ;##+203F rolShotSize (1B3F:03) ; GameObject3 (Alien plunger-shot) ; ;##+2040 obj3TimerMSB (1B40:00) @ <024B ;##+2041 obj3TimerLSB (1B41:00) @ <0255 ;##+2042 obj3TimerExtra (1B42:00) @ <025D ;##+2043 obj3HandlerLSB (1B43:B6) @ <0263 ;##+2044 obj3HandlerMSB (1B44:04) Handler code at 04B6 @ <0265 ;Plunger-alien-shot data structure ;##+2045 pluShotStatus (1B45:00) ;##+2046 pluShotStepCnt (1B46:00) @ <0492 <0517 ;##+2047 pluShotTrack (1B47:01) A 1 means this shot does not track the player ;##+2048 pluShotCFirLSB (1B48:00) Pointer to column-firing table LSB @ >067E ;##+2049 pluShotCFirMSB (1B49:1D) Pointer to column-firing table MSB @ >067E ;##+204A pluShotBlowCnt (1B4A:04) ;##+204B pluShotImageLSB (1B4B:E2) ;##+204C pluShotImageMSB (1B4C:1C) ;##+204D pluShotYr (1B4D:00) ;##+204E pluSHotXr (1B4E:00) ;##+204F pluShotSize (1B4F:03) ; GameObject4 (Flying saucer OR alien squiggly shot) ;##+2050 obj4TimerMSB (1B50:00) @ <024B >0280 ;##+2051 obj4TimerLSB (1B51:00) @ <0255 >027E ;##+2052 obj4TimerExtra (1B52:00) @ <025D ;##+2053 obj4HandlerLSB (1B53:82) @ <0263 ;##+2054 obj4HandlerMSB (1B54:06) Handler code at 0682 @ <0265 ;Squiggly-alien-shot data structure ;##+2055 squShotStatus (1B55:00) @ <18B8 <18C0 ;##+2056 squShotStepCnt (1B56:00) @ <0498 <04D0 <0691 ;##+2057 squShotTrack (1B57:01) A 1 means this shot does not track the player ;##+2058 squShotCFirLSB (1B58:06) Pointer to column-firing table LSB @ >054C ;##+2059 squShotCFirMSB (1B59:1D) Pointer to column-firing table MSB @ >054C ;##+205A squSHotBlowCnt (1B5A:04) ;##+205B squShotImageLSB (1B5B:D0) ;##+205C squShotImageMSB (1B5C:1C) ;##+205D squShotYr (1B5D:00) ;##+205E squShotXr (1B5E:00) ;##+205F squShotSize (1B5F:03) ;##+2060 endOfTasks (1B60:FF) FF marks the end of the tasks list @ <024B ;##+2061 collision (1B61:00) Set to 1 if sprite-draw detects collision @ <0421 <05FB >1495 >14A6 >14BA ;##+2062 expAlienLSB (1B62:C0) @ <1A3B ;##+2063 expAlienMSB (1B63:1C) Exploding alien picture 1CC0 @ <1A3D ;##+2064 expAlienYr (1B64:00) Y coordinate of exploding alien @ >150F <153D <1A3F ;##+2065 expAlienXr (1B65:00) X coordinate of exploding alien @ >150F <153D <1A41 ;##+2066 expAlienSize (1B66:10) Size of exploding alien sprite (16 bytes) @ <1A43 ;##+2067 playerDataMSB (1B67:21) Current player's data-pointer MSB (21xx or 22xx) @ <010D <014B <01BD <02ED >0312 <0630 <0807 <0886 <0898 <08C1 <09CA *09F9 *0A01 *0A04 <158B <1613 <16AE <17C0 <18E7 <1913 ;##+2068 playerOK (1B68:01) 1 means OK, 0 means blowing up @ <0141 >029B >033E <1747 ;##+2069 enableAlienFire (1B69:00) 1 means aliens can fire, 0 means not @ >029E <0341 >0348 <0571 ;##+206A alienFireDelay (1B6A:30) Count down till aliens can fire (2069 flag is then set) @ >02A3 <03B4 >03B4 ;##+206B oneAlien (1B6B:00) 1 when only one alien is on screen ;##+206C temp206C (1B6C:12) Holds the value ten ... number of characters in each "=xx POINTS" string but gets set to 18 in mem copy before game. @ >1822 <184D ;##+206D invaded (1B6D:00) Set to 1 when player blows up because rack has reached bottom @ <02C6 >1973 ;##+206E skipPlunger (1B6E:00) When there is only one alien left this goes to 1 to disable the plunger-shot when it ends @ <04B7 >0505 ; +206F unused206F (1B6F:00) ;##+2070 otherShot1 (1B70:0F) When processing a shot, this holds one of the other shot's info @ >0495 >04CD >051A <057C ;##+2071 otherShot2 (1B71:0B) When processing a shot, this holds one of the other shot's info @ >049B >04D3 >0520 <0589 ;##+2072 vblankStatus (1B72:00) 80=screen is being drawn (don't touch), 0=blanking in progress (ok to change) @ >0016 >008D <1A09 ; Alien shot information (copied from the 3 actual structures when processed) ;##+2073 aShotStatus (1B73:18) Bit 0 set if shot is blowing up, bit 7 set if active @ <0566 <05BA >05BD <05C9 <0612 >0617 ;##+2074 aShotStepCnt (1B74:26) Count of steps made by shot (used for fire reload rate) @ >057A <05BF >05BF <05D0 >05D0 ;##+2075 aShotTrack (1B75:0F) 0 if shot tracks player or 1 if it uses the column-fire table @ <0597 ;##+2076 aShotCFirLSB (1B76:0B) Pointer to column-firing table LSB @ <04D9 >04E4 <0508 <0526 >0531 <0549 <059C >05A2 ;##+2077 aShotCFirMSB (1B77:00) Pointer to column-firing table MSB @ <0508 <0549 <059C >05A2 ;##+2078 aShotBlowCnt (1B78:18) Alen shot blow up counter. At 3 the explosion is drawn. At 0 it is done. @ <04A1 <04E7 <0534 <0647 >0647 <0648 ;##+2079 aShotImageLSB (1B79:04) Alien shot image LSB @ <05D4 >05E2 >0654 <1A3B ;##+207A aShotImageMSB (1B7A:11) Alien shot image MSB @ >0654 <1A3D ;##+207B alienShotYr (1B7B:24) Alien shot delta Y @ >05B4 <05E5 >05ED <05F3 <0600 <065D >065D <065E >065E <1A3F ;##+207C alienShotXr (1B7C:1B) Alien shot delta X @ >05B4 <065A >065A <065B >065B <1A0A <1A41 ;##+207D alienShotSize (1B7D:25) Alien shot size @ >0661 <1A43 ;##+207E alienShotDelta (1B7E:FC) Alien shot speed. Normally -1 but set to -4 with less than 9 aliens @ <05E9 *08E0 >18B0 ;##+207F shotPicEnd (1B7F:00) the last picture in the current alien shot animation @ >0550 <05DC ;##+2080 shotSync (1B80:01) All 3 shots are synchronized to the GO-2 timer. This is copied from timer in the game loop @ >0075 <04BC <0683 >18AB ;##+2081 tmp2081 (1B81:FF) Used to hold the remember/restore flag in shield-copy routine @ >021E <022B ;##+2082 numAliens (1B82:FF) Number of aliens on screen @ <04FC <069E <082B <08D8 >1605 <1759 <1782 <18F3 ;##+2083 saucerStart (1B83:00) Flag to start saucer (set to 1 when 2091:2092 counts down to 0) @ <068C >0926 ;##+2084 saucerActive (1B84:00) Saucer is on screen (1 means yes) @ <045D <0699 >06A6 <1807 ;##+2085 saucerHit (1B85:00) Saucer has been hit (1 means draw it but don't move it) @ <06B5 *157B <180D ;##+2086 saucerHitTime (1B86:20) Hit-sequence timer (explosion drawn at 1F, score drawn at 18) @ ;##+2087 saucerPriLocLSB (1B87:64) Mystery ship print descriptor ... coordinate LSB @ *0729 *0759 <1A3B ;##+2088 saucerPriLocMSB (1B88:1D) Mystery ship print descriptor ... coordinate MSB @ <1A3D ;##+2089 saucerPriPicLSB (1B89:D0) Mystery ship print descriptor ... message LSB @ <1A3F ;##+208A saucerPriPicMSB (1B8A:29) Mystery ship print descriptor ... message MSB @ >0471 <06BD >06C1 <06CA <1A0A <1A41 ;##+208B saucerPriSize (1B8B:18) Mystery ship print descriptor ... number of characters @ <1A43 ;##+208C saucerDeltaY (1B8C:02) Mystery ship delta Y @ >0474 <06C0 ;##+208D sauScoreLSB (1B8D:54) Pointer into mystery-ship score table (MSB) @ <0447 >0453 *0711 ;##+208E sauScoreMSB (1B8E:1D) Pointer into mystery-ship score table (LSB) @ <0447 >0453 ;##+208F shotCountLSB (1B8F:00) Bumped every shot-removal. Saucer's direction is bit 0. (0=2/29, 1=-2/E0) @ <0456 >045A ;##+2090 shotCountMSB (1B90:08) Read as two-bytes with 208F, but never used as such. @ <0456 >045A ;##+2091 tillSaucerLSB (1B91:00) @ <0919 >092A ;##+2092 tillSaucerMSB (1B92:06) Count down every game loop. When it reaches 0 saucer is triggerd. Reset to 600. @ <0919 >092A ;##+2093 waitStartLoop (1B93:00) 1=in wait-for-start loop, 0=in splash screens @ <005D >0767 *17FE ;##+2094 soundPort3 (1B94:00) Current status of sound port (out $03) @ <18FA >18FE <19DC >19E0 ;##+2095 changeFleetSnd (1B95:01) Set to 1 in ISR if time to change the fleet sound @ >1765 <1775 >17A7 ;##+2096 fleetSndCnt (1B96:40) Delay until next fleet movement tone @ <1751 >1751 >1763 ;##+2097 fleetSndReload (1B97:00) Reload value for fleet sound counter @ <1761 >178F ;##+2098 soundPort5 (1B98:01) Current status of sound port (out $05) @ >0320 *0A27 <1756 <176D <1795 <1799 >17A5 ;##+2099 extraHold (1B99:00) Duration counter for extra-ship sound @ *0974 <17AD >17AD ;##+209A tilt (1B9A:00) 1 if tilt handling is in progress @ *17D2 *17E5 *17FB ;##+209B fleetSndHold (1B9B:10) Time to hold fleet-sound at each change @ <1743 >1743 >1769 ; +209C unused209C (1B9C:9E) ; +209D unused209D (1B9D:00) ; +209E unused209E (1B9E:20) ; +209F unused209F (1B9F:1C) ; This is the image of the alien sprite pulling the upside down Y. The code expects it to be 0030 below the ; second animation picture at 1BD0. This must be unused. The copy to RAM isn't used. ; ; +20A0 unused20A0 (1BA0:00) ; +20A1 unused20A1 (1BA1:03) ; +20A2 unused20A2 (1BA2:04) ; +20A3 unused20A3 (1BA3:78) ; +20A4 unused20A4 (1BA4:14) ; +20A5 unused20A5 (1BA5:13) ; +20A6 unused20A6 (1BA6:08) ; +20A7 unused20A7 (1BA7:1A) ; +20A8 unused20A8 (1BA8:3D) ; +20A9 unused20A9 (1BA9:68) ; +20AA unused20AA (1BAA:FC) ; +20AB unused20AB (1BAB:FC) ; +20AC unused20AC (1BAC:68) ; +20AD unused20AD (1BAD:3D) ; +20AE unused20AE (1BAE:1A) ; +20AF unused20AF (1BAF:00) ; +20B0 unused20B0 (1BB0:00) ; +20B1 unused20B1 (1BB1:00) ; +20B2 unused20B2 (1BB2:01) ; +20B3 unused20B3 (1BB3:B8) ; +20B4 unused20B4 (1BB4:98) ; +20B5 unused20B5 (1BB5:A0) ; +20B6 unused20B6 (1BB6:1B) ; +20B7 unused20B7 (1BB7:10) ; +20B8 unused20B8 (1BB8:FF) ; +20B9 unused20B9 (1BB9:00) ; +20BA unused20BA (1BBA:A0) ; +20BB unused20BB (1BBB:1B) ; +20BC unused20BC (1BBC:00) ; +20BD unused20BD (1BBD:00) ; +20BE unused20BE (1BBE:00) ; +20BF unused20BF (1BBF:00) ;--- End of inialization copy from ROM mirror ; These are copied once from ROM at startup (01E6). ; Splash screen animation structure ; ;##+20C0 isrDelay Delay counter decremented in ISR @ <001C >001C >08A6 <08A9 *0A44 *0A47 >0A9B <0A9E >0AD7 <0ADA ;##+20C1 isrSplashTask 1=In demo, 2=Little-alien and Y, 4=shooting extra 'C' @ <009E <056C >0801 >0A82 >0A8F <0ABF >0B6B >0B8A >18B5 >1982 ;##+20C2 splashAnForm Image form (increments each draw) @ <186B >186B <1879 ;##+20C3 splashDeltaX Delta X @ <186D ;##+20C4 splashDeltaY Delta Y @ <01DA ;##+20C5 splashYr Y coordinate @ <01DD >01DE <1A3B ;##+20C6 splashXr X coordinate @ <01E1 >01E2 <1A3D ;##+20C7 splashImageLSB @ >1888 <1A3F ;##+20C8 splashImageMSB Base image 1BA0 (small alien with upside down Y) @ >1888 <1A41 ;##+20C9 splashImageSize Size of image (16 bytes) @ <1A43 ;##+20CA splashTargetY Target Y coordinate @ <1872 ;##+20CB splashReached Reached target Y flag (1 when reached) @ <0A87 >189A ;##+20CC splashImRestLSB Base image for restore 1BA0 is small alien with upside down Y @ <187E ;##+20CD splashImRestMSB @ <187E ;##+20CE twoPlayers 1 for yes, 0 means 1 player @ <02E6 >079B <08E4 <1698 ;##+20CF aShotReloadRate Based on the MSB of the player's score ... how fast the aliens reload their shots @ <0584 <0591 >1728 >18E1 ; +20D0 unused20D0 ; This is where the alien-sprite-carying-the-Y ... ; +20D1 unused20D1 ; ... lives in ROM ; +20D2 unused20D2 ; +20D3 unused20D3 ; +20D4 unused20D4 ; +20D5 unused20D5 ; +20D6 unused20D6 ; +20D7 unused20D7 ; +20D8 unused20D8 ; +20D9 unused20D9 ; +20DA unused20DA ; +20DB unused20DB ; +20DC unused20DC ; +20DD unused20DD ; +20DE unused20DE ; +20DF unused20DF ; +20E0 unused20E0 ; +20E1 unused20E1 ; +20E2 unused20E2 ; +20E3 unused20E3 ; +20E4 unused20E4 ;##+20E5 player1Ex Extra ship has been awarded = 0 @ >07C5 <093A ;##+20E6 player2Ex Extra ship has been awarded = 0 @ >07C5 <093A ;##+20E7 player1Alive 1 if player is alive, 0 if dead (after last man) @ <02E1 >07C2 >1674 <16C1 ;##+20E8 player2Alive 1 if player is alive, 0 if dead (after last man) @ <02E1 >07C2 >1674 <16C1 ;##+20E9 suspendPlay (1BE9:01) 1=game things are moving, 0=game things are suspended @ <0042 <0090 *09F3 >19D3 ;##+20EA coinSwitch (1BEA:00) 1=switch down, 0=switch up (used to debounce coin switch) @ <0026 >003F >0069 ;##+20EB numCoins (1BEB:00) number of coin credits in BCD format (99 max) @ <002D >0038 <0050 <077F <079E >07A3 <1947 ;##+20EC splashAnimate (1BEC:01) 0 for animation during splash and 1 for not. This alternates after every cycle. @ <0AF6 <0B17 <0B9E <0BC6 <0BDD >0BE1 ;##+20ED demoCmdPtrLSB (1BED:74) pointer to demo commands LSB 1663 @ <1657 >1663 ;##+20EE demoCmdPtrMSB (1BEE:1F) pointer to demo commands MSB @ <1657 >1663 ;##+20EF gameMode (1BEF:00) 1=game running, 0=demo or splash screens @ <0049 <0097 <02CB <034E >07BF <0A5F <162B >16DB ; +20F0 unused20F0 (1BF0:80) ;##+20F1 adjustScore (1BF1:00) Set to 1 if score needs adjusting @ *070E <098B >0991 >0A7A ;##+20F2 scoreDeltaLSB (1BF2:00) Score adjustment (LSB) @ *0733 <0995 >0A78 ;##+20F3 scoreDeltaMSB (1BF3:00) Score adjustment (MSB) @ <0995 >0A75 ;##+20F4 HiScorL (1BF4:00) Hi-score descriptor ... value LSB @ <1681 >1690 <1931 ;##+20F5 HiScorM (1BF5:00) Hi-score descriptor ... value MSB @ <167D >1694 <1933 ;##+20F6 HiScorLoL (1BF6:1C) Hi-score descriptor ... location LSB @ <1935 ;##+20F7 HiScorLoM (1BF7:2F) Hi-score descriptor ... location MSB @ <1937 ;##+20F8 P1ScorL (1BF8:00) Hi-score descriptor ... value LSB @ >07AC <099A >099D <168B <168F <1931 ;##+20F9 P1ScorM (1BF9:00) Hi-score descriptor ... value MSB @ >07AC <094C <09A0 >09A3 <167E <1693 <1712 <1933 ;##+20FA P1ScorLoL (1BFA:1C) Hi-score descriptor ... location LSB @ <09A6 <1935 ;##+20FB P1ScorLoM (1BFB:27) Hi-score descriptor ... location MSB @ <09A8 <1937 ;##+20FC P2ScorL (1BFC:00) Hi-score descriptor ... value LSB @ >07AF <168B <1931 ;##+20FD P2ScorM (1BFD:00) Hi-score descriptor ... value MSB @ >07AF <094C <167E <1712 <1933 ;##+20FE P2ScorLoL (1BFE:1C) Hi-score descriptor ... location LSB @ <1935 ;##+20FF P2ScorLoM (1BFF:39) Hi-score descriptor ... location MSB @ <1937 ; Player 1 specific data ;2100 - 2136 Player 1 alien ship indicators (0=dead) 11*5 = 55 ;2137 - 2141 Unused 11 bytes (room for another row of aliens?) ;2142 - 21F1 Player 1 shields remembered between rounds 44 bytes * 4 shields ($B0 bytes) ;21F2 - 21FA Unused 9 bytes ; +21FB p1RefAlienDX Player 1 reference-alien delta X ; +21FC p1RefAlienY Player 1 reference-alien Y coordinate ; +21FD p1RefAlienX Player 1 reference-alien X coordiante ; +21FE p1RackCnt Player 1 rack-count (starts at 0 but get incremented to 1-8) ; +21FF p1ShipsRem Ships remaining after current dies ; Player 2 specific data ;2200 - 2236 Player 2 alien ship indicators (0=dead) 11*5 = 55 ;2237 - 2241 Unused 11 bytes (room for another row of aliens?) ;2242 - 22F1 Player 2 shields remembered between rounds 44 bytes * 4 shields ($B0 bytes) ;22F2 - 22FA Unused 9 bytes ; +22FB p2RefAlienDX Player 2 reference-alien delta X ; +22FC p2RefAlienYr Player 2 reference-alien Y coordinate ; +22FD p2RefAlienXr Player 2 reference-alien X coordiante ; +22FE p2RackCnt Player 2 rack-count (starts at 0 but get incremented to 1-8) ; +22FF p2ShipsRem Ships remiaing after current dies@ 07D7 ; In the emulator run the stack builds down through 23DE (23FF - 23DE). Roughly 16 levels. ;##Hardware ; Much of this comes from the comments in the MAME emulator. ; ; invaders.h 0000-07FF ; invaders.g 0800-0FFF ; invaders.f 1000-17FF ; invaders.e 1800-1FFF ; The mame/drivers/mw8080bw.c comments have the following information about the interrupts: ; The CPU's INT line is asserted via a D flip-flop at E3. ; The flip-flop is clocked by the expression (!(64V | !128V) | VBLANK). ; According to this, the LO to HI transition happens when the vertical ; sync chain is 0x80 and 0xda and VBLANK is 0 and 1, respectively. ; These correspond to lines 96 and 224 as displayed. ; The interrupt vector is provided by the expression: ; 0xc7 | (64V << 4) | (!64V << 3), giving 0xcf and 0xd7 for the vectors. ; The flip-flop, thus the INT line, is later cleared by the CPU via ; one of its memory access control signals. ; ; The value CF is RST 8 and D7 is RST 10. ; If I understand this right then the system gets RST 8 when the beam is *near* the ; middle of the screen and RST 10 when it is at the end (start of VBLANK). ; Video = 256x * 224y @60Hz vertical ; Video hardware 7168 bytes lbpp bitmap (32 bytes per scanline) ;0000-1FFF 8K ROM ;2000-23FF 1K RAM ;2400-3FFF 7K Video RAM ;4000- RAM mirror ;I/O ports: ;read: ;00 INPUTS (Mapped in hardware but never used by the code) ;01 INPUTS ;02 INPUTS ;03 bit shift register read ;write: ;02 shift amount (3 bits) ;03 sound bits ;04 shift data ;05 sound bits ;06 watch-dog ;07 * See below ; Dedicated shift hardware goes like this: ; Write LSB of 16bit value to port 4 ; Write MSB of 16bit value to port 4 ; Write left-shift-amount to port 2 ; Read port 3 returns the upper byte of the 16bit value ; after it has been shifted left N bits ;Space Invaders ;-------------- ;Input: ;Port 0 ; bit 0 DIP4 (Cocktail request?) ; bit 1 Always 1 ; bit 2 Always 1 ; bit 3 Always 1 ; bit 4 Fire ; bit 5 Left ; bit 6 Right ; bit 7 * See below ;Port 1 ; bit 0 = CREDIT (1 if deposit) ; bit 1 = 2P start (1 if pressed) ; bit 2 = 1P start (1 if pressed) ; bit 3 = Always 1 ; bit 4 = 1P shot (1 if pressed) ; bit 5 = 1P left (1 if pressed) ; bit 6 = 1P right (1 if pressed) ; bit 7 = Not connected ;Port 2 ; bit 0 = DIP3 00 = 3 ships 10 = 5 ships ; bit 1 = DIP5 01 = 4 ships 11 = 6 ships ; bit 2 = Tilt ; bit 3 = DIP6 0 = extra ship at 1500, 1 = extra ship at 1000 ; bit 4 = P2 shot (1 if pressed) ; bit 5 = P2 left (1 if pressed) ; bit 6 = P2 right (1 if pressed) ; bit 7 = DIP7 Coin info displayed in demo screen 0=ON ; Port 3 ; bit 0-7 Shift register data ; ; Output ;Port 2: ; bit 0,1,2 Shift amount ;Port 3: ; bit 0=UFO (repeats) SX0 0.raw ; bit 1=Shot SX1 1.raw ; bit 2=Flash (player die) SX2 2.raw ; bit 3=Invader die SX3 3.raw ; bit 4=Extended play SX4 ; bit 5= AMP enable SX5 ; bit 6= NC (not wired) ; bit 7= NC (not wired) ;Port 4: ; bit 0-7 shift data (LSB on 1st write, MSB on 2nd) ;Port 5: ; bit 0=Fleet movement 1 SX6 4.raw ; bit 1=Fleet movement 2 SX7 5.raw ; bit 2=Fleet movement 3 SX8 6.raw ; bit 3=Fleet movement 4 SX9 7.raw ; bit 4=UFO Hit SX10 8.raw ; bit 5= NC (Cocktail mode control ... to flip screen) ; bit 6= NC (not wired) ; bit 7= NC (not wired) ; ;Port 6: ; Watchdog ... read or write to reset ;16 bit shift register: ; f 0 bit ; xxxxxxxxyyyyyyyy ; ; Writing to port 4 shifts x into y, and the new value into x, eg. ; $0000, ; write $aa -> $aa00, ; write $ff -> $ffaa, ; write $12 -> $12ff, .. ; ; Writing to port 2 (bits 0,1,2) sets the offset for the 8 bit result, eg. ; offset 0: ; rrrrrrrr result=xxxxxxxx ; xxxxxxxxyyyyyyyy ; ; offset 2: ; rrrrrrrr result=xxxxxxyy ; xxxxxxxxyyyyyyyy ; ; offset 7: ; rrrrrrrr result=xyyyyyyy ; xxxxxxxxyyyyyyyy ; ; Reading from port 3 returns said result. ; Screen Geometry ; 2400 - 3FFF (1C00 bytes = 256 * 28) 28*8=224. Screen is 256x224 pixels. ; Screen layout. Take this map and rotate it counter clockwise once. Thus the first ; byte is lower left. First "row" ends upper left. Last byte is upper right. ; ; ; 2400 2401 2402 .... 241F ; 01234567 01234567 01234567 .... 01234567 ; ; 2420 2421 2422 .... 243F ; 01234567 01234567 01234567 .... 01234567 ; ; . . ; . . ; . . ; . . ; ; 3FE0 3FE1 3FE2 .... 3FFF ; 01234567 01234567 01234567 .... 01234567 ;##Reset 0000: 00 NOP ; %% Interesting. Why waste the ... 0001: 00 NOP ; ... CPU cycles with NOPs ? ... 0002: 00 NOP ; ... Slot for jump in development? 0003: C3 D4 18 JP $18D4 ; Continue startup at 18D4 0006: 00 00 ; Padding before fixed ISR address ;##ScanLine96 ; Interrupt brings us here when the beam is *near* the middle of the screen. The real middle ; would be 224/2 = 112. The code pretends this interrupt happesn at line 128. ; 0008: F5 PUSH AF ; Save ... 0009: C5 PUSH BC ; ... 000A: D5 PUSH DE ; ... 000B: E5 PUSH HL ; ... everything 000C: C3 8C 00 JP $008C ; Continue ISR at 8C 000F: 00 ; Padding before fixed ISR address ;##ScanLine224 ; Interrupt brings us here when the beam is at the end of the screen (line 224) when ; the VBLANK begins. ; 0010: F5 PUSH AF ; Save ... 0011: C5 PUSH BC ; ... 0012: D5 PUSH DE ; ... 0013: E5 PUSH HL ; ... everything 0014: 3E 80 LD A,$80 ; Flag that tells objects ... 0016: 32 72 20 LD ($2072),A ; ... on the lower half of the screen to draw/move 0019: 21 C0 20 LD HL,$20C0 ; Decrement ... 001C: 35 DEC (HL) ; ... the general countdown (used for pauses) 001D: CD CD 17 CALL $17CD ; Check and handle TILT 0020: DB 01 IN A,($01) ; Read coin switch 0022: 0F RRCA ; Has a coin been deposited (bit 0)? 0023: DA 67 00 JP C,$0067 ; Yes ... note that switch is closed and continue at 3F with A=1 0026: 3A EA 20 LD A,($20EA) ; Switch is now open. Was it ... 0029: A7 AND A ; ... closed last time? 002A: CA 42 00 JP Z,$0042 ; No ... skip registering the credit ; ; Handle bumping credit count 002D: 3A EB 20 LD A,($20EB) ; Number of credits in BCD 0030: FE 99 CP $99 ; 99 credits already? 0032: CA 3E 00 JP Z,$003E ; Yes ... ignore this (better than rolling over to 00) 0035: C6 01 ADD A,$01 ; Bump number of credits 0037: 27 DAA ; Make it binary coded decimal 0038: 32 EB 20 LD ($20EB),A ; New number of credits 003B: CD 47 19 CALL $1947 ; Draw credits on screen 003E: AF XOR A ; Credit switch ... 003F: 32 EA 20 LD ($20EA),A ; ... has opened ; 0042: 3A E9 20 LD A,($20E9) ; Are we moving ... 0045: A7 AND A ; ... game objects? 0046: CA 82 00 JP Z,$0082 ; No ... restore registers and out 0049: 3A EF 20 LD A,($20EF) ; Are we in ... 004C: A7 AND A ; ... game mode? 004D: C2 6F 00 JP NZ,$006F ; Yes ... go process game-play things and out 0050: 3A EB 20 LD A,($20EB) ; Number of credits 0053: A7 AND A ; Are there any credits (player standing there)? 0054: C2 5D 00 JP NZ,$005D ; Yes ... skip any ISR animations for the splash screens 0057: CD BF 0A CALL $0ABF ; Process ISR tasks for splash screens 005A: C3 82 00 JP $0082 ; Restore registers and out ; ; At this point no game is going and there are credits 005D: 3A 93 20 LD A,($2093) ; Are we in the ... 0060: A7 AND A ; ... "press start" loop? 0061: C2 82 00 JP NZ,$0082 ; Yes ... restore registers and out 0064: C3 65 07 JP $0765 ; Start the "press start" loop ; ; Mark credit as needing registering 0067: 3E 01 LD A,$01 ; Remember switch ... 0069: 32 EA 20 LD ($20EA),A ; ... state for debounce 006C: C3 3F 00 JP $003F ; Continue ; ; Main game-play timing loop 006F: CD 40 17 CALL $1740 ; Time down fleet sound and sets flag if needs new delay value 0072: 3A 32 20 LD A,($2032) ; Use rolling shot's timer to sync ... 0075: 32 80 20 LD ($2080),A ; ... other two shots 0078: CD 00 01 CALL $0100 ; Draw the current alien (or exploding alien) 007B: CD 48 02 CALL $0248 ; Process game objects (including player object) 007E: CD 13 09 CALL $0913 ; Count down time to saucer 0081: 00 NOP ; %% Why are we waiting? ; 0082: E1 POP HL ; Restore ... 0083: D1 POP DE ; ... 0084: C1 POP BC ; ... 0085: F1 POP AF ; ... everything 0086: FB EI ; Enable interrupts 0087: C9 RET ; Return from interrupt 0088: 00 00 00 00 ; %% Why waste the space? ; Continues here at scanline 96 ; 008C: AF XOR A ; Flag that tells ... 008D: 32 72 20 LD ($2072),A ; ... objects on the upper half of screen to draw/move 0090: 3A E9 20 LD A,($20E9) ; Are we moving ... 0093: A7 AND A ; ... game objects? 0094: CA 82 00 JP Z,$0082 ; No ... restore and return 0097: 3A EF 20 LD A,($20EF) ; Are we in ... 009A: A7 AND A ; ... game mode? 009B: C2 A5 00 JP NZ,$00A5 ; Yes .... process game objects and out 009E: 3A C1 20 LD A,($20C1) ; Splash-animation tasks 00A1: 0F RRCA ; If we are in demo-mode then we'll process the tasks anyway 00A2: D2 82 00 JP NC,$0082 ; Not in demo mode ... done ; 00A5: 21 20 20 LD HL,$2020 ; Game object table (skip player-object at 2010) 00A8: CD 4B 02 CALL $024B ; Process all game objects (except player object) 00AB: CD 41 01 CALL $0141 ; Advance cursor to next alien (move the alien if it is last one) 00AE: C3 82 00 JP $0082 ; Restore and return ;##-InitRack ; Initialize the player's rack of aliens. Copy the reference-location and deltas from the ; player's data bank. ; 00B1: CD 86 08 CALL $0886 ; 2xFC Get current player's ref-alien position pointer 00B4: E5 PUSH HL ; Hold pointer 00B5: 7E LD A,(HL) ; Get player's ... 00B6: 23 INC HL ; ... ref-alien ... 00B7: 66 LD H,(HL) ; ... 00B8: 6F LD L,A ; ... coordinates 00B9: 22 09 20 LD ($2009),HL ; Set game's reference alien's X,Y 00BC: 22 0B 20 LD ($200B),HL ; Set game's alien cursor bit position 00BF: E1 POP HL ; Restore pointer 00C0: 2B DEC HL ; 21FB or 22FB ref alien's delta (left or right) 00C1: 7E LD A,(HL) ; Get ref alien's delta X 00C2: FE 03 CP $03 ; If there is one alien it will move right at 3 00C4: C2 C8 00 JP NZ,$00C8 ; Not 3 ... keep it 00C7: 3D DEC A ; If it is 3, back it down to 2 until it switches again 00C8: 32 08 20 LD ($2008),A ; Store alien deltaY 00CB: FE FE CP $FE ; Moving left? 00CD: 3E 00 LD A,$00 ; Value of 0 for rack-moving-right (not XOR so flags are unaffected) 00CF: C2 D3 00 JP NZ,$00D3 ; Not FE ... keep the value 0 for right 00D2: 3C INC A ; It IS FE ... use 1 for left 00D3: 32 0D 20 LD ($200D),A ; Store rack direction 00D6: C9 RET ; Done 00D7: 3E 02 LD A,$02 ; Set ... 00D9: 32 FB 21 LD ($21FB),A ; ... player 1 and 2 ... 00DC: 32 FB 22 LD ($22FB),A ; ... alien delta to 2 (right 2 pixels) 00DF: C3 E4 08 JP $08E4 00E2: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00F0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ; ; %% Lots of wasted space here. Seems to be padding the next routine to 0100 ;##-DrawAlien ; 2006 holds the index into the alien flag data grid. 2067 holds the MSB of the pointer (21xx or 22xx). ; If there is an alien exploding time it down. Otherwise draw the alien if it alive (or skip if ; it isn't). If an alien is drawn (or blank) then the 2000 alien-drawing flag is cleared. ; 0100: 21 02 20 LD HL,$2002 ; Is there an ... 0103: 7E LD A,(HL) ; ... alien ... 0104: A7 AND A ; ... exploding? 0105: C2 38 15 JP NZ,$1538 ; Yes ... go time it down and out ; 0108: E5 PUSH HL ; 2002 on the stack 0109: 3A 06 20 LD A,($2006) ; Get alien index ... 010C: 6F LD L,A ; ... for the 21xx or 22xx pointer 010D: 3A 67 20 LD A,($2067) ; Get MSB ... 0110: 67 LD H,A ; ... of data area (21xx or 22xx) 0111: 7E LD A,(HL) ; Get alien status flag 0112: A7 AND A ; Is the alien alive? 0113: E1 POP HL ; HL=2002 0114: CA 36 01 JP Z,$0136 ; No alien ... skip drawing alien sprite (but flag done) 0117: 23 INC HL ; HL=2003 Bump descriptor 0118: 23 INC HL ; HL=2004 Point to alien's row 0119: 7E LD A,(HL) ; Get alien type 011A: 23 INC HL ; HL=2005 Bump descriptor 011B: 46 LD B,(HL) ; Get animation number 011C: E6 FE AND $FE ; Translate row to type offset as follows: ... 011E: 07 RLCA ; ... 0,1 -> 32 (type 1) ... 011F: 07 RLCA ; ... 2,3 -> 16 (type 2) ... 0120: 07 RLCA ; ... 4 -> 32 (type 3) on top row 0121: 5F LD E,A ; Sprite offset LSB 0122: 16 00 LD D,$00 ; MSB is 0 0124: 21 00 1C LD HL,$1C00 ; Position 0 alien sprites 0127: 19 ADD HL,DE ; Offset to sprite type 0128: EB EX DE,HL ; Sprite offset to DE 0129: 78 LD A,B ; Animation frame number 012A: A7 AND A ; Is it position 0? 012B: C4 3B 01 CALL NZ,$013B ; No ... add 30 and use position 1 alien sprites 012E: 2A 0B 20 LD HL,($200B) ; Pixel position 0131: 06 10 LD B,$10 ; 16 rows in alien sprites 0133: CD D3 15 CALL $15D3 ; Draw shifted sprite ; 0136: AF XOR A ; Let the ISR routine ... 0137: 32 00 20 LD ($2000),A ; ... advance the cursor to the next alien 013A: C9 RET ; Out ; 013B: 21 30 00 LD HL,$0030 ; Offset sprite pointer ... 013E: 19 ADD HL,DE ; ... to animation frame 1 sprites 013F: EB EX DE,HL ; Back to DE 0140: C9 RET ; Out ;##-CursorNextAlien ; This is called from the mid-screen ISR to set the cursor for the next alien to draw. ; When the cursor moves over all aliens then it is reset to the beginning and the reference ; alien is moved to its next position. ; ; The flag at 2000 keeps this in sync with the alien-draw routine called from the end-screen ISR. ; When the cursor is moved here then the flag at 2000 is set to 1. This routine will not change ; the cursor until the alien-draw routine at 100 clears the flag. Thus no alien is skipped. ; 0141: 3A 68 20 LD A,($2068) ; Is the player ... 0144: A7 AND A ; ... blowing up? 0145: C8 RET Z ; Yes ... ignore the aliens 0146: 3A 00 20 LD A,($2000) ; Still waiting on ... 0149: A7 AND A ; ... this alien to be drawn? 014A: C0 RET NZ ; Yes ... leave cursor in place 014B: 3A 67 20 LD A,($2067) ; Load alien-data ... 014E: 67 LD H,A ; ... MSB (either 21xx or 22xx) 014F: 3A 06 20 LD A,($2006) ; Load the xx part of the alien flag pointer 0152: 16 02 LD D,$02 ; When all are gone this triggers 1A1 to return from this stack frame 0154: 3C INC A ; Have we drawn all aliens ... 0155: FE 37 CP $37 ; ... at last position? 0157: CC A1 01 CALL Z,$01A1 ; Yes ... move the bottom/right alien and reset index to 0 015A: 6F LD L,A ; HL now points to alien flag 015B: 46 LD B,(HL) ; Is alien ... 015C: 05 DEC B ; ... alive? 015D: C2 54 01 JP NZ,$0154 ; No ... skip to next alien 0160: 32 06 20 LD ($2006),A ; New alien index 0163: CD 7A 01 CALL $017A ; Calculate bit position and type for index 0166: 61 LD H,C ; The calculation returns the MSB in C 0167: 22 0B 20 LD ($200B),HL ; Store new bit position 016A: 7D LD A,L ; Has this alien ... 016B: FE 28 CP $28 ; ... reached the end of screen? 016D: DA 71 19 JP C,$1971 ; Yes ... kill the player 0170: 7A LD A,D ; This alien's ... 0171: 32 04 20 LD ($2004),A ; ... row index 0174: 3E 01 LD A,$01 ; Set the wait-flag for the ... 0176: 32 00 20 LD ($2000),A ; ... draw-alien routine to clear 0179: C9 RET ; Done ;##-GetAlienCoords ; Convert alien index in L to screen bit position in C,L. ; Return alien row index (converts to type) in D. ; 017A: 16 00 LD D,$00 ; Row 0 017C: 7D LD A,L ; Hold onto alien index 017D: 21 09 20 LD HL,$2009 ; Get alien X ... 0180: 46 LD B,(HL) ; ... to B 0181: 23 INC HL ; Get alien y ... 0182: 4E LD C,(HL) ; ... to C 0183: FE 0B CP $0B ; Can we take a full row off of index? 0185: FA 94 01 JP M,$0194 ; No ... we have the row 0188: DE 0B SBC A,$0B ; Subtract off 11 (one whole row) 018A: 5F LD E,A ; Hold the new index 018B: 78 LD A,B ; Add ... 018C: C6 10 ADD A,$10 ; ... 16 to bit ... 018E: 47 LD B,A ; ... position Y (1 row in rack) 018F: 7B LD A,E ; Restore tallied index 0190: 14 INC D ; Next row 0191: C3 83 01 JP $0183 ; Keep skipping whole rows ; 0194: 68 LD L,B ; We have the LSB (the row) 0195: A7 AND A ; Are we in the right column? 0196: C8 RET Z ; Yes ... X and Y are right 0197: 5F LD E,A ; Hold index 0198: 79 LD A,C ; Add ... 0199: C6 10 ADD A,$10 ; ... 16 to bit ... 019B: 4F LD C,A ; ... position X (1 column in rack) 019C: 7B LD A,E ; Restore index 019D: 3D DEC A ; We adjusted for 1 column 019E: C3 95 01 JP $0195 ; Keep moving over column ;##-MoveRefAlien ; The "reference alien" is the bottom left. All other aliens are drawn relative to this ; reference. This routine moves the reference alien (the delta is set elsewhere) and toggles ; the animation frame number between 0 and 1. ; 01A1: 15 DEC D ; This decrements with each call to move 01A2: CA CD 01 JP Z,$01CD ; Return out of TWO call frames (only used if no aliens left) 01A5: 21 06 20 LD HL,$2006 ; Set current alien ... 01A8: 36 00 LD (HL),$00 ; ... index to 0 01AA: 23 INC HL ; Point to DeltaX 01AB: 4E LD C,(HL) ; Load DX into C 01AC: 36 00 LD (HL),$00 ; Set DX to 0 01AE: CD D9 01 CALL $01D9 ; Move alien 01B1: 21 05 20 LD HL,$2005 ; Alien animation frame number 01B4: 7E LD A,(HL) ; Toggle ... 01B5: 3C INC A ; ... animation ... 01B6: E6 01 AND $01 ; ... number between ... 01B8: 77 LD (HL),A ; ... 0 and 1 01B9: AF XOR A ; Alien index in A is now 0 01BA: 21 67 20 LD HL,$2067 ; Restore H ... 01BD: 66 LD H,(HL) ; ... to player data MSB (21 or 22) 01BE: C9 RET ; Done 01BF: 00 ; %% Why? ;##-InitAliens ; Initialize the 55 aliens from last to 1st. 1 means alive. ; 01C0: 21 00 21 LD HL,$2100 ; Start of alien structures (this is the last alien) 01C3: 06 37 LD B,$37 ; Count to 55 (that's five rows of 11 aliens) 01C5: 36 01 LD (HL),$01 ; Bring alien to live 01C7: 23 INC HL ; Next alien 01C8: 05 DEC B ; All done? 01C9: C2 C5 01 JP NZ,$01C5 ; No ... keep looping 01CC: C9 RET ; Done ;##-ReturnTwo ; If there are no aliens left on the screen then MoveDrawAlien comes here which returns from the ; caller's stack frame. ; 01CD: E1 POP HL ; Drop return to caller 01CE: C9 RET ; Return to caller's caller ;##-DrawBottomLine ; Draw a 1px line across the player's stash at the bottom of the screen. ; 01CF: 3E 01 LD A,$01 ; Bit 1 set ... going to draw a 1-pixel stripe down left side 01D1: 06 E0 LD B,$E0 ; All the way down the screen 01D3: 21 02 24 LD HL,$2402 ; Screen coordinates (3rd byte from upper left) 01D6: C3 CC 14 JP $14CC ; Draw line down left side ;##-AddDelta ; HL points to descriptor: DX DY XX YY except DX is already loaded in C ; %% Why the "already loaded" part? Why not just load it here? ; 01D9: 23 INC HL ; We loaded delta-x already ... skip over it 01DA: 46 LD B,(HL) ; Get delta-y 01DB: 23 INC HL ; Skip over it 01DC: 79 LD A,C ; Add delta-x ... 01DD: 86 ADD A,(HL) ; ... to x 01DE: 77 LD (HL),A ; Store new x 01DF: 23 INC HL ; Skip to y 01E0: 78 LD A,B ; Add delta-y ... 01E1: 86 ADD A,(HL) ; ... to y 01E2: 77 LD (HL),A ; Store new y 01E3: C9 RET ; Done ;##-CopyRAMMirror ; Block copy ROM mirror 1B00-1BBF to initialize RAM at 2000-20BF. ; 01E4: 06 C0 LD B,$C0 ; Number of bytes 01E6: 11 00 1B LD DE,$1B00 ; RAM mirror in ROM 01E9: 21 00 20 LD HL,$2000 ; Start of RAM 01EC: C3 32 1A JP $1A32 ; Copy [DE]->[HL] and return ;##-DrawShieldPl1 ; Draw the shields for player 1 (draws it in the buffer in the player's data area). ; 01EF: 21 42 21 LD HL,$2142 ; Player 1 shield buffer (remember between games in multi-player) 01F2: C3 F8 01 JP $01F8 ; Common draw point ; ;##-DrawShieldPl2 ; Draw the shields for player 1 (draws it in the buffer in the player's data area). ; 01F5: 21 42 22 LD HL,$2242 ; Player 2 shield buffer (remember between games in multi-player) ; 01F8: 0E 04 LD C,$04 ; Going to draw 4 shields 01FA: 11 20 1D LD DE,$1D20 ; Shield pixel pattern 01FD: D5 PUSH DE ; Hold the start for the next shield 01FE: 06 2C LD B,$2C ; 44 bytes to copy 0200: CD 32 1A CALL $1A32 ; Block copy DE to HL (B bytes) 0203: D1 POP DE ; Restore start of shield pattern 0204: 0D DEC C ; Drawn all shields? 0205: C2 FD 01 JP NZ,$01FD ; No ... go draw them all 0208: C9 RET ; Done ;##-RememberShields1 ; Copy shields on the screen to player 1's data area. ; 0209: 3E 01 LD A,$01 ; Not zero means remember 020B: C3 1B 02 JP $021B ; Shuffle-shields player 1 ;##-RememberShields2 ; Copy shields on the screen to player 2's data area. ; 020E: 3E 01 LD A,$01 ; Not zero means remember 0210: C3 14 02 JP $0214 ; Shuffle-shields player 2 ;##-RestoreShields2 ; Copy shields from player 2's data area to screen. ; 0213: AF XOR A ; Zero means restore 0214: 11 42 22 LD DE,$2242 ; Player 2 shield buffer (remember between games in multi-player) 0217: C3 1E 02 JP $021E ; Shuffle-shields player 2 ;##-RestoreShields1 ; Copy shields from player 1's data area to screen. ; 021A: AF XOR A ; Zero means restore 021B: 11 42 21 LD DE,$2142 ; Player 1 shield buffer (remember between games in multi-player) ;##-CopyShields ; A is 1 for screen-to-buffer, 0 for to buffer-to-screen ; HL is screen coordinates of first shield. There are 23 rows between shields. ; DE is sprite buffer in memory. ; 021E: 32 81 20 LD ($2081),A ; Remember copy/restore flag 0221: 01 02 16 LD BC,$1602 ; 22 rows, 2 bytes/row (for 1 shield pattern) 0224: 21 06 28 LD HL,$2806 ; Screen coordinates 0227: 3E 04 LD A,$04 ; Four shields to move 0229: F5 PUSH AF ; Hold shield count 022A: C5 PUSH BC ; Hold sprite-size 022B: 3A 81 20 LD A,($2081) ; Get back copy/restore flag 022E: A7 AND A ; Not zero ... 022F: C2 42 02 JP NZ,$0242 ; ... means remember shidles 0232: CD 69 1A CALL $1A69 ; Restore player's shields 0235: C1 POP BC ; Get back sprite-size 0236: F1 POP AF ; Get back shield count 0237: 3D DEC A ; Have we moved all shields? 0238: C8 RET Z ; Yes ... out 0239: D5 PUSH DE ; Hold sprite buffer 023A: 11 E0 02 LD DE,$02E0 ; Add 2E0 (23 rows) to get to ... 023D: 19 ADD HL,DE ; ... next shield on screen 023E: D1 POP DE ; restore sprite buffer 023F: C3 29 02 JP $0229 ; Go back and do all ; 0242: CD 7C 14 CALL $147C ; Remember player's shields 0245: C3 35 02 JP $0235 ; Continue with next shield ;##-RunGameObjs ; Process game objects. Each game object has a 16 byte structure. The handler routine for the object ; is at xx03 and xx04 of the structure. The pointer to xx04 is pushed onto the stack before calling ; the handler. ; ; All game objects (except task 0 ... the player) are called at the mid-screen and end-screen renderings. ; Each object decides when to run based on its Y (not rotated) coordinate. If an object is on the lower ; half of the screen then it does its work when the beam is at the top of the screen. If an object is ; on the top of the screen then it does its work when the beam is at the bottom. This keeps the ; object from updating while it is being drawn which would result in an ugly flicker. ; ; ; The player is only processed at the mid-screen interrupt. I am not sure why. ; ; The first three bytes of the structure are used for status and timers. ; ; If the first byte is FF then the end of the game-task list has been reached. ; If the first byte is FE then the object is skipped. ; ; If the first-two bytes are non-zero then they are treated like a two-byte counter ; and decremented as such. The 2nd byte is the LSB (moves the fastest). ; ; If the first-two bytes are zero then the third byte is treated as an additional counter. It ; is decremented as such. ; ; When all three bytes reach zero the task is executed. ; ; The third-byte-counter was used as a speed-governor for the player's object, but evidently even the slowest ; setting was too slow. It got changed to 0 (fastest possible). ; 0248: 21 10 20 LD HL,$2010 ; First game object (active player) 024B: 7E LD A,(HL) ; Have we reached the ... 024C: FE FF CP $FF ; ... end of the object list? 024E: C8 RET Z ; Yes ... done 024F: FE FE CP $FE ; Is object active? 0251: CA 81 02 JP Z,$0281 ; No ... skip it 0254: 23 INC HL ; xx01 0255: 46 LD B,(HL) ; First byte to B 0256: 4F LD C,A ; Hold 1st byte 0257: B0 OR B ; OR 1st and 2nd byte 0258: 79 LD A,C ; Restore 1st byte 0259: C2 77 02 JP NZ,$0277 ; If word at xx00,xx02 is non zero then decrement it ; 025C: 23 INC HL ; xx02 025D: 7E LD A,(HL) ; Get byte counter 025E: A7 AND A ; Is it 0? 025F: C2 88 02 JP NZ,$0288 ; No ... decrement byte counter at xx02 0262: 23 INC HL ; xx03 0263: 5E LD E,(HL) ; Get handler address LSB 0264: 23 INC HL ; xx04 0265: 56 LD D,(HL) ; Get handler address MSB 0266: E5 PUSH HL ; Remember pointer to MSB 0267: EB EX DE,HL ; Handler address to HL 0268: E5 PUSH HL ; Now to stack (making room for indirect call) 0269: 21 6F 02 LD HL,$026F ; Return address to 026F 026C: E3 EX (SP),HL ; Return address (026F) now on stack. Handler in HL. 026D: D5 PUSH DE ; Push pointer to data struct (xx04) for handler to use 026E: E9 JP (HL) ; Run object's code (will return to next line) 026F: E1 POP HL ; Restore pointer to xx04 0270: 11 0C 00 LD DE,$000C ; Offset to next ... 0273: 19 ADD HL,DE ; ... game task (C+4=10) 0274: C3 4B 02 JP $024B ; Do next game task ; ; Word at xx00 and xx01 is non-zero. Decrement it and move to next task. 0277: 05 DEC B ; Decrement ... 0278: 04 INC B ; ... two ... 0279: C2 7D 02 JP NZ,$027D ; ... byte ... 027C: 3D DEC A ; ... value ... 027D: 05 DEC B ; ... at ... 027E: 70 LD (HL),B ; ... xx00 ... 027F: 2B DEC HL ; ... and ... 0280: 77 LD (HL),A ; ... xx01 ; 0281: 11 10 00 LD DE,$0010 ; Next ... 0284: 19 ADD HL,DE ; ... object descriptor 0285: C3 4B 02 JP $024B ; Keep processing game objects ; ; Word at xx00 and xx01 is zero and byte at xx02 is non-zero. Decrement xx02 and ; move to next task. 0288: 35 DEC (HL) ; Decrement the xx02 counter 0289: 2B DEC HL ; Back up to ... 028A: 2B DEC HL ; ... start of game task 028B: C3 81 02 JP $0281 ; Next game task ;##-GameObj0 ; Game object 0: Move/draw the player ; ; This task is only called at the mid-screen ISR. It ALWAYS does its work here, even though ; the player can be on the top or bottom of the screen (not rotated). ; 028E: E1 POP HL ; Get player object structure 2014 028F: 23 INC HL ; Point to blow-up status 0290: 7E LD A,(HL) ; Get player blow-up status 0291: FE FF CP $FF ; Player is blowing up? 0293: CA 3B 03 JP Z,$033B ; No ... go do normal movement ; ; Handle blowing up player 0296: 23 INC HL ; Point to blow-up delay count 0297: 35 DEC (HL) ; Decrement the blow-up delay 0298: C0 RET NZ ; Not time for a new blow-up sprite ... out 0299: 47 LD B,A ; Hold sprite image number 029A: AF XOR A ; 0 029B: 32 68 20 LD ($2068),A ; Player is NOT OK ... player is blowing up 029E: 32 69 20 LD ($2069),A ; Alien fire is disabled 02A1: 3E 30 LD A,$30 ; Reset count ... 02A3: 32 6A 20 LD ($206A),A ; ... till alien shots are enabled 02A6: 78 LD A,B ; Restore sprite image number (used if we go to 39B) 02A7: 36 05 LD (HL),$05 ; Reload time between blow-up changes 02A9: 23 INC HL ; Point to number of blow-up changes 02AA: 35 DEC (HL) ; Count down blow-up changes 02AB: C2 9B 03 JP NZ,$039B ; Still blowing up ... go draw next sprite ; ; Blow up finished 02AE: 2A 1A 20 LD HL,($201A) ; Player's coordinates 02B1: 06 10 LD B,$10 ; 16 Bytes 02B3: CD 24 14 CALL $1424 ; Erase simple sprite (the player) 02B6: 21 10 20 LD HL,$2010 ; Restore player ... 02B9: 11 10 1B LD DE,$1B10 ; ... structure ... 02BC: 06 10 LD B,$10 ; ... from ... 02BE: CD 32 1A CALL $1A32 ; ... ROM mirror 02C1: 06 00 LD B,$00 ; Turn off ... 02C3: CD DC 19 CALL $19DC ; ... all sounds 02C6: 3A 6D 20 LD A,($206D) ; Has rack reached ... 02C9: A7 AND A ; ... the bottom of the screen? 02CA: C0 RET NZ ; Yes ... done here 02CB: 3A EF 20 LD A,($20EF) ; Are we in ... 02CE: A7 AND A ; ... game mode? 02CF: C8 RET Z ; No ... return to splash screens 02D0: 31 00 24 LD SP,$2400 ; We aren't going to return 02D3: FB EI ; Enable interrupts (we just dropped the ISR context) 02D4: CD D7 19 CALL $19D7 ; Disable game tasks 02D7: CD 2E 09 CALL $092E ; Get number of ships for active player 02DA: A7 AND A ; Any left? 02DB: CA 6D 16 JP Z,$166D ; No ... handle game over for player 02DE: CD E7 18 CALL $18E7 ; Get player-alive status pointer 02E1: 7E LD A,(HL) ; Is player ... 02E2: A7 AND A ; ... alive? 02E3: CA 2C 03 JP Z,$032C ; Yes ... remove a ship from player's stash and reenter game loop 02E6: 3A CE 20 LD A,($20CE) ; Multi-player game 02E9: A7 AND A ; Only one player? 02EA: CA 2C 03 JP Z,$032C ; Yes ... remove a ship from player's stash and reenter game loop 02ED: 3A 67 20 LD A,($2067) ; Player data MSB 02F0: F5 PUSH AF ; Hold the MSB 02F1: 0F RRCA ; Player 1 is active player? 02F2: DA 32 03 JP C,$0332 ; Yes ... go store player 1 shields and come back to 02F8 02F5: CD 0E 02 CALL $020E ; No ... go store player 2 shields 02F8: CD 78 08 CALL $0878 ; Get ref-alien info and pointer to storage 02FB: 73 LD (HL),E ; Hold the ... 02FC: 23 INC HL ; ... ref-alien ... 02FD: 72 LD (HL),D ; ... screen coordinates 02FE: 2B DEC HL ; Back up ... 02FF: 2B DEC HL ; .. to delta storage 0300: 70 LD (HL),B ; Store ref-alien's delta (direction) 0301: 00 NOP ; %% Why? 0302: CD E4 01 CALL $01E4 ; Copy RAM mirror (getting ready to switch players) 0305: F1 POP AF ; Restore active player MSB 0306: 0F RRCA ; Player 1? 0307: 3E 21 LD A,$21 ; Player 1 data pointer 0309: 06 00 LD B,$00 ; Cocktail bit=0 (player 1) 030B: D2 12 03 JP NC,$0312 ; It was player one ... keep data for player 2 030E: 06 20 LD B,$20 ; Cocktail bit=1 (player 2) 0310: 3E 22 LD A,$22 ; Player 2 data pointer 0312: 32 67 20 LD ($2067),A ; Change players 0315: CD B6 0A CALL $0AB6 ; Two second delay 0318: AF XOR A ; Clear the player-object ... 0319: 32 11 20 LD ($2011),A ; ... timer (player can move instantly after switching players) 031C: 78 LD A,B ; Cocktail bit to A 031D: D3 05 OUT ($05),A ; Set the cocktail mode 031F: 3C INC A ; Fleet sound 1 (first tone) 0320: 32 98 20 LD ($2098),A ; Set the port 5 hold 0323: CD D6 09 CALL $09D6 ; Clear center window 0326: CD 7F 1A CALL $1A7F ; Remove a ship and update indicators 0329: C3 F9 07 JP $07F9 ; Tell the players that the switch has been made ; 032C: CD 7F 1A CALL $1A7F ; Remove a ship and update indicators 032F: C3 17 08 JP $0817 ; Continue into game loop ; 0332: CD 09 02 CALL $0209 ; Remember the shields for player 1 0335: C3 F8 02 JP $02F8 ; Back to switching-players above 0338: 00 00 00 ; %% Why ; Player not blowing up ... handle inputs 033B: 21 68 20 LD HL,$2068 ; Player OK flag 033E: 36 01 LD (HL),$01 ; Flag 1 ... player is OK 0340: 23 INC HL ; 2069 0341: 7E LD A,(HL) ; Alien shots enabled? 0342: A7 AND A ; Set flags 0343: C3 B0 03 JP $03B0 ; Continue 0346: 00 NOP ; %% Why? 0347: 2B DEC HL ; 2069 0348: 36 01 LD (HL),$01 ; Enable alien fire 034A: 3A 1B 20 LD A,($201B) ; Current player coordinates 034D: 47 LD B,A ; Hold it 034E: 3A EF 20 LD A,($20EF) ; Are we in ... 0351: A7 AND A ; ... game mode? 0352: C2 63 03 JP NZ,$0363 ; Yes ... use switches as player controls ; 0355: 3A 1D 20 LD A,($201D) ; Get demo command 0358: 0F RRCA ; Is it right? 0359: DA 81 03 JP C,$0381 ; Yes ... do right 035C: 0F RRCA ; Is it left? 035D: DA 8E 03 JP C,$038E ; Yes ... do left 0360: C3 6F 03 JP $036F ; Skip over movement (draw player and out) ; Player is in control 0363: CD C0 17 CALL $17C0 ; Read active player controls 0366: 07 RLCA ; Test for ... 0367: 07 RLCA ; ... right button 0368: DA 81 03 JP C,$0381 ; Yes ... handle move right 036B: 07 RLCA ; Test for left button 036C: DA 8E 03 JP C,$038E ; Yes ... handle move left ; Draw player sprite 036F: 21 18 20 LD HL,$2018 ; Active player descriptor 0372: CD 3B 1A CALL $1A3B ; Load 5 byte sprite descriptor in order: EDLHB 0375: CD 47 1A CALL $1A47 ; Convert HL to screen coordinates 0378: CD 39 14 CALL $1439 ; Draw player 037B: 3E 00 LD A,$00 ; Clear the task timer. Nobody changes this but it could have ... 037D: 32 12 20 LD ($2012),A ; ... been speed set for the player with a value other than 0 (not XORA) 0380: C9 RET ; Out ;##-MovePlayerRight ; Handle player moving right 0381: 78 LD A,B ; Player coordinate 0382: FE D9 CP $D9 ; At right edge? 0384: CA 6F 03 JP Z,$036F ; Yes ... ignore this 0387: 3C INC A ; Bump X coordinate 0388: 32 1B 20 LD ($201B),A ; New X coordinate 038B: C3 6F 03 JP $036F ; Draw player and out ;##-MovePlayerLeft ; Handle player moving left 038E: 78 LD A,B ; Player coordinate 038F: FE 30 CP $30 ; At left edge 0391: CA 6F 03 JP Z,$036F ; Yes ... ignore this 0394: 3D DEC A ; Bump X coordinate 0395: 32 1B 20 LD ($201B),A ; New X coordinate 0398: C3 6F 03 JP $036F ; Draw player and out ;##-DrawPlayerDie ; Toggle the player's blowing-up sprite between two pictures and draw it 039B: 3C INC A ; Toggle blowing-up ... 039C: E6 01 AND $01 ; ... player sprite (0,1,0,1) 039E: 32 15 20 LD ($2015),A ; Hold current state 03A1: 07 RLCA ; *2 03A2: 07 RLCA ; *4 03A3: 07 RLCA ; *8 03A4: 07 RLCA ; *16 03A5: 21 70 1C LD HL,$1C70 ; Base blow-up sprite location 03A8: 85 ADD A,L ; Offset sprite ... 03A9: 6F LD L,A ; ... pointer 03AA: 22 18 20 LD ($2018),HL ; New blow-up sprite picture 03AD: C3 6F 03 JP $036F ; Draw new blow-up sprite and out 03B0: C2 4A 03 JP NZ,$034A ; Alien shots enabled ... move player's ship, draw it, and out 03B3: 23 INC HL ; To 206A 03B4: 35 DEC (HL) ; Time until aliens can fire 03B5: C2 4A 03 JP NZ,$034A ; Not time to enable ... move player's ship, draw it, and out 03B8: C3 46 03 JP $0346 ; Enable alien fire ... move player's ship, draw it, and out ;##-GameObj1 ; Game object 1: Move/draw the player shot ; ; This task executes at either mid-screen ISR (if it is on the top half of the non-rotated screen) or ; at the end-screen ISR (if it is on the bottom half of the screen). ; 03BB: 11 2A 20 LD DE,$202A ; Object's Yn coordiante 03BE: CD 06 1A CALL $1A06 ; Compare to screen-update location 03C1: E1 POP HL ; Pointer to task data 03C2: D0 RET NC ; Make sure we are in the right ISR 03C3: 23 INC HL ; Point to 2025 ... the shot status 03C4: 7E LD A,(HL) ; Get shot status 03C5: A7 AND A ; Return if ... 03C6: C8 RET Z ; ... no shot is active ; 03C7: FE 01 CP $01 ; Shot just starting (requested elsewhere)? 03C9: CA FA 03 JP Z,$03FA ; Yes ... go initiate shot ; 03CC: FE 02 CP $02 ; Progressing normally? 03CE: CA 0A 04 JP Z,$040A ; Yes ... go move it ; 03D1: 23 INC HL ; 2026 03D2: FE 03 CP $03 ; Shot blowing up (not because of alien)? 03D4: C2 2A 04 JP NZ,$042A ; No ... try other options ; ; Shot blowing up because it left the playfield, hit a shield, or hit another bullet 03D7: 35 DEC (HL) ; Decrement the timer 03D8: CA 36 04 JP Z,$0436 ; If done then 03DB: 7E LD A,(HL) ; Get timer value 03DC: FE 0F CP $0F ; Starts at 10 ... first decrement brings us here 03DE: C0 RET NZ ; Not the first time ... explosion has been drawn ; Draw explosion first pass through timer loop 03DF: E5 PUSH HL ; Hold pointer to data 03E0: CD 30 04 CALL $0430 ; Read shot descriptor 03E3: CD 52 14 CALL $1452 ; Erase the sprite 03E6: E1 POP HL ; 2026 (timer flag) 03E7: 23 INC HL ; 2027 point to sprite LSB 03E8: 34 INC (HL) ; Change 1C90 to 1C91 03E9: 23 INC HL ; 2028 03EA: 23 INC HL ; 2029 03EB: 35 DEC (HL) ; Drop X coordinate ... 03EC: 35 DEC (HL) ; ... by 2 03ED: 23 INC HL ; 202A 03EE: 35 DEC (HL) ; Drop Y ... 03EF: 35 DEC (HL) ; ... coordinate ... 03F0: 35 DEC (HL) ; ... by ... 03F1: 23 INC HL ; ... 3 03F2: 36 08 LD (HL),$08 ; 202B 8 bytes in size of sprite 03F4: CD 30 04 CALL $0430 ; Read player shot structure 03F7: C3 00 14 JP $1400 ; Draw sprite and out ; ;##-InitPlyShot 03FA: 3C INC A ; Type is now ... 03FB: 77 LD (HL),A ; ... 2 (in progress) 03FC: 3A 1B 20 LD A,($201B) ; Players Y coordinate 03FF: C6 08 ADD A,$08 ; To center of player 0401: 32 2A 20 LD ($202A),A ; Shot's Y coordinate 0404: CD 30 04 CALL $0430 ; Read 5 byte structure 0407: C3 00 14 JP $1400 ; Draw sprite and out ; ;##-MovePlyShot 040A: CD 30 04 CALL $0430 ; Read the shot structure 040D: D5 PUSH DE ; Hold pointer to sprite image 040E: E5 PUSH HL ; Hold sprite coordinates 040F: C5 PUSH BC ; Hold sprite size (in B) 0410: CD 52 14 CALL $1452 ; Erase the sprite from the screen 0413: C1 POP BC ; Restore size 0414: E1 POP HL ; Restore coords 0415: D1 POP DE ; Restore pointer to sprite image 0416: 3A 2C 20 LD A,($202C) ; DeltaX for shot 0419: 85 ADD A,L ; Move the shot ... 041A: 6F LD L,A ; ... up the screen 041B: 32 29 20 LD ($2029),A ; Store shot's new X coordinate 041E: CD 91 14 CALL $1491 ; Draw sprite with collision detection 0421: 3A 61 20 LD A,($2061) ; Test for ... 0424: A7 AND A ; ... collision 0425: C8 RET Z ; No collision ... out ; ; Collision with alien detected 0426: 32 02 20 LD ($2002),A ; Set to not-0 indicating ... 0429: C9 RET ; ... an alien is blowing up ; ; Other shot-status options 042A: FE 05 CP $05 ; Alien explosion in progress? 042C: C8 RET Z ; Yes ... nothing to do 042D: C3 36 04 JP $0436 ; Anything else erases the shot and removes it from duty ;##-ReadPlyShot 0430: 21 27 20 LD HL,$2027 ; Read 5 byte sprite structure for ... 0433: C3 3B 1A JP $1A3B ; ... player shot ;##-EndOfBlowup 0436: CD 30 04 CALL $0430 ; Read the shot structure 0439: CD 52 14 CALL $1452 ; Erase the player's shot 043C: 21 25 20 LD HL,$2025 ; Reinit ... 043F: 11 25 1B LD DE,$1B25 ; ... shot structure ... 0442: 06 07 LD B,$07 ; ... from ... 0444: CD 32 1A CALL $1A32 ; ... ROM mirror 0447: 2A 8D 20 LD HL,($208D) ; Get pointer to saucer-score table 044A: 2C INC L ; Every shot explosion advances it one 044B: 7D LD A,L ; Have we passed ... 044C: FE 63 CP $63 ; ... the end at 1D63 044E: DA 53 04 JP C,$0453 ; No .... keep it 0451: 2E 54 LD L,$54 ; Wrap back around to 1D54 0453: 22 8D 20 LD ($208D),HL ; New score pointer 0456: 2A 8F 20 LD HL,($208F) ; Increments with every shot ... 0459: 2C INC L ; ... but only LSB %% ... 045A: 22 8F 20 LD ($208F),HL ; ... used for saucer direction ; 045D: 3A 84 20 LD A,($2084) ; Is saucer ... 0460: A7 AND A ; ... on screen? 0461: C0 RET NZ ; Yes ... don't reset it ; ; Setup saucer direction for next trip 0462: 7E LD A,(HL) ; Shot counter 0463: E6 01 AND $01 ; Lowest bit set? 0465: 01 29 02 LD BC,$0229 ; Xr delta of 2 starting at Xr=29 0468: C2 6E 04 JP NZ,$046E ; Yes ... use 2/29 046B: 01 E0 FE LD BC,$FEE0 ; No ... Xr delta of -2 starting at Xr=E0 046E: 21 8A 20 LD HL,$208A ; Saucer descriptor 0471: 71 LD (HL),C ; Store Xr coordinate 0472: 23 INC HL ; Point to ... 0473: 23 INC HL ; ... delta Xr 0474: 70 LD (HL),B ; Store delta Xr 0475: C9 RET ; Done ;##-GameObj2 ; Game object 2: Allien rolling-shot (targets player specifically) ; ; The 2-byte value at 2038 is where the firing-column-table-pointer would be (see other ; shots ... next game objects). This shot doesn't use that table. It targets the player ; specifically. Instead the value is used as a flag to have the shot skip its first ; attempt at firing every time it is reinitialized (when it blows up). ; ; The task-timer at 2032 is copied to 2080 in the game loop. The flag is used as a ; synchronization flag to keep all the shots processed on separate interrupt ticks. This ; has the main effect of slowing the shots down. ; ; When the timer is 2 the squiggly-shot/saucer (object 4 ) runs. ; When the timer is 1 the plunger-shot (object 3) runs. ; Whne the timer is 0 this object, the rolling-shot, runs. ; 0476: E1 POP HL ; Game object data 0477: 3A 32 1B LD A,($1B32) ; Restore delay from ... 047A: 32 32 20 LD ($2032),A ; ... ROM mirror (value 2) 047D: 2A 38 20 LD HL,($2038) ; Get pointer to ... 0480: 7D LD A,L ; ... column-firing table. 0481: B4 OR H ; All zeros? 0482: C2 8A 04 JP NZ,$048A ; No ... must be a valid column. Go fire. 0485: 2B DEC HL ; Decrement the counter 0486: 22 38 20 LD ($2038),HL ; Store new counter value (run the shot next time) 0489: C9 RET ; And out 048A: 11 35 20 LD DE,$2035 ; Rolling-shot data structure 048D: 3E F9 LD A,$F9 ; Last picture of "rolling" alien shot 048F: CD 50 05 CALL $0550 ; Set code to handle rolling-shot 0492: 3A 46 20 LD A,($2046) ; Get the plunger-shot step count 0495: 32 70 20 LD ($2070),A ; Hold it 0498: 3A 56 20 LD A,($2056) ; Get the squiggly-shot step count 049B: 32 71 20 LD ($2071),A ; Hold it 049E: CD 63 05 CALL $0563 ; Handle active shot structure 04A1: 3A 78 20 LD A,($2078) ; Blow up counter 04A4: A7 AND A ; Test if shot has cycled through blowing up 04A5: 21 35 20 LD HL,$2035 ; Rolling-shot data structure 04A8: C2 5B 05 JP NZ,$055B ; If shot is still running, copy the updated data and out ;##-ResetShot ; The rolling-shot has blown up. Reset the data structure. 04AB: 11 30 1B LD DE,$1B30 ; Reload ... 04AE: 21 30 20 LD HL,$2030 ; ... object ... 04B1: 06 10 LD B,$10 ; ... structure ... 04B3: C3 32 1A JP $1A32 ; ... from ROM mirror and out ;##-GameObj3 ; Game object 3: Alien plunger-shot ; This is skipped if there is only one alien left on the screen. ; 04B6: E1 POP HL ; Game object data 04B7: 3A 6E 20 LD A,($206E) ; One alien left? Skip plunger shot? 04BA: A7 AND A ; Check 04BB: C0 RET NZ ; Yes. Only one alien. Skip this shot. 04BC: 3A 80 20 LD A,($2080) ; Sync flag (copied from GO-2's timer value) 04BF: FE 01 CP $01 ; GO-2 and GO-4 are idle? 04C1: C0 RET NZ ; No ... only one shot at a time 04C2: 11 45 20 LD DE,$2045 ; Plunger alien shot data structure 04C5: 3E ED LD A,$ED ; Last picture of "plunger" alien shot 04C7: CD 50 05 CALL $0550 ; Copy the plunger alien to the active structure 04CA: 3A 36 20 LD A,($2036) ; Step count from rolling-shot 04CD: 32 70 20 LD ($2070),A ; Hold it 04D0: 3A 56 20 LD A,($2056) ; Step count from squiggly shot 04D3: 32 71 20 LD ($2071),A ; Hold it 04D6: CD 63 05 CALL $0563 ; Handle active shot structure 04D9: 3A 76 20 LD A,($2076) ; LSB of column-firing table 04DC: FE 10 CP $10 ; Been through all entries in the table? 04DE: DA E7 04 JP C,$04E7 ; Not yet ... table is OK 04E1: 3A 48 1B LD A,($1B48) ; Been through all .. 04E4: 32 76 20 LD ($2076),A ; ... so reset pointer into firing-column table 04E7: 3A 78 20 LD A,($2078) ; Get the blow up timer 04EA: A7 AND A ; Zero means shot is done 04EB: 21 45 20 LD HL,$2045 ; Plunger shot data 04EE: C2 5B 05 JP NZ,$055B ; If shot is still running, go copy the updated data and out ; 04F1: 11 40 1B LD DE,$1B40 ; Reload ... 04F4: 21 40 20 LD HL,$2040 ; ... object ... 04F7: 06 10 LD B,$10 ; ... structure ... 04F9: CD 32 1A CALL $1A32 ; ... from mirror ; 04FC: 3A 82 20 LD A,($2082) ; Number of aliens on screen 04FF: 3D DEC A ; Is there only one left? 0500: C2 08 05 JP NZ,$0508 ; No ... move on 0503: 3E 01 LD A,$01 ; Disable plunger shot ... 0505: 32 6E 20 LD ($206E),A ; ... when only one alien remains 0508: 2A 76 20 LD HL,($2076) ; Set the plunger shot's ... 050B: C3 7E 06 JP $067E ; ... column-firing pointer data ; Game task 4 when splash screen alien is shooting extra "C" with a squiggly shot 050E: E1 POP HL ; Ignore the task data pointer passed on stack ; ; GameObject 4 comes here if processing a squiggly shot 050F: 11 55 20 LD DE,$2055 ; Squiggly shot data structure 0512: 3E DB LD A,$DB ; LSB of last byte of picture 0514: CD 50 05 CALL $0550 ; Copy squiggly shot to 0517: 3A 46 20 LD A,($2046) ; Get plunger ... 051A: 32 70 20 LD ($2070),A ; ... step count 051D: 3A 36 20 LD A,($2036) ; Get rolling ... 0520: 32 71 20 LD ($2071),A ; ... step count 0523: CD 63 05 CALL $0563 ; Handle active shot structure 0526: 3A 76 20 LD A,($2076) ; LSB of column-firing table pointer 0529: FE 15 CP $15 ; Have we processed all entries? 052B: DA 34 05 JP C,$0534 ; No ... don't reset it 052E: 3A 58 1B LD A,($1B58) ; Reset the pointer ... 0531: 32 76 20 LD ($2076),A ; ... back to the start of the table 0534: 3A 78 20 LD A,($2078) ; Check to see if squiggly shot is done 0537: A7 AND A ; 0 means blow-up timer expired 0538: 21 55 20 LD HL,$2055 ; Squiggly shot data structure 053B: C2 5B 05 JP NZ,$055B ; If shot is still running, go copy the updated data and out ; Shot explosion is over. Remove the shot. 053E: 11 50 1B LD DE,$1B50 ; Reload 0541: 21 50 20 LD HL,$2050 ; ... object ... 0544: 06 10 LD B,$10 ; ... structure ... 0546: CD 32 1A CALL $1A32 ; ... from mirror 0549: 2A 76 20 LD HL,($2076) ; Copy pointer to column-firing table ... 054C: 22 58 20 LD ($2058),HL ; ... back to data structure (for next shot) 054F: C9 RET ; Done ;##-ToShotStruct 0550: 32 7F 20 LD ($207F),A ; LSB of last byte of last picture in sprite 0553: 21 73 20 LD HL,$2073 ; Destination is the shot-structure 0556: 06 0B LD B,$0B ; 11 bytes 0558: C3 32 1A JP $1A32 ; Block copy and out ;##-FromShotStruct 055B: 11 73 20 LD DE,$2073 ; Source is the shot-structure 055E: 06 0B LD B,$0B ; 11 bytes 0560: C3 32 1A JP $1A32 ; Block copy and out ;##-HandleAlienShot ; Each of the 3 shots copy their data to the 2073 structure (0B bytes) and call this. ; Then they copy back if the shot is still active. Otherwise they copy from the mirror. ; ; The alien "fire rate" is based on the number of steps the other two shots on the screen ; have made. The smallest number-of-steps is compared to the reload-rate. If it is too ; soon then no shot is made. The reload-rate is based on the player's score. The MSB ; is looked up in a table to get the reload-rate. The smaller the rate the faster the ; aliens fire. Setting rate this way keeps shots from walking on each other. ; 0563: 21 73 20 LD HL,$2073 ; Start of active shot structure 0566: 7E LD A,(HL) ; Get the shot status 0567: E6 80 AND $80 ; Is the shot active? 0569: C2 C1 05 JP NZ,$05C1 ; Yes ... go move it 056C: 3A C1 20 LD A,($20C1) ; ISR splash task 056F: FE 04 CP $04 ; Shooting the "C" ? 0571: 3A 69 20 LD A,($2069) ; Alien fire enabled flag 0574: CA B7 05 JP Z,$05B7 ; We are shooting the extra "C" ... just flag it active and out 0577: A7 AND A ; Is alien fire enabled? 0578: C8 RET Z ; No ... don't start a new shot 0579: 23 INC HL ; 2074 step count of current shot 057A: 36 00 LD (HL),$00 ; clear the step count ; Make sure it isn't too soon to fire another shot 057C: 3A 70 20 LD A,($2070) ; Get the step count of the 1st "other shot" 057F: A7 AND A ; Any steps made? 0580: CA 89 05 JP Z,$0589 ; No ... ignore this count 0583: 47 LD B,A ; Shuffle off step count 0584: 3A CF 20 LD A,($20CF) ; Get the reload rate (based on MSB of score) 0587: B8 CP B ; Too soon to fire again? 0588: D0 RET NC ; Yes ... don't fire 0589: 3A 71 20 LD A,($2071) ; Get the step count of the 2nd "other shot" 058C: A7 AND A ; Any steps made? 058D: CA 96 05 JP Z,$0596 ; No steps on any shot ... we are clear to fire 0590: 47 LD B,A ; Shuffle off step count 0591: 3A CF 20 LD A,($20CF) ; Get the reload rate (based on MSB of score) 0594: B8 CP B ; Too soon to fire again? 0595: D0 RET NC ; Yes ... don't fire 0596: 23 INC HL ; 2075 0597: 7E LD A,(HL) ; Get tracking flag 0598: A7 AND A ; Does this shot track the player? 0599: CA 1B 06 JP Z,$061B ; Yes ... go make a tracking shot; 059C: 2A 76 20 LD HL,($2076) ; Column-firing table 059F: 4E LD C,(HL) ; Get next column to fire from 05A0: 23 INC HL ; Bump the ... 05A1: 00 NOP ; % WHY? 05A2: 22 76 20 LD ($2076),HL ; ... pointer into column table 05A5: CD 2F 06 CALL $062F ; Find alien in target column 05A8: D0 RET NC ; No alien is alive in target column ... out ; 05A9: CD 7A 01 CALL $017A ; Get coordinates of alien (lowest alien in firing column) 05AC: 79 LD A,C ; Offset ... 05AD: C6 07 ADD A,$07 ; ... Y by 7 05AF: 67 LD H,A ; To H 05B0: 7D LD A,L ; Offset ... 05B1: D6 0A SUB $0A ; ... X down 10 05B3: 6F LD L,A ; To L 05B4: 22 7B 20 LD ($207B),HL ; Set shot coordinates below alien ; 05B7: 21 73 20 LD HL,$2073 ; Alien shot status 05BA: 7E LD A,(HL) ; Get the status 05BB: F6 80 OR $80 ; Mark this shot ... 05BD: 77 LD (HL),A ; ... as actively running 05BE: 23 INC HL ; 2074 step count 05BF: 34 INC (HL) ; Give this shot 1 step (it just started) 05C0: C9 RET ; Out ; ; Move the alien shot 05C1: 11 7C 20 LD DE,$207C ; Alien-shot Y coordinate 05C4: CD 06 1A CALL $1A06 ; Compare to beam position 05C7: D0 RET NC ; Not the right ISR for this shot ; 05C8: 23 INC HL ; 2073 status 05C9: 7E LD A,(HL) ; Get shot status 05CA: E6 01 AND $01 ; Bit 0 is 1 if blowing up 05CC: C2 44 06 JP NZ,$0644 ; Go do shot-is-blowing-up sequence 05CF: 23 INC HL ; 2074 step count 05D0: 34 INC (HL) ; Count the steps (used for fire rate) 05D1: CD 75 06 CALL $0675 ; Erase shot 05D4: 3A 79 20 LD A,($2079) ; Get LSB of the image pointer 05D7: C6 03 ADD A,$03 ; Next set of images 05D9: 21 7F 20 LD HL,$207F ; End of image 05DC: BE CP (HL) ; Have we reached the end of the set? 05DD: DA E2 05 JP C,$05E2 ; No ... keep it 05E0: D6 0C SUB $0C ; Back up to the 1st image in the set 05E2: 32 79 20 LD ($2079),A ; New LSB image pointer 05E5: 3A 7B 20 LD A,($207B) ; Get shot's Y coordinate 05E8: 47 LD B,A ; Hold it 05E9: 3A 7E 20 LD A,($207E) ; Get alien shot delta 05EC: 80 ADD A,B ; Add to shots coordinate 05ED: 32 7B 20 LD ($207B),A ; New shot Y coordinate 05F0: CD 6C 06 CALL $066C ; Draw the alien shot 05F3: 3A 7B 20 LD A,($207B) ; Shot's Y coordinate 05F6: FE 15 CP $15 ; Still in the active playfield? 05F8: DA 12 06 JP C,$0612 ; No ... end it 05FB: 3A 61 20 LD A,($2061) ; Did shot collide ... 05FE: A7 AND A ; ... with something? 05FF: C8 RET Z ; No ... we are done here 0600: 3A 7B 20 LD A,($207B) ; Shot's Y coordinate 0603: FE 1E CP $1E ; Is it below player's area? 0605: DA 12 06 JP C,$0612 ; Yes ... end it 0608: FE 27 CP $27 ; Is it above player's area? 060A: 00 NOP ; %% WHY? 060B: D2 12 06 JP NC,$0612 ; Yes ... end it 060E: 97 SUB A ; Flag that player ... 060F: 32 15 20 LD ($2015),A ; ... has been struck ; 0612: 3A 73 20 LD A,($2073) ; Flag to ... 0615: F6 01 OR $01 ; ... start shot ... 0617: 32 73 20 LD ($2073),A ; ... blowing up 061A: C9 RET ; Out ; ; Start a shot right over the player 061B: 3A 1B 20 LD A,($201B) ; Player's X coordinate 061E: C6 08 ADD A,$08 ; Center of player 0620: 67 LD H,A ; To H for routine 0621: CD 6F 15 CALL $156F ; Find the column 0624: 79 LD A,C ; Get the column right over player 0625: FE 0C CP $0C ; Is it a valid column? 0627: DA A5 05 JP C,$05A5 ; Yes ... use what we found 062A: 0E 0B LD C,$0B ; Else use ... 062C: C3 A5 05 JP $05A5 ; ... as far over as we can ;##-FindInColumn ; C contains the target column. Look for a live alien in the column starting with ; the lowest position. Return C=1 if found ... HL points to found slot. 062F: 0D DEC C ; Column that is firing 0630: 3A 67 20 LD A,($2067) ; Player's MSB (21xx or 22xx) 0633: 67 LD H,A ; To MSB of HL 0634: 69 LD L,C ; Column to L 0635: 16 05 LD D,$05 ; 5 rows of aliens 0637: 7E LD A,(HL) ; Get alien's status 0638: A7 AND A ; 0 means dead 0639: 37 SCF ; In case not 0 063A: C0 RET NZ ; Alien is alive? Yes ... return 063B: 7D LD A,L ; Get the flag pointer LSB 063C: C6 0B ADD A,$0B ; Jump to same column on next row of rack (+11 aliens per row) 063E: 6F LD L,A ; New alien index 063F: 15 DEC D ; Tested all rows? 0640: C2 37 06 JP NZ,$0637 ; No ... keep looking for a live alien up the rack 0643: C9 RET ; Didn't find a live alien. Return with C=0. ;##-ShotBlowingUp ; Alien shot is blowing up 0644: 21 78 20 LD HL,$2078 ; Blow up timer 0647: 35 DEC (HL) ; Decrement the value 0648: 7E LD A,(HL) ; Get the value 0649: FE 03 CP $03 ; First tick, 4, we draw the explosion 064B: C2 67 06 JP NZ,$0667 ; After that just wait 064E: CD 75 06 CALL $0675 ; Erase the shot 0651: 21 DC 1C LD HL,$1CDC ; Alien shot ... 0654: 22 79 20 LD ($2079),HL ; ... explosion sprite 0657: 21 7C 20 LD HL,$207C ; Alien shot Y 065A: 35 DEC (HL) ; Left two for ... 065B: 35 DEC (HL) ; ... explosion 065C: 2B DEC HL ; Point slien shot X 065D: 35 DEC (HL) ; Up two for ... 065E: 35 DEC (HL) ; ... explosion 065F: 3E 06 LD A,$06 ; Alien shot descriptor ... 0661: 32 7D 20 LD ($207D),A ; ... size 6 0664: C3 6C 06 JP $066C ; Draw alien shot explosion 0667: A7 AND A ; Have we reached 0? 0668: C0 RET NZ ; No ... keep waiting 0669: C3 75 06 JP $0675 ; Erase the explosion and out ; 066C: 21 79 20 LD HL,$2079 ; Alien shot descriptor 066F: CD 3B 1A CALL $1A3B ; Read 5 byte structure 0672: C3 91 14 JP $1491 ; Draw shot and out ; 0675: 21 79 20 LD HL,$2079 ; Alien shot descriptor 0678: CD 3B 1A CALL $1A3B ; Read 5 byte structure 067B: C3 52 14 JP $1452 ; Erase the shot and out 067E: 22 48 20 LD ($2048),HL ; From 50B, update ... 0681: C9 RET ; ... column-firing table pointer and out ;##-GameObj4 ; Game object 4: Flying Saucer OR squiggly shot ; ; This task is shared by the squiggly-shot and the flying saucer. The saucer waits until the ; squiggly-shot is over before it begins. ; 0682: E1 POP HL ; Pull data pointer from the stack (not going to use it) 0683: 3A 80 20 LD A,($2080) ; Sync flag (copied from GO-2's timer value) 0686: FE 02 CP $02 ; Are GO-2 and GO-3 idle? 0688: C0 RET NZ ; No ... only one at a time 0689: 21 83 20 LD HL,$2083 ; Time-till-saucer flag 068C: 7E LD A,(HL) ; Is it time ... 068D: A7 AND A ; ... for a saucer? 068E: CA 0F 05 JP Z,$050F ; No ... go process squiggly shot 0691: 3A 56 20 LD A,($2056) ; Is there a ... 0694: A7 AND A ; ... squiggly shot going? 0695: C2 0F 05 JP NZ,$050F ; Yes ... go handle squiggly shot 0698: 23 INC HL ; Saucer on screen flag 0699: 7E LD A,(HL) ; (2084) Is the saucer ... 069A: A7 AND A ; ... already on the screen? 069B: C2 AB 06 JP NZ,$06AB ; Yes ... go handle it 069E: 3A 82 20 LD A,($2082) ; Number of aliens remaining 06A1: FE 08 CP $08 ; Less than ... 06A3: DA 0F 05 JP C,$050F ; ... 8 ... no saucer 06A6: 36 01 LD (HL),$01 ; (2084) The saucer is on the screen 06A8: CD 3C 07 CALL $073C ; Draw the flying saucer 06AB: 11 8A 20 LD DE,$208A ; Saucer's Y coordinate 06AE: CD 06 1A CALL $1A06 ; Compare to beam position 06B1: D0 RET NC ; Not the right ISR for moving saucer 06B2: 21 85 20 LD HL,$2085 ; Saucer hit flag 06B5: 7E LD A,(HL) ; Has saucer ... 06B6: A7 AND A ; ... been hit? 06B7: C2 D6 06 JP NZ,$06D6 ; Yes ... don't move it 06BA: 21 8A 20 LD HL,$208A ; Saucer's structure 06BD: 7E LD A,(HL) ; Get saucer's Y coordinate 06BE: 23 INC HL ; Bump to ... 06BF: 23 INC HL ; ... delta Y 06C0: 86 ADD A,(HL) ; Move saucer 06C1: 32 8A 20 LD ($208A),A ; New coordinate 06C4: CD 3C 07 CALL $073C ; Draw the flying saucer 06C7: 21 8A 20 LD HL,$208A ; Saucer's structure 06CA: 7E LD A,(HL) ; Y coordinate 06CB: FE 28 CP $28 ; Too low? End of screen? 06CD: DA F9 06 JP C,$06F9 ; Yes ... remove from play 06D0: FE E1 CP $E1 ; Too high? End of screen? 06D2: D2 F9 06 JP NC,$06F9 ; Yes ... remove from play 06D5: C9 RET ; Done 06D6: 06 FE LD B,$FE ; Turn off ... 06D8: CD DC 19 CALL $19DC ; ... flying saucer sound 06DB: 23 INC HL ; (2086) show-hit timer 06DC: 35 DEC (HL) ; Count down show-hit timer 06DD: 7E LD A,(HL) ; Get current value 06DE: FE 1F CP $1F ; Starts at 20 ... is this the first tick of show-hit timer? 06E0: CA 4B 07 JP Z,$074B ; Yes ... go show the explosion 06E3: FE 18 CP $18 ; A little later ... 06E5: CA 0C 07 JP Z,$070C ; ... show the score besides the saucer and add it 06E8: A7 AND A ; Has timer expired? 06E9: C0 RET NZ ; No ... let it run 06EA: 06 EF LD B,$EF ; 1110_1111 (mask off saucer hit sound) 06EC: 21 98 20 LD HL,$2098 ; Get current ... 06EF: 7E LD A,(HL) ; ... value of port 5 sound 06F0: A0 AND B ; Mask off the saucer-hit sound 06F1: 77 LD (HL),A ; Set the new value 06F2: E6 20 AND $20 ; All sound off but ... 06F4: D3 05 OUT ($05),A ; ... cocktail cabinet bit 06F6: 00 NOP ; %% Why 06F7: 00 NOP ; %% 06F8: 00 NOP ; %% ; 06F9: CD 42 07 CALL $0742 ; Covert pixel pos from descriptor to HL screen and shift 06FC: CD CB 14 CALL $14CB ; Clear a one byte sprite at HL 06FF: 21 83 20 LD HL,$2083 ; Saucer structure 0702: 06 0A LD B,$0A ; 10 bytes in saucer structure 0704: CD 5F 07 CALL $075F ; Re-initialize saucer structure 0707: 06 FE LD B,$FE ; Turn off UFO ... 0709: C3 DC 19 JP $19DC ; ... sound and out 070C: 3E 01 LD A,$01 ; Flag the score ... 070E: 32 F1 20 LD ($20F1),A ; ... needs updating 0711: 2A 8D 20 LD HL,($208D) ; Saucer score table 0714: 46 LD B,(HL) ; Get score for this saucer 0715: 0E 04 LD C,$04 ; There are only 4 possibilities 0717: 21 50 1D LD HL,$1D50 ; Possible scores table 071A: 11 4C 1D LD DE,$1D4C ; Print strings for each score 071D: 1A LD A,(DE) ; Find ... 071E: B8 CP B ; ... the ... 071F: CA 28 07 JP Z,$0728 ; ... print ... 0722: 23 INC HL ; ... string ... 0723: 13 INC DE ; ... for ... 0724: 0D DEC C ; ... the ... 0725: C2 1D 07 JP NZ,$071D ; ... score 0728: 7E LD A,(HL) ; Get LSB of message (MSB is 2088 which is 1D) 0729: 32 87 20 LD ($2087),A ; Message's LSB (_50=1D94 100=1D97 150=1D9A 300=1D9D) 072C: 26 00 LD H,$00 ; MSB = 0 ... 072E: 68 LD L,B ; HL = B 072F: 29 ADD HL,HL ; *2 0730: 29 ADD HL,HL ; *4 0731: 29 ADD HL,HL ; *8 0732: 29 ADD HL,HL ; *16 0733: 22 F2 20 LD ($20F2),HL ; Add score for hitting saucer (015 becomes 150 in BCD). 0736: CD 42 07 CALL $0742 ; Get the flying saucer score descriptor 0739: C3 F1 08 JP $08F1 ; Print the three-byte score and out 073C: CD 42 07 CALL $0742 ; Draw the ... 073F: C3 39 14 JP $1439 ; ... flying saucer 0742: 21 87 20 LD HL,$2087 ; Read flying saucer ... 0745: CD 3B 1A CALL $1A3B ; ... structure 0748: C3 47 1A JP $1A47 ; Convert pixel number to screen and shift and out ; 074B: 06 10 LD B,$10 ; Saucer hit sound bit 074D: 21 98 20 LD HL,$2098 ; Current state of sounds 0750: 7E LD A,(HL) ; OR ... 0751: B0 OR B ; ... in ... 0752: 77 LD (HL),A ; ... saucer-hit sound 0753: CD 70 17 CALL $1770 ; Turn off fleet sound and start saucer-hit 0756: 21 7C 1D LD HL,$1D7C ; Sprite for saucer blowing up 0759: 22 87 20 LD ($2087),HL ; Store it in structure 075C: C3 3C 07 JP $073C ; Draw the flying saucer ; 075F: 11 83 1B LD DE,$1B83 ; Data for saucer (702 sets count to 0A) 0762: C3 32 1A JP $1A32 ; Reset saucer object data ;##-WaitForStart ; Wait for player 1 start button press 0765: 3E 01 LD A,$01 ; Tell ISR that we ... 0767: 32 93 20 LD ($2093),A ; ... have started to wait 076A: 31 00 24 LD SP,$2400 ; Reset stack 076D: FB EI ; Enable interrupts 076E: CD 79 19 CALL $1979 ; Suspend game tasks 0771: CD D6 09 CALL $09D6 ; Clear center window 0774: 21 13 30 LD HL,$3013 ; Screen coordinates 0777: 11 F3 1F LD DE,$1FF3 ; "PRESS" 077A: 0E 04 LD C,$04 ; Message length 077C: CD F3 08 CALL $08F3 ; Print it 077F: 3A EB 20 LD A,($20EB) ; Number of credits 0782: 3D DEC A ; Set flags 0783: 21 10 28 LD HL,$2810 ; Screen coordinates 0786: 0E 14 LD C,$14 ; Message length 0788: C2 57 08 JP NZ,$0857 ; Take 1 or 2 player start 078B: 11 CF 1A LD DE,$1ACF ; "ONLY 1PLAYER BUTTON " 078E: CD F3 08 CALL $08F3 ; Print message 0791: DB 01 IN A,($01) ; Read player controls 0793: E6 04 AND $04 ; 1Player start button? 0795: CA 7F 07 JP Z,$077F ; No ... wait for button or credit ;============================================================= ;##-NewGame ; START NEW GAME ; ; 1 Player start 0798: 06 99 LD B,$99 ; Essentially a -1 for DAA 079A: AF XOR A ; Clear two player flag ; ; 2 player start sequence enters here with a=1 and B=98 (-2) 079B: 32 CE 20 LD ($20CE),A ; Set flag for 1 or 2 players 079E: 3A EB 20 LD A,($20EB) ; Number of credits 07A1: 80 ADD A,B ; Take away credits 07A2: 27 DAA ; Convert back to DAA 07A3: 32 EB 20 LD ($20EB),A ; New credit count 07A6: CD 47 19 CALL $1947 ; Display number of credits 07A9: 21 00 00 LD HL,$0000 ; Score of 0000 07AC: 22 F8 20 LD ($20F8),HL ; Clear player-1 score 07AF: 22 FC 20 LD ($20FC),HL ; CLear player-2 score 07B2: CD 25 19 CALL $1925 ; Print player-1 score 07B5: CD 2B 19 CALL $192B ; Print player-2 score 07B8: CD D7 19 CALL $19D7 ; Disable game tasks 07BB: 21 01 01 LD HL,$0101 ; Two bytes 1, 1 07BE: 7C LD A,H ; 1 to A 07BF: 32 EF 20 LD ($20EF),A ; 20EF=1 ... game mode 07C2: 22 E7 20 LD ($20E7),HL ; 20E7 and 20E8 both one ... players 1 and 2 are alive 07C5: 22 E5 20 LD ($20E5),HL ; Extra-ship is available for player-1 and player-2 07C8: CD 56 19 CALL $1956 ; Print scores and credits 07CB: CD EF 01 CALL $01EF ; Draw shields for player-1 07CE: CD F5 01 CALL $01F5 ; Draw shields for player-2 07D1: CD D1 08 CALL $08D1 ; Get number of ships from DIP settings 07D4: 32 FF 21 LD ($21FF),A ; Player-1 ships 07D7: 32 FF 22 LD ($22FF),A ; Player-2 ships 07DA: CD D7 00 CALL $00D7 ; Set player-1 and player-2 alien racks going right 07DD: AF XOR A ; Make a 0 07DE: 32 FE 21 LD ($21FE),A ; Player 1 is on first rack of aliens 07E1: 32 FE 22 LD ($22FE),A ; Player 2 is on first rack of aliens 07E4: CD C0 01 CALL $01C0 ; Initialize 55 aliens for player 1 07E7: CD 04 19 CALL $1904 ; Initialize 55 aliens for player 2 07EA: 21 78 38 LD HL,$3878 ; Screen coordinates for lower-left alien 07ED: 22 FC 21 LD ($21FC),HL ; Initialize reference alien for player 1 07F0: 22 FC 22 LD ($22FC),HL ; Initialize reference alien for player 2 07F3: CD E4 01 CALL $01E4 ; Copy ROM mirror to RAM (2000 - 20C0) 07F6: CD 7F 1A CALL $1A7F ; Initialize ship hold indicator ; 07F9: CD 8D 08 CALL $088D ; Prompt with "PLAY PLAYER " 07FC: CD D6 09 CALL $09D6 ; Clear the playfield 07FF: 00 NOP ; % Why? 0800: AF XOR A ; Make a 0 0801: 32 C1 20 LD ($20C1),A ; Disable isr splash-task animation 0804: CD CF 01 CALL $01CF ; Draw line across screen under player 0807: 3A 67 20 LD A,($2067) ; Current player 080A: 0F RRCA ; Right bit tells all 080B: DA 72 08 JP C,$0872 ; Go do player 1 ; 080E: CD 13 02 CALL $0213 ; Restore shields for player 2 0811: CD CF 01 CALL $01CF ; Draw line across screen under player 0814: CD B1 00 CALL $00B1 ; Initialize alien rack for current player 0817: CD D1 19 CALL $19D1 ; Enable game tasks in ISR 081A: 06 20 LD B,$20 ; Enable ... 081C: CD FA 18 CALL $18FA ; ... sound amplifier ; ; GAME LOOP ; 081F: CD 18 16 CALL $1618 ; Initiate player shot if button pressed 0822: CD 0A 19 CALL $190A ; Collision detect player's shot and rack-bump 0825: CD F3 15 CALL $15F3 ; Count aliens (count to 2082) 0828: CD 88 09 CALL $0988 ; Adjust score (and print) if there is an adjustment 082B: 3A 82 20 LD A,($2082) ; Number of live aliens 082E: A7 AND A ; All aliens gone? 082F: CA EF 09 JP Z,$09EF ; Yes ... end of turn 0832: CD 0E 17 CALL $170E ; Update alien-shot-rate based on player's score 0835: CD 35 09 CALL $0935 ; Check (and handle) extra ship award 0838: CD D8 08 CALL $08D8 ; Adjust alien shot speed 083B: CD 2C 17 CALL $172C ; Shot sound on or off with 2025 083E: CD 59 0A CALL $0A59 ; Check if player is hit 0841: CA 49 08 JP Z,$0849 ; No hit ... jump handler 0844: 06 04 LD B,$04 ; Player hit sound 0846: CD FA 18 CALL $18FA ; Make explosion sound 0849: CD 75 17 CALL $1775 ; Extra-ship sound timer, set fleet-delay, play fleet movement sound 084C: D3 06 OUT ($06),A ; Feed the watchdog 084E: CD 04 18 CALL $1804 ; Control saucer sound 0851: C3 1F 08 JP $081F ; Continue game loop 0854: 00 00 00 ; %% Why? ; Test for 1 or 2 player start button press 0857: 11 BA 1A LD DE,$1ABA ; "1 OR 2PLAYERS BUTTON" 085A: CD F3 08 CALL $08F3 ; Print message 085D: 06 98 LD B,$98 ; -2 (take away 2 credits) 085F: DB 01 IN A,($01) ; Read player controls 0861: 0F RRCA ; Test ... 0862: 0F RRCA ; ... bit 2 0863: DA 6D 08 JP C,$086D ; 2 player button pressed ... do it 0866: 0F RRCA ; Test bit 3 0867: DA 98 07 JP C,$0798 ; One player start ... do it 086A: C3 7F 07 JP $077F ; Keep waiting on credit or button ; 2 PLAYER START 086D: 3E 01 LD A,$01 ; Flag 2 player game 086F: C3 9B 07 JP $079B ; Continue normal startup 0872: CD 1A 02 CALL $021A ; Restore shields for player 1 0875: C3 14 08 JP $0814 ; Continue in game loop 0878: 3A 08 20 LD A,($2008) ; Alien deltaY 087B: 47 LD B,A ; Hold it 087C: 2A 09 20 LD HL,($2009) ; Alien coordinates 087F: EB EX DE,HL ; Coordinates to DE 0880: C3 86 08 JP $0886 ; HL is 21FC or 22FC and out 0883: 00 00 00 ; %% Why? ;##-GetAlRefPtr ; Get pointer to player's alien ref coordiantes 0886: 3A 67 20 LD A,($2067) ; Player data MSB (21 or 22) 0889: 67 LD H,A ; To H 088A: 2E FC LD L,$FC ; 21FC or 22FC ... alien coordinates 088C: C9 RET ; Done ;##-PromptPlayer ; Print "PLAY PLAYER " and blink score for 2 seconds. ; 088D: 21 11 2B LD HL,$2B11 ; Screen coordinates 0890: 11 70 1B LD DE,$1B70 ; Message "PLAY PLAYER<1>" 0893: 0E 0E LD C,$0E ; 14 bytes in message 0895: CD F3 08 CALL $08F3 ; Print the message 0898: 3A 67 20 LD A,($2067) ; Get the player number 089B: 0F RRCA ; C will be set for player 1 089C: 3E 1C LD A,$1C ; The "2" character 089E: 21 11 37 LD HL,$3711 ; Replace the "<1>" with "<2"> 08A1: D4 FF 08 CALL NC,$08FF ; If player 2 ... change the message 08A4: 3E B0 LD A,$B0 ; Delay of 176 (roughly 2 seconds) 08A6: 32 C0 20 LD ($20C0),A ; Set the ISR delay value ; 08A9: 3A C0 20 LD A,($20C0) ; Get the ISR delay value 08AC: A7 AND A ; Has the 2 second delay expired? 08AD: C8 RET Z ; Yes ... done 08AE: E6 04 AND $04 ; Every 4 ISRs ... 08B0: C2 BC 08 JP NZ,$08BC ; ... flash the player's score 08B3: CD CA 09 CALL $09CA ; Get the score descriptor for the active player 08B6: CD 31 19 CALL $1931 ; Draw the score 08B9: C3 A9 08 JP $08A9 ; Back to the top of the wait loop ; 08BC: 06 20 LD B,$20 ; 32 rows (4 characters * 8 bytes each) 08BE: 21 1C 27 LD HL,$271C ; Player-1 score on the screen 08C1: 3A 67 20 LD A,($2067) ; Get the player number 08C4: 0F RRCA ; C will be set for player 1 08C5: DA CB 08 JP C,$08CB ; We have the right score coordinates 08C8: 21 1C 39 LD HL,$391C ; Use coordinates for player-2's score 08CB: CD CB 14 CALL $14CB ; Clear a one byte sprite at HL 08CE: C3 A9 08 JP $08A9 ; Back to the top of the wait loop ;##-GetShipsPerCred ; Get number of ships from DIP settings 08D1: DB 02 IN A,($02) ; DIP settings 08D3: E6 03 AND $03 ; Get number of ships 08D5: C6 03 ADD A,$03 ; From 3-6 08D7: C9 RET ; Out ;##-SpeedShots ; With less than 9 aliens on the screen the alien shots get a tad bit faster. Probably ; because the advancing rack can catch them. ; 08D8: 3A 82 20 LD A,($2082) ; Number of aliens on screen 08DB: FE 09 CP $09 ; More than 8? 08DD: D0 RET NC ; Yes ... leave shot speed alone 08DE: 3E FB LD A,$FB ; Normally FF (-1) ... now FB (-4) 08E0: 32 7E 20 LD ($207E),A ; Speed up alien shots 08E3: C9 RET ; Done 08E4: 3A CE 20 LD A,($20CE) ; Number of players 08E7: A7 AND A ; Skip if ... 08E8: C0 RET NZ ; ... two player 08E9: 21 1C 39 LD HL,$391C ; Player 2's score 08EC: 06 20 LD B,$20 ; 32 rows is 4 digits * 8 rows each 08EE: C3 CB 14 JP $14CB ; Clear a one byte sprite (32 rows long) at HL 08F1: 0E 03 LD C,$03 ; Length of saucer-score message ... fall into print ;##-PrintMessage ; Print a message on the screen ; HL = coordinates ; DE = message buffer ; C = length 08F3: 1A LD A,(DE) ; Get character 08F4: D5 PUSH DE ; Preserve 08F5: CD FF 08 CALL $08FF ; Print character 08F8: D1 POP DE ; Restore 08F9: 13 INC DE ; Next character 08FA: 0D DEC C ; All done? 08FB: C2 F3 08 JP NZ,$08F3 ; Print all of message 08FE: C9 RET ; Out ;============================================================= ;##-DrawChar ; Get pointer to 8 byte sprite number in A and ; draw sprite on screen at HL 08FF: 11 00 1E LD DE,$1E00 ; Character set 0902: E5 PUSH HL ; Preserve 0903: 26 00 LD H,$00 ; MSB=0 0905: 6F LD L,A ; Character number to L 0906: 29 ADD HL,HL ; HL = HL *2 0907: 29 ADD HL,HL ; *4 0908: 29 ADD HL,HL ; *8 (8 bytes each) 0909: 19 ADD HL,DE ; Get pointer to sprite 090A: EB EX DE,HL ; Now into DE 090B: E1 POP HL ; Restore HL 090C: 06 08 LD B,$08 ; 8 bytes each 090E: D3 06 OUT ($06),A ; Feed watchdog 0910: C3 39 14 JP $1439 ; To screen ;##-TimeToSaucer 0913: 3A 09 20 LD A,($2009) ; Reference alien's X coordinate 0916: FE 78 CP $78 ; Don't process saucer timer ... ($78 is 1st rack Yr) 0918: D0 RET NC ; ... unless aliens are closer to bottom 0919: 2A 91 20 LD HL,($2091) ; Time to saucer 091C: 7D LD A,L ; Is it time ... 091D: B4 OR H ; ... for a saucer 091E: C2 29 09 JP NZ,$0929 ; No ... skip flagging 0921: 21 00 06 LD HL,$0600 ; Reset timer to 600 game loops 0924: 3E 01 LD A,$01 ; Flag a ... 0926: 32 83 20 LD ($2083),A ; ... saucer sequence 0929: 2B DEC HL ; Decrement the ... 092A: 22 91 20 LD ($2091),HL ; ... time-to-saucer 092D: C9 RET ; Done ;============================================================= ; Get number of ships for acive player 092E: CD 11 16 CALL $1611 ; HL points to player data 0931: 2E FF LD L,$FF ; Last byte = numbe of ships 0933: 7E LD A,(HL) ; Get number of ships 0934: C9 RET ; Done ;============================================================= ; Award extra ship if score has reached ceiling 0935: CD 10 19 CALL $1910 ; Get descriptor of sorts 0938: 2B DEC HL ; Back up ... 0939: 2B DEC HL ; ... two bytes 093A: 7E LD A,(HL) ; Has extra ship ... 093B: A7 AND A ; already been awarded? 093C: C8 RET Z ; Yes ... ignore 093D: 06 15 LD B,$15 ; Default 1500 093F: DB 02 IN A,($02) ; Read DIP settings 0941: E6 08 AND $08 ; Extra ship at 1000 or 1500 0943: CA 48 09 JP Z,$0948 ; 0=1500 0946: 06 10 LD B,$10 ; Awarded at 1000 0948: CD CA 09 CALL $09CA ; Get score descriptor for active player 094B: 23 INC HL ; MSB of score ... 094C: 7E LD A,(HL) ; ... to accumulator 094D: B8 CP B ; Time for an extra ship? 094E: D8 RET C ; No ... out 094F: CD 2E 09 CALL $092E ; Get pointer to number of ships 0952: 34 INC (HL) ; Bump number of ships 0953: 7E LD A,(HL) ; Get the new total 0954: F5 PUSH AF ; Hang onto it for a bit 0955: 21 01 25 LD HL,$2501 ; Screen coords for ship hold 0958: 24 INC H ; Bump to ... 0959: 24 INC H ; ... next 095A: 3D DEC A ; ... spot 095B: C2 58 09 JP NZ,$0958 ; Find spot for new ship 095E: 06 10 LD B,$10 ; 16 byte sprite 0960: 11 60 1C LD DE,$1C60 ; Player sprite 0963: CD 39 14 CALL $1439 ; Draw the sprite 0966: F1 POP AF ; Restore the count 0967: 3C INC A ; +1 0968: CD 8B 1A CALL $1A8B ; Print the number of ships 096B: CD 10 19 CALL $1910 ; Get descriptor for active player of some sort 096E: 2B DEC HL ; Back up ... 096F: 2B DEC HL ; ... two bytes 0970: 36 00 LD (HL),$00 ; Flag extra ship has been awarded 0972: 3E FF LD A,$FF ; Set timer ... 0974: 32 99 20 LD ($2099),A ; ... for extra-ship sound 0977: 06 10 LD B,$10 ; Make sound ... 0979: C3 FA 18 JP $18FA ; ... for extra man ;##-AlienScoreValue 097C: 21 A0 1D LD HL,$1DA0 ; Table for scores for hitting alien 097F: FE 02 CP $02 ; 0 or 1 (lower two rows) ... 0981: D8 RET C ; ... return HL points to value 10 0982: 23 INC HL ; next value 0983: FE 04 CP $04 ; 2 or 3 (middle two rows) ... 0985: D8 RET C ; ... return HL points to value 20 0986: 23 INC HL ; Top row ... 0987: C9 RET ; ... return HL points to value 30 ;##-AdjustScore ; Adjust the score for the active player. 20F1 is 1 if there is a new value to add. ; The adjustment is in 20F2,20F3. Then print the score. 0988: CD CA 09 CALL $09CA ; Get score structure for active player 098B: 3A F1 20 LD A,($20F1) ; Does the score ... 098E: A7 AND A ; ... need increasing? 098F: C8 RET Z ; No ... done 0990: AF XOR A ; Mark score ... 0991: 32 F1 20 LD ($20F1),A ; ... as adjusted 0994: E5 PUSH HL ; Hold the pointer to the structure 0995: 2A F2 20 LD HL,($20F2) ; Get requested adjustment 0998: EB EX DE,HL ; Adjustment to DE 0999: E1 POP HL ; Get back pointer to structure 099A: 7E LD A,(HL) ; Add adjustment ... 099B: 83 ADD A,E ; ... first byte 099C: 27 DAA ; Adjust it for BCD 099D: 77 LD (HL),A ; Store new LSB 099E: 5F LD E,A ; Add adjustment ... 099F: 23 INC HL ; ... to ... 09A0: 7E LD A,(HL) ; ... second ... 09A1: 8A ADC A,D ; ... byte 09A2: 27 DAA ; Adjust for BCD (cary gets dropped) 09A3: 77 LD (HL),A ; Store second byte 09A4: 57 LD D,A ; Second byte to D (first byte still in E) 09A5: 23 INC HL ; Load ... 09A6: 7E LD A,(HL) ; ... the ... 09A7: 23 INC HL ; ... screen ... 09A8: 66 LD H,(HL) ; ... coordinates ... 09A9: 6F LD L,A ; ... to HL 09AA: C3 AD 09 JP $09AD ; %% Usually a good idea, but wasted here ;##-Print4Digits ; Print 4 digits in DE 09AD: 7A LD A,D ; Get first 2 digits of BCD or hex 09AE: CD B2 09 CALL $09B2 ; Print them 09B1: 7B LD A,E ; Get second 2 digits of BCD or hex (fall into print) ;##-DrawHexByte ; Display 2 digits in A to screen at HL 09B2: D5 PUSH DE ; Preserve 09B3: F5 PUSH AF ; Save for later 09B4: 0F RRCA ; Get ... 09B5: 0F RRCA ; ... 09B6: 0F RRCA ; ... 09B7: 0F RRCA ; ... left digit 09B8: E6 0F AND $0F ; Mask out lower digit's bits 09BA: CD C5 09 CALL $09C5 ; To screen at HL 09BD: F1 POP AF ; Restore digit 09BE: E6 0F AND $0F ; Mask out upper digit 09C0: CD C5 09 CALL $09C5 ; To screen 09C3: D1 POP DE ; Restore 09C4: C9 RET ; Done ; 09C5: C6 1A ADD A,$1A ; Bump to number characters 09C7: C3 FF 08 JP $08FF ; Continue ... ; Get score descriptor for active player 09CA: 3A 67 20 LD A,($2067) ; Get active player 09CD: 0F RRCA ; Test for player 09CE: 21 F8 20 LD HL,$20F8 ; Player 1 score descriptor 09D1: D8 RET C ; Keep it if player 1 is active 09D2: 21 FC 20 LD HL,$20FC ; Else get player 2 descriptor 09D5: C9 RET ; Out ;##-ClearPlayField ; Clear center window of screen 09D6: 21 02 24 LD HL,$2402 ; Thrid from left, top of screen 09D9: 36 00 LD (HL),$00 ; Clear screen byte 09DB: 23 INC HL ; Next in row 09DC: 7D LD A,L ; Get X ... 09DD: E6 1F AND $1F ; ... coordinate 09DF: FE 1C CP $1C ; Edge minus a buffer? 09E1: DA E8 09 JP C,$09E8 ; No ... keep going 09E4: 11 06 00 LD DE,$0006 ; Else ... bump to 09E7: 19 ADD HL,DE ; ... next edge + buffer 09E8: 7C LD A,H ; Get Y coordinate 09E9: FE 40 CP $40 ; Reached bottom? 09EB: DA D9 09 JP C,$09D9 ; No ... keep going 09EE: C9 RET ; Done 09EF: CD 3C 0A CALL $0A3C 09F2: AF XOR A ; Suspend ... 09F3: 32 E9 20 LD ($20E9),A ; ... ISR game tasks 09F6: CD D6 09 CALL $09D6 ; Clear playfield 09F9: 3A 67 20 LD A,($2067) ; Hold current player number ... 09FC: F5 PUSH AF ; ... on stack 09FD: CD E4 01 CALL $01E4 ; Block copy RAM mirror from ROM 0A00: F1 POP AF ; Restore ... 0A01: 32 67 20 LD ($2067),A ; ... current player number 0A04: 3A 67 20 LD A,($2067) ; %% Why load this again? Nobody ever jumps to 0A04? 0A07: 67 LD H,A ; To H 0A08: E5 PUSH HL ; Hold player-data pointer 0A09: 2E FE LD L,$FE ; 2xFE ... rack count 0A0B: 7E LD A,(HL) ; Get the number of racks the player has beaten 0A0C: E6 07 AND $07 ; 0-7 0A0E: 3C INC A ; Now 1-8 0A0F: 77 LD (HL),A ; Update count since player just beat a rack 0A10: 21 A2 1D LD HL,$1DA2 ; Starting coordinate of alien table 0A13: 23 INC HL ; Find the ... 0A14: 3D DEC A ; ... right entry ... 0A15: C2 13 0A JP NZ,$0A13 ; ... in the table 0A18: 7E LD A,(HL) ; Get the starting Y coordiante 0A19: E1 POP HL ; Restore player's pointer 0A1A: 2E FC LD L,$FC ; 2xFC ... 0A1C: 77 LD (HL),A ; Set rack's starting Y coordinate 0A1D: 23 INC HL ; Point to X 0A1E: 36 38 LD (HL),$38 ; Set rack's starting X coordinate to 38 0A20: 7C LD A,H ; Player ... 0A21: 0F RRCA ; ... number to carry 0A22: DA 33 0A JP C,$0A33 ; 2nd player stuff 0A25: 3E 21 LD A,$21 ; Start fleet with ... 0A27: 32 98 20 LD ($2098),A ; ... first sound 0A2A: CD F5 01 CALL $01F5 ; Draw shields for player 2 0A2D: CD 04 19 CALL $1904 ; Initalize aliens for player 2 0A30: C3 04 08 JP $0804 ; Continue at top of game loop ; 0A33: CD EF 01 CALL $01EF ; Draw shields for player 1 0A36: CD C0 01 CALL $01C0 ; Initialize aliens for player 1 0A39: C3 04 08 JP $0804 ; Continue at top of game loop ; 0A3C: CD 59 0A CALL $0A59 ; Check player collision 0A3F: C2 52 0A JP NZ,$0A52 ; Player is not alive ... skip delay 0A42: 3E 30 LD A,$30 ; Half second delay 0A44: 32 C0 20 LD ($20C0),A ; Set ISR timer 0A47: 3A C0 20 LD A,($20C0) ; Has timer expired? 0A4A: A7 AND A ; Check exipre 0A4B: C8 RET Z ; Out if done 0A4C: CD 59 0A CALL $0A59 ; Check player collision 0A4F: CA 47 0A JP Z,$0A47 ; No collision ... wait on timer 0A52: CD 59 0A CALL $0A59 ; Wait for ... 0A55: C2 52 0A JP NZ,$0A52 ; ... collision to end 0A58: C9 RET ; Done ; Check to see if player is hit 0A59: 3A 15 20 LD A,($2015) ; Active player hit flag 0A5C: FE FF CP $FF ; All FFs means player is OK 0A5E: C9 RET ; Out ;##-ScoreForAlien ; Start the hit-alien sound and flag the adjustment for the score. ; B contains the row, which determines the score value. 0A5F: 3A EF 20 LD A,($20EF) ; Are we in ... 0A62: A7 AND A ; ... game mode? 0A63: CA 7C 0A JP Z,$0A7C ; No ... skip scoring in demo 0A66: 48 LD C,B ; Hold row number 0A67: 06 08 LD B,$08 ; Alien hit sound 0A69: CD FA 18 CALL $18FA ; Enable sound 0A6C: 41 LD B,C ; Restore row number 0A6D: 78 LD A,B ; Into A 0A6E: CD 7C 09 CALL $097C ; Look up the score for the alien 0A71: 7E LD A,(HL) ; Get the score value 0A72: 21 F3 20 LD HL,$20F3 ; Pointer to score delta 0A75: 36 00 LD (HL),$00 ; Upper byte of score delta is "00" 0A77: 2B DEC HL ; Point to score delta LSB 0A78: 77 LD (HL),A ; Set score for hitting alien 0A79: 2B DEC HL ; Point to adjust-score-flag 0A7A: 36 01 LD (HL),$01 ; The score will get changed elsewhere 0A7C: 21 62 20 LD HL,$2062 ; Return exploding-alien descriptor 0A7F: C9 RET ; Out ;##-Animate ; Start the ISR moving the sprite. Return when done. 0A80: 3E 02 LD A,$02 ; Start simple linear ... 0A82: 32 C1 20 LD ($20C1),A ; ... sprite animation (splash) 0A85: D3 06 OUT ($06),A ; Feed watchdog 0A87: 3A CB 20 LD A,($20CB) ; Has the ... 0A8A: A7 AND A ; ... sprite reached target? 0A8B: CA 85 0A JP Z,$0A85 ; No ... wait 0A8E: AF XOR A ; Stop ... 0A8F: 32 C1 20 LD ($20C1),A ; ... ISR animation 0A92: C9 RET ; Done ;##-PrintMessageDel ; Print message from DE to screen at HL (length in B) with a ; delay between letters. 0A93: D5 PUSH DE ; Preserve 0A94: 1A LD A,(DE) ; Get character 0A95: CD FF 08 CALL $08FF ; Draw character on screen 0A98: D1 POP DE ; Preserve 0A99: 3E 07 LD A,$07 ; Delay between letters 0A9B: 32 C0 20 LD ($20C0),A ; Set counter 0A9E: 3A C0 20 LD A,($20C0) ; Get counter 0AA1: 3D DEC A ; Is it 1? 0AA2: C2 9E 0A JP NZ,$0A9E ; No ... wait on it 0AA5: 13 INC DE ; Next in message 0AA6: 0D DEC C ; All done? 0AA7: C2 93 0A JP NZ,$0A93 ; No ... do all 0AAA: C9 RET ; Out ;##-SplashSquiggly 0AAB: 21 50 20 LD HL,$2050 ; Pointer to game-object 4 timer 0AAE: C3 4B 02 JP $024B ; Process squiggly-shot in demo mode ;##-OneSecDelay ; Delay 64 interrupts 0AB1: 3E 40 LD A,$40 ; Delay of 64 (tad over 1 sec) 0AB3: C3 D7 0A JP $0AD7 ; Do delay ;##-TwoSecDelay ; Delay 128 interrupts 0AB6: 3E 80 LD A,$80 ; Delay of 80 (tad over 2 sec) 0AB8: C3 D7 0A JP $0AD7 ; Do delay ;##-SplashDemo 0ABB: E1 POP HL ; Drop the call to ABF and ... 0ABC: C3 72 00 JP $0072 ; ... do a demo game loop without sound ;##-ISRSplTasks ; Different types of splash tasks managed by ISR in splash screens. The ISR ; calls this if in splash-mode. These may have been bit flags to allow all 3 ; at the same time. Maybe it is just easier to do a switch with a rotate-to-carry. ; 0ABF: 3A C1 20 LD A,($20C1) ; Get the ISR task number 0AC2: 0F RRCA ; In demo play mode? 0AC3: DA BB 0A JP C,$0ABB ; 1: Yes ... go do game play (without sound) 0AC6: 0F RRCA ; Moving little alien from point A to B? 0AC7: DA 68 18 JP C,$1868 ; 2: Yes ... go move little alien from point A to B 0ACA: 0F RRCA ; Shooting extra "C" with squiggly shot? 0ACB: DA AB 0A JP C,$0AAB ; 4: Yes ... go shoot extra "C" in splash 0ACE: C9 RET ; No task to do ; Message to center of screen. ; Only used in one place for "SPACE INVADERS" 0ACF: 21 14 2B LD HL,$2B14 ; Near center of screen 0AD2: 0E 0F LD C,$0F ; 15 bytes in message 0AD4: C3 93 0A JP $0A93 ; Print and out ;##-WaitOnDelay ; Wait on ISR counter to reach 0 0AD7: 32 C0 20 LD ($20C0),A ; Delay counter 0ADA: 3A C0 20 LD A,($20C0) ; Get current delay 0ADD: A7 AND A ; Zero yet? 0ADE: C2 DA 0A JP NZ,$0ADA ; No ... wait on it 0AE1: C9 RET ; Out ;##-IniSplashAni ; Init the splash-animation block 0AE2: 21 C2 20 LD HL,$20C2 ; The splash-animation descriptor 0AE5: 06 0C LD B,$0C ; C bytes 0AE7: C3 32 1A JP $1A32 ; Block copy DE to descriptor ;============================================================= ; After initialization ... splash screens 0AEA: AF XOR A ; Make a 0 0AEB: D3 03 OUT ($03),A ; Turn off sound 0AED: D3 05 OUT ($05),A ; Turn off sound 0AEF: CD 82 19 CALL $1982 ; Turn off ISR splash-task 0AF2: FB EI ; Enable interrupts (using them for delays) 0AF3: CD B1 0A CALL $0AB1 ; One second delay 0AF6: 3A EC 20 LD A,($20EC) ; Splash screen type 0AF9: A7 AND A ; Set flags based on type 0AFA: 21 17 30 LD HL,$3017 ; Screen coordinates (middle near top) 0AFD: 0E 04 LD C,$04 ; 4 characters in "PLAY" 0AFF: C2 E8 0B JP NZ,$0BE8 ; Not 0 ... do "normal" PLAY 0B02: 11 FA 1C LD DE,$1CFA ; The "PLAy" with an upside down 'Y' 0B05: CD 93 0A CALL $0A93 ; Print the "PLAy" 0B08: 11 AF 1D LD DE,$1DAF ; "SPACE INVADERS" message 0B0B: CD CF 0A CALL $0ACF ; Print to middle-ish of screen 0B0E: CD B1 0A CALL $0AB1 ; One second delay 0B11: CD 15 18 CALL $1815 ; Draw "SCORE ADVANCE TABLE" with print delay 0B14: CD B6 0A CALL $0AB6 ; Two second delay 0B17: 3A EC 20 LD A,($20EC) ; Do splash ... 0B1A: A7 AND A ; ... animations? 0B1B: C2 4A 0B JP NZ,$0B4A ; Not 0 ... no animations ; ; Animate small alien replacing upside-down Y with correct Y 0B1E: 11 95 1A LD DE,$1A95 ; Animate sprite from Y=FE to Y=9E step -1 0B21: CD E2 0A CALL $0AE2 ; Copy to splash-animate structure 0B24: CD 80 0A CALL $0A80 ; Wait for ISR to move sprite (small alien) 0B27: 11 B0 1B LD DE,$1BB0 ; Animate sprite from Y=98 to Y=FF step 1 0B2A: CD E2 0A CALL $0AE2 ; Copy to splash-animate structure 0B2D: CD 80 0A CALL $0A80 ; Wait for ISR to move sprite (alien pulling upside down Y) 0B30: CD B1 0A CALL $0AB1 ; One second delay 0B33: 11 C9 1F LD DE,$1FC9 ; Animate sprite from Y=FF to Y=97 step 1 0B36: CD E2 0A CALL $0AE2 ; Copy to splash-animate structure 0B39: CD 80 0A CALL $0A80 ; Wait for ISR to move sprite (alien pushing Y) 0B3C: CD B1 0A CALL $0AB1 ; One second delay 0B3F: 21 B7 33 LD HL,$33B7 ; Where the splash alien ends up 0B42: 06 0A LD B,$0A ; 10 rows 0B44: CD CB 14 CALL $14CB ; Clear a one byte sprite at HL 0B47: CD B6 0A CALL $0AB6 ; Two second delay ; ; Play demo 0B4A: CD D6 09 CALL $09D6 ; Clear playfield 0B4D: 3A FF 21 LD A,($21FF) ; Number of ships for player-1 0B50: A7 AND A ; If non zero ... 0B51: C2 5D 0B JP NZ,$0B5D ; ... keep it (counts down between demos) 0B54: CD D1 08 CALL $08D1 ; Get number of ships from DIP settings 0B57: 32 FF 21 LD ($21FF),A ; Reset number of ships for player-1 0B5A: CD 7F 1A CALL $1A7F ; Remove a ship from stash and update indicators ; 0B5D: CD E4 01 CALL $01E4 ; Block copy ROM mirror to initialize RAM 0B60: CD C0 01 CALL $01C0 ; Initialize all player 1 aliens 0B63: CD EF 01 CALL $01EF ; Draw shields for player 1 (to buffer) 0B66: CD 1A 02 CALL $021A ; Restore shields for player 1 (to screen) 0B69: 3E 01 LD A,$01 ; ISR splash-task ... 0B6B: 32 C1 20 LD ($20C1),A ; ... playing demo 0B6E: CD CF 01 CALL $01CF ; Draw playfield line ; 0B71: CD 18 16 CALL $1618 ; In demo ... process demo movement and always fire 0B74: CD F1 0B CALL $0BF1 ; Check player shot and aliens bumping edges of screen and hidden message 0B77: D3 06 OUT ($06),A ; Feed watchdog 0B79: CD 59 0A CALL $0A59 ; Has demo player been hit? 0B7C: CA 71 0B JP Z,$0B71 ; No ... continue game 0B7F: AF XOR A ; Remove player shot ... 0B80: 32 25 20 LD ($2025),A ; ... from activity 0B83: CD 59 0A CALL $0A59 ; Wait for demo player ... 0B86: C2 83 0B JP NZ,$0B83 ; ... to stop exploding ; ; Credit information 0B89: AF XOR A ; Turn off ... 0B8A: 32 C1 20 LD ($20C1),A ; ... splash animation 0B8D: CD B1 0A CALL $0AB1 ; One second delay 0B90: CD 88 19 CALL $1988 ; %%Something else at one time? Jump straight to clear-play-field 0B93: 0E 0C LD C,$0C ; Message size 0B95: 21 11 2C LD HL,$2C11 ; Screen coordinates 0B98: 11 90 1F LD DE,$1F90 ; "INSERT COIN" 0B9B: CD F3 08 CALL $08F3 ; Print message 0B9E: 3A EC 20 LD A,($20EC) ; Do splash ... 0BA1: FE 00 CP $00 ; ... animations? 0BA3: C2 AE 0B JP NZ,$0BAE ; Not 0 ... not on this screen 0BA6: 21 11 33 LD HL,$3311 ; Screen coordinates 0BA9: 3E 02 LD A,$02 ; Character "C" 0BAB: CD FF 08 CALL $08FF ; Put an extra "C" for "CCOIN" on the screen 0BAE: 01 9C 1F LD BC,$1F9C ; "<1 OR 2 PLAYERS> " 0BB1: CD 56 18 CALL $1856 ; Load the screen,pointer 0BB4: CD 4C 18 CALL $184C ; Print the message 0BB7: DB 02 IN A,($02) ; Display coin info (bit 7) ... 0BB9: 07 RLCA ; ... on demo screen? 0BBA: DA C3 0B JP C,$0BC3 ; 1 means no ... skip it 0BBD: 01 A0 1F LD BC,$1FA0 ; "*1 PLAYER 1 COIN " 0BC0: CD 3A 18 CALL $183A ; Load the descriptor 0BC3: CD B6 0A CALL $0AB6 ; Print TWO descriptors worth 0BC6: 3A EC 20 LD A,($20EC) ; Doing splash ... 0BC9: FE 00 CP $00 ; ... animation? 0BCB: C2 DA 0B JP NZ,$0BDA ; Not 0 ... not on this screen 0BCE: 11 D5 1F LD DE,$1FD5 ; Animation for small alien to line up with extra "C" 0BD1: CD E2 0A CALL $0AE2 ; Copy the animation block 0BD4: CD 80 0A CALL $0A80 ; Wait for the animation to complete 0BD7: CD 9E 18 CALL $189E ; Animate alien shot to extra "C" 0BDA: 21 EC 20 LD HL,$20EC ; Toggle ... 0BDD: 7E LD A,(HL) ; ... the ... 0BDE: 3C INC A ; ... splash screen ... 0BDF: E6 01 AND $01 ; ... animation for ... 0BE1: 77 LD (HL),A ; ... next time 0BE2: CD D6 09 CALL $09D6 ; Clear play field 0BE5: C3 DF 18 JP $18DF ; Keep splashing 0BE8: 11 AB 1D LD DE,$1DAB ;"PLAY" with normal 'Y' 0BEB: CD 93 0A CALL $0A93 ; Print it 0BEE: C3 0B 0B JP $0B0B ; Continue with splash (HL will be pointing to next message) 0BF1: CD 0A 19 CALL $190A ; Check if player is shot and aliens bumping the edge of screen 0BF4: C3 9A 19 JP $199A ; Check for hidden-message display sequence ;##-MessageCorp ; "TAITO COP" 0BF7: 13 00 08 13 0E 26 02 0E 0F ; %% Why all the space? 0C00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0C20: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0C40: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0C60: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0C80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0CA0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0CC0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0CE0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0D00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0D20: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0D40: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0D60: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0D80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0DA0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0DC0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0DE0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0E00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0E20: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0E40: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0E60: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0E80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0EA0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0EC0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0EE0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0F00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0F20: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0F40: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0F60: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0F80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0FA0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0FC0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0FE0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 1000: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 1020: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 1040: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 1060: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 1080: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 10A0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 10C0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 10E0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 1100: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 1120: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 1140: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 1160: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 1180: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 11A0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 11C0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 11E0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 1200: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 1220: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 1240: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 1260: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 1280: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 12A0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 12C0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 12E0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 1300: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 1320: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 1340: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 1360: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 1380: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 13A0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 13C0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 13E0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ;##-DrawShiftedSprite ; The only differences between this and EraseSimpleSprite is two CPL instructions in the latter and ; the use of AND instead of OR. NOP takes the same amount of time/space as CPL. So the two NOPs ; here make these two parallel routines the same size and speed. ; 1400: 00 NOP ; Time/size pad to match CPL in EraseShiftedSprite 1401: CD 74 14 CALL $1474 ; Convert pixel number to coord and shift 1404: 00 NOP ; Time/size pad to match CPL in EraseShiftedSprite 1405: C5 PUSH BC ; Hold count 1406: E5 PUSH HL ; Hold start coordinate 1407: 1A LD A,(DE) ; Get the picture bits 1408: D3 04 OUT ($04),A ; Store in shift register 140A: DB 03 IN A,($03) ; Read the shifted pixels 140C: B6 OR (HL) ; OR them onto the screen 140D: 77 LD (HL),A ; Store them back to screen 140E: 23 INC HL ; Next colummn on screen 140F: 13 INC DE ; Next in picture 1410: AF XOR A ; Shift over ... 1411: D3 04 OUT ($04),A ; ... to next byte in register (shift in 0) 1413: DB 03 IN A,($03) ; Read the shifted pixels 1415: B6 OR (HL) ; OR them onto the screen 1416: 77 LD (HL),A ; Store them back to screen 1417: E1 POP HL ; Restore starting coordinate 1418: 01 20 00 LD BC,$0020 ; Add 32 ... 141B: 09 ADD HL,BC ; ... to coordinate (move to next row) 141C: C1 POP BC ; Restore count 141D: 05 DEC B ; All done? 141E: C2 05 14 JP NZ,$1405 ; No ... go do all rows 1421: C9 RET ; Done 1422: 00 00 ; %% Why? ;##-EraseSimpleSprite ; Clear a sprite from the screen (standard pixel number descriptor). ; %% We clear 2 bytes even though the draw-simple only draws one. 1424: CD 74 14 CALL $1474 ; Convert pixel number in HL 1427: C5 PUSH BC ; Hold 1428: E5 PUSH HL ; Hold 1429: AF XOR A ; 0 142A: 77 LD (HL),A ; Clear screen byte 142B: 23 INC HL ; Next byte 142C: 77 LD (HL),A ; Clear byte 142D: 23 INC HL ; %% Is this to mimic timing? We increment then pop 142E: E1 POP HL ; Restore screen coordinate 142F: 01 20 00 LD BC,$0020 ; Add 1 row ... 1432: 09 ADD HL,BC ; ... to screen coordinate 1433: C1 POP BC ; Restore counter 1434: 05 DEC B ; All rows done? 1435: C2 27 14 JP NZ,$1427 ; Do all rows 1438: C9 RET ; out ;##-DrawSimpSprite ; Display character to screen ; HL = screen coordinates ; DE = character data ; B = number of rows 1439: C5 PUSH BC ; Preserve counter 143A: 1A LD A,(DE) ; From character set ... 143B: 77 LD (HL),A ; ... to screen 143C: 13 INC DE ; Next in character set 143D: 01 20 00 LD BC,$0020 ; Next row ... 1440: 09 ADD HL,BC ; ... on screen 1441: C1 POP BC ; Restore counter 1442: 05 DEC B ; Decrement counter 1443: C2 39 14 JP NZ,$1439 ; Do all 1446: C9 RET ; Out 1447: 00 00 00 00 00 00 00 00 00 00 00 ; %% Why? ;##-EraseShifted ; Erases a shifted sprite from screen (like for player's explosion) 1452: CD 74 14 CALL $1474 ; Convert pixel number in HL to coorinates with shift 1455: C5 PUSH BC ; Hold BC 1456: E5 PUSH HL ; Hold coordinate 1457: 1A LD A,(DE) ; Get picture value 1458: D3 04 OUT ($04),A ; Value into shift register 145A: DB 03 IN A,($03) ; Read shifted sprite picture 145C: 2F CPL ; Reverse it (erasing bits) 145D: A6 AND (HL) ; Erase the bits from the screen 145E: 77 LD (HL),A ; Store the erased pattern back 145F: 23 INC HL ; Next column on screen 1460: 13 INC DE ; Next in image 1461: AF XOR A ; Shift register over ... 1462: D3 04 OUT ($04),A ; ... 8 bits (shift in 0) 1464: DB 03 IN A,($03) ; Read 2nd byte of image 1466: 2F CPL ; Reverse it (erasing bits) 1467: A6 AND (HL) ; Erase the bits from the screen 1468: 77 LD (HL),A ; Store the erased pattern back 1469: E1 POP HL ; Restore starting coordinate 146A: 01 20 00 LD BC,$0020 ; Add 32 ... 146D: 09 ADD HL,BC ; ... to next row 146E: C1 POP BC ; Restore BC (count) 146F: 05 DEC B ; All rows done? 1470: C2 55 14 JP NZ,$1455 ; No ... erase all 1473: C9 RET ; Done ;##-CnvtPixNumber ; Convert pixel number in HL to screen coordinate and shift amount. ; HL gets screen coordinate. ; Hardware shift-register gets amount. 1474: 7D LD A,L ; Get X coordinate 1475: E6 07 AND $07 ; Shift by pixel position 1477: D3 02 OUT ($02),A ; Write shift amount to hardware 1479: C3 47 1A JP $1A47 ; HL = HL/8 + 2000 (screen coordinate) ;##-RememberShields ; In a multi-player game the player's shields are block-copied to and from RAM between turns. ; HL = screen pointer ; DE = memory buffer ; B = number of rows ; C = number of columns 147C: C5 PUSH BC ; Hold counter 147D: E5 PUSH HL ; Hold start 147E: 7E LD A,(HL) ; From sprite ... (should be DE) 147F: 12 LD (DE),A ; ... to screen ... (should be HL) 1480: 13 INC DE ; Next in sprite 1481: 23 INC HL ; Next on screen 1482: 0D DEC C ; All columns done? 1483: C2 7E 14 JP NZ,$147E ; No ... do multi columns 1486: E1 POP HL ; Restore screen start 1487: 01 20 00 LD BC,$0020 ; Add 32 ... 148A: 09 ADD HL,BC ; ... to get to next row 148B: C1 POP BC ; Pop the counters 148C: 05 DEC B ; All rows done? 148D: C2 7C 14 JP NZ,$147C ; No ... do multi rows 1490: C9 RET ; Done ;##-DrawSprCollision 1491: CD 74 14 CALL $1474 ; Convert pixel number to coord and shift 1494: AF XOR A ; Clear the ... 1495: 32 61 20 LD ($2061),A ; ... collision-detection flag 1498: C5 PUSH BC ; Hold count 1499: E5 PUSH HL ; Hold screen 149A: 1A LD A,(DE) ; Get byte 149B: D3 04 OUT ($04),A ; Write first byte to shift register 149D: DB 03 IN A,($03) ; Read shifted pattern 149F: F5 PUSH AF ; Hold the pattern 14A0: A6 AND (HL) ; Any bits from pixel collide with bits on screen? 14A1: CA A9 14 JP Z,$14A9 ; No ... leave flag alone 14A4: 3E 01 LD A,$01 ; Yes ... set ... 14A6: 32 61 20 LD ($2061),A ; ... collision flag 14A9: F1 POP AF ; Restore the pixel pattern 14AA: B6 OR (HL) ; OR it onto the screen 14AB: 77 LD (HL),A ; Store new screen value 14AC: 23 INC HL ; Next byte on screen 14AD: 13 INC DE ; Next in pixel pattern 14AE: AF XOR A ; Write zero ... 14AF: D3 04 OUT ($04),A ; ... to shift register 14B1: DB 03 IN A,($03) ; Read 2nd half of shifted sprite 14B3: F5 PUSH AF ; Hold pattern 14B4: A6 AND (HL) ; Any bits from pixel collide with bits on screen? 14B5: CA BD 14 JP Z,$14BD ; No ... leave flag alone 14B8: 3E 01 LD A,$01 ; Yes ... set ... 14BA: 32 61 20 LD ($2061),A ; ... collision flag 14BD: F1 POP AF ; Restore the pixel pattern 14BE: B6 OR (HL) ; OR it onto the screen 14BF: 77 LD (HL),A ; Store new screen pattern 14C0: E1 POP HL ; Starting screen coordinate 14C1: 01 20 00 LD BC,$0020 ; Add 32 ... 14C4: 09 ADD HL,BC ; ... to get to next row 14C5: C1 POP BC ; Restore count 14C6: 05 DEC B ; All done? 14C7: C2 98 14 JP NZ,$1498 ; No ... do all rows 14CA: C9 RET ; Done ;##-ClearSmallSprite ; Clear a one byte sprite at HL. B=number of rows. 14CB: AF XOR A ; 0 14CC: C5 PUSH BC ; Preserve BC 14CD: 77 LD (HL),A ; Clear screen byte 14CE: 01 20 00 LD BC,$0020 ; Bump HL ... 14D1: 09 ADD HL,BC ; ... one screen row 14D2: C1 POP BC ; Restore 14D3: 05 DEC B ; All done? 14D4: C2 CC 14 JP NZ,$14CC ; No ... clear all 14D7: C9 RET ;##-PlayerShotHit ; The player's shot hit something (or is being removed from play) ; 14D8: 3A 25 20 LD A,($2025) ; Player shot flag 14DB: FE 05 CP $05 ; Alien explosion in progress? 14DD: C8 RET Z ; Yes ... ignore this function 14DE: FE 02 CP $02 ; Normal movement? 14E0: C0 RET NZ ; No ... out ; 14E1: 3A 29 20 LD A,($2029) ; Get Yr coordinate of player shot 14E4: FE D8 CP $D8 ; Compare to 216 (40 from Top-rotated) 14E6: 47 LD B,A ; Hold value for later 14E7: D2 30 15 JP NC,$1530 ; Yr is within 40 from top initiate miss-explosion (shot flag 3) 14EA: 3A 02 20 LD A,($2002) ; Is an alien ... 14ED: A7 AND A ; ... blowing up? 14EE: C8 RET Z ; No ... out ; 14EF: 78 LD A,B ; Get original Yr coordinate back to A 14F0: FE CE CP $CE ; Compare to 206 (50 from rotated top) 14F2: D2 79 15 JP NC,$1579 ; Yr is within 50 from top? Yes ... saucer must be hit 14F5: C6 06 ADD A,$06 ; Offset to coordinate for wider "explosion" picture 14F7: 47 LD B,A ; Hold that 14F8: 3A 09 20 LD A,($2009) ; Ref alien Y coordianate ; If the lower 4 rows are all empty then the reference alien's Y coordinate will wrap around from 0 to F8. ; At this point the top row of aliens is in the shields and we will assume that everything is within ; the rack. 14FB: FE 90 CP $90 ; This is true if ... 14FD: D2 04 15 JP NC,$1504 ; ... aliens are down in the shields 1500: B8 CP B ; Compare to shot's coordinate 1501: D2 30 15 JP NC,$1530 ; Outside the rack-square ... do miss explosion ;##CodeBug1 ; ; We get here if the player's shot hit something within the rack area (a shot or an alien). ; Find the alien that is (or would be) where the shot hit. If there is no alien alive at the row/column ; thn the player hit an alien missile. If there is an alien then explode the alien. ; ; There is a code bug here, but it is extremely subtle. The algorithm for finding the row/column in the ; rack works by adding 16 to the reference coordinates (X for column, Y for row) until it passes or equals ; the target coordinates. This works great as long as the target point is within the alien's rack area. ; If the reference point is far to the right, the column number will be greater than 11, which messes ; up the column/row-to-pointer math. ; ; The entire rack of aliens is based on the lower left alien. Imagine all aliens are dead except the ; upper left. It wiggles down the screen and enters the players shields on the lower left where it begins ; to eat them. Imagine the player is under his own shields on the right side of the screen and fires a ; shot into his own shield. ; ; The alien is in the rack on row 4 (rows are numbered from bottom up starting with 0). The shot hits ; the shields below the alien's Y coordinate and gets correctly assigned to row 3. The alien is in the rack ; at column 0 (columns are numbered from left to right starting with 0). The shot hits the shields far to ; the right of the alien's X coordinate. The algorithm says it is in column 11. But 0-10 are the only ; correct values. ; ; The column/row-to-pointer math works by multiplying the row by 11 and adding the column. For the alien ; that is 11*4 + 0 = 44. For the shot that is 11*3 +11 = 44. The game thinks the shot hit the alien. ; 1504: 68 LD L,B ; L now holds the shot coordinate (adjusted) 1505: CD 62 15 CALL $1562 ; Look up row number to B 1508: 3A 2A 20 LD A,($202A) ; Player's shot's Xr coordinate ... 150B: 67 LD H,A ; ... to H 150C: CD 6F 15 CALL $156F ; Get alien's coordinate 150F: 22 64 20 LD ($2064),HL ; Put it in the exploding-alien descriptor 1512: 3E 05 LD A,$05 ; Flag alien explosion ... 1514: 32 25 20 LD ($2025),A ; ... in progress 1517: CD 81 15 CALL $1581 ; Get descriptor for alien 151A: 7E LD A,(HL) ; Is alien ... 151B: A7 AND A ; ... alive 151C: CA 30 15 JP Z,$1530 ; No ... must have been an alien shot ; 151F: 36 00 LD (HL),$00 ; Make alien invader dead 1521: CD 5F 0A CALL $0A5F ; Makes alien explosion sound and adjust score 1524: CD 3B 1A CALL $1A3B ; Load 5 byte sprite descriptor 1527: CD D3 15 CALL $15D3 ; Draw explosion sprite on screen 152A: 3E 10 LD A,$10 ; Initiate alien-explosion 152C: 32 03 20 LD ($2003),A ; ... timer to 16 152F: C9 RET ; Out ; ; Player shot leaving playfield, hitting shield, or hitting an alien shot 1530: 3E 03 LD A,$03 ; Mark ... 1532: 32 25 20 LD ($2025),A ; ... player shot hit something other than alien 1535: C3 4A 15 JP $154A ; Finish up ; ;##-AExplodeTime ; Time down the alien explosion. Remove when done. 1538: 21 03 20 LD HL,$2003 ; Decrement alien explosion ... 153B: 35 DEC (HL) ; ... timer 153C: C0 RET NZ ; Not done ... out 153D: 2A 64 20 LD HL,($2064) ; Pixel pointer for exploding alien 1540: 06 10 LD B,$10 ; 16 row pixel 1542: CD 24 14 CALL $1424 ; Clear the explosion sprite from the screen 1545: 3E 04 LD A,$04 ; 4 means that ... 1547: 32 25 20 LD ($2025),A ; ... alien has exploded (remove from active duty) ; 154A: AF XOR A ; Turn off ... 154B: 32 02 20 LD ($2002),A ; ... alien-is-blowing-up flag 154E: 06 F7 LD B,$F7 ; Turn off ... 1550: C3 DC 19 JP $19DC ; ... alien exploding sound 1553: 00 ;##-Cnt16s ; Count number of 16s needed to bring reference (in A) up to target (in H). ; If the reference starts out beyond the target then we add 16s as long as ; the reference has a signed bit. But these aren't signed quantities. This ; doesn't make any sense. This counting algorithm produces questionable ; results if the reference is beyond the target. ; 1554: 0E 00 LD C,$00 ; Count of 16s 1556: BC CP H ; Compare reference coordinate to target 1557: D4 90 15 CALL NC,$1590 ; If reference is greater or equal then do something questionable ... see below 155A: BC CP H ; Compare reference coordinate to target 155B: D0 RET NC ; If reference is greater or equal then done 155C: C6 10 ADD A,$10 ; Add 16 to reference 155E: 0C INC C ; Bump 16s count 155F: C3 5A 15 JP $155A ; Keep testing ;##-FindRow ; L contains a Yr coordinate. Find the row number within the rack that corresponds ; to the Yr coordinate. Return the row coordinate in L and the row number in C. ; 1562: 3A 09 20 LD A,($2009) ; Reference alien Yr coordinate 1565: 65 LD H,L ; Target Yr coordinate to H 1566: CD 54 15 CALL $1554 ; Count 16s needed to bring ref alien to target 1569: 41 LD B,C ; Count to B 156A: 05 DEC B ; Base 0 156B: DE 10 SBC A,$10 ; The counting also adds 16 no matter what 156D: 6F LD L,A ; To coordinate 156E: C9 RET ; Done ;##-FindColumn ; H contains a Xr coordinate. Find the column number within the rack that corresponds ; to the Xr coordinate. Return the column coordinate in H and the column number in C. ; 156F: 3A 0A 20 LD A,($200A) ; Reference alien Yn coordinate 1572: CD 54 15 CALL $1554 ; Count 16s to bring Y to target Y 1575: DE 10 SBC A,$10 ; Subtract off extra 16 1577: 67 LD H,A ; To H 1578: C9 RET ; Done 1579: 3E 01 LD A,$01 ; Mark flying ... 157B: 32 85 20 LD ($2085),A ; ... saucer has been hit 157E: C3 45 15 JP $1545 ; Remove player shot ;##-GetAlienStatPtr ; B is row number. C is column number (starts at 1). ; Return pointer to alien-status flag for current player. 1581: 78 LD A,B ; Hold original 1582: 07 RLCA ; *2 1583: 07 RLCA ; *4 1584: 07 RLCA ; *8 1585: 80 ADD A,B ; *9 1586: 80 ADD A,B ; *10 1587: 80 ADD A,B ; *11 1588: 81 ADD A,C ; Add row offset to column offset 1589: 3D DEC A ; -1 158A: 6F LD L,A ; Set LSB of HL 158B: 3A 67 20 LD A,($2067) ; Set ... 158E: 67 LD H,A ; ... MSB of HL with active player indicator 158F: C9 RET ;##-WrapRef ; This is called if the reference point is greater than the target point. I believe the goal is to ; wrap the reference back around until it is lower than the target point. But the algorithm simply adds ; until the sign bit of the the reference is 0. If the target is 2 and the reference is 238 then this ; algorithm moves the reference 238+16=244 then 244+16=4. Then the algorithm stops. But the reference is ; STILL greater than the target. ; ; Also imagine that the target is 20 and the reference is 40. The algorithm adds 40+16=56, which is not ; negative, so it stops there. ; ; I think the intended code is "JP NC" instead of "JP M", but even that doesn't make sense. ; 1590: 0C INC C ; Increase 16s count 1591: C6 10 ADD A,$10 ; Add 16 to ref 1593: FA 90 15 JP M,$1590 ; Keep going till result is positive 1596: C9 RET ; Out ;##-RackBump ; When rack bumps the edge of the screen then the direction flips and the rack ; drops 8 pixels. The deltaX and deltaY values are changed here. Interestingly ; if there is only one alien left then the right value is 3 instead of the ; usual 2. The left direction is always -2. 1597: 3A 0D 20 LD A,($200D) ; Get rack direction 159A: A7 AND A ; Moving right? 159B: C2 B7 15 JP NZ,$15B7 ; No ... handle moving left ; 159E: 21 A4 3E LD HL,$3EA4 ; Line down the right edge of playfield 15A1: CD C5 15 CALL $15C5 ; Check line down the edge 15A4: D0 RET NC ; Nothing is there ... return 15A5: 06 FE LD B,$FE ; Delta X of -2 15A7: 3E 01 LD A,$01 ; Rack now moving right ; 15A9: 32 0D 20 LD ($200D),A ; Set new rack direction 15AC: 78 LD A,B ; B has delta X 15AD: 32 08 20 LD ($2008),A ; Set new delta X 15B0: 3A 0E 20 LD A,($200E) ; Set delta Y ... 15B3: 32 07 20 LD ($2007),A ; ... to drop rack by 8 15B6: C9 RET ; Done ; 15B7: 21 24 25 LD HL,$2524 ; Line down the left edge of playfield 15BA: CD C5 15 CALL $15C5 ; Check line down the edge 15BD: D0 RET NC ; Nothing is there ... return 15BE: CD F1 18 CALL $18F1 ; Get moving-right delta X value of 2 (3 if just one alien left) 15C1: AF XOR A ; Rack now moving left 15C2: C3 A9 15 JP $15A9 ; Set rack direction ; 15C5: 06 17 LD B,$17 ; Checking 23 bytes down the screen in a line 15C7: 7E LD A,(HL) ; Get screen memory 15C8: A7 AND A ; Is screen memory empty? 15C9: C2 6B 16 JP NZ,$166B ; No ... set carry flag and out 15CC: 23 INC HL ; Next byte on screen 15CD: 05 DEC B ; All column done? 15CE: C2 C7 15 JP NZ,$15C7 ; No ... keep looking 15D1: C9 RET ; Return with carry flag clear 15D2: 00 NOP ; %% Why? Something optimized? ;##-DrawSprite ; Draw sprite at [DE] to screen at pixel position in HL ; The hardware shift register is used in converting pixel positions ; to screen coordinates. 15D3: CD 74 14 CALL $1474 ; Convert pixel number to screen/shift 15D6: E5 PUSH HL ; Preserve screen coordinate 15D7: C5 PUSH BC ; Hold for a second 15D8: E5 PUSH HL ; Hold for a second 15D9: 1A LD A,(DE) ; From sprite data 15DA: D3 04 OUT ($04),A ; Write data to shift register 15DC: DB 03 IN A,($03) ; Read back shifted amount 15DE: 77 LD (HL),A ; Shifted sprite to screen 15DF: 23 INC HL ; Adjacent cell 15E0: 13 INC DE ; Next in sprite data 15E1: AF XOR A ; 0 15E2: D3 04 OUT ($04),A ; Write 0 to shift register 15E4: DB 03 IN A,($03) ; Read back remainder of previous 15E6: 77 LD (HL),A ; Write remainder to adjacent 15E7: E1 POP HL ; Old screen coordinate 15E8: 01 20 00 LD BC,$0020 ; Offset screen ... 15EB: 09 ADD HL,BC ; ... to next row 15EC: C1 POP BC ; Restore count 15ED: 05 DEC B ; All done? 15EE: C2 D7 15 JP NZ,$15D7 ; No ... do all 15F1: E1 POP HL ; Restore HL 15F2: C9 RET ; Done ;##-CountAliens ; Count number of aliens remaining in active game and return count 2082 holds the current count. ; If only 1, 206B gets a flag of 1 %% but ever nobody checks this 15F3: CD 11 16 CALL $1611 ; Get active player descriptor 15F6: 01 00 37 LD BC,$3700 ; B=55 aliens to check? 15F9: 7E LD A,(HL) ; Get byte 15FA: A7 AND A ; Is it a zero? 15FB: CA FF 15 JP Z,$15FF ; Yes ... don't count it 15FE: 0C INC C ; Count the live aliens 15FF: 23 INC HL ; Next alien 1600: 05 DEC B ; Count ... 1601: C2 F9 15 JP NZ,$15F9 ; ... all alien indicators 1604: 79 LD A,C ; Get the count 1605: 32 82 20 LD ($2082),A ; Hold it 1608: FE 01 CP $01 ; Just one? 160A: C0 RET NZ ; No keep going 160B: 21 6B 20 LD HL,$206B ; Set flag if ... 160E: 36 01 LD (HL),$01 ; ... only one alien left 1610: C9 RET ; Out ;##-GetPlayerDataPtr ; Set HL with 2100 if player 1 is active or 2200 if player 2 is active ; 1611: 2E 00 LD L,$00 ; Byte boundary 1613: 3A 67 20 LD A,($2067) ; Active player number 1616: 67 LD H,A ; Set HL to data 1617: C9 RET ; Done ;##-PlrFireOrDemo ; Initiate player fire if button is pressed. ; Demo commands are parsed here if in demo mode 1618: 3A 15 20 LD A,($2015) ; Is there an active player? 161B: FE FF CP $FF ; FF = alive 161D: C0 RET NZ ; Player has been shot - no firing 161E: 21 10 20 LD HL,$2010 ; Get player ... 1621: 7E LD A,(HL) ; ... task ... 1622: 23 INC HL ; ... timer ... 1623: 46 LD B,(HL) ; ... value 1624: B0 OR B ; Is the timer 0 (object active)? 1625: C0 RET NZ ; No ... no firing till player object starts 1626: 3A 25 20 LD A,($2025) ; Does the player have ... 1629: A7 AND A ; ... a shot on the screen? 162A: C0 RET NZ ; Yes ... ignore 162B: 3A EF 20 LD A,($20EF) ; Are we in ... 162E: A7 AND A ; ... game mode? 162F: CA 52 16 JP Z,$1652 ; No ... in demo mode ... constant firing in demo 1632: 3A 2D 20 LD A,($202D) ; Is fire button ... 1635: A7 AND A ; ... being held down? 1636: C2 48 16 JP NZ,$1648 ; Yes ... wait for bounce 1639: CD C0 17 CALL $17C0 ; Read active player controls 163C: E6 10 AND $10 ; Fire-button pressed? 163E: C8 RET Z ; No ... out 163F: 3E 01 LD A,$01 ; Flag 1641: 32 25 20 LD ($2025),A ; Flag shot active 1644: 32 2D 20 LD ($202D),A ; Flag that fire button is down 1647: C9 RET ; Out 1648: CD C0 17 CALL $17C0 ; Read active player controls 164B: E6 10 AND $10 ; Fire-button pressed? 164D: C0 RET NZ ; Yes ... ignore 164E: 32 2D 20 LD ($202D),A ; Else ... clear flag 1651: C9 RET ; Out ; Handle demo (constant fire, parse demo commands) 1652: 21 25 20 LD HL,$2025 ; Demo fires ... 1655: 36 01 LD (HL),$01 ; ... constantly 1657: 2A ED 20 LD HL,($20ED) ; Demo command bufer 165A: 23 INC HL ; Next position 165B: 7D LD A,L ; Command buffer ... 165C: FE 7E CP $7E ; ... wraps around 165E: DA 63 16 JP C,$1663 ; ... Buffer from 1F74 to 1F7E 1661: 2E 74 LD L,$74 ; ... overflow 1663: 22 ED 20 LD ($20ED),HL ; Next demo command 1666: 7E LD A,(HL) ; Get next command 1667: 32 1D 20 LD ($201D),A ; Set command for movement 166A: C9 RET ; Done 166B: 37 SCF ; Set carry flag 166C: C9 RET ; Done 166D: AF XOR A ; 0 166E: CD 8B 1A CALL $1A8B ; Print ZERO ships remain 1671: CD 10 19 CALL $1910 ; Get active-flag ptr for current player 1674: 36 00 LD (HL),$00 ; Flag player is dead 1676: CD CA 09 CALL $09CA ; Get score descriptor for current player 1679: 23 INC HL ; Point to high two digits 167A: 11 F5 20 LD DE,$20F5 ; Current high score upper two digits 167D: 1A LD A,(DE) ; Is player score greater ... 167E: BE CP (HL) ; ... than high score? 167F: 1B DEC DE ; Point to LSB 1680: 2B DEC HL ; Point to LSB 1681: 1A LD A,(DE) ; Go ahead and fetch high score lower two digits 1682: CA 8B 16 JP Z,$168B ; Upper two are the same ... have to check lower two 1685: D2 98 16 JP NC,$1698 ; Player score is lower than high ... nothing to do 1688: C3 8F 16 JP $168F ; Player socre is higher ... go copy the new high score ; 168B: BE CP (HL) ; Is lower digit higher? (upper was the same) 168C: D2 98 16 JP NC,$1698 ; No ... high score is still greater than player's score 168F: 7E LD A,(HL) ; Copy the new ... 1690: 12 LD (DE),A ; ... high score lower two digits 1691: 13 INC DE ; Point to MSB 1692: 23 INC HL ; Point to MSB 1693: 7E LD A,(HL) ; Copy the new ... 1694: 12 LD (DE),A ; ... high score upper two digits 1695: CD 50 19 CALL $1950 ; Draw the new high score 1698: 3A CE 20 LD A,($20CE) ; Number of players 169B: A7 AND A ; Is this a single player game? 169C: CA C9 16 JP Z,$16C9 ; Yes ... short message 169F: 21 03 28 LD HL,$2803 ; Screen coordinates 16A2: 11 A6 1A LD DE,$1AA6 ; "GAME OVER PLAYER< >" 16A5: 0E 14 LD C,$14 ; 20 characters 16A7: CD 93 0A CALL $0A93 ; Print message 16AA: 25 DEC H ; Back up ... 16AB: 25 DEC H ; ... to player indicator 16AC: 06 1B LD B,$1B ; "1" 16AE: 3A 67 20 LD A,($2067) ; Player number 16B1: 0F RRCA ; Is this player 1? 16B2: DA B7 16 JP C,$16B7 ; Yes ... keep the digit 16B5: 06 1C LD B,$1C ; Else ... set digit 2 16B7: 78 LD A,B ; To A 16B8: CD FF 08 CALL $08FF ; Print player number 16BB: CD B1 0A CALL $0AB1 ; Short delay 16BE: CD E7 18 CALL $18E7 ; Get current player "alive" flag 16C1: 7E LD A,(HL) ; Is player ... 16C2: A7 AND A ; ... alive? 16C3: CA C9 16 JP Z,$16C9 ; No ... skip to "GAME OVER" sequence 16C6: C3 ED 02 JP $02ED ; Switch players and game loop ; 16C9: 21 18 2D LD HL,$2D18 ; Screen coordinates 16CC: 11 A6 1A LD DE,$1AA6 ; "GAME OVER PLAYER< >" 16CF: 0E 0A LD C,$0A ; Just the "GAME OVER" part 16D1: CD 93 0A CALL $0A93 ; Print message 16D4: CD B6 0A CALL $0AB6 ; Long delay 16D7: CD D6 09 CALL $09D6 ; Clear center window 16DA: AF XOR A ; Now in ... 16DB: 32 EF 20 LD ($20EF),A ; ... demo mode 16DE: D3 05 OUT ($05),A ; All sound off 16E0: CD D1 19 CALL $19D1 ; Enable ISR game tasks 16E3: C3 89 0B JP $0B89 ; Print credit information and do splash 16E6: 31 00 24 LD SP,$2400 ; Reset stack 16E9: FB EI ; Enable interrupts 16EA: AF XOR A ; Flag ... 16EB: 32 15 20 LD ($2015),A ; ... player is shot 16EE: CD D8 14 CALL $14D8 ; Player's shot collision detection 16F1: 06 04 LD B,$04 ; Player has been hit ... 16F3: CD FA 18 CALL $18FA ; ... sound 16F6: CD 59 0A CALL $0A59 ; Has flag been set? 16F9: C2 EE 16 JP NZ,$16EE ; No ... wait for the flag 16FC: CD D7 19 CALL $19D7 ; Disable ISR game tasks 16FF: 21 01 27 LD HL,$2701 ; Player's stash of ships 1702: CD FA 19 CALL $19FA ; Erase the stash of shps 1705: AF XOR A ; Print ... 1706: CD 8B 1A CALL $1A8B ; ... a zero (number of ships) 1709: 06 FB LD B,$FB ; Turn off ... 170B: C3 6B 19 JP $196B ; ... player shot sound ;##-AShotReloadRate ; Use the player's MSB to determine how fast the aliens reload their ; shots for another fire. 170E: CD CA 09 CALL $09CA ; Get score descriptor for active player 1711: 23 INC HL ; MSB value 1712: 7E LD A,(HL) ; Get the MSB value 1713: 11 B8 1C LD DE,$1CB8 ; Score MSB table 1716: 21 A1 1A LD HL,$1AA1 ; Corresponding fire reload rate table 1719: 0E 04 LD C,$04 ; Only 4 entries (a 5th value of 7 is used after that) 171B: 47 LD B,A ; Hold the score value 171C: 1A LD A,(DE) ; Get lookup from table 171D: B8 CP B ; Compare them 171E: D2 27 17 JP NC,$1727 ; Equal or below ... use this table entry 1721: 23 INC HL ; Next ... 1722: 13 INC DE ; ... entry in table 1723: 0D DEC C ; Do all ... 1724: C2 1C 17 JP NZ,$171C ; ... 4 entries in the tables 1727: 7E LD A,(HL) ; Load the shot reload value 1728: 32 CF 20 LD ($20CF),A ; Save the value for use in shot routine 172B: C9 RET ; Done ; Shot sound on or off depending on 2025 ;##-ShotSound 172C: 3A 25 20 LD A,($2025) ; Player shot flag 172F: FE 00 CP $00 ; Active shot? 1731: C2 39 17 JP NZ,$1739 ; Yes ... go 1734: 06 FD LD B,$FD ; Sound mask 1736: C3 DC 19 JP $19DC ; Mask off sound ; 1739: 06 02 LD B,$02 ; Sound bit 173B: C3 FA 18 JP $18FA ; OR on sound 173E: 00 00 ; %% Why? ;##-TimeFleetSound ; This called from the ISR times down the fleet and sets the flag at 2095 if ; the fleet needs a change in sound handling (new delay, new sound) 1740: 21 9B 20 LD HL,$209B ; Pointer to hold time for fleet 1743: 35 DEC (HL) ; Decrement hold time 1744: CC 6D 17 CALL Z,$176D ; If 0 turn fleet movement sound off 1747: 3A 68 20 LD A,($2068) ; Is player OK? 174A: A7 AND A ; 1 means OK 174B: CA 6D 17 JP Z,$176D ; Player not OK ... fleet movement sound off and out 174E: 21 96 20 LD HL,$2096 ; Current time on fleet sound 1751: 35 DEC (HL) ; Count down 1752: C0 RET NZ ; Not time to change sound ... out 1753: 21 98 20 LD HL,$2098 ; Current sound port 3 value 1756: 7E LD A,(HL) ; Get value 1757: D3 05 OUT ($05),A ; Set sounds 1759: 3A 82 20 LD A,($2082) ; Number of aliens on active screen 175C: A7 AND A ; Is it zero? 175D: CA 6D 17 JP Z,$176D ; Yes ... turn off fleet movement sound and out 1760: 2B DEC HL ; (2097) Point to fleet timer reload 1761: 7E LD A,(HL) ; Get fleet delay value 1762: 2B DEC HL ; (2096) Point to fleet timer 1763: 77 LD (HL),A ; Reload the timer 1764: 2B DEC HL ; Point to change-sound 1765: 36 01 LD (HL),$01 ; (2095) time to change sound 1767: 3E 04 LD A,$04 ; Set hold ... 1769: 32 9B 20 LD ($209B),A ; ... time for fleet sound 176C: C9 RET ; Done 176D: 3A 98 20 LD A,($2098) ; Current sound port 3 value 1770: E6 30 AND $30 ; Mask off fleet movement sounds 1772: D3 05 OUT ($05),A ; Set sounds 1774: C9 RET ; Out ;##-FleetDelayExShip ; This game-loop routine handles two sound functions. The routine does: ; 1) Time out the extra-ship awarded sound and turn it off when done ; 2) Load the fleet sound delay based on number of remaining aliens ; 3) Make the changing fleet sound ; ; The 2095 flag is set by the ISR and cleared here. The ISR does the timing and sets 2095 when it ; is time to make a new fleet sound. ; 1775: 3A 95 20 LD A,($2095) ; Time for new ... 1778: A7 AND A ; ... fleet movement sound? 1779: CA AA 17 JP Z,$17AA ; No ... skip to extra-man timing 177C: 21 11 1A LD HL,$1A11 ; Number of aliens list coupled ... 177F: 11 21 1A LD DE,$1A21 ; ... with delay list 1782: 3A 82 20 LD A,($2082) ; Get the number of aliens on the screen 1785: BE CP (HL) ; Compare it to the first list value 1786: D2 8E 17 JP NC,$178E ; Number of live aliens is higher than value ... use the delay 1789: 23 INC HL ; Move to ... 178A: 13 INC DE ; ... next list value 178B: C3 85 17 JP $1785 ; Find the right delay 178E: 1A LD A,(DE) ; Get the delay from the second list 178F: 32 97 20 LD ($2097),A ; Store the new alien sound delay 1792: 21 98 20 LD HL,$2098 ; Get current state ... 1795: 7E LD A,(HL) ; ... of sound port 1796: E6 30 AND $30 ; Mask off all fleet movement sounds 1798: 47 LD B,A ; Hold the value 1799: 7E LD A,(HL) ; Get current state 179A: E6 0F AND $0F ; This time ONLY the fleet movement sounds 179C: 07 RLCA ; Shift next to next sound 179D: FE 10 CP $10 ; Overflow? 179F: C2 A4 17 JP NZ,$17A4 ; No ... keep it 17A2: 3E 01 LD A,$01 ; Reset back to first sound 17A4: B0 OR B ; Add fleet sounds to current sound value 17A5: 77 LD (HL),A ; Store new sound value 17A6: AF XOR A ; Restart ... 17A7: 32 95 20 LD ($2095),A ; ... waiting on fleet time ; 17AA: 21 99 20 LD HL,$2099 ; Sound timer for award extra ship 17AD: 35 DEC (HL) ; Time expired? 17AE: C0 RET NZ ; No ... leave sound playing 17AF: 06 EF LD B,$EF ; Turn off bit set with #$10 (award extra ship) 17B1: C3 DC 19 JP $19DC ; Stop sound and out ;##-SndOffExtPly 17B4: 06 EF LD B,$EF ; Mask off sound bit 4 (Extended play) 17B6: 21 98 20 LD HL,$2098 ; Current sound content 17B9: 7E LD A,(HL) ; Get current sound bits 17BA: A0 AND B ; Turn off extended play 17BB: 77 LD (HL),A ; Remember settings 17BC: D3 05 OUT ($05),A ; Turn off extended play 17BE: C9 RET ; Out 17BF: 00 ; %% Why? ;##-ReadInputs ; Read control inputs for active player 17C0: 3A 67 20 LD A,($2067) ; Get active player 17C3: 0F RRCA ; Test player 17C4: D2 CA 17 JP NC,$17CA ; Player 2 ... read port 2 17C7: DB 01 IN A,($01) ; Player 1 ... read port 1 17C9: C9 RET ; Out 17CA: DB 02 IN A,($02) ; Get controls for player 2 17CC: C9 RET ; Out ; Check and handle TILT ;##-CheckHandleTilt 17CD: DB 02 IN A,($02) ; Read input port 17CF: E6 04 AND $04 ; Tilt? 17D1: C8 RET Z ; No tilt ... return 17D2: 3A 9A 20 LD A,($209A) ; Already in TILT handle? 17D5: A7 AND A ; 1 = yes 17D6: C0 RET NZ ; Yes ... ignore it now 17D7: 31 00 24 LD SP,$2400 ; Reset stack 17DA: 06 04 LD B,$04 ; Do this 4 times 17DC: CD D6 09 CALL $09D6 ; Clear center window 17DF: 05 DEC B ; All done? 17E0: C2 DC 17 JP NZ,$17DC ; No ... do again 17E3: 3E 01 LD A,$01 ; Flag ... 17E5: 32 9A 20 LD ($209A),A ; ... handling TILT 17E8: CD D7 19 CALL $19D7 ; Disable game tasks 17EB: FB EI ; Re-enable interrupts 17EC: 11 BC 1C LD DE,$1CBC ; Message "TILT" 17EF: 21 16 30 LD HL,$3016 ; Center of screen 17F2: 0E 04 LD C,$04 ; Four letters 17F4: CD 93 0A CALL $0A93 ; Print "TILT" 17F7: CD B1 0A CALL $0AB1 ; Short delay 17FA: AF XOR A ; Zero 17FB: 32 9A 20 LD ($209A),A ; TILT handle over 17FE: 32 93 20 LD ($2093),A ; Back into splash screens 1801: C3 C9 16 JP $16C9 ; Handle game over for player ;##-CtrlSaucerSound 1804: 21 84 20 LD HL,$2084 ; Saucer on screen flag 1807: 7E LD A,(HL) ; Is the saucer ... 1808: A7 AND A ; ... on the screen? 1809: CA 07 07 JP Z,$0707 ; No ... UFO sound off 180C: 23 INC HL ; Saucer hit flag 180D: 7E LD A,(HL) ; (2085) Get saucer hit flag 180E: A7 AND A ; Is saucer in "hit" sequence? 180F: C0 RET NZ ; Yes ... out 1810: 06 01 LD B,$01 ; Retrigger saucer ... 1812: C3 FA 18 JP $18FA ; ... sound (retrigger makes it warble?) ;##-DrawAdvTable ; Draw "SCORE ADVANCE TABLE" 1815: 21 10 28 LD HL,$2810 ; 0x410 is 1040 rotCol=32, rotRow=16 1818: 11 A3 1C LD DE,$1CA3 ; "*SCORE ADVANCE TABLE*" 181B: 0E 15 LD C,$15 ; 21 bytes in message 181D: CD F3 08 CALL $08F3 ; Print message 1820: 3E 0A LD A,$0A ; 10 bytes in every "=xx POINTS" string 1822: 32 6C 20 LD ($206C),A ; Hold the count 1825: 01 BE 1D LD BC,$1DBE ; Coordinate/sprite for drawing table 1828: CD 56 18 CALL $1856 ; Get HL=coordinate, DE=image 182B: DA 37 18 JP C,$1837 ; Move on if done 182E: CD 44 18 CALL $1844 ; Draw 16-byte sprite 1831: C3 28 18 JP $1828 ; Do all in table ; 1834: CD B1 0A CALL $0AB1 ; One second delay 1837: 01 CF 1D LD BC,$1DCF ; Coordinate/message for drawing table 183A: CD 56 18 CALL $1856 ; Get HL=coordinate, DE=message 183D: D8 RET C ; Out if done 183E: CD 4C 18 CALL $184C ; Print message 1841: C3 3A 18 JP $183A ; Do all in table ; 1844: C5 PUSH BC ; Hold BC 1845: 06 10 LD B,$10 ; 16 bytes 1847: CD 39 14 CALL $1439 ; Draw simple 184A: C1 POP BC ; Restore BC 184B: C9 RET ; Out ; 184C: C5 PUSH BC ; Hold BC 184D: 3A 6C 20 LD A,($206C) ; Count of 10 ... 1850: 4F LD C,A ; ... to C 1851: CD 93 0A CALL $0A93 ; Print the message with delay between letters 1854: C1 POP BC ; Restore BC 1855: C9 RET ; Out ;##-ReadPriStruct ; Read a 4-byte print-structure pointed to by BC ; HL=Screen coordiante, DE=pointer to message ; If the first byte is FF then return with C=1. 1856: 0A LD A,(BC) ; Get the screen LSB 1857: FE FF CP $FF ; Valid? 1859: 37 SCF ; If not C will be 1 185A: C8 RET Z ; Return if 255 185B: 6F LD L,A ; Screen LSB to L 185C: 03 INC BC ; Next 185D: 0A LD A,(BC) ; Read screen MSB 185E: 67 LD H,A ; Screen MSB to H 185F: 03 INC BC ; Next 1860: 0A LD A,(BC) ; Read message LSB 1861: 5F LD E,A ; Message LSB to E 1862: 03 INC BC ; Next 1863: 0A LD A,(BC) ; Read message MSB 1864: 57 LD D,A ; Message MSB to D 1865: 03 INC BC ; Next (for next print) 1866: A7 AND A ; Clear C 1867: C9 RET ; Done ;##-SplashSprite ; Moves a sprite up or down in splash mode. Interrupt moves the sprite. When it reaches ; Y value in 20CA the flag at 20CB is raised. The image flips between two pictures every ; 4 movements. 1868: 21 C2 20 LD HL,$20C2 ; Descriptor 186B: 34 INC (HL) ; Change image 186C: 23 INC HL ; Point to delta-x 186D: 4E LD C,(HL) ; Get delta-x 186E: CD D9 01 CALL $01D9 ; Add delta-X and delta-Y to X and Y 1871: 47 LD B,A ; Current y coordinate 1872: 3A CA 20 LD A,($20CA) ; Has sprite reached ... 1875: B8 CP B ; ... target coordinate? 1876: CA 98 18 JP Z,$1898 ; Yes ... flag and out 1879: 3A C2 20 LD A,($20C2) ; Image number 187C: E6 04 AND $04 ; Watching bit 3 for flip delay 187E: 2A CC 20 LD HL,($20CC) ; Image 1881: C2 88 18 JP NZ,$1888 ; Did bit 3 go to 0? No ... keep current image 1884: 11 30 00 LD DE,$0030 ; 16*3 ... 1887: 19 ADD HL,DE ; ... use other image form 1888: 22 C7 20 LD ($20C7),HL ; Image to descriptor structure 188B: 21 C5 20 LD HL,$20C5 ; X,Y,Image descriptor 188E: CD 3B 1A CALL $1A3B ; Read sprite descriptor 1891: EB EX DE,HL ; Image to DE, position to HL 1892: C3 D3 15 JP $15D3 ; Draw the sprite 1895: 00 00 00 1898: 3E 01 LD A,$01 ; Flag that sprite ... 189A: 32 CB 20 LD ($20CB),A ; ... reached location 189D: C9 RET ; Out ;Animate alien shot to extra "C" in splash 189E: 21 50 20 LD HL,$2050 ; Task descriptor for game object 4 (squiggly shot) 18A1: 11 C0 1B LD DE,$1BC0 ; Task info for animate-shot-to-extra-C 18A4: 06 10 LD B,$10 ; Block copy ... 18A6: CD 32 1A CALL $1A32 ; ... 16 bytes 18A9: 3E 02 LD A,$02 ; Set shot sync ... 18AB: 32 80 20 LD ($2080),A ; ... to run the squiggly shot 18AE: 3E FF LD A,$FF ; Shot direction (-1) 18B0: 32 7E 20 LD ($207E),A ; Alien shot delta 18B3: 3E 04 LD A,$04 ; Animate ... 18B5: 32 C1 20 LD ($20C1),A ; ... shot 18B8: 3A 55 20 LD A,($2055) ; Has shot ... 18BB: E6 01 AND $01 ; ... collided? 18BD: CA B8 18 JP Z,$18B8 ; No ... keep waiting 18C0: 3A 55 20 LD A,($2055) ; Wait ... 18C3: E6 01 AND $01 ; ... for explosion ... 18C5: C2 C0 18 JP NZ,$18C0 ; ... to finish 18C8: 21 11 33 LD HL,$3311 ; Here is where the extra C is 18CB: 3E 26 LD A,$26 ; Space character 18CD: 00 NOP ; %% Why? 18CE: CD FF 08 CALL $08FF ; Draw character 18D1: C3 B6 0A JP $0AB6 ; Two second delay and out ; Initializiation comes here ; 18D4: 31 00 24 LD SP,$2400 ; Set stack pointer just below screen 18D7: 06 00 LD B,$00 ; Count 256 bytes 18D9: CD E6 01 CALL $01E6 ; Copy ROM to RAM 18DC: CD 56 19 CALL $1956 ; Print scores and credits ; 18DF: 3E 08 LD A,$08 ; Set alien ... 18E1: 32 CF 20 LD ($20CF),A ; ... shot reload rate 18E4: C3 EA 0A JP $0AEA ; Top of splash screen loop ; Get player-alive flag for OTHER player 18E7: 3A 67 20 LD A,($2067) ; Player data MSB 18EA: 21 E7 20 LD HL,$20E7 ; Alive flags (player 1 and 2) 18ED: 0F RRCA ; Bit 1=1 for player 1 18EE: D0 RET NC ; Player 2 ... we have it ... out 18EF: 23 INC HL ; Player 1's flag 18F0: C9 RET ; Done ; If there is one alien left then the right motion is 3 instead of 2. That's ; why the timing is hard to hit after the change. 18F1: 06 02 LD B,$02 ; Rack moving right delta X 18F3: 3A 82 20 LD A,($2082) ; Number of aliens on screen 18F6: 3D DEC A ; Just one left? 18F7: C0 RET NZ ; No ... use right delta X of 2 18F8: 04 INC B ; Just one alien ... move right at 3 instead of 2 18F9: C9 RET ; Done ;##-SoundBits3On ; Add in bit for sound 18FA: 3A 94 20 LD A,($2094) ; Current value of sound port 18FD: B0 OR B ; Add in new sounds 18FE: 32 94 20 LD ($2094),A ; New value of sound port 1901: D3 03 OUT ($03),A ; Write new value to sound hardware 1903: C9 RET ;##-InitAliensP2 1904: 21 00 22 LD HL,$2200 ; Player 2 data area 1907: C3 C3 01 JP $01C3 ; Initialize player 2 aliens ;##-PlyrShotAndBump 190A: CD D8 14 CALL $14D8 ; Player's shot collision detection 190D: C3 97 15 JP $1597 ; Change alien deltaX and deltaY when rack bumps edges ;##-CurPlyAlive ; Get the current player's alive status 1910: 21 E7 20 LD HL,$20E7 ; Alive flags 1913: 3A 67 20 LD A,($2067) ; Player 1 or 2 1916: 0F RRCA ; Will be 1 if player 1 1917: D8 RET C ; Return if player 1 1918: 23 INC HL ; Bump to player 2 1919: C9 RET ; Return ;##-DrawScoreHead ; Print score header " SCORE<1> HI-SCORE SCORE<2> " 191A: 0E 1C LD C,$1C ; 28 bytes in message 191C: 21 1E 24 LD HL,$241E ; Screen coordinates 191F: 11 E4 1A LD DE,$1AE4 ; Score header message 1922: C3 F3 08 JP $08F3 ; Print score header 1925: 21 F8 20 LD HL,$20F8 ; Player 1 score descriptor 1928: C3 31 19 JP $1931 ; Print score 192B: 21 FC 20 LD HL,$20FC ; Player 2 score descriptor 192E: C3 31 19 JP $1931 ; Print score ;##-DrawScore ; Print score. ; HL = descriptor 1931: 5E LD E,(HL) ; Get score LSB 1932: 23 INC HL ; Next 1933: 56 LD D,(HL) ; Get score MSB 1934: 23 INC HL ; Next 1935: 7E LD A,(HL) ; Get coordinate LSB 1936: 23 INC HL ; Next 1937: 66 LD H,(HL) ; Get coordiante MSB 1938: 6F LD L,A ; Set LSB 1939: C3 AD 09 JP $09AD ; Print 4 digits in DE ; Print message "CREDIT " 193C: 0E 07 LD C,$07 ; 7 bytes in message 193E: 21 01 35 LD HL,$3501 ; Screen coordinates 1941: 11 A9 1F LD DE,$1FA9 ; Message = "CREDIT " 1944: C3 F3 08 JP $08F3 ; Print message ;##-DrawNumCredits ; Display number of credits on screen 1947: 3A EB 20 LD A,($20EB) ; Number of credits 194A: 21 01 3C LD HL,$3C01 ; Screen coordinates 194D: C3 B2 09 JP $09B2 ; Character to screen ;##-PrintHiScore 1950: 21 F4 20 LD HL,$20F4 ; Hi Score descriptor 1953: C3 31 19 JP $1931 ; Print Hi-Score ;##-DrawStatus ; Print scores (with header) and credits (with label) 1956: CD 5C 1A CALL $1A5C ; Clear 2 rows on the screen 1959: CD 1A 19 CALL $191A ; Print score header 195C: CD 25 19 CALL $1925 ; Print player 1 score 195F: CD 2B 19 CALL $192B ; Print player 2 score 1962: CD 50 19 CALL $1950 ; Print hi score 1965: CD 3C 19 CALL $193C ; Print credit lable 1968: C3 47 19 JP $1947 ; Number of credits 196B: CD DC 19 CALL $19DC ; From 170B with B=FB. Turn off player shot sound 196E: C3 71 16 JP $1671 ; Update high-score if player's score is greater 1971: 3E 01 LD A,$01 ; Set flag that ... 1973: 32 6D 20 LD ($206D),A ; ... aliens reached bottom of screen 1976: C3 E6 16 JP $16E6 ; End of round 1979: CD D7 19 CALL $19D7 ; Disable ISR game tasks 197C: CD 47 19 CALL $1947 ; Display number of credits on screen 197F: C3 3C 19 JP $193C ; Print message "CREDIT" 1982: 32 C1 20 LD ($20C1),A ; Set ISR splash task 1985: C9 RET ; Done 1986: 8B 19 ; Points to print TAITO CORPORATION message ... not sure why 1988: C3 D6 09 JP $09D6 ; Clear playfield and out ; Print "*TAITO CORPORATION*" 198B: 21 03 28 LD HL,$2803 ; Screen coordinates 198E: 11 BE 19 LD DE,$19BE ; Message "*TAITO CORPORATION*" 1991: 0E 13 LD C,$13 ; Messgae length 1993: C3 F3 08 JP $08F3 ; Print message 1996: 00 00 00 00 ; %% Why? ;##-CheckHiddenMes ; There is a hidden message "TAITO COP" (with no "R") in the game. It can only be ; displayed in the demonstration game during the splash screens. You must enter ; 2 seqences of buttons. Timing is not critical. As long as you eventually get all ; the buttons up/down in the correct pattern then the game will register the ; sequence. ; ; 1st: 2start(down) 1start(up) 1fire(down) 1left(down) 1right(down) ; 2nd: 2start(up) 1start(down) 1fire(down) 1left(down) 1right(up) ; ; Unfortunately MAME does not deliver the simultaneous button presses correctly. You can see the message in ; MAME by changing 19A6 to 02 and 19B1 to 02. Then the 2start(down) is the only sequence. ; 199A: 3A 1E 20 LD A,($201E) ; Has the 1st "hidden-message" sequence ... 199D: A7 AND A ; ... been registered? 199E: C2 AC 19 JP NZ,$19AC ; Yes ... go look for the 2nd sequence 19A1: DB 01 IN A,($01) ; Get player inputs 19A3: E6 76 AND $76 ; 0111_0110 Keep 2Pstart, 1Pstart, 1Pshot, 1Pleft, 1Pright 19A5: D6 72 SUB $72 ; 0111_0010 1st sequence: 2Pstart, 1Pshot, 1Pleft, 1Pright 19A7: C0 RET NZ ; Not first sequence ... out 19A8: 3C INC A ; Flag that 1st sequence ... 19A9: 32 1E 20 LD ($201E),A ; ... has been entered 19AC: DB 01 IN A,($01) ; Check inputs for 2nd sequence 19AE: E6 76 AND $76 ; 0111_0110 Keep 2Pstart, 1Pstart, 1Pshot, 1Pleft, 1Pright 19B0: FE 34 CP $34 ; 0011_0100 2nd sequence: 1Pstart, 1Pshot, 1Pleft 19B2: C0 RET NZ ; If not second sequence ignore 19B3: 21 1B 2E LD HL,$2E1B ; Screen coordinates 19B6: 11 F7 0B LD DE,$0BF7 ; Message = "TAITO COP" (no R) 19B9: 0E 09 LD C,$09 ; Message length 19BB: C3 F3 08 JP $08F3 ; Print message and out ;##-MessageTaito ; "*TAITO CORPORATION*" 19BE: 28 13 00 08 13 0E 26 02 0E 11 0F 0E 11 19CB: 00 13 08 0E 0D 28 ;##-EnableGameTasks ; Enable ISR game tasks 19D1: 3E 01 LD A,$01 ; Set ISR ... 19D3: 32 E9 20 LD ($20E9),A ; ... game tasks enabled 19D6: C9 RET ; Done ;##-DsableGameTasks ; Disable ISR game tasks ; Clear 20E9 flag 19D7: AF XOR A ; Clear ISR game tasks flag 19D8: C3 D3 19 JP $19D3 ; Save a byte (the RET) 19DB: 00 ; %% Here is the byte saved. I wonder if this was an optimizer pass. ;##-SoundBits3Off ; Turn off bit in sound port 19DC: 3A 94 20 LD A,($2094) ; Current sound effects value 19DF: A0 AND B ; Mask bits off 19E0: 32 94 20 LD ($2094),A ; Store new hold value 19E3: D3 03 OUT ($03),A ; Change sounds 19E5: C9 RET ; Done ;##-DrawNumShips ; Show ships remaining in hold for the player 19E6: 21 01 27 LD HL,$2701 ; Screen coordinates 19E9: CA FA 19 JP Z,$19FA ; None in reserve ... skip display ; Draw line of ships 19EC: 11 60 1C LD DE,$1C60 ; Player sprite 19EF: 06 10 LD B,$10 ; 16 rows 19F1: 4F LD C,A ; Hold count 19F2: CD 39 14 CALL $1439 ; Display 1byte sprite to screen 19F5: 79 LD A,C ; Restore remaining 19F6: 3D DEC A ; All done? 19F7: C2 EC 19 JP NZ,$19EC ; No ... keep going ; Clear remainder of line 19FA: 06 10 LD B,$10 ; 16 rows 19FC: CD CB 14 CALL $14CB ; Clear 1byte sprite at HL 19FF: 7C LD A,H ; Get Y coordinate 1A00: FE 35 CP $35 ; At edge? 1A02: C2 FA 19 JP NZ,$19FA ; No ... do all 1A05: C9 RET ; Out ;##-CompYToBeam ; ; The ISRs set the upper bit of 2072 based on where the beam is. This is compared to the ; upper bit of an object's Y coordinate to decide whic ISR should handle it. When the ; beam passes the halfway point (or near it ... at scanline 96), the upper bit is cleared. ; When the beam reaches the end of the screen the upper bit is set. ; ; The task then runs in the ISR if the Y coordiante bit matches the 2072 flag. Objects that ; are at the top of the screen (upper bit of Y clear) run in the mid-screen ISR when ; the beam has moved to the bottom of the screen. Objects that are at the bottom of the screen ; (upper bit of Y set) run in the end-screen ISR when the beam is moving back to the top. ; ; The pointer to the object's Y coordinate is passed in DE. CF is set if the upper bits are ; the same (the calling ISR should execute the task). ; 1A06: 21 72 20 LD HL,$2072 ; Get the ... 1A09: 46 LD B,(HL) ; ... beam position status 1A0A: 1A LD A,(DE) ; Get the task structure flag 1A0B: E6 80 AND $80 ; Only upper bits count 1A0D: A8 XOR B ; XOR them together 1A0E: C0 RET NZ ; Not the same (CF cleared) 1A0F: 37 SCF ; Set the CF if the same 1A10: C9 RET ; Done ; Alien delay lists. First list is the number of aliens. The second list is the corresponding delay. ; This delay is only for the rate of change in the fleet's sound. ; The check takes the first num-aliens-value that is lower or the same as the actual num-aliens on screen. ; ; The game starts with 55 aliens. The aliens are move/drawn one per interrupt which means it ; takes 55 interrupts. The first delay value is 52 ... which is almost in sync with the number ; of aliens. It is a tad faster and you can observe the sound and steps getting out of sync. ; 1A11: 32 2B 24 1C 16 11 0D 0A 08 07 06 05 04 03 02 01 1A21: 34 2E 27 22 1C 18 15 13 10 0E 0D 0C 0B 09 07 05 1A31: FF ; %% Needless terminator. The list value "1" catches everything. ;##-BlockCopy ; Copy from [DE] to [HL] (b bytes) 1A32: 1A LD A,(DE) ; Copy from [DE] to ... 1A33: 77 LD (HL),A ; ... [HL] 1A34: 23 INC HL ; Next destination 1A35: 13 INC DE ; Next source 1A36: 05 DEC B ; Count in B 1A37: C2 32 1A JP NZ,$1A32 ; Do all 1A3A: C9 RET ; Done ;##-ReadDesc ; Load 5 bytes sprite descriptor from [HL] 1A3B: 5E LD E,(HL) ; Descriptor ... 1A3C: 23 INC HL ; ... sprite ... 1A3D: 56 LD D,(HL) ; ... 1A3E: 23 INC HL ; ... picture 1A3F: 7E LD A,(HL) ; Descriptor ... 1A40: 23 INC HL ; ... screen ... 1A41: 4E LD C,(HL) ; ... 1A42: 23 INC HL ; ... location 1A43: 46 LD B,(HL) ; Number of bytes in sprite 1A44: 61 LD H,C ; From A,C to ... 1A45: 6F LD L,A ; ... H,L 1A46: C9 RET ; Done ;##-ConvToScr ; The screen is organized as one-bit-per-pixel. ; In: HL contains pixel number (bbbbbbbbbbbbbppp) ; Convert from pixel number to screen coordinates (without shift) ; Shift HL right 3 bits (clearing the top 2 bits) ; and set the third bit from the left. 1A47: C5 PUSH BC ; Hold B (will mangle) 1A48: 06 03 LD B,$03 ; 3 shifts (divide by 8) 1A4A: 7C LD A,H ; H to A 1A4B: 1F RRA ; Shift right (into carry, from doesn't matter) 1A4C: 67 LD H,A ; Back to H 1A4D: 7D LD A,L ; L to A 1A4E: 1F RRA ; Shift right (from/to carry) 1A4F: 6F LD L,A ; Back to L 1A50: 05 DEC B ; Do all ... 1A51: C2 4A 1A JP NZ,$1A4A ; ... 3 shifts 1A54: 7C LD A,H ; H to A 1A55: E6 3F AND $3F ; Mask off all but screen (less than or equal 3F) 1A57: F6 20 OR $20 ; Offset into RAM 1A59: 67 LD H,A ; Back to H 1A5A: C1 POP BC ; Restore B 1A5B: C9 RET ; Done ;##-Clear2Rows ; Clear 2 rows on the screen (2 vertical lines when rotated) 1A5C: 21 00 24 LD HL,$2400 ; Screen coordinate 1A5F: 36 00 LD (HL),$00 ; Clear it 1A61: 23 INC HL ; Next byte 1A62: 7C LD A,H ; Have we done ... 1A63: FE 40 CP $40 ; ... 2 rows? 1A65: C2 5F 1A JP NZ,$1A5F ; No ... keep going 1A68: C9 RET ; Out ;##-RestoreShields ; Logically OR the player's shields back onto the playfield ; DE = sprite ; HL = screen ; C = bytes per row ; B = number of rows 1A69: C5 PUSH BC ; Preserve BC 1A6A: E5 PUSH HL ; Hold for a bit 1A6B: 1A LD A,(DE) ; From sprite 1A6C: B6 OR (HL) ; OR with screen 1A6D: 77 LD (HL),A ; Back to screen 1A6E: 13 INC DE ; Next sprite 1A6F: 23 INC HL ; Next on screen 1A70: 0D DEC C ; Row done? 1A71: C2 6B 1A JP NZ,$1A6B ; No ... do entire row 1A74: E1 POP HL ; Original start 1A75: 01 20 00 LD BC,$0020 ; Bump HL by ... 1A78: 09 ADD HL,BC ; ... one screen row 1A79: C1 POP BC ; Restore 1A7A: 05 DEC B ; Row counter 1A7B: C2 69 1A JP NZ,$1A69 ; Do all rows 1A7E: C9 RET ;##-RemoveShip ; Remove a ship from the players stash and update the ; hold indicators on the screen. 1A7F: CD 2E 09 CALL $092E ; Get last byte from player data 1A82: A7 AND A ; Is it 0? 1A83: C8 RET Z ; Skip 1A84: F5 PUSH AF ; Preserve number remaining 1A85: 3D DEC A ; Remove a ship from the stash 1A86: 77 LD (HL),A ; New number of ships 1A87: CD E6 19 CALL $19E6 ; Draw the line of ships 1A8A: F1 POP AF ; Restore number 1A8B: 21 01 25 LD HL,$2501 ; Screen coordinates 1A8E: E6 0F AND $0F ; Make sure it is a digit 1A90: C3 C5 09 JP $09C5 ; Print number remaining ;========================================================== ; DATA FROM HERE DOWN ; 1A93: 00 00 ; Splash screen animation structure 1 ; 00 Image form (increments each draw) ; 00 Delta X ; FF Delta Y is -1 ; B8 X coordinate ; FE Y starting coordiante ; 1C20 Base image (small alien) ; 10 Size of image (16 bytes) ; 9E Target Y coordiante ; 00 Reached Y flag ; 1C20 Base iamge (small alien) 1A95: 00 00 FF B8 FE 20 1C 10 9E 00 20 1C ;##-AShotReloadRate ; The tables at 1CB8 and 1AA1 control how fast shots are created. The speed is based ; on the upper byte of the player's score. For a score of less than or equal 0200 then ; the fire speed is 30. For a score less than or equal 1000 the shot speed is 10. Less ; than or equal 2000 the speed is 0B. Less than or equal 3000 is 08. And anything ; above 3000 is 07. ; ; 1CB8: 02 10 20 30 ; 1AA1: 30 10 0B 08 1AA5: 07 ; Fastest shot firing speed ;##-MessageGOver ; GAME OVER PLAYER< >" 1AA6: 06 00 0C 04 26 0E 15 04 11 26 26 0F 1AB2: 0B 00 18 04 11 24 26 25 ;##-MessageB1or2 ; "1 OR 2PLAYERS BUTTON" 1ABA: 1B 26 0E 11 26 1C 0F 0B 00 18 04 1AC5: 11 12 26 01 14 13 13 0E 0D 26 ;##-Message1Only ; "ONLY 1PLAYER BUTTON " ; Note the space on the end ... both alternatives are same length 1ACF: 0E 0D 0B 18 26 1B 0F 0B 00 18 04 11 26 26 1ADD: 01 14 13 13 0E 0D 26 ;##-MessageScore ; " SCORE<1> HI-SCORE SCORE<2>" 1AE4: 26 12 02 0E 11 04 24 1B 25 26 07 08 1AF0: 3F 12 02 0E 11 04 26 12 02 0E 11 04 1AFC: 24 1C 25 26 ;-------------------------- RAM initialization ----------------------------- ; Coppied to RAM (2000) C0 bytes as initialization. ; See the description of RAM at the top of this file for the details on this data. 1B00: 01 00 00 10 00 00 00 00 02 78 38 78 38 00 F8 00 1B10: 00 80 00 8E 02 FF 05 0C 60 1C 20 30 10 01 00 00 1B20: 00 00 00 BB 03 00 10 90 1C 28 30 01 04 00 FF FF 1B30: 00 00 02 76 04 00 00 00 00 00 04 EE 1C 00 00 03 1B40: 00 00 00 B6 04 00 00 01 00 1D 04 E2 1C 00 00 03 1B50: 00 00 00 82 06 00 00 01 06 1D 04 D0 1C 00 00 03 1B60: FF 00 C0 1C 00 00 10 21 01 00 30 00 12 00 00 00 ; These don't need to be copied over to RAM (see 1BA0 below). ;##-MesssageP1 ; "PLAY PLAYER<1>" 1B70: 0F 0B 00 18 26 0F 0B 00 18 04 11 24 1B 25 FC 1B8F: 00 1B80: 01 FF FF 00 00 00 20 64 1D D0 29 18 02 54 1D 00 1B90: 08 00 06 00 00 01 40 00 01 00 00 10 9E 00 20 1C ; These don't need to be copied over to RAM I believe this to be a mistake. The constant at 01E4 is C0, ; which is the size of this mirror with the added sprite. It should be A0. I believe there was a macro ; to size this area and later the splash screens where put in. Some of the data spilled over into this ; and the macro automatically included it. No harm. ;##AlienSprCYA ; Alien sprite type C pulling upside down Y ; ........ ; **...... ; ..*..... ; ...****. ; ..*.*... ; **..*... ; ...*.... ; .*.**... ; *.****.. ; ...*.**. ; ..****** ; ..****** ; ...*.**. ; *.****.. ; .*.**... ; ........ 1BA0: 00 03 04 78 14 13 08 1A 3D 68 FC FC 68 3D 1A 00 1BB0: 00 00 01 B8 98 A0 1B 10 FF 00 A0 1B 00 00 00 00 ;--------------------------- End of initialization copy ------------------------- ; Shot descriptor for splash shooting the extra "C" 1BC0: 00 10 00 0E 05 00 00 00 00 00 07 D0 1C C8 9B 03 ;##AlienSprCYB ; Alien sprite C pulling upside down Y. Note the difference between this and the first picutre ; above. The Y is closer to the ship. This gives the effect of the Y kind of "sticking" in the ; animation. ; ........ ; ........ ; **...... ; ..*..... ; ...****. ; ..*.*... ; **.*.... ; *..**... ; .*.***.. ; *.**.**. ; .*.***** ; .*.***** ; *.**.**. ; .*.***.. ; *..**... ; ........ ; 1BD0: 00 00 03 04 78 14 0B 19 3A 6D FA FA 6D 3A 19 00 ; More RAM initialization copied by 18D9 1BE0: 00 00 00 00 00 00 00 00 00 01 00 00 01 74 1F 00 1BF0: 80 00 00 00 00 00 1C 2F 00 00 1C 27 00 00 1C 39 ;##-AlienSprA ; Alien sprite type A,B, and C at positions 0 ; ........ ........ ........ ; ........ ........ ........ ; *..***.. ........ ........ ; *..****. ...****. ........ ; .*.****. *.***... *..**... ; .***.**. .*****.* .*.***.. ; ..**.*** ..**.**. *.**.**. ; .*.***** ..****.. .*.***** ; .*.***** ..****.. .*.***** ; ..**.*** ..****.. *.**.**. ; .***.**. ..**.**. .*.***.. ; .*.****. .*****.* *..**... ; *..****. *.***... ........ ; *..***.. ...****. ........ ; ........ ........ ........ ; ........ ........ ........ 1C00: 00 00 39 79 7A 6E EC FA FA EC 6E 7A 79 39 00 00 1C10: 00 00 00 78 1D BE 6C 3C 3C 3C 6C BE 1D 78 00 00 1C20: 00 00 00 00 19 3A 6D FA FA 6D 3A 19 00 00 00 00 ;##-AlienSprB ; Alien sprite type A,B, and C at positions 1 ; ........ ........ ........ ; ........ ........ ........ ; ...***.. ........ ........ ; .*.****. .***.... ........ ; *******. ...**... .*.**... ; *.**.**. .*****.* *.****.. ; ..**.*** *.**.**. ...*.**. ; .*.***** *.****.. ..****** ; .*.***** ..****.. ..****** ; ..**.*** *.****.. ...*.**. ; *.**.**. *.**.**. *.****.. ; *******. .*****.* .*.**... ; .*.****. ...**... ........ ; ...***.. .***.... ........ ; ........ ........ ........ ; ........ ........ ........ 1C30: 00 00 38 7A 7F 6D EC FA FA EC 6D 7F 7A 38 00 00 1C40: 00 00 00 0E 18 BE 6D 3D 3C 3D 6D BE 18 0E 00 00 1C50: 00 00 00 00 1A 3D 68 FC FC 68 3D 1A 00 00 00 00 ;##-PlayerSprite ; Player sprite ; ........ ; ........ ; ****.... ; *****... ; *****... ; *****... ; *****... ; *******. ; ******** ; *******. ; *****... ; *****... ; *****... ; *****... ; ****.... ; ........ 1C60: 00 00 0F 1F 1F 1F 1F 7F FF 7F 1F 1F 1F 1F 0F 00 ;##-PlrBlowupSprites ; ........ ; ..*..... ; *....... ; **..*... ; **...... ; ***..... ; **..**.* ; ****.... ; ****.*.. ; **...... ; ****.*.. ; *..*..*. ; ..*..... ; **...... ; ........ ; *....... ; 1C70: 00 04 01 13 03 07 B3 0F 2F 03 2F 49 04 03 00 01 ; ; ......*. ; ...*.... ; *.*..... ; **...*.* ; .*.*.... ; **...... ; **.**.*. ; ****.... ; ***..*.. ; ***..*.. ; **.*.... ; **.*..*. ; ......*. ; ..*....* ; *...*... ; ...*..*. 1C80: 40 08 05 A3 0A 03 5B 0F 27 27 0B 4B 40 84 11 48 ;##-PlayerShotSpr 1C90: 0F ;....**** ;##-ShotExploding ; *..**..* ; ..****.. ; .******. ; *.****.. ; ..****.* ; .*****.. ; ..*****. ; *..**..* 1C91: 99 3C 7E 3D BC 3E 7C 99 ;##-Message10Pts ; Ran out of space at 1DFE 1C99: 27 1B 1A 26 0F 0E 08 0D 13 12 ; "=10 POINTS" ;##-MessageAdv ; "*SCORE ADVANCE TABLE*" 1CA3: 28 12 02 0E 11 04 26 00 1CAB: 03 15 00 0D 02 04 26 13 1CB3: 00 01 0B 04 28 ;##-AReloadScoreTab ; The tables at 1CB8 and 1AA1 control how fast shots are created. The speed is based ; on the upper byte of the player's score. For a score of less than or equal 0200 then ; the fire speed is 30. For a score less than or equal 1000 the shot speed is 10. Less ; than or equal 2000 the speed is 0B. Less than or equal 3000 is 08. And anything ; above 3000 is 07. ; ; 1AA1: 30 10 0B 08 ; 1AA5: 07 ; Fastest shot firing speed ; 1CB8: 02 10 20 30 ;##-MessageTilt 1CBC: 13 08 0B 13 ; "TILT" ;##-AlienExplode ; Alien exploding sprite ; ........ ; ...*.... ; *..*..*. ; .*...*.. ; ..*.*... ; *......* ; .*....*. ; ........ ; .*....*. ; *......* ; ..*.*... ; .*...*.. ; *..*..*. ; ...*.... ; ........ ; ........ 1CC0: 00 08 49 22 14 81 42 00 42 81 14 22 49 08 00 00 ;##-SquiglyShot ; Squigly shot picture in 4 animation frames ; 1CD0: 44 ; ..*...*. 1CD1: AA ; .*.*.*.* 1CD2: 10 ; ....*... 1CD3: 88 ; ...*...* 1CD4: 54 ; ..*.*.*. 1CD5: 22 ; .*...*.. 1CD6: 10 ; ....*... 1CD7: AA ; .*.*.*.* 1CD8: 44 ; ..*...*. 1CD9: 22 ; .*...*.. 1CDA: 54 ; ..*.*.*. 1CDB: 88 ; ...*...* ;##-AShotExplo ; Alien shot exploding 1CDC: 4A ; .*.*..*. 1CDD: 15 ; *.*.*... 1CDE: BE ; .*****.* 1CDF: 3F ; ******.. 1CE0: 5E ; .****.*. 1CE1: 25 ; *.*..*.. ;##-PlungerShot ; Alien shot ... the plunger looking one 1CE2: 04 ; ..*..... 1CE3: FC ; ..****** 1CE4: 04 ; ..*..... 1CE5: 10 ; ....*... 1CE6: FC ; ..****** 1CE7: 10 ; ....*... 1CE8: 20 ; .....*.. 1CE9: FC ; ..****** 1CEA: 20 ; .....*.. 1CEB: 80 ; .......* 1CEC: FC ; ..****** 1CED: 80 ; .......* ;##-RollShot ; Alien shot ... the rolling one 1CEE: 00 ; ........ 1CEF: FE ; .******* 1CF0: 00 ; ........ 1CF1: 24 ; ..*..*.. 1CF2: FE ; .******* 1CF3: 12 ; .*..*... 1CF4: 00 ; ........ 1CF5: FE ; .******* 1CF6: 00 ; ........ 1CF7: 48 ; ...*..*. 1CF8: FE ; .******* 1CF9: 90 ; ....*..* ;##-MessagePlayUY 1CFA: 0F 0B 00 29 ; "PLAy" with an upside down 'Y' for splash screen 1CFE: 00 00 ;##-ColFireTable ; This table decides which column a shot will fall from. The column number is read from the ; table (1-11) and the pointer increases for the shot type. For instance, the "squiggly" shot ; will fall from columns in this order: 0B, 01, 06, 03. If you play the game you'll see that ; order. ; ; The "plunger" shot uses index 00-0F (inclusive) ; The "squiggly" shot uses index 06-14 (inclusive) ; The "rolling" shot targets the player 1D00: 01 07 01 01 01 04 0B 01 06 03 01 01 0B 09 02 08 1D10: 02 0B 04 07 0A ; ; This appears to be part of the column-firing table, but it is never used. ; Perhaps this was originally intended for the "plunger" shot but then the ; "plunger" was change to target the player specifically. 1D15: 05 02 05 04 06 07 08 0A 06 0A 03 ;##-ShieldImage ; Shield image pattern. 2 x 22 = 44 bytes. ; ;************.... ;*************... ;**************.. ;***************. ;**************** ;..************** ;...************* ;....************ ;....************ ;....************ ;....************ ;....************ ;....************ ;....************ ;...************* ;..************** ;**************** ;**************** ;***************. ;**************.. ;*************... ;************.... ; 1D20: FF 0F FF 1F FF 3F FF 7F FF FF FC FF F8 FF F0 FF F0 FF F0 FF F0 FF 1D36: F0 FF F0 FF F0 FF F8 FF FC FF FF FF FF FF FF 7F FF 3F FF 1F FF 0F 1D4C: 05 10 15 30 ; Table of possible saucer scores 1D50: 94 97 9A 9D ; Table of corresponding string prints for each possible score ;##-SaucerScrTab ; The 208D points here to the score given when the saucer is shot. It advances ; every time the player-shot is removed. The table wraps. Thus the one and only ; 300 comes up every 16 shots (after an initial 8). 1D54: 10 05 05 10 15 10 10 05 30 10 10 10 05 15 10 05 ;##-SpriteSaucer ; ........ ; ........ ; ........ ; ........ ; ..*..... ; ..**.... ; .****... ; ***.**.. ; .*****.. ; ..*****. ; ..*.***. ; .******. ; .******. ; ..*.***. ; ..*****. ; .*****.. ; ***.**.. ; .****... ; ..**.... ; ..*..... ; ........ ; ........ ; ........ ; ........ 1D64: 00 00 00 00 04 0C 1E 37 3E 7C 74 7E 7E 74 7C 3E 37 1E 0C 04 00 00 00 00 ;##-SpriteSaucerExp ;........ ;.*...*.. ;........ ;*.*..*.* ;......*. ;...*.... ;...**..* ;*.****.. ;.**.**.* ;..****.. ;.**.**.. ;*.***... ;....*... ;...*..*. ;.*...**. ;.**.**.* ;*.***... ;...**..* ;...*.... ;.*....*. ;....*..* ;...*.... ;........ ;........ 1D7C: 00 22 00 A5 40 08 98 3D B6 3C 36 1D 10 48 62 B6 1D 98 08 42 90 08 00 00 ;##-SaucSoreStr 1D94: 26 1F 1A ; _50 1D97: 1B 1A 1A ; 100 1D9A: 1B 1F 1A ; 150 1D9D: 1D 1A 1A ; 300 ;##-AlienScores ; Score table for hitting alien type 1DA0: 10 ; Bottom 2 rows 1DA1: 20 ; Middle row 1DA2: 30 ; Highest row ;##-AlienStartTable ; Starting Y coordinates for aliens at beginning of rounds. The first round is initialized to $78 at 07EA. ; After that this table is used for 2nd, 3rd, 4th, 5th, 6th, 7th, 8th, and 9th. The 10th starts over at ; 1DA3 (60). 1DA3: 60 1DA4: 50 1DA5: 48 1DA6: 48 1DA7: 48 1DA8: 40 1DA9: 40 1DAA: 40 ;##-MessagePlayY 1DAB: 0F 0B 00 18 ; "PLAY" with normal Y ;##-MessageInvaders ; "SPACE INVADERS" 1DAF: 12 0F 00 02 04 26 26 08 0D 15 00 03 04 11 12 ; Tables used to draw "SCORE ADVANCE TABLE" information 1DBE: 0E 2C 68 1D ; Flying Saucer 1DC2: 0C 2C 20 1C ; Alien C, sprite 0 1DC6: 0A 2C 40 1C ; Alien B, sprite 1 1DCA: 08 2C 00 1C ; Alien A, sprite 0 1DCE: FF ; End of list ; ;##-AlienScoreTable 1DCF: 0E 2E E0 1D ; "=? MYSTERY" 1DD3: 0C 2E EA 1D ; "=30 POINTS" 1DD7: 0A 2E F4 1D ; "=20 POINTS" 1DDB: 08 2E 99 1C ; "=10 POINTS" 1DDF: FF ; End of list ;##-MessageMyst 1DE0: 27 38 26 0C 18 12 13 04 11 18 ; "=? MYSTERY" ;##-Message30Pts 1DEA: 27 1D 1A 26 0F 0E 08 0D 13 12 ; "=30 POINTS" ;##-Message20Pts 1DF4: 27 1C 1A 26 0F 0E 08 0D 13 12 ; "=20 POINTS" ; Ran out of space here. The "=10" message is up at 1C99. That keeps ; the font table firmly at 1E00. 1DFE: 00 00 ; Padding to put font table at 1E00 ;============================================================= ;##-Characters ; 8 byte sprites ; The screen is turned so rotate these pictures counter-clockwise. ; Some of the font characters at the end were never needed. The ROM overwrites these characters with ; data near the end. For instance, 1F90 would be a character but has the "INSERT COIN" message. The "?" ; character is at 1FC0 and is used in messages as is 1FF8 "-". 1E00: 00 1F 24 44 24 1F 00 00 ; ........ ........ ........ ........ ........ ........ ........ ........ 1E08: 00 7F 49 49 49 36 00 00 ; *****... *******. .*****.. *******. *******. *******. .*****.. *******. 1E10: 00 3E 41 41 41 22 00 00 ; ..*..*.. *..*..*. *.....*. *.....*. *..*..*. ...*..*. *.....*. ...*.... 1E18: 00 7F 41 41 41 3E 00 00 ; ..*...*. *..*..*. *.....*. *.....*. *..*..*. ...*..*. *.....*. ...*.... 1E20: 00 7F 49 49 49 41 00 00 ; ..*..*.. *..*..*. *.....*. *.....*. *..*..*. ...*..*. *.*...*. ...*.... 1E28: 00 7F 48 48 48 40 00 00 ; *****... .**.**.. .*...*.. .*****.. *.....*. ......*. ***...*. *******. 1E30: 00 3E 41 41 45 47 00 00 ; ........ ........ ........ ........ ........ ........ ........ ........ 1E38: 00 7F 08 08 08 7F 00 00 ; ........ ........ ........ ........ ........ ........ ........ ........ 1E40: 00 00 41 7F 41 00 00 00 ; ........ ........ ........ ........ ........ ........ ........ ........ 1E48: 00 02 01 01 01 7E 00 00 ; ........ .*...... *******. *******. *******. *******. .*****.. *******. 1E50: 00 7F 08 14 22 41 00 00 ; *.....*. *....... ...*.... *....... .....*.. ....*... *.....*. ...*..*. 1E58: 00 7F 01 01 01 01 00 00 ; *******. *....... ..*.*... *....... ...**... ...*.... *.....*. ...*..*. 1E60: 00 7F 20 18 20 7F 00 00 ; *.....*. *....... .*...*.. *....... .....*.. ..*..... *.....*. ...*..*. 1E68: 00 7F 10 08 04 7F 00 00 ; ........ .******. *.....*. *....... *******. *******. .*****.. ....**.. 1E70: 00 3E 41 41 41 3E 00 00 ; ........ ........ ........ ........ ........ ........ ........ ........ 1E78: 00 7F 48 48 48 30 00 00 ; ........ ........ ........ ........ ........ ........ ........ ........ 1E80: 00 3E 41 45 42 3D 00 00 ; ........ ........ ........ ........ ........ ........ ........ ........ 1E88: 00 7F 48 4C 4A 31 00 00 ; .*****.. *******. .*..**.. ......*. .******. ..*****. *******. **...**. 1E90: 00 32 49 49 49 26 00 00 ; *.....*. ...*..*. *..*..*. ......*. *....... .*...... .*...... ..*.*... 1E98: 00 40 40 7F 40 40 00 00 ; *.*...*. ..**..*. *..*..*. *******. *....... *....... ..**.... ...*.... 1EA0: 00 7E 01 01 01 7E 00 00 ; .*....*. .*.*..*. *..*..*. ......*. *....... .*...... .*...... ..*.*... 1EA8: 00 7C 02 01 02 7C 00 00 ; *.****.. *...**.. .**..*.. ......*. .******. ..*****. *******. **...**. 1EB0: 00 7F 02 0C 02 7F 00 00 ; ........ ........ ........ ........ ........ ........ ........ ........ 1EB8: 00 63 14 08 14 63 00 00 ; ........ ........ ........ ........ ........ ........ ........ ........ 1EC0: 00 60 10 0F 10 60 00 00 ; ........ ........ ........ ........ ........ ........ ........ ........ 1EC8: 00 43 45 49 51 61 00 00 ; .....**. **....*. .*****.. ........ **...*.. .*....*. ..**.... .*..***. 1ED0: 00 3E 45 49 51 3E 00 00 ; ....*... *.*...*. *.*...*. *....*.. *.*...*. *.....*. ..*.*... *...*.*. 1ED8: 00 00 21 7F 01 00 00 00 ; ****.... *..*..*. *..*..*. *******. *..*..*. *..*..*. ..*..*.. *...*.*. 1EE0: 00 23 45 49 49 31 00 00 ; ....*... *...*.*. *...*.*. *....... *..*..*. *..**.*. *******. *...*.*. 1EE8: 00 42 41 49 59 66 00 00 ; .....**. *....**. .*****.. ........ *...**.. .**..**. ..*..... .***..*. 1EF0: 00 0C 14 24 7F 04 00 00 ; ........ ........ ........ ........ ........ ........ ........ ........ 1EF8: 00 72 51 51 51 4E 00 00 ; ........ ........ ........ ........ ........ ........ ........ ........ 1F00: 00 1E 29 49 49 46 00 00 ; ........ ........ ........ ........ ........ ........ ........ ........ 1F08: 00 40 47 48 50 60 00 00 ; .****... ......*. .**.**.. *...**.. ...*.... ........ ........ ..*.*... 1F10: 00 36 49 49 49 36 00 00 ; *..*.*.. ***...*. *..*..*. *..*..*. ..*.*... *.....*. ........ ..*.*... 1F18: 00 31 49 49 4A 3C 00 00 ; *..*..*. ...*..*. *..*..*. *..*..*. .*...*.. .*...*.. ........ ..*.*... 1F20: 00 08 14 22 41 00 00 00 ; *..*..*. ....*.*. *..*..*. .*.*..*. *.....*. ..*.*... ........ ..*.*... 1F28: 00 00 41 22 14 08 00 00 ; .**...*. .....**. .**.**.. ..****.. ........ ...*.... ........ ..*.*... 1F30: 00 00 00 00 00 00 00 00 ; ........ ........ ........ ........ ........ ........ ........ ........ 1F38: 00 14 14 14 14 14 00 00 ; ........ ........ ........ ........ ........ ........ ........ ........ 1F40: 00 22 14 7F 14 22 00 00 ; ........ ........ 1F48: 00 03 04 78 04 03 00 00 ; .*...*.. **...... ; ..*.*... ..*..... ; *******. ...****. ; ..*.*... ..*..... ; .*...*.. **...... ; ........ ........ ; ........ ........ ;##-MessageP1or2 1F50: 24 1B 26 0E 11 26 1C 26 ; "<1 OR 2 PLAYERS> " 1F58: 0F 0B 00 18 04 11 12 25 1F60: 26 26 ;##-Message1Coin 1F62: 28 1B 26 0F 0B 00 18 04 ; "*1 PLAYER 1 COIN " 1F6A: 11 26 26 1B 26 02 0E 08 1F72: 0D 26 ;##-DemoCommands ; (1=Right, 2=Left) 1F74: 01 01 00 00 01 00 02 01 00 02 01 00 ;##AlienSprCA ; Small alien pushing Y back onto screen ; .....**. ; ....*... ; ****.... ; ....*... ; .....**. ; ....**.. ; ...**... ; .*.**... ; *.****.. ; ...*.**. ; ..****** ; ..****** ; ...*.**. ; *.****.. ; .*.**... ; ........ 1F80: 60 10 0F 10 60 30 18 1A 3D 68 FC FC 68 3D 1A 00 ;##-MessageCoin 1F90: 08 0D 12 04 11 13 26 26 02 0E 08 0D ; "INSERT COIN" ;##-CreditTable 1F9C: 0D 2A 50 1F ; "<1 OR 2 PLAYERS> " to screen at 2A0D 1FA0: 0A 2A 62 1F ; "*1 PLAYER 1 COIN " to screen at 2A0A 1FA4: 07 2A E1 1F ; "*2 PLAYERS 2 COINS" to screen at 2A07 1FA8: FF ; Terminates "table print" ;##-MessageCredit 1FA9: 02 11 04 03 08 13 26 ; "CREDIT " (with space on the end) ;##AlienSprCB ; ........ ; .....**. ; ....*... ; ****.... ; ....*... ; .....**. ; ...***.. ; *..**... ; .*.***.. ; *.**.**. ; .*.***** ; .*.***** ; *.**.**. ; .*.***.. ; *..**... ; ........ 1FB0: 00 60 10 0F 10 60 38 19 3A 6D FA FA 6D 3A 19 00 1FC0: 00 20 40 4D 50 20 00 00 ; "?" 1FC8: 00 ; Splash screen animation structure 3 ; 00 Image form (increments each draw) ; 00 Delta X ; FF Delta Y is -1 ; B8 X coordinate ; FF Y starting coordiante ; 1F80 Base image (small alien with Y) ; 10 Size of image (16 bytes) ; 97 Target Y coordiante ; 00 Reached Y flag ; 1F80 Base iamge (small alien with Y) ; 1FC9: 00 00 FF B8 FF 80 1F 10 97 00 80 1F ; Splash screen animation structure 4 ; 00 Image form (increments each draw) ; 00 Delta X ; 01 Delta Y is 1 ; D0 X coordinate ; 22 Y starting coordiante ; 1C20 Base image (small alien) ; 10 Size of image (16 bytes) ; 94 Target Y coordiante ; 00 Reached Y flag ; 1C20 Base iamge (small alien) ; 1FD5: 00 00 01 D0 22 20 1C 10 94 00 20 1C ;##-Message2Coins 1FE1: 28 1C 26 0F 0B 00 18 04 ; "*2 PLAYERS 2 COINS" 1FE9: 11 12 26 1C 26 02 0E 08 1FF1: 0D 12 ;##-MessagePush 1FF3: 0F 14 12 07 26 ; "PUSH " (with space on the end) 1FF8: 00 08 08 08 08 08 00 00 ; 3F:"-"