Created
September 23, 2012 22:35
-
-
Save cjcliffe/3773297 to your computer and use it in GitHub Desktop.
Dreamcast ISO prepartion tool
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
#include <stdio.h> | |
#include <stdlib.h> | |
#define MAXCHUNK (2048*1024) | |
static unsigned int seed; | |
void my_srand(unsigned int n) | |
{ | |
seed = n & 0xffff; | |
} | |
unsigned int my_rand() | |
{ | |
seed = (seed * 2109 + 9273) & 0x7fff; | |
return (seed + 0xc000) & 0xffff; | |
} | |
void load(FILE *fh, unsigned char *ptr, unsigned long sz) | |
{ | |
if(fread(ptr, 1, sz, fh) != sz) | |
{ | |
fprintf(stderr, "Read error!\n"); | |
exit(1); | |
} | |
} | |
void load_chunk(FILE *fh, unsigned char *ptr, unsigned long sz) | |
{ | |
static int idx[MAXCHUNK/32]; | |
int i; | |
/* Convert chunk size to number of slices */ | |
sz /= 32; | |
/* Initialize index table with unity, | |
so that each slice gets loaded exactly once */ | |
for(i = 0; i < sz; i++) | |
idx[i] = i; | |
for(i = sz-1; i >= 0; --i) | |
{ | |
/* Select a replacement index */ | |
int x = (my_rand() * i) >> 16; | |
/* Swap */ | |
int tmp = idx[i]; | |
idx[i] = idx[x]; | |
idx[x] = tmp; | |
/* Load resulting slice */ | |
load(fh, ptr+32*idx[i], 32); | |
} | |
} | |
void load_file(FILE *fh, unsigned char *ptr, unsigned long filesz) | |
{ | |
unsigned long chunksz; | |
my_srand(filesz); | |
/* Descramble 2 meg blocks for as long as possible, then | |
gradually reduce the window down to 32 bytes (1 slice) */ | |
for(chunksz = MAXCHUNK; chunksz >= 32; chunksz >>= 1) | |
while(filesz >= chunksz) | |
{ | |
load_chunk(fh, ptr, chunksz); | |
filesz -= chunksz; | |
ptr += chunksz; | |
} | |
/* Load final incomplete slice */ | |
if(filesz) | |
load(fh, ptr, filesz); | |
} | |
void read_file(char *filename, unsigned char **ptr, unsigned long *sz) | |
{ | |
FILE *fh = fopen(filename, "rb"); | |
if(fh == NULL) | |
{ | |
fprintf(stderr, "Can't open \"%s\".\n", filename); | |
exit(1); | |
} | |
if(fseek(fh, 0, SEEK_END)<0) | |
{ | |
fprintf(stderr, "Seek error.\n"); | |
exit(1); | |
} | |
*sz = ftell(fh); | |
*ptr = malloc(*sz); | |
if( *ptr == NULL ) | |
{ | |
fprintf(stderr, "Out of memory.\n"); | |
exit(1); | |
} | |
if(fseek(fh, 0, SEEK_SET)<0) | |
{ | |
fprintf(stderr, "Seek error.\n"); | |
exit(1); | |
} | |
load_file(fh, *ptr, *sz); | |
fclose(fh); | |
} | |
void save(FILE *fh, unsigned char *ptr, unsigned long sz) | |
{ | |
if(fwrite(ptr, 1, sz, fh) != sz) | |
{ | |
fprintf(stderr, "Write error!\n"); | |
exit(1); | |
} | |
} | |
void save_chunk(FILE *fh, unsigned char *ptr, unsigned long sz) | |
{ | |
static int idx[MAXCHUNK/32]; | |
int i; | |
/* Convert chunk size to number of slices */ | |
sz /= 32; | |
/* Initialize index table with unity, | |
so that each slice gets saved exactly once */ | |
for(i = 0; i < sz; i++) | |
idx[i] = i; | |
for(i = sz-1; i >= 0; --i) | |
{ | |
/* Select a replacement index */ | |
int x = (my_rand() * i) >> 16; | |
/* Swap */ | |
int tmp = idx[i]; | |
idx[i] = idx[x]; | |
idx[x] = tmp; | |
/* Save resulting slice */ | |
save(fh, ptr+32*idx[i], 32); | |
} | |
} | |
void save_file(FILE *fh, unsigned char *ptr, unsigned long filesz) | |
{ | |
unsigned long chunksz; | |
my_srand(filesz); | |
/* Descramble 2 meg blocks for as long as possible, then | |
gradually reduce the window down to 32 bytes (1 slice) */ | |
for(chunksz = MAXCHUNK; chunksz >= 32; chunksz >>= 1) | |
while(filesz >= chunksz) | |
{ | |
save_chunk(fh, ptr, chunksz); | |
filesz -= chunksz; | |
ptr += chunksz; | |
} | |
/* Save final incomplete slice */ | |
if(filesz) | |
save(fh, ptr, filesz); | |
} | |
void write_file(char *filename, unsigned char *ptr, unsigned long sz) | |
{ | |
FILE *fh = fopen(filename, "wb"); | |
if(fh == NULL) | |
{ | |
fprintf(stderr, "Can't open \"%s\".\n", filename); | |
exit(1); | |
} | |
save_file(fh, ptr, sz); | |
fclose(fh); | |
} | |
void descramble(char *src, char *dst) | |
{ | |
unsigned char *ptr = NULL; | |
unsigned long sz = 0; | |
FILE *fh; | |
read_file(src, &ptr, &sz); | |
fh = fopen(dst, "wb"); | |
if(fh == NULL) | |
{ | |
fprintf(stderr, "Can't open \"%s\".\n", dst); | |
exit(1); | |
} | |
if( fwrite(ptr, 1, sz, fh) != sz ) | |
{ | |
fprintf(stderr, "Write error.\n"); | |
exit(1); | |
} | |
fclose(fh); | |
free(ptr); | |
} | |
void scramble(char *src, char *dst) | |
{ | |
unsigned char *ptr = NULL; | |
unsigned long sz = 0; | |
FILE *fh; | |
fh = fopen(src, "rb"); | |
if(fh == NULL) | |
{ | |
fprintf(stderr, "Can't open \"%s\".\n", src); | |
exit(1); | |
} | |
if(fseek(fh, 0, SEEK_END)<0) | |
{ | |
fprintf(stderr, "Seek error.\n"); | |
exit(1); | |
} | |
sz = ftell(fh); | |
ptr = malloc(sz); | |
if( ptr == NULL ) | |
{ | |
fprintf(stderr, "Out of memory.\n"); | |
exit(1); | |
} | |
if(fseek(fh, 0, SEEK_SET)<0) | |
{ | |
fprintf(stderr, "Seek error.\n"); | |
exit(1); | |
} | |
if( fread(ptr, 1, sz, fh) != sz ) | |
{ | |
fprintf(stderr, "Read error.\n"); | |
exit(1); | |
} | |
fclose(fh); | |
write_file(dst, ptr, sz); | |
free(ptr); | |
} | |
int main(int argc, char *argv[]) | |
{ | |
int opt = 0; | |
if(argc > 1 && !strcmp(argv[1], "-d")) | |
opt ++; | |
if(argc != 3+opt) | |
{ | |
fprintf(stderr, "Usage: %s [-d] from to\n", argv[0]); | |
exit(1); | |
} | |
if(opt) | |
descramble(argv[2], argv[3]); | |
else | |
scramble(argv[1], argv[2]); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment