cog/Frameworks/AudioOverload/aosdk/eng_dsf/eng_dsf.c

262 lines
4.9 KiB
C

//
// Audio Overload
// Emulated music player
//
// (C) 2000-2008 Richard F. Bannister
//
//
// eng_dsf.c
//
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "ao.h"
#include "eng_protos.h"
#include "corlett.h"
#include "dc_hw.h"
#include "aica.h"
#define DEBUG_LOADER (0)
#define DK_CORE (1)
#if DK_CORE
#include "arm7.h"
#else
#include "arm7core.h"
#endif
static corlett_t *c = NULL;
static char psfby[256];
static uint32 decaybegin, decayend, total_samples;
void *aica_start(const void *config);
void aica_stop(void);
void AICA_Update(void *param, INT16 **inputs, INT16 **buf, int samples);
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);
free(lib_decoded);
}
}
// 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;
}
int32 dsf_gen(int16 *buffer, uint32 samples)
{
int i;
int16 output[44100/30], output2[44100/30];
int16 *stereo[2];
int16 *outp = buffer;
int opos;
opos = 0;
for (i = 0; i < samples; i++)
{
#if DK_CORE
ARM7_Execute((33000000 / 60 / 4) / 735);
#else
arm7_execute((33000000 / 60 / 4) / 735);
#endif
stereo[0] = &output[opos];
stereo[1] = &output2[opos];
AICA_Update(NULL, NULL, stereo, 1);
opos++;
}
for (i = 0; i < samples; i++)
{
// process the fade tags
if (total_samples >= decaybegin)
{
if (total_samples >= decayend)
{
// song is done here, signal your player appropriately!
// ao_song_done = 1;
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 dsf_stop(void)
{
aica_stop();
free(c);
return AO_SUCCESS;
}
int32 dsf_command(int32 command, int32 parameter)
{
switch (command)
{
case COMMAND_RESTART:
return AO_SUCCESS;
}
return AO_FAIL;
}
int32 dsf_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;
}