Making MGS1 PSFs playable in HE?! by Nisto at 3:31 PM EDT on August 6, 2018
So I've been battling this for about an entire week now, and I'm out of ideas. I'm trying to make the PSF set of MGS1 playable in Highly Experimental by replacing SPU IRQ related code, since it isn't well supported in HE and most other PSF engines. I have learned much more about the game code since the initial rip I made last year, but I still can't figure out a way to make the PSFs compatible with Highly Experimental. I have now managed to hack out all the multi-threading related calls (the Multi Task Scheduler) and also the SPU IRQ related code, so the code is actually pretty straight-forward now. However, without SPU IRQs, I have not been able to replicate correct timing. It either plays too fast or too slow, depending on various approaches and parameters.
SPU IRQs in MGS1 are triggered from a single one-time call to SpuSetKey. The magic of it is that the ADPCM address specified in the SpuVoiceAttr struct to SpuSetVoiceAttr is the same address defined to trigger an interrupt when the data there is read (and I must assume the data read operation happens through SpuSetKey, because if I remove the call, no interrupts occur). Furthermore, the data at the IRQ address contains a silent, looped ADPCM stream, so interrupts are triggered automatically and continuously. The most important piece of information here though, is that they set the pitch value in the SpuVoiceAttr struct to 4096 ("pt" units), which represents 44100 Hz according to the SDK docs. From what I can tell, at this rate (pitch), 256 bytes (448 samples) are read between each interrupt, which is half of the stream's size (512 bytes).
So now, the question is, how could I replicate this timing in a simple loop without the use of SPU IRQs? Any ideas? I'm simply calling the sequencer function (similar to calling SsSeqCalledTbyT in a loop), which is essentially the same that happens with SPU IRQs. Here's what I've tried so far:
* Calling SpuSetKey to trigger a non-looped silent ADPCM stream followed by polling SpuGetKeyStatus to check that it finished playing (SPU_ON_ENV_OFF) - this actually works decently, but it's just a little too slow in PSFLab/foo_psf - no good in viopsf (w/ spumednafen.dll), skips a lot - Mednafen itself does play it without a hitch
* Polling root counters 0, 1 and 2 - I used SetRCnt followed by GetRCnt in RCntMdNOINTR mode, but the results seem totally random?
* VSync(-1), VSync(0), VSync... - Obviously not enough precision with this, but I tried it...
I had no idea about this! Sadly I can't help you though, but I'll keep an eye on this.
I just checked the preliminary set and I have to ask, once you figure it out, can you do the same for the Integral/VR Mission exclusive tracks? I ripped the hidden tracks in Integral from an emulator's SPU plugin years ago, and I was able to eliminate the codec noise at the beginning but the game plays the songs with a little fade-in, and I assume the tracks are not stored that way.
Here are the songs in question for anyone interested (there are more in the VR Missions disc, but those were already ripped by someone else) https://mediafire.com/file/x6ibr4fazg6bbnx/ https://mediafire.com/file/zd29hczn4xhlsoc/
I thought the Integral/VR Mission tracks were already ripped by nisto in the general xsf thread. That was sometime after the initial release of the MGS psfs.
EDIT: The tracks in question were indeed already ripped, codec noise is not there however the fade-in effect is.
Also to add to the list of players that can play MGS's psf's, I think purei's source was updated to support them. But that's just the source, I'm not aware of any exe floating around anywhere.
While i can't help you with technical stuff, i'll just let you know that your current rip will play fine on the real hardware.
I converted your *.psf to .exe using psf2exe. And then used no$psx "Utility > Upload to PSX" to send on a scph-7502 via Xplorer cartridge flashed with "NO$CASH Kernel Clone - New Expansion ROM Version" http://www.psxdev.net/forum/viewtopic.php?f=76&t=1319
I also tried the same using original Xplorer roms but for some reason it will play way too fast regardless if video mode is set to PAL or NTSC.
Since the set is not in miniPSF format, it gets pretty big, so I'd advice you to rip it yourself instead with the Python script/kit I uploaded if you want everything. It's not that difficult to use, really.
Lastly, I'd recommend playing these PSFs with viopsf with the Mednafen SPU plugin.
Any real benefit to using the mednafen spu plugin over the updated peop's? I suppose it's more accurate, but it just doesn't sound it, plus the viopsf author updated the peops plugin, so whatever issues it had before that I noticed are gone... plus sinc interpolation.
I honestly wouldn't know which one is supposed to be more accurate. I haven't tried Pete's plugin much.
Is the source/dll provided in the viopsf archive being updated by the viopsf developer, or can it be downloaded separately somewhere? I looked on Pete's site (pbernert.com) and the latest release I see is from 2004.
The plugin is different from the one in Pete's site, but I'm not sure if it's the viopsf author updating it or someone else. Before the July 22 update, I would've had a hard time recommending it do to some issues here and there, but they appear to be gone now.
If you do end up trying pete's plugin, use "PSX Reverb 2". The default reverb will ends up sounding the same as all the other ones.
Isn't the reverb modeled after the actual hardware and down to which coefficients the software actually uses? It's also running at half the sample rate of the hardware, so it downsamples on input, and upsamples on output.