; Copyright 2014-2017, 2019, 2021, 2025 Richard Dymond (rjdymond@gmail.com)

[Bug:faultyClock:12:30am in the afternoon]
The clock-updating code at #R35410 doesn't switch from 'am' to 'pm' until 1pm
(instead of 12 noon), and also doesn't switch from 'pm' to 'am' at midnight.

[Bug:theStickyBed:The sticky bed]
After collecting all the items, if Willy jumps onto the bed in #R58112(Master
Bedroom) (which is a conveyor moving right) instead of walking up to the foot
of it, he will stop moving and the 'P' (right) key becomes unresponsive. This
happens because the code at #R36619 flips bit 0 of #REGe - which has already
been reset because Willy is on a conveyor moving right - to 1, thus preventing
the conveyor from moving Willy, and also effectively disabling the 'P' key.

To see this, use POKE #R41983(41983),255 to make the tap in #R57600(The
Bathroom) the only item that needs to be collected to complete the game, make
your way to the bedroom, and jump onto the bed.

However, all is not lost. Willy can be moved off the bed by using one of the
other 'right' keys: 'I', 'Y', 'R', 'W', '7' or '8'.

To make the bed unsticky:

POKE #R58326(58326),254

[Bug:selfCollectingItem:The self-collecting item]
The item in #R57088(Swimming Pool) is automatically collected as soon as Willy
enters the room; this is because the room's background tile has white INK, and
the routine at #R37841 collects any item that is drawn on a cell with white
INK. There are no other rooms whose background tile has white INK.

To change the INK of the room's background tile from white to cyan, enabling
Willy to collect the item himself:

POKE #R57248(57248),5

Note that this changes the rope's colour from white to cyan.

[Bug:theInvisibleItem:The invisible item]
There is an item in #R56320(First Landing), but you could be forgiven for not
knowing because it's invisible. To give the item a shape and make it visible:

POKE 56548,24: POKE 56549,24

But now that the item is revealed, we can also see that it's unreachable:

#PUSHS
#POKES56548,24,2
#ROOM28,2,16,0,16,16,5(first_landing_item1)

To add a ledge and open the wall to make the item reachable:

POKE 56350,0: POKE 56358,0: POKE 56365,170

#POKES56350,0;56358,0;56365,170
#ROOM28,2,16,0,16,16,5(first_landing_item2)
#POPS

The #POKE(theOfficialSoftwareProjectsPOKEs)(official Software Projects POKE) to
fix this bug is

POKE #R42183(42183),11

which moves the item to #R51968(The Hall) (where it is still invisible, but now
reachable).

[Bug:theInaccessibleItems:The inaccessible items]
The items in #R60160(Conservatory Roof) can only be collected by entering the
room from the ledge on the lower left in #R59904(Under the Roof), but that
ledge is unreachable.

The #POKE(theOfficialSoftwareProjectsPOKEs)(official Software Projects POKE) to
fix this bug is

POKE #R56832(56876),4

which makes it possible to access the right-hand side of #R58368(A bit of tree)
(and from there the lower right side in #R59904(Under the Roof)) from
#R56832(The Banyan Tree).

[Bug:theUncollectableItem:The uncollectable item]
The item on the far right in #R60160(Conservatory Roof) cannot be collected
because there is an unavoidable nasty in the way.

The #POKE(theOfficialSoftwareProjectsPOKEs)(official Software Projects POKE) to
fix this bug is

POKE #R60160#60160(60231),0

which removes the nasty next to the item.

[Bug:guardianHalos:Guardian halos]
In a room with a non-black background, a guardian defined with BRIGHT INK is
drawn with a 'halo': a BRIGHT sprite background that contrasts with the
non-BRIGHT room background. There are four guardians affected by this
phenomenon:

#UDGTABLE(gallery)
{ #ROOM9,2,5,7,6,6(halo1) | #ROOM9,2,26,8,6,6(halo2) |
  #ROOM15,2,9,8,6,6(halo3) |
  #ROOM39,2,6,1,6,6(halo4) }
{ =c2 #R51456(On a Branch Over the Drive) |
  #R52992(I'm sure I've seen this before..) |
  #R59136(Emergency Generator) }
TABLE#

The following POKEs modify the section of code at #R37334 so that a guardian is
drawn in non-BRIGHT INK and PAPER when the room background is not black, thus
preventing any halo:

<div>POKE 37371,40</div>
<div>POKE 37372,2</div>
<div>POKE 37373,203</div>
<div>POKE 37374,177</div>
<div>POKE 37375,177</div>
<div>POKE 37376,205</div>
<div>POKE 37377,201</div>
<div>POKE 37378,147</div>
<div>POKE 37379,79</div>

[Bug:fromTopToBottom:From top to bottom]
In a room that contains a rope and has no exit to the room above, Willy can
jump while at the highest point on the rope (when it's at the leftmost or
rightmost extent of its swing) through the top of the room and reappear on the
floor of the same room. The only rooms where this can happen are #R53760(On the
Roof) and #R64000(The Beach).

To prevent Willy from climbing high enough up the rope to be able to jump
through the top of the room:

<div>POKE #R37781(37782),15</div>
<div>POKE 37786,15</div>

The number 15 here determines the highest segment of rope that Willy can reach
(originally 12, three segments higher up). At segment 15, Willy's y-coordinate
never goes below 25 while he's on the rope, and is adjusted down to 24 (see
#R36782) when he jumps off, which is too far from the top of the room (the
maximum height Willy can jump is 20 pixels). At segment 14, Willy's
y-coordinate never goes below 23 while he's on the rope, but is adjusted down
to 16 when he jumps off, which is close enough to the top of the room to be
able to jump through it.

The code at #R37601 adjusts Willy's location depending on where he's hanging on
to the rope. Specifically, his pixel y-coordinate is set to Y-8, where Y is the
pixel y-coordinate of the segment of rope whose index matches the value of the
rope status indicator at #R34262.

[Bug:longDistanceNasties:Long distance nasties]
If Willy falls through the bottom of a room and there is a nasty at the top of
the room in a direct line above him, he will die before he reaches the room
below.

The only room affected by this bug is #R59904(Under the Roof). Use the
following POKE to start the game in that room and see what happens when Willy
steps off the ledge:

POKE 34795,42

The problem lies in the section of code at #R38392, which sets the attribute
bytes for the cells occupied by and below Willy's sprite. If Willy is below the
level of the floor, #REGhl (which holds the address of the cell in the
attribute buffer at #R23552) is eventually incremented so that it points to the
cell in the ceiling above Willy in the attribute buffer at #R24064. Then the
routine at #R38430 is called to actually set the attribute byte for the cell,
detects the nasty there, and kills Willy.

<div>POKE 38452,208</div>
<div>POKE 38453,253</div>
<div>POKE 64976,203</div>
<div>POKE 64977,76</div>
<div>POKE 64978,202</div>
<div>POKE 64979,182</div>
<div>POKE 64980,144</div>

[Bug:dontMindYourHead:Don't mind your head]
The code at #R36828 onwards that moves Willy left does not check for a wall
tile at head height, which means Willy can move right to left through a wall
tile at that position. To see this, add a wall tile at head height in
#R57600(The Bathroom) and guide Willy through it:

POKE 57708,32

#PUSHS
#POKES57708,32
#WILLY33,17,104,4,15,12,6,4,1(dmyh)
#POPS

However, the code at #R36942 onwards that moves Willy right does check for a
wall tile at head height (at #R37031), so Willy (correctly) cannot move left to
right through a wall tile at that position.

Note that the ability to walk from right to left through a wall tile at head
height comes in handy in #R54016(The Forgotten Abbey) - without that ability,
Willy would not be able to collect the item without sacrificing a life.

[Bug:stuckInTheWall:Stuck in the wall]
If Willy enters #R61696(The Wine Cellar) from the ledge in #R54016(The
Forgotten Abbey), he must keep moving left until he clears all the wall tiles,
otherwise he can become trapped inside them by the conveyor below trying to
move him to the right.

To get on the conveyor, stand facing left at the top of the ramp in The
Forgotten Abbey (see the first image below) and jump left towards the exit -
Willy will land on the ledge (second image). Then walk left into The Wine
Cellar.

#UDGTABLE(gallery) {
  #WILLY19,2,88,6,0,9,6,6(sitw1_1) |
  #WILLY19,1,80,7,0,9,6,6(sitw1_2) |
  #WILLY49,29,80,3,26,9,6,6(sitw1_3)
} TABLE#

Willy can also get stuck in the wall tiles that make up the elephant's head in
#R59392(Dr Jones will never believe this). Start at the location shown in the
first image below, and then walk left.

#UDGTABLE(gallery)
{ #WILLY40,18,24,7,16,1,6,6(sitw2_1) | #WILLY40,15,24,3,13,1,6,6(sitw2_2) }
TABLE#

Getting stuck in these places is possible because Willy can walk right to left
through wall tiles at head height, but not left to right (see
#BUG(dontMindYourHead)()).

[Bug:missedNote:The missed note]
Each note of the #R34399(in-game tune) is played twice by the section of code
at #R35644, <em>except</em> the first note when a new game starts. This is
because the in-game music note index at #R34273 is incremented from 0 to 1 on
the first pass through the code <em>before</em> the first note is played.

[Bug:theBlankConveyor:The blank conveyor]
The conveyor tile in #R60160(Conservatory Roof) is completely blank and its
attribute byte is #b255 - a solid, bright white block - which is characteristic
of unused tiles elsewhere. However, the conveyor tile <em>is</em> used in this
room, and it doesn't look good:

#UDGTABLE { #ROOM43,2,22,12,10,4(blank_conveyor) } TABLE#

See also #FACT(unanimatedConveyors)().

[Bug:corruptedConveyors:Corrupted conveyors]
The conveyors in #R55296(West of Kitchen), #R56576(The Nightmare Room),
#R61696(The Wine Cellar) and #R62208(Tool#SPACE(2)Shed) don't look quite as
they should. The reason for this is a bug in the code at #R36177: if a graphic
data byte of the background, floor, wall, nasty or ramp tile in a room matches
the attribute byte of the conveyor tile to be drawn, the '#S/CPIR/' instruction
exits early, leaving #REGhl pointing at the wrong location.

Here are some 'before' and 'after' pictures showing what the conveyors actually
look like and what they look like when drawn properly.

#UDGTABLE(gallery)
{ #R55296(West of Kitchen) |
  #ROOM24,2,21,11,7,3,2(conveyor24_before) |
  #ROOM24,2,21,11,7,3,14(conveyor24_after) }
{ #R56576(The Nightmare Room) |
  #ROOM29,2,26,6,3,3,0(conveyor29_before) |
  #ROOM29,2,26,6,3,3,8(conveyor29_after) }
{ #R61696(The Wine Cellar) |
  #ROOM49,2,26,11,7,3,2(conveyor49_before) |
  #ROOM49,2,26,11,7,3,8(conveyor49_after) }
{ #R62208(Tool#SPACE(2)Shed) |
  #ROOM51,2,6,14,20,2,2(conveyor51_before) |
  #ROOM51,2,6,14,20,2,10(conveyor51_after) }
{ =t | Before | After }
TABLE#

To fix the bug:

<div>POKE 36178,151</div>
<div>POKE 36181,9</div>
<div>POKE 36183,205</div>
<div>POKE 36184,38</div>
<div>POKE 36185,255</div>
<div>POKE 65318,9</div>
<div>POKE 65319,190</div>
<div>POKE 65322,75</div>
<div>POKE 65323,35</div>
<div>POKE 65324,201</div>

See also #BUG(corruptedNasties)().

[Bug:veryCorruptedConveyor:Very corrupted conveyor]
You might be thinking that the fix given above for the corrupted conveyors bug
does not do much for the appearance of the conveyor in #R56576(The Nightmare
Room). Perhaps that's because the real problem with this conveyor is that its
attribute byte and graphic data - which should occupy addresses
#R56781(#N56781-#N56789) - appear to have been shifted by one byte back to
#N56780-#N56788 (overwriting the eighth graphic byte of the ramp tile). If they
are shifted along to the right spot, the conveyor takes on a much more
reasonable appearance:

#UDGTABLE(gallery)
{ #ROOM29,2,26,6,3,3,0(conveyor29_before) |
  #PUSHS #FOR(56789,56781,-1)||n|#POKES(n,#PEEK(n-1))||
  #ROOM29,2,26,6,3,3,14(conveyor29_after2)
  #POPS }
{ Before | After }
TABLE#

In addition, if the byte at #N56789 (#b85) is shifted back round to #N(56780),
it seems to fix the appearance of the ramp tile (by filling the gap at the
bottom):

#UDGTABLE(gallery)
{ #ROOM29,2,6,12,5,4,0(ramp29_before) |
  #PUSHS #POKES56780,85
  #ROOM29,2,6,12,5,4,8(ramp29_after)
  #POPS }
{ Before | After }
TABLE#

[Bug:corruptedNasties:Corrupted nasties]
The nasty tiles down the right hand side of #R58368(A bit of tree) don't look
quite as they should. The reason for this is the same bug in the code at
#R36177 that causes the #BUG(corruptedConveyors)(corrupted conveyors): if a
graphic data byte of the background, floor or wall tile in a room matches the
attribute byte of the nasty tile to be drawn, the '#S/CPIR/' instruction exits
early, leaving #REGhl pointing at the wrong location.

Here are the 'before' and 'after' pictures showing what the nasties actually
look like and what they look like when drawn properly.

#UDGTABLE(gallery)
{ #ROOM36,2,28,0,4,4,0(nasty36_before) |
  #ROOM36,2,28,0,4,4,8(nasty36_after) }
{ Before | After }
TABLE#

[Bug:invalidGridLocation:Invalid grid location]
If the LSB of the system variable FRAMES is #b142 when the game starts, the
routine at #R34499 will ask for the code at the grid location 'D>', which
doesn't exist on the code sheet.

Should you ever need it, the code for 'D>' is 1444.

POKE #R34555(34556),180

[Bug:thePauseBug:The pause bug]
The Spectrum will hang when trying to resume the game after being paused if an
Interface 1 is connected. This happens because the #REGc register holds #b0
instead of #b254 when the keyboard is read by the '#S/IN A,(C)/' instruction at
#R35620.

POKE #R35615(35615),62: POKE #R35620(35620),219: POKE #R35620(35621),254

[Bug:theAtticBug:The Attic bug]
Perhaps the most famous of all the bugs in Jet Set Willy, the Attic bug is
responsible for certain rooms becoming impossible to navigate after Willy has
visited #R59648(The Attic), thus making it impossible to complete the game.

The root cause of the bug is a misplaced arrow, defined by the entity
specification at #R59900. The second byte of the entity specification is an
index into the table of screen buffer addresses at #R33280, and determines the
arrow's y-coordinate; the index should be an even number, but the value of the
second byte is #b213, which means the arrow-drawing routine at #R37310 looks up
the word at #N33493 and finds #N(41066), way outside the actual screen buffer
at #N24576-#N28671. As a result, the misplaced arrow is 'drawn' at the
following addresses:

#LIST
{ #R40704(#N40810-#N40841): unused (set to #b65, with no effect on the game) }
{ #R41064(#N41066-#N41097): the third byte of entity definition #b13 through to
  the second byte of entity definition #b17 (set to #b255); this affects the
  guardians in #R52736(Rescue Esmerelda), #R52992(I'm sure I've seen this
  before..), #R53248(We must perform a Quirkafleeg), #R49408(The Bridge),
  #R50688(Entrance to Hades), #R56064(The Chapel) and #R58880(Priests' Hole) }
{ #R41320(#N41322-#N41353): the third byte of entity definition #b45 through to
  the second byte of entity definition #b49 (set to #b65); this affects the
  guardians in #R52480(Out on a limb), #R55808(East Wall Base), #R52224(Tree
  Top), #R51200(Inside the MegaTrunk), #R55040(The Kitchen) and #R55296(West of
  Kitchen) }
LIST#

The #POKE(theOfficialSoftwareProjectsPOKEs)(official Software Projects POKE) to
fix the Attic bug is

POKE #R59900(59901),82

which sets the pixel y-coordinate of the arrow to 41.
