www.pudn.com > potemkin_sourceforPSP.rar > BlockDevices.cpp


#include "stdafx.h" 
 
extern "C" 
{ 
#include "../../zlib/zlib.h" 
 
}; 
 
#include "BlockDevices.h" 
 
 
 
FileBlockDevice::FileBlockDevice(std::string _filename) 
: filename(_filename) 
{ 
	f = fopen(_filename.c_str(), "rb"); 
	fseek(f,0,SEEK_END); 
	filesize = ftell(f); 
	fseek(f,0,SEEK_SET); 
} 
 
FileBlockDevice::~FileBlockDevice() 
{ 
	fclose(f); 
} 
 
bool FileBlockDevice::ReadBlock(int blockNumber, u8 *outPtr)  
{ 
	fseek(f, blockNumber * GetBlockSize(), SEEK_SET); 
	fread(outPtr, 2048, 1, f); 
	return true; 
} 
 
 
 
 
 
//complessed ISO(9660) header format 
typedef struct ciso_header 
{ 
	unsigned char magic[4];			// +00 : 'C','I','S','O'                  
	unsigned long header_size;		// +04 : header size (==0x18)             
	unsigned long long total_bytes;	// +08 : number of original data size     
	unsigned long block_size;		// +10 : number of compressed block size  
	unsigned char ver;				// +14 : version 01                       
	unsigned char align;			// +15 : align of index value             
	unsigned char rsv_06[2];		// +16 : reserved                         
#if 0 
	// INDEX BLOCK 
	unsigned int index[0];			// +18 : block[0] index                  
	unsigned int index[1];			// +1C : block[1] index                   
	: 
	: 
	unsigned int index[last];		// +?? : block[last]                      
	unsigned int index[last+1];		// +?? : end of last data point           
	// DATA BLOCK 
	unsigned char data[];			// +?? : compressed or plain sector data 
#endif 
} CISO_H; 
 
 
CISOFileBlockDevice::CISOFileBlockDevice(std::string _filename) 
: filename(_filename) 
{ 
 
	//CISO format is EXTREMELY crappy and incomplete. All tools make broken CISO. 
 
	f = fopen(_filename.c_str(), "rb"); 
	CISO_H hdr; 
	fread(&hdr, 1, sizeof(CISO_H), f); 
	if (memcmp(hdr.magic, "CISO", 4) != 0) 
	{ 
		//ARGH! 
 
	} 
	else 
	{ 
		LOG(LOADER, "Valid CSO!"); 
	} 
	if (hdr.ver > 1) 
	{ 
		LOG(LOADER, "CSO version too high!"); 
		//ARGH! 
	} 
 
	int hdrSize = hdr.header_size; 
	blockSize = hdr.block_size; 
	if (blockSize != 0x800) 
	{ 
		LOG(LOADER, "CSO Unsupported Block Size"); 
	} 
	indexShift = hdr.align; 
	u64 totalSize = hdr.total_bytes; 
	numBlocks = (int)(totalSize / blockSize); 
	LOG(LOADER, "hdrSize=%i numBlocks=%i align=%i", hdrSize, numBlocks, indexShift); 
 
	int indexSize = numBlocks + 1; 
 
	index = new u32[indexSize]; 
	fread(index, 4, indexSize, f); 
} 
 
CISOFileBlockDevice::~CISOFileBlockDevice() 
{ 
	fclose(f); 
	delete [] index; 
} 
 
u8 inbuffer[4096]; //too big 
z_stream z; 
u8 inbuffer2[4096]; //too big 
 
bool CISOFileBlockDevice::ReadBlock(int blockNumber, u8 *outPtr)  
{ 
	u32 idx = index[blockNumber]; 
	u32 idx2 = index[blockNumber+1]; 
	 
	int plain = idx & 0x80000000; 
	 
	idx = (idx & 0x7FFFFFFF) << indexShift; 
	idx2 = (idx2 & 0x7FFFFFFF) << indexShift; 
 
	u32 compressedReadPos = idx; 
	u32 compressedReadSize = idx2 - idx; 
 
	fseek(f, compressedReadPos, SEEK_SET); 
	fread(inbuffer, compressedReadSize, 1, f); 
 
	if (plain) 
	{ 
		memset(outPtr, 0, 2048); 
		memcpy(outPtr, inbuffer, compressedReadSize); 
	} 
	else 
	{ 
		memset(outPtr, 0, 2048); 
		z.zalloc = Z_NULL; 
		z.zfree = Z_NULL; 
		z.opaque = Z_NULL; 
		if(inflateInit2(&z, -15) != Z_OK) 
		{ 
			LOG(LOADER, "deflateInit : %s\n", (z.msg) ? z.msg : "???"); 
			return 1; 
		} 
		z.avail_in = compressedReadSize; 
		z.next_out = outPtr; 
		z.avail_out = blockSize; 
		z.next_in = inbuffer; 
 
		int status = inflate(&z, Z_FULL_FLUSH); 
		if(status != Z_STREAM_END) 
			//if (status != Z_OK) 
		{ 
			LOG(LOADER, "block %d:inflate : %s[%d]\n", blockNumber, (z.msg) ? z.msg : "error", status); 
			return 1; 
		} 
		int cmp_size = blockSize - z.avail_out; 
		if(cmp_size != blockSize) 
		{ 
			LOG(LOADER, "block %d : block size error %d != %d\n", blockNumber, cmp_size, blockSize); 
			return 1; 
		} 
	} 
	return true; 
} 
 
 
 
 
/* 
 
 
#ifndef __CISO_H__ 
#define __CISO_H__ 
 
#define SWAPLL(x) \ 
( \ 
(((x) & 0xff00000000000000LL) >> 8 * 7) \ 
| (((x) & 0xff000000000000LL) >> 8 * 5) \ 
| (((x) & 0xff0000000000LL) >> 8 * 3) \ 
| (((x) & 0xff00000000LL) >> 8 * 1) \ 
| (((x) & 0xff000000LL) << 8 * 1) \ 
| (((x) & 0xff0000LL) << 8 * 3) \ 
| (((x) & 0xff00LL) << 8 * 5) \ 
| (((x) & 0xffLL) << 8 * 7) \ 
) 
 
#define SWAPL(x) (((((unsigned long) x)) >> 24) | (((x) & 0xff0000) >> 8) | (((x) & 0xff00) << 8) | (((x)) << 24)) 
#define SWAPW(x) ((((x) & 0xff00) >> 8) | (((x) & 0xff) << 8)) 
 
 
 
//note: 
 
//file_pos_sector[n]  = (index[n]&0x7fffffff) << CISO_H.align 
//file_size_sector[n] = ( (index[n+1]&0x7fffffff) << CISO_H.align) - file_pos_sector[n] 
 
//if(index[n]&0x80000000) 
//// read 0x800 without compress 
//else 
//// read file_size_sector[n] bytes and decompress data 
 
#endif 
 
 
const char *fname_in, *fname_out; 
FILE *fin, *fout; 
z_stream z; 
 
unsigned int *index_buf = NULL; 
unsigned int *crc_buf = NULL; 
unsigned char *block_buf1 = NULL; 
unsigned char *block_buf2 = NULL; 
 
//*************************************************************************** 
//compress ISO to CSO 
//*************************************************************************** 
 
CISO_H ciso; 
int ciso_total_block; 
 
unsigned long long check_file_size(FILE * fp) 
{ 
	unsigned long long pos; 
 
	if(fseek(fp, 0, SEEK_END) < 0) 
		return -1; 
	pos = ftell(fp); 
	if(pos == -1) 
		return pos; 
 
	// init ciso header 
	memset(&ciso, 0, sizeof(ciso)); 
 
	ciso.magic[0] = 'C'; 
	ciso.magic[1] = 'I'; 
	ciso.magic[2] = 'S'; 
	ciso.magic[3] = 'O'; 
	ciso.ver = 0x01; 
 
	ciso.block_size = 0x800;	// ISO9660 one of sector  
	ciso.total_bytes = pos; 
#if 0 
	// align >0 has bug  
	for(ciso.align = 0; (ciso.total_bytes >> ciso.align) > 0x80000000LL; ciso.align++); 
#endif 
 
	ciso_total_block = pos / ciso.block_size; 
 
	fseek(fp, 0, SEEK_SET); 
 
	return pos; 
} 
 
void endianconvert_header(CISO_H *header) 
{ 
	// typedef struct ciso_header 
	// { 
	// unsigned char magic[4];			// +00 : 'C','I','S','O'                  
	// unsigned long header_size;		// +04 : header size (==0x18)             
	// unsigned long long total_bytes;	// +08 : number of original data size     
	// unsigned long block_size;		// +10 : number of compressed block size  
	// unsigned char ver;				// +14 : version 01                       
	// unsigned char align;			// +15 : align of index value             
	// unsigned char rsv_06[2];		// +16 : reserved                         
	// } CISO_H; 
 
	header->header_size = SWAPL(header->header_size); 
	header->total_bytes = SWAPLL(header->total_bytes); 
	header->block_size = SWAPL(header->block_size); 
} 
 
//**************************************************************************** 
//decompress CSO to ISO 
//**************************************************************************** 
int decomp_ciso(void) 
{ 
	unsigned long long file_size; 
	unsigned int index, index2; 
	unsigned long long read_pos, read_size; 
	int total_sectors; 
	int index_size; 
	int block; 
	unsigned char buf4[4]; 
	int cmp_size; 
	int status; 
	int percent_period; 
	int percent_cnt; 
	int plain; 
 
	// read header 
	if(fread(&ciso, 1, sizeof(ciso), fin) != sizeof(ciso)) 
	{ 
		printf("file read error\n"); 
		return 1; 
	} 
 
	endianconvert_header(&ciso); 
 
	// check header 
	if( 
		ciso.magic[0] != 'C' || 
		ciso.magic[1] != 'I' || 
		ciso.magic[2] != 'S' || 
		ciso.magic[3] != 'O' || 
		ciso.block_size == 0 || 
		ciso.total_bytes == 0 
		) 
	{ 
		printf("ciso file format error\n"); 
		return 1; 
	} 
 
	ciso_total_block = ciso.total_bytes / ciso.block_size; 
 
	// printf("header_size: %d\n", ciso.header_size); // only for debug 
	// printf("total_bytes: %lld\n", ciso.total_bytes); // only for debug 
	// printf("block_size: %d\n", ciso.block_size); // only for debug 
	// printf("total block: %d\n", ciso_total_block); // only for debug 
 
	// allocate index block 
	index_size = (ciso_total_block + 1) * sizeof(unsigned long); 
	// printf("index size: %d\n", index_size); // only for debug 
	index_buf = malloc(index_size); 
	block_buf1 = malloc(ciso.block_size); 
	block_buf2 = malloc(ciso.block_size * 2); 
 
	if(!index_buf || !block_buf1 || !block_buf2) 
	{ 
		printf("Can't allocate memory\n"); 
		return 1; 
	} 
	memset(index_buf, 0, index_size); 
 
	// read index block 
	if(fread(index_buf, 1, index_size, fin) != index_size) 
	{ 
		printf("file read error\n"); 
		return 1; 
	} 
 
	// show info 
	printf("Decompress '%s' to '%s'\n", fname_in, fname_out); 
	printf("Total File Size %lld bytes\n", ciso.total_bytes); 
	printf("block size      %d  bytes\n", ciso.block_size); 
	printf("total blocks    %d  blocks\n", ciso_total_block); 
	printf("index align     %d\n", 1 << ciso.align); 
 
	// init zlib 
	z.zalloc = Z_NULL; 
	z.zfree = Z_NULL; 
	z.opaque = Z_NULL; 
 
	// decompress data 
	percent_period = ciso_total_block / 100; 
	percent_cnt = 0; 
 
	for(block = 0; block < ciso_total_block; block++) 
	{ 
		if(--percent_cnt <= 0) 
		{ 
			percent_cnt = percent_period; 
			printf("decompress %d%%\r", block / percent_period); 
			fflush(stdout); 
		} 
 
		if(inflateInit2(&z, -15) != Z_OK) 
		{ 
			printf("deflateInit : %s\n", (z.msg) ? z.msg : "???"); 
			return 1; 
		} 
 
		// check index 
		index = SWAPL(index_buf[block]); 
		plain = index & 0x80000000; 
		index &= 0x7fffffff; 
		read_pos = index << (ciso.align); 
		if(plain) 
		{ 
			read_size = ciso.block_size; 
		} 
		else 
		{ 
			index2 = SWAPL(index_buf[block + 1]) & 0x7fffffff; 
			read_size = (index2 - index) << (ciso.align); 
		} 
		fseek(fin, read_pos, SEEK_SET); 
 
		z.avail_in = fread(block_buf2, 1, read_size, fin); 
		if(z.avail_in != read_size) 
		{ 
			printf("block=%d : read error\n", block); 
			return 1; 
		} 
 
		if(plain) 
		{ 
			memcpy(block_buf1, block_buf2, read_size); 
			cmp_size = read_size; 
		} 
		else 
		{ 
			z.next_out = block_buf1; 
			z.avail_out = ciso.block_size; 
			z.next_in = block_buf2; 
			status = inflate(&z, Z_FULL_FLUSH); 
			if(status != Z_STREAM_END) 
				//if (status != Z_OK) 
			{ 
				printf("block %d:inflate : %s[%d]\n", block, (z.msg) ? z.msg : "error", status); 
				return 1; 
			} 
			cmp_size = ciso.block_size - z.avail_out; 
			if(cmp_size != ciso.block_size) 
			{ 
				printf("block %d : block size error %d != %d\n", block, cmp_size, ciso.block_size); 
				return 1; 
			} 
		} 
		// write decompressed block 
		if(fwrite(block_buf1, 1, cmp_size, fout) != cmp_size) 
		{ 
			printf("block %d : Write error\n", block); 
			return 1; 
		} 
 
		// term zlib 
		if(inflateEnd(&z) != Z_OK) 
		{ 
			printf("inflateEnd : %s\n", (z.msg) ? z.msg : "error"); 
			return 1; 
		} 
	} 
 
	printf("ciso decompress completed\n"); 
	return 0; 
} 
 
*/