Jump to content


Photo

Free space and code optimisation in "JSW"


240 replies to this topic

#21 IRF

IRF

    Advanced Member

  • Contributor
  • 3,760 posts

Posted 20 June 2016 - 04:16 PM

Oh, and one more point, returning to Danny's original enquiry: since only #A3FA is overwritten during the course of the game (for the reason described above), the other five unused guardian definition bytes (#A3F9 and #A3FB-E) should be perfectly safe to re-use.


Edited by IRF, 20 June 2016 - 04:41 PM.


#22 JohnElliott

JohnElliott

    Newbie

  • Contributor
  • 8 posts

Posted 20 June 2016 - 06:41 PM

However, I've just had a look in JSWED, in the Game tab, and it looks like both of these boxes (as well as *all* of the other ones *except* for "Black Willy") *cannot* be either ticked or unticked - they are filled with blue, sort of. I'm not quite sure how to interpret this...

 

It means that at least one byte in a location touched by the patch is neither the original one from JSW, nor the modified one from the patch. So JSWED cannot safely apply or deapply the patch.



#23 IRF

IRF

    Advanced Member

  • Contributor
  • 3,760 posts

Posted 21 June 2016 - 01:02 AM

Further to my earlier post, I now can report that I have safely inserted a Guardian of Class 127 into a test file!  Everything is working fine, including the Item Drawing and Item Collection loops (which no longer call up the value of #A3FF).

 

However, JSWED doesn't display the first 25 items in the Item Table for some reason* - although they are present and collectable in the game.  This occurred in a game with 256 items, so it may not affect games to the same extent where there are fewer items present.

 

In any case, I recommend that you only make the enabling code changes to insert a Guardian Class 127, after you've got to the point where you're happy with the item distribution in a game.  (Although subsequent changes to item distribution can of course be made via the hex editor.)

 

* EDIT: I've just realised that it's happening because the last byte of the Guardian Class 127's definition just so happens to be #19 (25 in decimal) - JSWED is still picking up the value of #A3FF in order to display the items!

 

As I said, it doesn't affect the game itself, but to prevent this glitch in JSWED, you could simply ensure that one of your Arrow Guardian Classes occupies slot 127 (#A3F8-A3FF), since the eighth byte of an Arrow's definition is unused.  So you could insert the value [256 minus the number of items in the game] at #A3FF, just for the purpose of viewing all the items in JSWED, and it wouldn't affect the Arrows at all.  (The eighth byte of an Arrow's definition is normally 0 by default anyway, which suits a game with 256 items, but it doesn't have to be.)

 

Actually, that would negate the need to make the changes to the code at #8802 and #93D3 (although those changes can in themselves provide useful byte-efficiencies at pinch-points in the code).

 

UPDATE: It is far safer to have an Arrow occupy Class 127, as otherwise if you alter the number of items in JSWED, the editor changes the value of the eighth byte of Class 127's definition - the maximum extent of the range of a horizontal/vertical guardian or rope - which could cause the guardian to collide with room elements!

 

Arrows are absolutely fine as Class 127 though!  So if you shift one of your existing arrow definitions to #A3F8-A3FF (quite easy to do as half of the bytes are 00), then you'll free up a slot that's easily editable in JSWED for your new guardian class!  And then you can safely make changes to the number of items in JSWED; the redundant eighth byte of the Class 127 Arrow definition will be updated, with no impact whatsoever on the function of the Arrow!


Edited by IRF, 04 July 2016 - 04:30 PM.


#24 IRF

IRF

    Advanced Member

  • Contributor
  • 3,760 posts

Posted 23 June 2016 - 03:24 PM

A few other tips about inserting Guardian Class 127:

 

- Since JSWED doesn't recognise G127, it has to be created manually using the hex editor, populating the eight bytes #A3F8-A3FF in the Entity Definitions section.  Thus it is most convenient to copy the eight bytes of an existing Arrow definition across to those addresses, and then create the new Guardian Class in the space where the Arrow definition used to sit (e.g. Class 45 in original JSW).  That way you can use JSWED's Graphical User Interface to create the new guardian in the normal way.

 

- Each instance of the newly-defined G127 Arrow has to be manually inserted into the Guardian List for each room where it appears, by altering the first specification byte from '45' [or whatever] to '7F'.  If you leave the second specification byte unchanged, then the y-coordinate of the G127 Arrows will be the same as before (including Invalid values if required).

 

- Arrows usually appear last in a Guardian List, which is another reason to use Class 127 for Arrows - to minimise the need to manually rearrange the other guardians in the list. (i.e. if you created a Vertical G127 Guardian in a room with an Arrow, you would have to place it before the Arrow and manually insert the Arrow afterwards in the hex code, to prevent a potential fatal collision).

 

- Finally, an 'FF' Terminator byte has to be manually added at the end of any Guardian List that has had a G127 inserted (unless the list is filled with the maximum of eight 'entities').  JSWED normally does this automatically to terminate the list, but it won't in this case - possibly because it thinks that '7F' will do the job of terminating the list (which, to be fair, it used to do prior to the application of the code changes set out in Post #20 of this thread).

 

- Additional point: Make sure you have the Adjacent Ropes Patch (New) in place, so that any data left 'lying around' in the Entity Buffer after the FF Terminator byte, can't trigger the Rope-Teleport Bug!


Edited by IRF, 11 July 2016 - 11:57 PM.


#25 jetsetdanny

jetsetdanny

    Advanced Member

  • Contributor
  • 1,895 posts

Posted 02 July 2016 - 10:52 AM

I would like to add another suggestion to this open thread, copying it from Ian (IRF)'s PM. This is Ian's "invention", which I would like to quote while at the same time testifying that it works just fine - I have applied it in the (soon-to-be-released) Special Edition of "Willy's New Mansion".

 

So here is Ian's idea:

 

---

More potential spare bytes: In any room where there is no Ramp or Conveyor (or Fire cells, etc) - the eight (contiguous) graphic bytes associated with each such unused room element.

This also applies where there are composite room elements (Ramp-Conveyors, etc), for the eight graphic bytes of whichever component is lower down the list (Conveyors in the example of Ramp-Conveyors). Because the pixel pattern of the earlier room component will be picked up and used to draw the composite cells (e.g. the Ramp graphic in the above example), the space in the code attibuted to the pixel pattern of the latter component (e.g. Conveyor) is unused.

However, in contrast, recycling the unused cell attribute bytes is not safe, since a Z80 command inserted therein might accidentally match an attribute byte of another room element, affecting the properties of such elements.

e.g. if Water cells on a particular, Ramp-less screen have colour attributes set to Blue Ink on Green Paper [00100001 - #21 in hex], and then a '21' (LD HL, $00) command were to be inserted into the attribute byte for Ramps on that screen, then all Water cells would become Water-Ramps!

N.B. It is only safe to use the eight spare graphic bytes if Stuart's Cell Graphics Bug Fix is in place (otherwise the same 'coincidence effect' mentioned above could take place!)

---

 

I would just rephrase the above saying that if the value of the new code does *not* match the cell attribute, it is safe to use the attribute byte as well. And, in fact, the probability of the two values matching is rather low, I believe. So in most cases you can have additional 9 spare bytes for each element if Air, Water, Earth, Fire or Ramp are not used in a room. Furthermore, you can have additional 12 bytes for the conveyor, because  after the 9 bytes analogous to the other cell types (at ... CD - ... D5) there follow immediately four more bytes specific to the coveyor (at ... D6 - ... D9) and the last of them is length. So I believe that as long as the length byte is set to 0, the other additional bytes (specifying the direction of the conveyor and its location in the attribute buffer) can be safely overwritten (if there is no conveyor, it doesn't matter what direction is has).

 

SkoolKid's disassembly illustrates the layout of this potential free space.

 

In one instance in the Special Edition of "Willy's New Mansion" (the room "Internet Cafe", where Fire, Ramp or Conveyor cells are not used) I had a continuous chunk of 30 spare bytes, which is quite a lot! 

 

Many thanks to Ian for his insightful coming up with this helpful idea!  :) 



#26 IRF

IRF

    Advanced Member

  • Contributor
  • 3,760 posts

Posted 02 July 2016 - 12:02 PM

Danny, you could go even further with that approach! You could also use the first three of the following four bytes (Offsets #DA-DD - the Ramp definition bytes), as long as the preceding code happened to have a zero at Offset #D9 (corresponding to a Conveyor length of 0).

e.g. Consider the sequence of code that draws or writes attributes to an area of the screen, terminating in a LDIR command. If the length parameter of the LDIR loop is less than 256, and the penultimate* instruction is 'LD BC, $0000' which takes the Z80 format '01 XY 00' [length of loop is represented by C=XY; the higher byte B=00]. Thus if the last byte of that command sits at Offset #D9, then the LDIR command (2 bytes) and a terminating 'C9' Return could occupy Offsets #DA-DC.

Offset #DD would have to be set to 00 though, to ensure that the Ramp length is zero.

(* In some LDIR loops there is also a command such as LD (HL), $00 [Z80 opcode '36'] or LD (HL), A [Z80 opcode '77'] that sets an initial value for e.g. a colour attribute, prior to the loop commencing - but I believe that can be placed before the LD BC command, rather than afterwards, thus facilitating the above suggestion.)


Edited by IRF, 03 July 2016 - 10:22 AM.


#27 jetsetdanny

jetsetdanny

    Advanced Member

  • Contributor
  • 1,895 posts

Posted 02 July 2016 - 07:07 PM

Thanks for the suggestion, Ian.

 

I guess it could also work if Offset #D9 was left as 00 as a break in the code (NOPPed out, so to speak). So, for example, there would be some meaningful code before it, then 00 at #D9 and then e.g. a jump to somewhere else (C3 .. .. ) at #DA - #DC.

 

I doubt I will apply it in "WNM SE" (there's no need for it), but it's something to keep in mind for the future...


  • IRF likes this

#28 IRF

IRF

    Advanced Member

  • Contributor
  • 3,760 posts

Posted 02 July 2016 - 07:46 PM

Indeed, you could jump to the remaining chunk of five spare bytes in the guardian data for one of the rooms...

#29 IRF

IRF

    Advanced Member

  • Contributor
  • 3,760 posts

Posted 02 July 2016 - 07:50 PM

One other thought - if a room doesn't contain any collectable items [e.g. the Master Bedroom in most games tends to avoid having items, unless you want to potentially see Maria suddenly vanish if they are the last to be collected!], then the eight bytes that define the item graphic are spare and can be put to other uses.  That's Offsets #E1 to #E8.


Edited by IRF, 04 July 2016 - 12:25 PM.


#30 IRF

IRF

    Advanced Member

  • Contributor
  • 3,760 posts

Posted 04 July 2016 - 12:17 PM

I would just rephrase the above saying that if the value of the new code does *not* match the cell attribute, it is safe to use the attribute byte as well. And, in fact, the probability of the two values matching is rather low, I believe.

 

Just to be on the safe side, you should double-check that any Z80 opcode, or operand, or data byte, that has been placed in a slot that is normally reserved for a room cell's attribute byte, does not match any of the attribute bytes for the other cell types for that particular room.

 

i.e. ensure that there is no match between Offsets #A0, #A9, #B2, #BB, #C4 or #CD [unless such a match has been deliberately implemented in a room, in order to create composite cells such as Water-Ramps etc.]


Edited by IRF, 04 July 2016 - 01:47 PM.





1 user(s) are reading this topic

0 members, 0 guests, 0 anonymous users


    Alexa (1)