andrewbroad Posted March 14, 2016 Report Share Posted March 14, 2016 (edited) And one more reflection about inserting two "main" patch vectors. While probably possible technically (why not?), I think it simply wouldn't make much sense. A patch vector is a subroutine, a chunk of code, which does something special in the room, and the two bytes in the room data point to where the patch vector for this particular room should be activated from (where it starts). The patch vector may include various elements, including calls to other subroutines. So, once you have been able to call a patch vector, you can make it perform all the tricks you want for this room. So you don't need a second patch vector. It could be useful to have a room-setup patch vector in addition to the main-loop patch-vector. John Elliott Edited March 14, 2016 by andrewbroad Spider and jetsetdanny 2 Quote Link to comment Share on other sites More sharing options...
IRF Posted April 9, 2016 Report Share Posted April 9, 2016 (edited) First of all, what I call "the main patch vector" (which Geoff simply calls "the patch vector", but they are all patch vectors, so I think it's good to distinguish this one from all the other, room-specific ones) has to be called from the main game loop. Geoff does it at #89F5-#89F7. I'm not sure if it has to necessarily be in this very spot, but I have just followed what Geoff did and placed it there and it works fine. So at #89F5 you have to insert the following code: CD x y CD is the CALL instruction, and x y are the two parts of the address where your "main patch vector" will be, in reversed order. So, for example, if you place the main patch vector at #8141, the CALL instruction at #89F5 has to be: CD 41 81 Now, in order to be able to insert the call instruction at #89F5, you need to have three bytes of unused space there. These are easy to achieve in a non-modified JSW48 game, because there is code which is unused at #8A0B - #8A25. So my suggestion is to (for example): - Move the code at #89F5-#8A0A three bytes down to #89F8-#8A0D (this frees up #89F5-#89F7). - Insert "CD 41 81" at #89F5-#89F7. - NOP out (set to zeroes) the addresses #8A0E-#8A25. In this case, the main patch vector is set to be at #8141. This address is the beginning of unused space which extends until #81FF in an unmodified JSW48 game. The main patch vector is 5 bytes long and it is the following code: 2A EE 80 E9 C9 So you need to insert this code at #8141-#8145. It could be inserted somewhere else where free space is, of course; in such case the CALL command at #89F5-#89F7 would have to be adjusted accordingly (to show the correct address). Now, as quoted before, the main patch vector uses two bytes within the room data of each room to specify the location of a subroutine which will be called to achieve some special effects. These bytes are always at #nnEE and #nnEF in the room data. So, for example, they would be at #C0EE and #C0EF in "The Off Licence" in the original "JSW". Now, after applying the instruction to call the main patch vector and the main patch vector itself, the value of the addresses #nnEE and #nnEF in *every* room has to be modified adequately, i.e. it has to hold the address of the patch vector meant for this room or - if no patch vector is meant for this room - it *has* to point to the address where the C9 (RET) instruction is in the main patch vector. So in the example we are discussing, in every room where no patch vector is to be applied, the value of #nnEE and #nnEF *has* to be 45 81 - because the instruction C9 at the end of the main patch vector is at 8145. Otherwise the game will crash upon entering a room where this has not been set properly. In the rooms where specific patch vectors are to be applied, the value of #nnEE and #nnEF should point to the addresses where these patch vectors start. So, for example, using the free space extending between #8141 and #81FF, we we could insert a patch vector which will do something special in "The Off Licence". We could place this patch vector right after the main patch vector, starting at #8146. So the value of the addresses #C0EE and #C0EF would have to be, respectively, 46 and 81, to point to the address 8146 where the patch vector for this room begins. Danny, I believe that there is one aspect which you omitted to mention in your otherwise comprehensive (and much-appreciated) guide to inserting Patch Vectors. Namely, the fact that each Patch Vector should be concluded with a 'C9' Return command. You did explicitly point out that the Main Patch Vector ends with a 'C9' (which returns the program back to the main loop by default, for those rooms that don't have a room-specific Patch Vector). However, I think your guide should explicitly mention the fact that when a room-specific PV is called up, the relevant chunk of code should also end in a 'C9' command. (May I kindly suggest that you edit your initial post in this thread accordingly?) By the way, my ruminations on this have helped me to understand why the Main PV is called up from the Main Loop, rather than having been directly inserted into the Main Loop (which on the face of it would save four bytes: 3 for the Call and 1 for the Return). I still maintain that the Main PV could be inserted into the Main Loop (as per our previous discussion). However, it would mean that each and every room-specific PV would have to be terminated with a 3-byte Direct Jump command (or at best a 2-byte Relative Jump, if a particular PV's address happened to be within 128 bytes of the Main Loop), rather than a single-byte Return. So the notional 'saving' of 4 bytes, achieved by inserting the Main Patch Vector into the Main Loop, would soon be overtaken by the increased length of all the room-specific Patch Vectors! Edited April 9, 2016 by IRF Quote Link to comment Share on other sites More sharing options...
IRF Posted April 10, 2016 Report Share Posted April 10, 2016 (edited) Now, as quoted before, the main patch vector uses two bytes within the room data of each room to specify the location of a subroutine which will be called to achieve some special effects. I guess that the need to 'return' is implicit in the above sentence, but it would be good to make it explicit in your guide. EDIT: Is the definition of a 'sub-routine' a section of code that is arrived at by being called up from elsewhere, and which therefore requires, by its very definition, to be terminated with a 'return'? I've been using the term to refer to certain parts (i.e. subsections) within a routine which don't need to be 'called up' as such. (For example, the 'Play a note of the in-game music' subsection of code within the Main Loop.) But that might have been sloppy use of language on my part? (It wouldn't be the first time!) Edited April 10, 2016 by IRF Quote Link to comment Share on other sites More sharing options...
jetsetdanny Posted April 10, 2016 Author Report Share Posted April 10, 2016 To be honest, I use the word "subroutine" from time to time, but I'm not 100% sure how it should be defined. I perceive it as a part of a "major" routine, if that makes sense. Wikipedia has this to say about it: In computer programming, a subroutine is a sequence of program instructions that perform a specific task, packaged as a unit. This unit can then be used in programs wherever that particular task should be performed. Subprograms may be defined within programs, or separately in libraries that can be used by multiple programs. In different programming languages, a subroutine may be called a procedure, a function, a routine, a method, or a subprogram. andrewbroad 1 Quote Link to comment Share on other sites More sharing options...
jetsetdanny Posted April 10, 2016 Author Report Share Posted April 10, 2016 Done as you have suggested, Ian! I have edited my original post, including a mention that it's done on your advice :) . An astute observer will note that in "WNM SE" there will be patch vectors in 62 out of the 66 rooms of the game... ;) IRF 1 Quote Link to comment Share on other sites More sharing options...
IRF Posted April 10, 2016 Report Share Posted April 10, 2016 Could you perhaps squeeze a few more bytes out of the code so that EVERY room has one? (e.g. the spare 6 bytes in G127's data, if you haven't already used them?) Quote Link to comment Share on other sites More sharing options...
IRF Posted April 10, 2016 Report Share Posted April 10, 2016 Thanks for the credit, Danny! . It has to happen at the very of the patch vector, of course Just to be pedantic, the word 'end' is missing there, I think? Quote Link to comment Share on other sites More sharing options...
jetsetdanny Posted April 10, 2016 Author Report Share Posted April 10, 2016 Corrected Thanks for the credit, Danny!Just to be pedantic, the word 'end' is missing there, I think? Corrected! You *are* an astute observer, Ian! :) IRF and Spider 2 Quote Link to comment Share on other sites More sharing options...
jetsetdanny Posted April 10, 2016 Author Report Share Posted April 10, 2016 Could you perhaps squeeze a few more bytes out of the code so that EVERY room has one? (e.g. the spare 6 bytes in G127's data, if you haven't already used them?) My preference is to leave some rooms without patch vectors, for various reasons, both room-specific and general, the general one being to prove that it is also possible to have rooms *without* any PVs ;) . Not all rooms where there are active PVs have PVs which are exclusive. In other words, there are several PVs which are applied, without any variation, in more than one room. So it wouldn't be a problem to add some of them to the rooms which have no active PVs at the moment. However, I don't think I will be doing it. Spider and IRF 2 Quote Link to comment Share on other sites More sharing options...
andrewbroad Posted April 10, 2016 Report Share Posted April 10, 2016 To be honest, I use the word "subroutine" from time to time, but I'm not 100% sure how it should be defined. I perceive it as a part of a "major" routine, if that makes sense. Wikipedia has this to say about it: In computer programming, a subroutine is a sequence of program instructions that perform a specific task, packaged as a unit. This unit can then be used in programs wherever that particular task should be performed. Subprograms may be defined within programs, or separately in libraries that can be used by multiple programs. In different programming languages, a subroutine may be called a procedure, a function, a routine, a method, or a subprogram. In Z80 machine code, CALLing a subroutine pushes the address of the next instruction after the CALL instruction onto the stack, and sets the program counter to the address specified by the CALL instruction, so as to execute the subroutine. RETurning from a subroutine pops the return address off the stack, and sets the program counter to the return address, so as to execute the next instruction after the CALL. Whereas a jump (JP or JR) instruction simply sets the program counter without affecting the stack. So a subroutine is a CALLable sequence of instructions with at least one RET instruction. Spider, IRF and jetsetdanny 3 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.