Clarifying Module System Operations

Users who are viewing this thread

dunde said:
I wonder why the facecode operations needs string operands. Why don't they make it with integer operands?

Because the face code is by far much much higher than 2 ^ 32 (max int 32).
0x0000000000000001124000000020000000000000001c00800000000000000000 = 6724590433320233934322779735076119692987884466761552101376
 
The_dragon said:
dunde said:
I wonder why the facecode operations needs string operands. Why don't they make it with integer operands?

Because the face code is by far much much higher than 2 ^ 32 (max int 32).
0x0000000000000001124000000020000000000000001c00800000000000000000 = 6724590433320233934322779735076119692987884466761552101376

AFAIK, WB's variables are about 52 bits length.
 
I remember ShocK told me something about a possible bug with beard operations, being unable to give the face "no beard". Returns the value as 0, but can't give it back for some odd reason.
 
dunde said:
AFAIK, WB's variables are about 52 bits length.

Warband variables are 32 bits long. Much higher than 32 bits would make the game a little bit slower on 32 bits machines (since it will require some extra cpu cycles just to make a sum (using bignum libraries)).
I tested the max len when I was trying to store a server IP into a variable (IP number) and I ended up doing some checks and using the negative flag bit too (without negative bit I would have 31 bits which is half the amount of higher IP number(ipv 4)).

EDIT: even if it were 64 bits, the max number would be 18446744073709551616 (far smaller than the face code xD).
 
But they could have just made those ops directly retrieve or set a certain facial feature as an integer. That they haven't likely shows they're putting some effort into associating numbers with strings.
 
Do Achievement related operations work on mods?
ie: get_achievement_stat, set_achievement_stat, unlock_achievement

or should I remove it from my admin tools mod.
 
The_dragon said:
dunde said:
AFAIK, WB's variables are about 52 bits length.

Warband variables are 32 bits long. Much higher than 32 bits would make the game a little bit slower on 32 bits machines (since it will require some extra cpu cycles just to make a sum (using bignum libraries)).
Actually, they are 64 bits long and all the math ops (val_add, sub, mul..) use 64 bit arithmetic.
Values that come from the MS scripts have the upper 8 bits used for special tags and are masked out on use, making them 56 bits long, the rest (values in registers, local variables, and global variables) have all 64 bits available for use.
Most of the time it's a bad idea to use 64 bit values in multiplayer mods since the network message operations only send the lower 32 bits of a value.
 
Here is a small test that I set up
Code:
    (assign, reg1, 2147483648),
    (display_message, "@2147483648 = {reg1}"),  # 2 to pow 31
    (assign, reg1, 2147483647),
    (display_message, "@2147483647 = {reg1}"),  # 2 to pow 31 - 1
    (assign, reg1, 4294967296),
    (display_message, "@4294967296 = {reg1}"),  # 2 to pow 32
    (assign, reg1, 4294967295),
    (display_message, "@4294967295 = {reg1}"),  # 2 to pow 32 - 1

And here is the result:
2147483648 = -2147483648
2147483647 = 2147483647
4294967296 = 0
4294967295 = -1

You can clearly see that bit number 32 is the sign bit.
Also you can see that
4294967295 = 011111111111111111111111111111111 = -1
4294967296 = 100000000000000000000000000000000 = 0 - that extra bit is not taken into consideration; means that it acts like a 32 bit variable

I've seen that WSE uses 64 bits local variables (module system local variables) which surprised me because my test result in variables being 32 bits long.

EDIT: I ran this from the main menu presentation (game_start).
 
Lav said:
Your test will have the same results if 64-bit registers are converted to 32-bit values before being printed.
They are not explicitely converted to 32-bit values, but they use the %d format specifier to print them so the upper 32 bits are effectively ignored.

It's very easy to see that 64 bit variables are used. Just look at the assembly for val_add:
Code:
add ecx, esi
adc eax, [esp+36]
If it was 32 bit arithmetic there would be a single add, instead there is add + adc, which is how x86 code does 64 bit addition.
 
Ok...I am wrong...once again...

So all warband string parsers (receive url and receive network message) uses only 32 bits for integers.... that explains why I couldn't correctly receive an IP from a webserver (if the number was less than 0, then I needed to add 2147483648 for the correct IP).
 
cmpxchg8b said:
Lav said:
Your test will have the same results if 64-bit registers are converted to 32-bit values before being printed.
They are not explicitly converted to 32-bit values, but they use the %d format specifier to print them so the upper 32 bits are effectively ignored.

Then I guess that saving it to other register, right-shifting it (using the bitwise operators), and then printing something like
Code:
{reg1}{reg0}
would sort of work. Right?

Code:
(assign, reg0, 0xFFFFFFFFFF),
(assign, reg1, reg0),
(val_rshift, reg1, 32),
(display_message, "@0xFFFFFFFFFF = 1099511627775 = ({reg1}<<32)|{reg0}"),
 
Here is a traditionally "mod and divide" script to convert variable to string
Code:
("int_to_string", [
    (store_script_param, ":very_long_number", 1),

    (str_clear, s0),
    (assign, ":end", 20), #2 to power 64 has 20 digits, so 20 digits long is the max number
    (try_for_range, ":unused", 0, ":end"),
      (store_mod, reg1, ":very_long_number", 10),
      (val_div, ":very_long_number", 10),
      (str_store_string, s0, "@{reg1}{s0}"),
      (eq, ":very_long_number", 0),
      (assign, ":end", 0),
    (try_end),
]),

 
The_dragon said:
Here is a traditionally "mod and divide" script to convert variable to string
Code:
("int_to_string", [
    (store_script_param, ":very_long_number", 1),

    (str_clear, s0),
    (assign, ":end", 20), #2 to power 64 has 20 digits, so 20 digits long is the max number
    (try_for_range, ":unused", 0, ":end"),
      (store_mod, reg1, ":very_long_number", 10),
      (val_div, ":very_long_number", 10),
      (str_store_string, s0, "@{reg1}{s0}"),
      (eq, ":very_long_number", 0),
      (assign, ":end", 0),
    (try_end),
]),

Cool! That reminds me to an exercise that appeared in my programming fundamentals' exam.
The module system syntax makes it way harder to read, it's easier than it looks.

It can be summed up as: get right-most digit of the number, append it as prefix to the string, right-shift the number one decimal point, repeat until the number reaches zero.

Code:
num = 1234
str = ""

while(num != 0)
{
  str = (num % 10) . str
  num /= 10
}


Anyway, that's great! Now we have methods for representing and chunking data in the engine for network usage and debugging, so that's something.
 
Back
Top Bottom