Jump to content

Using WeiDU to change flags (.sto, .itm, etc...)


Salk

Recommended Posts

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

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

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, 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 0b10000000
Now 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

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

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

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

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 :p

 

I haven't used, or learned how to use, BNOT.

Link to comment

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 :p

BAND: &

BOR: |

BNOT: ` (backtick)

 

The first two share a nice parallel with the logical operators && and ||.

Link to comment

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

Archived

This topic is now archived and is closed to further replies.

×
×
  • Create New...