Skip to content

Instantly share code, notes, and snippets.

@kode54
Last active January 28, 2021 23:08
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kode54/1b6eed5d864b0f3f8789d21e9183692f to your computer and use it in GitHub Desktop.
Save kode54/1b6eed5d864b0f3f8789d21e9183692f to your computer and use it in GitHub Desktop.
GSF to GBA ROM converter, requires my libpsflib.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <psflib/psflib.h>
void * source_fopen(const char * path)
{
return fopen(path, "rb");
}
size_t source_fread(void * buffer, size_t size, size_t count, void * handle)
{
return fread(buffer, size, count, (FILE *)handle);
}
int source_fseek(void * handle, int64_t offset, int whence)
{
return fseek((FILE *)handle, offset, whence);
}
int source_fclose(void * handle)
{
fclose((FILE *)handle);
return 0;
}
long source_ftell(void * handle)
{
return ftell((FILE *)handle);
}
static psf_file_callbacks source_callbacks =
{
"/|\\",
source_fopen,
source_fread,
source_fseek,
source_fclose,
source_ftell
};
unsigned get_be16( void const* p )
{
return (unsigned) ((unsigned char const*) p) [0] << 8 |
(unsigned) ((unsigned char const*) p) [1];
}
unsigned get_le32( void const* p )
{
return (unsigned) ((unsigned char const*) p) [3] << 24 |
(unsigned) ((unsigned char const*) p) [2] << 16 |
(unsigned) ((unsigned char const*) p) [1] << 8 |
(unsigned) ((unsigned char const*) p) [0];
}
unsigned get_be32( void const* p )
{
return (unsigned) ((unsigned char const*) p) [0] << 24 |
(unsigned) ((unsigned char const*) p) [1] << 16 |
(unsigned) ((unsigned char const*) p) [2] << 8 |
(unsigned) ((unsigned char const*) p) [3];
}
void set_le32( void* p, unsigned n )
{
((unsigned char*) p) [0] = (unsigned char) n;
((unsigned char*) p) [1] = (unsigned char) (n >> 8);
((unsigned char*) p) [2] = (unsigned char) (n >> 16);
((unsigned char*) p) [3] = (unsigned char) (n >> 24);
}
struct gsf_loader_state
{
int entry_set;
uint32_t entry;
uint8_t * data;
size_t data_size;
};
static int gsf_loader(void * context, const uint8_t * exe, size_t exe_size,
const uint8_t * reserved, size_t reserved_size)
{
if ( exe_size < 12 ) return -1;
struct gsf_loader_state * state = ( struct gsf_loader_state * ) context;
unsigned char *iptr;
size_t isize;
unsigned char *xptr;
unsigned xentry = get_le32(exe + 0);
unsigned xsize = get_le32(exe + 8);
unsigned xofs = get_le32(exe + 4) & 0x1ffffff;
if ( xsize < exe_size - 12 ) return -1;
if (!state->entry_set)
{
state->entry = xentry;
state->entry_set = 1;
}
{
iptr = state->data;
isize = state->data_size;
state->data = 0;
state->data_size = 0;
}
if (!iptr)
{
size_t rsize = xofs + xsize;
{
rsize -= 1;
rsize |= rsize >> 1;
rsize |= rsize >> 2;
rsize |= rsize >> 4;
rsize |= rsize >> 8;
rsize |= rsize >> 16;
rsize += 1;
}
iptr = (unsigned char *) malloc(rsize + 10);
if (!iptr)
return -1;
memset(iptr, 0, rsize + 10);
isize = rsize;
}
else if (isize < xofs + xsize)
{
size_t rsize = xofs + xsize;
{
rsize -= 1;
rsize |= rsize >> 1;
rsize |= rsize >> 2;
rsize |= rsize >> 4;
rsize |= rsize >> 8;
rsize |= rsize >> 16;
rsize += 1;
}
xptr = (unsigned char *) realloc(iptr, xofs + rsize + 10);
if (!xptr)
{
free(iptr);
return -1;
}
iptr = xptr;
isize = rsize;
}
memcpy(iptr + xofs, exe + 12, xsize);
{
state->data = iptr;
state->data_size = isize;
}
return 0;
}
static void print_message(void * context, const char * message)
{
fputs(message, stderr);
fflush(stderr);
}
int main(int argc, char ** argv)
{
int err;
char outname[512];
char * ptr;
FILE * f;
struct gsf_loader_state state;
if (argc != 2)
{
fprintf(stderr, "Usage:\tgsf2rom <filename.gsf>\n");
return 1;
}
memset(&state, 0, sizeof(state));
err = psf_load( argv[1], &source_callbacks, 0x22, gsf_loader, &state, 0, 0, 0, print_message, 0 );
if (err <= 0)
{
fprintf(stderr, "Invalid GSF file: %s\n", argv[1]);
return 1;
}
strcpy(outname, argv[1]);
ptr = strrchr(outname, '.');
if (!ptr) ptr = outname + strlen(outname);
strcpy(ptr, ".gba");
f = fopen(outname, "wb");
if (!f)
{
fprintf(stderr, "Unable to open output file: %s\n", outname);
return 1;
}
fwrite(state.data, 1, state.data_size, f);
fclose(f);
free(state.data);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment