Skip to content

Instantly share code, notes, and snippets.

@cjcliffe
Created September 23, 2012 22:35
Show Gist options
  • Save cjcliffe/3773297 to your computer and use it in GitHub Desktop.
Save cjcliffe/3773297 to your computer and use it in GitHub Desktop.
Dreamcast ISO prepartion tool
#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