Salk Posted March 8, 2017 Share Posted March 8, 2017 Hello!Here I come with another request for clarification. I read CamDawg's tutorial but I found it a bit hard to follow (all the part about BIT BOR and THIS is not clear to me) so I was wondering if someone could give me a practical example about how to use WeiDu to change, for instance, what kind of rooms are available in a specific inn. Let's say I want Feldepost's Inn to not offer Peasant and Merchant rooms (it is supposed to be a highly luxurious place to sleep at, after all). Currently a patron can sleep in Peasant, Merchant, Noble and Royal rooms. Using NI is just a matter of clicking twice but I would like to learn how to do it with WeiDU instead. COPY_EXISTING ~inn3351.sto~ ~override~ /* CONTENT */ BUT_ONLY I suppose WRITE_LONG 0x5c is needed but what else?Thanks! Link to comment
Roxanne Posted March 8, 2017 Share Posted March 8, 2017 COPY_EXISTING ~inn3351.sto~ ~override~WRITE_LONG 0x5c 12 //was 15 beforeBUT_ONLY Link to comment
Salk Posted March 8, 2017 Author Share Posted March 8, 2017 Thanks, Roxanne!Could you tell me how you came with that number (12) and how you knew it was 15 before? I managed to accomplish the same result with this: COPY_EXISTING ~inn3351.sto~ ~override~ WRITE_BYTE 0x5c 0b00001100 BUT_ONLY but I guess there is a difference and that someone can tell me which. Link to comment
Gwendolyne Posted March 8, 2017 Share Posted March 8, 2017 COPY_EXISTING ~inn3351.sto~ ~override~ WRITE_LONG 0x5c (THIS BAND BNOT BIT0) // remove Peasant rooms WRITE_LONG 0x5c (THIS BAND BNOT BIT1) // remove Merchant rooms BUT_ONLY And if you want to add peasant rooms : WRITE_LONG 0x5c THIS | BIT0 Link to comment
Roxanne Posted March 8, 2017 Share Posted March 8, 2017 Thanks, Roxanne! Could you tell me how you came with that number (12) and how you knew it was 15 before? I managed to accomplish the same result with this: COPY_EXISTING ~inn3351.sto~ ~override~ WRITE_BYTE 0x5c 0b00001100 BUT_ONLY but I guess there is a difference and that someone can tell me which. I think there is no difference. If you go to offset 5c (using NI) you get the flags display in plain language. Right clicking on it gives you options to display the field contents in different formats (Hex, binary, number...) There are probably a number of other methods. Link to comment
Salk Posted March 8, 2017 Author Share Posted March 8, 2017 Thank you very much for your help, Gwendolyne and Roxanne. Link to comment
subtledoctor Posted March 8, 2017 Share Posted March 8, 2017 Salk, as far as the BOR and BAND stuff, it took me a while to wrap my head around it as well. Here is the basic gist of its utility. Let's say my mod alters offset 0x5c of inn3351.sto like so: WRITE_BYTE 0x5c 0b10000000Now you come along and want to set the 3rd and 4th bits, as in your example above. The result will be, you will unto my change and break my mod. So you really want to set the 3rd and 4th bits, while making sure that you don't alter the other ones. In this case, you would use BOR. it means, "set a bit to 1, if either the existing version or my new version has that bit set to 1." So you first read the byte, and then apply you patch in that conditional manner: READ_BYTE 0x5c store WRITE_BYTE 0x5c (%store% BOR 0b00001100)That guarantees that the 3rd and 4th bits are set to 1, regardless of their original value. And it guarantees that the other six bits remain as they were before your patch - since you have them all at 0, they will only be set to 1 if they were already 1. BAND means "only set a bit to 1 if both the old version and my new version both set it to 1." BAND is used when you want to uncheck flags within a byte. You could reverse your change like so: READ_BYTE 0x5c store WRITE_BYTE 0x5c (%store% BAND 0b11110011)That will keep bits at 1 if they already were 1, except the 3rd and 4th bits which will become 0. Hope that's clear. I still have to pause for 10 seconds and work this stuff out in my head every time I do this. But it can be very handy. Link to comment
DavidW Posted March 8, 2017 Share Posted March 8, 2017 I'll make another attempt to generate interest in the SFO function library in SCS, in which you'd do this by LAF edit_store STR_VAR store=inn3351 editstring="room_peasant=>0 room_merchant=>0" END Link to comment
Salk Posted March 8, 2017 Author Share Posted March 8, 2017 Thank you very much for the tutorial, subtledoctor. Very useful. And that function seems really handy, DavidW. I'll see if I can figure out how to use the SFO function library. Thanks. Link to comment
Salk Posted March 9, 2017 Author Share Posted March 9, 2017 So you really want to set the 5th and 6th bits, while making sure that you don't alter the other ones. In this case, you would use BOR. it means, "set a bit to 1, if either the existing version or my new version has that bit set to 1." So you first read the byte, and then apply you patch in that conditional manner: READ_BYTE 0x5c store WRITE_BYTE 0x5c (%store% BOR 0x00001100)That guarantees that the 5th and 6th bits are set to 1, regardless of their original value. And it guarantees that the other six bits remain as they were before your patch - since you have them all at 0, they will only be set to 1 if they were already 1. A few observations: you wrote 0x00001100 but it should really be 0b00001100, right? Also, what I really wanted to set above were the 3rd and 4th bits, not the 5th and 6th ones, since they are counted from right to left? Said that, that piece of code alone is not sufficient because the Inn would *still* offer the rooms (Peasant and Merchant) that I do not want available, just because it is preserving the original bits. Am I supposed to add a second line like this? WRITE_BYTE 0x5c (%store% BAND 0b11111100) Or perhaps there is a one line way to do everything? Do you know how BNOT and THIS work, as in Gwendolyne's example? Thanks! Link to comment
Mike1072 Posted March 9, 2017 Share Posted March 9, 2017 Also, what I really wanted to set above were the 3rd and 4th bits, not the 5th and 6th ones, since they are counted from right to left? Yes, in 0b00001100, it is the third and fourth bits that are set to 1. They may be referred to as bit2 and bit3, because labelling starts with bit0 in the right-most column. Said that, that piece of code alone is not sufficient because the Inn would *still* offer the rooms (Peasant and Merchant) that I do not want available, just because it is preserving the original bits. Am I supposed to add a second line like this? WRITE_BYTE 0x5c (%store% BAND 0b11111100)Or perhaps there is a one line way to do everything? If you wanted to, you could chain them together like so: WRITE_BYTE 0x5c (%store% BAND 0b11111100) BOR 0b00001100(It's similar to arithmetic.) Do you know how BNOT and THIS work, as in Gwendolyne's example? THIS is a special variable that is automatically set every time you WRITE_ to a field. Before the WRITE_ occurs, the current value of the field is READ_ and stored in the variable named THIS. It's for convenience. READ_BYTE 0x5c store WRITE_BYTE 0x5c (%store% BOR 0b00001100)is equivalent to WRITE_BYTE 0x5c (THIS BOR 0b00001100) BNOT is a bitwise command that changes bits in a value - all the 0s become 1s and all the 1s become 0s. In Gwendolyne's example, WRITE_LONG 0x5c (THIS BAND BNOT BIT0), what's happening is BNOT is being applied to the variable BIT0. The BIT0 variable has a value of 0b00000001. Therefore, BNOT BIT0 is 0b11111110. So, if you BAND BNOT BIT0, you are preserving all bits except BIT0, which you set to 0. If you BOR BIT0, you preserve all bits except BIT0, which you set to 1. Link to comment
subtledoctor Posted March 9, 2017 Share Posted March 9, 2017 Yes - you are correct of course. I was writing off the top of my head, on my phone, on a train. I've updated my post for the sake of posterity. (I had always thought about the bits as going from left to right when written, and from bottom to top when looking in NI... I am still a rank amateur at this.) I believe THIS is a variable which just represents the existing byte, letting you skip the READ_BYTE line. I've only started using it very recently; I tend to still READ_BYTE and use a variable since it's easier to see what my code is doing. (If I focus on other stuff for a couple months and then come back to my code, sometimes I literally don't understand what I had done earlier.) The pipe symbol "|" is just a synonym for BOR... I forget what the 1-character synonym for BAND is - I haven't found it necessary to shorten 3-letter words I haven't used, or learned how to use, BNOT. Link to comment
Mike1072 Posted March 9, 2017 Share Posted March 9, 2017 The pipe symbol "|" is just a synonym for BAND... I forget what the 1-character synonym for BOR is - I haven't found it necessary to shorten 3-letter words BAND: & BOR: | BNOT: ` (backtick) The first two share a nice parallel with the logical operators && and ||. Link to comment
Salk Posted March 9, 2017 Author Share Posted March 9, 2017 I think this could be very useful for others as well. Thanks, Mike1072 and subtledoctor. Link to comment
Ardanis Posted March 9, 2017 Share Posted March 9, 2017 I haven't used, or learned how to use, BNOT. BNOT 0b00001000 = 0b11110111 This is particularly useful for unchecking flags: WRITE_BYTE offset THIS | BIT1 // set BIT1 WRITE_BYTE offset THIS & `BIT1 // unset BIT1 I believe THIS is a variable which just represents the existing byte, letting you skip the READ_BYTE line. Same for _SHORT and _LONG. Link to comment
Recommended Posts
Archived
This topic is now archived and is closed to further replies.