From UODemo Wiki
Jump to: navigation, search

The scripts subdirectory contains many files with a .m extension. The files contain binary data and cannot be read by hand. There is also one text file named sdb.txt.

A decompiler can be found here : Mass M Decompiler.
A list with commands that scripts can use can be found here : Command List

The .m files are not encrypted but they do contain a sort of obfuscated, intermediate binary language between the original script files and the runtime engine of uodemo.exe.

The .m files consist of obfuscated tokens, constants (byte, word, and double word values), string indexes into sdb.txt and quoted string indexes into sdb.txt. Constant, strings and quoted strings are preceded by a (obfuscated) token describing them. Quoted strings can be concatenated on-the-fly by the parser.

The obfuscation works as follows: each token is represented by 5 different words (2 bytes).

For example, the token "IF" is coded as byte 0x25, which is obfuscated to be 0x12C2, 0x1003, 0x0607, 0x0784 or 0x2B0F. So to decompile the .m file you must look-up each obfuscated word and convert it to a byte, then convert that byte to a token which we humans can read. This is a straight-forward process, therefor, (re-)compilation of .m files can be achieved with ease.

Decompilation : 0x12C2 or 0x1003 or 0x0607 or 0x0784 or 0x2B0F -> 0x25 -> IF
Compilation : IF -> 0x25 -> 0x12C2 or 0x1003 or 0x0607 or 0x0784 or 0x2B0F

This is a list of supported tokens:
0x390C, 0x0F3E, 0x0199, 0x0124, 0x305E -> 0x02 -> (
0x39B3, 0x2D12, 0x26A6, 0x5D03, 0x1238 -> 0x03 -> )
0x3B25, 0x1E1F, 0x1AD4, 0x7F96, 0x7FF5 -> 0x04 -> ,
0x0732, 0x0120, 0x5CFD, 0x3E12, 0x3BF6 -> 0x06 -> ;
0x3A9E, 0x0DDC, 0x5E14, 0x2E40, 0x1CD0 -> 0x07 -> {
0x7EB7, 0x6032, 0x2C3B, 0x15A1, 0x3EF6 -> 0x08 -> }
0x409D, 0x12E1, 0x121F, 0x26CA, 0x3699 -> 0x09 -> [
0x0902, 0x7BB9, 0x139D, 0x187E, 0x16C5 -> 0x0A -> ]
0x3CD5, 0x13E9, 0x4080, 0x5DB2, 0x33EA -> 0x0B -> ! (not)
0x23C9, 0x60BF, 0x3CD6, 0x0FBF, 0x2F14 -> 0x0C -> + (add)
0x047E, 0x368E, 0x2FFF, 0x288F, 0x7DD1 -> 0x0D -> - (substract)
0x261E, 0x5E9D, 0x1916, 0x32E6, 0x401D -> 0x0E -> * (multiply)
0x0384, 0x18D7, 0x0FC9, 0x0E12, 0x2833 -> 0x0F -> / (divide)
0x249E, 0x2B0C, 0x11F4, 0x5DD5, 0x127E -> 0x10 -> % (modula)
0x0135, 0x07CF, 0x1AF4, 0x0ECC, 0x01D3 -> 0x11 -> == (equal to)
0x0E90, 0x3A2D, 0x37E6, 0x19D9, 0x252A -> 0x12 -> != (not equal to)
0x37E5, 0x1DC0, 0x1481, 0x4087, 0x2B01 -> 0x13 -> < (lower then)
0x16D4, 0x3A8D, 0x7FBE, 0x0C7B, 0x0C15 -> 0x14 -> > (higher then)
0x3807, 0x0633, 0x251F, 0x1D18, 0x3492 -> 0x15 -> <= (lower then or equal to)
0x19DA, 0x39CE, 0x3BB1, 0x3004, 0x1796 -> 0x16 -> >= (higher then or equal to)
0x1F16, 0x182F, 0x2CF7, 0x5ED0, 0x1316 -> 0x17 -> = (assign)
0x5D24, 0x0588, 0x7CFE, 0x2725, 0x0DE5 -> 0x18 -> && (logical and)
0x13D3, 0x29D8, 0x0A28, 0x09CE, 0x3960 -> 0x19 -> || (logical or)
0x5CCD, 0x0940, 0x293B, 0x40A5, 0x1D11 -> 0x1B -> ++ (increment)
0x2528, 0x0EA9, 0x3F0B, 0x3087, 0x3F97 -> 0x1C -> -- (decrement)
0x30F1, 0x3295, 0x01C1, 0x0CE1, 0x3EE9 -> 0x1D -> int (integer)
0x3F9A, 0x30A7, 0x2DB5, 0x169A, 0x2FE7 -> 0x1E -> str (string)
0x10D9, 0x0390, 0x2A38, 0x0728, 0x5C5E -> 0x1F -> ust (?)
0x01E1, 0x1030, 0x1BD9, 0x159F, 0x2BA5 -> 0x20 -> loc (location (x, y, z))
0x28E2, 0x2F0C, 0x1289, 0x3382, 0x36C2 -> 0x21 -> obj (object)
0x26B1, 0x1CDF, 0x27DA, 0x0E29, 0x113E -> 0x22 -> lis (list)
0x2E39, 0x1D3F, 0x1D5E, 0x1FF1, 0x7E0E -> 0x23 -> voi (void)
0x12C2, 0x1003, 0x0607, 0x0784, 0x2B0F -> 0x25 -> if
0x3305, 0x32E7, 0x212C, 0x018E, 0x3308 -> 0x26 -> else
0x3106, 0x018C, 0x357E, 0x0A87, 0x5D2B -> 0x28 -> while
0x7DAA, 0x2F0B, 0x1BFC, 0x13F5, 0x1ECA -> 0x2A -> for
0x017B, 0x6014, 0x0E99, 0x33CD, 0x27D3 -> 0x2C -> continue
0x7F0D, 0x04F0, 0x183A, 0x1FB4, 0x13A6 -> 0x2D -> break
0x04B0, 0x1927, 0x08FF, 0x31D8, 0x0914 -> 0x2F -> switch
0x3223, 0x17B8, 0x3895, 0x248D, 0x342D -> 0x31 -> case
0x5D3D, 0x3260, 0x32DE, 0x2780, 0x31AD -> 0x32 -> default
0x5DE9, 0x5EA5, 0x11D5, 0x199F, 0x2F15 -> 0x33 -> return
0x0E01, 0x19FE, 0x3821, 0x0B93, 0x0A2F -> 0x34 -> "declares a function and defines the implementation!"
0x09B3, 0x038F, 0x328A, 0x08AF, 0x5CCA -> 0x35 -> "implement an event"
0x0C95, 0x7CBE, 0x7C27, 0x5D2A, 0x2FA1 -> 0x36 -> "declare a variable at script level"
0x31BE, 0x15B4, 0x07C9, 0x27C0, 0x1B32 -> 0x37 -> "include another script" (see NOTE)
0x2934, 0x3E09, 0x012C, 0x2CC6, 0x7FA6 -> 0x38 -> "declares a function without defining the implementation!"
0x5D17, 0x0A1D, 0x3B29, 0x2BFA, 0x2BB8 -> 0x3A -> quoted-string (C style = terminated with a 0-byte)
0x17BD, 0x21EB, 0x2015, 0x5DB8, 0x15E1 -> 0x3C -> constant byte (gets zero extended to signed 32-bit integer)
0x5B60, 0x3D8F, 0x0FF4, 0x275B, 0x3C8A -> 0x3D -> constant word (gets zero extended to signed 32-bit integer)
0x188F, 0x5D27, 0x7F5C, 0x01F7, 0x093B -> 0x3E -> constant dword (gets casted to signed 32-bit integer)
0x3510, 0x0B9B, 0x06E9, 0x3B9E, 0x0B31 -> 0x41 -> string (C style = terminated with a 0-byte)
NOTE: if you include a script it must the very first statement and you can only include one script per script!

This is a list of supported but unused tokens:
0x263D, 0x3B97, 0x4027, 0x138A, 0x282D -> 0x1A -> ^ (xor)
NOTE: this means you can create scripts that implement XOR (none of the included OSI scripts do this)

This is a list of defined but unsupported tokens:
0x1EDC, 0x20A8, 0x37BE, 0x01EB, 0x123B -> 0x27 -> ENDIF
0x03FA, 0x0AF0, 0x0786, 0x2332, 0x1295 -> 0x29 -> ENDWHILE
0x0D9F, 0x388A, 0x15FD, 0x7CB8, 0x1AF6 -> 0x2B -> ENDFOR
0x190B, 0x3605, 0x20AD, 0x32CF, 0x2CD5 -> 0x2E -> GOTO (it's unclear how this statement works!)
0x13F4, 0x3A27, 0x387C, 0x32C1, 0x198C -> 0x30 -> ENDSWITCH
NOTE: the ENDxxx statements are only used internally and are added by the parser where needed

This is a list of obfuscated but unsupported tokens:
0x0BB3, 0x2EA6, 0x12DB, 0x153C, 0x7E87 -> 0x01
0x323B, 0x260D, 0x030A, 0x301C, 0x0BDB -> 0x05
0x06E3, 0x36A1, 0x0C1E, 0x2120, 0x1DCB -> 0x24
0x06D8, 0x3181, 0x2738, 0x3212, 0x03F9 -> 0x39
0x1DB5, 0x2F95, 0x0EF5, 0x5CDF, 0x7B8B -> 0x3B
0x2F84, 0x1DC3, 0x1DA7, 0x1A30, 0x2410 -> 0x3F
0x02EE, 0x0603, 0x012F, 0x2C9E, 0x2BEF -> 0x40

The language is very close to the C language, notice the existance of the { and } brackets. Also the for loop and switch statements work like its C variant, with support for the break and default keywords [1].