this will be updated periodically
I've been messing around with programming on my playstation 2 (slim) for a few days and have found some interesting things which I will jot down in this website.
First off, I should say what my setup looks like
I'm using:
- -an ubuntu vm hosted on my desktop pc, with a pre-built ps2dev toolchain extracted into its appropriate spots and some environment variables set (namely the locations of the as and ld programs in the toolchain)
- -an ethernet switchbox, which is plugged into my pc, my router, and my ps2 slim
- -a ps2 slim, which has been modified with mechapwn (unused for my workflow) and is otherwise unmodded
- -a dvd with freedvdboot burned onto it
- -a usb drive with ps2link on it
Before I start writing a program, I turn on the ps2 slim with the FreeDVDBoot dvd inside, and the usb drive inserted. It usually takes a few attempts (opening and closing the disc bay) before it reads the dvd.
Then I use ULaunchElf to launch ps2link, and leave it on the side til I've written a program for it. If you're launching ps2link for the first time, you'll want to note the IP Address it shows on screen.
You should save this as an environment variable in linux ($PS2HOSTNAME). That way, you don't need to write the address every time you use ps2client
Also, you'll need an RGB or yPbPr/component video output from your ps2. One of those ps2-specific HDMI converter things should work fine too. PS2Link's text is nearly unreadable with composite video.
On the ubuntu vm, I write my program in MIPS assembly, then assemble and link it as a .elf file, using the ps2dev toolchain's appropriate as and ld programs.
Then, I use ps2client (included with the ps2dev toolchain) to send the .elf file to my ps2. Like this: ps2client execee host:ratfun.elf
ANYWAYS:
I haven't gotten very far with my coding in this way. I'm following along with this MIPS assembly course and I'm still on very basic stuff,
arithmetic and bit logic between registers, no I/O, that kinda thing. At this level of program, I can't even begin to have my own graphical output and I can't quite get that ps2client debug stuff to work.
However, when the ps2 runs into an Emotion Engine Exception, ps2link will show a debug screen with what all the general purpose registers contain. So all my programs, right now, end with the following:
The Magic Instruction that Bugchecks Your PS2
teq $0,$0
"teq" means "Trap on Equal". It takes in 2 registers and compares their values. If those 2 values are equal, it causes a Trap exception, which throws up that debug screen we want, so we can see what we've done to the registers.
Any register passed into it twice will probably make it Always trap, but I use $0 since register 0 will never ever change its value from 0, so it's guaranteed to work.
anyways, those observations And Whatnot
- the ps2's Emotion Engine Core has 128 bit registers, but I'm not exactly sure how to use the upper 64 bits. dsll (doubleword shift left) cuts off at the 64th bit, and there's no quadword shift left.
- the ps2link debug screen displays the registers in a Strange way. when you expect to see
0x0000000000000000FFFFFFFFFFFFFFFF, you'll see0x00000000FFFFFFFF00000000FFFFFFFFinstead. - the expected behavior of the
div $rs, $rtinstruction is that the result of dividing the contents of $rs by the contents of $rt will be left in the LO register, but on the ps2 it seems like the result is put into $rs. This doesn't seem to be documented anywhere. - January 27th, 2026:
judging from the result of exactly 1 test so far, when you declare a variable in a .data segment, the starting address is 0x001000E4, going up. I think. An earlier observation made me think it was 0x001000DC, but trying to use this in a program was unsuccessful. Using 0x001000E4 in a new test, however, did work.
(I should note, I have no idea whether this may change with a different method for execution. Maybe this specific address only works with ps2link, and won't work from uLaunchElf or a disc. I'll find out later.)
A new test revealed a new, slightly different address. I think the exact address for the start of the data segment depends on how many instructions are in the program (otherwise i'm not sure What it depends on). I think the conclusion to be made from this is that you shouldn't use hard-coded addresses in your program for things you've declared in the .data segment.