Manic Miner: Routine at 8BDD

| Routines

8BDD: Move Willy (2)

Used by the routine at 8ABB. This routine checks the keyboard and joystick, and moves Willy left or right if necessary.
Input
HL | Attribute buffer address of the left-hand cell below Willy's sprite
8BDD | LD A,($806B) | Pick up the airborne status indicator from 806B
8BE0 | CP $0C | Has Willy just landed after falling from too great a height?
8BE2 | JP NC,$8D06 | If so, kill him
8BE5 | LD E,$FF | Initialise E to 0xFF (all bits set); it will be used to hold keyboard and joystick readings
8BE7 | XOR A | Reset the airborne status indicator at 806B (Willy has landed safely)
8BE8 | LD ($806B),A
8BEB | LD A,($8044) | Pick up the attribute byte of the conveyor tile for the current cavern from 8044
8BEE | CP (HL) | Does the attribute byte of the left-hand cell below Willy's sprite match that of the conveyor tile?
8BEF | JR Z,$8BF5 | Jump if so
8BF1 | INC HL | Point HL at the right-hand cell below Willy's sprite
8BF2 | CP (HL) | Does the attribute byte of the right-hand cell below Willy's sprite match that of the conveyor tile?
8BF3 | JR NZ,$8BFB | Jump if not
8BF5 | LD A,($806F) | Pick up the direction byte of the conveyor definition from 806F (0=left, 1=right)
8BF8 | SUB $03 | Now E=0xFD (bit 1 reset) if the conveyor is moving left, or 0xFE (bit 0 reset) if it's moving right
8BFA | LD E,A
8BFB | LD BC,$DFFE | Read keys P-O-I-U-Y (right, left, right, left, right) into bits 0-4 of A
8BFE | IN A,(C)
8C00 | AND $1F | Set bit 5 and reset bits 6 and 7
8C02 | OR $20
8C04 | AND E | Reset bit 0 if the conveyor is moving right, or bit 1 if it's moving left
8C05 | LD E,A | Save the result in E
8C06 | LD BC,$FBFE | Read keys Q-W-E-R-T (left, right, left, right, left) into bits 0-4 of A
8C09 | IN A,(C)
8C0B | AND $1F | Keep only bits 0-4, shift them into bits 1-5, and set bit 0
8C0D | RLC A
8C0F | OR $01
8C11 | AND E | Merge this keyboard reading into bits 1-5 of E
8C12 | LD E,A
8C13 | LD B,$F7 | Read keys 1-2-3-4-5 ('5' is left) into bits 0-4 of A
8C15 | IN A,(C)
8C17 | RRCA | Rotate the result right and set bits 0-2 and 4-7; this ignores every key except '5' (left)
8C18 | OR $F7
8C1A | AND E | Merge this reading of the '5' key into bit 3 of E
8C1B | LD E,A
8C1C | LD B,$EF | Read keys 0-9-8-7-6 ('8' is right) into bits 0-4 of A
8C1E | IN A,(C)
8C20 | OR $FB | Set bits 0, 1 and 3-7; this ignores every key except '8' (right)
8C22 | AND E | Merge this reading of the '8' key into bit 2 of E
8C23 | LD E,A
8C24 | LD A,($8459) | Collect the Kempston joystick indicator from 8459
8C27 | OR A | Is the joystick connected?
8C28 | JR Z,$8C34 | Jump if not
8C2A | LD BC,$001F | Collect input from the joystick
8C2D | IN A,(C)
8C2F | AND $03 | Keep only bits 0 (right) and 1 (left) and flip them
8C31 | CPL
8C32 | AND E | Merge this reading of the joystick right and left buttons into bits 0 and 1 of E
8C33 | LD E,A
At this point, bits 0-5 in E indicate the direction in which Willy is being moved or trying to move. If bit 0, 2 or 4 is reset, Willy is being moved or trying to move right; if bit 1, 3 or 5 is reset, Willy is being moved or trying to move left.
8C34 | LD C,$00 | Initialise C to 0 (no movement)
8C36 | LD A,E | Copy the movement bits into A
8C37 | AND $2A | Keep only bits 1, 3 and 5 (the 'left' bits)
8C39 | CP $2A | Are any of these bits reset?
8C3B | JR Z,$8C3F | Jump if not
8C3D | LD C,$04 | Set bit 2 of C: Willy is moving left
8C3F | LD A,E | Copy the movement bits into A
8C40 | AND $15 | Keep only bits 0, 2 and 4 (the 'right' bits)
8C42 | CP $15 | Are any of these bits reset?
8C44 | JR Z,$8C48 | Jump if not
8C46 | SET 3,C | Set bit 3 of C: Willy is moving right
8C48 | LD A,($806A) | Pick up Willy's direction and movement flags from 806A
8C4B | ADD A,C | Point HL at the entry in the left-right movement table at 8408 that corresponds to the direction Willy is facing, and the direction in which he is being moved or trying to move
8C4C | LD C,A
8C4D | LD B,$00
8C4F | LD HL,$8408
8C52 | ADD HL,BC
8C53 | LD A,(HL) | Update Willy's direction and movement flags at 806A with the entry from the left-right movement table
8C54 | LD ($806A),A
That is left-right movement taken care of. Now check the jump keys.
8C57 | LD BC,$7EFE | Read keys SHIFT-Z-X-C-V and B-N-M-SS-SPACE
8C5A | IN A,(C)
8C5C | AND $1F | Are any of these keys being pressed?
8C5E | CP $1F
8C60 | JR NZ,$8C7B | Jump if so
8C62 | LD B,$EF | Read keys 0-9-8-7-6 into bits 0-4 of A
8C64 | IN A,(C)
8C66 | AND $09 | Keep only bits 0 (the '0' key) and 3 (the '7' key)
8C68 | CP $09 | Is '0' or '7' being pressed?
8C6A | JR NZ,$8C7B | Jump if so
8C6C | LD A,($8459) | Collect the Kempston joystick indicator from 8459
8C6F | OR A | Is the joystick connected?
8C70 | JR Z,$8C83 | Jump if not
8C72 | LD BC,$001F | Collect input from the joystick
8C75 | IN A,(C)
8C77 | BIT 4,A | Is the fire button being pressed?
8C79 | JR Z,$8C83 | Jump if not
A jump key or the fire button is being pressed. Time to make Willy jump.
8C7B | XOR A | Initialise the jumping animation counter at 806E
8C7C | LD ($806E),A
8C7F | INC A | Set the airborne status indicator at 806B to 1: Willy is jumping
8C80 | LD ($806B),A
This entry point is used by the routine at 8ABB.
8C83 | LD A,($806A) | Pick up Willy's direction and movement flags from 806A
8C86 | AND $02 | Is Willy moving?
8C88 | RET Z | Return if not
8C89 | LD A,($806A) | Pick up Willy's direction and movement flags from 806A
8C8C | AND $01 | Is Willy facing right?
8C8E | JP Z,$8CCA | Jump if so
Willy is moving left.
8C91 | LD A,($8069) | Pick up Willy's animation frame from 8069
8C94 | OR A | Is it 0?
8C95 | JR Z,$8C9C | If so, jump to move Willy's sprite left across a cell boundary
8C97 | DEC A | Decrement Willy's animation frame at 8069
8C98 | LD ($8069),A
8C9B | RET |
Willy's sprite is moving left across a cell boundary. In the comments that follow, (x,y) refers to the coordinates of the top-left cell currently occupied by Willy's sprite.
8C9C | LD HL,($806C) | Collect Willy's attribute buffer coordinates from 806C
8C9F | DEC HL | Point HL at the cell at (x-1,y+1)
8CA0 | LD DE,$0020
8CA3 | ADD HL,DE
8CA4 | LD A,($803B) | Pick up the attribute byte of the wall tile for the current cavern from 803B
8CA7 | CP (HL) | Is there a wall tile in the cell pointed to by HL?
8CA8 | RET Z | Return if so without moving Willy (his path is blocked)
8CA9 | LD A,($8068) | Pick up Willy's y-coordinate from 8068
8CAC | AND $0F | Does Willy's sprite currently occupy only two rows of cells?
8CAE | JR Z,$8CB9 | Jump if so
8CB0 | LD A,($803B) | Pick up the attribute byte of the wall tile for the current cavern from 803B
8CB3 | ADD HL,DE | Point HL at the cell at (x-1,y+2)
8CB4 | CP (HL) | Is there a wall tile in the cell pointed to by HL?
8CB5 | RET Z | Return if so without moving Willy (his path is blocked)
8CB6 | OR A | Clear the carry flag for subtraction
8CB7 | SBC HL,DE | Point HL at the cell at (x-1,y+1)
8CB9 | LD A,($803B) | Pick up the attribute byte of the wall tile for the current cavern from 803B
8CBC | OR A | Clear the carry flag for subtraction
8CBD | SBC HL,DE | Point HL at the cell at (x-1,y)
8CBF | CP (HL) | Is there a wall tile in the cell pointed to by HL?
8CC0 | RET Z | Return if so without moving Willy (his path is blocked)
8CC1 | LD ($806C),HL | Save Willy's new attribute buffer coordinates (in HL) at 806C
8CC4 | LD A,$03 | Change Willy's animation frame at 8069 from 0 to 3
8CC6 | LD ($8069),A
8CC9 | RET |
Willy is moving right.
8CCA | LD A,($8069) | Pick up Willy's animation frame from 8069
8CCD | CP $03 | Is it 3?
8CCF | JR Z,$8CD6 | If so, jump to move Willy's sprite right across a cell boundary
8CD1 | INC A | Increment Willy's animation frame at 8069
8CD2 | LD ($8069),A
8CD5 | RET |
Willy's sprite is moving right across a cell boundary. In the comments that follow, (x,y) refers to the coordinates of the top-left cell currently occupied by Willy's sprite.
8CD6 | LD HL,($806C) | Collect Willy's attribute buffer coordinates from 806C
8CD9 | INC HL | Point HL at the cell at (x+2,y)
8CDA | INC HL
8CDB | LD DE,$0020 | Prepare DE for addition
8CDE | LD A,($803B) | Pick up the attribute byte of the wall tile for the current cavern from 803B
8CE1 | ADD HL,DE | Point HL at the cell at (x+2,y+1)
8CE2 | CP (HL) | Is there a wall tile in the cell pointed to by HL?
8CE3 | RET Z | Return if so without moving Willy (his path is blocked)
8CE4 | LD A,($8068) | Pick up Willy's y-coordinate from 8068
8CE7 | AND $0F | Does Willy's sprite currently occupy only two rows of cells?
8CE9 | JR Z,$8CF4 | Jump if so
8CEB | LD A,($803B) | Pick up the attribute byte of the wall tile for the current cavern from 803B
8CEE | ADD HL,DE | Point HL at the cell at (x+2,y+2)
8CEF | CP (HL) | Is there a wall tile in the cell pointed to by HL?
8CF0 | RET Z | Return if so without moving Willy (his path is blocked)
8CF1 | OR A | Clear the carry flag for subtraction
8CF2 | SBC HL,DE | Point HL at the cell at (x+2,y+1)
8CF4 | LD A,($803B) | Pick up the attribute byte of the wall tile for the current cavern from 803B
8CF7 | OR A | Clear the carry flag for subtraction
8CF8 | SBC HL,DE | Point HL at the cell at (x+2,y)
8CFA | CP (HL) | Is there a wall tile in the cell pointed to by HL?
8CFB | RET Z | Return if so without moving Willy (his path is blocked)
8CFC | DEC HL | Point HL at the cell at (x+1,y)
8CFD | LD ($806C),HL | Save Willy's new attribute buffer coordinates (in HL) at 806C
8D00 | XOR A | Change Willy's animation frame at 8069 from 3 to 0
8D01 | LD ($8069),A
8D04 | RET |