

The CEX class has a function that adds a message to the queue. This led me to a global instance of the CEX class which manages the message queue and a list of objects that can receive messages. From there I could walk up the stack trace and find what was calling the message handler functions. Where do the messages come from? I found out by using WinDbg to run the game and put a breakpoint on the message handler functions. Message handler map for the Theatre class Creating enums made it easier to identify other usages of the message IDs. I also named the “get message handler map” function in the CMH vtable. I created structures in Ghidra for the message handler maps and the messages, and created enums for the message IDs. The CMH class has a message dispatch function that searches for the message ID in the handler map and then tries the parent’s message handler map if it can’t find the message ID. The structure also has a pointer to the parent class’s message handler map. The CMH base class includes a function that returns a pointer to a structure that maps message IDs to functions that handle the message. the user requested to open a movie file). the user moved the mouse) and high-level game logic (eg. These messages handle low-level user interaction (eg. Many of the game’s classes, including the GOB class, inherit from a base class that provides functions for handling messages.

Similarly, I spent a bunch of time looking at string handling functions, list functions and file IO classes - they aren’t very interesting, but definitely helped to provide context when reversing more complicated parts of the game engine.

The iterator class probably isn’t the most interesting thing to reverse engineer in the binary, but mapping out these kinds of basic classes is important as they are often referenced in more complex functions. Annotated decompilation of 'find graphical object by hWnd' function The result would then be compared with something. I noticed a pattern with how the GTE object was used: the object would be initialized, then another GTE function would be repeatedly called in a loop. I found another object, GTE, was often referenced when the global GOB was accessed. I suspect this may be a remnant of development versions of the game engine - or possibly they added the feature and just never used it.
#3D MOVIE MAKER CODE#
There’s a bunch of code in the binary for handling MDI windows which doesn’t seem to be used. In 3DMM everything is rendered on a single window object, so all of the objects have the same hWnd. GOBs also hold a handle to the window (hWnd) on which they are drawn. The game has a global pointer to the root GOB which contains all of the GOBs for the game’s UI. GOBs are hierarchical: a GOB has a pointer to a single child GOB, and has a pointer to a sibling GOB that acts as a singly-linked list of GOBs at the same level of the hierarchy. GOBs have some of the basic properties you would expect an entity in a 2D game engine to have: a unique ID, a position and a size. I guessed this was the base class for graphical objects. I found from my reconstructed class hierarchy that all of the UI-related objects derive from the GOB class.

So, I decided to look at common base classes instead. MVIE for movie, STIO for the Studio, TATR for the Theatre), but these objects are quite complex. How do we identify the interesting classes to start reversing first? I started looking at classes that I could recognise from their type tags (eg. Previously, I recovered the class hierarchy by reversing the game’s custom runtime type identification code.
#3D MOVIE MAKER SERIES#
This blog series is about my adventures in reversing 3D Movie Maker and some of the interesting things I learnt along the way. Reverse engineering 3D Movie Maker - Part 2Ī while ago, I started reverse engineering Microsoft 3D Movie Maker to understand how it works and to develop my game reversing skills.
