# HG changeset patch # User Matti Hamalainen # Date 1352400469 -7200 # Node ID d508c7c4bc69b91afc376d7438b5285da8c4a5f0 # Parent a7ee5dc23e780914aceaac6088389a16b202e04a Add libSIDPlay2-FP backend interface module. diff -r a7ee5dc23e78 -r d508c7c4bc69 Makefile.am --- a/Makefile.am Thu Nov 08 20:47:05 2012 +0200 +++ b/Makefile.am Thu Nov 08 20:47:49 2012 +0200 @@ -118,6 +118,7 @@ src/xs_sidplay.h \ src/xs_sidplay1.cpp src/xs_sidplay1.h \ src/xs_sidplay2.cpp src/xs_sidplay2.h \ + src/xs_sidplayfp.cpp src/xs_sidplayfp.h \ src/xs_slsup.c src/xs_slsup.h \ src/xs_player.h \ src/xmms-sid.c src/xmms-sid.h diff -r a7ee5dc23e78 -r d508c7c4bc69 src/xmms-sid.c --- a/src/xmms-sid.c Thu Nov 08 20:47:05 2012 +0200 +++ b/src/xmms-sid.c Thu Nov 08 20:47:49 2012 +0200 @@ -44,10 +44,13 @@ /* List of emulator engines */ #ifdef HAVE_SIDPLAY1 -#include "xs_sidplay1.h" +# include "xs_sidplay1.h" #endif #ifdef HAVE_SIDPLAY2 -#include "xs_sidplay2.h" +# include "xs_sidplay2.h" +#endif +#ifdef HAVE_SIDPLAY2 +# include "xs_sidplay2.h" #endif static XSEngine xs_enginelist[] = @@ -74,6 +77,17 @@ xs_sidplay2_flush }, #endif +#ifdef HAVE_SIDPLAY2_FP + { + XS_ENG_SIDPLAY2_FP, + xs_sidplayfp_probe, + xs_sidplayfp_init, xs_sidplayfp_close, + xs_sidplayfp_initsong, xs_sidplayfp_fillbuffer, + xs_sidplayfp_load, xs_sidplayfp_delete, + xs_sidplayfp_getinfo, xs_sidplayfp_updateinfo, + xs_sidplayfp_flush + }, +#endif }; static const gint xs_nenginelist = sizeof(xs_enginelist) / sizeof(xs_enginelist[0]); diff -r a7ee5dc23e78 -r d508c7c4bc69 src/xs_config.h --- a/src/xs_config.h Thu Nov 08 20:47:05 2012 +0200 +++ b/src/xs_config.h Thu Nov 08 20:47:49 2012 +0200 @@ -13,7 +13,8 @@ */ enum XS_EMUENGINE { XS_ENG_SIDPLAY1 = 1, - XS_ENG_SIDPLAY2 + XS_ENG_SIDPLAY2, + XS_ENG_SIDPLAY2_FP }; diff -r a7ee5dc23e78 -r d508c7c4bc69 src/xs_sidplayfp.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/xs_sidplayfp.cpp Thu Nov 08 20:47:49 2012 +0200 @@ -0,0 +1,382 @@ +/* + XMMS-SID - SIDPlay input plugin for X MultiMedia System (XMMS) + + libSIDPlay v2-FP support + + Programmed and designed by Matti 'ccr' Hamalainen + (C) Copyright 1999-2012 Tecnic Software productions (TNSP) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ +#include "xmms-sid.h" + +#ifdef HAVE_SIDPLAY2_FP + +#include +#include "xs_sidplay2.h" +#include "xs_config.h" + + +#ifdef HAVE_SIDPLAY2_FP_V1 +# include +# include +# include +# include +# include +#else +# include +# include +# include +#endif + + +class XSSIDPlayFP { +public: +#ifdef HAVE_SIDPLAY2_FP_V1 + sidplayfp emu; + SidConfig config; +#else + sidplay2 emu; + sid2_config_t config; +#endif + SidTune tune; + + XSSIDPlayFP(void); + virtual ~XSSIDPlayFP(void); +}; + + +#ifdef HAVE_RESID_BUILDER +# include +# include +#endif + +#ifdef HAVE_HARDSID_BUILDER +# include +#endif + + +XSSIDPlayFP::XSSIDPlayFP(void) : tune(0) +{ +} + + +XSSIDPlayFP::~XSSIDPlayFP(void) +{ + emu.load(NULL); +} + + +/* We need to 'export' all this pseudo-C++ crap */ +extern "C" { + + +/* Return song information + */ +#define TFUNCTION xs_sidplayfp_getinfo +#define TFUNCTION2 xs_sidplayfp_updateinfo +#define TENGINE XSSIDPlayFP +#define TTUNEINFO SidTuneInfo +#define TTUNE SidTune + +#ifdef HAVE_SIDPLAY2_FP_V1 +#define sid2_mono SidConfig::MONO +#define sid2_stereo SidConfig::STEREO +#define SID2_MOS8580 SidConfig::MOS8580 +#define SID2_MOS6581 SidConfig::MOS6581 +#define SID2_CLOCK_PAL SidConfig::CLOCK_PAL +#define SID2_CLOCK_NTSC SidConfig::CLOCK_NTSC +#define SIDTUNE_CLOCK_UNKNOWN SidTuneInfo::CLOCK_UNKNOWN +#define SIDTUNE_CLOCK_PAL SidTuneInfo::CLOCK_PAL +#define SIDTUNE_CLOCK_NTSC SidTuneInfo::CLOCK_NTSC +#define SIDTUNE_CLOCK_ANY SidTuneInfo::CLOCK_ANY +#define SIDTUNE_SPEED_VBI SidTuneInfo::SPEED_VBI +#define SIDTUNE_SPEED_CIA_1A SidTuneInfo::SPEED_CIA_1A +#endif + +#include "xs_sidplay.h" + + +/* Check if we can play the given file + */ +gboolean xs_sidplayfp_probe(XSFile *f) +{ + gchar tmpBuf[5]; + + if (!f) return FALSE; + + if (xs_fread(tmpBuf, sizeof(gchar), 4, f) != 4) + return FALSE; + + if (!strncmp(tmpBuf, "PSID", 4) || !strncmp(tmpBuf, "RSID", 4)) + return TRUE; + else + return FALSE; +} + + +/* Initialize SIDPlay2 + */ +gboolean xs_sidplayfp_init(XSEngineState * state) +{ + XSSIDPlayFP *engine; + assert(state); + + /* Allocate internal structures */ + engine = new XSSIDPlayFP(); + state->internal = engine; + if (!engine) + return FALSE; + + /* Get current configuration */ + engine->config = engine->emu.config(); + + /* Configure channels and stuff */ + engine->config.playback = (state->audioChannels == XS_CHN_MONO) ? sid2_mono : sid2_stereo; + + /* Audio parameters sanity checking and setup */ + state->audioBitsPerSample = XS_RES_16BIT; + engine->config.samplingMethod = SID2_RESAMPLE_INTERPOLATE; + engine->config.frequency = state->audioFrequency; + + /* Initialize builder object */ + XSDEBUG("init builder #%i, maxsids=%i\n", xs_cfg.sid2Builder, (engine->emu.info()).maxsids); + + switch (xs_cfg.sid2Builder) + { +#ifdef HAVE_RESID_BUILDER + case XS_BLD_RESID: + { + ReSIDBuilder *rs = new ReSIDBuilder("ReSID builder"); +#ifdef HAVE_SIDPLAY2_FP_V1 + if (rs && rs->getStatus()) + { + } +#else + if (rs) + { + engine->config.sidEmulation = rs; + if (!*rs) return FALSE; + rs->create((engine->emu.info()).maxsids); + if (!*rs) return FALSE; + rs->bias(0.0f); + } +#endif // HAVE_SIDPLAY2_FP_V1 + } + break; +#endif // HAVE_RESID_BUILDER + + +#ifdef HAVE_RESID_FP_BUILDER + case XS_BLD_RESID_FP: + { + ReSIDfpBuilder *rs = new ReSIDfpBuilder("ReSID builder FP!"); + if (rs) + { + engine->config.sidEmulation = rs; + if (!*rs) return FALSE; + rs->create((engine->emu.info()).maxsids); + if (!*rs) return FALSE; + + rs->filter6581Curve(0.0); + rs->filter8580Curve(0.0); + } + } + break; +#endif + +#ifdef HAVE_HARDSID_BUILDER + case XS_BLD_HARDSID: + { + HardSIDBuilder *hs = new HardSIDBuilder("HardSID builder (FP)"); + engine->config.sidEmulation = (sidbuilder *) hs; + if (hs) + { + hs->create((engine->emu.info()).maxsids); + if (!*hs) + { + xs_error("hardSID->create() failed.\n"); + return FALSE; + } + } + } + break; +#endif + + default: + xs_error("[SIDPlay2] Invalid or unsupported builder selected.\n"); + break; + } + + if (!engine->config.sidEmulation) + { + xs_error("[SIDPlay2] Could not initialize SIDBuilder object.\n"); + return FALSE; + } + + // Setup filter + engine->config.sidEmulation->filter(xs_cfg.emulateFilters); + if (!*(engine->config.sidEmulation)) + { + xs_error("builder->filter(%d) failed.\n", xs_cfg.emulateFilters); + return FALSE; + } + + XSDEBUG("%s\n", engine->config.sidEmulation->credits()); + + /* Clockspeed settings */ + switch (xs_cfg.clockSpeed) + { + case XS_CLOCK_NTSC: + engine->config.clockDefault = SID2_CLOCK_NTSC; + break; + + default: + case XS_CLOCK_PAL: + engine->config.clockDefault = SID2_CLOCK_PAL; + xs_cfg.clockSpeed = XS_CLOCK_PAL; + break; + } + + + /* Configure rest of the emulation */ + engine->config.sidDefault = xs_cfg.mos8580 ? SID2_MOS8580 : SID2_MOS6581; + engine->config.clockForced = xs_cfg.forceSpeed; + +#ifndef HAVE_SIDPLAY2_FP_V1 + engine->config.sidSamples = TRUE; + engine->config.sidModel = xs_cfg.forceModel ? engine->config.sidDefault : SID2_MODEL_CORRECT; + engine->config.clockSpeed = xs_cfg.forceSpeed ? engine->config.clockDefault : SID2_CLOCK_CORRECT; +#endif + + return TRUE; +} + + +/* Close SIDPlay2 engine + */ +void xs_sidplayfp_close(XSEngineState * state) +{ + XSSIDPlayFP *engine = (XSSIDPlayFP *) state->internal; + + xs_sidplayfp_delete(state); + + if (engine) + { + delete engine; + engine = NULL; + } + + state->internal = NULL; +} + + +/* Initialize current song and sub-tune + */ +gboolean xs_sidplayfp_initsong(XSEngineState * state) +{ + XSSIDPlayFP *engine = (XSSIDPlayFP *) state->internal; + + if (!engine) + return FALSE; + + if (!engine->tune.selectSong(state->currSong)) + { + xs_error("[SIDPlay2] tune.selectSong() failed\n"); + return FALSE; + } + + if (engine->emu.load(&(engine->tune)) < 0) + { + xs_error("[SIDPlay2] emu.load() failed\n"); + return FALSE; + } + + if (engine->emu.config(engine->config) < 0) + { + xs_error("[SIDPlay2] Emulator engine configuration failed!\n"); + return FALSE; + } + + return TRUE; +} + + +/* Emulate and render audio data to given buffer + */ +guint xs_sidplayfp_fillbuffer(XSEngineState * state, gchar * audioBuffer, guint audioBufSize) +{ + XSSIDPlayFP *engine = (XSSIDPlayFP *) state->internal; + + if (!engine) + return 0; + +#if 1 + int nsamples = audioBufSize / sizeof(short); + return engine->emu.play((short *) audioBuffer, nsamples) * sizeof(short); +#else + int nsamples = audioBufSize / sizeof(short); + fprintf(stderr, "%p, %d -> %d\n", audioBuffer, audioBufSize, nsamples); + return 0; +#endif +} + + +/* Load a given SID-tune file + */ +gboolean xs_sidplayfp_load(XSEngineState * state, gchar * filename) +{ + XSSIDPlayFP *engine = (XSSIDPlayFP *) state->internal; + + if (!engine || !filename) + return FALSE; + + engine->tune.load(filename); + if (!engine->tune) + { + xs_error("Could not load file '%s': %s\n", + filename, (engine->tune.getInfo()).statusString); + return FALSE; + } + + return TRUE; +} + + +/* Delete INTERNAL information + */ +void xs_sidplayfp_delete(XSEngineState * state) +{ + XSSIDPlayFP *engine = (XSSIDPlayFP *) state->internal; +} + + +/* Hardware backend flushing + */ +void xs_sidplayfp_flush(XSEngineState * state) +{ + XSSIDPlayFP *engine = (XSSIDPlayFP *) state->internal; + +#ifdef HAVE_HARDSID_BUILDER + if (xs_cfg.sid2Builder == XS_BLD_HARDSID) + { + ((HardSIDBuilder *) engine->config.sidEmulation)->flush(); + } +#endif +} + + +} /* extern "C" */ +#endif /* HAVE_SIDPLAY2_FP */ diff -r a7ee5dc23e78 -r d508c7c4bc69 src/xs_sidplayfp.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/xs_sidplayfp.h Thu Nov 08 20:47:49 2012 +0200 @@ -0,0 +1,25 @@ +#ifndef XS_SIDPLAYFP_H +#define XS_SIDPLAYFP_H + +#include "xs_player.h" +#include "xs_support.h" + +#ifdef __cplusplus +extern "C" { +#endif + +gboolean xs_sidplayfp_probe(XSFile *); +void xs_sidplayfp_close(XSEngineState *); +gboolean xs_sidplayfp_init(XSEngineState *); +gboolean xs_sidplayfp_initsong(XSEngineState *); +guint xs_sidplayfp_fillbuffer(XSEngineState *, gchar *, guint); +gboolean xs_sidplayfp_load(XSEngineState *, gchar *); +void xs_sidplayfp_delete(XSEngineState *); +XSTuneInfo* xs_sidplayfp_getinfo(const gchar *); +gboolean xs_sidplayfp_updateinfo(XSEngineState *); +void xs_sidplayfp_flush(XSEngineState *); + +#ifdef __cplusplus +} +#endif +#endif /* XS_SIDPLAYFP_H */