#include "GSFPlugin.h"
#include <coreutils/utils.h>
#include <psf/PSFFile.h>
#include <cstdio>
#include <cstdlib>
#include <set>
#include <unordered_map>
extern "C"
{
#include "VBA/psftag.h"
#include "gsf.h"
}
#include <coreutils/fifo.h>
extern "C"
{
int defvolume = 1000;
int relvolume = 1000;
int TrackLength = 0;
int FadeLength = 0;
int IgnoreTrackLength, DefaultLength = 150000;
int playforever = 1;
int fileoutput = 0;
int TrailingSilence = 1000;
int DetectSilence = 0, silencedetected = 0, silencelength = 5;
int cpupercent = 0, sndSamplesPerSec, sndNumChannels;
int sndBitsPerSample = 16;
int deflen = 120, deffade = 4;
int decode_pos_ms;
extern unsigned short soundFinalWave[2304];
extern int soundBufferLen;
}
static utils::Fifo<int16_t>* gsfFifo = nullptr;
extern "C" void end_of_track()
{
}
extern "C" void writeSound(void)
{
gsfFifo->put((short*)soundFinalWave, soundBufferLen / 2);
decode_pos_ms +=
(soundBufferLen / (2 * sndNumChannels) * 1000) / sndSamplesPerSec;
}
namespace musix {
class GSFPlayer : public ChipPlayer
{
public:
explicit GSFPlayer(const std::string& fileName)
: fifo(512 * 1024), psf{fileName}
{
decode_pos_ms = 0;
TrailingSilence = 1000;
IgnoreTrackLength = 1;
DetectSilence = 0;
silencedetected = 0;
playforever = 1;
gsfFifo = &fifo;
if (psf.valid()) {
auto& tags = psf.tags();
int seconds = psf.songLength();
setMeta("composer", tags["artist"], "sub_title", tags["title"],
"game", tags["game"], "format", "Gameboy Advance", "length",
seconds);
}
LOGD("GSF:{}", fileName.c_str());
int r = GSFRun(fileName.c_str());
if (r == 0) {
throw player_exception("GSFPlugin error: Could not load gsf");
}
}
~GSFPlayer() override { GSFClose(); }
int getSamples(int16_t* target, int noSamples) override
{
int lastTL = TrackLength;
int count = 100;
while (fifo.filled() < noSamples * 2 && count > 0) {
EmulationLoop();
count--;
}
if (count == 0) { return -1; }
if (decode_pos_ms > TrackLength && (playforever == 0)) { return -1; }
if (fifo.filled() == 0) { return 0; }
int len = fifo.get(target, noSamples);
return len;
}
private:
utils::Fifo<int16_t> fifo;
PSFFile psf;
};
static const std::set<std::string> supported_ext{"gsf", "minigsf"};
bool GSFPlugin::canHandle(const std::string& name)
{
auto ext = utils::path_extension(name);
return supported_ext.count(utils::path_extension(name)) > 0;
}
ChipPlayer* GSFPlugin::fromFile(const std::string& fileName)
{
return new GSFPlayer{fileName};
};
} extern "C" void gsfplugin_register()
{
musix::ChipPlugin::addPluginConstructor([](std::string const& config) {
return std::make_shared<musix::GSFPlugin>();
});
}