@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

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?

foone,
@foone@digipres.club avatar

the struct WiiControllerPack has, at offset 1480, an array of 4 KPADStatus structures.
Each of those is 250 bytes. So this array is over by byte 2440.
So where does the next member start? offset 16888.

foone,
@foone@digipres.club avatar

that's 14,448 bytes of nothin'.

or maybe, given that it's left out of the debugging info, 3612 separate vtable pointers!

(this is a joke. it can't possibly be that)

foone,
@foone@digipres.club avatar

wait. the revolution SDK defines KPADStatus about how I'd expect but then it defines KPADUnifiedWpadStatus which is a union of various things. I wonder if my debugging info is eliding some weird union nonsense going on which explains why everything is so big

foone,
@foone@digipres.club avatar

no these all seem to be smaller

what the fuck

foone,
@foone@digipres.club avatar

this is the worst thing about reverse engineering.
you pretty much never can assume "well something weird happened randomly"

foone,
@foone@digipres.club avatar

no, there is A Reason why the compiler did this, and you are going to have to find out what it was

foone,
@foone@digipres.club avatar

me "well at least I have a bunch of types from the debug files, so I can finally figure out the types of a bunch of these untyped globals! goodbye, undefined1 PrimDrawer::bPrimBuffer[6144], let's see what you really are!"

Dumped DWARF debugging info: "unsigned char PrimDrawer::bPrimBuffer[6144]"

WELL THAT DIDN'T HELP MUCH

foone,
@foone@digipres.club avatar

I'm pretty sure this game had two programmers who each compiled 50% of the game's code.

Programmer A had their compiler set to output every bit of debug information it could, short of just shipping the .cpp files

Programmer B had their compiler set to aggressively optimize and never output any debugging info

at the end of the development, the object files from these two developers were linked together, then that binary was shipped to the customer

foone,
@foone@digipres.club avatar

seriously. I have complete info telling me that void WorldObject::updateVisRes(const WClipFrust &, CCheckResults); was defined on line 335 of E:\Build\WheelJeopardy\World/WorldObjectBase.h

what's a WClipFrust? that information is not in the debugging info. Go fuck yourself.

foone,
@foone@digipres.club avatar

I think the only thing this compiler has ever inlined is vector.push_back()

foone,
@foone@digipres.club avatar

which is great because it really aids clarity of reverse engineering that every time they call vector.push_back() there's 20 lines of support code for it

foone,
@foone@digipres.club avatar

just after I say this, guess what I find, plain as day, in the disassembly?

MVectorBase<WStaticMesh*,WStaticMesh*,4>::push_back((MVectorBase<WStaticMesh*,WStaticMesh*,4> *)&this->static_meshes,local_20);

OH SO YOU ONLY SOMETIMES INLINE IT, DO YOU?

foone,
@foone@digipres.club avatar

it's inlined earlier in this same function

what the fuck

foone,
@foone@digipres.club avatar

either they REALLY wanted to specify that this class initializes all the floats to 340282349999999991754788743781432688640, or they accidentally included a little-endian NaN when they meant a big-endian NaN.

foone,
@foone@digipres.club avatar

I'm not really sure how you accidently code a floating point number to have the wrong endianness.

foone,
@foone@digipres.club avatar

yeah after some dynamic testing, I think the reason this particular WStaticMesh and WSector and WPortal and WOccluder is extra cursed, with missing debug info and incorrect-invalid-floats?

It's never called. Why would it be? This is a game that basically takes place in one big room, plus a menu. Why would your map need to be split up into sectors?

foone,
@foone@digipres.club avatar

it probably got left in because

  1. codewarrior is terrible at dead code elimination (and all other optimizations)
  2. they have an advanced scripting engine, making dead code elimination even harder
  • All
  • Subscribed
  • Moderated
  • Favorites
  • JUstTest
  • InstantRegret
  • mdbf
  • ethstaker
  • magazineikmin
  • cubers
  • rosin
  • thenastyranch
  • Youngstown
  • osvaldo12
  • slotface
  • khanakhh
  • kavyap
  • DreamBathrooms
  • provamag3
  • Durango
  • everett
  • tacticalgear
  • modclub
  • anitta
  • cisconetworking
  • tester
  • ngwrru68w68
  • GTA5RPClips
  • normalnudes
  • megavids
  • Leos
  • lostlight
  • All magazines