mirror of
https://github.com/ZDoom/gzdoom.git
synced 2024-11-22 12:11:25 +00:00
Upgrade game-music-emu to version 0.6.0
This commit is contained in:
parent
1d1289722f
commit
fbddfbe576
95 changed files with 1139 additions and 650 deletions
|
@ -1,5 +1,15 @@
|
|||
cmake_minimum_required( VERSION 2.4 )
|
||||
include( CheckCXXCompilerFlag )
|
||||
# CMake project definition file.
|
||||
project(libgme)
|
||||
|
||||
include (CheckCXXCompilerFlag)
|
||||
|
||||
# When version is changed, also change the one in gme/gme.h to match
|
||||
set(GME_VERSION 0.6.0 CACHE INTERNAL "libgme Version")
|
||||
|
||||
# 2.6+ always assumes FATAL_ERROR, but 2.4 and below don't.
|
||||
# Of course, 2.4 might work, in which case you're welcome to drop
|
||||
# down the requirement, but I can't test that.
|
||||
cmake_minimum_required(VERSION 2.6 FATAL_ERROR)
|
||||
|
||||
make_release_only()
|
||||
|
||||
|
@ -19,51 +29,80 @@ if( "${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" OR "${CMAKE_CXX_COMPILER_ID}" STRE
|
|||
endif( HAVE_NO_ARRAY_BOUNDS )
|
||||
endif( "${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" OR "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang" )
|
||||
|
||||
add_library( gme
|
||||
gme/Blip_Buffer.cpp
|
||||
gme/Classic_Emu.cpp
|
||||
gme/Data_Reader.cpp
|
||||
gme/Dual_Resampler.cpp
|
||||
gme/Effects_Buffer.cpp
|
||||
gme/Fir_Resampler.cpp
|
||||
gme/gme.cpp
|
||||
gme/Gme_File.cpp
|
||||
gme/M3u_Playlist.cpp
|
||||
gme/Multi_Buffer.cpp
|
||||
gme/Music_Emu.cpp
|
||||
|
||||
gme/Ay_Apu.cpp
|
||||
gme/Ay_Cpu.cpp
|
||||
gme/Ay_Emu.cpp
|
||||
gme/Gb_Apu.cpp
|
||||
gme/Gb_Cpu.cpp
|
||||
gme/Gb_Oscs.cpp
|
||||
gme/Gbs_Emu.cpp
|
||||
gme/Gym_Emu.cpp
|
||||
gme/Hes_Apu.cpp
|
||||
gme/Hes_Cpu.cpp
|
||||
gme/Hes_Emu.cpp
|
||||
gme/Kss_Cpu.cpp
|
||||
gme/Kss_Emu.cpp
|
||||
gme/Kss_Scc_Apu.cpp
|
||||
gme/Nes_Apu.cpp
|
||||
gme/Nes_Cpu.cpp
|
||||
gme/Nes_Fme7_Apu.cpp
|
||||
gme/Nes_Namco_Apu.cpp
|
||||
gme/Nes_Oscs.cpp
|
||||
gme/Nes_Vrc6_Apu.cpp
|
||||
gme/Nsf_Emu.cpp
|
||||
gme/Nsfe_Emu.cpp
|
||||
gme/Sap_Apu.cpp
|
||||
gme/Sap_Cpu.cpp
|
||||
gme/Sap_Emu.cpp
|
||||
gme/Sms_Apu.cpp
|
||||
gme/Snes_Spc.cpp
|
||||
gme/Spc_Cpu.cpp
|
||||
gme/Spc_Dsp.cpp
|
||||
gme/Spc_Emu.cpp
|
||||
gme/Vgm_Emu.cpp
|
||||
gme/Vgm_Emu_Impl.cpp
|
||||
gme/Ym2413_Emu.cpp
|
||||
gme/Ym2612_Emu.cpp )
|
||||
target_link_libraries( gme )
|
||||
|
||||
|
||||
# Default emulators to build (all of them! ;)
|
||||
if (NOT DEFINED USE_GME_AY)
|
||||
SET(USE_GME_AY 1 CACHE BOOL "Enable support for Spectrum ZX music emulation")
|
||||
endif()
|
||||
|
||||
if (NOT DEFINED USE_GME_GBS)
|
||||
SET(USE_GME_GBS 1 CACHE BOOL "Enable support for Game Boy music emulation")
|
||||
endif()
|
||||
|
||||
if (NOT DEFINED USE_GME_GYM)
|
||||
SET(USE_GME_GYM 1 CACHE BOOL "Enable Sega MegaDrive/Genesis music emulation")
|
||||
endif()
|
||||
|
||||
if (NOT DEFINED USE_GME_HES)
|
||||
SET(USE_GME_HES 1 CACHE BOOL "Enable PC Engine/TurboGrafx-16 music emulation")
|
||||
endif()
|
||||
|
||||
if (NOT DEFINED USE_GME_KSS)
|
||||
SET(USE_GME_KSS 1 CACHE BOOL "Enable MSX or other Z80 systems music emulation")
|
||||
endif()
|
||||
|
||||
if (NOT DEFINED USE_GME_NSF)
|
||||
SET(USE_GME_NSF 1 CACHE BOOL "Enable NES NSF music emulation")
|
||||
endif()
|
||||
|
||||
if (NOT DEFINED USE_GME_NSFE)
|
||||
SET(USE_GME_NSFE 1 CACHE BOOL "Enable NES NSFE and NSF music emulation")
|
||||
endif()
|
||||
|
||||
if (NOT DEFINED USE_GME_SAP)
|
||||
SET(USE_GME_SAP 1 CACHE BOOL "Enable Atari SAP music emulation")
|
||||
endif()
|
||||
|
||||
if (NOT DEFINED USE_GME_SPC)
|
||||
SET(USE_GME_SPC 1 CACHE BOOL "Enable SNES SPC music emulation")
|
||||
endif()
|
||||
|
||||
if (NOT DEFINED USE_GME_VGM)
|
||||
SET(USE_GME_VGM 1 CACHE BOOL "Enable Sega VGM/VGZ music emulation")
|
||||
endif()
|
||||
|
||||
if (USE_GME_NSFE AND NOT USE_GME_NSF)
|
||||
MESSAGE(" -- NSFE support requires NSF, enabling NSF support. --")
|
||||
SET(USE_GME_NSF 1 CACHE BOOL "Enable NES NSF music emulation" FORCE)
|
||||
endif()
|
||||
|
||||
# Check for GCC "visibility" support.
|
||||
if (CMAKE_COMPILER_IS_GNUCXX)
|
||||
check_cxx_compiler_flag (-fvisibility=hidden __LIBGME_TEST_VISIBILITY)
|
||||
set (ENABLE_VISIBILITY OFF)
|
||||
if (__LIBGME_TEST_VISIBILITY)
|
||||
# get the gcc version
|
||||
exec_program(${CMAKE_CXX_COMPILER} ARGS --version OUTPUT_VARIABLE _gcc_version_info)
|
||||
string (REGEX MATCH "[3-9]\\.[0-9]\\.[0-9]" _gcc_version "${_gcc_version_info}")
|
||||
|
||||
# gcc <4.1 had poor support for symbol visibility
|
||||
if ((${_gcc_version} VERSION_GREATER "4.1") OR (${_gcc_version} VERSION_EQUAL "4.1"))
|
||||
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fvisibility=hidden")
|
||||
set (ENABLE_VISIBILITY ON)
|
||||
add_definitions (-DLIBGME_VISIBILITY)
|
||||
|
||||
# GCC >= 4.2 also correctly supports making inline members have hidden
|
||||
# visibility by default.
|
||||
if ((${_gcc_version} VERSION_GREATER "4.2") OR (${_gcc_version} VERSION_EQUAL "4.2"))
|
||||
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fvisibility-inlines-hidden")
|
||||
endif()
|
||||
endif()
|
||||
endif() # test visibility
|
||||
endif (CMAKE_COMPILER_IS_GNUCXX)
|
||||
|
||||
# Cache this result
|
||||
set( LIBGME_HAVE_GCC_VISIBILITY ${ENABLE_VISIBILITY} CACHE BOOL "GCC support for hidden visibility")
|
||||
|
||||
# Shared library defined here
|
||||
add_subdirectory(gme)
|
||||
|
|
|
@ -1,6 +1,50 @@
|
|||
Game_Music_Emu Change Log
|
||||
-------------------------
|
||||
|
||||
Game_Music_Emu 0.6.0
|
||||
--------------------
|
||||
|
||||
- Note: A 0.5.6 release was referenced but never tagged or packaged.
|
||||
|
||||
- SPC improvements:
|
||||
- Switched to newer snes_spc 0.9.0 for SPC emulation. Uses fast DSP.
|
||||
- Fixed Spc_Emu::gain().
|
||||
- Fixed support for files <0x10200 bytes.
|
||||
|
||||
- Other bugfixes:
|
||||
- Fixed a couple of GBS bugs, one involving access of memory after
|
||||
realloc.
|
||||
- Blip_Buffer works on systems where 'double' is a single-precision
|
||||
floating-point type.
|
||||
- Fix uninitialized buffer size in dual_resampler.
|
||||
- Compilation warnings squashed out as of clang 3.3-pre and gcc 4.7.2.
|
||||
|
||||
- API changes/additions:
|
||||
- Removed documentation of C++ interface, as the C interface in gme.h is
|
||||
the only supported one.
|
||||
- Added gme_enable_accuracy() for enabling more accurate sound emulation
|
||||
options (currently affects SPC only).
|
||||
|
||||
- Build system improvements:
|
||||
- Add pkg_config support.
|
||||
- Fix build on case-insensitive systems.
|
||||
- Allow for install on Cygwin.
|
||||
- Fix install on multilib systems, such as many 64-bit distros (CMake must
|
||||
be able to figure out your system's libsuffix, if any).
|
||||
- C++ implementation symbols are not leaked into the resultant library
|
||||
file (requires symbol visibility support).
|
||||
|
||||
- Sample player improvements:
|
||||
- Can toggle fast/accurate emulation (with the 'A' key).
|
||||
|
||||
Game_Music_Emu 0.5.5
|
||||
--------------------
|
||||
- CMake build support has been added. You can build Game_Music_Emu as
|
||||
a shared library and install it so that you do not have to include your
|
||||
own copy if you know libgme will be present on your target system.
|
||||
Requires CMake 2.6 or higher.
|
||||
|
||||
|
||||
Game_Music_Emu 0.5.2
|
||||
--------------------
|
||||
- *TONS* of changes and improvements. You should re-read the new header
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
Game_Music_Emu 0.5.2 Design
|
||||
Game_Music_Emu 0.6.0 Design
|
||||
---------------------------
|
||||
This might be slightly out-of-date at times, but will be a big help in
|
||||
understanding the library implementation.
|
||||
|
|
|
@ -1,15 +1,14 @@
|
|||
Game_Music_Emu 0.5.2
|
||||
Game_Music_Emu 0.6.0
|
||||
--------------------
|
||||
Author : Shay Green <gblargg@gmail.com>
|
||||
Website: http://www.slack.net/~ant/libs/
|
||||
Forum : http://groups.google.com/group/blargg-sound-libs
|
||||
Source : https://code.google.com/p/game-music-emu/
|
||||
License: GNU Lesser General Public License (LGPL)
|
||||
|
||||
Contents
|
||||
--------
|
||||
* Overview
|
||||
* C and C++ interfaces
|
||||
* Function reference
|
||||
* Error handling
|
||||
* Emulator types
|
||||
* M3U playlist support
|
||||
|
@ -21,7 +20,6 @@ Contents
|
|||
* Modular construction
|
||||
* Obscure features
|
||||
* Solving problems
|
||||
* Deprecated features
|
||||
* Thanks
|
||||
|
||||
|
||||
|
@ -62,56 +60,15 @@ deleted with gme_set_user_cleanup()
|
|||
Refer to gme.h for a comprehensive summary of features.
|
||||
|
||||
|
||||
C and C++ interfaces
|
||||
--------------------
|
||||
While the library is written in C++, an extensive C interface is
|
||||
provided in gme.h. This C interface will be referred to throughout this
|
||||
documentation unless a feature is only available in the full C++
|
||||
interface. All C interface functions and other names have the gme_
|
||||
prefix, so you can recognize a C++-only feature by the lack of gme_ in
|
||||
the names used (contact me if you'd like a feature added to the C
|
||||
interface). If you're building a shared library, I highly recommend
|
||||
sticking to the C interface only, because it will be more stable between
|
||||
releases of the library than the C++ interface. Finally, the C and C++
|
||||
interfaces can be freely mixed without problems. Compare demo/basics.c
|
||||
with demo/cpp_basics.cpp to see how the C and C++ interfaces translate
|
||||
between each other.
|
||||
|
||||
|
||||
Function reference
|
||||
------------------
|
||||
Read the following header files for a complete reference to functions
|
||||
and features. The second group of header files can only be used in C++.
|
||||
|
||||
blargg_config.h Library configuration
|
||||
gme.h C interface (also usable from C++)
|
||||
|
||||
Gme_File.h File loading and track information
|
||||
Music_Emu.h Track playback and adjustments
|
||||
Data_Reader.h Custom data readers
|
||||
Effects_Buffer.h Sound buffer with adjustable stereo echo and panning
|
||||
M3u_Playlist.h M3U playlist support
|
||||
Gbs_Emu.h GBS equalizer settings
|
||||
Nsf_Emu.h NSF equalizer settings
|
||||
Spc_Emu.h SPC surround disable
|
||||
Vgm_Emu.h VGM oversampling disable and custom buffer query
|
||||
|
||||
|
||||
Error handling
|
||||
--------------
|
||||
Functions which can fail have a return type of gme_err_t (blargg_err_t
|
||||
in the C++ interfaces), which is a pointer to an error string (const
|
||||
char*). If a function is successful it returns NULL. Errors that you can
|
||||
easily avoid are checked with debug assertions; gme_err_t return values
|
||||
are only used for genuine run-time errors that can't be easily predicted
|
||||
in advance (out of memory, I/O errors, incompatible file data). Your
|
||||
code should check all error values.
|
||||
|
||||
To improve usability for C programmers, C++ programmers unfamiliar with
|
||||
exceptions, and compatibility with older C++ compilers, the library does
|
||||
*not* throw any C++ exceptions and uses malloc() instead of the standard
|
||||
operator new. This means that you *must* check for NULL when creating a
|
||||
library object with the new operator.
|
||||
Functions which can fail have a return type of gme_err_t, which is a
|
||||
pointer to an error string (const char*). If a function is successful it
|
||||
returns NULL. Errors that you can easily avoid are checked with debug
|
||||
assertions; gme_err_t return values are only used for genuine run-time
|
||||
errors that can't be easily predicted in advance (out of memory, I/O
|
||||
errors, incompatible file data). Your code should check all error
|
||||
values.
|
||||
|
||||
When loading a music file in the wrong emulator or trying to load a
|
||||
non-music file, gme_wrong_file_type is returned. You can check for this
|
||||
|
@ -154,7 +111,9 @@ If you want to remove support for some music types to reduce your
|
|||
executable size, edit GME_TYPE_LIST in blargg_config.h. For example, to
|
||||
support just NSF and GBS, use this:
|
||||
|
||||
#define GME_TYPE_LIST gme_nsf_type, gme_gbs_type
|
||||
#define GME_TYPE_LIST \
|
||||
gme_nsf_type,\
|
||||
gme_gbs_type
|
||||
|
||||
|
||||
M3U playlist support
|
||||
|
@ -271,40 +230,6 @@ create an emulator, you can use the following methods of loading:
|
|||
|
||||
error = gme_load_custom( emu, my_read, file_size, my_data );
|
||||
|
||||
* If you must load the file data into memory yourself, you can have the
|
||||
library use your data directly *without* making a copy. If you do this,
|
||||
you must not free the data until you're done playing the file.
|
||||
|
||||
error = emu->load_mem( pointer, size );
|
||||
|
||||
* If you've already read the first bytes of a file (perhaps to determine
|
||||
the file type) and want to avoid seeking back to the beginning for
|
||||
performance reasons, use Remaining_Reader:
|
||||
|
||||
Std_File_Reader in;
|
||||
error = in.open( file_path );
|
||||
|
||||
char header [4];
|
||||
error = in.read( &header, sizeof header );
|
||||
...
|
||||
|
||||
Remaining_Reader rem( &header, sizeof header, &in );
|
||||
error = emu->load( rem );
|
||||
|
||||
If you merely need access to a file's header after loading, use the
|
||||
emulator-specific header() functions, after casting the Music_Emu
|
||||
pointer to the specific emulator's type. This example examines the
|
||||
chip_flags field of the header if it's an NSF file:
|
||||
|
||||
if ( music_emu->type() == gme_nsf_type )
|
||||
{
|
||||
Nsf_Emu* nsf_emu = (Nsf_Emu*) music_emu;
|
||||
if ( nsf_emu->header().chip_flags & 0x01 )
|
||||
...
|
||||
}
|
||||
|
||||
Contact me if you want more information about loading files.
|
||||
|
||||
|
||||
Sound parameters
|
||||
----------------
|
||||
|
@ -437,21 +362,6 @@ separate threads.
|
|||
* If all else fails, see if the demos work.
|
||||
|
||||
|
||||
Deprecated features
|
||||
-------------------
|
||||
The following functions and other features have been deprecated and will
|
||||
be removed in a future release of the library. Alternatives to the
|
||||
deprecated features are listed to the right.
|
||||
|
||||
Music_Emu::error_count() warning()
|
||||
load( header, reader ) see "Loading file data" above
|
||||
Spc_Emu::trailer() track_info()
|
||||
Spc_Emu::trailer_size()
|
||||
Gym_Emu::track_length() track_info()
|
||||
Vgm_Emu::gd3_data() track_info()
|
||||
Nsfe_Emu::disable_playlist() clear_playlist()
|
||||
|
||||
|
||||
Thanks
|
||||
------
|
||||
Big thanks to Chris Moeller (kode54) for help with library testing and
|
||||
|
@ -461,4 +371,6 @@ Brad Martin's excellent OpenSPC SNES DSP emulator worked well from the
|
|||
start. Also thanks to Richard Bannister, Mahendra Tallur, Shazz,
|
||||
nenolod, theHobbit, Johan Samuelsson, and nes6502 for testing, using,
|
||||
and giving feedback for the library in their respective game music
|
||||
players.
|
||||
players. More recently, Lucas Paul and Michael Pyne have helped nudge the
|
||||
library into a public repository and get its interface more stable for use
|
||||
in shared libraries.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// Game_Music_Emu 0.5.2. http://www.slack.net/~ant/
|
||||
// Game_Music_Emu 0.6.0. http://www.slack.net/~ant/
|
||||
|
||||
#include "Ay_Apu.h"
|
||||
|
||||
|
@ -123,8 +123,8 @@ void Ay_Apu::write_data_( int addr, int data )
|
|||
|
||||
if ( (unsigned) addr >= 14 )
|
||||
{
|
||||
#ifdef dprintf
|
||||
dprintf( "Wrote to I/O port %02X\n", (int) addr );
|
||||
#ifdef debug_printf
|
||||
debug_printf( "Wrote to I/O port %02X\n", (int) addr );
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -220,7 +220,7 @@ void Ay_Apu::run_until( blip_time_t final_end_time )
|
|||
end_time = final_end_time;
|
||||
|
||||
//if ( !(regs [12] | regs [11]) )
|
||||
// dprintf( "Used envelope period 0\n" );
|
||||
// debug_printf( "Used envelope period 0\n" );
|
||||
}
|
||||
else if ( !volume )
|
||||
{
|
||||
|
@ -250,7 +250,7 @@ void Ay_Apu::run_until( blip_time_t final_end_time )
|
|||
ntime = start_time + old_noise_delay;
|
||||
noise_lfsr = old_noise_lfsr;
|
||||
//if ( (regs [6] & 0x1F) == 0 )
|
||||
// dprintf( "Used noise period 0\n" );
|
||||
// debug_printf( "Used noise period 0\n" );
|
||||
}
|
||||
|
||||
// The following efficiently handles several cases (least demanding first):
|
||||
|
@ -299,7 +299,7 @@ void Ay_Apu::run_until( blip_time_t final_end_time )
|
|||
while ( ntime <= end ) // must advance *past* time to avoid hang
|
||||
{
|
||||
int changed = noise_lfsr + 1;
|
||||
noise_lfsr = ((blargg_ulong)-(blargg_long)(noise_lfsr & 1) & 0x12000) ^ (noise_lfsr >> 1);
|
||||
noise_lfsr = (-(noise_lfsr & 1) & 0x12000) ^ (noise_lfsr >> 1);
|
||||
if ( changed & 2 )
|
||||
{
|
||||
delta = -delta;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// AY-3-8910 sound chip emulator
|
||||
|
||||
// Game_Music_Emu 0.5.2
|
||||
// Game_Music_Emu 0.6.0
|
||||
#ifndef AY_APU_H
|
||||
#define AY_APU_H
|
||||
|
||||
|
@ -50,7 +50,6 @@ private:
|
|||
Blip_Buffer* output;
|
||||
} oscs [osc_count];
|
||||
blip_time_t last_time;
|
||||
byte latch;
|
||||
byte regs [reg_count];
|
||||
|
||||
struct {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// Game_Music_Emu 0.5.2. http://www.slack.net/~ant/
|
||||
// Game_Music_Emu 0.6.0. http://www.slack.net/~ant/
|
||||
|
||||
/*
|
||||
Last validated with zexall 2006.11.21 5:26 PM
|
||||
|
@ -807,6 +807,7 @@ possibly_out_of_time:
|
|||
case 0xCB:
|
||||
unsigned data2;
|
||||
data2 = INSTR( 1 );
|
||||
(void) data2; // TODO is this the same as data in all cases?
|
||||
pc++;
|
||||
switch ( data )
|
||||
{
|
||||
|
@ -1047,7 +1048,7 @@ possibly_out_of_time:
|
|||
blargg_ulong sum = temp + (flags & C01);
|
||||
flags = ~data >> 2 & N02;
|
||||
if ( flags )
|
||||
sum = (blargg_ulong)-(blargg_long)sum;
|
||||
sum = -sum;
|
||||
sum += rp.hl;
|
||||
temp ^= rp.hl;
|
||||
temp ^= sum;
|
||||
|
@ -1252,7 +1253,7 @@ possibly_out_of_time:
|
|||
|
||||
case 0x4F: // LD R,A
|
||||
SET_R( rg.a );
|
||||
dprintf( "LD R,A not supported\n" );
|
||||
debug_printf( "LD R,A not supported\n" );
|
||||
warning = true;
|
||||
goto loop;
|
||||
|
||||
|
@ -1262,7 +1263,7 @@ possibly_out_of_time:
|
|||
|
||||
case 0x5F: // LD A,R
|
||||
rg.a = GET_R();
|
||||
dprintf( "LD A,R not supported\n" );
|
||||
debug_printf( "LD A,R not supported\n" );
|
||||
warning = true;
|
||||
ld_ai_common:
|
||||
flags = (flags & C01) | SZ28( rg.a ) | (r.iff2 << 2 & V04);
|
||||
|
@ -1285,7 +1286,7 @@ possibly_out_of_time:
|
|||
goto loop;
|
||||
|
||||
default:
|
||||
dprintf( "Opcode $ED $%02X not supported\n", data );
|
||||
debug_printf( "Opcode $ED $%02X not supported\n", data );
|
||||
warning = true;
|
||||
goto loop;
|
||||
}
|
||||
|
@ -1545,7 +1546,7 @@ possibly_out_of_time:
|
|||
}
|
||||
|
||||
default:
|
||||
dprintf( "Opcode $%02X $CB $%02X not supported\n", opcode, data2 );
|
||||
debug_printf( "Opcode $%02X $CB $%02X not supported\n", opcode, data2 );
|
||||
warning = true;
|
||||
goto loop;
|
||||
}
|
||||
|
@ -1634,7 +1635,7 @@ possibly_out_of_time:
|
|||
}
|
||||
|
||||
default:
|
||||
dprintf( "Unnecessary DD/FD prefix encountered\n" );
|
||||
debug_printf( "Unnecessary DD/FD prefix encountered\n" );
|
||||
warning = true;
|
||||
pc--;
|
||||
goto loop;
|
||||
|
@ -1643,7 +1644,7 @@ possibly_out_of_time:
|
|||
}
|
||||
|
||||
}
|
||||
dprintf( "Unhandled main opcode: $%02X\n", opcode );
|
||||
debug_printf( "Unhandled main opcode: $%02X\n", opcode );
|
||||
assert( false );
|
||||
|
||||
halt:
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// Z80 CPU emulator
|
||||
|
||||
// Game_Music_Emu 0.5.2
|
||||
// Game_Music_Emu 0.6.0
|
||||
#ifndef AY_CPU_H
|
||||
#define AY_CPU_H
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// Game_Music_Emu 0.5.2. http://www.slack.net/~ant/
|
||||
// Game_Music_Emu 0.6.0. http://www.slack.net/~ant/
|
||||
|
||||
#include "Ay_Emu.h"
|
||||
|
||||
|
@ -47,8 +47,8 @@ Ay_Emu::~Ay_Emu() { }
|
|||
|
||||
static byte const* get_data( Ay_Emu::file_t const& file, byte const* ptr, int min_size )
|
||||
{
|
||||
long pos = long(ptr - (byte const*) file.header);
|
||||
long file_size = long(file.end - (byte const*) file.header);
|
||||
long pos = ptr - (byte const*) file.header;
|
||||
long file_size = file.end - (byte const*) file.header;
|
||||
assert( (unsigned long) pos <= (unsigned long) file_size - 2 );
|
||||
int offset = (BOOST::int16_t) get_be16( ptr );
|
||||
if ( !offset || blargg_ulong (pos + offset) > blargg_ulong (file_size - min_size) )
|
||||
|
@ -207,11 +207,11 @@ blargg_err_t Ay_Emu::start_track_( int track )
|
|||
if ( len > blargg_ulong (file.end - in) )
|
||||
{
|
||||
set_warning( "Missing file data" );
|
||||
len = unsigned(file.end - in);
|
||||
len = file.end - in;
|
||||
}
|
||||
//dprintf( "addr: $%04X, len: $%04X\n", addr, len );
|
||||
//debug_printf( "addr: $%04X, len: $%04X\n", addr, len );
|
||||
if ( addr < ram_start && addr >= 0x400 ) // several tracks use low data
|
||||
dprintf( "Block addr in ROM\n" );
|
||||
debug_printf( "Block addr in ROM\n" );
|
||||
memcpy( mem.ram + addr, in, len );
|
||||
|
||||
if ( file.end - blocks < 8 )
|
||||
|
@ -242,7 +242,7 @@ blargg_err_t Ay_Emu::start_track_( int track )
|
|||
};
|
||||
memcpy( mem.ram, passive, sizeof passive );
|
||||
unsigned play_addr = get_be16( more_data + 4 );
|
||||
//dprintf( "Play: $%04X\n", play_addr );
|
||||
//debug_printf( "Play: $%04X\n", play_addr );
|
||||
if ( play_addr )
|
||||
{
|
||||
memcpy( mem.ram, active, sizeof active );
|
||||
|
@ -315,7 +315,7 @@ void Ay_Emu::cpu_out_misc( cpu_time_t time, unsigned addr, int data )
|
|||
}
|
||||
}
|
||||
|
||||
dprintf( "Unmapped OUT: $%04X <- $%02X\n", addr, data );
|
||||
debug_printf( "Unmapped OUT: $%04X <- $%02X\n", addr, data );
|
||||
return;
|
||||
|
||||
enable_cpc:
|
||||
|
@ -356,7 +356,7 @@ int ay_cpu_in( Ay_Cpu*, unsigned addr )
|
|||
if ( (addr & 0xFF) == 0xFE )
|
||||
return 0xFF; // other values break some beeper tunes
|
||||
|
||||
dprintf( "Unmapped IN : $%04X\n", addr );
|
||||
debug_printf( "Unmapped IN : $%04X\n", addr );
|
||||
return 0xFF;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// Sinclair Spectrum AY music file emulator
|
||||
|
||||
// Game_Music_Emu 0.5.2
|
||||
// Game_Music_Emu 0.6.0
|
||||
#ifndef AY_EMU_H
|
||||
#define AY_EMU_H
|
||||
|
||||
|
@ -46,7 +46,6 @@ protected:
|
|||
private:
|
||||
file_t file;
|
||||
|
||||
unsigned play_addr;
|
||||
cpu_time_t play_period;
|
||||
cpu_time_t next_play;
|
||||
Blip_Buffer* beeper_output;
|
||||
|
|
|
@ -233,18 +233,32 @@ static void gen_sinc( float* out, int count, double oversample, double treble, d
|
|||
double const to_angle = PI / 2 / maxh / oversample;
|
||||
for ( int i = 0; i < count; i++ )
|
||||
{
|
||||
double angle = ((i - count) * 2 + 1) * to_angle;
|
||||
double c = rolloff * cos( (maxh - 1.0) * angle ) - cos( maxh * angle );
|
||||
double cos_nc_angle = cos( maxh * cutoff * angle );
|
||||
double cos_nc1_angle = cos( (maxh * cutoff - 1.0) * angle );
|
||||
double cos_angle = cos( angle );
|
||||
double angle = ((i - count) * 2 + 1) * to_angle;
|
||||
double angle_maxh = angle * maxh;
|
||||
double angle_maxh_mid = angle_maxh * cutoff;
|
||||
|
||||
c = c * pow_a_n - rolloff * cos_nc1_angle + cos_nc_angle;
|
||||
double d = 1.0 + rolloff * (rolloff - cos_angle - cos_angle);
|
||||
double b = 2.0 - cos_angle - cos_angle;
|
||||
double a = 1.0 - cos_angle - cos_nc_angle + cos_nc1_angle;
|
||||
double y = maxh;
|
||||
|
||||
out [i] = (float) ((a * d + c * b) / (b * d)); // a / b + c / d
|
||||
// 0 to Fs/2*cutoff, flat
|
||||
if ( angle_maxh_mid ) // unstable at t=0
|
||||
y *= sin( angle_maxh_mid ) / angle_maxh_mid;
|
||||
|
||||
// Fs/2*cutoff to Fs/2, logarithmic rolloff
|
||||
double cosa = cos( angle );
|
||||
double den = 1 + rolloff * (rolloff - cosa - cosa);
|
||||
|
||||
// Becomes unstable when rolloff is near 1.0 and t is near 0,
|
||||
// which is the only time den becomes small
|
||||
if ( den > 1e-13 )
|
||||
{
|
||||
double num =
|
||||
(cos( angle_maxh - angle ) * rolloff - cos( angle_maxh )) * pow_a_n -
|
||||
cos( angle_maxh_mid - angle ) * rolloff + cos( angle_maxh_mid );
|
||||
|
||||
y = y * cutoff + num / den;
|
||||
}
|
||||
|
||||
out [i] = (float) y;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
153
game-music-emu/gme/CMakeLists.txt
Normal file
153
game-music-emu/gme/CMakeLists.txt
Normal file
|
@ -0,0 +1,153 @@
|
|||
# List of source files required by libgme and any emulators
|
||||
# This is not 100% accurate (Fir_Resampler for instance) but
|
||||
# you'll be OK.
|
||||
set(libgme_SRCS Blip_Buffer.cpp
|
||||
Classic_Emu.cpp
|
||||
Data_Reader.cpp
|
||||
Dual_Resampler.cpp
|
||||
Effects_Buffer.cpp
|
||||
Fir_Resampler.cpp
|
||||
gme.cpp
|
||||
Gme_File.cpp
|
||||
M3u_Playlist.cpp
|
||||
Multi_Buffer.cpp
|
||||
Music_Emu.cpp
|
||||
)
|
||||
|
||||
# Ay_Apu is very popular around here
|
||||
if (USE_GME_AY OR USE_GME_KSS)
|
||||
set(libgme_SRCS ${libgme_SRCS}
|
||||
Ay_Apu.cpp
|
||||
)
|
||||
endif()
|
||||
|
||||
# so is Ym2612_Emu
|
||||
if (USE_GME_VGM OR USE_GME_GYM)
|
||||
set(libgme_SRCS ${libgme_SRCS}
|
||||
Ym2612_Emu.cpp
|
||||
)
|
||||
endif()
|
||||
|
||||
# But none are as popular as Sms_Apu
|
||||
if (USE_GME_VGM OR USE_GME_GYM OR USE_GME_KSS)
|
||||
set(libgme_SRCS ${libgme_SRCS}
|
||||
Sms_Apu.cpp
|
||||
)
|
||||
endif()
|
||||
|
||||
if (USE_GME_AY)
|
||||
set(libgme_SRCS ${libgme_SRCS}
|
||||
# Ay_Apu.cpp included earlier
|
||||
Ay_Cpu.cpp
|
||||
Ay_Emu.cpp
|
||||
)
|
||||
endif()
|
||||
|
||||
if (USE_GME_GBS)
|
||||
set(libgme_SRCS ${libgme_SRCS}
|
||||
Gb_Apu.cpp
|
||||
Gb_Cpu.cpp
|
||||
Gb_Oscs.cpp
|
||||
Gbs_Emu.cpp
|
||||
)
|
||||
endif()
|
||||
|
||||
if (USE_GME_GYM)
|
||||
set(libgme_SRCS ${libgme_SRCS}
|
||||
# Sms_Apu.cpp included earlier
|
||||
# Ym2612_Emu.cpp included earlier
|
||||
Gym_Emu.cpp
|
||||
)
|
||||
endif()
|
||||
|
||||
if (USE_GME_HES)
|
||||
set(libgme_SRCS ${libgme_SRCS}
|
||||
Hes_Apu.cpp
|
||||
Hes_Cpu.cpp
|
||||
Hes_Emu.cpp
|
||||
)
|
||||
endif()
|
||||
|
||||
if (USE_GME_KSS)
|
||||
set(libgme_SRCS ${libgme_SRCS}
|
||||
# Ay_Apu.cpp included earlier
|
||||
# Sms_Apu.cpp included earlier
|
||||
Kss_Cpu.cpp
|
||||
Kss_Emu.cpp
|
||||
Kss_Scc_Apu.cpp
|
||||
)
|
||||
endif()
|
||||
|
||||
if (USE_GME_NSF OR USE_GME_NSFE)
|
||||
set(libgme_SRCS ${libgme_SRCS}
|
||||
Nes_Apu.cpp
|
||||
Nes_Cpu.cpp
|
||||
Nes_Fme7_Apu.cpp
|
||||
Nes_Namco_Apu.cpp
|
||||
Nes_Oscs.cpp
|
||||
Nes_Vrc6_Apu.cpp
|
||||
Nsf_Emu.cpp
|
||||
)
|
||||
endif()
|
||||
|
||||
if (USE_GME_NSFE)
|
||||
set(libgme_SRCS ${libgme_SRCS}
|
||||
Nsfe_Emu.cpp
|
||||
)
|
||||
endif()
|
||||
|
||||
if (USE_GME_SAP)
|
||||
set(libgme_SRCS ${libgme_SRCS}
|
||||
Sap_Apu.cpp
|
||||
Sap_Cpu.cpp
|
||||
Sap_Emu.cpp
|
||||
)
|
||||
endif()
|
||||
|
||||
if (USE_GME_SPC)
|
||||
set(libgme_SRCS ${libgme_SRCS}
|
||||
Snes_Spc.cpp
|
||||
Spc_Cpu.cpp
|
||||
Spc_Dsp.cpp
|
||||
Spc_Emu.cpp
|
||||
Spc_Filter.cpp
|
||||
)
|
||||
endif()
|
||||
|
||||
if (USE_GME_VGM)
|
||||
set(libgme_SRCS ${libgme_SRCS}
|
||||
# Sms_Apu.cpp included earlier
|
||||
# Ym2612_Emu.cpp included earlier
|
||||
Vgm_Emu.cpp
|
||||
Vgm_Emu_Impl.cpp
|
||||
Ym2413_Emu.cpp
|
||||
)
|
||||
endif()
|
||||
|
||||
# These headers are part of the generic gme interface.
|
||||
set (EXPORTED_HEADERS gme.h)
|
||||
|
||||
# Run during cmake phase, so this is available during make
|
||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/gme_types.h.in
|
||||
${CMAKE_CURRENT_BINARY_DIR}/gme_types.h)
|
||||
|
||||
# On some platforms we may need to change headers or whatnot based on whether
|
||||
# we're building the library or merely using the library. The following is
|
||||
# only defined when building the library to allow us to tell which is which.
|
||||
add_definitions(-DBLARGG_BUILD_DLL)
|
||||
|
||||
# For the gme_types.h
|
||||
include_directories(${CMAKE_CURRENT_BINARY_DIR})
|
||||
|
||||
# Add library to be compiled.
|
||||
add_library(gme ${libgme_SRCS})
|
||||
|
||||
# The version is the release. The "soversion" is the API version. As long
|
||||
# as only build fixes are performed (i.e. no backwards-incompatible changes
|
||||
# to the API), the SOVERSION should be the same even when bumping up VERSION.
|
||||
# The way gme.h is designed, SOVERSION should very rarely be bumped, if ever.
|
||||
# Hopefully the API can stay compatible with old versions.
|
||||
#set_target_properties(gme
|
||||
# PROPERTIES VERSION ${GME_VERSION}
|
||||
# SOVERSION 0)
|
||||
target_link_libraries(gme)
|
|
@ -1,4 +1,4 @@
|
|||
// Game_Music_Emu 0.5.2. http://www.slack.net/~ant/
|
||||
// Game_Music_Emu 0.6.0. http://www.slack.net/~ant/
|
||||
|
||||
#include "Classic_Emu.h"
|
||||
|
||||
|
@ -176,9 +176,9 @@ void Rom_Data_::set_addr_( long addr, int unit )
|
|||
|
||||
if ( 0 )
|
||||
{
|
||||
dprintf( "addr: %X\n", addr );
|
||||
dprintf( "file_size: %d\n", file_size_ );
|
||||
dprintf( "rounded: %d\n", rounded );
|
||||
dprintf( "mask: $%X\n", mask );
|
||||
debug_printf( "addr: %X\n", addr );
|
||||
debug_printf( "file_size: %d\n", file_size_ );
|
||||
debug_printf( "rounded: %d\n", rounded );
|
||||
debug_printf( "mask: $%X\n", mask );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// Common aspects of emulators which use Blip_Buffer for sound output
|
||||
|
||||
// Game_Music_Emu 0.5.2
|
||||
// Game_Music_Emu 0.6.0
|
||||
#ifndef CLASSIC_EMU_H
|
||||
#define CLASSIC_EMU_H
|
||||
|
||||
|
|
|
@ -1,15 +1,12 @@
|
|||
// File_Extractor 0.4.0. http://www.slack.net/~ant/
|
||||
|
||||
#define _CRT_SECURE_NO_WARNINGS
|
||||
#define IN_GME 1
|
||||
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "Data_Reader.h"
|
||||
|
||||
#include "blargg_endian.h"
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
/* Copyright (C) 2005-2006 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
|
||||
|
@ -92,11 +89,11 @@ Remaining_Reader::Remaining_Reader( void const* h, long size, Data_Reader* r )
|
|||
in = r;
|
||||
}
|
||||
|
||||
long Remaining_Reader::remain() const { return long(header_end - header + in->remain()); }
|
||||
long Remaining_Reader::remain() const { return header_end - header + in->remain(); }
|
||||
|
||||
long Remaining_Reader::read_first( void* out, long count )
|
||||
{
|
||||
long first = long(header_end - header);
|
||||
long first = header_end - header;
|
||||
if ( first )
|
||||
{
|
||||
if ( first > count )
|
||||
|
@ -213,7 +210,7 @@ long Std_File_Reader::size() const
|
|||
|
||||
long Std_File_Reader::read_avail( void* p, long s )
|
||||
{
|
||||
return (long)fread( p, 1, s, (FILE*) file_ );
|
||||
return fread( p, 1, s, (FILE*) file_ );
|
||||
}
|
||||
|
||||
blargg_err_t Std_File_Reader::read( void* p, long s )
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
#define DATA_READER_H
|
||||
|
||||
#include "blargg_common.h"
|
||||
#include "gme.h"
|
||||
|
||||
// Supports reading and finding out how many bytes are remaining
|
||||
class Data_Reader {
|
||||
|
@ -117,7 +116,7 @@ private:
|
|||
// Invokes callback function to read data. Size of data must be specified in advance.
|
||||
class Callback_Reader : public Data_Reader {
|
||||
public:
|
||||
typedef const char* (GMEAPI *callback_t)( void* data, void* out, int count );
|
||||
typedef const char* (*callback_t)( void* data, void* out, int count );
|
||||
Callback_Reader( callback_t, long size, void* data = 0 );
|
||||
public:
|
||||
long read_avail( void*, long );
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// Game_Music_Emu 0.5.2. http://www.slack.net/~ant/
|
||||
// Game_Music_Emu 0.6.0. http://www.slack.net/~ant/
|
||||
|
||||
#include "Dual_Resampler.h"
|
||||
|
||||
|
@ -20,7 +20,13 @@ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
|
|||
|
||||
unsigned const resampler_extra = 256;
|
||||
|
||||
Dual_Resampler::Dual_Resampler() { }
|
||||
Dual_Resampler::Dual_Resampler() :
|
||||
sample_buf_size(0),
|
||||
oversamples_per_frame(-1),
|
||||
buf_pos(-1),
|
||||
resampler_size(0)
|
||||
{
|
||||
}
|
||||
|
||||
Dual_Resampler::~Dual_Resampler() { }
|
||||
|
||||
|
@ -62,10 +68,10 @@ void Dual_Resampler::play_frame_( Blip_Buffer& blip_buf, dsample_t* out )
|
|||
assert( blip_buf.samples_avail() == pair_count );
|
||||
|
||||
resampler.write( new_count );
|
||||
|
||||
|
||||
long count = resampler.read( sample_buf.begin(), sample_buf_size );
|
||||
assert( count == (long) sample_buf_size );
|
||||
|
||||
|
||||
mix_samples( blip_buf, out );
|
||||
blip_buf.remove_samples( pair_count );
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// Combination of Fir_Resampler and Blip_Buffer mixing. Used by Sega FM emulators.
|
||||
|
||||
// Game_Music_Emu 0.5.2
|
||||
// Game_Music_Emu 0.6.0
|
||||
#ifndef DUAL_RESAMPLER_H
|
||||
#define DUAL_RESAMPLER_H
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// Game_Music_Emu 0.5.2. http://www.slack.net/~ant/
|
||||
// Game_Music_Emu 0.6.0. http://www.slack.net/~ant/
|
||||
|
||||
#include "Effects_Buffer.h"
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// Multi-channel effects buffer with panning, echo and reverb
|
||||
|
||||
// Game_Music_Emu 0.5.2
|
||||
// Game_Music_Emu 0.6.0
|
||||
#ifndef EFFECTS_BUFFER_H
|
||||
#define EFFECTS_BUFFER_H
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// Game_Music_Emu 0.5.2. http://www.slack.net/~ant/
|
||||
// Game_Music_Emu 0.6.0. http://www.slack.net/~ant/
|
||||
|
||||
#include "Fir_Resampler.h"
|
||||
|
||||
|
@ -156,7 +156,7 @@ int Fir_Resampler_::input_needed( blargg_long output_count ) const
|
|||
output_count -= 2;
|
||||
}
|
||||
|
||||
long input_extra = long(input_count - (write_pos - &buf [(width_ - 1) * stereo]));
|
||||
long input_extra = input_count - (write_pos - &buf [(width_ - 1) * stereo]);
|
||||
if ( input_extra < 0 )
|
||||
input_extra = 0;
|
||||
return input_extra;
|
||||
|
@ -186,7 +186,7 @@ int Fir_Resampler_::avail_( blargg_long input_count ) const
|
|||
|
||||
int Fir_Resampler_::skip_input( long count )
|
||||
{
|
||||
int remain = int(write_pos - buf.begin());
|
||||
int remain = write_pos - buf.begin();
|
||||
int max_count = remain - width_ * stereo;
|
||||
if ( count > max_count )
|
||||
count = max_count;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// Finite impulse response (FIR) resampler with adjustable FIR size
|
||||
|
||||
// Game_Music_Emu 0.5.2
|
||||
// Game_Music_Emu 0.6.0
|
||||
#ifndef FIR_RESAMPLER_H
|
||||
#define FIR_RESAMPLER_H
|
||||
|
||||
|
@ -31,7 +31,7 @@ public:
|
|||
void clear();
|
||||
|
||||
// Number of input samples that can be written
|
||||
int max_write() const { return int(buf.end() - write_pos); }
|
||||
int max_write() const { return buf.end() - write_pos; }
|
||||
|
||||
// Pointer to place to write input samples
|
||||
sample_t* buffer() { return write_pos; }
|
||||
|
@ -40,7 +40,7 @@ public:
|
|||
void write( long count );
|
||||
|
||||
// Number of input samples in buffer
|
||||
int written() const { return int(write_pos - &buf [write_offset]); }
|
||||
int written() const { return write_pos - &buf [write_offset]; }
|
||||
|
||||
// Skip 'count' input samples. Returns number of samples actually skipped.
|
||||
int skip_input( long count );
|
||||
|
@ -51,7 +51,7 @@ public:
|
|||
int input_needed( blargg_long count ) const;
|
||||
|
||||
// Number of output samples available
|
||||
int avail() const { return avail_( blargg_long(write_pos - &buf [width_ * stereo]) ); }
|
||||
int avail() const { return avail_( write_pos - &buf [width_ * stereo] ); }
|
||||
|
||||
public:
|
||||
~Fir_Resampler_();
|
||||
|
@ -161,11 +161,11 @@ int Fir_Resampler<width>::read( sample_t* out_begin, blargg_long count )
|
|||
|
||||
imp_phase = res - remain;
|
||||
|
||||
int left = int(write_pos - in);
|
||||
int left = write_pos - in;
|
||||
write_pos = &buf [left];
|
||||
memmove( buf.begin(), in, left * sizeof *in );
|
||||
|
||||
return int(out - out_begin);
|
||||
return out - out_begin;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -271,7 +271,7 @@ void Gb_Apu::write_register( blip_time_t time, unsigned addr, int data )
|
|||
}
|
||||
else
|
||||
{
|
||||
//dprintf( "APU powered on\n" );
|
||||
//debug_printf( "APU powered on\n" );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// Game_Music_Emu 0.5.2. http://www.slack.net/~ant/
|
||||
// Game_Music_Emu 0.6.0. http://www.slack.net/~ant/
|
||||
|
||||
#include "Gb_Cpu.h"
|
||||
|
||||
|
@ -89,11 +89,6 @@ unsigned const n_flag = 0x40;
|
|||
unsigned const h_flag = 0x20;
|
||||
unsigned const c_flag = 0x10;
|
||||
|
||||
#ifdef _MSC_VER
|
||||
// warning C4101: 'blargg_failed_' : unreferenced local variable
|
||||
// -- produced by the BOOST_STATIC_ASSERT line below
|
||||
#pragma warning(disable:4101)
|
||||
#endif
|
||||
bool Gb_Cpu::run( blargg_long cycle_count )
|
||||
{
|
||||
state_.remain = blargg_ulong (cycle_count + clocks_per_instr) / clocks_per_instr;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// Nintendo Game Boy CPU emulator
|
||||
// Treats every instruction as taking 4 cycles
|
||||
|
||||
// Game_Music_Emu 0.5.2
|
||||
// Game_Music_Emu 0.6.0
|
||||
#ifndef GB_CPU_H
|
||||
#define GB_CPU_H
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// Game_Music_Emu 0.5.2. http://www.slack.net/~ant/
|
||||
// Game_Music_Emu 0.6.0. http://www.slack.net/~ant/
|
||||
|
||||
#include "Gbs_Emu.h"
|
||||
|
||||
|
@ -18,8 +18,10 @@ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
|
|||
|
||||
#include "blargg_source.h"
|
||||
|
||||
Gbs_Emu::equalizer_t const Gbs_Emu::handheld_eq = { -47.0, 2000, 0, 0, 0, 0, 0, 0, 0, 0 };
|
||||
Gbs_Emu::equalizer_t const Gbs_Emu::headphones_eq = { 0.0, 300, 0, 0, 0, 0, 0, 0, 0, 0 };
|
||||
Gbs_Emu::equalizer_t const Gbs_Emu::handheld_eq =
|
||||
Music_Emu::make_equalizer( -47.0, 2000 );
|
||||
Gbs_Emu::equalizer_t const Gbs_Emu::headphones_eq =
|
||||
Music_Emu::make_equalizer( 0.0, 300 );
|
||||
|
||||
Gbs_Emu::Gbs_Emu()
|
||||
{
|
||||
|
@ -39,8 +41,7 @@ Gbs_Emu::Gbs_Emu()
|
|||
set_max_initial_silence( 21 );
|
||||
set_gain( 1.2 );
|
||||
|
||||
static equalizer_t const eq = { -1.0, 120, 0, 0, 0, 0, 0, 0, 0, 0 };
|
||||
set_equalizer( eq );
|
||||
set_equalizer( make_equalizer( -1.0, 120 ) );
|
||||
}
|
||||
|
||||
Gbs_Emu::~Gbs_Emu() { }
|
||||
|
@ -151,7 +152,7 @@ void Gbs_Emu::set_bank( int n )
|
|||
{
|
||||
// TODO: what is the correct behavior? Current Game & Watch Gallery
|
||||
// rip requires that this have no effect or set to bank 1.
|
||||
//dprintf( "Selected ROM bank 0\n" );
|
||||
//debug_printf( "Selected ROM bank 0\n" );
|
||||
return;
|
||||
//n = 1;
|
||||
}
|
||||
|
@ -212,11 +213,11 @@ blargg_err_t Gbs_Emu::start_track_( int track )
|
|||
for ( int i = 0; i < (int) sizeof sound_data; i++ )
|
||||
apu.write_register( 0, i + apu.start_addr, sound_data [i] );
|
||||
|
||||
cpu::reset( rom.unmapped() );
|
||||
|
||||
unsigned load_addr = get_le16( header_.load_addr );
|
||||
cpu::rst_base = load_addr;
|
||||
rom.set_addr( load_addr );
|
||||
cpu::rst_base = load_addr;
|
||||
|
||||
cpu::reset( rom.unmapped() );
|
||||
|
||||
cpu::map_code( ram_addr, 0x10000 - ram_addr, ram );
|
||||
cpu::map_code( 0, bank_size, rom.at_addr( 0 ) );
|
||||
|
@ -265,13 +266,13 @@ blargg_err_t Gbs_Emu::run_clocks( blip_time_t& duration, int )
|
|||
}
|
||||
else if ( cpu::r.pc > 0xFFFF )
|
||||
{
|
||||
dprintf( "PC wrapped around\n" );
|
||||
debug_printf( "PC wrapped around\n" );
|
||||
cpu::r.pc &= 0xFFFF;
|
||||
}
|
||||
else
|
||||
{
|
||||
set_warning( "Emulation error (illegal/unsupported instruction)" );
|
||||
dprintf( "Bad opcode $%.2x at $%.4x\n",
|
||||
debug_printf( "Bad opcode $%.2x at $%.4x\n",
|
||||
(int) *cpu::get_code( cpu::r.pc ), (int) cpu::r.pc );
|
||||
cpu::r.pc = (cpu::r.pc + 1) & 0xFFFF;
|
||||
cpu_time += 6;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// Nintendo Game Boy GBS music file emulator
|
||||
|
||||
// Game_Music_Emu 0.5.2
|
||||
// Game_Music_Emu 0.6.0
|
||||
#ifndef GBS_EMU_H
|
||||
#define GBS_EMU_H
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// Game_Music_Emu 0.5.2. http://www.slack.net/~ant/
|
||||
// Game_Music_Emu 0.6.0. http://www.slack.net/~ant/
|
||||
|
||||
#include "Gme_File.h"
|
||||
|
||||
|
@ -60,8 +60,8 @@ blargg_err_t Gme_File::load_mem_( byte const* data, long size )
|
|||
blargg_err_t Gme_File::load_( Data_Reader& in )
|
||||
{
|
||||
RETURN_ERR( file_data.resize( in.remain() ) );
|
||||
RETURN_ERR( in.read( file_data.begin(), (long)file_data.size() ) );
|
||||
return load_mem_( file_data.begin(), (long)file_data.size() );
|
||||
RETURN_ERR( in.read( file_data.begin(), file_data.size() ) );
|
||||
return load_mem_( file_data.begin(), file_data.size() );
|
||||
}
|
||||
|
||||
// public load functions call this at beginning
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// Common interface to game music file loading and information
|
||||
|
||||
// Game_Music_Emu 0.5.2
|
||||
// Game_Music_Emu 0.6.0
|
||||
#ifndef GME_FILE_H
|
||||
#define GME_FILE_H
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// Game_Music_Emu 0.5.2. http://www.slack.net/~ant/
|
||||
// Game_Music_Emu 0.6.0. http://www.slack.net/~ant/
|
||||
|
||||
#include "Gym_Emu.h"
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// Sega Genesis/Mega Drive GYM music file emulator
|
||||
// Includes with PCM timing recovery to improve sample quality.
|
||||
|
||||
// Game_Music_Emu 0.5.2
|
||||
// Game_Music_Emu 0.6.0
|
||||
#ifndef GYM_EMU_H
|
||||
#define GYM_EMU_H
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// Game_Music_Emu 0.5.2. http://www.slack.net/~ant/
|
||||
// Game_Music_Emu 0.6.0. http://www.slack.net/~ant/
|
||||
|
||||
#include "Hes_Apu.h"
|
||||
|
||||
|
@ -106,10 +106,10 @@ void Hes_Osc::run_until( synth_t& synth_, blip_time_t end_time )
|
|||
unsigned noise_lfsr = this->noise_lfsr;
|
||||
do
|
||||
{
|
||||
int new_dac = 0x1F & (unsigned)-(signed)(noise_lfsr >> 1 & 1);
|
||||
int new_dac = 0x1F & -(noise_lfsr >> 1 & 1);
|
||||
// Implemented using "Galios configuration"
|
||||
// TODO: find correct LFSR algorithm
|
||||
noise_lfsr = (noise_lfsr >> 1) ^ (0xE008 & (unsigned)-(signed)(noise_lfsr & 1));
|
||||
noise_lfsr = (noise_lfsr >> 1) ^ (0xE008 & -(noise_lfsr & 1));
|
||||
//noise_lfsr = (noise_lfsr >> 1) ^ (0x6000 & -(noise_lfsr & 1));
|
||||
int delta = new_dac - dac;
|
||||
if ( delta )
|
||||
|
@ -158,7 +158,7 @@ void Hes_Osc::run_until( synth_t& synth_, blip_time_t end_time )
|
|||
//period = 0x1000 * 2;
|
||||
period = 1;
|
||||
//if ( !(volume_0 | volume_1) )
|
||||
// dprintf( "Used period 0\n" );
|
||||
// debug_printf( "Used period 0\n" );
|
||||
}
|
||||
|
||||
// maintain phase when silent
|
||||
|
@ -295,7 +295,7 @@ void Hes_Apu::write_data( blip_time_t time, int addr, int data )
|
|||
|
||||
case 0x809:
|
||||
if ( !(data & 0x80) && (data & 0x03) != 0 )
|
||||
dprintf( "HES LFO not supported\n" );
|
||||
debug_printf( "HES LFO not supported\n" );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// Turbo Grafx 16 (PC Engine) PSG sound chip emulator
|
||||
|
||||
// Game_Music_Emu 0.5.2
|
||||
// Game_Music_Emu 0.6.0
|
||||
#ifndef HES_APU_H
|
||||
#define HES_APU_H
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// Game_Music_Emu 0.5.2. http://www.slack.net/~ant/
|
||||
// Game_Music_Emu 0.6.0. http://www.slack.net/~ant/
|
||||
|
||||
#include "Hes_Cpu.h"
|
||||
|
||||
|
@ -148,7 +148,7 @@ loop:
|
|||
/*
|
||||
static long count;
|
||||
if ( count == 1844 ) Debugger();
|
||||
if ( s.base != correct ) dprintf( "%ld\n", count );
|
||||
if ( s.base != correct ) debug_printf( "%ld\n", count );
|
||||
count++;
|
||||
*/
|
||||
}
|
||||
|
@ -741,7 +741,7 @@ possibly_out_of_time:
|
|||
ARITH_ADDR_MODES( 0x65 ) // ADC
|
||||
adc_imm: {
|
||||
if ( status & st_d )
|
||||
dprintf( "Decimal mode not supported\n" );
|
||||
debug_printf( "Decimal mode not supported\n" );
|
||||
fint16 carry = c >> 8 & 1;
|
||||
fint16 ov = (a ^ 0x80) + carry + (BOOST::int8_t) data; // sign-extend
|
||||
status &= ~st_v;
|
||||
|
@ -1085,7 +1085,7 @@ possibly_out_of_time:
|
|||
goto loop;
|
||||
}
|
||||
delayed_cli:
|
||||
dprintf( "Delayed CLI not supported\n" ); // TODO: implement
|
||||
debug_printf( "Delayed CLI not supported\n" ); // TODO: implement
|
||||
goto loop;
|
||||
}
|
||||
|
||||
|
@ -1100,7 +1100,7 @@ possibly_out_of_time:
|
|||
s_time += delta;
|
||||
if ( s_time < 0 )
|
||||
goto loop;
|
||||
dprintf( "Delayed SEI not supported\n" ); // TODO: implement
|
||||
debug_printf( "Delayed SEI not supported\n" ); // TODO: implement
|
||||
goto loop;
|
||||
}
|
||||
|
||||
|
@ -1145,7 +1145,7 @@ possibly_out_of_time:
|
|||
goto loop;
|
||||
|
||||
case 0x54: // CSL
|
||||
dprintf( "CSL not supported\n" );
|
||||
debug_printf( "CSL not supported\n" );
|
||||
illegal_encountered = true;
|
||||
goto loop;
|
||||
|
||||
|
@ -1154,7 +1154,7 @@ possibly_out_of_time:
|
|||
|
||||
case 0xF4: { // SET
|
||||
//fuint16 operand = GET_MSB();
|
||||
dprintf( "SET not handled\n" );
|
||||
debug_printf( "SET not handled\n" );
|
||||
//switch ( data )
|
||||
//{
|
||||
//}
|
||||
|
@ -1233,7 +1233,7 @@ possibly_out_of_time:
|
|||
|
||||
default:
|
||||
assert( (unsigned) opcode <= 0xFF );
|
||||
dprintf( "Illegal opcode $%02X at $%04X\n", (int) opcode, (int) pc - 1 );
|
||||
debug_printf( "Illegal opcode $%02X at $%04X\n", (int) opcode, (int) pc - 1 );
|
||||
illegal_encountered = true;
|
||||
goto loop;
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// PC Engine CPU emulator for use with HES music files
|
||||
|
||||
// Game_Music_Emu 0.5.2
|
||||
// Game_Music_Emu 0.6.0
|
||||
#ifndef HES_CPU_H
|
||||
#define HES_CPU_H
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// Game_Music_Emu 0.5.2. http://www.slack.net/~ant/
|
||||
// Game_Music_Emu 0.6.0. http://www.slack.net/~ant/
|
||||
|
||||
#include "Hes_Emu.h"
|
||||
|
||||
|
@ -273,12 +273,12 @@ void Hes_Emu::cpu_write_vdp( int addr, int data )
|
|||
}
|
||||
else
|
||||
{
|
||||
dprintf( "VDP not supported: $%02X <- $%02X\n", vdp.latch, data );
|
||||
debug_printf( "VDP not supported: $%02X <- $%02X\n", vdp.latch, data );
|
||||
}
|
||||
break;
|
||||
|
||||
case 3:
|
||||
dprintf( "VDP MSB not supported: $%02X <- $%02X\n", vdp.latch, data );
|
||||
debug_printf( "VDP MSB not supported: $%02X <- $%02X\n", vdp.latch, data );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -325,7 +325,7 @@ void Hes_Emu::cpu_write_( hes_addr_t addr, int data )
|
|||
run_until( time );
|
||||
irq.disables = data;
|
||||
if ( (data & 0xF8) && (data & 0xF8) != 0xF8 ) // flag questionable values
|
||||
dprintf( "Int mask: $%02X\n", data );
|
||||
debug_printf( "Int mask: $%02X\n", data );
|
||||
break;
|
||||
|
||||
case 0x1403:
|
||||
|
@ -344,7 +344,7 @@ void Hes_Emu::cpu_write_( hes_addr_t addr, int data )
|
|||
return;
|
||||
|
||||
default:
|
||||
dprintf( "unmapped write $%04X <- $%02X\n", addr, data );
|
||||
debug_printf( "unmapped write $%04X <- $%02X\n", addr, data );
|
||||
return;
|
||||
#endif
|
||||
}
|
||||
|
@ -368,14 +368,14 @@ int Hes_Emu::cpu_read_( hes_addr_t addr )
|
|||
|
||||
case 0x0002:
|
||||
case 0x0003:
|
||||
dprintf( "VDP read not supported: %d\n", addr );
|
||||
debug_printf( "VDP read not supported: %d\n", addr );
|
||||
return 0;
|
||||
|
||||
case 0x0C01:
|
||||
//return timer.enabled; // TODO: remove?
|
||||
case 0x0C00:
|
||||
run_until( time );
|
||||
dprintf( "Timer count read\n" );
|
||||
debug_printf( "Timer count read\n" );
|
||||
return (unsigned) (timer.count - 1) / timer_base;
|
||||
|
||||
case 0x1402:
|
||||
|
@ -396,7 +396,7 @@ int Hes_Emu::cpu_read_( hes_addr_t addr )
|
|||
break;
|
||||
|
||||
default:
|
||||
dprintf( "unmapped read $%04X\n", addr );
|
||||
debug_printf( "unmapped read $%04X\n", addr );
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// TurboGrafx-16/PC Engine HES music file emulator
|
||||
|
||||
// Game_Music_Emu 0.5.2
|
||||
// Game_Music_Emu 0.6.0
|
||||
#ifndef HES_EMU_H
|
||||
#define HES_EMU_H
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// Game_Music_Emu 0.5.2. http://www.slack.net/~ant/
|
||||
// Game_Music_Emu 0.6.0. http://www.slack.net/~ant/
|
||||
|
||||
/*
|
||||
Last validated with zexall 2006.11.14 2:19 PM
|
||||
|
@ -841,6 +841,7 @@ possibly_out_of_time:
|
|||
case 0xCB:
|
||||
unsigned data2;
|
||||
data2 = instr [1];
|
||||
(void) data2; // TODO is this the same as data in all cases?
|
||||
pc++;
|
||||
switch ( data )
|
||||
{
|
||||
|
@ -1084,7 +1085,7 @@ possibly_out_of_time:
|
|||
blargg_ulong sum = temp + (flags & C01);
|
||||
flags = ~data >> 2 & N02;
|
||||
if ( flags )
|
||||
sum = (blargg_ulong)-(blargg_long)sum;
|
||||
sum = -sum;
|
||||
sum += rp.hl;
|
||||
temp ^= rp.hl;
|
||||
temp ^= sum;
|
||||
|
@ -1289,7 +1290,7 @@ possibly_out_of_time:
|
|||
|
||||
case 0x4F: // LD R,A
|
||||
SET_R( rg.a );
|
||||
dprintf( "LD R,A not supported\n" );
|
||||
debug_printf( "LD R,A not supported\n" );
|
||||
warning = true;
|
||||
goto loop;
|
||||
|
||||
|
@ -1299,7 +1300,7 @@ possibly_out_of_time:
|
|||
|
||||
case 0x5F: // LD A,R
|
||||
rg.a = GET_R();
|
||||
dprintf( "LD A,R not supported\n" );
|
||||
debug_printf( "LD A,R not supported\n" );
|
||||
warning = true;
|
||||
ld_ai_common:
|
||||
flags = (flags & C01) | SZ28( rg.a ) | (r.iff2 << 2 & V04);
|
||||
|
@ -1322,7 +1323,7 @@ possibly_out_of_time:
|
|||
goto loop;
|
||||
|
||||
default:
|
||||
dprintf( "Opcode $ED $%02X not supported\n", data );
|
||||
debug_printf( "Opcode $ED $%02X not supported\n", data );
|
||||
warning = true;
|
||||
goto loop;
|
||||
}
|
||||
|
@ -1583,7 +1584,7 @@ possibly_out_of_time:
|
|||
}
|
||||
|
||||
default:
|
||||
dprintf( "Opcode $%02X $CB $%02X not supported\n", opcode, data2 );
|
||||
debug_printf( "Opcode $%02X $CB $%02X not supported\n", opcode, data2 );
|
||||
warning = true;
|
||||
goto loop;
|
||||
}
|
||||
|
@ -1672,7 +1673,7 @@ possibly_out_of_time:
|
|||
}
|
||||
|
||||
default:
|
||||
dprintf( "Unnecessary DD/FD prefix encountered\n" );
|
||||
debug_printf( "Unnecessary DD/FD prefix encountered\n" );
|
||||
warning = true;
|
||||
pc--;
|
||||
goto loop;
|
||||
|
@ -1681,7 +1682,7 @@ possibly_out_of_time:
|
|||
}
|
||||
|
||||
}
|
||||
dprintf( "Unhandled main opcode: $%02X\n", opcode );
|
||||
debug_printf( "Unhandled main opcode: $%02X\n", opcode );
|
||||
assert( false );
|
||||
|
||||
hit_idle_addr:
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// Z80 CPU emulator
|
||||
|
||||
// Game_Music_Emu 0.5.2
|
||||
// Game_Music_Emu 0.6.0
|
||||
#ifndef KSS_CPU_H
|
||||
#define KSS_CPU_H
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// Game_Music_Emu 0.5.2. http://www.slack.net/~ant/
|
||||
// Game_Music_Emu 0.6.0. http://www.slack.net/~ant/
|
||||
|
||||
#include "Kss_Emu.h"
|
||||
|
||||
|
@ -230,9 +230,9 @@ blargg_err_t Kss_Emu::start_track_( int track )
|
|||
bank_count = max_banks;
|
||||
set_warning( "Bank data missing" );
|
||||
}
|
||||
//dprintf( "load_size : $%X\n", load_size );
|
||||
//dprintf( "bank_size : $%X\n", bank_size );
|
||||
//dprintf( "bank_count: %d (%d claimed)\n", bank_count, header_.bank_mode & 0x7F );
|
||||
//debug_printf( "load_size : $%X\n", load_size );
|
||||
//debug_printf( "bank_size : $%X\n", bank_size );
|
||||
//debug_printf( "bank_count: %d (%d claimed)\n", bank_count, header_.bank_mode & 0x7F );
|
||||
|
||||
ram [idle_addr] = 0xFF;
|
||||
cpu::reset( unmapped_write, unmapped_read );
|
||||
|
@ -301,7 +301,7 @@ void Kss_Emu::cpu_write( unsigned addr, int data )
|
|||
return;
|
||||
}
|
||||
|
||||
dprintf( "LD ($%04X),$%02X\n", addr, data );
|
||||
debug_printf( "LD ($%04X),$%02X\n", addr, data );
|
||||
}
|
||||
|
||||
void kss_cpu_write( Kss_Cpu* cpu, unsigned addr, int data )
|
||||
|
@ -358,7 +358,7 @@ void kss_cpu_out( Kss_Cpu* cpu, cpu_time_t time, unsigned addr, int data )
|
|||
#endif
|
||||
}
|
||||
|
||||
dprintf( "OUT $%04X,$%02X\n", addr, data );
|
||||
debug_printf( "OUT $%04X,$%02X\n", addr, data );
|
||||
}
|
||||
|
||||
int kss_cpu_in( Kss_Cpu*, cpu_time_t, unsigned addr )
|
||||
|
@ -368,7 +368,7 @@ int kss_cpu_in( Kss_Cpu*, cpu_time_t, unsigned addr )
|
|||
//{
|
||||
//}
|
||||
|
||||
dprintf( "IN $%04X\n", addr );
|
||||
debug_printf( "IN $%04X\n", addr );
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// MSX computer KSS music file emulator
|
||||
|
||||
// Game_Music_Emu 0.5.2
|
||||
// Game_Music_Emu 0.6.0
|
||||
#ifndef KSS_EMU_H
|
||||
#define KSS_EMU_H
|
||||
|
||||
|
@ -68,7 +68,6 @@ private:
|
|||
void update_gain();
|
||||
|
||||
unsigned scc_enabled; // 0 or 0xC000
|
||||
byte const* bank_data;
|
||||
int bank_count;
|
||||
void set_bank( int logical, int physical );
|
||||
blargg_long bank_size() const { return (16 * 1024L) >> (header_.bank_mode >> 7 & 1); }
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// Game_Music_Emu 0.5.2. http://www.slack.net/~ant/
|
||||
// Game_Music_Emu 0.6.0. http://www.slack.net/~ant/
|
||||
|
||||
#include "Kss_Scc_Apu.h"
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// Konami SCC sound chip emulator
|
||||
|
||||
// Game_Music_Emu 0.5.2
|
||||
// Game_Music_Emu 0.6.0
|
||||
#ifndef KSS_SCC_APU_H
|
||||
#define KSS_SCC_APU_H
|
||||
|
||||
|
|
|
@ -1,6 +1,4 @@
|
|||
// Game_Music_Emu 0.5.2. http://www.slack.net/~ant/
|
||||
|
||||
#define IN_GME 1
|
||||
// Game_Music_Emu 0.6.0. http://www.slack.net/~ant/
|
||||
|
||||
#include "M3u_Playlist.h"
|
||||
#include "Music_Emu.h"
|
||||
|
@ -54,9 +52,9 @@ blargg_err_t Gme_File::load_m3u( const char* path ) { return load_m3u_( playlist
|
|||
|
||||
blargg_err_t Gme_File::load_m3u( Data_Reader& in ) { return load_m3u_( playlist.load( in ) ); }
|
||||
|
||||
gme_err_t GMEAPI gme_load_m3u( Music_Emu* me, const char* path ) { return me->load_m3u( path ); }
|
||||
BLARGG_EXPORT gme_err_t gme_load_m3u( Music_Emu* me, const char* path ) { return me->load_m3u( path ); }
|
||||
|
||||
gme_err_t GMEAPI gme_load_m3u_data( Music_Emu* me, const void* data, long size )
|
||||
BLARGG_EXPORT gme_err_t gme_load_m3u_data( Music_Emu* me, const void* data, long size )
|
||||
{
|
||||
Mem_File_Reader in( data, size );
|
||||
return me->load_m3u( in );
|
||||
|
@ -409,7 +407,7 @@ blargg_err_t M3u_Playlist::parse()
|
|||
blargg_err_t M3u_Playlist::load( Data_Reader& in )
|
||||
{
|
||||
RETURN_ERR( data.resize( in.remain() + 1 ) );
|
||||
RETURN_ERR( in.read( data.begin(), long(data.size() - 1) ) );
|
||||
RETURN_ERR( in.read( data.begin(), data.size() - 1 ) );
|
||||
return parse();
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// M3U playlist file parser, with support for subtrack information
|
||||
|
||||
// Game_Music_Emu 0.5.2
|
||||
// Game_Music_Emu 0.6.0
|
||||
#ifndef M3U_PLAYLIST_H
|
||||
#define M3U_PLAYLIST_H
|
||||
|
||||
|
@ -43,7 +43,7 @@ public:
|
|||
int repeat; // count
|
||||
};
|
||||
entry_t const& operator [] ( int i ) const { return entries [i]; }
|
||||
int size() const { return (int)entries.size(); }
|
||||
int size() const { return entries.size(); }
|
||||
|
||||
void clear();
|
||||
|
||||
|
|
|
@ -114,7 +114,7 @@ long Stereo_Buffer::read_samples( blip_sample_t* out, long count )
|
|||
if ( count )
|
||||
{
|
||||
int bufs_used = stereo_added | was_stereo;
|
||||
//dprintf( "%X\n", bufs_used );
|
||||
//debug_printf( "%X\n", bufs_used );
|
||||
if ( bufs_used <= 1 )
|
||||
{
|
||||
mix_mono( out, count );
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// Game_Music_Emu 0.5.2. http://www.slack.net/~ant/
|
||||
// Game_Music_Emu 0.6.0. http://www.slack.net/~ant/
|
||||
|
||||
#include "Music_Emu.h"
|
||||
|
||||
|
@ -24,7 +24,8 @@ int const silence_threshold = 0x10;
|
|||
long const fade_block_size = 512;
|
||||
int const fade_shift = 8; // fade ends with gain at 1.0 / (1 << fade_shift)
|
||||
|
||||
Music_Emu::equalizer_t const Music_Emu::tv_eq = { -8.0, 180, 0, 0, 0, 0, 0, 0, 0, 0 };
|
||||
Music_Emu::equalizer_t const Music_Emu::tv_eq =
|
||||
Music_Emu::make_equalizer( -8.0, 180 );
|
||||
|
||||
void Music_Emu::clear_track_vars()
|
||||
{
|
||||
|
@ -305,7 +306,7 @@ static long count_silence( Music_Emu::sample_t* begin, long size )
|
|||
Music_Emu::sample_t* p = begin + size;
|
||||
while ( (unsigned) (*--p + silence_threshold / 2) <= (unsigned) silence_threshold ) { }
|
||||
*begin = first;
|
||||
return size - long(p - begin);
|
||||
return size - (p - begin);
|
||||
}
|
||||
|
||||
// fill internal buffer and check it for silence
|
||||
|
@ -340,14 +341,14 @@ blargg_err_t Music_Emu::play( long out_count, sample_t* out )
|
|||
assert( emu_time >= out_time );
|
||||
|
||||
// prints nifty graph of how far ahead we are when searching for silence
|
||||
//dprintf( "%*s \n", int ((emu_time - out_time) * 7 / sample_rate()), "*" );
|
||||
//debug_printf( "%*s \n", int ((emu_time - out_time) * 7 / sample_rate()), "*" );
|
||||
|
||||
long pos = 0;
|
||||
if ( silence_count )
|
||||
{
|
||||
// during a run of silence, run emulator at >=2x speed so it gets ahead
|
||||
long ahead_time = silence_lookahead * (out_time + out_count - silence_time) + silence_time;
|
||||
while ( emu_time < ahead_time && !(buf_remain || emu_track_ended_) )
|
||||
while ( emu_time < ahead_time && !(buf_remain | emu_track_ended_) )
|
||||
fill_buf();
|
||||
|
||||
// fill with silence
|
||||
|
@ -404,6 +405,7 @@ blargg_err_t Gme_Info_::set_sample_rate_( long ) { return 0; }
|
|||
void Gme_Info_::pre_load() { Gme_File::pre_load(); } // skip Music_Emu
|
||||
void Gme_Info_::post_load_() { Gme_File::post_load_(); } // skip Music_Emu
|
||||
void Gme_Info_::set_equalizer_( equalizer_t const& ){ check( false ); }
|
||||
void Gme_Info_::enable_accuracy_( bool ) { check( false ); }
|
||||
void Gme_Info_::mute_voices_( int ) { check( false ); }
|
||||
void Gme_Info_::set_tempo_( double ) { }
|
||||
blargg_err_t Gme_Info_::start_track_( int ) { return "Use full emulator for playback"; }
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// Common interface to game music file emulators
|
||||
|
||||
// Game_Music_Emu 0.5.2
|
||||
// Game_Music_Emu 0.6.0
|
||||
#ifndef MUSIC_EMU_H
|
||||
#define MUSIC_EMU_H
|
||||
|
||||
|
@ -82,6 +82,10 @@ public:
|
|||
// on others this has no effect. Should be called only once *before* set_sample_rate().
|
||||
virtual void set_buffer( Multi_Buffer* ) { }
|
||||
|
||||
// Enables/disables accurate emulation options, if any are supported. Might change
|
||||
// equalizer settings.
|
||||
void enable_accuracy( bool enable = true );
|
||||
|
||||
// Sound equalization (treble/bass)
|
||||
|
||||
// Frequency equalizer parameters (see gme.txt)
|
||||
|
@ -93,6 +97,14 @@ public:
|
|||
|
||||
// Set frequency equalizer parameters
|
||||
void set_equalizer( equalizer_t const& );
|
||||
|
||||
// Construct equalizer of given treble/bass settings
|
||||
static const equalizer_t make_equalizer( double treble, double bass )
|
||||
{
|
||||
const Music_Emu::equalizer_t e = { treble, bass,
|
||||
0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 };
|
||||
return e;
|
||||
}
|
||||
|
||||
// Equalizer settings for TV speaker
|
||||
static equalizer_t const tv_eq;
|
||||
|
@ -111,7 +123,8 @@ protected:
|
|||
void remute_voices();
|
||||
|
||||
virtual blargg_err_t set_sample_rate_( long sample_rate ) = 0;
|
||||
virtual void set_equalizer_( equalizer_t const& ) { };
|
||||
virtual void set_equalizer_( equalizer_t const& ) { }
|
||||
virtual void enable_accuracy_( bool /* enable */ ) { }
|
||||
virtual void mute_voices_( int mask ) = 0;
|
||||
virtual void set_tempo_( double ) = 0;
|
||||
virtual blargg_err_t start_track_( int ) = 0; // tempo is set before this
|
||||
|
@ -160,8 +173,8 @@ private:
|
|||
void emu_play( long count, sample_t* out );
|
||||
|
||||
Multi_Buffer* effects_buffer;
|
||||
friend GMEDLL Music_Emu* GMEAPI gme_new_emu( gme_type_t, int );
|
||||
friend GMEDLL void GMEAPI gme_set_stereo_depth( Music_Emu*, double );
|
||||
friend Music_Emu* gme_new_emu( gme_type_t, int );
|
||||
friend void gme_set_stereo_depth( Music_Emu*, double );
|
||||
};
|
||||
|
||||
// base class for info-only derivations
|
||||
|
@ -169,6 +182,7 @@ struct Gme_Info_ : Music_Emu
|
|||
{
|
||||
virtual blargg_err_t set_sample_rate_( long sample_rate );
|
||||
virtual void set_equalizer_( equalizer_t const& );
|
||||
virtual void enable_accuracy_( bool );
|
||||
virtual void mute_voices_( int mask );
|
||||
virtual void set_tempo_( double );
|
||||
virtual blargg_err_t start_track_( int );
|
||||
|
@ -189,6 +203,7 @@ inline int Music_Emu::current_track() const { return current_track_; }
|
|||
inline bool Music_Emu::track_ended() const { return track_ended_; }
|
||||
inline const Music_Emu::equalizer_t& Music_Emu::equalizer() const { return equalizer_; }
|
||||
|
||||
inline void Music_Emu::enable_accuracy( bool b ) { enable_accuracy_( b ); }
|
||||
inline void Music_Emu::set_tempo_( double t ) { tempo_ = t; }
|
||||
inline void Music_Emu::remute_voices() { mute_voices( mute_mask_ ); }
|
||||
inline void Music_Emu::ignore_silence( bool b ) { ignore_silence_ = b; }
|
||||
|
|
|
@ -385,7 +385,7 @@ int Nes_Apu::read_status( nes_time_t time )
|
|||
irq_changed();
|
||||
}
|
||||
|
||||
//dprintf( "%6d/%d Read $4015->$%02X\n", frame_delay, frame, result );
|
||||
//debug_printf( "%6d/%d Read $4015->$%02X\n", frame_delay, frame, result );
|
||||
|
||||
return result;
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// Game_Music_Emu 0.5.2. http://www.slack.net/~ant/
|
||||
// Game_Music_Emu 0.6.0. http://www.slack.net/~ant/
|
||||
|
||||
#include "Nes_Cpu.h"
|
||||
|
||||
|
@ -921,7 +921,7 @@ imm##op:
|
|||
goto loop;
|
||||
status &= ~st_i;
|
||||
handle_cli: {
|
||||
//dprintf( "CLI at %d\n", TIME );
|
||||
//debug_printf( "CLI at %d\n", TIME );
|
||||
this->r.status = status; // update externally-visible I flag
|
||||
blargg_long delta = s.base - irq_time_;
|
||||
if ( delta <= 0 )
|
||||
|
@ -944,7 +944,7 @@ imm##op:
|
|||
|
||||
// TODO: implement
|
||||
delayed_cli:
|
||||
dprintf( "Delayed CLI not emulated\n" );
|
||||
debug_printf( "Delayed CLI not emulated\n" );
|
||||
goto loop;
|
||||
}
|
||||
|
||||
|
@ -960,7 +960,7 @@ imm##op:
|
|||
if ( s_time < 0 )
|
||||
goto loop;
|
||||
|
||||
dprintf( "Delayed SEI not emulated\n" );
|
||||
debug_printf( "Delayed SEI not emulated\n" );
|
||||
goto loop;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// NES 6502 CPU emulator
|
||||
|
||||
// Game_Music_Emu 0.5.2
|
||||
// Game_Music_Emu 0.6.0
|
||||
#ifndef NES_CPU_H
|
||||
#define NES_CPU_H
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// Game_Music_Emu 0.5.2. http://www.slack.net/~ant/
|
||||
// Game_Music_Emu 0.6.0. http://www.slack.net/~ant/
|
||||
|
||||
#include "Nes_Fme7_Apu.h"
|
||||
|
||||
|
@ -56,7 +56,7 @@ void Nes_Fme7_Apu::run_until( blip_time_t end_time )
|
|||
// check for unsupported mode
|
||||
#ifndef NDEBUG
|
||||
if ( (mode & 011) <= 001 && vol_mode & 0x1F )
|
||||
dprintf( "FME7 used unimplemented sound mode: %02X, vol_mode: %02X\n",
|
||||
debug_printf( "FME7 used unimplemented sound mode: %02X, vol_mode: %02X\n",
|
||||
mode, vol_mode & 0x1F );
|
||||
#endif
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// Sunsoft FME-7 sound emulator
|
||||
|
||||
// Game_Music_Emu 0.5.2
|
||||
// Game_Music_Emu 0.6.0
|
||||
#ifndef NES_FME7_APU_H
|
||||
#define NES_FME7_APU_H
|
||||
|
||||
|
@ -97,8 +97,8 @@ inline void Nes_Fme7_Apu::write_data( blip_time_t time, int data )
|
|||
{
|
||||
if ( (unsigned) latch >= reg_count )
|
||||
{
|
||||
#ifdef dprintf
|
||||
dprintf( "FME7 write to %02X (past end of sound registers)\n", (int) latch );
|
||||
#ifdef debug_printf
|
||||
debug_printf( "FME7 write to %02X (past end of sound registers)\n", (int) latch );
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// Game_Music_Emu 0.5.2. http://www.slack.net/~ant/
|
||||
// Game_Music_Emu 0.6.0. http://www.slack.net/~ant/
|
||||
|
||||
#include "Nsf_Emu.h"
|
||||
|
||||
|
@ -31,8 +31,10 @@ int const fme7_flag = 0x20;
|
|||
|
||||
long const clock_divisor = 12;
|
||||
|
||||
Nsf_Emu::equalizer_t const Nsf_Emu::nes_eq = { -1.0, 80, 0, 0, 0, 0, 0, 0, 0, 0 };
|
||||
Nsf_Emu::equalizer_t const Nsf_Emu::famicom_eq = { -15.0, 80, 0, 0, 0, 0, 0, 0, 0, 0 };
|
||||
Nsf_Emu::equalizer_t const Nsf_Emu::nes_eq =
|
||||
Music_Emu::make_equalizer( -1.0, 80 );
|
||||
Nsf_Emu::equalizer_t const Nsf_Emu::famicom_eq =
|
||||
Music_Emu::make_equalizer( -15.0, 80 );
|
||||
|
||||
int Nsf_Emu::pcm_read( void* emu, nes_addr_t addr )
|
||||
{
|
||||
|
@ -442,7 +444,7 @@ void Nsf_Emu::cpu_write_misc( nes_addr_t addr, int data )
|
|||
// memory mapper?
|
||||
if ( addr == 0xFFF8 ) return;
|
||||
|
||||
dprintf( "write_unmapped( 0x%04X, 0x%02X )\n", (unsigned) addr, (unsigned) data );
|
||||
debug_printf( "write_unmapped( 0x%04X, 0x%02X )\n", (unsigned) addr, (unsigned) data );
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// Nintendo NES/Famicom NSF music file emulator
|
||||
|
||||
// Game_Music_Emu 0.5.2
|
||||
// Game_Music_Emu 0.6.0
|
||||
#ifndef NSF_EMU_H
|
||||
#define NSF_EMU_H
|
||||
|
||||
|
|
|
@ -1,6 +1,4 @@
|
|||
// Game_Music_Emu 0.5.2. http://www.slack.net/~ant/
|
||||
|
||||
#define _CRT_SECURE_NO_WARNINGS
|
||||
// Game_Music_Emu 0.6.0. http://www.slack.net/~ant/
|
||||
|
||||
#include "Nsfe_Emu.h"
|
||||
|
||||
|
@ -37,7 +35,7 @@ inline void Nsfe_Info::unload()
|
|||
void Nsfe_Info::disable_playlist( bool b )
|
||||
{
|
||||
playlist_disabled = b;
|
||||
info.track_count = (byte)playlist.size();
|
||||
info.track_count = playlist.size();
|
||||
if ( !info.track_count || playlist_disabled )
|
||||
info.track_count = actual_track_count_;
|
||||
}
|
||||
|
@ -137,7 +135,7 @@ blargg_err_t Nsfe_Info::load( Data_Reader& in, Nsf_Emu* nsf_emu )
|
|||
blargg_long size = get_le32( block_header [0] );
|
||||
blargg_long tag = get_le32( block_header [1] );
|
||||
|
||||
//dprintf( "tag: %c%c%c%c\n", char(tag), char(tag>>8), char(tag>>16), char(tag>>24) );
|
||||
//debug_printf( "tag: %c%c%c%c\n", char(tag), char(tag>>8), char(tag>>16), char(tag>>24) );
|
||||
|
||||
switch ( tag )
|
||||
{
|
||||
|
@ -173,7 +171,7 @@ blargg_err_t Nsfe_Info::load( Data_Reader& in, Nsf_Emu* nsf_emu )
|
|||
blargg_vector<char> chars;
|
||||
blargg_vector<const char*> strs;
|
||||
RETURN_ERR( read_strs( in, size, chars, strs ) );
|
||||
int n = (int)strs.size();
|
||||
int n = strs.size();
|
||||
|
||||
if ( n > 3 )
|
||||
copy_str( strs [3], info.dumper, sizeof info.dumper );
|
||||
|
@ -192,7 +190,7 @@ blargg_err_t Nsfe_Info::load( Data_Reader& in, Nsf_Emu* nsf_emu )
|
|||
|
||||
case BLARGG_4CHAR('e','m','i','t'):
|
||||
RETURN_ERR( track_times.resize( size / 4 ) );
|
||||
RETURN_ERR( in.read( track_times.begin(), (long)track_times.size() * 4 ) );
|
||||
RETURN_ERR( in.read( track_times.begin(), track_times.size() * 4 ) );
|
||||
break;
|
||||
|
||||
case BLARGG_4CHAR('l','b','l','t'):
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// Nintendo NES/Famicom NSFE music file emulator
|
||||
|
||||
// Game_Music_Emu 0.5.2
|
||||
// Game_Music_Emu 0.6.0
|
||||
#ifndef NSFE_EMU_H
|
||||
#define NSFE_EMU_H
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// Game_Music_Emu 0.5.2. http://www.slack.net/~ant/
|
||||
// Game_Music_Emu 0.6.0. http://www.slack.net/~ant/
|
||||
|
||||
#include "Sap_Apu.h"
|
||||
|
||||
|
@ -30,7 +30,7 @@ static void gen_poly( blargg_ulong mask, int count, byte* out )
|
|||
{
|
||||
// implemented using "Galios configuration"
|
||||
bits |= (n & 1) << b;
|
||||
n = (n >> 1) ^ (mask & (blargg_ulong)-(blargg_long)(n & 1));
|
||||
n = (n >> 1) ^ (mask & -(n & 1));
|
||||
}
|
||||
while ( b++ < 7 );
|
||||
*out++ = bits;
|
||||
|
@ -66,7 +66,7 @@ Sap_Apu_Impl::Sap_Apu_Impl()
|
|||
blargg_ulong rev = n & 1;
|
||||
for ( int i = 1; i < poly5_len; i++ )
|
||||
rev |= (n >> i & 1) << (poly5_len - i);
|
||||
dprintf( "poly5: 0x%08lX\n", rev );
|
||||
debug_printf( "poly5: 0x%08lX\n", rev );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -114,7 +114,7 @@ inline void Sap_Apu::calc_periods()
|
|||
period = (period - 6) * divider;
|
||||
|
||||
if ( (osc [-1].regs [1] & 0x1F) > 0x10 )
|
||||
dprintf( "Use of slave channel in 16-bit mode not supported\n" );
|
||||
debug_printf( "Use of slave channel in 16-bit mode not supported\n" );
|
||||
}
|
||||
}
|
||||
osc->period = period;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// Atari POKEY sound chip emulator
|
||||
|
||||
// Game_Music_Emu 0.5.2
|
||||
// Game_Music_Emu 0.6.0
|
||||
#ifndef SAP_APU_H
|
||||
#define SAP_APU_H
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// Game_Music_Emu 0.5.2. http://www.slack.net/~ant/
|
||||
// Game_Music_Emu 0.6.0. http://www.slack.net/~ant/
|
||||
|
||||
#include "Sap_Cpu.h"
|
||||
|
||||
|
@ -889,7 +889,7 @@ imm##op:
|
|||
goto loop;
|
||||
}
|
||||
delayed_cli:
|
||||
dprintf( "Delayed CLI not emulated\n" );
|
||||
debug_printf( "Delayed CLI not emulated\n" );
|
||||
goto loop;
|
||||
}
|
||||
|
||||
|
@ -904,7 +904,7 @@ imm##op:
|
|||
s_time += delta;
|
||||
if ( s_time < 0 )
|
||||
goto loop;
|
||||
dprintf( "Delayed SEI not emulated\n" );
|
||||
debug_printf( "Delayed SEI not emulated\n" );
|
||||
goto loop;
|
||||
}
|
||||
|
||||
|
@ -945,7 +945,7 @@ handle_brk:
|
|||
goto idle_done;
|
||||
pc++;
|
||||
result_ = 4;
|
||||
dprintf( "BRK executed\n" );
|
||||
debug_printf( "BRK executed\n" );
|
||||
|
||||
interrupt:
|
||||
{
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// Atari 6502 CPU emulator
|
||||
|
||||
// Game_Music_Emu 0.5.2
|
||||
// Game_Music_Emu 0.6.0
|
||||
#ifndef SAP_CPU_H
|
||||
#define SAP_CPU_H
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// Game_Music_Emu 0.5.2. http://www.slack.net/~ant/
|
||||
// Game_Music_Emu 0.6.0. http://www.slack.net/~ant/
|
||||
|
||||
#include "Sap_Emu.h"
|
||||
|
||||
|
@ -119,7 +119,7 @@ static blargg_err_t parse_info( byte const* in, long size, Sap_Emu::info_t* out
|
|||
char const* tag = (char const*) in;
|
||||
while ( in < line_end && *in > ' ' )
|
||||
in++;
|
||||
int tag_len = int((char const*) in - tag);
|
||||
int tag_len = (char const*) in - tag;
|
||||
|
||||
while ( in < line_end && *in <= ' ' ) in++;
|
||||
|
||||
|
@ -256,7 +256,7 @@ blargg_err_t Sap_Emu::load_mem_( byte const* in, long size )
|
|||
|
||||
set_warning( info.warning );
|
||||
set_track_count( info.track_count );
|
||||
set_voice_count( Sap_Apu::osc_count << (int)info.stereo );
|
||||
set_voice_count( Sap_Apu::osc_count << info.stereo );
|
||||
apu_impl.volume( gain() );
|
||||
|
||||
return setup_buffer( 1773447 );
|
||||
|
@ -315,8 +315,8 @@ inline void Sap_Emu::call_init( int track )
|
|||
|
||||
case 'C':
|
||||
r.a = 0x70;
|
||||
r.x = (BOOST::uint8_t)(info.music_addr&0xFF);
|
||||
r.y = (BOOST::uint8_t)(info.music_addr >> 8);
|
||||
r.x = info.music_addr&0xFF;
|
||||
r.y = info.music_addr >> 8;
|
||||
run_routine( info.play_addr + 3 );
|
||||
r.a = 0;
|
||||
r.x = track;
|
||||
|
@ -336,7 +336,7 @@ blargg_err_t Sap_Emu::start_track_( int track )
|
|||
{
|
||||
unsigned start = get_le16( in );
|
||||
unsigned end = get_le16( in + 2 );
|
||||
//dprintf( "Block $%04X-$%04X\n", start, end );
|
||||
//debug_printf( "Block $%04X-$%04X\n", start, end );
|
||||
in += 4;
|
||||
if ( end < start )
|
||||
{
|
||||
|
@ -390,7 +390,7 @@ void Sap_Emu::cpu_write_( sap_addr_t addr, int data )
|
|||
}
|
||||
|
||||
if ( (addr & ~0x0010) != 0xD20F || data != 0x03 )
|
||||
dprintf( "Unmapped write $%04X <- $%02X\n", addr, data );
|
||||
debug_printf( "Unmapped write $%04X <- $%02X\n", addr, data );
|
||||
}
|
||||
|
||||
inline void Sap_Emu::call_play()
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// Atari XL/XE SAP music file emulator
|
||||
|
||||
// Game_Music_Emu 0.5.2
|
||||
// Game_Music_Emu 0.6.0
|
||||
#ifndef SAP_EMU_H
|
||||
#define SAP_EMU_H
|
||||
|
||||
|
|
|
@ -141,7 +141,7 @@ void Sms_Noise::run( blip_time_t time, blip_time_t end_time )
|
|||
do
|
||||
{
|
||||
int changed = shifter + 1;
|
||||
shifter = (feedback & (unsigned)-(signed)(shifter & 1)) ^ (shifter >> 1);
|
||||
shifter = (feedback & -(shifter & 1)) ^ (shifter >> 1);
|
||||
if ( changed & 2 ) // true if bits 0 and 1 differ
|
||||
{
|
||||
delta = -delta;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// SPC emulation support: init, sample buffering, reset, SPC loading
|
||||
|
||||
// snes_spc 0.9.0. http://www.slack.net/~ant/
|
||||
// Game_Music_Emu 0.6.0. http://www.slack.net/~ant/
|
||||
|
||||
#include "Snes_Spc.h"
|
||||
|
||||
|
@ -303,7 +303,7 @@ void Snes_Spc::set_output( sample_t* out, int size )
|
|||
assert( out <= out_end );
|
||||
}
|
||||
|
||||
dsp.set_output( out, int(out_end - out) );
|
||||
dsp.set_output( out, out_end - out );
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// SNES SPC-700 APU emulator
|
||||
|
||||
// snes_spc 0.9.0
|
||||
// Game_Music_Emu 0.6.0
|
||||
#ifndef SNES_SPC_H
|
||||
#define SNES_SPC_H
|
||||
|
||||
|
@ -66,10 +66,7 @@ public:
|
|||
// Sets tempo, where tempo_unit = normal, tempo_unit / 2 = half speed, etc.
|
||||
enum { tempo_unit = 0x100 };
|
||||
void set_tempo( int );
|
||||
|
||||
enum { gain_unit = Spc_Dsp::gain_unit };
|
||||
void set_gain( int gain );
|
||||
|
||||
|
||||
// SPC music files
|
||||
|
||||
// Loads SPC data into emulator
|
||||
|
@ -107,6 +104,22 @@ public:
|
|||
bool check_kon();
|
||||
#endif
|
||||
|
||||
public:
|
||||
// TODO: document
|
||||
struct regs_t
|
||||
{
|
||||
int pc;
|
||||
int a;
|
||||
int x;
|
||||
int y;
|
||||
int psw;
|
||||
int sp;
|
||||
};
|
||||
regs_t& smp_regs() { return m.cpu_regs; }
|
||||
|
||||
uint8_t* smp_ram() { return m.ram.ram; }
|
||||
|
||||
void run_until( time_t t ) { run_until_( t ); }
|
||||
public:
|
||||
BLARGG_DISABLE_NOTHROW
|
||||
|
||||
|
@ -146,15 +159,7 @@ private:
|
|||
|
||||
uint8_t smp_regs [2] [reg_count];
|
||||
|
||||
struct
|
||||
{
|
||||
int pc;
|
||||
int a;
|
||||
int x;
|
||||
int y;
|
||||
int psw;
|
||||
int sp;
|
||||
} cpu_regs;
|
||||
regs_t cpu_regs;
|
||||
|
||||
rel_time_t dsp_time;
|
||||
time_t spc_time;
|
||||
|
@ -271,8 +276,6 @@ inline void Snes_Spc::write_port( time_t t, int port, int data )
|
|||
run_until_( t ) [0x10 + port] = data;
|
||||
}
|
||||
|
||||
inline void Snes_Spc::set_gain( int gain ) { dsp.set_gain( gain ); }
|
||||
|
||||
inline void Snes_Spc::mute_voices( int mask ) { dsp.mute_voices( mask ); }
|
||||
|
||||
inline void Snes_Spc::disable_surround( bool disable ) { dsp.disable_surround( disable ); }
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// Core SPC emulation: CPU, timers, SMP registers, memory
|
||||
|
||||
// snes_spc 0.9.0. http://www.slack.net/~ant/
|
||||
// Game_Music_Emu 0.6.0. http://www.slack.net/~ant/
|
||||
|
||||
#include "Snes_Spc.h"
|
||||
|
||||
|
@ -176,7 +176,7 @@ inline void Snes_Spc::dsp_write( int data, rel_time_t time )
|
|||
if ( REGS [r_dspaddr] <= 0x7F )
|
||||
dsp.write( REGS [r_dspaddr], data );
|
||||
else if ( !SPC_MORE_ACCURACY )
|
||||
dprintf( "SPC wrote to DSP register > $7F\n" );
|
||||
debug_printf( "SPC wrote to DSP register > $7F\n" );
|
||||
}
|
||||
|
||||
|
||||
|
@ -277,8 +277,9 @@ static unsigned char const glitch_probs [3] [256] =
|
|||
};
|
||||
#endif
|
||||
|
||||
// divided into multiple functions to keep rarely-used functionality separate
|
||||
// so often-used functionality can be optimized better by compiler
|
||||
// Read/write handlers are divided into multiple functions to keep rarely-used
|
||||
// functionality separate so often-used functionality can be optimized better
|
||||
// by compiler.
|
||||
|
||||
// If write isn't preceded by read, data has this added to it
|
||||
int const no_read_before_write = 0x2000;
|
||||
|
@ -302,7 +303,7 @@ void Snes_Spc::cpu_write_smp_reg_( int data, rel_time_t time, int addr )
|
|||
t->next_time == time + TIMER_MUL( t, 1 ) &&
|
||||
((period - 1) | ~0x0F) & period )
|
||||
{
|
||||
//dprintf( "SPC pathological timer target write\n" );
|
||||
//debug_printf( "SPC pathological timer target write\n" );
|
||||
|
||||
// If the period is 3, 5, or 9, there's a probability this behavior won't occur,
|
||||
// based on the previous period
|
||||
|
@ -331,7 +332,7 @@ void Snes_Spc::cpu_write_smp_reg_( int data, rel_time_t time, int addr )
|
|||
case r_t1out:
|
||||
case r_t2out:
|
||||
if ( !SPC_MORE_ACCURACY )
|
||||
dprintf( "SPC wrote to counter %d\n", (int) addr - r_t0out );
|
||||
debug_printf( "SPC wrote to counter %d\n", (int) addr - r_t0out );
|
||||
|
||||
if ( data < no_read_before_write / 2 )
|
||||
run_timer( &m.timers [addr - r_t0out], time - 1 )->counter = 0;
|
||||
|
@ -345,7 +346,7 @@ void Snes_Spc::cpu_write_smp_reg_( int data, rel_time_t time, int addr )
|
|||
|
||||
case r_test:
|
||||
if ( (uint8_t) data != 0x0A )
|
||||
dprintf( "SPC wrote to test register\n" );
|
||||
debug_printf( "SPC wrote to test register\n" );
|
||||
break;
|
||||
|
||||
case r_control:
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// snes_spc 0.9.0. http://www.slack.net/~ant/
|
||||
// Game_Music_Emu 0.6.0. http://www.slack.net/~ant/
|
||||
|
||||
/* 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
|
||||
|
@ -16,7 +16,7 @@ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
|
|||
#if SPC_MORE_ACCURACY
|
||||
#define SUSPICIOUS_OPCODE( name ) ((void) 0)
|
||||
#else
|
||||
#define SUSPICIOUS_OPCODE( name ) dprintf( "SPC: suspicious opcode: " name "\n" )
|
||||
#define SUSPICIOUS_OPCODE( name ) debug_printf( "SPC: suspicious opcode: " name "\n" )
|
||||
#endif
|
||||
|
||||
#define CPU_READ( time, offset, addr )\
|
||||
|
@ -69,7 +69,7 @@ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
|
|||
#define READ_PROG16( addr ) GET_LE16( ram + (addr) )
|
||||
|
||||
#define SET_PC( n ) (pc = ram + (n))
|
||||
#define GET_PC() (int(pc - ram))
|
||||
#define GET_PC() (pc - ram)
|
||||
#define READ_PC( pc ) (*(pc))
|
||||
#define READ_PC16( pc ) GET_LE16( pc )
|
||||
|
||||
|
@ -77,7 +77,7 @@ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
|
|||
#define SPC_NO_SP_WRAPAROUND 0
|
||||
|
||||
#define SET_SP( v ) (sp = ram + 0x101 + (v))
|
||||
#define GET_SP() (int(sp - 0x101 - ram))
|
||||
#define GET_SP() (sp - 0x101 - ram)
|
||||
|
||||
#if SPC_NO_SP_WRAPAROUND
|
||||
#define PUSH16( v ) (sp -= 2, SET_LE16( sp, v ))
|
||||
|
@ -87,7 +87,7 @@ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
|
|||
#else
|
||||
#define PUSH16( data )\
|
||||
{\
|
||||
int addr = int((sp -= 2) - ram);\
|
||||
int addr = (sp -= 2) - ram;\
|
||||
if ( addr > 0x100 )\
|
||||
{\
|
||||
SET_LE16( sp, data );\
|
||||
|
@ -242,7 +242,7 @@ loop:
|
|||
BRANCH( (uint8_t) nz )
|
||||
|
||||
case 0x3F:{// CALL
|
||||
int old_addr = int(GET_PC() + 2);
|
||||
int old_addr = GET_PC() + 2;
|
||||
SET_PC( READ_PC16( pc ) );
|
||||
PUSH16( old_addr );
|
||||
goto loop;
|
||||
|
@ -256,7 +256,7 @@ loop:
|
|||
}
|
||||
#else
|
||||
{
|
||||
int addr = int(sp - ram);
|
||||
int addr = sp - ram;
|
||||
SET_PC( GET_LE16( sp ) );
|
||||
sp += 2;
|
||||
if ( addr < 0x1FF )
|
||||
|
@ -1184,7 +1184,7 @@ loop:
|
|||
{
|
||||
addr &= 0xFFFF;
|
||||
SET_PC( addr );
|
||||
dprintf( "SPC: PC wrapped around\n" );
|
||||
debug_printf( "SPC: PC wrapped around\n" );
|
||||
goto loop;
|
||||
}
|
||||
}
|
||||
|
@ -1205,7 +1205,7 @@ stop:
|
|||
|
||||
// Uncache registers
|
||||
if ( GET_PC() >= 0x10000 )
|
||||
dprintf( "SPC: PC wrapped around\n" );
|
||||
debug_printf( "SPC: PC wrapped around\n" );
|
||||
m.cpu_regs.pc = (uint16_t) GET_PC();
|
||||
m.cpu_regs.sp = ( uint8_t) GET_SP();
|
||||
m.cpu_regs.a = ( uint8_t) a;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// snes_spc 0.9.0. http://www.slack.net/~ant/
|
||||
// Game_Music_Emu 0.6.0. http://www.slack.net/~ant/
|
||||
|
||||
#include "Spc_Dsp.h"
|
||||
|
||||
|
@ -155,7 +155,7 @@ inline void Spc_Dsp::init_counter()
|
|||
// counters start out with this synchronization
|
||||
m.counters [0] = 1;
|
||||
m.counters [1] = 0;
|
||||
m.counters [2] = -0x20;
|
||||
m.counters [2] = -0x20u;
|
||||
m.counters [3] = 0x0B;
|
||||
|
||||
int n = 2;
|
||||
|
@ -606,8 +606,8 @@ skip_brr:
|
|||
}
|
||||
|
||||
// Sound out
|
||||
int l = (((main_out_l * mvoll + echo_in_l * (int8_t) REG(evoll)) >> 14) * m.gain) >> 8;
|
||||
int r = (((main_out_r * mvolr + echo_in_r * (int8_t) REG(evolr)) >> 14) * m.gain) >> 8;
|
||||
int l = (main_out_l * mvoll + echo_in_l * (int8_t) REG(evoll)) >> 14;
|
||||
int r = (main_out_r * mvolr + echo_in_r * (int8_t) REG(evolr)) >> 14;
|
||||
|
||||
CLAMP16( l );
|
||||
CLAMP16( r );
|
||||
|
@ -641,7 +641,6 @@ void Spc_Dsp::mute_voices( int mask )
|
|||
void Spc_Dsp::init( void* ram_64k )
|
||||
{
|
||||
m.ram = (uint8_t*) ram_64k;
|
||||
set_gain( gain_unit );
|
||||
mute_voices( 0 );
|
||||
disable_surround( false );
|
||||
set_output( 0, 0 );
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
// Fast SNES SPC-700 DSP emulator (about 3x speed of accurate one)
|
||||
|
||||
// snes_spc 0.9.0
|
||||
// Game_Music_Emu 0.6.0
|
||||
#ifndef SPC_DSP_H
|
||||
#define SPC_DSP_H
|
||||
|
||||
#include "blargg_common.h"
|
||||
|
||||
class Spc_Dsp {
|
||||
struct Spc_Dsp {
|
||||
public:
|
||||
typedef BOOST::uint8_t uint8_t;
|
||||
|
||||
|
@ -51,10 +51,7 @@ public:
|
|||
|
||||
// If true, prevents channels and global volumes from being phase-negated
|
||||
void disable_surround( bool disable = true );
|
||||
|
||||
enum { gain_unit = 0x100 };
|
||||
void set_gain( int gain );
|
||||
|
||||
|
||||
// State
|
||||
|
||||
// Resets DSP and uses supplied values to initialize registers
|
||||
|
@ -140,7 +137,6 @@ private:
|
|||
// non-emulation state
|
||||
uint8_t* ram; // 64K shared RAM between DSP and SMP
|
||||
int mute_mask;
|
||||
int gain;
|
||||
int surround_threshold;
|
||||
sample_t* out;
|
||||
sample_t* out_end;
|
||||
|
@ -158,7 +154,7 @@ private:
|
|||
|
||||
#include <assert.h>
|
||||
|
||||
inline int Spc_Dsp::sample_count() const { return int(m.out - m.out_begin); }
|
||||
inline int Spc_Dsp::sample_count() const { return m.out - m.out_begin; }
|
||||
|
||||
inline int Spc_Dsp::read( int addr ) const
|
||||
{
|
||||
|
@ -204,8 +200,6 @@ inline void Spc_Dsp::write( int addr, int data )
|
|||
}
|
||||
}
|
||||
|
||||
inline void Spc_Dsp::set_gain( int gain ) { m.gain = gain; }
|
||||
|
||||
inline void Spc_Dsp::disable_surround( bool disable )
|
||||
{
|
||||
m.surround_threshold = disable ? 0 : -0x4000;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// Game_Music_Emu 0.5.2. http://www.slack.net/~ant/
|
||||
// Game_Music_Emu 0.6.0. http://www.slack.net/~ant/
|
||||
|
||||
#include "Spc_Emu.h"
|
||||
|
||||
|
@ -19,6 +19,8 @@ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
|
|||
|
||||
#include "blargg_source.h"
|
||||
|
||||
// TODO: support Spc_Filter's bass
|
||||
|
||||
Spc_Emu::Spc_Emu()
|
||||
{
|
||||
set_type( gme_spc_type );
|
||||
|
@ -54,7 +56,7 @@ static void get_spc_xid6( byte const* begin, long size, track_info_t* out )
|
|||
byte const* in = begin + 8;
|
||||
if ( end - in > info_size )
|
||||
{
|
||||
dprintf( "Extra data after SPC xid6 info\n" );
|
||||
debug_printf( "Extra data after SPC xid6 info\n" );
|
||||
end = in + info_size;
|
||||
}
|
||||
|
||||
|
@ -114,7 +116,7 @@ static void get_spc_xid6( byte const* begin, long size, track_info_t* out )
|
|||
default:
|
||||
if ( id < 0x01 || (id > 0x07 && id < 0x10) ||
|
||||
(id > 0x14 && id < 0x30) || id > 0x36 )
|
||||
dprintf( "Unknown SPC xid6 block: %X\n", (int) id );
|
||||
debug_printf( "Unknown SPC xid6 block: %X\n", (int) id );
|
||||
break;
|
||||
}
|
||||
if ( field )
|
||||
|
@ -134,7 +136,7 @@ static void get_spc_xid6( byte const* begin, long size, track_info_t* out )
|
|||
{
|
||||
// ...but some files have no padding
|
||||
in = unaligned;
|
||||
dprintf( "SPC info tag wasn't properly padded to align\n" );
|
||||
debug_printf( "SPC info tag wasn't properly padded to align\n" );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -226,14 +228,14 @@ struct Spc_File : Gme_Info_
|
|||
{
|
||||
RETURN_ERR( xid6.resize( xid6_size ) );
|
||||
RETURN_ERR( in.skip( xid6_offset - Spc_Emu::header_size ) );
|
||||
RETURN_ERR( in.read( xid6.begin(), (long)xid6.size() ) );
|
||||
RETURN_ERR( in.read( xid6.begin(), xid6.size() ) );
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
blargg_err_t track_info_( track_info_t* out, int ) const
|
||||
{
|
||||
get_spc_info( header, xid6.begin(), (long)xid6.size(), out );
|
||||
get_spc_info( header, xid6.begin(), xid6.size(), out );
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
@ -244,12 +246,13 @@ static Music_Emu* new_spc_file() { return BLARGG_NEW Spc_File; }
|
|||
static gme_type_t_ const gme_spc_type_ = { "Super Nintendo", 1, &new_spc_emu, &new_spc_file, "SPC", 0 };
|
||||
gme_type_t const gme_spc_type = &gme_spc_type_;
|
||||
|
||||
|
||||
// Setup
|
||||
|
||||
blargg_err_t Spc_Emu::set_sample_rate_( long sample_rate )
|
||||
{
|
||||
RETURN_ERR( apu.init() );
|
||||
apu.set_gain( (int) (gain() * Snes_Spc::gain_unit) );
|
||||
enable_accuracy( false );
|
||||
if ( sample_rate != native_sample_rate )
|
||||
{
|
||||
RETURN_ERR( resampler.buffer_size( native_sample_rate / 20 * 2 ) );
|
||||
|
@ -258,6 +261,12 @@ blargg_err_t Spc_Emu::set_sample_rate_( long sample_rate )
|
|||
return 0;
|
||||
}
|
||||
|
||||
void Spc_Emu::enable_accuracy_( bool b )
|
||||
{
|
||||
Music_Emu::enable_accuracy_( b );
|
||||
filter.enable( b );
|
||||
}
|
||||
|
||||
void Spc_Emu::mute_voices_( int m )
|
||||
{
|
||||
Music_Emu::mute_voices_( m );
|
||||
|
@ -277,17 +286,29 @@ blargg_err_t Spc_Emu::load_mem_( byte const* in, long size )
|
|||
|
||||
// Emulation
|
||||
|
||||
void Spc_Emu::set_tempo_( double t ) { apu.set_tempo( (int) (t * Snes_Spc::tempo_unit) ); }
|
||||
void Spc_Emu::set_tempo_( double t )
|
||||
{
|
||||
apu.set_tempo( (int) (t * apu.tempo_unit) );
|
||||
}
|
||||
|
||||
blargg_err_t Spc_Emu::start_track_( int track )
|
||||
{
|
||||
RETURN_ERR( Music_Emu::start_track_( track ) );
|
||||
resampler.clear();
|
||||
filter.clear();
|
||||
RETURN_ERR( apu.load_spc( file_data, file_size ) );
|
||||
filter.set_gain( (int) (gain() * SPC_Filter::gain_unit) );
|
||||
apu.clear_echo();
|
||||
return 0;
|
||||
}
|
||||
|
||||
blargg_err_t Spc_Emu::play_and_filter( long count, sample_t out [] )
|
||||
{
|
||||
RETURN_ERR( apu.play( count, out ) );
|
||||
filter.run( out, count );
|
||||
return 0;
|
||||
}
|
||||
|
||||
blargg_err_t Spc_Emu::skip_( long count )
|
||||
{
|
||||
if ( sample_rate() != native_sample_rate )
|
||||
|
@ -299,7 +320,10 @@ blargg_err_t Spc_Emu::skip_( long count )
|
|||
// TODO: shouldn't skip be adjusted for the 64 samples read afterwards?
|
||||
|
||||
if ( count > 0 )
|
||||
{
|
||||
RETURN_ERR( apu.skip( count ) );
|
||||
filter.clear();
|
||||
}
|
||||
|
||||
// eliminate pop due to resampler
|
||||
const int resampler_latency = 64;
|
||||
|
@ -310,7 +334,7 @@ blargg_err_t Spc_Emu::skip_( long count )
|
|||
blargg_err_t Spc_Emu::play_( long count, sample_t* out )
|
||||
{
|
||||
if ( sample_rate() == native_sample_rate )
|
||||
return apu.play( count, out );
|
||||
return play_and_filter( count, out );
|
||||
|
||||
long remain = count;
|
||||
while ( remain > 0 )
|
||||
|
@ -319,7 +343,7 @@ blargg_err_t Spc_Emu::play_( long count, sample_t* out )
|
|||
if ( remain > 0 )
|
||||
{
|
||||
long n = resampler.max_write();
|
||||
RETURN_ERR( apu.play( n, resampler.buffer() ) );
|
||||
RETURN_ERR( play_and_filter( n, resampler.buffer() ) );
|
||||
resampler.write( n );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,12 +1,13 @@
|
|||
// Super Nintendo SPC music file emulator
|
||||
|
||||
// Game_Music_Emu 0.5.2
|
||||
// Game_Music_Emu 0.6.0
|
||||
#ifndef SPC_EMU_H
|
||||
#define SPC_EMU_H
|
||||
|
||||
#include "Fir_Resampler.h"
|
||||
#include "Music_Emu.h"
|
||||
#include "Snes_Spc.h"
|
||||
#include "Spc_Filter.h"
|
||||
|
||||
class Spc_Emu : public Music_Emu {
|
||||
public:
|
||||
|
@ -65,11 +66,15 @@ protected:
|
|||
blargg_err_t skip_( long );
|
||||
void mute_voices_( int );
|
||||
void set_tempo_( double );
|
||||
void enable_accuracy_( bool );
|
||||
private:
|
||||
byte const* file_data;
|
||||
long file_size;
|
||||
Fir_Resampler<24> resampler;
|
||||
SPC_Filter filter;
|
||||
Snes_Spc apu;
|
||||
|
||||
blargg_err_t play_and_filter( long count, sample_t out [] );
|
||||
};
|
||||
|
||||
inline void Spc_Emu::disable_surround( bool b ) { apu.disable_surround( b ); }
|
||||
|
|
83
game-music-emu/gme/Spc_Filter.cpp
Normal file
83
game-music-emu/gme/Spc_Filter.cpp
Normal file
|
@ -0,0 +1,83 @@
|
|||
// Game_Music_Emu 0.6.0. http://www.slack.net/~ant/
|
||||
|
||||
#include "Spc_Filter.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
/* Copyright (C) 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"
|
||||
|
||||
void SPC_Filter::clear() { memset( ch, 0, sizeof ch ); }
|
||||
|
||||
SPC_Filter::SPC_Filter()
|
||||
{
|
||||
enabled = true;
|
||||
gain = gain_unit;
|
||||
bass = bass_norm;
|
||||
clear();
|
||||
}
|
||||
|
||||
void SPC_Filter::run( short* io, int count )
|
||||
{
|
||||
require( (count & 1) == 0 ); // must be even
|
||||
|
||||
int const gain = this->gain;
|
||||
if ( enabled )
|
||||
{
|
||||
int const bass = this->bass;
|
||||
chan_t* c = &ch [2];
|
||||
do
|
||||
{
|
||||
// cache in registers
|
||||
int sum = (--c)->sum;
|
||||
int pp1 = c->pp1;
|
||||
int p1 = c->p1;
|
||||
|
||||
for ( int i = 0; i < count; i += 2 )
|
||||
{
|
||||
// Low-pass filter (two point FIR with coeffs 0.25, 0.75)
|
||||
int f = io [i] + p1;
|
||||
p1 = io [i] * 3;
|
||||
|
||||
// High-pass filter ("leaky integrator")
|
||||
int delta = f - pp1;
|
||||
pp1 = f;
|
||||
int s = sum >> (gain_bits + 2);
|
||||
sum += (delta * gain) - (sum >> bass);
|
||||
|
||||
// Clamp to 16 bits
|
||||
if ( (short) s != s )
|
||||
s = (s >> 31) ^ 0x7FFF;
|
||||
|
||||
io [i] = (short) s;
|
||||
}
|
||||
|
||||
c->p1 = p1;
|
||||
c->pp1 = pp1;
|
||||
c->sum = sum;
|
||||
++io;
|
||||
}
|
||||
while ( c != ch );
|
||||
}
|
||||
else if ( gain != gain_unit )
|
||||
{
|
||||
short* const end = io + count;
|
||||
while ( io < end )
|
||||
{
|
||||
int s = (*io * gain) >> gain_bits;
|
||||
if ( (short) s != s )
|
||||
s = (s >> 31) ^ 0x7FFF;
|
||||
*io++ = (short) s;
|
||||
}
|
||||
}
|
||||
}
|
53
game-music-emu/gme/Spc_Filter.h
Normal file
53
game-music-emu/gme/Spc_Filter.h
Normal file
|
@ -0,0 +1,53 @@
|
|||
// Simple low-pass and high-pass filter to better match sound output of a SNES
|
||||
|
||||
// Game_Music_Emu 0.6.0
|
||||
#ifndef SPC_FILTER_H
|
||||
#define SPC_FILTER_H
|
||||
|
||||
#include "blargg_common.h"
|
||||
|
||||
struct SPC_Filter {
|
||||
public:
|
||||
|
||||
// Filters count samples of stereo sound in place. Count must be a multiple of 2.
|
||||
typedef short sample_t;
|
||||
void run( sample_t* io, int count );
|
||||
|
||||
// Optional features
|
||||
|
||||
// Clears filter to silence
|
||||
void clear();
|
||||
|
||||
// Sets gain (volume), where gain_unit is normal. Gains greater than gain_unit
|
||||
// are fine, since output is clamped to 16-bit sample range.
|
||||
enum { gain_unit = 0x100 };
|
||||
void set_gain( int gain );
|
||||
|
||||
// Enables/disables filtering (when disabled, gain is still applied)
|
||||
void enable( bool b );
|
||||
|
||||
// Sets amount of bass (logarithmic scale)
|
||||
enum { bass_none = 0 };
|
||||
enum { bass_norm = 8 }; // normal amount
|
||||
enum { bass_max = 31 };
|
||||
void set_bass( int bass );
|
||||
|
||||
public:
|
||||
SPC_Filter();
|
||||
BLARGG_DISABLE_NOTHROW
|
||||
private:
|
||||
enum { gain_bits = 8 };
|
||||
int gain;
|
||||
int bass;
|
||||
bool enabled;
|
||||
struct chan_t { int p1, pp1, sum; };
|
||||
chan_t ch [2];
|
||||
};
|
||||
|
||||
inline void SPC_Filter::enable( bool b ) { enabled = b; }
|
||||
|
||||
inline void SPC_Filter::set_gain( int g ) { gain = g; }
|
||||
|
||||
inline void SPC_Filter::set_bass( int b ) { bass = b; }
|
||||
|
||||
#endif
|
|
@ -1,4 +1,4 @@
|
|||
// Game_Music_Emu 0.5.2. http://www.slack.net/~ant/
|
||||
// Game_Music_Emu 0.6.0. http://www.slack.net/~ant/
|
||||
|
||||
#include "Vgm_Emu.h"
|
||||
|
||||
|
@ -36,8 +36,7 @@ Vgm_Emu::Vgm_Emu()
|
|||
|
||||
set_silence_lookahead( 1 ); // tracks should already be trimmed
|
||||
|
||||
static equalizer_t const eq = { -14.0, 80, 0, 0, 0, 0, 0, 0, 0, 0 };
|
||||
set_equalizer( eq );
|
||||
set_equalizer( make_equalizer( -14.0, 80 ) );
|
||||
}
|
||||
|
||||
Vgm_Emu::~Vgm_Emu() { }
|
||||
|
@ -58,7 +57,7 @@ static byte const* skip_gd3_str( byte const* in, byte const* end )
|
|||
static byte const* get_gd3_str( byte const* in, byte const* end, char* field )
|
||||
{
|
||||
byte const* mid = skip_gd3_str( in, end );
|
||||
int len = int(mid - in) / 2 - 1;
|
||||
int len = (mid - in) / 2 - 1;
|
||||
if ( len > 0 )
|
||||
{
|
||||
len = min( len, (int) Gme_File::max_field_ );
|
||||
|
@ -109,7 +108,7 @@ byte const* Vgm_Emu::gd3_data( int* size ) const
|
|||
return 0;
|
||||
|
||||
byte const* gd3 = data + header_size + gd3_offset;
|
||||
long gd3_size = check_gd3_header( gd3, long(data_end - gd3) );
|
||||
long gd3_size = check_gd3_header( gd3, data_end - gd3 );
|
||||
if ( !gd3_size )
|
||||
return 0;
|
||||
|
||||
|
@ -185,7 +184,7 @@ struct Vgm_File : Gme_Info_
|
|||
if ( gd3_size )
|
||||
{
|
||||
RETURN_ERR( gd3.resize( gd3_size ) );
|
||||
RETURN_ERR( in.read( gd3.begin(), (long)gd3.size() ) );
|
||||
RETURN_ERR( in.read( gd3.begin(), gd3.size() ) );
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
|
@ -218,8 +217,8 @@ void Vgm_Emu::set_tempo_( double t )
|
|||
{
|
||||
vgm_rate = (long) (44100 * t + 0.5);
|
||||
blip_time_factor = (long) floor( double (1L << blip_time_bits) / vgm_rate * psg_rate + 0.5 );
|
||||
//dprintf( "blip_time_factor: %ld\n", blip_time_factor );
|
||||
//dprintf( "vgm_rate: %ld\n", vgm_rate );
|
||||
//debug_printf( "blip_time_factor: %ld\n", blip_time_factor );
|
||||
//debug_printf( "vgm_rate: %ld\n", vgm_rate );
|
||||
// TODO: remove? calculates vgm_rate more accurately (above differs at most by one Hz only)
|
||||
//blip_time_factor = (long) floor( double (1L << blip_time_bits) * psg_rate / 44100 / t + 0.5 );
|
||||
//vgm_rate = (long) floor( double (1L << blip_time_bits) * psg_rate / blip_time_factor + 0.5 );
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// Sega Master System/Mark III, Sega Genesis/Mega Drive, BBC Micro VGM music file emulator
|
||||
|
||||
// Game_Music_Emu 0.5.2
|
||||
// Game_Music_Emu 0.6.0
|
||||
#ifndef VGM_EMU_H
|
||||
#define VGM_EMU_H
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// Game_Music_Emu 0.5.2. http://www.slack.net/~ant/
|
||||
// Game_Music_Emu 0.6.0. http://www.slack.net/~ant/
|
||||
|
||||
#include "Vgm_Emu.h"
|
||||
|
||||
|
@ -244,7 +244,7 @@ int Vgm_Emu_Impl::play_frame( blip_time_t blip_time, int sample_count, sample_t*
|
|||
int pairs = min_pairs;
|
||||
while ( (pairs = to_fm_time( vgm_time )) < min_pairs )
|
||||
vgm_time++;
|
||||
//dprintf( "pairs: %d, min_pairs: %d\n", pairs, min_pairs );
|
||||
//debug_printf( "pairs: %d, min_pairs: %d\n", pairs, min_pairs );
|
||||
|
||||
if ( ym2612.enabled() )
|
||||
{
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// Low-level parts of Vgm_Emu
|
||||
|
||||
// Game_Music_Emu 0.5.2
|
||||
// Game_Music_Emu 0.6.0
|
||||
#ifndef VGM_EMU_IMPL_H
|
||||
#define VGM_EMU_IMPL_H
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
|
||||
// Use in place of Ym2413_Emu.cpp and ym2413.c to disable support for this chip
|
||||
|
||||
// Game_Music_Emu 0.5.2. http://www.slack.net/~ant/
|
||||
// Game_Music_Emu 0.6.0. http://www.slack.net/~ant/
|
||||
|
||||
#include "Ym2413_Emu.h"
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// YM2413 FM sound chip emulator interface
|
||||
|
||||
// Game_Music_Emu 0.5.2
|
||||
// Game_Music_Emu 0.6.0
|
||||
#ifndef YM2413_EMU_H
|
||||
#define YM2413_EMU_H
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// Game_Music_Emu 0.5.2. http://www.slack.net/~ant/
|
||||
// Game_Music_Emu 0.6.0. http://www.slack.net/~ant/
|
||||
|
||||
// Based on Gens 2.10 ym2612.c
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// YM2612 FM sound chip emulator interface
|
||||
|
||||
// Game_Music_Emu 0.5.2
|
||||
// Game_Music_Emu 0.6.0
|
||||
#ifndef YM2612_EMU_H
|
||||
#define YM2612_EMU_H
|
||||
|
||||
|
|
|
@ -15,6 +15,13 @@
|
|||
#ifndef BLARGG_COMMON_H
|
||||
#define BLARGG_COMMON_H
|
||||
|
||||
// BLARGG_RESTRICT: equivalent to restrict, where supported
|
||||
#if __GNUC__ >= 3 || _MSC_VER >= 1100
|
||||
#define BLARGG_RESTRICT __restrict
|
||||
#else
|
||||
#define BLARGG_RESTRICT
|
||||
#endif
|
||||
|
||||
// STATIC_CAST(T,expr): Used in place of static_cast<T> (expr)
|
||||
#ifndef STATIC_CAST
|
||||
#define STATIC_CAST(T,expr) ((T) (expr))
|
||||
|
@ -54,10 +61,11 @@ public:
|
|||
};
|
||||
|
||||
#ifndef BLARGG_DISABLE_NOTHROW
|
||||
#if __cplusplus < 199711
|
||||
#define BLARGG_THROWS( spec )
|
||||
#else
|
||||
// throw spec mandatory in ISO C++ if operator new can return NULL
|
||||
#if __cplusplus >= 199711 || __GNUC__ >= 3
|
||||
#define BLARGG_THROWS( spec ) throw spec
|
||||
#else
|
||||
#define BLARGG_THROWS( spec )
|
||||
#endif
|
||||
#define BLARGG_DISABLE_NOTHROW \
|
||||
void* operator new ( size_t s ) BLARGG_THROWS(()) { return malloc( s ); }\
|
||||
|
@ -68,6 +76,7 @@ public:
|
|||
#define BLARGG_NEW new (std::nothrow)
|
||||
#endif
|
||||
|
||||
// BLARGG_4CHAR('a','b','c','d') = 'abcd' (four character integer constant)
|
||||
#define BLARGG_4CHAR( a, b, c, d ) \
|
||||
((a&0xFF)*0x1000000L + (b&0xFF)*0x10000L + (c&0xFF)*0x100L + (d&0xFF))
|
||||
|
||||
|
@ -110,18 +119,17 @@ public:
|
|||
#endif
|
||||
|
||||
// blargg_long/blargg_ulong = at least 32 bits, int if it's big enough
|
||||
#include <limits.h>
|
||||
|
||||
#if INT_MAX >= 0x7FFFFFFF
|
||||
typedef int blargg_long;
|
||||
#else
|
||||
#if INT_MAX < 0x7FFFFFFF || LONG_MAX == 0x7FFFFFFF
|
||||
typedef long blargg_long;
|
||||
#else
|
||||
typedef int blargg_long;
|
||||
#endif
|
||||
|
||||
#if UINT_MAX >= 0xFFFFFFFF
|
||||
typedef unsigned blargg_ulong;
|
||||
#else
|
||||
#if UINT_MAX < 0xFFFFFFFF || ULONG_MAX == 0xFFFFFFFF
|
||||
typedef unsigned long blargg_ulong;
|
||||
#else
|
||||
typedef unsigned blargg_ulong;
|
||||
#endif
|
||||
|
||||
// BOOST::int8_t etc.
|
||||
|
@ -171,5 +179,18 @@ public:
|
|||
};
|
||||
#endif
|
||||
|
||||
#if __GNUC__ >= 3
|
||||
#define BLARGG_DEPRECATED __attribute__ ((deprecated))
|
||||
#else
|
||||
#define BLARGG_DEPRECATED
|
||||
#endif
|
||||
|
||||
// Use in place of "= 0;" for a pure virtual, since these cause calls to std C++ lib.
|
||||
// During development, BLARGG_PURE( x ) expands to = 0;
|
||||
// virtual int func() BLARGG_PURE( { return 0; } )
|
||||
#ifndef BLARGG_PURE
|
||||
#define BLARGG_PURE( def ) def
|
||||
#endif
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
@ -6,9 +6,22 @@
|
|||
// Uncomment to use zlib for transparent decompression of gzipped files
|
||||
//#define HAVE_ZLIB_H
|
||||
|
||||
// Uncomment to support only the listed game music types. See gme_type_list.cpp
|
||||
// for a list of all types.
|
||||
//#define GME_TYPE_LIST gme_nsf_type, gme_gbs_type
|
||||
// Uncomment and edit list to support only the listed game music types,
|
||||
// so that the others don't get linked in at all.
|
||||
/*
|
||||
#define GME_TYPE_LIST \
|
||||
gme_ay_type,\
|
||||
gme_gbs_type,\
|
||||
gme_gym_type,\
|
||||
gme_hes_type,\
|
||||
gme_kss_type,\
|
||||
gme_nsf_type,\
|
||||
gme_nsfe_type,\
|
||||
gme_sap_type,\
|
||||
gme_spc_type,\
|
||||
gme_vgm_type,\
|
||||
gme_vgz_type
|
||||
*/
|
||||
|
||||
// Uncomment to enable platform-specific optimizations
|
||||
//#define BLARGG_NONPORTABLE 1
|
||||
|
@ -27,5 +40,4 @@
|
|||
#include "config.h"
|
||||
#endif
|
||||
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,20 +1,20 @@
|
|||
// CPU Byte Order Utilities
|
||||
|
||||
// Game_Music_Emu 0.5.2
|
||||
#ifndef BLARGG_ENDIAN
|
||||
#define BLARGG_ENDIAN
|
||||
|
||||
#include "blargg_common.h"
|
||||
|
||||
// BLARGG_CPU_CISC: Defined if CPU has very few general-purpose registers (< 16)
|
||||
#if defined (_M_IX86) || defined (_M_IA64) || defined (__i486__) || \
|
||||
defined (__x86_64__) || defined (__ia64__) || defined (__i386__)
|
||||
#if defined (__i386__) || defined (__x86_64__) || defined (_M_IX86) || defined (_M_X64)
|
||||
#define BLARGG_CPU_X86 1
|
||||
#define BLARGG_CPU_CISC 1
|
||||
#endif
|
||||
|
||||
#if defined (__powerpc__) || defined (__ppc__) || defined (__POWERPC__) || defined (__powerc)
|
||||
#if defined (__powerpc__) || defined (__ppc__) || defined (__ppc64__) || \
|
||||
defined (__POWERPC__) || defined (__powerc)
|
||||
#define BLARGG_CPU_POWERPC 1
|
||||
#define BLARGG_CPU_RISC 1
|
||||
#endif
|
||||
|
||||
// BLARGG_BIG_ENDIAN, BLARGG_LITTLE_ENDIAN: Determined automatically, otherwise only
|
||||
|
@ -36,10 +36,10 @@
|
|||
#endif
|
||||
|
||||
#if defined (MSB_FIRST) || defined (__BIG_ENDIAN__) || defined (WORDS_BIGENDIAN) || \
|
||||
defined (__mips__) || defined (__sparc__) || BLARGG_CPU_POWERPC || \
|
||||
defined (__sparc__) || BLARGG_CPU_POWERPC || \
|
||||
(defined (BIG_ENDIAN) && BIG_ENDIAN+0 != 4321)
|
||||
#define BLARGG_BIG_ENDIAN 1
|
||||
#else
|
||||
#elif !defined (__mips__)
|
||||
// No endian specified; assume little-endian, since it's most common
|
||||
#define BLARGG_LITTLE_ENDIAN 1
|
||||
#endif
|
||||
|
@ -64,45 +64,60 @@ inline void blargg_verify_byte_order()
|
|||
#endif
|
||||
}
|
||||
|
||||
inline unsigned get_le16( void const* p ) {
|
||||
return ((unsigned char const*) p) [1] * 0x100u +
|
||||
((unsigned char const*) p) [0];
|
||||
inline unsigned get_le16( void const* p )
|
||||
{
|
||||
return (unsigned) ((unsigned char const*) p) [1] << 8 |
|
||||
(unsigned) ((unsigned char const*) p) [0];
|
||||
}
|
||||
inline unsigned get_be16( void const* p ) {
|
||||
return ((unsigned char const*) p) [0] * 0x100u +
|
||||
((unsigned char const*) p) [1];
|
||||
|
||||
inline unsigned get_be16( void const* p )
|
||||
{
|
||||
return (unsigned) ((unsigned char const*) p) [0] << 8 |
|
||||
(unsigned) ((unsigned char const*) p) [1];
|
||||
}
|
||||
inline blargg_ulong get_le32( void const* p ) {
|
||||
return ((unsigned char const*) p) [3] * 0x01000000u +
|
||||
((unsigned char const*) p) [2] * 0x00010000u +
|
||||
((unsigned char const*) p) [1] * 0x00000100u +
|
||||
((unsigned char const*) p) [0];
|
||||
|
||||
inline blargg_ulong get_le32( void const* p )
|
||||
{
|
||||
return (blargg_ulong) ((unsigned char const*) p) [3] << 24 |
|
||||
(blargg_ulong) ((unsigned char const*) p) [2] << 16 |
|
||||
(blargg_ulong) ((unsigned char const*) p) [1] << 8 |
|
||||
(blargg_ulong) ((unsigned char const*) p) [0];
|
||||
}
|
||||
inline blargg_ulong get_be32( void const* p ) {
|
||||
return ((unsigned char const*) p) [0] * 0x01000000u +
|
||||
((unsigned char const*) p) [1] * 0x00010000u +
|
||||
((unsigned char const*) p) [2] * 0x00000100u +
|
||||
((unsigned char const*) p) [3];
|
||||
|
||||
inline blargg_ulong get_be32( void const* p )
|
||||
{
|
||||
return (blargg_ulong) ((unsigned char const*) p) [0] << 24 |
|
||||
(blargg_ulong) ((unsigned char const*) p) [1] << 16 |
|
||||
(blargg_ulong) ((unsigned char const*) p) [2] << 8 |
|
||||
(blargg_ulong) ((unsigned char const*) p) [3];
|
||||
}
|
||||
inline void set_le16( void* p, unsigned n ) {
|
||||
|
||||
inline void set_le16( void* p, unsigned n )
|
||||
{
|
||||
((unsigned char*) p) [1] = (unsigned char) (n >> 8);
|
||||
((unsigned char*) p) [0] = (unsigned char) n;
|
||||
}
|
||||
inline void set_be16( void* p, unsigned n ) {
|
||||
|
||||
inline void set_be16( void* p, unsigned n )
|
||||
{
|
||||
((unsigned char*) p) [0] = (unsigned char) (n >> 8);
|
||||
((unsigned char*) p) [1] = (unsigned char) n;
|
||||
}
|
||||
inline void set_le32( void* p, blargg_ulong n ) {
|
||||
((unsigned char*) p) [3] = (unsigned char) (n >> 24);
|
||||
((unsigned char*) p) [2] = (unsigned char) (n >> 16);
|
||||
((unsigned char*) p) [1] = (unsigned char) (n >> 8);
|
||||
|
||||
inline void set_le32( void* p, blargg_ulong n )
|
||||
{
|
||||
((unsigned char*) p) [0] = (unsigned char) n;
|
||||
((unsigned char*) p) [1] = (unsigned char) (n >> 8);
|
||||
((unsigned char*) p) [2] = (unsigned char) (n >> 16);
|
||||
((unsigned char*) p) [3] = (unsigned char) (n >> 24);
|
||||
}
|
||||
inline void set_be32( void* p, blargg_ulong n ) {
|
||||
((unsigned char*) p) [0] = (unsigned char) (n >> 24);
|
||||
((unsigned char*) p) [1] = (unsigned char) (n >> 16);
|
||||
((unsigned char*) p) [2] = (unsigned char) (n >> 8);
|
||||
|
||||
inline void set_be32( void* p, blargg_ulong n )
|
||||
{
|
||||
((unsigned char*) p) [3] = (unsigned char) n;
|
||||
((unsigned char*) p) [2] = (unsigned char) (n >> 8);
|
||||
((unsigned char*) p) [1] = (unsigned char) (n >> 16);
|
||||
((unsigned char*) p) [0] = (unsigned char) (n >> 24);
|
||||
}
|
||||
|
||||
#if BLARGG_NONPORTABLE
|
||||
|
@ -117,30 +132,41 @@ inline void set_be32( void* p, blargg_ulong n ) {
|
|||
#define GET_BE32( addr ) (*(BOOST::uint32_t*) (addr))
|
||||
#define SET_BE16( addr, data ) (void) (*(BOOST::uint16_t*) (addr) = (data))
|
||||
#define SET_BE32( addr, data ) (void) (*(BOOST::uint32_t*) (addr) = (data))
|
||||
#endif
|
||||
|
||||
#if BLARGG_CPU_POWERPC && defined (__MWERKS__)
|
||||
// PowerPC has special byte-reversed instructions
|
||||
// to do: assumes that PowerPC is running in big-endian mode
|
||||
// to do: implement for other compilers which don't support these macros
|
||||
#define GET_LE16( addr ) (__lhbrx( (addr), 0 ))
|
||||
#define GET_LE32( addr ) (__lwbrx( (addr), 0 ))
|
||||
#define SET_LE16( addr, data ) (__sthbrx( (data), (addr), 0 ))
|
||||
#define SET_LE32( addr, data ) (__stwbrx( (data), (addr), 0 ))
|
||||
|
||||
#if BLARGG_CPU_POWERPC
|
||||
// PowerPC has special byte-reversed instructions
|
||||
#if defined (__MWERKS__)
|
||||
#define GET_LE16( addr ) (__lhbrx( addr, 0 ))
|
||||
#define GET_LE32( addr ) (__lwbrx( addr, 0 ))
|
||||
#define SET_LE16( addr, in ) (__sthbrx( in, addr, 0 ))
|
||||
#define SET_LE32( addr, in ) (__stwbrx( in, addr, 0 ))
|
||||
#elif defined (__GNUC__)
|
||||
#define GET_LE16( addr ) ({unsigned short ppc_lhbrx_; __asm__ volatile( "lhbrx %0,0,%1" : "=r" (ppc_lhbrx_) : "r" (addr) : "memory" ); ppc_lhbrx_;})
|
||||
#define GET_LE32( addr ) ({unsigned short ppc_lwbrx_; __asm__ volatile( "lwbrx %0,0,%1" : "=r" (ppc_lwbrx_) : "r" (addr) : "memory" ); ppc_lwbrx_;})
|
||||
#define SET_LE16( addr, in ) ({__asm__ volatile( "sthbrx %0,0,%1" : : "r" (in), "r" (addr) : "memory" );})
|
||||
#define SET_LE32( addr, in ) ({__asm__ volatile( "stwbrx %0,0,%1" : : "r" (in), "r" (addr) : "memory" );})
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef GET_LE16
|
||||
#define GET_LE16( addr ) get_le16( addr )
|
||||
#define GET_LE32( addr ) get_le32( addr )
|
||||
#define SET_LE16( addr, data ) set_le16( addr, data )
|
||||
#endif
|
||||
|
||||
#ifndef GET_LE32
|
||||
#define GET_LE32( addr ) get_le32( addr )
|
||||
#define SET_LE32( addr, data ) set_le32( addr, data )
|
||||
#endif
|
||||
|
||||
#ifndef GET_BE16
|
||||
#define GET_BE16( addr ) get_be16( addr )
|
||||
#define GET_BE32( addr ) get_be32( addr )
|
||||
#define SET_BE16( addr, data ) set_be16( addr, data )
|
||||
#endif
|
||||
|
||||
#ifndef GET_BE32
|
||||
#define GET_BE32( addr ) get_be32( addr )
|
||||
#define SET_BE32( addr, data ) set_be32( addr, data )
|
||||
#endif
|
||||
|
||||
|
|
|
@ -1,4 +1,8 @@
|
|||
// Included at the beginning of library source files, after all other #include lines
|
||||
/* Included at the beginning of library source files, after all other #include lines.
|
||||
Sets up helpful macros and services used in my source code. They don't need
|
||||
module an annoying module prefix on their names since they are defined after
|
||||
all other #include lines. */
|
||||
|
||||
#ifndef BLARGG_SOURCE_H
|
||||
#define BLARGG_SOURCE_H
|
||||
|
||||
|
@ -16,10 +20,10 @@
|
|||
|
||||
// Like printf() except output goes to debug log file. Might be defined to do
|
||||
// nothing (not even evaluate its arguments).
|
||||
// void dprintf( const char* format, ... );
|
||||
inline void blargg_dprintf_( const char*, ... ) { }
|
||||
#undef dprintf
|
||||
#define dprintf (1) ? (void) 0 : blargg_dprintf_
|
||||
// void debug_printf( const char* format, ... );
|
||||
static inline void blargg_dprintf_( const char*, ... ) { }
|
||||
#undef debug_printf
|
||||
#define debug_printf (1) ? (void) 0 : blargg_dprintf_
|
||||
|
||||
// If enabled, evaluate expr and if false, make debug log entry with source file
|
||||
// and line. Meant for finding situations that should be examined further, but that
|
||||
|
@ -42,9 +46,25 @@ inline void blargg_dprintf_( const char*, ... ) { }
|
|||
#undef min
|
||||
#undef max
|
||||
|
||||
#define DEF_MIN_MAX( type ) \
|
||||
static inline type min( type x, type y ) { if ( x < y ) return x; return y; }\
|
||||
static inline type max( type x, type y ) { if ( y < x ) return x; return y; }
|
||||
|
||||
DEF_MIN_MAX( int )
|
||||
DEF_MIN_MAX( unsigned )
|
||||
DEF_MIN_MAX( long )
|
||||
DEF_MIN_MAX( unsigned long )
|
||||
DEF_MIN_MAX( float )
|
||||
DEF_MIN_MAX( double )
|
||||
|
||||
#undef DEF_MIN_MAX
|
||||
|
||||
/*
|
||||
// using const references generates crappy code, and I am currenly only using these
|
||||
// for built-in types, so they take arguments by value
|
||||
|
||||
// TODO: remove
|
||||
inline int min( int x, int y )
|
||||
template<class T>
|
||||
inline T min( T x, T y )
|
||||
{
|
||||
|
@ -60,17 +80,29 @@ inline T max( T x, T y )
|
|||
return y;
|
||||
return x;
|
||||
}
|
||||
*/
|
||||
|
||||
// TODO: good idea? bad idea?
|
||||
#undef byte
|
||||
#define byte byte_
|
||||
typedef unsigned char byte;
|
||||
|
||||
// Setup compiler defines useful for exporting required public API symbols in gme.cpp
|
||||
#ifndef BLARGG_EXPORT
|
||||
#if defined (_WIN32) && defined(BLARGG_BUILD_DLL)
|
||||
#define BLARGG_EXPORT __declspec(dllexport)
|
||||
#elif defined (LIBGME_VISIBILITY)
|
||||
#define BLARGG_EXPORT __attribute__((visibility ("default")))
|
||||
#else
|
||||
#define BLARGG_EXPORT
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// deprecated
|
||||
#define BLARGG_CHECK_ALLOC CHECK_ALLOC
|
||||
#define BLARGG_RETURN_ERR RETURN_ERR
|
||||
|
||||
// BLARGG_SOURCE_BEGIN: If defined, #included, allowing redefition of dprintf and check
|
||||
// BLARGG_SOURCE_BEGIN: If defined, #included, allowing redefition of debug_printf and check
|
||||
#ifdef BLARGG_SOURCE_BEGIN
|
||||
#include BLARGG_SOURCE_BEGIN
|
||||
#endif
|
||||
|
|
|
@ -10,9 +10,9 @@ int Gbs_Emu::cpu_read( gb_addr_t addr )
|
|||
result = apu.read_register( clock(), addr );
|
||||
#ifndef NDEBUG
|
||||
else if ( unsigned (addr - 0x8000) < 0x2000 || unsigned (addr - 0xE000) < 0x1F00 )
|
||||
dprintf( "Read from unmapped memory $%.4x\n", (unsigned) addr );
|
||||
debug_printf( "Read from unmapped memory $%.4x\n", (unsigned) addr );
|
||||
else if ( unsigned (addr - 0xFF01) < 0xFF80 - 0xFF01 )
|
||||
dprintf( "Unhandled I/O read 0x%4X\n", (unsigned) addr );
|
||||
debug_printf( "Unhandled I/O read 0x%4X\n", (unsigned) addr );
|
||||
#endif
|
||||
return result;
|
||||
}
|
||||
|
@ -38,7 +38,7 @@ void Gbs_Emu::cpu_write( gb_addr_t addr, int data )
|
|||
ram [offset] = 0xFF;
|
||||
|
||||
//if ( addr == 0xFFFF )
|
||||
// dprintf( "Wrote interrupt mask\n" );
|
||||
// debug_printf( "Wrote interrupt mask\n" );
|
||||
}
|
||||
}
|
||||
else if ( (addr ^ 0x2000) <= 0x2000 - 1 )
|
||||
|
@ -48,7 +48,7 @@ void Gbs_Emu::cpu_write( gb_addr_t addr, int data )
|
|||
#ifndef NDEBUG
|
||||
else if ( unsigned (addr - 0x8000) < 0x2000 || unsigned (addr - 0xE000) < 0x1F00 )
|
||||
{
|
||||
dprintf( "Wrote to unmapped memory $%.4x\n", (unsigned) addr );
|
||||
debug_printf( "Wrote to unmapped memory $%.4x\n", (unsigned) addr );
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
@ -59,7 +59,7 @@ void Gbs_Emu::cpu_write( gb_addr_t addr, int data )
|
|||
#define CPU_READ_FAST_( emu, addr, time, out ) \
|
||||
{\
|
||||
out = READ_PROG( addr );\
|
||||
if ( unsigned (addr - Gb_Apu::start_addr) <= Gb_Apu::register_count )\
|
||||
if ( unsigned (addr - Gb_Apu::start_addr) < Gb_Apu::register_count )\
|
||||
out = emu->apu.read_register( emu->cpu_time - time * clocks_per_instr, addr );\
|
||||
else\
|
||||
check( out == emu->cpu_read( addr ) );\
|
||||
|
|
|
@ -1,9 +1,8 @@
|
|||
// Game_Music_Emu 0.5.2. http://www.slack.net/~ant/
|
||||
|
||||
#define IN_GME 1
|
||||
// Game_Music_Emu 0.6.0. http://www.slack.net/~ant/
|
||||
|
||||
#include "Music_Emu.h"
|
||||
|
||||
#include "gme_types.h"
|
||||
#if !GME_DISABLE_STEREO_DEPTH
|
||||
#include "Effects_Buffer.h"
|
||||
#endif
|
||||
|
@ -24,32 +23,51 @@ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
|
|||
|
||||
#include "blargg_source.h"
|
||||
|
||||
#ifndef GME_TYPE_LIST
|
||||
|
||||
// Default list of all supported game music types (copy this to blargg_config.h
|
||||
// if you want to modify it)
|
||||
#define GME_TYPE_LIST \
|
||||
gme_ay_type,\
|
||||
gme_gbs_type,\
|
||||
gme_gym_type,\
|
||||
gme_hes_type,\
|
||||
gme_kss_type,\
|
||||
gme_nsf_type,\
|
||||
gme_nsfe_type,\
|
||||
gme_sap_type,\
|
||||
gme_spc_type,\
|
||||
gme_vgm_type,\
|
||||
gme_vgz_type
|
||||
|
||||
#endif
|
||||
|
||||
gme_type_t const* GMEAPI gme_type_list()
|
||||
BLARGG_EXPORT gme_type_t const* gme_type_list()
|
||||
{
|
||||
static gme_type_t const gme_type_list_ [] = { GME_TYPE_LIST, 0 };
|
||||
static gme_type_t const gme_type_list_ [] = {
|
||||
#ifdef GME_TYPE_LIST
|
||||
GME_TYPE_LIST,
|
||||
#else
|
||||
#ifdef USE_GME_AY
|
||||
gme_ay_type,
|
||||
#endif
|
||||
#ifdef USE_GME_GBS
|
||||
gme_gbs_type,
|
||||
#endif
|
||||
#ifdef USE_GME_GYM
|
||||
gme_gym_type,
|
||||
#endif
|
||||
#ifdef USE_GME_HES
|
||||
gme_hes_type,
|
||||
#endif
|
||||
#ifdef USE_GME_KSS
|
||||
gme_kss_type,
|
||||
#endif
|
||||
#ifdef USE_GME_NSF
|
||||
gme_nsf_type,
|
||||
#endif
|
||||
#ifdef USE_GME_NSFE
|
||||
gme_nsfe_type,
|
||||
#endif
|
||||
#ifdef USE_GME_SAP
|
||||
gme_sap_type,
|
||||
#endif
|
||||
#ifdef USE_GME_SPC
|
||||
gme_spc_type,
|
||||
#endif
|
||||
#ifdef USE_GME_VGM
|
||||
gme_vgm_type,
|
||||
gme_vgz_type,
|
||||
#endif
|
||||
#endif
|
||||
0
|
||||
};
|
||||
|
||||
return gme_type_list_;
|
||||
}
|
||||
|
||||
const char* GMEAPI gme_identify_header( void const* header )
|
||||
BLARGG_EXPORT const char* gme_identify_header( void const* header )
|
||||
{
|
||||
switch ( get_be32( header ) )
|
||||
{
|
||||
|
@ -78,7 +96,7 @@ static void to_uppercase( const char* in, int len, char* out )
|
|||
*out = 0; // extension too long
|
||||
}
|
||||
|
||||
gme_type_t GMEAPI gme_identify_extension( const char* extension_ )
|
||||
BLARGG_EXPORT gme_type_t gme_identify_extension( const char* extension_ )
|
||||
{
|
||||
char const* end = strrchr( extension_, '.' );
|
||||
if ( end )
|
||||
|
@ -93,7 +111,7 @@ gme_type_t GMEAPI gme_identify_extension( const char* extension_ )
|
|||
return 0;
|
||||
}
|
||||
|
||||
gme_err_t GMEAPI gme_identify_file( const char* path, gme_type_t* type_out )
|
||||
BLARGG_EXPORT gme_err_t gme_identify_file( const char* path, gme_type_t* type_out )
|
||||
{
|
||||
*type_out = gme_identify_extension( path );
|
||||
// TODO: don't examine header if file has extension?
|
||||
|
@ -108,7 +126,7 @@ gme_err_t GMEAPI gme_identify_file( const char* path, gme_type_t* type_out )
|
|||
return 0;
|
||||
}
|
||||
|
||||
gme_err_t GMEAPI gme_open_data( void const* data, long size, Music_Emu** out, int sample_rate )
|
||||
BLARGG_EXPORT gme_err_t gme_open_data( void const* data, long size, Music_Emu** out, int sample_rate )
|
||||
{
|
||||
require( (data || !size) && out );
|
||||
*out = 0;
|
||||
|
@ -132,7 +150,7 @@ gme_err_t GMEAPI gme_open_data( void const* data, long size, Music_Emu** out, in
|
|||
return err;
|
||||
}
|
||||
|
||||
GMEEXPORT gme_err_t GMEAPI gme_open_file( const char* path, Music_Emu** out, int sample_rate )
|
||||
BLARGG_EXPORT gme_err_t gme_open_file( const char* path, Music_Emu** out, int sample_rate )
|
||||
{
|
||||
require( path && out );
|
||||
*out = 0;
|
||||
|
@ -169,7 +187,7 @@ GMEEXPORT gme_err_t GMEAPI gme_open_file( const char* path, Music_Emu** out, int
|
|||
return err;
|
||||
}
|
||||
|
||||
Music_Emu* GMEAPI gme_new_emu( gme_type_t type, int rate )
|
||||
BLARGG_EXPORT Music_Emu* gme_new_emu( gme_type_t type, int rate )
|
||||
{
|
||||
if ( type )
|
||||
{
|
||||
|
@ -202,27 +220,27 @@ Music_Emu* GMEAPI gme_new_emu( gme_type_t type, int rate )
|
|||
return 0;
|
||||
}
|
||||
|
||||
gme_err_t GMEAPI gme_load_file( Music_Emu* me, const char* path ) { return me->load_file( path ); }
|
||||
BLARGG_EXPORT gme_err_t gme_load_file( Music_Emu* me, const char* path ) { return me->load_file( path ); }
|
||||
|
||||
gme_err_t GMEAPI gme_load_data( Music_Emu* me, void const* data, long size )
|
||||
BLARGG_EXPORT gme_err_t gme_load_data( Music_Emu* me, void const* data, long size )
|
||||
{
|
||||
Mem_File_Reader in( data, size );
|
||||
return me->load( in );
|
||||
}
|
||||
|
||||
gme_err_t GMEAPI gme_load_custom( Music_Emu* me, gme_reader_t func, long size, void* data )
|
||||
BLARGG_EXPORT gme_err_t gme_load_custom( Music_Emu* me, gme_reader_t func, long size, void* data )
|
||||
{
|
||||
Callback_Reader in( func, size, data );
|
||||
return me->load( in );
|
||||
}
|
||||
|
||||
void GMEAPI gme_delete( Music_Emu* me ) { delete me; }
|
||||
BLARGG_EXPORT void gme_delete( Music_Emu* me ) { delete me; }
|
||||
|
||||
gme_type_t GMEAPI gme_type( Music_Emu const* me ) { return me->type(); }
|
||||
BLARGG_EXPORT gme_type_t gme_type( Music_Emu const* me ) { return me->type(); }
|
||||
|
||||
const char* GMEAPI gme_warning( Music_Emu* me ) { return me->warning(); }
|
||||
BLARGG_EXPORT const char* gme_warning( Music_Emu* me ) { return me->warning(); }
|
||||
|
||||
int GMEAPI gme_track_count( Music_Emu const* me ) { return me->track_count(); }
|
||||
BLARGG_EXPORT int gme_track_count( Music_Emu const* me ) { return me->track_count(); }
|
||||
|
||||
struct gme_info_t_ : gme_info_t
|
||||
{
|
||||
|
@ -231,7 +249,7 @@ struct gme_info_t_ : gme_info_t
|
|||
BLARGG_DISABLE_NOTHROW
|
||||
};
|
||||
|
||||
gme_err_t GMEAPI gme_track_info( Music_Emu const* me, gme_info_t** out, int track )
|
||||
BLARGG_EXPORT gme_err_t gme_track_info( Music_Emu const* me, gme_info_t** out, int track )
|
||||
{
|
||||
*out = NULL;
|
||||
|
||||
|
@ -297,12 +315,12 @@ gme_err_t GMEAPI gme_track_info( Music_Emu const* me, gme_info_t** out, int trac
|
|||
return 0;
|
||||
}
|
||||
|
||||
void GMEAPI gme_free_info( gme_info_t* info )
|
||||
BLARGG_EXPORT void gme_free_info( gme_info_t* info )
|
||||
{
|
||||
delete STATIC_CAST(gme_info_t_*,info);
|
||||
}
|
||||
|
||||
void GMEAPI gme_set_stereo_depth( Music_Emu* me, double depth )
|
||||
BLARGG_EXPORT void gme_set_stereo_depth( Music_Emu* me, double depth )
|
||||
{
|
||||
#if !GME_DISABLE_STEREO_DEPTH
|
||||
if ( me->effects_buffer )
|
||||
|
@ -310,24 +328,26 @@ void GMEAPI gme_set_stereo_depth( Music_Emu* me, double depth )
|
|||
#endif
|
||||
}
|
||||
|
||||
void* GMEAPI gme_user_data ( Music_Emu const* me ) { return me->user_data(); }
|
||||
void GMEAPI gme_set_user_data ( Music_Emu* me, void* new_user_data ) { me->set_user_data( new_user_data ); }
|
||||
void GMEAPI gme_set_user_cleanup(Music_Emu* me, gme_user_cleanup_t func ) { me->set_user_cleanup( func ); }
|
||||
BLARGG_EXPORT void* gme_user_data ( Music_Emu const* me ) { return me->user_data(); }
|
||||
BLARGG_EXPORT void gme_set_user_data ( Music_Emu* me, void* new_user_data ) { me->set_user_data( new_user_data ); }
|
||||
BLARGG_EXPORT void gme_set_user_cleanup(Music_Emu* me, gme_user_cleanup_t func ) { me->set_user_cleanup( func ); }
|
||||
|
||||
gme_err_t GMEAPI gme_start_track ( Music_Emu* me, int index ) { return me->start_track( index ); }
|
||||
gme_err_t GMEAPI gme_play ( Music_Emu* me, int n, short* p ) { return me->play( n, p ); }
|
||||
gme_err_t GMEAPI gme_skip ( Music_Emu* me, long n ) { return me->skip( n ); }
|
||||
void GMEAPI gme_set_fade ( Music_Emu* me, int start_msec ) { me->set_fade( start_msec ); }
|
||||
int GMEAPI gme_track_ended ( Music_Emu const* me ) { return me->track_ended(); }
|
||||
int GMEAPI gme_tell ( Music_Emu const* me ) { return me->tell(); }
|
||||
gme_err_t GMEAPI gme_seek ( Music_Emu* me, int msec ) { return me->seek( msec ); }
|
||||
int GMEAPI gme_voice_count ( Music_Emu const* me ) { return me->voice_count(); }
|
||||
void GMEAPI gme_ignore_silence ( Music_Emu* me, int disable ) { me->ignore_silence( disable != 0 ); }
|
||||
void GMEAPI gme_set_tempo ( Music_Emu* me, double t ) { me->set_tempo( t ); }
|
||||
void GMEAPI gme_mute_voice ( Music_Emu* me, int index, int mute ) { me->mute_voice( index, mute != 0 ); }
|
||||
void GMEAPI gme_mute_voices ( Music_Emu* me, int mask ) { me->mute_voices( mask ); }
|
||||
BLARGG_EXPORT gme_err_t gme_start_track ( Music_Emu* me, int index ) { return me->start_track( index ); }
|
||||
BLARGG_EXPORT gme_err_t gme_play ( Music_Emu* me, int n, short* p ) { return me->play( n, p ); }
|
||||
BLARGG_EXPORT void gme_set_fade ( Music_Emu* me, int start_msec ) { me->set_fade( start_msec ); }
|
||||
BLARGG_EXPORT int gme_track_ended ( Music_Emu const* me ) { return me->track_ended(); }
|
||||
BLARGG_EXPORT int gme_tell ( Music_Emu const* me ) { return me->tell(); }
|
||||
BLARGG_EXPORT gme_err_t gme_seek ( Music_Emu* me, int msec ) { return me->seek( msec ); }
|
||||
BLARGG_EXPORT int gme_voice_count ( Music_Emu const* me ) { return me->voice_count(); }
|
||||
BLARGG_EXPORT void gme_ignore_silence ( Music_Emu* me, int disable ) { me->ignore_silence( disable != 0 ); }
|
||||
BLARGG_EXPORT void gme_set_tempo ( Music_Emu* me, double t ) { me->set_tempo( t ); }
|
||||
BLARGG_EXPORT void gme_mute_voice ( Music_Emu* me, int index, int mute ) { me->mute_voice( index, mute != 0 ); }
|
||||
BLARGG_EXPORT void gme_mute_voices ( Music_Emu* me, int mask ) { me->mute_voices( mask ); }
|
||||
BLARGG_EXPORT void gme_enable_accuracy( Music_Emu* me, int enabled ) { me->enable_accuracy( enabled ); }
|
||||
BLARGG_EXPORT void gme_clear_playlist ( Music_Emu* me ) { me->clear_playlist(); }
|
||||
BLARGG_EXPORT int gme_type_multitrack( gme_type_t t ) { return t->track_count != 1; }
|
||||
|
||||
void GMEAPI gme_set_equalizer ( Music_Emu* me, gme_equalizer_t const* eq )
|
||||
BLARGG_EXPORT void gme_set_equalizer ( Music_Emu* me, gme_equalizer_t const* eq )
|
||||
{
|
||||
Music_Emu::equalizer_t e = me->equalizer();
|
||||
e.treble = eq->treble;
|
||||
|
@ -335,16 +355,22 @@ void GMEAPI gme_set_equalizer ( Music_Emu* me, gme_equalizer_t const* eq )
|
|||
me->set_equalizer( e );
|
||||
}
|
||||
|
||||
void GMEAPI gme_equalizer( Music_Emu const* me, gme_equalizer_t* out )
|
||||
BLARGG_EXPORT void gme_equalizer( Music_Emu const* me, gme_equalizer_t* out )
|
||||
{
|
||||
gme_equalizer_t e = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
|
||||
gme_equalizer_t e = gme_equalizer_t(); // Default-init all fields to 0.0f
|
||||
e.treble = me->equalizer().treble;
|
||||
e.bass = me->equalizer().bass;
|
||||
*out = e;
|
||||
}
|
||||
|
||||
const char* GMEAPI gme_voice_name( Music_Emu const* me, int i )
|
||||
BLARGG_EXPORT const char* gme_voice_name( Music_Emu const* me, int i )
|
||||
{
|
||||
assert( (unsigned) i < (unsigned) me->voice_count() );
|
||||
return me->voice_names() [i];
|
||||
}
|
||||
|
||||
BLARGG_EXPORT const char* gme_type_system( gme_type_t type )
|
||||
{
|
||||
assert( type );
|
||||
return type->system;
|
||||
}
|
||||
|
|
|
@ -1,33 +1,15 @@
|
|||
/* Game music emulator library C interface (also usable from C++) */
|
||||
|
||||
/* Game_Music_Emu 0.5.2 */
|
||||
/* Game_Music_Emu 0.6.0 */
|
||||
#ifndef GME_H
|
||||
#define GME_H
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#define GMEAPI __stdcall
|
||||
#else
|
||||
#define GMEAPI
|
||||
#endif
|
||||
|
||||
#if defined(_MSC_VER) && defined(GME_DLL)
|
||||
#define GMEEXPORT __declspec(dllexport)
|
||||
#define GMEIMPORT __declspec(dllimport)
|
||||
#if IN_GME
|
||||
#define GMEDLL GMEEXPORT
|
||||
#else
|
||||
#define GMEDLL GMEIMPORT
|
||||
#endif
|
||||
#else
|
||||
#define GMEEXPORT
|
||||
#define GMEIMPORT
|
||||
#define GMEDLL
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define GME_VERSION 0x000600 /* 1 byte major, 1 byte minor, 1 byte patch-level */
|
||||
|
||||
/* Error string returned by library functions, or NULL if no error (success) */
|
||||
typedef const char* gme_err_t;
|
||||
|
||||
|
@ -38,38 +20,35 @@ typedef struct Music_Emu Music_Emu;
|
|||
/******** Basic operations ********/
|
||||
|
||||
/* Create emulator and load game music file/data into it. Sets *out to new emulator. */
|
||||
GMEDLL gme_err_t GMEAPI gme_open_file( const char path [], Music_Emu** out, int sample_rate );
|
||||
gme_err_t gme_open_file( const char path [], Music_Emu** out, int sample_rate );
|
||||
|
||||
/* Number of tracks available */
|
||||
GMEDLL int GMEAPI gme_track_count( Music_Emu const* );
|
||||
int gme_track_count( Music_Emu const* );
|
||||
|
||||
/* Start a track, where 0 is the first track */
|
||||
GMEDLL gme_err_t GMEAPI gme_start_track( Music_Emu*, int index );
|
||||
gme_err_t gme_start_track( Music_Emu*, int index );
|
||||
|
||||
/* Generate 'count' 16-bit signed samples info 'out'. Output is in stereo. */
|
||||
GMEDLL gme_err_t GMEAPI gme_play( Music_Emu*, int count, short out [] );
|
||||
|
||||
/* Skip n samples */
|
||||
GMEDLL gme_err_t GMEAPI gme_skip( Music_Emu*, long n );
|
||||
gme_err_t gme_play( Music_Emu*, int count, short out [] );
|
||||
|
||||
/* Finish using emulator and free memory */
|
||||
GMEDLL void GMEAPI gme_delete( Music_Emu* );
|
||||
void gme_delete( Music_Emu* );
|
||||
|
||||
|
||||
/******** Track position/length ********/
|
||||
|
||||
/* Set time to start fading track out. Once fade ends track_ended() returns true.
|
||||
Fade time can be changed while track is playing. */
|
||||
GMEDLL void GMEAPI gme_set_fade( Music_Emu*, int start_msec );
|
||||
void gme_set_fade( Music_Emu*, int start_msec );
|
||||
|
||||
/* True if a track has reached its end */
|
||||
GMEDLL int GMEAPI gme_track_ended( Music_Emu const* );
|
||||
int gme_track_ended( Music_Emu const* );
|
||||
|
||||
/* Number of milliseconds (1000 = one second) played since beginning of track */
|
||||
GMEDLL int GMEAPI gme_tell( Music_Emu const* );
|
||||
int gme_tell( Music_Emu const* );
|
||||
|
||||
/* Seek to new time in track. Seeking backwards or far forward can take a while. */
|
||||
GMEDLL gme_err_t GMEAPI gme_seek( Music_Emu*, int msec );
|
||||
gme_err_t gme_seek( Music_Emu*, int msec );
|
||||
|
||||
|
||||
/******** Informational ********/
|
||||
|
@ -80,22 +59,22 @@ enum { gme_info_only = -1 };
|
|||
|
||||
/* Most recent warning string, or NULL if none. Clears current warning after returning.
|
||||
Warning is also cleared when loading a file and starting a track. */
|
||||
GMEDLL const char* GMEAPI gme_warning( Music_Emu* );
|
||||
const char* gme_warning( Music_Emu* );
|
||||
|
||||
/* Load m3u playlist file (must be done after loading music) */
|
||||
GMEDLL gme_err_t GMEAPI gme_load_m3u( Music_Emu*, const char path [] );
|
||||
gme_err_t gme_load_m3u( Music_Emu*, const char path [] );
|
||||
|
||||
/* Clear any loaded m3u playlist and any internal playlist that the music format
|
||||
supports (NSFE for example). */
|
||||
GMEDLL void GMEAPI gme_clear_playlist( Music_Emu* );
|
||||
void gme_clear_playlist( Music_Emu* );
|
||||
|
||||
/* Gets information for a particular track (length, name, author, etc.).
|
||||
Must be freed after use. */
|
||||
typedef struct gme_info_t gme_info_t;
|
||||
GMEDLL gme_err_t GMEAPI gme_track_info( Music_Emu const*, gme_info_t** out, int track );
|
||||
gme_err_t gme_track_info( Music_Emu const*, gme_info_t** out, int track );
|
||||
|
||||
/* Frees track information */
|
||||
GMEDLL void GMEAPI gme_free_info( gme_info_t* );
|
||||
void gme_free_info( gme_info_t* );
|
||||
|
||||
struct gme_info_t
|
||||
{
|
||||
|
@ -127,30 +106,31 @@ struct gme_info_t
|
|||
|
||||
/* Adjust stereo echo depth, where 0.0 = off and 1.0 = maximum. Has no effect for
|
||||
GYM, SPC, and Sega Genesis VGM music */
|
||||
GMEDLL void GMEAPI gme_set_stereo_depth( Music_Emu*, double depth );
|
||||
void gme_set_stereo_depth( Music_Emu*, double depth );
|
||||
|
||||
/* Disable automatic end-of-track detection and skipping of silence at beginning
|
||||
if ignore is true */
|
||||
GMEDLL void GMEAPI gme_ignore_silence( Music_Emu*, int ignore );
|
||||
void gme_ignore_silence( Music_Emu*, int ignore );
|
||||
|
||||
/* Adjust song tempo, where 1.0 = normal, 0.5 = half speed, 2.0 = double speed.
|
||||
Track length as returned by track_info() assumes a tempo of 1.0. */
|
||||
GMEDLL void GMEAPI gme_set_tempo( Music_Emu*, double tempo );
|
||||
void gme_set_tempo( Music_Emu*, double tempo );
|
||||
|
||||
/* Number of voices used by currently loaded file */
|
||||
GMEDLL int GMEAPI gme_voice_count( Music_Emu const* );
|
||||
int gme_voice_count( Music_Emu const* );
|
||||
|
||||
/* Name of voice i, from 0 to gme_voice_count() - 1 */
|
||||
GMEDLL const char* GMEAPI gme_voice_name( Music_Emu const*, int i );
|
||||
const char* gme_voice_name( Music_Emu const*, int i );
|
||||
|
||||
/* Mute/unmute voice i, where voice 0 is first voice */
|
||||
GMEDLL void GMEAPI gme_mute_voice( Music_Emu*, int index, int mute );
|
||||
void gme_mute_voice( Music_Emu*, int index, int mute );
|
||||
|
||||
/* Set muting state of all voices at once using a bit mask, where -1 mutes all
|
||||
voices, 0 unmutes them all, 0x01 mutes just the first voice, etc. */
|
||||
GMEDLL void GMEAPI gme_mute_voices( Music_Emu*, int muting_mask );
|
||||
void gme_mute_voices( Music_Emu*, int muting_mask );
|
||||
|
||||
/* Frequency equalizer parameters (see gme.txt) */
|
||||
/* Implementers: If modified, also adjust Music_Emu::make_equalizer as needed */
|
||||
typedef struct gme_equalizer_t
|
||||
{
|
||||
double treble; /* -50.0 = muffled, 0 = flat, +5.0 = extra-crisp */
|
||||
|
@ -160,11 +140,13 @@ typedef struct gme_equalizer_t
|
|||
} gme_equalizer_t;
|
||||
|
||||
/* Get current frequency equalizater parameters */
|
||||
GMEDLL void GMEAPI gme_equalizer( Music_Emu const*, gme_equalizer_t* out );
|
||||
void gme_equalizer( Music_Emu const*, gme_equalizer_t* out );
|
||||
|
||||
/* Change frequency equalizer parameters */
|
||||
GMEDLL void GMEAPI gme_set_equalizer( Music_Emu*, gme_equalizer_t const* eq );
|
||||
void gme_set_equalizer( Music_Emu*, gme_equalizer_t const* eq );
|
||||
|
||||
/* Enables/disables most accurate sound emulation options */
|
||||
void gme_enable_accuracy( Music_Emu*, int enabled );
|
||||
|
||||
|
||||
/******** Game music types ********/
|
||||
|
@ -187,17 +169,17 @@ extern const gme_type_t
|
|||
gme_vgz_type;
|
||||
|
||||
/* Type of this emulator */
|
||||
GMEDLL gme_type_t GMEAPI gme_type( Music_Emu const* );
|
||||
gme_type_t gme_type( Music_Emu const* );
|
||||
|
||||
/* Pointer to array of all music types, with NULL entry at end. Allows a player linked
|
||||
to this library to support new music types without having to be updated. */
|
||||
GMEDLL gme_type_t const* GMEAPI gme_type_list();
|
||||
gme_type_t const* gme_type_list();
|
||||
|
||||
/* Name of game system for this music file type */
|
||||
GMEDLL const char* GMEAPI gme_type_system( gme_type_t );
|
||||
const char* gme_type_system( gme_type_t );
|
||||
|
||||
/* True if this music file type supports multiple tracks */
|
||||
GMEDLL int GMEAPI gme_type_multitrack( gme_type_t );
|
||||
int gme_type_multitrack( gme_type_t );
|
||||
|
||||
|
||||
/******** Advanced file loading ********/
|
||||
|
@ -206,50 +188,50 @@ GMEDLL int GMEAPI gme_type_multitrack( gme_type_t );
|
|||
extern const char* const gme_wrong_file_type;
|
||||
|
||||
/* Same as gme_open_file(), but uses file data already in memory. Makes copy of data. */
|
||||
GMEDLL gme_err_t GMEAPI gme_open_data( void const* data, long size, Music_Emu** out, int sample_rate );
|
||||
gme_err_t gme_open_data( void const* data, long size, Music_Emu** out, int sample_rate );
|
||||
|
||||
/* Determine likely game music type based on first four bytes of file. Returns
|
||||
string containing proper file suffix (i.e. "NSF", "SPC", etc.) or "" if
|
||||
file header is not recognized. */
|
||||
GMEDLL const char* GMEAPI gme_identify_header( void const* header );
|
||||
const char* gme_identify_header( void const* header );
|
||||
|
||||
/* Get corresponding music type for file path or extension passed in. */
|
||||
GMEDLL gme_type_t GMEAPI gme_identify_extension( const char path_or_extension [] );
|
||||
gme_type_t gme_identify_extension( const char path_or_extension [] );
|
||||
|
||||
/* Determine file type based on file's extension or header (if extension isn't recognized).
|
||||
Sets *type_out to type, or 0 if unrecognized or error. */
|
||||
GMEDLL gme_err_t GMEAPI gme_identify_file( const char path [], gme_type_t* type_out );
|
||||
gme_err_t gme_identify_file( const char path [], gme_type_t* type_out );
|
||||
|
||||
/* Create new emulator and set sample rate. Returns NULL if out of memory. If you only need
|
||||
track information, pass gme_info_only for sample_rate. */
|
||||
GMEDLL Music_Emu* GMEAPI gme_new_emu( gme_type_t, int sample_rate );
|
||||
Music_Emu* gme_new_emu( gme_type_t, int sample_rate );
|
||||
|
||||
/* Load music file into emulator */
|
||||
GMEDLL gme_err_t GMEAPI gme_load_file( Music_Emu*, const char path [] );
|
||||
gme_err_t gme_load_file( Music_Emu*, const char path [] );
|
||||
|
||||
/* Load music file from memory into emulator. Makes a copy of data passed. */
|
||||
GMEDLL gme_err_t GMEAPI gme_load_data( Music_Emu*, void const* data, long size );
|
||||
gme_err_t gme_load_data( Music_Emu*, void const* data, long size );
|
||||
|
||||
/* Load music file using custom data reader function that will be called to
|
||||
read file data. Most emulators load the entire file in one read call. */
|
||||
typedef gme_err_t (GMEAPI *gme_reader_t)( void* your_data, void* out, int count );
|
||||
GMEDLL gme_err_t GMEAPI gme_load_custom( Music_Emu*, gme_reader_t, long file_size, void* your_data );
|
||||
typedef gme_err_t (*gme_reader_t)( void* your_data, void* out, int count );
|
||||
gme_err_t gme_load_custom( Music_Emu*, gme_reader_t, long file_size, void* your_data );
|
||||
|
||||
/* Load m3u playlist file from memory (must be done after loading music) */
|
||||
GMEDLL gme_err_t GMEAPI gme_load_m3u_data( Music_Emu*, void const* data, long size );
|
||||
gme_err_t gme_load_m3u_data( Music_Emu*, void const* data, long size );
|
||||
|
||||
|
||||
/******** User data ********/
|
||||
|
||||
/* Set/get pointer to data you want to associate with this emulator.
|
||||
You can use this for whatever you want. */
|
||||
GMEDLL void GMEAPI gme_set_user_data( Music_Emu*, void* new_user_data );
|
||||
GMEDLL void* GMEAPI gme_user_data( Music_Emu const* );
|
||||
void gme_set_user_data( Music_Emu*, void* new_user_data );
|
||||
void* gme_user_data( Music_Emu const* );
|
||||
|
||||
/* Register cleanup function to be called when deleting emulator, or NULL to
|
||||
clear it. Passes user_data to cleanup function. */
|
||||
typedef void (GMEAPI *gme_user_cleanup_t)( void* user_data );
|
||||
GMEDLL void GMEAPI gme_set_user_cleanup( Music_Emu*, gme_user_cleanup_t func );
|
||||
typedef void (*gme_user_cleanup_t)( void* user_data );
|
||||
void gme_set_user_cleanup( Music_Emu*, gme_user_cleanup_t func );
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
|
21
game-music-emu/gme/gme_types.h
Normal file
21
game-music-emu/gme/gme_types.h
Normal file
|
@ -0,0 +1,21 @@
|
|||
#ifndef GME_TYPES_H
|
||||
#define GME_TYPES_H
|
||||
|
||||
/*
|
||||
* This is a default gme_types.h for use when *not* using
|
||||
* CMake. If CMake is in use gme_types.h.in will be
|
||||
* processed instead.
|
||||
*/
|
||||
#define USE_GME_AY
|
||||
#define USE_GME_GBS
|
||||
#define USE_GME_GYM
|
||||
#define USE_GME_HES
|
||||
#define USE_GME_KSS
|
||||
#define USE_GME_NSF
|
||||
#define USE_GME_NSFE
|
||||
#define USE_GME_SAP
|
||||
#define USE_GME_SPC
|
||||
/* VGM and VGZ are a package deal */
|
||||
#define USE_GME_VGM
|
||||
|
||||
#endif /* GME_TYPES_H */
|
23
game-music-emu/gme/gme_types.h.in
Normal file
23
game-music-emu/gme/gme_types.h.in
Normal file
|
@ -0,0 +1,23 @@
|
|||
#ifndef GME_TYPES_H
|
||||
#define GME_TYPES_H
|
||||
|
||||
/* CMake will either define the following to 1, or #undef it,
|
||||
* depending on the options passed to CMake. This is used to
|
||||
* conditionally compile in the various emulator types.
|
||||
*
|
||||
* See gme_type_list() in gme.cpp
|
||||
*/
|
||||
|
||||
#cmakedefine USE_GME_AY
|
||||
#cmakedefine USE_GME_GBS
|
||||
#cmakedefine USE_GME_GYM
|
||||
#cmakedefine USE_GME_HES
|
||||
#cmakedefine USE_GME_KSS
|
||||
#cmakedefine USE_GME_NSF
|
||||
#cmakedefine USE_GME_NSFE
|
||||
#cmakedefine USE_GME_SAP
|
||||
#cmakedefine USE_GME_SPC
|
||||
/* VGM and VGZ are a package deal */
|
||||
#cmakedefine USE_GME_VGM
|
||||
|
||||
#endif /* GME_TYPES_H */
|
|
@ -44,7 +44,7 @@ inline byte const* Hes_Emu::cpu_set_mmr( int page, int bank )
|
|||
|
||||
default:
|
||||
if ( bank != 0xFF )
|
||||
dprintf( "Unmapped bank $%02X\n", bank );
|
||||
debug_printf( "Unmapped bank $%02X\n", bank );
|
||||
return rom.unmapped();
|
||||
}
|
||||
|
||||
|
|
|
@ -34,7 +34,7 @@ int Nsf_Emu::cpu_read( nes_addr_t addr )
|
|||
result = addr >> 8; // simulate open bus
|
||||
|
||||
if ( addr != 0x2002 )
|
||||
dprintf( "Read unmapped $%.4X\n", (unsigned) addr );
|
||||
debug_printf( "Read unmapped $%.4X\n", (unsigned) addr );
|
||||
|
||||
exit:
|
||||
return result;
|
||||
|
|
|
@ -20,7 +20,7 @@ void Sap_Emu::cpu_write( sap_addr_t addr, int data )
|
|||
int Sap_Emu::cpu_read( sap_addr_t addr )
|
||||
{
|
||||
if ( (addr & 0xF900) == 0xD000 )
|
||||
dprintf( "Unmapped read $%04X\n", addr );
|
||||
debug_printf( "Unmapped read $%04X\n", addr );
|
||||
return mem.ram [addr];
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
Game_Music_Emu 0.5.2: Game Music Emulators
|
||||
Game_Music_Emu 0.6.0: Game Music Emulators
|
||||
------------------------------------------
|
||||
Game_Music_Emu is a collection of video game music file emulators that
|
||||
support the following formats and systems:
|
||||
|
@ -14,7 +14,7 @@ SPC Super Nintendo/Super Famicom
|
|||
VGM/VGZ Sega Master System/Mark III, Sega Genesis/Mega Drive,BBC Micro
|
||||
|
||||
Features:
|
||||
* Can be used in C and C++ code
|
||||
* C interface for use in C, C++, and other compatible languages
|
||||
* High emphasis has been placed on making the library very easy to use
|
||||
* One set of common functions work with all emulators the same way
|
||||
* Several code examples, including music player using SDL
|
||||
|
@ -42,8 +42,17 @@ License: GNU Lesser General Public License (LGPL)
|
|||
Getting Started
|
||||
---------------
|
||||
Build a program consisting of demo/basics.c, demo/Wave_Writer.cpp, and
|
||||
all source files in gme/. Be sure "test.nsf" is in the same directory.
|
||||
Running the program should generate the recording "out.wav".
|
||||
all source files in gme/. If you have CMake 2.6 or later, execute
|
||||
|
||||
run cmake
|
||||
cd demo
|
||||
run make
|
||||
|
||||
Be sure "test.nsf" is in the same directory as the program. Running it
|
||||
should generate the recording "out.wav".
|
||||
|
||||
A slightly more extensive demo application is available in the player/
|
||||
directory. It requires SDL to build.
|
||||
|
||||
Read gme.txt for more information. Post to the discussion forum for
|
||||
assistance.
|
||||
|
@ -55,16 +64,17 @@ gme.txt General notes about the library
|
|||
changes.txt Changes made since previous releases
|
||||
design.txt Library design notes
|
||||
license.txt GNU Lesser General Public License
|
||||
CMakeLists.txt CMake build rules
|
||||
|
||||
test.nsf Test file for NSF emulator
|
||||
test.m3u Test m3u playlist for features.c demo
|
||||
|
||||
demo/
|
||||
basics.c Records NSF file to wave sound file
|
||||
cpp_basics.cpp C++ version of basics.c
|
||||
features.c Demonstrates many additional features
|
||||
Wave_Writer.h WAVE sound file writer used for demo output
|
||||
Wave_Writer.cpp
|
||||
CMakeLists.txt CMake build rules
|
||||
|
||||
player/ Player using the SDL multimedia library
|
||||
player.cpp Simple music player with waveform display
|
||||
|
@ -72,22 +82,13 @@ player/ Player using the SDL multimedia library
|
|||
Music_Player.h
|
||||
Audio_Scope.cpp Audio waveform scope
|
||||
Audio_Scope.h
|
||||
CMakeLists.txt CMake build rules
|
||||
|
||||
gme/
|
||||
blargg_config.h Library configuration (modify this file as needed)
|
||||
|
||||
gme.h C interface (also usable in C++, and simpler too)
|
||||
gme.h Library interface header file
|
||||
gme.cpp
|
||||
|
||||
Gme_File.h File loading and track information
|
||||
Music_Emu.h Track playback and adjustments
|
||||
Data_Reader.h Custom data readers
|
||||
|
||||
Effects_Buffer.h Sound buffer with stereo echo and panning
|
||||
Effects_Buffer.cpp
|
||||
|
||||
M3u_Playlist.h M3U playlist support
|
||||
M3u_Playlist.cpp
|
||||
|
||||
Ay_Emu.h ZX Spectrum AY emulator
|
||||
Ay_Emu.cpp
|
||||
|
@ -113,7 +114,7 @@ gme/
|
|||
Hes_Cpu.h
|
||||
hes_cpu_io.h
|
||||
Hes_Emu.cpp
|
||||
|
||||
|
||||
Kss_Emu.h MSX Home Computer/other Z80 systems KSS emulator
|
||||
Kss_Emu.cpp
|
||||
Kss_Cpu.cpp
|
||||
|
@ -180,26 +181,36 @@ gme/
|
|||
Dual_Resampler.h
|
||||
Fir_Resampler.cpp
|
||||
Fir_Resampler.h
|
||||
|
||||
|
||||
M3u_Playlist.h M3U playlist support
|
||||
M3u_Playlist.cpp
|
||||
|
||||
Effects_Buffer.h Sound buffer with stereo echo and panning
|
||||
Effects_Buffer.cpp
|
||||
|
||||
blargg_common.h Common files needed by all emulators
|
||||
blargg_endian.h
|
||||
blargg_source.h
|
||||
Blip_Buffer.cpp
|
||||
Blip_Buffer.h
|
||||
Gme_File.h
|
||||
Gme_File.cpp
|
||||
Music_Emu.h
|
||||
Music_Emu.cpp
|
||||
Classic_Emu.h
|
||||
Classic_Emu.cpp
|
||||
Multi_Buffer.h
|
||||
Multi_Buffer.cpp
|
||||
Data_Reader.h
|
||||
Data_Reader.cpp
|
||||
|
||||
CMakeLists.txt CMake build rules
|
||||
|
||||
|
||||
Legal
|
||||
-----
|
||||
Game_Music_Emu library copyright (C) 2003-2006 Shay Green.
|
||||
SNES SPC DSP emulator based on OpenSPC, copyright (C) 2002 Brad Martin.
|
||||
Game_Music_Emu library copyright (C) 2003-2009 Shay Green.
|
||||
Sega Genesis YM2612 emulator copyright (C) 2002 Stephane Dallongeville.
|
||||
|
||||
--
|
||||
--
|
||||
Shay Green <gblargg@gmail.com>
|
||||
|
|
Loading…
Reference in a new issue