Exemple #1
0
Tuple *psf2_tuple(const char *filename, VFSFile *file)
{
	Tuple *t;
	corlett_t *c;
	void *buf;
	int64_t sz;

	vfs_file_get_contents (filename, & buf, & sz);

	if (!buf)
		return NULL;

	if (corlett_decode(buf, sz, NULL, NULL, &c) != AO_SUCCESS)
		return NULL;

	t = tuple_new_from_filename(filename);

	tuple_set_int(t, FIELD_LENGTH, NULL, c->inf_length ? psfTimeToMS(c->inf_length) + psfTimeToMS(c->inf_fade) : -1);
	tuple_set_str(t, FIELD_ARTIST, NULL, c->inf_artist);
	tuple_set_str(t, FIELD_ALBUM, NULL, c->inf_game);
	tuple_set_str(t, -1, "game", c->inf_game);
	tuple_set_str(t, FIELD_TITLE, NULL, c->inf_title);
	tuple_set_str(t, FIELD_COPYRIGHT, NULL, c->inf_copy);
	tuple_set_str(t, FIELD_QUALITY, NULL, _("sequenced"));
	tuple_set_str(t, FIELD_CODEC, NULL, "PlayStation 1/2 Audio");
	tuple_set_str(t, -1, "console", "PlayStation 1/2");

	free(c);
	free(buf);

	return t;
}
Exemple #2
0
s32 ssf_start(u8 *buffer, u32 length, int m68k_core, int sndcore, char* filename)
{
	u8 *file, *lib_decoded, *lib_raw_file;
	u32 offset, lengthMS, fadeMS;
	u64 file_len, lib_len, lib_raw_length;
	corlett_t *lib;
	char *libfile;
	int i;

   M68KInit(m68k_core);
   ScspInit(sndcore);

	// clear Saturn work RAM before we start scribbling in it
	memset((void *)SoundRam, 0, 0x80000);

	// Decode the current SSF
	if (corlett_decode(buffer, length, &file, &file_len, &c) != AO_SUCCESS)
	{
		return AO_FAIL;
	}

	#if DEBUG_LOADER
	printf("%d bytes decoded\n", file_len);
	#endif

	// Get the library file, if any
	for (i=0; i<9; i++) 
	{
		libfile = i ? c->libaux[i-1] : c->lib;
		if (libfile[0] != 0)
		{
			u64 tmp_length;
         char libfile_path[2048] = { 0 };

         if (!get_lib_file(filename, libfile, libfile_path))
            return AO_FAIL;
         
			#if DEBUG_LOADER	
			printf("Loading library: %s\n", c->lib);
			#endif
			if (ao_get_lib(libfile_path, &lib_raw_file, &tmp_length) != AO_SUCCESS)
			{
				return AO_FAIL;
			}
			lib_raw_length = tmp_length;
		
			if (corlett_decode(lib_raw_file, lib_raw_length, &lib_decoded, &lib_len, &lib) != AO_SUCCESS)
			{
				free(lib_raw_file);
				free(file);
				return AO_FAIL;
			}
				
			// Free up raw file
			free(lib_raw_file);

			// patch the file into ram
			offset = lib_decoded[0] | lib_decoded[1]<<8 | lib_decoded[2]<<16 | lib_decoded[3]<<24;

			// guard against invalid data
			if ((offset + (lib_len-4)) > 0x7ffff)
			{
				lib_len = 0x80000-offset+4;
			}
			memcpy(&SoundRam[offset], lib_decoded+4, lib_len-4);

			// Dispose the corlett structure for the lib - we don't use it
			free(lib);
		}
	}

	// now patch the file into RAM over the libraries
	offset = file[3]<<24 | file[2]<<16 | file[1]<<8 | file[0];

	// guard against invalid data
	if ((offset + (file_len-4)) > 0x7ffff)
	{
		file_len = 0x80000-offset+4;
	}

	memcpy(&SoundRam[offset], file+4, file_len-4);

	free(file);
	
	// Finally, set psfby tag
	strcpy(psfby, "n/a");
	if (c)
	{
		for (i = 0; i < MAX_UNKNOWN_TAGS; i++)
		{
			if (!strcasecmp(c->tag_name[i], "psfby"))
				strcpy(psfby, c->tag_data[i]);
		}
	}

	#if DEBUG_LOADER && 1
	{
		FILE *f;

		f = fopen("satram.bin", "wb");
		fwrite(sat_ram, 512*1024, 1, f);
		fclose(f);
	}
	#endif

	// now flip everything (this makes sense because he's using starscream)
	for (i = 0; i < 512*1024; i+=2)
	{
		u8 temp;

		temp = SoundRam[i];
		SoundRam[i] = SoundRam[i+1];
		SoundRam[i+1] = temp;
	}

	M68KStart ();

	// now figure out the time in samples for the length/fade
	lengthMS = psfTimeToMS(c->inf_length);
	fadeMS = psfTimeToMS(c->inf_fade);
	total_samples = 0;

	if (lengthMS == 0)
	{
		lengthMS = ~0;
	}

	if (lengthMS == ~0)
	{
		decaybegin = lengthMS;
	}
	else
	{
		lengthMS = (lengthMS * 441) / 10;
		fadeMS = (fadeMS * 441) / 10;

		decaybegin = lengthMS;
		decayend = lengthMS + fadeMS;
	}

	return AO_SUCCESS;
}
int32 dsf_start(uint8 *buffer, uint32 length)
{
	uint8 *file, *lib_decoded, *lib_raw_file;
	uint32 offset, plength, lengthMS, fadeMS;
	uint64 file_len, lib_len, lib_raw_length;
	corlett_t *lib;
	char *libfile;
	int i;

	// clear Dreamcast work RAM before we start scribbling in it
	memset(dc_ram, 0, 8*1024*1024);

	// Decode the current SSF
	if (corlett_decode(buffer, length, &file, &file_len, &c) != AO_SUCCESS)
	{
		return AO_FAIL;
	}

	#if DEBUG_LOADER
	printf("%d bytes decoded\n", file_len);
	#endif

	// Get the library file, if any
	for (i=0; i<9; i++) {
		libfile = i ? c->libaux[i-1] : c->lib;
		if (libfile[0] != 0)
		{
			uint64 tmp_length;
	
			#if DEBUG_LOADER	
			printf("Loading library: %s\n", c->lib);
			#endif
			if (ao_get_lib(libfile, &lib_raw_file, &tmp_length) != AO_SUCCESS)
			{
				return AO_FAIL;
			}
			lib_raw_length = tmp_length;
		
			if (corlett_decode(lib_raw_file, lib_raw_length, &lib_decoded, &lib_len, &lib) != AO_SUCCESS)
			{
				free(lib_raw_file);
				return AO_FAIL;
			}
				
			// Free up raw file
			free(lib_raw_file);

			// patch the file into ram
			offset = lib_decoded[0] | lib_decoded[1]<<8 | lib_decoded[2]<<16 | lib_decoded[3]<<24;
			memcpy(&dc_ram[offset], lib_decoded+4, lib_len-4);

			// Dispose the corlett structure for the lib - we don't use it
			free(lib);
		}
	}

	// now patch the file into RAM over the libraries
	offset = file[3]<<24 | file[2]<<16 | file[1]<<8 | file[0];
	memcpy(&dc_ram[offset], file+4, file_len-4);

	free(file);
	
	// Finally, set psfby/ssfby tag
	strcpy(psfby, "n/a");
	if (c)
	{
		for (i = 0; i < MAX_UNKNOWN_TAGS; i++)
		{
			if ((!strcasecmp(c->tag_name[i], "psfby")) || (!strcasecmp(c->tag_name[i], "ssfby")))
				strcpy(psfby, c->tag_data[i]);
		}
	}

	#if DEBUG_LOADER && 1
	{
		FILE *f;

		f = fopen("dcram.bin", "wb");
		fwrite(dc_ram, 2*1024*1024, 1, f);
		fclose(f);
	}
	#endif

	#if DK_CORE
	ARM7_Init();
	#else
	arm7_init(0, 45000000, NULL, NULL);
	arm7_reset();
	#endif
	dc_hw_init();

	// now figure out the time in samples for the length/fade
	lengthMS = psfTimeToMS(c->inf_length);
	fadeMS = psfTimeToMS(c->inf_fade);
	total_samples = 0;

	if (lengthMS == 0)
	{
		lengthMS = ~0;
	}

	if (lengthMS == ~0)
	{
		decaybegin = lengthMS;
	}
	else
	{
		lengthMS = (lengthMS * 441) / 10;
		fadeMS = (fadeMS * 441) / 10;

		decaybegin = lengthMS;
		decayend = lengthMS + fadeMS;
	}

	return AO_SUCCESS;
}
Exemple #4
0
void *qsf_start(const char *path, uint8 *buffer, uint32 length)
{
    qsf_synth_t *s = malloc (sizeof (qsf_synth_t));
    memset (s, 0, sizeof (qsf_synth_t));

	uint8 *file = NULL, *lib_decoded = NULL, *lib_raw_file = NULL;
	uint64 file_len, lib_len, lib_raw_length;
	corlett_t *lib;

	s->z80 = z80_init();
	s->z80->userdata = s;

	s->Z80ROM = malloc(512*1024);
	s->QSamples = malloc(8*1024*1024);

	s->skey1 = s->skey2 = 0;
	s->akey = 0;
	s->xkey = 0;
	s->cur_bank = 0;

	// Decode the current QSF
	if (corlett_decode(buffer, length, &file, &file_len, &s->c) != AO_SUCCESS)
	{
		return AO_FAIL;
	}

	// Get the library file
	if (s->c->lib[0] != 0)
	{
		uint64 tmp_length;
	
        char libpath[PATH_MAX];
        ao_getlibpath (path, s->c->lib, libpath, sizeof (libpath));

#if DEBUG_LOADER	
        printf("Loading library: %s\n", libpath);
#endif
        if (ao_get_lib(libpath, &lib_raw_file, &tmp_length) != AO_SUCCESS)
        {
            free (file);
            qsf_stop (s);
            return NULL;
		}
		lib_raw_length = tmp_length;
		
		if (corlett_decode(lib_raw_file, lib_raw_length, &lib_decoded, &lib_len, &lib) != AO_SUCCESS)
		{
			free(lib_raw_file);
            free (file);
            qsf_stop (s);
            return NULL;
		}
				
		// Free up raw file
		free(lib_raw_file);

		// use the contents
		qsf_walktags(s, lib_decoded, lib_decoded+lib_len);
		
		// Dispose the corlett structure for the lib - we don't use it
		free(lib);
		if (lib_decoded) {
            free (lib_decoded);
            lib_decoded = NULL;
        }
	}

	// now patch the file into RAM OVER the libraries
	qsf_walktags(s, file, file+file_len);

	free(file);

	if ((s->skey1 != 0) && (s->skey2 != 0))
	{
		#if DEBUG_LOADER
		printf("Decoding Kabuki: skey1 %08x skey2 %08x akey %04x xkey %02x\n", skey1, skey2, akey, xkey);
		#endif

		s->uses_kabuki = 1;
		cps1_decode((unsigned char *)s->Z80ROM, s->skey1, s->skey2, s->akey, s->xkey);
	}

	// set qsfby tag
	strcpy(s->qsfby, "n/a");
	if (s->c)
	{
		int i;
		for (i = 0; i < MAX_UNKNOWN_TAGS; i++)
		{
			if (!strcasecmp(s->c->tag_name[i], "qsfby"))
			{
				strcpy(s->qsfby, s->c->tag_data[i]);
			}
		}
	}

	memcpy (s->initRAM, s->RAM, 0x1000);
	memcpy (s->initRAM2, s->RAM2, 0x1000);

    if (s->z80) {
        z80_reset(s->z80, NULL);
        z80_set_irq_callback(s->z80, qsf_irq_cb);
    }
	qsintf.sample_rom = s->QSamples;
	s->qs = qsound_sh_start(&qsintf);
	s->samples_to_next_tick = samples_per_tick;

	return s;
}
int32 psf_start(uint8 *buffer, uint32 length)
{
    uint8 *file, *lib_decoded, *lib_raw_file, *alib_decoded;
    uint32 offset, plength, PC, SP, GP, lengthMS, fadeMS;
    uint64 file_len, lib_len, lib_raw_length, alib_len;
    corlett_t *lib;
    int i;
    union cpuinfo mipsinfo;

    // clear PSX work RAM before we start scribbling in it
    memset(psx_ram, 0, 2*1024*1024);

//	printf("Length = %d\n", length);

    // Decode the current GSF
    if (corlett_decode(buffer, length, &file, &file_len, &c) != AO_SUCCESS)
    {
        return AO_FAIL;
    }

//	printf("file_len %d reserve %d\n", file_len, c->res_size);

    // check for PSX EXE signature
    if (strncmp((char *)file, "PS-X EXE", 8))
    {
        return AO_FAIL;
    }

#if DEBUG_LOADER
    offset = file[0x18] | file[0x19]<<8 | file[0x1a]<<16 | file[0x1b]<<24;
    printf("Text section start: %x\n", offset);
    offset = file[0x1c] | file[0x1d]<<8 | file[0x1e]<<16 | file[0x1f]<<24;
    printf("Text section size: %x\n", offset);
    printf("Region: [%s]\n", &file[0x4c]);
    printf("refresh: [%s]\n", c->inf_refresh);
#endif

    if (c->inf_refresh[0] == '5')
    {
        psf_refresh = 50;
    }
    if (c->inf_refresh[0] == '6')
    {
        psf_refresh = 60;
    }

    PC = file[0x10] | file[0x11]<<8 | file[0x12]<<16 | file[0x13]<<24;
    GP = file[0x14] | file[0x15]<<8 | file[0x16]<<16 | file[0x17]<<24;
    SP = file[0x30] | file[0x31]<<8 | file[0x32]<<16 | file[0x33]<<24;

#if DEBUG_LOADER
    printf("Top level: PC %x GP %x SP %x\n", PC, GP, SP);
#endif

    // Get the library file, if any
    if (c->lib[0] != 0)
    {
        uint64 tmp_length;

#if DEBUG_LOADER
        printf("Loading library: %s\n", c->lib);
#endif
        if (ao_get_lib(c->lib, &lib_raw_file, &tmp_length) != AO_SUCCESS)
        {
            return AO_FAIL;
        }
        lib_raw_length = tmp_length;

        if (corlett_decode(lib_raw_file, lib_raw_length, &lib_decoded, &lib_len, &lib) != AO_SUCCESS)
        {
            free(lib_raw_file);
            return AO_FAIL;
        }

        // Free up raw file
        free(lib_raw_file);

        if (strncmp((char *)lib_decoded, "PS-X EXE", 8))
        {
            printf("Major error!  PSF was OK, but referenced library is not!\n");
            free(lib);
            return AO_FAIL;
        }

#if DEBUG_LOADER
        offset = lib_decoded[0x18] | lib_decoded[0x19]<<8 | lib_decoded[0x1a]<<16 | lib_decoded[0x1b]<<24;
        printf("Text section start: %x\n", offset);
        offset = lib_decoded[0x1c] | lib_decoded[0x1d]<<8 | lib_decoded[0x1e]<<16 | lib_decoded[0x1f]<<24;
        printf("Text section size: %x\n", offset);
        printf("Region: [%s]\n", &lib_decoded[0x4c]);
        printf("refresh: [%s]\n", lib->inf_refresh);
#endif

        // if the original file had no refresh tag, give the lib a shot
        if (psf_refresh == -1)
        {
            if (lib->inf_refresh[0] == '5')
            {
                psf_refresh = 50;
            }
            if (lib->inf_refresh[0] == '6')
            {
                psf_refresh = 60;
            }
        }

        PC = lib_decoded[0x10] | lib_decoded[0x11]<<8 | lib_decoded[0x12]<<16 | lib_decoded[0x13]<<24;
        GP = lib_decoded[0x14] | lib_decoded[0x15]<<8 | lib_decoded[0x16]<<16 | lib_decoded[0x17]<<24;
        SP = lib_decoded[0x30] | lib_decoded[0x31]<<8 | lib_decoded[0x32]<<16 | lib_decoded[0x33]<<24;

#if DEBUG_LOADER
        printf("Library: PC %x GP %x SP %x\n", PC, GP, SP);
#endif

        // now patch the file into RAM
        offset = lib_decoded[0x18] | lib_decoded[0x19]<<8 | lib_decoded[0x1a]<<16 | lib_decoded[0x1b]<<24;
        offset &= 0x3fffffff;	// kill any MIPS cache segment indicators
        plength = lib_decoded[0x1c] | lib_decoded[0x1d]<<8 | lib_decoded[0x1e]<<16 | lib_decoded[0x1f]<<24;
#if DEBUG_LOADER
        printf("library offset: %x plength: %d\n", offset, plength);
#endif
        memcpy(&psx_ram[offset/4], lib_decoded+2048, plength);

        // Dispose the corlett structure for the lib - we don't use it
        free(lib);
    }

    // now patch the main file into RAM OVER the libraries (but not the aux lib)
    offset = file[0x18] | file[0x19]<<8 | file[0x1a]<<16 | file[0x1b]<<24;
    offset &= 0x3fffffff;	// kill any MIPS cache segment indicators
    plength = file[0x1c] | file[0x1d]<<8 | file[0x1e]<<16 | file[0x1f]<<24;

    // Philosoma has an illegal "plength".  *sigh*
    if (plength > (file_len-2048))
    {
        plength = file_len-2048;
    }
    memcpy(&psx_ram[offset/4], file+2048, plength);

    // load any auxiliary libraries now
    for (i = 0; i < 8; i++)
    {
        if (c->libaux[i][0] != 0)
        {
            uint64 tmp_length;

#if DEBUG_LOADER
            printf("Loading aux library: %s\n", c->libaux[i]);
#endif

            if (ao_get_lib(c->libaux[i], &lib_raw_file, &tmp_length) != AO_SUCCESS)
            {
                return AO_FAIL;
            }
            lib_raw_length = tmp_length;

            if (corlett_decode(lib_raw_file, lib_raw_length, &alib_decoded, &alib_len, &lib) != AO_SUCCESS)
            {
                free(lib_raw_file);
                return AO_FAIL;
            }

            // Free up raw file
            free(lib_raw_file);

            if (strncmp((char *)alib_decoded, "PS-X EXE", 8))
            {
                printf("Major error!  PSF was OK, but referenced library is not!\n");
                free(lib);
                return AO_FAIL;
            }

#if DEBUG_LOADER
            offset = alib_decoded[0x18] | alib_decoded[0x19]<<8 | alib_decoded[0x1a]<<16 | alib_decoded[0x1b]<<24;
            printf("Text section start: %x\n", offset);
            offset = alib_decoded[0x1c] | alib_decoded[0x1d]<<8 | alib_decoded[0x1e]<<16 | alib_decoded[0x1f]<<24;
            printf("Text section size: %x\n", offset);
            printf("Region: [%s]\n", &alib_decoded[0x4c]);
#endif

            // now patch the file into RAM
            offset = alib_decoded[0x18] | alib_decoded[0x19]<<8 | alib_decoded[0x1a]<<16 | alib_decoded[0x1b]<<24;
            offset &= 0x3fffffff;	// kill any MIPS cache segment indicators
            plength = alib_decoded[0x1c] | alib_decoded[0x1d]<<8 | alib_decoded[0x1e]<<16 | alib_decoded[0x1f]<<24;
            memcpy(&psx_ram[offset/4], alib_decoded+2048, plength);

            // Dispose the corlett structure for the lib - we don't use it
            free(lib);
        }
    }

    free(file);
//	free(lib_decoded);

    // Finally, set psfby tag
    strcpy(psfby, "n/a");
    if (c)
    {
        int i;
        for (i = 0; i < MAX_UNKNOWN_TAGS; i++)
        {
            if (!strcasecmp(c->tag_name[i], "psfby"))
                strcpy(psfby, c->tag_data[i]);
        }
    }

    mips_init();
    mips_reset(NULL);

    // set the initial PC, SP, GP
#if DEBUG_LOADER
    printf("Initial PC %x, GP %x, SP %x\n", PC, GP, SP);
    printf("Refresh = %d\n", psf_refresh);
#endif
    mipsinfo.i = PC;
    mips_set_info(CPUINFO_INT_PC, &mipsinfo);

    // set some reasonable default for the stack
    if (SP == 0)
    {
        SP = 0x801fff00;
    }

    mipsinfo.i = SP;
    mips_set_info(CPUINFO_INT_REGISTER + MIPS_R29, &mipsinfo);
    mips_set_info(CPUINFO_INT_REGISTER + MIPS_R30, &mipsinfo);

    mipsinfo.i = GP;
    mips_set_info(CPUINFO_INT_REGISTER + MIPS_R28, &mipsinfo);

#if DEBUG_LOADER && 1
    {
        FILE *f;

        f = fopen("psxram.bin", "wb");
        fwrite(psx_ram, 2*1024*1024, 1, f);
        fclose(f);
    }
#endif

    psx_hw_init();
    SPUinit();
    SPUopen();

    lengthMS = psfTimeToMS(c->inf_length);
    fadeMS = psfTimeToMS(c->inf_fade);

#if DEBUG_LOADER
    printf("length %d fade %d\n", lengthMS, fadeMS);
#endif

    if (lengthMS == 0)
    {
        lengthMS = ~0;
    }

    setlength(lengthMS, fadeMS);

    // patch illegal Chocobo Dungeon 2 code - CaitSith2 put a jump in the delay slot from a BNE
    // and rely on Highly Experimental's buggy-ass CPU to rescue them.  Verified on real hardware
    // that the initial code is wrong.
    if (c->inf_game)
    {
        if (!strcmp(c->inf_game, "Chocobo Dungeon 2"))
        {
            if (psx_ram[0xbc090/4] == LE32(0x0802f040))
            {
                psx_ram[0xbc090/4] = LE32(0);
                psx_ram[0xbc094/4] = LE32(0x0802f040);
                psx_ram[0xbc098/4] = LE32(0);
            }
        }
    }

//	psx_ram[0x118b8/4] = LE32(0);	// crash 2 hack

    // backup the initial state for restart
    memcpy(initial_ram, psx_ram, 2*1024*1024);
    memcpy(initial_scratch, psx_scratch, 0x400);
    initialPC = PC;
    initialGP = GP;
    initialSP = SP;

    mips_execute(5000);

    return AO_SUCCESS;
}
int32 qsf_start(uint8 *buffer, uint32 length)
{
	uint8 *file, *lib_decoded, *lib_raw_file;
	uint64 file_len, lib_len, lib_raw_length;
	corlett_t *lib;

	z80_init();

	Z80ROM = malloc(512*1024);
	QSamples = malloc(8*1024*1024);

	skey1 = skey2 = 0;
	akey = 0;
	xkey = 0;
	cur_bank = 0;

	memset(RAM, 0, 0x1000);
	memset(RAM2, 0, 0x1000);
		
	// Decode the current QSF
	if (corlett_decode(buffer, length, &file, &file_len, &c) != AO_SUCCESS)
	{
		return AO_FAIL;
	}

	// Get the library file
	if (c->lib[0] != 0)
	{
		uint64 tmp_length;
	
		#if DEBUG_LOADER	
		printf("Loading library: %s\n", c->lib);
		#endif
		if (ao_get_lib(c->lib, &lib_raw_file, &tmp_length) != AO_SUCCESS)
		{
			return AO_FAIL;
		}
		lib_raw_length = tmp_length;
		
		if (corlett_decode(lib_raw_file, lib_raw_length, &lib_decoded, &lib_len, &lib) != AO_SUCCESS)
		{
			free(lib_raw_file);
			return AO_FAIL;
		}
				
		// Free up raw file
		free(lib_raw_file);

		// use the contents
		qsf_walktags(lib_decoded, lib_decoded+lib_len);
		
		// Dispose the corlett structure for the lib - we don't use it
		free(lib);
	}

	// now patch the file into RAM OVER the libraries
	qsf_walktags(file, file+file_len);

	free(file);

	if ((skey1 != 0) && (skey2 != 0))
	{
		#if DEBUG_LOADER
		printf("Decoding Kabuki: skey1 %08x skey2 %08x akey %04x xkey %02x\n", skey1, skey2, akey, xkey);
		#endif

		uses_kabuki = 1;
		cps1_decode((unsigned char *)Z80ROM, skey1, skey2, akey, xkey);
	}

	// set qsfby tag
	strcpy(qsfby, "n/a");
	if (c)
	{
		int i;
		for (i = 0; i < MAX_UNKNOWN_TAGS; i++)
		{
			if (!strcasecmp(c->tag_name[i], "qsfby"))
			{
				strcpy(qsfby, c->tag_data[i]);
			}
		}
	}

	z80_reset(NULL);
	z80_set_irq_callback(qsf_irq_cb);
	qsintf.sample_rom = QSamples;
	qsound_sh_start(&qsintf);

	return AO_SUCCESS;
}
// load and set up a 2sf file
int read_in_file(char *name) {
    FILE *file;
    uint32 filesig;
    uint8 *filedata;
    uint64 file_len;
    unsigned int size;
    struct stat st;

    c = NULL;

    file = fopen(name, "rb");

    if (!file) {
        RED();
        printf("ERROR: could not open file %s\n", name);
        NORMAL();
        return -1;
    }

    // get the length of the file by using fstat
    fstat(fileno(file), &st);

    if (st.st_size > UINT_MAX) {
        fclose(file);
        RED();
        printf("ERROR: file size of %zu bytes is larger than maximum supported value of %u\n", st.st_size, UINT_MAX);
        NORMAL();
        return -1;
    }

    size = (unsigned int) st.st_size;

    buffer = malloc((size_t) size);

    if (!buffer) {
        fclose(file);
        RED();
        printf("ERROR: could not allocate %d bytes of memory\n", size);
        NORMAL();
        return -1;
    }

    // read the file
    fread(buffer, size, 1, file);
    fclose(file);

    // init our *SF engine so we can get tags
    if (corlett_decode(buffer, size, &filedata, &file_len, &c) != AO_SUCCESS) {
        RED();
        printf("ERROR: Tag format unreadable in file ");
        MAGENTA();
        printf("%s\n", name);
        NORMAL();
        return -1;
    }
    free(filedata);    // we don't use this

    if (xsf_start(buffer, size) != XSF_TRUE) {
        RED();
        printf("ERROR: vio2sf failed to load file \n");
        MAGENTA();
        printf("%s\n", name);
        NORMAL();
        return -1;
    }

    return 0;
}