mirror of
https://github.com/ZDoom/gzdoom.git
synced 2024-11-26 05:51:20 +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 )
|
# CMake project definition file.
|
||||||
include( CheckCXXCompilerFlag )
|
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()
|
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( HAVE_NO_ARRAY_BOUNDS )
|
||||||
endif( "${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" OR "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang" )
|
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
|
# Default emulators to build (all of them! ;)
|
||||||
gme/Data_Reader.cpp
|
if (NOT DEFINED USE_GME_AY)
|
||||||
gme/Dual_Resampler.cpp
|
SET(USE_GME_AY 1 CACHE BOOL "Enable support for Spectrum ZX music emulation")
|
||||||
gme/Effects_Buffer.cpp
|
endif()
|
||||||
gme/Fir_Resampler.cpp
|
|
||||||
gme/gme.cpp
|
if (NOT DEFINED USE_GME_GBS)
|
||||||
gme/Gme_File.cpp
|
SET(USE_GME_GBS 1 CACHE BOOL "Enable support for Game Boy music emulation")
|
||||||
gme/M3u_Playlist.cpp
|
endif()
|
||||||
gme/Multi_Buffer.cpp
|
|
||||||
gme/Music_Emu.cpp
|
if (NOT DEFINED USE_GME_GYM)
|
||||||
|
SET(USE_GME_GYM 1 CACHE BOOL "Enable Sega MegaDrive/Genesis music emulation")
|
||||||
gme/Ay_Apu.cpp
|
endif()
|
||||||
gme/Ay_Cpu.cpp
|
|
||||||
gme/Ay_Emu.cpp
|
if (NOT DEFINED USE_GME_HES)
|
||||||
gme/Gb_Apu.cpp
|
SET(USE_GME_HES 1 CACHE BOOL "Enable PC Engine/TurboGrafx-16 music emulation")
|
||||||
gme/Gb_Cpu.cpp
|
endif()
|
||||||
gme/Gb_Oscs.cpp
|
|
||||||
gme/Gbs_Emu.cpp
|
if (NOT DEFINED USE_GME_KSS)
|
||||||
gme/Gym_Emu.cpp
|
SET(USE_GME_KSS 1 CACHE BOOL "Enable MSX or other Z80 systems music emulation")
|
||||||
gme/Hes_Apu.cpp
|
endif()
|
||||||
gme/Hes_Cpu.cpp
|
|
||||||
gme/Hes_Emu.cpp
|
if (NOT DEFINED USE_GME_NSF)
|
||||||
gme/Kss_Cpu.cpp
|
SET(USE_GME_NSF 1 CACHE BOOL "Enable NES NSF music emulation")
|
||||||
gme/Kss_Emu.cpp
|
endif()
|
||||||
gme/Kss_Scc_Apu.cpp
|
|
||||||
gme/Nes_Apu.cpp
|
if (NOT DEFINED USE_GME_NSFE)
|
||||||
gme/Nes_Cpu.cpp
|
SET(USE_GME_NSFE 1 CACHE BOOL "Enable NES NSFE and NSF music emulation")
|
||||||
gme/Nes_Fme7_Apu.cpp
|
endif()
|
||||||
gme/Nes_Namco_Apu.cpp
|
|
||||||
gme/Nes_Oscs.cpp
|
if (NOT DEFINED USE_GME_SAP)
|
||||||
gme/Nes_Vrc6_Apu.cpp
|
SET(USE_GME_SAP 1 CACHE BOOL "Enable Atari SAP music emulation")
|
||||||
gme/Nsf_Emu.cpp
|
endif()
|
||||||
gme/Nsfe_Emu.cpp
|
|
||||||
gme/Sap_Apu.cpp
|
if (NOT DEFINED USE_GME_SPC)
|
||||||
gme/Sap_Cpu.cpp
|
SET(USE_GME_SPC 1 CACHE BOOL "Enable SNES SPC music emulation")
|
||||||
gme/Sap_Emu.cpp
|
endif()
|
||||||
gme/Sms_Apu.cpp
|
|
||||||
gme/Snes_Spc.cpp
|
if (NOT DEFINED USE_GME_VGM)
|
||||||
gme/Spc_Cpu.cpp
|
SET(USE_GME_VGM 1 CACHE BOOL "Enable Sega VGM/VGZ music emulation")
|
||||||
gme/Spc_Dsp.cpp
|
endif()
|
||||||
gme/Spc_Emu.cpp
|
|
||||||
gme/Vgm_Emu.cpp
|
if (USE_GME_NSFE AND NOT USE_GME_NSF)
|
||||||
gme/Vgm_Emu_Impl.cpp
|
MESSAGE(" -- NSFE support requires NSF, enabling NSF support. --")
|
||||||
gme/Ym2413_Emu.cpp
|
SET(USE_GME_NSF 1 CACHE BOOL "Enable NES NSF music emulation" FORCE)
|
||||||
gme/Ym2612_Emu.cpp )
|
endif()
|
||||||
target_link_libraries( gme )
|
|
||||||
|
# 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 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
|
Game_Music_Emu 0.5.2
|
||||||
--------------------
|
--------------------
|
||||||
- *TONS* of changes and improvements. You should re-read the new header
|
- *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
|
This might be slightly out-of-date at times, but will be a big help in
|
||||||
understanding the library implementation.
|
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>
|
Author : Shay Green <gblargg@gmail.com>
|
||||||
Website: http://www.slack.net/~ant/libs/
|
Website: http://www.slack.net/~ant/libs/
|
||||||
Forum : http://groups.google.com/group/blargg-sound-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)
|
License: GNU Lesser General Public License (LGPL)
|
||||||
|
|
||||||
Contents
|
Contents
|
||||||
--------
|
--------
|
||||||
* Overview
|
* Overview
|
||||||
* C and C++ interfaces
|
|
||||||
* Function reference
|
|
||||||
* Error handling
|
* Error handling
|
||||||
* Emulator types
|
* Emulator types
|
||||||
* M3U playlist support
|
* M3U playlist support
|
||||||
|
@ -21,7 +20,6 @@ Contents
|
||||||
* Modular construction
|
* Modular construction
|
||||||
* Obscure features
|
* Obscure features
|
||||||
* Solving problems
|
* Solving problems
|
||||||
* Deprecated features
|
|
||||||
* Thanks
|
* Thanks
|
||||||
|
|
||||||
|
|
||||||
|
@ -62,56 +60,15 @@ deleted with gme_set_user_cleanup()
|
||||||
Refer to gme.h for a comprehensive summary of features.
|
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
|
Error handling
|
||||||
--------------
|
--------------
|
||||||
Functions which can fail have a return type of gme_err_t (blargg_err_t
|
Functions which can fail have a return type of gme_err_t, which is a
|
||||||
in the C++ interfaces), which is a pointer to an error string (const
|
pointer to an error string (const char*). If a function is successful it
|
||||||
char*). If a function is successful it returns NULL. Errors that you can
|
returns NULL. Errors that you can easily avoid are checked with debug
|
||||||
easily avoid are checked with debug assertions; gme_err_t return values
|
assertions; gme_err_t return values are only used for genuine run-time
|
||||||
are only used for genuine run-time errors that can't be easily predicted
|
errors that can't be easily predicted in advance (out of memory, I/O
|
||||||
in advance (out of memory, I/O errors, incompatible file data). Your
|
errors, incompatible file data). Your code should check all error
|
||||||
code should check all error values.
|
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.
|
|
||||||
|
|
||||||
When loading a music file in the wrong emulator or trying to load a
|
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
|
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
|
executable size, edit GME_TYPE_LIST in blargg_config.h. For example, to
|
||||||
support just NSF and GBS, use this:
|
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
|
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 );
|
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
|
Sound parameters
|
||||||
----------------
|
----------------
|
||||||
|
@ -437,21 +362,6 @@ separate threads.
|
||||||
* If all else fails, see if the demos work.
|
* 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
|
Thanks
|
||||||
------
|
------
|
||||||
Big thanks to Chris Moeller (kode54) for help with library testing and
|
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,
|
start. Also thanks to Richard Bannister, Mahendra Tallur, Shazz,
|
||||||
nenolod, theHobbit, Johan Samuelsson, and nes6502 for testing, using,
|
nenolod, theHobbit, Johan Samuelsson, and nes6502 for testing, using,
|
||||||
and giving feedback for the library in their respective game music
|
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"
|
#include "Ay_Apu.h"
|
||||||
|
|
||||||
|
@ -123,8 +123,8 @@ void Ay_Apu::write_data_( int addr, int data )
|
||||||
|
|
||||||
if ( (unsigned) addr >= 14 )
|
if ( (unsigned) addr >= 14 )
|
||||||
{
|
{
|
||||||
#ifdef dprintf
|
#ifdef debug_printf
|
||||||
dprintf( "Wrote to I/O port %02X\n", (int) addr );
|
debug_printf( "Wrote to I/O port %02X\n", (int) addr );
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -220,7 +220,7 @@ void Ay_Apu::run_until( blip_time_t final_end_time )
|
||||||
end_time = final_end_time;
|
end_time = final_end_time;
|
||||||
|
|
||||||
//if ( !(regs [12] | regs [11]) )
|
//if ( !(regs [12] | regs [11]) )
|
||||||
// dprintf( "Used envelope period 0\n" );
|
// debug_printf( "Used envelope period 0\n" );
|
||||||
}
|
}
|
||||||
else if ( !volume )
|
else if ( !volume )
|
||||||
{
|
{
|
||||||
|
@ -250,7 +250,7 @@ void Ay_Apu::run_until( blip_time_t final_end_time )
|
||||||
ntime = start_time + old_noise_delay;
|
ntime = start_time + old_noise_delay;
|
||||||
noise_lfsr = old_noise_lfsr;
|
noise_lfsr = old_noise_lfsr;
|
||||||
//if ( (regs [6] & 0x1F) == 0 )
|
//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):
|
// 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
|
while ( ntime <= end ) // must advance *past* time to avoid hang
|
||||||
{
|
{
|
||||||
int changed = noise_lfsr + 1;
|
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 )
|
if ( changed & 2 )
|
||||||
{
|
{
|
||||||
delta = -delta;
|
delta = -delta;
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
// AY-3-8910 sound chip emulator
|
// AY-3-8910 sound chip emulator
|
||||||
|
|
||||||
// Game_Music_Emu 0.5.2
|
// Game_Music_Emu 0.6.0
|
||||||
#ifndef AY_APU_H
|
#ifndef AY_APU_H
|
||||||
#define AY_APU_H
|
#define AY_APU_H
|
||||||
|
|
||||||
|
@ -50,7 +50,6 @@ private:
|
||||||
Blip_Buffer* output;
|
Blip_Buffer* output;
|
||||||
} oscs [osc_count];
|
} oscs [osc_count];
|
||||||
blip_time_t last_time;
|
blip_time_t last_time;
|
||||||
byte latch;
|
|
||||||
byte regs [reg_count];
|
byte regs [reg_count];
|
||||||
|
|
||||||
struct {
|
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
|
Last validated with zexall 2006.11.21 5:26 PM
|
||||||
|
@ -807,6 +807,7 @@ possibly_out_of_time:
|
||||||
case 0xCB:
|
case 0xCB:
|
||||||
unsigned data2;
|
unsigned data2;
|
||||||
data2 = INSTR( 1 );
|
data2 = INSTR( 1 );
|
||||||
|
(void) data2; // TODO is this the same as data in all cases?
|
||||||
pc++;
|
pc++;
|
||||||
switch ( data )
|
switch ( data )
|
||||||
{
|
{
|
||||||
|
@ -1047,7 +1048,7 @@ possibly_out_of_time:
|
||||||
blargg_ulong sum = temp + (flags & C01);
|
blargg_ulong sum = temp + (flags & C01);
|
||||||
flags = ~data >> 2 & N02;
|
flags = ~data >> 2 & N02;
|
||||||
if ( flags )
|
if ( flags )
|
||||||
sum = (blargg_ulong)-(blargg_long)sum;
|
sum = -sum;
|
||||||
sum += rp.hl;
|
sum += rp.hl;
|
||||||
temp ^= rp.hl;
|
temp ^= rp.hl;
|
||||||
temp ^= sum;
|
temp ^= sum;
|
||||||
|
@ -1252,7 +1253,7 @@ possibly_out_of_time:
|
||||||
|
|
||||||
case 0x4F: // LD R,A
|
case 0x4F: // LD R,A
|
||||||
SET_R( rg.a );
|
SET_R( rg.a );
|
||||||
dprintf( "LD R,A not supported\n" );
|
debug_printf( "LD R,A not supported\n" );
|
||||||
warning = true;
|
warning = true;
|
||||||
goto loop;
|
goto loop;
|
||||||
|
|
||||||
|
@ -1262,7 +1263,7 @@ possibly_out_of_time:
|
||||||
|
|
||||||
case 0x5F: // LD A,R
|
case 0x5F: // LD A,R
|
||||||
rg.a = GET_R();
|
rg.a = GET_R();
|
||||||
dprintf( "LD A,R not supported\n" );
|
debug_printf( "LD A,R not supported\n" );
|
||||||
warning = true;
|
warning = true;
|
||||||
ld_ai_common:
|
ld_ai_common:
|
||||||
flags = (flags & C01) | SZ28( rg.a ) | (r.iff2 << 2 & V04);
|
flags = (flags & C01) | SZ28( rg.a ) | (r.iff2 << 2 & V04);
|
||||||
|
@ -1285,7 +1286,7 @@ possibly_out_of_time:
|
||||||
goto loop;
|
goto loop;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
dprintf( "Opcode $ED $%02X not supported\n", data );
|
debug_printf( "Opcode $ED $%02X not supported\n", data );
|
||||||
warning = true;
|
warning = true;
|
||||||
goto loop;
|
goto loop;
|
||||||
}
|
}
|
||||||
|
@ -1545,7 +1546,7 @@ possibly_out_of_time:
|
||||||
}
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
dprintf( "Opcode $%02X $CB $%02X not supported\n", opcode, data2 );
|
debug_printf( "Opcode $%02X $CB $%02X not supported\n", opcode, data2 );
|
||||||
warning = true;
|
warning = true;
|
||||||
goto loop;
|
goto loop;
|
||||||
}
|
}
|
||||||
|
@ -1634,7 +1635,7 @@ possibly_out_of_time:
|
||||||
}
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
dprintf( "Unnecessary DD/FD prefix encountered\n" );
|
debug_printf( "Unnecessary DD/FD prefix encountered\n" );
|
||||||
warning = true;
|
warning = true;
|
||||||
pc--;
|
pc--;
|
||||||
goto loop;
|
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 );
|
assert( false );
|
||||||
|
|
||||||
halt:
|
halt:
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
// Z80 CPU emulator
|
// Z80 CPU emulator
|
||||||
|
|
||||||
// Game_Music_Emu 0.5.2
|
// Game_Music_Emu 0.6.0
|
||||||
#ifndef AY_CPU_H
|
#ifndef AY_CPU_H
|
||||||
#define 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"
|
#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 )
|
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 pos = ptr - (byte const*) file.header;
|
||||||
long file_size = long(file.end - (byte const*) file.header);
|
long file_size = file.end - (byte const*) file.header;
|
||||||
assert( (unsigned long) pos <= (unsigned long) file_size - 2 );
|
assert( (unsigned long) pos <= (unsigned long) file_size - 2 );
|
||||||
int offset = (BOOST::int16_t) get_be16( ptr );
|
int offset = (BOOST::int16_t) get_be16( ptr );
|
||||||
if ( !offset || blargg_ulong (pos + offset) > blargg_ulong (file_size - min_size) )
|
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) )
|
if ( len > blargg_ulong (file.end - in) )
|
||||||
{
|
{
|
||||||
set_warning( "Missing file data" );
|
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
|
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 );
|
memcpy( mem.ram + addr, in, len );
|
||||||
|
|
||||||
if ( file.end - blocks < 8 )
|
if ( file.end - blocks < 8 )
|
||||||
|
@ -242,7 +242,7 @@ blargg_err_t Ay_Emu::start_track_( int track )
|
||||||
};
|
};
|
||||||
memcpy( mem.ram, passive, sizeof passive );
|
memcpy( mem.ram, passive, sizeof passive );
|
||||||
unsigned play_addr = get_be16( more_data + 4 );
|
unsigned play_addr = get_be16( more_data + 4 );
|
||||||
//dprintf( "Play: $%04X\n", play_addr );
|
//debug_printf( "Play: $%04X\n", play_addr );
|
||||||
if ( play_addr )
|
if ( play_addr )
|
||||||
{
|
{
|
||||||
memcpy( mem.ram, active, sizeof active );
|
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;
|
return;
|
||||||
|
|
||||||
enable_cpc:
|
enable_cpc:
|
||||||
|
@ -356,7 +356,7 @@ int ay_cpu_in( Ay_Cpu*, unsigned addr )
|
||||||
if ( (addr & 0xFF) == 0xFE )
|
if ( (addr & 0xFF) == 0xFE )
|
||||||
return 0xFF; // other values break some beeper tunes
|
return 0xFF; // other values break some beeper tunes
|
||||||
|
|
||||||
dprintf( "Unmapped IN : $%04X\n", addr );
|
debug_printf( "Unmapped IN : $%04X\n", addr );
|
||||||
return 0xFF;
|
return 0xFF;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
// Sinclair Spectrum AY music file emulator
|
// Sinclair Spectrum AY music file emulator
|
||||||
|
|
||||||
// Game_Music_Emu 0.5.2
|
// Game_Music_Emu 0.6.0
|
||||||
#ifndef AY_EMU_H
|
#ifndef AY_EMU_H
|
||||||
#define AY_EMU_H
|
#define AY_EMU_H
|
||||||
|
|
||||||
|
@ -46,7 +46,6 @@ protected:
|
||||||
private:
|
private:
|
||||||
file_t file;
|
file_t file;
|
||||||
|
|
||||||
unsigned play_addr;
|
|
||||||
cpu_time_t play_period;
|
cpu_time_t play_period;
|
||||||
cpu_time_t next_play;
|
cpu_time_t next_play;
|
||||||
Blip_Buffer* beeper_output;
|
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;
|
double const to_angle = PI / 2 / maxh / oversample;
|
||||||
for ( int i = 0; i < count; i++ )
|
for ( int i = 0; i < count; i++ )
|
||||||
{
|
{
|
||||||
double angle = ((i - count) * 2 + 1) * to_angle;
|
double angle = ((i - count) * 2 + 1) * to_angle;
|
||||||
double c = rolloff * cos( (maxh - 1.0) * angle ) - cos( maxh * angle );
|
double angle_maxh = angle * maxh;
|
||||||
double cos_nc_angle = cos( maxh * cutoff * angle );
|
double angle_maxh_mid = angle_maxh * cutoff;
|
||||||
double cos_nc1_angle = cos( (maxh * cutoff - 1.0) * angle );
|
|
||||||
double cos_angle = cos( angle );
|
|
||||||
|
|
||||||
c = c * pow_a_n - rolloff * cos_nc1_angle + cos_nc_angle;
|
double y = maxh;
|
||||||
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;
|
|
||||||
|
|
||||||
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"
|
#include "Classic_Emu.h"
|
||||||
|
|
||||||
|
@ -176,9 +176,9 @@ void Rom_Data_::set_addr_( long addr, int unit )
|
||||||
|
|
||||||
if ( 0 )
|
if ( 0 )
|
||||||
{
|
{
|
||||||
dprintf( "addr: %X\n", addr );
|
debug_printf( "addr: %X\n", addr );
|
||||||
dprintf( "file_size: %d\n", file_size_ );
|
debug_printf( "file_size: %d\n", file_size_ );
|
||||||
dprintf( "rounded: %d\n", rounded );
|
debug_printf( "rounded: %d\n", rounded );
|
||||||
dprintf( "mask: $%X\n", mask );
|
debug_printf( "mask: $%X\n", mask );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
// Common aspects of emulators which use Blip_Buffer for sound output
|
// 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
|
#ifndef CLASSIC_EMU_H
|
||||||
#define CLASSIC_EMU_H
|
#define CLASSIC_EMU_H
|
||||||
|
|
||||||
|
|
|
@ -1,15 +1,12 @@
|
||||||
// File_Extractor 0.4.0. http://www.slack.net/~ant/
|
// 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 "Data_Reader.h"
|
||||||
|
|
||||||
#include "blargg_endian.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
|
/* 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
|
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
|
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;
|
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 Remaining_Reader::read_first( void* out, long count )
|
||||||
{
|
{
|
||||||
long first = long(header_end - header);
|
long first = header_end - header;
|
||||||
if ( first )
|
if ( first )
|
||||||
{
|
{
|
||||||
if ( first > count )
|
if ( first > count )
|
||||||
|
@ -213,7 +210,7 @@ long Std_File_Reader::size() const
|
||||||
|
|
||||||
long Std_File_Reader::read_avail( void* p, long s )
|
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 )
|
blargg_err_t Std_File_Reader::read( void* p, long s )
|
||||||
|
|
|
@ -5,7 +5,6 @@
|
||||||
#define DATA_READER_H
|
#define DATA_READER_H
|
||||||
|
|
||||||
#include "blargg_common.h"
|
#include "blargg_common.h"
|
||||||
#include "gme.h"
|
|
||||||
|
|
||||||
// Supports reading and finding out how many bytes are remaining
|
// Supports reading and finding out how many bytes are remaining
|
||||||
class Data_Reader {
|
class Data_Reader {
|
||||||
|
@ -117,7 +116,7 @@ private:
|
||||||
// Invokes callback function to read data. Size of data must be specified in advance.
|
// Invokes callback function to read data. Size of data must be specified in advance.
|
||||||
class Callback_Reader : public Data_Reader {
|
class Callback_Reader : public Data_Reader {
|
||||||
public:
|
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 );
|
Callback_Reader( callback_t, long size, void* data = 0 );
|
||||||
public:
|
public:
|
||||||
long read_avail( void*, long );
|
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"
|
#include "Dual_Resampler.h"
|
||||||
|
|
||||||
|
@ -20,7 +20,13 @@ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
|
||||||
|
|
||||||
unsigned const resampler_extra = 256;
|
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() { }
|
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 );
|
assert( blip_buf.samples_avail() == pair_count );
|
||||||
|
|
||||||
resampler.write( new_count );
|
resampler.write( new_count );
|
||||||
|
|
||||||
long count = resampler.read( sample_buf.begin(), sample_buf_size );
|
long count = resampler.read( sample_buf.begin(), sample_buf_size );
|
||||||
assert( count == (long) sample_buf_size );
|
assert( count == (long) sample_buf_size );
|
||||||
|
|
||||||
mix_samples( blip_buf, out );
|
mix_samples( blip_buf, out );
|
||||||
blip_buf.remove_samples( pair_count );
|
blip_buf.remove_samples( pair_count );
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
// Combination of Fir_Resampler and Blip_Buffer mixing. Used by Sega FM emulators.
|
// 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
|
#ifndef DUAL_RESAMPLER_H
|
||||||
#define 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"
|
#include "Effects_Buffer.h"
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
// Multi-channel effects buffer with panning, echo and reverb
|
// 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
|
#ifndef EFFECTS_BUFFER_H
|
||||||
#define 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"
|
#include "Fir_Resampler.h"
|
||||||
|
|
||||||
|
@ -156,7 +156,7 @@ int Fir_Resampler_::input_needed( blargg_long output_count ) const
|
||||||
output_count -= 2;
|
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 )
|
if ( input_extra < 0 )
|
||||||
input_extra = 0;
|
input_extra = 0;
|
||||||
return input_extra;
|
return input_extra;
|
||||||
|
@ -186,7 +186,7 @@ int Fir_Resampler_::avail_( blargg_long input_count ) const
|
||||||
|
|
||||||
int Fir_Resampler_::skip_input( long count )
|
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;
|
int max_count = remain - width_ * stereo;
|
||||||
if ( count > max_count )
|
if ( count > max_count )
|
||||||
count = max_count;
|
count = max_count;
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
// Finite impulse response (FIR) resampler with adjustable FIR size
|
// 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
|
#ifndef FIR_RESAMPLER_H
|
||||||
#define FIR_RESAMPLER_H
|
#define FIR_RESAMPLER_H
|
||||||
|
|
||||||
|
@ -31,7 +31,7 @@ public:
|
||||||
void clear();
|
void clear();
|
||||||
|
|
||||||
// Number of input samples that can be written
|
// 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
|
// Pointer to place to write input samples
|
||||||
sample_t* buffer() { return write_pos; }
|
sample_t* buffer() { return write_pos; }
|
||||||
|
@ -40,7 +40,7 @@ public:
|
||||||
void write( long count );
|
void write( long count );
|
||||||
|
|
||||||
// Number of input samples in buffer
|
// 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.
|
// Skip 'count' input samples. Returns number of samples actually skipped.
|
||||||
int skip_input( long count );
|
int skip_input( long count );
|
||||||
|
@ -51,7 +51,7 @@ public:
|
||||||
int input_needed( blargg_long count ) const;
|
int input_needed( blargg_long count ) const;
|
||||||
|
|
||||||
// Number of output samples available
|
// 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:
|
public:
|
||||||
~Fir_Resampler_();
|
~Fir_Resampler_();
|
||||||
|
@ -161,11 +161,11 @@ int Fir_Resampler<width>::read( sample_t* out_begin, blargg_long count )
|
||||||
|
|
||||||
imp_phase = res - remain;
|
imp_phase = res - remain;
|
||||||
|
|
||||||
int left = int(write_pos - in);
|
int left = write_pos - in;
|
||||||
write_pos = &buf [left];
|
write_pos = &buf [left];
|
||||||
memmove( buf.begin(), in, left * sizeof *in );
|
memmove( buf.begin(), in, left * sizeof *in );
|
||||||
|
|
||||||
return int(out - out_begin);
|
return out - out_begin;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -271,7 +271,7 @@ void Gb_Apu::write_register( blip_time_t time, unsigned addr, int data )
|
||||||
}
|
}
|
||||||
else
|
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"
|
#include "Gb_Cpu.h"
|
||||||
|
|
||||||
|
@ -89,11 +89,6 @@ unsigned const n_flag = 0x40;
|
||||||
unsigned const h_flag = 0x20;
|
unsigned const h_flag = 0x20;
|
||||||
unsigned const c_flag = 0x10;
|
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 )
|
bool Gb_Cpu::run( blargg_long cycle_count )
|
||||||
{
|
{
|
||||||
state_.remain = blargg_ulong (cycle_count + clocks_per_instr) / clocks_per_instr;
|
state_.remain = blargg_ulong (cycle_count + clocks_per_instr) / clocks_per_instr;
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
// Nintendo Game Boy CPU emulator
|
// Nintendo Game Boy CPU emulator
|
||||||
// Treats every instruction as taking 4 cycles
|
// Treats every instruction as taking 4 cycles
|
||||||
|
|
||||||
// Game_Music_Emu 0.5.2
|
// Game_Music_Emu 0.6.0
|
||||||
#ifndef GB_CPU_H
|
#ifndef GB_CPU_H
|
||||||
#define 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"
|
#include "Gbs_Emu.h"
|
||||||
|
|
||||||
|
@ -18,8 +18,10 @@ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
|
||||||
|
|
||||||
#include "blargg_source.h"
|
#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::handheld_eq =
|
||||||
Gbs_Emu::equalizer_t const Gbs_Emu::headphones_eq = { 0.0, 300, 0, 0, 0, 0, 0, 0, 0, 0 };
|
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()
|
Gbs_Emu::Gbs_Emu()
|
||||||
{
|
{
|
||||||
|
@ -39,8 +41,7 @@ Gbs_Emu::Gbs_Emu()
|
||||||
set_max_initial_silence( 21 );
|
set_max_initial_silence( 21 );
|
||||||
set_gain( 1.2 );
|
set_gain( 1.2 );
|
||||||
|
|
||||||
static equalizer_t const eq = { -1.0, 120, 0, 0, 0, 0, 0, 0, 0, 0 };
|
set_equalizer( make_equalizer( -1.0, 120 ) );
|
||||||
set_equalizer( eq );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Gbs_Emu::~Gbs_Emu() { }
|
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
|
// TODO: what is the correct behavior? Current Game & Watch Gallery
|
||||||
// rip requires that this have no effect or set to bank 1.
|
// 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;
|
return;
|
||||||
//n = 1;
|
//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++ )
|
for ( int i = 0; i < (int) sizeof sound_data; i++ )
|
||||||
apu.write_register( 0, i + apu.start_addr, 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 );
|
unsigned load_addr = get_le16( header_.load_addr );
|
||||||
cpu::rst_base = load_addr;
|
|
||||||
rom.set_addr( 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( ram_addr, 0x10000 - ram_addr, ram );
|
||||||
cpu::map_code( 0, bank_size, rom.at_addr( 0 ) );
|
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 )
|
else if ( cpu::r.pc > 0xFFFF )
|
||||||
{
|
{
|
||||||
dprintf( "PC wrapped around\n" );
|
debug_printf( "PC wrapped around\n" );
|
||||||
cpu::r.pc &= 0xFFFF;
|
cpu::r.pc &= 0xFFFF;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
set_warning( "Emulation error (illegal/unsupported instruction)" );
|
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 );
|
(int) *cpu::get_code( cpu::r.pc ), (int) cpu::r.pc );
|
||||||
cpu::r.pc = (cpu::r.pc + 1) & 0xFFFF;
|
cpu::r.pc = (cpu::r.pc + 1) & 0xFFFF;
|
||||||
cpu_time += 6;
|
cpu_time += 6;
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
// Nintendo Game Boy GBS music file emulator
|
// Nintendo Game Boy GBS music file emulator
|
||||||
|
|
||||||
// Game_Music_Emu 0.5.2
|
// Game_Music_Emu 0.6.0
|
||||||
#ifndef GBS_EMU_H
|
#ifndef GBS_EMU_H
|
||||||
#define 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"
|
#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 )
|
blargg_err_t Gme_File::load_( Data_Reader& in )
|
||||||
{
|
{
|
||||||
RETURN_ERR( file_data.resize( in.remain() ) );
|
RETURN_ERR( file_data.resize( in.remain() ) );
|
||||||
RETURN_ERR( in.read( file_data.begin(), (long)file_data.size() ) );
|
RETURN_ERR( in.read( file_data.begin(), file_data.size() ) );
|
||||||
return load_mem_( file_data.begin(), (long)file_data.size() );
|
return load_mem_( file_data.begin(), file_data.size() );
|
||||||
}
|
}
|
||||||
|
|
||||||
// public load functions call this at beginning
|
// public load functions call this at beginning
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
// Common interface to game music file loading and information
|
// 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
|
#ifndef GME_FILE_H
|
||||||
#define 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"
|
#include "Gym_Emu.h"
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
// Sega Genesis/Mega Drive GYM music file emulator
|
// Sega Genesis/Mega Drive GYM music file emulator
|
||||||
// Includes with PCM timing recovery to improve sample quality.
|
// 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
|
#ifndef GYM_EMU_H
|
||||||
#define 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"
|
#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;
|
unsigned noise_lfsr = this->noise_lfsr;
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
int new_dac = 0x1F & (unsigned)-(signed)(noise_lfsr >> 1 & 1);
|
int new_dac = 0x1F & -(noise_lfsr >> 1 & 1);
|
||||||
// Implemented using "Galios configuration"
|
// Implemented using "Galios configuration"
|
||||||
// TODO: find correct LFSR algorithm
|
// 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));
|
//noise_lfsr = (noise_lfsr >> 1) ^ (0x6000 & -(noise_lfsr & 1));
|
||||||
int delta = new_dac - dac;
|
int delta = new_dac - dac;
|
||||||
if ( delta )
|
if ( delta )
|
||||||
|
@ -158,7 +158,7 @@ void Hes_Osc::run_until( synth_t& synth_, blip_time_t end_time )
|
||||||
//period = 0x1000 * 2;
|
//period = 0x1000 * 2;
|
||||||
period = 1;
|
period = 1;
|
||||||
//if ( !(volume_0 | volume_1) )
|
//if ( !(volume_0 | volume_1) )
|
||||||
// dprintf( "Used period 0\n" );
|
// debug_printf( "Used period 0\n" );
|
||||||
}
|
}
|
||||||
|
|
||||||
// maintain phase when silent
|
// maintain phase when silent
|
||||||
|
@ -295,7 +295,7 @@ void Hes_Apu::write_data( blip_time_t time, int addr, int data )
|
||||||
|
|
||||||
case 0x809:
|
case 0x809:
|
||||||
if ( !(data & 0x80) && (data & 0x03) != 0 )
|
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
|
// 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
|
#ifndef HES_APU_H
|
||||||
#define 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"
|
#include "Hes_Cpu.h"
|
||||||
|
|
||||||
|
@ -148,7 +148,7 @@ loop:
|
||||||
/*
|
/*
|
||||||
static long count;
|
static long count;
|
||||||
if ( count == 1844 ) Debugger();
|
if ( count == 1844 ) Debugger();
|
||||||
if ( s.base != correct ) dprintf( "%ld\n", count );
|
if ( s.base != correct ) debug_printf( "%ld\n", count );
|
||||||
count++;
|
count++;
|
||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
|
@ -741,7 +741,7 @@ possibly_out_of_time:
|
||||||
ARITH_ADDR_MODES( 0x65 ) // ADC
|
ARITH_ADDR_MODES( 0x65 ) // ADC
|
||||||
adc_imm: {
|
adc_imm: {
|
||||||
if ( status & st_d )
|
if ( status & st_d )
|
||||||
dprintf( "Decimal mode not supported\n" );
|
debug_printf( "Decimal mode not supported\n" );
|
||||||
fint16 carry = c >> 8 & 1;
|
fint16 carry = c >> 8 & 1;
|
||||||
fint16 ov = (a ^ 0x80) + carry + (BOOST::int8_t) data; // sign-extend
|
fint16 ov = (a ^ 0x80) + carry + (BOOST::int8_t) data; // sign-extend
|
||||||
status &= ~st_v;
|
status &= ~st_v;
|
||||||
|
@ -1085,7 +1085,7 @@ possibly_out_of_time:
|
||||||
goto loop;
|
goto loop;
|
||||||
}
|
}
|
||||||
delayed_cli:
|
delayed_cli:
|
||||||
dprintf( "Delayed CLI not supported\n" ); // TODO: implement
|
debug_printf( "Delayed CLI not supported\n" ); // TODO: implement
|
||||||
goto loop;
|
goto loop;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1100,7 +1100,7 @@ possibly_out_of_time:
|
||||||
s_time += delta;
|
s_time += delta;
|
||||||
if ( s_time < 0 )
|
if ( s_time < 0 )
|
||||||
goto loop;
|
goto loop;
|
||||||
dprintf( "Delayed SEI not supported\n" ); // TODO: implement
|
debug_printf( "Delayed SEI not supported\n" ); // TODO: implement
|
||||||
goto loop;
|
goto loop;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1145,7 +1145,7 @@ possibly_out_of_time:
|
||||||
goto loop;
|
goto loop;
|
||||||
|
|
||||||
case 0x54: // CSL
|
case 0x54: // CSL
|
||||||
dprintf( "CSL not supported\n" );
|
debug_printf( "CSL not supported\n" );
|
||||||
illegal_encountered = true;
|
illegal_encountered = true;
|
||||||
goto loop;
|
goto loop;
|
||||||
|
|
||||||
|
@ -1154,7 +1154,7 @@ possibly_out_of_time:
|
||||||
|
|
||||||
case 0xF4: { // SET
|
case 0xF4: { // SET
|
||||||
//fuint16 operand = GET_MSB();
|
//fuint16 operand = GET_MSB();
|
||||||
dprintf( "SET not handled\n" );
|
debug_printf( "SET not handled\n" );
|
||||||
//switch ( data )
|
//switch ( data )
|
||||||
//{
|
//{
|
||||||
//}
|
//}
|
||||||
|
@ -1233,7 +1233,7 @@ possibly_out_of_time:
|
||||||
|
|
||||||
default:
|
default:
|
||||||
assert( (unsigned) opcode <= 0xFF );
|
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;
|
illegal_encountered = true;
|
||||||
goto loop;
|
goto loop;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
// PC Engine CPU emulator for use with HES music files
|
// 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
|
#ifndef HES_CPU_H
|
||||||
#define 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"
|
#include "Hes_Emu.h"
|
||||||
|
|
||||||
|
@ -273,12 +273,12 @@ void Hes_Emu::cpu_write_vdp( int addr, int data )
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
dprintf( "VDP not supported: $%02X <- $%02X\n", vdp.latch, data );
|
debug_printf( "VDP not supported: $%02X <- $%02X\n", vdp.latch, data );
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 3:
|
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;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -325,7 +325,7 @@ void Hes_Emu::cpu_write_( hes_addr_t addr, int data )
|
||||||
run_until( time );
|
run_until( time );
|
||||||
irq.disables = data;
|
irq.disables = data;
|
||||||
if ( (data & 0xF8) && (data & 0xF8) != 0xF8 ) // flag questionable values
|
if ( (data & 0xF8) && (data & 0xF8) != 0xF8 ) // flag questionable values
|
||||||
dprintf( "Int mask: $%02X\n", data );
|
debug_printf( "Int mask: $%02X\n", data );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x1403:
|
case 0x1403:
|
||||||
|
@ -344,7 +344,7 @@ void Hes_Emu::cpu_write_( hes_addr_t addr, int data )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
dprintf( "unmapped write $%04X <- $%02X\n", addr, data );
|
debug_printf( "unmapped write $%04X <- $%02X\n", addr, data );
|
||||||
return;
|
return;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
@ -368,14 +368,14 @@ int Hes_Emu::cpu_read_( hes_addr_t addr )
|
||||||
|
|
||||||
case 0x0002:
|
case 0x0002:
|
||||||
case 0x0003:
|
case 0x0003:
|
||||||
dprintf( "VDP read not supported: %d\n", addr );
|
debug_printf( "VDP read not supported: %d\n", addr );
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
case 0x0C01:
|
case 0x0C01:
|
||||||
//return timer.enabled; // TODO: remove?
|
//return timer.enabled; // TODO: remove?
|
||||||
case 0x0C00:
|
case 0x0C00:
|
||||||
run_until( time );
|
run_until( time );
|
||||||
dprintf( "Timer count read\n" );
|
debug_printf( "Timer count read\n" );
|
||||||
return (unsigned) (timer.count - 1) / timer_base;
|
return (unsigned) (timer.count - 1) / timer_base;
|
||||||
|
|
||||||
case 0x1402:
|
case 0x1402:
|
||||||
|
@ -396,7 +396,7 @@ int Hes_Emu::cpu_read_( hes_addr_t addr )
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
dprintf( "unmapped read $%04X\n", addr );
|
debug_printf( "unmapped read $%04X\n", addr );
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
// TurboGrafx-16/PC Engine HES music file emulator
|
// TurboGrafx-16/PC Engine HES music file emulator
|
||||||
|
|
||||||
// Game_Music_Emu 0.5.2
|
// Game_Music_Emu 0.6.0
|
||||||
#ifndef HES_EMU_H
|
#ifndef HES_EMU_H
|
||||||
#define 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
|
Last validated with zexall 2006.11.14 2:19 PM
|
||||||
|
@ -841,6 +841,7 @@ possibly_out_of_time:
|
||||||
case 0xCB:
|
case 0xCB:
|
||||||
unsigned data2;
|
unsigned data2;
|
||||||
data2 = instr [1];
|
data2 = instr [1];
|
||||||
|
(void) data2; // TODO is this the same as data in all cases?
|
||||||
pc++;
|
pc++;
|
||||||
switch ( data )
|
switch ( data )
|
||||||
{
|
{
|
||||||
|
@ -1084,7 +1085,7 @@ possibly_out_of_time:
|
||||||
blargg_ulong sum = temp + (flags & C01);
|
blargg_ulong sum = temp + (flags & C01);
|
||||||
flags = ~data >> 2 & N02;
|
flags = ~data >> 2 & N02;
|
||||||
if ( flags )
|
if ( flags )
|
||||||
sum = (blargg_ulong)-(blargg_long)sum;
|
sum = -sum;
|
||||||
sum += rp.hl;
|
sum += rp.hl;
|
||||||
temp ^= rp.hl;
|
temp ^= rp.hl;
|
||||||
temp ^= sum;
|
temp ^= sum;
|
||||||
|
@ -1289,7 +1290,7 @@ possibly_out_of_time:
|
||||||
|
|
||||||
case 0x4F: // LD R,A
|
case 0x4F: // LD R,A
|
||||||
SET_R( rg.a );
|
SET_R( rg.a );
|
||||||
dprintf( "LD R,A not supported\n" );
|
debug_printf( "LD R,A not supported\n" );
|
||||||
warning = true;
|
warning = true;
|
||||||
goto loop;
|
goto loop;
|
||||||
|
|
||||||
|
@ -1299,7 +1300,7 @@ possibly_out_of_time:
|
||||||
|
|
||||||
case 0x5F: // LD A,R
|
case 0x5F: // LD A,R
|
||||||
rg.a = GET_R();
|
rg.a = GET_R();
|
||||||
dprintf( "LD A,R not supported\n" );
|
debug_printf( "LD A,R not supported\n" );
|
||||||
warning = true;
|
warning = true;
|
||||||
ld_ai_common:
|
ld_ai_common:
|
||||||
flags = (flags & C01) | SZ28( rg.a ) | (r.iff2 << 2 & V04);
|
flags = (flags & C01) | SZ28( rg.a ) | (r.iff2 << 2 & V04);
|
||||||
|
@ -1322,7 +1323,7 @@ possibly_out_of_time:
|
||||||
goto loop;
|
goto loop;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
dprintf( "Opcode $ED $%02X not supported\n", data );
|
debug_printf( "Opcode $ED $%02X not supported\n", data );
|
||||||
warning = true;
|
warning = true;
|
||||||
goto loop;
|
goto loop;
|
||||||
}
|
}
|
||||||
|
@ -1583,7 +1584,7 @@ possibly_out_of_time:
|
||||||
}
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
dprintf( "Opcode $%02X $CB $%02X not supported\n", opcode, data2 );
|
debug_printf( "Opcode $%02X $CB $%02X not supported\n", opcode, data2 );
|
||||||
warning = true;
|
warning = true;
|
||||||
goto loop;
|
goto loop;
|
||||||
}
|
}
|
||||||
|
@ -1672,7 +1673,7 @@ possibly_out_of_time:
|
||||||
}
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
dprintf( "Unnecessary DD/FD prefix encountered\n" );
|
debug_printf( "Unnecessary DD/FD prefix encountered\n" );
|
||||||
warning = true;
|
warning = true;
|
||||||
pc--;
|
pc--;
|
||||||
goto loop;
|
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 );
|
assert( false );
|
||||||
|
|
||||||
hit_idle_addr:
|
hit_idle_addr:
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
// Z80 CPU emulator
|
// Z80 CPU emulator
|
||||||
|
|
||||||
// Game_Music_Emu 0.5.2
|
// Game_Music_Emu 0.6.0
|
||||||
#ifndef KSS_CPU_H
|
#ifndef KSS_CPU_H
|
||||||
#define 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"
|
#include "Kss_Emu.h"
|
||||||
|
|
||||||
|
@ -230,9 +230,9 @@ blargg_err_t Kss_Emu::start_track_( int track )
|
||||||
bank_count = max_banks;
|
bank_count = max_banks;
|
||||||
set_warning( "Bank data missing" );
|
set_warning( "Bank data missing" );
|
||||||
}
|
}
|
||||||
//dprintf( "load_size : $%X\n", load_size );
|
//debug_printf( "load_size : $%X\n", load_size );
|
||||||
//dprintf( "bank_size : $%X\n", bank_size );
|
//debug_printf( "bank_size : $%X\n", bank_size );
|
||||||
//dprintf( "bank_count: %d (%d claimed)\n", bank_count, header_.bank_mode & 0x7F );
|
//debug_printf( "bank_count: %d (%d claimed)\n", bank_count, header_.bank_mode & 0x7F );
|
||||||
|
|
||||||
ram [idle_addr] = 0xFF;
|
ram [idle_addr] = 0xFF;
|
||||||
cpu::reset( unmapped_write, unmapped_read );
|
cpu::reset( unmapped_write, unmapped_read );
|
||||||
|
@ -301,7 +301,7 @@ void Kss_Emu::cpu_write( unsigned addr, int data )
|
||||||
return;
|
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 )
|
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
|
#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 )
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
// MSX computer KSS music file emulator
|
// MSX computer KSS music file emulator
|
||||||
|
|
||||||
// Game_Music_Emu 0.5.2
|
// Game_Music_Emu 0.6.0
|
||||||
#ifndef KSS_EMU_H
|
#ifndef KSS_EMU_H
|
||||||
#define KSS_EMU_H
|
#define KSS_EMU_H
|
||||||
|
|
||||||
|
@ -68,7 +68,6 @@ private:
|
||||||
void update_gain();
|
void update_gain();
|
||||||
|
|
||||||
unsigned scc_enabled; // 0 or 0xC000
|
unsigned scc_enabled; // 0 or 0xC000
|
||||||
byte const* bank_data;
|
|
||||||
int bank_count;
|
int bank_count;
|
||||||
void set_bank( int logical, int physical );
|
void set_bank( int logical, int physical );
|
||||||
blargg_long bank_size() const { return (16 * 1024L) >> (header_.bank_mode >> 7 & 1); }
|
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"
|
#include "Kss_Scc_Apu.h"
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
// Konami SCC sound chip emulator
|
// Konami SCC sound chip emulator
|
||||||
|
|
||||||
// Game_Music_Emu 0.5.2
|
// Game_Music_Emu 0.6.0
|
||||||
#ifndef KSS_SCC_APU_H
|
#ifndef KSS_SCC_APU_H
|
||||||
#define KSS_SCC_APU_H
|
#define KSS_SCC_APU_H
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,4 @@
|
||||||
// Game_Music_Emu 0.5.2. http://www.slack.net/~ant/
|
// Game_Music_Emu 0.6.0. http://www.slack.net/~ant/
|
||||||
|
|
||||||
#define IN_GME 1
|
|
||||||
|
|
||||||
#include "M3u_Playlist.h"
|
#include "M3u_Playlist.h"
|
||||||
#include "Music_Emu.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 ) ); }
|
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 );
|
Mem_File_Reader in( data, size );
|
||||||
return me->load_m3u( in );
|
return me->load_m3u( in );
|
||||||
|
@ -409,7 +407,7 @@ blargg_err_t M3u_Playlist::parse()
|
||||||
blargg_err_t M3u_Playlist::load( Data_Reader& in )
|
blargg_err_t M3u_Playlist::load( Data_Reader& in )
|
||||||
{
|
{
|
||||||
RETURN_ERR( data.resize( in.remain() + 1 ) );
|
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();
|
return parse();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
// M3U playlist file parser, with support for subtrack information
|
// 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
|
#ifndef M3U_PLAYLIST_H
|
||||||
#define M3U_PLAYLIST_H
|
#define M3U_PLAYLIST_H
|
||||||
|
|
||||||
|
@ -43,7 +43,7 @@ public:
|
||||||
int repeat; // count
|
int repeat; // count
|
||||||
};
|
};
|
||||||
entry_t const& operator [] ( int i ) const { return entries [i]; }
|
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();
|
void clear();
|
||||||
|
|
||||||
|
|
|
@ -114,7 +114,7 @@ long Stereo_Buffer::read_samples( blip_sample_t* out, long count )
|
||||||
if ( count )
|
if ( count )
|
||||||
{
|
{
|
||||||
int bufs_used = stereo_added | was_stereo;
|
int bufs_used = stereo_added | was_stereo;
|
||||||
//dprintf( "%X\n", bufs_used );
|
//debug_printf( "%X\n", bufs_used );
|
||||||
if ( bufs_used <= 1 )
|
if ( bufs_used <= 1 )
|
||||||
{
|
{
|
||||||
mix_mono( out, count );
|
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"
|
#include "Music_Emu.h"
|
||||||
|
|
||||||
|
@ -24,7 +24,8 @@ int const silence_threshold = 0x10;
|
||||||
long const fade_block_size = 512;
|
long const fade_block_size = 512;
|
||||||
int const fade_shift = 8; // fade ends with gain at 1.0 / (1 << fade_shift)
|
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()
|
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;
|
Music_Emu::sample_t* p = begin + size;
|
||||||
while ( (unsigned) (*--p + silence_threshold / 2) <= (unsigned) silence_threshold ) { }
|
while ( (unsigned) (*--p + silence_threshold / 2) <= (unsigned) silence_threshold ) { }
|
||||||
*begin = first;
|
*begin = first;
|
||||||
return size - long(p - begin);
|
return size - (p - begin);
|
||||||
}
|
}
|
||||||
|
|
||||||
// fill internal buffer and check it for silence
|
// 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 );
|
assert( emu_time >= out_time );
|
||||||
|
|
||||||
// prints nifty graph of how far ahead we are when searching for silence
|
// 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;
|
long pos = 0;
|
||||||
if ( silence_count )
|
if ( silence_count )
|
||||||
{
|
{
|
||||||
// during a run of silence, run emulator at >=2x speed so it gets ahead
|
// 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;
|
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_buf();
|
||||||
|
|
||||||
// fill with silence
|
// 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_::pre_load() { Gme_File::pre_load(); } // skip Music_Emu
|
||||||
void Gme_Info_::post_load_() { Gme_File::post_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_::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_::mute_voices_( int ) { check( false ); }
|
||||||
void Gme_Info_::set_tempo_( double ) { }
|
void Gme_Info_::set_tempo_( double ) { }
|
||||||
blargg_err_t Gme_Info_::start_track_( int ) { return "Use full emulator for playback"; }
|
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
|
// Common interface to game music file emulators
|
||||||
|
|
||||||
// Game_Music_Emu 0.5.2
|
// Game_Music_Emu 0.6.0
|
||||||
#ifndef MUSIC_EMU_H
|
#ifndef MUSIC_EMU_H
|
||||||
#define 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().
|
// on others this has no effect. Should be called only once *before* set_sample_rate().
|
||||||
virtual void set_buffer( Multi_Buffer* ) { }
|
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)
|
// Sound equalization (treble/bass)
|
||||||
|
|
||||||
// Frequency equalizer parameters (see gme.txt)
|
// Frequency equalizer parameters (see gme.txt)
|
||||||
|
@ -93,6 +97,14 @@ public:
|
||||||
|
|
||||||
// Set frequency equalizer parameters
|
// Set frequency equalizer parameters
|
||||||
void set_equalizer( equalizer_t const& );
|
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
|
// Equalizer settings for TV speaker
|
||||||
static equalizer_t const tv_eq;
|
static equalizer_t const tv_eq;
|
||||||
|
@ -111,7 +123,8 @@ protected:
|
||||||
void remute_voices();
|
void remute_voices();
|
||||||
|
|
||||||
virtual blargg_err_t set_sample_rate_( long sample_rate ) = 0;
|
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 mute_voices_( int mask ) = 0;
|
||||||
virtual void set_tempo_( double ) = 0;
|
virtual void set_tempo_( double ) = 0;
|
||||||
virtual blargg_err_t start_track_( int ) = 0; // tempo is set before this
|
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 );
|
void emu_play( long count, sample_t* out );
|
||||||
|
|
||||||
Multi_Buffer* effects_buffer;
|
Multi_Buffer* effects_buffer;
|
||||||
friend GMEDLL Music_Emu* GMEAPI gme_new_emu( gme_type_t, int );
|
friend Music_Emu* gme_new_emu( gme_type_t, int );
|
||||||
friend GMEDLL void GMEAPI gme_set_stereo_depth( Music_Emu*, double );
|
friend void gme_set_stereo_depth( Music_Emu*, double );
|
||||||
};
|
};
|
||||||
|
|
||||||
// base class for info-only derivations
|
// 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 blargg_err_t set_sample_rate_( long sample_rate );
|
||||||
virtual void set_equalizer_( equalizer_t const& );
|
virtual void set_equalizer_( equalizer_t const& );
|
||||||
|
virtual void enable_accuracy_( bool );
|
||||||
virtual void mute_voices_( int mask );
|
virtual void mute_voices_( int mask );
|
||||||
virtual void set_tempo_( double );
|
virtual void set_tempo_( double );
|
||||||
virtual blargg_err_t start_track_( int );
|
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 bool Music_Emu::track_ended() const { return track_ended_; }
|
||||||
inline const Music_Emu::equalizer_t& Music_Emu::equalizer() const { return equalizer_; }
|
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::set_tempo_( double t ) { tempo_ = t; }
|
||||||
inline void Music_Emu::remute_voices() { mute_voices( mute_mask_ ); }
|
inline void Music_Emu::remute_voices() { mute_voices( mute_mask_ ); }
|
||||||
inline void Music_Emu::ignore_silence( bool b ) { ignore_silence_ = b; }
|
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();
|
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;
|
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"
|
#include "Nes_Cpu.h"
|
||||||
|
|
||||||
|
@ -921,7 +921,7 @@ imm##op:
|
||||||
goto loop;
|
goto loop;
|
||||||
status &= ~st_i;
|
status &= ~st_i;
|
||||||
handle_cli: {
|
handle_cli: {
|
||||||
//dprintf( "CLI at %d\n", TIME );
|
//debug_printf( "CLI at %d\n", TIME );
|
||||||
this->r.status = status; // update externally-visible I flag
|
this->r.status = status; // update externally-visible I flag
|
||||||
blargg_long delta = s.base - irq_time_;
|
blargg_long delta = s.base - irq_time_;
|
||||||
if ( delta <= 0 )
|
if ( delta <= 0 )
|
||||||
|
@ -944,7 +944,7 @@ imm##op:
|
||||||
|
|
||||||
// TODO: implement
|
// TODO: implement
|
||||||
delayed_cli:
|
delayed_cli:
|
||||||
dprintf( "Delayed CLI not emulated\n" );
|
debug_printf( "Delayed CLI not emulated\n" );
|
||||||
goto loop;
|
goto loop;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -960,7 +960,7 @@ imm##op:
|
||||||
if ( s_time < 0 )
|
if ( s_time < 0 )
|
||||||
goto loop;
|
goto loop;
|
||||||
|
|
||||||
dprintf( "Delayed SEI not emulated\n" );
|
debug_printf( "Delayed SEI not emulated\n" );
|
||||||
goto loop;
|
goto loop;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
// NES 6502 CPU emulator
|
// NES 6502 CPU emulator
|
||||||
|
|
||||||
// Game_Music_Emu 0.5.2
|
// Game_Music_Emu 0.6.0
|
||||||
#ifndef NES_CPU_H
|
#ifndef NES_CPU_H
|
||||||
#define 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"
|
#include "Nes_Fme7_Apu.h"
|
||||||
|
|
||||||
|
@ -56,7 +56,7 @@ void Nes_Fme7_Apu::run_until( blip_time_t end_time )
|
||||||
// check for unsupported mode
|
// check for unsupported mode
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
if ( (mode & 011) <= 001 && vol_mode & 0x1F )
|
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 );
|
mode, vol_mode & 0x1F );
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
// Sunsoft FME-7 sound emulator
|
// Sunsoft FME-7 sound emulator
|
||||||
|
|
||||||
// Game_Music_Emu 0.5.2
|
// Game_Music_Emu 0.6.0
|
||||||
#ifndef NES_FME7_APU_H
|
#ifndef NES_FME7_APU_H
|
||||||
#define 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 )
|
if ( (unsigned) latch >= reg_count )
|
||||||
{
|
{
|
||||||
#ifdef dprintf
|
#ifdef debug_printf
|
||||||
dprintf( "FME7 write to %02X (past end of sound registers)\n", (int) latch );
|
debug_printf( "FME7 write to %02X (past end of sound registers)\n", (int) latch );
|
||||||
#endif
|
#endif
|
||||||
return;
|
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"
|
#include "Nsf_Emu.h"
|
||||||
|
|
||||||
|
@ -31,8 +31,10 @@ int const fme7_flag = 0x20;
|
||||||
|
|
||||||
long const clock_divisor = 12;
|
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::nes_eq =
|
||||||
Nsf_Emu::equalizer_t const Nsf_Emu::famicom_eq = { -15.0, 80, 0, 0, 0, 0, 0, 0, 0, 0 };
|
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 )
|
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?
|
// memory mapper?
|
||||||
if ( addr == 0xFFF8 ) return;
|
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
|
#endif
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
// Nintendo NES/Famicom NSF music file emulator
|
// Nintendo NES/Famicom NSF music file emulator
|
||||||
|
|
||||||
// Game_Music_Emu 0.5.2
|
// Game_Music_Emu 0.6.0
|
||||||
#ifndef NSF_EMU_H
|
#ifndef NSF_EMU_H
|
||||||
#define NSF_EMU_H
|
#define NSF_EMU_H
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,4 @@
|
||||||
// Game_Music_Emu 0.5.2. http://www.slack.net/~ant/
|
// Game_Music_Emu 0.6.0. http://www.slack.net/~ant/
|
||||||
|
|
||||||
#define _CRT_SECURE_NO_WARNINGS
|
|
||||||
|
|
||||||
#include "Nsfe_Emu.h"
|
#include "Nsfe_Emu.h"
|
||||||
|
|
||||||
|
@ -37,7 +35,7 @@ inline void Nsfe_Info::unload()
|
||||||
void Nsfe_Info::disable_playlist( bool b )
|
void Nsfe_Info::disable_playlist( bool b )
|
||||||
{
|
{
|
||||||
playlist_disabled = b;
|
playlist_disabled = b;
|
||||||
info.track_count = (byte)playlist.size();
|
info.track_count = playlist.size();
|
||||||
if ( !info.track_count || playlist_disabled )
|
if ( !info.track_count || playlist_disabled )
|
||||||
info.track_count = actual_track_count_;
|
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 size = get_le32( block_header [0] );
|
||||||
blargg_long tag = get_le32( block_header [1] );
|
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 )
|
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<char> chars;
|
||||||
blargg_vector<const char*> strs;
|
blargg_vector<const char*> strs;
|
||||||
RETURN_ERR( read_strs( in, size, chars, strs ) );
|
RETURN_ERR( read_strs( in, size, chars, strs ) );
|
||||||
int n = (int)strs.size();
|
int n = strs.size();
|
||||||
|
|
||||||
if ( n > 3 )
|
if ( n > 3 )
|
||||||
copy_str( strs [3], info.dumper, sizeof info.dumper );
|
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'):
|
case BLARGG_4CHAR('e','m','i','t'):
|
||||||
RETURN_ERR( track_times.resize( size / 4 ) );
|
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;
|
break;
|
||||||
|
|
||||||
case BLARGG_4CHAR('l','b','l','t'):
|
case BLARGG_4CHAR('l','b','l','t'):
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
// Nintendo NES/Famicom NSFE music file emulator
|
// Nintendo NES/Famicom NSFE music file emulator
|
||||||
|
|
||||||
// Game_Music_Emu 0.5.2
|
// Game_Music_Emu 0.6.0
|
||||||
#ifndef NSFE_EMU_H
|
#ifndef NSFE_EMU_H
|
||||||
#define 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"
|
#include "Sap_Apu.h"
|
||||||
|
|
||||||
|
@ -30,7 +30,7 @@ static void gen_poly( blargg_ulong mask, int count, byte* out )
|
||||||
{
|
{
|
||||||
// implemented using "Galios configuration"
|
// implemented using "Galios configuration"
|
||||||
bits |= (n & 1) << b;
|
bits |= (n & 1) << b;
|
||||||
n = (n >> 1) ^ (mask & (blargg_ulong)-(blargg_long)(n & 1));
|
n = (n >> 1) ^ (mask & -(n & 1));
|
||||||
}
|
}
|
||||||
while ( b++ < 7 );
|
while ( b++ < 7 );
|
||||||
*out++ = bits;
|
*out++ = bits;
|
||||||
|
@ -66,7 +66,7 @@ Sap_Apu_Impl::Sap_Apu_Impl()
|
||||||
blargg_ulong rev = n & 1;
|
blargg_ulong rev = n & 1;
|
||||||
for ( int i = 1; i < poly5_len; i++ )
|
for ( int i = 1; i < poly5_len; i++ )
|
||||||
rev |= (n >> i & 1) << (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;
|
period = (period - 6) * divider;
|
||||||
|
|
||||||
if ( (osc [-1].regs [1] & 0x1F) > 0x10 )
|
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;
|
osc->period = period;
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
// Atari POKEY sound chip emulator
|
// Atari POKEY sound chip emulator
|
||||||
|
|
||||||
// Game_Music_Emu 0.5.2
|
// Game_Music_Emu 0.6.0
|
||||||
#ifndef SAP_APU_H
|
#ifndef SAP_APU_H
|
||||||
#define 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"
|
#include "Sap_Cpu.h"
|
||||||
|
|
||||||
|
@ -889,7 +889,7 @@ imm##op:
|
||||||
goto loop;
|
goto loop;
|
||||||
}
|
}
|
||||||
delayed_cli:
|
delayed_cli:
|
||||||
dprintf( "Delayed CLI not emulated\n" );
|
debug_printf( "Delayed CLI not emulated\n" );
|
||||||
goto loop;
|
goto loop;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -904,7 +904,7 @@ imm##op:
|
||||||
s_time += delta;
|
s_time += delta;
|
||||||
if ( s_time < 0 )
|
if ( s_time < 0 )
|
||||||
goto loop;
|
goto loop;
|
||||||
dprintf( "Delayed SEI not emulated\n" );
|
debug_printf( "Delayed SEI not emulated\n" );
|
||||||
goto loop;
|
goto loop;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -945,7 +945,7 @@ handle_brk:
|
||||||
goto idle_done;
|
goto idle_done;
|
||||||
pc++;
|
pc++;
|
||||||
result_ = 4;
|
result_ = 4;
|
||||||
dprintf( "BRK executed\n" );
|
debug_printf( "BRK executed\n" );
|
||||||
|
|
||||||
interrupt:
|
interrupt:
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
// Atari 6502 CPU emulator
|
// Atari 6502 CPU emulator
|
||||||
|
|
||||||
// Game_Music_Emu 0.5.2
|
// Game_Music_Emu 0.6.0
|
||||||
#ifndef SAP_CPU_H
|
#ifndef SAP_CPU_H
|
||||||
#define 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"
|
#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;
|
char const* tag = (char const*) in;
|
||||||
while ( in < line_end && *in > ' ' )
|
while ( in < line_end && *in > ' ' )
|
||||||
in++;
|
in++;
|
||||||
int tag_len = int((char const*) in - tag);
|
int tag_len = (char const*) in - tag;
|
||||||
|
|
||||||
while ( in < line_end && *in <= ' ' ) in++;
|
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_warning( info.warning );
|
||||||
set_track_count( info.track_count );
|
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() );
|
apu_impl.volume( gain() );
|
||||||
|
|
||||||
return setup_buffer( 1773447 );
|
return setup_buffer( 1773447 );
|
||||||
|
@ -315,8 +315,8 @@ inline void Sap_Emu::call_init( int track )
|
||||||
|
|
||||||
case 'C':
|
case 'C':
|
||||||
r.a = 0x70;
|
r.a = 0x70;
|
||||||
r.x = (BOOST::uint8_t)(info.music_addr&0xFF);
|
r.x = info.music_addr&0xFF;
|
||||||
r.y = (BOOST::uint8_t)(info.music_addr >> 8);
|
r.y = info.music_addr >> 8;
|
||||||
run_routine( info.play_addr + 3 );
|
run_routine( info.play_addr + 3 );
|
||||||
r.a = 0;
|
r.a = 0;
|
||||||
r.x = track;
|
r.x = track;
|
||||||
|
@ -336,7 +336,7 @@ blargg_err_t Sap_Emu::start_track_( int track )
|
||||||
{
|
{
|
||||||
unsigned start = get_le16( in );
|
unsigned start = get_le16( in );
|
||||||
unsigned end = get_le16( in + 2 );
|
unsigned end = get_le16( in + 2 );
|
||||||
//dprintf( "Block $%04X-$%04X\n", start, end );
|
//debug_printf( "Block $%04X-$%04X\n", start, end );
|
||||||
in += 4;
|
in += 4;
|
||||||
if ( end < start )
|
if ( end < start )
|
||||||
{
|
{
|
||||||
|
@ -390,7 +390,7 @@ void Sap_Emu::cpu_write_( sap_addr_t addr, int data )
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( (addr & ~0x0010) != 0xD20F || data != 0x03 )
|
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()
|
inline void Sap_Emu::call_play()
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
// Atari XL/XE SAP music file emulator
|
// Atari XL/XE SAP music file emulator
|
||||||
|
|
||||||
// Game_Music_Emu 0.5.2
|
// Game_Music_Emu 0.6.0
|
||||||
#ifndef SAP_EMU_H
|
#ifndef SAP_EMU_H
|
||||||
#define 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
|
do
|
||||||
{
|
{
|
||||||
int changed = shifter + 1;
|
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
|
if ( changed & 2 ) // true if bits 0 and 1 differ
|
||||||
{
|
{
|
||||||
delta = -delta;
|
delta = -delta;
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
// SPC emulation support: init, sample buffering, reset, SPC loading
|
// 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"
|
#include "Snes_Spc.h"
|
||||||
|
|
||||||
|
@ -303,7 +303,7 @@ void Snes_Spc::set_output( sample_t* out, int size )
|
||||||
assert( out <= out_end );
|
assert( out <= out_end );
|
||||||
}
|
}
|
||||||
|
|
||||||
dsp.set_output( out, int(out_end - out) );
|
dsp.set_output( out, out_end - out );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
// SNES SPC-700 APU emulator
|
// SNES SPC-700 APU emulator
|
||||||
|
|
||||||
// snes_spc 0.9.0
|
// Game_Music_Emu 0.6.0
|
||||||
#ifndef SNES_SPC_H
|
#ifndef SNES_SPC_H
|
||||||
#define SNES_SPC_H
|
#define SNES_SPC_H
|
||||||
|
|
||||||
|
@ -66,10 +66,7 @@ public:
|
||||||
// Sets tempo, where tempo_unit = normal, tempo_unit / 2 = half speed, etc.
|
// Sets tempo, where tempo_unit = normal, tempo_unit / 2 = half speed, etc.
|
||||||
enum { tempo_unit = 0x100 };
|
enum { tempo_unit = 0x100 };
|
||||||
void set_tempo( int );
|
void set_tempo( int );
|
||||||
|
|
||||||
enum { gain_unit = Spc_Dsp::gain_unit };
|
|
||||||
void set_gain( int gain );
|
|
||||||
|
|
||||||
// SPC music files
|
// SPC music files
|
||||||
|
|
||||||
// Loads SPC data into emulator
|
// Loads SPC data into emulator
|
||||||
|
@ -107,6 +104,22 @@ public:
|
||||||
bool check_kon();
|
bool check_kon();
|
||||||
#endif
|
#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:
|
public:
|
||||||
BLARGG_DISABLE_NOTHROW
|
BLARGG_DISABLE_NOTHROW
|
||||||
|
|
||||||
|
@ -146,15 +159,7 @@ private:
|
||||||
|
|
||||||
uint8_t smp_regs [2] [reg_count];
|
uint8_t smp_regs [2] [reg_count];
|
||||||
|
|
||||||
struct
|
regs_t cpu_regs;
|
||||||
{
|
|
||||||
int pc;
|
|
||||||
int a;
|
|
||||||
int x;
|
|
||||||
int y;
|
|
||||||
int psw;
|
|
||||||
int sp;
|
|
||||||
} cpu_regs;
|
|
||||||
|
|
||||||
rel_time_t dsp_time;
|
rel_time_t dsp_time;
|
||||||
time_t spc_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;
|
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::mute_voices( int mask ) { dsp.mute_voices( mask ); }
|
||||||
|
|
||||||
inline void Snes_Spc::disable_surround( bool disable ) { dsp.disable_surround( disable ); }
|
inline void Snes_Spc::disable_surround( bool disable ) { dsp.disable_surround( disable ); }
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
// Core SPC emulation: CPU, timers, SMP registers, memory
|
// 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"
|
#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 )
|
if ( REGS [r_dspaddr] <= 0x7F )
|
||||||
dsp.write( REGS [r_dspaddr], data );
|
dsp.write( REGS [r_dspaddr], data );
|
||||||
else if ( !SPC_MORE_ACCURACY )
|
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
|
#endif
|
||||||
|
|
||||||
// divided into multiple functions to keep rarely-used functionality separate
|
// Read/write handlers are divided into multiple functions to keep rarely-used
|
||||||
// so often-used functionality can be optimized better by compiler
|
// 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
|
// If write isn't preceded by read, data has this added to it
|
||||||
int const no_read_before_write = 0x2000;
|
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 ) &&
|
t->next_time == time + TIMER_MUL( t, 1 ) &&
|
||||||
((period - 1) | ~0x0F) & period )
|
((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,
|
// If the period is 3, 5, or 9, there's a probability this behavior won't occur,
|
||||||
// based on the previous period
|
// 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_t1out:
|
||||||
case r_t2out:
|
case r_t2out:
|
||||||
if ( !SPC_MORE_ACCURACY )
|
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 )
|
if ( data < no_read_before_write / 2 )
|
||||||
run_timer( &m.timers [addr - r_t0out], time - 1 )->counter = 0;
|
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:
|
case r_test:
|
||||||
if ( (uint8_t) data != 0x0A )
|
if ( (uint8_t) data != 0x0A )
|
||||||
dprintf( "SPC wrote to test register\n" );
|
debug_printf( "SPC wrote to test register\n" );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case r_control:
|
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
|
/* 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
|
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
|
#if SPC_MORE_ACCURACY
|
||||||
#define SUSPICIOUS_OPCODE( name ) ((void) 0)
|
#define SUSPICIOUS_OPCODE( name ) ((void) 0)
|
||||||
#else
|
#else
|
||||||
#define SUSPICIOUS_OPCODE( name ) dprintf( "SPC: suspicious opcode: " name "\n" )
|
#define SUSPICIOUS_OPCODE( name ) debug_printf( "SPC: suspicious opcode: " name "\n" )
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define CPU_READ( time, offset, addr )\
|
#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 READ_PROG16( addr ) GET_LE16( ram + (addr) )
|
||||||
|
|
||||||
#define SET_PC( n ) (pc = ram + (n))
|
#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_PC( pc ) (*(pc))
|
||||||
#define READ_PC16( pc ) GET_LE16( 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 SPC_NO_SP_WRAPAROUND 0
|
||||||
|
|
||||||
#define SET_SP( v ) (sp = ram + 0x101 + (v))
|
#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
|
#if SPC_NO_SP_WRAPAROUND
|
||||||
#define PUSH16( v ) (sp -= 2, SET_LE16( sp, v ))
|
#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
|
#else
|
||||||
#define PUSH16( data )\
|
#define PUSH16( data )\
|
||||||
{\
|
{\
|
||||||
int addr = int((sp -= 2) - ram);\
|
int addr = (sp -= 2) - ram;\
|
||||||
if ( addr > 0x100 )\
|
if ( addr > 0x100 )\
|
||||||
{\
|
{\
|
||||||
SET_LE16( sp, data );\
|
SET_LE16( sp, data );\
|
||||||
|
@ -242,7 +242,7 @@ loop:
|
||||||
BRANCH( (uint8_t) nz )
|
BRANCH( (uint8_t) nz )
|
||||||
|
|
||||||
case 0x3F:{// CALL
|
case 0x3F:{// CALL
|
||||||
int old_addr = int(GET_PC() + 2);
|
int old_addr = GET_PC() + 2;
|
||||||
SET_PC( READ_PC16( pc ) );
|
SET_PC( READ_PC16( pc ) );
|
||||||
PUSH16( old_addr );
|
PUSH16( old_addr );
|
||||||
goto loop;
|
goto loop;
|
||||||
|
@ -256,7 +256,7 @@ loop:
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
{
|
{
|
||||||
int addr = int(sp - ram);
|
int addr = sp - ram;
|
||||||
SET_PC( GET_LE16( sp ) );
|
SET_PC( GET_LE16( sp ) );
|
||||||
sp += 2;
|
sp += 2;
|
||||||
if ( addr < 0x1FF )
|
if ( addr < 0x1FF )
|
||||||
|
@ -1184,7 +1184,7 @@ loop:
|
||||||
{
|
{
|
||||||
addr &= 0xFFFF;
|
addr &= 0xFFFF;
|
||||||
SET_PC( addr );
|
SET_PC( addr );
|
||||||
dprintf( "SPC: PC wrapped around\n" );
|
debug_printf( "SPC: PC wrapped around\n" );
|
||||||
goto loop;
|
goto loop;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1205,7 +1205,7 @@ stop:
|
||||||
|
|
||||||
// Uncache registers
|
// Uncache registers
|
||||||
if ( GET_PC() >= 0x10000 )
|
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.pc = (uint16_t) GET_PC();
|
||||||
m.cpu_regs.sp = ( uint8_t) GET_SP();
|
m.cpu_regs.sp = ( uint8_t) GET_SP();
|
||||||
m.cpu_regs.a = ( uint8_t) a;
|
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"
|
#include "Spc_Dsp.h"
|
||||||
|
|
||||||
|
@ -155,7 +155,7 @@ inline void Spc_Dsp::init_counter()
|
||||||
// counters start out with this synchronization
|
// counters start out with this synchronization
|
||||||
m.counters [0] = 1;
|
m.counters [0] = 1;
|
||||||
m.counters [1] = 0;
|
m.counters [1] = 0;
|
||||||
m.counters [2] = -0x20;
|
m.counters [2] = -0x20u;
|
||||||
m.counters [3] = 0x0B;
|
m.counters [3] = 0x0B;
|
||||||
|
|
||||||
int n = 2;
|
int n = 2;
|
||||||
|
@ -606,8 +606,8 @@ skip_brr:
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sound out
|
// Sound out
|
||||||
int l = (((main_out_l * mvoll + echo_in_l * (int8_t) REG(evoll)) >> 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) * m.gain) >> 8;
|
int r = (main_out_r * mvolr + echo_in_r * (int8_t) REG(evolr)) >> 14;
|
||||||
|
|
||||||
CLAMP16( l );
|
CLAMP16( l );
|
||||||
CLAMP16( r );
|
CLAMP16( r );
|
||||||
|
@ -641,7 +641,6 @@ void Spc_Dsp::mute_voices( int mask )
|
||||||
void Spc_Dsp::init( void* ram_64k )
|
void Spc_Dsp::init( void* ram_64k )
|
||||||
{
|
{
|
||||||
m.ram = (uint8_t*) ram_64k;
|
m.ram = (uint8_t*) ram_64k;
|
||||||
set_gain( gain_unit );
|
|
||||||
mute_voices( 0 );
|
mute_voices( 0 );
|
||||||
disable_surround( false );
|
disable_surround( false );
|
||||||
set_output( 0, 0 );
|
set_output( 0, 0 );
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
// Fast SNES SPC-700 DSP emulator (about 3x speed of accurate one)
|
// 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
|
#ifndef SPC_DSP_H
|
||||||
#define SPC_DSP_H
|
#define SPC_DSP_H
|
||||||
|
|
||||||
#include "blargg_common.h"
|
#include "blargg_common.h"
|
||||||
|
|
||||||
class Spc_Dsp {
|
struct Spc_Dsp {
|
||||||
public:
|
public:
|
||||||
typedef BOOST::uint8_t uint8_t;
|
typedef BOOST::uint8_t uint8_t;
|
||||||
|
|
||||||
|
@ -51,10 +51,7 @@ public:
|
||||||
|
|
||||||
// If true, prevents channels and global volumes from being phase-negated
|
// If true, prevents channels and global volumes from being phase-negated
|
||||||
void disable_surround( bool disable = true );
|
void disable_surround( bool disable = true );
|
||||||
|
|
||||||
enum { gain_unit = 0x100 };
|
|
||||||
void set_gain( int gain );
|
|
||||||
|
|
||||||
// State
|
// State
|
||||||
|
|
||||||
// Resets DSP and uses supplied values to initialize registers
|
// Resets DSP and uses supplied values to initialize registers
|
||||||
|
@ -140,7 +137,6 @@ private:
|
||||||
// non-emulation state
|
// non-emulation state
|
||||||
uint8_t* ram; // 64K shared RAM between DSP and SMP
|
uint8_t* ram; // 64K shared RAM between DSP and SMP
|
||||||
int mute_mask;
|
int mute_mask;
|
||||||
int gain;
|
|
||||||
int surround_threshold;
|
int surround_threshold;
|
||||||
sample_t* out;
|
sample_t* out;
|
||||||
sample_t* out_end;
|
sample_t* out_end;
|
||||||
|
@ -158,7 +154,7 @@ private:
|
||||||
|
|
||||||
#include <assert.h>
|
#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
|
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 )
|
inline void Spc_Dsp::disable_surround( bool disable )
|
||||||
{
|
{
|
||||||
m.surround_threshold = disable ? 0 : -0x4000;
|
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"
|
#include "Spc_Emu.h"
|
||||||
|
|
||||||
|
@ -19,6 +19,8 @@ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
|
||||||
|
|
||||||
#include "blargg_source.h"
|
#include "blargg_source.h"
|
||||||
|
|
||||||
|
// TODO: support Spc_Filter's bass
|
||||||
|
|
||||||
Spc_Emu::Spc_Emu()
|
Spc_Emu::Spc_Emu()
|
||||||
{
|
{
|
||||||
set_type( gme_spc_type );
|
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;
|
byte const* in = begin + 8;
|
||||||
if ( end - in > info_size )
|
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;
|
end = in + info_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -114,7 +116,7 @@ static void get_spc_xid6( byte const* begin, long size, track_info_t* out )
|
||||||
default:
|
default:
|
||||||
if ( id < 0x01 || (id > 0x07 && id < 0x10) ||
|
if ( id < 0x01 || (id > 0x07 && id < 0x10) ||
|
||||||
(id > 0x14 && id < 0x30) || id > 0x36 )
|
(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;
|
break;
|
||||||
}
|
}
|
||||||
if ( field )
|
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
|
// ...but some files have no padding
|
||||||
in = unaligned;
|
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;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -226,14 +228,14 @@ struct Spc_File : Gme_Info_
|
||||||
{
|
{
|
||||||
RETURN_ERR( xid6.resize( xid6_size ) );
|
RETURN_ERR( xid6.resize( xid6_size ) );
|
||||||
RETURN_ERR( in.skip( xid6_offset - Spc_Emu::header_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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
blargg_err_t track_info_( track_info_t* out, int ) const
|
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;
|
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 };
|
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_;
|
gme_type_t const gme_spc_type = &gme_spc_type_;
|
||||||
|
|
||||||
|
|
||||||
// Setup
|
// Setup
|
||||||
|
|
||||||
blargg_err_t Spc_Emu::set_sample_rate_( long sample_rate )
|
blargg_err_t Spc_Emu::set_sample_rate_( long sample_rate )
|
||||||
{
|
{
|
||||||
RETURN_ERR( apu.init() );
|
RETURN_ERR( apu.init() );
|
||||||
apu.set_gain( (int) (gain() * Snes_Spc::gain_unit) );
|
enable_accuracy( false );
|
||||||
if ( sample_rate != native_sample_rate )
|
if ( sample_rate != native_sample_rate )
|
||||||
{
|
{
|
||||||
RETURN_ERR( resampler.buffer_size( native_sample_rate / 20 * 2 ) );
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Spc_Emu::enable_accuracy_( bool b )
|
||||||
|
{
|
||||||
|
Music_Emu::enable_accuracy_( b );
|
||||||
|
filter.enable( b );
|
||||||
|
}
|
||||||
|
|
||||||
void Spc_Emu::mute_voices_( int m )
|
void Spc_Emu::mute_voices_( int m )
|
||||||
{
|
{
|
||||||
Music_Emu::mute_voices_( m );
|
Music_Emu::mute_voices_( m );
|
||||||
|
@ -277,17 +286,29 @@ blargg_err_t Spc_Emu::load_mem_( byte const* in, long size )
|
||||||
|
|
||||||
// Emulation
|
// 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 )
|
blargg_err_t Spc_Emu::start_track_( int track )
|
||||||
{
|
{
|
||||||
RETURN_ERR( Music_Emu::start_track_( track ) );
|
RETURN_ERR( Music_Emu::start_track_( track ) );
|
||||||
resampler.clear();
|
resampler.clear();
|
||||||
|
filter.clear();
|
||||||
RETURN_ERR( apu.load_spc( file_data, file_size ) );
|
RETURN_ERR( apu.load_spc( file_data, file_size ) );
|
||||||
|
filter.set_gain( (int) (gain() * SPC_Filter::gain_unit) );
|
||||||
apu.clear_echo();
|
apu.clear_echo();
|
||||||
return 0;
|
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 )
|
blargg_err_t Spc_Emu::skip_( long count )
|
||||||
{
|
{
|
||||||
if ( sample_rate() != native_sample_rate )
|
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?
|
// TODO: shouldn't skip be adjusted for the 64 samples read afterwards?
|
||||||
|
|
||||||
if ( count > 0 )
|
if ( count > 0 )
|
||||||
|
{
|
||||||
RETURN_ERR( apu.skip( count ) );
|
RETURN_ERR( apu.skip( count ) );
|
||||||
|
filter.clear();
|
||||||
|
}
|
||||||
|
|
||||||
// eliminate pop due to resampler
|
// eliminate pop due to resampler
|
||||||
const int resampler_latency = 64;
|
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 )
|
blargg_err_t Spc_Emu::play_( long count, sample_t* out )
|
||||||
{
|
{
|
||||||
if ( sample_rate() == native_sample_rate )
|
if ( sample_rate() == native_sample_rate )
|
||||||
return apu.play( count, out );
|
return play_and_filter( count, out );
|
||||||
|
|
||||||
long remain = count;
|
long remain = count;
|
||||||
while ( remain > 0 )
|
while ( remain > 0 )
|
||||||
|
@ -319,7 +343,7 @@ blargg_err_t Spc_Emu::play_( long count, sample_t* out )
|
||||||
if ( remain > 0 )
|
if ( remain > 0 )
|
||||||
{
|
{
|
||||||
long n = resampler.max_write();
|
long n = resampler.max_write();
|
||||||
RETURN_ERR( apu.play( n, resampler.buffer() ) );
|
RETURN_ERR( play_and_filter( n, resampler.buffer() ) );
|
||||||
resampler.write( n );
|
resampler.write( n );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,12 +1,13 @@
|
||||||
// Super Nintendo SPC music file emulator
|
// Super Nintendo SPC music file emulator
|
||||||
|
|
||||||
// Game_Music_Emu 0.5.2
|
// Game_Music_Emu 0.6.0
|
||||||
#ifndef SPC_EMU_H
|
#ifndef SPC_EMU_H
|
||||||
#define SPC_EMU_H
|
#define SPC_EMU_H
|
||||||
|
|
||||||
#include "Fir_Resampler.h"
|
#include "Fir_Resampler.h"
|
||||||
#include "Music_Emu.h"
|
#include "Music_Emu.h"
|
||||||
#include "Snes_Spc.h"
|
#include "Snes_Spc.h"
|
||||||
|
#include "Spc_Filter.h"
|
||||||
|
|
||||||
class Spc_Emu : public Music_Emu {
|
class Spc_Emu : public Music_Emu {
|
||||||
public:
|
public:
|
||||||
|
@ -65,11 +66,15 @@ protected:
|
||||||
blargg_err_t skip_( long );
|
blargg_err_t skip_( long );
|
||||||
void mute_voices_( int );
|
void mute_voices_( int );
|
||||||
void set_tempo_( double );
|
void set_tempo_( double );
|
||||||
|
void enable_accuracy_( bool );
|
||||||
private:
|
private:
|
||||||
byte const* file_data;
|
byte const* file_data;
|
||||||
long file_size;
|
long file_size;
|
||||||
Fir_Resampler<24> resampler;
|
Fir_Resampler<24> resampler;
|
||||||
|
SPC_Filter filter;
|
||||||
Snes_Spc apu;
|
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 ); }
|
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"
|
#include "Vgm_Emu.h"
|
||||||
|
|
||||||
|
@ -36,8 +36,7 @@ Vgm_Emu::Vgm_Emu()
|
||||||
|
|
||||||
set_silence_lookahead( 1 ); // tracks should already be trimmed
|
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( make_equalizer( -14.0, 80 ) );
|
||||||
set_equalizer( eq );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Vgm_Emu::~Vgm_Emu() { }
|
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 )
|
static byte const* get_gd3_str( byte const* in, byte const* end, char* field )
|
||||||
{
|
{
|
||||||
byte const* mid = skip_gd3_str( in, end );
|
byte const* mid = skip_gd3_str( in, end );
|
||||||
int len = int(mid - in) / 2 - 1;
|
int len = (mid - in) / 2 - 1;
|
||||||
if ( len > 0 )
|
if ( len > 0 )
|
||||||
{
|
{
|
||||||
len = min( len, (int) Gme_File::max_field_ );
|
len = min( len, (int) Gme_File::max_field_ );
|
||||||
|
@ -109,7 +108,7 @@ byte const* Vgm_Emu::gd3_data( int* size ) const
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
byte const* gd3 = data + header_size + gd3_offset;
|
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 )
|
if ( !gd3_size )
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
@ -185,7 +184,7 @@ struct Vgm_File : Gme_Info_
|
||||||
if ( gd3_size )
|
if ( gd3_size )
|
||||||
{
|
{
|
||||||
RETURN_ERR( gd3.resize( 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;
|
return 0;
|
||||||
|
@ -218,8 +217,8 @@ void Vgm_Emu::set_tempo_( double t )
|
||||||
{
|
{
|
||||||
vgm_rate = (long) (44100 * t + 0.5);
|
vgm_rate = (long) (44100 * t + 0.5);
|
||||||
blip_time_factor = (long) floor( double (1L << blip_time_bits) / vgm_rate * psg_rate + 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 );
|
//debug_printf( "blip_time_factor: %ld\n", blip_time_factor );
|
||||||
//dprintf( "vgm_rate: %ld\n", vgm_rate );
|
//debug_printf( "vgm_rate: %ld\n", vgm_rate );
|
||||||
// TODO: remove? calculates vgm_rate more accurately (above differs at most by one Hz only)
|
// 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 );
|
//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 );
|
//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
|
// 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
|
#ifndef VGM_EMU_H
|
||||||
#define 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"
|
#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;
|
int pairs = min_pairs;
|
||||||
while ( (pairs = to_fm_time( vgm_time )) < min_pairs )
|
while ( (pairs = to_fm_time( vgm_time )) < min_pairs )
|
||||||
vgm_time++;
|
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() )
|
if ( ym2612.enabled() )
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
// Low-level parts of Vgm_Emu
|
// Low-level parts of Vgm_Emu
|
||||||
|
|
||||||
// Game_Music_Emu 0.5.2
|
// Game_Music_Emu 0.6.0
|
||||||
#ifndef VGM_EMU_IMPL_H
|
#ifndef VGM_EMU_IMPL_H
|
||||||
#define 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
|
// 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"
|
#include "Ym2413_Emu.h"
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
// YM2413 FM sound chip emulator interface
|
// YM2413 FM sound chip emulator interface
|
||||||
|
|
||||||
// Game_Music_Emu 0.5.2
|
// Game_Music_Emu 0.6.0
|
||||||
#ifndef YM2413_EMU_H
|
#ifndef YM2413_EMU_H
|
||||||
#define 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
|
// Based on Gens 2.10 ym2612.c
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
// YM2612 FM sound chip emulator interface
|
// YM2612 FM sound chip emulator interface
|
||||||
|
|
||||||
// Game_Music_Emu 0.5.2
|
// Game_Music_Emu 0.6.0
|
||||||
#ifndef YM2612_EMU_H
|
#ifndef YM2612_EMU_H
|
||||||
#define YM2612_EMU_H
|
#define YM2612_EMU_H
|
||||||
|
|
||||||
|
|
|
@ -15,6 +15,13 @@
|
||||||
#ifndef BLARGG_COMMON_H
|
#ifndef BLARGG_COMMON_H
|
||||||
#define 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)
|
// STATIC_CAST(T,expr): Used in place of static_cast<T> (expr)
|
||||||
#ifndef STATIC_CAST
|
#ifndef STATIC_CAST
|
||||||
#define STATIC_CAST(T,expr) ((T) (expr))
|
#define STATIC_CAST(T,expr) ((T) (expr))
|
||||||
|
@ -54,10 +61,11 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifndef BLARGG_DISABLE_NOTHROW
|
#ifndef BLARGG_DISABLE_NOTHROW
|
||||||
#if __cplusplus < 199711
|
// throw spec mandatory in ISO C++ if operator new can return NULL
|
||||||
#define BLARGG_THROWS( spec )
|
#if __cplusplus >= 199711 || __GNUC__ >= 3
|
||||||
#else
|
|
||||||
#define BLARGG_THROWS( spec ) throw spec
|
#define BLARGG_THROWS( spec ) throw spec
|
||||||
|
#else
|
||||||
|
#define BLARGG_THROWS( spec )
|
||||||
#endif
|
#endif
|
||||||
#define BLARGG_DISABLE_NOTHROW \
|
#define BLARGG_DISABLE_NOTHROW \
|
||||||
void* operator new ( size_t s ) BLARGG_THROWS(()) { return malloc( s ); }\
|
void* operator new ( size_t s ) BLARGG_THROWS(()) { return malloc( s ); }\
|
||||||
|
@ -68,6 +76,7 @@ public:
|
||||||
#define BLARGG_NEW new (std::nothrow)
|
#define BLARGG_NEW new (std::nothrow)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// BLARGG_4CHAR('a','b','c','d') = 'abcd' (four character integer constant)
|
||||||
#define BLARGG_4CHAR( a, b, c, d ) \
|
#define BLARGG_4CHAR( a, b, c, d ) \
|
||||||
((a&0xFF)*0x1000000L + (b&0xFF)*0x10000L + (c&0xFF)*0x100L + (d&0xFF))
|
((a&0xFF)*0x1000000L + (b&0xFF)*0x10000L + (c&0xFF)*0x100L + (d&0xFF))
|
||||||
|
|
||||||
|
@ -110,18 +119,17 @@ public:
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// blargg_long/blargg_ulong = at least 32 bits, int if it's big enough
|
// blargg_long/blargg_ulong = at least 32 bits, int if it's big enough
|
||||||
#include <limits.h>
|
|
||||||
|
|
||||||
#if INT_MAX >= 0x7FFFFFFF
|
#if INT_MAX < 0x7FFFFFFF || LONG_MAX == 0x7FFFFFFF
|
||||||
typedef int blargg_long;
|
|
||||||
#else
|
|
||||||
typedef long blargg_long;
|
typedef long blargg_long;
|
||||||
|
#else
|
||||||
|
typedef int blargg_long;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if UINT_MAX >= 0xFFFFFFFF
|
#if UINT_MAX < 0xFFFFFFFF || ULONG_MAX == 0xFFFFFFFF
|
||||||
typedef unsigned blargg_ulong;
|
|
||||||
#else
|
|
||||||
typedef unsigned long blargg_ulong;
|
typedef unsigned long blargg_ulong;
|
||||||
|
#else
|
||||||
|
typedef unsigned blargg_ulong;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// BOOST::int8_t etc.
|
// BOOST::int8_t etc.
|
||||||
|
@ -171,5 +179,18 @@ public:
|
||||||
};
|
};
|
||||||
#endif
|
#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
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -6,9 +6,22 @@
|
||||||
// Uncomment to use zlib for transparent decompression of gzipped files
|
// Uncomment to use zlib for transparent decompression of gzipped files
|
||||||
//#define HAVE_ZLIB_H
|
//#define HAVE_ZLIB_H
|
||||||
|
|
||||||
// Uncomment to support only the listed game music types. See gme_type_list.cpp
|
// Uncomment and edit list to support only the listed game music types,
|
||||||
// for a list of all types.
|
// so that the others don't get linked in at all.
|
||||||
//#define GME_TYPE_LIST gme_nsf_type, gme_gbs_type
|
/*
|
||||||
|
#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
|
// Uncomment to enable platform-specific optimizations
|
||||||
//#define BLARGG_NONPORTABLE 1
|
//#define BLARGG_NONPORTABLE 1
|
||||||
|
@ -27,5 +40,4 @@
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1,20 +1,20 @@
|
||||||
// CPU Byte Order Utilities
|
// CPU Byte Order Utilities
|
||||||
|
|
||||||
// Game_Music_Emu 0.5.2
|
|
||||||
#ifndef BLARGG_ENDIAN
|
#ifndef BLARGG_ENDIAN
|
||||||
#define BLARGG_ENDIAN
|
#define BLARGG_ENDIAN
|
||||||
|
|
||||||
#include "blargg_common.h"
|
#include "blargg_common.h"
|
||||||
|
|
||||||
// BLARGG_CPU_CISC: Defined if CPU has very few general-purpose registers (< 16)
|
// BLARGG_CPU_CISC: Defined if CPU has very few general-purpose registers (< 16)
|
||||||
#if defined (_M_IX86) || defined (_M_IA64) || defined (__i486__) || \
|
#if defined (__i386__) || defined (__x86_64__) || defined (_M_IX86) || defined (_M_X64)
|
||||||
defined (__x86_64__) || defined (__ia64__) || defined (__i386__)
|
|
||||||
#define BLARGG_CPU_X86 1
|
#define BLARGG_CPU_X86 1
|
||||||
#define BLARGG_CPU_CISC 1
|
#define BLARGG_CPU_CISC 1
|
||||||
#endif
|
#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_POWERPC 1
|
||||||
|
#define BLARGG_CPU_RISC 1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// BLARGG_BIG_ENDIAN, BLARGG_LITTLE_ENDIAN: Determined automatically, otherwise only
|
// BLARGG_BIG_ENDIAN, BLARGG_LITTLE_ENDIAN: Determined automatically, otherwise only
|
||||||
|
@ -36,10 +36,10 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined (MSB_FIRST) || defined (__BIG_ENDIAN__) || defined (WORDS_BIGENDIAN) || \
|
#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)
|
(defined (BIG_ENDIAN) && BIG_ENDIAN+0 != 4321)
|
||||||
#define BLARGG_BIG_ENDIAN 1
|
#define BLARGG_BIG_ENDIAN 1
|
||||||
#else
|
#elif !defined (__mips__)
|
||||||
// No endian specified; assume little-endian, since it's most common
|
// No endian specified; assume little-endian, since it's most common
|
||||||
#define BLARGG_LITTLE_ENDIAN 1
|
#define BLARGG_LITTLE_ENDIAN 1
|
||||||
#endif
|
#endif
|
||||||
|
@ -64,45 +64,60 @@ inline void blargg_verify_byte_order()
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
inline unsigned get_le16( void const* p ) {
|
inline unsigned get_le16( void const* p )
|
||||||
return ((unsigned char const*) p) [1] * 0x100u +
|
{
|
||||||
((unsigned char const*) p) [0];
|
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 +
|
inline unsigned get_be16( void const* p )
|
||||||
((unsigned char const*) p) [1];
|
{
|
||||||
|
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 +
|
inline blargg_ulong get_le32( void const* p )
|
||||||
((unsigned char const*) p) [2] * 0x00010000u +
|
{
|
||||||
((unsigned char const*) p) [1] * 0x00000100u +
|
return (blargg_ulong) ((unsigned char const*) p) [3] << 24 |
|
||||||
((unsigned char const*) p) [0];
|
(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 +
|
inline blargg_ulong get_be32( void const* p )
|
||||||
((unsigned char const*) p) [1] * 0x00010000u +
|
{
|
||||||
((unsigned char const*) p) [2] * 0x00000100u +
|
return (blargg_ulong) ((unsigned char const*) p) [0] << 24 |
|
||||||
((unsigned char const*) p) [3];
|
(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) [1] = (unsigned char) (n >> 8);
|
||||||
((unsigned char*) p) [0] = (unsigned char) n;
|
((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) [0] = (unsigned char) (n >> 8);
|
||||||
((unsigned char*) p) [1] = (unsigned char) n;
|
((unsigned char*) p) [1] = (unsigned char) n;
|
||||||
}
|
}
|
||||||
inline void set_le32( void* p, blargg_ulong n ) {
|
|
||||||
((unsigned char*) p) [3] = (unsigned char) (n >> 24);
|
inline void set_le32( void* p, blargg_ulong n )
|
||||||
((unsigned char*) p) [2] = (unsigned char) (n >> 16);
|
{
|
||||||
((unsigned char*) p) [1] = (unsigned char) (n >> 8);
|
|
||||||
((unsigned char*) p) [0] = (unsigned char) 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);
|
inline void set_be32( void* p, blargg_ulong n )
|
||||||
((unsigned char*) p) [1] = (unsigned char) (n >> 16);
|
{
|
||||||
((unsigned char*) p) [2] = (unsigned char) (n >> 8);
|
|
||||||
((unsigned char*) p) [3] = (unsigned char) 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
|
#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 GET_BE32( addr ) (*(BOOST::uint32_t*) (addr))
|
||||||
#define SET_BE16( addr, data ) (void) (*(BOOST::uint16_t*) (addr) = (data))
|
#define SET_BE16( addr, data ) (void) (*(BOOST::uint16_t*) (addr) = (data))
|
||||||
#define SET_BE32( addr, data ) (void) (*(BOOST::uint32_t*) (addr) = (data))
|
#define SET_BE32( addr, data ) (void) (*(BOOST::uint32_t*) (addr) = (data))
|
||||||
#endif
|
|
||||||
|
#if BLARGG_CPU_POWERPC
|
||||||
#if BLARGG_CPU_POWERPC && defined (__MWERKS__)
|
// PowerPC has special byte-reversed instructions
|
||||||
// PowerPC has special byte-reversed instructions
|
#if defined (__MWERKS__)
|
||||||
// to do: assumes that PowerPC is running in big-endian mode
|
#define GET_LE16( addr ) (__lhbrx( addr, 0 ))
|
||||||
// to do: implement for other compilers which don't support these macros
|
#define GET_LE32( addr ) (__lwbrx( addr, 0 ))
|
||||||
#define GET_LE16( addr ) (__lhbrx( (addr), 0 ))
|
#define SET_LE16( addr, in ) (__sthbrx( in, addr, 0 ))
|
||||||
#define GET_LE32( addr ) (__lwbrx( (addr), 0 ))
|
#define SET_LE32( addr, in ) (__stwbrx( in, addr, 0 ))
|
||||||
#define SET_LE16( addr, data ) (__sthbrx( (data), (addr), 0 ))
|
#elif defined (__GNUC__)
|
||||||
#define SET_LE32( addr, data ) (__stwbrx( (data), (addr), 0 ))
|
#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
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef GET_LE16
|
#ifndef GET_LE16
|
||||||
#define GET_LE16( addr ) get_le16( addr )
|
#define GET_LE16( addr ) get_le16( addr )
|
||||||
#define GET_LE32( addr ) get_le32( addr )
|
|
||||||
#define SET_LE16( addr, data ) set_le16( addr, data )
|
#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 )
|
#define SET_LE32( addr, data ) set_le32( addr, data )
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef GET_BE16
|
#ifndef GET_BE16
|
||||||
#define GET_BE16( addr ) get_be16( addr )
|
#define GET_BE16( addr ) get_be16( addr )
|
||||||
#define GET_BE32( addr ) get_be32( addr )
|
|
||||||
#define SET_BE16( addr, data ) set_be16( addr, data )
|
#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 )
|
#define SET_BE32( addr, data ) set_be32( addr, data )
|
||||||
#endif
|
#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
|
#ifndef BLARGG_SOURCE_H
|
||||||
#define 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
|
// Like printf() except output goes to debug log file. Might be defined to do
|
||||||
// nothing (not even evaluate its arguments).
|
// nothing (not even evaluate its arguments).
|
||||||
// void dprintf( const char* format, ... );
|
// void debug_printf( const char* format, ... );
|
||||||
inline void blargg_dprintf_( const char*, ... ) { }
|
static inline void blargg_dprintf_( const char*, ... ) { }
|
||||||
#undef dprintf
|
#undef debug_printf
|
||||||
#define dprintf (1) ? (void) 0 : blargg_dprintf_
|
#define debug_printf (1) ? (void) 0 : blargg_dprintf_
|
||||||
|
|
||||||
// If enabled, evaluate expr and if false, make debug log entry with source file
|
// 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
|
// 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 min
|
||||||
#undef max
|
#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
|
// using const references generates crappy code, and I am currenly only using these
|
||||||
// for built-in types, so they take arguments by value
|
// for built-in types, so they take arguments by value
|
||||||
|
|
||||||
|
// TODO: remove
|
||||||
|
inline int min( int x, int y )
|
||||||
template<class T>
|
template<class T>
|
||||||
inline T min( T x, T y )
|
inline T min( T x, T y )
|
||||||
{
|
{
|
||||||
|
@ -60,17 +80,29 @@ inline T max( T x, T y )
|
||||||
return y;
|
return y;
|
||||||
return x;
|
return x;
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
// TODO: good idea? bad idea?
|
// TODO: good idea? bad idea?
|
||||||
#undef byte
|
#undef byte
|
||||||
#define byte byte_
|
#define byte byte_
|
||||||
typedef unsigned char 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
|
// deprecated
|
||||||
#define BLARGG_CHECK_ALLOC CHECK_ALLOC
|
#define BLARGG_CHECK_ALLOC CHECK_ALLOC
|
||||||
#define BLARGG_RETURN_ERR RETURN_ERR
|
#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
|
#ifdef BLARGG_SOURCE_BEGIN
|
||||||
#include BLARGG_SOURCE_BEGIN
|
#include BLARGG_SOURCE_BEGIN
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -10,9 +10,9 @@ int Gbs_Emu::cpu_read( gb_addr_t addr )
|
||||||
result = apu.read_register( clock(), addr );
|
result = apu.read_register( clock(), addr );
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
else if ( unsigned (addr - 0x8000) < 0x2000 || unsigned (addr - 0xE000) < 0x1F00 )
|
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 )
|
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
|
#endif
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -38,7 +38,7 @@ void Gbs_Emu::cpu_write( gb_addr_t addr, int data )
|
||||||
ram [offset] = 0xFF;
|
ram [offset] = 0xFF;
|
||||||
|
|
||||||
//if ( addr == 0xFFFF )
|
//if ( addr == 0xFFFF )
|
||||||
// dprintf( "Wrote interrupt mask\n" );
|
// debug_printf( "Wrote interrupt mask\n" );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if ( (addr ^ 0x2000) <= 0x2000 - 1 )
|
else if ( (addr ^ 0x2000) <= 0x2000 - 1 )
|
||||||
|
@ -48,7 +48,7 @@ void Gbs_Emu::cpu_write( gb_addr_t addr, int data )
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
else if ( unsigned (addr - 0x8000) < 0x2000 || unsigned (addr - 0xE000) < 0x1F00 )
|
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
|
#endif
|
||||||
}
|
}
|
||||||
|
@ -59,7 +59,7 @@ void Gbs_Emu::cpu_write( gb_addr_t addr, int data )
|
||||||
#define CPU_READ_FAST_( emu, addr, time, out ) \
|
#define CPU_READ_FAST_( emu, addr, time, out ) \
|
||||||
{\
|
{\
|
||||||
out = READ_PROG( addr );\
|
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 );\
|
out = emu->apu.read_register( emu->cpu_time - time * clocks_per_instr, addr );\
|
||||||
else\
|
else\
|
||||||
check( out == emu->cpu_read( addr ) );\
|
check( out == emu->cpu_read( addr ) );\
|
||||||
|
|
|
@ -1,9 +1,8 @@
|
||||||
// Game_Music_Emu 0.5.2. http://www.slack.net/~ant/
|
// Game_Music_Emu 0.6.0. http://www.slack.net/~ant/
|
||||||
|
|
||||||
#define IN_GME 1
|
|
||||||
|
|
||||||
#include "Music_Emu.h"
|
#include "Music_Emu.h"
|
||||||
|
|
||||||
|
#include "gme_types.h"
|
||||||
#if !GME_DISABLE_STEREO_DEPTH
|
#if !GME_DISABLE_STEREO_DEPTH
|
||||||
#include "Effects_Buffer.h"
|
#include "Effects_Buffer.h"
|
||||||
#endif
|
#endif
|
||||||
|
@ -24,32 +23,51 @@ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
|
||||||
|
|
||||||
#include "blargg_source.h"
|
#include "blargg_source.h"
|
||||||
|
|
||||||
#ifndef GME_TYPE_LIST
|
BLARGG_EXPORT gme_type_t const* 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()
|
|
||||||
{
|
{
|
||||||
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_;
|
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 ) )
|
switch ( get_be32( header ) )
|
||||||
{
|
{
|
||||||
|
@ -78,7 +96,7 @@ static void to_uppercase( const char* in, int len, char* out )
|
||||||
*out = 0; // extension too long
|
*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_, '.' );
|
char const* end = strrchr( extension_, '.' );
|
||||||
if ( end )
|
if ( end )
|
||||||
|
@ -93,7 +111,7 @@ gme_type_t GMEAPI gme_identify_extension( const char* extension_ )
|
||||||
return 0;
|
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 );
|
*type_out = gme_identify_extension( path );
|
||||||
// TODO: don't examine header if file has extension?
|
// 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;
|
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 );
|
require( (data || !size) && out );
|
||||||
*out = 0;
|
*out = 0;
|
||||||
|
@ -132,7 +150,7 @@ gme_err_t GMEAPI gme_open_data( void const* data, long size, Music_Emu** out, in
|
||||||
return err;
|
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 );
|
require( path && out );
|
||||||
*out = 0;
|
*out = 0;
|
||||||
|
@ -169,7 +187,7 @@ GMEEXPORT gme_err_t GMEAPI gme_open_file( const char* path, Music_Emu** out, int
|
||||||
return err;
|
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 )
|
if ( type )
|
||||||
{
|
{
|
||||||
|
@ -202,27 +220,27 @@ Music_Emu* GMEAPI gme_new_emu( gme_type_t type, int rate )
|
||||||
return 0;
|
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 );
|
Mem_File_Reader in( data, size );
|
||||||
return me->load( in );
|
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 );
|
Callback_Reader in( func, size, data );
|
||||||
return me->load( in );
|
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
|
struct gme_info_t_ : gme_info_t
|
||||||
{
|
{
|
||||||
|
@ -231,7 +249,7 @@ struct gme_info_t_ : gme_info_t
|
||||||
BLARGG_DISABLE_NOTHROW
|
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;
|
*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;
|
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);
|
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 !GME_DISABLE_STEREO_DEPTH
|
||||||
if ( me->effects_buffer )
|
if ( me->effects_buffer )
|
||||||
|
@ -310,24 +328,26 @@ void GMEAPI gme_set_stereo_depth( Music_Emu* me, double depth )
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void* GMEAPI gme_user_data ( Music_Emu const* me ) { return me->user_data(); }
|
BLARGG_EXPORT void* 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 ); }
|
BLARGG_EXPORT void 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_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 ); }
|
BLARGG_EXPORT gme_err_t 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 ); }
|
BLARGG_EXPORT gme_err_t 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 ); }
|
BLARGG_EXPORT void gme_set_fade ( Music_Emu* me, int start_msec ) { me->set_fade( start_msec ); }
|
||||||
void GMEAPI 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(); }
|
||||||
int GMEAPI gme_track_ended ( Music_Emu const* me ) { return me->track_ended(); }
|
BLARGG_EXPORT int gme_tell ( Music_Emu const* me ) { return me->tell(); }
|
||||||
int GMEAPI 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 ); }
|
||||||
gme_err_t GMEAPI 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(); }
|
||||||
int GMEAPI 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 ); }
|
||||||
void GMEAPI 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 ); }
|
||||||
void GMEAPI 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 ); }
|
||||||
void GMEAPI 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 ); }
|
||||||
void GMEAPI 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();
|
Music_Emu::equalizer_t e = me->equalizer();
|
||||||
e.treble = eq->treble;
|
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 );
|
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.treble = me->equalizer().treble;
|
||||||
e.bass = me->equalizer().bass;
|
e.bass = me->equalizer().bass;
|
||||||
*out = e;
|
*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() );
|
assert( (unsigned) i < (unsigned) me->voice_count() );
|
||||||
return me->voice_names() [i];
|
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 emulator library C interface (also usable from C++) */
|
||||||
|
|
||||||
/* Game_Music_Emu 0.5.2 */
|
/* Game_Music_Emu 0.6.0 */
|
||||||
#ifndef GME_H
|
#ifndef GME_H
|
||||||
#define 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
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#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) */
|
/* Error string returned by library functions, or NULL if no error (success) */
|
||||||
typedef const char* gme_err_t;
|
typedef const char* gme_err_t;
|
||||||
|
|
||||||
|
@ -38,38 +20,35 @@ typedef struct Music_Emu Music_Emu;
|
||||||
/******** Basic operations ********/
|
/******** Basic operations ********/
|
||||||
|
|
||||||
/* Create emulator and load game music file/data into it. Sets *out to new emulator. */
|
/* 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 */
|
/* 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 */
|
/* 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. */
|
/* 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 [] );
|
gme_err_t gme_play( Music_Emu*, int count, short out [] );
|
||||||
|
|
||||||
/* Skip n samples */
|
|
||||||
GMEDLL gme_err_t GMEAPI gme_skip( Music_Emu*, long n );
|
|
||||||
|
|
||||||
/* Finish using emulator and free memory */
|
/* Finish using emulator and free memory */
|
||||||
GMEDLL void GMEAPI gme_delete( Music_Emu* );
|
void gme_delete( Music_Emu* );
|
||||||
|
|
||||||
|
|
||||||
/******** Track position/length ********/
|
/******** Track position/length ********/
|
||||||
|
|
||||||
/* Set time to start fading track out. Once fade ends track_ended() returns true.
|
/* Set time to start fading track out. Once fade ends track_ended() returns true.
|
||||||
Fade time can be changed while track is playing. */
|
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 */
|
/* 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 */
|
/* 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. */
|
/* 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 ********/
|
/******** Informational ********/
|
||||||
|
@ -80,22 +59,22 @@ enum { gme_info_only = -1 };
|
||||||
|
|
||||||
/* Most recent warning string, or NULL if none. Clears current warning after returning.
|
/* 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. */
|
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) */
|
/* 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
|
/* Clear any loaded m3u playlist and any internal playlist that the music format
|
||||||
supports (NSFE for example). */
|
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.).
|
/* Gets information for a particular track (length, name, author, etc.).
|
||||||
Must be freed after use. */
|
Must be freed after use. */
|
||||||
typedef struct gme_info_t gme_info_t;
|
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 */
|
/* Frees track information */
|
||||||
GMEDLL void GMEAPI gme_free_info( gme_info_t* );
|
void gme_free_info( gme_info_t* );
|
||||||
|
|
||||||
struct 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
|
/* Adjust stereo echo depth, where 0.0 = off and 1.0 = maximum. Has no effect for
|
||||||
GYM, SPC, and Sega Genesis VGM music */
|
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
|
/* Disable automatic end-of-track detection and skipping of silence at beginning
|
||||||
if ignore is true */
|
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.
|
/* 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. */
|
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 */
|
/* 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 */
|
/* 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 */
|
/* 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
|
/* 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. */
|
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) */
|
/* Frequency equalizer parameters (see gme.txt) */
|
||||||
|
/* Implementers: If modified, also adjust Music_Emu::make_equalizer as needed */
|
||||||
typedef struct gme_equalizer_t
|
typedef struct gme_equalizer_t
|
||||||
{
|
{
|
||||||
double treble; /* -50.0 = muffled, 0 = flat, +5.0 = extra-crisp */
|
double treble; /* -50.0 = muffled, 0 = flat, +5.0 = extra-crisp */
|
||||||
|
@ -160,11 +140,13 @@ typedef struct gme_equalizer_t
|
||||||
} gme_equalizer_t;
|
} gme_equalizer_t;
|
||||||
|
|
||||||
/* Get current frequency equalizater parameters */
|
/* 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 */
|
/* 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 ********/
|
/******** Game music types ********/
|
||||||
|
@ -187,17 +169,17 @@ extern const gme_type_t
|
||||||
gme_vgz_type;
|
gme_vgz_type;
|
||||||
|
|
||||||
/* Type of this emulator */
|
/* 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
|
/* 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. */
|
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 */
|
/* 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 */
|
/* 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 ********/
|
/******** Advanced file loading ********/
|
||||||
|
@ -206,50 +188,50 @@ GMEDLL int GMEAPI gme_type_multitrack( gme_type_t );
|
||||||
extern const char* const gme_wrong_file_type;
|
extern const char* const gme_wrong_file_type;
|
||||||
|
|
||||||
/* Same as gme_open_file(), but uses file data already in memory. Makes copy of data. */
|
/* 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
|
/* 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
|
string containing proper file suffix (i.e. "NSF", "SPC", etc.) or "" if
|
||||||
file header is not recognized. */
|
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. */
|
/* 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).
|
/* 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. */
|
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
|
/* 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. */
|
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 */
|
/* 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. */
|
/* 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
|
/* 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. */
|
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 );
|
typedef gme_err_t (*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 );
|
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) */
|
/* 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 ********/
|
/******** User data ********/
|
||||||
|
|
||||||
/* Set/get pointer to data you want to associate with this emulator.
|
/* Set/get pointer to data you want to associate with this emulator.
|
||||||
You can use this for whatever you want. */
|
You can use this for whatever you want. */
|
||||||
GMEDLL void GMEAPI gme_set_user_data( Music_Emu*, void* new_user_data );
|
void gme_set_user_data( Music_Emu*, void* new_user_data );
|
||||||
GMEDLL void* GMEAPI gme_user_data( Music_Emu const* );
|
void* gme_user_data( Music_Emu const* );
|
||||||
|
|
||||||
/* Register cleanup function to be called when deleting emulator, or NULL to
|
/* Register cleanup function to be called when deleting emulator, or NULL to
|
||||||
clear it. Passes user_data to cleanup function. */
|
clear it. Passes user_data to cleanup function. */
|
||||||
typedef void (GMEAPI *gme_user_cleanup_t)( void* user_data );
|
typedef void (*gme_user_cleanup_t)( void* user_data );
|
||||||
GMEDLL void GMEAPI gme_set_user_cleanup( Music_Emu*, gme_user_cleanup_t func );
|
void gme_set_user_cleanup( Music_Emu*, gme_user_cleanup_t func );
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#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:
|
default:
|
||||||
if ( bank != 0xFF )
|
if ( bank != 0xFF )
|
||||||
dprintf( "Unmapped bank $%02X\n", bank );
|
debug_printf( "Unmapped bank $%02X\n", bank );
|
||||||
return rom.unmapped();
|
return rom.unmapped();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -34,7 +34,7 @@ int Nsf_Emu::cpu_read( nes_addr_t addr )
|
||||||
result = addr >> 8; // simulate open bus
|
result = addr >> 8; // simulate open bus
|
||||||
|
|
||||||
if ( addr != 0x2002 )
|
if ( addr != 0x2002 )
|
||||||
dprintf( "Read unmapped $%.4X\n", (unsigned) addr );
|
debug_printf( "Read unmapped $%.4X\n", (unsigned) addr );
|
||||||
|
|
||||||
exit:
|
exit:
|
||||||
return result;
|
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 )
|
int Sap_Emu::cpu_read( sap_addr_t addr )
|
||||||
{
|
{
|
||||||
if ( (addr & 0xF900) == 0xD000 )
|
if ( (addr & 0xF900) == 0xD000 )
|
||||||
dprintf( "Unmapped read $%04X\n", addr );
|
debug_printf( "Unmapped read $%04X\n", addr );
|
||||||
return mem.ram [addr];
|
return mem.ram [addr];
|
||||||
}
|
}
|
||||||
#endif
|
#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
|
Game_Music_Emu is a collection of video game music file emulators that
|
||||||
support the following formats and systems:
|
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
|
VGM/VGZ Sega Master System/Mark III, Sega Genesis/Mega Drive,BBC Micro
|
||||||
|
|
||||||
Features:
|
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
|
* 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
|
* One set of common functions work with all emulators the same way
|
||||||
* Several code examples, including music player using SDL
|
* Several code examples, including music player using SDL
|
||||||
|
@ -42,8 +42,17 @@ License: GNU Lesser General Public License (LGPL)
|
||||||
Getting Started
|
Getting Started
|
||||||
---------------
|
---------------
|
||||||
Build a program consisting of demo/basics.c, demo/Wave_Writer.cpp, and
|
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.
|
all source files in gme/. If you have CMake 2.6 or later, execute
|
||||||
Running the program should generate the recording "out.wav".
|
|
||||||
|
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
|
Read gme.txt for more information. Post to the discussion forum for
|
||||||
assistance.
|
assistance.
|
||||||
|
@ -55,16 +64,17 @@ gme.txt General notes about the library
|
||||||
changes.txt Changes made since previous releases
|
changes.txt Changes made since previous releases
|
||||||
design.txt Library design notes
|
design.txt Library design notes
|
||||||
license.txt GNU Lesser General Public License
|
license.txt GNU Lesser General Public License
|
||||||
|
CMakeLists.txt CMake build rules
|
||||||
|
|
||||||
test.nsf Test file for NSF emulator
|
test.nsf Test file for NSF emulator
|
||||||
test.m3u Test m3u playlist for features.c demo
|
test.m3u Test m3u playlist for features.c demo
|
||||||
|
|
||||||
demo/
|
demo/
|
||||||
basics.c Records NSF file to wave sound file
|
basics.c Records NSF file to wave sound file
|
||||||
cpp_basics.cpp C++ version of basics.c
|
|
||||||
features.c Demonstrates many additional features
|
features.c Demonstrates many additional features
|
||||||
Wave_Writer.h WAVE sound file writer used for demo output
|
Wave_Writer.h WAVE sound file writer used for demo output
|
||||||
Wave_Writer.cpp
|
Wave_Writer.cpp
|
||||||
|
CMakeLists.txt CMake build rules
|
||||||
|
|
||||||
player/ Player using the SDL multimedia library
|
player/ Player using the SDL multimedia library
|
||||||
player.cpp Simple music player with waveform display
|
player.cpp Simple music player with waveform display
|
||||||
|
@ -72,22 +82,13 @@ player/ Player using the SDL multimedia library
|
||||||
Music_Player.h
|
Music_Player.h
|
||||||
Audio_Scope.cpp Audio waveform scope
|
Audio_Scope.cpp Audio waveform scope
|
||||||
Audio_Scope.h
|
Audio_Scope.h
|
||||||
|
CMakeLists.txt CMake build rules
|
||||||
|
|
||||||
gme/
|
gme/
|
||||||
blargg_config.h Library configuration (modify this file as needed)
|
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.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.h ZX Spectrum AY emulator
|
||||||
Ay_Emu.cpp
|
Ay_Emu.cpp
|
||||||
|
@ -113,7 +114,7 @@ gme/
|
||||||
Hes_Cpu.h
|
Hes_Cpu.h
|
||||||
hes_cpu_io.h
|
hes_cpu_io.h
|
||||||
Hes_Emu.cpp
|
Hes_Emu.cpp
|
||||||
|
|
||||||
Kss_Emu.h MSX Home Computer/other Z80 systems KSS emulator
|
Kss_Emu.h MSX Home Computer/other Z80 systems KSS emulator
|
||||||
Kss_Emu.cpp
|
Kss_Emu.cpp
|
||||||
Kss_Cpu.cpp
|
Kss_Cpu.cpp
|
||||||
|
@ -180,26 +181,36 @@ gme/
|
||||||
Dual_Resampler.h
|
Dual_Resampler.h
|
||||||
Fir_Resampler.cpp
|
Fir_Resampler.cpp
|
||||||
Fir_Resampler.h
|
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_common.h Common files needed by all emulators
|
||||||
blargg_endian.h
|
blargg_endian.h
|
||||||
blargg_source.h
|
blargg_source.h
|
||||||
Blip_Buffer.cpp
|
Blip_Buffer.cpp
|
||||||
Blip_Buffer.h
|
Blip_Buffer.h
|
||||||
|
Gme_File.h
|
||||||
Gme_File.cpp
|
Gme_File.cpp
|
||||||
|
Music_Emu.h
|
||||||
Music_Emu.cpp
|
Music_Emu.cpp
|
||||||
Classic_Emu.h
|
Classic_Emu.h
|
||||||
Classic_Emu.cpp
|
Classic_Emu.cpp
|
||||||
Multi_Buffer.h
|
Multi_Buffer.h
|
||||||
Multi_Buffer.cpp
|
Multi_Buffer.cpp
|
||||||
|
Data_Reader.h
|
||||||
Data_Reader.cpp
|
Data_Reader.cpp
|
||||||
|
|
||||||
|
CMakeLists.txt CMake build rules
|
||||||
|
|
||||||
|
|
||||||
Legal
|
Legal
|
||||||
-----
|
-----
|
||||||
Game_Music_Emu library copyright (C) 2003-2006 Shay Green.
|
Game_Music_Emu library copyright (C) 2003-2009 Shay Green.
|
||||||
SNES SPC DSP emulator based on OpenSPC, copyright (C) 2002 Brad Martin.
|
|
||||||
Sega Genesis YM2612 emulator copyright (C) 2002 Stephane Dallongeville.
|
Sega Genesis YM2612 emulator copyright (C) 2002 Stephane Dallongeville.
|
||||||
|
|
||||||
--
|
--
|
||||||
Shay Green <gblargg@gmail.com>
|
Shay Green <gblargg@gmail.com>
|
||||||
|
|
Loading…
Reference in a new issue