10/11/16

SNES Station PS2 Updated (0.2.5 Mod - 0.2.6 Mod)

In these days I've been working on a mod for SNES Station and I came up with two versions of it.
These mods are based on Megaman SNES Station extension, since the source code of SNES Station, as far as I know, has never been released.

Many thanks go to:
  • Hiryu, he originally wrote the SNES Station PS2 emulator, and everyone behind it.
  • Megaman, for the SNES Station extension (which these mods are based on).
  • The PCSX2 guys for making a great work with the PCSX2 Debugger in the latest dev versions (I simply love it)!

So, here I go with simple release notes (below there will be technical details):

SNES Station 0.2.5 Mod
+ Now it works without needing a CD/DVD in the disc tray.
+ Fixed a bug in the USB rom selection where there was an extra empty space that could hang/crash the emulator if selected.
+ MC1 now is working in ROM selection menu.
+ Improved Save States stability.

SNES Station 0.2.6 Mod
+ Rewritten ROM selection interface, now it looks similar to the one in uLaunchELF.
+ IRX modules are loaded only when needed and some of them are updated.
+ Added support to Cheats (please follow this link to know how to apply them).
+ Save States and SRAM Saves now will be written and loaded in the same directory where the ROM starts (except if ROMs are loaded from CD/DVD). So now, for better readibility, save files are filtered out in the ROM selection menu.

Plus, SNES Station has always had the support for IPS patches, but I don't really know if it was ever mentioned anywhere (I discovered it by debugging it).
To make them work they need to be copied in the same directory as the ROMs and they must be named with the same name.
e.g.: if the game name is "SimCity 2000.smc", the IPS patch must be named "SimCity 2000.ips" and it must be copied in the same place as the game.

I couldn't test the HDD support, because I don't have one. I could only test partitions enumeration and display thanks to a PCSX2 plugin.
However, if HDD support worked with the previous versions it will surely work even now.

One last thing: since the 0.2.6 Mod will write save files in the same place where the ROM starts, it means they can be written even on USB or HDD.
I personally tested them on an USB pendrive and it works perfectly! But I won't assume any responsability for any damage on those devices!


Now the technical details:

To make SNES Station work without CD/DVD it sufficed to find where the CD/DVD IRX module was loaded and to fill it with zeroes, in MIPS asm it's the equivalent of nops. At first I didn't get it perfectly right, because I didn't know that MIPS processors have a thing called delay slot.
Then, since all the CD/DVD functions are protected from initialization lack (all the functions check if the module was inited before proceding) I decided to remain them intact as they were.
The next step was to find the address where the CD/DVD IRX module was loaded and manually loading it only when the CDROM folder was accessed.

About the USB "hidden" entry, I only had to change the place where the entry counter was being incremented.

Making the second slot of Memory Card work in the ROM selection menu was a bit difficult, at the end I came up with an idea that seems to work properly: placing a call to mcGetInfo() with the related mcSync() just before the Memory Card directory was being read.

To make Save States more stable I had to proceed in two ways:
1) I wrote a supplement function binded to fioClose() that automatically closes all the opened files whenever a file is closed. This was needed because in the emulator code while saving or loading a save state (I forgot which of the two) the file is never closed and so it becomes locked. This means that the subsequent calls to fileXioOpen() will never work.
2) I fixed some jump branches in asm thanks to the help of the PCSX2 Debugger. Pratically the calls to fioOpen() and fileXioOpen() when they succeed will always return a number bigger or equal to zero (bgez). In some cases the branches tested only if it wasn't equal to zero (bnez), thus making it work unreliably. I think that those calls in the original code were assumed to be like a fopen() call, which behaves precisely like that.

About cheats it was really funny to understand how to make them work!
The functions needed to make it work were bundled in the emulator, but never called.
To find them I had in front of me the source code of Snes9x on GitHub.
For first I decided to put a breakpoint on the fioOpen() calls and when as an argument it figured out the string name of a cheat file, I traced back the caller thanks to the MIPS ra register and found the place where cheats were being loaded.
In the Snes9x source code, just above the function that loads the cheat files there's another function to apply them. So by scrolling a bit of asm lines what I found? The same even there!
At the end the only thing left to do was to find a place where to call it, because it wasn't called anywhere. And fortunately I found a place where I could call it that is executed every frame (or at least it seems so). If it was called on every CPU opcode there was going to be a lot of unnecessary overhead.
Plus I decided to patch that address dynamically only if a cheat file is found.
Then I only had to make a little fix to make it use the correct values from the cheat file.

To make Save States and SRAM Saves being written wherever the ROM was opened, it was pretty much simple! I had to track if opened files belonged to the mc0:SNES_EMU/ directory and then I had to redirect them to the ROM directory (obviously only if the game was loaded and only if it didn't start from CD/DVD). The only difficult thing was to find the variable that enabled/disabled the save menu entries. In fact when the emulator was loaded without a Memory Card those entries were completely disabled even if a Memory Card was inserted after. So after finding that variable I could enable/disable them when needed.
I even had to patch dynamically some branches that checked Memory Card free space to make saves work even without Memory Card.

Last thing I did was to restore the internal printing function of the emulator, it became broken when all the fio calls were exchanged with the fileXio ones. And for the 0.2.6 Mod I decided even to remove all the printing functions used inside the extension because the strings occupied space and the printf found by Megaman was unstable, few times it damaged stack and/or registers. Maybe it was the compiler fault, I don't really know.

That's all!
Please let me know if there are any issues!

No comments:

Post a Comment