Jump to content

Beyond DefaultGameCore.ini - Analyzing the Game Scripts


Beknatok

Recommended Posts

Found stuff:

 

class BytecodeReader
   {
       private const int EX_LocalVariable = 0x00;
       private const int EX_InstanceVariable = 0x01;
       private const int EX_DefaultVariable = 0x02;
       private const int EX_Return = 0x04;
       private const int EX_Switch = 0x05;
       private const int EX_Jump = 0x06;
       private const int EX_JumpIfNot = 0x07;
       private const int EX_Stop = 0x08;
       private const int EX_Assert = 0x09;
       private const int EX_Case = 0x0A;
       private const int EX_Nothing = 0x0B;
       private const int EX_LabelTable = 0x0C;
       private const int EX_GotoLabel = 0x0D;
       private const int EX_EatReturnValue = 0x0E;
       private const int EX_Let = 0x0F;
       private const int EX_DynArrayElement = 0x10;
       private const int EX_New = 0x11;
       private const int EX_ClassContext = 0x12;
       private const int EX_Metacast = 0x13;
       private const int EX_LetBool = 0x14;
       // EX_EndParmValue = 0x15?
       private const int EX_EndFunctionParms = 0x16;
       private const int EX_Self = 0x17;
       private const int EX_Skip = 0x18;
       private const int EX_Context = 0x19;
       private const int EX_ArrayElement = 0x1A;
       private const int EX_VirtualFunction = 0x1B;
       private const int EX_FinalFunction = 0x1C;
       private const int EX_IntConst = 0x1D;
       private const int EX_FloatConst = 0x1E;
       private const int EX_StringConst = 0x1F;
       private const int EX_ObjectConst = 0x20;
       private const int EX_NameConst = 0x21;
       private const int EX_RotationConst = 0x22;
       private const int EX_VectorConst = 0x23;
       private const int EX_ByteConst = 0x24;
       private const int EX_IntZero = 0x25;
       private const int EX_IntOne = 0x26;
       private const int EX_True = 0x27;
       private const int EX_False = 0x28;
       private const int EX_NativeParm = 0x29;
       private const int EX_NoObject = 0x2A;
       private const int EX_IntConstByte = 0x2C;
       private const int EX_BoolVariable = 0x2D;
       private const int EX_DynamicCast = 0x2E;
       private const int EX_Iterator = 0x2F;
       private const int EX_IteratorPop = 0x30;
       private const int EX_IteratorNext = 0x31;
       private const int EX_StructCmpEq = 0x32;
       private const int EX_StructCmpNe = 0x33;
       private const int EX_UnicodeStringConst = 0x34;
       private const int EX_StructMember = 0x35;
       private const int EX_DynArrayLength = 0x36;
       private const int EX_GlobalFunction = 0x37;
       private const int EX_PrimitiveCast = 0x38;
       private const int EX_DynArrayInsert = 0x39;
       private const int EX_ByteToInt = 0x3A;        // EX_ReturnNothing = 0x3A
       private const int EX_EqualEqual_DelDel = 0x3B;
       private const int EX_NotEqual_DelDel = 0x3C;
       private const int EX_EqualEqual_DelFunc = 0x3D;
       private const int EX_NotEqual_DelFunc = 0x3E;
       private const int EX_EmptyDelegate = 0x3F;
       private const int EX_DynArrayRemove = 0x40;
       private const int EX_DebugInfo = 0x41;
       private const int EX_DelegateFunction = 0x42;
       private const int EX_DelegateProperty = 0x43;
       private const int EX_LetDelegate = 0x44;
       private const int EX_Conditional = 0x45;
       private const int EX_DynArrayFind = 0x46;
       private const int EX_DynArrayFindStruct = 0x47;
       private const int EX_LocalOutVariable = 0x48;
       private const int EX_DefaultParmValue = 0x49;
       private const int EX_EmptyParmValue = 0x4A;
       private const int EX_InstanceDelegate = 0x4B;
       private const int EX_GoW_DefaultValue = 0x50;
       private const int EX_InterfaceContext = 0x51;
       private const int EX_InterfaceCast = 0x52;
       private const int EX_EndOfScript = 0x53;
       private const int EX_DynArrayAdd = 0x54;
       private const int EX_DynArrayAddItem = 0x55;
       private const int EX_DynArrayRemoveItem = 0x56;
       private const int EX_DynArrayInsertItem = 0x57;
       private const int EX_DynArrayIterator = 0x58;

       private const int EX_ExtendedNative = 0x60;
       private const int EX_FirstNative = 0x70;

Link to comment
Share on other sites

  • Replies 102
  • Created
  • Last Reply

Top Posters In This Topic

Im at work so dont relay to heavy on it, could be mistakes in it

 

look at the bytecode

 

take a look at the tokencodes

 

If condtionals seems to be done through a if not equal token, didnt saw other things yet

after the jump tokens the next thing is the offset for the leave

 

altering the 0x07 for conditional jump to 0x06 for an uncondtional jump will give you the control what to do next

 

Edit:

well this list seems familar :D

 

The Case Switch under it is important too

Edited by dreadylein
Link to comment
Share on other sites

Original hex of that code:

 

Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F

00000000  DA 35 00 00 9F 1F 00 00 00 00 00 00 D5 35 00 00  Ú5..Ÿ.......Õ5..
00000010  00 00 00 00 00 00 00 00 DA 35 00 00 00 00 00 00  ........Ú5......
00000020  91 03 00 00 D5 C1 00 00 A2 00 00 00 76 00 00 00  ‘...ÕÁ..¢...v...
00000030  07 19 00 9A 00 D8 35 00 00 1D FF FF FF FF 16 04  ...š.Ø5...ÿÿÿÿ..
00000040  1D FF FF FF FF 07 52 00 84 9B 38 3A 00 D9 35 00  .ÿÿÿÿ.R.„›8:.Ù5.
00000050  00 38 3A 24 03 16 18 16 00 1B BF 14 00 00 00 00  .8:$......¿.....
00000060  00 00 38 3A 00 DA 35 00 00 16 16 0F 00 D8 35 00  ..8:.Ú5......Ø5.
00000070  00 25 0F 00 D6 35 00 00 12 20 6D FE FF FF 09 00  .%..Ö5... mþÿÿ..
00000080  F7 FD FF FF 00 02 F7 FD FF FF 04 38 44 AB 38 3F  ÷ýÿÿ..÷ýÿÿ.8D«8?
00000090  90 00 D8 35 00 00 2C 18 16 00 D6 35 00 00 16 04  ..Ø5..,...Ö5....
000000A0  3A D7 35 00 00 53 00 00 00 02 00 02 00 5E 0F 00  :×5..S.......^..
000000B0  00 00 00 00 00                                   .....

 

I can't find these:

 

EX_NotEqual_DelDel = 0x3C;

EX_NotEqual_DelFunc = 0x3E;

 

 

So maybe I'll change one of the jumps from:

 

EX_JumpIfNot = 0x07;

 

to:

 

EX_Jump = 0x06;

 

and see what that does.

 

UPDATE: Also can't find EX_StructCmpNe = 0x33; in the code, either. What gives? Why can't I find anything to match a "!=" ? The only explanation I can think of is that it just didn't compile that way, and it's effectively doing the != another way. Or that code in unhoop is incorrect for xcom (this appears to be true). Or both. Dunno.

 

function int GetItemBuildTime(XComGame.XGGameData.EItemType eItem, XGStrategyActor.EItemCategory eItemCat, int iEngineerDays)
{
local float fBalanceFactor;

// End:0x19 Loop:False
if(iEngineerDays == -1)
{
	return -1;
}
// This is an implied JumpToken;
//goto J0x52;
//eItemCat != 3 || (IsShipWeapon(eItem));
//iEngineerDays = 0;
//J0x52:

fBalanceFactor = class'XGTacticalGameCore'.default.ITEM_TIME_BALANCE;
return int(float(iEngineerDays * 24) * fBalanceFactor);
}

 

Flipping the second 07 (at location 45) to an 06 gives us that... So it should skip all the code I commented out. :D

 

Thanks for the help dreadylein. :D

Edited by Daemonjax
Link to comment
Share on other sites

Yup, i mostly do it this way:

 

make an unpack of a upk

Search the right Functionfile

Open it in a Hexeditor

Open a Commandline

 

Alter something, make a repack as x.upk

Put it into ueviewer and look at the changes

 

Repeat

 

So i can see the original function and all the changes

 

And yes, as i said only saw conditional jumps, no compares yet

 

Edit:

Could you pm me the bytecode ?

Edited by dreadylein
Link to comment
Share on other sites

EDIT: Haha, the server carked out on me, and by the time my post went through you'd already found all this. I'll leave this post up in case you didn't know about the Native Tables, since I didn't see you talking about that.

 

Just took a look at the file; there's two 0x07s in there, which are JumpIfNotEqual. One of them needs to be changed to 0x06, which is Jump (unconditionally). I'm assuming it's the second one, since that if statement we're looking at comes second.

 

Also, I missed your earlier post. 0x9A is ==, 0x9B is != (but, I found other bytecodes for those operators, F1 and F2, if I remember correctly). So just changing a 9A to a 9B will change an == to a !=.

 

I mentioned this in another post, but it bears repeating: this source file from an UnrealScript disassembler has a ton of useful information on the bytecode, including many of the native bytecode instructions. For other operators and functions, you'll want to look in the Native Tables folder in the UE Explorer directory, and the ExportTable.txt, ImportTable.txt, and NameTable.txt extracted from the UPKs using Gildor's tools.

 

(The Native Tables files are a bit confusing, but if you open them in a hex editor it only takes a little time to figure them out. It goes <operator/function> <some garbage> <bytecode>. Knowing that == is 9A and != is 9B should help you figure it out.)

Edited by kanet32
Link to comment
Share on other sites

Grats :)

hate my weak english :o , kanet32 pretty much explained whats missing to understand nearly all of the bytecode :)

 

A tool which helps us out a bit would be awesome :o

Shouldnt be terrrible complicatet i guess

 

Mh a simple list about the bytecodes we searched in the table or source would help big times :o

Having it at one look would be nice i guess

Edited by dreadylein
Link to comment
Share on other sites

Alter something, make a repack as x.upk

 

You can skip this step if you just edit the hexedit the upk directly :D

 

0x9A is ==, 0x9B is != (but, I found other bytecodes for those operators, F1 and F2, if I remember correctly). So just changing a 9A to a 9B will change an == to a !=.

 

I mentioned this in another post, but it bears repeating: this source file from an UnrealScript disassembler has a ton of useful information on the bytecode, including many of the native bytecode instructions. For other operators and functions, you'll want to look in the Native Tables folder in the UE Explorer directory, and the ExportTable.txt, ImportTable.txt, and NameTable.txt extracted from the UPKs using Gildor's tools.

 

(The Native Tables files are a bit confusing, but if you open them in a hex editor it only takes a little time to figure them out. It goes <operator/function> <some garbage> <bytecode>. Knowing that == is 9A and != is 9B should help you figure it out.)

 

Good info.

 

Someone should take all that information and make it something easily human readable/searchable.

 

a simple list about the bytecodes we searched in the table or source would help big times

 

Yeps. I think we should do it, because I get the feeling we'll be limited to modding this way for a long while.

Edited by Daemonjax
Link to comment
Share on other sites

I'd do it myself, but I'm a bit busy today. It would be fairly easy to just add the stuff in the Native Tables to that list of instructions you posted above (it's the UE3 or UDK tables we should be using, they're the most recent). The list of imports, exports, and names from the package, however, is also fairly important and those files are massive.

 

Writing a simpler disassembler than UE Explorer is also probably doable, one that simply puts one instruction per line and replaces them with the instruction name, like an assembly language. Then you could reverse the progress to turn a modified pseudo-assembly back into bytecode. As near as I can tell, the UnrealScript compiler doesn't seem to actually do anything to the code. It's not an optimising compiler. So what UE Explorer shows is literally what's in the bytecode, just with the semantic sugar peeled off and the all the variable and function names replaced with indices into a table. I'm not sure this is worth the effort, though. It might be better to just keep doing what we're doing now until someone with better knowledge of the UDK figures out how to get the UnrealScript compiler to work with the XCOM UPKs.

Link to comment
Share on other sites

  • Recently Browsing   0 members

    • No registered users viewing this page.

×
×
  • Create New...