Jump to content

Siren 2 (2006, PS2) .rom and chunk files


ldvd

Recommended Posts

Siren 2 contains 8 chunk archives and a separate .rom file. The latter works as the game's table of contents and from what I can tell:

Archive header (0x20 bytes long):
4 - ID (SLPK)
4 - fairly long number that doesn't match with the chunk's filesize
4 - number of files within the game's archives
4 - offset to the game's tail
4 - null bytes
4 - unknown, could be related to the game's image's sectors
4 - fairly large number, around 2GB long
4 - fairly large number that's slightly smaller than the previous entry

File entry directory (0xA550 bytes long):
4 - relative filename offset inside tail, counts null byte as part of the filename
4 - unknown, number of different entries matches with number of archives, seems to identify each of the archive files
4 - possible file offset inside chunk file containing it
4 - possible filesize

Filename directory (starts on 0xA570 until EoF, contains 0xA55 entries):
Lists each rom.00X file in sequential order, followed by each of its files' full path filenames
Both the files and the rom.00X filenames end with a null byte

SPK.rom starts with the magic bytes SLPK, ROM.000-007 don't seem to have a header file and act exclusively as file archives. The game uses little endian ordering for its byte entries.

Zip contains SPK.rom as well as the first 16MBs of ROM.000 and ROM.004.

siren2.zip

Edited by ldvd
Link to comment
Share on other sites

  • ldvd changed the title to Need help extracting Siren 2 (PS2) .rom and chunk files

The archive directory entry's first "unknown" is the archive filename offset:

image.png.23a83bb0d442e816ba6c54c51f17ce17.png

The "maybeFileSize" certainly seems likely given the corresponding filename extensions (PSS's are larger than WaveBank audio and TIM2 images).

The "maybeChunkOffset" is tough to gauge without knowing the full size of the archive files. How large is each one?

In ROM.000, there are multiple TIM2 files which you might be able to cross reference with offsets here:

  • 1F60h
  • 9FE0h
  • A160h
  • A2E0h
  • 12360h
  • 124E0h
  • 13560h

image.png.4cb1e635eece5bb71ab3a35cf14a6ad7.png

None of these offsets match records in ROM.000 though 🤔 (e.g. 00 E8 3E 1D):

image.png.28b9a66ff5ef59c67e2fb0f8fdada603.png

Maybe it's a bitfield? I tried shifting 0x1D3EE800 by multiple shifts though, and still none matched. Maybe each numbered archive actually has a relative base offset? It's also weird that the least significant byte would always be zero, because while some alignment is expected for data type alignment (often 4/8/16 bytes), 256 bytes of alignment feels wasteful (but maybe not 🤷) :

image.png.4db9cd243e41a5da2129f6b50b2afa54.png

010 Editor template:

LittleEndian();
BitfieldRightToLeft();

// define missing types
typedef char int8;
typedef char char8;
typedef wchar_t char16;
typedef uchar uint8;

// Archive header (0x20 bytes long)
struct ArchiveHeader
{
    char8 tag[4];           // 4 - ID (SLPK)
    uint32 unknown1;        // 4 - fairly long number that doesn't match with the chunk's filesize
    uint32 fileCount;       // 4 - number of files within the game's archives
    uint32 filenamesOffset; // 4 - offset to the list of filenames
    uint32 empty;           // 4 - null bytes
    uint32 unknown2;        // 4 - unknown, could be related to the game's image's sectors
    uint32 unknown3;        // 4 - fairly large number, around 2GB long
    uint32 unknown4;        // 4 - fairly large number that's slightly smaller than the previous entry
};

// File entry directory (16 bytes each, 0xA550 bytes total):
struct ArchiveDirectoryEntry(uint32 filenamesOffset)
{
    uint32 filenameOffset;          // 4 - relative filename offset inside tail, counts null byte as part of the filename
    uint32 archiveFilenameOffset;   // 4 - unknown, number of different entries matches with number of archives, seems to identify each of the archive files
    uint32 maybeChunkOffset;        // 4 - possible file offset inside chunk file containing it
    uint32 maybeFileSize;           // 4 - possible filesize

    local int64 originalFilePosition <hidden=true> = FTell();
    FSeek(filenamesOffset + filenameOffset);
    string filename;
    FSeek(filenamesOffset + archiveFilenameOffset);
    string externalArchiveFilename;
    FSeek(originalFilePosition);
};

ArchiveHeader header;
ArchiveDirectoryEntry entries(header.filenamesOffset)[header.fileCount] <optimize=false, open=true>;

 

Edited by piken
  • Thanks 1
Link to comment
Share on other sites

Posted (edited)
7 hours ago, piken said:

The archive directory entry's first "unknown" is the archive filename offset:

Hadn't thought of that. Checked each archive's filename offset and they match with the address in that field.

How were you able to create those tables in your image? Were those done in HxD, or in that 010 Editor you've linked? Fresh off a single tutorial, all that's in the OP are wild guesses I hadn't checked thoroughly. Formatting entries like that would come in handy now that I know they can be done.

7 hours ago, piken said:

The "maybeChunkOffset" is tough to gauge without knowing the full size of the archive files. How large is each one?

ROM.000 is 537.675.840 bytes long, ROM.001 equals 550.553.664 bytes, ROM.002 574.061.760 bytes, ROM.003 549.920.704 bytes, ROM.004 537.743.872 bytes, ROM.005 581.976.128 bytes, ROM.006 538.966.080 bytes and ROM.007 597.037.120 bytes. I made that assumption because the chunk offset value never seems to be larger than the chunk's filesize.

7 hours ago, piken said:

None of these offsets match records in ROM.000 though

0x1D3EE800 in ROM.000 starts with the string TIM2.

HxD_4u0uWRjZot.png.6afafc1462199203f7cd7993c11057aa.png 

I've cross-referenced filenames in address A9B6 (ROM.000), AFB4 (ROM.001) and 1682A (ROM.004) by hand. Following these files' chunk offsets I've been similarly greeted with the string "TIM2", and all three of them ended with a similar tail mostly made of FF bytes per the field's filesize. I'm certain the file format's correct, and the sample files I provided were perhaps corrupted. Try this format out with the game's original files (JPN version).

Only thing we'd need now is to convert the file format into a QuickBMS script to extract the files with. I would do it, but my experience with QuickBMS is null and my programming skills are negligible.

Edited by ldvd
  • Like 1
Link to comment
Share on other sites

> Were those done in HxD, or in that 010 Editor you've linked?

Yep, 010 Editor is pretty useful for deeper inspection, enough that I bought it (but I also use free HxD for lighter tasks, and I tried imhex, but it feels kinda awkward 😅).

> I've cross-referenced filenames in address

Nice. Sounds like it is pretty well figured out now then (and maybe those other unknown fields can just safely stay unknown).

> my experience with QuickBMS is null

Likewise (it certainly looks different compared to all the other programming languages I've used 🤔). There's also Noesis that you could write a Python plugin for 🤷‍♂️. Good luck. 🤞

Link to comment
Share on other sites

  • ldvd changed the title to Siren 2 (2006, PS2) .rom and chunk files

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...