Resource centre for ZX Spectrum games
using Manic Miner and Jet Set Willy game engines
Archive of the
Manic Miner & Jet Set Willy Yahoo! Group
messages
|
|
||
|
|
Message: 5792
Author: andrewbroad
Date: 09/04/2006
Subject: Relocatable patches (using RoomNo as an example)
RoomNo is John Elliott's patch to print the room-number at the
bottom-right of the screen.
This message stemmed from my desire to apply RoomNo to Death TV
v0.3..., and the inability of John Elliott's HEXPAT utility to apply
it to a JSW64 game.
http://www.seasip.demon.co.uk/Jsw/patches.html
-----------
The problem
-----------
A lot of patches include subroutines (and sometimes data-areas)
which need to fit in parts of memory which are unused for any other
purpose.
So the first problem, when applying a patch to a particular MM/JSW
game, is to find a range of memory-addresses which is unused, and
which is big enough for the subroutine (or data-area) to fit in.
Unfortunately, John Elliott's patches are distributed in a format
such that the addresses of subroutines (and data-areas) are fixed -
they cannot be changed using his HEXPAT utility.
This is not a problem when applying a patch to an unpatched MM or
JSW48 game-engine, or even JSW128 AFAIK. The lay user need not worry
about setting the start-address for the subroutine (or data-area),
because it is hard-wired into the patch.
But if two separate patches use overlapping address-ranges, then one
will overwrite the other and there will be chaos.
And the patches with subroutines (or data-areas) are generally
inapplicable to JSW64, where the address-ranges that are usually
free in JSW48 are used for other purposes.
So if you try to apply the RoomNo patch to a JSW64 game using
HEXPAT, then the game will crash because the patch-file (roomno.hex)
is hardwired to locate the "showrm" subroutine at #97C6 (and its
data-area at #97C3) - an address which is used for other code in
JSW64.
-----------------------------------------------
My solution: A notation for relocatable patches
-----------------------------------------------
I have invented a notation for distributing patches, in a form that
can be typed into JSWED's hex-editor, such that the addresses of
their subroutines and data-areas, which may have to be relocated,
are given as variables. It's up to the user to choose appropriate
values for these variables.
I illustrate the notation using RoomNo as an example:
Variables:
>>>xHxL: address of default string ("000") - length 3 bytes
yHyL: address of subroutine to print room-number - length #31 bytes
zz: colour-attribute of room-number
<<<
Recommendations:
>>>yHyL = xHxL + 3
xHxL = #97C3 (JSW48 and JSW128 only)
yHxL = #97C6 (JSW48 and JSW128 only)
zz = #44
<<<
Hex-editor:
>>>8A47: yL yH
xHxL: 30 30 30
yHyL: CD 80 96 3A 20 84 0E 30
+#08: DD 21 xL xH D6 64 38 03
+#10: 0C 18 F9 C6 64 DD 71 00
+#18: 0E 30 D6 0A 38 03 0C 18
+#20: F9 C6 3A DD 71 01 DD 77
+#28: 02 0E 03 11 FD 50 C3 80
+#30: 96
9AFD: zz zz zz
<<<
Notice how the addresses appear among the hex-values: the low byte
followed by the high byte. So using yHyL = #97C6, you would type
"yL yH" into the hex-editor as "C6 97" (well, it /would/ be nice if
JSWED printed spaces between the bytes, and printed the hex-literals
in capitals).
I plan to use the above notation on my "Patches" web-page (when
written), and to write a SPECSAISIE function that can take a text-
file written in this notation as input (the user would first edit
the text-file to give values for the variables, then run the
SPECSAISIE function).
------------------------
Finding unused addresses
------------------------
If you wish to apply a patch and choose your own addresses for the
subroutines and data-areas (instead of the addresses given in
Recommendations, which are inapplicable to JSW64), you must first
find unused addresses in your game-file (a task which will hopefully
one day be automated, but which must be done manually for now).
In the unpatched game-engines, the free space is as follows:
MM48
----
* #934C-9CFF (#9B4 bytes) contain assembly-code which can safely be
overwritten.
* There may be some unused space in the room-definitions,
particularly Offsets 733-767 for rooms which have neither VGs nor
special graphics.
http://geocities.com/andrewbroad/spectrum/willy/mm_format.html
JSW48
-----
* #869F-87C9 (#12B bytes) contain the colour-code routine, which is
usually bypassed.
* #96F4-97FF (#10C bytes) contain unused code followed by zeroes.
* #9B00-9BFF (#100 bytes) contain the sprites and colour-attributes
for the colour-code screen, which is usually bypassed.
It is possible to place patches in unused sprite-pages; in the
original JSW, the following addresses are free:
* #9C00-9C3F (#40 bytes) are two unused sprite-frames.
* #9E00-9EB3 (#B4 bytes) are the 'passwords' for the colour-code
screen, which is usually bypassed.
* #9EB4-9FFF (#14C bytes) are unused.
* #A680-AAFF (#480 bytes) are unused.
* #B100-B1FF (#100 bytes) are the Macaroni Ted sprite, which is
unused in the original JSW.
* #B300-B3FF (#100 bytes) are unused.
It is possible to place patches in unused rooms (Room [r] starts at
#C000 + #100*r); in the original JSW, the following addresses are
free:
* #EF00-EFFF [47].
* #FD00-FFFF [61-63].
JSW128
------
* #96F4-97FF (#10C bytes) contain unused code followed by zeroes.
* Free space in #9800-F6FF (Bank 0) varies from game to game, and
it's up to the author to keep an accurate record of this using
JSWED's Memory screen (it can also be useful to consult the
Sprites screen, and even the Hex-editor, to get a more precise
idea of which addresses are unused).
JSW64
-----
* Free space in #9800-F6FF (Bank 0) varies from game to game, and
it's up to the author to keep an accurate record of this using
JSWED's Memory screen (it can also be useful to consult the
Sprites screen, and even the Hex-editor, to get a more precise
idea of which addresses are unused).
* The unused space in rooms can be used for local patch-vectors,
since the room-definition gets copied to the current-room buffer
starting at #8000 - but it cannot be used for global patches, since
the rooms reside in memory-banks that are usually paged out.
Death TV
--------
There are no free pages in this game according to JSWED's Memory
screen, so I decided to relocate the RoomNo patch at the end of the
teleporter-list (only safe because I'm not going to add more
teleporters myself):
xHxL = #EA50 (in Bank 0)
yHyL = #EA53 (in Bank 0)
Thus the Hex-editor section above is instantiated as follows (anyone
who is serious about learning this stuff should try instantiating it
themselves, then check it against my instantiation below):
>>>8A47: 53 EA
EA50: 30 30 30 CD 80 96 3A 20
EA58: 84 0E 30 DD 21 50 EA D6
EA60: 64 38 03 0C 18 F9 C6 64
EA68: DD 71 00 0E 30 D6 0A 38
EA70: 03 0C 18 F9 C6 3A DD 71
EA78: 01 DD 77 02 0E 03 11 FD
EA80: 50 C3 80 96
9AFD: 44 44 44
<<<
QED.
--
Dr. Andrew Broad
http://geocities.com/andrewbroad/
http://geocities.com/andrewbroad/spectrum/
http://geocities.com/andrewbroad/spectrum/willy/
