PSISOIMG0000
ISO.BIN structure[edit | edit source]
All offsets are in little endian (except in the last table where there are two counters in decimal)
1 block = 1024 bytes (0x400) 1 cluster = 16 blocks = 1024*16 bytes =16384 bytes (0x4000)
disc_starts ----------> 0x000400 (disc1), 0x100400 (disc2), 0x200400 (disc3), 0x300400 (disc4), etc... disc_tocs -----------> 0x000C00 (disc1), 0x100C00 (disc2), 0x200C00 (disc3), 0x300C00 (disc4), etc... disc_map_tables ----> 0x004400 (disc1), 0x104400 (disc2), 0x204400 (disc3), 0x304400 (disc4), etc...
Header (optional)[edit | edit source]
1 block = 1024 bytes (0x400)
Always exists in PS1 classic multidiscs (the example below is from ff8), in the official PS1 classics single disc doesnt exists, but the custom PS1 classics single discs can use it (there are custom tools that adds it in all cases)
Block Nº | Offset | Length | Name | Example | Description |
---|---|---|---|---|---|
0 common_header |
0x0000 | 0x10 (16 bytes) | magic | PSTITLEIMG000000 | |
0x0010 | 0x1F0 (496 bytes) | padding | |||
0x0200 | 0x64 (100 bytes) | discs_start_offsets | 00 04 00 00 | 25 chunks of 4 bytes ... each chunk = start position of each disc, in games with only 1 disc only the first 4 bytes are used. Only 5 discs are supported by emulator. | |
0x0264 | 0x10 (16 bytes) | game_id | _SLES_12345 | common identifier for all discs. | |
0x0274 | 0x18 (8 bytes) | padding | |||
0x028C | 0x80 (128 bytes) | unknown | |||
0x030C | 0x80 (128 bytes) | unknown | related to data from 0x390 | ||
0x038C | 0x04 (4 bytes) | unknown | |||
0x0390 | 0x3E (62 bytes) | unknown | related to data from 0x30C | ||
0x03CE | 0x02 (2 bytes) | padding | |||
0x03D0 | 0x04 (4 bytes) | unknown | |||
0x03D4 | 0x2C (44 bytes) | padding |
Section[edit | edit source]
64 clusters, 1024 blocks, 10485576 bytes (0x100000)
This structure is repeated one time for every disc of the game all them joined together consecutivelys (the example below is from ff8), the whole space is reserved even when there is no data used
Cluster Nº | Block Nº | Offset | Length | Name | Example | Notes |
---|---|---|---|---|---|---|
0 Disc map header |
1 | 0x0000 | 0x00C (12 bytes) | magic | PSISOIMG0000 | |
0x000C | 0x004 (4 bytes) | section size | Offset from the start of the PSISOIMG section to the next section For uncompressed images this is usually 0x100000 + size of iso-image padded to 0x9300 If the disc contains CD-DA tracks then this number will also include all the ATRACK encoded audio that follows after the disk image. | |||
0x0010 | 0x3F0 (1008 bytes) | padding | ||||
2 | 0x0400 | 0x010 (16 bytes) | disc id | _SLES_12345 | in games with several discs each disc has a different id | |
0x0410 | 0x14 (20 bytes) | padding | ||||
0x0420 | 0x4 (4 bytes) | ps1 config firmware | 0x06070070 | config revision in little endian. | ||
0x0424 | 0x4 (4 bytes) | ps1 config firmware | 0x06060000 | config revision in little endian. | ||
0x0428 | 0x84 (132 bytes) | ps1 configs 1 | 0x00104500 | Ad hoc game configs in little endian. Single config is 4 bytes param. | ||
0x04AC | 0x84 (132 bytes) | ps1 configs 2 | 0x00104500 | Ad hoc game configs in little endian. Single config is 4 bytes param. | ||
3 | 0x0800 | 0x3FС (1020 bytes) | Disc toc table | variable | Table of content, like CUE sheet, supports upto 99 entries (102 entries total) | |
0x0BFC | 0x004 (4 bytes) | disc start offset | 0x100000 | |||
4 | 0x0C00 | 0x400 (1024 bytes) | Audio tracks table | Datas of audio tracks (2-65). offset, size, and more | ||
5 | 0x1000 | 0x220 (544 bytes) | Audio tracks table | Datas of audio tracks (66-99). offset, size, and more | ||
0x1220 | 0x0fce9e31 (4 bytes) | isoimage size | isoimgsize + 'disc start offset' + 0x2d31 | |||
0x122C | 0x080 (128 bytes) | unknown | Memory card related, probably custom path for external card. | |||
0x12AC | 0x004 (4 bytes) | unknown | Latest POPS read value but never use it, maybe some leftover from older version. | |||
0x12B0 | 0x004 (4 bytes) | Libcrypt Magic Word | 0x72D01234 | Little endian. Magic word is used as an answer to COP0 BPC reads for libcrypt games. Magic word needs to be xored with 0x72D0EE59 before supplying. | ||
0x12B4 | 0x004 (4 bytes) | unknown | Emulator test if value is greater than 0, but value itself is not used (works like bool). | |||
0x12D4 | 0x004 (4 bytes) | subchannel offset | 0x100400 | Offset to where subchannel data is stored. This is used with libcrypt. | ||
0x12D8 | 0x004 (4 bytes) | subchannel count | 0x178 | Number of subchannel blocks. Each block is 12 bytes. | ||
0x12DC | 0x3E (62 bytes) | unknown | ||||
0x131A | 0x124 (230 bytes) | padding | ||||
6 | 0x1400 | 0x400 (1024 bytes) | not used | |||
7 | 0x1800 | 0x400 (1024 bytes) | not used | |||
8 | 0x1C00 | 0x400 (1024 bytes) | not used | |||
9 | 0x2000 | 0x400 (1024 bytes) | not used | |||
10 | 0x2400 | 0x400 (1024 bytes) | not used | |||
11 | 0x2800 | 0x400 (1024 bytes) | not used | |||
12 | 0x2C00 | 0x400 (1024 bytes) | not used | |||
13 | 0x3000 | 0x400 (1024 bytes) | not used | |||
14 | 0x3400 | 0x400 (1024 bytes) | not used | |||
15 | 0x3800 | 0x400 (1024 bytes) | not used | |||
16 | 0x3C00 | 0x010 (16 bytes) | checksum | 0x1CCE0033... | It seems to be the checksum of this block, and because this block is always unused the checksum is always 1CCE003360C6E8A6B36A972D00EAFDBF | |
0x3C10 | 0x3F0 (1008 bytes) | padding | ||||
1 Disc map table |
17 | 0x4000 | variable | Disc map table | Divided in chunks of 32 bytes | |
Up to 32 | ||||||
Up to 64 Disc map table |
Disc toc table[edit | edit source]
Entry structure:
Entry Nº | Offset | Length | Name | Example | Notes |
---|---|---|---|---|---|
1 | 0x00 | 0x01 (1 byte) | TYPE | 0x41/0x01 | entry flags |
0x01 | 0x01 (1 byte) | TNO | 00 | always zero | |
0x02 | 0x01 (1 byte) | POINT | 0xA0/0xA1/0xA2/0x01/0x02/0x03/etc | increases | |
0x03 | 0x01 (1 byte) | MIN | varies | decimal | |
0x04 | 0x01 (1 byte) | SEC | varies | decimal | |
0x05 | 0x01 (1 byte) | FRAME | varies | decimal | |
0x06 | 0x01 (1 byte) | ZERO | 00 | always zero | |
0x07 | 0x01 (1 byte) | PMIN | varies | decimal | |
0x08 | 0x01 (1 byte) | PSEC | varies | decimal | |
0x09 | 0x01 (1 byte) | PFRAME | varies | decimal | |
Up to 102 | same structure than the previous entry |
Audio tracks table[edit | edit source]
Entry structure:
Entry Nº | Offset | Length | Name | Example | Notes |
---|---|---|---|---|---|
1 | 0x00 | 0x04 (4 bytes) | offset | ||
0x04 | 0x04 (4 bytes) | size | |||
0x08 | 0x04 (4 bytes) | unknown_0 | always zeroed | ||
0x0C | 0x04 (4 bytes) | enc_key | encryption key (or 0 if not encrypted) | ||
Up to 98 | same structure than the previous entry |
The audio tracks themselves are raw ATRAC3 streams without a header. One way to create such blobs is to use the atracdenc encoder and strip of the first 0x60 bytes which is the header. The resulting blob is what the Audio tracks table entries will point to.
Disc map table[edit | edit source]
The table has an area reserved of 1032192 bytes. Divided in 32256 entries, of 32 bytes each entry. The number of used entryes in the file_table can vary (seems to be dependant of the .iso contents). The number of entries availables to store data is affected by a checksum (16 bytes) that is present only in the the last block of each cluster (in block nº16 of every cluster) When this checksum is between used entryes... his length is 32 bytes (it "steals" the area of one entry) Seems to be a checksum of this block... when the block is filled with zeroes the checksum is : 1CCE0033 60C6E8A6 B36A972D 00EAFDBF
The first 4 bytes of each entry (file offset from start of .iso root) increases for each entry in a amount of bytes determined by the previous entryes.... in other words... the second file in the .iso is displaced the number of bytes used by the first file... and the third file is displaced in a amount of bytes used by the addition of the sizes of first and second file.
File_type needs to be 0 for compressed blocks on PSP or else it will create an audible buzz when playing the CDDA tracks.
Entry Nº | Offset | Length | Name | Example | Notes |
---|---|---|---|---|---|
1 | 0x00 | 0x04 (4 bytes) | file_offset | 0 | file offset from start of .iso root (for the first entry is always 0) |
0x04 | 0x02 (2 bytes) | file_size | variable | this size determines the displacement of the next file (in the next entry) | |
0x06 | 0x02 (2 bytes) | file_type ? | 01 00 | usually 1... and 0 for the last entry | |
0x08 | 0x10 (16 bytes) | file_checksum | variable | First 16 bytes of the sha1 of the uncompressed data | |
0x18 | 0x08 (8 bytes) | padding | |||
Up to 32256 | same structure than the previous entry |
Common Disc table[edit | edit source]
Composed by a variable number of entries (depends of the number of files/folders inside the discs), 12 bytes each entry
Entry Nº | Offset | Length | Name | Example | Notes |
---|---|---|---|---|---|
1 | 0x00 | 0x04 (4 bytes) | file_offset ? | 0 | always increases |
0x04 | 0x02 (2 bytes) | file_type ? | 01 01 | always 01 01 | |
0x06 | 0x03 (3 bytes) | counter 1 | some kind of counter, in decimal, always increases <-------- related with "sectors" inside the .iso ? | ||
0x09 | 0x03 (3 bytes) | counter 2 | another counter, in decimal, always increases, its in relationship with the previous counter (this one is always 200 bytes bigger than the previous one) | ||
Up to ? | same structure than the previous entry |
Subchannel data[edit | edit source]
This is data stored in separate .pgd in psar (0xED4 [0x12D4] in ISO header point to it if available), should be required only for games that use libcrypt protection (LC2 and higher). Header of decrypted file is FFFFFFFF 00000000 FFFFFFFF, end of file is marked by FFFFFFFF FFFFFFFF FFFFFFFF. Values are always 150 sectors lower than real disc sector (pregap?). Values are in little endian (sector only actually, others are 1 byte values). See section below for example code on how to generate this table.
Entry Nº | Name | Offset | Size (bytes) | Example | Notes |
---|---|---|---|---|---|
1 or 2? | Sector | 0x00 | 4 | Sector number - 150 | |
Track Number | 0x04 | 1 | 0x01 | Always 0x01 | |
Index | 0x05 | 1 | 0x01 | Always 0x01 | |
Pmin(relative) | 0x06 | 1 | |||
Psec(relative) | 0x07 | 1 | |||
Pframe(relative) | 0x08 | 1 | |||
Amin (Absolute) | 0x09 | 1 | |||
Asec (Absolute) | 0x0A | 1 | |||
Aframe (Absolute) | 0x0B | 1 | |||
Up to 1024 | or up to 1022? (minus header/footer) same structure than the previous entry |
- More info: https://www.psx-place.com/threads/ps1-libcrypt-support-on-ps3-official-emus-research-thread.35836/page-13#post-318506
- Unpacker able to extract that data: PSone Classic Tools