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: 7121
Author: ian.rushforth
Date: 28/07/2017
Subject: Re: two other random points
SOA wrote:
> So, I was playing UMM, and I had a bizarre moment. In "Cold Storage", at the moment when the container > fell, there was a sudden glitch whereby I saw a rope appear in its place. This lasted only a split second > before Willy was transported, via the magic of malfunction, to that "welcome" room near the very beginning of > the game. Only embedded in the floor, naturally. I have been unable to replicate the error, and in any case > I've since resaved my save file further into the game. Still, a curious moment
I have had a similar experience in the room 'Eugene Lair' of UMM!
Preamble: it occurred when I was trying to implement a fix for the bug which Igor described in Yahoo message no 5527 https://groups.yahoo.com/neo/groups/manicminerandjetsetwilly/conversations/messages/5527 The bug turns the Skylabs into Droplets; because a Droplet was encountered earlier in the game, the Droplets Patch will have overwritten the value of #FF61 with #00 instead of #08. My 'quick and dirty' solution for this bug is to change all Skylabs in the game into Droplets (change the value of Byte 0 from #08 to #78), and then assign a value of 8 to the upper nybble of Byte 1 for each Skylab in the game.
This has the effect of restoring the value #08 to #FF61 - the horizontal displacement of the Skylabs - whenever a Skylab is encountered, whilst allowing the Droplet to continue to function with a horizontal displacement of 0.
(Basically, I have inverted the logic of these guardian types: instead of thinking of Droplets as Skylabs which don't have a horizontal displacement, we should think of Skylabs as Droplets which DO have a horizontal displacement!)
However, implementing the above sometimes causes the bug described above by SOA to occur in the room 'Eugene Lair'. It doesn't seem to occur during Willy's first life; only if he stands still and waits for the 'exploding lava' Skylabs to kill him, and then stands around during his second life until the central 'DIE MORTAL' lettering has disappeared. (The lettering is comprised of guardians above Willy's head which disappear via a 'Drawing Stopper' activated by a Trigger, which in itself is activated, after a short delay, by an invisible Eugene! Also, Willy is protected from jumping up and hitting the lettering by an overhead Earth cell, which is turned to an Air cell once the lettering has gone by an invisible Opening Wall. It's an ingeniously assembled room, like many other in the game! By the way, I strongly recommend you try playing this room 'as manufacturer intended' by implementing the solution - notwithstanding the occasional glitch I'm reporting here - as it's an awesome challenge; nowhere is safe!!) Anyway, I digress - on Willy's second life, once the 'DIE MORTAL' lettering has disappeared, the multicoloured horizontal 'worm' guardian transmogrifies into a rope on the right-hand side of the screen for a single time-frame, before pixel-colliding with the 'Final Barrier' bitmap and teleporting Willy to the room above (Room 0: 'Living Quarters'). In fact, if you clear some pixels from the 'Final Barrier' bitmap, and the Willy-like static white guardian* in the vicinity, and reload the game, then on his second life Willy is teleported onto the rope and jigs about in a very quirky manner! (*If you don't clear this guardian, Willy is teleported into a fatal collision with it!)
So, all very strange. I saved some snapshots and looked at the definitions in the room buffer of the guardians which follow on after the Droplet-Skylabs:
Immediately after the Droplet-Skylab there is a black (invisible) vertical guardian, whose purpose seems to be disguise one of the Skylabs when it is located at the far left-hand side of the room (the 'exploding lava' effect emerges from the horizontal pairs of cyan Crumbly cells; at the left-hand side of the room, there are some red Earth cell 'bricks' located at the equivalent position, so I guess Igor used an invisible vertical guardian to disguise the emergence of a Skylab there for aesthetic purposes). Then after the black invisible vertical guardian comes the horizontal multicolour 'worm'.
Looking at the buffer definitions before the bug takes place:
Invisible vertical (#82B7-#82BE): 12 00 01 C0 00 99 70 A0 Colourful worm (#82BF-#82C6): 09 D3 05 A0 FC 81 05 19
Immediately after the bug has kicked in:
Invisible vertical (#82B7-#82BE): 3A 00 01 C0 00 99 D3 80 Colourful worm (#82BF-#82C6): B3 82 DA D2 44 40 44 EC
So you can see that the 'new' bug has corrupted the last two bytes of the guardian which immediately follows on from the Droplet-Skylabs (the variation in the value of the vertical's Byte 0 is a normal process during runtime, reflecting the incrementation of its current animation-frame). The last two bytes here define the vertical bounds, which is harmless in this case as the guardian has a vertical speed of 00.
And the 'new' bug has also corrupted all eight bytes of the horizontal multicolour 'worm'. In particular, note the lower bybble of Byte 0 now holds a value of 3, representing a rope (albeit that it is an invalid rope in a number of ways, arising from the values of the subsequent definition bytes).
I did a bit more experimentation by transposing the positions of the invisible vertical and multicolour horizontal guardians in the room's guardian instance list, That had the effect that the horizontal guardian's last two definition bytes were corrupted, as before, except that the effect of this was no longer harmless - it moved faster as a result of Bit 7 of Byte 7 being set, which you would expect in JSW64, and it carried on moving rightwards until it crashed into something (killing Willy, even though he was out of reach, hanging on the weird rope by that point), as a result of the horizontal's rightmost bound (Bits 0-4 of Byte 0) being set to 0. However, the fact that it was moving right and not left means that it must have turned round prior to the corruption. (The guardian starts off at the leftmost extent of its bound; it doesn't start moving until a 'Movement Stopper' has been turned off by another Trigger! So I would suggest that the corruption, if it is arising from the Droplet-Skylabs, is caused by the first attempt to draw the Droplet-Skylabs, not the first attempt to move the Droplet-Skylabs - since the Droplet-Skylabs precede the two corrupted guardians, and the 'Move the guardians' routine is enacted before the 'Draw the guardians' routine during each pass through the Main Loop.)
Swapping the relative position of the two corrupted guardians also meant that the vertical guardian is the one which is turned into a weird rope (I confirmed this by assigning it a green INK colour and a few infilled pixels in its bitmap; those static pixels were initially drawn at the left-hand side of the screen [incidentally confirming the position of the 'disguised' Skylab, via a burst of green 'lava'!], but those green pixels just at the point when Willy was teleported onto the rope [I still had the path of the rope cleared at this point, to prevent the instantaneous teleportation to the room above]).
I also tried swapping the relative positions of the two Droplet-Skylabs in the room's guardian instance list, and this seemed to stop the 'new' bug (the subsequent guardian corruption) from taking place! Also, editing the vertical speed of the Droplet-Skylabs seemed to stop the corruption. But I'm not sure whether that variable in itself determines the corruption, or whether it just changes the timing of the point of collision of Willy's first life with one of the Droplet-Skylabs, and the corruption only occurs at certain times for some reason?
It's all rather bizarre, and I can't get to the bottom of why the corruption of those two guardians is taking place!!
I also observed that if I sacrificed the first life early by jumping into one of the fire guardians, waited without moving for a Skylab to take the second life, then on the third life, the corruption/weird rope thing didn't happen. So I even tried changing the initial number of lives in the game (from 2 to 3), to see whether the corruption only occurs when Willy has an odd number of lives on the status bar! But that seemed to stop the corruption altogether!
So I reverted back to two initial lives, and confirmed that the corruption started taking place again (on the second life only, as previously). I then noticed that the corruption doesn't take place if the in-game music is switched off! Curiouser and curiouser, said Alice... The only possible connection I could think of with the music, is that the in-game music routine in JSw64 (and JSW128) involves 'paging' in and out of a different bank of memory, with interrupts and all that stuff involved (something which I haven't yet fully got my head around). But I wondered if it might be something to do with the emulator accessing different banks of memory?
I then remembered a very minor error in John Elliott's amendments to the in-game music routine in JSW64 (and JSW128). Part of John's partial diassembly of the JSW128 changes (http://www.seasip.info/Jsw/jswdiffs.html) is reproduced below. The conditional relative jump at #8B65 is supposed to jump to #8B70, rather than #8B6F. So I changed the operand value at #8B66, from '08' to '09', and this seemed to magically cure the guardian corruption problem altogether! But I have no idea why?!?
One final observation - the guardian corruption bug only took place, in a 'fresh' file, when I loaded it up into the online emulator (QAOP) which I regularly use. When the tap file was loaded up into SPIN, the corruption didn't happen. However, it can be seen in SPIN if I save a .z80 snapshot in the online emulator, just after the corruption has occurred, and then load that up into SPIN. (That's how I managed to analyse the values of the guardian definitions in the buffer, via SPIN's debugger tool.)
Does anyone have any thoughts? Sorry for the long post, but I have given as much detail as I could, in the hope that someone more knowledgeable than me might be able to get to the bottom of it!?!
RLCA R8B55: XOR A SUB 1Ch LD (B85E0),A NEG LD A,(B85E1) ADD A,(HL) LD D,A INC A LD A,(80DEh) LD (B85E1),A LD E,D LD BC,3 LD A,(B85E2) ;Stop tune? R8B63: OUT (0FEh),A AND 2 DEC E JR Z,R8B6F JR NZ,R8B6B LD A,8 LD E,D XOR 18h LD (B85FB),A ;Set stop flag R8B6B: DJNZ R8B63 NOP DEC C NOP JR NZ,R8B63 NOP
