Jump to content
Jet Set Willy & Manic Miner Community

IRF

Contributor
  • Posts

    5,105
  • Joined

  • Last visited

Everything posted by IRF

  1. For reference, this was the post that Norman Sword is referring to (thanks Norman): http://jswmm.co.uk/topic/185-free-space-and-code-optimisation-in-jsw/page-8?do=findComment&comment=6101
  2. The point I was making is that SPECSAISIE prints the initials 'BGB' for at least half of the rooms in JSW! But you only appear to have spotted the ones that happen to sit in the right-hand columns of the tables ('jutting out' from the main tables, so to speak). If you look again you will see there are 'BGB' entries scattered throughout the tables that you failed to spot the first time! ;)
  3. I've just come across the first of the previously-documented instances of the CGB: the conveyor in Room 24 ('West of Kitchen'). Interestingly enough, the conveyor attribute matches one of the Water cell graphic bytes - but even if it didn't, the buggy CPIR loop would have encountered a match with two of the Earth cell graphic bytes anyway, before it reached the proper conveyor attribute byte! EDIT: A similar thing is true of the instance affecting the conveyor in 'Tool Shed'. ****** Room 29 'The Nightmare Room' - the previously-documented instance of CGB affecting the conveyor is present in the table - but that only occurs because the attribute byte for conveyor is located at the wrong Offset Byte within the room data! Once the misaligned bytes are shunted into where we think are their correct locations, the Cell Graphics Bug stops occurring even without the CGB Bug-Fix in place! Also in the Nightmare Room, as I spotted earlier, the Fire cells (which are unused but which have a defined pixel-pattern and non-#FF attribute) would be affected by the CGB if any were placed in the layout. ****** I've been through all the tables, and I'm now confident that there are no more* matches that would give rise to the Cell Graphics Bug, other than with a default #FF attribute byte for unused room elements. * i.e. no more matches other than the conveyors documented in the SkoolKit disassembly, the recently discovered instance affecting the Fire cells in 'A Bit of Tree', and the 'theoretical instance' affecting the unused Fire cells in 'The Nightmare Room' (which has a defined attribute and graphic, even though it is unused). Phew! P.S. I'd be happy to analyse similar tables for 'Manic Miner', if you have the time and inclination to put MM through the same SPECSAISIE analysis?
  4. I've been going through the data. As I highlighted above, there are lots of instances of an unused room element with attribute set to #FF (or -1 as it is referred to in the SPECSAISIE tables), which matches with a full-infilled pixel-row that is listed earlier in the room data. Which is not a problem for unused room elements, of course. Aside: This has prompted me to think of something - if any of the non-conveyor tiles in 'Conservatory Roof' had happened to have a fully filled-in pixel-row, then the Cell Graphics Bug would have caused the conveyor present in that room to have a pixel-pattern, even though Matthew never defined one! Although since the conveyor attribute is set to #FF, this pixel pattern would only display itself when Willy is killed in that room, causing all the infilled pixels in the primary pixel-buffer instantaneously to flash in white-INK-on-black-PAPER! Anyway, one non-#FF value that I have come across is in Room 18 ('On the Roof'). The ramp attribute byte is set to #07, and there is a graphic byte with that value in the Earth cell data (third pixel-row down). However, the Cell Graphics Bug does not occur, because Water and Ramp cells share a common attribute in that room, and so the Water cell pixel pattern (which comes before Earth's definition in the data) takes precedence for the Water-Ramp combined cell-types.
  5. Danny, have you only spotted the instances where the initials 'BGB' appear in the rightmost column of the tables (the 'overspill' column, that is empty in most cases)? There is an instance in Room 2 ('Under the MegaTree'), which is embedded in the middle of a table (and a regular 'Offset byte' number is shunted along into the right-hand column). The fourth pixel-row of the (unused) ramp tiles was apparently assigned a value of #FF (a solid line), which is rather peculiar given that there is no ramp in that room, and all the other ramp pixel-rows are blank (#00). That is then causing a match with the attribute byte for the (also unused) conveyor in that room. So (i) the 'BGB' flag must appear immediately after the byte which causes the erroneous match; (ii) there are probably more instances than you indicated at the top of your post #30 in this thread (many of which may be the default #FF 'unused attribute' value matching with a fully-infilled pixel-row); (iii) further investigation should (hopefully) confirm that all the previously-known instances of the CGB have been detected by SPECSAISIE after all!
  6. Taking Room 16 (Quirkafleeg), the instance flagged up relates to the fact that the bottom pixel-row of the Fire cells is entirely filled in (value #FF), which causes a match with the (default) value of #FF for the conveyor attribute in that room. But there is no conveyor in Quirkafleeg, and if Matthew had put one in, he would almost certainly have ascribed a different attribute to it (notwithstanding the solid white block in Conservatory Roof, which must have been an omission on Matthew's part). So it is clearly necessary to do some manual, post-SPECSAISIE analysis of the generated tables, in order to extract any 'genuine' instances of the CGB.
  7. Thanks Danny! Rooms 47, 62 and 63 aren't used in the game, of course!
  8. Regarding the point in bold, this is actually the case in Jet Set Willy! If you place some Fire cells into 'The Nightmare Room', they aren't drawn as defined in the code, because their attribute byte matches the penultimate Earth cell graphic byte and so the Cell-Graphics Bug kicks into effect again! Richard's investigations evidently only took into account the defined room tiles that actually made it into the published game, not the ones that Matthew Smith defined but left unused and buried in the code!
  9. Should have gone to SPECSAISIE! :D EDIT: Danny, in case that goes over your head - that's a play on the words of a series of TV adverts for a budget opticians we have here in Britain, called Specsavers. (Someone does something ridiculous due to their poor eyesight, followed by the punchline: "Should have gone to Specsavers!". Check out YouTube if you want a brief diversion.) BTW, did you try out that function of SPECSAISIE on an unmodified copy of JSW and/or MM, Danny? (To confirm what we already know in relation to the former, or to spot previously unidentified instances in the latter - there may be some lurking in the defined-but-unused cell types?)
  10. Thanks Richard, that's useful to know. :) Have you checked whether the Cell-Graphics Bug affects any cavern elements in Manic Miner? I can't think of any examples off the top of my head, but it can occur in theory because the same erroneous use of a CPIR command is present in the routine which draws the layout to the pixel-buffer. I know that there are instances in Andrew Broad's mirror-imaged versions of both Manic Miner and Jet Set Willy - in the latter, there are new instances that arise because the graphic bytes are all laterally-inverted (Fire cells in The Attic, for example, whose attribute byte matches the penultimate graphic byte of the Earth cells if it's inverted), whilst I believe the same mirroring process either changes the nature of some of the existing examples of conveyor corruption, or in some cases 'cures' them altogether (i.e. prevents them from arising). ****** Here's another thing for your JSW TODO list (although I may have already mentioned this - can't remember - or perhaps you have already mentioned it in the JSW disassembly): Several vertical guardians in Jet Set Willy can extend below the bottom of their specified range (one or two of the bats that lurk between the columns of Fire cells in 'At the Foot of the MegaTree' do so, for example). It happens if the difference between the guardian's upper and lower bounds isn't exactly divisible its vertical speed. The 'out of bounds' situation only prevails for a single time-frame, whilst the guardian's direction of travel is being reversed. N.B. It doesn't happen at the top of a vertical guardian's specified range, because there is a specific command at #91A8 which sets the guardian's definition byte 06 as a 'hard' upper bound. ****** One other little point that you might be interested in, Richard - please see the post at the following link, which gives a possible explanation for the existence of a redundant instruction that is present in the 'Lose a Life' routine of both JSW (#8C19) and Manic Miner (#8925). You describe the instruction thus: "Set bit 4 of A (for no apparent reason)". http://jswmm.co.uk/topic/185-free-space-and-code-optimisation-in-jsw/?p=7817
  11. Thanks Norman. You could use a similar PUSH IX / POP HL trick for all the 'Move the guardians' elements (ropes and horizontal guardians as well), couldn't you? Since H and L aren't used at all within that routine (and nor is there a CALL to a subroutine that does use H or L). EDIT: In fact, if that is the case, then couldn't the PUSH IX / POP HL be placed near the very start of the 'Move the Guardians' routine - after #90C0 but before #90C4 (with #91BB jumping back to include this 'variable swap') - so that it only has to be done once, rather than at the start of each branch of the routine (for ropes, horizontal and vertical guardians)?
  12. Here's another bug fix, although this applies to the 'Move the guardians' routine, rather than 'Draw the guardians'. This fixes the bug (feature?) whereby certain vertical guardians can extend beyond their lowest permitted bound (if the distance between their upper and lower bounds isn't exactly divisible by their vertical speed). For comparison, this is the original code, courtesy of SkoolKid http://skoolkid.github.io/jetsetwilly/asm/90C0.html DD 7E 03 9193 LD A,(IX+$03) Update the guardian's y-coordinate DD 86 04 9196 ADD A,(IX+$04) DD 77 03 9199 LD (IX+$03),A DD BE 07 919C CP (IX+$07) Has the guardian reached the lowest point of its path (maximum y-coordinate)? 30 0D 919F JR NC,$91AE If so, jump to change its direction of movement DD BE 06 91A1 CP (IX+$06) Compare the new y-coordinate with the minimum value (the highest point of its path) 28 02 91A4 JR Z,$91A8 If they match, jump to change the guardian's direction of movement 30 0E 91A6 JR NC,$91B6 If the new y-coordinate is above the minimum value, jump to consider the next entity DD 7E 06 91A8 LD A,(IX+$06) Make sure that the guardian's y-coordinate is set to its minimum value DD 77 03 91AB LD (IX+$03),A DD 7E 04 91AE LD A,(IX+$04) Negate the y-coordinate increment; this changes the guardian's direction of movement ED 44 91B1 NEG DD 77 04 91B3 LD (IX+$04),A The above would need to be replaced with the following (which requires code consolidation to fit eight extra bytes into the available space, or else a JUMP to somewhere with the necessary free space): DD 7E 03 LD A, (IX+$03) Pick up the guardian's y-coordinate DD 86 04 ADD A, (IX+$04) Add the guardian's vertical speed; A now holds the updated y DD BE 07 CP (IX+$07) Has the guardian reached or gone past its lower bound? 30 07 JR NC, change_direction If so, jump to change its direction of movement DD BE 06 CP (IX+$06) Compare the new coordinate with the guardian's upper bound 28 02 JR Z, change_direction If they match, jump to change the guardian's direction of movement 30 16 JR NC, update_y If the guardian hasn't gone past its upper bound, jump to update y DD 7E 04 change_direction: LD A, (IX+$04) Negate the y-coordinate increment; ED 44 NEG this changes the guardian's DD 77 04 LD (IX+$04), A direction of movement DD CB 04 7E BIT 7, (IX+$04) Is the guardian's vertical speed now negative? 20 05 JR NZ, reached_bottom If so, the guardian must have reached its lower bound, so jump DD 7E 06 reached_top LD A, (IX+$06) Otherwise, the guardian has reached its upper bound, so 18 03 JP update_y make sure that the guardian's y-coordinate is set to its minimum value DD 7E 07 reached_bottom LD A, (IX+$07) Make sure that the guardians' y-coordinate is set to its maximum value DD 77 03 update_y LD (IX+$03), A Update the guardian's y-coordinate
  13. Further to the above, I've also noticed that if you apply the Infinite Lives POKE, the RIP sprite briefly appears when Willy is killed - overprinting the right-hand dancing Willy in the 'Remaining Lives' bar - but then the rightmost dancing Willy is restored (replacing the RIP sprite) when the game resumes!
  14. Has anyone noticed the instance of the Cell Graphics Bug affecting the Fire cells in 'A Bit of Tree' in the original JSW? It isn't documented anywhere in SkoolKid's JSW disassembly, I don't recall Stuart Brady mentioning it when he introduced his Cell Graphics Bug Fix, and a search in the Yahoo Group has drawn a blank. However, I find it hard to believe (in fact incredible!) that this hasn't been spotted before!?
  15. I've tweaked the layout of the two 'Multimedia Guardian' test files, and re-uploaded them to my post from last night, in order to illustrate the point that Air cells can also have their PAPER miscoloured, if they are entered from the left (or from above) by a guardian that is passing from a different medium with a different PAPER setting.
  16. You can see the bug in action in Andrew Broad's game 'JSW64:MM: James Bond'. That project would certainly benefit from the bug fix I've come up with, if Andrew ever gets round to developing the game further. Andrew had to pack a lot into every room (a whole James Bond movie's plot is represented by each room!), so the layouts are quite dense. As a result, there are a number of guardians which move through non-Air room elements, causing the PAPER colour of certain cells to be temporarily discoloured. Sometimes non-Air cells assume the PAPER colour of the Air cells; at other points in the guardian's trajectory, it is the Air cells which temporarily take on an anomalous PAPER colour. (Actually, the latter is something that my test file doesn't demonstrate [EDIT: It does now!], because the top-left cell of a guardian determines the PAPER setting of the rest of the guardian's surroundings, and in the test file the Air cells are all either above or to the left of the Water cells. So the Air PAPER colour always happens to takes precedence. I might rearrange the layout slightly, putting the 'parting of the Waters' more centrally, in order to display the full range of buggy behaviour - i.e. as the horizontal guardian passes through a column of Air cells sandwiched between two columns of Water cells, the PAPER behind the guardian will change TWICE.)
  17. Et voila! In the attached 'Multimedia Guardian Test' file, the start room is set to the Swimming Pool. There are several vertical guardians (two BRIGHT and two non-BRIGHT) which dip in and out of the Water. The horizontal Monk guardian has turned into King Canute and is "holding back the tide" in the middle of the pool! The bottom row of the pool is comprised of INKless Fire cells, with the same cyan PAPER setting as the Water cells, but with BRIGHT On for the Fire and BRIGHT Off for the Water. The black Air cells have BRIGHTness switched to On. The 'Draw the guardians' routine now CALLS a subroutine, located at #9718, up to six times for each guardian that it draws. You can see that the guardians retain their original BRIGHTness setting when they are in the black background (Air) cells, but they assume the BRIGHTness setting of their host cells if the PAPER setting of the cells isn't black. You can also observe that the guardians are no longer drawn with a fixed PAPER colour for all of the cells that they occupy (based on the PAPER setting of their top-left cell). EDIT: I've also attached a file called 'Multimedia Guardian Without Fix', which illustrates the original problem when guardians (vertical or horizontal) move between different media of differing PAPER settings. Multimedia Guardian Test.z80 Multimedia Guardian Without Fix.z80
  18. Thinking some more about the above, it could be resolved by taking the same approach to distributing the attributes for guardians, as the code which sets Willy's attributes in the secondary attribute buffer. i.e. put the code at #91EE-#91FD (modified to fix the Guardian Aura Bug) into a subroutine, which is then CALLed four or six times (each CALL would replace one of the existing LD (HL),C commands in the code that follows, up to #920E). Of course, the fix is only necessary if you have guardians moving between different mediums, which would both probably need to be INKless in order to prevent a pixel collision between the guardian and the non-Air blocks. In the original game, the Swimming Pool is the only place that I can think of where this would be possible (since the Water cells in that room contain no infilled pixels).
  19. But not entirely eliminated though! I believe it is still possible to jump into/through Earth blocks on the descent part of a jump. The fundamental reason why this is possible within the JSW game engine, is because when Willy is jumping, his y-coordinate is adjusted before a check is made for standonable cells beneath his feet. (In contrast, when Willy is falling, his y-coordinate isn't adjusted until after the check is made for platforms underneath his feet.) For reference: http://skoolkid.github.io/jetsetwilly/asm/8DD3.html I can conceive of two possible fixes for this (although quirkophiles such as Dr Andrew Broad wouldn't thank me for it!): (1) Rearrange the 'Move Willy (1)' routine, so that Willy's y-coordinate isn't adjusted until after the check for underfoot cell behaviour. (i.e. only proceed to adjust his vertical position downwards IF there is nothing underneath his feet to break his fall.) I haven't considered this in detail; it could be complicated because the code handling Willy's jumping and falling behaviour are interwoven within that routine; (2) Replicate (a modified version of) the code at #8EBC-#8ED3, which detects a collision between Willy and an overhead Earth block, and resets his coordinates downwards accordingly, to eject him from the Earth block. This is intended to curtail a jump upwards through Earth blocks, but it also gives rise (inadvertently, I would imagine) to the infamous 'Innocent-Looking Block' behaviour. I've tried out the second approach to a fix, and it works. ;) After the instruction at #8E00, but before the command at #8E03, insert the following code. (This requires a fair bit of consolidation to make the code fit, or else a JUMP to free space elsewhere in the code.) Note that when the program reaches here, the A register will hold the attribute byte for Earth blocks/wall tiles, as defined at #8DF7, and the HL register-pair will be pointing at the top-right cell of Willy's sprite (see #8DFE): LD DE, #0040 ADD HL, DE Point HL at the right-hand cell below Willy's sprite. CP (HL) Set the zero flag if the right-hand cell below Willy's sprite contains an Earth block. DEC HL Point HL at the left-hand cell below Willy's sprite. JR Z, earthleg If the right-hand cell below Willy's sprite contains an Earth block, then jump to the code which prevents him from jumping into it from a certain angle. CP (HL) Does the left-hand cell below Willy's sprite contain an Earth block? JR NZ, #8E03 If not, then resume executing the regular 'Move Willy (1)' routine (make the jumping sound, etc.) That is then followed on immediately (if the left-hand cell below Willy's sprite does contain an Earth block) by: earthleg: LD A, (#85CF) Round Willy's y-coordinate down AND #F0 to the nearest multiple of #10; LD (#85CF), A this ensures that he is cell-row aligned, and standing on the Earth block which he would otherwise have jumped through. CALL #8E9C Align Willy's attribute coordinates with his pixel y-coordinate. [i'm not sure that's strictly necessary in this context, but I've included it as a precautionary measure.] JP #8ED4 Proceed to the 'Move Willy (2)' routine, which resets Willy's jump counter (#85D1) and then detects movement keypresses. (N.B. The HL register-pair is now pointing at the appropriate cell to pick up underfoot conveyor behaviour.) N.B. The above fix only prevents Willy from jumping into Earth blocks. It doesn't address the ability of Willy to walk into Earth blocks that are situated in certain positions in the vicinity of a ramp (e.g. Willy can walk down the ramp in 'On Top of the House') - that's a whole different kettle of fish!
  20. I think the fact that the room name remains printed on the status bar during 'Game Over' (something which I don't normally like) kind of makes sense with that POKE in place.
  21. I have now tried out the alternative end to the 'Lose a life' routine, and removed the code in 'Room setup' which wipes the bottom screen-third. As per the above, instead of the expired lives being overwritten by a blank sprite (32 contiguous zeroes), I have printed a modified version of the Barrel sprite in their place. (With the three 'X's being replaced by the letters 'RIP'!) I have also tweaked the 'Draw the remaining lives' routine so that the consecutive lives appear in different animation-frames - like in Geoff Mode, but I have gone further than he did so that the adjacent lives are updated at different times as well. It all works fine. :)
  22. Try POKE #8C39, #57 in JSW, and then lose all your lives, for an interesting variation on the original Game Over sequence...
  23. Not quite so simple though surely? Because of the non-linear way that the graphic bytes are distributed on the screen. In order to erase pairs of bytes from 16 consecutive raster lines, wouldn't you end up having to partially replicate the routine at #9456 anyway? In looking elsewhere for 32 contiguous zeroes, I was wondering whether perhaps you could point DE at #5B00, the top of the stack, since all of page #5B holds zeros by default, and the stack pointer should never reach anywhere near that far! Would there be an unforeseen danger in that? (N.B. There's a whole chunk of hundreds of unused addresses in the ROM, which would be ideal for the purpose, but unfortunately they're filled with #FF rather than #00.) Another option I'm considering is, instead of just erasing the expired lives, print over them with a bespoke 16x16 graphic indicating their demise. The code which animates the remaining lives wouldn't touch such graphics, I believe.
  24. It could be anywhere that there are 32 contiguous zero bytes in the code.
  25. Norman, I recall you querying the need to print the 'remaining lives' Willies during every pass through the Main Loop, if they aren't dancing (because the in-game music isn't playing). I would infer from this that perhaps you have a check of the Music Flag in the Main Loop, and that you only CALL the routine at #898B if that flag is raised (or should that be lowered?) But if that's the case, then you presumably also need to have a CALL to #898B from the 'Room setup' routine? (Because all the status bar pixels are wiped as part of the Room setup routine.) Well, if the approach which I outlined in my post from earlier this afternoon works okay (admittedly I haven't tried it out yet!), then such a CALL to print the current number of lives at each room refresh would no longer be necessary? EDIT: Although you would have to CALL it at the very start of the game, from #88FC. (Unless the in-game music is always initialised to be on at the start of each game.)
×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.