package: src:game-music-emu severity: wishlist control: tag -1 patch Upstream provides a public interface to the snes_spc library in a separate download not included with gme [0]. Some games rely on this interface, for example eternity [1].
I've prepared a patch that adds the SPC interface as a separate library, see attached. I copied the snes_spc files directly into debian/spc, but maybe this could be cleaner as a multiple upstream source package. If you would prefer that approach, please let me know and I will refactor. Thank you for considering. Best wishes, Mike [0] http://blargg.parodius.com/libs/snes_spc-0.9.0.zip [1] http://ftp-master.debian.org/new/eternity_3.42.02-1.html
diff -Nru game-music-emu-0.6.1/debian/control game-music-emu-0.6.1/debian/control --- game-music-emu-0.6.1/debian/control 2015-09-19 16:51:41.000000000 +0000 +++ game-music-emu-0.6.1/debian/control 2017-05-22 00:40:24.000000000 +0000 @@ -53,3 +53,21 @@ This package contains the header files, static libraries and symbolic links that developers using libgme will need. +Package: libgme-spc0 +Architecture: any +Multi-Arch: same +Section: libs +Depends: ${shlibs:Depends}, + ${misc:Depends} +Description: Playback library for SPC video game music files - shared library + This package contains the shared libraries necessary to run programs + using SPC. + +Package: libgme-spc-dev +Architecture: any +Multi-Arch: same +Section: libdevel +Depends: ${misc:Depends} +Description: Playback library for SPC video game music files - development files + This package contains the header files, static libraries + and symbolic links that developers using SPC library will need. diff -Nru game-music-emu-0.6.1/debian/libgme-spc0.install game-music-emu-0.6.1/debian/libgme-spc0.install --- game-music-emu-0.6.1/debian/libgme-spc0.install 1970-01-01 00:00:00.000000000 +0000 +++ game-music-emu-0.6.1/debian/libgme-spc0.install 2017-05-22 00:40:24.000000000 +0000 @@ -0,0 +1 @@ +debian/tmp/usr/lib/*/libgme-spc.so.* diff -Nru game-music-emu-0.6.1/debian/libgme-spc-dev.install game-music-emu-0.6.1/debian/libgme-spc-dev.install --- game-music-emu-0.6.1/debian/libgme-spc-dev.install 1970-01-01 00:00:00.000000000 +0000 +++ game-music-emu-0.6.1/debian/libgme-spc-dev.install 2017-05-22 00:40:24.000000000 +0000 @@ -0,0 +1,2 @@ +debian/tmp/usr/lib/*/libgme-spc.so +debian/tmp/usr/include/gme/spc.h diff -Nru game-music-emu-0.6.1/debian/patches/series game-music-emu-0.6.1/debian/patches/series --- game-music-emu-0.6.1/debian/patches/series 2017-01-30 17:10:39.000000000 +0000 +++ game-music-emu-0.6.1/debian/patches/series 2017-05-22 00:40:24.000000000 +0000 @@ -1,2 +1,3 @@ 01_enable-zlib.patch 03_link-zlib.patch +spc.patch diff -Nru game-music-emu-0.6.1/debian/patches/spc.patch game-music-emu-0.6.1/debian/patches/spc.patch --- game-music-emu-0.6.1/debian/patches/spc.patch 1970-01-01 00:00:00.000000000 +0000 +++ game-music-emu-0.6.1/debian/patches/spc.patch 2017-05-22 00:40:24.000000000 +0000 @@ -0,0 +1,10 @@ +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -88,6 +88,7 @@ endif (CMAKE_COMPILER_IS_GNUCXX) + + # Shared library defined here + add_subdirectory(gme) ++add_subdirectory(debian/spc) + + # EXCLUDE_FROM_ALL adds build rules but keeps it out of default build + add_subdirectory(player EXCLUDE_FROM_ALL) diff -Nru game-music-emu-0.6.1/debian/rules game-music-emu-0.6.1/debian/rules --- game-music-emu-0.6.1/debian/rules 2015-07-22 21:51:31.000000000 +0000 +++ game-music-emu-0.6.1/debian/rules 2017-05-22 00:40:24.000000000 +0000 @@ -8,7 +8,7 @@ override_dh_auto_install: dh_auto_install mkdir debian/tmp/usr/lib/$(DEB_HOST_MULTIARCH) - mv debian/tmp/usr/lib/libgme.so* debian/tmp/usr/lib/$(DEB_HOST_MULTIARCH) + mv debian/tmp/usr/lib/libgme*.so* debian/tmp/usr/lib/$(DEB_HOST_MULTIARCH) override_dh_makeshlibs: dh_makeshlibs -- -c4 diff -Nru game-music-emu-0.6.1/debian/spc/CMakeLists.txt game-music-emu-0.6.1/debian/spc/CMakeLists.txt --- game-music-emu-0.6.1/debian/spc/CMakeLists.txt 1970-01-01 00:00:00.000000000 +0000 +++ game-music-emu-0.6.1/debian/spc/CMakeLists.txt 2017-05-22 00:40:24.000000000 +0000 @@ -0,0 +1,8 @@ +FILE(GLOB SPC_SOURCES *.cpp ../../gme/Snes_Spc.cpp ../../gme/Spc_Filter.cpp ../../gme/Spc_Cpu.cpp ../../gme/Spc_Dsp.cpp) +INCLUDE_DIRECTORIES(../../gme) +ADD_LIBRARY(gme-spc SHARED ${SPC_SOURCES}) +SET_TARGET_PROPERTIES(gme-spc PROPERTIES VERSION ${GME_VERSION} SOVERSION 0) + +install(TARGETS gme-spc LIBRARY DESTINATION lib${LIB_SUFFIX}) + +install(FILES spc.h DESTINATION include/gme) diff -Nru game-music-emu-0.6.1/debian/spc/spc.cpp game-music-emu-0.6.1/debian/spc/spc.cpp --- game-music-emu-0.6.1/debian/spc/spc.cpp 1970-01-01 00:00:00.000000000 +0000 +++ game-music-emu-0.6.1/debian/spc/spc.cpp 2017-05-22 00:40:24.000000000 +0000 @@ -0,0 +1,71 @@ +// snes_spc 0.9.0. http://www.slack.net/~ant/ + +#include "spc.h" + +#include "Snes_Spc.h" +#include "Spc_Filter.h" + +/* Copyright (C) 2004-2007 Shay Green. This module is free software; you +can redistribute it and/or modify it under the terms of the GNU Lesser +General Public License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. This +module 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 Lesser General Public License for more +details. You should have received a copy of the GNU Lesser General Public +License along with this module; if not, write to the Free Software Foundation, +Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ + +#include "blargg_source.h" + +BLARGG_EXPORT SNES_SPC* spc_new( void ) +{ + // be sure constants match + assert( spc_sample_rate == (int) SNES_SPC::sample_rate ); + assert( spc_rom_size == (int) SNES_SPC::rom_size ); + assert( spc_clock_rate == (int) SNES_SPC::clock_rate ); + assert( spc_clocks_per_sample == (int) SNES_SPC::clocks_per_sample ); + assert( spc_port_count == (int) SNES_SPC::port_count ); + assert( spc_voice_count == (int) SNES_SPC::voice_count ); + assert( spc_tempo_unit == (int) SNES_SPC::tempo_unit ); + assert( spc_file_size == (int) SNES_SPC::spc_file_size ); + #if !SPC_NO_COPY_STATE_FUNCS + assert( spc_state_size == (int) SNES_SPC::state_size ); + #endif + + SNES_SPC* s = new SNES_SPC; + if ( s && s->init() ) + { + delete s; + s = 0; + } + return s; +} + +BLARGG_EXPORT void spc_delete ( SNES_SPC* s ) { delete s; } +BLARGG_EXPORT void spc_set_output ( SNES_SPC* s, spc_sample_t* p, int n ) { s->set_output( p, n ); } +BLARGG_EXPORT int spc_sample_count ( SNES_SPC const* s ) { return s->sample_count(); } +BLARGG_EXPORT void spc_soft_reset ( SNES_SPC* s ) { s->soft_reset(); } +BLARGG_EXPORT int spc_read_port ( SNES_SPC* s, spc_time_t t, int p ) { return s->read_port( t, p ); } +BLARGG_EXPORT void spc_write_port ( SNES_SPC* s, spc_time_t t, int p, int d ) { s->write_port( t, p, d ); } +BLARGG_EXPORT void spc_end_frame ( SNES_SPC* s, spc_time_t t ) { s->end_frame( t ); } +BLARGG_EXPORT void spc_mute_voices ( SNES_SPC* s, int mask ) { s->mute_voices( mask ); } +BLARGG_EXPORT void spc_disable_surround( SNES_SPC* s, int disable ) { s->disable_surround( disable ); } +BLARGG_EXPORT void spc_set_tempo ( SNES_SPC* s, int tempo ) { s->set_tempo( tempo ); } +BLARGG_EXPORT spc_err_t spc_load_spc ( SNES_SPC* s, void const* p, long n ) { return s->load_spc( p, n ); } +BLARGG_EXPORT void spc_clear_echo ( SNES_SPC* s ) { s->clear_echo(); } +BLARGG_EXPORT spc_err_t spc_play ( SNES_SPC* s, int count, short* out ) { return s->play( count, out ); } +BLARGG_EXPORT spc_err_t spc_skip ( SNES_SPC* s, int count ) { return s->skip( count ); } +#if !SPC_NO_COPY_STATE_FUNCS +BLARGG_EXPORT void spc_copy_state ( SNES_SPC* s, unsigned char** p, spc_copy_func_t f ) { s->copy_state( p, f ); } +BLARGG_EXPORT void spc_init_header ( void* spc_out ) { SNES_SPC::init_header( spc_out ); } +BLARGG_EXPORT void spc_save_spc ( SNES_SPC* s, void* spc_out ) { s->save_spc( spc_out ); } +BLARGG_EXPORT int spc_check_kon ( SNES_SPC* s ) { return s->check_kon(); } +#endif + +BLARGG_EXPORT SPC_Filter* spc_filter_new( void ) { return new SPC_Filter; } +BLARGG_EXPORT void spc_filter_delete( SPC_Filter* f ) { delete f; } +BLARGG_EXPORT void spc_filter_run( SPC_Filter* f, spc_sample_t* p, int s ) { f->run( p, s ); } +BLARGG_EXPORT void spc_filter_clear( SPC_Filter* f ) { f->clear(); } +BLARGG_EXPORT void spc_filter_set_gain( SPC_Filter* f, int gain ) { f->set_gain( gain ); } +BLARGG_EXPORT void spc_filter_set_bass( SPC_Filter* f, int bass ) { f->set_bass( bass ); } diff -Nru game-music-emu-0.6.1/debian/spc/spc.h game-music-emu-0.6.1/debian/spc/spc.h --- game-music-emu-0.6.1/debian/spc/spc.h 1970-01-01 00:00:00.000000000 +0000 +++ game-music-emu-0.6.1/debian/spc/spc.h 2017-05-22 00:40:24.000000000 +0000 @@ -0,0 +1,147 @@ +/* SNES SPC-700 APU emulator C interface (also usable from C++) */ + +/* snes_spc 0.9.0 */ +#ifndef SPC_H +#define SPC_H + +#include <stddef.h> + +#ifdef __cplusplus + extern "C" { +#endif + +/* Error string return. NULL if success, otherwise error message. */ +typedef const char* spc_err_t; + +typedef struct Snes_Spc SNES_SPC; + +/* Creates new SPC emulator. NULL if out of memory. */ +SNES_SPC* spc_new( void ); + +/* Frees SPC emulator */ +void spc_delete( SNES_SPC* ); + +/* Sample pairs generated per second */ +enum { spc_sample_rate = 32000 }; + + +/**** Emulator use ****/ + +/* Sets IPL ROM data. Library does not include ROM data. Most SPC music files +don't need ROM, but a full emulator must provide this. */ +enum { spc_rom_size = 0x40 }; +void spc_init_rom( SNES_SPC*, unsigned char const rom [spc_rom_size] ); + +/* Sets destination for output samples */ +typedef short spc_sample_t; +void spc_set_output( SNES_SPC*, spc_sample_t* out, int out_size ); + +/* Number of samples written to output since last set */ +int spc_sample_count( SNES_SPC const* ); + +/* Resets SPC to power-on state. This resets your output buffer, so you must +call spc_set_output() after this. */ +void spc_reset( SNES_SPC* ); + +/* Emulates pressing reset switch on SNES. This resets your output buffer, so +you must call spc_set_output() after this. */ +void spc_soft_reset( SNES_SPC* ); + +/* 1024000 SPC clocks per second, sample pair every 32 clocks */ +typedef int spc_time_t; +enum { spc_clock_rate = 1024000 }; +enum { spc_clocks_per_sample = 32 }; + +/* Reads/writes port at specified time */ +enum { spc_port_count = 4 }; +int spc_read_port ( SNES_SPC*, spc_time_t, int port ); +void spc_write_port( SNES_SPC*, spc_time_t, int port, int data ); + +/* Runs SPC to end_time and starts a new time frame at 0 */ +void spc_end_frame( SNES_SPC*, spc_time_t end_time ); + + +/**** Sound control ****/ + +/*Mutes voices corresponding to non-zero bits in mask. Reduces emulation accuracy. */ +enum { spc_voice_count = 8 }; +void spc_mute_voices( SNES_SPC*, int mask ); + +/* If true, prevents channels and global volumes from being phase-negated. +Only supported by fast DSP; has no effect on accurate DSP. */ +void spc_disable_surround( SNES_SPC*, int disable ); + +/* Sets tempo, where spc_tempo_unit = normal, spc_tempo_unit / 2 = half speed, etc. */ +enum { spc_tempo_unit = 0x100 }; +void spc_set_tempo( SNES_SPC*, int ); + + +/**** SPC music playback *****/ + +/* Loads SPC data into emulator. Returns NULL on success, otherwise error string. */ +spc_err_t spc_load_spc( SNES_SPC*, void const* spc_in, long size ); + +/* Clears echo region. Useful after loading an SPC as many have garbage in echo. */ +void spc_clear_echo( SNES_SPC* ); + +/* Plays for count samples and write samples to out. Discards samples if out +is NULL. Count must be a multiple of 2 since output is stereo. */ +spc_err_t spc_play( SNES_SPC*, int count, short* out ); + +/* Skips count samples. Several times faster than spc_play(). */ +spc_err_t spc_skip( SNES_SPC*, int count ); + + +/**** State save/load (only available with accurate DSP) ****/ + +/* Saves/loads exact emulator state */ +enum { spc_state_size = 67 * 1024L }; /* maximum space needed when saving */ +typedef void (*spc_copy_func_t)( unsigned char** io, void* state, size_t ); +void spc_copy_state( SNES_SPC*, unsigned char** io, spc_copy_func_t ); + +/* Writes minimal SPC file header to spc_out */ +void spc_init_header( void* spc_out ); + +/* Saves emulator state as SPC file data. Writes spc_file_size bytes to spc_out. +Does not set up SPC header; use spc_init_header() for that. */ +enum { spc_file_size = 0x10200 }; /* spc_out must have this many bytes allocated */ +void spc_save_spc( SNES_SPC*, void* spc_out ); + +/* Returns non-zero if new key-on events occurred since last check. Useful for +trimming silence while saving an SPC. */ +int spc_check_kon( SNES_SPC* ); + + +/**** SPC_Filter ****/ + +typedef struct SPC_Filter SPC_Filter; + +/* Creates new filter. NULL if out of memory. */ +SPC_Filter* spc_filter_new( void ); + +/* Frees filter */ +void spc_filter_delete( SPC_Filter* ); + +/* Filters count samples of stereo sound in place. Count must be a multiple of 2. */ +void spc_filter_run( SPC_Filter*, spc_sample_t* io, int count ); + +/* Clears filter to silence */ +void spc_filter_clear( SPC_Filter* ); + +/* Sets gain (volume), where spc_filter_gain_unit is normal. Gains greater than +spc_filter_gain_unit are fine, since output is clamped to 16-bit sample range. */ +enum { spc_filter_gain_unit = 0x100 }; +void spc_filter_set_gain( SPC_Filter*, int gain ); + +/* Sets amount of bass (logarithmic scale) */ +enum { spc_filter_bass_none = 0 }; +enum { spc_filter_bass_norm = 8 }; /* normal amount */ +enum { spc_filter_bass_max = 31 }; +void spc_filter_set_bass( SPC_Filter*, int bass ); + + +#ifdef __cplusplus + } +#endif + +#endif