PS2 Julian's various PS2 projects (Worklog)

I was thinking about Software like OPL assigning/emulating a MAC and the producers of these adapters adding LAN with ONE or a few MACs only!

Basically "MAC-Spoofing" on the software-side, which can also be "reused" for other purposes I think!
 
Looks like someone wrote a project to interface from a Raspberry Pi to a IDE drive using SMI: https://github.com/fenlogic/IDE_trial
Might be interesting to see if it would be possible to interface with host instead with SMI. (ATAPI wrapped packets?)

---

Finished non-trivial type and name assignment for register variables on the decompiler. It won't work too well if a register is reused for another local variable, but that's fine for my use case.

Next up is type/name assignments for global/static variable and stack variables.
 
* PSF and PSF2 playback over libsd*

Interesting. If only the ePSXe team could have created that PSF ripper that they were talking about.
I would love to make/rip PSF's but I am not a coder so it's a no go for me unless someone eventually
creates one.
 
Some notes about path handling...

The POSIX specification uses "/" as the root, and additional filesystems could be mounted inside the root, e.g. "/mnt/data".
The path separator is "/".
Current directory starts with "./".

Win32 absolute paths can start with a drive letter (e.g. "Z:\") or a UNC path (e.g. "\\localhost\mnt\share").
The drive letter is only a single character and only can be alphabet (e.g. A through Z).
(It is possible to use a unicode character e.g. ♪ for the drive letter, but it is not well-supported)
The path separator is "\", but "/" is also accepted.
Current directory starts with ".\"

For Classic Mac OS, the absolute path starts with the drive name e.g. "Macintosh HD:file".
The path delimiter is ":"
Current directory starts with ":"

Now, here's the kicker…
For platforms like PS2, PSP, Vita, they use e.g. the following syntax instead:
"mc0:/"

Notice the following:
There are multiple characters before : (not only 1), so not Win32 compatible
It does not start with "/", so not POSIX compatible.

This means that different logic/concepts are needed to deal with this kind of path. This does not fit in within the POSIX or the Win32 methodology.
 
Probably how I'll handle the PSF2 playback using libsd: Maybe do something like a "logging" mechanism.

R3000 is processed on EE. Just enough of SPU2 is implemented on EE, so that state / echo buffer readbacks are "good enough".
Reads/writes/DMA xfers are logged on EE, minimized to libsd calls, and sent to IOP with DMA. No sound data (state / echo buffer etc) goes back to EE.

--

Probably how I would implement UDPIPU is either one of two of the following:

RTP and any of:
1. MPEG2 I-frames decoded by IPU, possibly lz4 compressed
2. H.264
and any of:
1. Opus
2. ADPCM
3. PCM

The choice I will make will depend on benchmarks.

I will probably base the protocol on what Moonlight is doing.
For now, the design is looking like a bridge application would be needed to bridge PS2 and Gamestream server.

On a related note, looks like there is an OSS server for Gamestream: https://github.com/loki-47-6F-64/sunshine

--

Seems like GCC 12 is close to being released: https://gcc.gnu.org/pipermail/gcc/2022-April/238491.html

--

I haven't gotten the design for UDPBD write support nailed down yet.

What complicates things is that the server is a loop based design while the client uses an interrupt based design in addition to loops.
Server blocks on recvfrom and then does sendto based on the contents of the packet.
Client calls a function based on an interrupt. Client sends packets by direct address writes (DMA is only done for read).

So basically:
For UDPBD connect, server sends identify packet, client receives identify packet and calls interrupt, read headers by address reads, response by direct address writes.
For UDPBD read, data is fragmented into several parts, loop for each part, send read command for range, wait semaphore.
- Server receives read command, fragments range and sends multiple of those packets.
- Client receives read packet and calls interrupt, read headers by address reads, DMA right into user buffer, signal semaphore.

I'd think I'd like to simplify the read by removing the loop from the initial send, and instead requesting the whole range. Instead, make the server calculate the fragmentation and when the client should send ACKs/NAKs and reset the timeout alarm.
 
Last edited:
Oh, you are already talking about the streaming-server-implementation as well, but to be frank the "normal" UDPBD-Streaming as another "block device" in OPL would be awesome already!

Having streaming, possibly even in higher resolutions would be a "killer app"!

Regarding MPEG2-I Frames: I don't think that it is much faster than using MPEG4v3 (h.263), because the quantizer matrix is only using another layout of "numbers", how a macro-block is "quantized".
The GENERAL codec and implementation however matters A LOT! I doubt we can decode GMC, QPel, etc. in HD "in time"!
I DO think we can have h.263 in HD and decode it very fast and without introducing much latency.
From the server to the picture on the screen it might be ~60-120ms... Maybe not feasible for Beat-em-up-games, but enough for a lot of other games.

But... It needs some optimizations... If others join the project, we could have optimizations on both sides (PS2 AND PC)!


Regarding audio: What about a compressed stream? Do you fear it having a high latency?
 
Last edited:
Oh, you are already talking about the streaming-server-implementation as well, but to be frank the "normal" UDPBD-Streaming as another "block device" in OPL would be awesome already!

Having streaming, possibly even in higher resolutions would be a "killer app"!
Ah, whoops, that was a typo. It should be UDPIPU
 
In any way, we could utilize ALL parts of the platform/PS2! FPU or VU or EE for decoding, etc.!

It could be improved for DECKARD vs. "normal", etc.!
 
Some wishlist of libraries to add to ps2sdk-ports:

libcurl
mbedtls
libwebp
libopus
brotli (for WOFF2 font compression in freetype)
libarchive
SDL2

Would probably allow for even more space savings and also allow access to sites that are HTTPS only like GitHub.

---

I'd like to eventually make it so that CDVD SCMD packets are generated on the EE and then passed through iomanX devctl to sceCdApplySCmd on the IOP.

And a similar thing to MCMAN too.
That should allow non blocking commands so other threads can run while they are processing.
Also, it should allow easy access to extra SCMDs without needing to replace the IOP CDVDMAN/CDVDFSV module. In fact, sceCdNoticeGameStart is already implemented in this way in libcdvd in ps2sdk.

---

I'd like to eventually add ifdefs for the renamed libcdvd functions... This is very low hanging fruit.
 
I think it would be interesting to have my own take at replicating the PS2 clock.

Basically, these would probably be done:
* Scene description in glTF
* UV scroll/scale for animation
* Animate position/rotation based on time

I would like the actual animation logic to be minimal so that it can be easily ported to different systems e.g. Three.js, Udon, …
 
I wrote a atad shim layer over dvr_hdd0: devctls. Not sure if it works, however. But I'll have some time to try it in a week or so.

I guess next up is to figure out the logic on how the DVRP firmware determines the 28bit LBA location (2GB or 40GB), or the logic of the result of HDIOC_GETMAXLBA48 / 0x683B
 
dvrfile.irx appears to have proxies for dvr_hdck, dvr_fssk, and dvr_fsck. But those strings don't appear in the DVRP firmware. I wonder if it's just unused, or maybe the FSCK elf does something differently…

---

Potentially found the reason why the DVR area PFS driver breaks on 250GB drives… The pfsCheckExtendedZoneSize function in the xosd driver checks for over 0x100000, but the DVRP driver checks for over 0x1000000 instead (that's another 0 appended to it)

---

Basically I think this is what you need to do to re-initialize the HDD after patching the SCE security command out: 0x10008412 - ata_device_sce_identify_drive (you want to stub this so it always passes) 0x10008b80 - ata_init_devices (contains a call to ata_device_sce_identify_drive) 0x10008dfc - ata_get_devinfo DVRP filesystem side reinitialization: 0x10070050 - this variable is set to 1 in ata_get_devinfo. Need to reset to 0 after patching so it can pick up the HDD 0x100201c8 - initializes ioman 0x1001e4c4 - initializes the apa driver (also inits ATA by calling ata_get_devinfo) 0x1002430c - initializes the pfs driver 0x1003352c - mounts __xcontents and __xdata to dvr_pfs0: and dvr_pfs1: respectively HDD emulation reinitialization: 0x1000e8fa - HDD emulation service startup (also inits ATA by calling ata_get_devinfo)

---

Hopefully with reimplementation of sysclib/padman/mcman/libpad2/libmc2 it would be possible to free up a bit of IOP RAM space, maybe allowing for larger caches and larger block compression
And improve pademu/mcemu/IGR/mx4sio compatibility in the process
I'm planning on how I should go around building a database of EE/IOP libraries/versions being used on each game. This database might also help Play! emulator witch does HLE.

---

I made some more improvements on the STABS parser. Now register variables are correct (using the function to map microcode register to cpu register), stack variables are implemented, and global variables are implemented.

Next up is to rearrange functions as described in the debugging information…

---

It seems like the arcade modules reference flash memory, but I took a look at the arcade PCB and the referenced chips don't appear to be on the board… But there is definitely SRAM and RAM on board. Maybe the flash memory was used for development only?

---

Before I continue to work on some PS2-side projects, first I'll improve the debugging utilities, so it will allow me to iterate faster.
 
The STABS debug information is missing the following:

1. callback arguments
Code:
void (*callback) (/* The part that would go in here is missing */);
2. vararg
Code:
int function(int arg1, int arg2, /* This part is missing in the debug information -> */ ... /* <- */);
3. const
Code:
int function(/* This is missing -> */ const /* <- */ char *arg1);

So I'll need to manually fix those…
 
Last edited:
I may have figured out how to derive if vararg just from the debug information.

Basically:
1. va_list is not an argument type
2. va_list is a local variable type

If both of these are true, then it's probably a vararg (...). This probably won't work for functions that take va_list in addition to vararg, but this is good enough.

For missing const, could probably just use cppcheck's constness analysis.
 

Similar threads

Back
Top