Author |
Posted on 2016/02/17
#1446
|
CuriousTommy |
I wasn't sure if putting this in the Mario Kart 7 help forum was appropriate considering that this would technically apply to any game that uses .sarc files. A quick back story: So I have been looking into how .sarc files and I was confused about how EveryFileExplorer was able to read 'unsafe' .sarc files since these files don't contain any filename strings until I found out that Gericom uses a premade .saht file. On to the question: Is the .saht a Nintendo file format, or something that Gericom just made up? Also, where did Gericom get the real string names? I actually have a working python code that analyses the file Just be sure to have the file be called HashTable.saht and put it in same directory as from struct import * FileIn = "HashTable.saht" SAHTFile = open(FileIn, mode = 'br', buffering = 0) SAHTHeader = unpack('<4s', SAHTFile.read(4)) SAHTFileSize = unpack(' SAHTDataOffset = unpack(' SAHTNrEntries = unpack(' print("The Header file is {0}.".format(SAHTHeader)) print("The File Size is {0}.".format(SAHTFileSize)) print("The Data Offset is {0}".format(SAHTDataOffset)) if SAHTNrEntries is 1: print("The Number Entry is {0}.".format(SAHTNrEntries)) else: print("The Number Entries are {0}".format(SAHTNrEntries)) print("") print("") for i in range(0,SAHTNrEntries): StartingPoint = SAHTFile.tell() SAHTHash = hex(unpack(' print("The Hash is {0}.".format(SAHTHash)) Buffer = unpack('<1s', SAHTFile.read(1)) SAHTString = b'' SAHTString += Buffer while Buffer != b'\\x00': # My idea behind this code is to keep unpacking the # Buffer until the Buffer hit a Null (or None in python) # value. Then the program would stop doing this. But, becuase # of how the code works, it also factors in a Null, however the if # statement catches this. Just keep this in mind when using .tell() Buffer = unpack('<1s', SAHTFile.read(1)) if Buffer != b'\\x00' and Buffer != b'/': SAHTString += Buffer elif Buffer == b'/': print("The fake 'directory' is {0}.".format(SAHTString)) Buffer = unpack('<1s', SAHTFile.read(1)) SAHTString = b'' if Buffer != b'\\x00': SAHTString += Buffer else: pass else: pass print("The file name is {0}.".format(SAHTString)) HitNullPoint = SAHTFile.tell() print("The actual range of data value is from {0} (Start at Hash Value) " "to {1} (First null value after string).".format(StartingPoint, HitNullPoint)) print("Actual relative cursor location {0}.".format(HitNullPoint - StartingPoint)) if (HitNullPoint - StartingPoint) % SAHTDataOffset == 0: pass else: NextHashPoint = SAHTDataOffset - ((HitNullPoint - StartingPoint) % SAHTDataOffset) print("The distance of bytes to the next hash is {0}.".format(NextHashPoint)) SAHTFile.seek(HitNullPoint + NextHashPoint) print("") |
Author |
Posted on 2016/02/17
#1447
|
CuriousTommy |
I realised that the code doesn't show... Click me instead! |
Author |
Posted on 2016/02/18
#1448
|
MKGirlism |
SARC is a File Format made by Nintendo, I'm not sure about SAHT. And the real string names can be found by Hex Editing. |
Author |
Posted on 2016/02/18
#1449
|
CuriousTommy |
SARC is a File Format made by Nintendo, I'm not sure about SAHT. Yeah, I am going to ask Gericom about that. And the real string names can be found by Hex Editing. Do you know what particular file I should look at? I know for a fact that it isn't in the .sarc course files. Looking that the documentation on 3dbrew, the real strings should be after the SFAT Header, but I don't see it in any of the .sarc courses files... |
Author |
Posted on 2016/02/18
#1453
|
Gericom |
@CuriousTommy The made the SAHT format myself. Inside the SARC files are name hashes that are used by the game to still be able to use a path. Reversing is not possible, but I could guess a lot of names (based on a list of object names in mk7 and the course names), and put the hash-name pairs in a table. If you want, you can calculate the hash from a path here: http://www.florian.nouwt.com/SarcHash/ Also, if you want to edit the hashtable, you can simply open it with EFE. |
Author |
Posted on 2016/02/18
#1454
|
CuriousTommy |
@CuriousTommy Okay, thanks so much! I will also be sure to credit you. |