#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "ao.h"
#include "eng_protos.h"
#include "corlett.h"
#include "sat_hw.h"
#include "scsp.h"
#define DEBUG_LOADER (0)
static corlett_t *c = NULL;
static char psfby[256];
static uint32 decaybegin, decayend, total_samples;
void *scsp_start(const void *config);
void SCSP_Update(void *param, INT16 **inputs, INT16 **buf, int samples);
int32 ssf_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;
memset(sat_ram, 0, 512*1024);
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
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(lib_raw_file);
offset = lib_decoded[0] | lib_decoded[1]<<8 | lib_decoded[2]<<16 | lib_decoded[3]<<24;
if ((offset + (lib_len-4)) > 0x7ffff)
{
lib_len = 0x80000-offset+4;
}
memcpy(&sat_ram[offset], lib_decoded+4, lib_len-4);
free(lib);
}
}
offset = file[3]<<24 | file[2]<<16 | file[1]<<8 | file[0];
if ((offset + (file_len-4)) > 0x7ffff)
{
file_len = 0x80000-offset+4;
}
memcpy(&sat_ram[offset], file+4, file_len-4);
free(file);
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
for (i = 0; i < 512*1024; i+=2)
{
uint8 temp;
temp = sat_ram[i];
sat_ram[i] = sat_ram[i+1];
sat_ram[i+1] = temp;
}
sat_hw_init();
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 ssf_gen(int16 *buffer, uint32 samples)
{
int i;
int16 output[65536], output2[65536];
int16 *stereo[2];
int16 *outp = buffer;
int opos;
opos = 0;
for (i = 0; i < samples; i++)
{
m68k_execute((11300000/60)/735);
stereo[0] = &output[opos];
stereo[1] = &output2[opos];
SCSP_Update(NULL, NULL, stereo, 1);
opos++;
}
for (i = 0; i < samples; i++)
{
if (total_samples >= decaybegin)
{
if (total_samples >= decayend)
{
output[i] = 0;
output2[i] = 0;
}
else
{
int32 fader = 256 - (256*(total_samples - decaybegin)/(decayend-decaybegin));
output[i] = (output[i] * fader)>>8;
output2[i] = (output2[i] * fader)>>8;
total_samples++;
}
}
else
{
total_samples++;
}
*outp++ = output[i];
*outp++ = output2[i];
}
return AO_SUCCESS;
}
int32 ssf_stop(void)
{
return AO_SUCCESS;
}
int32 ssf_command(int32 command, int32 parameter)
{
switch (command)
{
case COMMAND_RESTART:
return AO_SUCCESS;
}
return AO_FAIL;
}
int32 ssf_fill_info(ao_display_info *info)
{
if (c == NULL)
return AO_FAIL;
strcpy(info->title[1], "Name: ");
sprintf(info->info[1], "%s", c->inf_title);
strcpy(info->title[2], "Game: ");
sprintf(info->info[2], "%s", c->inf_game);
strcpy(info->title[3], "Artist: ");
sprintf(info->info[3], "%s", c->inf_artist);
strcpy(info->title[4], "Copyright: ");
sprintf(info->info[4], "%s", c->inf_copy);
strcpy(info->title[5], "Year: ");
sprintf(info->info[5], "%s", c->inf_year);
strcpy(info->title[6], "Length: ");
sprintf(info->info[6], "%s", c->inf_length);
strcpy(info->title[7], "Fade: ");
sprintf(info->info[7], "%s", c->inf_fade);
strcpy(info->title[8], "Ripper: ");
sprintf(info->info[8], "%s", psfby);
return AO_SUCCESS;
}