Finding and manipulating Pointer Tables

Malenko

Established Member
Last update for the guide was 09/29/2024

First off, MASSSSSSIVE thanks to @bbayles for holding my hand through this. This is basically his guide but written by me, showing you the steps I followed to get results.
Here is his Saturn Blog: Rings of Saturn | Bo | Substack

Prerequisites:
Basic computing skills
Understand hexadecimal
Knowing this isnt as hard as you think it is.
Lastly Mednafen Ghidra and JDK installed
A hex editor and byte_search

This tutorial will deal with the Japanese game “Gensou Suikoden” by Konami. It won't cover setting up or installing Mednafen, Mednaffe, or Ghidra. Honestly if getting those up is a struggle, the rest of this will likely be a bit much.

To follow this tutorial you must have *some* data to look for. Finding the data is not covered by this tutorial. I am just going to give a brief overview of what the data is, so the rest of this tutorial makes sense.

For this game I found Theo’s name. You can see his name in this screenshot.
AD_4nXeyswMEJLeUYHDGdXjgiG1ryp4zt-VBBIGyboNQkBwceZvtgJixmjCW2MQ7pezYKk8-f7DEsGelMA14g5OaZof06QvF-Ty7HFAsP7HZ6_pXRqSfhrA9mlrbT_G7UORI_23EkbQ6x23GE4q57NqmfTwF2V6M


テ オ in terms of the games data , this is A8 9A 0F ; I found the data (A8 9A) and the control for for end of read (0F) here, in the 0 file
AD_4nXdLr7q-dyfEHUMdLTK-3m-bWZUYKechsxgCaVGL6YVyfuh5UIppYlQpgSuHAffbA8R29x-_BsLEZaGo47C76W2vibXdNwapqnmM-IUA_0CjpGunzWjRwp7MHACKQKV7KJo12wZ2AbtZlJt36BKPkzhVAVw

0x05AFC4


With the prefix out of the way here's the tutorial!
Download and install Mednafen, Mednaffe, and Ghidra make sure you have a hex editor and byte_search as well (it just makes finding stuff go so much faster)

Mednaffe is kinda optional but convenient to not have to type commands or run bat files to use Mednafen.
AD_4nXe1DKiIoij5Kn7AaHHYGdnWC1alZ8nfTHdMePnZq6CWAjOSGeNLvfIa25nzl9laumq9N3De9s21RYmH8eY43I1Rgcr0VC7PV3td_ReB4ZycTfyKl0iXY-F8IboHrjOD4RdtvwVATgxE3Ac-8mSwZjPiguCF


once you have the game running, pause the emulation (Alt+P) and take a save state (F5)
AD_4nXdSl46-gTNqqdR2xdZOP1AlnVOHmnb2CId_yn8hTUK5wI8gxhuvaJCTY23iK5dbOXXZLob9Ah-YE0kL8k8caaRQ29ouiYwW7d7e-v8sBNzu2SFZT9IZYLcjQsQf0-ZRdm-3nyDtGdWnZ9S_tpHVzxIvsKTR



Open the debugger (Alt+D), change to RAM mode (Alt+3) and page over to High Work RAM (> key)
AD_4nXfPNegeOx-wGAur7lAuABKYx8pOGH9H6VfDbryZ8uiCOmUWlFHq4a2_3qBfqcfkqb-HVwRxe9mM_FLRtHXN8Uk-51XbRSg4bzWTzzwv8w4ACagJL10A6yPGxqkvoU3Bh-_M7U9NtfrK4Xfb4whBJqk4mCI

(Alt+D gets you this, the debugger)

on that screen hit Alt+3 to get to the memory screen:
AD_4nXdeFmqzkqOYe5-XeMyFKFbZ5LRK4aFn4bRgNOWT7kdKaFw0yhiOLpJo9wdO1X5cmIHgjujEJmXbGEWbjbuH3NJrRYshzH7OFElz-K5OTIpy23B4LYMIJTd_t07sGNAZXvz2fOM6r1PUA6_QND9Slw_JRWU


Then hit > until you are on high work RAM (other games may use Low Work RAM but for this game we use high)
AD_4nXfEESI9CrohmKpxDdJodiIOVqQFH3jCJfygwW98E17K1dcrNNvA2XSn5De20r0eXHcEdHZJIALCqhZPE_giQ28XlGqQCihRskHlgt-mRZ1AYoUnmai3pPxsijO7HQ73IxBGd8wzrLRqAAMYWe-qk5FxYw8-


Pressing D on this screen will prompt you to dump the memory, enter 0 fffff NameOfFile
AD_4nXexlY1pozNzu6Varl6HgXx7vDpZEzzgSEb5mNbO--JaKmzhbpRL1LGiebfnNLKuK-MjwTFeJYRq55HNZiCGkND-AdFdZ52ha7ma2VEgujT_Y-a7WOLOVGhtCa4i5cpRhnWkhLaTJPRWFbQif_2NKjdjJ7PX

I named it HiRAMDump.bin
Dumping from LowRAM is exactly the same but you do it from the LowRAM screen.

Open Ghidra and start a new project, it does not matter what you name it.
AD_4nXfaqmEJG82_0k7o-jT_3EVBM8JJOJRmqJCeKFhb0lQU7lhG7TuPIH72Y26uVzkb93Baj9oGnRXeioqsDhdRLmXmaAUdiD4-pjDT2xmcUUpdHTsmk-aBOkTqPl4NW6IB8r4_uBJH-IQtzcHau--iUzp2IEbX

Next, import the file through the file drop down menu, or hit I
AD_4nXdAnmsozKLdyzBHmLrnwKtZGTqDQvgCLBuw9cU-RGnhFJE7PfgBRMDBmUK1nfKyqA2TvsM6dOqCPXQy4R_AP5gGI1Ql-Tc8ErwtyU_QbQ3iRKMbJUX7dZMZTZH1m_EGn7gQNYv82wjjgTeB79yY3THJPQEG


The file you saved from RAM will be in the root of your Mednafen folder
AD_4nXfaIq0rXJ9UD0RyYKDcq9Qv0baj0TaZiU8C7mK28sRyku2d_u4Adm5ZgJESLzpsgdGKYQ0v3Ca4aCkx6rPCIlVZDq_IAaWTRlULgz8lJ1zBAoPlxkxpVAW3N5cYsEmdo8QuL5_k2XnFCnLY6fYWLMvboQNq


Import the file into Ghidra with language set to SH-2 and base address set to 06000000 (set the base address to 02000000 for LowRAM)

AD_4nXd4JE6AvsYvH64x1XGyPPERVFnktgLFmK4MVOfnbXXhByPj1jxQ8HMYccaG3yc930GwT7NZ4Z4p8aJDQOzUJCMWXk6t4xnLq2LSRPuznWd_YmZBsecloWF8gD0yfGsRbdP47xtblu3Oqcfr4W6SP6ubY-A

AD_4nXfK08iLx3DTjv3Uufns3tFxZfCU-SMz45cJCqqJV4D8SbG5giON-hAPxjgQrECX-G9juUPnm7g1E_LFQwL0lVcbdYERuy74_HhQfx09S1himAfdPWrBzhefiUKcSZejjr1_rpuR0nD1kVg1laQpU45v8u0

AD_4nXdl8BbQTLcF2_o1XNboSgJjhBPOpApYMKOfOiD2U94XQZDwxfnK6fE1aBvcjRNCKODdIEgR3LvEYlnRzYIFTUMAR2b14SY9k6HGTAgPoDSGo0nV9avsOHdS6vlp-yJRszm-3L6m4Ufo6Z1w8iaLPP0cTms4

AD_4nXdNMbVEfeUXu5PMrQZpShNBXgXnReUtPC2h-PyFjjKLTkMGW4poCY4m9JYyl8bQI59L3Quh7U6aNp2uu54SD7u-e44wLMDMfybMdgujtzBqLWaKVqWrqwp2nGJ1qGNRIGhzA5Tjeo0aC50Rf3XrQMONl61l


After you hit ok, a file import screen will come up that should look similar to this:
AD_4nXeD_jO9oOAWnXqoGLODj5YjsbnzM-rBIrmSSVMvQg8AAY6hNQL74suEiiQ69T_UbMrsGA9_AtEf7s1JSaCxYscQbtjpVod1yDDCzSNii3kiU62-4VNN7Re_O6_Cy70s_Nd5R6FzRbOxcJLCN-dALpX_j41u


Open the file in Ghidra by double clicking it (in Ghidra 11.2 a weird dragon animation plays)
AD_4nXdowSeWSfxLjL1z7G4oCB7cj4-3qXu2_6lYEPV79T5xAAx0OtTxPaM8MiWYDUgA_eYHvZ_qd8SJ_senKYLY7E8NR4QKhmOCbOgkBfp8eIdBfnGulfLZI8_DR1V8CkjeRDQHVU9vY8flJUlfFhFUJYx_rHO2


Select No to the analyze pop up:
AD_4nXc54GZR121xuAfVnW_q6vlZIXDrIisubTy6RLSBOsnfBfjsoUzC1KTjoaMa9TcTmUKmPM8dB4x9LvYXLL118mabsYhN1tunWrnasrb3HQ3qmgaEHv4k4ZCPgIWv-I7rZgNaILPjJYxoJ6kQwjQtsNKC2BQD


Open the Python/Jython console (Window > Python or Jython )
AD_4nXf2UNMnM7-6yTn8T_wtq0_2i9mwQZmMKhuPvmLAqU3EPysH6jrye22Ezgz6nQv2VdmyCoHNC4MOFyS3uPPQ90GAYswbWlvInskTjbSQCIUJwUiAfwp1_KnafSyPJkbp2RdA1A_NDNU3MyMRWUG1oxGnsx9-

11.1 calls it Python and it was changed to Jython in 11.2 but they are functionally the same AFAIK

Paste in BoBayles's script from here: https://gist.github.com/bbayles/c0b08d6843e64eeccdc5bbc31c641735

I hit enter twice then close Jython.
 
Last edited:
Next chose "Auto Analyze" from the Analyze drop down menu or hit A
AD_4nXc6wqima0xBTh_wDtEY8Nns9FcXJxCkAVewIyxwMVAKr2IykrneST9ZTdsmL7fVcNnEcl0h3ElJVy0NvIVPBMAdbPH4FVWLca95WHoinOYIzSkVPEmKkL36PIw49Qzu3k4i3_eOgRjU1SDIhTUmfq-bmb-O


Check the top box for aggressive Instruction Finder:
AD_4nXcP75qC-YfY5Ebf--7LE2lMUNIr2EGm3wILoZvjydqc-wM4MJWFmVWFkNrhrY_fpta3p3L7yjuMv0Ejh2e10m-iDoF_FN3yqXppYlCfzH-pPaQIwmTuQFhrXcNeA-3Y0cP9Ks_oMnzcytnrNjgXr8iXW9DC


When that has finished press S to search, and search for the values from 0 file that make up Theo's name (A8 9A 0F 00)
AD_4nXcV3HCF4w5-4HKVxoS_3ZWbPJhQmG8KNEqBdysccCs8s3vQumPb0MV3JyBYJkSqpEe9sUiS0dsohU3rirV6MFzB5eBjMQi5z_9V4CV6eyFep6sxMHLN9MpNX0tF0PN-L7UPVv3D2FfgYXB9kvhiOFu4oq6q


The location is 0x05EFC4 , which is 4000h more than the offset in the 0 file

If we search for 05EFC4 in all the files, we see it at 0x5B205 in the 0 file.
AD_4nXeXUtHGxQ7No-BhjuQThZtLQrYJ9g7pdQOMckp4dxj0YOliq9pQypOZBYJse-Da_BNEzrjpxYsjBNRWDFl0XNQOIafyPlL_B7GE-RsyLlUqlRxqmQiOZwMFGprhdO8Sb_l8QaoQCIdCRNpevUFAUg4LdnQ


I’ve highlighted here, but when you see data that looks like this, it's a pretty good indicator that it is a pointer table.
AD_4nXfqOJcKqCAllty3rdwhmeEyNJcjufIzD9Z3aNFV95t1eCcz9cGpg-QHufneuGaiZ0LzVGUqEV0TlNIdFXpppT9GQPdDldkGyalAgWIl-YJ7YCfHiO3oK8gI3DqcBaT2K0p3csbE9pU_uXrcB17cUagUDQ0


"pretty good indicator" isnt good enough, we need to test by altering some data.
Once again, here is Theo's name
AD_4nXeU3A1M63Rdy08jYJAHosW3hhHxiSKDp2XuWrCyVdOjYNwDfWk0ard2Q8-0HZN3m0eutifCOukWd9_TSFRZsbxJOjhaTyVuA9NW8R8x_NEyDoKqGifIR7noZ-FYuVBZ5HCWxdpA3tkn2AV2zvtMv-z4Ds0


We need 4 bytes for THEO in English, and we totally lucked out there there are 2 extra bytes to the left. Let’s take them.
AD_4nXdastTHA3sIUj4rVQiGHV585qGBEuNk6-tFUfUNxIf7x-pOlrgslsTN3ISQXQTsGywcnJrRylv-5l60M9VuvQM_zjDA-BHs-flaFUz998PxMZIaOHdKa9syG4GyLqS3OQmvD209e8QgIiyruFdVk4kl8j7u

The values for the English letters were discovered via brute force and are posted in this thread: Genso Suikoden Translation help?

Since we took 2 more byte than before, we need to change the offset of the pointer table to be 2 lower than before, this is the before:
AD_4nXfS-piRSUT8zfJrcIe2gNp1P9t0h5lOOXpYPS1YiPG1xkvD-gnDkDVbXX9ZhrCRgifYaRXY1QQNAJjWKacoRIEmfXIkdVkOGKE6PbaKQLlKecyLPHJB0x21lHQqW5Ge4MM31b44OLOZosbhQXJfOTsAw2g


And this is the after:
AD_4nXe9MwLLl84SBoUxBp7VKDzxzVH-DIgCQXDuYPe76CK0DKHLKSv0Suvr51QIkl4yh0PV9vdwgGBoVJx6ichCtrfXMepmC7QuFAS-vKHIzmmVThSC0ykxdFbG5B_dx-b8zsyLbWimqqxPi1UGq-VqztTSOWGJ


This effectively uses up 2 unused bytes and gives up 4 letters for Theo instead of two. Now we need to test this in game. Inject the changed 0 bin file through whatever method is best for you and you should get a result like below:
AD_4nXepZpgpsGdHng7B7uwXYWNSO14Ev1bjuIZX3MNdZz4P2_IU9hHeOvPYvtgXhrkvZ0vo6fhnYC8p7D-AqSR3Aa6xg4aHKkuqx5MWKOQmUV74Ff7Ey99qeny-eFlTlwPV8A3qSXsFpenAPPsOTgd7DCR0dOro


Please post any questions, the hope is to flesh this out to be a good starting point for finding and manipulating pointer tables
 
Last edited:
Back
Top