This is some code that will change the endianness of certain entries within the header and ISO block table of PS3 minis.
I wrote this with very short notice and very quickly. There may be silly mistakes and stuff that just doesn't make sense. With that data that I was provided, the app works fine.
If this ends up being of no use, I don't mind. It's not particularly fascinating anyway.
Hello to all PSP Devs, PS3 Devs and zecoxao.
Tested under gcc i686-apple-darwin11
http://pb.arnoldbronson.comli.com/index.php?show=91
Code: Select all
#include <stdlib.h>
#include <stdio.h>
#include <memory.h>
/*
* PS3 Minis Header Endian Swapping Sample 0.0.1
* by arnold, zecoxao Tues 2 April 2013
*
*/
typedef char s8;
typedef unsigned char u8;
typedef unsigned int u32;
//Endian swap for u32.
#define _ES32(val) \
((u32)(((((u32)val) & 0xff000000) >> 24) | \
((((u32)val) & 0x00ff0000) >> 8 ) | \
((((u32)val) & 0x0000ff00) << 8 ) | \
((((u32)val) & 0x000000ff) << 24)))
typedef struct MINIS_ISO_BIN_HEADER {
u32 magic1; // 0x0 - NPUMDIMG
u32 magic2; // 0x4
u32 unk1; // 0x8
u32 block_size; // 0xC
u8 content_id[0x24]; // 0x10 e.g. UP4123-NPUZ00119_00-ANGRYBIRDSGAME01
u8 junk0[0x14]; // 0x34
u32 unk2; // 0x48
u32 junk1[2]; // 0x4C
u32 lba_start; // 0x54
u32 junk2; // 0x58
u32 unk3; // 0x5C
u32 junk3; // 0x60
u32 lba_end; // 0x64
u32 unk4; // 0x68
u32 np_table_addr; // 0x6C
u8 game_id[10]; // 0x70 - e.g. NPUZ-00119
u8 junk4[0x26]; // 0x7A
u8 header_key[0x10]; // 0xA0
u8 junk5[0x50]; // 0xB0
}MINIS_ISO_BIN_HEADER;
//0x100 -
typedef struct MINIS_ISO_BIN_BLOCK_TABLE_ENTRY
{
u8 block_mac[0x10]; // 0x00
u32 block_offset; // 0x10
u32 block_size; // 0x14
u8 padding[8]; // 0x18
}MINIS_ISO_BIN_BLOCK_TABLE_ENTRY;
int ReadFile(char *file, int seek, void *buf, int size);
int WriteFile(char *file, void *buf, int size);
int ProcessHeader(char* inFile, char* outFile);
u32 GetNumberOfBlocks(char* inFile);
int ProcessIsoTable(char* inFile, char* outFile, int blockCount);
int main(int args, char* argp[])
{
if (args < 6)
{
printf("Usage: <toolname> <header_in.bin> <header_out.bin> <isotable_in.bin> <isotable_out.bin> <final_out.bin>\n");
return -1;
}
printf("PS3 Minis Header Endian Swapping Sample 0.0.1\n");
printf("by arnold with info from zecoxao\nBuilt %s\n\n", __DATE__);
if (ProcessHeader(argp[1], argp[2]) < 0)
{
printf("Error Processing Header\n");
return -2;
}
int blocks = GetNumberOfBlocks(argp[1]);
//printf("%d\n", blocks);
if (ProcessIsoTable(argp[3], argp[4], blocks) < 0)
{
printf("Error Processing ISO Table\n");
return -3;
}
printf("Writing final result to %s\n", argp[5]);
char* finalBuffer = malloc(sizeof(MINIS_ISO_BIN_HEADER) + blocks * sizeof(MINIS_ISO_BIN_BLOCK_TABLE_ENTRY));
ReadFile(argp[2], 0, finalBuffer, sizeof(MINIS_ISO_BIN_HEADER));
ReadFile(argp[4], 0, finalBuffer + sizeof(MINIS_ISO_BIN_HEADER), blocks * sizeof(MINIS_ISO_BIN_BLOCK_TABLE_ENTRY));
WriteFile(argp[5], finalBuffer, sizeof(MINIS_ISO_BIN_HEADER) + blocks * sizeof(MINIS_ISO_BIN_BLOCK_TABLE_ENTRY));
free(finalBuffer);
return 0;
}
int ReadFile(char *file, int seek, void *buf, int size)
{
long fileSize = -1;
size_t res = -1;
FILE* fd = fopen(file, "rb");
if (fd == NULL)
{
printf("ReadFile: Error, File cannot be opened\n");
return -2;
}
// Get file size
fseek(fd, 0, SEEK_END);
fileSize = ftell(fd);
rewind(fd);
res = fread (buf, 1, size, fd);
fclose (fd);
return res;
}
int WriteFile(char *file, void *buf, int size)
{
FILE* fd = fopen(file, "wb");
if (fd < 0)
{
return -1; //fd;
}
int written = fwrite(buf, 1, size, fd);
fclose(fd);
return written;
}
int ProcessHeader(char* inFile, char* outFile)
{
printf("Processing Header...\n");
u8* headerBuffer = malloc(1024);
memset(headerBuffer, 0, 1024);
printf("Input: %s \nOutput: %s\n", inFile, outFile);
// Read the header to memory
ReadFile(inFile, 0, headerBuffer, 256);
MINIS_ISO_BIN_HEADER* minisHeader = (MINIS_ISO_BIN_HEADER*)headerBuffer;
// Check MAGIC
if (minisHeader->magic1 != 0x4D55504E &&
minisHeader->magic2 != 0x474D4944)
{
printf("Not a valid header input\n");
return -1;
}
// Swap the required header entries
printf("Swapping required header entries\n");
minisHeader->unk1 = _ES32(minisHeader->unk1);
minisHeader->block_size = _ES32(minisHeader->block_size);
minisHeader->unk2 = _ES32(minisHeader->unk2);
minisHeader->lba_start = _ES32(minisHeader->lba_start);
minisHeader->unk3 = _ES32(minisHeader->unk3);
minisHeader->lba_end = _ES32(minisHeader->lba_end);
minisHeader->unk4 = _ES32(minisHeader->unk4);
minisHeader->np_table_addr = _ES32(minisHeader->np_table_addr);
// Write the file to disk
printf("Writing new header to disk\n");
WriteFile(outFile, headerBuffer, 256);
printf("Done Processing Header.\n");
free(headerBuffer);
return 0;
}
u32 GetNumberOfBlocks(char* inFile)
{
u32 blockCount = 0;
/*
LBA start (np_header+0x54)
LBA end (np_header+0x64)
block_size (np_header+0x0c)
lba_size (end-start+1)
total_blocks (lba_size+block_size-1)/block_size
*/
printf("Getting Header Data for Block Count...\n");
u8* headerBuffer = malloc(1024);
memset(headerBuffer, 0, 1024);
printf("Input: %s\n", inFile);
// Read the header to memory
ReadFile(inFile, 0, headerBuffer, 256);
MINIS_ISO_BIN_HEADER* minisHeader = (MINIS_ISO_BIN_HEADER*)headerBuffer;
// Check MAGIC
if (minisHeader->magic1 != 0x4D55504E &&
minisHeader->magic2 != 0x474D4944)
{
printf("Not a valid header input\n");
return -1;
}
u32 lba_start = minisHeader->lba_start;
u32 lba_end = minisHeader->lba_end;
u32 block_size = minisHeader->block_size;
u32 lba_size = lba_end - lba_start + 1;
blockCount = (lba_size + block_size - 1)/block_size;
printf("blockCount: %d = (%d + %d - 1)/%d\n", blockCount, lba_size, block_size, block_size);
free(headerBuffer);
return blockCount;
}
int ProcessIsoTable(char* inFile, char* outFile, int blockCount)
{
printf("Processing ISO table...\n");
u8* dataBuffer = malloc(blockCount * sizeof(MINIS_ISO_BIN_BLOCK_TABLE_ENTRY));
MINIS_ISO_BIN_BLOCK_TABLE_ENTRY* block_table = (MINIS_ISO_BIN_BLOCK_TABLE_ENTRY*)dataBuffer;
memset(dataBuffer, 0, blockCount * sizeof(MINIS_ISO_BIN_BLOCK_TABLE_ENTRY));
printf("Input: %s \nOutput: %s\n", inFile, outFile);
// Read the header to memory
ReadFile(inFile, 0, dataBuffer, blockCount * sizeof(MINIS_ISO_BIN_BLOCK_TABLE_ENTRY));
printf("Total blocks to swap: %d\n", blockCount);
int i = 0;
for (i = 0; i < blockCount; i++)
{
block_table[i].block_offset = _ES32(block_table[i].block_offset);
block_table[i].block_size = _ES32(block_table[i].block_size);
}
printf("Swapped data in %d entries in ISO table\n", i);
// Write the file to disk
printf("Writing new ISO table to disk\n");
WriteFile(outFile, block_table, blockCount * sizeof(MINIS_ISO_BIN_BLOCK_TABLE_ENTRY));
printf("Done Processing ISO Table.\n");
free(block_table);
return 0;
}
Advertising