### What is this? ### This is the patch for game Shadow Man: 2econd Coming on PS2, it fixes bug in SOUNDREL.IRX that can cause data corruption during loading. On emulators this bug is more pronounced because they don't take into account access delays introduced by laser mechanism and in some circumstances it shows itself on real hardware. And that is how I experienced this game back in the day, my own PS2 read data from CD faster than it was decompressed, so in some levels I had broken textures. For patching use any available PPF patching tool, PPF-O-Matic is a good choice. ISOs must have these checksums: USA Serial number: SLUS_204.13 CRC32: dd673b1d MD5: 17e1f9e7624a0c099a28c0c3ceb644fb SHA-1: 419697e9a655517e0b2589a28de8ca6862dca66f Europe Serial number: SLES_504.46 CRC32: fad31937 MD5: 53a561de1c635da4d96a041b6aa2141a SHA-1: cb64690f82146ee3839a9b53dded5ae3edbf43ec Germany Serial number: SLES_506.08 CRC32: 8acb782f MD5: 69f76731d730d4f19ded307cc6fe4c36 SHA-1: 13624d5101f10d172c6a907113b1b9d0feaf0f19 ### Explanation of the bug in the IRX module ### Loading function has two modes for loading data: 1. Double buffered mode for reading directly from CD by setting sector address and number of sectors to read. 2. Single buffered mode for reading through the use of file system access, its purpose is loading from host but it can access files on CD if forced. During initialization stage IRX module statically allocates two buffers for compressed data, they're both equal to 0x8000 bytes and placed next to each other. But data chunks on CD are very rarely aligned to boundary of 0x800 bytes(single sector size), so if chunk has size between 0x7802 and 0x8000 bytes and it's located at the risky offset then it can span across bigger number of sectors than can fit into one buffer of 0x8000 bytes. Here is visual representation of how this happens: A B ------------------------------------- ------------------------ | ! | | | ! | | 1 ! | 2 | 3 ~/~ 16 | 17 ! | | ! | | | ! | ------------------------------------- ------------------------ On this picture you can see boundaries of chunk 'A-B' marked by ! symbol and the rest is the boundaries of sectors. We can see here that if only data was properly aligned, it would nicely fit into 16 sectors, but instead it spans across 17 of them and IRX module actually reads data from CD by the number of sectors which contain the whole chunk, it can be unpacked properly only when it's fully loaded. So when such chunk arrives into buffer to be processed it can either corrupt currently processed data in the neighbor buffer or will be corrupted itself by the next chunk. And while the code which decides how many sectors to load is really working as intended the actual bug is in the buffers allocation here: .text:000016B4 jal sub_D10 .text:000016B8 li $a0, 0x8000 # 1st load buffer size .text:000016BC li $a0, 0x8000 # 2nd load buffer size These values must be set to 0x8800, extra 0x1000 bytes isn't such a big deal and in my tests game didn't had issues with such approach. It is also possible to force IRX module to always use file system access instead of direct CD access but it will potentially decrease loading speed, so I chose first method. Raziel I.C.H.I. Znot 17.12.2019