ISO.BIN.EDAT
iso.bin structure (decrypted)
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...
iso.bin Header
1 block = 1024 bytes (0x400)
Block Nº | Offset | Length | Name | Example | Description |
---|---|---|---|---|---|
0 common_header |
0x0000 | 16 bytes (0x10) | magic | PSTITLEIMG000000 | |
0x0010 | 496 bytes (0x1F0) | padding | |||
0x0200 | 100 bytes (0x64) | 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 | |
0x0264 | 16 bytes (0x10) | game_id | _SLES_12345 | common identifyer for all discs | |
0x0274 | 396 bytes (0x18C) | padding |
iso.bin Disc map
64 clusters, 1024 blocks, 10485576 bytes (0x100000)
This structure is repeated one time for every disc of the game all them joined together consecutively, 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 | 0x0400 | 16 bytes (0x10) | magic | PSISOIMG0000 | In "PSP Minis" It's NPUMDIMG (NP UMD Image) ..... probably another for "ps2 classics" (speculation) |
0x0410 | 1008 bytes (0x3F0) | padding | ||||
2 | 0x0800 | 16 bytes (0x10) | disc_id | _SLES_12345 | in games with several discs each disc has a different id | |
0x0810 | 1008 bytes (0x3F0) | padding | ||||
3 | 0x0C00 | 1020 bytes (0x3FС) | disc_TOC | variable | Table of content, like CUE sheet, supports upto 99 tracks(102entries total) | |
4 | 0x1000 | 1024 bytes (0x400) | reserved ? | Optionally used to store big TOC's ? | ||
5 | 0x1400 | 724 bytes (0x2D4) | unknwon | |||
0x16D4 | 2 bytes (0x02) | block size ? | 1024 | <--- this is wrong, but matches for the first disc | ||
0x16D6 | 2 bytes (0x02) | number of clusters | 64 | its always 64 clusters (so seems to be right) | ||
0x16D8 | 2 bytes (0x02) | number of blocks ? | 1024 | <--- this is wrong, but matches for the first disc | ||
0x16DA | 294 bytes (0x126) | padding | ||||
6 | 0x1800 | 1024 bytes (0x400) | not used | |||
7 | 0x1C00 | 1024 bytes (0x400) | not used | |||
8 | 0x2000 | 1024 bytes (0x400) | not used | |||
9 | 0x2400 | 1024 bytes (0x400) | not used | |||
10 | 0x2800 | 1024 bytes (0x400) | not used | |||
11 | 0x2C00 | 1024 bytes (0x400) | not used | |||
12 | 0x3000 | 1024 bytes (0x400) | not used | |||
13 | 0x3400 | 1024 bytes (0x400) | not used | |||
14 | 0x3800 | 1024 bytes (0x400) | not used | |||
15 | 0x3C00 | 1024 bytes (0x400) | not used | |||
16 | 0x4000 | 16 bytes (0x10) | checksum | 1CCE0033 60C6E8A6 B36A972D 00EAFDBF | seems to be the checksum of this block, and because this block is always unused... this checksum is always the same | |
0x4010 | 1008 bytes (0x3F0) | padding | ||||
1 Disc map table |
17 | 0x4400 | variable | Disc map table | divided in chunks of 32 bytes. See table below | |
Up to 32 | ||||||
Up to 64 Disc map table |
iso.bin Disc map table
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
Entry Nº | Offset | Length | Name | Example | Notes |
---|---|---|---|---|---|
1 | 0x00 | 4 bytes (0x04) | file_offset | 0 | file offset from start of .iso root (for the first entry is always 0) |
0x04 | 2 bytes (0x02) | file_size | variable | this size determines the displacement of the next file (in the next entry) | |
0x06 | 2 bytes (0x02) | file_type ? | 01 00 | usually 1... and 0 for the last entry | |
0x08 | 16 bytes (0x10) | file_checksum ? | variable | unknown | |
0x18 | 8 bytes (0x08) | padding | |||
Up to 32256 | same structure than the previous entry |
iso.bin Common Disc table
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 | 4 bytes (0x04) | file_offset ? | 0 | always increases |
0x04 | 2 bytes (0x02) | file_type ? | 01 01 | always 01 01 | |
0x06 | 3 bytes (0x03) | counter 1 | some kind of counter, in decimal, always increases <-------- related with "sectors" inside the .iso ? | ||
0x09 | 3 bytes (0x03) | 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) |
There are 2 "special" entries to mark the "start of a disc" (FFFFFFFF 00000000 FFFFFFFF), and the "end of a disc" (FFFFFFFF FFFFFFFF FFFFFFFF). Between the start and the end, there are a variable number of entries.
There is also an added string at the end of the last disc (after the last FFFFFFFF FFFFFFFF FFFFFFFF entry)... is a 40 bytes unknown area (in my example my game had 4 discs so maybe this area is divided in chunks of 10 bytes for each disc)
So as an example... for a game with 4 discs this table is:
- first entry of disc 1 ---> FFFFFFFF 00000000 FFFFFFFF (start of disc 1)
- next entries of disc 1 --> data from disc.... the number is variable
- last entry of disc 1 ---> FFFFFFFF FFFFFFFF FFFFFFFF (end of disc 1)
- first entry of disc 2 ---> FFFFFFFF 00000000 FFFFFFFF (start of disc 2)
- next entries of disc 2 --> data from disc.... the number is variable
- last entry of disc 2 ---> FFFFFFFF FFFFFFFF FFFFFFFF (end of disc 2)
- first entry of disc 3 ---> FFFFFFFF 00000000 FFFFFFFF (start of disc 3)
- next entries of disc 3 --> data from disc.... the number is variable
- last entry of disc 3 ---> FFFFFFFF FFFFFFFF FFFFFFFF (end of disc 3)
- first entry of disc 4 ---> FFFFFFFF 00000000 FFFFFFFF (start of disc 4)
- next entries of disc 4 --> data from disc.... the number is variable
- last entry of disc 4 ---> FFFFFFFF FFFFFFFF FFFFFFFF (end of disc 4)
- unknown area of 40 bytes (10 bytes for each disc ?)
disc_TOC
Entry Nº | Offset | Length | Name | Example | Notes |
---|---|---|---|---|---|
1 | 0x00 | 1 byte (0x01) | TYPE | 41 / 01 | |
0x01 | 1 byte (0x01) | TNO | 00 | always zero | |
0x02 | 1 byte (0x01) | POINT | A0/A1/A2/01/02/03/etc | increases | |
0x03 | 1 byte (0x01) | MIN | varies | decimal | |
0x04 | 1 byte (0x01) | SEC | varies | decimal | |
0x05 | 1 byte (0x01) | FRAME | varies | decimal | |
0x06 | 1 byte (0x01) | ZERO | 00 | always zero | |
0x07 | 1 byte (0x01) | PMIN | varies | decimal | |
0x08 | 1 byte (0x01) | PSEC | varies | decimal | |
0x09 | 1 byte (0x01) | PFRAME | varies | decimal |
u8 TYPE u8 TNO u8 POINT u8 MIN u8 SEC u8 FRAME u8 ZERO u8 PMIN u8 PSEC u8 PFRAME
Minis ISO.BIN structure
Header
Name | Offset | Size | Example | Remark |
---|---|---|---|---|
Magic! | 0x0 | 0x8 | NPUMDIMG | |
unk1 | 0x8 | 0x4 | N.A | (be) |
Block Size | 0xC | 0x4 | N.A | (be) |
ContentID | 0x10 | 0x24 | UP4123-NPUZ00119_00-ANGRYBIRDSGAME01 | |
Padding1 | 0x34 | 0xC | ({0x0}filled) | |
Common1 | 0x40 | 0x4 | 0x00 0x08 0x00 0xE0 | |
Padding2 | 0x44 | 0x4 | ({0x0}filled) | |
unk2 | 0x48 | 0x4 | N.A | (be) |
Padding3 | 0x4c | 0x8 | ({0x0}filled) | |
LBA Start | 0x54 | 0x4 | N.A | (be) |
Padding4 | 0x58 | 0x4 | ({0x0}filled) | |
unk3 | 0x5C | 0x4 | N.A | (be) |
Padding5 | 0x60 | 0x4 | ({0x0}filled) | |
LBA End | 0x64 | 0x4 | N.A | (be) |
unk4 | 0x68 | 0x4 | N.A | (be) |
Np_Table Offset | 0x6C | 0x4 | N.A | (be) |
GameID | 0x70 | 0xA | NPUZ-00119 | |
Common2 | 0x7A | 0x26 | N.A | |
Header Key | 0xA0 | 0x10 | N.A. | |
Padding6 | 0xB0 | 0x50 | N.A({0x0} filled) |
Iso Block Table (1st decrypted but compressed block)
Name | Offset | Size | Example | Remark |
---|---|---|---|---|
Block MAC | 0x100 | 0x10 | N.A | |
Block Offset | 0x110 | 0x4 | N.A | (be) |
Block Size | 0x114 | 0x4 | N.A | (be) |
Padding | 0x118 | 0x8 | 00000000 |
Until X blocks where X is the block number
Minis MINIS.BIN structure
Header
Name | Offset | Size | Example | Remark |
---|---|---|---|---|
Magic! | 0x0 | 0x8 | NPUMDIMG | |
unk1(be) | 0x8 | 0x4 | N.A | |
Block Size(be) | 0xC | 0x4 | N.A | |
ContentID | 0x10 | 0x24 | UP4123-NPUZ00119_00-ANGRYBIRDSGAME01 | |
Padding | 0x34 | 0x8 | ({0x0} filled) | |
Encrypted Version Key | 0x40 | 0x10 | N.A | AES-CBC Encrypted |
Notes
- You can decrypt any eboot.pbp from a mini OR pspremaster OR psn paid eboot(?) with npdpc
- You can use any header on an iso.bin, and the ps3 won't even try to check it
- (be) means that the generated table values will have to be endian swapped when using npdpc (now possible thanks to arnold)
- [arnold's code]
- [kirk lib]
Decrypting owned ISO.BIN.EDATs and MINIS.EDATs
These examples work with every EDAT type.
Decrypting with SCE SDK
#define PSP_EMULATOR_KLIC {{0x2A, 0x6A, 0xFB, 0xCF, 0x43, 0xD1, 0x57, 0x9F, 0x7D, 0x73, 0x87, 0x41, 0xA1, 0x3B, 0xD4, 0x2E}} #define BUF_SIZE (16*1024) #define NP_POOL_SIZE (128*1024) #include <np.h> #include <np/drm.h> #include <stdio.h> #include <cell/cell_fs.h> #include <cell/sysmodule.h> int main () { uint8_t np_pool[NP_POOL_SIZE]; uint8_t read_buf[BUF_SIZE]; int ret; int fd1,fd2; uint64_t file_size; uint64_t sw; char *edata_file,*raw_file; //raw_file will be created if it does not exist SceNpDrmKey k_licensee = PSP_EMULATOR_KLIC; ret = cellSysmoduleLoadModule(CELL_SYSMODULE_FS); ret = cellSysmoduleLoadModule(CELL_SYSMODULE_SYSUTIL_NP); printf("sceNpInit()\n"); ret = sceNpInit(NP_POOL_SIZE, np_pool); printf(" Open '%s' as NPDRM file\n", edata_file); ret = sceNpDrmIsAvailable2(&k_licensee, edata_file); if (ret != CELL_OK) { printf("EDAT not activated\n"); return ret; } SceNpDrmOpenArg arg; arg.flag = SCE_NP_DRM_OPEN_FLAG; ret = cellFsOpen(edata_file, CELL_FS_O_RDONLY, &fd1, &arg, sizeof(arg)); if (ret != CELL_FS_OK) { printf("Error opening for reading\n"); return ret; } printf("Opening file to dump to '%s'\n", raw_file); ret = cellFsOpen(raw_file, CELL_FS_O_RDWR|CELL_FS_O_CREAT, &fd2, NULL, 0); if (ret != CELL_FS_OK) { printf("Error opening file\n"); cellFsClose(fd2); return ret; } printf("\n[ dump edata ]\n"); for (uint64_t r = 0; r < file_size; r += BUF_SIZE) { uint64_t rsize; uint64_t remain = file_size - r; if (remain > BUF_SIZE) { remain = BUF_SIZE; } ret = cellFsRead(fd1, read_buf, remain, &rsize); if (ret != CELL_OK || rsize != remain) { printf("Read error ('%s'): ret = 0x%08x, size = %llx, %llx\n", edata_file, ret, remain, rsize); if (ret == CELL_OK) { ret = -1; } cellFsClose(fd1); cellFsClose(fd2); return ret; } printf("dump data: (0x%08llx - 0x%08llx) ", r, r + remain); ret = cellFsWrite(fd2, (const void *)read_buf, (size_t)remain, &sw); if (ret != CELL_FS_OK) { cellFsClose(fd1); cellFsClose(fd2); printf("ERROR\n"); return -1; } printf("OK\n"); } /* file close */ ret = cellFsClose(fd1); ret = cellFsClose(fd2); ret = sceNpTerm(); ret = cellSysmoduleUnloadModule(CELL_SYSMODULE_SYSUTIL_NP); ret = cellSysmoduleUnloadModule(CELL_SYSMODULE_FS); return ret; }
Decrypting with PSL1GHT
- https://github.com/euss/psp_edat_decryptor (not my code, just git'ed it for convenience)
Decrypted Content
Please help with your own uploads to better understand the structure.
Links to Samples of Decrypted ISO.BIN.EDATs
Angry Birds(USA) NPUZ00119 http://www.multiupload.nl/UM81ZBTR8E Angry Birds(EUR) NPEZ00232 http://www.multiupload.nl/D1HUZ7SWDT 4x4 Jam(EUR) NPEZ00205 http://www.multiupload.nl/02QCPA3O7E Arcade Essentials NPEZ00204(EUR) http://www.multiupload.nl/OMW6QFBQCY Brick Breaker(EUR) NPEZ00168 http://www.multiupload.nl/CWKCVYPSWV Golf Mania(EUR) NPEZ00424 http://www.multiupload.nl/DQN196Z5CK Zenonia(EUR) NPEZ00250 http://www.multiupload.nl/DHO3Z4E1MG Abe's Oddysee(EUR) SLES00664 http://www.multiupload.nl/KCGKIBQTAR Final Fantasy VII SCES00867(EUR) http://www.multiupload.nl/WBWFB2B8ZX Final Fantasy VIII SLES02080(EUR) http://www.multiupload.nl/JT8IVA1ZQH
Links to Samples of Decrypted MINIS.EDATs
4x4 Jam(EUR) NPEZ00205 http://www.multiupload.nl/R62SRQO1MX Angry Birds(USA) NPUZ00119 http://www.multiupload.nl/6PJP0E6JHH Angry Birds(EUR) NPEZ00232 http://www.multiupload.nl/EAGC8J7OEW Arcade Essentials NPEZ00204(EUR) http://www.multiupload.nl/2NHPQFDF8O Brick Breaker(EUR) NPEZ00168 http://www.multiupload.nl/Q3Y87ZT3GH Golf Mania(EUR) NPEZ00424 http://www.multiupload.nl/6960196VTY Zenonia(EUR) NPEZ00250 http://www.multiupload.nl/HQEIXG8MGO
Samples of Decrypted MINIS2.EDATs
Monster Hunter Portable 3rd HD Remaster
VERSION = 0xFFFFFFFF S3D.ENABLE = 2 SDRAM_SIZE = 02800000 MIPS_CODE_BLOCK_SIZE = 8192
K-ON Houkago Live HD Ver
VERSION = 0xFFFFFFFF AW.EXT_MODE = 3 AW.EXT_CMD = 2 SDRAM_SIZE = 02800000 ADDITIONAL_KEY_ASSIGN = 8000000000000000 S3D.ENABLE = 1 ADHOC.EMUPA_TITLE_ID = ULJM05709
Shin Sangoku Musou Multi Raid 2 HD Ver
VERSION = 0xFFFFFFFF AW.EXT_MODE = 3 AW.EXT_CMD = 2 SDRAM_SIZE = 02800000 ADDITIONAL_KEY_ASSIGN = 0000000047C6C544 S3D.ENABLE = 1 ADHOC.EMUPA_TITLE_ID = ULJM05637 AW.VRAM_MODE = 1 SAVEDATA_LOAD_CACHE_TARGET_NAME = ULJM05637DQUEST
Eiyuu Densetsu: Sora no Kiseki FC Kai HD Edition
VERSION = 0xFFFFFFFF SDRAM_SIZE = 03000000 ADDITIONAL_KEY_ASSIGN = 0000000047C6C544 S3D.ENABLE = 1 AW.EXT_MODE = 3 AW.EXT_CMD = 3 ADHOC_PARTY = 0 VSYNC_OFFSET_US = 2000
Eiyuu Densetsu: Sora no Kiseki SC Kai HD Edition
VERSION = 0xFFFFFFFF SDRAM_SIZE = 04000000 CODE_SIZE_LIMIT = 00800000 ADDITIONAL_KEY_ASSIGN = 8000000000000000 S3D.ENABLE = 2 AW.EXT_MODE = 3 AW.EXT_CMD = 3 ADHOC_PARTY = 0 VSYNC_OFFSET_US = 2000
About PS2 Classics
There are some new formats present in PS2 Classics. The first one is ISO.BIN.ENC, the second one is .dxt, which is inside CONTENT folder and there's also a single file named CONFIG. You can see more about this when you first install a PS2 Classic. There's also a problem with the Data while trying to execute the instalable file. The message Unsupported Data appears on the screen when highliting the file and the error 80028F14 is shown while trying to start.
This was made with the Max Payne game. There could probably be other formats present aswell
ISO.BIN.EDAT
For PSN PS2-Classics Games ISO.BIN.EDAT only contains the Title Id of the disc.
Example:
SLES-12345
|