rendered paste body/*
Copyright 2007,2008 Luigi Auriemma
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
http://www.gnu.org/licenses/gpl.txt
*/
#define _LARGE_FILES // if it's not supported the tool will work
#define __USE_LARGEFILE64 // without support for large files
#define __USE_FILE_OFFSET64
#define _LARGEFILE_SOURCE
#define _LARGEFILE64_SOURCE
#define _FILE_OFFSET_BITS 64
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <zlib.h>
typedef uint8_t u8;
typedef uint16_t u16;
typedef uint32_t u32;
typedef uint64_t u64;
#define VER "0.1.1"
#define BBIS_SIGN 0x73696262
#define BLHR_SIGN 0x72686c62
#define BSDR_SIGN 0x72647362
#define PRINTF64(x) (u32)(x >> 32), (u32)(x) // I64x, llx? blah
#if defined(__MINGW32__) && defined(_LARGE_FILES)
#define off_t off64_t
#define fopen fopen64
#define fseek fseeko64
#define ftell ftello64
#endif
u8 *show_hash(u8 *hash);
void myalloc(u8 **data, unsigned wantsize, unsigned *currsize);
void myfr(FILE *fd, void *data, unsigned size);
void myfw(FILE *fd, void *data, unsigned size);
int unzip(z_stream *z, u8 *in, int insz, u8 *out, int outsz);
void std_err(void);
#pragma pack(2)
typedef struct {
u32 sign; // blhr
u32 size; // size of the data plus ver and num
u32 ver; // ignored
u32 num; // number of blhr_data structures
} blhr_t;
typedef struct {
u64 offset; // input offset
u32 zsize; // block size
u32 sector; // where to place the output
u32 size; // size in sectors!
u32 type; // type
} blhr_data_t;
typedef struct {
u32 sign; // bbis
u32 unknown1; // ignored, probably the size of the structure
u16 ver; // version, 1
u32 image_type; // 8
u16 padding; // ignored
u32 sectors; // number of sectors of the ISO
u32 sectorsz; // CD use sectors and this is the size of them (chunks)
u32 unknown2; // almost ignored
u64 blhr; // where is located the blhr header
u32 blhrbbissz; // total size of the blhr and bbis headers
u8 hash[16]; // hash? what algo?
u32 unknown3; // ignored
u32 unknown4; // ignored
} bbis_t;
#pragma pack()
int main(int argc, char *argv[]) {
z_stream z;
blhr_data_t *blhr_data;
blhr_t blhr;
bbis_t bbis;
FILE *fdi,
*fdo;
u64 tot,
file_size;
int i,
insz,
outsz;
u8 ans[8],
*filei,
*fileo,
*in,
*out;
setbuf(stdout, NULL);
fputs("\n"
"UIF2ISO "VER"\n"
"by Luigi Auriemma\n"
"e-mail: aluigi@autistici.org\n"
"web: aluigi.org\n"
"\n", stdout);
if(argc < 3) {
printf("\n"
"Usage: %s <input.UIF> <output.ISO>\n"
"\n", argv[0]);
exit(1);
}
filei = argv[1];
fileo = argv[2];
printf("- open %s\n", filei);
fdi = fopen(filei, "rb");
if(!fdi) std_err();
printf("- create %s\n", fileo);
fdo = fopen(fileo, "rb");
if(fdo) {
fclose(fdo);
printf("- the output file already exists, do you want to overwrite it (y/N)? ");
if(!fgets(ans, sizeof(ans), stdin)) exit(1);
if((ans[0] != 'y') && (ans[0] != 'Y')) exit(1);
}
fdo = fopen(fileo, "wb");
if(!fdo) std_err();
z.zalloc = (alloc_func)0;
z.zfree = (free_func)0;
z.opaque = (voidpf)0;
if(inflateInit2(&z, 15)) {
printf("\nError: zlib initialization error\n");
exit(1);
}
fseek(fdi, 0, SEEK_END);
file_size = ftell(fdi);
if(fseek(fdi, file_size - sizeof(bbis), SEEK_SET)) {
if(((file_size - sizeof(bbis)) > 0x7fffffff) && ((file_size - sizeof(bbis)) < file_size)) printf(" an error here means that your exe has no full LARGE_FILES 64 bit support!\n");
std_err();
}
myfr(fdi, &bbis, sizeof(bbis));
if(bbis.sign != BBIS_SIGN) {
printf("\nError: wrong bbis signature (%08x)\n", bbis.sign);
exit(1);
}
printf("\n"
" file size %08x%08x\n"
" version %hu\n"
" image type %u\n"
" padding %hu\n"
" sectors %u\n"
" sectors size %u\n"
" blhr offset %08x%08x\n"
" blhr size %u\n"
" hash %s\n"
" unknowns %08x %08x %08x %08x\n",
PRINTF64(file_size),
bbis.ver,
bbis.image_type,
bbis.padding,
bbis.sectors,
bbis.sectorsz,
PRINTF64(bbis.blhr),
bbis.blhrbbissz,
show_hash(bbis.hash),
bbis.unknown1, bbis.unknown2, bbis.unknown3, bbis.unknown4);
if(fseek(fdi, bbis.blhr, SEEK_SET)) std_err();
myfr(fdi, &blhr, sizeof(blhr));
if(blhr.sign != BLHR_SIGN) {
if(blhr.sign == BSDR_SIGN) {
printf("\nError: the input UIF is password protected (not yet supported)\n");
} else {
printf("\nError: wrong blhr signature (%08x)\n", blhr.sign);
}
exit(1);
}
in = out = NULL;
insz = outsz = 0;
tot = 0;
myalloc(&in, blhr.size - 8, &insz);
myfr(fdi, in, insz);
blhr_data = (void *)malloc(sizeof(blhr_data_t) * blhr.num);
if(!blhr_data) std_err();
unzip(&z, in, insz, (void *)blhr_data, sizeof(blhr_data_t) * blhr.num);
for(i = 0; i < blhr.num; i++) {
printf(" %03d%%\r", (i * 100) / blhr.num);
#ifdef VERBOSE
printf("\n"
"offset %08x%08x\n"
"input size %08x\n"
"output sector %08x\n"
"sectors %08x\n",
PRINTF64(blhr_data[i].offset),
blhr_data[i].zsize,
blhr_data[i].sector,
blhr_data[i].size);
#endif
myalloc(&in, blhr_data[i].zsize, &insz);
if(blhr_data[i].zsize) {
if(fseek(fdi, blhr_data[i].offset, SEEK_SET)) std_err();
myfr(fdi, in, blhr_data[i].zsize);
}
blhr_data[i].size *= bbis.sectorsz;
myalloc(&out, blhr_data[i].size, &outsz);
switch(blhr_data[i].type) {
case 1: { // non compressed
if(blhr_data[i].zsize > blhr_data[i].size) {
printf("\nError: input size is bigger than output\n");
exit(1);
}
memcpy(out, in, blhr_data[i].zsize);
memset(out + blhr_data[i].zsize, 0, blhr_data[i].size - blhr_data[i].zsize); // needed?
break;
}
case 3: { // multi byte
memset(out, 0, blhr_data[i].size);
break;
}
case 5: { // compressed
unzip(&z, in, blhr_data[i].zsize, out, blhr_data[i].size);
break;
}
default: {
printf("\nError: unknown type (%d)\n", blhr_data[i].type);
exit(1);
}
}
if(fseek(fdo, blhr_data[i].sector * bbis.sectorsz, SEEK_SET)) std_err();
myfw(fdo, out, blhr_data[i].size);
tot += blhr_data[i].size;
}
printf(" 100%%\n"
"- 0x%08x%08x bytes written\n",
PRINTF64(tot));
inflateEnd(&z);
fclose(fdi);
fclose(fdo);
return(0);
}
u8 *show_hash(u8 *hash) {
int i;
static u8 vis[33];
static const char hex[16] = "0123456789abcdef";
u8 *p;
p = vis;
for(i = 0; i < 16; i++) {
*p++ = hex[hash[i] >> 4];
*p++ = hex[hash[i] & 15];
}
*p = 0;
return(vis);
}
void myalloc(u8 **data, unsigned wantsize, unsigned *currsize) {
if(wantsize <= *currsize) return;
*data = realloc(*data, wantsize);
if(!*data) std_err();
*currsize = wantsize;
}
void myfr(FILE *fd, void *data, unsigned size) {
if(fread(data, 1, size, fd) == size) return;
printf("\nError: incomplete input file, can't read %u bytes\n", size);
exit(1);
}
void myfw(FILE *fd, void *data, unsigned size) {
if(fwrite(data, 1, size, fd) == size) return;
printf("\nError: problems during the writing of the output file\n");
exit(1);
}
int unzip(z_stream *z, u8 *in, int insz, u8 *out, int outsz) {
inflateReset(z);
z->next_in = in;
z->avail_in = insz;
z->next_out = out;
z->avail_out = outsz;
if(inflate(z, Z_SYNC_FLUSH) != Z_STREAM_END) {
printf("\nError: the compressed input is wrong or incomplete\n");
exit(1);
}
return(z->total_out);
}
void std_err(void) {
perror("\nError");
exit(1);
}