IRF Posted December 13, 2017 Report Share Posted December 13, 2017 (edited) Thanks Norman! It'll take me a while to fully process that, but I think I understand the gist of it.. Edited December 13, 2017 by IRF Quote Link to comment Share on other sites More sharing options...
IRF Posted December 13, 2017 Report Share Posted December 13, 2017 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! Spider and jetsetdanny 2 Quote Link to comment Share on other sites More sharing options...
Norman Sword Posted December 13, 2017 Report Share Posted December 13, 2017 Seeing the Ramp code this morning I realised that the subroutine it called was no longer needed. So I have rewritten the code and saved another seven bytes. IRF, Spider and jetsetdanny 3 Quote Link to comment Share on other sites More sharing options...
IRF Posted December 14, 2017 Report Share Posted December 14, 2017 (edited) 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.) What is happening is that Willy is being blocked from moving past a cell boundary by a pseudo-Earth cell which is residing within part of the program's stack!!The stack (page #5B) directly precedes the secondary attribute buffer (pages #5C-#5D) in the code. As Willy progresses up a ramp, the check for Earth cells at head-height is being decremented (via the HL register-pair) up to the cell-row above his head - but in the case of a ramp extending up to the top of the room, this means that when Willy occupies the top two cell-rows, HL is pointing at an address which is beyond the top of the secondary attribute buffer, somewhere in the range #5BE0-#5BFF. i.e. towards the base of the stack!In the case of 'Back Stairway', the ramp reaches the top of the room near the (horizontal) centre of the room, so the address being tested is around #5BF0 or thereabouts. The values stored around there tend to be #00 (i.e. NOPped out addresses), because the part of the stack which actually gets used during execution of the game (starting at #5BFF) doesn't tend to reach that far. So in the test file, a NOPped out address in the stack is matching with 'Back Stairway's defined Earth attribute value, and is therefore blocking Willy's progress.But if the ramp was reaching the top of the room at the top-right corner, such as occurs in 'West Wing', then HL would be 'spilling over' into parts of the stack which do tend to get written to during execution of the game. Therefore, the 'Move Willy (3)' routine would encounter arbitrary values which are determined by whatever RETurn addresses or PUSHed variables had been recently placed onto the base of the stack at a given point in time. Thus it is possible to conceive of a situation whereby an attribute match with a more 'regular' value for the current room's Earth cell attribute might cause Willy's progress past the top of the screen to be blocked - or not! - depending on the specific status of the stack at a given moment during the running of the program!! 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 Edited January 9, 2018 by IRF Spider 1 Quote Link to comment Share on other sites More sharing options...
IRF Posted December 14, 2017 Report Share Posted December 14, 2017 (edited) 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: ;in theory this position could be off the top of the screen bit 1,h jr nz,ignore_head_check cp (hl) ;head ret z ;return if path is blocked ignore_head_check: 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: ; this test was only performed on left move ; this is now symetrical - checks both left and right the same way 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. ****** ; three outcomes going up bc=-32 ; going down bc=+32 ; no ramp bc=0 ld bc,-32 ld e,(ix+ramp_where_1) ld a,(RAMP_DIR) ;either 0 or 1 and 1 ;get rid of other bits cp (ix+ramp_condition) ; the sign test ; this condition swaps on left and right jr z,down_ ld bc,+32 ld e,(ix+ramp_where_2) down_: add hl,de ; add offset to find ramp/stair square 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). Edited December 23, 2017 by IRF Spider 1 Quote Link to comment Share on other sites More sharing options...
IRF Posted December 14, 2017 Report Share Posted December 14, 2017 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). 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!) Spider 1 Quote Link to comment Share on other sites More sharing options...
Norman Sword Posted December 14, 2017 Report Share Posted December 14, 2017 If you wish to write a better version, please feel free to do so. My code is simply illustrating a path that can be taken. IRF and Spider 2 Quote Link to comment Share on other sites More sharing options...
IRF Posted December 15, 2017 Report Share Posted December 15, 2017 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! Spider 1 Quote Link to comment Share on other sites More sharing options...
Norman Sword Posted December 17, 2017 Report Share Posted December 17, 2017 (edited) A viewpoint (which might change) based on code written today. The previous code and several other bits that modify the path that willy can take still have problems. I wrote a routine that shows in real time what tiles are being checked by this program. (allowing frame by frame analysis). What this routine showed was, that the checking has flaws in its design. The original routine was not symmetrical, and it was the non symmetry that allowed for jumping into gaps in walls. (In jsw all the gaps are accessed by jumping left) If symmetry is introduced then those gap jumps become impossible. But the other problems become more noticeable. Passing through a wall In the code that checks for ramps and also checks for blocking the move left and right, was a check for reducing the three cell check to only two, when willy was cell aligned. The primary reason was when willy walks along a platform, the third cell was below his feet. Since he was walking along the top of the cells, they could not block his path. Hence the third cell check is removed for that reason. (otherwise willy can not walk along a wall) However when willy is jumping the third cell is crucial for deciding if willy can move. g00a h00b kcde In the text diagram above willy occupies the four squares with "0" in them, in this case willy is jumping right and is on his way down. The two squares with "a" and "b" are clear. Since willy in this thought experiment is now cell aligned. The present routine has decided that "e" can be ignored. This then permits willy to move diagonally downward to the right to now occupy the cell "e". This is why the jump right on the "FIRST LANDING" passes through a square and lands inside the floor when jumping the gap on the lower floor. If I add a check for falling into the routine that checks for wall blocking when moving. The purpose of which is solely to force the third cell check when falling. Then this particular problem disappears. However it still permits passing though a wall block in "on top of the house" when walking down a stair (because those blocks are NOT checked by the stair check routine) Symmetry The third cell check stops one problem. But Symmetry causes a problem when jumping into gaps. Again looking at the text diagram, the cell "g" was not tested moving left, and that permitted walking through cells at head height. The cell "a" was tested when walking right. It is the lack of cell testing that permits jumping into wall gaps, when jumping left. The symmetrical code I posted will not permit jumping into two cell wide gaps in specific conditions because of the extra check. The jump left in "ball room east" into the gap above the red barrel can no longer be done. The reason is because the checking now stop movement into wall tiles. The gap was only two cells wide only when cell aligned. This does not happen when jumping from a horizontal position (which is level with the gap), because the forward motion has ceased at the exact point that the cells are aligned. From my viewpoint the non symmetry was deliberate, and in looking at the way the code is written, it is possible the change in logic from left and right was a quirk that was exploited I however prefer these anomalies to be written out of the code. Whatever it does one way should be the same the other way. Back to the cell checking.. Introducing a specific check for jumping (downward) to force a third square check, stops the movement into wall cells on jumping downward. It also appears that stopping the check for willies head when jumping and moving downward either left or right. Re-enables the passage into gaps. Removing the check for willies head (cell "g" or cell "a") but forcing the check for the third tile, means that willy can move into a two cell wide gap. In practical terms this is similar to permitting passage through the corner of a wall cell on his way down, only if the two cells below are not occupied by a wall. This Matthew style FIX permits a one frame movement into the gap. I have not had a good look at the code to implement these changes, in a manner that I am happy with. I have however added two additional pieces of code to implement these changes, which seem to do as I want. Which is symmetry in movement. 1) checking head height cell and blocking willy from moving through them ... *NOTE 1 2) ability to still jump into gaps 3) stop passage into wall cells *Note 1 The upper Platform in "the Forgotten Abbey" if left as a wall will block Willy walking of the conveyor underneath it. Edited December 17, 2017 by Norman Sword IRF and Spider 2 Quote Link to comment Share on other sites More sharing options...
IRF Posted December 17, 2017 Report Share Posted December 17, 2017 (edited) 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.) Edited December 17, 2017 by IRF Spider 1 Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.