Getting pointers from M2Emulator

Technical discussion for those interested in Supermodel development and Model 3 reverse engineering. Prospective contributors welcome.
Forum rules
Keep it classy!

  • No ROM requests or links.
  • Do not ask to be a play tester.
  • Do not ask about release dates.
  • No drama!

Getting pointers from M2Emulator

Postby Pedro Pablo » Thu Feb 23, 2017 3:03 pm

Hello Supermodel fashionistas! (I couldn't find another description)

Some time ago i was developing an app written in Python to read memory address or UDP servers from racing games to get telemetry and getting work servomotors or displays like speedometers, tachometers, gear indicator, etc...... I'm still newbie with coding but at least i've done something, here's a crappy demostration on my channel https://www.youtube.com/watch?v=6fBrVqy9n10

I'm trying to get the data from many racing games as possible either if it's from memory address, udp server, memory mapping, etc..... Some time ago i was able to get the speed, rpm and gear from Daytona 2, but some user told that it's kinda difficult to get the pointer from Supermodel. So i'm trying to get the same data from Daytona USA using M2 Emulator but it is also difficult to get the pointers. Any idea or tip to get that?
User avatar
Pedro Pablo
 
Posts: 16
Joined: Tue Dec 27, 2016 4:17 pm

Re: Getting pointers from M2Emulator

Postby Bart » Mon Feb 27, 2017 10:13 am

That's pretty interesting! How did you obtain it from Supermodel? My guess is that you identified the program space address where the game was storing its speedometer data. Why would this method not also work for M2emulator?
User avatar
Bart
Site Admin
 
Posts: 1917
Joined: Thu Sep 01, 2011 2:13 pm
Location: New York City

Re: Getting pointers from M2Emulator

Postby Pedro Pablo » Tue Feb 28, 2017 10:51 am

With Cheat Engine I started to find unknown values, then looking when it increases or decreases. IDK where i read about the "dinamyc memory changes" on Supermodel and because of that it's kinda hard to get the pointers. It would be great to develop a software to output the values straight from the emulator and not using a software to read memory addresses.

Soon i'll post pictures what i'm looking for
Last edited by Pedro Pablo on Sat Apr 08, 2017 10:24 pm, edited 1 time in total.
User avatar
Pedro Pablo
 
Posts: 16
Joined: Tue Dec 27, 2016 4:17 pm

Re: Getting pointers from M2Emulator

Postby Pedro Pablo » Wed Mar 01, 2017 11:46 am

http://imgur.com/a/HTglM

Here is a picture of Supermodel and Cheat Engine. Some values represents the car speed in the game world, and other values represents the car speed to control the speedometer (like the address which contains '13'). Also, keep in mind that i press the brake pedal into the floor some values goes to 0 (the speedometer), but some values still shows some numbers because the car is still moving (the car movement in the game world).

What's next? With that memory addresses i need to find the pointers of the certain value because it changes when i reopen the emulator. Some of those values are just pointers from other values (but it still changes the i reopen supermodel) because on the demostration some addresses shows the values and other it shows '0'
User avatar
Pedro Pablo
 
Posts: 16
Joined: Tue Dec 27, 2016 4:17 pm

Re: Getting pointers from M2Emulator

Postby Bart » Thu Mar 02, 2017 8:29 am

Pedro Pablo wrote:http://imgur.com/a/HTglM

Here is a picture of Supermodel and Cheat Engine. Some values represents the car speed in the game world, and other values represents the car speed to control the speedometer (like the address which contains '13'). Also, keep in mind that i press the brake pedal into the floor some values goes to 0 (the speedometer), but some values still shows some numbers because the car is still moving (the car movement in the game world).

What's next? With that memory addresses i need to find the pointers of the certain value because it changes when i reopen the emulator. Some of those values are just pointers from other values (but it still changes the i reopen supermodel) because on the demostration some addresses shows the values and other it shows '0'


The core Model 3 object is allocated dynamically.

Code: Select all
IEmulator *Model3 = new CModel3();


Then, another dynamic allocation for the actual RAM space is made by CModel3.

Code: Select all
  // Allocate all memory for ROMs and PPC RAM
  memoryPool = new(std::nothrow) UINT8[MEMORY_POOL_SIZE];
  if (NULL == memoryPool)
    return ErrorLog("Insufficient memory for Model 3 object (needs %1.1f MB).", memSizeMB);
   
  // Set up pointers
  ram = &memoryPool[OFFSET_RAM];
  crom = &memoryPool[OFFSET_CROM];
  vrom = &memoryPool[OFFSET_VROM];
  soundROM = &memoryPool[OFFSET_SOUNDROM];
  sampleROM = &memoryPool[OFFSET_SAMPLEROM];
  dsbROM = &memoryPool[OFFSET_DSBPROGROM];
  mpegROM = &memoryPool[OFFSET_DSBMPEGROM];
  backupRAM = &memoryPool[OFFSET_BACKUPRAM];
  securityRAM = &memoryPool[OFFSET_SECURITYRAM];
  driveROM = &memoryPool[OFFSET_DRIVEROM];
  SetCROMBank(0xFF);


Relying on memory addresses inside of a compiled program is flaky. Eventually, even if you get it right, something is bound to change in a future build that breaks your code.

However, for the time being, you might be able to identify the RAM address by its offset from the start of the memory pool. Supermodel allocates Model 3 memory in large, contiguous blocks (enough for all the different memory regions it needs to emulate). You can see this happening above. There is one allocation and then a bunch of pointers are set to different parts of this single, giant array.

For you, these lines are important to understand:

Code: Select all
  memoryPool = new(std::nothrow) UINT8[MEMORY_POOL_SIZE];
  ...
  ram = &memoryPool[OFFSET_RAM];


These pointers are stored in memory close to each other (in fact, right next to each other):

Code: Select all
  // Emulated core Model 3 memory regions
  UINT8   *memoryPool;  // single allocated region for all ROM and system RAM
  UINT8   *ram;         // 8 MB PowerPC RAM
  UINT8   *crom;        // 8+128 MB CROM (fixed CROM first, then 64MB of banked CROMs -- Daytona2 might need extra?)
  UINT8   *vrom;        // 64 MB VROM (video ROM, visible only to Real3D)
  UINT8   *soundROM;    // 512 KB sound ROM (68K program)
  UINT8   *sampleROM;   // 8 MB samples (68K)
  UINT8   *dsbROM;      // 128 KB DSB ROM (Z80 program)
  UINT8   *mpegROM;     // 8 MB DSB MPEG ROM
  UINT8   *backupRAM;   // 128 KB Backup RAM (battery backed)
  UINT8   *securityRAM; // 128 KB Security Board RAM
  UINT8   *driveROM;    // 32 KB drive board ROM (Z80 program) (optional)


I don't know if your cheat engine supports it but you can try the following search: find two 64-bit integers (the pointers) next to each other, where VALUE2 - VALUE1 = OFFSET_RAM.

Unfortunately, OFFSET_RAM is 0! But you could look for another region with a more distinctive offset. The offsets are defined in Model3.cpp:

Code: Select all
// Offsets of memory regions within Model 3's pool
#define OFFSET_RAM          0         // 8 MB
#define OFFSET_CROM         0x800000  // 8 MB (fixed CROM)
#define OFFSET_CROMxx       0x1000000 // 128 MB (banked CROM0-3 must follow fixed CROM)
#define OFFSET_VROM         0x9000000 // 64 MB
#define OFFSET_BACKUPRAM    0xD000000 // 128 KB
#define OFFSET_SECURITYRAM  0xD020000 // 128 KB
#define OFFSET_SOUNDROM     0xD040000 // 512 KB (68K sound board program)
#define OFFSET_SAMPLEROM    0xD0C0000 // 16 MB (sound board samples)
#define OFFSET_DSBPROGROM   0xE0C0000 // 128 KB (DSB program)
#define OFFSET_DSBMPEGROM   0xE0E0000 // 16 MB (DSB MPEG data -- Z80 version only uses 8MB)
#define OFFSET_DRIVEROM     0xF0E0000 // 64 KB


Let's say you pick sound ROM, which is at memoryPool+0xd020000. You would search for VALUE2-VALUE1 = 0xd020000, where VALUE2 is a value 4 qwords further in memory than VALUE1 (look at where the soundROM pointer is located relative to memoryPool).

Pretty cumbersome and not bullet proof. Maybe I should just print the pointer hex addresses to error.log each time?
User avatar
Bart
Site Admin
 
Posts: 1917
Joined: Thu Sep 01, 2011 2:13 pm
Location: New York City

Re: Getting pointers from M2Emulator

Postby Spindizzi » Mon Mar 06, 2017 7:28 am

Hello,
This last week end, I've made a little mod to supermodel project just for fun
I've connected directly an arduino to supermodel3 for printing speed value on racing game. Based on Pedro Pablo's idea but directly coded in supermodel so memory adresses never change
I only made for x86 machines because it needs other modifications in the code for linux/mac.

I use Boost library (http://www.boost.org/) to have access to serial port
but I don't know if this is permit by the supermodel project team to use this external free lib :?:

If it's okay I will publish code and how to do

++
Spindizzi
 
Posts: 53
Joined: Thu Nov 17, 2016 8:55 am
Location: France

Re: Getting pointers from M2Emulator

Postby Cel_da » Thu Mar 09, 2017 12:01 pm

With these tools is it possible to create some kind of mod to use the rev lights in G27 wheel and Supermodel games? It would be great!
Just an idea ;)
Thanks!
Cel_da
 
Posts: 42
Joined: Thu Apr 16, 2015 2:51 am
Location: Portugal

Re: Getting pointers from M2Emulator

Postby Bart » Thu Mar 09, 2017 12:31 pm

Spindizzi wrote:Hello,
This last week end, I've made a little mod to supermodel project just for fun
I've connected directly an arduino to supermodel3 for printing speed value on racing game. Based on Pedro Pablo's idea but directly coded in supermodel so memory adresses never change
I only made for x86 machines because it needs other modifications in the code for linux/mac.

I use Boost library (http://www.boost.org/) to have access to serial port
but I don't know if this is permit by the supermodel project team to use this external free lib :?:

If it's okay I will publish code and how to do

++


It's perfectly fine. Supermodel is GPL and you can do what you like with it provided you obey the conditions of that license.
User avatar
Bart
Site Admin
 
Posts: 1917
Joined: Thu Sep 01, 2011 2:13 pm
Location: New York City

Re: Getting pointers from M2Emulator

Postby Pedro Pablo » Thu Mar 09, 2017 7:26 pm

First, thanks Bart to give an answer to my question and also to give some documentation about i'm looking for. Sadly i coudn't undertstand what you wrote because i'm not very good in C++, and IDK nothing about memory allocation, pointers, even from source code, that i'ts too advanced for me. At least someone like Spindizzi understood what i said and i'm grateful that he made something that I couldn't make. I hope to see your source code and trying to understandwhat do you do

Cel_da wrote:With these tools is it possible to create some kind of mod to use the rev lights in G27 wheel and Supermodel games? It would be great!
Just an idea ;)
Thanks!


Is not very hard. With the RPM value you can make a script in your favourite language and then manipulate the leds
Last edited by Pedro Pablo on Fri Mar 10, 2017 9:07 am, edited 1 time in total.
User avatar
Pedro Pablo
 
Posts: 16
Joined: Tue Dec 27, 2016 4:17 pm

Re: Getting pointers from M2Emulator

Postby Spindizzi » Fri Mar 10, 2017 2:06 am

Hi,
Thanks Bart, for the clarification
I hope I won't break any rules including boost lib to your project

So the purpose of this little mod is to make output of datas from games (speed, leds, gear, rpm....) to process them visually with real leds, 7 segments leds, lcd, servo on arduino or other things like that
The most tricky part of this is to find offset in memory of Supermodel (I found some)
It's just a proof of concept and for the fun :)
In this exemple of code, I use Boost library (http://www.boost.org/) for opening a serial port (Com5/115200) <- can be changed in source code
Tested in windows only but I think it can be easily portable to Linux/mac because Boost lib is portable too

To use
Download boost lib already compiled (x32 and/or x64) and extract
https://sourceforge.net/projects/boost/files/boost-binaries/1.63.0/ (msvc14 version for VS2015)
patch-diff original supermodel code with the code I made (supermodel.h,model3.h,model3.cpp)
https://yadi.sk/d/kevRfWqp3FRhRa
Add boost include directory and boost lib directory to the supermodel project
Change Com port number and speed to your need (in the Init() function)
Programme a sketch for arduino to process data received on serial port
the trame is "=Gx=Vyyy=Rzzzz=Lw" with x=gear number(ascii), yyy=speed (3 ascii numbers), zzzz=rpm (4 ascii numbers), w=leds (ascii number)
see exemple for an 8digits 7segment leds
If no arduino, you can uncomment the printf in the function Output_datas() to see effects on the console

++
Spindizzi
 
Posts: 53
Joined: Thu Nov 17, 2016 8:55 am
Location: France

Next

Return to The Dark Room

Who is online

Users browsing this forum: No registered users and 1 guest