Jump to content


Photo

Free space and code optimisation in "JSW"


240 replies to this topic

#11 JohnElliott

JohnElliott

    Newbie

  • Contributor
  • 8 posts

Posted 12 June 2016 - 07:04 PM

It could be a rope, certainly. I do have the 'adjacent ropes patch' in place. It even occured to me that *it* could be using this space to write data to (instead of the buffer at 81..).

 

In any case, this area is now 'too suspicious' for me to place any code...

 

Not guilty, yerhonner. The adjacent ropes patch doesn't use any of this space.



#12 IRF

IRF

    Advanced Member

  • Contributor
  • 3,744 posts

Posted 12 June 2016 - 07:13 PM

Not guilty, yerhonner. The adjacent ropes patch doesn't use any of this space.

 

I'd be interested to know exactly how the adjacent ropes patch does work.  Here's my best guess, without studying the relevant code:

 

As I understand it, one of the 'regular' 8 bytes for the rope definition is unused in the original game, which is rather inefficient - perhaps you used that (Byte 6) for the 'Index of the segment of rope being drawn' (which populates Byte 9 in the original game)?

 

Then the only other thing that would need to be shifted, to prevent an 'overspill' into the next guardian's definition data, is a single Bit of Byte 11, which in original JSW is used as an indicator of whether Willy is on the rope (as in this particular rope - otherwise the Airborne Status Indicator, which tells you whether Willy is on a rope, could do the job!)  Perhaps you reassigned this function to one of the unused Bits of Byte 0 of the rope definition?



#13 JohnElliott

JohnElliott

    Newbie

  • Contributor
  • 8 posts

Posted 12 June 2016 - 07:56 PM

From the start of the source file:

; Adjacent Ropes patch (second try)
;
; Change all IX+9 references to IX+6
; Change all IX+11 (bit 0) references to IX+0 (bit 5)
;


#14 IRF

IRF

    Advanced Member

  • Contributor
  • 3,744 posts

Posted 12 June 2016 - 08:55 PM

Thanks John.  It looks like my guess was spot on!

 

I presume the lower 'unused Bits' of Guardian Definition Byte 0 are used for defining higher values of the Guardian Type? (i.e. beyond the standard horizontal/vertical/rope/arrow.)


Edited by IRF, 13 June 2016 - 12:46 AM.


#15 IRF

IRF

    Advanced Member

  • Contributor
  • 3,744 posts

Posted 15 June 2016 - 09:03 AM

 

From the start of the source file:

; Adjacent Ropes patch (second try)
;
; Change all IX+9 references to IX+6
; Change all IX+11 (bit 0) references to IX+0 (bit 5)
;

 

Out of interest John, how did the 'Old' adjacent ropes patch work? (Or not, as the case may be!?)


Edited by IRF, 15 June 2016 - 09:07 AM.


#16 JohnElliott

JohnElliott

    Newbie

  • Contributor
  • 8 posts

Posted 15 June 2016 - 06:33 PM

Out of interest John, how did the 'Old' adjacent ropes patch work? (Or not, as the case may be!?)

 

The original one only fixed up the IX+9 references, not the IX+11 ones.



#17 IRF

IRF

    Advanced Member

  • Contributor
  • 3,744 posts

Posted 15 June 2016 - 06:49 PM

Thanks, John.
 

I've done just that and the results are not encouraging.
 
I put the code which stops the border from getting stuck on the wrong colour for the room Willy is in, if Willy collects an item or the arrow warning sound occurs whilst the in-game music is switched off (called from 925E and 941D) at A3F9 – A3FE. However, I found out that it didn't work.
 
The reason for it is that the byte at A3FA gets overwritten during the game  :( . I'm not sure what overwrites it, but I am not going to investigate it; I'll just look for another place to put the six bytes of the "border reversal" code.


Danny, is it the 'old' or 'new' adjacent ropes patch that you had in place when you ran into the above problem?

 

Can you recall what exactly #A3FA was overwritten with?  Was it either 00 or 01, by any chance?


Edited by IRF, 15 June 2016 - 10:42 PM.


#18 jetsetdanny

jetsetdanny

    Advanced Member

  • Contributor
  • 1,893 posts

Posted 20 June 2016 - 01:54 PM

Well, to be honest - I don't know.

 

I was just going to say that both boxes (the one corresponding to "Adjacent ropes patch (new)" and the one corresponding to "Adjacent ropes patch (old)") are ticked and hypothesise that the "old" one gets ticked automatically once you tick the new one (because you can't apply both fixes at the same time).

 

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...

 

And concerning what exactly #A3FA was overwritten with - I can't remember. I *think* it wasn't 00 or 01, but I'm not sure. I do have these files somewhere, but I have hundreds of files of "WNM SE" already and it would be too time-consuming to try to find the right one now (it would actually be much quicker to just reinsert the code into the space in question and see what happens when the game starts).


  • IRF likes this

#19 IRF

IRF

    Advanced Member

  • Contributor
  • 3,744 posts

Posted 20 June 2016 - 02:11 PM

Don't worry, I just wondered if you could recall off the top of your head.

 

My theory as to what was going on was probably wrong anyway, as it would have involved #A3FB being overwritten (I think!?)

 

EDIT: Actually, I'm not even sure about that now!  I was thinking in terms of a rope's data 'overspilling' its eight bytes, but that should only really affect the bytes just after the 'Entity Buffer' at #8100, not the Entity Definitions that are copied into the buffer upon entry to each room.

 

FURTHER THOUGHT: Andrew Broad reported the 'Entity Specification' area of the Room Buffer being affected if Guardian Class 127 was defined (filling rooms that didn't already have 8 guardians with either Class 0 or Class 127 guardians), but again that involves corruption of areas of buffer code, not the 'source data' at #A0xx.


Edited by IRF, 20 June 2016 - 03:47 PM.


#20 IRF

IRF

    Advanced Member

  • Contributor
  • 3,744 posts

Posted 20 June 2016 - 03:47 PM

Regarding this post:

 

http://jswmm.co.uk/t...age-1#entry3701

 

I think I've got to the bottom of it!

Contrary to the impression you might have got from my previous post, the third byte of each Entity Definition in the #A000-A0FF range is overwritten during the course of the game! (Whilst the third bytes of each entity definition are initialised to zero, and listed as such in the disassembly, you may find that the values are non-zero in snapshot files.)

However, this doesn't normally matter, as the values of those bytes are 'instance-specific', and so are regularly updated using the second byte of the appropriate entry in the Entity Specification for each room, each time a guardian is inserted into a room.

Now, whenever the routine at #8912 comes across a 'Terminator' byte in a room's Guardian List data, it treats it as a 'Class 127 [#7F]' guardian (because Bit 7 of the first byte of the entity specification is reset at #892E), and so the subsequent value (i.e. the 'Guardian Specification' byte immediately following the 'FF 'Terminator', which would usually be 00 by default - but Danny, if in your WNM-SE file you had 'recycled' some of the spare bytes in unfilled rooms' Guardian List data, for other purposes, then it could be anything and could vary as Willy moves from room to room!) is copied into the address #A3FA (which is the third byte of Guardian Class 127's eight Definition Bytes!) - mystery solved!

The way to prevent this would be to tweak the routine at #8912. Immediately after the 'Pick up the first byte of the entity specification' LD L, (IX+$00), remove the RES 7, L and replace it with a check 'Is it #FF?':  EX AF, AF'LD A, LCP $FF. [If not, skip the next three bytes.]  If so, copy 'FF' to the address that is currently pointed at by the 'DE' register pair (i.e. the first byte of the Entity Buffer entry that is currently under consideration) and then jump forward to #894A, bypassing the loops which populate the rest of the entity buffer: JR NZ $03; LD (DE), A; JR $1BEX AF, AF'.  [The purpose of the two bookending EX AF, AF' commands is to retain, in A', the value of the A register which is counting down, from a starting value of 8, the number of entities being considered.  Once the loop is exited early by the presence of an 'FF' Terminator byte, the value of A' no longer needs to be retained.]

 

If the guardian specification byte under consideration isn't an 'FF' Terminator, then the existing code is resumed at #8930 (after passing through the second EX AF, AF' command to restore the 'entity counter' to A). N.B. the operand of the relative jump at #8948 would need to be changed accordingly, to ensure that it still loops back to #892B.

 

[In Z80 code: remove 'CB BD' from #892E; insert '08 7D FE FF 20 03 12 18 1B 08'; replace '20 E1' previously at #8948 with '20 D9'.]

 

The above would probably require some consolidation, although a relative jump could be squeezed into the space currently occupied by the RES 7, L command, which might help if the other few bytes could be located within 128 bytes of the source address. In which case, the operands of the new relative jumps above would need to be altered, and a new jump back to #8930 inserted at the end.

 

Alternatively, the nearby efficiencies that we have already identified should just about be enough to allow the additional 8 bytes of code to be inserted in situ i.e. by setting the border colour more efficiently at #8980; swapping the absolute jump at #8988 for a relative jump; removing the 'DI' command at #8898; and swapping the absolute jumps at #8892 and #88AE for relative jumps.

[With the above in place, when a 'Terminator' byte is encountered by the program whilst it is filling the entity buffer, the rest of the buffer may retain the data from the previous room, rather than being filled with '00's.  However, that won't matter because the 'Move the guardians' and 'Draw the guardians' routines will in any case skip all subsequent addresses in the entity buffer as soon as they encounter a 'FF' value.  EDIT: Although a Rope might pick up un-erased values in the second and fourth bytes of the next guardian in the list, potentially triggering the Rope-Teleport Bug, so you should ensure that John Elliott's Adjacent Ropes Patch (New) is in place - but then, I would strongly recommend that you have that in place in any game file in any case!]

In theory, the suggested changes to the code would allow Guardian Class 127 to be safely defined, provided that #A3FF's use as an 'Item Index' is reallocated to another address*. It would be entered into a room's guardian list as Class #7F, and (with the RES 7, L command expunged) it would be treated differently to an 'FF' Terminator byte.

 

(* Or the LD A, ($A3FF) commands at #8802 and #93D3 could be replaced with LD A, $00 [the operand being the previous value of #A3FF] - saving two bytes - or in a game with 256 items, simply replaced with XOR A instructions - saving four bytes.)

 

{One other caveat: you would have to make sure that all the 'even' Entity Specification Bytes in every room were within the range 00-7F [apart from the FF Terminator, of course]; otherwise, higher values (with Bit 7 set) would cause the program to try and interpret data in the range #A400-A7FF [Item Table data, Toilet graphic bytes, etc] as guardian definition bytes - which could be 'fun'!!  There's no reason why that would happen, though, unless you deliberately - manually in the hex editor - enter a Guardian Class 128-254 into a room's Guardian List!}


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





0 user(s) are reading this topic

0 members, 0 guests, 0 anonymous users