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

Reply via email to