Since 2013, I'm participating in the global game jam at a local site close to where I live. I do it mostly for fun and to socialize, rather than making a "cool" game. For this reason since two years I go home and sleep during the jam nights and come back in the morning. Better to take it easy, eh?
One of the diversifiers for this year was the following:
NES: Make the game playable on an old school console, either directly or through an emulator.
Remembering that I recently bought a PS One with 5 original games and two controllers(which was by the way a nice deal of 15 Euros), I decided to go with this diversifier to make a game for the PSX platform.
After a small search on the internet I've found two suitable SDK's for this:
The first one is the Psy-Q SDK, which was the official SDK for the PS1. Today it has bunch of documentation on the internet, however it was not updated since ages. Furthermore, it only runs on 32-bit Windows systems and due to it's closed nature it's not easy to use it on a GNU/Linux system.
The second one was the PSXSDK, which is actually a set of free and open source tools and the necessary toolchain for building programs compatible with the PSX hardware. Unfortunately for now it only supports 2D games, but I don't have enough hairs on my chest to code a 3D game for the PSX anyway.
Getting the PSXSDK
The SDK can be downloaded from here. There is a precompiled toolchain available. It worked fine for me on Debian 7, just had to create some symbolic links to some libraries for the older version numbers. The SDK basically contains a GCC compiler configured for the MIPS architecture, and some programs for converting files.
Process of building a PSX game with PSXSDK
Here are the summery of the process for building a game:
- Convert the assets using the tools provided. For example you can convert WAV files to VAG, and BMP images to TIM. There is a very uncomfortable thing with creating TIM files, which I will explain later.
- Then you build the code and obtain an ELF binary.
- Using the elf2exe converter, create an EXE file from the ELF binary.
- Using the systemcnf tool, create a system.cnf file from the EXE.
At this point you actually have the necessary files, and in theory you can run the EXE file using an emulator. However this was not working for me with the PCSX emulator. I could only run the BIN/CUE image on the emulator. The rest of the steps to do this are as follows:
- Create an ISO image of the root folder of your game where the necessary files are. I was using genisoimage to do this.
- Using the mkpsxiso tool provided, convert the ISO to a PSX compatible BIN and provide a license file. I'll write about this license file later.
So you are actually done, you can either run this BIN image using an emulator or burn it to a disc.
Copy protection in the PSX
Detailed info about the security system in the PS1 can be found here. After reading the article it is possible to say that there is no importance of the license file that we put in our BIN image. As long as you are burning your disc with a conventional CD driver, you would either need a modded PSX or to do the swap-trick in order to run your game. Unfortunately my PS One was not modded so I had to do the swap-trick every time I tried to test the game on the device.
Video RAM of the PSX
As explained here, the VRAM of the PSX has a drawing and a display area, together with an area for loading the textures. Basically when you load an image file(TIM), you load it to the area on the right(see the image in the above link).
When using the bmp2tim tool of the PSXSDK, you have to specify the origins for loading the image in the framebuffer. Yes, while converting the BMP image. This can easily turn to be very complicated. In fact, it made me question myself why I didn't just use Unity3d to make a game.
For example in our game we were using 320x240 resolution for the PSX. This means there were two rectangles of size 320x240 with the top-left origins of (0,0) and (0,240). These two areas were used as display buffers, While the area after 320 pixels horizontally was left for loading the textures. Having a background image of size 320x240 for each background, I tried to set their origins to (320,0). For some reason, the right part of the background images were not rendered. After some while I found out that the textures couldn't be bigger than 256 pixels in each dimension, so I divided the background images to two separate images of size 160x240, loading them to framebuffer origins (320,0) and (480,0).
One has to be careful about the origins in the framebuffer, if you place the textures in overlapping places in the VRAM, and later load the overlapping images in your code, the image which you load previously would be overwritten by the overlapping image.
Anyway, this was just a jam game so I'm sure there are bunch of interesting stuff about PSXSDK which I'm not aware of. To sum up, it was a nice experience to work on a 20 year old platform! kthxbye!