Jet Set 40-40 - Readme

You might also like

Download as txt, pdf, or txt
Download as txt, pdf, or txt
You are on page 1of 15

=============================================

| Jet Set 40-40 |


| |
| Game Builders: Andy Ford & Daniel Gromann |
| |
| Technical Contribution: Ian Rushforth |
| |
| (jswmm.co.uk) |
=============================================

'Jet Set 40-40' is a redesign of Matthew Smith's classic ZX Spectrum 48K game 'Jet
Set Willy'. It can be played on a real Spectrum, on the Sinclair ZX Spectrum
Vega/Vega+ or on a computer, game console or another device using a ZX Spectrum
emulator.

The layout of 'Jet Set 40-40' is very similar to that of the original 'Jet Set
Willy' (henceforth abbreviated as 'JSW'), but the number of rooms has been reduced
to 40. There is one item per room, but the player has to collect four complete sets
of items; once the last item of one set has been collected, the items of the next
set will appear. The difficulty of the game will increase with each consecutive set
of items, as more and more guardians threaten Willy's progress through his mansion
and its surroundings.

The player is offered a choice of rooms in which they can start the game. An option
of playing without some of the most extreme challenges can also be chosen. We hope
you will enjoy this 'quadruple quadragesimal' challenge!

Contents

I. Acknowledgements and thanks

II. Instructions

III. Game history

IV. Technical information

V. The legal bit

VI. Closing remarks

----------------------------------------------------------------------

I. Acknowledgements and thanks

The authors would like to express their gratitude to:

- Matthew Smith, creator of the original 'JSW' and 'Manic Miner'.

- John Elliott, for his excellent JSW Editor (JSWED,


http://www.seasip.info/Jsw/jswed.html), which was the main tool used to create the
game, and for JSWED's accompanying documentation. A modified version of John's
solution, which defines Willy's facing direction and frame of animation at the
start of each game, has been used in the Starting Room Selection Screen routine.
- Richard Dymond ('SkoolKid'), for his complete JSW disassembly
(http://skoolkid.github.io/jetsetwilly/ in hex and
http://skoolkit.ca/disassemblies/jet_set_willy/index.html in decimal), which was of
great assistance in implementing various code modifications and optimisations in
'Jet Set 40-40', as well as for his 'Skool Daze' disassembly
(http://skoolkid.github.io/skooldaze/ in hex and
http://skoolkit.ca/disassemblies/skool_daze/index.html in decimal), which made it
easy to rip some sound effects from that game.

- David S. Reidy and Keith Warrington, the authors of 'Skool Daze' (Microsphere,
1984), the game from which the sound effects audible after selecting the starting
screen and upon reaching the bed just before the toilet run have been copied.

- Jon R. Lemmon and Tim Kemp, the authors of 'Project-X: The Micro Man' (Compass
Software, 1985), the game from which the font has been copied.

- Richard Hallas, for coding 'Wheels', one of the in-game tunes, and the 'Radetzky
March', used in the game as the 128-byte-long 'victory tune'. Furthermore,
Richard's document 'A Miner Triad' (http://hallas.net/Software/music.htm) is an
invaluable guide to creating music for JSW/Manic Miner games.

- Andrew Broad, for his 'Lord of the Dance' coded in the JSW48 format, used as one
of the in-game tunes, for his JSW-related technical documents and for establishing
and managing the Manic Miner & Jet Set Willy Yahoo! Group
(https://groups.yahoo.com/neo/groups/manicminerandjetsetwilly/info).

- Stuart Brady, for his Cell-Graphics Bug Fix, which ensures that all cell graphics
are drawn as the designer intended.

- Norman Sword, for his optimised routine dealing with ropes, which freed up a
sizable chunk of spare space, later used for other purposes. A discussion with
Norman on jswmm.co.uk also inspired Ian Rushforth to carry out further optimisation
of the item-handling code (with an additional benefit in terms of speeding up the
program).

- Jonathan Graham Harston, for his 'Full Z80 Opcode List Including Undocumented
Opcodes' (http://www.z80.info/z80oplist.txt), for his 'JSW' related documentation
(http://mdfs.net/Software/JSW/) and for his elegant Pause Bug Fix.

- James Moxham, for his 'ZINT Z80 Interpreter' (http://www.z80.info/z80code.htm),


which is a highly informative introduction to the Z80 instruction set.

- The authors of Binary Hex Converter (http://www.binaryhexconverter.com/), which


was the standard tool used to convert values back and forth between the decimal,
binary and hexadecimal systems. The Bitwise Calculator at
http://www.miniwebtool.com/bitwise-calculator/ was also a useful tool.

- The ZX Spin team, for their ZX Spin (http://www.zophar.net/sinclair/zx-


spin.html), which was used by Daniel Gromann in playtesting.

- Jan Bobrowski, for his Qaop/JS HTML5 ZX Spectrum emulator, which was used by Ian
Rushforth in playtesting.

- Claus Jahn, for his ZX-Modules (http://www.zx-modules.de), particularly ZX-


Paintbrush which was used during the creation of the loading and title screens, and
ZX-Blockeditor which was used during the creation of the final TAP and TZX files.

- The authors of the games from which various sprites have been borrowed (a
detailed list is included below).
The rooms

Most of the rooms preserve their general layout from the original 'JSW'.
Modifications (such as the diptych 'East Attic' - 'West Attic') are mainly the work
of Andy Ford, who also defined the game's map (especially in where it differs from
the original).

The sprites

The majority of the sprites in the game are Matthew Smith's classics from the
original 'JSW'. The remaining ones are (only examples of where they appear in the
game are given, the list of their appearances is by no means exhaustive):

- The '1 ton' vertical guardians in 'Master Bedroom' and the 'penny-farthing'
guardians in 'Front Door' were copied from 'Technician Ted' by Steve Marsden and
David Cooke (Hewson Consultants Ltd, 1984).

- The rightmost, red vertical guardian in 'Master Bedroom' was copied from 'The
DrUnKeN mAsTeR!!!' by the DrUnKeN mAsTeR!!! (BaSe1 PrOdUcTiOnZ, 2002).

- The white and yellow vertical guardians in 'Orangery' were copied from 'JSW
(Sunday Afternoon Graphical Remix)' by Darren McCowan (2001).

- The magenta vertical guardians in 'Orangery' were copied from 'Jet Set Willy II:
The Final Frontier' by Derrick P. Rowson (Software Projects Ltd, 1985), originally
created as an Amstrad version of 'JSW' by Derrick P. Rowson and Steve Wetherill.

- The stationary 'forcefield' guardian in 'East Attic' was copied from 'The Deadly
Mission' by Adam Britton (1985).

- The bright green horizontal guardian in 'West Ballroom', the magenta horizontal
guardians in 'Security Guard' and the red 'trap door' guardian in 'First Landing'
were copied from 'Willy's Holiday' by Adam Britton (1985).

- The green horizontal guardian in 'Back Stairway' is an upside-down version of a


sprite copied from 'Technician Ted', tweaked by Ian Rushforth.

- The magenta 'portcullis' guardian in 'The Chapel', the vertical 'insect'


guardians in 'Conservatory Roof' and the blue 'periscope' guardian in 'First
Landing' were designed by Daniel Gromann (the periscope being a modification of the
'periscope / Macaroni Ted' guardian from 'Jet Set Willy II: The Final Frontier').

- The swordfish sign was copied from 'Manic Miner' by Matthew Smith (Bug-Byte,
1983).

The music

The title-screen tune is the original tune from 'JSW', i.e. the 'Moonlight Sonata',
coded by Matthew Smith, originally composed by Ludwig van Beethoven (the Piano
Sonata No. 14 in C♯ minor 'Quasi una fantasia', Op. 27, No. 2, 1801).

The game features six in-game tunes. They are:

- The original tune from 'JSW' ('If I Were a Rich Man'), coded by Matthew Smith,
originally written by Sheldon Harnick and Jerry Bock for the 1964 musical 'Fiddler
on the Roof' (audible e.g. in 'The Bathroom').

- The original tune from 'Manic Miner' ('In the Hall of the Mountain King'), used
also in 'Jet Set Willy II: The Final Frontier', coded by Matthew Smith, originally
composed by Edvard Grieg (1875) (audible e.g. in 'Driveway').

- 'Lord of the Dance', coded by Andrew Broad (first released as an Easter egg in
his 2004 game 'Party Willy'), originally written by Sydney Carter (1963), although
the tune is, in fact, a traditional Shaker tune (audible e.g. in 'At the Top of the
House').

- 'Wheels', coded by Richard Hallas, originally composed by Richard Stephens, Jimmy


Torres and Norman Petty (1960) and released by the String-A-Longs on their first
single (the tune has had over a hundred cover versions since, including by Joe Loss
['Wheels Cha-Cha'] and Billy Vaughn). An earlier adaptation of 'Wheels' was
featured in Richard's 1985 classic 'Join the Jet-Set!' (it can be chosen as tune
No. 7 before the start of the game). Richard coded the new note-perfect
transcription especially for 'Jet Set 40-40' upon receiving a request from Ian.

- A portion of the 'Moonlight Sonata', coded by Matthew Smith as the title-screen


tune, played as the in-game tune in 'The Nightmare Room'.

- 'Radetzky March', coded by Richard Hallas, originally composed by Johann Strauss


Sr. (1848), used as the 'victory tune'. An earlier, shorter (64-byte) version of
the 'Radetzky March' was scored by Richard for Philip Bee's game 'Jet-Set Willy
Ivy' (Filsoft, 1998), while a longer (256-byte) version is featured in 'Jet Set
Mini' by Ian Rushforth and Andy Ford (2017).

The font

The custom game font was added by Andy Ford. It was taken from 'Project-X: The
Micro Man' by Jon R. Lemmon and Tim Kemp (Compass Software, 1985) with a few very
minor alterations to its layout.

The title screen

The title screen was designed by Andy Ford. It was initially created in BASIC using
the built-in graphics, and then modified using ZX-Paintbrush to create the final
layout.

The loading screen

The loading screen was designed by Daniel Gromann, using ZX-Paintbrush and various
other tools.

Support for the Vega/Vega+

The ZXK file to map the Vega controls to the ZX Spectrum keys used by the game was
created by Ian Rushforth. Ian also tested it on a real Vega to ensure it was fully
functional.

----------------------------------------------------------------------
II. Instructions

The object of the game is to guide Willy and collect all of the flashing items
scattered around his mansion, avoiding the moving and unmoving guardians and the
stationary nasties which may kill you (as will falling from an excessive height).
With all the items collected, the player needs to go to 'Master Bedroom' where
Maria will no longer be blocking access to Willy's bed. The whole process has to be
completed before midnight.

At the start, there is one item to collect in each of the 40 rooms of the game.
After the last item of the first set has been collected, the items of the second
set will appear (as will some additional guardians). This process will repeat after
collecting the items of the second and third set. The fourth set of items is the
final one.

After pressing ENTER to start the game, the player is asked whether or not they
want to face maximum difficulty. Choosing 'Y' will allow the game to be played in
its most difficult permutation. Choosing 'N' will result in ten guardians (and one
lethal arrow) which create the hardest challenges for the player being omitted, and
one guardian being converted to a less threatening incarnation! These guardians
will be restored if 'Y' is chosen at the start of the next game.

The player is then presented with a 'Starting Room Selection' menu screen. Press a
number key from 0 to 9 to choose the room in which the game will start and to
launch it.

Use O-Left, P-Right (or a combination of keys from the top row of letters) and
SPACE or any of the letters from the bottom row to jump.
A-G pauses the game; any other key unpauses it.
H-ENTER/RETURN toggle the music ON/OFF.
Pressing SHIFT+SPACE together at the same time abandons the current game.

'Jet Set 40-40' has been fully and extensively playtested by Daniel Gromann. It is
possible to complete the game in either difficulty mode, before the in-game clock
strikes noon, and without losing a single life!

----------------------------------------------------------------------

III. Game history

The 'Jet Set 40-40' project was started by Andy Ford at the end of July 2017 as
'JSW with 40 objects and 40 rooms - that simple'. Apart from modifying the layout,
Andy introduced various other tweaks such as:

- a redesigned title screen;

- a custom font;

- 24-hour clock with the game ending at midnight;

- minor adjustments to the 'lower screen' (the status area) display such as the
lives colouring and the text positioning;

- removal of unwanted routines such as the colour-code keypad and inactivity timer.

At the end of July 2017 the project was presented in the Contributor Lounge of the
Jet Set Willy & Manic Miner Community, where Ian Rushforth and Daniel Gromann
joined in and became engaged in its further development. Daniel came up with the
idea of having 4 sets of 40 items each, and a theoretical technical solution for
it. Ian then created and implemented a different, much more efficient solution, as
well as a tweak to have the guardians appear 'in instalments'. Andy and Daniel
defined the placement of the additional Item Sets. Daniel added new guardians, some
technical features (various in-game tunes, colourful arrows), the Starting Room
Selection Screen, the choice of difficulty level at the start and a number of
special effects related to the completion of the game. He also created the loading
screen. Ian, in turn, added one more guardian (which appears in a room that is not
normally accessible during gameplay…), an additional tune coded by Richard Hallas
and some technical tweaks. Finally, Andy created a custom BASIC loader and the
final TAP and TZX files of the game.

Following Andy's initial decision to make room 40 ('Master Bedroom') the last
screen in the game as far as the code is concerned, during the development of the
project a part of its challenge was always keeping everything below room 40's code
addresses. This has been achieved thanks to various optimisations and consolidation
of the code when new features were added.

By the time the project was ready for release, almost 1200 posts had been exchanged
between the contributors in the pertinent topic at jswmm.co.uk.

The game was released on Friday 26th January 2018, two years to the day after the
release of the authors' first joint project, 'Jet Set Willy: The Nightmare Edition'
(http://jswmm.co.uk/topic/161-file-jet-set-willy-the-nightmare-edition/).

----------------------------------------------------------------------

IV. Technical information

The game contains a number of features which go beyond the standard JSW48 game
engine (i.e. the game engine used by the original 'JSW'). Some of them are
described below.

1. Multiple sets of items to collect

This novelty was created by Ian Rushforth.

Preamble: In the original 'JSW' game engine, the items are handled as follows:

- The item definitions are stored in a table across pages #A4 and #A5 of the code
(two definition bytes per item, one in each half of the table). The table is
populated 'from the last entry downwards', i.e. Offset #FF (the addresses
#A4FF/#A5FF), then Offset #FE, etc.

- The address #A3FF is a fixed variable which is used as an index pointing at the
first item. It holds the low byte of the address of the first entry defined in each
half of the table (so for example, in a game with three items, #A3FF would hold the
value #FD - meaning that the first item's definition bytes are found at the
addresses #A4FD and #A5FD).

- The 'Game initialisation' routine, which starts at #87CA, picks up the value of
#A3FF and uses it to establish a loop, pointing the HL register-pair at each
defined item entry in the half of the Item Table occupying page #A4 in turn, and
setting Bit 6 for each byte. This bit acts as the item's Collection Flag. The L
register is incremented during each pass through this loop, in order to point HL at
the next item entry (H has a fixed value of #A4 throughout). The loop is sustained
until L is incremented past #FF to #00 (thus setting the Zero Flag), at which point
all items will have been marked as 'uncollected' (Bit 6 set).

- The 'Game initialisation' routine also initialises the value of the address
#85DE. This is a counter of the number of items remaining, expressed as a negative
number in the range -256 (#00) to -1 (#FF). At the beginning of each game, the
value of #A3FF is copied to #85DE, and then the former remains fixed during the
course of the game, whilst the latter is incremented during runtime each time an
item is collected.

- The 'Game initialisation' routine initialises the values of the addresses #857C
to #857E to #30. These three addresses are displayed on the physical screen as an
ASCII counter of the number of items collected throughout the game (beginning with
'000').

- The address #85DF acts as an indicator of the current Game Mode. This is
initialised to zero, to indicate that there are items left scattered around Willy's
house, and he cannot go to bed until he has collected them all.

- Once the game is running, the routine at #93D1 is called during every pass
through the game's Main Loop. This routine picks up the 'Index of the first item'
from #A3FF, and then sets up a loop via HL, to consider each item defined in the
game in turn.

- If an item is located in the room currently occupied by Willy, AND if that item
is flagged as still being uncollected, then the routine checks whether the cell in
which the item is located (determined by the rest of the relevant entry in the Item
Table at pages #A4 and #A5) contains white INK. This is used as an indicator that
Willy (whose colour attribute is white) has touched the item under consideration.

- If there is no white INK present, then the item remains uncollected and therefore
its graphic is drawn at the appropriate coordinates.

- If white INK is present, then the item is collected, which involves several
aspects: the on-screen ASCII tally (#857C-#857E) is incremented, a sound effect
takes place, the pertinent entry in page #A4 of the Item Table has its Bit 6 reset
(marking it as 'collected'), and finally the value of the internal item counter
(#85DE) is incremented.

- If that last step has incremented the value of #85DE 'up' to #00, then the Zero
Flag will be set, and this is interpreted by the code as a sign that there are no
items remaining uncollected. Willy has finished tidying up his house and is now
allowed to go to bed. The value of the Game Mode Indicator is set to #01, which
means that Maria will no longer be present in the Master Bedroom, preventing Willy
from reaching his bed!

In the 'Jet Set 40-40' game engine, the items are handled as follows:

- Each room, numbered from 1-40, contains exactly four items.

- Items appear in the game in sets of 40 (one per room); each set has to be fully
collected before the next set appears.

- The item definitions are still stored in a table across pages #A4 and #A5 of the
code, but the items are arranged sequentially in (reverse) room number order. If a
room's number is expressed as a negative number, then this gives the index to point
at the first item definition for each room, and then the entries for the next three
items for that room can be accessed in turn by subtracting 40 from the entry for
the previous item.

- Thus the entries in the Item Table from #A460/#A560 to #A4FF/#A5FF are used to
store the item definitions, e.g. the first data entry in the table, representing
the fourth item in Room 40, is located at the addresses #A460 and #A560: -{40 + (4-
1) x 40} = -160 = -#A0 ≡ #60: hence Offset #60. (Note that all addresses prior to
that in the Item Table, which are not used for item data - i.e. the addresses
#A400-#A45F and #A500-#A55F - have been 'recycled' and used by the program for
various other purposes.)

- The use of the address #A3FF as a fixed 'Index to the first item' variable is no
longer needed. #A3FF is redesignated as a runtime variable, keeping track of the
current Item Set that Willy is collecting. Its default value in the game file is
still set to #60 (so that the JSWED editor, which isn't aware of the changes to the
game engine, still respects #A3FF's old purpose and therefore displays all the
items in its GUI).

- However, as soon as the game is loaded, the 'Game initialisation' routine sets
the value of #A3FF to #01 (representing Item Set 1). The routine then points the HL
register-pair directly at the address #A460, before performing the same loop as
occurs in the original 'JSW', to set the Collection Flag (Bit 6) for each item's
entry in page #A4 of the code.

- The 'Game initialisation' routine sets the value of #85DE to an initial value of
#D8, which equates to a negative decimal value of -40. The variable at #85DE
performs a similar role as it did in the original 'JSW', except that in 'Jet Set
40-40' it keeps a tally of the number of items remaining to be collected FROM THE
CURRENT ITEM SET.

- The 'Game initialisation' routine also initialises the values of the ASCII
counters at #857C to #857E. However, the number of items in each set is limited to
two digits, so only #857D and #857E are 'zeroed' to #30 and used for the purpose of
tallying items collected. The address #857C is redefined as the ASCII counter of
the current Item Set under consideration, and is therefore assigned an initial
value of #31 (the ASCII character code for '1').

- As in the original 'JSW', the address #85DF acts as an indicator of the current
Game Mode, and it is initialised with a value of #00.

- Once the game is running, the routine at #93D1 is called during every pass
through the game's Main Loop. This item-handling routine has been restructured, so
that it only picks up the value of one pair of entries from the Item Table (the
corresponding offsets in pages #A4/#A5), representing the single item from the
current Item Set in the room that Willy is presently occupying (the current room
number variable being stored at the address #85CB). This arrangement gives rise to
a noticeable speeding up of the running of the game, since the program is no longer
needlessly taking into consideration every single item in the whole game, during
each time-frame of the game!

- The drawing of items is handled in a similar manner to the original 'JSW', as is


the situation when an item is picked up but other items remain uncollected from the
current Item Set.

- However, when Willy clears the final item from the Item Set currently under
consideration, the program jumps to a new piece of code at #96F4, to handle the
transition between Item Sets. Depending on the circumstances, flow of execution
here branches off in two different directions:
- If Willy has just finished collecting Item Set 1, 2 or 3, then the 'Current Item
Set' variable at #A3FF is incremented, along with the on-screen ASCII 'Item Set'
counter at #857C. But the 'Number of Items Remaining' counter (#85DE) is reset back
to #D8 (-40), so that this variable can begin to count the next set of items, and
the on-screen ASCII 'Items Cleared' tally (#857D-E) is reset back to '00' for the
next Item Set.

- If Willy has just finished collecting the final Item Set (Set 4), then his
mission is complete, and the Game Mode Indicator at #85DF is incremented to #01 to
move Maria out of the way of Willy's bed.

- There are also some special effects which take place during the transition
between Item Sets / Game Modes. There now follows a disassembly of the restructured
item-handling routine and the 'Next Item Set' code.

At #93D1, 'Draw the item in the current room, or collect it if Willy is touching
it':

#93D1 3A CB 85 LD A, (#85CB) Load up the 'Current Room Number'


variable to the Accumulator
#93D4 B7 OR A This command sets the Zero Flag if (and
only if) A holds a value of zero
#93D5 C8 RET Z If the Zero Flag is set, then return to
the Main Loop (Room 00 is not one of the forty defined rooms)
#93D6 6F LD L, A Otherwise, copy the room number to the
L register
#93D7 3A FF A3 LD A, (#A3FF) Pick up the 'Current Item Set' counter
in A
#93DA 3D DEC A Decrement it
#93DB 28 06 JR Z, #93E3 Skip forward if Willy is still
collecting Item Set 1
#93DD 47 LD B, A Copy [Item Set-1] to B
#93DE AF XOR A Reset the Accumulator to zero
#93DF C6 D8 ADD A, #D8 Subtract #28 (40 in decimal)…
#93E1 10 FC DJNZ #93DF … for each Item Set already cleared
#93E3 95 SUB A, L Subtract the current room number from A
#93E4 6F LD L, A L now holds the offset for the correct
item definition…
#93E5 26 A4 LD H, #A4 … as stored in Page #A4 of the code
#93E7 CB 76 BIT 6, (HL) Check the Collection Flag for the item
under consideration
#93E9 C8 RET Z Return to the Main Loop if the item has
already been collected

#93EA 7E LD A, (HL) Copy the item definition byte from page


#A4 to A
#93EB 07 RLCA Put Bit 7 into Bit 0…
#93EC E6 01 AND #01 … and ignore all other bits
#93EE C6 5C ADD A, #5C The attribute buffer is located at
addresses #5C00-#5DFF
#93F0 57 LD D, A D now holds the high byte of the item's
attribute coordinates
#93F1 24 INC H Point H at Page #A5 for the other item
definition byte
#93F2 5E LD E, (HL) E now holds the low byte of the current
item's coordinates
#93F3 25 DEC H Point H back to Page #A4 (in case we
have to reset the Collection Flag later on)
#93F4 1A LD A, (DE) Load the current item's attribute
coordinates to A…
#93F5 3C INC A … increment it…
#93F6 E6 07 AND #07 … and select Bits 0-2; the Zero Flag
will now be set if (and only if) the INK attribute at the item's location is white
#93F8 20 37 JR NZ, #9431 If not, then jump forward to draw the
item

But if the item has encountered white INK, then the item is collected as flow of
execution of the routine continues:

#93FA DD 21 7D 85 LD IX, #857D Point IX at the ASCII counter of 'Items


Cleared' (in the current Item Set)
#93FE DD 34 01 INC (IX+#01) Increment the units digit
#9401 DD 7E 01 LD A, (IX+#01) Load the units digit to A
#9404 FE 3A CP #3A Has it just rolled past '9'?
#9406 20 07 JR NZ, #940F If not, then skip forward
#9408 DD 36 01 30 LD (IX+#01), #30 If so, then set the units digit to '0'…
#940C DD 34 00 INC (IX+#00) … and increment the tens digit

#940F 3A DE 80 LD A, (#80DE) Pick up the border colour for the


current room
#9412 0E 80 LD C, #80 S
#9414 D3 FE OUT (#FE), A O
#9416 EE 18 XOR #18 U
#9418 5F LD E, A N
#9419 3E 90 LD A, #90 D
#941B 91 SUB A, C
#941C 47 LD B, A E
#941D 7B LD A, E F
#941E 10 FE DJNZ #941E F
#9420 0D DEC C E
#9421 0D DEC C C
#9422 20 F0 JR NZ, #9414 T
#9424 3A DE 85 LD A, (#85DE) Load up the 'Number of Items Remaining'
internal variable to A…
#9427 3C INC A … increment it…
#9428 32 DE 85 LD (#85DE), A … and update the variable
#942B CB B6 RES 6, (HL) Clear the Collection Flag for the item
under consideration
#942D C0 RET NZ Return to the Main Loop UNLESS the
'Number of Items Remaining' value has just reached #00, thus setting the Zero Flag…
#942E C3 F4 96 JP #96F4 … in which case Willy has just cleared
the last item in the current set, so the program jumps to the 'Next Item Set' code

#9431 3A E0 85 LD A, (#85E0) Load the 'Game Tick' counter to A


#9434 E6 03 AND #03 Select Bits 0-1 of A
#9436 C6 03 ADD A, #03 Generate a value representing an INK
colour of magenta, green, cyan or yellow
#9438 4F LD C, A Copy the value to the C register
#9439 1A LD A, (DE) Load up the current colour attribute at
the item's location
#943A E6 F8 AND #F8 Select only the PAPER/BRIGHT/FLASH bits
#943C B1 OR C Merge with the INK colour stored in C
#943D 12 LD (DE), A Update the item's colour attribute in
the attribute buffer
#943E 7A LD A, D Copy the high byte of the attribute
coordinates to A
#943F 07 RLCA Rotate Bit 0 of A leftwards…
#9440 07 RLCA … again…
#9441 07 RLCA … and again…
#9442 E6 08 AND #08 … until it's in Bit 3, and then filter
out all other bits
#9444 C6 60 ADD A, #60 The pixel-buffer is located at
addresses #6000-#6FFF
#9446 57 LD D, A DE now points at the item's address in
the pixel-buffer
#9447 21 E1 80 LD HL, #80E1 Pick up the address of the item graphic
for the current room
#944A C3 99 96 JP #9699 Jump to a late entry point in the
subroutine at #9691, to draw the item at the appropriate location in the pixel-
buffer
The subroutine at #9691 ends in a RET,
which returns flow of execution back to the Main Loop once the item has been drawn

At #96F4, 'Next Item Set':

#96F4 3A FF A3 LD A, #A3FF Load up the 'Current Item Set' counter


to A
#96F7 07 RLCA Multiply it…
#96F8 07 RLCA … by…
#96F9 07 RLCA … eight
#96FA 32 CD 85 LD (#85CD), A … and then load the result up to the
'Screen Flash Counter' variable
(causing the screen to flash X times
through all eight PAPER colours, when Willy has just finished collecting Item Set
X)
#96FD FE 20 CP #20 If A now holds a value of #20, then
this command sets the Zero Flag…
#96FF 28 1E JR Z, #971F … meaning that all four Item Sets have
now been cleared, so skip forwards in the code to move on to the next Game Mode

If the command at #96FF did not have the effect of setting the Zero Flag, then flow
of execution proceeds straight to #9701:

#9701 21 FF A3 LD HL, #A3FF Point HL at the 'Current Item Set'


counter…
#9704 34 INC (HL) … and increment this internal variable
#9705 3E D8 LD A, #D8 Moving onto the next Item Set…
#9707 32 DE 85 LD (#85DE), A … reset the 'Number of Items Remaining'
internal variable back to -#28 (-40)
#970A 3A 1B 89 LD A, (#891B) Pick up the 'Maximum Guardians'
parameter in A…
#970D E6 FE AND #FE … disregard Bit 0 (to ensure an even
number of guardians per room, after the initial Item Set 1 has been completed)…
#970F C6 02 ADD A, #02 … add 2 to the value…
#9711 32 1B 89 LD (#891B), A … and then update the 'Maximum
Guardians' parameter (see the next section for more details)
#9714 21 7C 85 LD HL, #857C Point HL at the ASCII 'Item Set'
counter…
#9717 34 INC (HL) … and increment it
#9718 21 30 30 LD HL, #3030 Assign the ASCII character code for
'00' to the HL register-pair…
#971B 22 7D 85 LD (#857D), HL … and then reset the ASCII 'Items
Cleared' counter, in preparation for the next Item Set
#971E C9 RET Return to the Main Loop – Willy has
moved on to start tidying up the next Item Set
#971F 3E 01 LD A, #01 Willy has finally collected all four
Item Sets…
#9721 32 DF 85 LD (#85DF), A … so update the 'Game Mode Indicator'
variable to shift Maria away from Willy's bed
#9724 06 20 LD B, #20 Select 20 bytes to update the
attributes…
#9726 21 60 5A LD HL, #5A60 … of the relevant character row on the
status bar…
#9729 CB FE SET 7, (HL) … setting the FLASH Bit across the row…
#972B 23 INC HL … to celebrate…
#972C 10 FB DJNZ #9729 … Willy's success…
#972E C9 RET Return to the Main Loop – Willy can now
go to bed!

2. The guardians multiply as the game progresses

This novelty was created by Ian Rushforth.

In the original 'JSW' code, at #8929 in the 'Initialise the current room' routine,
there is the following command: LD A, #08.

The operand of this command determines the maximum number of entities


(ropes/arrows/guardians – not including Maria) within each room in the game.

In 'Jet Set 40-40', the 'Game initialisation' routine sets the operand of the
equivalent command (which is now at #891A-B, due to code shuffling) to a value of
#03 at the start of each game. This means that at the beginning of the game, there
are a maximum of three entities per room.

However, once each set of items has been cleared by Willy, this game parameter is
increased (by editing the value of address #891B - see the disassembly in the
previous section), so that the occupancy limit of each room expands when the game
moves on to the next Item Set. This gives rise to a 'Multiplying Guardians' effect,
ratcheting up the difficulty level of the game as the player progresses.

The general rule is that two further guardians are added to each room, every time
the game proceeds to the next Item Set. However, the initial occupancy rate during
the first Item Set is three, rather than two guardians, to allow the tripartite
'Evil Priest' guardian in rooms such as 'The Chapel' to appear in all its glory
from the outset.

Note that after moving on to the next Item Set, the player will not observe an
immediate increase in the number of guardians per room; the effect does not
manifest itself until the next time that Willy moves into a different room (or he
is 'respawned' after losing a life).

3. The in-game tune set individually in each room

The way the in-game tune is chosen in each room in 'Jet Set 40-40' mirrors the
solution created jointly by Daniel Gromann and Ian Rushforth which had first been
applied in the Special Edition of 'Willy's New Mansion' (2016).

Offsets #DF and #E0 in each room's data (which were unused in the original 'JSW')
specify the (reversed) address of the in-game tune to be used in this room. The
instruction at #8B4D - #8B4F (changed from LD HL,#865F [21 5F 86] to LD HL,(#80DF)
[2A DF 80]) loads this address (from the room's data copied into the room buffer)
so that the routine which plays a note of the in-game music knows where to look for
the tune (instead of the permanent address #865F, the start of the tune is defined
by the value of Offsets #DF and #E0 in the room buffer). The appropriate values for
the start of each tune have been set in each room's data.

4. The colour of arrows set individually in each room

The way the colour of arrows is defined in each room in 'Jet Set 40-40' mirrors the
solution created jointly by Ian Rushforth and Daniel Gromann which had first been
applied in the Special Edition of 'Willy's New Mansion' (2016).

In the original 'JSW', all arrows are white. The following code sets the arrow's
colour there:

9286 7E LD A,(HL)
9287 F6 07 OR #07 set the INK to #07 (white) regardless of the
background's INK colour ('background' here meaning whatever character square the
arrow is passing through)
9289 77 LD (HL),A set the INK to white at the arrow's location

In 'Jet Set 40-40', the code has been modified in the following way:

9286 3A ED 80 LD A,(#80ED) pick up the arrow's attributes from Offset #ED in the
room buffer
9289 77 LD (HL),A set these attributes at the arrow's location

As a result, the arrow's attributes are defined in Offset #ED of each room (unused
in the original 'JSW'). In rooms with no arrows the value of this offset has been
set to #00 (it could be anything, as it has no bearing on the game).

Please see the 'Willy's New Mansion Special Edition' Readme


(http://www.jswcentral.org/download/Willy's_New_Mansion_-_Special_Edition.zip or
https://xa.bi/jsw/download/Willy's_New_Mansion_-_Special_Edition.zip) for more
details concerning this solution.

5. The choice of difficulty level at the start of the game

The code which deals with this issue starts at #A50C. The code modifies the values
of the first byte of (two-byte-long) guardian specifications within the room data
(i.e. in the #..F0 - #..FF range). If the player chooses 'Y', proper values are
written for twelve most difficult guardians (so that they will appear in this game,
even if they had been wiped out by a choice of 'N' at the start of the previous
one). If the player chooses 'N', the first byte of data of eleven of these
guardians is NOPped out (so that they will not appear in this game, being replaced
by 'blank guardians'), and the first byte of data of one guardian is modified (so
that another entity appears in place of the one from the 'maximum difficulty'
version).

The screen which prompts the player with 'Maximum difficulty? Y/N' will also
respond to the player pressing the '6' and '7' keys for the 'Y' and 'N' options,
respectively. This has been implemented by Ian Rushforth in order to make it
possible to map the Vega control buttons to all of the ZX Spectrum keys used by the
game (the mapping had to be done for numerical keys for each of the ten starting
rooms and the 'Y/N' difficulty options - twelve options in total, while there are
only eleven buttons on the Vega unit). Ian also provided a code which checks
whether the player is still holding the '6' or '7' keys, and does not allow them to
proceed until they have let go of the key in question (the code is at #99CE -
#99D9). This prevents a situation in which, due to one of these keys being pressed
for too long, a starting screen of either 'Priest's Hole' (option 6) or 'Tree Top'
(option 7) would be inadvertently selected on the Starting Room Selection Screen.

6. The Starting Room Selection Screen

The code which deals with this screen starts at #86AA. When the starting room is
chosen, not only is the current room number set (which in the original 'JSW' is
done at #87EA - #87EE), but Willy's pixel y-coordinate (in the original 'JSW'
initialised at #87E5 - #87E9), Willy's attribute coordinates (in the original 'JSW'
initialised at #87EF - #87F4), Willy's facing direction (not initialised in the
original 'JSW') and frame of animation (not initialised in the original 'JSW') are
defined as well. As a result, for each of the rooms which may be selected, Willy
always starts the game in exactly the same position and stance (in the original
'JSW', Willy's animation frame and the direction he is facing at the start of a
game are whatever they were when he died in the previous game).

Thanks to the code provided by Ian, mentioned above, after the player presses one
of the numerical keys on this screen, the program will not proceed to load the
starting room until the player has let go of that key. This prevents a situation in
which, due to '0', '5', '6', '7' or '8' being pressed for too long, Willy would
jump or move prematurely after the starting room has loaded.

7. Sound effects from 'Skool Daze'

These were added to 'Jet Set 40-40' by Daniel. It was a relatively easy task thanks
to Richard Dymond ('SkoolKid')'s disassembly of 'Skool Daze' (see the links in
section I above). Some necessary adjustments were made to the code to accommodate
it in 'Jet Set 40-40'. The routine which plays the tune is at #8356 - #837E and
#B496 - #B4B0. The data for the tune played after the starting room has been
selected is at #A400 - #A421, and the data for the tune played upon reaching the
bed in 'Master Bedroom' after all items have been collected is at #A422 - #A444.
Note duration and pitch data for the tunes is at #A500 - #A50B. The code which
launches the tune after the starting room has been selected is at #99C2 - #99C7
(with a call to #B4AA) and the code which launches the tune played upon reaching
the bed in 'Master Bedroom' after all items have been collected is at #B4B1 - #B4BE
(with a relative jump to #B4AA). The latter makes sure that the tune is played only
once, by checking the variable at #8FBF (otherwise the tune, which is triggered by
Willy's x-coordinate, would be played twice before he changes his x-coordinate at
the start of the toilet run - which would be too much).

----------------------------------------------------------------------

V. The legal bit

'Jet Set 40-40' is freeware, and all of its innovative elements may freely be
reused in other projects. If you do so, please acknowledge their authorship.

----------------------------------------------------------------------

VI. Closing remarks

We hope you enjoy playing 'Jet Set 40-40' as much as we did writing it!
If you have any queries, comments or general feedback, please contact us on the
email address below, or come and visit our Jet Set Willy & Manic Miner Community at
jswmm.co.uk to join in with Willy-based discussions! Do let us know you've had a go
at 'Jet Set 40-40', even without any specific comments - the biggest gratification
and encouragement for anyone designing free games is to know that someone else has
played them.

Please check out our other projects, available for download at


http://jswmm.co.uk/files/category/3-jswmm-releases/.

Please visit also JSW Central (www.jswcentral.org), a source of information on JSW


& MM games.

Andy Ford, Daniel Gromann & Ian Rushforth, 26th January 2018

projects@jswmm.co.uk

You might also like