Manic Miner: Routine at 870E

| Routines

870E: Main loop

The routine at 8684 continues here. The first thing to do is check whether there are any remaining lives to draw at the bottom of the screen.
870E | LD A,($8457) | Pick up the number of lives remaining from 8457
8711 | LD HL,$50A0 | Set HL to the display file address at which to draw the first Willy sprite
8714 | OR A | Are there any lives remaining?
8715 | JR Z,$8730 | Jump if not
8717 | LD B,A | Initialise B to the number of lives remaining
The following loop draws the remaining lives at the bottom of the screen.
8718 | LD C,$00 | C=0; this tells the sprite-drawing routine at 8FF4 to overwrite any existing graphics
871A | PUSH HL | Save HL and BC briefly
871B | PUSH BC
871C | LD A,($845B) | Pick up the in-game music note index from 845B; this will determine the animation frame for the Willy sprites
871F | RLCA | Now A=0x00 (frame 0), 0x20 (frame 1), 0x40 (frame 2) or 0x60 (frame 3)
8720 | RLCA
8721 | RLCA
8722 | AND $60
8724 | LD E,A | Point DE at the corresponding Willy sprite (at 8200+A)
8725 | LD D,$82
8727 | CALL $8FF4 | Draw the Willy sprite on the screen
872A | POP BC | Restore HL and BC
872B | POP HL
872C | INC HL | Move HL along to the location at which to draw the next Willy sprite
872D | INC HL
872E | DJNZ $8718 | Jump back to draw any remaining sprites
Now draw a boot if cheat mode has been activated.
8730 | LD A,($845D) | Pick up the 6031769 key counter from 845D
8733 | CP $07 | Has 6031769 been keyed in yet?
8735 | JR NZ,$873F | Jump if not
8737 | LD DE,$BAE0 | Point DE at the graphic data for the boot (at BAE0)
873A | LD C,$00 | C=0 (overwrite mode)
873C | CALL $8FF4 | Draw the boot at the bottom of the screen next to the remaining lives
Next, prepare the screen and attribute buffers for drawing to the screen.
873F | LD HL,$5E00 | Copy the contents of the attribute buffer at 5E00 (the attributes for the empty cavern) into the attribute buffer at 5C00
8742 | LD DE,$5C00
8745 | LD BC,$0200
8748 | LDIR
874A | LD HL,$7000 | Copy the contents of the screen buffer at 7000 (the tiles for the empty cavern) into the screen buffer at 6000
874D | LD DE,$6000
8750 | LD BC,$1000
8753 | LDIR
8755 | CALL $8D0F | Move the horizontal guardians in the current cavern
8758 | LD A,($845A) | Pick up the game mode indicator from 845A
875B | OR A | Are we in demo mode?
875C | CALL Z,$8ABB | If not, move Willy
875F | LD A,($845A) | Pick up the game mode indicator from 845A
8762 | OR A | Are we in demo mode?
8763 | CALL Z,$923A | If not, check and set the attribute bytes for Willy's sprite in the buffer at 5C00, and draw Willy to the screen buffer at 6000
8766 | CALL $8DAA | Draw the horizontal guardians in the current cavern
8769 | CALL $9105 | Move the conveyor in the current cavern
876C | CALL $8F63 | Draw the items in the current cavern and collect any that Willy is touching
876F | LD A,($8407) | Pick up the number of the current cavern from 8407
8772 | CP $04 | Are we in Eugene's Lair?
8774 | CALL Z,$8DF8 | If so, move and draw Eugene
8777 | LD A,($8407) | Pick up the number of the current cavern from 8407
877A | CP $0D | Are we in Skylab Landing Bay?
877C | JP Z,$8E75 | If so, move and draw the Skylabs
877F | LD A,($8407) | Pick up the number of the current cavern from 8407
8782 | CP $08 | Are we in Wacky Amoebatrons or beyond?
8784 | CALL NC,$8EF1 | If so, move and draw the vertical guardians
8787 | LD A,($8407) | Pick up the number of the current cavern from 8407
878A | CP $07 | Are we in Miner Willy meets the Kong Beast?
878C | CALL Z,$9135 | If so, move and draw the Kong Beast
878F | LD A,($8407) | Pick up the number of the current cavern from 8407
8792 | CP $0B | Are we in Return of the Alien Kong Beast?
8794 | CALL Z,$9135 | If so, move and draw the Kong Beast
8797 | LD A,($8407) | Pick up the number of the current cavern from 8407
879A | CP $12 | Are we in Solar Power Generator?
879C | CALL Z,$8D73 | If so, move and draw the light beam
This entry point is used by the routine at 8E75.
879F | CALL $8FC5 | Draw the portal, or move to the next cavern if Willy has entered it
This entry point is used by the routine at 8D05.
87A2 | LD HL,$6000 | Copy the contents of the screen buffer at 6000 to the display file
87A5 | LD DE,$4000
87A8 | LD BC,$1000
87AB | LDIR
87AD | LD A,($8458) | Pick up the screen flash counter from 8458
87B0 | OR A | Is it zero?
87B1 | JR Z,$87C8 | Jump if so
87B3 | DEC A | Decrement the screen flash counter at 8458
87B4 | LD ($8458),A
87B7 | RLCA | Move bits 0-2 into bits 3-5 and clear all the other bits
87B8 | RLCA
87B9 | RLCA
87BA | AND $38
87BC | LD HL,$5C00 | Set every attribute byte in the buffer at 5C00 to this value
87BF | LD DE,$5C01
87C2 | LD BC,$01FF
87C5 | LD (HL),A
87C6 | LDIR
87C8 | LD HL,$5C00 | Copy the contents of the attribute buffer at 5C00 to the attribute file
87CB | LD DE,$5800
87CE | LD BC,$0200
87D1 | LDIR
87D3 | LD IX,$8429 | Print the score (see 8429) at (19,26)
87D7 | LD DE,$507A
87DA | LD C,$06
87DC | CALL $92BA
87DF | LD IX,$841F | Print the high score (see 841F) at (19,11)
87E3 | LD DE,$506B
87E6 | LD C,$06
87E8 | CALL $92BA
87EB | CALL $8A3C | Decrease the air remaining in the current cavern
87EE | JP Z,$88FF | Jump if there's no air left
Now check whether SHIFT and SPACE are being pressed.
87F1 | LD BC,$FEFE | Read keys SHIFT-Z-X-C-V
87F4 | IN A,(C)
87F6 | LD E,A | Save the result in E
87F7 | LD B,$7F | Read keys B-N-M-SS-SPACE
87F9 | IN A,(C)
87FB | OR E | Combine the results
87FC | AND $01 | Are SHIFT and SPACE being pressed?
87FE | JP Z,$85CC | If so, quit the game
Now read the keys A, S, D, F and G (which pause the game).
8801 | LD B,$FD | Read keys A-S-D-F-G
8803 | IN A,(C)
8805 | AND $1F | Are any of these keys being pressed?
8807 | CP $1F
8809 | JR Z,$8815 | Jump if not
880B | LD B,$02 | Read every half-row of keys except A-S-D-F-G
880D | IN A,(C)
880F | AND $1F | Are any of these keys being pressed?
8811 | CP $1F
8813 | JR Z,$880B | Jump back if not (the game is still paused)
Here we check whether Willy has had a fatal accident.
8815 | LD A,($806B) | Pick up the airborne status indicator from 806B
8818 | CP $FF | Has Willy landed after falling from too great a height, or collided with a nasty or a guardian?
881A | JP Z,$88FF | Jump if so
Now read the keys H, J, K, L and ENTER (which toggle the in-game music).
881D | LD B,$BF | Prepare B for reading keys H-J-K-L-ENTER
881F | LD HL,$845C | Point HL at the music flags at 845C
8822 | IN A,(C) | Read keys H-J-K-L-ENTER
8824 | AND $1F | Are any of these keys being pressed?
8826 | CP $1F
8828 | JR Z,$8834 | Jump if not
882A | BIT 0,(HL) | Were any of these keys being pressed the last time we checked?
882C | JR NZ,$8836 | Jump if so
882E | LD A,(HL) | Set bit 0 (the keypress flag) and flip bit 1 (the in-game music flag) at 845C
882F | XOR $03
8831 | LD (HL),A
8832 | JR $8836 |
8834 | RES 0,(HL) | Reset bit 0 (the keypress flag) at 845C
8836 | BIT 1,(HL) | Has the in-game music been switched off?
8838 | JR NZ,$885F | Jump if so
The next section of code plays a note of the in-game music. Your browser doesn't support HTML5 audio. Here is a link to the audio instead.
883A | LD A,($845B) | Increment the in-game music note index at 845B
883D | INC A
883E | LD ($845B),A
8841 | AND $7E | Point HL at the appropriate entry in the tune data table at 858C
8843 | RRCA
8844 | LD E,A
8845 | LD D,$00
8847 | LD HL,$858C
884A | ADD HL,DE
884B | LD A,($8073) | Pick up the border colour for the current cavern from 8073
884E | LD E,(HL) | Initialise the pitch delay counter in E
884F | LD BC,$0003 | Initialise the duration delay counters in B (0) and C (3)
8852 | OUT ($FE),A | Produce a note of the in-game music
8854 | DEC E
8855 | JR NZ,$885A
8857 | LD E,(HL)
8858 | XOR $18
885A | DJNZ $8852
885C | DEC C
885D | JR NZ,$8852
If we're in demo mode, check the keyboard and joystick and return to the title screen if there's any input.
885F | LD A,($845A) | Pick up the game mode indicator from 845A
8862 | OR A | Are we in demo mode?
8863 | JR Z,$8884 | Jump if not
8865 | DEC A | We're in demo mode; is it time to show the next cavern?
8866 | JP Z,$88FF | Jump if so
8869 | LD ($845A),A | Update the game mode indicator at 845A
886C | LD BC,$00FE | Read every row of keys on the keyboard
886F | IN A,(C)
8871 | AND $1F | Are any keys being pressed?
8873 | CP $1F
8875 | JP NZ,$85CC | If so, return to the title screen
8878 | LD A,($8459) | Pick up the Kempston joystick indicator from 8459
887B | OR A | Is there a joystick connected?
887C | JR Z,$8884 | Jump if not
887E | IN A,($1F) | Collect input from the joystick
8880 | OR A | Is the joystick being moved or the fire button being pressed?
8881 | JP NZ,$85CC | If so, return to the title screen
Here we check the teleport keys.
8884 | LD BC,$EFFE | Read keys 6-7-8-9-0
8887 | IN A,(C)
8889 | BIT 4,A | Is '6' (the activator key) being pressed?
888B | JP NZ,$88A8 | Jump if not
888E | LD A,($845D) | Pick up the 6031769 key counter from 845D
8891 | CP $07 | Has 6031769 been keyed in yet?
8893 | JP NZ,$88A8 | Jump if not
8896 | LD B,$F7 | Read keys 1-2-3-4-5
8898 | IN A,(C)
889A | CPL | Keep only bits 0-4 and flip them
889B | AND $1F
889D | CP $14 | Is the result 0x14 or greater?
889F | JP NC,$88A8 | Jump if so (this is not a cavern number)
88A2 | LD ($8407),A | Store the cavern number at 8407
88A5 | JP $8691 | Teleport into the cavern
Now check the 6031769 keys.
88A8 | LD A,($845D) | Pick up the 6031769 key counter from 845D
88AB | CP $07 | Has 6031769 been keyed in yet?
88AD | JP Z,$870E | If so, jump back to the start of the main loop
88B0 | RLCA | Point IX at the corresponding entry in the 6031769 table at 8460
88B1 | LD E,A
88B2 | LD D,$00
88B4 | LD IX,$8460
88B8 | ADD IX,DE
88BA | LD BC,$F7FE | Read keys 1-2-3-4-5
88BD | IN A,(C)
88BF | AND $1F | Keep only bits 0-4
88C1 | CP (IX+$00) | Does this match the first byte of the entry in the 6031769 table?
88C4 | JR Z,$88D8 | Jump if so
88C6 | CP $1F | Are any of the keys 1-2-3-4-5 being pressed?
88C8 | JP Z,$870E | If not, jump back to the start of the main loop
88CB | CP (IX-$02) | Does the keyboard reading match the first byte of the previous entry in the 6031769 table?
88CE | JP Z,$870E | If so, jump back to the start of the main loop
88D1 | XOR A | Reset the 6031769 key counter at 845D to 0 (an incorrect key is being pressed)
88D2 | LD ($845D),A
88D5 | JP $870E | Jump back to the start of the main loop
88D8 | LD B,$EF | Read keys 6-7-8-9-0
88DA | IN A,(C)
88DC | AND $1F | Keep only bits 0-4
88DE | CP (IX+$01) | Does this match the second byte of the entry in the 6031769 table?
88E1 | JR Z,$88F5 | If so, jump to increment the 6031769 key counter
88E3 | CP $1F | Are any of the keys 6-7-8-9-0 being pressed?
88E5 | JP Z,$870E | If not, jump back to the start of the main loop
88E8 | CP (IX-$01) | Does the keyboard reading match the second byte of the previous entry in the 6031769 table?
88EB | JP Z,$870E | If so, jump back to the start of the main loop
88EE | XOR A | Reset the 6031769 key counter at 845D to 0 (an incorrect key is being pressed)
88EF | LD ($845D),A
88F2 | JP $870E | Jump back to the start of the main loop
88F5 | LD A,($845D) | Increment the 6031769 key counter at 845D (the next key in the sequence is being pressed)
88F8 | INC A
88F9 | LD ($845D),A
88FC | JP $870E | Jump back to the start of the main loop
The air in the cavern has run out, or Willy has had a fatal accident, or it's demo mode and it's time to show the next cavern.
88FF | LD A,($845A) | Pick up the game mode indicator from 845A
8902 | OR A | Is it demo mode?
8903 | JP NZ,$9028 | If so, move to the next cavern
8906 | LD A,$47 | A=0x47 (INK 7: PAPER 0: BRIGHT 1)
The following loop fills the top two thirds of the attribute file with a single value (0x47, 0x46, 0x45, 0x44, 0x43, 0x42, 0x41 or 0x40) and makes a sound effect. Your browser doesn't support HTML5 audio. Here is a link to the audio instead.
8908 | LD HL,$5800 | Fill the top two thirds of the attribute file with the value in A
890B | LD DE,$5801
890E | LD BC,$01FF
8911 | LD (HL),A
8912 | LDIR
8914 | LD E,A | Save the attribute byte (0x40-0x47) in E for later retrieval
8915 | CPL | D=63-8*(E AND 7); this value determines the pitch of the short note that will be played
8916 | AND $07
8918 | RLCA
8919 | RLCA
891A | RLCA
891B | OR $07
891D | LD D,A
891E | LD C,E | C=8+32*(E AND 7); this value determines the duration of the short note that will be played
891F | RRC C
8921 | RRC C
8923 | RRC C
8925 | OR $10 | Set bit 4 of A (for no apparent reason)
8927 | XOR A | Set A=0 (this will make the border black)
8928 | OUT ($FE),A | Produce a short note whose pitch is determined by D and whose duration is determined by C
892A | XOR $18
892C | LD B,D
892D | DJNZ $892D
892F | DEC C
8930 | JR NZ,$8928
8932 | LD A,E | Restore the attribute byte (originally 0x47) to A
8933 | DEC A | Decrement it (effectively decrementing the INK colour)
8934 | CP $3F | Have we used attribute value 0x40 (INK 0) yet?
8936 | JR NZ,$8908 | If not, jump back to update the INK colour in the top two thirds of the screen and make another sound effect
Finally, check whether any lives remain.
8938 | LD HL,$8457 | Pick up the number of lives remaining from 8457
893B | LD A,(HL)
893C | OR A | Are there any lives remaining?
893D | JP Z,$8944 | If not, display the game over sequence
8940 | DEC (HL) | Decrease the number of lives remaining by one
8941 | JP $8691 | Jump back to reinitialise the current cavern