@foone@digipres.club avatar

foone

@foone@digipres.club

Hardware / software necromancer, collector of Weird Stuff, maker of Death Generators. (she/they🏳️‍⚧️)

This profile is from a federated server and may be incomplete. Browse more on the original instance.

foone, to random
@foone@digipres.club avatar

bad news: after extensive digging into how Wheel of Fortune (2010, Wii) loads resource files, it seems that there's no way to get it to load patch files from the memory card.

It seems to only look for them on the DVD

foone,
@foone@digipres.club avatar

so it adds the / directory of the DVD to the searcxh path, then bundles (where the bundles are), then scripts (where the scripts are), then /Audio (where the audio files are), then it runs into a problem

foone,
@foone@digipres.club avatar

it queries the current language and tries to add /Audio/$ThatLanguage to the search path. It fails because that folder doesn't exist.

So then it falls back to adding /Audio\English, which also doesn't exist. But since it doesn't check that the add succeeds, it continues loading.

foone,
@foone@digipres.club avatar

Then it adds /Video (where the videos are) and then /Media

There is no /Media on the disc, so I don't know what was supposed to be in there.

foone,
@foone@digipres.club avatar

Finally it checks the language (again!) and adds /Speech/$ThatLanguage to the search path.

Since getLanguage always returns "American", this'll try to add /Speech/American to the search path, and then fail because that folder doesn't exist.
Fortunately the fallback it does try, /Speech\English, does exist.

foone,
@foone@digipres.club avatar

it's not my job to offer code reviews of 13 year old games but this seems less than efficient.
what if they want scripts to vary from language to language? or, hey, some of these movies have voiceovers in them... why not localize those?

foone,
@foone@digipres.club avatar

The answer for scripts at least is that they implemented PackageAppInterface::getLanguage in their scripting engine, so each script can handle their own localization, rather than having per-localization scripts.

foone,
@foone@digipres.club avatar

Maybe they do the same thing with movies. The movies are probably getting played by the scripting engine, so they could just switch what filenames they call for different languages

foone,
@foone@digipres.club avatar

not that it matters in this case: Wheel of Fortune is a US-only game so the only language it exists in is English

foone,
@foone@digipres.club avatar

but this same engine is used in a bunch of games, many of which presumably had non-english versions.

foone,
@foone@digipres.club avatar

You wanna know the weirdest thing this game does with regards to loading bundles?

So, it tries to mount 4 bundles at startup:

The system resources bundle (filename unknown), "SharedAssets.bdg", "Wheel.bdg", and "Patch.bdg".

Now, the disc only contains SharedAssets.bdg, and Wheel.bdg. Patch.bdg is missing, but that's okay, apparently.

But the system resources bundle is vital to having the game boot up. It's not in any file visible in the filesystem. So where is it?

foone,
@foone@digipres.club avatar

SURPRISE! It's a ROM Bundle!

Wait this is a game shipped on an optical disc, it doesn't have any ROMs?

foone,
@foone@digipres.club avatar

well, ROM bundle just means that instead of a filename to mount, you give it a memory pointer + length.
And it parses the bundle out of RAM.

So... I guess it manually loads the bundle from somewhere else? NOPE!

foone,
@foone@digipres.club avatar

there's no code in the game to load the memory location it loads the system bundle out of

foone,
@foone@digipres.club avatar

they embedded it into the executable. That bundle's memory is loaded by the OS loader.

foone,
@foone@digipres.club avatar

and this quickly gets really confusing because one of the first things the game loads is "[SHARED]\Localization\SharedLoc.loc.prd", which you'd think is in the SharedBundle, and it is!

foone,
@foone@digipres.club avatar

except that one isn't used, because it's also in the "ROM bundle" and that one overrides it.

foone,
@foone@digipres.club avatar

which frankly is an underrated anti-reversing technique. Have multiple copies of important subfiles in separate datafiles and have complex precedence rules to determine which one gets loaded, then ignore all of them for another copy you embedded into the binary

foone,
@foone@digipres.club avatar

anyway I don't think they were intentionally trying to make this hard to reverse engineer (if they were, they failed so hard), but it does mean that technically to automatically know what resources will be loaded by the game, you have to solve the halting problem

foone,
@foone@digipres.club avatar

since you can't just look at the bundle files on disc and interpret what data is in them, as the existence of ROM bundles mean you have to ask the question "will this executable ever call BundleManager::mountBundle(BundleManager*,uchar*,int)?" and that's not possible to automatically know. FORTUNATELY I'm doing this manually and the behavior is deterministic.

foone,
@foone@digipres.club avatar

anyway, this is only vaguely related, but there needs to be a tool that helps tie dynamic debugging with static debugging.

foone,
@foone@digipres.club avatar

like, use the dynamic debugging traces to do things like annotate functions with records of how often they get called from different sources

foone,
@foone@digipres.club avatar

or click a function and see what arguments it has been called with in traces

foone,
@foone@digipres.club avatar

sadly the wii balance board support classes in the engine are just leftovers from the engine's use in other games, and not proof that the developers of Wheel of Fortune (2010, Wii) were far ahead of their time in avant-garde gaming

foone,
@foone@digipres.club avatar

although given my reverse engineering work, it's possible that I may one day reverse this wrong

foone,
@foone@digipres.club avatar

man I'm used to weird padding in structures and strange gaps, but 14 kilobytes? Why?

  • All
  • Subscribed
  • Moderated
  • Favorites
  • megavids
  • Durango
  • DreamBathrooms
  • ngwrru68w68
  • osvaldo12
  • cubers
  • magazineikmin
  • ethstaker
  • Youngstown
  • rosin
  • slotface
  • everett
  • kavyap
  • InstantRegret
  • JUstTest
  • khanakhh
  • thenastyranch
  • anitta
  • modclub
  • GTA5RPClips
  • mdbf
  • cisconetworking
  • tester
  • tacticalgear
  • provamag3
  • Leos
  • normalnudes
  • lostlight
  • All magazines