Page 1 of 1

psyq2elf - Convert Psy-Q SDK libraries

Posted: March 21st, 2020, 10:59 am
by jype
After using Psy-Q SDK for a while I got fed up with using the > 20 year old development environment through DOSBox. I liked having a complete SDK, but wished it could be used with modern tools.

Inspired by spirit_t0aster's work, I started looking into reverse engineering the remaining bits of the Psy-Q library format. At some point I realized that the format is similar enough to ELF, and could in fact be converted with minimal workarounds.

The Psy-Q library format supports arbitrary length expressions for relocations, which would be horrible to hack around with the ELF format. Luckily only a handful of the expression types are actually used in the library object files, and they can be expressed with ELF symbol offsets and relocations.

So I created a set of tools called psyq2elf that can convert Psy-Q libraries to ELF libraries. The converted libraries can be used to build PSX executables with modern GCC. So far, all Psy-Q SDK examples and test projects that I've tried have worked.

As has been said before, the Psy-Q SDK is copyrighted, and of poor quality. It would be better to focus on using and developing open source PSX SDKs.

But anyway, I hope the tools can be useful to someone, for PSX development or maybe even reverse engineering purposes.

psyq2elf source code and examples:
https://gitlab.com/jype/psyq2elf

Image

The example project also shows how to build PSX executables with only a linker script and objcopy (without elf2exe).

Projects that the work is based on:
spirit t0aster's worklog
armips
REDasm
PSn00bSDK (toolchain guide, EXE header)

Re: psyq2elf - Convert Psy-Q SDK libraries

Posted: March 21st, 2020, 1:58 pm
by Shadow
That's really nice work! Would be very interesting to see a modern GCC compilers binary output and compare the assembly with the CCPSX compiler to see if it optimises better.

Re: psyq2elf - Convert Psy-Q SDK libraries

Posted: April 13th, 2020, 11:39 am
by SamuelHusky
It's really nice to see something like this being worked on.

Your code built fine on Ubuntu with GCC 7.5.0 and converted the libraries as expected.

Toolchain is Binutils 2.34 and GCC 9.3.0 (mipsel-unknown) and the cube example compiles ok. However I seem to not be able to get it to run. (Have tried GCC 8.2.0 as well)

No$PSX seems to break at 1FC08E90 with a jrel instruction that comes up as Undef Opcode.

Any idea? Let me know if you need more info.

Re: psyq2elf - Convert Psy-Q SDK libraries

Posted: April 14th, 2020, 1:32 am
by jype
Thanks for trying it out, I did find a bug in the executable header - most emulators don't care about some of the values so it worked anyway. This is now fixed in the repository.

I tested the cube example with epsxe, no$psx, mednafen, pcsxr and on hardware.
Did you run "cube.exe" (not "cube" ELF file) with no$psx? Can you try pulling the fix from the repository and recompiling the example, and maybe also with another emulator?

If it still doesn't work you can upload "cube" ELF and I can try to debug it :)

Re: psyq2elf - Convert Psy-Q SDK libraries

Posted: April 14th, 2020, 8:24 am
by SamuelHusky
Dude, you are magic! Your change has fixed the issue I was having compiling the cube example.

As a side note I did try ePSXe originally, but just had black screen.

Image

Re: psyq2elf - Convert Psy-Q SDK libraries

Posted: March 7th, 2021, 7:26 am
by Elvarg
I'm having issues building the example cube program. When I run the make command it complains about not finding entry symbol __SN_ENTRY_POINT; though it's included in the source file and it also complains about other undefined symbols.

Here's my output result:

Code: Select all

mipsel-unknown-elf-ld: warning: cannot find entry symbol __SN_ENTRY_POINT; defaulting to 0000000080010800
mipsel-unknown-elf-ld: cube.o: in function `init_cube':
cube.c:(.text+0x20): undefined reference to `SetPolyF4'
mipsel-unknown-elf-ld: cube.o: in function `main':
(.text.startup+0x58): undefined reference to `ResetGraph'
mipsel-unknown-elf-ld: (.text.startup+0x60): undefined reference to `InitGeom'
mipsel-unknown-elf-ld: (.text.startup+0x68): undefined reference to `SetGraphDebug'
mipsel-unknown-elf-ld: (.text.startup+0x74): undefined reference to `FntLoad'
mipsel-unknown-elf-ld: (.text.startup+0x94): undefined reference to `FntOpen'
mipsel-unknown-elf-ld: (.text.startup+0x9c): undefined reference to `SetDumpFnt'
mipsel-unknown-elf-ld: (.text.startup+0xa8): undefined reference to `SetGeomOffset'
mipsel-unknown-elf-ld: (.text.startup+0xb0): undefined reference to `SetGeomScreen'
mipsel-unknown-elf-ld: (.text.startup+0xc8): undefined reference to `SetDefDrawEnv'
mipsel-unknown-elf-ld: (.text.startup+0xe0): undefined reference to `SetDefDrawEnv'
mipsel-unknown-elf-ld: (.text.startup+0xf8): undefined reference to `SetDefDispEnv'
mipsel-unknown-elf-ld: (.text.startup+0x110): undefined reference to `SetDefDispEnv'
mipsel-unknown-elf-ld: (.text.startup+0x118): undefined reference to `srand'
mipsel-unknown-elf-ld: (.text.startup+0x130): undefined reference to `rand'
mipsel-unknown-elf-ld: (.text.startup+0x138): undefined reference to `rand'
mipsel-unknown-elf-ld: (.text.startup+0x140): undefined reference to `rand'
mipsel-unknown-elf-ld: (.text.startup+0x188): undefined reference to `SetDispMask'
mipsel-unknown-elf-ld: (.text.startup+0x190): undefined reference to `PutDrawEnv'
mipsel-unknown-elf-ld: (.text.startup+0x198): undefined reference to `PutDispEnv'
mipsel-unknown-elf-ld: (.text.startup+0x26c): undefined reference to `RotMatrix'
mipsel-unknown-elf-ld: (.text.startup+0x28c): undefined reference to `TransMatrix'
mipsel-unknown-elf-ld: (.text.startup+0x298): undefined reference to `ClearOTagR'
mipsel-unknown-elf-ld: (.text.startup+0x2b0): undefined reference to `FntPrint'
mipsel-unknown-elf-ld: (.text.startup+0x2c4): undefined reference to `SetRotMatrix'
mipsel-unknown-elf-ld: (.text.startup+0x2d8): undefined reference to `SetTransMatrix'
mipsel-unknown-elf-ld: (.text.startup+0x368): undefined reference to `RotAverageNclip4'
mipsel-unknown-elf-ld: (.text.startup+0x3a4): undefined reference to `AddPrim'
mipsel-unknown-elf-ld: (.text.startup+0x3b4): undefined reference to `DrawSync'
mipsel-unknown-elf-ld: (.text.startup+0x3bc): undefined reference to `VSync'
mipsel-unknown-elf-ld: (.text.startup+0x3d0): undefined reference to `ClearImage'
mipsel-unknown-elf-ld: (.text.startup+0x3d8): undefined reference to `DrawOTag'
mipsel-unknown-elf-ld: (.text.startup+0x3e0): undefined reference to `FntFlush'
mipsel-unknown-elf-ld: cube.o:(.hdr+0x10): undefined reference to `__SN_ENTRY_POINT'
I already use PSN00BSDK with its toolchain so I see no point in building another toolchain for PSYQ SDK.

Re: psyq2elf - Convert Psy-Q SDK libraries

Posted: March 10th, 2021, 6:38 am
by jype
Elvarg, the same toolchain should work for both PSn00bSDK and the cube example. I pushed a minor fix for the cube makefile that might help with the linker issue.

The "undefined reference" errors are due to PSYQ libraries not being linked at all (or being empty?) - if the makefile fix doesn't work, could you provide the make output before the errors? It should be something like this:

Code: Select all

mipsel-unknown-elf-gcc -c -g -O3 -G0 -ffreestanding -I../../include cube.c
mipsel-unknown-elf-ld -o cube -g -T linker.ld cube.o ../../lib/libcard.a ../../lib/libpress.a ../../lib/libgpu.a ../../lib/libgs.a ../../lib/libgte.a ../../lib/libcd.a ../../lib/libetc.a ../../lib/libsn.a ../../
lib/libsnd.a ../../lib/libspu.a ../../lib/libmath.a ../../lib/libcomb.a ../../lib/libcard.a ../../lib/libtap.a ../../lib/libsio.a ../../lib/libpad.a ../../lib/libc2.a ../../lib/libapi.a

Re: psyq2elf - Convert Psy-Q SDK libraries

Posted: March 11th, 2021, 4:11 am
by Elvarg
Nope, it still gives me "undefined reference" errors. I even checked if had my libs in the correct directory and it still gives me those errors.

Here's my output before the errors:

Code: Select all

mipsel-unknown-elf-gcc -c -g -O3 -G0 -ffreestanding -I../../include cube.c
mipsel-unknown-elf-ld -o cube -g -T linker.ld cube.o 

/usr/local/mipsel-unknown-elf/third_party/psyq/lib/libcard.a 
/usr/local/mipsel-unknown-elf/third_party/psyq/lib/libpress.a 
/usr/local/mipsel-unknown-elf/third_party/psyq/lib/libgpu.a 
/usr/local/mipsel-unknown-elf/third_party/psyq/lib/libgs.a 
/usr/local/mipsel-unknown-elf/third_party/psyq/lib/libgte.a 
/usr/local/mipsel-unknown-elf/third_party/psyq/lib/libcd.a 
/usr/local/mipsel-unknown-elf/third_party/psyq/lib/libetc.a 
/usr/local/mipsel-unknown-elf/third_party/psyq/lib/libsn.a 
/usr/local/mipsel-unknown-elf/third_party/psyq/lib/libsnd.a 
/usr/local/mipsel-unknown-elf/third_party/psyq/lib/libspu.a 
/usr/local/mipsel-unknown-elf/third_party/psyq/lib/libmath.a 
/usr/local/mipsel-unknown-elf/third_party/psyq/lib/libcomb.a 
/usr/local/mipsel-unknown-elf/third_party/psyq/lib/libcard.a 
/usr/local/mipsel-unknown-elf/third_party/psyq/lib/libtap.a 
/usr/local/mipsel-unknown-elf/third_party/psyq/lib/libsio.a 
/usr/local/mipsel-unknown-elf/third_party/psyq/lib/libpad.a 
/usr/local/mipsel-unknown-elf/third_party/psyq/lib/libc2.a 
/usr/local/mipsel-unknown-elf/third_party/psyq/lib/libapi.a

Re: psyq2elf - Convert Psy-Q SDK libraries

Posted: March 11th, 2021, 10:14 am
by jype
That's strange, I would guess there's a problem with the libraries then. Does __SN_ENTRY_POINT exist in libsn.a?

Code: Select all

mipsel-unknown-elf-readelf -a /usr/local/mipsel-unknown-elf/third_party/psyq/lib/libsn.a | grep __SN_ENTRY_POINT
I attached converted Psy-Q 4.6 includes and libraries to the first post of this thread to save the trouble if the converter won't work properly.

Edit: There was a bug in psyq2elf that could cause empty output, the bug was fixed by javabird25. I think you hit this same bug, you can try converting again with latest psyq2elf.