-
Posts
5,112 -
Joined
-
Last visited
Everything posted by IRF
-
It isn't the #52 at #86D6 which you need to change. That just determines the height of the air supply pixel-rows within the chosen character-row. I think you would need to do the following: At #86DA: replace the #24 with #44 At #86DC: replace the #25 with #45 At #86E2: replace the #24 with #44 At #8A4C: replace the #24 with #44 Then in each individual cavern definition, add #20 to the relevant Offset Byte (#xBC, where x = 2,6,A or E). e.g. For the Central Cavern, edit #B2BC to replace the value #3F with #5F. ****** Warning: That might do odd things to the sound effect when the remaining air supply is counted down after Willy has completed a cavern! If you wanted to preserve the sound effect, then I suspect you would have to insert a SUB A, #20 immediately before the CPL instruction at #90D1. Fortunately, I have just identified two inefficiencies in the vicinity of that part of Matthew's code, which would free up the necessary two bytes to allow you to insert the SUB A, #20 with minimal code-shuffling: - At #90D4, there is a two-byte RLC A command which could be replaced with a single-byte RLCA; - At #90D7, there is a two-byte LD A, #00 command which could be replaced with a single-byte XOR A. (Don't forget to adjust the operand of the relative jump at #90E6 accordingly.) ****** Er, good luck!!!
-
Having now investigated this, I am extremely pleased to report that I was correct, both in my diagnosis that there is a problem (a bug in the Geoff Mode game engine), and with my prescribed solution (which fixes the bug with a single POKE)!
-
A few more errors/inefficiencies in the Geoff Mode disassembly (for my own future reference, if nothing else): https://web.archive.org/web/20030701143111/http://www.cix.co.uk/~morven/jsw/geoff_dis.html The opcodes in bold text above are erroneous, it should read 'C3 BC 8D'. Actually, it could read 'C3 92 8B', and jump to an identical bit of code which sits at the end of another subroutine (see below). Also, the RET command at #916C above is superfluous, as the preceding jump goes to code which ends in a RET back to the Main Loop. As I mentioned above, the minor sprite patch in italics is superfluous if the jump from #9169 is directed to #8B92 (see bold highlight below). The 'necessary context' which Geoff referred to above, is to distinguish between the 'NW-SE' and 'NE-SW' types of diagonal guardians. Contrary to the Geoff Mode documentation, Bit 4 of Byte 1 of a diagonal guardian's Definition Bytes is not flipped when non-wraparound guardians change direction. The references to various types of diagonal guardian in the above is messy. "double dy" in italics above should refer to a type 3 diagonal guardian, for example. The subroutine at #8DB1 should be introduced as 'Used for diagonal and wraparound sprites': The Geoff Mode documentation implies that, as in Matthew Mode, Bit 7 of Guardian Definition Byte 0 keeps track of the current direction of horizontal (and diagonal) guardians. However, I'm not sure that it does in Geoff Mode. The direction of horizontal guardians is tracked via Byte 4 (which is a signed byte and determines the velocity) - as is the case for vertical guardians in both game engines. At #9193-#919C, both Byte 4 and Bit 7 of Byte 0 are toggled - via a NEG command and an XOR #80 gate respectively - but I believe that the latter bit of code (i.e. #9199-#919C, in italics below) may be superfluous: EDIT: Actually, whilst Bit 7 of Byte 0 isn't used to keep track of horizontal guardians in the 'Move the Guardians' routine, it is used by the 'Draw the guardians' routine, in order to determine which set of sprite-frames to use for bidirectional sprites. No errors here, but I thought it would be worth emphasising a particular difference between Geoff and Matthew Modes, which Geoff doesn't explicitly mention in his notes. Namely that vertical guardians cycle forwards through their sprite-frames as they descend the screen, but backwards through their sprite-frames as they ascend: In contrast, Matthew Mode vertical guardians always cycle forwards through their sprite-frames, regardless of the status of their vertical trajectory. (So, to give a real example, the foliage on the Plant Pots in 'Jet Set Mini' are always growing outwards, before suddenly being 'pruned back' and starting again; if they were present in a Geoff Mode game, then the leaves would reverse direction and start 'shrinking' as the guardian started to move up the screen.) ****** Finally, I have a sneaking suspicion, from studying the code, that if a type 2 wraparound diagonal guardian (i.e. one that traverses at 14 degrees from the horizontal) has an odd number of increments defined in Byte 7, then it might fall 'out of phase' by one vertical increment, each time it wraps around. That could cause the guardian to 'stray from the path' - potentially leading to problems like the guardian colliding with elements of a room's layout. I have yet experimented to test this out, but if I am right, then it might be easily resolved by swapping the RET Z at #8B7D for a RET NZ. i.e. so that type 2 diagonal guardians are only vertically adjusted when the counter at Byte 6 holds an even value (instead of only being vertically adjusted for odd values of Byte 6, as is currently the case in the Geoff Mode game engine).
-
Hi Mickey, Have you finalised this project? If not, there are (arguably) a couple of Water cells missing underneath the ramps in 'West Wing Roof' (at ground floor level, below and to the right of the ramp) and 'Back Stairway' (one of the water cells of the second platform from the bottom, again directly below the ramp). In the latter case, the contrast is quite striking with the way in which the ramp interacts with the bottom platform, and the other two platforms higher up the screen. If you did want to 'restore' them in your 'AMI' project, but can't see what I mean, then I'll try and do a couple of screenshots to illustrate where I'm talking about. :)
-
I've just come to realise why a certain aspect of the MM/JSW code is the way it is. The convention when copying data from one place to another is to use HL (or the indexed equivalents, IX or IY) to point at the data that you're copying, and DE as the addresses to which the values are copied. (DE presumably signifying 'DEstination'?) That's how LDIR loops operate, and also how the 'Print a message' and 'Print a single character' routines work. But in the case of the 'Draw a sprite' routine at #9456, it is the other way round - DE points at the sprite graphic data, whilst the address to which to draw each byte, in turn, is defined via HL. The reason for this is that the test for pixel collisions uses an AND (HL) instruction. Furthermore, if no collision occurs, then the process of merging the sprite being drawn with the existing background graphic is done via an OR (HL) instruction. There are no such equivalent Z80 commands involving the DE register-pair. i.e. there are no AND (DE) or OR (DE) commands in the Z80 instruction set. So that is why the DE and HL register-pairs are used in the way that they are by the 'Draw a sprite' routine.
-
The three byte command at #959A is unnecessary; if the program arrives there, then A already holds the number of the current room from #8420, having been assigned it by the identical command at #9534.
-
Geoff Mode's 'Move the guardians' routine actually takes the above approach further, in order to update the animation frame of a guardian, and the x-coordinate of horizontal/diagonal guardians. In these circumstances, part of a guardian definition byte needs to be updated without altering the rest of the byte. That's easy for a single flag - just toggle the relevant bit (e.g. Bit 7 of Byte 0 which specifies the direction - use XOR 80). However, when a variable uses more than a single bit, it gets more complicated. One example would be the two bits that determine a guardian's current frame of animation, which sits within the same definition byte (Byte 0) as the guardian type (lowest bits) as well as its direction flag. Another example is a guardian's x-coordinate, which shares a definition byte (Byte 2) with the Base sprite. The more familiar approach (to me at least) is to: - load the byte that you're updating into the A register, - do an AND for the bits you don't want to alter, - save the output into another variable such as C, - load the value you want for the bits you do want to update to A, - do an OR C to merge the two elements, - and then reload the output of that back into the definition byte. Geoff used the sequence XOR - AND - XOR, which I think is more efficient(?), to update only the parts of a byte that need updating, and leave the rest of the byte unchanged. The operand of both XOR commands being the guardian definition byte under consideration, whilst the operand of the AND command selects only the bits that you want to update. e.g. to update a guardian's x-coordinate, he uses: [A register holds the new value of the guardian's x-coordinate, in Bits 0-4; whilst Bits 5-7 are initially blank] XOR (IX+$02) AND #1F for updating Bits 0-4 XOR (IX+$02) [Then load A back into (IX+$02)] The end result is that the x-coordinate of the guardian is updated, but its Base Sprite is unaltered.
-
Another comment from Geoff's JSW webpage: https://web.archive.org/web/20030818082654/http://www.cix.co.uk:80/~morven/jsw/geoffmode.html I think this must refer to a rope where the lowest three Bits of the guardian definition Byte 0 are set to 111 (07), rather than the usual 011 (03):
-
I can't see any real reason why the 'Print the Remaining Lives' code in JSW is placed in a subroutine, and then CALLed from the start of the Main Loop. In Manic Miner, it forms the initial part of the Main Loop. Ditto with JSW Geoff Mode. If you remove the JP at #8988, the RET at #89AC and the CALL at #89AD, and then replace the RET Z at #8992 with a JR Z to the start of the rest of the Main Loop at #89B0, then you can achieve a net saving of six bytes. (Or five bytes if you've already implemented the one-byte optimisation of replacing the JP at #8988 with a JR.)
-
In response to a couple of Geoff Eddy's comments in his own game engine disassembly: Part of Geoff's (somewhat different) arrow-drawing routine: In relation to the first entry in bold (#925C), I would agree that this command is unnecessary. In relation to the second entry in bold (#9264-67), the reason why it was necessary to initially define H as #2E and then apply a RL H command, is because the Carry Flag is rotated into the lowest bit of H in the process. The Carry Flag will have been set, by the preceding SLA A at #8262, if (and only if) an arrow occupies the lower half of the playing area. Simply defining H as #5C would mean that all arrows could only occupy the upper half of the playing area, even if the game designer has specified a y-coordinate in the lower half. Geoff was obviously clever enough to recognise this when he first devised the routine, but must have forgotten his reasoning when he went back to disassemble his own work (presumably some time later)! ****** A comment in Geoff's Room Setup routine: I would dispute the comment in bold - Matthew didn't need to include a command which writes a terminating byte #FF to the address #8140, because that address already holds that value in the original game file (and it is never altered). So the code occupying #8949-4B in Geoff Mode would appear to be superfluous. Furthermore, the summary of the room buffers at the start of the Geoff Mode disassembly: ...seems to suggest that a room may hold up to nine guardians, rather than eight. It should probably read:
-
By that, do you mean that as soon as Willy enters a room with a rope, he is automatically teleported to the room above?
-
:thumbsup:
-
That's consistent with the large flashing block letters on the Title Screen, which Matthew also created, and which has a space (but no hyphen) between 'Jet' and 'Set'. It was also two separate words (unhyphenated) on the original cassette inlay (in graffiti-spray writing, representing Willy's trashed house!) By the way, when you mention minor layout changes to the new rooms, I'm wondering if you have followed through with an idea you mooted in the readme, of having two ropes that allow access up to the Tree House...?
-
I've just spotted another discrepancy in Geoff Eddy's PV disassembly. Here it is, for reference: In the third Geoff Mode game, Willy Takes a Trip, Room 8 (The Garden of Forbidden Fruits), there is a CALL to #85A8 (to move HL up a row). https://web.archive.org/web/20080511161939/http://www.cix.co.uk/~morven/jsw/patches.html But in the Geoff Mode game engine disassembly, the corresponding subroutine is located at #8BB2. https://web.archive.org/web/20030701143111/http://www.cix.co.uk/~morven/jsw/geoff_dis.html ****** Also, the 'fuzz border effect' subroutine is CALLed by some of the PVs in Geoff's earlier games from #876B, rather than from #8BEF where the 'fuzz' is located in Geoff Mode 2 (i.e. in ZX Willy the Bug Slayer).
-
Did you remove the hyphen from 'Jet-Set' in the scrolly (with a space character there instead)? (I'm being picky now!) By the way, I've just brought the Temporary Topic that you created back from the grave, in case it's of assistance... (I'm not sure whether I've revived it for another month, or permanently?)
-
By way of an explanation for the above: Earlier on, I think I established that the 'As Manufacturer Intended' game file was built upon a snapshot file - this conclusion was based on the fact that some of the addresses which store the variables that are used in the game (#85CB-#85E4), hold non-default (i.e. non-zero) values when you examine the game file's code in a hex editor. (Another example which I've just noticed - the range of variable addresses #8000-#813F [representing the buffer for the current room and its guardians] don't all hold zero values in 'AMI', as they do in an original JSW game file.) Anyway, one of those game variables is the WRITETYPER key counter at #85E3. Its default value (as per the SkoolKit disassembly) is 00, but in the 'AMI' game file, it holds a value of 01. To recap what you probably already know, the way that the WRITETYPER counter works, is that it is only updated when Willy is in First Landing and he is located on the floor of that room. It is incremented each time a correct letter key is pressed, but is reset to zero if an incorrect number key is pressed (see 'Main Loop(2)' in the disassembly). Once #85E3 reaches a value of 10 (by pressing each of the letters WRITETYPER in the correct order), then the Cheat Mode is activated. The value of 01 at #85E3 in 'AMI' suggests that the 'W' key was pressed whilst Willy was on the bottom of First Landing, but that this wasn't then followed by 'R', etc (which would have incremented the variable further). And the only way that I can think of in which the variable avoided being reset to zero by any key other than 'R' being pressed, is because Willy was then moved out of the zone (bottom level of First Landing) in which keypresses can influence the value of #85E3. Of course, 'W' is one of the Move Right keys, so if it was pressed for that purpose whilst Willy happened to be walking along the bottom of First Landing, then that would explain why #85E3 was incremented to 01. Willy presumably then proceeded rightwards because 'W' was continually pressed - either up the First Landing ramp (so that he was no longer at the correct y-coordinate for the WRITETYPER activation code), or else he walked rightwards under the ramp and then dropped through the bottom exit into To the Kitchens...Main Stairway (the wrong room for the check for WRITETYPER keys) - prior to the snapshot file being created. From this analysis, I deduced that Metalmickey (who presumably created the snapshot file upon which 'AMI' is based) is a left-handed player, who uses 'Q' and 'W' for Left and Right movement respectively. (In contrast, a right-handed 'O' and 'P' player would not cause the WRITETYPER variable to be 'accidentally' incremented as they passed along the bottom level of First Landing.) So to summarise, by studying the game code I was able to - correctly as it turned out - deduce that Mickey is a left-handed Willy player. Elementary, my dear Watson!
-
He has added a comment in the Manic Miner Trivia section, pointing out that adding the 'missing' conveyor to Amoebatrons' Revenge makes the cavern uncompletable. (Unless you reverse the polarity of course, but sadly he hasn't provided the POKE for that.) http://skoolkit.ca/disassemblies/manic_miner/reference/facts.html#unusedConveyors
-
Danny, hopefully you will now appreciate that the above wasn't merely a throwaway comment...
-
I never got round to explaining my thinking on the above - I don't have time right now but this is a reminder to myself to do it later...
-
This is now mentioned in the latest update of SkoolKid's JSW disassembly: http://skoolkit.ca/disassemblies/jet_set_willy/reference/bugs.html#missedNote
-
[File] JetSet Willy 2 (Amstrad) Cheat versions
IRF replied to Spider's topic in Download Discussions
Thanks Andy! Cheat Mode 2 sounds interesting! -
Shouldn't the operand in bold above actually be FC, to point back to #8D56? Although as it happens, the value of FB as stated above just jumps back to a '00' operand byte that sits immediately prior to the correct destination address. This is treated as a NOP, and so has no ill effect other than to (imperceptibly) slow down the routine. I believe that they are similar solutions, but Richard optimised the patch so as to fit within his self-imposed limit of a maximum of ten POKES per 'fix'. In order to achieve this, he identified and recycled an existing relative jump of the same length as the one I referred to above (i.e. '20 FC') at #FF28 within the unused TRS-DOS code at the end of the game file. (In fact, it was studying Richard's solution, in conjunction with his disassembly, which led me to spot Jonathan's apparent error.)
-
One more tiny suggestion for a tweak to the game file - in the scrolling message on the Title Screen, the use of the hyphen in the word 'Jet-Set' is inconsistent with the lettering on the Title Screen, and general usage. I believe that for consistency, it would be best to use 'Jet Set' (with a space character replacing the hyphen). Incidentally Andy, I would make the same recommendation for the banner at the top of this website (in that case, 'Jet Set' instead of 'JetSet'), although that's probably too much of a faff to change, so it's probably not worth worrying about too much. :)
-
I've just watched the end sequence after completing the game (I cheated and did POKE 34270, 255 so I only had to collect the Bathroom tap). Very nice effect after the clock reaches midnight! Just one little suggestion, if you're open to a final tweak - you could colour the top half of the 'victim' Cyan in this instance, to match their previous appearance? (I hope that doesn't provide too much of a spoiler?). It's no biggie though. Also, the Screen Flash effect looks good when it kicks in as Willy collects the last item. I wonder if it would be worth mentioning this in the readme, in a cryptic way? Something along the lines of "a special effect that is implemented via a bit of code which Matthew Smith devised for Manic Miner, and which remained in place (still functioning but unused) in the original JSW code".
-
If the two chunks of code, that print the current time (#8A31-#8A3C) and the number of items (#8A3D-#8A48) respectively, are swapped around, then IX will only need to be defined once at this point in the Main Loop (saving four bytes). Also, D will only have to be defined once for both functions, and so the second instance of LD DE, #0000 can be replaced with a LD E, #00 (saving another single byte). (N.B. The above efficiency would mean that if a game file has the 'Print the Time' code placed after the 'Update the Time' code - as is the case in Willy's New Mansion SE in order to make sure that the clock's colour is changed at precisely the right moment - then it would also need to have the 'Print the Number of Items Collected' code placed after the 'Update the Clock' code.)