-
Posts
5,112 -
Joined
-
Last visited
Everything posted by IRF
-
Glitch variant 3 attached. Now Willy can be killed by the right-most Crab (Fire cell), even though it's buried two cell-rows below Willy, if the previous game was abandoned mid-jump (leaving the value of the Jumping Animation Counter at a value that causes part of the Move Willy code to be bypassed). Bug Fix Glitch 3.rzx
-
I've just noticed that there's a slight glitch with the fix. If the game is ended abruptly while Willy is in mid-jump (by pressing SHIFT+SPACE), then sometimes when the next game is restarted, Willy cannot walk rightwards across a cell boundary. He can walk leftwards across a cell boundary though, until he's tried and failed to walk right, at which point he gets stuck within the two cell columns that he is occupying, as if invisible Earth cells on either side were keeping him there. I observed the above when he was stood on the right-hand side of The Beach, with a 'deep' block of Earth cells beneath him. However, if there is a row of Air cells underneath the surface he is standing on (i.e. if he's on a platform that is only one row deep, such as the left-hand platform in The Beach), then he falls through the floor when he tries to walk rightwards along the platform across a cell boundary! (That doesn't happen if he walks leftwards though, but if he then turns round and walks right then it happens as soon as he tries to proceed from Animation Frame 3 to Animation Frame 0.) Finally, during this period of 'misbehaviour' (from the point at which he is first stopped in his tracks or briefly whilst he's falling through the floor), his head takes on the colour of the Air Ink (so it's normally invisible except in a non-Rope room, where Air Paper and Air Ink colours are mis-matched). It's easy to bring this strange behaviour to an end though - just hit the jump key! When the phenomenon occurs, it seems as though his colour attributes are located one cell-row beneath where his sprite is drawn. And his physical presence must be one cell-row below his sprite too, hence he is stopped from proceeding by the blocks, or falls through a single-row platform. I think that it only happens if the game is abandoned at a point when the Jumping Animation Counter has reached one of the values that the new code checks for (12, 15 or 17; #0C, #0F or #11 in hex), in order to decide whether to allow Willy to move left or right past the cell boundary to be caught by a 'ledge'. Whenever Willy jumps, the command at #8F97 resets the Jumping Animation Counter to zero, hence jumping brings the behaviour to an end. This also means that if we're confident that the strange behaviour only occurs when re-starting the game (after the previous game has been abandoned mid-jump), then the simple fix would be to initialise the Jumping Animation Counter (#85D5) to zero at the start of every game. However, I'm concerned that there may be circumstances during a game when the Jumping Animation Counter might be left at a value that triggers the strange behaviour. e.g. when Willy jumps onto (or off) a ramp to (or from) an 'intermediate' (i.e. not cell-row aligned) y-position? Or perhaps when Willy jumps off a rope, or he jumps onto a rope and climbs up to emerge in the the next room (without performing another jump, which would reset the jump counter to zero)? Also, I wonder if it might be occurring because I've made some error in the way in which I've implemented the fix, so perhaps someone could 'mark my homework', so to speak, especially with regards to whether I've moved the code about correctly (i.e. are relative jumps still in order, etc)? It's strange that it's only triggered (at least initially) when Willy walks right, not left. That in particular makes me wonder whether I've made an error - because the fix is notionally the same in both directions - although having said that, there is an inherent asymmetry about how the coordinates are assigned in the Move Willy routine, with (x,y) being the coordinate of the top-left cell that Willy is occupying. EDIT: I've created a couple of .rzx files (attached) which illustrate the two variations of the glitch. Bug Fix Glitch 1.rzx Bug Fix Glitch 2.rzx
-
I'll try and do a detailed description at some point, but in a nutshell the new code is inserted at #9700, called up from the 'Move Willy (3)' routine, and involves checking the 'Jumping Animation Counter' variable at #85D5, and comparing it against various values (which correspond with instances during a jump when Willy is descending, and is one increment away from being cell-row-aligned). Then I inserted a check for Earth cells at head-height when Willy is moving left (analogous to the existing one in the code for Earth cells at head-height when he's moving right), to restore the symmetry to his movement. I also relocated the 'Kill Willy' routine from #90B6 to #96F4, which I initially did to find space to be able to insert a 'lesser' fix within the Move Willy (3) routine. However, in the end I had to put the new code elsewhere and jump to it anyway, so in hindsight I should have left 'Kill Willy' where it is. The new code is far from efficient as there was plenty of space at #9700 to insert it (so for example there are lots of absolute jumps rather than relative ones). Thus there is plenty of scope for you to put your optimisation skills to good use!
-
Sort of. Unlike previous fixes, this patch doesn't render The Wine Cellar impossible. Obviously the single item in the attached is impossible to collect, but that's because I've inserted a head-height Earth cell, precisely to demonstrate the point that I've fixed the bug which previously allowed Willy to walk leftwards through an Earth cell at head height. However, you can see that it is possible to jump between the Earth cell platforms! i.e. onto ledges that are situated underneath Earth cells. If you climb up the Water ladder that I've inserted to the right of Willy's starting point, in order to access the next level up, then you'll also see that this is a symmetrical fix. I've turned the right-hand Water cell platforms into Earth cells, but Willy can jump across safely whereas he wasn't able to before. For example, he can now access the exit from 'Emergency Generator' to 'Priest's Hole'! (Not to any avail though; he still can't climb down the East Wall.) I've also tested jumping over the Barrel Guardian in 'Ballroom East', and crossing 'The Banyan Tree' in both directions (very tricky but doable, except in The Nightmare Edition because of a strategically-placed Fire cell!), and even jumping over the Bad Apple Guardian in 'At the Foot of the MegaTree' in The Nightmare Edition. All fine! With the fix, Willy can also jump into cavities that are two cell-rows high and sited one or two cell-rows above his starting position. I've created a 'ladder' at the top of the right-hand chimney stack in Emergency Generator for you to test this out! (Navigate the starting position there to try it.) Jumping into a cavity that is one cell-row high is impossible though, as it should be (previously Willy could jump leftwards into such a cavity due to the bug). It is also impossible for Willy to jump into a cavity that is two cell-rows high that is sited at a height lower than his starting position (again, this is how it should be; once he has dropped to a position that is lower than the start of his jump, then he is no longer jumping but falling, and has lost all horizontal momentum). The quirkophiles amongst you will be pleased to know that other 'quirky features' such as jumping into Earth cells at leg-height, jumping through Innocent-Looking Blocks at head-height, and jumping through a 'standonable' cell that is adjacent to a Fire cell, are all still in operation! There are a few random blocks scattered around Emergency Gen which are handy for illustrating these. EDIT: I would also add that it fixes the bug whereby Willy can jump leftwards through an overhead Earth cell, and also the bug that allows him to walk up a ramp leftwards through an Earth cell at head-height. However, it doesn't stop him from walking (in either direction) up a ramp through an Earth cell that is located above his head. (There is no check in the code for Earth cells above Willy's head when he's walking up ramps. Or for that matter, Earth cells in the row beneath Willy - hence he can walk into the Earth cell at the bottom of the ramp in On Top of the House.)
-
Here's a surprise for you all. Check out the attached file. The starting point is The Wine Cellar. Try to collect the item! UPDATE: I noticed a minor 'glitch' in my first attempt at the bug fix, so I've deleted the file that was attached to this post. Please scroll down to post #8 in this thread, to get the updated file, in which I've sorted the problem! (N.B. The starting point in the updated file is The Beach, but it's not too far to wander to The Wine Cellar to test it out.) FURTHER UPDATE: See also the discussion in post #12 of this thread (on the next page to this) - there's a further imperfection that requires fixing. FINAL UPDATE: The code changes for the final version of this patch are documented later on in this thread: http://jswmm.co.uk/topic/196-dont-mind-your-head-while-walking-left-bug-fix-for-jsw/page-4?do=findComment&comment=5588 The file now attached here is a copy of original JSW with the patch inserted as per the code changes in the above link. Earth cell symmetry restored.TAP
-
Thanks Andy, I'll have a play later. I wonder if I increase the value of 35682 (#8B62) from zero, to anything up to #FF, can I increase the delay further by a factor of up to 256(!)?
-
Do you know a command that would have the effect of causing such a delay? EDIT: As it happens, over in a PM I've just been discussing the 'DJNZ' command. It works on the 'B' register. I'm now wondering if that was inserted after the register 'B' had been set to a high value (such as #FF), with the operand of the DJNZ set to itself, then maybe it could cause quite a delay? e.g. at 35343, insert 'LD B, #FF. Then at 35345, 'DJNZ 35345'. The command at 35345 would then take the value of B (which would be initialised to #FF each time the program passes through the main loop) and decrement it by one, then jump back to itself and keep decrementing B until it reached a value of zero, before proceeding with the rest of the program?
-
Question: Is there a way of seriously slowing down the JSW game engine, so that one can study the exact pixel placement of Willy at each stage during a jump? i.e. so the screen image is effectively still for a few seconds during every frame of animation? I was thinking some sort of command could be placed in the Main Loop which delays things? Placing him in a field of Water cells whose pixels consist of a grid of horizontal and vertical lines will also help with this task.
-
[Pedantry alert!] I've just noticed an error (I think) in the disassembly. The entry at #8820-8827 is described as "Copy the attribute bytes for the top two-thirds of the title screen from 9800 to the attribute file". In fact, the LD BC command at #8823 copies the attribute bytes for the entire title screen from #9800 AND #9A00, as determined by the operand #0300. (So it sets the attributes for the bottom third of the title screen, as well as for the playing area.)
-
If you don't mind having a shorter Title Screen tune - or none at all - then up to 99 bytes could be available for other purposes where the Title Screen tune is currently located in the code (#85FB to #865D). The value 'FF' at #865E terminates the playing of the music on the title screen (and progresses the program to the screeching noise/scrolling message), so if you are shortening the music, then the 'FF' should be located to just after the shortened tune code (or to #85FB in the case of having no Title Screen tune).
-
Danny, I was helped by advice from Stuart which I found in an old message of his: "So here it is again, the fix for the block-graphics bug, only this time I have pasted my fix into SkoolKid
-
Danny, Just to let you know, I have succeeded in inserting the Main Patch Vector into the Main Loop. However, this was more of an academic exercise - as previously discussed, it is more byte-intensive to rely on direct jumps back from each room-specific patch vector, rather than call commands. So, unlike the Cell Graphics Bug Fix (which is best applied directly into its host routine, if that can be achieved by consolidation), there is a sound 'bytes management' reason why the Main Patch Vector should be applied as a separate sub-routine.
-
For instance, there is a routine in JSW described in the SkoolKit dissasembly as 'Draw the rope, arrows and guardians in the current room'. But as well as being bookended by chunks of code that set up the drawing loop, there are three significant subsections that deal with, in turn: (1) horizontal and vertical guardians; (2) arrows; (3) ropes. I have been referring loosely to e.g. the 'draw an arrows subroutine'. If that isn't technically a 'subroutine' (because it isn't called up from elsewhere), then what should I be calling it?
-
Thank you for that clarification Andrew. Is there a word or phrase that we should be using, to avoid confusion, when referring to a subsection of code within a particular routine (i.e. not a 'subroutine' called up from elsewhere)?
-
Possibly a rope's data is overwriting it? Or do you have the 'adjacent ropes patch' in place?
-
To be clear, the 'border special effects' aren't actually present in original JSW, and the program already retains the border colour for the room in question.
-
Thanks for the credit, Danny! Just to be pedantic, the word 'end' is missing there, I think?
-
Could you perhaps squeeze a few more bytes out of the code so that EVERY room has one? (e.g. the spare 6 bytes in G127's data, if you haven't already used them?)
-
I guess that the need to 'return' is implicit in the above sentence, but it would be good to make it explicit in your guide. EDIT: Is the definition of a 'sub-routine' a section of code that is arrived at by being called up from elsewhere, and which therefore requires, by its very definition, to be terminated with a 'return'? I've been using the term to refer to certain parts (i.e. subsections) within a routine which don't need to be 'called up' as such. (For example, the 'Play a note of the in-game music' subsection of code within the Main Loop.) But that might have been sloppy use of language on my part? (It wouldn't be the first time!)
-
Danny, I believe that there is one aspect which you omitted to mention in your otherwise comprehensive (and much-appreciated) guide to inserting Patch Vectors. Namely, the fact that each Patch Vector should be concluded with a 'C9' Return command. You did explicitly point out that the Main Patch Vector ends with a 'C9' (which returns the program back to the main loop by default, for those rooms that don't have a room-specific Patch Vector). However, I think your guide should explicitly mention the fact that when a room-specific PV is called up, the relevant chunk of code should also end in a 'C9' command. (May I kindly suggest that you edit your initial post in this thread accordingly?) By the way, my ruminations on this have helped me to understand why the Main PV is called up from the Main Loop, rather than having been directly inserted into the Main Loop (which on the face of it would save four bytes: 3 for the Call and 1 for the Return). I still maintain that the Main PV could be inserted into the Main Loop (as per our previous discussion). However, it would mean that each and every room-specific PV would have to be terminated with a 3-byte Direct Jump command (or at best a 2-byte Relative Jump, if a particular PV's address happened to be within 128 bytes of the Main Loop), rather than a single-byte Return. So the notional 'saving' of 4 bytes, achieved by inserting the Main Patch Vector into the Main Loop, would soon be overtaken by the increased length of all the room-specific Patch Vectors!
-
By the way Danny, hopefully the bug fix will have 'liberated' you to consider changing guardians on Black screens in WNM to Bright ON, without fear of causing any instances of the Shadow Bug around guardians in the non-Black rooms.
-
I think I might have implemented it in that way in the first place, but when I came to typing it up for this article, I put the spare byte at the end, thinking that was 'neater'. (And I thought that if it had to be consolidated to sit alongside other spare bytes, to make good use of it anyway, then it wouldn't matter where exactly the spare byte was left.) However, as you've presumably realised Danny, if it's been left at the end of the section of modified original addresses, then it wouldn't be safe to keep it in situ and use it for a single-byte variable (such as the Music Flags). This is because the program would stumble across it after drawing every guardian in a non-Black room, and may take whatever the value of the Music Flags happens to be at that instant, and try to interpret it as a command code - with unpredictable and potentially disastrous consequences!! So your approach is better, Danny, as both of the alternative Guardian-drawing sub-routines bypasses the spare byte entirely! Thank you for pointing out this 'trick', which may be a useful general principle to apply elsewhere in the code!
-
Good question! I suppose - like inserting data into the unused addresses in the Rope Animation table - you could 'suck it and see'!
-
Actually, I've just noticed that the fix is even more comprehensive. The Swimming Pool has a Black background, but the Underwater Monk is walking amongst Inkless Water cells, which are of course non-Black (Cyan). If you edit original JSW and turn that Monk Bright Yellow, it has a Bright Cyan Shadow against the surrounding non-Bright Cyan Water cells. However, with the above patch in place, there is no shadow - the Monk is rendered non-Bright Yellow on this screen (unless the Water cells are set to Bright Cyan, in which case both the Monk Guardian and the pool's Water cells are Bright, so again no shadow!) But the same Guardian Class of Monk is seen in The Forgotten Abbey, this time in Bright Yellow!
-
What you call the "modified original code" is actually the 'new' code [although it's based on an unused routine left over from Manic Miner]. Whilst what you call the "new code" is actually the 'old' [original JSW] code, relocated! (I did it that way because the 'new' code is shorter, and therefore it - and a jump command to the new location - slotted nicely into the original location, without the need to carry out extensive consolidation of the existing 'Draw the guardians' routine.) Are you still following me? Good! On we go... The 'old' code (at the new location) actually starts at #96FA, as it is preceded by a check at #96F4: '7e e6 38 c2 f1 91'. The first three bytes of that selects the Paper colour of the current room's Air cells i.e. the screen's background colour. '7E' is LD A, (HL), which picks up the attribute byte of the cells in which a guardian is located; 'E6 38' is AND 00111000 (#38 expressed in binary), which selects Bits 3 to 5 (Paper colour) and ignores all the other bits of the attribute byte. Then there is a 'C2' (JP NZ) conditional absolute jump command, which returns the program back to #91F1 if the Air Paper is NOT ZERO (i.e. non-Black). Thus on the Black screens, the program proceeds as it always did (with both Bright and non-Bright Guardians potentially present, determined by the Brightness setting of each individual Guardian Class). Whereas on the non-Black screens, the Brightness setting of the guardians is determined by the Brightness setting of the screen's Air cells (as specified by the 'new' code, via an 'E6 78' command - AND 0111000). So the section of code that you thought was being bypassed is in fact the new element that fixes the 'Guardian Shadow' Bug! N.B. My first attempt at a fix only had that 'new' code in place [with the original JSW guardian-drawing code from #91EE-91FC removed entirely], which did indeed fix the 'shadow bug'. However, that placed limitations on the range of guardian colours that you could have present on the Black background screens - they could either all Bright or all non-Bright on a given screen, determined by the Air's Brightness setting. (Of course, on non-Black screens, you still cannot have both Bright AND non-Bright guardians without one or the other displaying a 'shadow' against the background - I don't think it is possible within the game engine to define screen cells that have Bright Ink and non-Bright Paper colours, or vice versa.) So to summarise, the final product - the code in the first post in this thread - calls up one of two sub-routines to draw the guardians onto a screen, and which one of the two sections of code is used is dependent on whether the screen's background (Air cells Paper colour) is Black or non-Black.