wghost81 Posted February 27, 2014 Share Posted February 27, 2014 Amineri, thanks! Yes, I was converting to names as an intermediate step. I didn't realized it can update hex-references directly. I didn't realized, UPKFILE can point to some third upk copy. :smile: I assumed, I have to set correct value for reference update to work, but then I found that I need to specify upk files anyway and then things got messed up completely inside my head. :smile: So yes, it works perfectly. :smile: Link to comment Share on other sites More sharing options...
wghost81 Posted February 27, 2014 Share Posted February 27, 2014 Some minor issues: 1. Copy/paste replace is working normally with usual text, but is behaving strange with highlighted code. 2. Highlight is not working until I type in some GUID. It doesn't actually use this GUID, apparently, as it works with incorrect GUID perfectly. 3. When I accidentally pointed reference lookup to compressed upk it did nothing. IMO, should at least show some error message about package being incorrect/compressed. Sorry for not posting it at project home: too much work (IRL) to little time... Link to comment Share on other sites More sharing options...
Amineri Posted February 27, 2014 Author Share Posted February 27, 2014 Sorry for not posting it at project home: too much work (IRL) to little time... No worries, this forum is perfectly fine. :) 1. Copy/paste replace is working normally with usual text, but is behaving strange with highlighted code. I've put in an issue ticket on this, and will look into it. We never actually implemented copy/paste functionality explicitly, we just took advantage of what was built into the Java components used. 2. Highlight is not working until I type in some GUID. It doesn't actually use this GUID, apparently, as it works with incorrect GUID perfectly. Actually I have it set up so that it doesn't attempt to parse any data unless it has a fully filled-out header (version, upkfile, guid, and function). The original purpose of this was to allow it act as a general-purpose text editor that would allow the user to manipulate text without trying to highlight garbage, but subsequent design decisions have made that less relevant. 3. When I accidentally pointed reference lookup to compressed upk it did nothing. IMO, should at least show some error message about package being incorrect/compressed. That's an interesting find -- I hadn't ever had that happen. I'm not sure whether our upk parser knows how to check if the upk it's trying to decode is compressed. We didn't explicitly put such a check in. It may be scanning through the compressed file locations and getting garbage data, which could potentially cause problems. Thanks again for the feedback :) Link to comment Share on other sites More sharing options...
wghost81 Posted February 28, 2014 Share Posted February 28, 2014 Another note: I'm experiencing considerable slowdowns when highlighting long code lines. Some of my mods are raw in-place hex editing, so I updated them by copying/pasting an entire code from HxD as one long line. This resulted in considerable slowdown of the entire program. Link to comment Share on other sites More sharing options...
wghost81 Posted March 1, 2014 Share Posted March 1, 2014 I've noticed, that only project which have been opened via "Open Project" are saved in project view (leftmost window). If you create project and then close UPKModder, new project will not be displayed after reopening it. But after you manually open project and close UPKModder, it will be displayed after reopening. Link to comment Share on other sites More sharing options...
Amineri Posted March 12, 2014 Author Share Posted March 12, 2014 I haven't made much headway in figuring out how to fix the various slowdowns for large files, but I've made headway in handling non-function hex changes in a way that is fairly patch-agnostic yet doesn't require me to build separate parsers for each type of structure in the upk (e.g. enums, variables). Basically I've fixed a small bug that was preventing the direct use of name/object strings within "raw" hex. By raw hex I mean hex code that isn't parse-able as unrealscript. I'm still doing some bug-testing on a new v0.82 that will allow this, but thought I'd post up some examples of how it's working so far. Changing default properties: MODFILEVERSION=4 UPKFILE=XComStrategyGame.upk GUID=UNSPECIFIED // no hex references in file FUNCTION=Default__XGStrategyAI KEYWORD=Sets default of m_bFirstMission (used to set hard missions) to false [BEFORE_HEX] <|m_bFirstMission|> 00 00 00 00 // name m_bFirstMission <|BoolProperty|> 00 00 00 00 // name BoolProperty 00 00 00 00 00 00 00 00 // no size for Bool 01 // bool value true [/BEFORE_HEX] [AFTER_HEX] <|m_bFirstMission|> 00 00 00 00 // name m_bFirstMission <|BoolProperty|> 00 00 00 00 // name BoolProperty 00 00 00 00 00 00 00 00 // no size for Bool 00 // bool value false [/AFTER_HEX] Extending an enumeration (combined with a RESIZE operation) : MODFILEVERSION=4 UPKFILE=XComStrategyGame.upk GUID=UNSPECIFIED // no hex references in file FUNCTION=EAlienObjective@XGStrategyActorNativeBase RESIZE=10 [BEFORE_HEX] [HEADER] //8F 00 00 00 E6 25 00 00 00 00 00 00 8F 00 00 00 09 00 00 00 //length [/HEADER] <|eObjective_Recon|> 00 00 00 00 // eObjective_Recon <|eObjective_Scout|> 00 00 00 00 // eObjective_Scout <|eObjective_Harvest|> 00 00 00 00 // eObjective_Harvest <|eObjective_Flyby|> 00 00 00 00 // eObjective_Flyby <|eObjective_Hunt|> 00 00 00 00 // eObjective_Hunt <|eObjective_Abduct|> 00 00 00 00 // eObjective_Abduct <|eObjective_Terrorize|> 00 00 00 00 // eObjective_Terrorize <|eObjective_Infiltrate|> 00 00 00 00 // eObjective_Infiltrate <|eObjective_MAX|> 00 00 00 00 // eObjective_MAX [/BEFORE_HEX] [AFTER_HEX] [HEADER] //8F 00 00 00 E6 25 00 00 00 00 00 00 8F 00 00 00 0b 00 00 00 [/HEADER] <|eObjective_Recon|> 00 00 00 00 // eObjective_Recon <|eObjective_Scout|> 00 00 00 00 // eObjective_Scout <|eObjective_Harvest|> 00 00 00 00 // eObjective_Harvest <|eObjective_Flyby|> 00 00 00 00 // eObjective_Flyby <|eObjective_Hunt|> 00 00 00 00 // eObjective_Hunt <|eObjective_Abduct|> 00 00 00 00 // eObjective_Abduct <|eObjective_Terrorize|> 00 00 00 00 // eObjective_Terrorize <|eObjective_Infiltrate|> 00 00 00 00 // eObjective_Infiltrate <|eObjective_Infiltrate|> 01 00 00 00 // eObjective_Infiltrate_1 <|eObjective_Infiltrate|> 02 00 00 00 // eObjective_Infiltrate_2 <|eObjective_MAX|> 00 00 00 00 //eObjective_MAX [/AFTER_HEX] Changing a variable definition : MODFILEVERSION=4 UPKFILE=XComStrategyGame.upk GUID=UNSPECIFIED // no hex references in file FUNCTION=m_arrObjectiveNames@XGStrategyAI //increase size of static array and remove enum link [BEFORE_HEX] {|CheckpointRecord@XGStrategyAI|} // last? <|None|> 00 00 00 00 // unknown {|CheckpointRecord@XGStrategyAI|} // next 08 00 00 00 // array size 02 80 40 00 00 00 00 00 // flags <|None|> 00 00 00 00 // unknown {|EAlienObjective@XGStrategyActorNativeBase|} // Enum [/BEFORE_HEX] [AFTER_HEX] {|CheckpointRecord@XGStrategyAI|} // last? <|None|> 00 00 00 00 // unknown {|CheckpointRecord@XGStrategyAI|} // next 0B 00 00 00 // array size 02 80 40 00 00 00 00 00 // flags <|None|> 00 00 00 00 // unknown 00 00 00 00 // Enum [/AFTER_HEX] Note that the GUID is now unspecified since there aren't any hex references remaining in the file. Link to comment Share on other sites More sharing options...
wghost81 Posted March 12, 2014 Share Posted March 12, 2014 I currently use virtual function token to update default properties with UPKModder. :smile: I just enclose 8-byte name indexes into 1B - 16 and run update references. Works perfect. And again, thanks for the great tool! Updated all my mods for patch 3 in a matter of hours. That's fantastic! Link to comment Share on other sites More sharing options...
Amineri Posted March 12, 2014 Author Share Posted March 12, 2014 I do a similar thing to convert both function names and import/export objects from references to names. For example, I copied out all of the raw XGItemLibrary default properties raw hex into a UPKmodder document and separated it into bits, then wrapped the name references with 1B ... 16 tokens and prefixed the object references with 00 and ran the reference updater to convert them all to names : MODFILEVERSION=4 UPKFILE=XComGame.upk GUID=UNSPECIFIED // no hex references in file FUNCTION=Default__XGItemLibrary [BEFORE_HEX] <|m_arrItems|> 00 00 00 00 // variable name <|ArrayProperty|> 00 00 00 00 // variable type 70 03 00 00 00 00 00 00 // size in bytes? DB 00 00 00 // array length ? 00 00 00 00 // item 0 eItem_NONE 00 00 00 00 // item 1 eItem_BEGIN_WEAPONS {|XGWeapon_Pistol|} // item 2 {|XGWeapon_AssaultRifle|} // item 3 {|XGWeapon_Shotgun|} // item 4 {|XGWeapon_Minigun|} // item 5 {|XGWeapon_SniperRifle|} // item 6 {|XGWeapon_RocketLauncher|} // item 7 {|XGWeapon_LaserPistol|} // item 8 {|XGWeapon_LaserAssaultRifle|} // item 9 {|XGWeapon_LaserAssaultGun|} //item 10 {|XGWeapon_HeavyLaser|} //item 11 {|XGWeapon_LaserSniperRifle|} //item 12 {|XGWeapon_PlasmaPistol|} //item 13 {|XGWeapon_PlasmaLightRifle|} //item 14 {|XGWeapon_PlasmaAssaultRifle|} //item 15 {|XGWeapon_AlloyCannon|} //item 16 {|XGWeapon_HeavyPlasma|} //item 17 {|XGWeapon_PlasmaSniperRifle|} //item 18 {|XGWeapon_BlasterLauncher|} //item 19 {|XGWeapon_MechtoidPlasmaCannon|} //item 20 {|XGWeapon_SeekerPlasmaPistol|} //item 21 {|XGWeapon_MEC_KineticStrike|} //item 22 {|XGWeapon_MEC_FlameThrower|} //item 23 {|XGWeapon_MEC_GrenadeLauncher|} //item 24 {|XGWeapon_MEC_RestorativeMist|} //item 25 {|XGWeapon_MEC_Electropulse|} //item 26 {|XGWeapon_MEC_ProximityMine|} //item 27 {|XGWeapon_Chaingun|} //item 28 {|XGWeapon_Railgun|} //item 29 {|XGWeapon_ParticleBeam|} //item 30 00 00 00 00 //item 31 eItem_BEGIN_SPECIAL_WEAPONS {|XGWeapon_SectopodArm|} //item 32 {|XGWeapon_SectopodCannon|} //item 33 00 00 00 00 //item 34 eItem_SectopodHeatRay {|XGWeapon_ChryssalidClaw|} //item 35 {|XGWeapon_DroneBeam|} //item 36 {|XGWeapon_PsiAmp|} //item 37 {|XGWeapon_Grapple|} //item 38 {|XGWeapon_Cyberdisc|} //item 39 00 00 00 00 //item 40 eItem_BEGIN_ALIEN_SHARED_WEAPONS {|XGWeapon_PlasmaPistolSectoid|} //item 41 {|XGWeapon_PlasmaLightRifle_ThinMan|} //item 42 {|XGWeapon_PlasmaLightRifle_Floater|} //item 43 {|XGWeapon_PlasmaLightRifle_Muton|} //item 44 {|XGWeapon_PlasmaAssaultRifle_Muton|} //item 45 {|XGWeapon_HeavyPlasma_Floater|} //item 46 {|XGWeapon_HeavyPlasma_Muton|} //item 47 00 00 00 00 //item 48 eItem_END_ALIEN_SHARED_WEAPONS {|XGWeapon_ZombieFist|} //item 49 {|XGWeapon_EtherealWeapon|} //item 50 {|XGWeapon_MutonBlade|} //item 51 {|XGWeapon_OutsiderWeapon|} //item 52 {|XGWeapon_SoldierNoWeapon|} //item 53 {|XGWeapon_Plague|} //item 54 {|XGWeapon_SectopodClusterBomb|} //item 55 {|XGWeapon_SeekerTentacles|} //item 56 00 00 00 00 //item 57 eItem_END_WEAPONS 00 00 00 00 //item 58 eItem_BEGIN_ARMOR 00 00 00 00 //item 59 eItem_ArmorKevlar 00 00 00 00 //item 60 eItem_ArmorCarapace 00 00 00 00 //item 61 eItem_ArmorSkeleton 00 00 00 00 //item 62 eItem_ArmorTitan 00 00 00 00 //item 63 eItem_ArmorArchangel 00 00 00 00 //item 64 eItem_ArmorGhost 00 00 00 00 //item 65 eItem_ArmorPsi 00 00 00 00 //item 66 eItem_ArmorCovertOps 00 00 00 00 //item 67 eItem_END_ARMOR 00 00 00 00 //item 68 eItem_BEGIN_ITEMS {|XGWeapon_Medikit|} //item 69 {|XGWeapon_CombatStims|} //item 70 {|XGWeapon_MindShield|} //item 71 {|XGWeapon_ChitinPlating|} //item 72 {|XGWeapon_ArcThrower|} //item 73 {|XGWeapon_TargetingModule|} //item 74 {|XGWeapon_ReinforcedArmor|} //item 75 {|XGWeapon_RespiratorImplant|} //item 76 00 00 00 00 //item 77 eItem_BallisticModule {|XGWeapon_ReaperRounds|} //item 78 00 00 00 00 //item 79 eItem_END_ITEMS 00 00 00 00 //item 80 eItem_BEGIN_GRENADES {|XGWeapon_FragGrenade|} //item 81 {|XGWeapon_SmokeGrenade|} //item 82 {|XGWeapon_FlashBang|} //item 83 {|XGWeapon_AlienGrenade|} //item 84 {|XGWeapon_GhostGrenade|} //item 85 {|XGWeapon_GasGrenade|} //item 86 {|XGWeapon_NeedleGrenade|} //item 87 {|XGWeapon_MimicBeacon|} //item 88 00 00 00 00 //item 89 eItem_BEGIN_ALIEN_GRENADES {|XGWeapon_SectoidGrenade|} //item 90 {|XGWeapon_FloaterGrenade|} //item 91 {|XGWeapon_MutonGrenade|} //item 92 {|XGWeapon_CyberdiscGrenade|} //item 93 {|XGWeapon_ThinManGrenade|} //item 94 00 00 00 00 //item 95 eItem_END_ALIEN_GRENADES {|XGWeapon_PsiGrenade|} //item 96 {|XGWeapon_BattleScanner|} //item 97 00 00 00 00 //item 98 eItem_END_GRENADES 00 00 00 00 //item 99 eItem_BEGIN_VEHICLES 00 00 00 00 //item 100 eItem_SHIV 00 00 00 00 //item 101 eItem_SHIV_Alloy 00 00 00 00 //item 102 eItem_SHIV_Hover 00 00 00 00 //item 103 eItem_Interceptor 00 00 00 00 //item 104 eItem_Firestorm 00 00 00 00 //item 105 eItem_Skyranger 00 00 00 00 //item 106 eItem_Satellite 00 00 00 00 //item 107 eItem_END_VEHICLES 00 00 00 00 //item 108 eItem_BEGIN_VEHICLE_UPGRADES {|XGWeapon_Shiv_Minigun|} //item 109 {|XGWeapon_Shiv_Sentry|} //item 110 {|XGWeapon_Shiv_Laser|} //item 111 {|XGWeapon_Shiv_Plasma|} //item 112 00 00 00 00 //item 113 eItem_SHIVDeck_I 00 00 00 00 //item 114 eItem_SHIVDeck_II 00 00 00 00 //item 115 eItem_SHIVDeck_III 00 00 00 00 //item 116 eItem_BEGIN_SHIP_WEAPONS 00 00 00 00 //item 117 eItem_IntWeap_I 00 00 00 00 //item 118 eItem_IntWeap_II 00 00 00 00 //item 119 eItem_IntWeap_III 00 00 00 00 //item 120 eItem_IntWeap_IV 00 00 00 00 //item 121 eItem_IntWeap_V 00 00 00 00 //item 122 eItem_IntWeap_VI 00 00 00 00 //item 123 eItem_END_SHIP_WEAPONS 00 00 00 00 //item 124 eItem_BEGIN_INTERCEPTOR_CONSUMABLES 00 00 00 00 //item 125 eItem_IntConsumable_Dodge 00 00 00 00 //item 126 eItem_IntConsumable_Boost 00 00 00 00 //item 127 eItem_IntConsumable_Hit 00 00 00 00 //item 128 eItem_END_INTERCEPTOR_CONSUMABLES 00 00 00 00 //item 129 eItem_END_VEHICLE_UPGRADES 00 00 00 00 //item 130 eItem_BEGIN_CORPSES 00 00 00 00 //item 131 eItem_CivilianCorpse 00 00 00 00 //item 132 eItem_TankCorpse 00 00 00 00 //item 133 eItem_SoldierCorpse 00 00 00 00 //item 134 eItem_SectoidCorpse 00 00 00 00 //item 135 eItem_SectoidCommanderCorpse 00 00 00 00 //item 136 eItem_FloaterCorpse 00 00 00 00 //item 137 eItem_FloaterHeavyCorpse 00 00 00 00 //item 138 eItem_ThinManCorpse 00 00 00 00 //item 139 eItem_MutonCorpse 00 00 00 00 //item 140 eItem_MutonEliteCorpse 00 00 00 00 //item 141 eItem_BerserkerCorpse 00 00 00 00 //item 142 eItem_CyberdiscCorpse 00 00 00 00 //item 143 eItem_EtherealCorpse 00 00 00 00 //item 144 eItem_CryssalidCorpse 00 00 00 00 //item 145 eItem_ZombieCorpse 00 00 00 00 //item 146 eItem_SectopodCorpse 00 00 00 00 //item 147 eItem_DroneCorpse 00 00 00 00 //item 148 eItem_END_CORPSES 00 00 00 00 //item 149 eItem_BEGIN_CAPTIVES 00 00 00 00 //item 150 eItem_SectoidCaptive 00 00 00 00 //item 151 eItem_SectoidCommanderCaptive 00 00 00 00 //item 152 eItem_FloaterCaptive 00 00 00 00 //item 153 eItem_FloaterHeavyCaptive 00 00 00 00 //item 154 eItem_ThinManCaptive 00 00 00 00 //item 155 eItem_MutonCaptive 00 00 00 00 //item 156 eItem_MutonEliteCaptive 00 00 00 00 //item 157 eItem_BerserkerCaptive 00 00 00 00 //item 158 eItem_EtherealCaptive 00 00 00 00 //item 159 eItem_END_CAPTIVES 00 00 00 00 //item 160 eItem_BEGIN_COLLECTIBLES 00 00 00 00 //item 161 eItem_Elerium115 00 00 00 00 //item 162 eItem_AlienAlloys 00 00 00 00 //item 163 eItem_WeaponFragment 00 00 00 00 //item 164 eItem_Meld 00 00 00 00 //item 165 eItem_AlienEntertainment 00 00 00 00 //item 166 eItem_AlienFood 00 00 00 00 //item 167 eItem_AlienStasisTank 00 00 00 00 //item 168 eItem_UFONavigation 00 00 00 00 //item 169 eItem_AlienSurgery 00 00 00 00 //item 170 eItem_UFOPowerSource 00 00 00 00 //item 171 eItem_HyperwaveBeacon 00 00 00 00 //item 172 eItem_DamagedAlienEntertainment 00 00 00 00 //item 173 eItem_DamagedAlienFood 00 00 00 00 //item 174 eItem_DamagedAlienStasisTank 00 00 00 00 //item 175 eItem_DamagedUFONavigation 00 00 00 00 //item 176 eItem_DamagedAlienSurgery 00 00 00 00 //item 177 eItem_DamagedUFOPowerSource 00 00 00 00 //item 178 eItem_DamagedHyperwaveBeacon 00 00 00 00 //item 179 eItem_UFOFusionLauncher 00 00 00 00 //item 180 eItem_PsiLink 00 00 00 00 //item 181 eItem_ExaltIntel 00 00 00 00 //item 182 eItem_END_COLLECTIBLES 00 00 00 00 //item 183 eItem_Base_Shard 00 00 00 00 //item 184 eItem_Skeleton_Key {|XGWeapon_SectopodChestCannon|} //iyrm 185 00 00 00 00 //item 186 eItem_XPACK_BEGIN_CORPSES 00 00 00 00 //item 187 eItem_MechtoidCore 00 00 00 00 //item 188 eItem_SeekerCorpse 00 00 00 00 //item 189 eItem_CorpsePlaceholder2 00 00 00 00 //item 190 eItem_XPACK_END_CORPSES 00 00 00 00 //item 191 eItem_BEGIN_MEC_ARMOR 00 00 00 00 //item 192 eItem_MecCivvies 00 00 00 00 //item 193 eItem_MecArmor1 00 00 00 00 //item 194 eItem_MecArmor2 00 00 00 00 //item 195 eItem_MecArmor3 00 00 00 00 //item 196 eItem_MecArmor1_Kinetic 00 00 00 00 //item 197 eItem_MecArmor1_Flamethrower 00 00 00 00 //item 198 eItem_MecArmor2_Kinetic_Grenade 00 00 00 00 //item 199 eItem_MecArmor2_Kinetic_Mist 00 00 00 00 //item 200 eItem_MecArmor2_Flamethrower_Grenade 00 00 00 00 //item 201 eItem_MecArmor2_Flamethrower_Mist 00 00 00 00 //item 202 eItem_MecArmor3_Kinetic_Grenade_Electro 00 00 00 00 //item 203 eItem_MecArmor3_Kinetic_Grenade_ProximityMine 00 00 00 00 //item 204 eItem_MecArmor3_Kinetic_Mist_Electro 00 00 00 00 //item 205 eItem_MecArmor3_Kinetic_Mist_ProximityMine 00 00 00 00 //item 206 eItem_MecArmor3_Flamethrower_Grenade_Electro 00 00 00 00 //item 207 eItem_MecArmor3_Flamethrower_Grenade_ProximityMine 00 00 00 00 //item 208 eItem_MecArmor3_Flamethrower_Mist_Electro 00 00 00 00 //item 209 eItem_MecArmor3_Flamethrower_Mist_ProximityMine 00 00 00 00 //item 210 eItem_END_MEC_ARMOR 00 00 00 00 //item 211 eItem_BEGIN_EXALT_WEAPONS {|XGWeapon_ExaltAssaultRifle|} //item 212 {|XGWeapon_ExaltSniperRifle|} //item 213 {|XGWeapon_ExaltMinigun|} //item 214 {|XGWeapon_ExaltLaserAssaultRifle|} //item 215 {|XGWeapon_ExaltLaserSniperRifle|} //item 216 {|XGWeapon_ExaltHeavyLaser|} //item 217 {|XGWeapon_ExaltRocketLauncher|} //item 218 [/BEFORE_HEX] I had to insert the item values / enums manually, though (with a bit of cut/paste from the enum reverse lookup). Link to comment Share on other sites More sharing options...
Amineri Posted March 12, 2014 Author Share Posted March 12, 2014 UPKmodder v0.82 has been uploaded : http://code.google.com/p/upk-modder This has only a single fix :- Fixed bug preventing processing of embedded names in hex. This fix allows embedding of namelist entries using <| ... |> delimiters, and embedding of import/export object entries using {| ... |} delimiters. The ReferenceUpdater tool built into UPKmodder can convert hex references to valid names using the correct delimiters with the "convert to names" option.The user can also manually enter names. Link to comment Share on other sites More sharing options...
Amineri Posted April 5, 2014 Author Share Posted April 5, 2014 I'd typed up some additional information regarding how to change object table entries for johnnylump, so I thought I'd post them here as well for anyone that is interested. Object table data is what is accessed with UE Explorer in the "Table Buffer". The actual object's hex itself is accessed via the "Buffer". Does this mean changing the first 48 bytes that comes out when you do a buffer dump? What if I want to change something that appears in the "table buffer" hex instead? Right, each object has information stored in two different places. The UE Explorer "Table Buffer" is the a table entry for the object (which has some basic descriptive information about the object, including the file position and file size of the object within the upk). Typically each of the table entries is 68 bytes long. UPKmodder automatically parses the entire object table for each upk it deals with. That's how it builds the reference ID-to-number mapping. The reference number is just the index within this table. XComGame.upk for EW has about 55,000 (= D6D8) entries in the table, so that's why the numbers grow around that big. UPKmodder extracts the "useful" information from each object using (this is pasted directly out of the Java source code for UPKmodder) : private void parseData(int[] data) { this.iType = data[0]; this.iParent = data[1]; this.iOuter = data[2]; this.iNamePtr = data[3]; this.iHighFlags = data[6]; this.iLowFlags = data[7]; this.iUpkSize = data[8]; this.iUpkPos = data[9]; // TODO: parse/store other values, create getters and other convenience methods (e.g. getNameListIndex(), etc.) }UPKmodder reads the object table data as 4-byte words instead of at the byte-level. Most entries contain 17 4-byte words, although the specifier at position 11 specifies additional 4 byte-words (this value is only non-zero for non-script objects, in my experience). The stuff at the back end of each isn't of use for scripting (e.g. variables, enumerations, functions), and appears to be used to define art asset object info (e.g. 3D meshes, animations, textures, sound files). I'm not sure what the 64 bits of flags all do, either. When you include a RESIZE= command for an object it automatically updates the UpkSize of the current object and the UpkPos of all subsequent objects (all objects that have a position later than the current one). --------------- In UE Explorer the regular hex "Buffer" displays the hex for the object itself. The position and size of this object within the upk file is defined via the UpkSize and UpkPos entries within the table entry for the object (i.e. if you looked up the table buffer, read words 8 and 9, opened the upk with HxD and went to that position you'd find the object hex). Functions contain both the run-time "byte-code" bytes as well as 48 bytes of header and 15 bytes of footer information. Typically the only bytes in the header/footer that are changed are the last two words, which contain the memory/file size of the byte-code. The preceding 40 bytes do contain some useful things, including some references (import, object, and/or name). This means that listing the full raw header hex isn't patch-safe, since those values may be updated. However, you can use the name of the object which UPKmodder will attempt to convert to hex at apply/revert-time, which does make it patch-safe. (e.g. {|iType@GetPossibleSpawns@XGDeployAI|}) I'm just not sure what the different header/footer bytes do specifically. I'm pretty sure that there are flags defining the function type (e.g. private, static, native, virtual) in the footer. And that some of the header information is used to in creating the linked list of local variables/parameters/return value for the function. Wghost is ahead of me in decoding that stuff. --------------By default UPKmodder changes the object entry itself (the "buffer dump"). It can change any bytes within the object hex, which is how we make changes to enumerations and variables, for example. For functions this includes the full function header (48 bytes) and footer (15 bytes). UPKmodder will only change hex in the object table when using special commands. For example the RESIZE= command alters size/position of many object table entries. Other commands include:ACTION=typechange -- a specific command that requires changing both the iType and UpkSize fields of the object table entry. These are specified using OBJECT_TYPE= and SIZE=, for example : ACTION=typechange //change object type parameter into int type [BEFORE_HEX] OBJECT_TYPE=Core:ObjectProperty@Core SIZE=2C // hexadecimal [/BEFORE_HEX] [AFTER_HEX] OBJECT_TYPE=Core:IntProperty@Core SIZE=28 // hexadecimal [/AFTER_HEX]For more general-purpose changes to the object table entry for an object, there is the - ACTION=genericObjectTableChange This allows you to manually change most any entry within the object table entry. Note that this can easily corrupt the upk, in particular if the size/position values are changed incorrectly. For this command new values are specified via keywords, instead of via generic hex changes. This is because UPKmodder has to store copies of most of the table entry data in order to properly decode things, so changing these things is a little trickier and has to be under tighter control. Fortunately there aren't many 'useful' table values, so they can all be specified directly. This command could actually supercede the "typechange" command, as it's more flexible. It allows any or all entries below to be changed --not all values have to be specified. The keywords that allow changes to the object table entry are :OBJECT_TYPE : bytes 0-3 in the table bufferOBJECT_PARENT : bytes 4-7 in the table bufferOBJECT_OUTER : bytes 8-11 in the table bufferOBJECT_NAMEIDX : bytes 12-15 in the table bufferOBJECT_HIGHFLAGS : bytes 20-23 in the table bufferOBJECT_LOWFLAGS : bytes 24-27 in the table bufferOBJECT_SIZE : bytes 28-31 in the table bufferOBJECT_POSITION : bytes 32-35 in the table buffer A few notes about these.OBJECT_TYPE is almost always an import object (reference value is negative), so in UPKmodder would be specified in a patch-safe manner as something like Core:IntProperty@Core, or Core:FunctionProperty@Core.OBJECT_PARENT is only used for classes, and indicates the parent of a class (e.g. XGWeapon is the parent of XGWeapon_AssaultRifle) This is typically a regular object referenceOBJECT_OUTER indicates hierarchical ownership. For example in iType@GetPossibleSpawns@XGDeployAI, the iType object has as OUTER the GetPossibleSpawns object, while GetPossibleSpawns has as OUTER the XGDeployAI object. XGDeployAI has a null OUTEROBJECT_NAMEIDX is a reference to a name entry (an index into the name table). This is effectively how each object is named. Objects with the same name reference the same name entry without problem.UPKmodder expects certain type values in each field :OBJECT_TYPE : must be a valid object (import or export) name (e.g. Core:Function@Core or Core:IntProperty@Core)OBJECT_PARENT : must be a valid object (import of export) nameOBJECT_OUTER : must be a valid object (import of export) nameOBJECT_NAMEIDX : must be a valid name on the namelistOBJECT_HIGHFLAGS : must be an integer, specified in hexadecimalOBJECT_LOWFLAGS : must be an integer, specifed in hexadecimalOBJECT_SIZE : must be an integer, specifed in hexadecimalOBJECT_POSITION : must be an integer, specifed in hexadecimalChanging the OBJECT_NAMEIDX for an object is problematic since the name is how the object is referenced in the first place. So changing the name results in UPKmodder being unable to properly locate the object after the change (to verify correct install and to be able to revert the change). IMPORTANT!!!When changing the NAMEIDX, leave the name of the current object out of the FUNCTION= (alternative usage OBJECT_ENTRY=) specifier. For example : MODFILEVERSION=4 UPKFILE=XComGame.upk GUID=1C 18 A1 1A 2B C3 34 4E 8B 2C 72 33 CD 16 7E 3E // XComGame_EW_patch3.upk OBJECT_ENTRY=CheckpointRecord_XGWeapon@XGWeapon ACTION=genericObjectTableChange //iOverheatChance@CheckpointRecord_XGWeapon@XGWeapon //alter CheckpointRecord_XGWeapon so that m_iTurnFired is the member, not iOverheatChance [BEFORE_HEX] OBJECT_NAMEIDX=iOverheatChance [/BEFORE_HEX] [AFTER_HEX] OBJECT_NAMEIDX=m_iTurnFired [/AFTER_HEX] In this case the object iOverheatChance@CheckpointRecord_XGWeapon@XGWeapon is being transformed into the object m_iTurnFired@CheckpointRecord_XGWeapon@XGWeapon. The CheckpointRecord_XGWeapon@XGWeapon object itself is not being changed. Instead if UPKmodder sees that the OBJECT_NAMEIDX= field is being changed, it automatically prepends the value to what is specified in the OBJECT_ENTRY field. So when applying the change, it locates the object with the name "iOverheatChance@CheckpointRecord_XGWeapon@XGWeapon"When reverting the change is locates the object with the name "m_iTurnFired@CheckpointRecord_XGWeapon@XGWeapon"Then testing for apply/revert status, it tests both. Link to comment Share on other sites More sharing options...
Recommended Posts