Last active
August 29, 2015 14:02
-
-
Save codestation/bf1cc67ddf7c490c9626 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#define _GNU_SOURCE 1 | |
#include <assert.h> | |
#include <fcntl.h> | |
#include <inttypes.h> | |
#include <malloc.h> | |
#include <stdio.h> | |
#include <string.h> | |
#include <sys/stat.h> | |
#include <time.h> | |
#include <unistd.h> | |
#include <lz4.h> | |
#include <openssl/md5.h> | |
#include <zlib.h> | |
// PSP compat layer | |
#define u8 uint8_t | |
#define u16 uint16_t | |
#define u32 uint32_t | |
#define u64 uint64_t | |
#define SceOff int64_t | |
#define SceUID int | |
#define PSP_SEEK_SET SEEK_SET | |
#define PSP_SEEK_CUR SEEK_CUR | |
#define PSP_SEEK_END SEEK_END | |
#define sceIoOpen(a,b,c) open(a,O_RDONLY,S_IRUSR) | |
#define sceIoLseek lseek | |
#define sceIoRead read | |
#define sceIoClose close | |
#define printk printf | |
#define sceKernelDelayThread(delay) usleep(delay) | |
#define oe_malloc malloc | |
// from misc headers | |
#define ISO_SECTOR_SIZE 2048 | |
#define CISO_IDX_BUFFER_SIZE 0x200 | |
#define CISO_DEC_BUFFER_SIZE 0x2000 | |
#define MIN(a, b) (((a) < (b)) ? (a) : (b)) | |
#define MAX(a, b) (((a) > (b)) ? (a) : (b)) | |
#define NELEMS(a) (sizeof(a) / sizeof(a[0])) | |
// from ISODrivers/Inferno/isoread.c | |
#define CISO_IDX_MAX_ENTRIES 4096 | |
#define REMAINDER(a,b) ((a) % (b)) | |
#define IS_DIVISIBLE(a,b) (REMAINDER(a,b) == 0) | |
#define GET_CSO_OFFSET(block) ((g_cso_idx_cache[block] & 0x7FFFFFFF) << g_CISO_hdr.align) | |
// 0x00002484 | |
void *g_sector_buf = NULL; | |
// 0x0000248C | |
int g_iso_opened = 0; | |
// 0x000023D0 | |
SceUID g_iso_fd = -1; | |
// 0x000023D4 | |
int g_total_sectors = -1; | |
// 0x00002488 | |
static int g_is_ciso = 0; | |
// 0x000024C0 | |
static void *g_ciso_block_buf = NULL; | |
// 0x000024C4, size CISO_DEC_BUFFER_SIZE + (1 << g_CISO_hdr.align), align 64 | |
static void *g_ciso_dec_buf = NULL; | |
// 0x00002704 | |
static int g_CISO_cur_idx = 0; | |
// 0x00002700 | |
static u32 g_ciso_dec_buf_offset = (u32)-1; | |
static int g_ciso_dec_buf_size = 0; | |
// 0x00002720 | |
static u32 g_ciso_total_block = 0; | |
static int lz4_compressed = 0; | |
struct CISO_header { | |
u8 magic[4]; // 0 | |
u32 header_size; // 4 | |
u64 total_bytes; // 8 | |
u32 block_size; // 16 | |
u8 ver; // 20 | |
u8 align; // 21 | |
u8 rsv_06[2]; // 22 | |
}; | |
// 0x00002708 | |
struct CISO_header g_CISO_hdr __attribute__((aligned(64))); | |
u32 g_CISO_idx_cache[CISO_IDX_BUFFER_SIZE / 4] __attribute__((aligned(64))); | |
u32 *g_cso_idx_cache = NULL; | |
u32 g_cso_idx_start_block = -1; | |
// variables for the simulation | |
static z_stream z; | |
static char *g_iso_fn = NULL; | |
u32 *g_cso_idx_cache_orig = NULL; | |
void *g_ciso_block_buf_orig = NULL; | |
void *g_ciso_dec_buf_orig = NULL; | |
// simulate psp decompress function | |
int sceKernelDeflateDecompress(u8 *dest, u32 destSize, u8 *src, u32 unknown) | |
{ | |
int ret = inflateInit2(&z, -15); | |
z.avail_in = 2048; | |
z.next_out = dest; | |
z.avail_out = destSize; | |
z.next_in = src; | |
ret = inflate(&z, Z_FULL_FLUSH); | |
inflateEnd(&z); | |
if (ret != Z_STREAM_END) { | |
return -1; | |
} else { | |
return destSize; | |
} | |
} | |
void wait_until_ms0_ready() | |
{ | |
// not used in simulation, lets init zlib here | |
z.zalloc = Z_NULL; | |
z.zfree = Z_NULL; | |
z.opaque = Z_NULL; | |
} | |
// 0x00000EE4 | |
static int ciso_get_nsector(SceUID fd) | |
{ | |
// return g_CISO_hdr.total_bytes / g_CISO_hdr.block_size;; | |
return g_ciso_total_block; | |
} | |
// 0x00000E58 | |
static int iso_get_nsector(SceUID fd) | |
{ | |
SceOff off, total; | |
off = sceIoLseek(fd, 0, PSP_SEEK_CUR); | |
total = sceIoLseek(fd, 0, PSP_SEEK_END); | |
sceIoLseek(fd, off, PSP_SEEK_SET); | |
return total / ISO_SECTOR_SIZE; | |
} | |
// 0x00000E58 | |
static int get_nsector(void) | |
{ | |
if(g_is_ciso) { | |
return ciso_get_nsector(g_iso_fd); | |
} | |
return iso_get_nsector(g_iso_fd); | |
} | |
// 0x00000F00 | |
static int is_ciso(SceUID fd) | |
{ | |
int ret; | |
u32 *magic; | |
g_CISO_hdr.magic[0] = '\0'; | |
g_ciso_dec_buf_offset = (u32)-1; | |
g_ciso_dec_buf_size = 0; | |
sceIoLseek(fd, 0, PSP_SEEK_SET); | |
ret = sceIoRead(fd, &g_CISO_hdr, sizeof(g_CISO_hdr)); | |
if(ret != sizeof(g_CISO_hdr)) { | |
ret = -1; | |
printk("%s: -> %d\n", __func__, ret); | |
goto exit; | |
} | |
magic = (u32*)g_CISO_hdr.magic; | |
if(*magic == 0x4F534943 || *magic == 0x4F53495A) { // CISO or ZISO | |
lz4_compressed = (*magic == 0x4F53495A) ? 1 : 0; | |
g_CISO_cur_idx = -1; | |
g_ciso_total_block = g_CISO_hdr.total_bytes / g_CISO_hdr.block_size; | |
printk("%s: total block %d\n", __func__, (int)g_ciso_total_block); | |
if(g_ciso_dec_buf == NULL) { | |
g_ciso_dec_buf = oe_malloc(CISO_DEC_BUFFER_SIZE + (1 << g_CISO_hdr.align) + 64); | |
if(g_ciso_dec_buf == NULL) { | |
ret = -2; | |
printk("%s: -> %d\n", __func__, ret); | |
goto exit; | |
} | |
g_ciso_dec_buf_orig = g_ciso_dec_buf; | |
if((uintptr_t)g_ciso_dec_buf & 63) | |
g_ciso_dec_buf = (void*)(((uintptr_t)g_ciso_dec_buf & (~63)) + 64); | |
} | |
if(g_ciso_block_buf == NULL) { | |
g_ciso_block_buf = oe_malloc(ISO_SECTOR_SIZE + 64); | |
if(g_ciso_block_buf == NULL) { | |
ret = -3; | |
printk("%s: -> %d\n", __func__, ret); | |
goto exit; | |
} | |
g_ciso_block_buf_orig = g_ciso_block_buf; | |
if((uintptr_t)g_ciso_block_buf & 63) | |
g_ciso_block_buf = (void*)(((uintptr_t)g_ciso_block_buf & (~63)) + 64); | |
} | |
if(g_cso_idx_cache == NULL) { | |
g_cso_idx_cache = oe_malloc(CISO_IDX_MAX_ENTRIES * 4 + 64); | |
if(g_cso_idx_cache == NULL) { | |
ret = -3; | |
printk("%s: -> %d\n", __func__, ret); | |
goto exit; | |
} | |
g_cso_idx_cache_orig = g_cso_idx_cache; | |
if((uintptr_t)g_cso_idx_cache & 63) | |
g_cso_idx_cache = (void*)(((uintptr_t)g_cso_idx_cache & (~63)) + 64); | |
} | |
ret = 0; | |
} else { | |
ret = 0x8002012F; | |
} | |
exit: | |
return ret; | |
} | |
// 0x000009D4 | |
int iso_open(void) | |
{ | |
int ret, retries; | |
wait_until_ms0_ready(); | |
if(g_iso_fd >= 0) | |
sceIoClose(g_iso_fd); | |
g_iso_opened = 0; | |
retries = 0; | |
do { | |
g_iso_fd = sceIoOpen(g_iso_fn, 0x000F0001, 0777); | |
if(g_iso_fd < 0) { | |
if(++retries >= 16) { | |
return -1; | |
} | |
sceKernelDelayThread(20000); | |
} | |
} while(g_iso_fd < 0); | |
if(g_iso_fd < 0) { | |
return -1; | |
} | |
g_is_ciso = 0; | |
ret = is_ciso(g_iso_fd); | |
if(ret >= 0) { | |
g_is_ciso = 1; | |
} | |
g_iso_opened = 1; | |
g_total_sectors = get_nsector(); | |
return 0; | |
} | |
// 0x00000BB4 | |
static int read_raw_data(u8* addr, u32 size, u32 offset) | |
{ | |
int ret, i; | |
SceOff ofs; | |
i = 0; | |
do { | |
i++; | |
ofs = sceIoLseek(g_iso_fd, offset, PSP_SEEK_SET); | |
if(ofs >= 0) { | |
i = 0; | |
break; | |
} else { | |
printk("%s: lseek retry %d error 0x%08X\n", __func__, i, (int)ofs); | |
iso_open(); | |
} | |
} while(i < 16); | |
if(i == 16) { | |
ret = 0x80010013; | |
goto exit; | |
} | |
for(i=0; i<16; ++i) { | |
ret = sceIoRead(g_iso_fd, addr, size); | |
if(ret >= 0) { | |
i = 0; | |
break; | |
} else { | |
printk("%s: read retry %d error 0x%08X\n", __func__, i, ret); | |
iso_open(); | |
} | |
} | |
if(i == 16) { | |
ret = 0x80010013; | |
goto exit; | |
} | |
exit: | |
return ret; | |
} | |
// 0x00001018 | |
static int read_cso_sector(u8 *addr, int sector) | |
{ | |
int ret; | |
int n_sector; | |
u32 offset, next_offset; | |
int size; | |
n_sector = sector - g_CISO_cur_idx; | |
// not within sector idx cache? | |
if(g_CISO_cur_idx == -1 || n_sector < 0 || n_sector >= NELEMS(g_CISO_idx_cache)) { | |
ret = read_raw_data((u8*)g_CISO_idx_cache, sizeof(g_CISO_idx_cache), (sector << 2) + sizeof(struct CISO_header)); | |
if(ret < 0) { | |
ret = -4; | |
printk("%s: -> %d\n", __func__, ret); | |
return ret; | |
} | |
g_CISO_cur_idx = sector; | |
n_sector = 0; | |
} | |
offset = (g_CISO_idx_cache[n_sector] & 0x7FFFFFFF) << g_CISO_hdr.align; | |
// is plain? | |
if(g_CISO_idx_cache[n_sector] & 0x80000000) { | |
return read_raw_data(addr, ISO_SECTOR_SIZE, offset); | |
} | |
sector++; | |
n_sector = sector - g_CISO_cur_idx; | |
if(g_CISO_cur_idx == -1 || n_sector < 0 || n_sector >= NELEMS(g_CISO_idx_cache)) { | |
ret = read_raw_data((u8*)g_CISO_idx_cache, sizeof(g_CISO_idx_cache), (sector << 2) + sizeof(struct CISO_header)); | |
if(ret < 0) { | |
ret = -5; | |
printk("%s: -> %d\n", __func__, ret); | |
return ret; | |
} | |
g_CISO_cur_idx = sector; | |
n_sector = 0; | |
} | |
next_offset = (g_CISO_idx_cache[n_sector] & 0x7FFFFFFF) << g_CISO_hdr.align; | |
size = next_offset - offset; | |
if(g_CISO_hdr.align) | |
size += 1 << g_CISO_hdr.align; | |
if(size <= ISO_SECTOR_SIZE) | |
size = ISO_SECTOR_SIZE; | |
if(g_ciso_dec_buf_offset == (u32)-1 || offset < g_ciso_dec_buf_offset || offset + size >= g_ciso_dec_buf_offset + g_ciso_dec_buf_size) { | |
ret = read_raw_data(g_ciso_dec_buf, size, offset); | |
/* May not reach CISO_DEC_BUFFER_SIZE */ | |
if(ret < 0) { | |
g_ciso_dec_buf_offset = (u32)-1; | |
ret = -6; | |
printk("%s: -> %d\n", __func__, ret); | |
return ret; | |
} | |
g_ciso_dec_buf_offset = offset; | |
g_ciso_dec_buf_size = ret; | |
} | |
if(!lz4_compressed) { | |
ret = sceKernelDeflateDecompress(addr, ISO_SECTOR_SIZE, g_ciso_dec_buf + offset - g_ciso_dec_buf_offset, 0); | |
} else { | |
ret = LZ4_decompress_fast(g_ciso_dec_buf + offset - g_ciso_dec_buf_offset, (char *)addr, ISO_SECTOR_SIZE); | |
if(ret < 0) { | |
ret = -20; | |
printk("%s: -> %d\n", __func__, ret); | |
} | |
} | |
return ret < 0 ? ret : ISO_SECTOR_SIZE; | |
} | |
static int read_cso_data(u8* addr, u32 size, u32 offset) | |
{ | |
u32 cur_block; | |
int pos, ret, read_bytes; | |
u32 o_offset = offset; | |
while(size > 0) { | |
cur_block = offset / ISO_SECTOR_SIZE; | |
pos = offset & (ISO_SECTOR_SIZE - 1); | |
if(cur_block >= g_total_sectors) { | |
// EOF reached | |
break; | |
} | |
ret = read_cso_sector(g_ciso_block_buf, cur_block); | |
if(ret != ISO_SECTOR_SIZE) { | |
ret = -7; | |
printk("%s: -> %d\n", __func__, ret); | |
return ret; | |
} | |
read_bytes = MIN(size, (ISO_SECTOR_SIZE - pos)); | |
memcpy(addr, g_ciso_block_buf + pos, read_bytes); | |
size -= read_bytes; | |
addr += read_bytes; | |
offset += read_bytes; | |
} | |
return offset - o_offset; | |
} | |
/** | |
* decompress (if necessary) a compressed block and copy it to the destination | |
* If offset_shift is nonzero then the decompressed data will by used from this offset. | |
* The block_num is used to know if it needs to be decompressed | |
*/ | |
static int decompress_block(u8 *dst, u8 *src, int size, int block_num, int offset_shift) | |
{ | |
int ret; | |
if(g_cso_idx_cache[block_num] & 0x80000000) { | |
// do not copy if the block is already in place | |
if(offset_shift > 0 || src != dst) { | |
// no decompression is needed, copy the data from the end of the buffer to the start | |
memmove(dst, src + offset_shift, size); | |
} | |
ret = size; | |
} else { | |
if(!lz4_compressed) { | |
// gzip decompress | |
ret = sceKernelDeflateDecompress(g_ciso_dec_buf, ISO_SECTOR_SIZE, src, 0); | |
} else { | |
// LZ4 decompress | |
ret = LZ4_decompress_fast((char *)src, (char *)g_ciso_dec_buf, ISO_SECTOR_SIZE); | |
} | |
if(ret < 0) { | |
ret = -20; | |
printk("%s: -> %d\n", __func__, ret); | |
return ret; | |
} | |
// copy the decompressed data to the destination buffer | |
memcpy(dst, g_ciso_dec_buf + offset_shift, size); | |
} | |
return ret; | |
} | |
static int refresh_cso_index(u32 size, u32 offset) { | |
// seek the first block offset | |
u32 starting_block = offset / ISO_SECTOR_SIZE; | |
// calculate the last needed block and read the index | |
u32 ending_block = (offset + size) / ISO_SECTOR_SIZE + 1; | |
u32 idx_size = (ending_block - starting_block + 1) * 4; | |
if (idx_size > CISO_IDX_MAX_ENTRIES * 4) { | |
// the requested index size is too big | |
return -1; | |
} | |
// out of scope, read cso index table again | |
if (starting_block < g_cso_idx_start_block|| ending_block >= g_cso_idx_start_block + CISO_IDX_MAX_ENTRIES) { | |
sceIoLseek(g_iso_fd, starting_block * 4 + 24, PSP_SEEK_SET); | |
u32 total_blocks = g_CISO_hdr.total_bytes / g_CISO_hdr.block_size; | |
if (starting_block > total_blocks) { | |
// the requested block goes beyond the max block number | |
return -1; | |
} | |
if (starting_block + 4096 > total_blocks) { | |
idx_size = (total_blocks - starting_block + 1) * 4; | |
} else { | |
idx_size = CISO_IDX_MAX_ENTRIES * 4; | |
} | |
sceIoRead(g_iso_fd, g_cso_idx_cache, idx_size); | |
g_cso_idx_start_block = starting_block; | |
return 0; | |
} | |
return starting_block - g_cso_idx_start_block; | |
} | |
static int read_cso_data_ng(u8 *addr, u32 size, u32 offset) | |
{ | |
u32 cso_block; | |
u32 start_blk = 0; | |
u32 first_block_size = 0; | |
u32 last_block_size = 0; | |
u32 cso_read_offset, cso_read_size; | |
if(offset > g_CISO_hdr.total_bytes) { | |
// return if the offset goes beyond the iso size | |
return 0; | |
} else if(offset + size > g_CISO_hdr.total_bytes) { | |
// adjust size if it tries to read beyond the game data | |
size = g_CISO_hdr.total_bytes - offset; | |
} | |
if ((start_blk = refresh_cso_index(size, offset)) < 0) { | |
//FIXME: fallback to slower read, try to get a bigger block instead | |
// a game shouldn't request more than 8MiB in a single read so this | |
// isn't executed in normal cases | |
printk("Index for read of size %i is greater that allowed maximum\n", size); | |
return read_cso_data(addr, size, offset); | |
} | |
// check if the first read is in the middle of a compressed block or if there is only one block | |
if(!IS_DIVISIBLE(offset, ISO_SECTOR_SIZE) || size <= ISO_SECTOR_SIZE) { | |
// calculate the offset and size of the compressed data | |
cso_read_offset = GET_CSO_OFFSET(start_blk); | |
cso_read_size = GET_CSO_OFFSET(start_blk + 1) - cso_read_offset; | |
// READ #2 (only if the first block is a partial one) | |
read_raw_data(g_ciso_block_buf, cso_read_size, cso_read_offset); | |
u32 offset_shift = REMAINDER(offset, ISO_SECTOR_SIZE); | |
// calculate the real size needed from the decompressed block | |
if(offset_shift + size <= ISO_SECTOR_SIZE) { | |
// if the size + offset shift is less than the sector size then | |
// use the value directly for the first block size | |
first_block_size = size; | |
} else { | |
// else use the remainder | |
first_block_size = ISO_SECTOR_SIZE - offset_shift; | |
} | |
// decompress (if required) | |
if(decompress_block(addr, g_ciso_block_buf, first_block_size, start_blk, offset_shift) < 0) { | |
return -2; | |
} | |
// update size | |
size -= first_block_size; | |
// only one block to read, return early | |
if(size == 0) { | |
return first_block_size; | |
} | |
// update offset and addr | |
offset += first_block_size; | |
addr += first_block_size; | |
start_blk++; | |
} | |
{ | |
// calculate the last block (or the remaining one) | |
cso_block = size / 2048 + start_blk; | |
// don't go over the next block if the read size occupies all of it | |
if(IS_DIVISIBLE(size, ISO_SECTOR_SIZE)) { | |
cso_block--; | |
} | |
cso_read_offset = GET_CSO_OFFSET(cso_block); | |
// get the compressed block size | |
cso_read_size = GET_CSO_OFFSET(cso_block + 1) - cso_read_offset; | |
// READ #3 (only if the last block is a partial one) | |
read_raw_data(g_ciso_block_buf, cso_read_size, cso_read_offset); | |
// calculate the partial decompressed block size | |
last_block_size = size % 2048; | |
// update size | |
size -= last_block_size; | |
// calculate the offset to place the last decompressed block | |
void *last_offset = addr + ((size / ISO_SECTOR_SIZE) * ISO_SECTOR_SIZE); | |
if(decompress_block(last_offset, g_ciso_block_buf, last_block_size, cso_block, 0) < 0) { | |
return -3; | |
} | |
// no more blocks | |
if(size == 0) { | |
return first_block_size +last_block_size; | |
} | |
} | |
// calculate the needed blocks | |
if(IS_DIVISIBLE(size, 2048)) { | |
cso_block = size / 2048; | |
} else { | |
cso_block = size / 2048 + 1; | |
} | |
cso_read_offset = GET_CSO_OFFSET(start_blk); | |
cso_read_size = GET_CSO_OFFSET(start_blk + cso_block) - cso_read_offset; | |
// place the compressed blocks at the end of the provided buffer | |
// so it can be reused in the decompression without overlap | |
u32 shifted_offset = cso_block * 2048 - cso_read_size; | |
// READ #4 (main section of compressed blocks) | |
read_raw_data(addr + shifted_offset, cso_read_size, cso_read_offset); | |
int i; | |
u32 read_size = 0; | |
// process every compressed block | |
for(i = 0; i < cso_block ; i++) { | |
// shift the source with the size of the last read | |
void *src = addr + shifted_offset + read_size; | |
// shift the destination, block by block | |
void *dst = addr + i * ISO_SECTOR_SIZE; | |
// calculate a size in case last block is a partial one and its | |
// size is less that the sector size | |
int dec_size = size < ISO_SECTOR_SIZE ? size : ISO_SECTOR_SIZE; | |
if(decompress_block(dst, src, dec_size, i + start_blk, 0) < 0) { | |
return -4; | |
} | |
cso_read_offset = GET_CSO_OFFSET(start_blk + i); | |
u32 decompressed_size = GET_CSO_OFFSET(start_blk + i + 1) - cso_read_offset; | |
read_size += decompressed_size; | |
} | |
return size + first_block_size + last_block_size; | |
} | |
// 0x00000C7C | |
int iso_read_old(u8 *address, u32 size, u32 offset) | |
{ | |
if(g_is_ciso != 0) { | |
return read_cso_data(address, size, offset); | |
} | |
return read_raw_data(address, size, offset); | |
} | |
// 0x00000C7C | |
int iso_read(u8 *address, u32 size, u32 offset) | |
{ | |
if(g_is_ciso != 0) { | |
return read_cso_data_ng(address, size, offset); | |
} | |
return read_raw_data(address, size, offset); | |
} | |
// TESTING CODE | |
void calculate_md5(unsigned char *out, unsigned char *in, int size) | |
{ | |
MD5_CTX mdContext; | |
MD5_Init(&mdContext); | |
MD5_Update(&mdContext, in, size); | |
MD5_Final(out, &mdContext); | |
} | |
int test_integrity(const char *offsetFile, unsigned char *buffer) | |
{ | |
FILE *fd = fopen(offsetFile, "r"); | |
if(fd == NULL) | |
return 1; | |
ssize_t read; | |
size_t len = 0; | |
char *line = NULL; | |
int lines = 0; | |
while ((read = getline(&line, &len, fd)) != -1) | |
{ | |
if(line[0] == '#') | |
continue; | |
int offset; | |
int read_size; | |
sscanf(line, "offset: %i, size: %i\n", &offset, &read_size); | |
memset(buffer, 0xCC, read_size); | |
unsigned char old_digest[MD5_DIGEST_LENGTH]; | |
unsigned char new_digest[MD5_DIGEST_LENGTH]; | |
int read_buffer; | |
if((read_buffer = iso_read_old(buffer, read_size, offset)) < 0) | |
{ | |
printf("Failed to read game (old method), return value: %i\n", read_buffer); | |
printf("Size %i, offset %i\n", read_size, offset); | |
return 1; | |
} | |
calculate_md5((unsigned char *)&old_digest, buffer, read_size); | |
if((read_buffer = iso_read(buffer, read_size, offset)) < 0) | |
{ | |
printf("Failed to read game (new method), return value: %i\n", read_buffer); | |
printf("Size %i, offset %i\n", read_size, offset); | |
return 1; | |
} | |
calculate_md5((unsigned char *)&new_digest, buffer, read_size); | |
if (memcmp(old_digest, new_digest, MD5_DIGEST_LENGTH) != 0) { | |
printf("MD5 check failed\n"); | |
printf("Size %i, offset %i\n", read_size, offset); | |
return 1; | |
} | |
lines++; | |
} | |
free(line); | |
fclose(fd); | |
printf("Total reads: %i\n", lines); | |
return 0; | |
} | |
typedef int(*read_func)(u8 *address, u32 size, u32 offset); | |
int process_loops(FILE *fd, unsigned char *buffer, int loops, read_func func) | |
{ | |
ssize_t read_size; | |
char *line = NULL; | |
size_t len = 0; | |
for(int i = 0; i < loops; i++) | |
{ | |
// reset cso cache | |
g_CISO_cur_idx = -1; | |
while ((read_size = getline(&line, &len, fd)) != -1) | |
{ | |
if(line[0] == '#') | |
continue; | |
int offset; | |
int read_size; | |
sscanf(line, "offset: %i, size: %i\n", &offset, &read_size); | |
int read_buffer; | |
if((read_buffer = func(buffer, read_size, offset)) < 0) | |
{ | |
printf("Failed to read game (old method), return value: %i\n", read_buffer); | |
free(line); | |
return 1; | |
} | |
} | |
free(line); | |
line = NULL; | |
// restart offset file | |
fseek(fd, 0, SEEK_SET); | |
} | |
return 0; | |
} | |
int test_speed(const char *offsetFile, unsigned char *buffer, int loops) | |
{ | |
FILE *fd = fopen(offsetFile, "r"); | |
if(fd == NULL) | |
return 1; | |
posix_fadvise(fileno(fd), 0, 0, POSIX_FADV_DONTNEED); | |
clock_t begin, end; | |
double time_spent; | |
// start timing old read | |
begin = clock(); | |
process_loops(fd, buffer, loops, iso_read_old); | |
end = clock(); | |
time_spent = (double) (end - begin) / CLOCKS_PER_SEC; | |
printk("time spent (old method): %f\n", time_spent); | |
// start timing new read | |
begin = clock(); | |
process_loops(fd, buffer, loops, iso_read); | |
end = clock(); | |
time_spent = (double) (end - begin) / CLOCKS_PER_SEC; | |
printk("time spent (new method): %f\n", time_spent); | |
fclose(fd); | |
return 0; | |
} | |
int main(int argc, char **argv) { | |
if (argc < 3) { | |
return 1; | |
} | |
g_iso_fn = argv[1]; | |
printk("Opening %s\n", g_iso_fn); | |
if(iso_open() == 0) | |
{ | |
posix_fadvise(g_iso_fd, 0, 0, POSIX_FADV_DONTNEED); | |
unsigned char *buffer = (unsigned char *)malloc(1024*1024); // 1MiB | |
printf("Integrity test...\n"); | |
if(test_integrity(argv[2], buffer) == 0) | |
{ | |
printf("Integrity test OK\n"); | |
printf("Starting speed test, %i loops\n", 500); | |
test_speed(argv[2], buffer, 500); | |
} | |
free(buffer); | |
close(g_iso_fd); | |
free(g_cso_idx_cache_orig); | |
free(g_ciso_block_buf_orig); | |
free(g_ciso_dec_buf_orig); | |
} | |
return 0; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
offset: 1048576, size: 1 | |
offset: 1048577, size: 1 | |
offset: 1048578, size: 1 | |
offset: 1048579, size: 1 | |
offset: 1048580, size: 1 | |
offset: 1048581, size: 1 | |
offset: 1048582, size: 1 | |
offset: 1048583, size: 1 | |
offset: 1048584, size: 1 | |
offset: 1048585, size: 1 | |
offset: 1048586, size: 1 | |
offset: 1048587, size: 1 | |
offset: 1048588, size: 1 | |
offset: 1048589, size: 1 | |
offset: 1048590, size: 1 | |
offset: 1048591, size: 1 | |
offset: 1048592, size: 1 | |
offset: 1048593, size: 1 | |
offset: 1048594, size: 1 | |
offset: 1048595, size: 1 | |
offset: 1048596, size: 1 | |
offset: 1048597, size: 1 | |
offset: 1048598, size: 1 | |
offset: 1048599, size: 1 | |
offset: 1048600, size: 1 | |
offset: 1048601, size: 1 | |
offset: 1048602, size: 1 | |
offset: 1048603, size: 1 | |
offset: 1048604, size: 1 | |
offset: 1048606, size: 2 | |
offset: 1048608, size: 2 | |
offset: 1048610, size: 2 | |
offset: 1048612, size: 2 | |
offset: 1048614, size: 2 | |
offset: 1048616, size: 2 | |
offset: 1048618, size: 2 | |
offset: 1048620, size: 2 | |
offset: 1048622, size: 2 | |
offset: 1048624, size: 2 | |
offset: 1048626, size: 2 | |
offset: 1048628, size: 2 | |
offset: 1048630, size: 2 | |
offset: 1048632, size: 2 | |
offset: 1048634, size: 2 | |
offset: 1048636, size: 2 | |
offset: 1048638, size: 2 | |
offset: 1048640, size: 2 | |
offset: 1048642, size: 2 | |
offset: 1048644, size: 2 | |
offset: 1048646, size: 2 | |
offset: 1048648, size: 2 | |
offset: 1048650, size: 2 | |
offset: 1048652, size: 2 | |
offset: 1048654, size: 2 | |
offset: 1048656, size: 2 | |
offset: 1048658, size: 2 | |
offset: 1048660, size: 2 | |
offset: 1048664, size: 4 | |
offset: 1048668, size: 4 | |
offset: 1048672, size: 4 | |
offset: 1048676, size: 4 | |
offset: 1048680, size: 4 | |
offset: 1048684, size: 4 | |
offset: 1048688, size: 4 | |
offset: 1048692, size: 4 | |
offset: 1048696, size: 4 | |
offset: 1048700, size: 4 | |
offset: 1048704, size: 4 | |
offset: 1048708, size: 4 | |
offset: 1048712, size: 4 | |
offset: 1048716, size: 4 | |
offset: 1048720, size: 4 | |
offset: 1048724, size: 4 | |
offset: 1048728, size: 4 | |
offset: 1048732, size: 4 | |
offset: 1048736, size: 4 | |
offset: 1048740, size: 4 | |
offset: 1048744, size: 4 | |
offset: 1048748, size: 4 | |
offset: 1048752, size: 4 | |
offset: 1048756, size: 4 | |
offset: 1048760, size: 4 | |
offset: 1048764, size: 4 | |
offset: 1048768, size: 4 | |
offset: 1048772, size: 4 | |
offset: 1048780, size: 8 | |
offset: 1048788, size: 8 | |
offset: 1048796, size: 8 | |
offset: 1048804, size: 8 | |
offset: 1048812, size: 8 | |
offset: 1048820, size: 8 | |
offset: 1048828, size: 8 | |
offset: 1048836, size: 8 | |
offset: 1048844, size: 8 | |
offset: 1048852, size: 8 | |
offset: 1048860, size: 8 | |
offset: 1048868, size: 8 | |
offset: 1048876, size: 8 | |
offset: 1048884, size: 8 | |
offset: 1048892, size: 8 | |
offset: 1048900, size: 8 | |
offset: 1048908, size: 8 | |
offset: 1048916, size: 8 | |
offset: 1048924, size: 8 | |
offset: 1048932, size: 8 | |
offset: 1048940, size: 8 | |
offset: 1048948, size: 8 | |
offset: 1048956, size: 8 | |
offset: 1048964, size: 8 | |
offset: 1048972, size: 8 | |
offset: 1048980, size: 8 | |
offset: 1048988, size: 8 | |
offset: 1048996, size: 8 | |
offset: 1049012, size: 16 | |
offset: 1049028, size: 16 | |
offset: 1049044, size: 16 | |
offset: 1049060, size: 16 | |
offset: 1049076, size: 16 | |
offset: 1049092, size: 16 | |
offset: 1049108, size: 16 | |
offset: 1049124, size: 16 | |
offset: 1049140, size: 16 | |
offset: 1049156, size: 16 | |
offset: 1049172, size: 16 | |
offset: 1049188, size: 16 | |
offset: 1049204, size: 16 | |
offset: 1049220, size: 16 | |
offset: 1049236, size: 16 | |
offset: 1049252, size: 16 | |
offset: 1049268, size: 16 | |
offset: 1049284, size: 16 | |
offset: 1049300, size: 16 | |
offset: 1049316, size: 16 | |
offset: 1049332, size: 16 | |
offset: 1049348, size: 16 | |
offset: 1049364, size: 16 | |
offset: 1049380, size: 16 | |
offset: 1049396, size: 16 | |
offset: 1049412, size: 16 | |
offset: 1049428, size: 16 | |
offset: 1049444, size: 16 | |
offset: 1049476, size: 32 | |
offset: 1049508, size: 32 | |
offset: 1049540, size: 32 | |
offset: 1049572, size: 32 | |
offset: 1049604, size: 32 | |
offset: 1049636, size: 32 | |
offset: 1049668, size: 32 | |
offset: 1049700, size: 32 | |
offset: 1049732, size: 32 | |
offset: 1049764, size: 32 | |
offset: 1049796, size: 32 | |
offset: 1049828, size: 32 | |
offset: 1049860, size: 32 | |
offset: 1049892, size: 32 | |
offset: 1049924, size: 32 | |
offset: 1049956, size: 32 | |
offset: 1049988, size: 32 | |
offset: 1050020, size: 32 | |
offset: 1050052, size: 32 | |
offset: 1050084, size: 32 | |
offset: 1050116, size: 32 | |
offset: 1050148, size: 32 | |
offset: 1050180, size: 32 | |
offset: 1050212, size: 32 | |
offset: 1050244, size: 32 | |
offset: 1050276, size: 32 | |
offset: 1050308, size: 32 | |
offset: 1050340, size: 32 | |
offset: 1050404, size: 64 | |
offset: 1050468, size: 64 | |
offset: 1050532, size: 64 | |
offset: 1050596, size: 64 | |
offset: 1050660, size: 64 | |
offset: 1050724, size: 64 | |
offset: 1050788, size: 64 | |
offset: 1050852, size: 64 | |
offset: 1050916, size: 64 | |
offset: 1050980, size: 64 | |
offset: 1051044, size: 64 | |
offset: 1051108, size: 64 | |
offset: 1051172, size: 64 | |
offset: 1051236, size: 64 | |
offset: 1051300, size: 64 | |
offset: 1051364, size: 64 | |
offset: 1051428, size: 64 | |
offset: 1051492, size: 64 | |
offset: 1051556, size: 64 | |
offset: 1051620, size: 64 | |
offset: 1051684, size: 64 | |
offset: 1051748, size: 64 | |
offset: 1051812, size: 64 | |
offset: 1051876, size: 64 | |
offset: 1051940, size: 64 | |
offset: 1052004, size: 64 | |
offset: 1052068, size: 64 | |
offset: 1052132, size: 64 | |
offset: 1052260, size: 128 | |
offset: 1052388, size: 128 | |
offset: 1052516, size: 128 | |
offset: 1052644, size: 128 | |
offset: 1052772, size: 128 | |
offset: 1052900, size: 128 | |
offset: 1053028, size: 128 | |
offset: 1053156, size: 128 | |
offset: 1053284, size: 128 | |
offset: 1053412, size: 128 | |
offset: 1053540, size: 128 | |
offset: 1053668, size: 128 | |
offset: 1053796, size: 128 | |
offset: 1053924, size: 128 | |
offset: 1054052, size: 128 | |
offset: 1054180, size: 128 | |
offset: 1054308, size: 128 | |
offset: 1054436, size: 128 | |
offset: 1054564, size: 128 | |
offset: 1054692, size: 128 | |
offset: 1054820, size: 128 | |
offset: 1054948, size: 128 | |
offset: 1055076, size: 128 | |
offset: 1055204, size: 128 | |
offset: 1055332, size: 128 | |
offset: 1055460, size: 128 | |
offset: 1055588, size: 128 | |
offset: 1055716, size: 128 | |
offset: 1055972, size: 256 | |
offset: 1056228, size: 256 | |
offset: 1056484, size: 256 | |
offset: 1056740, size: 256 | |
offset: 1056996, size: 256 | |
offset: 1057252, size: 256 | |
offset: 1057508, size: 256 | |
offset: 1057764, size: 256 | |
offset: 1058020, size: 256 | |
offset: 1058276, size: 256 | |
offset: 1058532, size: 256 | |
offset: 1058788, size: 256 | |
offset: 1059044, size: 256 | |
offset: 1059300, size: 256 | |
offset: 1059556, size: 256 | |
offset: 1059812, size: 256 | |
offset: 1060068, size: 256 | |
offset: 1060324, size: 256 | |
offset: 1060580, size: 256 | |
offset: 1060836, size: 256 | |
offset: 1061092, size: 256 | |
offset: 1061348, size: 256 | |
offset: 1061604, size: 256 | |
offset: 1061860, size: 256 | |
offset: 1062116, size: 256 | |
offset: 1062372, size: 256 | |
offset: 1062628, size: 256 | |
offset: 1062884, size: 256 | |
offset: 1063396, size: 512 | |
offset: 1063908, size: 512 | |
offset: 1064420, size: 512 | |
offset: 1064932, size: 512 | |
offset: 1065444, size: 512 | |
offset: 1065956, size: 512 | |
offset: 1066468, size: 512 | |
offset: 1066980, size: 512 | |
offset: 1067492, size: 512 | |
offset: 1068004, size: 512 | |
offset: 1068516, size: 512 | |
offset: 1069028, size: 512 | |
offset: 1069540, size: 512 | |
offset: 1070052, size: 512 | |
offset: 1070564, size: 512 | |
offset: 1071076, size: 512 | |
offset: 1071588, size: 512 | |
offset: 1072100, size: 512 | |
offset: 1072612, size: 512 | |
offset: 1073124, size: 512 | |
offset: 1073636, size: 512 | |
offset: 1074148, size: 512 | |
offset: 1074660, size: 512 | |
offset: 1075172, size: 512 | |
offset: 1075684, size: 512 | |
offset: 1076196, size: 512 | |
offset: 1076708, size: 512 | |
offset: 1077220, size: 512 | |
offset: 1078244, size: 1024 | |
offset: 1079268, size: 1024 | |
offset: 1080292, size: 1024 | |
offset: 1081316, size: 1024 | |
offset: 1082340, size: 1024 | |
offset: 1083364, size: 1024 | |
offset: 1084388, size: 1024 | |
offset: 1085412, size: 1024 | |
offset: 1086436, size: 1024 | |
offset: 1087460, size: 1024 | |
offset: 1088484, size: 1024 | |
offset: 1089508, size: 1024 | |
offset: 1090532, size: 1024 | |
offset: 1091556, size: 1024 | |
offset: 1092580, size: 1024 | |
offset: 1093604, size: 1024 | |
offset: 1094628, size: 1024 | |
offset: 1095652, size: 1024 | |
offset: 1096676, size: 1024 | |
offset: 1097700, size: 1024 | |
offset: 1098724, size: 1024 | |
offset: 1099748, size: 1024 | |
offset: 1100772, size: 1024 | |
offset: 1101796, size: 1024 | |
offset: 1102820, size: 1024 | |
offset: 1103844, size: 1024 | |
offset: 1104868, size: 1024 | |
offset: 1105892, size: 1024 | |
offset: 1107940, size: 2048 | |
offset: 1109988, size: 2048 | |
offset: 1112036, size: 2048 | |
offset: 1114084, size: 2048 | |
offset: 1116132, size: 2048 | |
offset: 1118180, size: 2048 | |
offset: 1120228, size: 2048 | |
offset: 1122276, size: 2048 | |
offset: 1124324, size: 2048 | |
offset: 1126372, size: 2048 | |
offset: 1128420, size: 2048 | |
offset: 1130468, size: 2048 | |
offset: 1132516, size: 2048 | |
offset: 1134564, size: 2048 | |
offset: 1136612, size: 2048 | |
offset: 1138660, size: 2048 | |
offset: 1140708, size: 2048 | |
offset: 1142756, size: 2048 | |
offset: 1144804, size: 2048 | |
offset: 1146852, size: 2048 | |
offset: 1148900, size: 2048 | |
offset: 1150948, size: 2048 | |
offset: 1152996, size: 2048 | |
offset: 1155044, size: 2048 | |
offset: 1157092, size: 2048 | |
offset: 1159140, size: 2048 | |
offset: 1161188, size: 2048 | |
offset: 1163236, size: 2048 | |
offset: 1167332, size: 4096 | |
offset: 1171428, size: 4096 | |
offset: 1175524, size: 4096 | |
offset: 1179620, size: 4096 | |
offset: 1183716, size: 4096 | |
offset: 1187812, size: 4096 | |
offset: 1191908, size: 4096 | |
offset: 1196004, size: 4096 | |
offset: 1200100, size: 4096 | |
offset: 1204196, size: 4096 | |
offset: 1208292, size: 4096 | |
offset: 1212388, size: 4096 | |
offset: 1216484, size: 4096 | |
offset: 1220580, size: 4096 | |
offset: 1224676, size: 4096 | |
offset: 1228772, size: 4096 | |
offset: 1232868, size: 4096 | |
offset: 1236964, size: 4096 | |
offset: 1241060, size: 4096 | |
offset: 1245156, size: 4096 | |
offset: 1249252, size: 4096 | |
offset: 1253348, size: 4096 | |
offset: 1257444, size: 4096 | |
offset: 1261540, size: 4096 | |
offset: 1265636, size: 4096 | |
offset: 1269732, size: 4096 | |
offset: 1273828, size: 4096 | |
offset: 1277924, size: 4096 | |
offset: 1286116, size: 8192 | |
offset: 1294308, size: 8192 | |
offset: 1302500, size: 8192 | |
offset: 1310692, size: 8192 | |
offset: 1318884, size: 8192 | |
offset: 1327076, size: 8192 | |
offset: 1335268, size: 8192 | |
offset: 1343460, size: 8192 | |
offset: 1351652, size: 8192 | |
offset: 1359844, size: 8192 | |
offset: 1368036, size: 8192 | |
offset: 1376228, size: 8192 | |
offset: 1384420, size: 8192 | |
offset: 1392612, size: 8192 | |
offset: 1400804, size: 8192 | |
offset: 1408996, size: 8192 | |
offset: 1417188, size: 8192 | |
offset: 1425380, size: 8192 | |
offset: 1433572, size: 8192 | |
offset: 1441764, size: 8192 | |
offset: 1449956, size: 8192 | |
offset: 1458148, size: 8192 | |
offset: 1466340, size: 8192 | |
offset: 1474532, size: 8192 | |
offset: 1482724, size: 8192 | |
offset: 1490916, size: 8192 | |
offset: 1499108, size: 8192 | |
offset: 1507300, size: 8192 | |
offset: 1523684, size: 16384 | |
offset: 1540068, size: 16384 | |
offset: 1556452, size: 16384 | |
offset: 1572836, size: 16384 | |
offset: 1589220, size: 16384 | |
offset: 1605604, size: 16384 | |
offset: 1621988, size: 16384 | |
offset: 1638372, size: 16384 | |
offset: 1654756, size: 16384 | |
offset: 1671140, size: 16384 | |
offset: 1687524, size: 16384 | |
offset: 1703908, size: 16384 | |
offset: 1720292, size: 16384 | |
offset: 1736676, size: 16384 | |
offset: 1753060, size: 16384 | |
offset: 1769444, size: 16384 | |
offset: 1785828, size: 16384 | |
offset: 1802212, size: 16384 | |
offset: 1818596, size: 16384 | |
offset: 1834980, size: 16384 | |
offset: 1851364, size: 16384 | |
offset: 1867748, size: 16384 | |
offset: 1884132, size: 16384 | |
offset: 1900516, size: 16384 | |
offset: 1916900, size: 16384 | |
offset: 1933284, size: 16384 | |
offset: 1949668, size: 16384 | |
offset: 1966052, size: 16384 | |
offset: 1998820, size: 32768 | |
offset: 2031588, size: 32768 | |
offset: 2064356, size: 32768 | |
offset: 2097124, size: 32768 | |
offset: 2129892, size: 32768 | |
offset: 2162660, size: 32768 | |
offset: 2195428, size: 32768 | |
offset: 2228196, size: 32768 | |
offset: 2260964, size: 32768 | |
offset: 2293732, size: 32768 | |
offset: 2326500, size: 32768 | |
offset: 2359268, size: 32768 | |
offset: 2392036, size: 32768 | |
offset: 2424804, size: 32768 | |
offset: 2457572, size: 32768 | |
offset: 2490340, size: 32768 | |
offset: 2523108, size: 32768 | |
offset: 2555876, size: 32768 | |
offset: 2588644, size: 32768 | |
offset: 2621412, size: 32768 | |
offset: 2654180, size: 32768 | |
offset: 2686948, size: 32768 | |
offset: 2719716, size: 32768 | |
offset: 2752484, size: 32768 | |
offset: 2785252, size: 32768 | |
offset: 2818020, size: 32768 | |
offset: 2850788, size: 32768 | |
offset: 2883556, size: 32768 | |
offset: 2949092, size: 65536 | |
offset: 3014628, size: 65536 | |
offset: 3080164, size: 65536 | |
offset: 3145700, size: 65536 | |
offset: 3211236, size: 65536 | |
offset: 3276772, size: 65536 | |
offset: 3342308, size: 65536 | |
offset: 3407844, size: 65536 | |
offset: 3473380, size: 65536 | |
offset: 3538916, size: 65536 | |
offset: 3604452, size: 65536 | |
offset: 3669988, size: 65536 | |
offset: 3735524, size: 65536 | |
offset: 3801060, size: 65536 | |
offset: 3866596, size: 65536 | |
offset: 3932132, size: 65536 | |
offset: 3997668, size: 65536 | |
offset: 4063204, size: 65536 | |
offset: 4128740, size: 65536 | |
offset: 4194276, size: 65536 | |
offset: 4259812, size: 65536 | |
offset: 4325348, size: 65536 | |
offset: 4390884, size: 65536 | |
offset: 4456420, size: 65536 | |
offset: 4521956, size: 65536 | |
offset: 4587492, size: 65536 | |
offset: 4653028, size: 65536 | |
offset: 4718564, size: 65536 | |
offset: 4849636, size: 131072 | |
offset: 4980708, size: 131072 | |
offset: 5111780, size: 131072 | |
offset: 5242852, size: 131072 | |
offset: 5373924, size: 131072 | |
offset: 5504996, size: 131072 | |
offset: 5636068, size: 131072 | |
offset: 5767140, size: 131072 | |
offset: 5898212, size: 131072 | |
offset: 6029284, size: 131072 | |
offset: 6160356, size: 131072 | |
offset: 6291428, size: 131072 | |
offset: 6422500, size: 131072 | |
offset: 6553572, size: 131072 | |
offset: 6684644, size: 131072 | |
offset: 6815716, size: 131072 | |
offset: 6946788, size: 131072 | |
offset: 7077860, size: 131072 | |
offset: 7208932, size: 131072 | |
offset: 7340004, size: 131072 | |
offset: 7471076, size: 131072 | |
offset: 7602148, size: 131072 | |
offset: 7733220, size: 131072 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment