Merge remote-tracking branch 'origin/master' into openal

Conflicts:
	src/CMakeLists.txt
This commit is contained in:
Chris Robinson 2014-06-15 12:04:15 -07:00
commit 7ff7c151a8
433 changed files with 11726 additions and 6060 deletions

11
.gitignore vendored
View file

@ -14,6 +14,7 @@
/release_gcc
/dumb/vc6/dumb_static/release
/dumb/vc6/dumb_static/debug
/dumb/vc6/dumb_static/x64
/DOOMSTATS.TXT
/src/gitinfo.h
/src/sc_man_scanner.h
@ -25,4 +26,14 @@
/tools/*/*.exe
/tools/lemon/build
/tools/re2c/build
/tools/updaterevision/x64/
/tools/zipdir/x64
/wadsrc/*.pk3
/build_vc2013
/bzip2/x64/
/disasm.txt
/game-music-emu/x64/
/gdtoa/x64/
/jpeg-6b/x64/
/lzma/x64/
/zlib/x64/

View file

@ -1,6 +1,10 @@
cmake_minimum_required( VERSION 2.4 )
project(ZDoom)
list( APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR} )
include( CreateLaunchers )
include( FindPackageHandleStandardArgs )
# Generator expression are available some time in CMake 2.8. Due to
# cmake_minimum_required, we can assume a minor version of > 7 implies major >= 2
if(${CMAKE_MAJOR_VERSION} GREATER 2 OR ${CMAKE_MINOR_VERSION} GREATER 7)
@ -9,6 +13,17 @@ else(${CMAKE_MAJOR_VERSION} GREATER 2 OR ${CMAKE_MINOR_VERSION} GREATER 7)
set( NO_GENERATOR_EXPRESSIONS ON )
endif(${CMAKE_MAJOR_VERSION} GREATER 2 OR ${CMAKE_MINOR_VERSION} GREATER 7)
# Support cross compiling
option( FORCE_CROSSCOMPILE "Turn on cross compiling." NO )
if( FORCE_CROSSCOMPILE )
set( CMAKE_CROSSCOMPILING TRUE )
endif( FORCE_CROSSCOMPILE )
if(CMAKE_CROSSCOMPILING)
set(IMPORT_EXECUTABLES "IMPORTFILE-NOTFOUND" CACHE FILEPATH "Export file from native build.")
include(${IMPORT_EXECUTABLES})
endif(CMAKE_CROSSCOMPILING)
# Simplify pk3 building, add_pk3(filename srcdirectory)
function( add_pk3 PK3_NAME PK3_DIR )
get_target_property(ZIPDIR_EXE zipdir LOCATION)
@ -19,21 +34,34 @@ function( add_pk3 PK3_NAME PK3_DIR )
set( PK3_TARGET "pk3" )
endif( ${PK3_TARGET} STREQUAL "zdoom_pk3" )
if( NO_GENERATOR_EXPRESSIONS )
if( NOT NO_GENERATOR_EXPRESSIONS AND NOT ZDOOM_OUTPUT_OLDSTYLE )
add_custom_command( OUTPUT ${ZDOOM_OUTPUT_DIR}/${PK3_NAME}
COMMAND ${ZIPDIR_EXE} -udf ${ZDOOM_OUTPUT_DIR}/${PK3_NAME} ${PK3_DIR}
COMMAND ${CMAKE_COMMAND} -E copy_if_different ${ZDOOM_OUTPUT_DIR}/${PK3_NAME} $<TARGET_FILE_DIR:zdoom>
DEPENDS zipdir ${PK3_DIR} )
else( NO_GENERATOR_EXPRESSIONS )
COMMAND ${CMAKE_COMMAND} -E copy_if_different ${ZDOOM_OUTPUT_DIR}/${PK3_NAME} $<TARGET_FILE_DIR:zdoom>/${PK3_NAME}
DEPENDS zipdir )
else( NOT NO_GENERATOR_EXPRESSIONS AND NOT ZDOOM_OUTPUT_OLDSTYLE )
add_custom_command( OUTPUT ${ZDOOM_OUTPUT_DIR}/${PK3_NAME}
COMMAND ${ZIPDIR_EXE} -udf ${ZDOOM_OUTPUT_DIR}/${PK3_NAME} ${PK3_DIR}
DEPENDS zipdir ${PK3_DIR} )
endif( NO_GENERATOR_EXPRESSIONS )
DEPENDS zipdir )
endif( NOT NO_GENERATOR_EXPRESSIONS AND NOT ZDOOM_OUTPUT_OLDSTYLE )
# Touch the zipdir executable here so that the pk3s are forced to rebuild
# each time since their dependecy has "changed."
add_custom_target( ${PK3_TARGET} ALL
COMMAND ${CMAKE_COMMAND} -E touch ${ZIPDIR_EXE}
DEPENDS ${ZDOOM_OUTPUT_DIR}/${PK3_NAME} )
endfunction( add_pk3 )
# Macro for building libraries without debugging information
macro( make_release_only )
set( CMAKE_C_FLAGS_MINSIZEREL ${CMAKE_C_FLAGS_RELEASE} )
set( CMAKE_C_FLAGS_RELWITHDEBINFO ${CMAKE_C_FLAGS_RELEASE} )
string( REPLACE "/MT " "/MTd " CMAKE_C_FLAGS_DEBUG ${CMAKE_C_FLAGS_RELEASE} )
set( CMAKE_CXX_FLAGS_MINSIZEREL ${CMAKE_CXX_FLAGS_RELEASE} )
set( CMAKE_CXX_FLAGS_RELWITHDEBINFO ${CMAKE_CXX_FLAGS_RELEASE} )
string( REPLACE "/MT " "/MTd " CMAKE_CXX_FLAGS_DEBUG ${CMAKE_CXX_FLAGS_RELEASE} )
endmacro( make_release_only )
IF( NOT CMAKE_BUILD_TYPE )
SET( CMAKE_BUILD_TYPE Debug CACHE STRING
"Choose the type of build, options are: Debug Release RelWithDebInfo MinSizeRel."
@ -42,6 +70,13 @@ ENDIF( NOT CMAKE_BUILD_TYPE )
set( ZDOOM_OUTPUT_DIR ${CMAKE_BINARY_DIR} CACHE PATH "Directory where zdoom.pk3 and the executable will be created." )
set( ZDOOM_EXE_NAME "zdoom" CACHE FILEPATH "Name of the executable to create." )
if( MSVC )
# Allow the user to use ZDOOM_OUTPUT_DIR as a single release point.
# Use zdoom, zdoomd, zdoom64, and zdoomd64 for the binary names
option( ZDOOM_OUTPUT_OLDSTYLE "Don't use Release/Debug directories." OFF )
else( MSVC )
set( ZDOOM_OUTPUT_OLDSTYLE OFF )
endif( MSVC )
if( "${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" OR "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang" )
set( PROFILE 0 CACHE BOOL "Enable profiling with gprof for Debug and RelWithDebInfo build types." )
@ -55,22 +90,48 @@ option( NO_OPENAL "Disable OpenAL sound support" OFF )
find_package( BZip2 )
find_package( JPEG )
find_package( ZLIB )
# GME
find_path( GME_INCLUDE_DIR gme.h )
find_library( GME_LIBRARIES gme )
mark_as_advanced( GME_INCLUDE_DIR GME_LIBRARIES )
FIND_PACKAGE_HANDLE_STANDARD_ARGS( GME
REQUIRED_VARS GME_LIBRARIES GME_INCLUDE_DIR
)
if( MSVC )
# Eliminate unreferenced functions and data
# Perform identical COMDAT folding
set( REL_LINKER_FLAGS "/opt:ref /opt:icf /nodefaultlib:msvcrt" )
set( REL_LINKER_FLAGS "/opt:ref /opt:icf /nodefaultlib:msvcrt /TSAWARE" )
# String pooling
# Function-level linking
# Disable run-time type information
set( ALL_C_FLAGS "/GF /Gy /GR-" )
# Avoid CRT DLL dependancies in release builds
set( REL_C_FLAGS "/MT" )
if( CMAKE_SIZEOF_VOID_P MATCHES "4")
# SSE2 option (mostly to switch it off in VC2012 and later where it's the default
option (ZDOOM_USE_SSE2 "Use SSE2 instruction set")
if (ZDOOM_USE_SSE2)
set( ALL_C_FLAGS "${ALL_C_FLAGS} /arch:SSE2")
else (ZDOOM_USE_SSE2)
if (MSVC_VERSION GREATER 1699)
# On Visual C++ 2012 and later SSE2 is the default, so we need to switch it off explicitly
set( ALL_C_FLAGS "${ALL_C_FLAGS} /arch:IA32")
endif (MSVC_VERSION GREATER 1699)
endif (ZDOOM_USE_SSE2)
endif( CMAKE_SIZEOF_VOID_P MATCHES "4")
# Avoid CRT DLL dependancies in release builds, optionally generate assembly output for checking crash locations.
option( ZDOOM_GENERATE_ASM "Generate assembly output." OFF )
if( ZDOOM_GENERATE_ASM )
set( REL_C_FLAGS "/MT /Oy /Oi /FAcs" )
else( ZDOOM_GENERATE_ASM )
set( REL_C_FLAGS "/MT /Oy /Oi" )
endif( ZDOOM_GENERATE_ASM )
# Debug allocations in debug builds
set( DEB_C_FLAGS "/D _CRTDBG_MAP_ALLOC" )
set( DEB_C_FLAGS "/D _CRTDBG_MAP_ALLOC /MTd" )
# Disable warnings for unsecure CRT functions from VC8+
if( MSVC_VERSION GREATER 1399 )
@ -81,10 +142,17 @@ if( MSVC )
string(REPLACE "/MD " " " CMAKE_CXX_FLAGS_RELEASE ${CMAKE_CXX_FLAGS_RELEASE} )
string(REPLACE "/MD " " " CMAKE_CXX_FLAGS_MINSIZEREL ${CMAKE_CXX_FLAGS_MINSIZEREL} )
string(REPLACE "/MD " " " CMAKE_CXX_FLAGS_RELWITHDEBINFO ${CMAKE_CXX_FLAGS_RELWITHDEBINFO} )
string(REPLACE "/MDd " " " CMAKE_CXX_FLAGS_DEBUG ${CMAKE_CXX_FLAGS_DEBUG} )
string(REPLACE "/MD " " " CMAKE_C_FLAGS_RELEASE ${CMAKE_C_FLAGS_RELEASE} )
string(REPLACE "/MD " " " CMAKE_C_FLAGS_MINSIZEREL ${CMAKE_C_FLAGS_MINSIZEREL} )
string(REPLACE "/MD " " " CMAKE_C_FLAGS_RELWITHDEBINFO ${CMAKE_C_FLAGS_RELWITHDEBINFO} )
string(REPLACE "/MDd " " " CMAKE_C_FLAGS_DEBUG ${CMAKE_C_FLAGS_DEBUG} )
string(REPLACE " /GR" " " CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS} )
else( MSVC )
set( REL_LINKER_FLAGS "" )
set( ALL_C_FLAGS "" )
set( REL_C_FLAGS "" )
set( DEB_C_FLAGS "" )
endif( MSVC )
set( CMAKE_EXE_LINKER_FLAGS_RELEASE "${CMAKE_EXE_LINKER_FLAGS_RELEASE} ${REL_LINKER_FLAGS}" )
@ -106,6 +174,7 @@ set( CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} ${DEB_C_FLAGS} -D_DEBUG" )
option(FORCE_INTERNAL_ZLIB "Use internal zlib")
option(FORCE_INTERNAL_JPEG "Use internal jpeg")
option(FORCE_INTERNAL_BZIP2 "Use internal bzip2")
option(FORCE_INTERNAL_GME "Use internal gme" ON)
if( ZLIB_FOUND AND NOT FORCE_INTERNAL_ZLIB )
message( STATUS "Using system zlib" )
@ -137,11 +206,19 @@ else( BZIP2_FOUND AND NOT FORCE_INTERNAL_BZIP2 )
set( BZIP2_LIBRARY bz2 )
endif( BZIP2_FOUND AND NOT FORCE_INTERNAL_BZIP2 )
if( GME_FOUND AND NOT FORCE_INTERNAL_GME )
message( STATUS "Using system gme library ${GME_INCLUDE_DIR}" )
else( GME_FOUND AND NOT FORCE_INTERNAL_GME )
message( STATUS "Using internal gme library" )
add_subdirectory( game-music-emu )
set( GME_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/game-music-emu" )
set( GME_LIBRARIES gme )
endif( GME_FOUND AND NOT FORCE_INTERNAL_GME )
set( LZMA_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/lzma/C" )
add_subdirectory( lzma )
add_subdirectory( tools )
add_subdirectory( game-music-emu )
add_subdirectory( dumb )
add_subdirectory( gdtoa )
add_subdirectory( wadsrc )
@ -150,3 +227,7 @@ add_subdirectory( src )
if( NOT WIN32 AND NOT APPLE )
add_subdirectory( output_sdl )
endif( NOT WIN32 AND NOT APPLE )
if( NOT CMAKE_CROSSCOMPILING )
export(TARGETS ${CROSS_EXPORTS} FILE "${CMAKE_BINARY_DIR}/ImportExecutables.cmake" )
endif( NOT CMAKE_CROSSCOMPILING )

48
CleanDirectoryList.cmake Normal file
View file

@ -0,0 +1,48 @@
# - Removes duplicate entries and non-directories from a provided list
#
# clean_directory_list(<listvar> [<additional list items>...])
#
# Requires CMake 2.6 or newer (uses the 'function' command)
#
# Original Author:
# 2009-2010 Ryan Pavlik <rpavlik@iastate.edu> <abiryan@ryand.net>
# http://academic.cleardefinition.com
# Iowa State University HCI Graduate Program/VRAC
#
# Copyright Iowa State University 2009-2010.
# Distributed under the Boost Software License, Version 1.0.
# (See accompanying file LICENSE_1_0.txt or copy at
# http://www.boost.org/LICENSE_1_0.txt)
if(__clean_directory_list)
return()
endif()
set(__clean_directory_list YES)
function(clean_directory_list _var)
# combine variable's current value with additional list items
set(_in ${${_var}} ${ARGN})
if(_in)
# Initial list cleaning
list(REMOVE_DUPLICATES _in)
# Grab the absolute path of each actual directory
set(_out)
foreach(_dir ${_in})
if(IS_DIRECTORY "${_dir}")
get_filename_component(_dir "${_dir}" ABSOLUTE)
file(TO_CMAKE_PATH "${_dir}" _dir)
list(APPEND _out "${_dir}")
endif()
endforeach()
if(_out)
# Clean up the output list now
list(REMOVE_DUPLICATES _out)
endif()
# return _out
set(${_var} "${_out}" PARENT_SCOPE)
endif()
endfunction()

336
CreateLaunchers.cmake Normal file
View file

@ -0,0 +1,336 @@
# - Create launchers to set working directory, env. vars, etc.
#
# include(CreateLaunchers) - to make these available
# guess_runtime_library_dirs(<outputvarname> [<extralibrary> ...])
# create_default_target_launcher(<targetname>
# [ARGS <args...>]
# [FORWARD_ARGS]
# [RUNTIME_LIBRARY_DIRS <dir...>]
# [WORKING_DIRECTORY <dir>]
# [ENVIRONMENT <VAR=value> [<VAR=value>...]])
#
# create_target_launcher(<targetname>
# [ARGS <args...>]
# [FORWARD_ARGS]
# [RUNTIME_LIBRARY_DIRS <dir...>]
# [WORKING_DIRECTORY <dir>]
# [ENVIRONMENT <VAR=value> [<VAR=value>...]])
#
# create_generic_launcher(<launchername>
# [RUNTIME_LIBRARY_DIRS <dir...>]
# [WORKING_DIRECTORY <dir>]
# [ENVIRONMENT <VAR=value> [<VAR=value>...]])
# - sets GENERIC_LAUNCHER_COMMAND and GENERIC_LAUNCHER_FAIL_REGULAR_EXPRESSION
#
# Requires these CMake modules:
# ListFilter
# ProgramFilesGlob
# CleanDirectoryList
#
# Requires CMake 2.6 or newer (uses the 'function' command)
#
# Original Author:
# 2009-2010 Ryan Pavlik <rpavlik@iastate.edu> <abiryan@ryand.net>
# http://academic.cleardefinition.com
# Iowa State University HCI Graduate Program/VRAC
#
# Copyright Iowa State University 2009-2010.
# Distributed under the Boost Software License, Version 1.0.
# (See accompanying file LICENSE_1_0.txt or copy at
# http://www.boost.org/LICENSE_1_0.txt)
if(__create_launchers)
return()
endif()
set(__create_launchers YES)
include(CleanDirectoryList)
# We must run the following at "include" time, not at function call time,
# to find the path to this module rather than the path to a calling list file
get_filename_component(_launchermoddir
${CMAKE_CURRENT_LIST_FILE}
PATH)
set(_launchermoddir "${_launchermoddir}/launcher-templates")
macro(_launcher_system_settings)
if(CMAKE_SIZEOF_VOID_P EQUAL 8)
set(BITS 64)
else()
set(BITS 32)
endif()
if(WIN32)
# Find user and system name
set(SYSTEM_NAME $ENV{USERDOMAIN})
set(USER_NAME $ENV{USERNAME})
set(VCPROJ_TYPE vcproj)
set(USERFILE_EXTENSION ${SYSTEM_NAME}.${USER_NAME}.user)
set(LAUNCHER_LINESEP "&#x0A;")
if(MSVC90)
set(USERFILE_VC_VERSION 9.00)
elseif(MSVC80)
set(USERFILE_VC_VERSION 8.00)
elseif(MSVC71)
set(USERFILE_VC_VERSION 7.10)
elseif(MSVC10 OR (MSVC AND MSVC_VERSION GREATER 1600)) # 2010 or newer
set(LAUNCHER_LINESEP "\n")
set(USERFILE_VC_VERSION 10.00)
set(USERFILE_EXTENSION user)
set(VCPROJ_TYPE vcxproj)
endif()
if(BITS EQUAL 64)
set(USERFILE_PLATFORM x64)
else()
set(USERFILE_PLATFORM Win${BITS})
endif()
set(_pathdelim ";")
set(_suffix "cmd")
else()
set(_pathdelim ":")
set(USERFILE_PLATFORM ${CMAKE_SYSTEM_NAME}${BITS})
set(_suffix "sh")
find_package(GDB QUIET)
if(GDB_FOUND)
set(LAUNCHERS_GOT_GDB YES)
if(GDB_HAS_RETURN_CHILD_RESULT)
set(LAUNCHERS_GDB_ARG --return-child-result)
endif()
else()
set(LAUNCHERS_GOT_GDB)
endif()
endif()
if(WIN32 AND NOT USERFILE_REMOTE_MACHINE)
site_name(USERFILE_REMOTE_MACHINE)
mark_as_advanced(USERFILE_REMOTE_MACHINE)
endif()
endmacro()
macro(_launcher_process_args)
set(_nowhere)
set(_curdest _nowhere)
set(_val_args
ARGS
RUNTIME_LIBRARY_DIRS
WORKING_DIRECTORY
ENVIRONMENT)
set(_bool_args FORWARD_ARGS)
foreach(_arg ${_val_args} ${_bool_args})
set(${_arg})
endforeach()
foreach(_element ${ARGN})
list(FIND _val_args "${_element}" _val_arg_find)
list(FIND _bool_args "${_element}" _bool_arg_find)
if("${_val_arg_find}" GREATER "-1")
set(_curdest "${_element}")
elseif("${_bool_arg_find}" GREATER "-1")
set("${_element}" ON)
set(_curdest _nowhere)
else()
list(APPEND ${_curdest} "${_element}")
endif()
endforeach()
if(_nowhere)
message(FATAL_ERROR
"Syntax error in use of a function in CreateLaunchers!")
endif()
# Turn into a list of native paths
set(_runtime_lib_dirs)
foreach(_dlldir ${RUNTIME_LIBRARY_DIRS})
file(TO_NATIVE_PATH "${_dlldir}" _path)
set(_runtime_lib_dirs "${_runtime_lib_dirs}${_path}${_pathdelim}")
endforeach()
if(NOT WORKING_DIRECTORY)
set(WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}")
endif()
if(FORWARD_ARGS)
if(WIN32)
set(FWD_ARGS %*)
else()
set(FWD_ARGS $*)
endif()
else()
set(FWD_ARGS)
endif()
set(USERFILE_WORKING_DIRECTORY "${WORKING_DIRECTORY}")
set(USERFILE_COMMAND_ARGUMENTS "${ARGS}")
set(LAUNCHERSCRIPT_COMMAND_ARGUMENTS "${ARGS} ${FWD_ARGS}")
if(WIN32)
set(RUNTIME_LIBRARIES_ENVIRONMENT "PATH=${_runtime_lib_dirs};%PATH%")
file(READ
"${_launchermoddir}/launcher.env.cmd.in"
_cmdenv)
else()
if(APPLE)
set(RUNTIME_LIBRARIES_ENVIRONMENT
"DYLD_LIBRARY_PATH=${_runtime_lib_dirs}:$DYLD_LIBRARY_PATH")
else()
set(RUNTIME_LIBRARIES_ENVIRONMENT
"LD_LIBRARY_PATH=${_runtime_lib_dirs}:$LD_LIBRARY_PATH")
endif()
file(READ
"${_launchermoddir}/launcher.env.sh.in"
_cmdenv)
endif()
set(USERFILE_ENVIRONMENT "${RUNTIME_LIBRARIES_ENVIRONMENT}")
set(USERFILE_ENV_COMMANDS)
foreach(_arg "${RUNTIME_LIBRARIES_ENVIRONMENT}" ${ENVIRONMENT})
string(CONFIGURE
"@USERFILE_ENVIRONMENT@@LAUNCHER_LINESEP@@_arg@"
USERFILE_ENVIRONMENT
@ONLY)
string(CONFIGURE
"@USERFILE_ENV_COMMANDS@${_cmdenv}"
USERFILE_ENV_COMMANDS
@ONLY)
endforeach()
endmacro()
macro(_launcher_produce_vcproj_user)
if(MSVC)
file(READ
"${_launchermoddir}/perconfig.${VCPROJ_TYPE}.user.in"
_perconfig)
set(USERFILE_CONFIGSECTIONS)
foreach(USERFILE_CONFIGNAME ${CMAKE_CONFIGURATION_TYPES})
get_target_property(USERFILE_${USERFILE_CONFIGNAME}_COMMAND
${_targetname}
LOCATION_${USERFILE_CONFIGNAME})
file(TO_NATIVE_PATH
"${USERFILE_${USERFILE_CONFIGNAME}_COMMAND}"
USERFILE_${USERFILE_CONFIGNAME}_COMMAND)
string(CONFIGURE "${_perconfig}" _temp @ONLY ESCAPE_QUOTES)
string(CONFIGURE
"${USERFILE_CONFIGSECTIONS}${_temp}"
USERFILE_CONFIGSECTIONS
ESCAPE_QUOTES)
endforeach()
configure_file("${_launchermoddir}/${VCPROJ_TYPE}.user.in"
${VCPROJNAME}.${VCPROJ_TYPE}.${USERFILE_EXTENSION}
@ONLY)
endif()
endmacro()
macro(_launcher_configure_executable _src _tmp _target)
# get_filename_component(_targetname "${_target}" NAME)
get_filename_component(_targetpath "${_target}" PATH)
configure_file("${_src}"
"${_tmp}"
@ONLY)
file(COPY "${_tmp}"
DESTINATION "${_targetpath}"
FILE_PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_WRITE GROUP_EXECUTE WORLD_READ WORLD_EXECUTE)
endmacro()
macro(_launcher_create_target_launcher)
if(CMAKE_CONFIGURATION_TYPES)
# Multi-config generator - multiple launchers
foreach(_config ${CMAKE_CONFIGURATION_TYPES})
get_target_property(USERFILE_${_config}_COMMAND
${_targetname}
LOCATION_${_config})
file(TO_NATIVE_PATH
"${USERFILE_${_config}_COMMAND}"
USERFILE_COMMAND)
set(_fn "launch-${_targetname}-${_config}.${_suffix}")
_launcher_configure_executable("${_launchermoddir}/targetlauncher.${_suffix}.in"
"${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/${_fn}"
"${CMAKE_CURRENT_BINARY_DIR}/${_fn}")
endforeach()
else()
# Single-config generator - single launcher
get_target_property(USERFILE_COMMAND
${_targetname}
LOCATION)
file(TO_NATIVE_PATH
"${USERFILE_COMMAND}"
USERFILE_COMMAND)
_launcher_configure_executable("${_launchermoddir}/targetlauncher.${_suffix}.in"
"${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/launch-${_targetname}.${_suffix}"
"${CMAKE_CURRENT_BINARY_DIR}/launch-${_targetname}.${_suffix}"
@ONLY)
endif()
endmacro()
function(create_default_target_launcher _targetname)
_launcher_system_settings()
_launcher_process_args(${ARGN})
set(VCPROJNAME "${CMAKE_BINARY_DIR}/ALL_BUILD")
_launcher_produce_vcproj_user()
_launcher_create_target_launcher()
endfunction()
function(create_target_launcher _targetname)
_launcher_system_settings()
_launcher_process_args(${ARGN})
set(VCPROJNAME "${CMAKE_CURRENT_BINARY_DIR}/${_targetname}")
_launcher_produce_vcproj_user()
_launcher_create_target_launcher()
endfunction()
function(create_generic_launcher _launchername)
_launcher_system_settings()
_launcher_process_args(${ARGN})
if(NOT IS_ABSOLUTE _launchername)
set(_launchername
"${CMAKE_CURRENT_BINARY_DIR}/${_launchername}.${_suffix}")
else()
set(_launchername "${_launchername}.${_suffix}")
endif()
if(WIN32)
set(GENERIC_LAUNCHER_COMMAND "${_launchername}" PARENT_SCOPE)
set(GENERIC_LAUNCHER_FAIL_REGULAR_EXPRESSION)
else()
set(GENERIC_LAUNCHER_COMMAND sh "${_launchername}" PARENT_SCOPE)
set(GENERIC_LAUNCHER_FAIL_REGULAR_EXPRESSION
"Program terminated with signal")
endif()
_launcher_configure_executable("${_launchermoddir}/genericlauncher.${_suffix}.in"
"${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/genericlauncher.${_suffix}.in"
"${_launchername}")
endfunction()
function(guess_runtime_library_dirs _var)
# Start off with the link directories of the calling listfile's directory
get_directory_property(_libdirs LINK_DIRECTORIES)
# Add additional libraries passed to the function
foreach(_lib ${ARGN})
get_filename_component(_libdir "${_lib}" PATH)
list(APPEND _libdirs "${_libdir}")
endforeach()
# Now, build a list of potential dll directories
set(_dlldirs)
foreach(_libdir ${_libdirs})
# Add the libdir itself
list(APPEND _dlldirs "${_libdir}")
# Look also in libdir/../bin since the dll might not be with the lib
get_filename_component(_libdir "${_libdir}/../bin" ABSOLUTE)
list(APPEND _dlldirs "${_libdir}")
endforeach()
# Only keep the valid, unique directories
clean_directory_list(_dlldirs)
# Return _dlldirs
set(${_var} "${_dlldirs}" PARENT_SCOPE)
endfunction()

View file

@ -1,5 +1,7 @@
cmake_minimum_required( VERSION 2.4 )
make_release_only()
if( "${CMAKE_C_COMPILER_ID}" STREQUAL "GNU" OR "${CMAKE_C_COMPILER_ID}" STREQUAL "Clang" )
set( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -fomit-frame-pointer" )
endif( "${CMAKE_C_COMPILER_ID}" STREQUAL "GNU" OR "${CMAKE_C_COMPILER_ID}" STREQUAL "Clang" )

View file

@ -1,5 +1,7 @@
cmake_minimum_required( VERSION 2.4 )
make_release_only()
include( CheckFunctionExists )
# DUMB is much slower in a Debug build than a Release build, so we force a Release

View file

@ -3950,6 +3950,7 @@ static int delta_to_note(float delta, int base)
return (int)note;
}
#if 0
// Period table for Protracker octaves 0-5:
static const unsigned short ProTrackerPeriodTable[6*12] =
{
@ -3981,6 +3982,7 @@ static const unsigned short ProTrackerTunedPeriods[16*12] =
1736,1640,1548,1460,1378,1302,1228,1160,1094,1032,974,920,
1724,1628,1536,1450,1368,1292,1220,1150,1086,1026,968,914
};
#endif
static void process_all_playing(DUMB_IT_SIGRENDERER *sigrenderer)
{
@ -4400,6 +4402,7 @@ static int process_tick(DUMB_IT_SIGRENDERER *sigrenderer)
int dumb_it_max_to_mix = 64;
#if 0
static const int aiMODVol[] =
{
0,
@ -4425,6 +4428,7 @@ static const int aiPTMVolScaled[] =
836, 847, 859, 870, 881, 897, 908, 916,
927, 939, 950, 962, 969, 983, 1005, 1024
};
#endif
static float calculate_volume(DUMB_IT_SIGRENDERER *sigrenderer, IT_PLAYING *playing, double volume)
{

View file

@ -31,8 +31,8 @@ static int it_riff_dsmf_process_sample( IT_SAMPLE * sample, const unsigned char
int flags;
memcpy( sample->filename, data, 13 );
sample->filename[ 14 ] = 0;
sample->filename[ 13 ] = 0;
flags = data[ 13 ] | ( data[ 14 ] << 8 );
sample->default_volume = data[ 15 ];
sample->length = data[ 16 ] | ( data[ 17 ] << 8 ) | ( data[ 18 ] << 16 ) | ( data[ 19 ] << 24 );

View file

@ -486,7 +486,7 @@ static DUMB_IT_SIGDATA *it_okt_load_sigdata(DUMBFILE *f)
/* And finally, the sample data */
k = get_chunk_count(mod, DUMB_ID('S','B','O','D'));
for (i = 0, j = 0; i < (unsigned)sigdata->n_samples, j < k; i++) {
for (i = 0, j = 0; i < (unsigned)sigdata->n_samples && j < k; i++) {
if (sigdata->sample[i].flags & IT_SAMPLE_EXISTS) {
chunk = get_chunk_by_type(mod, DUMB_ID('S','B','O','D'), j);
if (it_okt_read_sample_data(&sigdata->sample[i], (const char *)chunk->data, chunk->size)) {
@ -503,7 +503,7 @@ static DUMB_IT_SIGDATA *it_okt_load_sigdata(DUMBFILE *f)
chunk = get_chunk_by_type(mod, DUMB_ID('C','M','O','D'), 0);
for (i = 0, j = 0; i < n_channels, j < 4; j++) {
for (i = 0, j = 0; i < n_channels && j < 4; j++) {
k = (chunk->data[j * 2] << 8) | chunk->data[j * 2 + 1];
l = (j == 1 || j == 2) ? 48 : 16;
if (k == 0) {

View file

@ -1,5 +1,17 @@
cmake_minimum_required( VERSION 2.4 )
include( CheckCXXCompilerFlag )
# CMake project definition file.
project(libgme)
include (CheckCXXCompilerFlag)
# When version is changed, also change the one in gme/gme.h to match
set(GME_VERSION 0.6.0 CACHE INTERNAL "libgme Version")
# 2.6+ always assumes FATAL_ERROR, but 2.4 and below don't.
# Of course, 2.4 might work, in which case you're welcome to drop
# down the requirement, but I can't test that.
cmake_minimum_required(VERSION 2.6 FATAL_ERROR)
make_release_only()
# I don't plan on debugging this, so make it a release build.
if( NOT CMAKE_BUILD_TYPE MATCHES "Release" )
@ -17,51 +29,80 @@ if( "${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" OR "${CMAKE_CXX_COMPILER_ID}" STRE
endif( HAVE_NO_ARRAY_BOUNDS )
endif( "${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" OR "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang" )
add_library( gme
gme/Blip_Buffer.cpp
gme/Classic_Emu.cpp
gme/Data_Reader.cpp
gme/Dual_Resampler.cpp
gme/Effects_Buffer.cpp
gme/Fir_Resampler.cpp
gme/gme.cpp
gme/Gme_File.cpp
gme/M3u_Playlist.cpp
gme/Multi_Buffer.cpp
gme/Music_Emu.cpp
gme/Ay_Apu.cpp
gme/Ay_Cpu.cpp
gme/Ay_Emu.cpp
gme/Gb_Apu.cpp
gme/Gb_Cpu.cpp
gme/Gb_Oscs.cpp
gme/Gbs_Emu.cpp
gme/Gym_Emu.cpp
gme/Hes_Apu.cpp
gme/Hes_Cpu.cpp
gme/Hes_Emu.cpp
gme/Kss_Cpu.cpp
gme/Kss_Emu.cpp
gme/Kss_Scc_Apu.cpp
gme/Nes_Apu.cpp
gme/Nes_Cpu.cpp
gme/Nes_Fme7_Apu.cpp
gme/Nes_Namco_Apu.cpp
gme/Nes_Oscs.cpp
gme/Nes_Vrc6_Apu.cpp
gme/Nsf_Emu.cpp
gme/Nsfe_Emu.cpp
gme/Sap_Apu.cpp
gme/Sap_Cpu.cpp
gme/Sap_Emu.cpp
gme/Sms_Apu.cpp
gme/Snes_Spc.cpp
gme/Spc_Cpu.cpp
gme/Spc_Dsp.cpp
gme/Spc_Emu.cpp
gme/Vgm_Emu.cpp
gme/Vgm_Emu_Impl.cpp
gme/Ym2413_Emu.cpp
gme/Ym2612_Emu.cpp )
target_link_libraries( gme )
# Default emulators to build (all of them! ;)
if (NOT DEFINED USE_GME_AY)
SET(USE_GME_AY 1 CACHE BOOL "Enable support for Spectrum ZX music emulation")
endif()
if (NOT DEFINED USE_GME_GBS)
SET(USE_GME_GBS 1 CACHE BOOL "Enable support for Game Boy music emulation")
endif()
if (NOT DEFINED USE_GME_GYM)
SET(USE_GME_GYM 1 CACHE BOOL "Enable Sega MegaDrive/Genesis music emulation")
endif()
if (NOT DEFINED USE_GME_HES)
SET(USE_GME_HES 1 CACHE BOOL "Enable PC Engine/TurboGrafx-16 music emulation")
endif()
if (NOT DEFINED USE_GME_KSS)
SET(USE_GME_KSS 1 CACHE BOOL "Enable MSX or other Z80 systems music emulation")
endif()
if (NOT DEFINED USE_GME_NSF)
SET(USE_GME_NSF 1 CACHE BOOL "Enable NES NSF music emulation")
endif()
if (NOT DEFINED USE_GME_NSFE)
SET(USE_GME_NSFE 1 CACHE BOOL "Enable NES NSFE and NSF music emulation")
endif()
if (NOT DEFINED USE_GME_SAP)
SET(USE_GME_SAP 1 CACHE BOOL "Enable Atari SAP music emulation")
endif()
if (NOT DEFINED USE_GME_SPC)
SET(USE_GME_SPC 1 CACHE BOOL "Enable SNES SPC music emulation")
endif()
if (NOT DEFINED USE_GME_VGM)
SET(USE_GME_VGM 1 CACHE BOOL "Enable Sega VGM/VGZ music emulation")
endif()
if (USE_GME_NSFE AND NOT USE_GME_NSF)
MESSAGE(" -- NSFE support requires NSF, enabling NSF support. --")
SET(USE_GME_NSF 1 CACHE BOOL "Enable NES NSF music emulation" FORCE)
endif()
# Check for GCC "visibility" support.
if (CMAKE_COMPILER_IS_GNUCXX)
check_cxx_compiler_flag (-fvisibility=hidden __LIBGME_TEST_VISIBILITY)
set (ENABLE_VISIBILITY OFF)
if (__LIBGME_TEST_VISIBILITY)
# get the gcc version
exec_program(${CMAKE_CXX_COMPILER} ARGS --version OUTPUT_VARIABLE _gcc_version_info)
string (REGEX MATCH "[3-9]\\.[0-9]\\.[0-9]" _gcc_version "${_gcc_version_info}")
# gcc <4.1 had poor support for symbol visibility
if ((${_gcc_version} VERSION_GREATER "4.1") OR (${_gcc_version} VERSION_EQUAL "4.1"))
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fvisibility=hidden")
set (ENABLE_VISIBILITY ON)
add_definitions (-DLIBGME_VISIBILITY)
# GCC >= 4.2 also correctly supports making inline members have hidden
# visibility by default.
if ((${_gcc_version} VERSION_GREATER "4.2") OR (${_gcc_version} VERSION_EQUAL "4.2"))
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fvisibility-inlines-hidden")
endif()
endif()
endif() # test visibility
endif (CMAKE_COMPILER_IS_GNUCXX)
# Cache this result
set( LIBGME_HAVE_GCC_VISIBILITY ${ENABLE_VISIBILITY} CACHE BOOL "GCC support for hidden visibility")
# Shared library defined here
add_subdirectory(gme)

View file

@ -1,6 +1,50 @@
Game_Music_Emu Change Log
-------------------------
Game_Music_Emu 0.6.0
--------------------
- Note: A 0.5.6 release was referenced but never tagged or packaged.
- SPC improvements:
- Switched to newer snes_spc 0.9.0 for SPC emulation. Uses fast DSP.
- Fixed Spc_Emu::gain().
- Fixed support for files <0x10200 bytes.
- Other bugfixes:
- Fixed a couple of GBS bugs, one involving access of memory after
realloc.
- Blip_Buffer works on systems where 'double' is a single-precision
floating-point type.
- Fix uninitialized buffer size in dual_resampler.
- Compilation warnings squashed out as of clang 3.3-pre and gcc 4.7.2.
- API changes/additions:
- Removed documentation of C++ interface, as the C interface in gme.h is
the only supported one.
- Added gme_enable_accuracy() for enabling more accurate sound emulation
options (currently affects SPC only).
- Build system improvements:
- Add pkg_config support.
- Fix build on case-insensitive systems.
- Allow for install on Cygwin.
- Fix install on multilib systems, such as many 64-bit distros (CMake must
be able to figure out your system's libsuffix, if any).
- C++ implementation symbols are not leaked into the resultant library
file (requires symbol visibility support).
- Sample player improvements:
- Can toggle fast/accurate emulation (with the 'A' key).
Game_Music_Emu 0.5.5
--------------------
- CMake build support has been added. You can build Game_Music_Emu as
a shared library and install it so that you do not have to include your
own copy if you know libgme will be present on your target system.
Requires CMake 2.6 or higher.
Game_Music_Emu 0.5.2
--------------------
- *TONS* of changes and improvements. You should re-read the new header

View file

@ -1,4 +1,4 @@
Game_Music_Emu 0.5.2 Design
Game_Music_Emu 0.6.0 Design
---------------------------
This might be slightly out-of-date at times, but will be a big help in
understanding the library implementation.

View file

@ -80,6 +80,69 @@
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Debug|x64"
OutputDirectory="$(SolutionDir)$(PlatformName)\$(ConfigurationName)"
IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
ConfigurationType="4"
CharacterSet="2"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
TargetEnvironment="3"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
PreprocessorDefinitions="WIN32;_DEBUG;_LIB"
MinimalRebuild="true"
BasicRuntimeChecks="3"
RuntimeLibrary="1"
UsePrecompiledHeader="0"
WarningLevel="3"
Detect64BitPortabilityProblems="true"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLibrarianTool"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
@ -146,6 +209,73 @@
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|x64"
OutputDirectory="$(SolutionDir)$(PlatformName)\$(ConfigurationName)"
IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
ConfigurationType="4"
CharacterSet="2"
WholeProgramOptimization="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
TargetEnvironment="3"
/>
<Tool
Name="VCCLCompilerTool"
EnableIntrinsicFunctions="true"
FavorSizeOrSpeed="1"
OmitFramePointers="true"
WholeProgramOptimization="false"
PreprocessorDefinitions="WIN32;NDEBUG;_LIB"
StringPooling="true"
ExceptionHandling="0"
RuntimeLibrary="0"
UsePrecompiledHeader="0"
WarningLevel="3"
Detect64BitPortabilityProblems="true"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLibrarianTool"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release DLL|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
@ -221,136 +351,6 @@
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Debug|x64"
OutputDirectory="$(SolutionDir)$(PlatformName)\$(ConfigurationName)"
IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
ConfigurationType="4"
CharacterSet="2"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
TargetEnvironment="3"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
PreprocessorDefinitions="WIN32;_DEBUG;_LIB"
MinimalRebuild="true"
BasicRuntimeChecks="3"
RuntimeLibrary="1"
UsePrecompiledHeader="0"
WarningLevel="3"
Detect64BitPortabilityProblems="true"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLibrarianTool"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|x64"
OutputDirectory="$(SolutionDir)$(PlatformName)\$(ConfigurationName)"
IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
ConfigurationType="4"
CharacterSet="2"
WholeProgramOptimization="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
TargetEnvironment="3"
/>
<Tool
Name="VCCLCompilerTool"
EnableIntrinsicFunctions="true"
FavorSizeOrSpeed="1"
OmitFramePointers="true"
WholeProgramOptimization="false"
PreprocessorDefinitions="WIN32;NDEBUG;_LIB"
StringPooling="true"
ExceptionHandling="0"
RuntimeLibrary="0"
UsePrecompiledHeader="0"
WarningLevel="3"
Detect64BitPortabilityProblems="true"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLibrarianTool"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release DLL|x64"
OutputDirectory="$(SolutionDir)$(PlatformName)\$(ConfigurationName)"
@ -601,6 +601,10 @@
RelativePath=".\gme\Spc_Emu.cpp"
>
</File>
<File
RelativePath=".\gme\Spc_Filter.cpp"
>
</File>
<File
RelativePath=".\gme\Vgm_Emu.cpp"
>
@ -703,6 +707,10 @@
RelativePath=".\gme\Gme_File.h"
>
</File>
<File
RelativePath=".\gme\gme_types.h"
>
</File>
<File
RelativePath=".\gme\Gym_Emu.h"
>
@ -823,6 +831,10 @@
RelativePath=".\gme\Spc_Emu.h"
>
</File>
<File
RelativePath=".\gme\Spc_Filter.h"
>
</File>
<File
RelativePath=".\gme\Vgm_Emu.h"
>

View file

@ -1,15 +1,14 @@
Game_Music_Emu 0.5.2
Game_Music_Emu 0.6.0
--------------------
Author : Shay Green <gblargg@gmail.com>
Website: http://www.slack.net/~ant/libs/
Forum : http://groups.google.com/group/blargg-sound-libs
Source : https://code.google.com/p/game-music-emu/
License: GNU Lesser General Public License (LGPL)
Contents
--------
* Overview
* C and C++ interfaces
* Function reference
* Error handling
* Emulator types
* M3U playlist support
@ -21,7 +20,6 @@ Contents
* Modular construction
* Obscure features
* Solving problems
* Deprecated features
* Thanks
@ -62,56 +60,15 @@ deleted with gme_set_user_cleanup()
Refer to gme.h for a comprehensive summary of features.
C and C++ interfaces
--------------------
While the library is written in C++, an extensive C interface is
provided in gme.h. This C interface will be referred to throughout this
documentation unless a feature is only available in the full C++
interface. All C interface functions and other names have the gme_
prefix, so you can recognize a C++-only feature by the lack of gme_ in
the names used (contact me if you'd like a feature added to the C
interface). If you're building a shared library, I highly recommend
sticking to the C interface only, because it will be more stable between
releases of the library than the C++ interface. Finally, the C and C++
interfaces can be freely mixed without problems. Compare demo/basics.c
with demo/cpp_basics.cpp to see how the C and C++ interfaces translate
between each other.
Function reference
------------------
Read the following header files for a complete reference to functions
and features. The second group of header files can only be used in C++.
blargg_config.h Library configuration
gme.h C interface (also usable from C++)
Gme_File.h File loading and track information
Music_Emu.h Track playback and adjustments
Data_Reader.h Custom data readers
Effects_Buffer.h Sound buffer with adjustable stereo echo and panning
M3u_Playlist.h M3U playlist support
Gbs_Emu.h GBS equalizer settings
Nsf_Emu.h NSF equalizer settings
Spc_Emu.h SPC surround disable
Vgm_Emu.h VGM oversampling disable and custom buffer query
Error handling
--------------
Functions which can fail have a return type of gme_err_t (blargg_err_t
in the C++ interfaces), which is a pointer to an error string (const
char*). If a function is successful it returns NULL. Errors that you can
easily avoid are checked with debug assertions; gme_err_t return values
are only used for genuine run-time errors that can't be easily predicted
in advance (out of memory, I/O errors, incompatible file data). Your
code should check all error values.
To improve usability for C programmers, C++ programmers unfamiliar with
exceptions, and compatibility with older C++ compilers, the library does
*not* throw any C++ exceptions and uses malloc() instead of the standard
operator new. This means that you *must* check for NULL when creating a
library object with the new operator.
Functions which can fail have a return type of gme_err_t, which is a
pointer to an error string (const char*). If a function is successful it
returns NULL. Errors that you can easily avoid are checked with debug
assertions; gme_err_t return values are only used for genuine run-time
errors that can't be easily predicted in advance (out of memory, I/O
errors, incompatible file data). Your code should check all error
values.
When loading a music file in the wrong emulator or trying to load a
non-music file, gme_wrong_file_type is returned. You can check for this
@ -154,7 +111,9 @@ If you want to remove support for some music types to reduce your
executable size, edit GME_TYPE_LIST in blargg_config.h. For example, to
support just NSF and GBS, use this:
#define GME_TYPE_LIST gme_nsf_type, gme_gbs_type
#define GME_TYPE_LIST \
gme_nsf_type,\
gme_gbs_type
M3U playlist support
@ -271,40 +230,6 @@ create an emulator, you can use the following methods of loading:
error = gme_load_custom( emu, my_read, file_size, my_data );
* If you must load the file data into memory yourself, you can have the
library use your data directly *without* making a copy. If you do this,
you must not free the data until you're done playing the file.
error = emu->load_mem( pointer, size );
* If you've already read the first bytes of a file (perhaps to determine
the file type) and want to avoid seeking back to the beginning for
performance reasons, use Remaining_Reader:
Std_File_Reader in;
error = in.open( file_path );
char header [4];
error = in.read( &header, sizeof header );
...
Remaining_Reader rem( &header, sizeof header, &in );
error = emu->load( rem );
If you merely need access to a file's header after loading, use the
emulator-specific header() functions, after casting the Music_Emu
pointer to the specific emulator's type. This example examines the
chip_flags field of the header if it's an NSF file:
if ( music_emu->type() == gme_nsf_type )
{
Nsf_Emu* nsf_emu = (Nsf_Emu*) music_emu;
if ( nsf_emu->header().chip_flags & 0x01 )
...
}
Contact me if you want more information about loading files.
Sound parameters
----------------
@ -437,21 +362,6 @@ separate threads.
* If all else fails, see if the demos work.
Deprecated features
-------------------
The following functions and other features have been deprecated and will
be removed in a future release of the library. Alternatives to the
deprecated features are listed to the right.
Music_Emu::error_count() warning()
load( header, reader ) see "Loading file data" above
Spc_Emu::trailer() track_info()
Spc_Emu::trailer_size()
Gym_Emu::track_length() track_info()
Vgm_Emu::gd3_data() track_info()
Nsfe_Emu::disable_playlist() clear_playlist()
Thanks
------
Big thanks to Chris Moeller (kode54) for help with library testing and
@ -461,4 +371,6 @@ Brad Martin's excellent OpenSPC SNES DSP emulator worked well from the
start. Also thanks to Richard Bannister, Mahendra Tallur, Shazz,
nenolod, theHobbit, Johan Samuelsson, and nes6502 for testing, using,
and giving feedback for the library in their respective game music
players.
players. More recently, Lucas Paul and Michael Pyne have helped nudge the
library into a public repository and get its interface more stable for use
in shared libraries.

View file

@ -1,4 +1,4 @@
// Game_Music_Emu 0.5.2. http://www.slack.net/~ant/
// Game_Music_Emu 0.6.0. http://www.slack.net/~ant/
#include "Ay_Apu.h"
@ -123,8 +123,8 @@ void Ay_Apu::write_data_( int addr, int data )
if ( (unsigned) addr >= 14 )
{
#ifdef dprintf
dprintf( "Wrote to I/O port %02X\n", (int) addr );
#ifdef debug_printf
debug_printf( "Wrote to I/O port %02X\n", (int) addr );
#endif
}
@ -220,7 +220,7 @@ void Ay_Apu::run_until( blip_time_t final_end_time )
end_time = final_end_time;
//if ( !(regs [12] | regs [11]) )
// dprintf( "Used envelope period 0\n" );
// debug_printf( "Used envelope period 0\n" );
}
else if ( !volume )
{
@ -250,7 +250,7 @@ void Ay_Apu::run_until( blip_time_t final_end_time )
ntime = start_time + old_noise_delay;
noise_lfsr = old_noise_lfsr;
//if ( (regs [6] & 0x1F) == 0 )
// dprintf( "Used noise period 0\n" );
// debug_printf( "Used noise period 0\n" );
}
// The following efficiently handles several cases (least demanding first):

View file

@ -1,6 +1,6 @@
// AY-3-8910 sound chip emulator
// Game_Music_Emu 0.5.2
// Game_Music_Emu 0.6.0
#ifndef AY_APU_H
#define AY_APU_H
@ -50,7 +50,6 @@ private:
Blip_Buffer* output;
} oscs [osc_count];
blip_time_t last_time;
byte latch;
byte regs [reg_count];
struct {

View file

@ -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
@ -469,7 +469,7 @@ possibly_out_of_time:
add_hl_data: {
blargg_ulong sum = rp.hl + data;
data ^= rp.hl;
rp.hl = sum;
rp.hl = (uint16_t)sum;
flags = (flags & (S80 | Z40 | V04)) |
(sum >> 16) |
(sum >> 8 & (F20 | F08)) |
@ -719,7 +719,7 @@ possibly_out_of_time:
flags = (flags & (S80 | Z40 | P04)) |
(temp & (F20 | F08)) |
(temp >> 8);
rg.a = temp;
rg.a = (uint8_t)temp;
goto loop;
}
@ -807,6 +807,7 @@ possibly_out_of_time:
case 0xCB:
unsigned data2;
data2 = INSTR( 1 );
(void) data2; // TODO is this the same as data in all cases?
pc++;
switch ( data )
{
@ -1055,7 +1056,7 @@ possibly_out_of_time:
(temp >> 8 & H10) |
(sum >> 8 & (S80 | F20 | F08)) |
((temp - -0x8000) >> 14 & V04);
rp.hl = sum;
rp.hl = (uint16_t)sum;
if ( (uint16_t) sum )
goto loop;
flags |= Z40;
@ -1252,7 +1253,7 @@ possibly_out_of_time:
case 0x4F: // LD R,A
SET_R( rg.a );
dprintf( "LD R,A not supported\n" );
debug_printf( "LD R,A not supported\n" );
warning = true;
goto loop;
@ -1262,7 +1263,7 @@ possibly_out_of_time:
case 0x5F: // LD A,R
rg.a = GET_R();
dprintf( "LD A,R not supported\n" );
debug_printf( "LD A,R not supported\n" );
warning = true;
ld_ai_common:
flags = (flags & C01) | SZ28( rg.a ) | (r.iff2 << 2 & V04);
@ -1285,7 +1286,7 @@ possibly_out_of_time:
goto loop;
default:
dprintf( "Opcode $ED $%02X not supported\n", data );
debug_printf( "Opcode $ED $%02X not supported\n", data );
warning = true;
goto loop;
}
@ -1545,7 +1546,7 @@ possibly_out_of_time:
}
default:
dprintf( "Opcode $%02X $CB $%02X not supported\n", opcode, data2 );
debug_printf( "Opcode $%02X $CB $%02X not supported\n", opcode, data2 );
warning = true;
goto loop;
}
@ -1634,7 +1635,7 @@ possibly_out_of_time:
}
default:
dprintf( "Unnecessary DD/FD prefix encountered\n" );
debug_printf( "Unnecessary DD/FD prefix encountered\n" );
warning = true;
pc--;
goto loop;
@ -1643,7 +1644,7 @@ possibly_out_of_time:
}
}
dprintf( "Unhandled main opcode: $%02X\n", opcode );
debug_printf( "Unhandled main opcode: $%02X\n", opcode );
assert( false );
halt:

View file

@ -1,6 +1,6 @@
// Z80 CPU emulator
// Game_Music_Emu 0.5.2
// Game_Music_Emu 0.6.0
#ifndef AY_CPU_H
#define AY_CPU_H

View file

@ -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"
@ -209,9 +209,9 @@ blargg_err_t Ay_Emu::start_track_( int track )
set_warning( "Missing file data" );
len = unsigned(file.end - in);
}
//dprintf( "addr: $%04X, len: $%04X\n", addr, len );
//debug_printf( "addr: $%04X, len: $%04X\n", addr, len );
if ( addr < ram_start && addr >= 0x400 ) // several tracks use low data
dprintf( "Block addr in ROM\n" );
debug_printf( "Block addr in ROM\n" );
memcpy( mem.ram + addr, in, len );
if ( file.end - blocks < 8 )
@ -242,7 +242,7 @@ blargg_err_t Ay_Emu::start_track_( int track )
};
memcpy( mem.ram, passive, sizeof passive );
unsigned play_addr = get_be16( more_data + 4 );
//dprintf( "Play: $%04X\n", play_addr );
//debug_printf( "Play: $%04X\n", play_addr );
if ( play_addr )
{
memcpy( mem.ram, active, sizeof active );
@ -315,7 +315,7 @@ void Ay_Emu::cpu_out_misc( cpu_time_t time, unsigned addr, int data )
}
}
dprintf( "Unmapped OUT: $%04X <- $%02X\n", addr, data );
debug_printf( "Unmapped OUT: $%04X <- $%02X\n", addr, data );
return;
enable_cpc:
@ -356,7 +356,7 @@ int ay_cpu_in( Ay_Cpu*, unsigned addr )
if ( (addr & 0xFF) == 0xFE )
return 0xFF; // other values break some beeper tunes
dprintf( "Unmapped IN : $%04X\n", addr );
debug_printf( "Unmapped IN : $%04X\n", addr );
return 0xFF;
}

View file

@ -1,6 +1,6 @@
// Sinclair Spectrum AY music file emulator
// Game_Music_Emu 0.5.2
// Game_Music_Emu 0.6.0
#ifndef AY_EMU_H
#define AY_EMU_H
@ -46,7 +46,6 @@ protected:
private:
file_t file;
unsigned play_addr;
cpu_time_t play_period;
cpu_time_t next_play;
Blip_Buffer* beeper_output;

View file

@ -233,18 +233,32 @@ static void gen_sinc( float* out, int count, double oversample, double treble, d
double const to_angle = PI / 2 / maxh / oversample;
for ( int i = 0; i < count; i++ )
{
double angle = ((i - count) * 2 + 1) * to_angle;
double c = rolloff * cos( (maxh - 1.0) * angle ) - cos( maxh * angle );
double cos_nc_angle = cos( maxh * cutoff * angle );
double cos_nc1_angle = cos( (maxh * cutoff - 1.0) * angle );
double cos_angle = cos( angle );
double angle = ((i - count) * 2 + 1) * to_angle;
double angle_maxh = angle * maxh;
double angle_maxh_mid = angle_maxh * cutoff;
c = c * pow_a_n - rolloff * cos_nc1_angle + cos_nc_angle;
double d = 1.0 + rolloff * (rolloff - cos_angle - cos_angle);
double b = 2.0 - cos_angle - cos_angle;
double a = 1.0 - cos_angle - cos_nc_angle + cos_nc1_angle;
double y = maxh;
out [i] = (float) ((a * d + c * b) / (b * d)); // a / b + c / d
// 0 to Fs/2*cutoff, flat
if ( angle_maxh_mid ) // unstable at t=0
y *= sin( angle_maxh_mid ) / angle_maxh_mid;
// Fs/2*cutoff to Fs/2, logarithmic rolloff
double cosa = cos( angle );
double den = 1 + rolloff * (rolloff - cosa - cosa);
// Becomes unstable when rolloff is near 1.0 and t is near 0,
// which is the only time den becomes small
if ( den > 1e-13 )
{
double num =
(cos( angle_maxh - angle ) * rolloff - cos( angle_maxh )) * pow_a_n -
cos( angle_maxh_mid - angle ) * rolloff + cos( angle_maxh_mid );
y = y * cutoff + num / den;
}
out [i] = (float) y;
}
}

View 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)

View file

@ -1,4 +1,4 @@
// Game_Music_Emu 0.5.2. http://www.slack.net/~ant/
// Game_Music_Emu 0.6.0. http://www.slack.net/~ant/
#include "Classic_Emu.h"
@ -176,9 +176,9 @@ void Rom_Data_::set_addr_( long addr, int unit )
if ( 0 )
{
dprintf( "addr: %X\n", addr );
dprintf( "file_size: %d\n", file_size_ );
dprintf( "rounded: %d\n", rounded );
dprintf( "mask: $%X\n", mask );
debug_printf( "addr: %X\n", addr );
debug_printf( "file_size: %d\n", file_size_ );
debug_printf( "rounded: %d\n", rounded );
debug_printf( "mask: $%X\n", mask );
}
}

View file

@ -1,6 +1,6 @@
// Common aspects of emulators which use Blip_Buffer for sound output
// Game_Music_Emu 0.5.2
// Game_Music_Emu 0.6.0
#ifndef CLASSIC_EMU_H
#define CLASSIC_EMU_H

View file

@ -1,15 +1,14 @@
// File_Extractor 0.4.0. http://www.slack.net/~ant/
#define _CRT_SECURE_NO_WARNINGS
#define IN_GME 1
#include <assert.h>
#include <string.h>
#include <stdio.h>
#include "Data_Reader.h"
#include "blargg_endian.h"
#include <assert.h>
#include <string.h>
#include <stdio.h>
/* Copyright (C) 2005-2006 Shay Green. This module is free software; you
can redistribute it and/or modify it under the terms of the GNU Lesser
General Public License as published by the Free Software Foundation; either

View file

@ -5,7 +5,6 @@
#define DATA_READER_H
#include "blargg_common.h"
#include "gme.h"
// Supports reading and finding out how many bytes are remaining
class Data_Reader {
@ -117,7 +116,7 @@ private:
// Invokes callback function to read data. Size of data must be specified in advance.
class Callback_Reader : public Data_Reader {
public:
typedef const char* (GMEAPI *callback_t)( void* data, void* out, int count );
typedef const char* (*callback_t)( void* data, void* out, int count );
Callback_Reader( callback_t, long size, void* data = 0 );
public:
long read_avail( void*, long );

View file

@ -1,4 +1,4 @@
// Game_Music_Emu 0.5.2. http://www.slack.net/~ant/
// Game_Music_Emu 0.6.0. http://www.slack.net/~ant/
#include "Dual_Resampler.h"
@ -20,7 +20,13 @@ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
unsigned const resampler_extra = 256;
Dual_Resampler::Dual_Resampler() { }
Dual_Resampler::Dual_Resampler() :
sample_buf_size(0),
oversamples_per_frame(-1),
buf_pos(-1),
resampler_size(0)
{
}
Dual_Resampler::~Dual_Resampler() { }
@ -62,10 +68,10 @@ void Dual_Resampler::play_frame_( Blip_Buffer& blip_buf, dsample_t* out )
assert( blip_buf.samples_avail() == pair_count );
resampler.write( new_count );
long count = resampler.read( sample_buf.begin(), sample_buf_size );
assert( count == (long) sample_buf_size );
mix_samples( blip_buf, out );
blip_buf.remove_samples( pair_count );
}
@ -121,8 +127,8 @@ void Dual_Resampler::mix_samples( Blip_Buffer& blip_buf, dsample_t* out )
r = 0x7FFF - (r >> 24);
in += 2;
out [0] = l;
out [1] = r;
out [0] = (dsample_t)l;
out [1] = (dsample_t)r;
out += 2;
}

View file

@ -1,6 +1,6 @@
// Combination of Fir_Resampler and Blip_Buffer mixing. Used by Sega FM emulators.
// Game_Music_Emu 0.5.2
// Game_Music_Emu 0.6.0
#ifndef DUAL_RESAMPLER_H
#define DUAL_RESAMPLER_H

View file

@ -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"

View file

@ -1,6 +1,6 @@
// Multi-channel effects buffer with panning, echo and reverb
// Game_Music_Emu 0.5.2
// Game_Music_Emu 0.6.0
#ifndef EFFECTS_BUFFER_H
#define EFFECTS_BUFFER_H

View file

@ -1,4 +1,4 @@
// Game_Music_Emu 0.5.2. http://www.slack.net/~ant/
// Game_Music_Emu 0.6.0. http://www.slack.net/~ant/
#include "Fir_Resampler.h"
@ -156,7 +156,7 @@ int Fir_Resampler_::input_needed( blargg_long output_count ) const
output_count -= 2;
}
long input_extra = long(input_count - (write_pos - &buf [(width_ - 1) * stereo]));
long input_extra = input_count - (write_pos - &buf [(width_ - 1) * stereo]);
if ( input_extra < 0 )
input_extra = 0;
return input_extra;
@ -187,7 +187,7 @@ int Fir_Resampler_::avail_( blargg_long input_count ) const
int Fir_Resampler_::skip_input( long count )
{
int remain = int(write_pos - buf.begin());
int max_count = remain - width_ * stereo;
int max_count = int(remain - width_ * stereo);
if ( count > max_count )
count = max_count;

View file

@ -1,6 +1,6 @@
// Finite impulse response (FIR) resampler with adjustable FIR size
// Game_Music_Emu 0.5.2
// Game_Music_Emu 0.6.0
#ifndef FIR_RESAMPLER_H
#define FIR_RESAMPLER_H
@ -51,7 +51,7 @@ public:
int input_needed( blargg_long count ) const;
// Number of output samples available
int avail() const { return avail_( blargg_long(write_pos - &buf [width_ * stereo]) ); }
int avail() const { return avail_( blargg_long(write_pos - &buf [width_ * stereo] )); }
public:
~Fir_Resampler_();

View file

@ -271,7 +271,7 @@ void Gb_Apu::write_register( blip_time_t time, unsigned addr, int data )
}
else
{
//dprintf( "APU powered on\n" );
//debug_printf( "APU powered on\n" );
}
}
}

View file

@ -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"
@ -94,6 +94,7 @@ unsigned const c_flag = 0x10;
// -- produced by the BOOST_STATIC_ASSERT line below
#pragma warning(disable:4101)
#endif
bool Gb_Cpu::run( blargg_long cycle_count )
{
state_.remain = blargg_ulong (cycle_count + clocks_per_instr) / clocks_per_instr;
@ -716,7 +717,7 @@ loop:
temp += prev;
flags &= z_flag;
add_16_hl:
rp.hl = temp;
rp.hl = (uint16_t)temp;
add_16_comm:
flags |= (temp >> 12) & c_flag;
flags |= (((temp & 0x0FFF) - (prev & 0x0FFF)) >> 7) & h_flag;

View file

@ -1,7 +1,7 @@
// Nintendo Game Boy CPU emulator
// Treats every instruction as taking 4 cycles
// Game_Music_Emu 0.5.2
// Game_Music_Emu 0.6.0
#ifndef GB_CPU_H
#define GB_CPU_H

View file

@ -1,4 +1,4 @@
// Game_Music_Emu 0.5.2. http://www.slack.net/~ant/
// Game_Music_Emu 0.6.0. http://www.slack.net/~ant/
#include "Gbs_Emu.h"
@ -18,8 +18,10 @@ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
#include "blargg_source.h"
Gbs_Emu::equalizer_t const Gbs_Emu::handheld_eq = { -47.0, 2000, 0, 0, 0, 0, 0, 0, 0, 0 };
Gbs_Emu::equalizer_t const Gbs_Emu::headphones_eq = { 0.0, 300, 0, 0, 0, 0, 0, 0, 0, 0 };
Gbs_Emu::equalizer_t const Gbs_Emu::handheld_eq =
Music_Emu::make_equalizer( -47.0, 2000 );
Gbs_Emu::equalizer_t const Gbs_Emu::headphones_eq =
Music_Emu::make_equalizer( 0.0, 300 );
Gbs_Emu::Gbs_Emu()
{
@ -39,8 +41,7 @@ Gbs_Emu::Gbs_Emu()
set_max_initial_silence( 21 );
set_gain( 1.2 );
static equalizer_t const eq = { -1.0, 120, 0, 0, 0, 0, 0, 0, 0, 0 };
set_equalizer( eq );
set_equalizer( make_equalizer( -1.0, 120 ) );
}
Gbs_Emu::~Gbs_Emu() { }
@ -151,7 +152,7 @@ void Gbs_Emu::set_bank( int n )
{
// TODO: what is the correct behavior? Current Game & Watch Gallery
// rip requires that this have no effect or set to bank 1.
//dprintf( "Selected ROM bank 0\n" );
//debug_printf( "Selected ROM bank 0\n" );
return;
//n = 1;
}
@ -212,11 +213,11 @@ blargg_err_t Gbs_Emu::start_track_( int track )
for ( int i = 0; i < (int) sizeof sound_data; i++ )
apu.write_register( 0, i + apu.start_addr, sound_data [i] );
cpu::reset( rom.unmapped() );
unsigned load_addr = get_le16( header_.load_addr );
cpu::rst_base = load_addr;
rom.set_addr( load_addr );
cpu::rst_base = load_addr;
cpu::reset( rom.unmapped() );
cpu::map_code( ram_addr, 0x10000 - ram_addr, ram );
cpu::map_code( 0, bank_size, rom.at_addr( 0 ) );
@ -265,13 +266,13 @@ blargg_err_t Gbs_Emu::run_clocks( blip_time_t& duration, int )
}
else if ( cpu::r.pc > 0xFFFF )
{
dprintf( "PC wrapped around\n" );
debug_printf( "PC wrapped around\n" );
cpu::r.pc &= 0xFFFF;
}
else
{
set_warning( "Emulation error (illegal/unsupported instruction)" );
dprintf( "Bad opcode $%.2x at $%.4x\n",
debug_printf( "Bad opcode $%.2x at $%.4x\n",
(int) *cpu::get_code( cpu::r.pc ), (int) cpu::r.pc );
cpu::r.pc = (cpu::r.pc + 1) & 0xFFFF;
cpu_time += 6;

View file

@ -1,6 +1,6 @@
// Nintendo Game Boy GBS music file emulator
// Game_Music_Emu 0.5.2
// Game_Music_Emu 0.6.0
#ifndef GBS_EMU_H
#define GBS_EMU_H

View file

@ -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"

View file

@ -1,6 +1,6 @@
// Common interface to game music file loading and information
// Game_Music_Emu 0.5.2
// Game_Music_Emu 0.6.0
#ifndef GME_FILE_H
#define GME_FILE_H

View file

@ -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"

View file

@ -1,7 +1,7 @@
// Sega Genesis/Mega Drive GYM music file emulator
// Includes with PCM timing recovery to improve sample quality.
// Game_Music_Emu 0.5.2
// Game_Music_Emu 0.6.0
#ifndef GYM_EMU_H
#define GYM_EMU_H

View file

@ -1,4 +1,4 @@
// Game_Music_Emu 0.5.2. http://www.slack.net/~ant/
// Game_Music_Emu 0.6.0. http://www.slack.net/~ant/
#include "Hes_Apu.h"
@ -106,10 +106,10 @@ void Hes_Osc::run_until( synth_t& synth_, blip_time_t end_time )
unsigned noise_lfsr = this->noise_lfsr;
do
{
int new_dac = 0x1F & (unsigned)-(signed)(noise_lfsr >> 1 & 1);
int new_dac = 0x1F & (unsigned)-(int)(noise_lfsr >> 1 & 1);
// Implemented using "Galios configuration"
// TODO: find correct LFSR algorithm
noise_lfsr = (noise_lfsr >> 1) ^ (0xE008 & (unsigned)-(signed)(noise_lfsr & 1));
noise_lfsr = (noise_lfsr >> 1) ^ (0xE008 & (unsigned)-(int)(noise_lfsr & 1));
//noise_lfsr = (noise_lfsr >> 1) ^ (0x6000 & -(noise_lfsr & 1));
int delta = new_dac - dac;
if ( delta )
@ -158,7 +158,7 @@ void Hes_Osc::run_until( synth_t& synth_, blip_time_t end_time )
//period = 0x1000 * 2;
period = 1;
//if ( !(volume_0 | volume_1) )
// dprintf( "Used period 0\n" );
// debug_printf( "Used period 0\n" );
}
// maintain phase when silent
@ -295,7 +295,7 @@ void Hes_Apu::write_data( blip_time_t time, int addr, int data )
case 0x809:
if ( !(data & 0x80) && (data & 0x03) != 0 )
dprintf( "HES LFO not supported\n" );
debug_printf( "HES LFO not supported\n" );
}
}
}

View file

@ -1,6 +1,6 @@
// Turbo Grafx 16 (PC Engine) PSG sound chip emulator
// Game_Music_Emu 0.5.2
// Game_Music_Emu 0.6.0
#ifndef HES_APU_H
#define HES_APU_H

View file

@ -1,4 +1,4 @@
// Game_Music_Emu 0.5.2. http://www.slack.net/~ant/
// Game_Music_Emu 0.6.0. http://www.slack.net/~ant/
#include "Hes_Cpu.h"
@ -148,7 +148,7 @@ loop:
/*
static long count;
if ( count == 1844 ) Debugger();
if ( s.base != correct ) dprintf( "%ld\n", count );
if ( s.base != correct ) debug_printf( "%ld\n", count );
count++;
*/
}
@ -741,7 +741,7 @@ possibly_out_of_time:
ARITH_ADDR_MODES( 0x65 ) // ADC
adc_imm: {
if ( status & st_d )
dprintf( "Decimal mode not supported\n" );
debug_printf( "Decimal mode not supported\n" );
fint16 carry = c >> 8 & 1;
fint16 ov = (a ^ 0x80) + carry + (BOOST::int8_t) data; // sign-extend
status &= ~st_v;
@ -1085,7 +1085,7 @@ possibly_out_of_time:
goto loop;
}
delayed_cli:
dprintf( "Delayed CLI not supported\n" ); // TODO: implement
debug_printf( "Delayed CLI not supported\n" ); // TODO: implement
goto loop;
}
@ -1100,7 +1100,7 @@ possibly_out_of_time:
s_time += delta;
if ( s_time < 0 )
goto loop;
dprintf( "Delayed SEI not supported\n" ); // TODO: implement
debug_printf( "Delayed SEI not supported\n" ); // TODO: implement
goto loop;
}
@ -1145,7 +1145,7 @@ possibly_out_of_time:
goto loop;
case 0x54: // CSL
dprintf( "CSL not supported\n" );
debug_printf( "CSL not supported\n" );
illegal_encountered = true;
goto loop;
@ -1154,7 +1154,7 @@ possibly_out_of_time:
case 0xF4: { // SET
//fuint16 operand = GET_MSB();
dprintf( "SET not handled\n" );
debug_printf( "SET not handled\n" );
//switch ( data )
//{
//}
@ -1233,7 +1233,7 @@ possibly_out_of_time:
default:
assert( (unsigned) opcode <= 0xFF );
dprintf( "Illegal opcode $%02X at $%04X\n", (int) opcode, (int) pc - 1 );
debug_printf( "Illegal opcode $%02X at $%04X\n", (int) opcode, (int) pc - 1 );
illegal_encountered = true;
goto loop;
}

View file

@ -1,6 +1,6 @@
// PC Engine CPU emulator for use with HES music files
// Game_Music_Emu 0.5.2
// Game_Music_Emu 0.6.0
#ifndef HES_CPU_H
#define HES_CPU_H

View file

@ -1,4 +1,4 @@
// Game_Music_Emu 0.5.2. http://www.slack.net/~ant/
// Game_Music_Emu 0.6.0. http://www.slack.net/~ant/
#include "Hes_Emu.h"
@ -273,12 +273,12 @@ void Hes_Emu::cpu_write_vdp( int addr, int data )
}
else
{
dprintf( "VDP not supported: $%02X <- $%02X\n", vdp.latch, data );
debug_printf( "VDP not supported: $%02X <- $%02X\n", vdp.latch, data );
}
break;
case 3:
dprintf( "VDP MSB not supported: $%02X <- $%02X\n", vdp.latch, data );
debug_printf( "VDP MSB not supported: $%02X <- $%02X\n", vdp.latch, data );
break;
}
}
@ -325,7 +325,7 @@ void Hes_Emu::cpu_write_( hes_addr_t addr, int data )
run_until( time );
irq.disables = data;
if ( (data & 0xF8) && (data & 0xF8) != 0xF8 ) // flag questionable values
dprintf( "Int mask: $%02X\n", data );
debug_printf( "Int mask: $%02X\n", data );
break;
case 0x1403:
@ -344,7 +344,7 @@ void Hes_Emu::cpu_write_( hes_addr_t addr, int data )
return;
default:
dprintf( "unmapped write $%04X <- $%02X\n", addr, data );
debug_printf( "unmapped write $%04X <- $%02X\n", addr, data );
return;
#endif
}
@ -368,14 +368,14 @@ int Hes_Emu::cpu_read_( hes_addr_t addr )
case 0x0002:
case 0x0003:
dprintf( "VDP read not supported: %d\n", addr );
debug_printf( "VDP read not supported: %d\n", addr );
return 0;
case 0x0C01:
//return timer.enabled; // TODO: remove?
case 0x0C00:
run_until( time );
dprintf( "Timer count read\n" );
debug_printf( "Timer count read\n" );
return (unsigned) (timer.count - 1) / timer_base;
case 0x1402:
@ -396,7 +396,7 @@ int Hes_Emu::cpu_read_( hes_addr_t addr )
break;
default:
dprintf( "unmapped read $%04X\n", addr );
debug_printf( "unmapped read $%04X\n", addr );
#endif
}

View file

@ -1,6 +1,6 @@
// TurboGrafx-16/PC Engine HES music file emulator
// Game_Music_Emu 0.5.2
// Game_Music_Emu 0.6.0
#ifndef HES_EMU_H
#define HES_EMU_H

View file

@ -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
@ -503,7 +503,7 @@ possibly_out_of_time:
add_hl_data: {
blargg_ulong sum = rp.hl + data;
data ^= rp.hl;
rp.hl = sum;
rp.hl = (uint16_t)sum;
flags = (flags & (S80 | Z40 | V04)) |
(sum >> 16) |
(sum >> 8 & (F20 | F08)) |
@ -753,7 +753,7 @@ possibly_out_of_time:
flags = (flags & (S80 | Z40 | P04)) |
(temp & (F20 | F08)) |
(temp >> 8);
rg.a = temp;
rg.a = (uint8_t)temp;
goto loop;
}
@ -841,6 +841,7 @@ possibly_out_of_time:
case 0xCB:
unsigned data2;
data2 = instr [1];
(void) data2; // TODO is this the same as data in all cases?
pc++;
switch ( data )
{
@ -1092,7 +1093,7 @@ possibly_out_of_time:
(temp >> 8 & H10) |
(sum >> 8 & (S80 | F20 | F08)) |
((temp - -0x8000) >> 14 & V04);
rp.hl = sum;
rp.hl = (uint16_t)sum;
if ( (uint16_t) sum )
goto loop;
flags |= Z40;
@ -1289,7 +1290,7 @@ possibly_out_of_time:
case 0x4F: // LD R,A
SET_R( rg.a );
dprintf( "LD R,A not supported\n" );
debug_printf( "LD R,A not supported\n" );
warning = true;
goto loop;
@ -1299,7 +1300,7 @@ possibly_out_of_time:
case 0x5F: // LD A,R
rg.a = GET_R();
dprintf( "LD A,R not supported\n" );
debug_printf( "LD A,R not supported\n" );
warning = true;
ld_ai_common:
flags = (flags & C01) | SZ28( rg.a ) | (r.iff2 << 2 & V04);
@ -1322,7 +1323,7 @@ possibly_out_of_time:
goto loop;
default:
dprintf( "Opcode $ED $%02X not supported\n", data );
debug_printf( "Opcode $ED $%02X not supported\n", data );
warning = true;
goto loop;
}
@ -1583,7 +1584,7 @@ possibly_out_of_time:
}
default:
dprintf( "Opcode $%02X $CB $%02X not supported\n", opcode, data2 );
debug_printf( "Opcode $%02X $CB $%02X not supported\n", opcode, data2 );
warning = true;
goto loop;
}
@ -1672,7 +1673,7 @@ possibly_out_of_time:
}
default:
dprintf( "Unnecessary DD/FD prefix encountered\n" );
debug_printf( "Unnecessary DD/FD prefix encountered\n" );
warning = true;
pc--;
goto loop;
@ -1681,7 +1682,7 @@ possibly_out_of_time:
}
}
dprintf( "Unhandled main opcode: $%02X\n", opcode );
debug_printf( "Unhandled main opcode: $%02X\n", opcode );
assert( false );
hit_idle_addr:

View file

@ -1,6 +1,6 @@
// Z80 CPU emulator
// Game_Music_Emu 0.5.2
// Game_Music_Emu 0.6.0
#ifndef KSS_CPU_H
#define KSS_CPU_H

View file

@ -1,4 +1,4 @@
// Game_Music_Emu 0.5.2. http://www.slack.net/~ant/
// Game_Music_Emu 0.6.0. http://www.slack.net/~ant/
#include "Kss_Emu.h"
@ -230,9 +230,9 @@ blargg_err_t Kss_Emu::start_track_( int track )
bank_count = max_banks;
set_warning( "Bank data missing" );
}
//dprintf( "load_size : $%X\n", load_size );
//dprintf( "bank_size : $%X\n", bank_size );
//dprintf( "bank_count: %d (%d claimed)\n", bank_count, header_.bank_mode & 0x7F );
//debug_printf( "load_size : $%X\n", load_size );
//debug_printf( "bank_size : $%X\n", bank_size );
//debug_printf( "bank_count: %d (%d claimed)\n", bank_count, header_.bank_mode & 0x7F );
ram [idle_addr] = 0xFF;
cpu::reset( unmapped_write, unmapped_read );
@ -301,7 +301,7 @@ void Kss_Emu::cpu_write( unsigned addr, int data )
return;
}
dprintf( "LD ($%04X),$%02X\n", addr, data );
debug_printf( "LD ($%04X),$%02X\n", addr, data );
}
void kss_cpu_write( Kss_Cpu* cpu, unsigned addr, int data )
@ -358,7 +358,7 @@ void kss_cpu_out( Kss_Cpu* cpu, cpu_time_t time, unsigned addr, int data )
#endif
}
dprintf( "OUT $%04X,$%02X\n", addr, data );
debug_printf( "OUT $%04X,$%02X\n", addr, data );
}
int kss_cpu_in( Kss_Cpu*, cpu_time_t, unsigned addr )
@ -368,7 +368,7 @@ int kss_cpu_in( Kss_Cpu*, cpu_time_t, unsigned addr )
//{
//}
dprintf( "IN $%04X\n", addr );
debug_printf( "IN $%04X\n", addr );
return 0;
}

View file

@ -1,6 +1,6 @@
// MSX computer KSS music file emulator
// Game_Music_Emu 0.5.2
// Game_Music_Emu 0.6.0
#ifndef KSS_EMU_H
#define KSS_EMU_H
@ -68,7 +68,6 @@ private:
void update_gain();
unsigned scc_enabled; // 0 or 0xC000
byte const* bank_data;
int bank_count;
void set_bank( int logical, int physical );
blargg_long bank_size() const { return (16 * 1024L) >> (header_.bank_mode >> 7 & 1); }

View file

@ -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"

View file

@ -1,6 +1,6 @@
// Konami SCC sound chip emulator
// Game_Music_Emu 0.5.2
// Game_Music_Emu 0.6.0
#ifndef KSS_SCC_APU_H
#define KSS_SCC_APU_H

View file

@ -1,6 +1,4 @@
// Game_Music_Emu 0.5.2. http://www.slack.net/~ant/
#define IN_GME 1
// Game_Music_Emu 0.6.0. http://www.slack.net/~ant/
#include "M3u_Playlist.h"
#include "Music_Emu.h"
@ -54,9 +52,9 @@ blargg_err_t Gme_File::load_m3u( const char* path ) { return load_m3u_( playlist
blargg_err_t Gme_File::load_m3u( Data_Reader& in ) { return load_m3u_( playlist.load( in ) ); }
gme_err_t GMEAPI gme_load_m3u( Music_Emu* me, const char* path ) { return me->load_m3u( path ); }
BLARGG_EXPORT gme_err_t gme_load_m3u( Music_Emu* me, const char* path ) { return me->load_m3u( path ); }
gme_err_t GMEAPI gme_load_m3u_data( Music_Emu* me, const void* data, long size )
BLARGG_EXPORT gme_err_t gme_load_m3u_data( Music_Emu* me, const void* data, long size )
{
Mem_File_Reader in( data, size );
return me->load_m3u( in );

View file

@ -1,6 +1,6 @@
// M3U playlist file parser, with support for subtrack information
// Game_Music_Emu 0.5.2
// Game_Music_Emu 0.6.0
#ifndef M3U_PLAYLIST_H
#define M3U_PLAYLIST_H
@ -43,7 +43,7 @@ public:
int repeat; // count
};
entry_t const& operator [] ( int i ) const { return entries [i]; }
int size() const { return (int)entries.size(); }
int size() const { return int(entries.size()); }
void clear();

View file

@ -114,7 +114,7 @@ long Stereo_Buffer::read_samples( blip_sample_t* out, long count )
if ( count )
{
int bufs_used = stereo_added | was_stereo;
//dprintf( "%X\n", bufs_used );
//debug_printf( "%X\n", bufs_used );
if ( bufs_used <= 1 )
{
mix_mono( out, count );
@ -171,8 +171,8 @@ void Stereo_Buffer::mix_stereo( blip_sample_t* out_, blargg_long count )
BLIP_READER_NEXT( left, bass );
BLIP_READER_NEXT( right, bass );
out [0] = l;
out [1] = r;
out [0] = (blip_sample_t)l;
out [1] = (blip_sample_t)r;
out += 2;
}
@ -201,8 +201,8 @@ void Stereo_Buffer::mix_stereo_no_center( blip_sample_t* out_, blargg_long count
BLIP_READER_NEXT( left, bass );
BLIP_READER_NEXT( right, bass );
out [0] = l;
out [1] = r;
out [0] = (blip_sample_t)l;
out [1] = (blip_sample_t)r;
out += 2;
}
@ -223,8 +223,8 @@ void Stereo_Buffer::mix_mono( blip_sample_t* out_, blargg_long count )
s = 0x7FFF - (s >> 24);
BLIP_READER_NEXT( center, bass );
out [0] = s;
out [1] = s;
out [0] = (blip_sample_t)s;
out [1] = (blip_sample_t)s;
out += 2;
}

View file

@ -1,4 +1,4 @@
// Game_Music_Emu 0.5.2. http://www.slack.net/~ant/
// Game_Music_Emu 0.6.0. http://www.slack.net/~ant/
#include "Music_Emu.h"
@ -24,7 +24,8 @@ int const silence_threshold = 0x10;
long const fade_block_size = 512;
int const fade_shift = 8; // fade ends with gain at 1.0 / (1 << fade_shift)
Music_Emu::equalizer_t const Music_Emu::tv_eq = { -8.0, 180, 0, 0, 0, 0, 0, 0, 0, 0 };
Music_Emu::equalizer_t const Music_Emu::tv_eq =
Music_Emu::make_equalizer( -8.0, 180 );
void Music_Emu::clear_track_vars()
{
@ -305,7 +306,7 @@ static long count_silence( Music_Emu::sample_t* begin, long size )
Music_Emu::sample_t* p = begin + size;
while ( (unsigned) (*--p + silence_threshold / 2) <= (unsigned) silence_threshold ) { }
*begin = first;
return size - long(p - begin);
return size - (p - begin);
}
// fill internal buffer and check it for silence
@ -340,7 +341,7 @@ blargg_err_t Music_Emu::play( long out_count, sample_t* out )
assert( emu_time >= out_time );
// prints nifty graph of how far ahead we are when searching for silence
//dprintf( "%*s \n", int ((emu_time - out_time) * 7 / sample_rate()), "*" );
//debug_printf( "%*s \n", int ((emu_time - out_time) * 7 / sample_rate()), "*" );
long pos = 0;
if ( silence_count )
@ -404,6 +405,7 @@ blargg_err_t Gme_Info_::set_sample_rate_( long ) { return 0; }
void Gme_Info_::pre_load() { Gme_File::pre_load(); } // skip Music_Emu
void Gme_Info_::post_load_() { Gme_File::post_load_(); } // skip Music_Emu
void Gme_Info_::set_equalizer_( equalizer_t const& ){ check( false ); }
void Gme_Info_::enable_accuracy_( bool ) { check( false ); }
void Gme_Info_::mute_voices_( int ) { check( false ); }
void Gme_Info_::set_tempo_( double ) { }
blargg_err_t Gme_Info_::start_track_( int ) { return "Use full emulator for playback"; }

View file

@ -1,6 +1,6 @@
// Common interface to game music file emulators
// Game_Music_Emu 0.5.2
// Game_Music_Emu 0.6.0
#ifndef MUSIC_EMU_H
#define MUSIC_EMU_H
@ -82,6 +82,10 @@ public:
// on others this has no effect. Should be called only once *before* set_sample_rate().
virtual void set_buffer( Multi_Buffer* ) { }
// Enables/disables accurate emulation options, if any are supported. Might change
// equalizer settings.
void enable_accuracy( bool enable = true );
// Sound equalization (treble/bass)
// Frequency equalizer parameters (see gme.txt)
@ -93,6 +97,14 @@ public:
// Set frequency equalizer parameters
void set_equalizer( equalizer_t const& );
// Construct equalizer of given treble/bass settings
static const equalizer_t make_equalizer( double treble, double bass )
{
const Music_Emu::equalizer_t e = { treble, bass,
0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 };
return e;
}
// Equalizer settings for TV speaker
static equalizer_t const tv_eq;
@ -111,7 +123,8 @@ protected:
void remute_voices();
virtual blargg_err_t set_sample_rate_( long sample_rate ) = 0;
virtual void set_equalizer_( equalizer_t const& ) { };
virtual void set_equalizer_( equalizer_t const& ) { }
virtual void enable_accuracy_( bool /* enable */ ) { }
virtual void mute_voices_( int mask ) = 0;
virtual void set_tempo_( double ) = 0;
virtual blargg_err_t start_track_( int ) = 0; // tempo is set before this
@ -160,8 +173,8 @@ private:
void emu_play( long count, sample_t* out );
Multi_Buffer* effects_buffer;
friend GMEDLL Music_Emu* GMEAPI gme_new_emu( gme_type_t, int );
friend GMEDLL void GMEAPI gme_set_stereo_depth( Music_Emu*, double );
friend Music_Emu* gme_new_emu( gme_type_t, int );
friend void gme_set_stereo_depth( Music_Emu*, double );
};
// base class for info-only derivations
@ -169,6 +182,7 @@ struct Gme_Info_ : Music_Emu
{
virtual blargg_err_t set_sample_rate_( long sample_rate );
virtual void set_equalizer_( equalizer_t const& );
virtual void enable_accuracy_( bool );
virtual void mute_voices_( int mask );
virtual void set_tempo_( double );
virtual blargg_err_t start_track_( int );
@ -189,6 +203,7 @@ inline int Music_Emu::current_track() const { return current_track_; }
inline bool Music_Emu::track_ended() const { return track_ended_; }
inline const Music_Emu::equalizer_t& Music_Emu::equalizer() const { return equalizer_; }
inline void Music_Emu::enable_accuracy( bool b ) { enable_accuracy_( b ); }
inline void Music_Emu::set_tempo_( double t ) { tempo_ = t; }
inline void Music_Emu::remute_voices() { mute_voices( mute_mask_ ); }
inline void Music_Emu::ignore_silence( bool b ) { ignore_silence_ = b; }

View file

@ -385,7 +385,7 @@ int Nes_Apu::read_status( nes_time_t time )
irq_changed();
}
//dprintf( "%6d/%d Read $4015->$%02X\n", frame_delay, frame, result );
//debug_printf( "%6d/%d Read $4015->$%02X\n", frame_delay, frame, result );
return result;
}

View file

@ -1,4 +1,4 @@
// Game_Music_Emu 0.5.2. http://www.slack.net/~ant/
// Game_Music_Emu 0.6.0. http://www.slack.net/~ant/
#include "Nes_Cpu.h"
@ -921,7 +921,7 @@ imm##op:
goto loop;
status &= ~st_i;
handle_cli: {
//dprintf( "CLI at %d\n", TIME );
//debug_printf( "CLI at %d\n", TIME );
this->r.status = status; // update externally-visible I flag
blargg_long delta = s.base - irq_time_;
if ( delta <= 0 )
@ -944,7 +944,7 @@ imm##op:
// TODO: implement
delayed_cli:
dprintf( "Delayed CLI not emulated\n" );
debug_printf( "Delayed CLI not emulated\n" );
goto loop;
}
@ -960,7 +960,7 @@ imm##op:
if ( s_time < 0 )
goto loop;
dprintf( "Delayed SEI not emulated\n" );
debug_printf( "Delayed SEI not emulated\n" );
goto loop;
}

View file

@ -1,6 +1,6 @@
// NES 6502 CPU emulator
// Game_Music_Emu 0.5.2
// Game_Music_Emu 0.6.0
#ifndef NES_CPU_H
#define NES_CPU_H

View file

@ -1,4 +1,4 @@
// Game_Music_Emu 0.5.2. http://www.slack.net/~ant/
// Game_Music_Emu 0.6.0. http://www.slack.net/~ant/
#include "Nes_Fme7_Apu.h"
@ -56,7 +56,7 @@ void Nes_Fme7_Apu::run_until( blip_time_t end_time )
// check for unsupported mode
#ifndef NDEBUG
if ( (mode & 011) <= 001 && vol_mode & 0x1F )
dprintf( "FME7 used unimplemented sound mode: %02X, vol_mode: %02X\n",
debug_printf( "FME7 used unimplemented sound mode: %02X, vol_mode: %02X\n",
mode, vol_mode & 0x1F );
#endif

View file

@ -1,6 +1,6 @@
// Sunsoft FME-7 sound emulator
// Game_Music_Emu 0.5.2
// Game_Music_Emu 0.6.0
#ifndef NES_FME7_APU_H
#define NES_FME7_APU_H
@ -97,8 +97,8 @@ inline void Nes_Fme7_Apu::write_data( blip_time_t time, int data )
{
if ( (unsigned) latch >= reg_count )
{
#ifdef dprintf
dprintf( "FME7 write to %02X (past end of sound registers)\n", (int) latch );
#ifdef debug_printf
debug_printf( "FME7 write to %02X (past end of sound registers)\n", (int) latch );
#endif
return;
}

View file

@ -1,4 +1,4 @@
// Game_Music_Emu 0.5.2. http://www.slack.net/~ant/
// Game_Music_Emu 0.6.0. http://www.slack.net/~ant/
#include "Nsf_Emu.h"
@ -31,8 +31,10 @@ int const fme7_flag = 0x20;
long const clock_divisor = 12;
Nsf_Emu::equalizer_t const Nsf_Emu::nes_eq = { -1.0, 80, 0, 0, 0, 0, 0, 0, 0, 0 };
Nsf_Emu::equalizer_t const Nsf_Emu::famicom_eq = { -15.0, 80, 0, 0, 0, 0, 0, 0, 0, 0 };
Nsf_Emu::equalizer_t const Nsf_Emu::nes_eq =
Music_Emu::make_equalizer( -1.0, 80 );
Nsf_Emu::equalizer_t const Nsf_Emu::famicom_eq =
Music_Emu::make_equalizer( -15.0, 80 );
int Nsf_Emu::pcm_read( void* emu, nes_addr_t addr )
{
@ -442,7 +444,7 @@ void Nsf_Emu::cpu_write_misc( nes_addr_t addr, int data )
// memory mapper?
if ( addr == 0xFFF8 ) return;
dprintf( "write_unmapped( 0x%04X, 0x%02X )\n", (unsigned) addr, (unsigned) data );
debug_printf( "write_unmapped( 0x%04X, 0x%02X )\n", (unsigned) addr, (unsigned) data );
}
#endif
}

View file

@ -1,6 +1,6 @@
// Nintendo NES/Famicom NSF music file emulator
// Game_Music_Emu 0.5.2
// Game_Music_Emu 0.6.0
#ifndef NSF_EMU_H
#define NSF_EMU_H

View file

@ -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/
#define _CRT_SECURE_NO_WARNINGS
@ -137,7 +137,7 @@ blargg_err_t Nsfe_Info::load( Data_Reader& in, Nsf_Emu* nsf_emu )
blargg_long size = get_le32( block_header [0] );
blargg_long tag = get_le32( block_header [1] );
//dprintf( "tag: %c%c%c%c\n", char(tag), char(tag>>8), char(tag>>16), char(tag>>24) );
//debug_printf( "tag: %c%c%c%c\n", char(tag), char(tag>>8), char(tag>>16), char(tag>>24) );
switch ( tag )
{

View file

@ -1,6 +1,6 @@
// Nintendo NES/Famicom NSFE music file emulator
// Game_Music_Emu 0.5.2
// Game_Music_Emu 0.6.0
#ifndef NSFE_EMU_H
#define NSFE_EMU_H

View file

@ -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"
@ -66,7 +66,7 @@ Sap_Apu_Impl::Sap_Apu_Impl()
blargg_ulong rev = n & 1;
for ( int i = 1; i < poly5_len; i++ )
rev |= (n >> i & 1) << (poly5_len - i);
dprintf( "poly5: 0x%08lX\n", rev );
debug_printf( "poly5: 0x%08lX\n", rev );
}
}
@ -114,7 +114,7 @@ inline void Sap_Apu::calc_periods()
period = (period - 6) * divider;
if ( (osc [-1].regs [1] & 0x1F) > 0x10 )
dprintf( "Use of slave channel in 16-bit mode not supported\n" );
debug_printf( "Use of slave channel in 16-bit mode not supported\n" );
}
}
osc->period = period;

View file

@ -1,6 +1,6 @@
// Atari POKEY sound chip emulator
// Game_Music_Emu 0.5.2
// Game_Music_Emu 0.6.0
#ifndef SAP_APU_H
#define SAP_APU_H

View file

@ -1,4 +1,4 @@
// Game_Music_Emu 0.5.2. http://www.slack.net/~ant/
// Game_Music_Emu 0.6.0. http://www.slack.net/~ant/
#include "Sap_Cpu.h"
@ -889,7 +889,7 @@ imm##op:
goto loop;
}
delayed_cli:
dprintf( "Delayed CLI not emulated\n" );
debug_printf( "Delayed CLI not emulated\n" );
goto loop;
}
@ -904,7 +904,7 @@ imm##op:
s_time += delta;
if ( s_time < 0 )
goto loop;
dprintf( "Delayed SEI not emulated\n" );
debug_printf( "Delayed SEI not emulated\n" );
goto loop;
}
@ -945,7 +945,7 @@ handle_brk:
goto idle_done;
pc++;
result_ = 4;
dprintf( "BRK executed\n" );
debug_printf( "BRK executed\n" );
interrupt:
{

View file

@ -1,6 +1,6 @@
// Atari 6502 CPU emulator
// Game_Music_Emu 0.5.2
// Game_Music_Emu 0.6.0
#ifndef SAP_CPU_H
#define SAP_CPU_H

View file

@ -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"
@ -336,7 +336,7 @@ blargg_err_t Sap_Emu::start_track_( int track )
{
unsigned start = get_le16( in );
unsigned end = get_le16( in + 2 );
//dprintf( "Block $%04X-$%04X\n", start, end );
//debug_printf( "Block $%04X-$%04X\n", start, end );
in += 4;
if ( end < start )
{
@ -390,7 +390,7 @@ void Sap_Emu::cpu_write_( sap_addr_t addr, int data )
}
if ( (addr & ~0x0010) != 0xD20F || data != 0x03 )
dprintf( "Unmapped write $%04X <- $%02X\n", addr, data );
debug_printf( "Unmapped write $%04X <- $%02X\n", addr, data );
}
inline void Sap_Emu::call_play()

View file

@ -1,6 +1,6 @@
// Atari XL/XE SAP music file emulator
// Game_Music_Emu 0.5.2
// Game_Music_Emu 0.6.0
#ifndef SAP_EMU_H
#define SAP_EMU_H

View file

@ -1,6 +1,6 @@
// SPC emulation support: init, sample buffering, reset, SPC loading
// snes_spc 0.9.0. http://www.slack.net/~ant/
// Game_Music_Emu 0.6.0. http://www.slack.net/~ant/
#include "Snes_Spc.h"

View file

@ -1,6 +1,6 @@
// SNES SPC-700 APU emulator
// snes_spc 0.9.0
// Game_Music_Emu 0.6.0
#ifndef SNES_SPC_H
#define SNES_SPC_H
@ -66,10 +66,7 @@ public:
// Sets tempo, where tempo_unit = normal, tempo_unit / 2 = half speed, etc.
enum { tempo_unit = 0x100 };
void set_tempo( int );
enum { gain_unit = Spc_Dsp::gain_unit };
void set_gain( int gain );
// SPC music files
// Loads SPC data into emulator
@ -107,6 +104,22 @@ public:
bool check_kon();
#endif
public:
// TODO: document
struct regs_t
{
int pc;
int a;
int x;
int y;
int psw;
int sp;
};
regs_t& smp_regs() { return m.cpu_regs; }
uint8_t* smp_ram() { return m.ram.ram; }
void run_until( time_t t ) { run_until_( t ); }
public:
BLARGG_DISABLE_NOTHROW
@ -146,15 +159,7 @@ private:
uint8_t smp_regs [2] [reg_count];
struct
{
int pc;
int a;
int x;
int y;
int psw;
int sp;
} cpu_regs;
regs_t cpu_regs;
rel_time_t dsp_time;
time_t spc_time;
@ -271,8 +276,6 @@ inline void Snes_Spc::write_port( time_t t, int port, int data )
run_until_( t ) [0x10 + port] = data;
}
inline void Snes_Spc::set_gain( int gain ) { dsp.set_gain( gain ); }
inline void Snes_Spc::mute_voices( int mask ) { dsp.mute_voices( mask ); }
inline void Snes_Spc::disable_surround( bool disable ) { dsp.disable_surround( disable ); }

View file

@ -1,6 +1,6 @@
// Core SPC emulation: CPU, timers, SMP registers, memory
// snes_spc 0.9.0. http://www.slack.net/~ant/
// Game_Music_Emu 0.6.0. http://www.slack.net/~ant/
#include "Snes_Spc.h"
@ -176,7 +176,7 @@ inline void Snes_Spc::dsp_write( int data, rel_time_t time )
if ( REGS [r_dspaddr] <= 0x7F )
dsp.write( REGS [r_dspaddr], data );
else if ( !SPC_MORE_ACCURACY )
dprintf( "SPC wrote to DSP register > $7F\n" );
debug_printf( "SPC wrote to DSP register > $7F\n" );
}
@ -277,8 +277,9 @@ static unsigned char const glitch_probs [3] [256] =
};
#endif
// divided into multiple functions to keep rarely-used functionality separate
// so often-used functionality can be optimized better by compiler
// Read/write handlers are divided into multiple functions to keep rarely-used
// functionality separate so often-used functionality can be optimized better
// by compiler.
// If write isn't preceded by read, data has this added to it
int const no_read_before_write = 0x2000;
@ -302,7 +303,7 @@ void Snes_Spc::cpu_write_smp_reg_( int data, rel_time_t time, int addr )
t->next_time == time + TIMER_MUL( t, 1 ) &&
((period - 1) | ~0x0F) & period )
{
//dprintf( "SPC pathological timer target write\n" );
//debug_printf( "SPC pathological timer target write\n" );
// If the period is 3, 5, or 9, there's a probability this behavior won't occur,
// based on the previous period
@ -331,7 +332,7 @@ void Snes_Spc::cpu_write_smp_reg_( int data, rel_time_t time, int addr )
case r_t1out:
case r_t2out:
if ( !SPC_MORE_ACCURACY )
dprintf( "SPC wrote to counter %d\n", (int) addr - r_t0out );
debug_printf( "SPC wrote to counter %d\n", (int) addr - r_t0out );
if ( data < no_read_before_write / 2 )
run_timer( &m.timers [addr - r_t0out], time - 1 )->counter = 0;
@ -345,7 +346,7 @@ void Snes_Spc::cpu_write_smp_reg_( int data, rel_time_t time, int addr )
case r_test:
if ( (uint8_t) data != 0x0A )
dprintf( "SPC wrote to test register\n" );
debug_printf( "SPC wrote to test register\n" );
break;
case r_control:

View file

@ -1,4 +1,4 @@
// snes_spc 0.9.0. http://www.slack.net/~ant/
// Game_Music_Emu 0.6.0. http://www.slack.net/~ant/
/* Copyright (C) 2004-2007 Shay Green. This module is free software; you
can redistribute it and/or modify it under the terms of the GNU Lesser
@ -16,7 +16,7 @@ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
#if SPC_MORE_ACCURACY
#define SUSPICIOUS_OPCODE( name ) ((void) 0)
#else
#define SUSPICIOUS_OPCODE( name ) dprintf( "SPC: suspicious opcode: " name "\n" )
#define SUSPICIOUS_OPCODE( name ) debug_printf( "SPC: suspicious opcode: " name "\n" )
#endif
#define CPU_READ( time, offset, addr )\
@ -242,7 +242,7 @@ loop:
BRANCH( (uint8_t) nz )
case 0x3F:{// CALL
int old_addr = int(GET_PC() + 2);
int old_addr = GET_PC() + 2;
SET_PC( READ_PC16( pc ) );
PUSH16( old_addr );
goto loop;
@ -1184,7 +1184,7 @@ loop:
{
addr &= 0xFFFF;
SET_PC( addr );
dprintf( "SPC: PC wrapped around\n" );
debug_printf( "SPC: PC wrapped around\n" );
goto loop;
}
}
@ -1205,7 +1205,7 @@ stop:
// Uncache registers
if ( GET_PC() >= 0x10000 )
dprintf( "SPC: PC wrapped around\n" );
debug_printf( "SPC: PC wrapped around\n" );
m.cpu_regs.pc = (uint16_t) GET_PC();
m.cpu_regs.sp = ( uint8_t) GET_SP();
m.cpu_regs.a = ( uint8_t) a;

View file

@ -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"
@ -606,8 +606,8 @@ skip_brr:
}
// Sound out
int l = (((main_out_l * mvoll + echo_in_l * (int8_t) REG(evoll)) >> 14) * m.gain) >> 8;
int r = (((main_out_r * mvolr + echo_in_r * (int8_t) REG(evolr)) >> 14) * m.gain) >> 8;
int l = (main_out_l * mvoll + echo_in_l * (int8_t) REG(evoll)) >> 14;
int r = (main_out_r * mvolr + echo_in_r * (int8_t) REG(evolr)) >> 14;
CLAMP16( l );
CLAMP16( r );
@ -641,7 +641,6 @@ void Spc_Dsp::mute_voices( int mask )
void Spc_Dsp::init( void* ram_64k )
{
m.ram = (uint8_t*) ram_64k;
set_gain( gain_unit );
mute_voices( 0 );
disable_surround( false );
set_output( 0, 0 );

View file

@ -1,12 +1,12 @@
// Fast SNES SPC-700 DSP emulator (about 3x speed of accurate one)
// snes_spc 0.9.0
// Game_Music_Emu 0.6.0
#ifndef SPC_DSP_H
#define SPC_DSP_H
#include "blargg_common.h"
class Spc_Dsp {
struct Spc_Dsp {
public:
typedef BOOST::uint8_t uint8_t;
@ -51,10 +51,7 @@ public:
// If true, prevents channels and global volumes from being phase-negated
void disable_surround( bool disable = true );
enum { gain_unit = 0x100 };
void set_gain( int gain );
// State
// Resets DSP and uses supplied values to initialize registers
@ -140,7 +137,6 @@ private:
// non-emulation state
uint8_t* ram; // 64K shared RAM between DSP and SMP
int mute_mask;
int gain;
int surround_threshold;
sample_t* out;
sample_t* out_end;
@ -204,8 +200,6 @@ inline void Spc_Dsp::write( int addr, int data )
}
}
inline void Spc_Dsp::set_gain( int gain ) { m.gain = gain; }
inline void Spc_Dsp::disable_surround( bool disable )
{
m.surround_threshold = disable ? 0 : -0x4000;

View file

@ -1,4 +1,4 @@
// Game_Music_Emu 0.5.2. http://www.slack.net/~ant/
// Game_Music_Emu 0.6.0. http://www.slack.net/~ant/
#include "Spc_Emu.h"
@ -19,6 +19,8 @@ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
#include "blargg_source.h"
// TODO: support Spc_Filter's bass
Spc_Emu::Spc_Emu()
{
set_type( gme_spc_type );
@ -54,7 +56,7 @@ static void get_spc_xid6( byte const* begin, long size, track_info_t* out )
byte const* in = begin + 8;
if ( end - in > info_size )
{
dprintf( "Extra data after SPC xid6 info\n" );
debug_printf( "Extra data after SPC xid6 info\n" );
end = in + info_size;
}
@ -114,7 +116,7 @@ static void get_spc_xid6( byte const* begin, long size, track_info_t* out )
default:
if ( id < 0x01 || (id > 0x07 && id < 0x10) ||
(id > 0x14 && id < 0x30) || id > 0x36 )
dprintf( "Unknown SPC xid6 block: %X\n", (int) id );
debug_printf( "Unknown SPC xid6 block: %X\n", (int) id );
break;
}
if ( field )
@ -134,7 +136,7 @@ static void get_spc_xid6( byte const* begin, long size, track_info_t* out )
{
// ...but some files have no padding
in = unaligned;
dprintf( "SPC info tag wasn't properly padded to align\n" );
debug_printf( "SPC info tag wasn't properly padded to align\n" );
break;
}
}
@ -244,12 +246,13 @@ static Music_Emu* new_spc_file() { return BLARGG_NEW Spc_File; }
static gme_type_t_ const gme_spc_type_ = { "Super Nintendo", 1, &new_spc_emu, &new_spc_file, "SPC", 0 };
gme_type_t const gme_spc_type = &gme_spc_type_;
// Setup
blargg_err_t Spc_Emu::set_sample_rate_( long sample_rate )
{
RETURN_ERR( apu.init() );
apu.set_gain( (int) (gain() * Snes_Spc::gain_unit) );
enable_accuracy( false );
if ( sample_rate != native_sample_rate )
{
RETURN_ERR( resampler.buffer_size( native_sample_rate / 20 * 2 ) );
@ -258,6 +261,12 @@ blargg_err_t Spc_Emu::set_sample_rate_( long sample_rate )
return 0;
}
void Spc_Emu::enable_accuracy_( bool b )
{
Music_Emu::enable_accuracy_( b );
filter.enable( b );
}
void Spc_Emu::mute_voices_( int m )
{
Music_Emu::mute_voices_( m );
@ -277,17 +286,29 @@ blargg_err_t Spc_Emu::load_mem_( byte const* in, long size )
// Emulation
void Spc_Emu::set_tempo_( double t ) { apu.set_tempo( (int) (t * Snes_Spc::tempo_unit) ); }
void Spc_Emu::set_tempo_( double t )
{
apu.set_tempo( (int) (t * apu.tempo_unit) );
}
blargg_err_t Spc_Emu::start_track_( int track )
{
RETURN_ERR( Music_Emu::start_track_( track ) );
resampler.clear();
filter.clear();
RETURN_ERR( apu.load_spc( file_data, file_size ) );
filter.set_gain( (int) (gain() * SPC_Filter::gain_unit) );
apu.clear_echo();
return 0;
}
blargg_err_t Spc_Emu::play_and_filter( long count, sample_t out [] )
{
RETURN_ERR( apu.play( count, out ) );
filter.run( out, count );
return 0;
}
blargg_err_t Spc_Emu::skip_( long count )
{
if ( sample_rate() != native_sample_rate )
@ -299,7 +320,10 @@ blargg_err_t Spc_Emu::skip_( long count )
// TODO: shouldn't skip be adjusted for the 64 samples read afterwards?
if ( count > 0 )
{
RETURN_ERR( apu.skip( count ) );
filter.clear();
}
// eliminate pop due to resampler
const int resampler_latency = 64;
@ -310,7 +334,7 @@ blargg_err_t Spc_Emu::skip_( long count )
blargg_err_t Spc_Emu::play_( long count, sample_t* out )
{
if ( sample_rate() == native_sample_rate )
return apu.play( count, out );
return play_and_filter( count, out );
long remain = count;
while ( remain > 0 )
@ -319,7 +343,7 @@ blargg_err_t Spc_Emu::play_( long count, sample_t* out )
if ( remain > 0 )
{
long n = resampler.max_write();
RETURN_ERR( apu.play( n, resampler.buffer() ) );
RETURN_ERR( play_and_filter( n, resampler.buffer() ) );
resampler.write( n );
}
}

View file

@ -1,12 +1,13 @@
// Super Nintendo SPC music file emulator
// Game_Music_Emu 0.5.2
// Game_Music_Emu 0.6.0
#ifndef SPC_EMU_H
#define SPC_EMU_H
#include "Fir_Resampler.h"
#include "Music_Emu.h"
#include "Snes_Spc.h"
#include "Spc_Filter.h"
class Spc_Emu : public Music_Emu {
public:
@ -65,11 +66,15 @@ protected:
blargg_err_t skip_( long );
void mute_voices_( int );
void set_tempo_( double );
void enable_accuracy_( bool );
private:
byte const* file_data;
long file_size;
Fir_Resampler<24> resampler;
SPC_Filter filter;
Snes_Spc apu;
blargg_err_t play_and_filter( long count, sample_t out [] );
};
inline void Spc_Emu::disable_surround( bool b ) { apu.disable_surround( b ); }

View 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;
}
}
}

View 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

View file

@ -1,4 +1,4 @@
// Game_Music_Emu 0.5.2. http://www.slack.net/~ant/
// Game_Music_Emu 0.6.0. http://www.slack.net/~ant/
#include "Vgm_Emu.h"
@ -36,8 +36,7 @@ Vgm_Emu::Vgm_Emu()
set_silence_lookahead( 1 ); // tracks should already be trimmed
static equalizer_t const eq = { -14.0, 80, 0, 0, 0, 0, 0, 0, 0, 0 };
set_equalizer( eq );
set_equalizer( make_equalizer( -14.0, 80 ) );
}
Vgm_Emu::~Vgm_Emu() { }
@ -218,8 +217,8 @@ void Vgm_Emu::set_tempo_( double t )
{
vgm_rate = (long) (44100 * t + 0.5);
blip_time_factor = (long) floor( double (1L << blip_time_bits) / vgm_rate * psg_rate + 0.5 );
//dprintf( "blip_time_factor: %ld\n", blip_time_factor );
//dprintf( "vgm_rate: %ld\n", vgm_rate );
//debug_printf( "blip_time_factor: %ld\n", blip_time_factor );
//debug_printf( "vgm_rate: %ld\n", vgm_rate );
// TODO: remove? calculates vgm_rate more accurately (above differs at most by one Hz only)
//blip_time_factor = (long) floor( double (1L << blip_time_bits) * psg_rate / 44100 / t + 0.5 );
//vgm_rate = (long) floor( double (1L << blip_time_bits) * psg_rate / blip_time_factor + 0.5 );

View file

@ -1,6 +1,6 @@
// Sega Master System/Mark III, Sega Genesis/Mega Drive, BBC Micro VGM music file emulator
// Game_Music_Emu 0.5.2
// Game_Music_Emu 0.6.0
#ifndef VGM_EMU_H
#define VGM_EMU_H

View file

@ -1,4 +1,4 @@
// Game_Music_Emu 0.5.2. http://www.slack.net/~ant/
// Game_Music_Emu 0.6.0. http://www.slack.net/~ant/
#include "Vgm_Emu.h"
@ -244,7 +244,7 @@ int Vgm_Emu_Impl::play_frame( blip_time_t blip_time, int sample_count, sample_t*
int pairs = min_pairs;
while ( (pairs = to_fm_time( vgm_time )) < min_pairs )
vgm_time++;
//dprintf( "pairs: %d, min_pairs: %d\n", pairs, min_pairs );
//debug_printf( "pairs: %d, min_pairs: %d\n", pairs, min_pairs );
if ( ym2612.enabled() )
{

View file

@ -1,6 +1,6 @@
// Low-level parts of Vgm_Emu
// Game_Music_Emu 0.5.2
// Game_Music_Emu 0.6.0
#ifndef VGM_EMU_IMPL_H
#define VGM_EMU_IMPL_H

View file

@ -1,7 +1,7 @@
// Use in place of Ym2413_Emu.cpp and ym2413.c to disable support for this chip
// Game_Music_Emu 0.5.2. http://www.slack.net/~ant/
// Game_Music_Emu 0.6.0. http://www.slack.net/~ant/
#include "Ym2413_Emu.h"

View file

@ -1,6 +1,6 @@
// YM2413 FM sound chip emulator interface
// Game_Music_Emu 0.5.2
// Game_Music_Emu 0.6.0
#ifndef YM2413_EMU_H
#define YM2413_EMU_H

View file

@ -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
@ -11,7 +11,7 @@
#include <stdio.h>
#include <math.h>
/* Copyright (C) 2002 Stéphane Dallongeville (gens AT consolemul.com) */
/* Copyright (C) 2002 Stephane Dallongeville (gens AT consolemul.com) */
/* Copyright (C) 2004-2006 Shay Green. This module is free software; you
can redistribute it and/or modify it under the terms of the GNU Lesser
General Public License as published by the Free Software Foundation; either
@ -44,9 +44,9 @@ struct slot_t
int MUL; // parametre "multiple de frequence"
int TL; // Total Level = volume lorsque l'enveloppe est au plus haut
int TLL; // Total Level ajusted
int SLL; // Sustin Level (ajusted) = volume où l'enveloppe termine sa premiere phase de regression
int SLL; // Sustin Level (ajusted) = volume ol'enveloppe termine sa premiere phase de regression
int KSR_S; // Key Scale Rate Shift = facteur de prise en compte du KSL dans la variations de l'enveloppe
int KSR; // Key Scale Rate = cette valeur est calculee par rapport à la frequence actuelle, elle va influer
int KSR; // Key Scale Rate = cette valeur est calculee par rapport la frequence actuelle, elle va influer
// sur les differents parametres de l'enveloppe comme l'attaque, le decay ... comme dans la realite !
int SEG; // Type enveloppe SSG
int env_xor;
@ -58,24 +58,24 @@ struct slot_t
const int *RR; // Release Rate (table pointeur) = Taux pour le rel'chement (RR[KSR])
int Fcnt; // Frequency Count = compteur-frequence pour determiner l'amplitude actuelle (SIN[Finc >> 16])
int Finc; // frequency step = pas d'incrementation du compteur-frequence
// plus le pas est grand, plus la frequence est aïgu (ou haute)
// plus le pas est grand, plus la frequence est au (ou haute)
int Ecurp; // Envelope current phase = cette variable permet de savoir dans quelle phase
// de l'enveloppe on se trouve, par exemple phase d'attaque ou phase de maintenue ...
// en fonction de la valeur de cette variable, on va appeler une fonction permettant
// de mettre à jour l'enveloppe courante.
int Ecnt; // Envelope counter = le compteur-enveloppe permet de savoir où l'on se trouve dans l'enveloppe
// de mettre jour l'enveloppe courante.
int Ecnt; // Envelope counter = le compteur-enveloppe permet de savoir ol'on se trouve dans l'enveloppe
int Einc; // Envelope step courant
int Ecmp; // Envelope counter limite pour la prochaine phase
int EincA; // Envelope step for Attack = pas d'incrementation du compteur durant la phase d'attaque
// cette valeur est egal à AR[KSR]
// cette valeur est egal AR[KSR]
int EincD; // Envelope step for Decay = pas d'incrementation du compteur durant la phase de regression
// cette valeur est egal à DR[KSR]
// cette valeur est egal DR[KSR]
int EincS; // Envelope step for Sustain = pas d'incrementation du compteur durant la phase de maintenue
// cette valeur est egal à SR[KSR]
// cette valeur est egal SR[KSR]
int EincR; // Envelope step for Release = pas d'incrementation du compteur durant la phase de rel'chement
// cette valeur est egal à RR[KSR]
int *OUTp; // pointeur of SLOT output = pointeur permettant de connecter la sortie de ce slot à l'entree
// d'un autre ou carrement à la sortie de la voie
// cette valeur est egal RR[KSR]
int *OUTp; // pointeur of SLOT output = pointeur permettant de connecter la sortie de ce slot l'entree
// d'un autre ou carrement la sortie de la voie
int INd; // input data of the slot = donnees en entree du slot
int ChgEnM; // Change envelop mask.
int AMS; // AMS depth level of this SLOT = degre de modulation de l'amplitude par le LFO
@ -102,10 +102,10 @@ struct state_t
{
int TimerBase; // TimerBase calculation
int Status; // YM2612 Status (timer overflow)
int TimerA; // timerA limit = valeur jusqu'à laquelle le timer A doit compter
int TimerA; // timerA limit = valeur jusqu'laquelle le timer A doit compter
int TimerAL;
int TimerAcnt; // timerA counter = valeur courante du Timer A
int TimerB; // timerB limit = valeur jusqu'à laquelle le timer B doit compter
int TimerB; // timerB limit = valeur jusqu'laquelle le timer B doit compter
int TimerBL;
int TimerBcnt; // timerB counter = valeur courante du Timer B
int Mode; // Mode actuel des voie 3 et 6 (normal / special)
@ -1255,7 +1255,7 @@ void Ym2612_Impl::run( int pair_count, Ym2612_Emu::sample_t* out )
if ( YM2612.Mode & 3 )
run_timer( pair_count );
// Mise à jour des pas des compteurs-frequences s'ils ont ete modifies
// Mise jour des pas des compteurs-frequences s'ils ont ete modifies
for ( int chi = 0; chi < channel_count; chi++ )
{
@ -1277,7 +1277,7 @@ void Ym2612_Impl::run( int pair_count, Ym2612_Emu::sample_t* out )
int ksr = ch.KC [i2] >> sl.KSR_S; // keycode attenuation
sl.Finc = (finc + sl.DT [ch.KC [i2]]) * sl.MUL;
if (sl.KSR != ksr) // si le KSR a change alors
{ // les differents taux pour l'enveloppe sont mis à jour
{ // les differents taux pour l'enveloppe sont mis jour
sl.KSR = ksr;
sl.EincA = sl.AR [ksr];

View file

@ -1,6 +1,6 @@
// YM2612 FM sound chip emulator interface
// Game_Music_Emu 0.5.2
// Game_Music_Emu 0.6.0
#ifndef YM2612_EMU_H
#define YM2612_EMU_H

View file

@ -15,6 +15,13 @@
#ifndef BLARGG_COMMON_H
#define BLARGG_COMMON_H
// BLARGG_RESTRICT: equivalent to restrict, where supported
#if __GNUC__ >= 3 || _MSC_VER >= 1100
#define BLARGG_RESTRICT __restrict
#else
#define BLARGG_RESTRICT
#endif
// STATIC_CAST(T,expr): Used in place of static_cast<T> (expr)
#ifndef STATIC_CAST
#define STATIC_CAST(T,expr) ((T) (expr))
@ -54,10 +61,11 @@ public:
};
#ifndef BLARGG_DISABLE_NOTHROW
#if __cplusplus < 199711
#define BLARGG_THROWS( spec )
#else
// throw spec mandatory in ISO C++ if operator new can return NULL
#if __cplusplus >= 199711 || __GNUC__ >= 3
#define BLARGG_THROWS( spec ) throw spec
#else
#define BLARGG_THROWS( spec )
#endif
#define BLARGG_DISABLE_NOTHROW \
void* operator new ( size_t s ) BLARGG_THROWS(()) { return malloc( s ); }\
@ -68,6 +76,7 @@ public:
#define BLARGG_NEW new (std::nothrow)
#endif
// BLARGG_4CHAR('a','b','c','d') = 'abcd' (four character integer constant)
#define BLARGG_4CHAR( a, b, c, d ) \
((a&0xFF)*0x1000000L + (b&0xFF)*0x10000L + (c&0xFF)*0x100L + (d&0xFF))
@ -110,18 +119,17 @@ public:
#endif
// blargg_long/blargg_ulong = at least 32 bits, int if it's big enough
#include <limits.h>
#if INT_MAX >= 0x7FFFFFFF
typedef int blargg_long;
#else
#if INT_MAX < 0x7FFFFFFF || LONG_MAX == 0x7FFFFFFF
typedef long blargg_long;
#else
typedef int blargg_long;
#endif
#if UINT_MAX >= 0xFFFFFFFF
typedef unsigned blargg_ulong;
#else
#if UINT_MAX < 0xFFFFFFFF || ULONG_MAX == 0xFFFFFFFF
typedef unsigned long blargg_ulong;
#else
typedef unsigned blargg_ulong;
#endif
// BOOST::int8_t etc.
@ -171,5 +179,18 @@ public:
};
#endif
#if __GNUC__ >= 3
#define BLARGG_DEPRECATED __attribute__ ((deprecated))
#else
#define BLARGG_DEPRECATED
#endif
// Use in place of "= 0;" for a pure virtual, since these cause calls to std C++ lib.
// During development, BLARGG_PURE( x ) expands to = 0;
// virtual int func() BLARGG_PURE( { return 0; } )
#ifndef BLARGG_PURE
#define BLARGG_PURE( def ) def
#endif
#endif
#endif

View file

@ -6,9 +6,22 @@
// Uncomment to use zlib for transparent decompression of gzipped files
//#define HAVE_ZLIB_H
// Uncomment to support only the listed game music types. See gme_type_list.cpp
// for a list of all types.
//#define GME_TYPE_LIST gme_nsf_type, gme_gbs_type
// Uncomment and edit list to support only the listed game music types,
// so that the others don't get linked in at all.
/*
#define GME_TYPE_LIST \
gme_ay_type,\
gme_gbs_type,\
gme_gym_type,\
gme_hes_type,\
gme_kss_type,\
gme_nsf_type,\
gme_nsfe_type,\
gme_sap_type,\
gme_spc_type,\
gme_vgm_type,\
gme_vgz_type
*/
// Uncomment to enable platform-specific optimizations
//#define BLARGG_NONPORTABLE 1
@ -27,5 +40,4 @@
#include "config.h"
#endif
#endif

View file

@ -1,20 +1,20 @@
// CPU Byte Order Utilities
// Game_Music_Emu 0.5.2
#ifndef BLARGG_ENDIAN
#define BLARGG_ENDIAN
#include "blargg_common.h"
// BLARGG_CPU_CISC: Defined if CPU has very few general-purpose registers (< 16)
#if defined (_M_IX86) || defined (_M_IA64) || defined (__i486__) || \
defined (__x86_64__) || defined (__ia64__) || defined (__i386__)
#if defined (__i386__) || defined (__x86_64__) || defined (_M_IX86) || defined (_M_X64)
#define BLARGG_CPU_X86 1
#define BLARGG_CPU_CISC 1
#endif
#if defined (__powerpc__) || defined (__ppc__) || defined (__POWERPC__) || defined (__powerc)
#if defined (__powerpc__) || defined (__ppc__) || defined (__ppc64__) || \
defined (__POWERPC__) || defined (__powerc)
#define BLARGG_CPU_POWERPC 1
#define BLARGG_CPU_RISC 1
#endif
// BLARGG_BIG_ENDIAN, BLARGG_LITTLE_ENDIAN: Determined automatically, otherwise only
@ -36,10 +36,10 @@
#endif
#if defined (MSB_FIRST) || defined (__BIG_ENDIAN__) || defined (WORDS_BIGENDIAN) || \
defined (__mips__) || defined (__sparc__) || BLARGG_CPU_POWERPC || \
defined (__sparc__) || BLARGG_CPU_POWERPC || \
(defined (BIG_ENDIAN) && BIG_ENDIAN+0 != 4321)
#define BLARGG_BIG_ENDIAN 1
#else
#elif !defined (__mips__)
// No endian specified; assume little-endian, since it's most common
#define BLARGG_LITTLE_ENDIAN 1
#endif
@ -64,45 +64,60 @@ inline void blargg_verify_byte_order()
#endif
}
inline unsigned get_le16( void const* p ) {
return ((unsigned char const*) p) [1] * 0x100u +
((unsigned char const*) p) [0];
inline unsigned get_le16( void const* p )
{
return (unsigned) ((unsigned char const*) p) [1] << 8 |
(unsigned) ((unsigned char const*) p) [0];
}
inline unsigned get_be16( void const* p ) {
return ((unsigned char const*) p) [0] * 0x100u +
((unsigned char const*) p) [1];
inline unsigned get_be16( void const* p )
{
return (unsigned) ((unsigned char const*) p) [0] << 8 |
(unsigned) ((unsigned char const*) p) [1];
}
inline blargg_ulong get_le32( void const* p ) {
return ((unsigned char const*) p) [3] * 0x01000000u +
((unsigned char const*) p) [2] * 0x00010000u +
((unsigned char const*) p) [1] * 0x00000100u +
((unsigned char const*) p) [0];
inline blargg_ulong get_le32( void const* p )
{
return (blargg_ulong) ((unsigned char const*) p) [3] << 24 |
(blargg_ulong) ((unsigned char const*) p) [2] << 16 |
(blargg_ulong) ((unsigned char const*) p) [1] << 8 |
(blargg_ulong) ((unsigned char const*) p) [0];
}
inline blargg_ulong get_be32( void const* p ) {
return ((unsigned char const*) p) [0] * 0x01000000u +
((unsigned char const*) p) [1] * 0x00010000u +
((unsigned char const*) p) [2] * 0x00000100u +
((unsigned char const*) p) [3];
inline blargg_ulong get_be32( void const* p )
{
return (blargg_ulong) ((unsigned char const*) p) [0] << 24 |
(blargg_ulong) ((unsigned char const*) p) [1] << 16 |
(blargg_ulong) ((unsigned char const*) p) [2] << 8 |
(blargg_ulong) ((unsigned char const*) p) [3];
}
inline void set_le16( void* p, unsigned n ) {
inline void set_le16( void* p, unsigned n )
{
((unsigned char*) p) [1] = (unsigned char) (n >> 8);
((unsigned char*) p) [0] = (unsigned char) n;
}
inline void set_be16( void* p, unsigned n ) {
inline void set_be16( void* p, unsigned n )
{
((unsigned char*) p) [0] = (unsigned char) (n >> 8);
((unsigned char*) p) [1] = (unsigned char) n;
}
inline void set_le32( void* p, blargg_ulong n ) {
((unsigned char*) p) [3] = (unsigned char) (n >> 24);
((unsigned char*) p) [2] = (unsigned char) (n >> 16);
((unsigned char*) p) [1] = (unsigned char) (n >> 8);
inline void set_le32( void* p, blargg_ulong n )
{
((unsigned char*) p) [0] = (unsigned char) n;
((unsigned char*) p) [1] = (unsigned char) (n >> 8);
((unsigned char*) p) [2] = (unsigned char) (n >> 16);
((unsigned char*) p) [3] = (unsigned char) (n >> 24);
}
inline void set_be32( void* p, blargg_ulong n ) {
((unsigned char*) p) [0] = (unsigned char) (n >> 24);
((unsigned char*) p) [1] = (unsigned char) (n >> 16);
((unsigned char*) p) [2] = (unsigned char) (n >> 8);
inline void set_be32( void* p, blargg_ulong n )
{
((unsigned char*) p) [3] = (unsigned char) n;
((unsigned char*) p) [2] = (unsigned char) (n >> 8);
((unsigned char*) p) [1] = (unsigned char) (n >> 16);
((unsigned char*) p) [0] = (unsigned char) (n >> 24);
}
#if BLARGG_NONPORTABLE
@ -117,30 +132,41 @@ inline void set_be32( void* p, blargg_ulong n ) {
#define GET_BE32( addr ) (*(BOOST::uint32_t*) (addr))
#define SET_BE16( addr, data ) (void) (*(BOOST::uint16_t*) (addr) = (data))
#define SET_BE32( addr, data ) (void) (*(BOOST::uint32_t*) (addr) = (data))
#endif
#if BLARGG_CPU_POWERPC && defined (__MWERKS__)
// PowerPC has special byte-reversed instructions
// to do: assumes that PowerPC is running in big-endian mode
// to do: implement for other compilers which don't support these macros
#define GET_LE16( addr ) (__lhbrx( (addr), 0 ))
#define GET_LE32( addr ) (__lwbrx( (addr), 0 ))
#define SET_LE16( addr, data ) (__sthbrx( (data), (addr), 0 ))
#define SET_LE32( addr, data ) (__stwbrx( (data), (addr), 0 ))
#if BLARGG_CPU_POWERPC
// PowerPC has special byte-reversed instructions
#if defined (__MWERKS__)
#define GET_LE16( addr ) (__lhbrx( addr, 0 ))
#define GET_LE32( addr ) (__lwbrx( addr, 0 ))
#define SET_LE16( addr, in ) (__sthbrx( in, addr, 0 ))
#define SET_LE32( addr, in ) (__stwbrx( in, addr, 0 ))
#elif defined (__GNUC__)
#define GET_LE16( addr ) ({unsigned short ppc_lhbrx_; __asm__ volatile( "lhbrx %0,0,%1" : "=r" (ppc_lhbrx_) : "r" (addr) : "memory" ); ppc_lhbrx_;})
#define GET_LE32( addr ) ({unsigned short ppc_lwbrx_; __asm__ volatile( "lwbrx %0,0,%1" : "=r" (ppc_lwbrx_) : "r" (addr) : "memory" ); ppc_lwbrx_;})
#define SET_LE16( addr, in ) ({__asm__ volatile( "sthbrx %0,0,%1" : : "r" (in), "r" (addr) : "memory" );})
#define SET_LE32( addr, in ) ({__asm__ volatile( "stwbrx %0,0,%1" : : "r" (in), "r" (addr) : "memory" );})
#endif
#endif
#endif
#endif
#ifndef GET_LE16
#define GET_LE16( addr ) get_le16( addr )
#define GET_LE32( addr ) get_le32( addr )
#define SET_LE16( addr, data ) set_le16( addr, data )
#endif
#ifndef GET_LE32
#define GET_LE32( addr ) get_le32( addr )
#define SET_LE32( addr, data ) set_le32( addr, data )
#endif
#ifndef GET_BE16
#define GET_BE16( addr ) get_be16( addr )
#define GET_BE32( addr ) get_be32( addr )
#define SET_BE16( addr, data ) set_be16( addr, data )
#endif
#ifndef GET_BE32
#define GET_BE32( addr ) get_be32( addr )
#define SET_BE32( addr, data ) set_be32( addr, data )
#endif

View file

@ -1,4 +1,8 @@
// Included at the beginning of library source files, after all other #include lines
/* Included at the beginning of library source files, after all other #include lines.
Sets up helpful macros and services used in my source code. They don't need
module an annoying module prefix on their names since they are defined after
all other #include lines. */
#ifndef BLARGG_SOURCE_H
#define BLARGG_SOURCE_H
@ -16,10 +20,10 @@
// Like printf() except output goes to debug log file. Might be defined to do
// nothing (not even evaluate its arguments).
// void dprintf( const char* format, ... );
inline void blargg_dprintf_( const char*, ... ) { }
#undef dprintf
#define dprintf (1) ? (void) 0 : blargg_dprintf_
// void debug_printf( const char* format, ... );
static inline void blargg_dprintf_( const char*, ... ) { }
#undef debug_printf
#define debug_printf (1) ? (void) 0 : blargg_dprintf_
// If enabled, evaluate expr and if false, make debug log entry with source file
// and line. Meant for finding situations that should be examined further, but that
@ -42,9 +46,25 @@ inline void blargg_dprintf_( const char*, ... ) { }
#undef min
#undef max
#define DEF_MIN_MAX( type ) \
static inline type min( type x, type y ) { if ( x < y ) return x; return y; }\
static inline type max( type x, type y ) { if ( y < x ) return x; return y; }
DEF_MIN_MAX( int )
DEF_MIN_MAX( unsigned )
DEF_MIN_MAX( long )
DEF_MIN_MAX( unsigned long )
DEF_MIN_MAX( float )
DEF_MIN_MAX( double )
#undef DEF_MIN_MAX
/*
// using const references generates crappy code, and I am currenly only using these
// for built-in types, so they take arguments by value
// TODO: remove
inline int min( int x, int y )
template<class T>
inline T min( T x, T y )
{
@ -60,17 +80,29 @@ inline T max( T x, T y )
return y;
return x;
}
*/
// TODO: good idea? bad idea?
#undef byte
#define byte byte_
typedef unsigned char byte;
// Setup compiler defines useful for exporting required public API symbols in gme.cpp
#ifndef BLARGG_EXPORT
#if defined (_WIN32) && defined(BLARGG_BUILD_DLL)
#define BLARGG_EXPORT __declspec(dllexport)
#elif defined (LIBGME_VISIBILITY)
#define BLARGG_EXPORT __attribute__((visibility ("default")))
#else
#define BLARGG_EXPORT
#endif
#endif
// deprecated
#define BLARGG_CHECK_ALLOC CHECK_ALLOC
#define BLARGG_RETURN_ERR RETURN_ERR
// BLARGG_SOURCE_BEGIN: If defined, #included, allowing redefition of dprintf and check
// BLARGG_SOURCE_BEGIN: If defined, #included, allowing redefition of debug_printf and check
#ifdef BLARGG_SOURCE_BEGIN
#include BLARGG_SOURCE_BEGIN
#endif

View file

@ -10,9 +10,9 @@ int Gbs_Emu::cpu_read( gb_addr_t addr )
result = apu.read_register( clock(), addr );
#ifndef NDEBUG
else if ( unsigned (addr - 0x8000) < 0x2000 || unsigned (addr - 0xE000) < 0x1F00 )
dprintf( "Read from unmapped memory $%.4x\n", (unsigned) addr );
debug_printf( "Read from unmapped memory $%.4x\n", (unsigned) addr );
else if ( unsigned (addr - 0xFF01) < 0xFF80 - 0xFF01 )
dprintf( "Unhandled I/O read 0x%4X\n", (unsigned) addr );
debug_printf( "Unhandled I/O read 0x%4X\n", (unsigned) addr );
#endif
return result;
}
@ -38,7 +38,7 @@ void Gbs_Emu::cpu_write( gb_addr_t addr, int data )
ram [offset] = 0xFF;
//if ( addr == 0xFFFF )
// dprintf( "Wrote interrupt mask\n" );
// debug_printf( "Wrote interrupt mask\n" );
}
}
else if ( (addr ^ 0x2000) <= 0x2000 - 1 )
@ -48,7 +48,7 @@ void Gbs_Emu::cpu_write( gb_addr_t addr, int data )
#ifndef NDEBUG
else if ( unsigned (addr - 0x8000) < 0x2000 || unsigned (addr - 0xE000) < 0x1F00 )
{
dprintf( "Wrote to unmapped memory $%.4x\n", (unsigned) addr );
debug_printf( "Wrote to unmapped memory $%.4x\n", (unsigned) addr );
}
#endif
}
@ -59,7 +59,7 @@ void Gbs_Emu::cpu_write( gb_addr_t addr, int data )
#define CPU_READ_FAST_( emu, addr, time, out ) \
{\
out = READ_PROG( addr );\
if ( unsigned (addr - Gb_Apu::start_addr) <= Gb_Apu::register_count )\
if ( unsigned (addr - Gb_Apu::start_addr) < Gb_Apu::register_count )\
out = emu->apu.read_register( emu->cpu_time - time * clocks_per_instr, addr );\
else\
check( out == emu->cpu_read( addr ) );\

View file

@ -1,9 +1,8 @@
// Game_Music_Emu 0.5.2. http://www.slack.net/~ant/
#define IN_GME 1
// Game_Music_Emu 0.6.0. http://www.slack.net/~ant/
#include "Music_Emu.h"
#include "gme_types.h"
#if !GME_DISABLE_STEREO_DEPTH
#include "Effects_Buffer.h"
#endif
@ -24,32 +23,51 @@ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
#include "blargg_source.h"
#ifndef GME_TYPE_LIST
// Default list of all supported game music types (copy this to blargg_config.h
// if you want to modify it)
#define GME_TYPE_LIST \
gme_ay_type,\
gme_gbs_type,\
gme_gym_type,\
gme_hes_type,\
gme_kss_type,\
gme_nsf_type,\
gme_nsfe_type,\
gme_sap_type,\
gme_spc_type,\
gme_vgm_type,\
gme_vgz_type
#endif
gme_type_t const* GMEAPI gme_type_list()
BLARGG_EXPORT gme_type_t const* gme_type_list()
{
static gme_type_t const gme_type_list_ [] = { GME_TYPE_LIST, 0 };
static gme_type_t const gme_type_list_ [] = {
#ifdef GME_TYPE_LIST
GME_TYPE_LIST,
#else
#ifdef USE_GME_AY
gme_ay_type,
#endif
#ifdef USE_GME_GBS
gme_gbs_type,
#endif
#ifdef USE_GME_GYM
gme_gym_type,
#endif
#ifdef USE_GME_HES
gme_hes_type,
#endif
#ifdef USE_GME_KSS
gme_kss_type,
#endif
#ifdef USE_GME_NSF
gme_nsf_type,
#endif
#ifdef USE_GME_NSFE
gme_nsfe_type,
#endif
#ifdef USE_GME_SAP
gme_sap_type,
#endif
#ifdef USE_GME_SPC
gme_spc_type,
#endif
#ifdef USE_GME_VGM
gme_vgm_type,
gme_vgz_type,
#endif
#endif
0
};
return gme_type_list_;
}
const char* GMEAPI gme_identify_header( void const* header )
BLARGG_EXPORT const char* gme_identify_header( void const* header )
{
switch ( get_be32( header ) )
{
@ -78,7 +96,7 @@ static void to_uppercase( const char* in, int len, char* out )
*out = 0; // extension too long
}
gme_type_t GMEAPI gme_identify_extension( const char* extension_ )
BLARGG_EXPORT gme_type_t gme_identify_extension( const char* extension_ )
{
char const* end = strrchr( extension_, '.' );
if ( end )
@ -93,7 +111,7 @@ gme_type_t GMEAPI gme_identify_extension( const char* extension_ )
return 0;
}
gme_err_t GMEAPI gme_identify_file( const char* path, gme_type_t* type_out )
BLARGG_EXPORT gme_err_t gme_identify_file( const char* path, gme_type_t* type_out )
{
*type_out = gme_identify_extension( path );
// TODO: don't examine header if file has extension?
@ -108,7 +126,7 @@ gme_err_t GMEAPI gme_identify_file( const char* path, gme_type_t* type_out )
return 0;
}
gme_err_t GMEAPI gme_open_data( void const* data, long size, Music_Emu** out, int sample_rate )
BLARGG_EXPORT gme_err_t gme_open_data( void const* data, long size, Music_Emu** out, int sample_rate )
{
require( (data || !size) && out );
*out = 0;
@ -132,7 +150,7 @@ gme_err_t GMEAPI gme_open_data( void const* data, long size, Music_Emu** out, in
return err;
}
GMEEXPORT gme_err_t GMEAPI gme_open_file( const char* path, Music_Emu** out, int sample_rate )
BLARGG_EXPORT gme_err_t gme_open_file( const char* path, Music_Emu** out, int sample_rate )
{
require( path && out );
*out = 0;
@ -169,7 +187,7 @@ GMEEXPORT gme_err_t GMEAPI gme_open_file( const char* path, Music_Emu** out, int
return err;
}
Music_Emu* GMEAPI gme_new_emu( gme_type_t type, int rate )
BLARGG_EXPORT Music_Emu* gme_new_emu( gme_type_t type, int rate )
{
if ( type )
{
@ -202,27 +220,27 @@ Music_Emu* GMEAPI gme_new_emu( gme_type_t type, int rate )
return 0;
}
gme_err_t GMEAPI gme_load_file( Music_Emu* me, const char* path ) { return me->load_file( path ); }
BLARGG_EXPORT gme_err_t gme_load_file( Music_Emu* me, const char* path ) { return me->load_file( path ); }
gme_err_t GMEAPI gme_load_data( Music_Emu* me, void const* data, long size )
BLARGG_EXPORT gme_err_t gme_load_data( Music_Emu* me, void const* data, long size )
{
Mem_File_Reader in( data, size );
return me->load( in );
}
gme_err_t GMEAPI gme_load_custom( Music_Emu* me, gme_reader_t func, long size, void* data )
BLARGG_EXPORT gme_err_t gme_load_custom( Music_Emu* me, gme_reader_t func, long size, void* data )
{
Callback_Reader in( func, size, data );
return me->load( in );
}
void GMEAPI gme_delete( Music_Emu* me ) { delete me; }
BLARGG_EXPORT void gme_delete( Music_Emu* me ) { delete me; }
gme_type_t GMEAPI gme_type( Music_Emu const* me ) { return me->type(); }
BLARGG_EXPORT gme_type_t gme_type( Music_Emu const* me ) { return me->type(); }
const char* GMEAPI gme_warning( Music_Emu* me ) { return me->warning(); }
BLARGG_EXPORT const char* gme_warning( Music_Emu* me ) { return me->warning(); }
int GMEAPI gme_track_count( Music_Emu const* me ) { return me->track_count(); }
BLARGG_EXPORT int gme_track_count( Music_Emu const* me ) { return me->track_count(); }
struct gme_info_t_ : gme_info_t
{
@ -231,7 +249,7 @@ struct gme_info_t_ : gme_info_t
BLARGG_DISABLE_NOTHROW
};
gme_err_t GMEAPI gme_track_info( Music_Emu const* me, gme_info_t** out, int track )
BLARGG_EXPORT gme_err_t gme_track_info( Music_Emu const* me, gme_info_t** out, int track )
{
*out = NULL;
@ -297,12 +315,12 @@ gme_err_t GMEAPI gme_track_info( Music_Emu const* me, gme_info_t** out, int trac
return 0;
}
void GMEAPI gme_free_info( gme_info_t* info )
BLARGG_EXPORT void gme_free_info( gme_info_t* info )
{
delete STATIC_CAST(gme_info_t_*,info);
}
void GMEAPI gme_set_stereo_depth( Music_Emu* me, double depth )
BLARGG_EXPORT void gme_set_stereo_depth( Music_Emu* me, double depth )
{
#if !GME_DISABLE_STEREO_DEPTH
if ( me->effects_buffer )
@ -310,24 +328,26 @@ void GMEAPI gme_set_stereo_depth( Music_Emu* me, double depth )
#endif
}
void* GMEAPI gme_user_data ( Music_Emu const* me ) { return me->user_data(); }
void GMEAPI gme_set_user_data ( Music_Emu* me, void* new_user_data ) { me->set_user_data( new_user_data ); }
void GMEAPI gme_set_user_cleanup(Music_Emu* me, gme_user_cleanup_t func ) { me->set_user_cleanup( func ); }
BLARGG_EXPORT void* gme_user_data ( Music_Emu const* me ) { return me->user_data(); }
BLARGG_EXPORT void gme_set_user_data ( Music_Emu* me, void* new_user_data ) { me->set_user_data( new_user_data ); }
BLARGG_EXPORT void gme_set_user_cleanup(Music_Emu* me, gme_user_cleanup_t func ) { me->set_user_cleanup( func ); }
gme_err_t GMEAPI gme_start_track ( Music_Emu* me, int index ) { return me->start_track( index ); }
gme_err_t GMEAPI gme_play ( Music_Emu* me, int n, short* p ) { return me->play( n, p ); }
gme_err_t GMEAPI gme_skip ( Music_Emu* me, long n ) { return me->skip( n ); }
void GMEAPI gme_set_fade ( Music_Emu* me, int start_msec ) { me->set_fade( start_msec ); }
int GMEAPI gme_track_ended ( Music_Emu const* me ) { return me->track_ended(); }
int GMEAPI gme_tell ( Music_Emu const* me ) { return me->tell(); }
gme_err_t GMEAPI gme_seek ( Music_Emu* me, int msec ) { return me->seek( msec ); }
int GMEAPI gme_voice_count ( Music_Emu const* me ) { return me->voice_count(); }
void GMEAPI gme_ignore_silence ( Music_Emu* me, int disable ) { me->ignore_silence( disable != 0 ); }
void GMEAPI gme_set_tempo ( Music_Emu* me, double t ) { me->set_tempo( t ); }
void GMEAPI gme_mute_voice ( Music_Emu* me, int index, int mute ) { me->mute_voice( index, mute != 0 ); }
void GMEAPI gme_mute_voices ( Music_Emu* me, int mask ) { me->mute_voices( mask ); }
BLARGG_EXPORT gme_err_t gme_start_track ( Music_Emu* me, int index ) { return me->start_track( index ); }
BLARGG_EXPORT gme_err_t gme_play ( Music_Emu* me, int n, short* p ) { return me->play( n, p ); }
BLARGG_EXPORT void gme_set_fade ( Music_Emu* me, int start_msec ) { me->set_fade( start_msec ); }
BLARGG_EXPORT int gme_track_ended ( Music_Emu const* me ) { return me->track_ended(); }
BLARGG_EXPORT int gme_tell ( Music_Emu const* me ) { return me->tell(); }
BLARGG_EXPORT gme_err_t gme_seek ( Music_Emu* me, int msec ) { return me->seek( msec ); }
BLARGG_EXPORT int gme_voice_count ( Music_Emu const* me ) { return me->voice_count(); }
BLARGG_EXPORT void gme_ignore_silence ( Music_Emu* me, int disable ) { me->ignore_silence( disable != 0 ); }
BLARGG_EXPORT void gme_set_tempo ( Music_Emu* me, double t ) { me->set_tempo( t ); }
BLARGG_EXPORT void gme_mute_voice ( Music_Emu* me, int index, int mute ) { me->mute_voice( index, mute != 0 ); }
BLARGG_EXPORT void gme_mute_voices ( Music_Emu* me, int mask ) { me->mute_voices( mask ); }
BLARGG_EXPORT void gme_enable_accuracy( Music_Emu* me, int enabled ) { me->enable_accuracy( !!enabled ); }
BLARGG_EXPORT void gme_clear_playlist ( Music_Emu* me ) { me->clear_playlist(); }
BLARGG_EXPORT int gme_type_multitrack( gme_type_t t ) { return t->track_count != 1; }
void GMEAPI gme_set_equalizer ( Music_Emu* me, gme_equalizer_t const* eq )
BLARGG_EXPORT void gme_set_equalizer ( Music_Emu* me, gme_equalizer_t const* eq )
{
Music_Emu::equalizer_t e = me->equalizer();
e.treble = eq->treble;
@ -335,16 +355,22 @@ void GMEAPI gme_set_equalizer ( Music_Emu* me, gme_equalizer_t const* eq )
me->set_equalizer( e );
}
void GMEAPI gme_equalizer( Music_Emu const* me, gme_equalizer_t* out )
BLARGG_EXPORT void gme_equalizer( Music_Emu const* me, gme_equalizer_t* out )
{
gme_equalizer_t e = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
gme_equalizer_t e = gme_equalizer_t(); // Default-init all fields to 0.0f
e.treble = me->equalizer().treble;
e.bass = me->equalizer().bass;
*out = e;
}
const char* GMEAPI gme_voice_name( Music_Emu const* me, int i )
BLARGG_EXPORT const char* gme_voice_name( Music_Emu const* me, int i )
{
assert( (unsigned) i < (unsigned) me->voice_count() );
return me->voice_names() [i];
}
BLARGG_EXPORT const char* gme_type_system( gme_type_t type )
{
assert( type );
return type->system;
}

View file

@ -1,33 +1,15 @@
/* Game music emulator library C interface (also usable from C++) */
/* Game_Music_Emu 0.5.2 */
/* Game_Music_Emu 0.6.0 */
#ifndef GME_H
#define GME_H
#ifdef _MSC_VER
#define GMEAPI __stdcall
#else
#define GMEAPI
#endif
#if defined(_MSC_VER) && defined(GME_DLL)
#define GMEEXPORT __declspec(dllexport)
#define GMEIMPORT __declspec(dllimport)
#if IN_GME
#define GMEDLL GMEEXPORT
#else
#define GMEDLL GMEIMPORT
#endif
#else
#define GMEEXPORT
#define GMEIMPORT
#define GMEDLL
#endif
#ifdef __cplusplus
extern "C" {
#endif
#define GME_VERSION 0x000600 /* 1 byte major, 1 byte minor, 1 byte patch-level */
/* Error string returned by library functions, or NULL if no error (success) */
typedef const char* gme_err_t;
@ -38,38 +20,35 @@ typedef struct Music_Emu Music_Emu;
/******** Basic operations ********/
/* Create emulator and load game music file/data into it. Sets *out to new emulator. */
GMEDLL gme_err_t GMEAPI gme_open_file( const char path [], Music_Emu** out, int sample_rate );
gme_err_t gme_open_file( const char path [], Music_Emu** out, int sample_rate );
/* Number of tracks available */
GMEDLL int GMEAPI gme_track_count( Music_Emu const* );
int gme_track_count( Music_Emu const* );
/* Start a track, where 0 is the first track */
GMEDLL gme_err_t GMEAPI gme_start_track( Music_Emu*, int index );
gme_err_t gme_start_track( Music_Emu*, int index );
/* Generate 'count' 16-bit signed samples info 'out'. Output is in stereo. */
GMEDLL gme_err_t GMEAPI gme_play( Music_Emu*, int count, short out [] );
/* Skip n samples */
GMEDLL gme_err_t GMEAPI gme_skip( Music_Emu*, long n );
gme_err_t gme_play( Music_Emu*, int count, short out [] );
/* Finish using emulator and free memory */
GMEDLL void GMEAPI gme_delete( Music_Emu* );
void gme_delete( Music_Emu* );
/******** Track position/length ********/
/* Set time to start fading track out. Once fade ends track_ended() returns true.
Fade time can be changed while track is playing. */
GMEDLL void GMEAPI gme_set_fade( Music_Emu*, int start_msec );
void gme_set_fade( Music_Emu*, int start_msec );
/* True if a track has reached its end */
GMEDLL int GMEAPI gme_track_ended( Music_Emu const* );
int gme_track_ended( Music_Emu const* );
/* Number of milliseconds (1000 = one second) played since beginning of track */
GMEDLL int GMEAPI gme_tell( Music_Emu const* );
int gme_tell( Music_Emu const* );
/* Seek to new time in track. Seeking backwards or far forward can take a while. */
GMEDLL gme_err_t GMEAPI gme_seek( Music_Emu*, int msec );
gme_err_t gme_seek( Music_Emu*, int msec );
/******** Informational ********/
@ -80,22 +59,22 @@ enum { gme_info_only = -1 };
/* Most recent warning string, or NULL if none. Clears current warning after returning.
Warning is also cleared when loading a file and starting a track. */
GMEDLL const char* GMEAPI gme_warning( Music_Emu* );
const char* gme_warning( Music_Emu* );
/* Load m3u playlist file (must be done after loading music) */
GMEDLL gme_err_t GMEAPI gme_load_m3u( Music_Emu*, const char path [] );
gme_err_t gme_load_m3u( Music_Emu*, const char path [] );
/* Clear any loaded m3u playlist and any internal playlist that the music format
supports (NSFE for example). */
GMEDLL void GMEAPI gme_clear_playlist( Music_Emu* );
void gme_clear_playlist( Music_Emu* );
/* Gets information for a particular track (length, name, author, etc.).
Must be freed after use. */
typedef struct gme_info_t gme_info_t;
GMEDLL gme_err_t GMEAPI gme_track_info( Music_Emu const*, gme_info_t** out, int track );
gme_err_t gme_track_info( Music_Emu const*, gme_info_t** out, int track );
/* Frees track information */
GMEDLL void GMEAPI gme_free_info( gme_info_t* );
void gme_free_info( gme_info_t* );
struct gme_info_t
{
@ -127,30 +106,31 @@ struct gme_info_t
/* Adjust stereo echo depth, where 0.0 = off and 1.0 = maximum. Has no effect for
GYM, SPC, and Sega Genesis VGM music */
GMEDLL void GMEAPI gme_set_stereo_depth( Music_Emu*, double depth );
void gme_set_stereo_depth( Music_Emu*, double depth );
/* Disable automatic end-of-track detection and skipping of silence at beginning
if ignore is true */
GMEDLL void GMEAPI gme_ignore_silence( Music_Emu*, int ignore );
void gme_ignore_silence( Music_Emu*, int ignore );
/* Adjust song tempo, where 1.0 = normal, 0.5 = half speed, 2.0 = double speed.
Track length as returned by track_info() assumes a tempo of 1.0. */
GMEDLL void GMEAPI gme_set_tempo( Music_Emu*, double tempo );
void gme_set_tempo( Music_Emu*, double tempo );
/* Number of voices used by currently loaded file */
GMEDLL int GMEAPI gme_voice_count( Music_Emu const* );
int gme_voice_count( Music_Emu const* );
/* Name of voice i, from 0 to gme_voice_count() - 1 */
GMEDLL const char* GMEAPI gme_voice_name( Music_Emu const*, int i );
const char* gme_voice_name( Music_Emu const*, int i );
/* Mute/unmute voice i, where voice 0 is first voice */
GMEDLL void GMEAPI gme_mute_voice( Music_Emu*, int index, int mute );
void gme_mute_voice( Music_Emu*, int index, int mute );
/* Set muting state of all voices at once using a bit mask, where -1 mutes all
voices, 0 unmutes them all, 0x01 mutes just the first voice, etc. */
GMEDLL void GMEAPI gme_mute_voices( Music_Emu*, int muting_mask );
void gme_mute_voices( Music_Emu*, int muting_mask );
/* Frequency equalizer parameters (see gme.txt) */
/* Implementers: If modified, also adjust Music_Emu::make_equalizer as needed */
typedef struct gme_equalizer_t
{
double treble; /* -50.0 = muffled, 0 = flat, +5.0 = extra-crisp */
@ -160,11 +140,13 @@ typedef struct gme_equalizer_t
} gme_equalizer_t;
/* Get current frequency equalizater parameters */
GMEDLL void GMEAPI gme_equalizer( Music_Emu const*, gme_equalizer_t* out );
void gme_equalizer( Music_Emu const*, gme_equalizer_t* out );
/* Change frequency equalizer parameters */
GMEDLL void GMEAPI gme_set_equalizer( Music_Emu*, gme_equalizer_t const* eq );
void gme_set_equalizer( Music_Emu*, gme_equalizer_t const* eq );
/* Enables/disables most accurate sound emulation options */
void gme_enable_accuracy( Music_Emu*, int enabled );
/******** Game music types ********/
@ -187,17 +169,17 @@ extern const gme_type_t
gme_vgz_type;
/* Type of this emulator */
GMEDLL gme_type_t GMEAPI gme_type( Music_Emu const* );
gme_type_t gme_type( Music_Emu const* );
/* Pointer to array of all music types, with NULL entry at end. Allows a player linked
to this library to support new music types without having to be updated. */
GMEDLL gme_type_t const* GMEAPI gme_type_list();
gme_type_t const* gme_type_list();
/* Name of game system for this music file type */
GMEDLL const char* GMEAPI gme_type_system( gme_type_t );
const char* gme_type_system( gme_type_t );
/* True if this music file type supports multiple tracks */
GMEDLL int GMEAPI gme_type_multitrack( gme_type_t );
int gme_type_multitrack( gme_type_t );
/******** Advanced file loading ********/
@ -206,50 +188,50 @@ GMEDLL int GMEAPI gme_type_multitrack( gme_type_t );
extern const char* const gme_wrong_file_type;
/* Same as gme_open_file(), but uses file data already in memory. Makes copy of data. */
GMEDLL gme_err_t GMEAPI gme_open_data( void const* data, long size, Music_Emu** out, int sample_rate );
gme_err_t gme_open_data( void const* data, long size, Music_Emu** out, int sample_rate );
/* Determine likely game music type based on first four bytes of file. Returns
string containing proper file suffix (i.e. "NSF", "SPC", etc.) or "" if
file header is not recognized. */
GMEDLL const char* GMEAPI gme_identify_header( void const* header );
const char* gme_identify_header( void const* header );
/* Get corresponding music type for file path or extension passed in. */
GMEDLL gme_type_t GMEAPI gme_identify_extension( const char path_or_extension [] );
gme_type_t gme_identify_extension( const char path_or_extension [] );
/* Determine file type based on file's extension or header (if extension isn't recognized).
Sets *type_out to type, or 0 if unrecognized or error. */
GMEDLL gme_err_t GMEAPI gme_identify_file( const char path [], gme_type_t* type_out );
gme_err_t gme_identify_file( const char path [], gme_type_t* type_out );
/* Create new emulator and set sample rate. Returns NULL if out of memory. If you only need
track information, pass gme_info_only for sample_rate. */
GMEDLL Music_Emu* GMEAPI gme_new_emu( gme_type_t, int sample_rate );
Music_Emu* gme_new_emu( gme_type_t, int sample_rate );
/* Load music file into emulator */
GMEDLL gme_err_t GMEAPI gme_load_file( Music_Emu*, const char path [] );
gme_err_t gme_load_file( Music_Emu*, const char path [] );
/* Load music file from memory into emulator. Makes a copy of data passed. */
GMEDLL gme_err_t GMEAPI gme_load_data( Music_Emu*, void const* data, long size );
gme_err_t gme_load_data( Music_Emu*, void const* data, long size );
/* Load music file using custom data reader function that will be called to
read file data. Most emulators load the entire file in one read call. */
typedef gme_err_t (GMEAPI *gme_reader_t)( void* your_data, void* out, int count );
GMEDLL gme_err_t GMEAPI gme_load_custom( Music_Emu*, gme_reader_t, long file_size, void* your_data );
typedef gme_err_t (*gme_reader_t)( void* your_data, void* out, int count );
gme_err_t gme_load_custom( Music_Emu*, gme_reader_t, long file_size, void* your_data );
/* Load m3u playlist file from memory (must be done after loading music) */
GMEDLL gme_err_t GMEAPI gme_load_m3u_data( Music_Emu*, void const* data, long size );
gme_err_t gme_load_m3u_data( Music_Emu*, void const* data, long size );
/******** User data ********/
/* Set/get pointer to data you want to associate with this emulator.
You can use this for whatever you want. */
GMEDLL void GMEAPI gme_set_user_data( Music_Emu*, void* new_user_data );
GMEDLL void* GMEAPI gme_user_data( Music_Emu const* );
void gme_set_user_data( Music_Emu*, void* new_user_data );
void* gme_user_data( Music_Emu const* );
/* Register cleanup function to be called when deleting emulator, or NULL to
clear it. Passes user_data to cleanup function. */
typedef void (GMEAPI *gme_user_cleanup_t)( void* user_data );
GMEDLL void GMEAPI gme_set_user_cleanup( Music_Emu*, gme_user_cleanup_t func );
typedef void (*gme_user_cleanup_t)( void* user_data );
void gme_set_user_cleanup( Music_Emu*, gme_user_cleanup_t func );
#ifdef __cplusplus

View 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 */

View 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 */

Some files were not shown because too many files have changed in this diff Show more