Jump to content
Jet Set Willy & Manic Miner Community

IRF

Contributor
  • Posts

    5,112
  • Joined

  • Last visited

Everything posted by IRF

  1. Slight rewrite to detect 'On Top of the House'-type Earth/wall block: UPDATE: Edited to update the D register when Willy is moving left and about to step onto a wall tile (so that the ADD HL,DE instruction points HL at the correct room cell): ld a,(RAMP) cp (HL) jr nz,as_is ;if ramp is here keep bc=shift LD A,C CP #20 JR NZ found_ ;Willy is going up the ramp, so no need to check if he's about to step onto a wall LD A, (ix+ramp_condition) ;reuse existing variable... DEC A ;decrement... LD D,A ;and load into D, to give correct values for both left and right movement LD E,(ix+ramp_animation) ;reuse existing variable, which happens to hold the correct values for both left and right movement ADD HL,DE LD A, (wall) CP (HL) JR NZ, found_ ;no wall under Willy's front foot, so he proceeds down the ramp as normal ;ramp not found, or it was but an adjacent wall block 'over-ruled' it, so no offset needed as_is: LD BC, #0000 ;bc=0 no ramp so no offset/shift found_:
  2. Another couple of thoughts: the check for an overhead Earth block should also test whether Willy is in the top two rows before carrying out a test for a blocking Earth cell above him. Also, the test for an underfoot Earth block ahead of Willy should be done after the edge-of-room test (otherwise Earth blocks that are horizontally at the opposite end of the current room could have an inappropriate influence on his progression). EDIT: Actually, thinking about it, that latter point isn't important - when Willy walks off the edge of a room, the vertical displacement isn't applied anyway, even if he is on a ramp (hence the ramps in adjacent rooms don't line up when you view a master plan of the whole house e.g. see Orangery/West Wing Roof). The two additional checks for Earth/wall cells have different outcomes anyway (in the former case, Willy's diagonal movement is blocked; in the latter case, his diagonal movement is converted into sideways movement). **** Anyway, I'll try and put all of this into practice when I get a chance; ideally I will be able to build upon Norman Sword's work in making a generic 'sideways movement' routine, covering both left and right movements simultaneously. :)
  3. Sorry, the latter example should have read 'West Wing Roof'!
  4. Ramp up to the left: Offset #DA = 0 .... Test for Earth at Underfoot Ramp coordinate +1 Ramp up to the right: Offset #DA = 1 .... Test for Earth at Underfoot Ramp coordinate -1 So we need to map 0 to 1, and 1 to -1. LD A,(#80DA) RLCA 00 -> 00 01 -> 02 CPL 00 -> FF=-01 02 -> FD=-03 ADD A, #02 -01 -> 01 -03 -> -01 LD E,A There may be a more efficient, clever trick that utilises the Carry Flag? EDIT: Maybe need to adjust D as well? 0->0, 1->-1 LD A,(#80DA) NEG LD D,A Then ADD HL,DE FURTHER EDIT: It's actually more efficient just to do: LD A, (#80DA) AND #01 LD C,A - insert into original code after #95D0 .... OR A SBC HL,DE LD A,C XOR #01 ADD A, #40 LD E,A [D already holds 00] ADD HL,DE LD A,(Earth) CP(HL) JR Z, #95F8 [original JSW address, probably now changed]
  5. Sorry, that will probably only work if Willy's attribute coordinates (WATTR) hold an even value. If they hold an odd value, then the check for Earth blocks may be misplaced to a cell beyond where Willy is standing. I'll have to rethink the logic. EDIT: In specific terms, if the ramp slopes up to the left, then it will be detected at WATTR+#40 ; in that circumstance, the test for an Earth block needs to be at WATTR+#41. But if the ramp slopes up to the right, then it will be detected at WATTR=#41 ; the test for an Earth block then needs to be at WATTR+#40. Ideally, we would have a generic set of operations that will work for both ramp directions.
  6. http://skoolkid.github.io/jetsetwilly/reference/facts.html#rampsVsWalls Some preliminary thoughts: When Willy is walking up a ramp, add an additional check for an Earth block (and RET if one is encountered): - When Willy is walking left, the check should be made at (x,y-1); - When Willy is walking right, the check should be made at (x+1,y-1); where (x,y) are the coordinates of the top-left cell occupied by Willy's sprite prior to him crossing the cell boundary. **** When Willy is walking down a ramp, the simple solution would be to block his progress is there is an Earth block ahead of his sprite and two cell-rows below. But that doesn't seem logical. In the example seen in 'On Top of the House', I feel the most realistic solution would be for Willy to simply step onto the block at the base of the ramp. But that would require amendments to two different routines: (1) Edit the routine at #95C8 - after the check for a ramp cell under Willy's back foot, add an additional check for an Earth block under Willy's front foot (perform an XOR 01 on the L register, load the Earth attribute to A, and then do a CP (HL) / JP Z,#95F8 - all to be inserted in between the commands at #95DC and #95DE). So if Willy is standing on a ramp cell and an Earth block simultaneously, then the 'solidity' of the Earth block will take precedence over the 'downward pull' of the ramp cell* when deciding where to draw Willy; (2) Adjust the 'Move Willy (3)' routine so that, when Willy is about to step off a ramp cell at (x+1,y+2) / (x,y+2) [when walking left / right respectively i.e. a ramp cell in the cell underneath Willy's back foot], then make a check for an Earth block at (x,y+2) / (x+1,y+2) [i.e. in the cell underneath Willy's front foot], and if there is an Earth block there, then undo the commands which adjust Willy's coordinates downwards by a row as he moves past the cell boundary. Edit: i.e. at #900A and #9078, insert the extra check, and if there is an Earth block under Willy's front foot, then set BC=00 (although C=0 should be sufficient). **** * N.B. This shouldn't affect the ability for Willy to walk down a ramp cell through Water cells, such as occurs in 'Swimming Pool' or 'West Wing'.
  7. Actually, it's worth resetting Willy's starting position in the 'Jump Code rewrite' test file to The Banyan Tree (somewhere near the entrance from The Nightmare Room), and then try climbing to the top of the Banyan Tree, and also crossing through the Tree in both directions. The subtle difference in Willy's jumping mechanics end up causing quite a significant difference to the outcomes in that room in particular. For example, crossing from left to right used to be extremely tricky (requiring a well-timed jump to avoid the two 'central' vertical guardians); now it's actually impossible I believe - not because Willy hits the guardians, but because he gets caught by the water cells at the top right which he previously fell straight through. (In a sense, climbing the Banyan Tree [up the right hand side] is now easier, if you approach it from The Swimming Pool!)
  8. Further to the above, I have now implemented both of those methods for fixing the 'Through the Wall' bug. The two methods are completely different in their execution, and each fix gives rise to some different, quirky and interesting side-effects. The first method is implemented in the test file attached to this post: http://jswmm.co.uk/topic/185-free-space-and-code-optimisation-in-jsw/page-20?do=findComment&comment=8311 and the second method is in place in the file attached here: http://jswmm.co.uk/topic/196-dont-mind-your-head-while-walking-left-bug-fix-for-jsw/page-4?do=findComment&comment=8312
  9. And so it has - eventually - been done! Please see the attached file. There is an overhead 'Innocent-Looking Block' in The Bathroom; try and perform a 'standard' quirky jump through it (you can attempt this from various heights, via the stepped water cells which I've provided at the bottom of the ramp). Most of the more familiar quirky manoeuvres involving jumping through Earth cells have been 'switched off' for the descent part of Willy's jump, but something novel occurs on the ascent if you jump from a certain position... (i.e. try an upwards jump through the block, starting from the floor level). P.S. This 'New Superjump' relies on the fact that I haven't remedied the asymmetrical earth-at-head-height bug in the attached file. (i.e. Willy cannot perform this feat when jumping rightwards, only leftwards.) No ILB Test.z80
  10. I've now managed to fix the 'Move Willy' routine, in order to prevent Willy from jumping into wall tiles/earth blocks, and also to implement the check for head-height wall tiles in a symmetrical manner, but without preventing Willy from jumping into a gap that is two rows high and located below a wall platform (a la The Wine Cellar, Ballroom East, etc). Please see the attached test file. The fix is best illustrated in Emergency Generator, where it was previously impossible to jump rightwards from the right-hand chimney and escape via the gap at the top-right that leads to the Priest's Hole. (Previously, Willy fell through the Earth block beneath that gap, and plunged to his death - a similar phenomenon to the way he sinks into the floor at the bottom-right corner of First Landing, but here it has more deadly consequences!) Now the same manoeuvre in Emergency Generator can be done in three different ways, namely: starting off at a height two rows below the gap (i.e. by simply jumping from the start-up position in the test file); jumping from a height that is one row below the gap (I've removed a bit of the chimney to make it easier to reach that position); or jumping from the same height as the gap (i.e. from the top of the right-hand chimney stack). The basis of the fix is a rewrite of the code which SkoolKid calls 'Move Willy (1)' i.e. the code dealing with his vertical movement (jumping/falling). The code now tests whether Willy has landed on a solid platform before his y-coordinate is adjusted during a jump. Previously, his y-coordinate was adjusted first, and only then was a check done for an underfoot solid platform - that illogical sequence is the fundamental reason why Willy can jump into solid blocks in the original game engine. Several other quirky manoeuvres are prevented by this fix, such as the ability to jump through so-called 'Innocent-Looking Blocks', and the way in which Willy can, in some circumstances, fall through a standonable block that lies adjacent to a Fire cell. Other unintended consequences may also occur - for example, if Willy stands adjacent to a pillar of Earth blocks that is two cells high and tries to jump onto the pillar, he leaps all the way over and falls down on the far side of the pillar. This actually makes The Banyan Tree more difficult to climb/cross! N.B. These code changes do not prevent Willy's ability to walk into wall tiles by proceeding up or down a ramp. Jump Code rewrite.z80
  11. The two chunks of code at #8E12-#8E24 and at #8E81-#8E93 are identical, and could be put into a subroutine CALLed from both places. That would save a net total of twelve bytes I think (2x19 bytes replaced by 1x19+1 RET at the end, called by 2x3-byte CALL commands). **** The JR at #961C may be eliminated if the subroutine at #961E is relocated to after the code at #9637-#967F (or elsewhere).
  12. If the head-height check for walls is made to occur in both directions, then the problem with not being able to jump into the gaps in The Wine Cellar could be resolved by replacing the RET at #8EB5 with a jump to #8FBC. That has the effect of extending Willy's horizontal movement during a jump by one more increment - just enough to clear the gap. Your check for wall tiles 'two rows down' would not occur at that point, if the gap into which Willy is jumping is at the same height as he was at the start of the jump, because the code at #8EB0 will just have set the Airborne indicator to a value of 06. (Assuming that the test you have inserted for jumping only responds to a value of 01 stored at #85D1.)
  13. Norman, your latest contribution is an excellent piece of optimisation. My humble suggestion would only save another 4 bytes (by removing the check for whether HL had extended beyond the bottom of the screen). Keep up the good work!
  14. Just to clarify the above comment further, when Willy is walking on a ramp, his 'technical y-coordinate' as stored at #85CF remains as a multiple of #10 (he is 'technically cell-row-aligned). But the routine which draws Willy's sprite adds an offset, based on his frame of animation, if it detects that he is standing on a ramp. So the test for Earth cells three rows below the top of Willy's head isn't applied when he is walking down a ramp - you can see this in action in 'On top of the house', where Willy can walk through the solid block at the bottom of the ramp. (If you NOP out the JR Z,ONLY_TWO command in Norman's code, then the same Earth block stops Willy's progress down and off the 'On top of the house' ramp - note that this will also prevent Willy from walking along a horizontal platform comprised of Earth cells!)
  15. Further to my previous post, this is the part of Norman's code which prevents an undesirable check for Earth blocks above the top of the current room: There is also a similar bit in Norman's code which is intended to prevent an undesirable check for Earth blocks below the bottom of the current room. However, I don't think that's necessary - the routine only tests for Earth blocks in the cell-row that lies two rows below Willy's head in circumstances where Willy is jumping and isn't cell-row-aligned (in which case the attribute coordinates of the top-left of Willy's sprite will place him no lower than three rows above the bottom of the screen). ****** This comment puzzles me slightly: From the location of the commentary, it appears to refer to the test for Earth cells at the level of Willy's feet (for which there is symmetry in the original code), and at head-height level, the asymmetry in the original code was the opposite way around to the above. i.e the test at head height was only performed on rightwards movement. ****** For the record, I think the label 'down_' in the above should be labelled as 'up_'. (And jr z, up_ for the associated command). There is a match with the ramp_condition variable if Willy is walking in the direction that would take him UP the room's ramp (if he is on or about to step onto it).
  16. Norman Sword's last couple of posts have drawn attention to a bug which I haven't ever seen documented anywhere before. Please check out the attached test file - the starting location is set to 'Back Stairway', which i have modified so that the Earth attribute in that room is black INK on black PAPER (value #00); also, the Air PAPER setting is set to blue, so that you can distinguish the Air from the Earth cells. Note that the layout of the room hasn't been changed in any other way from the original game. Note also that the Earth cells in the top two rows still retain their original pixel patterns - you can see it flashing instantaneously when Willy loses a life within the room. Now, try walking Willy rightwards and up the ramp, towards the room above - you will see that as he reaches the top, his progress is blocked - for no apparent reason! (He can jump rightwards and escape off the top of the screen, but that's because Willy's sideways movement is handled differently when he is jumping, compared to when he is walking along a ramp.) Note that this phenomenon doesn't occur in the opposite direction (i.e. with a ramp that slopes in the opposite direction - up and left past the top of the screen, such as the ramp in 'Security Guard') - but that is only because there is no check in the original code for Earth cells to the left of Willy at head height. If that (separate and unrelated) bug is fixed, then this newly-discovered bug would also occur in such a circumstance. One other thought: This is a similar (but slightly different) phenomenon to another, more widely-reported bug whereby a Fire cell in the top cell-row of a room will kill Willy if he tries to drop down off the bottom of the room directly below said Fire cell. (In that case, HL is being incremented down beyond the bottom of the secondary attribute buffer into the top cell-row of the primary attribute buffer, where the primary copy of the same Fire cell resides.) Anyway, it would seem that Norman's latest code modifications (which combine Willy's leftward and rightward movements into one chunk of common code) will have the additional benefit of fixing this hitherto undocumented 'Earth Cell in the Stack' bug. Out of Bounds Earth Test.z80
  17. I wonder if a similar process could be used to optimise the code which moves horizontal guardians, so that the code which moves them left and right is shared? IX would already be in use by the guardian loop, but perhaps you could use the IY indexed register-pair to assign variables depending on a horizontal guardian's direction of travel? Or else use the B/C/D/E registers to set the variables? Geoff Mode takes that approach for the code which moves ropes - see #90D7 to #911D in the disassembly of his game engine: https://web.archive.org/web/20030701143111/http://www.cix.co.uk/~morven/jsw/geoff_dis.html Mind you, the existing code for moving horizontal guardians is much shorter than the equivalent Willy-handling code, so it might not be worth optimising/consolidating in the same way, even if it were possible - the table of variables, plus the code which sets up the combined left/right movement regime, might be as long as one half of the current code anyway!
  18. Thanks Norman! It'll take me a while to fully process that, but I think I understand the gist of it..
  19. JG Harston provides a patch to check for wall tiles at head-height in both directions: http://mdfs.net/Software/JSW/JGH/Docs/Patch.htm#wall The patch is made to fit into the available space by using some code efficiencies: Original code: Changed to: 9035 22 D3 85 LD (POSITION),HL 9035 3A B2 80 LD A,(WALL) 9038 78 LD A,B 9038 BE CP (HL) 9039 32 CF 85 LD (YPOSN),A 9039 C8 RET Z 903C 3E 03 LD A,&03 903A 22 D3 85 LD (POSITION),HL 903E 32 D2 85 LD (FRAME),A 903D 3E 03 LD A,&03 9041 C9 RET 903F C3 AE 90 JP &90AE This approach (of using common code at the end of the parts of the 'Move Willy (3)' routine which deal with Willy moving left and moving right) can be taken further, to save a few more bytes: Original code: Changed to: 9035 22 D3 85 LD (POSITION),HL 9035 3A B2 80 LD A,(WALL) 9038 78 LD A,B 9038 BE CP (HL) 9039 32 CF 85 LD (YPOSN),A 9039 C8 RET Z 903C 3E 03 LD A,&03 903A 3E 03 LD A,&03 903E 32 D2 85 LD (FRAME),A 903C C3 AB 90 JP &90AB 9041 C9 RET 903F 00 00 00 Three spare bytes 90AA 22 D3 85 LD (POSITION),HL 90AA AF XOR A 90AD AF XOR A 90AB 22 D3 85 LD (POSITION),HL
  20. Thanks Norman. I suppose there might be other functions where Matthew's code replicates something that is already available in the ROM?
  21. A few efficiencies can be found around the IN commands that take signals from the keyboard. Wherever there is a LD BC,#0000 followed by an IN A,(C) - this can be replaced with a LD A,#00 [the value that was previously being loaded up to B] followed by an IN A,(#FE). Also, in places where a routine responds to any keypress from one or more entire half-rows of keys*, you can replace this sequence: AND #1F CP #1F which leaves the Zero flag reset if and only if one of the appropriate keys is pressed, with this: OR #E0 CPL [Note that the CPL command leaves the Zero Flag unchanged, even if the Accumulator ends up with a value of #00.] INC A [This replaced the CPL command, which didn't work. INC A will set the Zero flag if and only if the previous value of A was #FF i.e. all bits set, because no keys in the relevant half-row are being pressed.] which has the same effect on the Zero flag, but requires one less byte. (*Such as pausing/unpausing the game, toggling the music on/off, or pressing a Jump key other than '0'. It wouldn't work when specific keys out of a half-row are being tested, such as Left-Right movement or the SHIFT+SPACE abandon-the-game key combo. Note that this won't work if the situation requires the precise value in A - as determined by the particular key in the half-row that was pressed - to be used for other purposes.)
  22. In the attached, I've tweaked my Game Over test file in accordance with Norman Sword's suggestions. I've also come up with a way of having a pause instead of (but of the same length as) a note, to punctuate the music. That required four additional bytes in the code, and the use of the value '01' in the music data to denote the 'dead notes'. Game Over Test 2.z80
  23. Thanks Norman. I was aware that I had implemented a 'quick and dirty' solution, which causes the changes in duration of the notes. (It's probably a deliberate effect in the original routine, as the increasing pitch causes the Monty Python foot to speed up as it descends onto Willy.)
×
×
  • Create New...

Important Information

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