psyq2elf - Convert Psy-Q SDK libraries
psyq2elf - Convert Psy-Q SDK libraries
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
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)
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
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)
You do not have the required permissions to view the files attached to this post.
Last edited by jype on May 7th, 2024, 9:51 pm, edited 2 times in total.
-
Shadow Verified
- Admin / PSXDEV
- Posts: 2670
- Joined: Dec 31, 2012
- PlayStation Model: H2000/5502
- Discord: Shadow^PSXDEV
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.
Development Console: SCPH-5502 with 8MB RAM, MM3 Modchip, PAL 60 Colour Modification (for NTSC), PSIO Switch Board, DB-9 breakout headers for both RGB and Serial output and an Xplorer with CAETLA 0.34.
PlayStation Development PC: Windows 98 SE, Pentium 3 at 400MHz, 128MB SDRAM, DTL-H2000, DTL-H2010, DTL-H201A, DTL-S2020 (with 4GB SCSI-2 HDD), 21" Sony G420, CD-R burner, 3.25" and 5.25" Floppy Diskette Drives, ZIP 100 Diskette Drive and an IBM Model M keyboard.
PlayStation Development PC: Windows 98 SE, Pentium 3 at 400MHz, 128MB SDRAM, DTL-H2000, DTL-H2010, DTL-H201A, DTL-S2020 (with 4GB SCSI-2 HDD), 21" Sony G420, CD-R burner, 3.25" and 5.25" Floppy Diskette Drives, ZIP 100 Diskette Drive and an IBM Model M keyboard.
-
- What is PSXDEV?
- Posts: 2
- Joined: Apr 07, 2020
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.
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.
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
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
-
- What is PSXDEV?
- Posts: 2
- Joined: Apr 07, 2020
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.
As a side note I did try ePSXe originally, but just had black screen.
You do not have the required permissions to view the files attached to this post.
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:
I already use PSN00BSDK with its toolchain so I see no point in building another toolchain for PSYQ SDK.
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'
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:
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
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:
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
That's strange, I would guess there's a problem with the libraries then. Does __SN_ENTRY_POINT exist in libsn.a?
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.
Code: Select all
mipsel-unknown-elf-readelf -a /usr/local/mipsel-unknown-elf/third_party/psyq/lib/libsn.a | grep __SN_ENTRY_POINT
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.
Updated Psy-Q 4.6 libraries attached in first post after fixing a symbol alignment bug.
The pcsx-redux project has an equivalent tool which is better maintained and tested:
https://github.com/grumpycoders/pcsx-re ... obj-parser
Examples and a link to psyq-obj-parser converted Psy-Q 4.7 libraries:
https://github.com/ABelliqueux/nolibgs_hello_worlds
The pcsx-redux project has an equivalent tool which is better maintained and tested:
https://github.com/grumpycoders/pcsx-re ... obj-parser
Examples and a link to psyq-obj-parser converted Psy-Q 4.7 libraries:
https://github.com/ABelliqueux/nolibgs_hello_worlds
Who is online
Users browsing this forum: No registered users and 2 guests