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