-
Posts
5,112 -
Joined
-
Last visited
Everything posted by IRF
-
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!
-
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.
-
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. :)
-
Try POKE #8C39, #57 in JSW, and then lose all your lives, for an interesting variation on the original Game Over sequence...
-
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.
-
It could be anywhere that there are 32 contiguous zero bytes in the code.
-
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.)
-
No I haven't tried it out yet, and yes I think you might be right about me being one Willy out. The problem would become evident immediately upon testing of course. I was going to do a DEC A before the RLCA, but forgot, and in any case using ADD #9E would be more byte-efficient.
-
The above intervention in the 'Lose a life' routine is actually one byte longer than the code which it makes redundant at #8958-64. However, replacing the LD C, #00 with a LD C,E command (E is defined as zero by the previous LD DE) will make the change 'globally byte-neutral'.
-
In between the commands that are currently at #8C3B and #8C3C, do: RLCA ADD A, #A0 #9E LD L, A LD H, #50 LD DE, #9800 [points DE at 32 contiguous NOPPED out bytes] LD C, #00 CALL #9456 Then there is no need to wipe the bottom third of the screen at room refresh (i.e. you may delete #8958-#8964 entirely). Nor is there a need to print the Items/Time character row at each room refresh, as long as that is done once at the start of the game (i.e. the code currently at #8971-#897C can be cut and pasted somewhere after #88FC but before #8912). N.B. If the standard 'Infinite Lives' POKE is applied (#8C3B, #00 or POKE 35899,0 in decimal), then I suspect that when Willy is killed, the right-hand life on the status bar might disappear briefly and then reappear - as if that life is magically regenerated! Which might be quite a nice effect!
-
That alternative approach should save a few bytes as well. (#857C-84.)
-
Actually, instead of the clock update code editing the ASCII values at addresses #857F-84, and then the contents of those addresses being printed to the display file (to overwrite the zeroes in the 32-byte message that is printed separately from #8554-8573) - couldn't the clock update code just edit the ASCII values of the addresses #856D-72, which are embedded within the 32-byte message? Ditto with the item count update code - instead of editing the addresses #857C-E (which are then copied over to the display file separately, again to overwrite zeroes), the routine at #93D1 could just work directly on #8564-66. With the game initialisation code setting both the start time and item count directly within the 32-byte message as well. Then when the Room setup routine printed that character line, it would be writing the correct values instead of zeros. It would make things a lot simpler! (Unless there's some reason that I haven't thought of which would preclude this approach?)
-
Yes, I'm getting the hang of your 'modus operandi' now!
-
Actually - note to self - the code at #88FC-#8906 really belongs at the start of the 'Display the title screen and play the theme tune' routine (next to the code which initialises the item count to zero).
-
The other day, following your previous comments on the matter, I was thinking about ways that would allow for the clock and item count to be printed only at the point when those elements actually need to be updated. If the text of the pertinent character line wasn't printed (with default '0's for the time and item count - see #8971-897C) each time the room is refreshed, then you wouldn't have to regularly overwrite the '0's. That character line could be printed once, at the start of the game (after #88FC, but prior to the 'Room setup' entry point at #8912). You would also need to print the initial values for the time and number of items at that point. But there is also a bit of code which wipes all the pixels from the bottom third of the screen whenever the room is refreshed (see #8958-8964). I tried removing that completely from the 'Room setup' routine, which only had one drawback - it meant that when Willy loses a life, the remaining lives carry on dancing, but the expired life was still shown (unanimated) on the status bar*. I thought that could be quite a cool effect, to distinguish the static, expired lives from the living, dancing ones - except that of course none of the lives dance if the in-game music isn't playing. So I'm considering a couple of options: - Enforce the animation of the remaining lives even if the music isn't playing (by tying the animation to the 'game clock' variable #85CB, instead of the 'music note index' at #85E1); - Every time Willy loses a life, erase the four character squares corresponding to the life that has just been lost (via an intervention at #8C3B). [*N.B. In Manic Miner, there may also be an issue with the air supply bar - if the program doesn't wipe the entire bottom screen-third, then the full length of the air supply character-row may need to be erased at 'cavern refresh', before the appropriate amount of air for the current cavern is drawn in.]
-
I was thinking that in the routine which animates the conveyor, maybe the code at #9507-#950B should come before the code from #94F9 to #9506? Otherwise, in rooms that have no conveyor, the program needlessly calculates the pixel-buffer addresses for the start of a non-existent conveyor. I'm not sure whether swapping the code round as suggested above would cause a perceptible increase in execution speed (in conveyor-less rooms), but as you say, slowdown is accumulative.
-
Don't worry, it's here on record now. Thank you for the clarification (and for the original optimisation!)
-
That looks like it only rotates the pertinent pair of graphic bytes once per time-frame? Meaning that the Master Bed would visible animate? (Whereas it doesn't in the original game, because the pixel pattern is such that two rotations, in either direction, leave the value of the bytes unchanged.) Talking of making tweaks to the original arrangement, adjusting the number of INC H commands will allow a different pixel-row of the conveyor, at an arbitrary depth beneath the top pixel-row, to act as the counter-rotating element of the conveyor.
-
Yes, that's what I meant. (Draw the arrow shaft first before reacting to the Zero Flag.) In relation to the byte count, I merely meant to point out that you did yourself a disservice!
-
Error in Norman Sword's post about the conveyor animation?: http://jswmm.co.uk/topic/185-free-space-and-code-optimisation-in-jsw/page-8?do=findComment&comment=6105 Shouldn't that be a LD A,(DE) in the context of the revised logic?
-
I believe that the running total of saved bytes at that point should be 10, rather than 9? I think it could also be done without using B (the net byte-saving would be the same). From #928E (rejigged code shown in bold): LD A,(IX+$06) LD (HL),A INC H INC H LD (HL),A DEC H LD A,(HL) AND C JP NZ,#90B7 ;>>>>> kill Willy LD (HL),#FF JP #93B3 The above arrangement would also mean that the arrow is drawn in its entirety at the moment when it hits Willy (whereas in the original code, only the top pixel-row is drawn at the point of death).
-
The above approach should also allow the code which draws Willy and the Toilet to be optimised, by simply setting the appropriate variables and then jumping to the routine at #9456.
-
In original JSW, at the instant when Willy collides with a guardian, that guardian is only drawn as far the graphical byte which collided with Willy. Furthermore, all guardians that appear subsequently in the current room's guardian list are not drawn at all in that moment. (That latter point means that composite guardians - for example the three-part Evil Priest Head or the Attic Centipede - are rendered incompletely at the time of Willy's collision with one component part of them*.) In the attached file, all the guardians (and arrows and ropes) in the current room are drawn in their entirety at the moment when Willy is killed by colliding with one of them. Note that in the attached file, the room still appears as 'empty' - without guardians, items or Willy - whenever Willy hits a Fire cell or falls a fatal distance. EDIT: * Unless it is the last component part to be drawn which is the one that Willy collides with. Complete Guardians.z80
-
The following sequence in the arrow-drawing code, at #927D, is used to detect a cell containing white INK: AND #07 CP #07 JR NZ... In Geoff Mode this is replaced with the following sequence, providing a saving of one byte (it is in a slightly different location in Geoff Mode, at #9271): INC A AND #07 JR NZ... This trick could be repeated at #93ED, in the item-drawing code, which also seeks out white INK cells.
-
Norman's latest contribution looks ingenious! I haven't fully got my head around it yet, but the basic principle is that, in his previous incarnation, only the lower nybble of the rope data table were used, so now he's merged pairs of entries so that it takes up half the space!