1: ; Jet Set Willy JSW48 Game Engine Source 2: ; ====================================== 3: ; JSW Copyright (C) 1984 Matthew Smith & Software Projects 4: 5: ; Commentary Copyright (C) 1985, 2004 J.G.Harston 6: ; See http://mdfs.net/Software/JSW/ 7: ; The source is assembleable with ZMac 8: ; See http://mdfs.net/Software/Z80/ZMac 9: 10: ; This was originally a commented disassembly, but it became easier to type 11: ; up as a source file and create the disassembly from it. 12: 13: ; I have typed this up from my disassembly commentary from an 19-year-old 14: ; exercise book ;) The guardian movement and Willy movement code is not 15: ; commented as I treated it as "magic" code that did it's job! I'd welcome 16: ; anyone else's commentary to be inserted, with appropriate credits. 17: 18: ; These flags control assembly of the JGH extensions. Set to 1 to turn 19: ; them on. 20: 0000 FIXPAUSE1 EQU 0 ; Pause bugfix version 1 21: 0000 FIXPAUSE2 EQU 0 ; Pause bugfix version 2 22: 0001 FIXPAUSE3 EQU 1 ; Pause bugfix version 3 23: 0001 FIXBLOCKS EQU 1 ; Block graphics bugfix 24: 0001 GAMEEXIT EQU 1 ; Allow exit from game 25: 0001 MOREROOMS EQU 1 ; 7-bit rooms 26: 0000 UDTELEPORT EQU 0 ; Up/Down teleport routine 27: 0000 WALLLEFT EQU 0 ; Check for wall when moving left 28: 0000 WALLRIGHT EQU 0 ; Ignore wall when moving right 29: 0001 ROOMSPRITE EQU 1 ; Room data specifies Willy's sprite? 30: ; Geoff/Broad/Elliot extension 31: 32: 8000 ORG &8000 ; Program starts at &8000 33: 34: 35: ; Some terminology 36: ; ================ 37: ; Room 38: ; 256 bytes of data that define a room and what guardians appear in it. 39: ; Guardian Instance 40: ; 2 bytes of data in a room specifying a guardian class and initial 41: ; position. Each room can have up to eight guardian instances. 42: ; Guardian Class 43: ; 8 bytes of data specifying how a guardian moves, its colours, minimum 44: ; and maximum positions and sprite. A JSW game can have up to 127 guardian 45: ; classes, numbered 0-126. 46: ; Sprite 47: ; 32 byte 16x16pixel 1bpp image. Can be numbered in various ways: 48: ; Sprite page/subpage: 49: ; sprite address=Page*256+subpage*32 50: ; Sprite bank/sprite: 51: ; sprite address=&8000+Bank*8192+sprite*32 52: ; Sprite Number: 53: ; sprite address=&9B00+sprite*32 54: ; Guardian 55: ; The guardian classes for a specific room specified by that room's guardian 56: ; instances. 57: ; With acknowledgements to Andrew Broad, JSWMM posting, 03-Apr-2004. 58: 59: 60: ; Guardian Classes 61: ; ================ 62: ; A guardian class is defined by eight bytes in the guardian table at &A000 63: ; 0 - b7=Direction, b3-b0=Type 64: ; Types are: 0=null, 1=horizontal, 2=vertical, 3=rope, 65: ; 4=arrow, 5=horizontal, 6=vertical, 7=rope 66: ; 1 - b7-b4=Animation, b3=BRIGHT, b2-b0=INK 67: ; 2 - Initial X (from room data) 68: ; 3 - Initial Y 69: ; 4 - Speed 70: ; 5 - Sprite page 71: ; 6 - Movement Minimum 72: ; 7 - Movement Maximum 73: 74: 75: ; Screen buffers 76: ; ============== 77: ; To prevent flicker and give fast screen update, JSW writes to two screen 78: ; buffers, copying from buffer 1 to buffer 2 before copying buffer 2 to the 79: ; screen to be displayed. 80: ; The current room is drawn to buffer 1. On each game tick buffer 1 is 81: ; copied to buffer 2. The sprites are draw to buffer 2, then buffer 2 is 82: ; copied to the screen. 83: 4000 SCREEN EQU &4000 ; Screen 84: 6000 SCREEN2 EQU &6000 ; Screen buffer 2 85: 7000 SCREEN1 EQU &7000 ; Screen buffer 1 86: 5800 ATTR EQU &5800 ; Attributes 87: 5C00 ATTR2 EQU &5C00 ; Attribute buffer 2 88: 5E00 ATTR1 EQU &5E00 ; Attribute buffer 1 89: 90: 91: ; Program data areas 92: ; ================== 93: 9800 ATTRS EQU &9800 ; Startup and status attributes 94: A000 GUARDIANS EQU &A000 ; Guardian table 95: A3FF OBJECTS EQU &A3FF ; Object table 96: AB00 SPRITES EQU &AB00 ; Main sprites 97: C000 ROOMS EQU &C000 ; Base of room data 98: 99: 100: ; Current room buffer 101: ; =================== 102: ; On entry to a room its definition is copied here. 103: 8000 ROOM DEFS 256 104: 8080 NAME EQU ROOM+&80 105: 80A0 BACKGROUND EQU ROOM+&A0 106: 80A9 FLOOR EQU ROOM+&A9 107: 80B2 WALL EQU ROOM+&B2 108: 80BB NASTY EQU ROOM+&BB 109: 80C4 SLOPE EQU ROOM+&C4 110: 80CD CONVEYOR EQU ROOM+&CD 111: 80D6 CONV_DIR EQU ROOM+&D6 112: 80D7 CONV_PSN EQU ROOM+&D7 113: 80D9 CONV_NUM EQU ROOM+&D9 114: 80DA SLOPE_DIR EQU ROOM+&DA 115: 80DB SLOPE_PSN EQU ROOM+&DB 116: 80DD SLOPE_NUM EQU ROOM+&DD 117: 80DE BORDER EQU ROOM+&DE 118: 80E1 OBJECT EQU ROOM+&E1 119: 80E9 LEFT EQU ROOM+&E9 120: 80EA RIGHT EQU ROOM+&EA 121: 80EB UP EQU ROOM+&EB 122: 80EC DOWN EQU ROOM+&EC 123: 80ED WILLYSP EQU ROOM+&ED 124: 80F0 INSTANCES EQU ROOM+&F0 125: 126: ; Current room's guardian instance buffer 127: ; ======================================= 128: ; The eight-byte data for each guardian specified in the current room at 129: ; &80F0-&80FF is copied here. If you only save the program code from &8200 130: ; onwards, this terminator will be omitted. Any room with exactly eight 131: ; guardians then continues using nonexistant guardian data past &8140. 132: ; This can happen if a room's eighth guardian is a rope, as a rope uses 133: ; sixteen bytes of guardian data and so will overwrite the terminator. 134: 8100 GUARDIAN DEFS 64 ; Space for 8 guardian instances 135: 8140 FF DEFB &FF ; This terminates the guardians 136: 8141 DEFS &BF ; Spare 137: 138: 139: ; Pixel-line lookup table 140: ; ======================= 141: ; The word at (PIXEL+line*2) is the address of the first character cell on 142: ; pixel line 'line' in the second screen buffer. This makes converting pixel 143: ; cell coordinates to screen address a lot faster and easier. 144: 8200 00600061 PIXEL: DEFW &6000,&6100,&6200,&6300,&6400,&6500,&6600,&6700 ; line 0 00620063 00640065 00660067 145: 8210 20602061 DEFW &6020,&6120,&6220,&6320,&6420,&6520,&6620,&6720 ; line 1 20622063 20642065 20662067 146: 8220 40604061 DEFW &6040,&6140,&6240,&6340,&6440,&6540,&6640,&6740 ; line 2 40624063 40644065 40664067 147: 8230 60606061 DEFW &6060,&6160,&6260,&6360,&6460,&6560,&6660,&6760 ; line 3 60626063 60646065 60666067 148: 8240 80608061 DEFW &6080,&6180,&6280,&6380,&6480,&6580,&6680,&6780 ; line 4 80628063 80648065 80668067 149: 8250 A060A061 DEFW &60A0,&61A0,&62A0,&63A0,&64A0,&65A0,&66A0,&67A0 ; line 5 A062A063 A064A065 A066A067 150: 8260 C060C061 DEFW &60C0,&61C0,&62C0,&63C0,&64C0,&65C0,&66C0,&67C0 ; line 6 C062C063 C064C065 C066C067 151: 8270 E060E061 DEFW &60E0,&61E0,&62E0,&63E0,&64E0,&65E0,&66E0,&67E0 ; line 7 E062E063 E064E065 E066E067 152: 8280 00680069 DEFW &6800,&6900,&6A00,&6B00,&6C00,&6D00,&6E00,&6F00 ; line 8 006A006B 006C006D 006E006F 153: 8290 20682069 DEFW &6820,&6920,&6A20,&6B20,&6C20,&6D20,&6E20,&6F20 ; line 9 206A206B 206C206D 206E206F 154: 82A0 40684069 DEFW &6840,&6940,&6A40,&6B40,&6C40,&6D40,&6E40,&6F40 ; line 10 406A406B 406C406D 406E406F 155: 82B0 60686069 DEFW &6860,&6960,&6A60,&6B60,&6C60,&6D60,&6E60,&6F60 ; line 11 606A606B 606C606D 606E606F 156: 82C0 80688069 DEFW &6880,&6980,&6A80,&6B80,&6C80,&6D80,&6E80,&6F80 ; line 12 806A806B 806C806D 806E806F 157: 82D0 A068A069 PIXTOILET: DEFW &68A0,&69A0,&6AA0,&6BA0,&6CA0,&6DA0,&6EA0,&6FA0 ; line 13 A06AA06B A06CA06D A06EA06F 158: 82E0 C068C069 DEFW &68C0,&69C0,&6AC0,&6BC0,&6CC0,&6DC0,&6EC0,&6FC0 ; line 14 C06AC06B C06CC06D C06EC06F 159: 82F0 E068E069 DEFW &68E0,&69E0,&6AE0,&6BE0,&6CE0,&6DE0,&6EE0,&6FE0 ; line 15 E06AE06B E06CE06D E06EE06F 160: 161: 162: ; Rope structure table 163: ; ==================== 164: 8300 00000000 ROPE: DEFB 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 ; Rope X offsets 00000000 00000000 00000000 165: 8310 00000000 DEFB 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 00000000 00000000 00000000 166: 8320 01010101 DEFB 1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2 01010101 01010101 02020202 167: 8330 02020202 DEFB 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2 02020202 02020202 02020202 168: 8340 02020102 DEFB 2,2,1,2,2,1,1,2,1,1,2,2,3,2,3,2 02010102 01010202 03020302 169: 8350 03030303 DEFB 3,3,3,3,3,3,0,0,0,0,0,0,0,0,0,0 03030000 00000000 00000000 170: 8360 00000000 DEFB 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 00000000 00000000 00000000 171: 8370 00000000 DEFB 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 00000000 00000000 00000000 172: 8380 06060606 DEFB 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6 ; Rope Y offsets 06060606 06060606 06060606 173: 8390 06060606 DEFB 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6 06060606 06060606 06060606 174: 83A0 06060606 DEFB 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6 06060606 06060606 06060606 175: 83B0 04060604 DEFB 4,6,6,4,6,4,6,4,6,4,4,4,6,4,4,4 06040604 06040404 06040404 176: 83C0 04040404 DEFB 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4 04040404 04040404 04040404 177: 83D0 04040404 DEFB 4,4,4,4,4,4,0,0,0,0,0,0,0,0,0,0 04040000 00000000 00000000 178: 83E0 00000000 DEFB 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 00000000 00000000 00000000 179: 83F0 00000000 DEFB 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 00000000 00000000 00000000 180: 181: 182: 183: ; Program starts here 184: ; =================== 185: 8400 F3 START: DI ; Disable interupts 186: 0001 IF GAMEEXIT 187: 8401 31005C LD SP,&5C00 ; Stack is at &5B00-&5BFF 188: 8404 C3CA87 JP GAMESTART ; Jump to GAMESTART to start 189: 190: ; Check a key to start the game, or exit to Basic 191: ; =============================================== 192: ; This is called from the intro screen. If SS-Space is pressed, Basic is 193: ; re-entered with RAMTOP at &7FFF. Otherwise, Enter/Fire/0 are checked. 194: 8407 3E7F L840D: LD A,&7F ; Keyrow 'b'-'spc' 195: 8409 DBFE IN A,(&FE) ; Read from keyboard 196: 840B E603 AND 3 ; SS-SPC pressed? 197: 840D C2C996 JP NZ,L96C9 ; No, check Enter 198: 8410 11FF7F LD DE,&7FFF ; Top of memory 199: 8413 C30500 JP &0005 ; Jump to NEW_ETC 200: ; 201: 8416 00000000 DEFB 0,0,0,0,0 ; Spare 00 202: 841B 00000000 DEFB 0,0,0,0,0 ; Spare 00 203: ELSE 230: ENDIF 231: 232: 8420 00 HERE: DEFB &00 ; Current room number 233: 234: ; Conveyor stuff 235: ; -------------- 236: 8421 00010001 L8421: DEFB 0,1,0,1,1,3,1,3,2,0,2,0,0,1,2,3 01030103 02000200 00010203 237: 238: ; Bitmaps for triangle characters 239: ; ------------------------------- 240: 8431 C0F0FCFF L8431: DEFB &C0,&F0,&FC,&FF,&FF,&FF,&FF,&FF FFFFFFFF 241: 8439 00000000 DEFB &00,&00,&00,&00,&C0,&F0,&FC,&FF C0F0FCFF 242: 8441 FFFFFFFF DEFB &FF,&FF,&FF,&FF,&FC,&F0,&C0,&00 FCF0C000 243: 8449 FCF0C000 DEFB &FC,&F0,&C0,&00,&00,&00,&00,&00 00000000 244: 245: 246: ; Program Strings 247: ; =============== 248: 8451 414952 L8451: DEFB "AIR" 249: 8454 2B2B2B2B MESSAGE: DEFB "+++++ Press ENTER to Start +++++" 2B205072 65737320 454E5445 5220746F 20537461 7274202B 2B2B2B2B 250: 8474 20204A45 DEFB " JET SET WILLY by Matthew Smith " 54205345 54205749 4C4C5920 6279204D 61747468 65772053 6D697468 2020 251: 8496 7F203139 DEFB &7F," 1984 SOFTWARE PROJECTS Ltd " 38342053 4F465457 41524520 50524F4A 45435453 204C7464 20 252: 84B3 2E202E20 DEFB ". . . . .Guide Willy to collect " 2E202E20 2E477569 64652057 696C6C79 20746F20 636F6C6C 65637420 253: 84D3 616C6C20 DEFB "all the items around the house " 74686520 6974656D 73206172 6F756E64 20746865 20686F75 736520 254: 84F2 6265666F DEFB "before Midnight so Maria will let " 7265204D 69646E69 67687420 736F204D 61726961 2077696C 6C206C65 7420 255: 8514 796F7520 DEFB "you get to your bed. . . . . . ." 67657420 746F2079 6F757220 6265642E 202E202E 202E202E 202E202E 256: 8534 2B2B2B2B DEFB "+++++ Press ENTER to Start +++++" 2B205072 65737320 454E5445 5220746F 20537461 7274202B 2B2B2B2B 257: 8554 4974656D ITEMS: DEFB "Items collected 000 Time 00:00 m" 7320636F 6C6C6563 74656420 30303020 54696D65 2030303A 3030206D 258: 8574 47616D65 GAME: DEFB "Game" 259: 8578 4F766572 OVER: DEFB "Over" 260: 857C 303030 COLLECTED: DEFB "000" 261: 857F 20373A30 NOWTIME: DEFB " 7:00a" ; Current time 3061 262: 8585 20373A30 STARTTIME: DEFB " 7:00a" ; Start time 3061 263: 264: 265: ; Password code entry prompts 266: ; =========================== 267: ; This space is spare if the password code is bypassed 268: 858B 456E7465 PROMPT1: DEFB "Enter Code at grid location " 7220436F 64652061 74206772 6964206C 6F636174 696F6E20 20202020 269: 85AB 536F7272 PROMPT2: DEFB "Sorry, try code at location " 792C2074 72792063 6F646520 6174206C 6F636174 696F6E20 20202020 270: 271: 272: ; Game state variables 273: ; ==================== 274: 85CB 00 TICKER: DEFB 0 ; Game ticker, 1/256th of a JSW minute 275: 85CC 00 LIVES: DEFB 0 ; Number of lives left 276: 85CD 00 FLASH: DEFB 0 ; Screen flash counter 277: 85CE 00 KEMPSTON: DEFB 0 ; Kempston joystick present 278: 279: 280: ; Current Willy state 281: ; =================== 282: 85CF 00 YPOSN: DEFB 0 ; Willy's Y position 283: 85D0 00 L85D0: DEFB 0 284: 85D1 00 FALLING: DEFB 0 ; died/movement/falling state - -1/0/1/2 285: 85D2 00 FRAME: DEFB 0 ; Willy's animation frame - 0/1/2/3 286: 85D3 0000 POSITION: DEFW 0 ; Willy's position on screen 287: 85D5 00 JUMPING: DEFB 0 ; jumping 288: 85D6 00 ONROPE: DEFB 0 ; rope flag - 0=not on a rope 289: 290: 291: ; Preserved Willy state 292: ; ===================== 293: ; On entry to a room, Willy's state is saved here and restored if he dies. 294: 85D7 00000000 L85D7: DEFB 0,0,0,0,0,0,0 ; Seven bytes of Willy state 000000 295: 296: 297: ; Other variables 298: ; =============== 299: 85DE 00 REMAIN: DEFB 0 ; Number of objects to collect. 300: 85DF 00 STATUS: DEFB 0 ; Game/finished/flee/vomit flag 301: 85E0 00 COUNTDOWN: DEFB 0 ; Pause countdown timer 302: 85E1 00 MTICK: DEFB 0 ; Music ticker 303: 85E2 00 MFLAGS: DEFB 0 ; Sound on/off flags 304: ; b0: 0='h'-'ent' pressed 305: ; b1: 0=play music, 1=no music 306: 85E3 00 TELEPORT: DEFB 0 ; Number of teleport keys matched 307: ; 10=Teleport ON 308: 85E4 00 TEMP: DEFB 0 ; Temporary location 309: 310: 311: ; Password entry codes 312: ; ==================== 313: ; Each keypress is encoded in two bytes, only b0-b4 relevant. 314: ; First byte is the keystate to expect reading 'Q'-'T'. 315: ; The second byte is the keystate to expect reading 'Y'-'P'. 316: 85E5 1F1F L85E5: DEFB &1F,&1F ; ---------- 317: 85E7 1D1F L85E7: DEFB &1D,&1F ; -W-------- 318: 85E9 171F DEFB &17,&1F ; ---R------ 319: 85EB 1F1B DEFB &1F,&1B ; -------I-- 320: 85ED 0F1F DEFB &0F,&1F ; ----T----- 321: 85EF 1B1F DEFB &1B,&1F ; --E------- 322: 85F1 0F1F DEFB &0F,&1F ; ----T----- 323: 85F3 1F0F DEFB &1F,&0F ; -----Y---- 324: 85F5 1F1E DEFB &1F,&1E ; ---------P 325: 85F7 1B1F DEFB &1B,&1F ; --E------- 326: 85F9 171F DEFB &17,&1F ; ---R------ 327: 328: 329: ; Game Music Data 330: ; =============== 331: ; Moonlight Sonata is played at the intro screen 332: 85FB 513C3351 MOONLIGHT: DEFB &51,&3C,&33,&51,&3C,&33,&51,&3C,&33,&51,&3C,&33 3C33513C 33513C33 333: 8607 513C3351 DEFB &51,&3C,&33,&51,&3C,&33,&51,&3C,&33,&51,&3C,&33 3C33513C 33513C33 334: 8613 4C3C334C DEFB &4C,&3C,&33,&4C,&3C,&33,&4C,&39,&2D,&4C,&39,&2D 3C334C39 2D4C392D 335: 861F 51402D51 DEFB &51,&40,&2D,&51,&3C,&33,&51,&3C,&36,&5B,&40,&36 3C33513C 365B4036 336: 862B 66513C51 DEFB &66,&51,&3C,&51,&3C,&33,&51,&3C,&33,&28,&3C,&28 3C33513C 33283C28 337: 8637 28362D51 DEFB &28,&36,&2D,&51,&36,&2D,&51,&36,&2D,&28,&36,&28 362D5136 2D283628 338: 8643 283C3351 DEFB &28,&3C,&33,&51,&3C,&33,&26,&3C,&2D,&4C,&3C,&2D 3C33263C 2D4C3C2D 339: 864F 28403351 DEFB &28,&40,&33,&51,&40,&33,&2D,&40,&36,&20,&40,&36 40332D40 36204036 340: 865B 3D793DFF DEFB &3D,&79,&3D,&FF ; Terminated with &FF 341: 342: ; If I Were A Rich Man is played through the game 343: 865F 56605660 RICHMAN: DEFB &56,&60,&56,&60,&66,&66,&80,&80,&80,&80,&66,&60 66668080 80806660 344: 866B 56605660 DEFB &56,&60,&56,&60,&66,&60,&56,&4C,&48,&4C,&48,&4C 6660564C 484C484C 345: 8677 56565656 DEFB &56,&56,&56,&56,&56,&56,&56,&56,&40,&40,&40,&40 56565656 40404040 346: 8683 44444C4C DEFB &44,&44,&4C,&4C,&56,&60,&66,&60,&56,&56,&66,&66 56606660 56566666 347: 868F 51566056 DEFB &51,&56,&60,&56,&51,&51,&60,&60,&40,&40,&40,&40 51516060 40404040 348: 869B 40404040 DEFB &40,&40,&40,&40 ; 64 bytes long, just loops 349: 350: 351: ; Copy Protection Password Entry Code 352: ; =================================== 353: ; This code space becomes free for other use if the password system is 354: ; bypassed. 355: 869F 210040 PASSCHECK: LD HL,&4000 ; Clear screen 356: 86A2 110140 LD DE,&4001 357: 86A5 01FF1A LD BC,&1AFF 358: 86A8 3600 LD (HL),&00 359: 86AA EDB0 LDIR 360: 86AC DD218B85 LD IX,PROMPT1 ; Point to message 1 361: 86B0 CDC386 CALL PASSASK ; Ask for a password 362: 86B3 CACA87 JP Z,GAMESTART ; Password ok, enter game 363: 86B6 DD21AB85 LD IX,PROMPT2 ; Point to message 2 364: 86BA CDC386 CALL PASSASK ; Ask for a password 365: 86BD CACA87 JP Z,GAMESTART ; Password ok, enter game 366: 86C0 C30000 JP &0000 ; Reset 367: 368: ; Ask for a password, displaying the message pointed to by IX 369: ; ----------------------------------------------------------- 370: 86C3 110048 PASSASK: LD DE,&4800 ; Point to line 8 371: 86C6 0E20 LD C,&20 ; 32 characters 372: 86C8 CD8096 CALL PRMESSAGE ; Print the message 373: 86CB 214248 LD HL,&4842 ; Column 2, line 10 374: 86CE 11009B LD DE,&9B00 ; Point to '1' block 375: 86D1 0E00 LD C,&00 ; Ignore collisions 376: 86D3 CD5694 CALL DRAWSPRITE ; Draw the sprite to screen 377: 86D6 214548 LD HL,&4845 ; Column 5, line 10 378: 86D9 CD5694 CALL DRAWSPRITE ; Draw '2' block 379: 86DC 214848 LD HL,&4848 ; Column 8, line 10 380: 86DF CD5694 CALL DRAWSPRITE ; Draw '3' block 381: 86E2 214B48 LD HL,&484B ; Column 11, line 10 382: 86E5 CD5694 CALL DRAWSPRITE ; Draw '4' block 383: 86E8 21809B LD HL,&9B80 ; Point to password screen attributes 384: 86EB 110059 LD DE,&5900 ; Point to screen middle third 385: 86EE 018000 LD BC,&0080 ; Four lines of attributes 386: 86F1 EDB0 LDIR ; Copy attributes to screen 387: 86F3 3A785C LD A,(&5C78) ; Get FRAMES to seed randomiser 388: 86F6 C625 ADD A,&25 389: 86F8 32785C LD (&5C78),A ; Store updated FRAMES for next call 390: 86FB FEB3 CP &B3 ; There are 180 codes. If FRAMES>&B3 391: 86FD 3802 JR C,L8701 ; reduce by 180. 392: 86FF D6B4 SUB &B4 393: 8701 6F L8701: LD L,A ; Index into passcodes in &9Exx 394: 8702 269E LD H,&9E 395: 8704 7E LD A,(HL) ; Get passcode 396: 8705 85 ADD A,L ; Add offset to passcode 397: 8706 32E485 LD (TEMP),A ; Store in temp location 398: 8709 4D LD C,L ; Calculate code location 399: 870A 1E2F LD E,&2F ; Start at digit '0'-1 400: 870C 1C L870C: INC E ; Increment digit 401: 870D 79 LD A,C 402: 870E FE12 CP &12 403: 8710 3805 JR C,L8717 ; Jump to ask for passcode 404: 8712 D612 SUB &12 405: 8714 4F LD C,A 406: 8715 18F5 JR L870C ; Loop to manipulate passcode 407: 408: 8717 7B L8717: LD A,E ; Get digit 409: 8718 111E48 LD DE,&481E ; Column 30, line 10 410: 871B CD9196 CALL PRCHAR ; Print digit 411: 871E 79 LD A,C ; Get letter offset 412: 871F C641 ADD A,&41 ; Add to 'A' 413: 8721 111D48 LD DE,&481D ; Coulmn 29, line 10 414: 8724 CD9196 CALL PRCHAR ; Print letter 415: 8727 DD215059 L8727: LD IX,&5950 ; Point to attributes for 1st block 416: 872B CD3C87 L872B: CALL PASSKEY ; Get keypress and colour in a block 417: 872E DD23 INC IX 418: 8730 DD23 INC IX 419: 8732 DD23 INC IX ; Bump IX up to point to next block 420: 8734 DD DEFB &DD 421: 8735 7D LD A,L ; LD A,IXL 422: 8736 FE5C CP &5C ; Got to nonexistant 5th block? 423: 8738 20F1 JR NZ,L872B ; No, loop to get another keypress 424: 873A 18EB JR L8727 ; Loop back to 1st block 425: 426: ; Get a passcode keypress 427: ; ----------------------- 428: 873C 01FEF7 PASSKEY: LD BC,&F7FE ; Keyboard row '1'-'5' 429: 873F ED78 IN A,(C) ; Read from keyboard 430: 8741 E60F AND &0F ; Keep '1'-'4' only 431: 8743 FE0F CP &0F ; No keys pressed? 432: 8745 20F5 JR NZ,PASSKEY ; Loop until *no* key pressed 433: 8747 06BF L8747: LD B,&BF ; Keyboard row 'H'-'ent' 434: 8749 ED78 IN A,(C) ; Read from keyboard 435: 874B CB47 BIT 0,A ; Is 'Enter' pressed? 436: 874D 2036 JR NZ,L8785 ; No, jump to look for digit keys 437: 874F 3A5959 LD A,(&5959) ; Get attribute of 4th block 438: 8752 E67F AND &7F ; Lose flash bit 439: 8754 FE07 CP &07 ; Is it still white ink? 440: 8756 282D JR Z,L8785 ; Jump to keep looking for digit keys 441: 8758 D608 SUB &08 442: 875A E618 AND &18 ; Keep two bits 443: 875C 0F RRCA 444: 875D 0F RRCA 445: 875E 0F RRCA 446: 875F 4F LD C,A 447: 8760 3A5359 LD A,(&5953) ; Get attribute of 2nd block 448: 8763 D608 SUB &08 449: 8765 E618 AND &18 ; Keep two bits 450: 8767 07 RLCA 451: 8768 B1 OR C 452: 8769 4F LD C,A 453: 876A 3A5659 LD A,(&5956) ; Get attribute of 3rd block 454: 876D D608 SUB &08 455: 876F E618 AND &18 ; Keep two bits 456: 8771 0F RRCA 457: 8772 B1 OR C 458: 8773 4F LD C,A 459: 8774 3A5059 LD A,(&5950) ; Get attribute of 1st block 460: 8777 D608 SUB &08 461: 8779 E618 AND &18 ; Keep two bits 462: 877B 07 RLCA 463: 877C 07 RLCA 464: 877D 07 RLCA 465: 877E E1 POP HL ; Lose return address 466: 877F B1 OR C ; Clear carry flag 467: 8780 21E485 LD HL,TEMP ; Point to temp store 468: 8783 BE CP (HL) ; Compare with entered passcode 469: 8784 C9 RET ; Return Z=Code Matches 470: 471: 8785 DDCB00FE L8785: SET 7,(IX+&00) ; Make current block flashing 472: 8789 DDCB01FE SET 7,(IX+&01) 473: 878D DDCB20FE SET 7,(IX+&20) 474: 8791 DDCB21FE SET 7,(IX+&21) 475: 8795 01FEF7 LD BC,&F7FE ; Keyboard row '1' to '5' 476: 8798 ED78 IN A,(C) ; Read keyboard 477: 879A E60F AND &0F ; Keep '1'-'4' 478: 879C 1E08 LD E,&08 ; Prepare for blue paper 479: 879E FE0E CP &0E ; '1' pressed? 480: 87A0 2813 JR Z,L87B5 ; Yes, jump to set 481: 87A2 1E10 LD E,&10 ; Prepare for red paper 482: 87A4 FE0D CP &0D ; '2' pressed? 483: 87A6 280D JR Z,L87B5 ; Yes, jump to set 484: 87A8 1E18 LD E,&18 ; Prepare for magenta paper 485: 87AA FE0B CP &0B ; '3' pressed? 486: 87AC 2807 JR Z,L87B5 ; Yes, jump to set 487: 87AE 1E20 LD E,&20 ; Prepare for green paper 488: 87B0 FE07 CP &07 ; '4' pressed? 489: 87B2 C24787 JP NZ,L8747 ; No, loop back to wait again 490: 87B5 DD7300 L87B5: LD (IX+&00),E ; Set attribute of the current block 491: 87B8 DD7301 LD (IX+&01),E 492: 87BB DD7320 LD (IX+&20),E 493: 87BE DD7321 LD (IX+&21),E 494: 87C1 011800 LD BC,&0018 ; Loop &1800 times 495: 87C4 10FE L87C4: DJNZ L87C4 ; Slight pause 496: 87C6 0D DEC C 497: 87C7 20FB JR NZ,L87C4 498: 87C9 C9 RET 499: 500: 501: ; JSW48 Game Engine 502: ; ================= 503: ; The actual game engine starts at GAMESTART. The code is entered here 504: ; from the password protection code, or direct from startup if the 505: ; password scheme is bypassed. 506: 507: ; Introduction screen 508: ; ------------------- 509: 87CA AF GAMESTART: XOR A ; Clear a load of variables 510: 87CB 32CE85 LD (KEMPSTON),A ; Kempston joystick not present 511: 87CE 32E185 LD (MTICK),A ; Music ticker 512: 87D1 32CD85 LD (FLASH),A ; No screen flash 513: 87D4 32D185 LD (FALLING),A ; Willy's not falling 514: 87D7 32CB85 LD (TICKER),A ; Game ticker counter 515: 87DA 32E085 LD (COUNTDOWN),A ; Autopause countdown timer 516: 87DD 32DF85 LD (STATUS),A ; Normal gameplay 517: 87E0 3E07 LD A,&07 518: 87E2 32CC85 LD (LIVES),A ; Set lives to 8 minus 1 519: 87E5 3ED0 LD A,&D0 520: 87E7 32CF85 LD (YPOSN),A ; Willy's pixel-line coordinate 521: 87EA 3E21 LD A,&21 522: 87EC 322084 LD (HERE),A ; Set HERE to 33 - The Bathroom 523: 87EF 21B45D LD HL,&5DB4 ; Put Willy at column 20, line 13 524: 87F2 22D385 LD (POSITION),HL ; Set Willy's location 525: 87F5 217C85 LD HL,COLLECTED ; Point to item count 526: 87F8 3630 LD (HL),&30 ; Initialise to "000" 527: 87FA 23 INC HL 528: 87FB 3630 LD (HL),&30 529: 87FD 23 INC HL 530: 87FE 3630 LD (HL),&30 531: 0001 IF MOREROOMS 532: 8800 26A6 LD H,&A6 ; Point to relocated collection flags 533: ELSE 535: ENDIF 536: 8802 3AFFA3 LD A,(OBJECTS) ; Get object count 537: 8805 6F LD L,A 538: 8806 32DE85 LD (REMAIN),A ; Set 'objects remaining' 539: 8809 CBF6 L8809: SET 6,(HL) ; Clear 'object collected flag' 540: 880B 2C INC L 541: 880C 20FB JR NZ,L8809 ; Loop for all objects 542: 880E 21E285 LD HL,MFLAGS 543: 8811 CBC6 SET 0,(HL) ; 'mute' keys not being pressed 544: 8813 210040 L8813: LD HL,&4000 ; Point to screen 545: 8816 110140 LD DE,&4001 546: 8819 01FF17 LD BC,&17FF 547: 881C 3600 LD (HL),&00 548: 881E EDB0 LDIR ; Clear screen 549: 8820 210098 LD HL,ATTRS ; Point to intro screen attributes 550: 8823 010003 LD BC,&0300 551: 8826 EDB0 LDIR ; Copy attributes to screen 552: 8828 21605A LD HL,&5A60 ; Point to attributes for line 16 553: 882B 11615A LD DE,&5A61 554: 882E 011F00 LD BC,&001F 555: 8831 3646 LD (HL),&46 ; Bright yellow on black 556: 8833 EDB0 LDIR ; Set attributes for line 16 557: 8835 DD215484 LD IX,MESSAGE ; Point to "Press SPACE..." 558: 8839 116050 LD DE,&5060 ; Point to line 16 559: 883C 0E20 LD C,&20 ; 32 characters to print 560: 883E CD8096 CALL PRMESSAGE ; Print the string 561: 8841 110058 LD DE,&5800 ; Draw the triangle based on the 562: 8844 1A L8844: LD A,(DE) ; attributes on the screen 563: 8845 B7 OR A 564: 8846 2846 JR Z,L888E ; Black/Black - block 565: 8848 FED3 CP &D3 566: 884A 2842 JR Z,L888E ; Red/Magenta - block 567: 884C FE09 CP &09 568: 884E 283E JR Z,L888E ; Blue/Blue - block 569: 8850 FE2D CP &2D 570: 8852 283A JR Z,L888E ; Cyan/Cyan - block 571: 8854 FE24 CP &24 572: 8856 2836 JR Z,L888E ; Green/Green - block 573: 8858 0E00 LD C,&00 574: 885A FE08 CP &08 575: 885C 2813 JR Z,L8871 576: 885E FE29 CP &29 577: 8860 280F JR Z,L8871 578: 8862 FE2C CP &2C 579: 8864 2808 JR Z,L886E 580: 8866 FE05 CP &05 581: 8868 2807 JR Z,L8871 582: 886A 0E10 LD C,&10 583: 886C 1803 JR L8871 584: 585: 886E 3E25 L886E: LD A,&25 586: 8870 12 LD (DE),A 587: 8871 7B L8871: LD A,E 588: 8872 E601 AND &01 589: 8874 07 RLCA 590: 8875 07 RLCA 591: 8876 07 RLCA 592: 8877 B1 OR C 593: 8878 4F LD C,A 594: 8879 0600 LD B,&00 595: 887B 213184 LD HL,L8431 ; Index into triangle bitmaps 596: 887E 09 ADD HL,BC 597: 887F D5 PUSH DE 598: 8880 CB42 BIT 0,D 599: 8882 1640 LD D,&40 600: 8884 2802 JR Z,L8888 601: 8886 1648 LD D,&48 602: 8888 0608 L8888: LD B,&08 603: 888A CD9B96 CALL PRMATRIX 604: 888D D1 POP DE 605: 888E 13 L888E: INC DE ; Move to next attribute 606: 888F 7A LD A,D ; Check address high byte 607: 8890 FE5A CP &5A ; Got to &5A00 yet? 608: 8892 C24488 JP NZ,L8844 ; Loop back for whole triangle 609: 610: 8895 011F00 LD BC,&001F ; Check for kempston joystick 611: 8898 F3 DI ; But INTs are already disabled 612: 8899 AF XOR A 613: 889A ED58 L889A: IN E,(C) ; Read IN 31 614: 889C B3 OR E 615: 889D 10FB DJNZ L889A ; Loop to read 256 times 616: 889F E620 AND &20 ; Check out of range value 617: 88A1 2005 JR NZ,L88A8 ; If set, no joystick present 618: 88A3 3E01 LD A,&01 619: 88A5 32CE85 LD (KEMPSTON),A ; Set joystick flag 620: 88A8 21FB85 L88A8: LD HL,MOONLIGHT ; Point to intro screen music 621: 88AB CDA296 CALL L96A2 ; Play until keypress 622: 88AE C2FC88 JP NZ,L88FC ; If ENTER/FIRE/0 pressed, start game 623: 88B1 AF XOR A ; Set scroll offset to zero 624: 88B2 32E485 LD (TEMP),A ; Save in temp store 625: 88B5 CDEB8A L88B5: CALL L8AEB ; Change screen attributes 626: 88B8 21605A LD HL,&5A60 ; Ensure line 19 is white ink on 627: 88BB 11615A LD DE,&5A61 ; blue paper 628: 88BE 011F00 LD BC,&001F 629: 88C1 364F LD (HL),&4F 630: 88C3 EDB0 LDIR 631: 88C5 3AE485 LD A,(TEMP) ; Get scroll offset 632: 88C8 DD215484 LD IX,MESSAGE ; Point to scrolling message 633: 88CC 5F LD E,A ; Pass scroll offset into DE 634: 88CD 1600 LD D,&00 635: 88CF DD19 ADD IX,DE ; Add scroll offset into message 636: 88D1 116050 LD DE,&5060 ; Point to line 19 637: 88D4 0E20 LD C,&20 ; 32 characters 638: 88D6 CD8096 CALL PRMESSAGE ; Print the string 639: 88D9 3AE485 LD A,(TEMP) ; Get scroll offset 640: 88DC E61F AND &1F ; Reduce to 0-31 641: 88DE C632 ADD A,&32 ; Add 50 -> 50-81 642: 88E0 CDDE96 CALL L96DE ; Play a note 643: 0001 IF GAMEEXIT 644: 88E3 CD0784 CALL L840D ; Check ENTER/FIRE/SS-SPACE 645: 88E6 00000000 DEFB 0,0,0,0,0,0 0000 646: ELSE 651: ENDIF 652: 88EC 200E JR NZ,L88FC ; ENTER pressed, enter current room 653: 88EE 3AE485 LD A,(TEMP) ; Get scroll offset 654: 88F1 3C INC A ; Increment offset 655: 88F2 FEE0 CP &E0 ; End of message yet? 656: 88F4 32E485 LD (TEMP),A ; Store offset back to temp location 657: 88F7 20BC JR NZ,L88B5 ; Loop to keep scrolling 658: 88F9 C31388 JP L8813 ; Jump back to play intro music 659: 660: 661: ; Play the game 662: ; ============= 663: ; Before starting the game, the screen is cleared and the clock is set to 664: ; 7:00am. 665: 88FC 218585 L88FC: LD HL,STARTTIME ; Point to start time 666: 88FF 117F85 LD DE,NOWTIME ; Point to current time 667: 8902 010600 LD BC,&0006 ; Six characters 668: 8905 EDB0 LDIR ; Set clock to 7:00am 669: 8907 21009A LD HL,ATTRS+512 ; Point to bottom third attributes 670: 890A 11005A LD DE,&5A00 671: 890D 010001 LD BC,&0100 672: 8910 EDB0 LDIR ; Set attrs of bottom of screen 673: 674: 675: ; Play a room 676: ; =========== 677: ; Entry here plays the room that is in HERE with Willy's position in 678: ; POSITION. Any movement between rooms jumps straight back to here. 679: 8912 3A2084 PLAYROOM: LD A,(HERE) ; Get current room 680: 0001 IF MOREROOMS 681: 8915 EEC0 XOR &C0 ; Convert to room data address 682: ELSE 684: ENDIF 685: 8917 67 LD H,A ; Rooms start at &C000 686: 8918 2E00 LD L,&00 687: 891A 110080 LD DE,ROOM ; Point to room buffer 688: 891D 010001 LD BC,&0100 ; A room definition is 256 bytes 689: 8920 EDB0 LDIR ; Copy current room to room buffer 690: 8922 DD21F080 L8922: LD IX,INSTANCES ; Point to this room's guardian data 691: 8926 110081 LD DE,GUARDIAN ; Point to expanded guardian data 692: 8929 3E08 LD A,&08 ; There are a maximum of 8 guardians 693: 892B DD6E00 L892B: LD L,(IX+&00) ; Get guardian number 694: 892E CBBD RES 7,L ; Ensure 0-127 695: 8930 2614 LD H,&14 ; Guardian table address DIV &800 696: 8932 29 ADD HL,HL 697: 8933 29 ADD HL,HL 698: 8934 29 ADD HL,HL ; HL=&A000+guardian*8 699: 8935 010200 LD BC,&0002 ; Copy first two bytes of data 700: 8938 EDB0 LDIR 701: 893A DD4E01 LD C,(IX+&01) ; Get guardian info byte 702: 893D 71 LD (HL),C ; Put into guardian data 703: 893E 010600 LD BC,&0006 ; Copy into guardian buffer 704: 8941 EDB0 LDIR 705: 8943 DD23 INC IX ; Move to next guardian entry 706: 8945 DD23 INC IX 707: 8947 3D DEC A 708: 8948 20E1 JR NZ,L892B ; Loop for eight entries 709: 710: 894A 21CF85 LD HL,YPOSN ; Current Willy state 711: 894D 11D785 LD DE,L85D7 ; Preserved Willy state 712: 8950 010700 LD BC,&0007 713: 8953 EDB0 LDIR ; Preserve current Willy state 714: 8955 CD338D CALL DRAWROOM ; Draw room to buffer 1 715: 8958 210050 LD HL,&5000 716: 895B 110150 LD DE,&5001 717: 895E 01FF07 LD BC,&07FF 718: 8961 3600 LD (HL),&00 719: 8963 EDB0 LDIR ; Clear bottom third of screen 720: 8965 DD218080 LD IX,NAME ; Point to room name 721: 8969 0E20 LD C,&20 ; 32 characters 722: 896B 110050 LD DE,&5000 ; Point to line 16 723: 896E CD8096 CALL PRMESSAGE ; Display room name 724: 8971 DD215485 LD IX,ITEMS ; Point to "Items collected..." 725: 8975 116050 LD DE,&5060 ; Point to line 19 726: 8978 0E20 LD C,&20 ; 32 characters 727: 897A CD8096 CALL PRMESSAGE ; Print string 728: 897D 3ADE80 LD A,(BORDER) ; Get border colour 729: 8980 0EFE LD C,&FE 730: 8982 ED79 OUT (C),A ; Set border colour 731: 8984 AF XOR A 732: 8985 32D685 LD (ONROPE),A ; Willy is not on a rope 733: 8988 C3AD89 JP ACTION ; Jump to action loop 734: 735: 736: ; Print moving Willies along the bottom of the screen 737: ; =================================================== 738: ; One Willy is displayed for each remaining life. The Willies are animated 739: ; according to the music ticker. If music is turned off the Willies will stand 740: ; still. 741: 898B 3ACC85 DRAWLIVES: LD A,(LIVES) ; Get number of remaining lives 742: 898E 21A050 LD HL,&50A0 ; Point to line 21 743: 8991 B7 OR A 744: 8992 C8 RET Z ; Exit with zero remaining lives 745: 8993 47 LD B,A ; Loop for remaining lives 746: 8994 0E00 L8994: LD C,&00 ; Ignore collisions 747: 8996 E5 PUSH HL ; Save registers 748: 8997 C5 PUSH BC 749: 8998 3AE185 LD A,(MTICK) ; Get music ticker 750: 899B 07 RLCA 751: 899C 07 RLCA 752: 899D 07 RLCA ; Multiply by eight 753: 899E E660 AND &60 ; Offset to sprite 0, 1, 2 or 3 754: 89A0 5F LD E,A ; Low byte of sprite address 755: 89A1 169D LD D,&9D ; Willies are in page &9D 756: 89A3 CD5694 CALL DRAWSPRITE ; Draw sprite 757: 89A6 C1 POP BC ; Restore registers 758: 89A7 E1 POP HL 759: 89A8 23 INC HL ; Move to next positon on screen 760: 89A9 23 INC HL 761: 89AA 10E8 DJNZ L8994 ; Loop for remaining lives 762: 89AC C9 RET 763: 764: 765: ; Action loop 766: ; =========== 767: 89AD CD8B89 ACTION: CALL DRAWLIVES ; Display remaining lives Willies 768: 89B0 21005E LD HL,&5E00 ; Point to attribute buffer 1 769: 89B3 11005C LD DE,&5C00 ; Point to attribute buffer 2 770: 89B6 010002 LD BC,&0200 771: 89B9 EDB0 LDIR ; Copy from attrs buffer 1 to 2 772: 89BB 210070 LD HL,&7000 ; Point to screen buffer 1 773: 89BE 110060 LD DE,&6000 ; Point to screen buffer 2 774: 89C1 010010 LD BC,&1000 775: 89C4 EDB0 LDIR ; Copy from screen buffer 1 to 2 776: 89C6 CDC090 CALL UPDATEGUARD ; Update guardians 777: 89C9 3ADF85 LD A,(STATUS) ; 778: 89CC FE03 CP &03 ; Is Willy throwing up? 779: 89CE C4D38D CALL NZ,MOVEMENT ; No, move Willy 780: 89D1 3ACF85 LD A,(YPOSN) ; Get Willy's position 781: 89D4 FEE1 CP &E1 ; Above the top of the screen? 782: 89D6 D4B094 CALL NC,GO_UP ; Go up 783: 89D9 3ADF85 LD A,(STATUS) ; Is Willy throwing up? 784: 89DC FE03 CP &03 ; If not, check what Willy is standing 785: 89DE C4C895 CALL NZ,UPDATEWILLY ; on and draw him 786: 89E1 3ADF85 LD A,(STATUS) 787: 89E4 FE02 CP &02 ; Is Willy fleeing? 788: 89E6 CC8495 CALL Z,CHKTOILET ; Yes, check if toilet reached yet 789: 89E9 CD3495 CALL SPECIAL ; Draw Maira and Toilet if needed 790: 89EC CDBE91 CALL DRAWGUARD ; Draw guardians to buffer 2 791: 89EF CDF994 CALL UPDATECONV ; Update conveyors in buffer 2 792: 89F2 CDD193 CALL CHKOBJECTS ; Draw objects to buffer 2 793: 89F5 210060 L89F5: LD HL,&6000 ; Point to screen 2 794: 89F8 110040 LD DE,&4000 ; Point to displayed screen 795: 89FB 010010 LD BC,&1000 796: 89FE EDB0 LDIR ; Copy screen buffer 2 to screen 797: 8A00 3ADF85 LD A,(STATUS) 798: 8A03 E602 AND &02 ; Keep flee/vomit bit 799: 8A05 0F RRCA ; Move to bit 0 800: 8A06 21D285 LD HL,FRAME ; Willy's animation frame 801: 8A09 B6 OR (HL) ; Merge vomit bit into frame 802: 8A0A 77 LD (HL),A ; Only frames 2 and 3 if vomiting 803: 804: ; The following code flashes the PAPER over the whole of the top two thirds 805: ; of the screen from white down to black, if FLASH is nonzero. This appears 806: ; to be a left-over from Manic Miner. [???] 807: 808: 8A0B 3ACD85 LD A,(FLASH) ; Get screen flash counter 809: 8A0E B7 OR A ; Is it zero? 810: 8A0F 2815 JR Z,L8A26 ; No screen flash, jump past 811: 8A11 3D DEC A ; Decrease flash counter 812: 8A12 32CD85 LD (FLASH),A 813: 8A15 07 RLCA ; Move up into PAPER 814: 8A16 07 RLCA 815: 8A17 07 RLCA 816: 8A18 E638 AND &38 ; Set PAPER with black INK 817: 8A1A 21005C LD HL,&5C00 818: 8A1D 11015C LD DE,&5C01 819: 8A20 01FF01 LD BC,&01FF 820: 8A23 77 LD (HL),A ; Set first attribute in buffer 2 821: 8A24 EDB0 LDIR ; Set all attributes 822: 8A26 21005C L8A26: LD HL,&5C00 ; Point to attribute buffer 2 823: 8A29 110058 LD DE,&5800 ; Point to displayed attributes 824: 8A2C 010002 LD BC,&0200 825: 8A2F EDB0 LDIR ; Copy attrs from buffer 2 to screen 826: 8A31 DD217F85 LD IX,NOWTIME ; Point to current time 827: 8A35 117950 LD DE,&5079 ; Point to line 19, column 25 828: 8A38 0E06 LD C,&06 ; "xx:xx?m"=six characters 829: 8A3A CD8096 CALL PRMESSAGE ; Display clock 830: 8A3D DD217C85 LD IX,COLLECTED ; Point to items collected string 831: 8A41 117050 LD DE,&5070 ; Point to line 19, column 16 832: 8A44 0E03 LD C,&03 ; "xxx"=three characters 833: 8A46 CD8096 CALL PRMESSAGE ; Display collected items count 834: 835: ; Update JSW clock 836: ; ---------------- 837: ; JSW runs 256 ticks of the TICKER variable per JSW minute. One JSW minute 838: ; equals about 15 real seconds, so the JSW clock runs about four times faster 839: ; than reality. 840: 8A49 3ACB85 LD A,(TICKER) ; Get TICKER 841: 8A4C 3C INC A ; Increment TICKER 842: 8A4D 32CB85 LD (TICKER),A ; Store updated TICKER 843: 8A50 2059 JR NZ,L8AAB ; TICKER<>0, so jump forward 844: 8A52 DD217F85 LD IX,NOWTIME ; Point to displayed clock to update 845: 8A56 DD3404 INC (IX+&04) ; Increment minutes units 846: 8A59 DD7E04 LD A,(IX+&04) ; Get minutes units 847: 8A5C FE3A CP &3A ; Overflowed past '9'? 848: 8A5E 204B JR NZ,L8AAB ; No, jump to continue 849: 8A60 DD360430 LD (IX+&04),&30 ; Reset minutes units to '0' 850: 8A64 DD3403 INC (IX+&03) ; Increment minutes tens digit 851: 8A67 DD7E03 LD A,(IX+&03) ; Get minutes tens digit 852: 8A6A FE36 CP &36 ; Overflowed past '5'? 853: 8A6C 203D JR NZ,L8AAB ; No, jump to continue 854: 8A6E DD360330 LD (IX+&03),&30 ; Reset minutes tens digit to '0' 855: 8A72 DD7E00 LD A,(IX+&00) ; Get Hours tens digit 856: 8A75 FE31 CP &31 ; Is it '1'? 857: 8A77 2020 JR NZ,L8A99 ; No, jump to update hours<10 858: 8A79 DD3401 INC (IX+&01) ; Increment hours units digit 859: 8A7C DD7E01 LD A,(IX+&01) ; Get hours unit digit 860: 8A7F FE33 CP &33 ; Overflowed past '2' (ie '12')? 861: 8A81 2028 JR NZ,L8AAB ; No, jump to continue 862: 8A83 DD7E05 LD A,(IX+&05) ; Get 'am' or 'pm' character 863: 8A86 FE70 CP &70 ; Is is 'p' for 'pm'? 864: 8A88 CACA87 JP Z,GAMESTART ; Yes -> midnight -> quit game 865: 8A8B DD360020 LD (IX+&00),&20 ; ' ' - set to "1:00pm" 866: 8A8F DD360131 LD (IX+&01),&31 ; '1' 867: 8A93 DD360570 LD (IX+&05),&70 ; 'p' 868: 8A97 1812 JR L8AAB ; Jump to continue 869: 8A99 DD3401 L8A99: INC (IX+&01) ; Update hours unit digit 870: 8A9C DD7E01 LD A,(IX+&01) ; Get hours unit digit 871: 8A9F FE3A CP &3A ; Overflowed past '9'? 872: 8AA1 2008 JR NZ,L8AAB ; No, jump to continue 873: 8AA3 DD360130 LD (IX+&01),&30 ; Set hours to '10' 874: 8AA7 DD360031 LD (IX+&00),&31 875: 876: 8AAB 01FEFE L8AAB: LD BC,&FEFE ; Keyboard row 'b'-'spc' 877: 8AAE ED78 IN A,(C) ; Read from keyboard 878: 8AB0 5F LD E,A ; Save result in E 879: 8AB1 067F LD B,&7F ; Keyboard row 'sht'-'v' 880: 8AB3 ED78 IN A,(C) ; Read from keyboard 881: 8AB5 B3 OR E ; Merge both rows 882: 8AB6 E601 AND &01 ; Keep Shift+Space 883: 8AB8 CACA87 JP Z,GAMESTART ; If pressed, go back to intro 884: 8ABB 3AE085 L8ABB: LD A,(COUNTDOWN) 885: 8ABE 3C INC A 886: 8ABF 32E085 LD (COUNTDOWN),A ; Update autopause counter 887: 8AC2 280D JR Z,L8AD1 888: 8AC4 06FD LD B,&FD 889: 8AC6 ED78 IN A,(C) 890: 8AC8 E61F AND &1F 891: 8ACA FE1F CP &1F 892: 8ACC 2849 JR Z,L8B17 893: 8ACE 110000 LD DE,&0000 894: 8AD1 0602 L8AD1: LD B,&02 ; Pause loop 895: 8AD3 ED78 IN A,(C) 896: 8AD5 E61F AND &1F 897: 8AD7 FE1F CP &1F 898: 8AD9 202C JR NZ,L8B07 899: 8ADB 1C INC E 900: 8ADC 20F3 JR NZ,L8AD1 901: 8ADE 14 INC D 902: 8ADF 20F0 JR NZ,L8AD1 903: 8AE1 3AE385 LD A,(TELEPORT) ; Get teleport flag 904: 8AE4 FE0A CP &0A ; Is teleport on? 905: 8AE6 C4EB8A CALL NZ,L8AEB ; No, change background colours 906: 8AE9 18E6 JR L8AD1 ; Loop to keep pausing 907: 908: ; Change background colours while paused 909: ; -------------------------------------- 910: ; While paused all the INKs on the screen change by have 3 added, and all the 911: ; PAPERs have 1 added, and the border is set to the INK of the first character 912: ; on screen. 913: 8AEB 210058 L8AEB: LD HL,&5800 ; Point to displayed attributes 914: 8AEE 7E LD A,(HL) ; 915: 8AEF E607 AND &07 ; Keep INK 916: 8AF1 D3FE OUT (&FE),A ; Set border colour 917: 8AF3 7E L8AF3: LD A,(HL) ; Get attribute 918: 8AF4 C603 ADD A,&03 ; Cycle INK by 3 919: 8AF6 E607 AND &07 920: 8AF8 57 LD D,A 921: 8AF9 7E LD A,(HL) ; Get attribute again 922: 8AFA C618 ADD A,&18 ; Cycle PAPER by 1 923: 8AFC E6B8 AND &B8 924: 8AFE B2 OR D ; Mask in updated INK 925: 8AFF 77 LD (HL),A ; Store back to attributes 926: 8B00 23 INC HL ; Move to next character cell 927: 8B01 7C LD A,H ; Loop for all 24 lines. Fix PAUSE 928: ; bug by changing this to CP &5A 929: 0000 IF FIXPAUSE1 931: ELSE 932: 8B02 FE5B CP &5B 933: ENDIF 934: 8B04 20ED JR NZ,L8AF3 ; Loop for all attributes 935: 8B06 C9 RET 936: 937: 8B07 21009A L8B07: LD HL,ATTRS+512 ; Point to attrs for lower screen 938: 8B0A 11005A LD DE,&5A00 ; Point to lower screen 939: 8B0D 010001 LD BC,&0100 ; Copy 256 bytes to screen 940: 941: ; This is where the PAUSE bug appears. C now holds &00 and will still hold 942: ; &00 after the following LDIR. The IN (C) instruction at &8B24 assumes 943: ; that C holds &FE. This results in an IN 0 which crashes the Interface 1. 944: ; If the attribute-changing routine at &8AEB doesn't change the bottom of 945: ; the screen, then this LDIR is not needed and can be changed to LD C,&FE 946: ; instead. 947: 948: 0000 IF FIXPAUSE1 950: ELSE 951: 8B10 EDB0 LDIR ; Change to LD C,&FE to fix PAUSE bug 952: ENDIF 953: 8B12 3ADE80 LD A,(BORDER) ; Get border colour 954: 8B15 D3FE OUT (&FE),A ; Set border 955: 8B17 3AD185 L8B17: LD A,(FALLING) ; Get flag 956: 957: ; An alternate pause fix is to crunch the following code down to release 958: ; a spare byte to replace the LD B,&BF with LD BC,&BFFE. 959: 960: 0000 IF FIXPAUSE2 966: ENDIF 967: 968: ; Another alternative is to read from port &FE directly instead of using 969: ; the zeroed BC register. 970: 971: 0001 IF FIXPAUSE3 972: 8B1A FEFF CP &FF ; &FF? 973: 8B1C CA018C JP Z,LOSTLIFE ; Lost a life 974: 8B1F 3EBF LD A,&BF ; 'h'-'enter' 975: 8B21 21E285 LD HL,MFLAGS 976: 8B24 DBFE IN A,(&FE) ; Read keyboard row 977: ENDIF 978: 979: 0000 IF FIXPAUSE1+FIXPAUSE2+FIXPAUSE3=0 985: ENDIF 986: 987: 8B26 E61F AND &1F ; Keep keys 988: 8B28 FE1F CP &1F ; Are any keys pressed? 989: 8B2A 280A JR Z,L8B36 ; No key pressed, jump ... 990: 8B2C CB46 BIT 0,(HL) 991: 8B2E 2008 JR NZ,L8B38 992: 8B30 7E LD A,(HL) 993: 8B31 EE03 XOR &03 994: 8B33 77 LD (HL),A 995: 8B34 1802 JR L8B38 996: 997: 8B36 CB86 L8B36: RES 0,(HL) 998: 8B38 CB4E L8B38: BIT 1,(HL) ; Is music enabled? 999: 8B3A 2034 JR NZ,L8B70 ; No, jump to check teleport 1000: 8B3C AF XOR A 1001: 8B3D 32E085 LD (COUNTDOWN),A 1002: 8B40 3AE185 LD A,(MTICK) ; Increment music ticker 1003: 8B43 3C INC A 1004: 8B44 32E185 LD (MTICK),A 1005: 1006: ; Play in-game music 1007: ; ----------------- 1008: 8B47 E67E AND &7E ; Lose bit 7 & bit 0 1009: 8B49 0F RRCA ; Divide by 2 -> A=0..63 1010: 8B4A 5F LD E,A ; Pass to DE. A new note is played 1011: 8B4B 1600 L8B4B: LD D,&00 ; every two game ticks. 1012: 8B4D 215F86 LD HL,RICHMAN ; Point to in-game music 1013: 8B50 19 ADD HL,DE ; Point to current note 1014: 8B51 3ACC85 LD A,(LIVES) ; Get number of remaining lives 1015: 8B54 07 RLCA ; Note gets lower with fewer lives 1016: 8B55 07 RLCA ; Lives*4 1017: 8B56 D61C SUB &1C ; Lives*4-&1C 1018: 8B58 ED44 NEG ; &1C-lives*4 -> 0..28 1019: 8B5A 86 ADD A,(HL) ; Add to current note 1020: 8B5B 57 LD D,A ; Save current note in D 1021: 8B5C 3ADE80 LD A,(BORDER) ; Get border colour 1022: 8B5F 5A LD E,D ; Initialise E with current note 1023: 8B60 010300 LD BC,&0003 1024: 8B63 D3FE L8B63: OUT (&FE),A ; Set buzzer state 1025: 8B65 1D DEC E 1026: 8B66 2003 JR NZ,L8B6B ; Loop for note delay 1027: 8B68 5A LD E,D ; Reinitialise E with current note 1028: 8B69 EE18 XOR &18 ; Toggle buzzer state 1029: 8B6B 10F6 L8B6B: DJNZ L8B63 ; Loop 256 times with this note 1030: 8B6D 0D DEC C 1031: 8B6E 20F3 JR NZ,L8B63 ; Loop 768 times with this note 1032: 1033: ; Check for teleport jump 1034: ; ----------------------- 1035: 8B70 01FEEF L8B70: LD BC,&EFFE ; Keyrow '6'-'0' 1036: 8B73 ED78 IN A,(C) ; Read keyboard 1037: 8B75 CB4F BIT 1,A ; Is '9' pressed? 1038: 8B77 C2978B JP NZ,L8B97 ; No, jump to check for password 1039: 8B7A E610 AND &10 ; Keep '6' keypress 1040: 8B7C EE10 XOR &10 ; Flip bit 1041: 8B7E 07 RLCA ; Move '6' up to bit 5 1042: 8B7F 57 LD D,A ; Save in D for later 1043: 8B80 3AE385 LD A,(TELEPORT) ; Get teleport state 1044: 8B83 FE0A CP &0A ; Is teleport on? 1045: 8B85 C2978B JP NZ,L8B97 ; No, jump to check for password 1046: 8B88 01FEF7 LD BC,&F7FE ; Keyrow '1'-'5' 1047: 8B8B ED78 IN A,(C) ; Read keyboard 1048: 8B8D 2F CPL ; Flip bits 1049: 8B8E E61F AND &1F ; Keep '1'-'5' 1050: 8B90 B2 OR D ; Merge bit 5 in from earlier 1051: 8B91 322084 LD (HERE),A ; Store as current room 1052: 8B94 C31289 JP PLAYROOM ; And jump to enter it 1053: 1054: ; Check for teleport password entry 1055: ; --------------------------------- 1056: 8B97 3AE385 L8B97: LD A,(TELEPORT) ; Get teleport state 1057: 8B9A FE0A CP &0A ; Is teleport already on? 1058: 8B9C CAAD89 JP Z,ACTION ; Yes, go back to action loop 1059: 8B9F 3A2084 LD A,(HERE) ; Are we in room 28? 1060: 8BA2 FE1C CP &1C ; (The Main Landing) 1061: 8BA4 C2AD89 JP NZ,ACTION ; No, go back to action loop 1062: 8BA7 3ACF85 LD A,(YPOSN) ; Get Willy's pixel-line position 1063: 8BAA FED0 CP &D0 ; Are we on the floor? 1064: 8BAC C2AD89 JP NZ,ACTION ; No, go back to action loop 1065: 8BAF 3AE385 LD A,(TELEPORT) ; Get teleport state 1066: 8BB2 07 RLCA ; Double it to index into keycodes 1067: 8BB3 5F LD E,A 1068: 8BB4 1600 LD D,&00 1069: 8BB6 DD21E785 LD IX,L85E7 ; Add to keycodes base 1070: 8BBA DD19 ADD IX,DE ; IX=>next keycode to expect 1071: 8BBC 01FEFB LD BC,&FBFE ; Keyrow 'Q'-'T' 1072: 8BBF ED78 IN A,(C) ; Read from keyboard 1073: 8BC1 E61F AND &1F ; Keep keys 1074: 8BC3 DDBE00 CP (IX+&00) ; Does it match expected keystate? 1075: 8BC6 2812 JR Z,L8BDA ; Yes, jump to check other half-row 1076: 8BC8 FE1F CP &1F ; Are no keys pressed? 1077: 8BCA CAAD89 JP Z,ACTION ; Yes, return to action loop 1078: 8BCD DDBEFE CP (IX-&02) ; Does it match previous keystate? 1079: 8BD0 CAAD89 JP Z,ACTION ; Yes, return to action loop 1080: 8BD3 AF XOR A ; Otherwise, reset teleport state 1081: 8BD4 32E385 LD (TELEPORT),A 1082: 8BD7 C3AD89 JP ACTION ; Return to action loop 1083: 1084: 8BDA 06DF L8BDA: LD B,&DF ; Keyrow 'Y'-'P' 1085: 8BDC ED78 IN A,(C) ; Read keyboard 1086: 8BDE E61F AND &1F ; Keep keys 1087: 8BE0 DDBE01 CP (IX+&01) ; Does it match expected keystate? 1088: 8BE3 2812 JR Z,L8BF7 ; Yes, jump to update teleport state 1089: 8BE5 FE1F CP &1F ; Are no keys pressed? 1090: 8BE7 CAAD89 JP Z,ACTION ; Yes, return to action loop 1091: 8BEA DDBEFF CP (IX-&01) ; Does it match previous keystate? 1092: 8BED CAAD89 JP Z,ACTION ; Yes, return to action loop 1093: 8BF0 AF XOR A ; Otherwise, resetl teleport state 1094: 8BF1 32E385 LD (TELEPORT),A 1095: 8BF4 C3AD89 JP ACTION ; Return to action loop 1096: 1097: 8BF7 3AE385 L8BF7: LD A,(TELEPORT) ; Get teleport state 1098: 8BFA 3C INC A ; One more keypress has been matched 1099: 8BFB 32E385 LD (TELEPORT),A ; Update teleport state 1100: 8BFE C3AD89 JP ACTION ; Return to action loop 1101: 1102: 1103: ; Lost a life 1104: ; =========== 1105: ; When Willy dies the screen colours cycle from white on black to black 1106: ; on black, with a squeeking sound. If there are no lives remaining, the 1107: ; game ends. Otherwise, Willy's state is restored to when he entered the 1108: ; room and the room is re-entered. 1109: 8C01 3E47 LOSTLIFE: LD A,&47 ; White INK on black PAPER 1110: 8C03 210058 L8C03: LD HL,&5800 ; Point to start of attributes 1111: 8C06 110158 LD DE,&5801 1112: 8C09 01FF01 LD BC,&01FF ; Top two thirds of screen 1113: 8C0C 77 LD (HL),A ; Set first attribute 1114: 8C0D EDB0 LDIR ; Set all attributes 1115: 8C0F 5F LD E,A ; Save current attributes in E 1116: 8C10 2F CPL ; Flip all bits 1117: 8C11 E607 AND &07 ; Keep INK 1118: 8C13 07 RLCA ; Move up three bits 1119: 8C14 07 RLCA 1120: 8C15 07 RLCA ; Buzzer pause is 8*(7-old INK) 1121: 8C16 F607 OR &07 ; Set INK to white 1122: 8C18 57 LD D,A ; Save in D 1123: 8C19 4B LD C,E ; Copy old attributes to C 1124: 8C1A CB09 RRC C ; Move down three bits 1125: 8C1C CB09 RRC C 1126: 8C1E CB09 RRC C ; Buzzer delay in C is old PAPER 1127: 8C20 F610 OR &10 ; Superfluous instruction? 1128: 8C22 AF XOR A ; Clear A 1129: 8C23 D3FE L8C23: OUT (&FE),A ; Set border and buzzer 1130: 8C25 EE18 XOR &18 ; Flip buzzer state 1131: 8C27 42 LD B,D ; 1132: 8C28 10FE L8C28: DJNZ L8C28 ; Pause according to INK value 1133: 8C2A 0D DEC C ; Loop according to PAPER value 1134: 8C2B 20F6 JR NZ,L8C23 ; Loop to make sound 1135: 8C2D 7B LD A,E ; Get saved attributes 1136: 8C2E 3D DEC A ; Decrease attribute 1137: 8C2F FE3F CP &3F ; Wrapped past black on black? 1138: 8C31 20D0 JR NZ,L8C03 ; Loop to cycles through colours 1139: 8C33 21CC85 LD HL,LIVES 1140: 8C36 7E LD A,(HL) ; Get remaining lives 1141: 8C37 B7 OR A ; No remaining lives? 1142: 8C38 CA4A8C JP Z,GAMEOVER ; None left - Game Over 1143: 8C3B 35 DEC (HL) ; Decrease remaining lives 1144: 8C3C 21D785 LD HL,L85D7 ; Point to saved Willy state 1145: 8C3F 11CF85 LD DE,YPOSN ; Point to current Willy state 1146: 8C42 010700 LD BC,&0007 ; 7 bytes in total 1147: 8C45 EDB0 LDIR ; Restore Willy state 1148: 8C47 C31289 JP PLAYROOM ; Jump to reenter current room 1149: 1150: 1151: ; Game Over 1152: ; ========= 1153: ; Willy has died and has no lives remaining. Clear the top of the screen and 1154: ; drop the foot onto Willy standing on the barrel. 1155: 8C4A 210040 GAMEOVER: LD HL,&4000 ; Point to screen 1156: 8C4D 110140 LD DE,&4001 1157: 8C50 01FF0F LD BC,&0FFF 1158: 8C53 3600 LD (HL),&00 ; Clear first byte 1159: 8C55 EDB0 LDIR ; Clear top two thirds of screen 1160: 8C57 AF XOR A ; TEMP holds pixel-line*2 1161: 8C58 32E485 LD (TEMP),A ; Start at pixel-line 0 1162: 8C5B 11409D LD DE,&9D40 ; Point to a Willy sprite 1163: 8C5E 218F48 LD HL,&488F ; Point to line 12, column 15 1164: 8C61 0E00 LD C,&00 ; Ignore collisions 1165: 8C63 CD5694 CALL DRAWSPRITE ; Draw Willy to screen 1166: 8C66 11609C LD DE,&9C60 ; Point to barrel sprite 1167: 8C69 21CF48 LD HL,&48CF ; Point to line 14, column 15 1168: 8C6C 0E00 LD C,&00 ; Ignore collisions 1169: 8C6E CD5694 CALL DRAWSPRITE ; Draw barrel to screen 1170: 1171: ; Now loop to draw the foot descending above Willy. As the foot descends it 1172: ; leaves two lines of pixels that generates the leg. 1173: 1174: 8C71 3AE485 L8C71: LD A,(TEMP) ; Get pixel-line*2 1175: 8C74 4F LD C,A ; Look up screen address 1176: 8C75 0682 LD B,PIXEL / 256 ; BC=> 1177: 8C77 0A LD A,(BC) ; Get low byte of pixel-line address 1178: 8C78 F60F OR &0F ; Set to column 15 1179: 8C7A 6F LD L,A ; Store in L 1180: 8C7B 03 INC BC ; Point to high byte of address 1181: 8C7C 0A LD A,(BC) ; Get high byte of pixel-line address 1182: 8C7D D620 SUB &20 ; Convert address from buffer 2 to 1183: 8C7F 67 LD H,A ; screen address and store in H 1184: ; HL now points to pixel-line in TEMP, 1185: ; column 15 on the displayed screen 1186: 8C80 11409C LD DE,&9C40 ; Point to foot sprite 1187: 8C83 0E00 LD C,&00 ; Ignore collisions 1188: 8C85 CD5694 CALL DRAWSPRITE ; Draw foot to screen 1189: 8C88 3AE485 LD A,(TEMP) ; Get pixel-line to generate sound 1190: 8C8B 2F CPL ; Delay gets shorter as foot decends 1191: ; So, pitch gets higher 1192: 8C8C 5F LD E,A ; Set buzzer delay 1193: 8C8D AF XOR A ; Clear initial buzzer state 1194: 8C8E 014000 LD BC,&0040 ; Toggle buzzer 64 times 1195: 8C91 D3FE L8C91: OUT (&FE),A ; Output to buzzer 1196: 8C93 EE18 XOR &18 ; Toggle buzzer state 1197: 8C95 43 LD B,E ; Get delay value 1198: 8C96 10FE L8C96: DJNZ L8C96 ; Delay according to foot height 1199: 8C98 0D DEC C 1200: 8C99 20F6 JR NZ,L8C91 ; Loop to toggle buzzer 1201: 8C9B 210058 LD HL,&5800 ; Point to attributes 1202: 8C9E 110158 LD DE,&5801 1203: 8CA1 01FF01 LD BC,&01FF ; Top two thirds of screen 1204: 8CA4 3AE485 LD A,(TEMP) ; Get pixel-line to generate colour 1205: 8CA7 E60C AND &0C ; Keep b2-b3 1206: 8CA9 07 RLCA ; Move up to PAPER 1207: 8CAA F647 OR &47 ; Ensure bright white INK 1208: 8CAC 77 LD (HL),A ; Set first attribute 1209: 8CAD EDB0 LDIR ; Copy to top two thirds of screen 1210: 8CAF E6FA AND &FA ; Lose INK 1211: 8CB1 F602 OR &02 ; Set INK to red 1212: 8CB3 32CF59 LD (&59CF),A ; Set attributes for barrel 1213: 8CB6 32D059 LD (&59D0),A 1214: 8CB9 32EF59 LD (&59EF),A 1215: 8CBC 32F059 LD (&59F0),A 1216: 8CBF 3AE485 LD A,(TEMP) ; Get pixel-line 1217: 8CC2 C604 ADD A,&04 ; Move down two lines 1218: 8CC4 32E485 LD (TEMP),A ; Store pixel-line 1219: 8CC7 FEC4 CP &C4 ; Has foot got past pixel-line 192? 1220: 8CC9 20A6 JR NZ,L8C71 ; Loop until foot reaches barrel 1221: 1222: 8CCB DD217485 LD IX,GAME ; Point to "Game" 1223: 8CCF 0E04 LD C,&04 ; 4 characters 1224: 8CD1 11CA40 LD DE,&40CA ; Line 6, column 10 1225: 8CD4 CD8096 CALL PRMESSAGE ; Print the message 1226: 8CD7 DD217885 LD IX,OVER ; Point to "Over" 1227: 8CDB 0E04 LD C,&04 ; 4 characters 1228: 8CDD 11D240 LD DE,&40D2 ; Line 6, column 18 1229: 8CE0 CD8096 CALL PRMESSAGE ; Print the message 1230: ; Print "Game Over" and wobble the colours 1231: 8CE3 010000 LD BC,&0000 ; C=initial colour, B=initial loop counter 1232: 8CE6 1606 LD D,&06 ; Loop 6*256 times 1233: 8CE8 10FE L8CE8: DJNZ L8CE8 ; Pause for 256 loops 1234: 8CEA 79 LD A,C ; Get current colour 1235: 8CEB E607 AND &07 ; Keep INK 1236: 8CED F640 OR &40 ; Ensure BRIGHT 1237: 8CEF 32CA58 LD (&58CA),A ; Set attribute of "G" 1238: 8CF2 3C INC A ; Increment INK 1239: 8CF3 E607 AND &07 ; Ensure black PAPER 1240: 8CF5 F640 OR &40 ; Ensure BRIGHT 1241: 8CF7 32CB58 LD (&58CB),A ; Set attribute of "a" 1242: 8CFA 3C INC A ; Increment INK 1243: 8CFB E607 AND &07 ; Ensure black PAPER 1244: 8CFD F640 OR &40 ; Ensure BRIGHT 1245: 8CFF 32CC58 LD (&58CC),A ; Set attribute of "m" 1246: 8D02 3C INC A ; Increment INK 1247: 8D03 E607 AND &07 ; Ensure black PAPER 1248: 8D05 F640 OR &40 ; Ensure BRIGHT 1249: 8D07 32CD58 LD (&58CD),A ; Set attribute of "e" 1250: 8D0A 3C INC A ; Increment INK 1251: 8D0B E607 AND &07 ; Ensure black PAPER 1252: 8D0D F640 OR &40 ; Ensure BRIGHT 1253: 8D0F 32D258 LD (&58D2),A ; Set attribute of "O" 1254: 8D12 3C INC A ; Increment INK 1255: 8D13 E607 AND &07 ; Ensure black PAPER 1256: 8D15 F640 OR &40 ; Ensure BRIGHT 1257: 8D17 32D358 LD (&58D3),A ; Set attribute of "v" 1258: 8D1A 3C INC A ; Increment INK 1259: 8D1B E607 AND &07 ; Ensure black PAPER 1260: 8D1D F640 OR &40 ; Ensure BRIGHT 1261: 8D1F 32D458 LD (&58D4),A ; Set attribute of "e" 1262: 8D22 3C INC A ; Increment INK 1263: 8D23 E607 AND &07 ; Ensure black PAPER 1264: 8D25 F640 OR &40 ; Ensure BRIGHT 1265: 8D27 32D558 LD (&58D5),A ; Set attribute of "r" 1266: 8D2A 0D DEC C ; Decrement colour 1267: 8D2B 20BB JR NZ,L8CE8 ; Loop 256 times 1268: 8D2D 15 DEC D ; Decrement main loop counter 1269: 8D2E 20B8 JR NZ,L8CE8 ; Loop 6*256 times 1270: 8D30 C3CA87 JP GAMESTART ; Go back to intro screen 1271: 1272: 1273: ; Draw the current room to Buffer 1 1274: ; ================================= 1275: 8D33 CD6B8D DRAWROOM: CALL BUILDROOM ; Build up the attributes for the room 1276: 8D36 DD21005E LD IX,&5E00 ; Point to top third attributes 1277: 8D3A 3E70 LD A,&70 ; Point to top third of buffer 1 1278: 8D3C 325D8D LD (L8D5C+1),A ; Poke into later code 1279: 8D3F CD4B8D CALL L8D4B ; Draw the characters for the attributes 1280: 8D42 DD21005F LD IX,&5F00 ; Point to middle third attributes 1281: 8D46 3E78 LD A,&78 ; Point to middle third of buffer 1 1282: 8D48 325D8D LD (L8D5C+1),A ; Poke into later code 1283: 1284: 0001 IF FIXBLOCKS 1285: 8D4B 1E00 L8D4B: LD E,&00 ; Start at screen address 0 1286: 8D4D DD7E00 L8D4D: LD A,(IX+0) ; Get current attribute 1287: 8D50 219780 LD HL,BACKGROUND-9 ; Start at the background attribute 1288: 8D53 010900 LD BC,9 ; Nine bytes per block 1289: 8D56 09 L8D56: ADD HL,BC ; Step to next block 1290: 8D57 BE CP (HL) ; Does attribute byte match? 1291: 8D58 20FC JR NZ,L8D56 ; No match, check next block 1292: 8D5A 0608 LD B,&08 ; Eight pixel-lines 1293: 8D5C 1600 L8D5C: LD D,&00 ; This is poked to &70 or &78 earlier 1294: 8D5E 23 L8D5E: INC HL ; Point to bitmap pixel line 1295: 8D5F 7E LD A,(HL) ; Get a character byte 1296: 8D60 12 LD (DE),A ; Store into screen buffer 1297: 8D61 14 INC D ; Move to next pixel-line 1298: 8D62 10FA DJNZ L8D5E ; Loop for eight pixel-lines 1299: 8D64 DD23 INC IX ; Move to next attribute 1300: 8D66 1C INC E ; Move to next screen address 1301: 8D67 C24D8D JP NZ,L8D4D ; Loop for 256 attributes 1302: 8D6A C9 RET 1303: ELSE 1331: ENDIF 1332: 1333: ; Build room 1334: ; ---------- 1335: 8D6B 210080 BUILDROOM: LD HL,ROOM ; Point to room buffer 1336: 8D6E DD21005E LD IX,&5E00 ; Point to attribute buffer 1 1337: 8D72 7E L8D72: LD A,(HL) ; Get a room byte 1338: 8D73 07 RLCA 1339: 8D74 07 RLCA ; Rotate b6-b7 to b0-b1 1340: 8D75 CDC08D CALL ROOMBLOCK ; Insert attribute for this block 1341: 8D78 7E LD A,(HL) ; Get the room byte again 1342: 8D79 0F RRCA 1343: 8D7A 0F RRCA 1344: 8D7B 0F RRCA 1345: 8D7C 0F RRCA ; Rotate b4-b5 to b0-b1 1346: 8D7D CDC08D CALL ROOMBLOCK ; Insert attribute for this block 1347: 8D80 7E LD A,(HL) ; Get the room byte again 1348: 8D81 0F RRCA 1349: 8D82 0F RRCA ; Rotate b2-b3 to b0-b1 1350: 8D83 CDC08D CALL ROOMBLOCK ; Insert attribute for this block 1351: 8D86 7E LD A,(HL) ; Get the room byte a fourth time 1352: 8D87 CDC08D CALL ROOMBLOCK ; Insert attribute for this block 1353: 8D8A 23 INC HL ; Point to next room byte 1354: 8D8B 7D LD A,L ; Get address low byte 1355: 8D8C E680 AND &80 ; Wrapped past &7F? 1356: 8D8E 28E2 JR Z,L8D72 ; Loop for 128 bytes 1357: 1358: ; Insert conveyor blocks into attribute buffer 1359: ; -------------------------------------------- 1360: 8D90 3AD980 LD A,(CONV_NUM) ; Get conveyor length 1361: 8D93 B7 OR A ; Is it zero? 1362: 8D94 280B JR Z,L8DA1 ; Jump forward with no conveyors 1363: 8D96 2AD780 LD HL,(CONV_PSN) ; Get conveyor start 1364: 8D99 47 LD B,A ; Pass conveyor length to B 1365: 8D9A 3ACD80 LD A,(CONVEYOR) ; Get conveyor attribute 1366: 8D9D 77 L8D9D: LD (HL),A ; Store a conveyor attribute block 1367: 8D9E 23 INC HL ; Move to next block 1368: 8D9F 10FC DJNZ L8D9D ; Loop for length of conveyor 1369: 8DA1 3ADD80 L8DA1: LD A,(SLOPE_NUM) ; Get slope length 1370: 8DA4 B7 OR A ; Is it zero? 1371: 8DA5 C8 RET Z ; Exit with no slopes 1372: 1373: ; Insert slope blocks into attribute buffer 1374: ; ----------------------------------------- 1375: 8DA6 2ADB80 LD HL,(SLOPE_PSN) ; Get slope start 1376: 8DA9 3ADA80 LD A,(SLOPE_DIR) ; Get slope direction 1377: 8DAC E601 AND &01 ; Keep left/right bit 1378: 8DAE 07 RLCA ; Move to b2 1379: 8DAF C6DF ADD A,&DF ; A=&DF or &E1 for left or right 1380: 8DB1 5F LD E,A ; Pass to E 1381: 8DB2 16FF LD D,&FF ; DE is step between slope addresses 1382: ; A slope leftwards steps by -33 (&FFDF) 1383: ; A slope rightwards steps by -31 (&FFE1) 1384: 8DB4 3ADD80 LD A,(SLOPE_NUM) ; Get slope length again 1385: 8DB7 47 LD B,A ; Pass length to B for looping 1386: 8DB8 3AC480 LD A,(SLOPE) ; Get slope attribute 1387: 8DBB 77 L8DBB: LD (HL),A ; Store a slope attribute block 1388: 8DBC 19 ADD HL,DE ; Move up and one block left or right 1389: 8DBD 10FC DJNZ L8DBB ; Loop for length of slope 1390: 8DBF C9 RET ; All done 1391: 1392: ; Insert a room block attribute 1393: ; ----------------------------- 1394: 8DC0 E603 ROOMBLOCK: AND &03 ; Keep b0-b1 1395: 8DC2 4F LD C,A ; Hold in C for additional add 1396: 8DC3 07 RLCA 1397: 8DC4 07 RLCA 1398: 8DC5 07 RLCA ; Multiply by 8 1399: 8DC6 81 ADD A,C ; Add again to multiply by 9 1400: 8DC7 C6A0 ADD A,BACKGROUND-ROOM ; Add to base of room blocks 1401: 8DC9 5F LD E,A ; Pass to E to point to attribute 1402: 8DCA 1680 LD D,ROOM / 256 ; within room buffer 1403: 8DCC 1A LD A,(DE) ; Get attribute for this block 1404: 8DCD DD7700 LD (IX+&00),A ; Store into attribute buffer 1405: 8DD0 DD23 INC IX ; Point to next buffer location 1406: 8DD2 C9 RET 1407: 1408: 1409: ; Move Willy 1410: ; ========== 1411: ; Move Willy taking account of keypresses, joystick state, whether Willy is on 1412: ; a conveyor or rope, whether he is jumping or falling, etc. 1413: ; Will probably use somebody else's commentary for here... 1414: 8DD3 3AD685 MOVEMENT: LD A,(ONROPE) ; Is Willy on a rope? 1415: 8DD6 3D DEC A 1416: 8DD7 CB7F BIT 7,A 1417: 8DD9 CAD48E JP Z,L8ED4 ; Jump to deal with Willy on a rope 1418: 8DDC 3AD185 LD A,(FALLING) ; moving/falling 1419: 8DDF FE01 CP &01 1420: 8DE1 2053 JR NZ,L8E36 1421: 8DE3 3AD585 LD A,(JUMPING) ; jumping 1422: 8DE6 E6FE AND &FE 1423: 8DE8 D608 SUB &08 1424: 8DEA 21CF85 LD HL,YPOSN ; Point to Willy's position 1425: 8DED 86 ADD A,(HL) 1426: 8DEE 77 LD (HL),A 1427: 8DEF FEF0 CP &F0 ; Above top of screen? 1428: 8DF1 D2B094 JP NC,GO_UP ; If so, go up 1429: 8DF4 CD9C8E CALL L8E9C 1430: 8DF7 3AB280 LD A,(WALL) ; Wall attribute 1431: 8DFA BE CP (HL) 1432: 8DFB CABC8E JP Z,L8EBC 1433: 8DFE 23 INC HL 1434: 8DFF BE CP (HL) 1435: 8E00 CABC8E JP Z,L8EBC 1436: 8E03 3AD585 LD A,(JUMPING) ; jumping 1437: 8E06 3C INC A 1438: 8E07 32D585 LD (JUMPING),A ; jumping 1439: 8E0A D608 SUB &08 1440: 8E0C F2118E JP P,L8E11 1441: 8E0F ED44 NEG 1442: 8E11 3C L8E11: INC A 1443: 8E12 07 RLCA 1444: 8E13 07 RLCA 1445: 8E14 07 RLCA 1446: 8E15 57 LD D,A 1447: 8E16 0E20 LD C,&20 1448: 8E18 3ADE80 LD A,(BORDER) 1449: 8E1B D3FE L8E1B: OUT (&FE),A 1450: 8E1D EE18 XOR &18 1451: 8E1F 42 LD B,D 1452: 8E20 10FE L8E20: DJNZ L8E20 1453: 8E22 0D DEC C 1454: 8E23 20F6 JR NZ,L8E1B 1455: 8E25 3AD585 LD A,(JUMPING) ; Get jump counter 1456: 8E28 FE12 CP &12 ; Jump has finished when counter is &12 1457: 8E2A CAB08E JP Z,L8EB0 ; Jump finished, set JUMPING to 6 1458: 8E2D FE10 CP &10 1459: 8E2F 2805 JR Z,L8E36 ; Check what Willy is standing on 1460: 8E31 FE0D CP &0D 1461: 8E33 C2BC8F JP NZ,&8FBC ; Not 13 or 16, skip ahead to do movement 1462: 8E36 3ACF85 L8E36: LD A,(YPOSN) 1463: 8E39 E60E AND &0E 1464: 8E3B 2025 JR NZ,L8E62 1465: 8E3D 2AD385 LD HL,(POSITION) ; Get Willy's position 1466: 8E40 114000 LD DE,&0040 1467: 8E43 19 ADD HL,DE ; Point to block under Willy's feet 1468: 8E44 CB4C BIT 1,H ; Wrapped off the bottom of the screen? 1469: 8E46 C2D294 JP NZ,GO_DOWN ; Yes, so go downwards 1470: 8E49 3ABB80 LD A,(NASTY) ; Get Nasty attribute 1471: 8E4C BE CP (HL) ; Is a nasty under Willy? 1472: 8E4D 2813 JR Z,L8E62 ; Yes, kill Willy 1473: 8E4F 23 INC HL ; Point to under Willy's right foot 1474: 8E50 3ABB80 LD A,(NASTY) ; Get Nasty attribute superfluously 1475: 8E53 BE CP (HL) ; Is a nasty under Willy? 1476: 8E54 280C JR Z,L8E62 ; Yes, kill Willy 1477: 8E56 3AA080 LD A,(BACKGROUND) ; Get the background attribute 1478: 8E59 BE CP (HL) ; Is there 'nothing' under Willy? 1479: 8E5A 2B DEC HL ; Point to under Willy's left foot 1480: 8E5B C2D48E JP NZ,L8ED4 ; Something under Willy, stop falling 1481: 8E5E BE CP (HL) ; Is there 'nothing' under Willy? 1482: 8E5F C2D48E JP NZ,L8ED4 ; No, so jump to stop falling 1483: 1484: 8E62 3AD185 L8E62: LD A,(FALLING) ; moving/falling? 1485: 8E65 FE01 CP &01 1486: 8E67 CABC8F JP Z,&8FBC 1487: 8E6A 21D085 LD HL,L85D0 1488: 8E6D CB8E RES 1,(HL) 1489: 8E6F 3AD185 LD A,(FALLING) 1490: 8E72 B7 OR A 1491: 8E73 CAB68E JP Z,L8EB6 1492: 8E76 3C INC A 1493: 8E77 FE10 CP &10 1494: 8E79 2002 JR NZ,L8E7D 1495: 8E7B 3E0C LD A,&0C 1496: 8E7D 32D185 L8E7D: LD (FALLING),A 1497: 8E80 07 RLCA 1498: 8E81 07 RLCA 1499: 8E82 07 RLCA 1500: 8E83 07 RLCA 1501: 8E84 57 LD D,A 1502: 8E85 0E20 LD C,&20 1503: 8E87 3ADE80 LD A,(BORDER) 1504: 8E8A D3FE OUT (&FE),A 1505: 8E8C EE18 XOR &18 1506: 8E8E 42 LD B,D 1507: 8E8F 10FE L8E8F: DJNZ L8E8F 1508: 8E91 0D DEC C 1509: 8E92 20F6 JR NZ,&8E8A 1510: 8E94 3ACF85 LD A,(YPOSN) 1511: 8E97 C608 ADD A,&08 1512: 8E99 32CF85 LD (YPOSN),A 1513: 8E9C E6F0 L8E9C: AND &F0 1514: 8E9E 6F LD L,A 1515: 8E9F AF XOR A 1516: 8EA0 CB15 RL L 1517: 8EA2 CE5C ADC A,&5C 1518: 8EA4 67 LD H,A 1519: 8EA5 3AD385 LD A,(POSITION) 1520: 8EA8 E61F AND &1F 1521: 8EAA B5 OR L 1522: 8EAB 6F LD L,A 1523: 8EAC 22D385 LD (POSITION),HL 1524: 8EAF C9 RET 1525: 1526: 8EB0 3E06 L8EB0: LD A,&06 1527: 8EB2 32D185 LD (FALLING),A 1528: 8EB5 C9 RET 1529: 1530: 8EB6 3E02 L8EB6: LD A,&02 1531: 8EB8 32D185 LD (FALLING),A 1532: 8EBB C9 RET 1533: 1534: 8EBC 3ACF85 L8EBC: LD A,(YPOSN) 1535: 8EBF C610 ADD A,&10 1536: 8EC1 E6F0 AND &F0 1537: 8EC3 32CF85 LD (YPOSN),A 1538: 8EC6 CD9C8E CALL L8E9C 1539: 8EC9 3E02 LD A,&02 1540: 8ECB 32D185 LD (FALLING),A 1541: 8ECE 21D085 LD HL,L85D0 1542: 8ED1 CB8E RES 1,(HL) 1543: 8ED3 C9 RET 1544: 1545: 1546: ; Move Willy 1547: ; ========== 1548: 8ED4 1EFF L8ED4: LD E,&FF ; Prepare E with 'not moving' 1549: 8ED6 3AD685 LD A,(ONROPE) 1550: 8ED9 3D DEC A 1551: 8EDA CB7F BIT 7,A 1552: 8EDC 281C JR Z,L8EFA 1553: 8EDE 3AD185 LD A,(FALLING) 1554: 8EE1 FE0C CP &0C 1555: 8EE3 D2B790 JP NC,DIED1 1556: 8EE6 AF XOR A 1557: 8EE7 32D185 LD (FALLING),A 1558: 8EEA 3ACD80 LD A,(CONVEYOR) ; Get conveyor attribute 1559: 8EED BE CP (HL) ; Check attribute under Willy 1560: 8EEE 2804 JR Z,L8EF4 ; Standing on a conveyor 1561: 8EF0 23 INC HL ; Look under Willy's right foot 1562: 8EF1 BE CP (HL) ; Check attribute under Willy 1563: 8EF2 2006 JR NZ,&8EFA ; Not standing on a conveyor 1564: 8EF4 3AD680 L8EF4: LD A,(CONV_DIR) ; Get conveyor direction 1565: 8EF7 D603 SUB &03 ; 0->bit1 clear, 1->bit0 clear 1566: 8EF9 5F LD E,A ; This also gives 2->sticky and 3->off 1567: ; [ref] 1568: 8EFA 01FEDF L8EFA: LD BC,&DFFE 1569: 8EFD ED78 IN A,(C) 1570: 8EFF E61F AND &1F 1571: 8F01 F620 OR &20 1572: 8F03 A3 AND E 1573: 8F04 5F LD E,A 1574: 8F05 3ADF85 LD A,(STATUS) 1575: 8F08 E602 AND &02 1576: 8F0A 0F RRCA 1577: 8F0B AB XOR E 1578: 8F0C 5F LD E,A 1579: 8F0D 01FEFB LD BC,&FBFE 1580: 8F10 ED78 IN A,(C) 1581: 8F12 E61F AND &1F 1582: 8F14 CB07 RLC A 1583: 8F16 F601 OR &01 1584: 8F18 A3 AND E 1585: 8F19 5F LD E,A 1586: 8F1A 06E7 LD B,&E7 1587: 8F1C ED78 IN A,(C) 1588: 8F1E 0F RRCA 1589: 8F1F F6F7 OR &F7 1590: 8F21 A3 AND E 1591: 8F22 5F LD E,A 1592: 8F23 06EF LD B,&EF 1593: 8F25 ED78 IN A,(C) 1594: 8F27 F6FB OR &FB 1595: 8F29 A3 AND E 1596: 8F2A 5F LD E,A 1597: 8F2B ED78 IN A,(C) 1598: 8F2D 0F RRCA 1599: 8F2E F6FB OR &FB 1600: 8F30 A3 AND E 1601: 8F31 5F LD E,A 1602: 8F32 3ACE85 LD A,(KEMPSTON) 1603: 8F35 B7 OR A 1604: 8F36 280A JR Z,L8F42 1605: 8F38 011F00 LD BC,&001F 1606: 8F3B ED78 IN A,(C) 1607: 8F3D E603 AND &03 1608: 8F3F 2F CPL 1609: 8F40 A3 AND E 1610: 8F41 5F LD E,A 1611: 8F42 0E00 L8F42: LD C,&00 1612: 8F44 7B LD A,E 1613: 8F45 E62A AND &2A 1614: 8F47 FE2A CP &2A 1615: 8F49 2806 JR Z,L8F51 1616: 8F4B 0E04 LD C,&04 1617: 8F4D AF XOR A 1618: 8F4E 32E085 LD (COUNTDOWN),A 1619: 8F51 7B L8F51: LD A,E 1620: 8F52 E615 AND &15 1621: 8F54 FE15 CP &15 1622: 8F56 2806 JR Z,L8F5E 1623: 8F58 CBD9 SET 3,C 1624: 8F5A AF XOR A 1625: 8F5B 32E085 LD (COUNTDOWN),A 1626: 8F5E 3AD085 L8F5E: LD A,(L85D0) 1627: 8F61 81 ADD A,C 1628: 8F62 4F LD C,A 1629: 8F63 0600 LD B,&00 1630: 8F65 212184 LD HL,L8421 1631: 8F68 09 ADD HL,BC 1632: 8F69 7E LD A,(HL) 1633: 8F6A 32D085 LD (L85D0),A 1634: 8F6D 01FE7E LD BC,&7EFE 1635: 8F70 ED78 IN A,(C) 1636: 8F72 E61F AND &1F 1637: 8F74 FE1F CP &1F 1638: 8F76 2017 JR NZ,L8F8F 1639: 8F78 06EF LD B,&EF 1640: 8F7A ED78 IN A,(C) 1641: 8F7C CB47 BIT 0,A 1642: 8F7E 280F JR Z,L8F8F 1643: 8F80 3ACE85 LD A,(KEMPSTON) 1644: 8F83 B7 OR A 1645: 8F84 2836 JR Z,L8FBC 1646: 8F86 011F00 LD BC,&001F 1647: 8F89 ED78 IN A,(C) 1648: 8F8B CB67 BIT 4,A 1649: 8F8D 282D JR Z,L8FBC 1650: 8F8F 3ADF85 L8F8F: LD A,(STATUS) 1651: 8F92 CB4F BIT 1,A 1652: 8F94 2026 JR NZ,L8FBC 1653: 8F96 AF XOR A 1654: 8F97 32D585 LD (JUMPING),A 1655: 8F9A 32E085 LD (COUNTDOWN),A 1656: 8F9D 3C INC A 1657: 8F9E 32D185 LD (FALLING),A 1658: 8FA1 3AD685 LD A,(ONROPE) 1659: 8FA4 3D DEC A 1660: 8FA5 CB7F BIT 7,A 1661: 8FA7 2013 JR NZ,L8FBC 1662: 8FA9 3EF0 LD A,&F0 1663: 8FAB 32D685 LD (ONROPE),A 1664: 8FAE 3ACF85 LD A,(YPOSN) 1665: 8FB1 E6F0 AND &F0 1666: 8FB3 32CF85 LD (YPOSN),A 1667: 8FB6 21D085 LD HL,L85D0 1668: 8FB9 CBCE SET 1,(HL) 1669: 8FBB C9 RET 1670: 1671: 8FBC 3AD085 L8FBC: LD A,(L85D0) 1672: 8FBF E602 AND &02 1673: 8FC1 C8 RET Z 1674: 8FC2 3AD685 LD A,(ONROPE) 1675: 8FC5 3D DEC A 1676: 8FC6 CB7F BIT 7,A 1677: 8FC8 C8 RET Z 1678: 8FC9 3AD085 LD A,(L85D0) 1679: 8FCC E601 AND &01 1680: 8FCE CA4290 JP Z,L9042 1681: 8FD1 3AD285 LD A,(FRAME) 1682: 8FD4 B7 OR A 1683: 8FD5 2805 JR Z,L8FDC 1684: 8FD7 3D DEC A 1685: 8FD8 32D285 LD (FRAME),A 1686: 8FDB C9 RET 1687: 1688: ; Move Willy leftwards 1689: ; -------------------- 1690: 8FDC 3AD185 L8FDC: LD A,(FALLING) 1691: 8FDF 010000 LD BC,&0000 ; 0 for no movement 1692: 8FE2 FE00 CP &00 ; 1693: 8FE4 2024 JR NZ,L900A 1694: 8FE6 2AD385 LD HL,(POSITION) 1695: 8FE9 010000 LD BC,&0000 ; again? 1696: 8FEC 3ADA80 LD A,(SLOPE_DIR) 1697: 8FEF 3D DEC A 1698: 8FF0 F6A1 OR &A1 1699: 8FF2 EEE0 XOR &E0 1700: 8FF4 5F LD E,A 1701: 8FF5 1600 LD D,&00 1702: 8FF7 19 ADD HL,DE ; Point to under Willy's feet 1703: 8FF8 3AC480 LD A,(SLOPE) ; Get slope attribute 1704: 8FFB BE CP (HL) ; Willy standing on a slope? 1705: 8FFC 200C JR NZ,L900A ; No, jump ahead 1706: 8FFE 012000 LD BC,&0020 ; +32 for downwards 1707: 9001 3ADA80 LD A,(SLOPE_DIR) 1708: 9004 B7 OR A 1709: 9005 2003 JR NZ,L900A 1710: 9007 01E0FF LD BC,&FFE0 ; -32 for upwards 1711: 900A 2AD385 L900A: LD HL,(POSITION) ; Get Willy's current position 1712: 900D 7D LD A,L 1713: 900E E61F AND &1F ; If Willy is in column zero, 1714: 9010 CA8A94 JP Z,GO_LEFT ; move left 1715: 9013 09 ADD HL,BC ; Willy's potential new position 1716: 9014 2B DEC HL ; Just left of Willy's head 1717: 9015 112000 LD DE,&0020 ; DE holds offset between lines 1718: 9018 19 ADD HL,DE ; Just left of Willy's feet 1719: 9019 3AB280 LD A,(WALL) ; Get wall attribute 1720: 901C BE CP (HL) ; Is there a wall here? 1721: 901D C8 RET Z ; If so, return without moving Willy 1722: 901E 3ACF85 LD A,(YPOSN) ; Get Willy's pixel-line position 1723: 9021 CB29 SRA C ; Is Willy occupying three character 1724: 9023 81 ADD A,C ; lines? 1725: 9024 47 LD B,A 1726: 9025 E60F AND &0F 1727: 9027 2809 JR Z,L9032 ; Only occupying two character lines 1728: 9029 3AB280 LD A,(WALL) ; Get wall attribute 1729: 902C 19 ADD HL,DE ; Point to left of Willy's feet on 3rd 1730: 902D BE CP (HL) ; character line. Is there wall here? 1731: 902E C8 RET Z ; If so, return without moving Willy 1732: 902F B7 OR A 1733: 9030 ED52 SBC HL,DE ; Move back to second character line 1734: 9032 B7 L9032: OR A ; Back to new head-height position 1735: 9033 ED52 SBC HL,DE ; Note: no check for wall block 1736: 0000 IF WALLLEFT 1743: ELSE 1744: 9035 22D385 LD (POSITION),HL ; Update Willy's position 1745: 9038 78 LD A,B 1746: 9039 32CF85 LD (YPOSN),A ; Update pixel-line position 1747: 903C 3E03 LD A,&03 ; Set Willy's sprite to frame 3 1748: 903E 32D285 LD (FRAME),A 1749: 9041 C9 RET 1750: ENDIF 1751: 1752: 9042 3AD285 L9042: LD A,(FRAME) 1753: 9045 FE03 CP &03 1754: 9047 2805 JR Z,L904E 1755: 9049 3C INC A 1756: 904A 32D285 LD (FRAME),A 1757: 904D C9 RET 1758: 1759: ; Move Willy rightwards 1760: ; --------------------- 1761: 904E 3AD185 L904E: LD A,(FALLING) 1762: 9051 010000 LD BC,&0000 ; 0 for no movement 1763: 9054 B7 OR A 1764: 9055 2021 JR NZ,L9078 1765: 9057 2AD385 LD HL,(POSITION) 1766: 905A 3ADA80 LD A,(SLOPE_DIR) 1767: 905D 3D DEC A 1768: 905E F69D OR &9D 1769: 9060 EEBF XOR &BF 1770: 9062 5F LD E,A 1771: 9063 1600 LD D,&00 1772: 9065 19 ADD HL,DE ; Point to under Willy's feet 1773: 9066 3AC480 LD A,(SLOPE) ; Get slope attribute 1774: 9069 BE CP (HL) ; Willy standing on a slope? 1775: 906A 200C JR NZ,L9078 ; No, jump ahead 1776: 906C 012000 LD BC,&0020 ; +32 for downwards 1777: 906F 3ADA80 LD A,(SLOPE_DIR) 1778: 9072 B7 OR A 1779: 9073 2803 JR Z,L9078 1780: 9075 01E0FF LD BC,&FFE0 ; -32 for upwards 1781: 9078 2AD385 L9078: LD HL,(POSITION) ; Get's Willy's current position 1782: 907B 09 ADD HL,BC ; Willy's potential new position 1783: 907C 23 INC HL 1784: 907D 23 INC HL ; Just right of Willy's head 1785: 907E 7D LD A,L 1786: 907F E61F AND &1F ; If Willy's position about to wrap 1787: 9081 CA9E94 JP Z,GO_RIGHT ; round into column zero, move right 1788: 9084 112000 LD DE,&0020 ; DE holds offset between lines 1789: 9087 3AB280 LD A,(WALL) ; Get wall attribute 1790: 908A 19 ADD HL,DE ; Just right of Willy's feet 1791: 908B BE CP (HL) ; Is there a wall here? 1792: 908C C8 RET Z ; If so, return without moving Willy 1793: 908D 3ACF85 LD A,(YPOSN) ; Get Willy's pixel-line position 1794: 9090 CB29 SRA C ; Is Willy occupying three character 1795: 9092 81 ADD A,C ; lines? 1796: 9093 47 LD B,A 1797: 9094 E60F AND &0F 1798: 9096 2809 JR Z,L90A1 ; Only occupying two character lines 1799: 9098 3AB280 LD A,(WALL) ; Get wall attribute 1800: 909B 19 ADD HL,DE ; Point right of Willy's feet on third 1801: 909C BE CP (HL) ; character line. Is there wall here? 1802: 909D C8 RET Z ; If so, return without moving Willy 1803: 909E B7 OR A 1804: 909F ED52 SBC HL,DE ; Move back to second character line 1805: 90A1 3AB280 L90A1: LD A,(WALL) ; Get wall attribute 1806: 90A4 B7 OR A ; 1807: 90A5 ED52 SBC HL,DE ; Now points to right of Willy's head 1808: 90A7 BE CP (HL) ; Check if that square is a wall 1809: 0000 IF WALLRIGHT 1811: ELSE 1812: 90A8 C8 RET Z ; Return without moving Willy 1813: ENDIF 1814: 90A9 2B DEC HL ; Back to new head-height position 1815: 90AA 22D385 LD (POSITION),HL ; Update Willy's position 1816: 90AD AF XOR A ; Set Willy's sprite to frame 0 1817: 90AE 32D285 L90AE: LD (FRAME),A 1818: 90B1 78 LD A,B 1819: 90B2 32CF85 LD (YPOSN),A ; Update pixel-line position 1820: 90B5 C9 RET 1821: ; Compare this with the left-movement code at L8FDC onwards. The left movement 1822: ; code checks Willy's future position at foot height only, while the right 1823: ; movement checks both at head height and at foot height. This is why wall 1824: ; blocks at head height can be moved through going left, but not right. 1825: ; [Andrew Broad, 11-12-2004] 1826: 1827: 90B6 E1 DIED2: POP HL 1828: 90B7 E1 DIED1: POP HL 1829: 90B8 3EFF LD A,&FF 1830: 90BA 32D185 LD (FALLING),A 1831: 90BD C3F589 JP L89F5 1832: 1833: 1834: ; Update active guardians in current room 1835: ; ======================================= 1836: 90C0 DD210081 UPDATEGUARD: LD IX,GUARDIAN ; Point to active guardian buffer 1837: 90C4 DD7E00 L90C4: LD A,(IX+&00) 1838: 90C7 FEFF CP &FF ; End marker? 1839: 90C9 C8 RET Z ; Exit when all done 1840: 90CA E603 AND &03 ; Check guardian type 1841: 90CC CAB691 JP Z,L91B6 ; Type 0/4 -> jump to check next guardian 1842: 90CF FE01 CP &01 ; Type 1/5? 1843: 90D1 CA3391 JP Z,L9133 ; Horizontal guardian 1844: 90D4 FE02 CP &02 ; Type 2/6? 1845: 90D6 CA7F91 JP Z,L917F ; Vertical guardian 1846: 1847: ; We're now left with type 3 and type 7 guardians - ropes. 1848: ; -------------------------------------------------------- 1849: 90D9 DDCB007E BIT 7,(IX+&00) ; Check rope direction 1850: 90DD 2820 JR Z,L90FF 1851: 90DF DD7E01 LD A,(IX+&01) 1852: 90E2 CB7F BIT 7,A 1853: 90E4 280F JR Z,L90F5 1854: 90E6 D602 SUB &02 1855: 90E8 FE94 CP &94 1856: 90EA 3031 JR NC,L911D 1857: 90EC D602 SUB &02 1858: 90EE FE80 CP &80 1859: 90F0 202B JR NZ,L911D 1860: 90F2 AF XOR A 1861: 90F3 1828 JR L911D 1862: 1863: 90F5 C602 L90F5: ADD A,&02 1864: 90F7 FE12 CP &12 1865: 90F9 3022 JR NC,L911D 1866: 90FB C602 ADD A,&02 1867: 90FD 181E JR L911D 1868: 1869: 90FF DD7E01 L90FF: LD A,(IX+&01) 1870: 9102 CB7F BIT 7,A 1871: 9104 200F JR NZ,L9115 1872: 9106 D602 SUB &02 1873: 9108 FE14 CP &14 1874: 910A 3011 JR NC,L911D 1875: 910C D602 SUB &02 1876: 910E B7 OR A 1877: 910F 200C JR NZ,L911D 1878: 9111 3E80 LD A,&80 1879: 9113 1808 JR L911D 1880: 1881: 9115 C602 L9115: ADD A,&02 1882: 9117 FE92 CP &92 1883: 9119 3002 JR NC,L911D 1884: 911B C602 ADD A,&02 1885: 911D DD7701 L911D: LD (IX+&01),A 1886: 9120 E67F AND &7F 1887: 9122 DDBE07 CP (IX+&07) 1888: 9125 C2B691 JP NZ,L91B6 1889: 9128 DD7E00 LD A,(IX+&00) 1890: 912B EE80 XOR &80 1891: 912D DD7700 LD (IX+&00),A 1892: 9130 C3B691 JP L91B6 1893: 1894: ; Horizontal guardian 1895: ; ------------------- 1896: 9133 DDCB007E L9133: BIT 7,(IX+&00) ; Get direction 1897: 9137 2023 JR NZ,L915C ; Jump to move right 1898: 1899: ; Move horizontal guardian left 1900: ; ----------------------------- 1901: 9139 DD7E00 LD A,(IX+&00) 1902: 913C D620 SUB &20 1903: 913E E67F AND &7F 1904: 9140 DD7700 LD (IX+&00),A 1905: 9143 FE60 CP &60 1906: 9145 386F JR C,L91B6 1907: 9147 DD7E02 LD A,(IX+&02) 1908: 914A E61F AND &1F 1909: 914C DDBE06 CP (IX+&06) 1910: 914F 2805 JR Z,L9156 1911: 9151 DD3502 DEC (IX+&02) 1912: 9154 1860 JR L91B6 1913: 1914: 9156 DD360081 L9156: LD (IX+&00),&81 1915: 915A 185A JR L91B6 1916: 1917: ; Move horizontal guardian right 1918: ; ------------------------------ 1919: 915C DD7E00 L915C: LD A,(IX+&00) 1920: 915F C620 ADD A,&20 1921: 9161 F680 OR &80 1922: 9163 DD7700 LD (IX+&00),A 1923: 9166 FEA0 CP &A0 1924: 9168 304C JR NC,L91B6 1925: 916A DD7E02 LD A,(IX+&02) 1926: 916D E61F AND &1F 1927: 916F DDBE07 CP (IX+&07) 1928: 9172 2805 JR Z,L9179 1929: 9174 DD3402 INC (IX+&02) 1930: 9177 183D JR L91B6 1931: 1932: 9179 DD360061 L9179: LD (IX+&00),&61 1933: 917D 1837 JR L91B6 1934: 1935: ; Vertical guardian 1936: ; ----------------- 1937: 917F DD7E00 L917F: LD A,(IX+&00) 1938: 9182 EE08 XOR &08 1939: 9184 DD7700 LD (IX+&00),A 1940: 9187 E618 AND &18 1941: 9189 2808 JR Z,L9193 1942: 918B DD7E00 LD A,(IX+&00) 1943: 918E C620 ADD A,&20 1944: 9190 DD7700 LD (IX+&00),A 1945: 9193 DD7E03 L9193: LD A,(IX+&03) 1946: 9196 DD8604 ADD A,(IX+&04) 1947: 9199 DD7703 LD (IX+&03),A 1948: 919C DDBE07 CP (IX+&07) 1949: 919F 300D JR NC,L91AE 1950: 91A1 DDBE06 CP (IX+&06) 1951: 91A4 2802 JR Z,L91A8 1952: 91A6 300E JR NC,L91B6 1953: 91A8 DD7E06 L91A8: LD A,(IX+&06) 1954: 91AB DD7703 LD (IX+&03),A 1955: 91AE DD7E04 L91AE: LD A,(IX+&04) 1956: 91B1 ED44 NEG 1957: 91B3 DD7704 LD (IX+&04),A 1958: 91B6 110800 L91B6: LD DE,&0008 ; Eight bytes per guardian 1959: 91B9 DD19 ADD IX,DE ; Point to next guardian 1960: 91BB C3C490 JP L90C4 ; Loop back to check all guardians 1961: 1962: 1963: ; Draw guardians to screen buffer 2 1964: ; ================================= 1965: 91BE DD210081 DRAWGUARD: LD IX,GUARDIAN ; Point to guardian buffer 1966: 91C2 DD7E00 L91C2: LD A,(IX+&00) ; Get guardian type 1967: 91C5 FEFF CP &FF ; End marker? 1968: 91C7 C8 RET Z ; Exit when all done 1969: 91C8 E607 AND &07 ; Check guardian type 1970: 91CA CAB393 JP Z,L93B3 ; Type 0 - null guardian 1971: 91CD FE03 CP &03 ; Type 3? - a rope? 1972: 91CF CAA492 JP Z,L92A4 ; Jump to deal with ropes 1973: 91D2 FE04 CP &04 ; Type 4 - an arrow? 1974: 91D4 2861 JR Z,L9237 ; Jump to deal with arrows 1975: 1976: ; Horizontal and vertical guardians are both draw the same way. Once their 1977: ; position has been updated, all they are is a sprite that needs to be placed 1978: ; on the screen at a specified position. 1979: 1980: 91D6 DD5E03 LD E,(IX+&03) ; Get Y position 1981: 91D9 1682 LD D,PIXEL / 256 ; Index into pixel-line table 1982: 91DB 1A LD A,(DE) ; Get low byte of Y position address 1983: 91DC 6F LD L,A ; Pass to L for later 1984: 91DD DD7E02 LD A,(IX+&02) ; Get X position 1985: 91E0 E61F AND &1F ; Reduce to 0-31 1986: 91E2 85 ADD A,L ; Add to Y position address 1987: 91E3 6F LD L,A ; And store back into L 1988: 91E4 7B LD A,E ; Convert this into an attribute buffer 1989: 91E5 07 RLCA ; address 1990: 91E6 E601 AND &01 1991: 91E8 F65C OR &5C 1992: 91EA 67 LD H,A ; HL=address in attribute buffer 2 1993: 91EB 111F00 LD DE,&001F ; Set DE to 31 for later adding 1994: 91EE DD7E01 LD A,(IX+&01) ; Get guardian's attribute 1995: 91F1 E60F AND &0F ; b0-b3=INK, b4=BRIGHT 1996: 91F3 C638 ADD A,&38 ; Move BRIGHT up to bit 6 1997: 91F5 E647 AND &47 ; Keep INK and BRIGHT 1998: 91F7 4F LD C,A ; Save in C 1999: 91F8 7E LD A,(HL) ; Get attribute in this position 2000: 91F9 E638 AND &38 ; Keep PAPER 2001: 91FB A9 XOR C ; Merge in guardian's INK and BRIGHT 2002: 91FC 4F LD C,A ; Pass back to C 2003: 91FD 71 LD (HL),C ; Store attribute for 2x2 characters 2004: 91FE 23 INC HL ; Set attributes for top two cells 2005: 91FF 71 LD (HL),C 2006: 9200 19 ADD HL,DE ; Add 31 to move to next line 2007: 9201 71 LD (HL),C ; Set attributes for bottom two cells 2008: 9202 23 INC HL 2009: 9203 71 LD (HL),C 2010: 9204 DD7E03 LD A,(IX+&03) ; Get guardian's Y position 2011: 9207 E60E AND &0E ; Has it moved away from pixel-line 0? 2012: 9209 2804 JR Z,L920F ; No, so only 2x2 blocks to colour 2013: 2014: ; Guardian overlaps three character lines, so six attribute cells need to be 2015: ; set to set it's colour. 2016: 2017: 920B 19 ADD HL,DE ; Add 31 to move to next line 2018: 920C 71 LD (HL),C ; Set attributes on two move cells 2019: 920D 23 INC HL 2020: 920E 71 LD (HL),C 2021: 920F 0E01 L920F: LD C,&01 ; Don't ignore collisions 2022: 9211 DD7E01 LD A,(IX+&01) ; Construct sprite address 2023: 9214 DDA600 AND (IX+&00) ; Sprite address subpage bit7 2024: 9217 DDB602 OR (IX+&02) ; X position top 3 bits 2025: 921A E6E0 AND &E0 ; 32 bytes per sprite 2026: 921C 5F LD E,A ; Set sprite address low byte 2027: 921D DD5605 LD D,(IX+&05) ; Get sprite address high byte 2028: 9220 2682 LD H,PIXEL / 256 ; Pixel-line buffer high byte 2029: 9222 DD6E03 LD L,(IX+&03) ; Get guardian's Y position 2030: 9225 DD7E02 LD A,(IX+&02) ; Get guardian's X position 2031: 9228 E61F AND &1F ; Resolve to 0-31 2032: 922A B6 OR (HL) ; Add to pixel-line start address low 2033: 922B 23 INC HL ; Point to pixel-line address high 2034: 922C 66 LD H,(HL) ; Get high byte of address 2035: 922D 6F LD L,A ; HL is address to draw sprite 2036: 922E CD5694 CALL DRAWSPRITE ; Draw the sprite 2037: 9231 C2B790 JP NZ,DIED1 ; If the sprite collided, kill Willy 2038: 9234 C3B393 JP L93B3 ; Draw next guardian 2039: 2040: ; Arrow 2041: ; ----- 2042: 9237 DDCB007E L9237: BIT 7,(IX+&00) ; Arrow direction 2043: 923B 2007 JR NZ,L9244 2044: 923D DD3504 DEC (IX+&04) 2045: 9240 0E2C LD C,&2C 2046: 9242 1805 JR L9249 2047: 2048: 9244 DD3404 L9244: INC (IX+&04) 2049: 9247 0EF4 LD C,&F4 2050: 9249 DD7E04 L9249: LD A,(IX+&04) 2051: 924C B9 CP C 2052: 924D 2013 JR NZ,L9262 2053: 924F 018002 LD BC,&0280 2054: 9252 3ADE80 LD A,(BORDER) 2055: 9255 D3FE L9255: OUT (&FE),A ; Squawk! 2056: 9257 EE18 XOR &18 2057: 9259 10FE L9259: DJNZ L9259 2058: 925B 41 LD B,C 2059: 925C 0D DEC C 2060: 925D 20F6 JR NZ,L9255 2061: 925F C3B393 JP L93B3 2062: 2063: 9262 E6E0 L9262: AND &E0 2064: 9264 C2B393 JP NZ,L93B3 2065: 9267 DD5E02 LD E,(IX+&02) 2066: 926A 1682 LD D,&82 2067: 926C 1A LD A,(DE) 2068: 926D DD8604 ADD A,(IX+&04) 2069: 9270 6F LD L,A 2070: 9271 7B LD A,E 2071: 9272 E680 AND &80 2072: 9274 07 RLCA 2073: 9275 F65C OR &5C 2074: 9277 67 LD H,A 2075: 9278 DD360500 LD (IX+&05),&00 2076: 927C 7E LD A,(HL) 2077: 927D E607 AND &07 2078: 927F FE07 CP &07 2079: 9281 2003 JR NZ,L9286 2080: 9283 DD3505 DEC (IX+&05) 2081: 9286 7E L9286: LD A,(HL) 2082: 9287 F607 OR &07 2083: 9289 77 LD (HL),A 2084: 928A 13 INC DE 2085: 928B 1A LD A,(DE) 2086: 928C 67 LD H,A 2087: 928D 25 DEC H 2088: 928E DD7E06 LD A,(IX+&06) 2089: 9291 77 LD (HL),A 2090: 9292 24 INC H 2091: 9293 7E LD A,(HL) 2092: 9294 DDA605 AND (IX+&05) 2093: 9297 C2B790 JP NZ,DIED1 2094: 929A 36FF LD (HL),&FF 2095: 929C 24 INC H 2096: 929D DD7E06 LD A,(IX+&06) 2097: 92A0 77 LD (HL),A 2098: 92A1 C3B393 JP L93B3 2099: 2100: 92A4 FD210082 L92A4: LD IY,PIXEL ; Pixel-line table 2101: 92A8 DD360900 LD (IX+&09),&00 2102: 92AC DD7E02 LD A,(IX+&02) 2103: 92AF DD7703 LD (IX+&03),A 2104: 92B2 DD360580 LD (IX+&05),&80 2105: 92B6 FD7E00 L92B6: LD A,(IY+&00) 2106: 92B9 DD8603 ADD A,(IX+&03) 2107: 92BC 6F LD L,A 2108: 92BD FD6601 LD H,(IY+&01) 2109: 92C0 3AD685 LD A,(ONROPE) 2110: 92C3 B7 OR A 2111: 92C4 2010 JR NZ,L92D6 2112: 92C6 DD7E05 LD A,(IX+&05) 2113: 92C9 A6 AND (HL) 2114: 92CA 2842 JR Z,L930E 2115: 92CC DD7E09 LD A,(IX+&09) 2116: 92CF 32D685 LD (ONROPE),A 2117: 92D2 DDCB0BC6 SET 0,(IX+&0B) 2118: 92D6 DDBE09 L92D6: CP (IX+&09) 2119: 92D9 2033 JR NZ,L930E 2120: 92DB DDCB0B46 BIT 0,(IX+&0B) 2121: 92DF 282D JR Z,L930E 2122: 92E1 DD4603 LD B,(IX+&03) 2123: 92E4 DD7E05 LD A,(IX+&05) 2124: 92E7 0E01 LD C,&01 2125: 92E9 FE04 CP &04 2126: 92EB 380F JR C,L92FC 2127: 92ED 0E00 LD C,&00 2128: 92EF FE10 CP &10 2129: 92F1 3809 JR C,L92FC 2130: 92F3 05 DEC B 2131: 92F4 0E03 LD C,&03 2132: 92F6 FE40 CP &40 2133: 92F8 3802 JR C,L92FC 2134: 92FA 0E02 LD C,&02 2135: 92FC ED43D285 L92FC: LD (FRAME),BC 2136: 9300 FD DEFB &FD 2137: 9301 7D LD A,L ; LD A,IYL 2138: 9302 D610 SUB &10 2139: 9304 32CF85 LD (YPOSN),A 2140: 9307 E5 PUSH HL 2141: 9308 CD9C8E CALL L8E9C 2142: 930B E1 POP HL 2143: 930C 1800 JR L930E 2144: 2145: 930E DD7E05 L930E: LD A,(IX+&05) 2146: 9311 B6 OR (HL) 2147: 9312 77 LD (HL),A 2148: 9313 DD7E09 LD A,(IX+&09) 2149: 9316 DD8601 ADD A,(IX+&01) 2150: 9319 6F LD L,A 2151: 931A CBFD SET 7,L 2152: 931C 2683 LD H,&83 ; Rope structure table 2153: 931E 5E LD E,(HL) 2154: 931F 1600 LD D,&00 2155: 9321 FD19 ADD IY,DE 2156: 9323 CBBD RES 7,L 2157: 9325 7E LD A,(HL) 2158: 9326 B7 OR A 2159: 9327 2827 JR Z,L9350 2160: 9329 47 LD B,A 2161: 932A DDCB017E BIT 7,(IX+&01) 2162: 932E 2811 JR Z,L9341 2163: 9330 DDCB0506 L9330: RLC (IX+&05) 2164: 9334 DDCB0546 BIT 0,(IX+&05) 2165: 9338 2803 JR Z,L933D 2166: 933A DD3503 DEC (IX+&03) 2167: 933D 10F1 L933D: DJNZ L9330 2168: 933F 180F JR L9350 2169: 2170: 9341 DDCB050E L9341: RRC (IX+&05) 2171: 9345 DDCB057E BIT 7,(IX+&05) 2172: 9349 2803 JR Z,L934E 2173: 934B DD3403 INC (IX+&03) 2174: 934E 10F1 L934E: DJNZ L9341 2175: 9350 DD7E09 L9350: LD A,(IX+&09) 2176: 9353 DDBE04 CP (IX+&04) 2177: 9356 2806 JR Z,L935E 2178: 9358 DD3409 INC (IX+&09) 2179: 935B C3B692 JP L92B6 2180: 2181: 935E 3AD685 L935E: LD A,(ONROPE) 2182: 9361 CB7F BIT 7,A 2183: 9363 280A JR Z,L936F 2184: 9365 3C INC A 2185: 9366 32D685 LD (ONROPE),A 2186: 9369 DDCB0B86 RES 0,(IX+&0B) 2187: 936D 1844 JR L93B3 2188: 2189: 936F DDCB0B46 L936F: BIT 0,(IX+&0B) 2190: 9373 283E JR Z,L93B3 2191: 9375 3AD085 LD A,(L85D0) 2192: 9378 CB4F BIT 1,A 2193: 937A 2837 JR Z,L93B3 2194: 937C 0F RRCA 2195: 937D DDAE00 XOR (IX+&00) 2196: 9380 07 RLCA 2197: 9381 07 RLCA 2198: 9382 E602 AND &02 2199: 9384 3D DEC A 2200: 9385 21D685 LD HL,ONROPE 2201: 9388 86 ADD A,(HL) 2202: 9389 77 LD (HL),A 2203: 938A 3AEB80 LD A,(UP) 2204: 938D 4F LD C,A 2205: 938E 3A2084 LD A,(HERE) ; Can't go up if UP goes to same room 2206: 9391 B9 CP C 2207: 9392 2007 JR NZ,L939B 2208: 9394 7E LD A,(HL) 2209: 9395 FE0C CP &0C 2210: 9397 3002 JR NC,L939B 2211: 9399 360C LD (HL),&0C 2212: 939B 7E L939B: LD A,(HL) 2213: 939C DDBE04 CP (IX+&04) 2214: 939F 3812 JR C,L93B3 2215: 93A1 2810 JR Z,L93B3 2216: 93A3 36F0 LD (HL),&F0 2217: 93A5 3ACF85 LD A,(YPOSN) 2218: 93A8 E6F8 AND &F8 2219: 93AA 32CF85 LD (YPOSN),A 2220: 93AD AF XOR A 2221: 93AE 32D185 LD (FALLING),A 2222: 93B1 1800 JR L93B3 2223: 2224: 93B3 110800 L93B3: LD DE,&0008 2225: 93B6 DD19 ADD IX,DE ; Point to next guardian 2226: 93B8 C3C291 JP L91C2 2227: 2228: ; Nothing seems to call this 2229: ; ========================== 2230: ; This sets the INK six attribute cells. This would be appropriate for a 32x32 2231: ; sprite that has moved away from pixel-line 0 in a character cell, and so 2232: ; overlaps three characters rows. 2233: 93BB 77 L93BB: LD (HL),A 2234: 93BC 3AA080 LD A,(BACKGROUND) 2235: 93BF E6F8 AND &F8 2236: 93C1 B6 OR (HL) 2237: 93C2 77 LD (HL),A 2238: 93C3 111F00 LD DE,&001F 2239: 93C6 23 INC HL 2240: 93C7 77 LD (HL),A 2241: 93C8 19 ADD HL,DE 2242: 93C9 77 LD (HL),A 2243: 93CA 23 INC HL 2244: 93CB 77 LD (HL),A 2245: 93CC 19 ADD HL,DE 2246: 93CD 77 LD (HL),A 2247: 93CE 23 INC HL 2248: 93CF 77 LD (HL),A 2249: 93D0 C9 RET 2250: 2251: 2252: ; Process objects 2253: ; =============== 2254: 93D1 CHKOBJECTS: 2255: 0001 IF MOREROOMS 2256: 93D1 26A6 LD H,&A6 ; High byte of collection flags 2257: ELSE 2259: ENDIF 2260: 93D3 3AFFA3 LD A,(OBJECTS) ; Get 256-number of objects 2261: 93D6 6F LD L,A ; HL points to collection flags 2262: 93D7 L93D7: 2263: 0001 IF MOREROOMS 2264: 93D7 CB76 BIT 6,(HL) ; Is this object collected? 2265: 93D9 2877 JR Z,L9452 ; Yes, jump to check next object 2266: 93DB 25 DEC H 2267: 93DC 25 DEC H ; Point to object position 2268: 93DD CDF496 CALL L96F4 ; Draw this object if in this room 2269: ELSE 2275: ENDIF 2276: 93E0 2070 JR NZ,L9452 ; No, jump to check next object 2277: 93E2 7E LD A,(HL) ; Get object Y position bit 4 2278: 93E3 07 RLCA ; Move to bit 0 2279: 93E4 E601 AND &01 2280: 93E6 C65C ADD A,&5C ; Object's screen half 2281: 93E8 57 LD D,A ; Pass to D for later on 2282: 93E9 24 INC H ; Point to position X and Y b0-b3 2283: 93EA 5E LD E,(HL) ; Pass to E 2284: 0001 IF MOREROOMS 2285: 93EB 24 INC H ; Point back to collection flags 2286: ELSE 2288: ENDIF 2289: 93EC 1A LD A,(DE) ; Get attribute at object's position 2290: 93ED E607 AND &07 ; Keep INK 2291: 93EF FE07 CP &07 ; White indicating Willy there? 2292: 93F1 203D JR NZ,L9430 ; Not white, draw the object 2293: 93F3 DD217C85 LD IX,COLLECTED ; Point to collected items string 2294: 93F7 DD3402 L93F7: INC (IX+&02) ; Increment a digit 2295: 93FA DD7E02 LD A,(IX+&02) ; Get current digit 2296: 93FD FE3A CP &3A ; Wrapped past '0'? 2297: 93FF 2008 JR NZ,L9409 ; No, continue to make a sound 2298: 9401 DD360230 LD (IX+&02),&30 ; Set current digit to '0' 2299: 9405 DD2B DEC IX ; Point to next higher order digit 2300: 9407 18EE JR L93F7 ; Loop to increment this digit 2301: 2302: ; Make a sound and collect an object 2303: ; ---------------------------------- 2304: 9409 3ADE80 L9409: LD A,(BORDER) ; Get border colour 2305: 940C 0E80 LD C,&80 2306: 940E D3FE L940E: OUT (&FE),A ; Write to buzzer 2307: 9410 EE18 XOR &18 ; Toggle buzzer state 2308: 9412 5F LD E,A 2309: 9413 3E90 LD A,&90 2310: 9415 91 SUB C 2311: 9416 47 LD B,A 2312: 9417 7B LD A,E 2313: 9418 10FE L9418: DJNZ L9418 ; Pause a while 2314: 941A 0D DEC C 2315: 941B 0D DEC C 2316: 941C 20F0 JR NZ,L940E ; Loop to play a note 2317: 941E 3ADE85 LD A,(REMAIN) ; Get remaining items 2318: 9421 3C INC A 2319: 9422 32DE85 LD (REMAIN),A ; Update remaining items 2320: 9425 2005 JR NZ,L942C ; Jump if not all collected 2321: 9427 3E01 LD A,&01 2322: 9429 32DF85 LD (STATUS),A ; Set STATUS to 'collected' 2323: 942C CBB6 L942C: RES 6,(HL) ; Clear 'not collected' flag 2324: 942E 1822 JR L9452 ; Loop to check next item 2325: 2326: ; Draw object and 'wobble' its colours 2327: ; ------------------------------------ 2328: 9430 3ACB85 L9430: LD A,(TICKER) ; Wobble colours with game ticker 2329: 9433 85 ADD A,L ; Add to object table offset 2330: 9434 E603 AND &03 ; Keep b0-b1, colours are 2331: 9436 C603 ADD A,&03 ; magenta, green, cyan, yellow 2332: 9438 4F LD C,A 2333: 9439 1A LD A,(DE) ; Get attributes under object 2334: 943A E6F8 AND &F8 ; Lose INK 2335: 943C B1 OR C ; Merge in wobbling INK 2336: 943D 12 LD (DE),A ; Store to attributes 2337: 0001 IF MOREROOMS 2338: 943E 7A LD A,D ; Get object's Y position bit 4 2339: 943F 00 NOP ; Already in bit 0 2340: ELSE 2343: ENDIF 2344: 9440 07 RLCA 2345: 9441 07 RLCA ; Move to bit 3, calculate screen 2346: 9442 07 RLCA ; address top third or middle third 2347: 9443 E608 AND &08 ; E already holds position with third 2348: 9445 C660 ADD A,&60 ; as it is the same as the attribute 2349: 9447 57 LD D,A ; address low byte 2350: 9448 E5 PUSH HL ; Save object table pointer 2351: 9449 21E180 LD HL,OBJECT ; Point to object's bitmap 2352: 944C 0608 LD B,&08 ; Eight pixel-lines 2353: 944E CD9B96 CALL PRMATRIX ; Draw the object 2354: 9451 E1 POP HL ; Restore object table pointer 2355: 9452 2C L9452: INC L ; Point to next item 2356: 9453 2082 JR NZ,L93D7 ; Loop until end of table reached 2357: 9455 C9 RET 2358: 2359: 2360: ; Draw a sprite 2361: ; ============= 2362: ; DE=sprite address 2363: ; HL=screen address 2364: ; C=0 - ignore collisions, C=1 - don't ignore collisions 2365: 9456 0610 DRAWSPRITE: LD B,&10 ; 16 pixel-lines 2366: 9458 CB41 L9458: BIT 0,C ; Check collision flag 2367: 945A 1A LD A,(DE) ; Get byte from sprite 2368: 945B 2804 JR Z,L9461 ; If ignoring collision, jump to store 2369: 945D A6 AND (HL) ; Mask with pixels on screen 2370: 945E C0 RET NZ ; If any overlap, exit with NZ set 2371: 945F 1A LD A,(DE) ; Get byte from sprite again 2372: 9460 B6 OR (HL) ; Merge with pixels on screen 2373: 9461 77 L9461: LD (HL),A ; Store byte to screen 2374: 9462 2C INC L ; Point to right-hand screen byte 2375: 9463 13 INC DE ; Point to next sprite byte 2376: 9464 CB41 BIT 0,C ; Check collision flag 2377: 9466 1A LD A,(DE) ; Get byte from sprite 2378: 9467 2804 JR Z,L946D ; If ignoring collision, jump to store 2379: 9469 A6 AND (HL) ; Mask with pixels on screen 2380: 946A C0 RET NZ ; If any overlap, exit with NZ set 2381: 946B 1A LD A,(DE) ; Get byte from sprite again 2382: 946C B6 OR (HL) ; Merge with pixels on screen 2383: 946D 77 L946D: LD (HL),A ; Store byte to screen 2384: 946E 2D DEC L ; Point back to left-hand screen byte 2385: 946F 24 INC H ; Move down one pixel-line 2386: 9470 13 INC DE ; Point to next sprite byte 2387: 9471 7C LD A,H ; Check screen address high byte to 2388: 9472 E607 AND &07 ; see if wrapped past pixel-line 7 2389: 9474 2010 JR NZ,L9486 2390: 9476 7C LD A,H ; Adjust screen address 2391: 9477 D608 SUB &08 2392: 9479 67 LD H,A 2393: 947A 7D LD A,L 2394: 947B C620 ADD A,&20 2395: 947D 6F LD L,A 2396: 947E E6E0 AND &E0 2397: 9480 2004 JR NZ,L9486 2398: 9482 7C LD A,H 2399: 9483 C608 ADD A,&08 2400: 9485 67 LD H,A 2401: 9486 10D0 L9486: DJNZ L9458 ; Loop for 16 pixel-lines 2402: 9488 AF XOR A ; Ensure Z set 2403: 9489 C9 RET ; Exit 2404: 2405: 2406: ; Move left 2407: ; ========= 2408: 948A 3AE980 GO_LEFT: LD A,(LEFT) ; Get room through left exit 2409: 948D 322084 LD (HERE),A ; Set current room 2410: 9490 3AD385 LD A,(POSITION) ; Get Willy's position 2411: 9493 F61F OR &1F ; Force into column 31 2412: 9495 E6FE AND &FE ; Make it column 30 2413: 9497 32D385 LD (POSITION),A ; Store Willy's position 2414: 949A E1 POP HL ; Lose return address 2415: 949B C31289 JP PLAYROOM ; Enter the new current room 2416: 2417: ; Move right 2418: ; ========== 2419: 949E 3AEA80 GO_RIGHT: LD A,(RIGHT) ; Get room through right exit 2420: 94A1 322084 LD (HERE),A ; Set current room 2421: 94A4 3AD385 LD A,(POSITION) ; Get Willy's position 2422: 94A7 E6E0 AND &E0 ; Force into column 0 2423: 94A9 32D385 LD (POSITION),A ; Store Willy's position 2424: 94AC E1 POP HL ; Lose return address 2425: 94AD C31289 JP PLAYROOM ; Enter the new current room 2426: 2427: ; Move up 2428: ; ======= 2429: 94B0 3AEB80 GO_UP: LD A,(UP) ; Get room through up exit 2430: 94B3 322084 LD (HERE),A ; Set current room 2431: 94B6 3AD385 LD A,(POSITION) ; Get Willy's position low byte 2432: 94B9 E61F AND &1F ; Keep X position 2433: 94BB C6A0 ADD A,&A0 ; Set Y position to line 13 2434: 94BD 32D385 LD (POSITION),A ; Store Willy's position low byte 2435: 94C0 3E5D LD A,&5D ; Put Willy in bottom half of screen 2436: 94C2 32D485 LD (POSITION+1),A ; Set Willy's position high byte 2437: 94C5 3ED0 LD A,&D0 ; Set Willy's Y position to line 13 2438: 94C7 32CF85 LD (YPOSN),A 2439: 94CA AF XOR A ; Clear movement flag 2440: 94CB 32D185 LD (FALLING),A ; Not falling, normal movement 2441: 94CE E1 POP HL ; Lose return address 2442: 94CF C31289 JP PLAYROOM ; Enter the new current room 2443: 2444: ; Move down 2445: ; ========= 2446: 94D2 3AEC80 GO_DOWN: LD A,(DOWN) ; Get room through down exit 2447: 94D5 322084 LD (HERE),A ; Set current room 2448: 94D8 AF XOR A 2449: 94D9 32CF85 LD (YPOSN),A ; Set Willy's Y position to line 0 2450: 94DC 3AD185 LD A,(FALLING) ; Get falling state 2451: 94DF FE0B CP &0B 2452: 94E1 3005 JR NC,&94E8 2453: 94E3 3E02 LD A,&02 2454: 94E5 32D185 LD (FALLING),A ; Set falling state to 2 2455: 94E8 3AD385 L94E8: LD A,(POSITION) ; Get Willy's position low byte 2456: 94EB E61F AND &1F ; Keep X position, set Y to 0 2457: 94ED 32D385 LD (POSITION),A ; Store Willy's position low byte 2458: 94F0 3E5C LD A,&5C ; Put Willy at top of screen 2459: 94F2 32D485 LD (POSITION+1),A ; Set Willy's position high byte 2460: 94F5 E1 POP HL ; Lose return address 2461: 94F6 C31289 JP PLAYROOM ; Enter the new current room 2462: 2463: 2464: ; Update conveyors appearance on screen 2465: ; ===================================== 2466: 94F9 2AD780 UPDATECONV: LD HL,(CONV_PSN) ; Get conveyor's start position 2467: 94FC 7C LD A,H ; Convert position to screen buffer 1 2468: 94FD E601 AND &01 ; address 2469: 94FF 07 RLCA 2470: 9500 07 RLCA 2471: 9501 07 RLCA 2472: 9502 C670 ADD A,&70 2473: 9504 67 LD H,A ; HL=address in screen buffer 1 2474: 9505 5D LD E,L ; Save in DE as well 2475: 9506 54 LD D,H 2476: 9507 3AD980 LD A,(CONV_NUM) ; Get conveyor length 2477: 950A B7 OR A 2478: 950B C8 RET Z ; No conveyor, so exit 2479: 950C 47 LD B,A ; Pass to B as loop counter 2480: 950D 3AD680 LD A,(CONV_DIR) ; Get conveyor direction 2481: 9510 B7 OR A ; Is it moving right? 2482: 9511 2013 JR NZ,L9526 ; Any non-zero direction rotates right 2483: 2484: ; Rotate conveyor leftwards 2485: ; ------------------------- 2486: 9513 7E LD A,(HL) ; Get conveyor top pixel-line 2487: 9514 CB07 RLC A ; Rotate left two bits 2488: 9516 CB07 RLC A 2489: 9518 24 INC H ; Point two pixel-lines down 2490: 9519 24 INC H 2491: 951A 4E LD C,(HL) ; Get conveyor's third pixel-line 2492: 951B CB09 RRC C ; Rotate right two bits 2493: 951D CB09 RRC C 2494: 951F 12 L951F: LD (DE),A ; Store updated top pixel-line 2495: 9520 71 LD (HL),C ; Store updated third pixel-line 2496: 9521 2C INC L ; Point to next conveyor character 2497: 9522 1C INC E 2498: 9523 10FA DJNZ L951F ; Loop for conveyor length 2499: 9525 C9 RET 2500: 2501: ; Rotate conveyor rightwards 2502: ; -------------------------- 2503: 9526 7E L9526: LD A,(HL) ; Get conveyor top pixel-line 2504: 9527 CB0F RRC A ; Rotate right two bits 2505: 9529 CB0F RRC A 2506: 952B 24 INC H ; Point to pixel-lines down 2507: 952C 24 INC H 2508: 952D 4E LD C,(HL) ; Get conveyor's third pixel-line 2509: 952E CB01 RLC C ; Rotate left two bits 2510: 9530 CB01 RLC C 2511: 9532 18EB JR L951F ; Jump to update whole conveyor 2512: 2513: 2514: ; Deal with special case rooms 2515: ; ============================ 2516: 9534 3A2084 SPECIAL: LD A,(HERE) ; Get current room 2517: 9537 FE23 CP &23 ; Master Bedroom? 2518: 9539 205F JR NZ,L959A ; No, jump to check for Bathroom 2519: 2520: ; Special actions for The Master Bedroom 2521: ; -------------------------------------- 2522: ; Draw Maria according to how far into the room Willy has got. This is 2523: ; measured by Willy's Y position, so if he jumps, Maria raises her arm. 2524: 953B 3ADF85 LD A,(STATUS) 2525: 953E B7 OR A ; Normal gameplay? 2526: 953F 2035 JR NZ,L9576 ; No, jump to check for the bed 2527: 9541 3ACB85 LD A,(TICKER) ; Animate Maria with the game ticker 2528: 9544 E602 AND &02 ; Keep bit 1 2529: 9546 0F RRCA 2530: 9547 0F RRCA 2531: 9548 0F RRCA 2532: 9549 0F RRCA ; Multiply by 16 to give 0 or 32 2533: 954A F680 OR &80 ; &80, &A0 are the foot tapping Maria 2534: 954C 5F LD E,A ; Pass to E as sprite subpage value 2535: 954D 3ACF85 LD A,(YPOSN) ; Get Willy's Y position 2536: 9550 FED0 CP &D0 ; Is Willy on the floor - line 13? 2537: 9552 2808 JR Z,DRAWMARIA ; Yes, jump to draw Maria 2538: 9554 1EC0 LD E,&C0 ; Point to Maria raising her hand 2539: 9556 FEC0 CP &C0 ; Has Willy started up the ramp? 2540: 9558 3002 JR NC,DRAWMARIA ; Yes, jump to draw Maria 2541: 955A 1EE0 LD E,&E0 ; Otherwise, Maria with outstretched arm 2542: 2543: 955C 169C DRAWMARIA: LD D,&9C ; Maria sprite page 2544: 955E 216E68 LD HL,&686E ; Maria's position in buffer 2 2545: 9561 0E01 LD C,&01 ; Don't ignore collisions 2546: 9563 CD5694 CALL DRAWSPRITE ; Draw Maria sprite 2547: 9566 C2B790 JP NZ,DIED1 ; Kill Willy if Maria touched him 2548: 9569 214545 LD HL,&4545 ; Bright cyan on black 2549: 956C 226E5D LD (&5D6E),HL ; Set colours of Maria's top half 2550: 956F 210707 LD HL,&0707 ; White on black 2551: 9572 228E5D LD (&5D8E),HL ; Set colours of Maria's skirt 2552: 9575 C9 RET 2553: 2554: ; Check if Willy has got as far as the bed 2555: ; ---------------------------------------- 2556: 9576 3AD385 L9576: LD A,(POSITION) ; Get Willy's position 2557: 9579 E61F AND &1F ; Get X coordinate 2558: 957B FE06 CP &06 ; Further left than X=6? 2559: 957D D0 RET NC ; Not reached the bed yet 2560: 957E 3E02 LD A,&02 ; Reached the bed 2561: 9580 32DF85 LD (STATUS),A ; Set STATUS to 2 to indicate fleeing 2562: 9583 C9 RET 2563: 2564: ; Has Willy reached the toilet while fleeing? 2565: ; ------------------------------------------- 2566: 9584 3A2084 CHKTOILET: LD A,(HERE) ; Get current room 2567: 9587 FE21 CP &21 ; The Bathroom? 2568: 9589 C0 RET NZ ; No, exit 2569: 958A 3AD385 LD A,(POSITION) ; Get Willy's position 2570: 958D FEBC CP &BC ; Line 13 (or 5!), column 28? 2571: 958F C0 RET NZ ; No, exit 2572: 9590 AF XOR A 2573: 9591 32CB85 LD (TICKER),A ; Force ticker to zero 2574: 9594 3E03 LD A,&03 2575: 9596 32DF85 LD (STATUS),A ; Set STATUS to 3 to indicate vomiting 2576: 9599 C9 RET 2577: 2578: ; Special actions for The Bathroom 2579: ; -------------------------------- 2580: ; Animate the toilet without killing Willy, or animate Willy communing with 2581: ; the porcelain. 2582: 959A 3A2084 L959A: LD A,(HERE) ; Get current room 2583: 959D FE21 CP &21 ; Bathroom? 2584: 959F C0 RET NZ ; No, exit 2585: 95A0 3ACB85 LD A,(TICKER) ; Animate toilet with the game ticker 2586: 95A3 E601 AND &01 ; Keep bit 0 2587: 95A5 0F RRCA 2588: 95A6 0F RRCA 2589: 95A7 0F RRCA ; Multiply by 32 to give &00 or &20 2590: 95A8 5F LD E,A ; Pass to E as the sprite subpage 2591: 95A9 3ADF85 LD A,(STATUS) 2592: 95AC FE03 CP &03 ; Is Willy throwing up? 2593: 95AE 2002 JR NZ,DRAWTOILET ; No, animate toilet 2594: 95B0 CBF3 SET 6,E ; Point to Willy and the toilet 2595: 2596: 95B2 16A6 DRAWTOILET: LD D,&A6 ; Toilet sprite page 2597: 95B4 DD21D082 LD IX,&82D0 ; Pixel-line address for line 13 2598: 95B8 011C10 LD BC,&101C ; 16 pixel lines, X position is &1C 2599: 95BB CD6896 CALL L9668 ; Draw toilet with the DRAWWILLY 2600: ; routine to merge with screen content 2601: 95BE 210707 LD HL,&0707 ; White on black 2602: 95C1 22BC5D LD (&5DBC),HL ; Set toilet's colours 2603: 95C4 22DC5D LD (&5DDC),HL 2604: 95C7 C9 RET 2605: 2606: 2607: ; Update Willy's position and draw him to screen buffer 2 2608: ; ======================================================= 2609: 95C8 2AD385 UPDATEWILLY: LD HL,(POSITION) ; Get Willy's position 2610: 95CB 0600 LD B,&00 2611: 95CD 3ADA80 LD A,(SLOPE_DIR) 2612: 95D0 E601 AND &01 2613: 95D2 C640 ADD A,&40 2614: 95D4 5F LD E,A 2615: 95D5 1600 LD D,&00 2616: 95D7 19 ADD HL,DE 2617: 95D8 3AC480 LD A,(SLOPE) 2618: 95DB BE CP (HL) 2619: 95DC 201A JR NZ,L95F8 2620: 95DE 3AD185 LD A,(FALLING) 2621: 95E1 B7 OR A 2622: 95E2 2014 JR NZ,L95F8 2623: 95E4 3AD285 LD A,(FRAME) 2624: 95E7 E603 AND &03 2625: 95E9 07 RLCA 2626: 95EA 07 RLCA 2627: 95EB 47 LD B,A 2628: 95EC 3ADA80 LD A,(SLOPE_DIR) 2629: 95EF E601 AND &01 2630: 95F1 3D DEC A 2631: 95F2 EE0C XOR &0C 2632: 95F4 A8 XOR B 2633: 95F5 E60C AND &0C 2634: 95F7 47 LD B,A 2635: 95F8 2AD385 L95F8: LD HL,(POSITION) 2636: 95FB 111F00 LD DE,&001F 2637: 95FE 0E0F LD C,&0F 2638: 9600 CD1E96 CALL L961E 2639: 9603 23 INC HL 2640: 9604 CD1E96 CALL L961E 2641: 9607 19 ADD HL,DE 2642: 9608 CD1E96 CALL L961E 2643: 960B 23 INC HL 2644: 960C CD1E96 CALL L961E 2645: 960F 3ACF85 LD A,(YPOSN) 2646: 9612 80 ADD A,B 2647: 9613 4F LD C,A 2648: 9614 19 ADD HL,DE 2649: 9615 CD1E96 CALL L961E 2650: 9618 23 INC HL 2651: 9619 CD1E96 CALL L961E 2652: 961C 1819 JR DRAWWILLY ; Display Willy 2653: 2654: 961E 3AA080 L961E: LD A,(BACKGROUND) ; Background 2655: 9621 BE CP (HL) 2656: 9622 200B JR NZ,L962F 2657: 9624 79 LD A,C 2658: 9625 E60F AND &0F 2659: 9627 2806 JR Z,L962F 2660: 9629 3AA080 LD A,(BACKGROUND) 2661: 962C F607 OR &07 2662: 962E 77 LD (HL),A 2663: 962F 3ABB80 L962F: LD A,(NASTY) 2664: 9632 BE CP (HL) 2665: 9633 CAB690 JP Z,DIED2 2666: 9636 C9 RET 2667: 2668: 2669: ; Display Willy 2670: ; ============= 2671: 9637 3ACF85 DRAWWILLY: LD A,(YPOSN) ; Get Willy's Y position 2672: 963A 80 ADD A,B 2673: 963B DD DEFB &DD 2674: 963C 2682 LD H,PIXEL / 256 ; LD IXH,&82 ; Pixel-line buffer 2675: 963E DD DEFB &DD 2676: 963F 6F LD L,A ; LD IXL,A 2677: 9640 3AD085 LD A,(L85D0) 2678: 9643 E601 AND &01 2679: 9645 0F RRCA 2680: 9646 5F LD E,A 2681: 9647 3AD285 LD A,(FRAME) 2682: 964A E603 AND &03 2683: 964C 0F RRCA 2684: 964D 0F RRCA 2685: 964E 0F RRCA 2686: 964F B3 OR E 2687: 9650 5F LD E,A 2688: 9651 169D LD D,&9D ; Point to Willy sprites 2689: 0001 IF ROOMSPRITE 2690: 9653 3AED80 LD A,(WILLYSP) ; Does room specify a player sprite? 2691: 9656 A7 AND A 2692: 9657 F26096 JP P,L9660 ; No, use Willy sprite 2693: 965A 57 LD D,A ; Use specified sprite 2694: 965B 00 NOP 2695: ELSE 2700: ENDIF 2701: 965C 7B LD A,E ; Reverse the sprite direction 2702: 965D EE80 XOR &80 ; Willy sprites are Right/Left 2703: 965F 5F LD E,A ; All other sprites are Left/Right 2704: 9660 0610 L9660: LD B,&10 ; 16 pixel-lines 2705: 9662 3AD385 LD A,(POSITION) ; Get Willy's position 2706: 9665 E61F AND &1F ; X position 2707: 9667 4F LD C,A 2708: 2709: 9668 DD7E00 L9668: LD A,(IX+&00) ; Get pixel-line address of column 0 2710: 966B DD6601 LD H,(IX+&01) 2711: 966E B1 OR C ; Add on X coordinate 2712: 966F 6F LD L,A ; HL=pixel-line address in buffer 2 2713: 9670 1A LD A,(DE) ; Get byte from sprite 2714: 9671 B6 OR (HL) ; Merge with screen content 2715: 9672 77 LD (HL),A ; Store to screen 2716: 9673 23 INC HL ; Move to next pixel cell 2717: 9674 13 INC DE ; Move to next sprite byte 2718: 9675 1A LD A,(DE) ; Get byte from sprite 2719: 9676 B6 OR (HL) ; Merge with screen content 2720: 9677 77 LD (HL),A ; Store to screen 2721: 9678 DD23 INC IX ; Point to next pixel-line address 2722: 967A DD23 INC IX 2723: 967C 13 INC DE ; Point to next sprite byte 2724: 967D 10E9 DJNZ L9668 ; Loop for 16 pixel-lines 2725: 967F C9 RET 2726: 2727: 2728: ; Write a string to the screen 2729: ; ============================ 2730: ; On entry: IX=>ASCII string 2731: ; DE=>Display address to write to 2732: ; C= String length 2733: 9680 DD7E00 PRMESSAGE: LD A,(IX+&00) ; Get a character 2734: 9683 CD9196 CALL PRCHAR ; Write to screen at DE 2735: 9686 DD23 INC IX ; Move to next character 2736: 9688 1C INC E ; Move to next screen cell 2737: 9689 7A LD A,D ; DE has been left pointing to the 2738: 968A D608 SUB &08 ; 'ninth' pixel line, so adjust 2739: 968C 57 LD D,A ; D back to line 1 2740: 968D 0D DEC C ; Decrement string length 2741: 968E 20F0 JR NZ,PRMESSAGE ; Loop for the string 2742: 9690 C9 RET 2743: 2744: ; Write a character to screen 2745: ; --------------------------- 2746: 9691 2607 PRCHAR: LD H,&07 2747: 9693 6F LD L,A ; Copy character to L 2748: 9694 CBFD SET 7,L 2749: 9696 29 ADD HL,HL ; Multiple HL by 8 2750: 9697 29 ADD HL,HL 2751: 9698 29 ADD HL,HL ; HL=>character matrix at &3C00-&3F00 2752: 9699 0608 LD B,&08 ; Eight pixel-lines 2753: 969B 7E PRMATRIX: LD A,(HL) ; Get character line 2754: 969C 12 LD (DE),A ; Store in screen 2755: 969D 23 INC HL ; Point to next character line 2756: 969E 14 INC D ; Point to next pixel line 2757: 969F 10FA DJNZ PRMATRIX ; Loop for all eight lines 2758: 96A1 C9 RET 2759: 2760: 2761: ; Play introductory tune 2762: ; ====================== 2763: 96A2 7E L96A2: LD A,(HL) ; Get current note 2764: 96A3 FEFF CP &FF ; End of tune? 2765: 96A5 C8 RET Z ; Yes, so exit 2766: 96A6 016400 LD BC,&0064 2767: 96A9 AF XOR A 2768: 96AA 5E LD E,(HL) 2769: 96AB 53 LD D,E 2770: 96AC D3FE L96AC: OUT (&FE),A 2771: 96AE 15 DEC D 2772: 96AF 2003 JR NZ,L96B4 2773: 96B1 53 LD D,E 2774: 96B2 EE18 XOR &18 2775: 96B4 10F6 L96B4: DJNZ L96AC 2776: 96B6 08 EX AF,AF' 2777: 96B7 79 LD A,C 2778: 96B8 FE32 CP &32 2779: 96BA 2002 JR NZ,L96BE 2780: 96BC CB13 RL E 2781: 96BE 08 L96BE: EX AF,AF' 2782: 96BF 0D DEC C 2783: 96C0 20EA JR NZ,L96AC 2784: 0001 IF GAMEEXIT 2785: 96C2 CD0784 CALL L840D ; Check ENTER/FIRE/SS-SPACE 2786: ELSE 2788: ENDIF 2789: 96C5 C0 RET NZ ; Exit if so 2790: 96C6 23 INC HL 2791: 96C7 18D9 JR L96A2 2792: 2793: 2794: ; Check if ENTER/FIRE/0 pressed 2795: ; On exit, NZ=ENTER, FIRE or 0 pressed 2796: 96C9 3ACE85 L96C9: LD A,(KEMPSTON) ; Is kempston present? 2797: 96CC B7 OR A 2798: 96CD 2805 JR Z,L96D4 ; No, jump to look at keyboard 2799: 96CF DB1F IN A,(&1F) ; Read joystick 2800: 96D1 CB67 BIT 4,A ; Check FIRE button 2801: 96D3 C0 RET NZ ; Return if pressed 2802: 96D4 01FEAF L96D4: LD BC,&AFFE ; Look at ENTER and 0 keys 2803: 96D7 ED78 IN A,(C) 2804: 96D9 E601 AND &01 2805: 96DB FE01 CP &01 ; Is ENTER/0 pressed? 2806: 96DD C9 RET 2807: 2808: 2809: ; Play a note from the sliding scale as intro message scrolls past 2810: ; ================================================================ 2811: 96DE 5F L96DE: LD E,A 2812: 96DF 0EFE LD C,&FE 2813: 96E1 57 L96E1: LD D,A 2814: 96E2 CBA2 RES 4,D 2815: 96E4 CB9A RES 3,D 2816: 96E6 43 LD B,E 2817: 96E7 B8 L96E7: CP B 2818: 96E8 2002 JR NZ,L96EC 2819: 96EA 1618 LD D,&18 2820: 96EC ED51 L96EC: OUT (C),D 2821: 96EE 10F7 DJNZ L96E7 2822: 96F0 3D DEC A 2823: 96F1 20EE JR NZ,L96E1 2824: 96F3 C9 RET 2825: 2826: 2827: ; Unused code 2828: ; =========== 2829: ; This code space can be used for patches to the game engine. 2830: ; The 7-bit room patch uses the space at &96F4-&96FF, and room 87 uses &97xx. 2831: 0001 IF MOREROOMS 2832: 96F4 4E L96F4: LD C,(HL) ; Get object's room number 2833: 96F5 CBB9 RES 7,C ; Remove screen address bit8 2834: 96F7 3A2084 LD A,(HERE) ; Get current room 2835: 96FA B9 CP C ; Is object in this room? 2836: 96FB C8 RET Z ; Yes, exit to collect 2837: 96FC 24 INC H ; Point HL back to 'collected' flags 2838: 96FD 24 INC H 2839: 96FE C9 RET ; and exit to check next object 2840: 96FF 00 NOP 2841: ELSE 2856: ENDIF 2857: 2858: ; Screen attributes 2859: ; ================= 2860: ; The startup screen attributes define where the triangle will be displayed as well 2861: ; as forming the words JET SET WILLY. 2862: 9700 DEFS ATTRS-$ 2863: 9800 00000000 DEFB &00,&00,&00,&00,&00,&00,&00,&00,&00,&00,&00,&00,&00,&00,&00,&00 00000000 00000000 00000000 2864: 9810 00000000 DEFB &00,&00,&00,&00,&00,&00,&00,&00,&00,&00,&00,&00,&00,&00,&00,&00 00000000 00000000 00000000 2865: 9820 00000000 DEFB &00,&00,&00,&00,&00,&00,&00,&00,&00,&00,&00,&00,&00,&00,&00,&00 00000000 00000000 00000000 2866: 9830 00000000 DEFB &00,&00,&00,&00,&00,&00,&00,&00,&00,&00,&00,&00,&00,&00,&00,&00 00000000 00000000 00000000 2867: 9840 00000000 DEFB &00,&00,&00,&00,&00,&00,&00,&00,&00,&00,&00,&00,&00,&00,&00,&00 00000000 00000000 00000000 2868: 9850 00002828 DEFB &00,&00,&28,&28,&05,&05,&00,&00,&00,&00,&00,&00,&00,&00,&00,&00 05050000 00000000 00000000 2869: 9860 00000000 DEFB &00,&00,&00,&00,&D3,&D3,&D3,&00,&D3,&D3,&D3,&00,&D3,&D3,&D3,&00 D3D3D300 D3D3D300 D3D3D300 2870: 9870 28D3D3D3 DEFB &28,&D3,&D3,&D3,&25,&D3,&D3,&D3,&00,&D3,&D3,&D3,&00,&00,&00,&00 25D3D3D3 00D3D3D3 00000000 2871: 9880 00000000 DEFB &00,&00,&00,&00,&00,&D3,&00,&00,&D3,&00,&00,&00,&00,&D3,&28,&28 00D30000 D3000000 00D32828 2872: 9890 2DD32525 DEFB &2D,&D3,&25,&25,&24,&D3,&00,&00,&00,&00,&D3,&00,&00,&00,&00,&00 24D30000 0000D300 00000000 2873: 98A0 00000000 DEFB &00,&00,&00,&00,&00,&D3,&00,&00,&D3,&D3,&D3,&00,&28,&D3,&2D,&2D 00D30000 D3D3D300 28D32D2D 2874: 98B0 25D3D3D3 DEFB &25,&D3,&D3,&D3,&24,&D3,&D3,&D3,&00,&00,&D3,&00,&00,&00,&00,&00 24D3D3D3 0000D300 00000000 2875: 98C0 00000000 DEFB &00,&00,&00,&00,&00,&D3,&00,&00,&D3,&00,&28,&28,&2D,&D3,&25,&25 00D30000 D3002828 2DD32525 2876: 98D0 24240CD3 DEFB &24,&24,&0C,&D3,&24,&D3,&00,&00,&00,&00,&D3,&00,&00,&00,&00,&00 24D30000 0000D300 00000000 2877: 98E0 00000000 DEFB &00,&00,&00,&00,&D3,&D3,&00,&00,&D3,&D3,&D3,&2D,&25,&D3,&24,&24 D3D30000 D3D3D32D 25D32424 2878: 98F0 04D3D3D3 DEFB &04,&D3,&D3,&D3,&24,&D3,&D3,&D3,&00,&00,&D3,&00,&00,&00,&00,&00 24D3D3D3 0000D300 00000000 2879: 9900 00000000 DEFB &00,&00,&00,&00,&00,&00,&00,&00,&29,&29,&2D,&2D,&2C,&2C,&04,&04 00000000 29292D2D 2C2C0404 2880: 9910 00000909 DEFB &00,&00,&09,&09,&24,&24,&00,&00,&00,&00,&00,&00,&00,&00,&00,&00 24240000 00000000 00000000 2881: 9920 00000000 DEFB &00,&00,&00,&00,&00,&00,&00,&00,&09,&09,&29,&29,&2D,&2D,&05,&05 00000000 09092929 2D2D0505 2882: 9930 00000909 DEFB &00,&00,&09,&09,&24,&24,&00,&00,&00,&00,&00,&00,&00,&00,&00,&00 24240000 00000000 00000000 2883: 9940 00000000 DEFB &00,&00,&00,&00,&00,&00,&D3,&00,&08,&08,&D3,&09,&D3,&29,&D3,&2D 0000D300 0808D309 D329D32D 2884: 9950 0505D309 DEFB &05,&05,&D3,&09,&24,&D3,&00,&00,&00,&D3,&00,&00,&00,&00,&00,&00 24D30000 00D30000 00000000 2885: 9960 00000000 DEFB &00,&00,&00,&00,&00,&00,&D3,&00,&00,&00,&D3,&08,&D3,&09,&D3,&29 0000D300 0000D308 D309D329 2886: 9970 2D2DD309 DEFB &2D,&2D,&D3,&09,&24,&D3,&00,&00,&00,&D3,&00,&00,&00,&00,&00,&00 24D30000 00D30000 00000000 2887: 9980 00000000 DEFB &00,&00,&00,&00,&00,&00,&D3,&00,&D3,&00,&D3,&00,&D3,&08,&D3,&09 0000D300 D300D300 D308D309 2888: 9990 2929D309 DEFB &29,&29,&D3,&09,&24,&D3,&D3,&D3,&D3,&D3,&00,&00,&00,&00,&00,&00 24D3D3D3 D3D30000 00000000 2889: 99A0 00000000 DEFB &00,&00,&00,&00,&00,&00,&D3,&00,&D3,&00,&D3,&00,&D3,&00,&D3,&08 0000D300 D300D300 D300D308 2890: 99B0 0909D309 DEFB &09,&09,&D3,&09,&24,&24,&00,&D3,&00,&00,&00,&00,&00,&00,&00,&00 242400D3 00000000 00000000 2891: 99C0 00000000 DEFB &00,&00,&00,&00,&00,&00,&D3,&D3,&D3,&D3,&D3,&00,&D3,&00,&D3,&D3 0000D3D3 D3D3D300 D300D3D3 2892: 99D0 D308D3D3 DEFB &D3,&08,&D3,&D3,&D3,&24,&00,&D3,&00,&00,&00,&00,&00,&00,&00,&00 D32400D3 00000000 00000000 2893: 99E0 00000000 DEFB &00,&00,&00,&00,&00,&00,&00,&00,&00,&00,&00,&00,&00,&00,&00,&00 00000000 00000000 00000000 2894: 99F0 00000808 DEFB &00,&00,&08,&08,&04,&04,&00,&00,&00,&00,&00,&00,&00,&00,&00,&00 04040000 00000000 00000000 2895: 2896: ; The attributes for the bottom third of the screen are used for the room name, items 2897: ; collected line, and for the colours of the lives left Willys. 2898: 9A00 46464646 DEFB &46,&46,&46,&46,&46,&46,&46,&46,&46,&46,&46,&46,&46,&46,&46,&46 ; Room name 46464646 46464646 46464646 2899: 9A10 46464646 DEFB &46,&46,&46,&46,&46,&46,&46,&46,&46,&46,&46,&46,&46,&46,&46,&46 46464646 46464646 46464646 2900: 9A20 00000000 DEFB &00,&00,&00,&00,&00,&00,&00,&00,&00,&00,&00,&00,&00,&00,&00,&00 00000000 00000000 00000000 2901: 9A30 00000000 DEFB &00,&00,&00,&00,&00,&00,&00,&00,&00,&00,&00,&00,&00,&00,&00,&00 00000000 00000000 00000000 2902: 9A40 00000000 DEFB &00,&00,&00,&00,&00,&00,&00,&00,&00,&00,&00,&00,&00,&00,&00,&00 00000000 00000000 00000000 2903: 9A50 00000000 DEFB &00,&00,&00,&00,&00,&00,&00,&00,&00,&00,&00,&00,&00,&00,&00,&00 00000000 00000000 00000000 2904: 9A60 01020304 DEFB &01,&02,&03,&04,&05,&06,&07,&07,&07,&07,&07,&07,&07,&07,&07,&07 ; Items 05060707 07070707 07070707 2905: 9A70 07070707 DEFB &07,&07,&07,&07,&07,&07,&07,&07,&07,&07,&06,&05,&04,&03,&02,&01 07070707 07070605 04030201 2906: 9A80 00000000 DEFB &00,&00,&00,&00,&00,&00,&00,&00,&00,&00,&00,&00,&00,&00,&00,&00 00000000 00000000 00000000 2907: 9A90 00000000 DEFB &00,&00,&00,&00,&00,&00,&00,&00,&00,&00,&00,&00,&00,&00,&00,&00 00000000 00000000 00000000 2908: 9AA0 45450606 DEFB &45,&45,&06,&06,&04,&04,&41,&41,&05,&05,&43,&43,&44,&44,&02,&02 ; Lives left 04044141 05054343 44440202 2909: 9AB0 45450606 DEFB &45,&45,&06,&06,&04,&04,&41,&41,&05,&05,&43,&43,&44,&44,&02,&02 04044141 05054343 44440202 2910: 9AC0 45450606 DEFB &45,&45,&06,&06,&04,&04,&41,&41,&05,&05,&43,&43,&44,&44,&02,&02 04044141 05054343 44440202 2911: 9AD0 45450606 DEFB &45,&45,&06,&06,&04,&04,&41,&41,&05,&05,&43,&43,&44,&44,&02,&02 04044141 05054343 44440202 2912: 9AE0 00000000 DEFB &00,&00,&00,&00,&00,&00,&00,&00,&00,&00,&00,&00,&00,&00,&00,&00 00000000 00000000 00000000 2913: 9AF0 00000000 DEFB &00,&00,&00,&00,&00,&00,&00,&00,&00,&00,&00,&00,&00,&00,&00,&00 00000000 00000000 00000000 **** .jsw48/asm **** Statistics: 277 symbols 6145 bytes Symbol Table: action 89ad l8b4b 8b4b+ l9418 9418 attr =5800+ l8b63 8b63 l942c 942c attr1 =5e00+ l8b6b 8b6b l9430 9430 attr2 =5c00+ l8b70 8b70 l9452 9452 attrs =9800 l8b97 8b97 l9458 9458 background =80a0 l8bda 8bda l9461 9461 border =80de l8bf7 8bf7 l946d 946d buildroom 8d6b l8c03 8c03 l9486 9486 chkobjects 93d1 l8c23 8c23 l94e8 94e8+ chktoilet 9584 l8c28 8c28 l951f 951f collected 857c l8c71 8c71 l9526 9526 conv_dir =80d6 l8c91 8c91 l9576 9576 conv_num =80d9 l8c96 8c96 l959a 959a conv_psn =80d7 l8ce8 8ce8 l95f8 95f8 conveyor =80cd l8d4b 8d4b l961e 961e countdown 85e0 l8d4d 8d4d l962f 962f died1 90b7 l8d56 8d56 l9660 9660 died2 90b6 l8d5c 8d5c l9668 9668 down =80ec l8d5e 8d5e l96a2 96a2 drawguard 91be l8d72 8d72 l96ac 96ac drawlives 898b l8d9d 8d9d l96b4 96b4 drawmaria 955c l8da1 8da1 l96be 96be drawroom 8d33 l8dbb 8dbb l96c9 96c9 drawsprite 9456 l8e11 8e11 l96d4 96d4 drawtoilet 95b2 l8e1b 8e1b l96de 96de drawwilly 9637 l8e20 8e20 l96e1 96e1 falling 85d1 l8e36 8e36 l96e7 96e7 fixblocks = 1 l8e62 8e62 l96ec 96ec fixpause1 = 0 l8e7d 8e7d l96f4 96f4 fixpause2 = 0 l8e8f 8e8f left =80e9 fixpause3 = 1 l8e9c 8e9c lives 85cc flash 85cd l8eb0 8eb0 lostlife 8c01 floor =80a9+ l8eb6 8eb6 message 8454 frame 85d2 l8ebc 8ebc mflags 85e2 game 8574 l8ed4 8ed4 moonlight 85fb gameexit = 1 l8ef4 8ef4 morerooms = 1 gameover 8c4a l8efa 8efa movement 8dd3 gamestart 87ca l8f42 8f42 mtick 85e1 go_down 94d2 l8f51 8f51 name =8080 go_left 948a l8f5e 8f5e nasty =80bb go_right 949e l8f8f 8f8f nowtime 857f go_up 94b0 l8fbc 8fbc object =80e1 guardian 8100 l8fdc 8fdc objects =a3ff guardians =a000+ l900a 900a onrope 85d6 here 8420 l9032 9032 over 8578 instances =80f0 l9042 9042 passask 86c3 items 8554 l904e 904e passcheck 869f+ jumping 85d5 l9078 9078 passkey 873c kempston 85ce l90a1 90a1 pixel 8200 l840d 8407 l90ae 90ae+ pixtoilet 82d0+ l8421 8421 l90c4 90c4 playroom 8912 l8431 8431 l90f5 90f5 position 85d3 l8451 8451+ l90ff 90ff prchar 9691 l85d0 85d0 l9115 9115 prmatrix 969b l85d7 85d7 l911d 911d prmessage 9680 l85e5 85e5+ l9133 9133 prompt1 858b l85e7 85e7 l9156 9156 prompt2 85ab l8701 8701 l915c 915c remain 85de l870c 870c l9179 9179 richman 865f l8717 8717 l917f 917f right =80ea l8727 8727 l9193 9193 room 8000 l872b 872b l91a8 91a8 roomblock 8dc0 l8747 8747 l91ae 91ae rooms =c000+ l8785 8785 l91b6 91b6 roomsprite = 1 l87b5 87b5 l91c2 91c2 rope 8300+ l87c4 87c4 l920f 920f screen =4000+ l8809 8809 l9237 9237 screen1 =7000+ l8813 8813 l9244 9244 screen2 =6000+ l8844 8844 l9249 9249 slope =80c4 l886e 886e l9255 9255 slope_dir =80da l8871 8871 l9259 9259 slope_num =80dd l8888 8888 l9262 9262 slope_psn =80db l888e 888e l9286 9286 special 9534 l889a 889a l92a4 92a4 sprites =ab00+ l88a8 88a8 l92b6 92b6 start 8400+ l88b5 88b5 l92d6 92d6 starttime 8585 l88fc 88fc l92fc 92fc status 85df l8922 8922+ l930e 930e teleport 85e3 l892b 892b l9330 9330 temp 85e4 l8994 8994 l933d 933d ticker 85cb l89f5 89f5 l9341 9341 udteleport = 0+ l8a26 8a26 l934e 934e up =80eb l8a99 8a99 l9350 9350 updateconv 94f9 l8aab 8aab l935e 935e updateguard 90c0 l8abb 8abb+ l936f 936f updatewilly 95c8 l8ad1 8ad1 l939b 939b wall =80b2 l8aeb 8aeb l93b3 93b3 wallleft = 0 l8af3 8af3 l93bb 93bb+ wallright = 0 l8b07 8b07 l93d7 93d7 willysp =80ed l8b17 8b17 l93f7 93f7 yposn 85cf l8b36 8b36 l9409 9409 l8b38 8b38 l940e 940e