Jet Set Willy: Routine at 37310

| Routines

37310: Draw the rope, arrows and guardians in the current room

Used by the routine at 35245. Draws the rope, arrows and guardians in the current room to the screen buffer at 24576.
37310 | LD IX,33024 | Point IX at the first byte of the first entity buffer at 33024
The drawing loop begins here.
37314 | LD A,(IX+0) | Pick up the first byte of the current entity's buffer
37317 | CP 255 | Have we already dealt with every entity?
37319 | RET Z | Return if so
37320 | AND 7 | Keep only bits 0-2 (which determine the type of entity)
37322 | JP Z,37811 | Jump to consider the next entity buffer if this one is not being used
37325 | CP 3 | Is this a rope?
37327 | JP Z,37540 | Jump if so
37330 | CP 4 | Is this an arrow?
37332 | JR Z,37431 | Jump if so
We are dealing with a horizontal or vertical guardian.
37334 | LD E,(IX+3) | Point DE at the entry in the screen buffer address lookup table at 33280 that corresponds to the guardian's y-coordinate
37337 | LD D,130
37339 | LD A,(DE) | Copy the LSB of the screen buffer address to L
37340 | LD L,A
37341 | LD A,(IX+2) | Pick up the guardian's x-coordinate from bits 0-4 of the third byte of its buffer
37344 | AND 31
37346 | ADD A,L | Adjust the LSB of the screen buffer address in L for the guardian's x-coordinate
37347 | LD L,A
37348 | LD A,E | Copy the fourth byte of the guardian's buffer to A
37349 | RLCA | H=92 or 93; now HL holds the address of the guardian's current location in the attribute buffer at 23552
37350 | AND 1
37352 | OR 92
37354 | LD H,A
37355 | LD DE,31 | Prepare DE for later addition
37358 | LD A,(IX+1) | Pick up the second byte of the guardian's buffer
37361 | AND 15 | Keep only bits 0-2 (INK colour) and 3 (BRIGHT value)
37363 | ADD A,56 | Push bit 3 up to bit 6
37365 | AND 71 | Keep only bits 0-2 (INK colour) and 6 (BRIGHT value)
37367 | LD C,A | Save this value in C temporarily
37368 | LD A,(HL) | Pick up the room attribute byte at the guardian's location from the buffer at 23552
37369 | AND 56 | Keep only bits 3-5 (PAPER colour)
37371 | XOR C | Merge the INK colour and BRIGHT value from C
37372 | LD C,A | Copy this attribute value to C
37373 | LD (HL),C | Set the attribute bytes in the buffer at 23552 for the top two rows of cells occupied by the guardian's sprite
37374 | INC HL
37375 | LD (HL),C
37376 | ADD HL,DE
37377 | LD (HL),C
37378 | INC HL
37379 | LD (HL),C
37380 | LD A,(IX+3) | Pick up the fourth byte of the guardian's buffer
37383 | AND 14 | Does the guardian's sprite occupy only two rows of cells at the moment?
37385 | JR Z,37391 | Jump if so
37387 | ADD HL,DE | Set the attribute bytes in the buffer at 23552 for the third row of cells occupied by the guardian's sprite
37388 | LD (HL),C
37389 | INC HL
37390 | LD (HL),C
37391 | LD C,1 | Prepare C for the call to 37974 later on
37393 | LD A,(IX+1) | Now bits 5-7 of A hold the animation frame mask
37396 | AND (IX+0) | 'AND' on the current animation frame (bits 5-7)
37399 | OR (IX+2) | 'OR' on the base sprite index (bits 5-7)
37402 | AND 224 | Keep only bits 5-7
37404 | LD E,A | Point DE at the graphic data for the guardian's current animation frame (see 43776)
37405 | LD D,(IX+5)
37408 | LD H,130 | Point HL at the guardian's current location in the screen buffer at 24576
37410 | LD L,(IX+3)
37413 | LD A,(IX+2)
37416 | AND 31
37418 | OR (HL)
37419 | INC HL
37420 | LD H,(HL)
37421 | LD L,A
37422 | CALL 37974 | Draw the guardian
37425 | JP NZ,37047 | Kill Willy if the guardian collided with him
37428 | JP 37811 | Jump to consider the next entity
We are dealing with an arrow. Your browser doesn't support HTML5 audio. Here is a link to the audio instead.
37431 | BIT 7,(IX+0) | Is the arrow travelling left to right?
37435 | JR NZ,37444 | Jump if so
37437 | DEC (IX+4) | Decrement the arrow's x-coordinate
37440 | LD C,44 | The sound effect for an arrow travelling right to left is made when the x-coordinate is 44
37442 | JR 37449 |
37444 | INC (IX+4) | Increment the arrow's x-coordinate
37447 | LD C,244 | The sound effect for an arrow travelling left to right is made when the x-coordinate is 244
37449 | LD A,(IX+4) | Pick up the arrow's x-coordinate (0-255)
37452 | CP C | Is it time to make the arrow sound effect?
37453 | JR NZ,37474 | Jump if not
37455 | LD BC,640 | Prepare the delay counters (B=2, C=128) for the arrow sound effect
37458 | LD A,(32990) | Pick up the border colour for the current room from 32990
37461 | OUT (254),A | Produce the arrow sound effect
37463 | XOR 24
37465 | DJNZ 37465
37467 | LD B,C
37468 | DEC C
37469 | JR NZ,37461
37471 | JP 37811 | Jump to consider the next entity
37474 | AND 224 | Is the arrow's x-coordinate in the range 0-31 (i.e. on-screen)?
37476 | JP NZ,37811 | If not, jump to consider the next entity
37479 | LD E,(IX+2) | Point DE at the entry in the screen buffer address lookup table at 33280 that corresponds to the arrow's y-coordinate
37482 | LD D,130
37484 | LD A,(DE) | Pick up the LSB of the screen buffer address
37485 | ADD A,(IX+4) | Adjust it for the arrow's x-coordinate
37488 | LD L,A | Point HL at the arrow's current location in the attribute buffer at 23552
37489 | LD A,E
37490 | AND 128
37492 | RLCA
37493 | OR 92
37495 | LD H,A
37496 | LD (IX+5),0 | Initialise the collision detection byte (0=off, 255=on)
37500 | LD A,(HL) | Pick up the room attribute byte at the arrow's location
37501 | AND 7 | Keep only bits 0-2 (INK colour)
37503 | CP 7 | Is the INK white?
37505 | JR NZ,37510 | Jump if not
37507 | DEC (IX+5) | Activate collision detection
37510 | LD A,(HL) | Set the INK colour to white at the arrow's location
37511 | OR 7
37513 | LD (HL),A
37514 | INC DE | Pick up the MSB of the screen buffer address for the arrow's location
37515 | LD A,(DE)
37516 | LD H,A | Point HL at the top pixel row of the arrow's location in the screen buffer at 24576
37517 | DEC H
37518 | LD A,(IX+6) | Draw the top pixel row of the arrow
37521 | LD (HL),A
37522 | INC H | Point HL at the middle pixel row of the arrow's location in the screen buffer at 24576
37523 | LD A,(HL) | Pick up the graphic byte that's already here
37524 | AND (IX+5) | Has the arrow hit anything that has white INK (e.g. Willy)?
37527 | JP NZ,37047 | If so, kill Willy
37530 | LD (HL),255 | Draw the shaft of the arrow
37532 | INC H | Point HL at the bottom pixel row of the arrow's location in the screen buffer at 24576
37533 | LD A,(IX+6) | Draw the bottom pixel row of the arrow
37536 | LD (HL),A
37537 | JP 37811 | Jump to consider the next entity
We are dealing with a rope.
37540 | LD IY,33280 | Point IY at the first byte of the screen buffer address lookup table at 33280
37544 | LD (IX+9),0 | Initialise the second byte in the following entity buffer to zero; this will count the segments of rope to draw
37548 | LD A,(IX+2) | Initialise the fourth byte of the rope's buffer; this holds the x-coordinate of the cell in which the segment of rope under consideration will be drawn
37551 | LD (IX+3),A
37554 | LD (IX+5),128 | Initialise the sixth byte of the rope's buffer to 128 (bit 7 set); the value held here is used to draw the segment of rope under consideration
The following loop draws each segment of the rope from top to bottom.
37558 | LD A,(IY+0) | Point HL at the location of the segment of rope under consideration in the screen buffer at 24576
37561 | ADD A,(IX+3)
37564 | LD L,A
37565 | LD H,(IY+1)
37568 | LD A,(34262) | Pick up the rope status indicator at 34262
37571 | OR A | Is Willy on the rope, or has he recently jumped or dropped off it?
37572 | JR NZ,37590 | Jump if so
37574 | LD A,(IX+5) | Pick up the drawing byte
37577 | AND (HL) | Is this segment of rope touching anything else that's been drawn so far (e.g. Willy)?
37578 | JR Z,37646 | Jump if not
37580 | LD A,(IX+9) | Copy the segment counter into the rope status indicator at 34262
37583 | LD (34262),A
37586 | SET 0,(IX+11) | Signal: Willy is on the rope
37590 | CP (IX+9) | Does the rope status indicator at 34262 match the segment counter?
37593 | JR NZ,37646 | Jump if not
37595 | BIT 0,(IX+11) | Is Willy on the rope (and clinging to this particular segment)?
37599 | JR Z,37646 | Jump if not
37601 | LD B,(IX+3) | Copy the x-coordinate of the cell containing the segment of rope under consideration to B
37604 | LD A,(IX+5) | Pick up the drawing byte in A
37607 | LD C,1 | The value in C will specify Willy's next animation frame; initialise it to 1
37609 | CP 4 | Is the set bit of the drawing byte in bit 0 or 1?
37611 | JR C,37628 | Jump if so
37613 | LD C,0 | Assume that Willy's next animation frame will be 0
37615 | CP 16 | Is the set bit of the drawing byte in bit 2 or 3?
37617 | JR C,37628 | Jump if so
37619 | DEC B | Decrement the x-coordinate
37620 | LD C,3 | Assume that Willy's next animation frame will be 3
37622 | CP 64 | Is the set bit of the drawing byte in bit 4 or 5?
37624 | JR C,37628 | Jump if so
37626 | LD C,2 | Willy's next animation frame will be 2 (the set bit of the drawing byte is in bit 6 or 7)
37628 | LD (34258),BC | Set Willy's animation frame at 34258, and temporarily store his x-coordinate at 34259
37632 | LD A,IYl | Update Willy's y-coordinate at 34255 to account for his change of location as the rope moves
37634 | SUB 16
37636 | LD (34255),A
37639 | PUSH HL | Save HL briefly
37640 | CALL 36508 | Update Willy's attribute buffer address at 34259 to account for his change of location as the rope moves
37643 | POP HL | Restore the screen buffer address of the segment of rope under consideration to HL
37644 | JR 37646 | Make a redundant jump to the next instruction
37646 | LD A,(IX+5) | Draw a pixel of the rope to the screen buffer at 24576
37649 | OR (HL)
37650 | LD (HL),A
37651 | LD A,(IX+9) | Point HL at the relevant entry in the second half of the rope animation table at 33536
37654 | ADD A,(IX+1)
37657 | LD L,A
37658 | SET 7,L
37660 | LD H,131
37662 | LD E,(HL) | Add its value to IY; now IY points at the entry in the screen buffer address lookup table at 33280 that corresponds to the next segment of rope to consider
37663 | LD D,0
37665 | ADD IY,DE
37667 | RES 7,L | Point HL at the relevant entry in the first half of the rope animation table at 33536
37669 | LD A,(HL) | Pick up its value
37670 | OR A | Is it zero?
37671 | JR Z,37712 | Jump if so
37673 | LD B,A | Copy the rope animation table entry value to B; this will count the rotations of the drawing byte
37674 | BIT 7,(IX+1) | Is the rope currently right of centre?
37678 | JR Z,37697 | Jump if so
37680 | RLC (IX+5) | Rotate the drawing byte left once
37684 | BIT 0,(IX+5) | Did that push the set bit from bit 7 into bit 0?
37688 | JR Z,37693 | Jump if not
37690 | DEC (IX+3) | Decrement the x-coordinate for the cell containing this segment of rope
37693 | DJNZ 37680 | Jump back until the drawing byte has been rotated as required
37695 | JR 37712 | Jump to consider the next segment of rope
37697 | RRC (IX+5) | Rotate the drawing byte right once
37701 | BIT 7,(IX+5) | Did that push the set bit from bit 0 into bit 7?
37705 | JR Z,37710 | Jump if not
37707 | INC (IX+3) | Increment the x-coordinate for the cell containing this segment of rope
37710 | DJNZ 37697 | Jump back until the drawing byte has been rotated as required
37712 | LD A,(IX+9) | Pick up the segment counter
37715 | CP (IX+4) | Have we drawn every segment of the rope yet?
37718 | JR Z,37726 | Jump if so
37720 | INC (IX+9) | Increment the segment counter
37723 | JP 37558 | Jump back to draw the next segment of rope
Now that the entire rope has been drawn, deal with Willy's movement along it.
37726 | LD A,(34262) | Pick up the rope status indicator at 34262
37729 | BIT 7,A | Has Willy recently jumped off the rope or dropped off the bottom of it (A>=240)?
37731 | JR Z,37743 | Jump if not
37733 | INC A | Update the rope status indicator at 34262
37734 | LD (34262),A
37737 | RES 0,(IX+11) | Signal: Willy is not on the rope
37741 | JR 37811 | Jump to consider the next entity
37743 | BIT 0,(IX+11) | Is Willy on the rope?
37747 | JR Z,37811 | If not, jump to consider the next entity
37749 | LD A,(34256) | Pick up Willy's direction and movement flags from 34256
37752 | BIT 1,A | Is Willy moving up or down the rope?
37754 | JR Z,37811 | If not, jump to consider the next entity
37756 | RRCA | XOR Willy's direction bit (0=facing right, 1=facing left) with the rope's direction bit (0=swinging right to left, 1=swinging left to right)
37757 | XOR (IX+0)
37760 | RLCA
37761 | RLCA | Now A=1 if Willy is facing the same direction as the rope is swinging (he will move down the rope), or -1 otherwise (he will move up the rope)
37762 | AND 2
37764 | DEC A
37765 | LD HL,34262 | Increment or decrement the rope status indicator at 34262
37768 | ADD A,(HL)
37769 | LD (HL),A
37770 | LD A,(33003) | Pick up the number of the room above from 33003 and copy it to C
37773 | LD C,A
37774 | LD A,(33824) | Pick up the number of the current room from 33824
37777 | CP C | Is there a room above this one?
37778 | JR NZ,37787 | Jump if so
37780 | LD A,(HL) | Pick up the rope status indicator at 34262
37781 | CP 12 | Is it 12 or greater?
37783 | JR NC,37787 | Jump if so
37785 | LD (HL),12 | Set the rope status indicator at 34262 to 12 (there is nowhere to go above this rope)
37787 | LD A,(HL) | Pick up the rope status indicator at 34262
37788 | CP (IX+4) | Compare it with the length of the rope
37791 | JR C,37811 | If Willy is at or above the bottom of the rope, jump to consider the next entity
37793 | JR Z,37811
37795 | LD (HL),240 | Set the rope status indicator at 34262 to 240 (Willy has just dropped off the bottom of the rope)
37797 | LD A,(34255) | Round down Willy's y-coordinate at 34255 to the nearest multiple of 8; this might move him upwards a little, but ensures that his actual pixel y-coordinate is a multiple of 4 before he starts falling
37800 | AND 248
37802 | LD (34255),A
37805 | XOR A | Initialise the airborne status indicator at 34257
37806 | LD (34257),A
37809 | JR 37811 | Make a redundant jump to the next instruction
The current entity has been dealt with. Time for the next one.
37811 | LD DE,8 | Point IX at the first byte of the next entity's buffer
37814 | ADD IX,DE
37816 | JP 37314 | Jump back to deal with it