[X3LU][KC] .obj files editing

The place to discuss scripting and game modifications for X³: Terran Conflict and X³: Albion Prelude.

Moderators: Moderators for English X Forum, Scripting / Modding Moderators

Post Reply
lostProfitssssArrgh
Posts: 161
Joined: Tue, 22. Aug 17, 13:14

[X3LU][KC] .obj files editing

Post by lostProfitssssArrgh » Sun, 24. Sep 17, 09:58

Hello!

First of all, a disclaimer : this topic was posted mainly to understand the intricacies of modifying .obj files, purely as a learning exercise. We'll assume that the subject is considered a grey-ish area, and that the theoretical methods for accessing and reinserting those are known. Also, please don't reply with requests for mods etc...

Disclaimer #2 : while not being entirely clueless about programming, I've never written compiled production code.

...

Let's start with an example : a while ago, I was trying to add to the 'famous quotes' displayed during the intro and made a list of another 67 of those. Adding those to the proper page # wasn't enough, even when inserted directly into 0001-L044. The conclusion I arrived to is that the total number of quotes (68 in LU) from which one is randomly picked is hard-coded somewhere other than the usual mod-related files. After digging around some more, this value seems to be defined in x3intro.obj (based on a test where adding an empty x3intro.obj crashes the game at the proper time with the error 'File not found : x3intro'). However, changing any/some/all 68d(44h) values to 135d(87h) never loads quotes past the 68th. Furthermore, changing only the most likely candidate (push 68d; call SE_random) has for effect to load the first quote (#0) listed in 0001-L044 but none of the others...

I'm confident that the .obj is properly generated since inserting an unmodified, de-compiled/re-compiled .obj works fine. On a side note, I also tried hex-editing (aka blind-gambling) the only reference to x06x44, assuming the x86 op-codes remain valid. No go.

So, *IF* the aforementioned approach is sound, the question boils down to : what aspect of the loading sequence or KC-related intricacy am I missing here?

Thanks a lot,
-lpa

User avatar
Jack08
Posts: 2993
Joined: Sun, 25. Dec 05, 10:42
x3tc

Post by Jack08 » Sun, 24. Sep 17, 11:39

Modifying

Code: Select all

           pushb      68d ; 44h
           push       1
           callasm    SE_Random
           push       1
           add        SP[0],SP[1]
to

Code: Select all

           pushb      135d
           push       1
           callasm    SE_Random
           push       1
           add        SP[0],SP[1]
*should* have worked, its very odd that it didnt. Did you place the new file in the <GameRoot>\L directory, and not the <GameRoot>\addon\L directory? The first is valid, the latter isnt.

If you want to see if your new strings are even beeing loaded, consider adding a direct offset instead of changing the random amount:

Code: Select all

           pushb      68d ; 44h
           push       1
           callasm    SE_Random
           pushb      68d ; <<<Offset 
           add        SP[0],SP[1]
P.S. This is alot of effort to add some strings the most users never really see anyway :D I know i always skip the egosoft into logo which skips the quote too haha.
[ external image ]
"One sure mark of a fool is to dismiss anything that falls outside his experience as being impossible."
―Farengar Secret-Fire

lostProfitssssArrgh
Posts: 161
Joined: Tue, 22. Aug 17, 13:14

Post by lostProfitssssArrgh » Sun, 24. Sep 17, 14:45

Hi!

Your suggestion about using an offset did confirm that the new quotes get loaded when forcing values > 68d.

Code: Select all

pushb      68d ; 44h 
push       1 
callasm    SE_Random 
pushb      69d ; NEW QUOTE LOADED!!!
I later discovered that using values > 127d to reference quote strings always returns index 0.

Code: Select all

pushb      128d ; Returns comment 0, hard limit somewhere else...
push       1 
callasm    SE_Random
So, there can only be 128 quotes in total... Having 135 did allow for discovering that limit, at least. However, I wasn't able to track down where that limit is set, but I didn't put that much effort into it (reading asm SUCKS).
Jack08 wrote:P.S. This is alot of effort to add some strings the most users never really see anyway :D I know i always skip the egosoft into logo which skips the quote too haha.
True that, I also use -skipintro -noabout nowadays. But some of the quotes are quite insightful, which motivated my initial foray into this thinking it would be a painless micro-mod...

___


Next project : testing x3galedit.obj to see if the 24*20 sector count is indeed limited by hard-coded loops like in x2story.cpp:

Code: Select all

for(loc2=0;loc2<15;loc2=loc2+1)
  {
  for(loc1=0;loc1<20;loc1=loc1+1)
   {
...}}
I'm guessing it is after looking at the asm, but it'll be really hard to confirm since compiling files larger than x3intro.obj crashes systematically. I've also looked a bit into hex-editing these, but I can't tell for sure if KC's op-codes are consistent with those of x86. Fun stuff :D

Thanks again,
-lpa

PS: I can't believe you guys in the LU team actually managed to pull it off while dealing with all this asm crap... Truly outstanding :thumb_up: :thumb_up: :thumb_up:

User avatar
Jack08
Posts: 2993
Joined: Sun, 25. Dec 05, 10:42
x3tc

Post by Jack08 » Sun, 24. Sep 17, 19:40

Sorry i just realized the mistake, 'pushb' can only be used to push 1 byte in size, hence b. You need to use pushw for 2 byte values or pushd for 4 byte values.

x86 has no bearing here.
[ external image ]
"One sure mark of a fool is to dismiss anything that falls outside his experience as being impossible."
―Farengar Secret-Fire

User avatar
Joubarbe
Posts: 4796
Joined: Tue, 31. Oct 06, 12:11
xr

Post by Joubarbe » Sun, 24. Sep 17, 19:45

You weirdos.

lostProfitssssArrgh
Posts: 161
Joined: Tue, 22. Aug 17, 13:14

Post by lostProfitssssArrgh » Sun, 24. Sep 17, 20:23

Jack08 wrote:Sorry i just realized the mistake, 'pushb' can only be used to push 1 byte in size, hence b. You need to use pushw for 2 byte values or pushd for 4 byte values.
Then 'pushb' must work with signed integers, otherwise the limit would be 255. I'll assume that also applies to 'pushw' and 'pushd'.

Jack08 wrote:x86 has no bearing here.
If I follow you correctly, I can't rely on x86 op-codes to edit .objs as binaries... :( So it's either figure out KC's keywords once compiled or get the compiler to work with larger files.

Thanks!
-lpa

lostProfitssssArrgh
Posts: 161
Joined: Tue, 22. Aug 17, 13:14

Post by lostProfitssssArrgh » Sun, 24. Sep 17, 20:30

Joubarbe wrote:You weirdos.
Must be. I'm having more fun figuring this out than playing Mayhem :P

User avatar
Litcube
Posts: 4254
Joined: Fri, 20. Oct 06, 19:02
xr

Post by Litcube » Mon, 25. Sep 17, 02:03

lostProfitssssArrgh wrote: I'm having more fun figuring this out than playing Mayhem :P
Oh snap

lostProfitssssArrgh
Posts: 161
Joined: Tue, 22. Aug 17, 13:14

Post by lostProfitssssArrgh » Thu, 28. Sep 17, 19:47

Image
Image

Yay! :D

The extra sectors don't show up in GE's map unfortunately; not that he game can handle 480 sectors anyway, let alone 832.

It's useless but it makes me feel like I've achieved something.

-lpa

User avatar
Jack08
Posts: 2993
Joined: Sun, 25. Dec 05, 10:42
x3tc

Post by Jack08 » Thu, 28. Sep 17, 22:32

Unfortunately thoes commands are hard coded to return a constant value, they dont actually "check" anything. So unless you get to the point where you can actually teleport to one of these coordinates its likely not working.
[ external image ]
"One sure mark of a fool is to dismiss anything that falls outside his experience as being impossible."
―Farengar Secret-Fire

Cycrow
Moderator (Script&Mod)
Moderator (Script&Mod)
Posts: 22227
Joined: Sun, 14. Nov 04, 23:26
x4

Post by Cycrow » Fri, 29. Sep 17, 10:30

Those values are basically #defines, so you would need to change every occurrence of them for it to work. Which would be difficult

lostProfitssssArrgh
Posts: 161
Joined: Tue, 22. Aug 17, 13:14

Post by lostProfitssssArrgh » Fri, 29. Sep 17, 11:37

Jack08 wrote:Unfortunately those commands are hard coded to return a constant value, they dont actually "check" anything. So unless you get to the point where you can actually teleport to one of these coordinates its likely not working.
Agreed.

I tried setenv-> and a test map with NewSector(24,20) added as text, but neither work when trying to access out-of-range sectors in the GE.
Cycrow wrote:Those values are basically #defines, so you would need to change every occurrence of them for it to work. Which would be difficult
I naively replaced every occurrence of close-to-one-another 24 and 20 values, within 'obvious' loop constructs (hard to be sure when looking at asm). Some of the boundary-related code got changed, like the getMaxX-Y() return values. However, getting everything to work with such an approach is indeed next to impossible...

One question became obvious though: is there a valid reason why maxX and maxY wouldn't be defined as global vars somewhere?

User avatar
Jack08
Posts: 2993
Joined: Sun, 25. Dec 05, 10:42
x3tc

Post by Jack08 » Fri, 29. Sep 17, 13:09

They are technically global defines, but your looking at compiled output, which the compiler optimizes by in-lining statically defined global values to save a lookup. (Tho technically, yes, they are not variables, they are #define preprocessor macros because AFAIK KC has no static variable concept, only non static global variables and an very odd/fake static class concept)
[ external image ]
"One sure mark of a fool is to dismiss anything that falls outside his experience as being impossible."
―Farengar Secret-Fire

lostProfitssssArrgh
Posts: 161
Joined: Tue, 22. Aug 17, 13:14

Post by lostProfitssssArrgh » Fri, 29. Sep 17, 14:33

@Jack08

Thanks for confirming that. Hoping to come in before a reply, I just rushed back from being afk after realizing a compiler would substitute an internal constant for the reason you mentioned, and maybe also when the value for that constant is shorter than the lookup address (uneducated guess). It just makes sense from a logic pov, so much so that looking it up seems futile.

Damn it, looking into this stuff further demonstrates my inadequacy with every step... And also makes it impossible to go back to simply enjoying this/any game.

*head explodes*

User avatar
Jack08
Posts: 2993
Joined: Sun, 25. Dec 05, 10:42
x3tc

Post by Jack08 » Fri, 29. Sep 17, 15:05

I've sent you a pm with hopefully a stable file, good luck.
[ external image ]
"One sure mark of a fool is to dismiss anything that falls outside his experience as being impossible."
―Farengar Secret-Fire

lostProfitssssArrgh
Posts: 161
Joined: Tue, 22. Aug 17, 13:14

Post by lostProfitssssArrgh » Sat, 30. Sep 17, 11:57

Jack08 wrote:I've sent you a pm with hopefully a stable file, good luck.
Thanks again. Did you manage to get the added sectors to be shown/visitable? I couldn't do so through the GE with the pm'd files :(
(I hope you didn't go out of your way making these, maybe thinking they were needed elsewhere. If so, I apologize for failing to point out this is only for practice.)

User avatar
Jack08
Posts: 2993
Joined: Sun, 25. Dec 05, 10:42
x3tc

Post by Jack08 » Sat, 30. Sep 17, 16:56

I didn't test them, as for them not showing up, its likely because of the universe bod file not containing them.

I've only tried this once in the past, so i never fully figured it all out (or if was even fully possible, could have engine level hard coding preventing it from working properly)
[ external image ]
"One sure mark of a fool is to dismiss anything that falls outside his experience as being impossible."
―Farengar Secret-Fire

lostProfitssssArrgh
Posts: 161
Joined: Tue, 22. Aug 17, 13:14

Post by lostProfitssssArrgh » Sun, 1. Oct 17, 16:32

Jack08 wrote:...its likely because of the universe bod file not containing them...
I added the following to x3folder/objects/cut/00749.bod :

Code: Select all

p 1112; B 2521; N 2521;
  { 0x2002;  213567; -175224; 0;  0.000000; 0.000000; 0.000000; 0.000000;  -1;  -1; } // 0
The new sector sector didn't show in GE maps, using either an empty map or loading a test map with the following definitions:

Code: Select all

<?xml version="1.0" encoding="UTF-8" ?>
<universe>
	<o f="1" t="1" x="1" y="3" r="8" size="10000000" m="0" p="77163135" qtrade="100" qfight="100" qbuild="100" qthink="100">
		<o t="2" s="0" neb="0" stars="0"/>
	</o>
	<o f="1" t="1" x="23" y="19" r="8" size="10000000" m="0" p="1123606" qtrade="100" qfight="100" qbuild="100" qthink="100">
		<o t="2" s="0" neb="0" stars="0"/>
	</o>
	<o f="1" t="1" x="24" y="20" r="8" size="10000000" m="0" p="77163136" qtrade="100" qfight="100" qbuild="100" qthink="100">
		<o t="2" s="0" neb="0" stars="0"/>
	</o>
</universe>
The first 2 sectors show alright, not the third (barring, dumb mistakes made on my end.)

Oh well. I'm guessing that there must be a ton of game internals and scripts relying on hard-coded sector coordinates anyways, getting the map to work would only be the beginning of a long and painful process.

So long 10,000 sector universe! :D

Post Reply

Return to “X³: Terran Conflict / Albion Prelude - Scripts and Modding”