-
Notifications
You must be signed in to change notification settings - Fork 7
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Speech MORT format codec parsing/decoding #13
Comments
By adapting some of the @SubDrag code to make it a standalone testing tool, I was able to convert the MORT subfile into an "horrible" sound... However, the general appearance of the audio signal seems to me not to be noise (not "random" enough). By stretching the sound as it went along, it was not too difficult to recognize a recognizable cry. I'm looking for adjustement in wav generation and looking further in C-asm code to better understand MORT compression protocol.
|
I don't have much notes on the speech compression. It was part of the Musyx package and iirc there was a special microcode by F5 for N64's audio chip that handled sound and maybe MORT decoding as well? |
Indeed, on the N64 version I could read that there was a microcode injected by the game cartridge. From what I could see and hear about the Factor5's ways, I would be inclined to think that it is the multi-channel support of the MusyX engine, allowing the superposition of SFX, soundtracks and voices of the game with a lower memory/computing power. Happy to share! I'm not a good Pascal programmer :P |
Little update: The "bit flag" in header correspond to samplerate (0=>8000 Hz and 1=>16000 Hz). I didn't tried to test it on linux system but I think it can work well... |
Thanks for the code. I might give it a try and clean it up somewhat and put it in repo afterwards. |
I've just added main part to handle input and to drive the "big" MORT decoder. The bulk of the clean up should be here. |
So the N64 Sound Tool can rip audio and speech from all MORT games. Rip is a strong word, it's kind of running through disassembled (at low level) code translated to C++ almost directly to spit out the output. It would be nice if someone cleaned this all up and made an encoder though, instead of the sort of hacky way it's done. Now anyways, what progress have you made here, or what are you trying to accomplish that's different? Other than a couple imperfect sounds here and there, and sampling rate being off due to games all having their own unique methods, 100% of N64 Sound can be ripped; I have no known misses. |
We are trying to reverse RS datas format on the PC version (even if N64 and PC code are similar: some of N64 functions/elements are present on PC). As you said, the parser act like a "blackbox" with datas in input and retrieve stream from output. I wished to be able to clean it up to get a more human readable code and writting a note on the MORT codec algorithm. Perhaps, we can make a MORT encoder after that... For now, I can extract all the quotes/speechs from PC datas with "speech" file in input. I've continued to search for MORT parser in PC code but no result. Maybe I should try with signature-sniffer approach... |
Sounds good, good luck. I did this before Ghidra - using Ghidra might not be a bad idea for it to make the code a little cleaner, once you find it on PC - looks like Ghidra doesn't map that well to the pure ASM rip here. It's a complex algorithm, with multiple stages, and something that happened long ago can impact something much later, and it's streaming. It also seems to grab different chunks/amounts of sound per framerate. It sure would be interesting to see this thing decoded for real and how it works. If you're parsing this on PC version, MORT decoder must exist... Maybe try and find these tables: Also are constants in Function80048B3C: |
See this commit to fix the starting too early sound issue: jombo23/N64-Tools@4fe1073 If you can make appropriate adjustments to fix issue. I see both sounds exactly matching in N64 that you posted above for MORT, and they are shown as 8000/16000 properly in N64 Sound Tool. They are at MORT header +0x6. So for example: So are you ripping it properly now, or it's just remotely garbage but sounds like a real sound? The MORT samples you posted above match exactly to N64, so should you should be able to rip these perfectly. MORT is fully software decoding btw - not using microcode on N64. And FYI the ASM rip is from Pokemon Stadium US 1.0 on N64 (addresses match that). I assume you are trying to find the algorithm on PC to use ghidra/decompile though. |
It's already a great work, knowing that it is the only usable code for the MORT codec that I could find until now! That's the point! As I know Factor5's methods, it's largely optimization oriented, I'll not be surprised to found some "tricks" with datas like "pattern reuse" or other such things. Yes I've got a clean sound after setting samplerate to 8000 or 16000 in function of specific header in PC version. I was wondering on N64, it would have been possible/useful but yes on PC, the decoder is necessarily present if there are MORT files in the game data. I hope I can find it soon to get a base of comparison with N64 asm extracted instructions. EDIT: I've located the 0x2B33, 0x4E66, 0x6600 parameters with Ghidra at function offset 0x5bce13. I see similarities in the structure of the function calls with the ripped N64 version. |
So the actual N64 game outputs raw 16-bit sound data. My toolchain spits out wav files, so that's a wav chunk. smpl is used for loops. Though this game doesn't have loops in there as far as I know, so it's all nulls, and not useful. OK good luck! Note that Ghidra kind of...lumps functions together, so it's not a trivial 1:1 mapping. Especially if you're comparing x86_64, but anyways, you have reference output, which should help hopefully. Good luck! I really would love to understand the algorithm, and have an encoder, but no small feat. |
Loop instruction? Interesting... |
I've finished my first pass on the main class. Removed a lot of redondant variables and added loop when necessary. It can always process rogue data correctly, I don't know if it's can always work with other N64 games @SubDrag. Some parts always seems unclear... Perhaps I should try to clean it up more once again. |
Yeah it works on all MORT games on N64. If you get something pretty high level would be interesting to see, but it's definitely a long shot to support an encoder, but maybe possible if you spend enough effort! |
Ah? Did you try with the new "middle-level" sources I've posted with my answer? |
I didn't try it, but presumably you tested if it matches the output; if so it's a valid update. |
There's a very poor importer now too. The algorithm is unknown, so brute-forcing is the best bet right now. The full brute force computers are not fast enough sadly. A partial brute-force gets iffy results, but at least, it's something that can import sound of some fashion. |
@SubDrag Are you talking about an importer/decoder other than the one you decompiled from the N64 version? |
There was no importer before - I just recently added a brute forced version in an attempt to get something importing. I never made any progress either in understanding their advanced algorithm, so this was best could do. |
Ah yes, I remember now how I've used it 2 years ago! You've done a good job of rewriting much of the pseudo assembler code too! Yeah the "bitstream" part of the decoder is a big mess, probably Huffman-style compression. That's a lot of speculation from the code and what I know of signal processing. It's only a matter of time before figuring out! |
Hi,
Okay everybody, it's a big one!
Speech in RS are recorded in propritary codec bearing the name of "MORT", MORT can be found in header of files inside "speech" file inside data.dat. Used in a lot of Factor5's games, MORT audio codec does not seem to be fully decoded for now...
I haven't found anything more accomplished than a reversed toolset of N64 version (https://github.com/jombo23/N64-Tools).
Despite efforts to recompile myself the tool, wav output seem broken...
IDA/Ghidra doesn't help me further than speech file RAM allocation and some pointer/config datas. I don't think the datas are "complex" to decode, but the decoder functions seem fragmented in the main program... Pretty hard to extract.
I'll keep trace of my "quest" in this issue, reverse engineering of RS doesn't have a lot of topic in the www universe x)
The text was updated successfully, but these errors were encountered: