Super Metroid for PS Vita
The TL:DR version is: here you can download the installation package for your PS Vita. You will need the rom for the assets, in the README you can find all the information on how to install and use this porting. It’s a first version and it has some bugs, but I was able to play a good chunk of the game for the moment. Enjoy!
Porting Super Metroid to PS Vita
I finally had some vacations, so I wanted to play Super Metroid (because why not? It’s the best game ever made) but I wanted to play it portable and with a good screen. This exclude the Switch (I have a launch model) or emulated on the deck (I have the LCD one). But luckily I have a PS Vita and it’s gorgeous OLED screen! I could have emulated it but then I remembered that a reverse-engineered PC porting exists! Then why not trying to bring it to Vita?
Ok, first things first: luckily the porting supports SDL for input and rendering, so it could be reused almost as-is, however it was extremely slow and I could get around 45/50 FPSs. Ok, Vita is not the most recent hardware, but I would expect it has enough CPU power for the game.
Checking the code, I’ve noticed that by default it executes the game in both “native” mode and an emulated one to confront the results and identify if and when the native version doesn’t work as expected. In my case I don’t care about this, so I’ve disabled the emulated version for this porting.
Except for that, the other fixes in my patch are pretty simple: I’ve created a new rendering path dedicated to Vita (for accounting the fixed-size screen and resolution) and some checks to avoid useless rendering calls. The most interesting part I think it’s this:
static inline void ClearBackdrop(PpuPixelPrioBufs *buf) {
- for (size_t i = 0; i != arraysize(buf->data); i += 4)
- *(uint64*)&buf->data[i] = 0x0500050005000500;
+ for (size_t i = 0; i != arraysize(buf->data); i += 1)
+ buf->data[i] = 0x0000;
}
In this function it’s trying to clean an array using a for cycle. And for reducing the number of iterations it’s using the pointer arithmetics to clear 8 bytes at the same time. However on Vita this causes a crash immediately!
add.w r3,r10,#0x10a00
...
adds r3,#0xf6
...
strd r4,r5,[r3,#0x8]!
cmp r2,r3
Checking the decompiled version, the issue seems to be a memory alignment. Checking on internet I’ve noticed that some old GCC versions has this issue, and since VitaSDK seems to use a version from that period (10.3). Changing it to use a simple loop it works without issues. If someone has more details, or if I’m being wrong, please let me know!
Also, interestingly (but it needs some more study) is that if I try to replace this call with a memset I have a 20 FPS performance hit! I’m really interested in why it happens, so I will need to investigate it a little in the future!
All in all, it was nice to work on this, since I’ve never tried to compile something for Vita, and I’ve found a couple of interesting points to explore in the future.