diff --git a/.gitignore b/.gitignore index 09e3fb4c4..cfa4882e6 100644 --- a/.gitignore +++ b/.gitignore @@ -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/ diff --git a/CMakeLists.txt b/CMakeLists.txt index 2ed3b4146..9b37adc23 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -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} $ - DEPENDS zipdir ${PK3_DIR} ) - else( NO_GENERATOR_EXPRESSIONS ) + COMMAND ${CMAKE_COMMAND} -E copy_if_different ${ZDOOM_OUTPUT_DIR}/${PK3_NAME} $/${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 ) diff --git a/CleanDirectoryList.cmake b/CleanDirectoryList.cmake new file mode 100644 index 000000000..58b8963f9 --- /dev/null +++ b/CleanDirectoryList.cmake @@ -0,0 +1,48 @@ +# - Removes duplicate entries and non-directories from a provided list +# +# clean_directory_list( [...]) +# +# Requires CMake 2.6 or newer (uses the 'function' command) +# +# Original Author: +# 2009-2010 Ryan Pavlik +# 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() diff --git a/CreateLaunchers.cmake b/CreateLaunchers.cmake new file mode 100644 index 000000000..8acca1c17 --- /dev/null +++ b/CreateLaunchers.cmake @@ -0,0 +1,336 @@ +# - Create launchers to set working directory, env. vars, etc. +# +# include(CreateLaunchers) - to make these available +# guess_runtime_library_dirs( [ ...]) +# create_default_target_launcher( +# [ARGS ] +# [FORWARD_ARGS] +# [RUNTIME_LIBRARY_DIRS ] +# [WORKING_DIRECTORY ] +# [ENVIRONMENT [...]]) +# +# create_target_launcher( +# [ARGS ] +# [FORWARD_ARGS] +# [RUNTIME_LIBRARY_DIRS ] +# [WORKING_DIRECTORY ] +# [ENVIRONMENT [...]]) +# +# create_generic_launcher( +# [RUNTIME_LIBRARY_DIRS ] +# [WORKING_DIRECTORY ] +# [ENVIRONMENT [...]]) +# - 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 +# 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 " ") + 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() diff --git a/bzip2/CMakeLists.txt b/bzip2/CMakeLists.txt index 6006f491c..5f35eb346 100644 --- a/bzip2/CMakeLists.txt +++ b/bzip2/CMakeLists.txt @@ -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" ) diff --git a/dumb/CMakeLists.txt b/dumb/CMakeLists.txt index ee50c4a0a..178de53a9 100644 --- a/dumb/CMakeLists.txt +++ b/dumb/CMakeLists.txt @@ -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 diff --git a/dumb/src/it/itrender.c b/dumb/src/it/itrender.c index 4f3d50dfa..d4678ab4f 100644 --- a/dumb/src/it/itrender.c +++ b/dumb/src/it/itrender.c @@ -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) { diff --git a/dumb/src/it/readdsmf.c b/dumb/src/it/readdsmf.c index 5db09a75c..be545a678 100644 --- a/dumb/src/it/readdsmf.c +++ b/dumb/src/it/readdsmf.c @@ -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 ); diff --git a/dumb/src/it/readokt.c b/dumb/src/it/readokt.c index 078929c5c..b662e55c4 100644 --- a/dumb/src/it/readokt.c +++ b/dumb/src/it/readokt.c @@ -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) { diff --git a/game-music-emu/CMakeLists.txt b/game-music-emu/CMakeLists.txt index 5c4a03043..d0cc7af5f 100644 --- a/game-music-emu/CMakeLists.txt +++ b/game-music-emu/CMakeLists.txt @@ -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) diff --git a/game-music-emu/changes.txt b/game-music-emu/changes.txt index 0405b5904..3e422988c 100644 --- a/game-music-emu/changes.txt +++ b/game-music-emu/changes.txt @@ -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 diff --git a/game-music-emu/design.txt b/game-music-emu/design.txt index 8c8c65b14..d42cadb12 100644 --- a/game-music-emu/design.txt +++ b/game-music-emu/design.txt @@ -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. diff --git a/game-music-emu/game-music-emu.vcproj b/game-music-emu/game-music-emu.vcproj index 00b05d5fd..8ded6444a 100644 --- a/game-music-emu/game-music-emu.vcproj +++ b/game-music-emu/game-music-emu.vcproj @@ -80,6 +80,69 @@ Name="VCPostBuildEventTool" /> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + @@ -703,6 +707,10 @@ RelativePath=".\gme\Gme_File.h" > + + @@ -823,6 +831,10 @@ RelativePath=".\gme\Spc_Emu.h" > + + diff --git a/game-music-emu/gme.txt b/game-music-emu/gme.txt index 2c963d8e3..98971f787 100644 --- a/game-music-emu/gme.txt +++ b/game-music-emu/gme.txt @@ -1,15 +1,14 @@ -Game_Music_Emu 0.5.2 +Game_Music_Emu 0.6.0 -------------------- Author : Shay Green 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. diff --git a/game-music-emu/gme/Ay_Apu.cpp b/game-music-emu/gme/Ay_Apu.cpp index 8c1c43a0f..d58d839fe 100644 --- a/game-music-emu/gme/Ay_Apu.cpp +++ b/game-music-emu/gme/Ay_Apu.cpp @@ -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): diff --git a/game-music-emu/gme/Ay_Apu.h b/game-music-emu/gme/Ay_Apu.h index 31956939e..b031f0473 100644 --- a/game-music-emu/gme/Ay_Apu.h +++ b/game-music-emu/gme/Ay_Apu.h @@ -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 { diff --git a/game-music-emu/gme/Ay_Cpu.cpp b/game-music-emu/gme/Ay_Cpu.cpp index b4487d9c9..cdc3947f6 100644 --- a/game-music-emu/gme/Ay_Cpu.cpp +++ b/game-music-emu/gme/Ay_Cpu.cpp @@ -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: diff --git a/game-music-emu/gme/Ay_Cpu.h b/game-music-emu/gme/Ay_Cpu.h index 07241d5e6..cd3d66747 100644 --- a/game-music-emu/gme/Ay_Cpu.h +++ b/game-music-emu/gme/Ay_Cpu.h @@ -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 diff --git a/game-music-emu/gme/Ay_Emu.cpp b/game-music-emu/gme/Ay_Emu.cpp index 090b5ef82..565559441 100644 --- a/game-music-emu/gme/Ay_Emu.cpp +++ b/game-music-emu/gme/Ay_Emu.cpp @@ -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; } diff --git a/game-music-emu/gme/Ay_Emu.h b/game-music-emu/gme/Ay_Emu.h index ba8445d31..86b020487 100644 --- a/game-music-emu/gme/Ay_Emu.h +++ b/game-music-emu/gme/Ay_Emu.h @@ -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; diff --git a/game-music-emu/gme/Blip_Buffer.cpp b/game-music-emu/gme/Blip_Buffer.cpp index 9dc89ea8d..2b88cd4f8 100644 --- a/game-music-emu/gme/Blip_Buffer.cpp +++ b/game-music-emu/gme/Blip_Buffer.cpp @@ -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; } } diff --git a/game-music-emu/gme/CMakeLists.txt b/game-music-emu/gme/CMakeLists.txt new file mode 100644 index 000000000..10544d721 --- /dev/null +++ b/game-music-emu/gme/CMakeLists.txt @@ -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) diff --git a/game-music-emu/gme/Classic_Emu.cpp b/game-music-emu/gme/Classic_Emu.cpp index 622a5154f..42bb2fbe2 100644 --- a/game-music-emu/gme/Classic_Emu.cpp +++ b/game-music-emu/gme/Classic_Emu.cpp @@ -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 ); } } diff --git a/game-music-emu/gme/Classic_Emu.h b/game-music-emu/gme/Classic_Emu.h index 8cd822ca2..99e99afbe 100644 --- a/game-music-emu/gme/Classic_Emu.h +++ b/game-music-emu/gme/Classic_Emu.h @@ -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 diff --git a/game-music-emu/gme/Data_Reader.cpp b/game-music-emu/gme/Data_Reader.cpp index 8c4d8d0e1..67fc8aefd 100644 --- a/game-music-emu/gme/Data_Reader.cpp +++ b/game-music-emu/gme/Data_Reader.cpp @@ -1,15 +1,14 @@ // File_Extractor 0.4.0. http://www.slack.net/~ant/ #define _CRT_SECURE_NO_WARNINGS -#define IN_GME 1 - -#include -#include -#include #include "Data_Reader.h" #include "blargg_endian.h" +#include +#include +#include + /* 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 diff --git a/game-music-emu/gme/Data_Reader.h b/game-music-emu/gme/Data_Reader.h index e6321eb04..acf571f67 100644 --- a/game-music-emu/gme/Data_Reader.h +++ b/game-music-emu/gme/Data_Reader.h @@ -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 ); diff --git a/game-music-emu/gme/Dual_Resampler.cpp b/game-music-emu/gme/Dual_Resampler.cpp index fe2085803..149f6d6af 100644 --- a/game-music-emu/gme/Dual_Resampler.cpp +++ b/game-music-emu/gme/Dual_Resampler.cpp @@ -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; } diff --git a/game-music-emu/gme/Dual_Resampler.h b/game-music-emu/gme/Dual_Resampler.h index 61beb8a08..6dc8dcfc2 100644 --- a/game-music-emu/gme/Dual_Resampler.h +++ b/game-music-emu/gme/Dual_Resampler.h @@ -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 diff --git a/game-music-emu/gme/Effects_Buffer.cpp b/game-music-emu/gme/Effects_Buffer.cpp index 730f8e94c..6af9c14be 100644 --- a/game-music-emu/gme/Effects_Buffer.cpp +++ b/game-music-emu/gme/Effects_Buffer.cpp @@ -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" diff --git a/game-music-emu/gme/Effects_Buffer.h b/game-music-emu/gme/Effects_Buffer.h index eb0aa67a3..832c44b06 100644 --- a/game-music-emu/gme/Effects_Buffer.h +++ b/game-music-emu/gme/Effects_Buffer.h @@ -1,6 +1,6 @@ // Multi-channel effects buffer with panning, echo and reverb -// Game_Music_Emu 0.5.2 +// Game_Music_Emu 0.6.0 #ifndef EFFECTS_BUFFER_H #define EFFECTS_BUFFER_H diff --git a/game-music-emu/gme/Fir_Resampler.cpp b/game-music-emu/gme/Fir_Resampler.cpp index 56ca47801..fa426c78c 100644 --- a/game-music-emu/gme/Fir_Resampler.cpp +++ b/game-music-emu/gme/Fir_Resampler.cpp @@ -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; diff --git a/game-music-emu/gme/Fir_Resampler.h b/game-music-emu/gme/Fir_Resampler.h index 36006de79..6cd1c218d 100644 --- a/game-music-emu/gme/Fir_Resampler.h +++ b/game-music-emu/gme/Fir_Resampler.h @@ -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_(); diff --git a/game-music-emu/gme/Gb_Apu.cpp b/game-music-emu/gme/Gb_Apu.cpp index 932ebb838..866594ddf 100644 --- a/game-music-emu/gme/Gb_Apu.cpp +++ b/game-music-emu/gme/Gb_Apu.cpp @@ -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" ); } } } diff --git a/game-music-emu/gme/Gb_Cpu.cpp b/game-music-emu/gme/Gb_Cpu.cpp index bc7ac1876..bfae186e9 100644 --- a/game-music-emu/gme/Gb_Cpu.cpp +++ b/game-music-emu/gme/Gb_Cpu.cpp @@ -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; diff --git a/game-music-emu/gme/Gb_Cpu.h b/game-music-emu/gme/Gb_Cpu.h index 953fbaf50..0994cec29 100644 --- a/game-music-emu/gme/Gb_Cpu.h +++ b/game-music-emu/gme/Gb_Cpu.h @@ -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 diff --git a/game-music-emu/gme/Gbs_Emu.cpp b/game-music-emu/gme/Gbs_Emu.cpp index 83aefb424..05a0b9935 100644 --- a/game-music-emu/gme/Gbs_Emu.cpp +++ b/game-music-emu/gme/Gbs_Emu.cpp @@ -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; diff --git a/game-music-emu/gme/Gbs_Emu.h b/game-music-emu/gme/Gbs_Emu.h index 6cc6b474b..b233a2b4f 100644 --- a/game-music-emu/gme/Gbs_Emu.h +++ b/game-music-emu/gme/Gbs_Emu.h @@ -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 diff --git a/game-music-emu/gme/Gme_File.cpp b/game-music-emu/gme/Gme_File.cpp index 2d3a140e0..912a9adc1 100644 --- a/game-music-emu/gme/Gme_File.cpp +++ b/game-music-emu/gme/Gme_File.cpp @@ -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" diff --git a/game-music-emu/gme/Gme_File.h b/game-music-emu/gme/Gme_File.h index f0e94302c..2d0a57344 100644 --- a/game-music-emu/gme/Gme_File.h +++ b/game-music-emu/gme/Gme_File.h @@ -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 diff --git a/game-music-emu/gme/Gym_Emu.cpp b/game-music-emu/gme/Gym_Emu.cpp index de34f64eb..f149aebb5 100644 --- a/game-music-emu/gme/Gym_Emu.cpp +++ b/game-music-emu/gme/Gym_Emu.cpp @@ -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" diff --git a/game-music-emu/gme/Gym_Emu.h b/game-music-emu/gme/Gym_Emu.h index 0f7a0e39c..1e4ed8b3e 100644 --- a/game-music-emu/gme/Gym_Emu.h +++ b/game-music-emu/gme/Gym_Emu.h @@ -1,7 +1,7 @@ // Sega Genesis/Mega Drive GYM music file emulator // Includes with PCM timing recovery to improve sample quality. -// Game_Music_Emu 0.5.2 +// Game_Music_Emu 0.6.0 #ifndef GYM_EMU_H #define GYM_EMU_H diff --git a/game-music-emu/gme/Hes_Apu.cpp b/game-music-emu/gme/Hes_Apu.cpp index cfb171d5b..56b59dd77 100644 --- a/game-music-emu/gme/Hes_Apu.cpp +++ b/game-music-emu/gme/Hes_Apu.cpp @@ -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" ); } } } diff --git a/game-music-emu/gme/Hes_Apu.h b/game-music-emu/gme/Hes_Apu.h index ca0c932fd..89dde02cd 100644 --- a/game-music-emu/gme/Hes_Apu.h +++ b/game-music-emu/gme/Hes_Apu.h @@ -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 diff --git a/game-music-emu/gme/Hes_Cpu.cpp b/game-music-emu/gme/Hes_Cpu.cpp index 2615a0bb9..4bfe8faff 100644 --- a/game-music-emu/gme/Hes_Cpu.cpp +++ b/game-music-emu/gme/Hes_Cpu.cpp @@ -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; } diff --git a/game-music-emu/gme/Hes_Cpu.h b/game-music-emu/gme/Hes_Cpu.h index 536e732f8..d46a0b8a8 100644 --- a/game-music-emu/gme/Hes_Cpu.h +++ b/game-music-emu/gme/Hes_Cpu.h @@ -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 diff --git a/game-music-emu/gme/Hes_Emu.cpp b/game-music-emu/gme/Hes_Emu.cpp index 2306e705d..e3c700dbc 100644 --- a/game-music-emu/gme/Hes_Emu.cpp +++ b/game-music-emu/gme/Hes_Emu.cpp @@ -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 } diff --git a/game-music-emu/gme/Hes_Emu.h b/game-music-emu/gme/Hes_Emu.h index 9951eb6a2..b4e20fd67 100644 --- a/game-music-emu/gme/Hes_Emu.h +++ b/game-music-emu/gme/Hes_Emu.h @@ -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 diff --git a/game-music-emu/gme/Kss_Cpu.cpp b/game-music-emu/gme/Kss_Cpu.cpp index c943a01fe..74230bf71 100644 --- a/game-music-emu/gme/Kss_Cpu.cpp +++ b/game-music-emu/gme/Kss_Cpu.cpp @@ -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: diff --git a/game-music-emu/gme/Kss_Cpu.h b/game-music-emu/gme/Kss_Cpu.h index 6297d1000..aec24e9d5 100644 --- a/game-music-emu/gme/Kss_Cpu.h +++ b/game-music-emu/gme/Kss_Cpu.h @@ -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 diff --git a/game-music-emu/gme/Kss_Emu.cpp b/game-music-emu/gme/Kss_Emu.cpp index 3176aece7..def6ee199 100644 --- a/game-music-emu/gme/Kss_Emu.cpp +++ b/game-music-emu/gme/Kss_Emu.cpp @@ -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; } diff --git a/game-music-emu/gme/Kss_Emu.h b/game-music-emu/gme/Kss_Emu.h index 4d8463abd..e457f7311 100644 --- a/game-music-emu/gme/Kss_Emu.h +++ b/game-music-emu/gme/Kss_Emu.h @@ -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); } diff --git a/game-music-emu/gme/Kss_Scc_Apu.cpp b/game-music-emu/gme/Kss_Scc_Apu.cpp index 1660ac3da..1ab14bd00 100644 --- a/game-music-emu/gme/Kss_Scc_Apu.cpp +++ b/game-music-emu/gme/Kss_Scc_Apu.cpp @@ -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" diff --git a/game-music-emu/gme/Kss_Scc_Apu.h b/game-music-emu/gme/Kss_Scc_Apu.h index 03a6a1080..c8c69f118 100644 --- a/game-music-emu/gme/Kss_Scc_Apu.h +++ b/game-music-emu/gme/Kss_Scc_Apu.h @@ -1,6 +1,6 @@ // Konami SCC sound chip emulator -// Game_Music_Emu 0.5.2 +// Game_Music_Emu 0.6.0 #ifndef KSS_SCC_APU_H #define KSS_SCC_APU_H diff --git a/game-music-emu/gme/M3u_Playlist.cpp b/game-music-emu/gme/M3u_Playlist.cpp index f5d38893a..ffd7d82c3 100644 --- a/game-music-emu/gme/M3u_Playlist.cpp +++ b/game-music-emu/gme/M3u_Playlist.cpp @@ -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 ); diff --git a/game-music-emu/gme/M3u_Playlist.h b/game-music-emu/gme/M3u_Playlist.h index a13387945..fe90dd9f8 100644 --- a/game-music-emu/gme/M3u_Playlist.h +++ b/game-music-emu/gme/M3u_Playlist.h @@ -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(); diff --git a/game-music-emu/gme/Multi_Buffer.cpp b/game-music-emu/gme/Multi_Buffer.cpp index ecd8f8add..b86142f63 100644 --- a/game-music-emu/gme/Multi_Buffer.cpp +++ b/game-music-emu/gme/Multi_Buffer.cpp @@ -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; } diff --git a/game-music-emu/gme/Music_Emu.cpp b/game-music-emu/gme/Music_Emu.cpp index b0f3f71d5..d0dbe77a8 100644 --- a/game-music-emu/gme/Music_Emu.cpp +++ b/game-music-emu/gme/Music_Emu.cpp @@ -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"; } diff --git a/game-music-emu/gme/Music_Emu.h b/game-music-emu/gme/Music_Emu.h index 6a2eaa110..b96f4b611 100644 --- a/game-music-emu/gme/Music_Emu.h +++ b/game-music-emu/gme/Music_Emu.h @@ -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; } diff --git a/game-music-emu/gme/Nes_Apu.cpp b/game-music-emu/gme/Nes_Apu.cpp index 8daf5d0e1..68edb446d 100644 --- a/game-music-emu/gme/Nes_Apu.cpp +++ b/game-music-emu/gme/Nes_Apu.cpp @@ -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; } diff --git a/game-music-emu/gme/Nes_Cpu.cpp b/game-music-emu/gme/Nes_Cpu.cpp index 480b4aa48..ac548d0ff 100644 --- a/game-music-emu/gme/Nes_Cpu.cpp +++ b/game-music-emu/gme/Nes_Cpu.cpp @@ -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; } diff --git a/game-music-emu/gme/Nes_Cpu.h b/game-music-emu/gme/Nes_Cpu.h index 94286708d..c139e069f 100644 --- a/game-music-emu/gme/Nes_Cpu.h +++ b/game-music-emu/gme/Nes_Cpu.h @@ -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 diff --git a/game-music-emu/gme/Nes_Fme7_Apu.cpp b/game-music-emu/gme/Nes_Fme7_Apu.cpp index c058f6b1f..bc8ca7f48 100644 --- a/game-music-emu/gme/Nes_Fme7_Apu.cpp +++ b/game-music-emu/gme/Nes_Fme7_Apu.cpp @@ -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 diff --git a/game-music-emu/gme/Nes_Fme7_Apu.h b/game-music-emu/gme/Nes_Fme7_Apu.h index eb60af038..9069bd06a 100644 --- a/game-music-emu/gme/Nes_Fme7_Apu.h +++ b/game-music-emu/gme/Nes_Fme7_Apu.h @@ -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; } diff --git a/game-music-emu/gme/Nsf_Emu.cpp b/game-music-emu/gme/Nsf_Emu.cpp index 59d9b98cf..eab4bfbfd 100644 --- a/game-music-emu/gme/Nsf_Emu.cpp +++ b/game-music-emu/gme/Nsf_Emu.cpp @@ -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 } diff --git a/game-music-emu/gme/Nsf_Emu.h b/game-music-emu/gme/Nsf_Emu.h index fcce66a1e..0b001686c 100644 --- a/game-music-emu/gme/Nsf_Emu.h +++ b/game-music-emu/gme/Nsf_Emu.h @@ -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 diff --git a/game-music-emu/gme/Nsfe_Emu.cpp b/game-music-emu/gme/Nsfe_Emu.cpp index a81b18865..5559bca9b 100644 --- a/game-music-emu/gme/Nsfe_Emu.cpp +++ b/game-music-emu/gme/Nsfe_Emu.cpp @@ -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 ) { diff --git a/game-music-emu/gme/Nsfe_Emu.h b/game-music-emu/gme/Nsfe_Emu.h index 00ac40399..32b05d55e 100644 --- a/game-music-emu/gme/Nsfe_Emu.h +++ b/game-music-emu/gme/Nsfe_Emu.h @@ -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 diff --git a/game-music-emu/gme/Sap_Apu.cpp b/game-music-emu/gme/Sap_Apu.cpp index 4ad7db11c..daf72ed4a 100644 --- a/game-music-emu/gme/Sap_Apu.cpp +++ b/game-music-emu/gme/Sap_Apu.cpp @@ -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; diff --git a/game-music-emu/gme/Sap_Apu.h b/game-music-emu/gme/Sap_Apu.h index c71ce31ed..8cdd7e50c 100644 --- a/game-music-emu/gme/Sap_Apu.h +++ b/game-music-emu/gme/Sap_Apu.h @@ -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 diff --git a/game-music-emu/gme/Sap_Cpu.cpp b/game-music-emu/gme/Sap_Cpu.cpp index 10dc60618..fd9112769 100644 --- a/game-music-emu/gme/Sap_Cpu.cpp +++ b/game-music-emu/gme/Sap_Cpu.cpp @@ -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: { diff --git a/game-music-emu/gme/Sap_Cpu.h b/game-music-emu/gme/Sap_Cpu.h index 433a4e3d3..ea42c7a80 100644 --- a/game-music-emu/gme/Sap_Cpu.h +++ b/game-music-emu/gme/Sap_Cpu.h @@ -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 diff --git a/game-music-emu/gme/Sap_Emu.cpp b/game-music-emu/gme/Sap_Emu.cpp index dfee3de72..31bce6a90 100644 --- a/game-music-emu/gme/Sap_Emu.cpp +++ b/game-music-emu/gme/Sap_Emu.cpp @@ -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() diff --git a/game-music-emu/gme/Sap_Emu.h b/game-music-emu/gme/Sap_Emu.h index 4878faa66..5b0dc47df 100644 --- a/game-music-emu/gme/Sap_Emu.h +++ b/game-music-emu/gme/Sap_Emu.h @@ -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 diff --git a/game-music-emu/gme/Snes_Spc.cpp b/game-music-emu/gme/Snes_Spc.cpp index d23e2bbe9..26574223d 100644 --- a/game-music-emu/gme/Snes_Spc.cpp +++ b/game-music-emu/gme/Snes_Spc.cpp @@ -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" diff --git a/game-music-emu/gme/Snes_Spc.h b/game-music-emu/gme/Snes_Spc.h index 93a593cc0..d6c4e8135 100644 --- a/game-music-emu/gme/Snes_Spc.h +++ b/game-music-emu/gme/Snes_Spc.h @@ -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 ); } diff --git a/game-music-emu/gme/Spc_Cpu.cpp b/game-music-emu/gme/Spc_Cpu.cpp index d59f778da..90f60ed29 100644 --- a/game-music-emu/gme/Spc_Cpu.cpp +++ b/game-music-emu/gme/Spc_Cpu.cpp @@ -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: diff --git a/game-music-emu/gme/Spc_Cpu.h b/game-music-emu/gme/Spc_Cpu.h index e1b4b17b8..0ce7af7de 100644 --- a/game-music-emu/gme/Spc_Cpu.h +++ b/game-music-emu/gme/Spc_Cpu.h @@ -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; diff --git a/game-music-emu/gme/Spc_Dsp.cpp b/game-music-emu/gme/Spc_Dsp.cpp index 41c79c152..ac0baed6b 100644 --- a/game-music-emu/gme/Spc_Dsp.cpp +++ b/game-music-emu/gme/Spc_Dsp.cpp @@ -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 ); diff --git a/game-music-emu/gme/Spc_Dsp.h b/game-music-emu/gme/Spc_Dsp.h index 14b131ac1..3cec1bd91 100644 --- a/game-music-emu/gme/Spc_Dsp.h +++ b/game-music-emu/gme/Spc_Dsp.h @@ -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; diff --git a/game-music-emu/gme/Spc_Emu.cpp b/game-music-emu/gme/Spc_Emu.cpp index 7f6e72faf..341b53f9d 100644 --- a/game-music-emu/gme/Spc_Emu.cpp +++ b/game-music-emu/gme/Spc_Emu.cpp @@ -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 ); } } diff --git a/game-music-emu/gme/Spc_Emu.h b/game-music-emu/gme/Spc_Emu.h index 0c4a7fb27..09063f123 100644 --- a/game-music-emu/gme/Spc_Emu.h +++ b/game-music-emu/gme/Spc_Emu.h @@ -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 ); } diff --git a/game-music-emu/gme/Spc_Filter.cpp b/game-music-emu/gme/Spc_Filter.cpp new file mode 100644 index 000000000..0f2d18a83 --- /dev/null +++ b/game-music-emu/gme/Spc_Filter.cpp @@ -0,0 +1,83 @@ +// Game_Music_Emu 0.6.0. http://www.slack.net/~ant/ + +#include "Spc_Filter.h" + +#include + +/* 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; + } + } +} diff --git a/game-music-emu/gme/Spc_Filter.h b/game-music-emu/gme/Spc_Filter.h new file mode 100644 index 000000000..5cdcc3606 --- /dev/null +++ b/game-music-emu/gme/Spc_Filter.h @@ -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 diff --git a/game-music-emu/gme/Vgm_Emu.cpp b/game-music-emu/gme/Vgm_Emu.cpp index fe4be10a5..0f6001aae 100644 --- a/game-music-emu/gme/Vgm_Emu.cpp +++ b/game-music-emu/gme/Vgm_Emu.cpp @@ -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 ); diff --git a/game-music-emu/gme/Vgm_Emu.h b/game-music-emu/gme/Vgm_Emu.h index 7a82fd109..65895afaa 100644 --- a/game-music-emu/gme/Vgm_Emu.h +++ b/game-music-emu/gme/Vgm_Emu.h @@ -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 diff --git a/game-music-emu/gme/Vgm_Emu_Impl.cpp b/game-music-emu/gme/Vgm_Emu_Impl.cpp index a2d7c93e5..60dc099fe 100644 --- a/game-music-emu/gme/Vgm_Emu_Impl.cpp +++ b/game-music-emu/gme/Vgm_Emu_Impl.cpp @@ -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() ) { diff --git a/game-music-emu/gme/Vgm_Emu_Impl.h b/game-music-emu/gme/Vgm_Emu_Impl.h index 4d387d090..b50094a01 100644 --- a/game-music-emu/gme/Vgm_Emu_Impl.h +++ b/game-music-emu/gme/Vgm_Emu_Impl.h @@ -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 diff --git a/game-music-emu/gme/Ym2413_Emu.cpp b/game-music-emu/gme/Ym2413_Emu.cpp index ede673045..d1c7a71b1 100644 --- a/game-music-emu/gme/Ym2413_Emu.cpp +++ b/game-music-emu/gme/Ym2413_Emu.cpp @@ -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" diff --git a/game-music-emu/gme/Ym2413_Emu.h b/game-music-emu/gme/Ym2413_Emu.h index 98a2a48e1..53ce38a96 100644 --- a/game-music-emu/gme/Ym2413_Emu.h +++ b/game-music-emu/gme/Ym2413_Emu.h @@ -1,6 +1,6 @@ // YM2413 FM sound chip emulator interface -// Game_Music_Emu 0.5.2 +// Game_Music_Emu 0.6.0 #ifndef YM2413_EMU_H #define YM2413_EMU_H diff --git a/game-music-emu/gme/Ym2612_Emu.cpp b/game-music-emu/gme/Ym2612_Emu.cpp index 41ebb093d..4f9d84271 100644 --- a/game-music-emu/gme/Ym2612_Emu.cpp +++ b/game-music-emu/gme/Ym2612_Emu.cpp @@ -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 #include -/* 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 oEl'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 Ela 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 aEu (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 Ejour l'enveloppe courante. + int Ecnt; // Envelope counter = le compteur-enveloppe permet de savoir oEl'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 EAR[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 EDR[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 ESR[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 ERR[KSR] + int *OUTp; // pointeur of SLOT output = pointeur permettant de connecter la sortie de ce slot El'entree + // d'un autre ou carrement Ela 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'Elaquelle 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'Elaquelle 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 Ejour 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 Ejour sl.KSR = ksr; sl.EincA = sl.AR [ksr]; diff --git a/game-music-emu/gme/Ym2612_Emu.h b/game-music-emu/gme/Ym2612_Emu.h index 383ac72d7..51cff6586 100644 --- a/game-music-emu/gme/Ym2612_Emu.h +++ b/game-music-emu/gme/Ym2612_Emu.h @@ -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 diff --git a/game-music-emu/gme/blargg_common.h b/game-music-emu/gme/blargg_common.h index e48d6469b..ed218a8da 100644 --- a/game-music-emu/gme/blargg_common.h +++ b/game-music-emu/gme/blargg_common.h @@ -15,6 +15,13 @@ #ifndef BLARGG_COMMON_H #define BLARGG_COMMON_H +// BLARGG_RESTRICT: equivalent to restrict, where supported +#if __GNUC__ >= 3 || _MSC_VER >= 1100 + #define BLARGG_RESTRICT __restrict +#else + #define BLARGG_RESTRICT +#endif + // STATIC_CAST(T,expr): Used in place of static_cast (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 -#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 diff --git a/game-music-emu/gme/blargg_config.h b/game-music-emu/gme/blargg_config.h index 5967b0fbe..377dd2d8c 100644 --- a/game-music-emu/gme/blargg_config.h +++ b/game-music-emu/gme/blargg_config.h @@ -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 diff --git a/game-music-emu/gme/blargg_endian.h b/game-music-emu/gme/blargg_endian.h index 671655654..ba09e067e 100644 --- a/game-music-emu/gme/blargg_endian.h +++ b/game-music-emu/gme/blargg_endian.h @@ -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 diff --git a/game-music-emu/gme/blargg_source.h b/game-music-emu/gme/blargg_source.h index 945bf3498..b011777ad 100644 --- a/game-music-emu/gme/blargg_source.h +++ b/game-music-emu/gme/blargg_source.h @@ -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 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 diff --git a/game-music-emu/gme/gb_cpu_io.h b/game-music-emu/gme/gb_cpu_io.h index ada99eadc..8bd69aa2d 100644 --- a/game-music-emu/gme/gb_cpu_io.h +++ b/game-music-emu/gme/gb_cpu_io.h @@ -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 ) );\ diff --git a/game-music-emu/gme/gme.cpp b/game-music-emu/gme/gme.cpp index c9154c7a4..990fee345 100644 --- a/game-music-emu/gme/gme.cpp +++ b/game-music-emu/gme/gme.cpp @@ -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; +} diff --git a/game-music-emu/gme/gme.h b/game-music-emu/gme/gme.h index 5e9470d02..1f2a2d150 100644 --- a/game-music-emu/gme/gme.h +++ b/game-music-emu/gme/gme.h @@ -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 diff --git a/game-music-emu/gme/gme_types.h b/game-music-emu/gme/gme_types.h new file mode 100644 index 000000000..06226f4aa --- /dev/null +++ b/game-music-emu/gme/gme_types.h @@ -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 */ diff --git a/game-music-emu/gme/gme_types.h.in b/game-music-emu/gme/gme_types.h.in new file mode 100644 index 000000000..4829b3e16 --- /dev/null +++ b/game-music-emu/gme/gme_types.h.in @@ -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 */ diff --git a/game-music-emu/gme/hes_cpu_io.h b/game-music-emu/gme/hes_cpu_io.h index b3d71dad4..ce60ce8ef 100644 --- a/game-music-emu/gme/hes_cpu_io.h +++ b/game-music-emu/gme/hes_cpu_io.h @@ -44,7 +44,7 @@ inline byte const* Hes_Emu::cpu_set_mmr( int page, int bank ) default: if ( bank != 0xFF ) - dprintf( "Unmapped bank $%02X\n", bank ); + debug_printf( "Unmapped bank $%02X\n", bank ); return rom.unmapped(); } diff --git a/game-music-emu/gme/nes_cpu_io.h b/game-music-emu/gme/nes_cpu_io.h index 4bae37931..68ce9b6ff 100644 --- a/game-music-emu/gme/nes_cpu_io.h +++ b/game-music-emu/gme/nes_cpu_io.h @@ -34,7 +34,7 @@ int Nsf_Emu::cpu_read( nes_addr_t addr ) result = addr >> 8; // simulate open bus if ( addr != 0x2002 ) - dprintf( "Read unmapped $%.4X\n", (unsigned) addr ); + debug_printf( "Read unmapped $%.4X\n", (unsigned) addr ); exit: return result; diff --git a/game-music-emu/gme/sap_cpu_io.h b/game-music-emu/gme/sap_cpu_io.h index 8c2f6dd09..d009d0d9b 100644 --- a/game-music-emu/gme/sap_cpu_io.h +++ b/game-music-emu/gme/sap_cpu_io.h @@ -20,7 +20,7 @@ void Sap_Emu::cpu_write( sap_addr_t addr, int data ) int Sap_Emu::cpu_read( sap_addr_t addr ) { if ( (addr & 0xF900) == 0xD000 ) - dprintf( "Unmapped read $%04X\n", addr ); + debug_printf( "Unmapped read $%04X\n", addr ); return mem.ram [addr]; } #endif diff --git a/game-music-emu/readme.txt b/game-music-emu/readme.txt index e3470bfa1..b7451da9f 100644 --- a/game-music-emu/readme.txt +++ b/game-music-emu/readme.txt @@ -1,4 +1,4 @@ -Game_Music_Emu 0.5.2: Game Music Emulators +Game_Music_Emu 0.6.0: Game Music Emulators ------------------------------------------ Game_Music_Emu is a collection of video game music file emulators that support the following formats and systems: @@ -14,7 +14,7 @@ SPC Super Nintendo/Super Famicom VGM/VGZ Sega Master System/Mark III, Sega Genesis/Mega Drive,BBC Micro Features: -* Can be used in C and C++ code +* C interface for use in C, C++, and other compatible languages * High emphasis has been placed on making the library very easy to use * One set of common functions work with all emulators the same way * Several code examples, including music player using SDL @@ -42,8 +42,17 @@ License: GNU Lesser General Public License (LGPL) Getting Started --------------- Build a program consisting of demo/basics.c, demo/Wave_Writer.cpp, and -all source files in gme/. Be sure "test.nsf" is in the same directory. -Running the program should generate the recording "out.wav". +all source files in gme/. If you have CMake 2.6 or later, execute + + run cmake + cd demo + run make + +Be sure "test.nsf" is in the same directory as the program. Running it +should generate the recording "out.wav". + +A slightly more extensive demo application is available in the player/ +directory. It requires SDL to build. Read gme.txt for more information. Post to the discussion forum for assistance. @@ -55,16 +64,17 @@ gme.txt General notes about the library changes.txt Changes made since previous releases design.txt Library design notes license.txt GNU Lesser General Public License +CMakeLists.txt CMake build rules test.nsf Test file for NSF emulator test.m3u Test m3u playlist for features.c demo demo/ basics.c Records NSF file to wave sound file - cpp_basics.cpp C++ version of basics.c features.c Demonstrates many additional features Wave_Writer.h WAVE sound file writer used for demo output Wave_Writer.cpp + CMakeLists.txt CMake build rules player/ Player using the SDL multimedia library player.cpp Simple music player with waveform display @@ -72,22 +82,13 @@ player/ Player using the SDL multimedia library Music_Player.h Audio_Scope.cpp Audio waveform scope Audio_Scope.h + CMakeLists.txt CMake build rules gme/ blargg_config.h Library configuration (modify this file as needed) - gme.h C interface (also usable in C++, and simpler too) + gme.h Library interface header file gme.cpp - - Gme_File.h File loading and track information - Music_Emu.h Track playback and adjustments - Data_Reader.h Custom data readers - - Effects_Buffer.h Sound buffer with stereo echo and panning - Effects_Buffer.cpp - - M3u_Playlist.h M3U playlist support - M3u_Playlist.cpp Ay_Emu.h ZX Spectrum AY emulator Ay_Emu.cpp @@ -113,7 +114,7 @@ gme/ Hes_Cpu.h hes_cpu_io.h Hes_Emu.cpp - + Kss_Emu.h MSX Home Computer/other Z80 systems KSS emulator Kss_Emu.cpp Kss_Cpu.cpp @@ -180,26 +181,36 @@ gme/ Dual_Resampler.h Fir_Resampler.cpp Fir_Resampler.h - + + M3u_Playlist.h M3U playlist support + M3u_Playlist.cpp + + Effects_Buffer.h Sound buffer with stereo echo and panning + Effects_Buffer.cpp + blargg_common.h Common files needed by all emulators blargg_endian.h blargg_source.h Blip_Buffer.cpp Blip_Buffer.h + Gme_File.h Gme_File.cpp + Music_Emu.h Music_Emu.cpp Classic_Emu.h Classic_Emu.cpp Multi_Buffer.h Multi_Buffer.cpp + Data_Reader.h Data_Reader.cpp + + CMakeLists.txt CMake build rules Legal ----- -Game_Music_Emu library copyright (C) 2003-2006 Shay Green. -SNES SPC DSP emulator based on OpenSPC, copyright (C) 2002 Brad Martin. +Game_Music_Emu library copyright (C) 2003-2009 Shay Green. Sega Genesis YM2612 emulator copyright (C) 2002 Stephane Dallongeville. --- +-- Shay Green diff --git a/gdtoa/CMakeLists.txt b/gdtoa/CMakeLists.txt index 4ad0be6de..72a365bbf 100644 --- a/gdtoa/CMakeLists.txt +++ b/gdtoa/CMakeLists.txt @@ -15,64 +15,34 @@ endif( "${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" OR "${CMAKE_CXX_COMPILER_ID}" S include_directories( ${CMAKE_CURRENT_BINARY_DIR} ) add_definitions( -DINFNAN_CHECK -DMULTIPLE_THREADS ) -if( NOT MSVC ) - add_executable( arithchk arithchk.c ) +if( NOT MSVC AND NOT APPLE ) + if( NOT CMAKE_CROSSCOMPILING ) + add_executable( arithchk arithchk.c ) + endif( NOT CMAKE_CROSSCOMPILING ) + get_target_property( ARITHCHK_EXE arithchk LOCATION ) add_custom_command( OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/arith.h - COMMAND ${CMAKE_CURRENT_BINARY_DIR}/arithchk >${CMAKE_CURRENT_BINARY_DIR}/arith.h + COMMAND ${ARITHCHK_EXE} >${CMAKE_CURRENT_BINARY_DIR}/arith.h DEPENDS arithchk ) - add_executable( qnan qnan.c arith.h ) + if( NOT CMAKE_CROSSCOMPILING ) + add_executable( qnan qnan.c arith.h ) + set( CROSS_EXPORTS ${CROSS_EXPORTS} arithchk qnan PARENT_SCOPE ) + endif( NOT CMAKE_CROSSCOMPILING ) + get_target_property( QNAN_EXE qnan LOCATION ) add_custom_command( OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/gd_qnan.h - COMMAND ${CMAKE_CURRENT_BINARY_DIR}/qnan >${CMAKE_CURRENT_BINARY_DIR}/gd_qnan.h + COMMAND ${QNAN_EXE} >${CMAKE_CURRENT_BINARY_DIR}/gd_qnan.h DEPENDS qnan ) set( GEN_FP_FILES arith.h gd_qnan.h ) set( GEN_FP_DEPS ${CMAKE_CURRENT_BINARY_DIR}/arith.h ${CMAKE_CURRENTY_BINARY_DIR}/gd_qnan.h ) -endif( NOT MSVC ) +endif( NOT MSVC AND NOT APPLE ) add_library( gdtoa ${GEN_FP_FILES} dmisc.c dtoa.c - g_Qfmt.c - g__fmt.c - g_ddfmt.c - g_dfmt.c - g_ffmt.c - g_xLfmt.c - g_xfmt.c - gdtoa.c - gethex.c - gmisc.c - hd_init.c - hexnan.c misc.c - smisc.c - strtoIQ.c - strtoId.c - strtoIdd.c - strtoIf.c - strtoIg.c - strtoIx.c - strtoIxL.c - strtod.c - strtodI.c - strtodg.c - strtof.c - strtopQ.c - strtopd.c - strtopdd.c - strtopf.c - strtopx.c - strtopxL.c - strtorQ.c - strtord.c - strtordd.c - strtorf.c - strtorx.c - strtorxL.c - sum.c - ulp.c) + ) target_link_libraries( gdtoa ) if( GEN_FP_DEPS ) add_dependencies( gdtoa ${GEN_FP_DEPS} ) diff --git a/gdtoa/README b/gdtoa/README index cf1947aa2..1bf7d91e4 100644 --- a/gdtoa/README +++ b/gdtoa/README @@ -56,7 +56,9 @@ two letters: whose sum is the desired value For decimal -> binary conversions, there are three families of -helper routines: one for round-nearest: +helper routines: one for round-nearest (or the current rounding +mode on IEEE-arithmetic systems that provide the C99 fegetround() +function, if compiled with -DHonor_FLT_ROUNDS): strtof strtod @@ -150,12 +152,14 @@ suffer double rounding due to use of extended-precision registers. For some conversions this variant of strtod is less efficient than the one in strtod.c when the latter is run with 53-bit rounding precision. -The values that the strto* routines return for NaNs are determined by -gd_qnan.h, which the makefile generates by running the program whose -source is qnan.c. Note that the rules for distinguishing signaling -from quiet NaNs are system-dependent. For cross-compilation, you need -to determine arith.h and gd_qnan.h suitably, e.g., using the -arithmetic of the target machine. +When float or double are involved, the values that the strto* routines +return for NaNs are determined by gd_qnan.h, which the makefile +generates by running the program whose source is qnan.c. For other +types, default NaN values are specified in g__fmt.c and may need +adjusting. Note that the rules for distinguishing signaling from +quiet NaNs are system-dependent. For cross-compilation, you need to +determine arith.h and gd_qnan.h suitably, e.g., using the arithmetic +of the target machine. C99's hexadecimal floating-point constants are recognized by the strto* routines (but this feature has not yet been heavily tested). @@ -170,10 +174,11 @@ hexadecimal digits, it is taken for the fraction bits of the resulting NaN; if there are two or more strings of hexadecimal digits, each string is assigned to the next available sequence of 32-bit words of fractions bits (starting with the most significant), right-aligned in -each sequence. +each sequence. Strings of hexadecimal digits may be preceded by "0x" +or "0X". -For binary -> decimal conversions, I've provided just one family -of helper routines: +For binary -> decimal conversions, I've provided a family of helper +routines: g_ffmt g_dfmt @@ -181,6 +186,12 @@ of helper routines: g_xfmt g_xLfmt g_Qfmt + g_ffmt_p + g_dfmt_p + g_ddfmt_p + g_xfmt_p + g_xLfmt_p + g_Qfmt_p which do a "%g" style conversion either to a specified number of decimal places (if their ndig argument is positive), or to the shortest @@ -191,6 +202,36 @@ in the buffer, if the buffer was long enough, or 0. Other forms of conversion are easily done with the help of gdtoa(), such as %e or %f style and conversions with direction of rounding specified (so that, if desired, the decimal value is either >= or <= the binary value). +On IEEE-arithmetic systems that provide the C99 fegetround() function, +if compiled with -DHonor_FLT_ROUNDS, these routines honor the current +rounding mode. For pedants, the ...fmt_p() routines are similar to the +...fmt() routines, but have an additional final int argument, nik, +that for conversions of Infinity or NaN, determines whether upper, +lower, or mixed case is used, whether (...) is added to NaN values, +and whether the sign of a NaN is reported or suppressed: + + nik = ic + 6*(nb + 3*ns), + +where ic with 0 <= ic < 6 controls the rendering of Infinity and NaN: + + 0 ==> Infinity or NaN + 1 ==> infinity or nan + 2 ==> INFINITY or NAN + 3 ==> Inf or NaN + 4 ==> inf or nan + 5 ==> INF or NAN + +nb with 0 <= nb < 3 determines whether NaN values are rendered +as NaN(...): + + 0 ==> no + 1 ==> yes + 2 ==> no for default NaN values; yes otherwise + +ns = 0 or 1 determines whether the sign of NaN values reported: + + 0 ==> distinguish NaN and -NaN + 1 ==> report both as NaN For an example of more general conversions based on dtoa(), see netlib's "printf.c from ampl/solvers". @@ -332,5 +373,28 @@ Compiling g__fmt.c, strtod.c, and strtodg.c with -DUSE_LOCALE causes the decimal-point character to be taken from the current locale; otherwise it is '.'. +Source files dtoa.c and strtod.c in this directory are derived from +netlib's "dtoa.c from fp" and are meant to function equivalently. +When compiled with Honor_FLT_ROUNDS #defined (on systems that provide +FLT_ROUNDS and fegetround() as specified in the C99 standard), they +honor the current rounding mode. Because FLT_ROUNDS is buggy on some +(Linux) systems -- not reflecting calls on fesetround(), as the C99 +standard says it should -- when Honor_FLT_ROUNDS is #defined, the +current rounding mode is obtained from fegetround() rather than from +FLT_ROUNDS, unless Trust_FLT_ROUNDS is also #defined. + +Compile with -DUSE_LOCALE to use the current locale; otherwise +decimal points are assumed to be '.'. With -DUSE_LOCALE, unless +you also compile with -DNO_LOCALE_CACHE, the details about the +current "decimal point" character string are cached and assumed not +to change during the program's execution. + +On machines with a 64-bit long double and perhaps a 113-bit "quad" +type, you can invoke "make Printf" to add Printf (and variants, such +as Fprintf) to gdtoa.a. These are analogs, declared in stdio1.h, of +printf and fprintf, etc. in which %La, %Le, %Lf, and %Lg are for long +double and (if appropriate) %Lqa, %Lqe, %Lqf, and %Lqg are for quad +precision printing. + Please send comments to David M. Gay (dmg at acm dot org, with " at " changed at "@" and " dot " changed to "."). diff --git a/gdtoa/arithchk.c b/gdtoa/arithchk.c index 3211aeda4..ef6cda3db 100644 --- a/gdtoa/arithchk.c +++ b/gdtoa/arithchk.c @@ -106,7 +106,7 @@ ccheck() long Cray1; /* Cray1 = 4617762693716115456 -- without overflow on non-Crays */ - Cray1 = printf(emptyfmt) < 0 ? 0 : 4617762; + Cray1 = printf("%s", emptyfmt) < 0 ? 0 : 4617762; if (printf(emptyfmt, Cray1) >= 0) Cray1 = 1000000*Cray1 + 693716; if (printf(emptyfmt, Cray1) >= 0) diff --git a/gdtoa/dmisc.c b/gdtoa/dmisc.c index 72d271ca9..3e712511b 100644 --- a/gdtoa/dmisc.c +++ b/gdtoa/dmisc.c @@ -46,7 +46,7 @@ rv_alloc(int i) j = sizeof(ULong); for(k = 0; - sizeof(Bigint) - sizeof(ULong) - sizeof(int) + j <= (size_t)i; + sizeof(Bigint) - sizeof(ULong) - sizeof(int) + j <= (size_t)(i); j <<= 1) k++; r = (int*)Balloc(k); diff --git a/gdtoa/dtoa.c b/gdtoa/dtoa.c index 4fc6633b7..c96e6a545 100644 --- a/gdtoa/dtoa.c +++ b/gdtoa/dtoa.c @@ -30,7 +30,6 @@ THIS SOFTWARE. * with " at " changed at "@" and " dot " changed to "."). */ #include "gdtoaimp.h" -#include /* dtoa for IEEE arithmetic (dmg): convert double to ASCII string. * @@ -67,7 +66,6 @@ THIS SOFTWARE. */ #ifdef Honor_FLT_ROUNDS -#define Rounding rounding #undef Check_FLT_ROUNDS #define Check_FLT_ROUNDS #else @@ -77,17 +75,17 @@ THIS SOFTWARE. char * dtoa #ifdef KR_headers - (d, mode, ndigits, decpt, sign, rve) - double d; int mode, ndigits, *decpt, *sign; char **rve; + (d0, mode, ndigits, decpt, sign, rve) + double d0; int mode, ndigits, *decpt, *sign; char **rve; #else - (double _d, int mode, int ndigits, int *decpt, int *sign, char **rve) + (double d0, int mode, int ndigits, int *decpt, int *sign, char **rve) #endif { /* Arguments ndigits, decpt, sign are similar to those of ecvt and fcvt; trailing zeros are suppressed from the returned string. If not null, *rve is set to point to the end of the return value. If d is +-Infinity or NaN, - then *decpt is set to INT_MAX. + then *decpt is set to 9999. mode: 0 ==> shortest string that yields d when read in @@ -129,12 +127,22 @@ dtoa U d, d2, eps; double ds; char *s, *s0; -#ifdef Honor_FLT_ROUNDS - int rounding; -#endif #ifdef SET_INEXACT int inexact, oldinexact; #endif +#ifdef Honor_FLT_ROUNDS /*{*/ + int Rounding; +#ifdef Trust_FLT_ROUNDS /*{{ only define this if FLT_ROUNDS really works! */ + Rounding = Flt_Rounds; +#else /*}{*/ + Rounding = 1; + switch(fegetround()) { + case FE_TOWARDZERO: Rounding = 0; break; + case FE_UPWARD: Rounding = 2; break; + case FE_DOWNWARD: Rounding = 3; + } +#endif /*}}*/ +#endif /*}*/ #ifndef MULTIPLE_THREADS if (dtoa_result) { @@ -142,36 +150,35 @@ dtoa dtoa_result = 0; } #endif - - dval(d) = _d; - if (word0(d) & Sign_bit) { + d.d = d0; + if (word0(&d) & Sign_bit) { /* set sign for everything, including 0's and NaNs */ *sign = 1; - word0(d) &= ~Sign_bit; /* clear sign bit */ + word0(&d) &= ~Sign_bit; /* clear sign bit */ } else *sign = 0; #if defined(IEEE_Arith) + defined(VAX) #ifdef IEEE_Arith - if ((word0(d) & Exp_mask) == Exp_mask) + if ((word0(&d) & Exp_mask) == Exp_mask) #else - if (word0(d) == 0x8000) + if (word0(&d) == 0x8000) #endif { /* Infinity or NaN */ - *decpt = INT_MAX; + *decpt = 9999; #ifdef IEEE_Arith - if (!word1(d) && !(word0(d) & 0xfffff)) + if (!word1(&d) && !(word0(&d) & 0xfffff)) return nrv_alloc("Infinity", rve, 8); #endif return nrv_alloc("NaN", rve, 3); } #endif #ifdef IBM - dval(d) += 0; /* normalize */ + dval(&d) += 0; /* normalize */ #endif - if (!dval(d)) { + if (!dval(&d)) { *decpt = 1; return nrv_alloc("0", rve, 1); } @@ -181,35 +188,35 @@ dtoa inexact = 1; #endif #ifdef Honor_FLT_ROUNDS - if ((rounding = Flt_Rounds) >= 2) { + if (Rounding >= 2) { if (*sign) - rounding = rounding == 2 ? 0 : 2; + Rounding = Rounding == 2 ? 0 : 2; else - if (rounding != 2) - rounding = 0; + if (Rounding != 2) + Rounding = 0; } #endif - b = d2b(dval(d), &be, &bbits); + b = d2b(dval(&d), &be, &bbits); #ifdef Sudden_Underflow - i = (int)(word0(d) >> Exp_shift1 & (Exp_mask>>Exp_shift1)); + i = (int)(word0(&d) >> Exp_shift1 & (Exp_mask>>Exp_shift1)); #else - if (( i = (int)(word0(d) >> Exp_shift1 & (Exp_mask>>Exp_shift1)) )!=0) { + if (( i = (int)(word0(&d) >> Exp_shift1 & (Exp_mask>>Exp_shift1)) )!=0) { #endif - dval(d2) = dval(d); - word0(d2) &= Frac_mask1; - word0(d2) |= Exp_11; + dval(&d2) = dval(&d); + word0(&d2) &= Frac_mask1; + word0(&d2) |= Exp_11; #ifdef IBM - if (( j = 11 - hi0bits(word0(d2) & Frac_mask) )!=0) - dval(d2) /= 1 << j; + if (( j = 11 - hi0bits(word0(&d2) & Frac_mask) )!=0) + dval(&d2) /= 1 << j; #endif /* log(x) ~=~ log(1.5) + (x-1.5)/1.5 * log10(x) = log(x) / log(10) * ~=~ log(1.5)/log(10) + (x-1.5)/(1.5*log(10)) - * log10(d) = (i-Bias)*log(2)/log(10) + log10(d2) + * log10(&d) = (i-Bias)*log(2)/log(10) + log10(&d2) * - * This suggests computing an approximation k to log10(d) by + * This suggests computing an approximation k to log10(&d) by * * k = (i - Bias)*0.301029995663981 * + ( (d2-1.5)*0.289529654602168 + 0.176091259055681 ); @@ -238,21 +245,21 @@ dtoa /* d is denormalized */ i = bbits + be + (Bias + (P-1) - 1); - x = i > 32 ? word0(d) << 64 - i | word1(d) >> i - 32 - : word1(d) << 32 - i; - dval(d2) = x; - word0(d2) -= 31*Exp_msk1; /* adjust exponent */ + x = i > 32 ? word0(&d) << (64 - i) | word1(&d) >> (i - 32) + : word1(&d) << (32 - i); + dval(&d2) = x; + word0(&d2) -= 31*Exp_msk1; /* adjust exponent */ i -= (Bias + (P-1) - 1) + 1; denorm = 1; } #endif - ds = (dval(d2)-1.5)*0.289529654602168 + 0.1760912590558 + i*0.301029995663981; + ds = (dval(&d2)-1.5)*0.289529654602168 + 0.1760912590558 + i*0.301029995663981; k = (int)ds; if (ds < 0. && ds != k) k--; /* want k = floor(ds) */ k_check = 1; if (k >= 0 && k <= Ten_pmax) { - if (dval(d) < tens[k]) + if (dval(&d) < tens[k]) k--; k_check = 0; } @@ -291,10 +298,11 @@ dtoa try_quick = 0; } leftright = 1; + ilim = ilim1 = -1; /* Values for cases 0 and 1; done here to */ + /* silence erroneous "gcc -Wall" warning. */ switch(mode) { case 0: case 1: - ilim = ilim1 = -1; i = 18; ndigits = 0; break; @@ -319,7 +327,7 @@ dtoa s = s0 = rv_alloc(i); #ifdef Honor_FLT_ROUNDS - if (mode > 1 && rounding != 1) + if (mode > 1 && Rounding != 1) leftright = 0; #endif @@ -328,7 +336,7 @@ dtoa /* Try to get by with floating-point arithmetic. */ i = 0; - dval(d2) = dval(d); + dval(&d2) = dval(&d); k0 = k; ilim0 = ilim; ieps = 2; /* conservative */ @@ -338,7 +346,7 @@ dtoa if (j & Bletch) { /* prevent overflows */ j &= Bletch - 1; - dval(d) /= bigtens[n_bigtens-1]; + dval(&d) /= bigtens[n_bigtens-1]; ieps++; } for(; j; j >>= 1, i++) @@ -346,32 +354,32 @@ dtoa ieps++; ds *= bigtens[i]; } - dval(d) /= ds; + dval(&d) /= ds; } else if (( j1 = -k )!=0) { - dval(d) *= tens[j1 & 0xf]; + dval(&d) *= tens[j1 & 0xf]; for(j = j1 >> 4; j; j >>= 1, i++) if (j & 1) { ieps++; - dval(d) *= bigtens[i]; + dval(&d) *= bigtens[i]; } } - if (k_check && dval(d) < 1. && ilim > 0) { + if (k_check && dval(&d) < 1. && ilim > 0) { if (ilim1 <= 0) goto fast_failed; ilim = ilim1; k--; - dval(d) *= 10.; + dval(&d) *= 10.; ieps++; } - dval(eps) = ieps*dval(d) + 7.; - word0(eps) -= (P-1)*Exp_msk1; + dval(&eps) = ieps*dval(&d) + 7.; + word0(&eps) -= (P-1)*Exp_msk1; if (ilim == 0) { S = mhi = 0; - dval(d) -= 5.; - if (dval(d) > dval(eps)) + dval(&d) -= 5.; + if (dval(&d) > dval(&eps)) goto one_digit; - if (dval(d) < -dval(eps)) + if (dval(&d) < -dval(&eps)) goto no_digits; goto fast_failed; } @@ -380,34 +388,34 @@ dtoa /* Use Steele & White method of only * generating digits needed. */ - dval(eps) = 0.5/tens[ilim-1] - dval(eps); + dval(&eps) = 0.5/tens[ilim-1] - dval(&eps); for(i = 0;;) { - L = (Long)dval(d); - dval(d) -= L; + L = (Long)dval(&d); + dval(&d) -= L; *s++ = '0' + (int)L; - if (dval(d) < dval(eps)) + if (dval(&d) < dval(&eps)) goto ret1; - if (1. - dval(d) < dval(eps)) + if (1. - dval(&d) < dval(&eps)) goto bump_up; if (++i >= ilim) break; - dval(eps) *= 10.; - dval(d) *= 10.; + dval(&eps) *= 10.; + dval(&d) *= 10.; } } else { #endif /* Generate ilim digits, then fix them up. */ - dval(eps) *= tens[ilim-1]; - for(i = 1;; i++, dval(d) *= 10.) { - L = (Long)(dval(d)); - if (!(dval(d) -= L)) + dval(&eps) *= tens[ilim-1]; + for(i = 1;; i++, dval(&d) *= 10.) { + L = (Long)(dval(&d)); + if (!(dval(&d) -= L)) ilim = i; *s++ = '0' + (int)L; if (i == ilim) { - if (dval(d) > 0.5 + dval(eps)) + if (dval(&d) > 0.5 + dval(&eps)) goto bump_up; - else if (dval(d) < 0.5 - dval(eps)) { + else if (dval(&d) < 0.5 - dval(&eps)) { while(*--s == '0'); s++; goto ret1; @@ -420,7 +428,7 @@ dtoa #endif fast_failed: s = s0; - dval(d) = dval(d2); + dval(&d) = dval(&d2); k = k0; ilim = ilim0; } @@ -432,22 +440,22 @@ dtoa ds = tens[k]; if (ndigits < 0 && ilim <= 0) { S = mhi = 0; - if (ilim < 0 || dval(d) <= 5*ds) + if (ilim < 0 || dval(&d) <= 5*ds) goto no_digits; goto one_digit; } - for(i = 1;; i++, dval(d) *= 10.) { - L = (Long)(dval(d) / ds); - dval(d) -= L*ds; + for(i = 1;; i++, dval(&d) *= 10.) { + L = (Long)(dval(&d) / ds); + dval(&d) -= L*ds; #ifdef Check_FLT_ROUNDS /* If FLT_ROUNDS == 2, L will usually be high by 1 */ - if (dval(d) < 0) { + if (dval(&d) < 0) { L--; - dval(d) += ds; + dval(&d) += ds; } #endif *s++ = '0' + (int)L; - if (!dval(d)) { + if (!dval(&d)) { #ifdef SET_INEXACT inexact = 0; #endif @@ -456,13 +464,18 @@ dtoa if (i == ilim) { #ifdef Honor_FLT_ROUNDS if (mode > 1) - switch(rounding) { + switch(Rounding) { case 0: goto ret1; case 2: goto bump_up; } #endif - dval(d) += dval(d); - if (dval(d) > ds || dval(d) == ds && L & 1) { + dval(&d) += dval(&d); +#ifdef ROUND_BIASED + if (dval(&d) >= ds) +#else + if (dval(&d) > ds || (dval(&d) == ds && L & 1)) +#endif + { bump_up: while(*--s == '9') if (s == s0) { @@ -524,12 +537,12 @@ dtoa spec_case = 0; if ((mode < 2 || leftright) #ifdef Honor_FLT_ROUNDS - && rounding == 1 + && Rounding == 1 #endif ) { - if (!word1(d) && !(word0(d) & Bndry_mask) + if (!word1(&d) && !(word0(&d) & Bndry_mask) #ifndef Sudden_Underflow - && word0(d) & (Exp_mask & ~Exp_msk1) + && word0(&d) & (Exp_mask & ~Exp_msk1) #endif ) { /* The special case */ @@ -615,9 +628,9 @@ dtoa j1 = delta->sign ? 1 : cmp(b, delta); Bfree(delta); #ifndef ROUND_BIASED - if (j1 == 0 && mode != 1 && !(word1(d) & 1) + if (j1 == 0 && mode != 1 && !(word1(&d) & 1) #ifdef Honor_FLT_ROUNDS - && rounding >= 1 + && Rounding >= 1 #endif ) { if (dig == '9') @@ -632,11 +645,11 @@ dtoa goto ret; } #endif - if (j < 0 || j == 0 && mode != 1 + if (j < 0 || (j == 0 && mode != 1 #ifndef ROUND_BIASED - && !(word1(d) & 1) + && !(word1(&d) & 1) #endif - ) { + )) { if (!b->x[0] && b->wds <= 1) { #ifdef SET_INEXACT inexact = 0; @@ -645,7 +658,7 @@ dtoa } #ifdef Honor_FLT_ROUNDS if (mode > 1) - switch(rounding) { + switch(Rounding) { case 0: goto accept_dig; case 2: goto keep_dig; } @@ -653,7 +666,11 @@ dtoa if (j1 > 0) { b = lshift(b, 1); j1 = cmp(b, S); - if ((j1 > 0 || j1 == 0 && dig & 1) +#ifdef ROUND_BIASED + if (j1 >= 0 /*)*/ +#else + if ((j1 > 0 || (j1 == 0 && dig & 1)) +#endif && dig++ == '9') goto round_9_up; } @@ -663,7 +680,7 @@ dtoa } if (j1 > 0) { #ifdef Honor_FLT_ROUNDS - if (!rounding) + if (!Rounding) goto accept_dig; #endif if (dig == '9') { /* possible if i == 1 */ @@ -706,14 +723,19 @@ dtoa /* Round off last digit */ #ifdef Honor_FLT_ROUNDS - switch(rounding) { + switch(Rounding) { case 0: goto trimzeros; case 2: goto roundoff; } #endif b = lshift(b, 1); j = cmp(b, S); - if (j > 0 || j == 0 && dig & 1) { +#ifdef ROUND_BIASED + if (j >= 0) +#else + if (j > 0 || (j == 0 && dig & 1)) +#endif + { roundoff: while(*--s == '9') if (s == s0) { @@ -724,7 +746,9 @@ dtoa ++*s++; } else { +#ifdef Honor_FLT_ROUNDS trimzeros: +#endif while(*--s == '0'); s++; } @@ -739,9 +763,9 @@ dtoa #ifdef SET_INEXACT if (inexact) { if (!oldinexact) { - word0(d) = Exp_1 + (70 << Exp_shift); - word1(d) = 0; - dval(d) += 1.; + word0(&d) = Exp_1 + (70 << Exp_shift); + word1(&d) = 0; + dval(&d) += 1.; } } else if (!oldinexact) diff --git a/gdtoa/g_Qfmt.c b/gdtoa/g_Qfmt.c index 9d227d170..0f0697005 100644 --- a/gdtoa/g_Qfmt.c +++ b/gdtoa/g_Qfmt.c @@ -51,19 +51,24 @@ THIS SOFTWARE. char* #ifdef KR_headers -g_Qfmt(buf, V, ndig, bufsize) char *buf; char *V; int ndig; unsigned bufsize; +g_Qfmt(buf, V, ndig, bufsize) char *buf; char *V; int ndig; size_t bufsize; #else -g_Qfmt(char *buf, void *V, int ndig, unsigned bufsize) +g_Qfmt(char *buf, void *V, int ndig, size_t bufsize) #endif { - static CONST FPI fpi = { 113, 1-16383-113+1, 32766 - 16383 - 113 + 1, 1, 0 }; + static FPI fpi0 = { 113, 1-16383-113+1, 32766 - 16383 - 113 + 1, 1, 0, Int_max }; char *b, *s, *se; ULong bits[4], *L, sign; int decpt, ex, i, mode; +#ifdef Honor_FLT_ROUNDS +#include "gdtoa_fltrnds.h" +#else +#define fpi &fpi0 +#endif if (ndig < 0) ndig = 0; - if (bufsize < (unsigned)(ndig + 10)) + if (bufsize < (size_t)(ndig + 10)) return 0; L = (ULong*)V; @@ -109,6 +114,6 @@ g_Qfmt(char *buf, void *V, int ndig, unsigned bufsize) return 0; mode = 0; } - s = gdtoa(&fpi, ex, bits, &i, mode, ndig, &decpt, &se); - return g__fmt(buf, s, se, decpt, sign); + s = gdtoa(fpi, ex, bits, &i, mode, ndig, &decpt, &se); + return g__fmt(buf, s, se, decpt, sign, bufsize); } diff --git a/gdtoa/g__fmt.c b/gdtoa/g__fmt.c index 021ecfb57..652c82b68 100644 --- a/gdtoa/g__fmt.c +++ b/gdtoa/g__fmt.c @@ -35,26 +35,77 @@ THIS SOFTWARE. #include "locale.h" #endif +#ifndef ldus_QNAN0 +#define ldus_QNAN0 0x7fff +#endif +#ifndef ldus_QNAN1 +#define ldus_QNAN1 0xc000 +#endif +#ifndef ldus_QNAN2 +#define ldus_QNAN2 0 +#endif +#ifndef ldus_QNAN3 +#define ldus_QNAN3 0 +#endif +#ifndef ldus_QNAN4 +#define ldus_QNAN4 0 +#endif + + const char *InfName[6] = { "Infinity", "infinity", "INFINITY", "Inf", "inf", "INF" }; + const char *NanName[3] = { "NaN", "nan", "NAN" }; + ULong NanDflt_Q_D2A[4] = { 0xffffffff, 0xffffffff, 0xffffffff, 0x7fffffff }; + ULong NanDflt_d_D2A[2] = { d_QNAN1, d_QNAN0 }; + ULong NanDflt_f_D2A[1] = { f_QNAN }; + ULong NanDflt_xL_D2A[3] = { 1, 0x80000000, 0x7fff0000 }; + UShort NanDflt_ldus_D2A[5] = { ldus_QNAN4, ldus_QNAN3, ldus_QNAN2, ldus_QNAN1, ldus_QNAN0 }; + char * #ifdef KR_headers -g__fmt(b, s, se, decpt, sign) char *b; char *s; char *se; int decpt; ULong sign; +g__fmt(b, s, se, decpt, sign, blen) char *b; char *s; char *se; int decpt; ULong sign; size_t blen; #else -g__fmt(char *b, char *s, char *se, int decpt, ULong sign) +g__fmt(char *b, char *s, char *se, int decpt, ULong sign, size_t blen) #endif { int i, j, k; - char *s0 = s; + char *be, *s0; + size_t len; #ifdef USE_LOCALE - char decimalpoint = *localeconv()->decimal_point; +#ifdef NO_LOCALE_CACHE + char *decimalpoint = localeconv()->decimal_point; + size_t dlen = strlen(decimalpoint); #else -#define decimalpoint '.' + char *decimalpoint; + static char *decimalpoint_cache; + static size_t dlen; + if (!(s0 = decimalpoint_cache)) { + s0 = localeconv()->decimal_point; + dlen = strlen(s0); + if ((decimalpoint_cache = (char*)MALLOC(strlen(s0) + 1))) { + strcpy(decimalpoint_cache, s0); + s0 = decimalpoint_cache; + } + } + decimalpoint = s0; #endif +#else +#define dlen 0 +#endif + s0 = s; + len = (se-s) + dlen + 6; /* 6 = sign + e+dd + trailing null */ + if (blen < len) + goto ret0; + be = b + blen - 1; if (sign) *b++ = '-'; if (decpt <= -4 || decpt > se - s + 5) { *b++ = *s++; if (*s) { - *b++ = decimalpoint; +#ifdef USE_LOCALE + while((*b = *decimalpoint++)) + ++b; +#else + *b++ = '.'; +#endif while((*b = *s++) !=0) b++; } @@ -69,6 +120,8 @@ g__fmt(char *b, char *s, char *se, int decpt, ULong sign) for(j = 2, k = 10; 10*k <= decpt; j++, k *= 10){} for(;;) { i = decpt / k; + if (b >= be) + goto ret0; *b++ = i + '0'; if (--j <= 0) break; @@ -78,22 +131,73 @@ g__fmt(char *b, char *s, char *se, int decpt, ULong sign) *b = 0; } else if (decpt <= 0) { - *b++ = decimalpoint; +#ifdef USE_LOCALE + while((*b = *decimalpoint++)) + ++b; +#else + *b++ = '.'; +#endif + if (be < b - decpt + (se - s)) + goto ret0; for(; decpt < 0; decpt++) *b++ = '0'; - while((*b = *s++) !=0) + while((*b = *s++) != 0) b++; } else { - while((*b = *s++) !=0) { + while((*b = *s++) != 0) { b++; - if (--decpt == 0 && *s) - *b++ = decimalpoint; + if (--decpt == 0 && *s) { +#ifdef USE_LOCALE + while(*b = *decimalpoint++) + ++b; +#else + *b++ = '.'; +#endif + } + } + if (b + decpt > be) { + ret0: + b = 0; + goto ret; } for(; decpt > 0; decpt--) *b++ = '0'; *b = 0; } + ret: freedtoa(s0); return b; } + + char * +add_nanbits_D2A(char *b, size_t blen, ULong *bits, int nb) +{ + ULong t; + char *rv; + int i, j; + size_t L; + static char Hexdig[16] = "0123456789abcdef"; + + while(!bits[--nb]) + if (!nb) + return b; + L = 8*nb + 3; + t = bits[nb]; + do ++L; while((t >>= 4)); + if (L > blen) + return b; + b += L; + *--b = 0; + rv = b; + *--b = /*(*/ ')'; + for(i = 0; i < nb; ++i) { + t = bits[i]; + for(j = 0; j < 8; ++j, t >>= 4) + *--b = Hexdig[t & 0xf]; + } + t = bits[nb]; + do *--b = Hexdig[t & 0xf]; while(t >>= 4); + *--b = '('; /*)*/ + return rv; + } diff --git a/gdtoa/g_ddfmt.c b/gdtoa/g_ddfmt.c index d96e78dbe..5ce4a076b 100644 --- a/gdtoa/g_ddfmt.c +++ b/gdtoa/g_ddfmt.c @@ -33,9 +33,9 @@ THIS SOFTWARE. char * #ifdef KR_headers -g_ddfmt(buf, dd, ndig, bufsize) char *buf; double *dd; int ndig; unsigned bufsize; +g_ddfmt(buf, dd0, ndig, bufsize) char *buf; double *dd0; int ndig; size_t bufsize; #else -g_ddfmt(char *buf, double *dd, int ndig, unsigned bufsize) +g_ddfmt(char *buf, double *dd0, int ndig, size_t bufsize) #endif { FPI fpi; @@ -43,12 +43,28 @@ g_ddfmt(char *buf, double *dd, int ndig, unsigned bufsize) ULong *L, bits0[4], *bits, *zx; int bx, by, decpt, ex, ey, i, j, mode; Bigint *x, *y, *z; - double ddx[2]; + U *dd, ddx[2]; +#ifdef Honor_FLT_ROUNDS /*{{*/ + int Rounding; +#ifdef Trust_FLT_ROUNDS /*{{ only define this if FLT_ROUNDS really works! */ + Rounding = Flt_Rounds; +#else /*}{*/ + Rounding = 1; + switch(fegetround()) { + case FE_TOWARDZERO: Rounding = 0; break; + case FE_UPWARD: Rounding = 2; break; + case FE_DOWNWARD: Rounding = 3; + } +#endif /*}}*/ +#else /*}{*/ +#define Rounding FPI_Round_near +#endif /*}}*/ - if (bufsize < 10 || bufsize < (unsigned)(ndig + 8)) + if (bufsize < 10 || bufsize < (size_t)(ndig + 8)) return 0; - L = (ULong*)dd; + dd = (U*)dd0; + L = dd->L; if ((L[_0] & 0x7ff00000L) == 0x7ff00000L) { /* Infinity or NaN */ if (L[_0] & 0xfffff || L[_1]) { @@ -73,7 +89,7 @@ g_ddfmt(char *buf, double *dd, int ndig, unsigned bufsize) goto nanret; goto infret; } - if (dd[0] + dd[1] == 0.) { + if (dval(&dd[0]) + dval(&dd[1]) == 0.) { b = buf; #ifndef IGNORE_ZERO_SIGN if (L[_0] & L[2+_0] & 0x80000000L) @@ -84,16 +100,16 @@ g_ddfmt(char *buf, double *dd, int ndig, unsigned bufsize) return b; } if ((L[_0] & 0x7ff00000L) < (L[2+_0] & 0x7ff00000L)) { - ddx[1] = dd[0]; - ddx[0] = dd[1]; + dval(&ddx[1]) = dval(&dd[0]); + dval(&ddx[0]) = dval(&dd[1]); dd = ddx; - L = (ULong*)dd; + L = dd->L; } - z = d2b(dd[0], &ex, &bx); - if (dd[1] == 0.) + z = d2b(dval(&dd[0]), &ex, &bx); + if (dval(&dd[1]) == 0.) goto no_y; x = z; - y = d2b(dd[1], &ey, &by); + y = d2b(dval(&dd[1]), &ey, &by); if ( (i = ex - ey) !=0) { if (i > 0) { x = lshift(x, i); @@ -136,7 +152,7 @@ g_ddfmt(char *buf, double *dd, int ndig, unsigned bufsize) } mode = 2; if (ndig <= 0) { - if (bufsize < (unsigned)((int)(fpi.nbits * .301029995664) + 10)) { + if (bufsize < (size_t)((int)(fpi.nbits * .301029995664) + 10)) { Bfree(z); return 0; } @@ -144,11 +160,12 @@ g_ddfmt(char *buf, double *dd, int ndig, unsigned bufsize) } fpi.emin = 1-1023-53+1; fpi.emax = 2046-1023-106+1; - fpi.rounding = FPI_Round_near; + fpi.rounding = Rounding; fpi.sudden_underflow = 0; + fpi.int_max = Int_max; i = STRTOG_Normal; s = gdtoa(&fpi, ex, bits, &i, mode, ndig, &decpt, &se); - b = g__fmt(buf, s, se, decpt, z->sign); + b = g__fmt(buf, s, se, decpt, z->sign, bufsize); Bfree(z); return b; } diff --git a/gdtoa/g_dfmt.c b/gdtoa/g_dfmt.c index 74b4ccc28..d8e1438c4 100644 --- a/gdtoa/g_dfmt.c +++ b/gdtoa/g_dfmt.c @@ -33,25 +33,32 @@ THIS SOFTWARE. char* #ifdef KR_headers -g_dfmt(buf, d, ndig, bufsize) char *buf; double *d; int ndig; unsigned bufsize; +g_dfmt(buf, d, ndig, bufsize) char *buf; double *d; int ndig; size_t bufsize; #else -g_dfmt(char *buf, double *d, int ndig, unsigned bufsize) +g_dfmt(char *buf, double *d, int ndig, size_t bufsize) #endif { - static CONST FPI fpi = { 53, 1-1023-53+1, 2046-1023-53+1, 1, 0 }; + static FPI fpi0 = { 53, 1-1023-53+1, 2046-1023-53+1, 1, 0, Int_max }; char *b, *s, *se; ULong bits[2], *L, sign; int decpt, ex, i, mode; +#ifdef Honor_FLT_ROUNDS +#include "gdtoa_fltrnds.h" +#else +#define fpi &fpi0 +#endif if (ndig < 0) ndig = 0; - if (bufsize < (unsigned)(ndig + 10)) + if (bufsize < (size_t)(ndig + 10)) return 0; L = (ULong*)d; sign = L[_0] & 0x80000000L; if ((L[_0] & 0x7ff00000) == 0x7ff00000) { /* Infinity or NaN */ + if (bufsize < 10) + return 0; if (L[_0] & 0xfffff || L[_1]) { return strcp(buf, "NaN"); } @@ -78,12 +85,11 @@ g_dfmt(char *buf, double *d, int ndig, unsigned bufsize) ex = 1; ex -= 0x3ff + 52; mode = 2; - if (ndig <= 0) { - if (bufsize < 25) - return 0; + if (ndig <= 0) mode = 0; - } i = STRTOG_Normal; - s = gdtoa(&fpi, ex, bits, &i, mode, ndig, &decpt, &se); - return g__fmt(buf, s, se, decpt, sign); + if (sign) + i = STRTOG_Normal | STRTOG_Neg; + s = gdtoa(fpi, ex, bits, &i, mode, ndig, &decpt, &se); + return g__fmt(buf, s, se, decpt, sign, bufsize); } diff --git a/gdtoa/g_ffmt.c b/gdtoa/g_ffmt.c index 9b2c5fea6..30b53ae7e 100644 --- a/gdtoa/g_ffmt.c +++ b/gdtoa/g_ffmt.c @@ -33,19 +33,24 @@ THIS SOFTWARE. char* #ifdef KR_headers -g_ffmt(buf, f, ndig, bufsize) char *buf; float *f; int ndig; unsigned bufsize; +g_ffmt(buf, f, ndig, bufsize) char *buf; float *f; int ndig; size_t bufsize; #else -g_ffmt(char *buf, float *f, int ndig, unsigned bufsize) +g_ffmt(char *buf, float *f, int ndig, size_t bufsize) #endif { - static CONST FPI fpi = { 24, 1-127-24+1, 254-127-24+1, 1, 0 }; + static FPI fpi0 = { 24, 1-127-24+1, 254-127-24+1, 1, 0, 6 }; char *b, *s, *se; ULong bits[1], *L, sign; int decpt, ex, i, mode; +#ifdef Honor_FLT_ROUNDS +#include "gdtoa_fltrnds.h" +#else +#define fpi &fpi0 +#endif if (ndig < 0) ndig = 0; - if (bufsize < (unsigned)(ndig + 10)) + if (bufsize < (size_t)(ndig + 10)) return 0; L = (ULong*)f; @@ -83,6 +88,6 @@ g_ffmt(char *buf, float *f, int ndig, unsigned bufsize) mode = 0; } i = STRTOG_Normal; - s = gdtoa(&fpi, ex, bits, &i, mode, ndig, &decpt, &se); - return g__fmt(buf, s, se, decpt, sign); + s = gdtoa(fpi, ex, bits, &i, mode, ndig, &decpt, &se); + return g__fmt(buf, s, se, decpt, sign, bufsize); } diff --git a/gdtoa/g_xLfmt.c b/gdtoa/g_xLfmt.c index a2a993b59..5cda8d59e 100644 --- a/gdtoa/g_xLfmt.c +++ b/gdtoa/g_xLfmt.c @@ -49,19 +49,24 @@ THIS SOFTWARE. char* #ifdef KR_headers -g_xLfmt(buf, V, ndig, bufsize) char *buf; char *V; int ndig; unsigned bufsize; +g_xLfmt(buf, V, ndig, bufsize) char *buf; char *V; int ndig; size_t bufsize; #else -g_xLfmt(char *buf, void *V, int ndig, unsigned bufsize) +g_xLfmt(char *buf, void *V, int ndig, size_t bufsize) #endif { - static CONST FPI fpi = { 64, 1-16383-64+1, 32766 - 16383 - 64 + 1, 1, 0 }; + static FPI fpi0 = { 64, 1-16383-64+1, 32766 - 16383 - 64 + 1, 1, 0, Int_max }; char *b, *s, *se; ULong bits[2], *L, sign; int decpt, ex, i, mode; +#ifdef Honor_FLT_ROUNDS +#include "gdtoa_fltrnds.h" +#else +#define fpi &fpi0 +#endif if (ndig < 0) ndig = 0; - if (bufsize < (unsigned)(ndig + 10)) + if (bufsize < (size_t)(ndig + 10)) return 0; L = (ULong*)V; @@ -103,6 +108,6 @@ g_xLfmt(char *buf, void *V, int ndig, unsigned bufsize) return 0; mode = 0; } - s = gdtoa(&fpi, ex, bits, &i, mode, ndig, &decpt, &se); - return g__fmt(buf, s, se, decpt, sign); + s = gdtoa(fpi, ex, bits, &i, mode, ndig, &decpt, &se); + return g__fmt(buf, s, se, decpt, sign, bufsize); } diff --git a/gdtoa/g_xfmt.c b/gdtoa/g_xfmt.c index c51a16dce..a0baa518c 100644 --- a/gdtoa/g_xfmt.c +++ b/gdtoa/g_xfmt.c @@ -53,20 +53,25 @@ THIS SOFTWARE. char* #ifdef KR_headers -g_xfmt(buf, V, ndig, bufsize) char *buf; char *V; int ndig; unsigned bufsize; +g_xfmt(buf, V, ndig, bufsize) char *buf; char *V; int ndig; size_t bufsize; #else -g_xfmt(char *buf, void *V, int ndig, unsigned bufsize) +g_xfmt(char *buf, void *V, int ndig, size_t bufsize) #endif { - static CONST FPI fpi = { 64, 1-16383-64+1, 32766 - 16383 - 64 + 1, 1, 0 }; + static FPI fpi0 = { 64, 1-16383-64+1, 32766 - 16383 - 64 + 1, 1, 0, Int_max }; char *b, *s, *se; ULong bits[2], sign; UShort *L; int decpt, ex, i, mode; +#ifdef Honor_FLT_ROUNDS +#include "gdtoa_fltrnds.h" +#else +#define fpi &fpi0 +#endif if (ndig < 0) ndig = 0; - if (bufsize < (unsigned)(ndig + 10)) + if (bufsize < (size_t)(ndig + 10)) return 0; L = (UShort *)V; @@ -76,14 +81,14 @@ g_xfmt(char *buf, void *V, int ndig, unsigned bufsize) if ( (ex = L[_0] & 0x7fff) !=0) { if (ex == 0x7fff) { /* Infinity or NaN */ - if (bits[0] | bits[1]) - b = strcp(buf, "NaN"); - else { + if (!bits[0] && bits[1]== 0x80000000) { b = buf; if (sign) *b++ = '-'; b = strcp(b, "Infinity"); } + else + b = strcp(buf, "NaN"); return b; } i = STRTOG_Normal; @@ -109,6 +114,6 @@ g_xfmt(char *buf, void *V, int ndig, unsigned bufsize) return 0; mode = 0; } - s = gdtoa(&fpi, ex, bits, &i, mode, ndig, &decpt, &se); - return g__fmt(buf, s, se, decpt, sign); + s = gdtoa(fpi, ex, bits, &i, mode, ndig, &decpt, &se); + return g__fmt(buf, s, se, decpt, sign, bufsize); } diff --git a/gdtoa/gdtoa.c b/gdtoa/gdtoa.c index 7e8d2b2bf..a4759968a 100644 --- a/gdtoa/gdtoa.c +++ b/gdtoa/gdtoa.c @@ -30,7 +30,6 @@ THIS SOFTWARE. * with " at " changed at "@" and " dot " changed to "."). */ #include "gdtoaimp.h" -#include static Bigint * #ifdef KR_headers @@ -62,7 +61,7 @@ bitstob(ULong *bits, int nbits, int *bbits) *x++ = (*bits >> 16) & ALL_ON; #endif } while(++bits <= be); - i = (int)(x - x0); + i = x - x0; while(!x0[--i]) if (!i) { b->wds = 0; @@ -116,14 +115,15 @@ gdtoa FPI *fpi; int be; ULong *bits; int *kindp, mode, ndigits, *decpt; char **rve; #else - (CONST FPI *fpi, int be, ULong *bits, int *kindp, int mode, int ndigits, int *decpt, char **rve) + (FPI *fpi, int be, ULong *bits, int *kindp, int mode, int ndigits, int *decpt, char **rve) #endif { /* Arguments ndigits and decpt are similar to the second and third arguments of ecvt and fcvt; trailing zeros are suppressed from the returned string. If not null, *rve is set to point to the end of the return value. If d is +-Infinity or NaN, - then *decpt is set to INT_MAX. + then *decpt is set to 9999. + be = exponent: value = (integer represented by bits) * (2 to the power of be). mode: 0 ==> shortest string that yields d when read in @@ -159,8 +159,8 @@ gdtoa Long L; Bigint *b, *b1, *delta, *mlo, *mhi, *mhi1, *S; double d2, ds; - U d, eps; char *s, *s0; + U d, eps; #ifndef MULTIPLE_THREADS if (dtoa_result) { @@ -177,10 +177,10 @@ gdtoa case STRTOG_Denormal: break; case STRTOG_Infinite: - *decpt = INT_MAX; + *decpt = -32768; return nrv_alloc("Infinity", rve, 8); case STRTOG_NaN: - *decpt = INT_MAX; + *decpt = -32768; return nrv_alloc("NaN", rve, 3); default: return 0; @@ -199,21 +199,21 @@ gdtoa return nrv_alloc("0", rve, 1); } - dval(d) = b2d(b, &i); + dval(&d) = b2d(b, &i); i = be + bbits - 1; - word0(d) &= Frac_mask1; - word0(d) |= Exp_11; + word0(&d) &= Frac_mask1; + word0(&d) |= Exp_11; #ifdef IBM - if ( (j = 11 - hi0bits(word0(d) & Frac_mask)) !=0) - dval(d) /= 1 << j; + if ( (j = 11 - hi0bits(word0(&d) & Frac_mask)) !=0) + dval(&d) /= 1 << j; #endif /* log(x) ~=~ log(1.5) + (x-1.5)/1.5 * log10(x) = log(x) / log(10) * ~=~ log(1.5)/log(10) + (x-1.5)/(1.5*log(10)) - * log10(d) = (i-Bias)*log(2)/log(10) + log10(d2) + * log10(&d) = (i-Bias)*log(2)/log(10) + log10(d2) * - * This suggests computing an approximation k to log10(d) by + * This suggests computing an approximation k to log10(&d) by * * k = (i - Bias)*0.301029995663981 * + ( (d2-1.5)*0.289529654602168 + 0.176091259055681 ); @@ -233,7 +233,7 @@ gdtoa i <<= 2; i += j; #endif - ds = (dval(d)-1.5)*0.289529654602168 + 0.1760912590558 + i*0.301029995663981; + ds = (dval(&d)-1.5)*0.289529654602168 + 0.1760912590558 + i*0.301029995663981; /* correct assumption about exponent range */ if ((j = i) < 0) @@ -248,13 +248,13 @@ gdtoa #ifdef IBM j = be + bbits - 1; if ( (j1 = j & 3) !=0) - dval(d) *= 1 << j1; - word0(d) += j << Exp_shift - 2 & Exp_mask; + dval(&d) *= 1 << j1; + word0(&d) += j << Exp_shift - 2 & Exp_mask; #else - word0(d) += (be + bbits - 1) << Exp_shift; + word0(&d) += (be + bbits - 1) << Exp_shift; #endif if (k >= 0 && k <= Ten_pmax) { - if (dval(d) < tens[k]) + if (dval(&d) < tens[k]) k--; k_check = 0; } @@ -284,11 +284,14 @@ gdtoa mode -= 4; try_quick = 0; } + else if (i >= -4 - Emin || i < Emin) + try_quick = 0; leftright = 1; + ilim = ilim1 = -1; /* Values for cases 0 and 1; done here to */ + /* silence erroneous "gcc -Wall" warning. */ switch(mode) { case 0: case 1: - ilim = ilim1 = -1; i = (int)(nbits * .30103) + 3; ndigits = 0; break; @@ -330,10 +333,10 @@ gdtoa /* Try to get by with floating-point arithmetic. */ i = 0; - d2 = dval(d); + d2 = dval(&d); #ifdef IBM - if ( (j = 11 - hi0bits(word0(d) & Frac_mask)) !=0) - dval(d) /= 1 << j; + if ( (j = 11 - hi0bits(word0(&d) & Frac_mask)) !=0) + dval(&d) /= 1 << j; #endif k0 = k; ilim0 = ilim; @@ -344,7 +347,7 @@ gdtoa if (j & Bletch) { /* prevent overflows */ j &= Bletch - 1; - dval(d) /= bigtens[n_bigtens-1]; + dval(&d) /= bigtens[n_bigtens-1]; ieps++; } for(; j; j >>= 1, i++) @@ -356,30 +359,30 @@ gdtoa else { ds = 1.; if ( (j1 = -k) !=0) { - dval(d) *= tens[j1 & 0xf]; + dval(&d) *= tens[j1 & 0xf]; for(j = j1 >> 4; j; j >>= 1, i++) if (j & 1) { ieps++; - dval(d) *= bigtens[i]; + dval(&d) *= bigtens[i]; } } } - if (k_check && dval(d) < 1. && ilim > 0) { + if (k_check && dval(&d) < 1. && ilim > 0) { if (ilim1 <= 0) goto fast_failed; ilim = ilim1; k--; - dval(d) *= 10.; + dval(&d) *= 10.; ieps++; } - dval(eps) = ieps*dval(d) + 7.; - word0(eps) -= (P-1)*Exp_msk1; + dval(&eps) = ieps*dval(&d) + 7.; + word0(&eps) -= (P-1)*Exp_msk1; if (ilim == 0) { S = mhi = 0; - dval(d) -= 5.; - if (dval(d) > dval(eps)) + dval(&d) -= 5.; + if (dval(&d) > dval(&eps)) goto one_digit; - if (dval(d) < -dval(eps)) + if (dval(&d) < -dval(&eps)) goto no_digits; goto fast_failed; } @@ -388,42 +391,40 @@ gdtoa /* Use Steele & White method of only * generating digits needed. */ - dval(eps) = ds*0.5/tens[ilim-1] - dval(eps); + dval(&eps) = ds*0.5/tens[ilim-1] - dval(&eps); for(i = 0;;) { - L = (Long)(dval(d)/ds); - dval(d) -= L*ds; + L = (Long)(dval(&d)/ds); + dval(&d) -= L*ds; *s++ = '0' + (int)L; - if (dval(d) < dval(eps)) { - if (dval(d)) + if (dval(&d) < dval(&eps)) { + if (dval(&d)) inex = STRTOG_Inexlo; goto ret1; } - if (ds - dval(d) < dval(eps)) + if (ds - dval(&d) < dval(&eps)) goto bump_up; if (++i >= ilim) break; - dval(eps) *= 10.; - dval(d) *= 10.; + dval(&eps) *= 10.; + dval(&d) *= 10.; } } else { #endif /* Generate ilim digits, then fix them up. */ - dval(eps) *= tens[ilim-1]; - for(i = 1;; i++, dval(d) *= 10.) { - if ( (L = (Long)(dval(d)/ds)) !=0) - dval(d) -= L*ds; + dval(&eps) *= tens[ilim-1]; + for(i = 1;; i++, dval(&d) *= 10.) { + if ( (L = (Long)(dval(&d)/ds)) !=0) + dval(&d) -= L*ds; *s++ = '0' + (int)L; if (i == ilim) { ds *= 0.5; - if (dval(d) > ds + dval(eps)) + if (dval(&d) > ds + dval(&eps)) goto bump_up; - else if (dval(d) < ds - dval(eps)) { - while(*--s == '0'){} - s++; - if (dval(d)) + else if (dval(&d) < ds - dval(&eps)) { + if (dval(&d)) inex = STRTOG_Inexlo; - goto ret1; + goto clear_trailing0; } break; } @@ -433,34 +434,34 @@ gdtoa #endif fast_failed: s = s0; - dval(d) = d2; + dval(&d) = d2; k = k0; ilim = ilim0; } /* Do we have a "small" integer? */ - if (be >= 0 && k <= Int_max) { + if (be >= 0 && k <= fpi->int_max) { /* Yes. */ ds = tens[k]; if (ndigits < 0 && ilim <= 0) { S = mhi = 0; - if (ilim < 0 || dval(d) <= 5*ds) + if (ilim < 0 || dval(&d) <= 5*ds) goto no_digits; goto one_digit; } - for(i = 1;; i++, dval(d) *= 10.) { - L = (Long)(dval(d) / ds); - dval(d) -= L*ds; + for(i = 1;; i++, dval(&d) *= 10.) { + L = (Long)(dval(&d) / ds); + dval(&d) -= L*ds; #ifdef Check_FLT_ROUNDS /* If FLT_ROUNDS == 2, L will usually be high by 1 */ - if (dval(d) < 0) { + if (dval(&d) < 0) { L--; - dval(d) += ds; + dval(&d) += ds; } #endif *s++ = '0' + (int)L; - if (dval(d) == 0.) + if (dval(&d) == 0.) break; if (i == ilim) { if (rdir) { @@ -469,8 +470,13 @@ gdtoa inex = STRTOG_Inexlo; goto ret1; } - dval(d) += dval(d); - if (dval(d) > ds || dval(d) == ds && L & 1) { + dval(&d) += dval(&d); +#ifdef ROUND_BIASED + if (dval(&d) >= ds) +#else + if (dval(&d) > ds || (dval(&d) == ds && L & 1)) +#endif + { bump_up: inex = STRTOG_Inexhi; while(*--s == '9') @@ -481,8 +487,12 @@ gdtoa } ++*s++; } - else + else { inex = STRTOG_Inexlo; + clear_trailing0: + while(*--s == '0'){} + ++s; + } break; } } @@ -493,13 +503,15 @@ gdtoa m5 = b5; mhi = mlo = 0; if (leftright) { - if (mode < 2) { - i = nbits - bbits; - if (be - i++ < fpi->emin) - /* denormal */ - i = be - fpi->emin + 1; + i = nbits - bbits; + if (be - i++ < fpi->emin && mode != 3 && mode != 5) { + /* denormal */ + i = be - fpi->emin + 1; + if (mode >= 2 && ilim > 0 && ilim < i) + goto small_ilim; } - else { + else if (mode >= 2) { + small_ilim: j = ilim - 1; if (m5 >= j) m5 -= j; @@ -560,28 +572,11 @@ gdtoa * and for all and pass them and a shift to quorem, so it * can do shifts and ors to compute the numerator for q. */ -#ifdef Pack_32 - if ( (i = ((s5 ? 32 - hi0bits(S->x[S->wds-1]) : 1) + s2) & 0x1f) !=0) - i = 32 - i; -#else - if ( (i = ((s5 ? 32 - hi0bits(S->x[S->wds-1]) : 1) + s2) & 0xf) !=0) - i = 16 - i; -#endif - if (i > 4) { - i -= 4; - b2 += i; - m2 += i; - s2 += i; - } - else if (i < 4) { - i += 28; - b2 += i; - m2 += i; - s2 += i; - } - if (b2 > 0) + i = ((s5 ? hi0bits(S->x[S->wds-1]) : ULbits - 1) - s2 - 4) & kmask; + m2 += i; + if ((b2 += i) > 0) b = lshift(b, b2); - if (s2 > 0) + if ((s2 += i) > 0) S = lshift(S, s2); if (k_check) { if (cmp(b,S) < 0) { @@ -646,11 +641,11 @@ gdtoa goto ret; } #endif - if (j < 0 || j == 0 && !mode + if (j < 0 || (j == 0 && !mode #ifndef ROUND_BIASED && !(bits[0] & 1) #endif - ) { + )) { if (rdir && (b->wds > 1 || b->x[0])) { if (rdir == 2) { inex = STRTOG_Inexlo; @@ -673,7 +668,11 @@ gdtoa if (j1 > 0) { b = lshift(b, 1); j1 = cmp(b, S); - if ((j1 > 0 || j1 == 0 && dig & 1) +#ifdef ROUND_BIASED + if (j1 >= 0 /*)*/ +#else + if ((j1 > 0 || (j1 == 0 && dig & 1)) +#endif && dig++ == '9') goto round_9_up; inex = STRTOG_Inexhi; @@ -718,13 +717,18 @@ gdtoa /* Round off last digit */ if (rdir) { - if (rdir == 2 || b->wds <= 1 && !b->x[0]) + if (rdir == 2 || (b->wds <= 1 && !b->x[0])) goto chopzeros; goto roundoff; } b = lshift(b, 1); j = cmp(b, S); - if (j > 0 || j == 0 && dig & 1) { +#ifdef ROUND_BIASED + if (j >= 0) +#else + if (j > 0 || (j == 0 && dig & 1)) +#endif + { roundoff: inex = STRTOG_Inexhi; while(*--s == '9') @@ -740,7 +744,7 @@ gdtoa if (b->wds > 1 || b->x[0]) inex = STRTOG_Inexlo; while(*--s == '0'){} - s++; + ++s; } ret: Bfree(S); diff --git a/gdtoa/gdtoa.h b/gdtoa/gdtoa.h index 95132294e..8b7390a28 100644 --- a/gdtoa/gdtoa.h +++ b/gdtoa/gdtoa.h @@ -32,7 +32,7 @@ THIS SOFTWARE. #ifndef GDTOA_H_INCLUDED #define GDTOA_H_INCLUDED -#ifdef _MSC_VER +#if defined(_MSC_VER) /* [RH] Generating arith.h strikes me as too cumbersome under Visual * Studio, so here's the equivalent, given the limited number of * architectures that MSC can target. (Itanium? Who cares about that?) @@ -43,19 +43,36 @@ THIS SOFTWARE. #ifdef _M_X64 #define X64_bit_pointers #endif +#elif defined(__APPLE__) +/* [BL] While generating the files may be easy, on OS X we have cross + * compiling to deal with, which means we can't run the generation + * program on the target. + */ +#if defined(__x86_64__) +#define IEEE_8087 +#define Arith_Kind_ASL 1 +#define Long int +#define Intcast (int)(long) +#define Double_Align +#define X64_bit_pointers +#elif defined(__i386__) +#define IEEE_8087 +#define Arith_Kind_ASL 1 +#else +#define IEEE_MC68k +#define Arith_Kind_ASL 2 +#define Double_Align +#endif #else #include "arith.h" #endif +#include /* for size_t */ -/* [RH] On 64-bit Unix systems, long is a 64-bit type. I do not that is - * is what is desired here, so I sacrifice compatibility with systems - * that use 16-bit ints (oh no!) and make Long an int instead. - */ #ifndef Long -typedef int Long; +#define Long int #endif #ifndef ULong -typedef unsigned int ULong; +typedef unsigned Long ULong; #endif #ifndef UShort typedef unsigned short UShort; @@ -91,9 +108,9 @@ typedef unsigned short UShort; /* The following may be or-ed into one of the above values. */ - STRTOG_Neg = 0x08, - STRTOG_Inexlo = 0x10, - STRTOG_Inexhi = 0x20, + STRTOG_Neg = 0x08, /* does not affect STRTOG_Inexlo or STRTOG_Inexhi */ + STRTOG_Inexlo = 0x10, /* returned result rounded toward zero */ + STRTOG_Inexhi = 0x20, /* returned result rounded away from zero */ STRTOG_Inexact = 0x30, STRTOG_Underflow= 0x40, STRTOG_Overflow = 0x80 @@ -106,6 +123,7 @@ FPI { int emax; int rounding; int sudden_underflow; + int int_max; } FPI; enum { /* FPI.rounding values: same as FLT_ROUNDS */ @@ -115,29 +133,31 @@ enum { /* FPI.rounding values: same as FLT_ROUNDS */ FPI_Round_down = 3 }; -// Our strtod is not the CRT's strtod. -#include -#define strtod mystrtod - #ifdef __cplusplus extern "C" { #endif extern char* dtoa ANSI((double d, int mode, int ndigits, int *decpt, int *sign, char **rve)); -extern char* gdtoa ANSI((CONST FPI *fpi, int be, ULong *bits, int *kindp, +extern char* gdtoa ANSI((FPI *fpi, int be, ULong *bits, int *kindp, int mode, int ndigits, int *decpt, char **rve)); extern void freedtoa ANSI((char*)); -extern float strtof ANSI((CONST char *, char **)); -extern double strtod ANSI((CONST char *, char **)); -extern int strtodg ANSI((CONST char*, char**, CONST FPI*, Long*, ULong*)); +//extern float strtof ANSI((CONST char *, char **)); +//extern double strtod ANSI((CONST char *, char **)); +extern int strtodg ANSI((CONST char*, char**, FPI*, Long*, ULong*)); -extern char* g_ddfmt ANSI((char*, double*, int, unsigned)); -extern char* g_dfmt ANSI((char*, double*, int, unsigned)); -extern char* g_ffmt ANSI((char*, float*, int, unsigned)); -extern char* g_Qfmt ANSI((char*, void*, int, unsigned)); -extern char* g_xfmt ANSI((char*, void*, int, unsigned)); -extern char* g_xLfmt ANSI((char*, void*, int, unsigned)); +extern char* g_ddfmt ANSI((char*, double*, int, size_t)); +extern char* g_ddfmt_p ANSI((char*, double*, int, size_t, int)); +extern char* g_dfmt ANSI((char*, double*, int, size_t)); +extern char* g_dfmt_p ANSI((char*, double*, int, size_t, int)); +extern char* g_ffmt ANSI((char*, float*, int, size_t)); +extern char* g_ffmt_p ANSI((char*, float*, int, size_t, int)); +extern char* g_Qfmt ANSI((char*, void*, int, size_t)); +extern char* g_Qfmt_p ANSI((char*, void*, int, size_t, int)); +extern char* g_xfmt ANSI((char*, void*, int, size_t)); +extern char* g_xfmt_p ANSI((char*, void*, int, size_t, int)); +extern char* g_xLfmt ANSI((char*, void*, int, size_t)); +extern char* g_xLfmt_p ANSI((char*, void*, int, size_t, int)); extern int strtoId ANSI((CONST char*, char**, double*, double*)); extern int strtoIdd ANSI((CONST char*, char**, double*, double*)); diff --git a/gdtoa/gdtoa.vcproj b/gdtoa/gdtoa.vcproj index 7195c1457..3ac6ce39d 100644 --- a/gdtoa/gdtoa.vcproj +++ b/gdtoa/gdtoa.vcproj @@ -293,50 +293,434 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + = 7400 appears to suffice; with * 4-byte pointers, PRIVATE_MEM >= 7112 appears adequate. - * #define INFNAN_CHECK on IEEE systems to cause strtod to check for - * Infinity and NaN (case insensitively). + * #define NO_INFNAN_CHECK if you do not wish to have INFNAN_CHECK + * #defined automatically on IEEE systems. On such systems, + * when INFNAN_CHECK is #defined, strtod checks + * for Infinity and NaN (case insensitively). * When INFNAN_CHECK is #defined and No_Hex_NaN is not #defined, * strtodg also accepts (case insensitively) strings of the form * NaN(x), where x is a string of hexadecimal digits (optionally @@ -151,7 +164,7 @@ THIS SOFTWARE. * dtoa. You may do so whether or not MULTIPLE_THREADS is #defined. * #define IMPRECISE_INEXACT if you do not care about the setting of * the STRTOG_Inexact bits in the special case of doing IEEE double - * precision conversions (which could also be done by the strtog in + * precision conversions (which could also be done by the strtod in * dtoa.c). * #define NO_HEX_FP to disable recognition of C9x's hexadecimal * floating-point constants. @@ -167,7 +180,7 @@ THIS SOFTWARE. #define GDTOAIMP_H_INCLUDED #include "gdtoa.h" -#ifdef _MSC_VER +#if defined(_MSC_VER) /* [RH] Generating gd_qnan.h strikes me as too cumbersome under Visual * Studio, so here's the equivalent, given the limited number of * architectures that MSC can target. (Itanium? Who cares about that?) @@ -188,10 +201,42 @@ THIS SOFTWARE. * it turns out that it has a true long double type. I thought that * all ia32 compilers had phased out extended precision. */ +#elif defined(__APPLE__) +#if defined(__x86_64__) || defined(__i386__) +#define f_QNAN 0xffc00000 +#define d_QNAN0 0x0 +#define d_QNAN1 0xfff80000 +#define ld_QNAN0 0x0 +#define ld_QNAN1 0xc0000000 +#define ld_QNAN2 0xffff +#define ld_QNAN3 0x0 +#define ldus_QNAN0 0x0 +#define ldus_QNAN1 0x0 +#define ldus_QNAN2 0x0 +#define ldus_QNAN3 0xc000 +#define ldus_QNAN4 0xffff +#else +#define f_QNAN 0xffc00000 +#define d_QNAN0 0xfff80000 +#define d_QNAN1 0x0 +#define ld_QNAN0 0xfff80000 +#define ld_QNAN1 0x0 +#define ld_QNAN2 0x0 +#define ld_QNAN3 0x0 +#define ldus_QNAN0 0xfff8 +#define ldus_QNAN1 0x0 +#define ldus_QNAN2 0x0 +#define ldus_QNAN3 0x0 +#define ldus_QNAN4 0x0 +#endif #else #include "gd_qnan.h" #endif +#ifdef Honor_FLT_ROUNDS +#include +#endif + #ifdef DEBUG #include "stdio.h" #define Bug(x) {fprintf(stderr, "%s\n", x); exit(1);} @@ -201,13 +246,13 @@ THIS SOFTWARE. #include "string.h" #ifdef KR_headers -#define KR_VOID char +#define Char char #else -#define KR_VOID void +#define Char void #endif #ifdef MALLOC -extern KR_VOID *MALLOC ANSI((size_t)); +extern Char *MALLOC ANSI((size_t)); #else #define MALLOC malloc #endif @@ -279,19 +324,19 @@ extern "C" { #endif #if defined(IEEE_8087) + defined(IEEE_MC68k) + defined(VAX) + defined(IBM) != 1 -#error Exactly one of IEEE_8087, IEEE_MC68k, VAX, or IBM should be defined. +Exactly one of IEEE_8087, IEEE_MC68k, VAX, or IBM should be defined. #endif typedef union { double d; ULong L[2]; } U; #ifdef IEEE_8087 -#define word0(x) x.L[1] -#define word1(x) x.L[0] +#define word0(x) (x)->L[1] +#define word1(x) (x)->L[0] #else -#define word0(x) x.L[0] -#define word1(x) x.L[1] +#define word0(x) (x)->L[0] +#define word1(x) (x)->L[1] #endif -#define dval(x) x.d +#define dval(x) (x)->d /* The following definition of Storeinc is appropriate for MIPS processors. * An alternative that might be better on some machines is @@ -405,6 +450,11 @@ typedef union { double d; ULong L[2]; } U; #ifndef IEEE_Arith #define ROUND_BIASED +#else +#ifdef ROUND_BIASED_without_Round_Up +#undef ROUND_BIASED +#define ROUND_BIASED +#endif #endif #ifdef RND_PRODQUOT @@ -460,12 +510,12 @@ extern double rnd_prod(double, double), rnd_quot(double, double); #define ALL_ON 0xffff #endif -#ifndef MULTIPLE_THREADS +//#ifndef MULTIPLE_THREADS #define ACQUIRE_DTOA_LOCK(n) /*nothing*/ #define FREE_DTOA_LOCK(n) /*nothing*/ -#endif +//#endif -#define Kmax (sizeof(size_t) << 3) +#define Kmax 9 struct Bigint { @@ -488,12 +538,15 @@ extern void memcpy_D2A ANSI((void*, const void*, size_t)); #define Balloc Balloc_D2A #define Bfree Bfree_D2A +#define InfName InfName_D2A +#define NanName NanName_D2A #define ULtoQ ULtoQ_D2A #define ULtof ULtof_D2A #define ULtod ULtod_D2A #define ULtodd ULtodd_D2A #define ULtox ULtox_D2A #define ULtoxL ULtoxL_D2A +#define add_nanbits add_nanbits_D2A #define any_on any_on_D2A #define b2d b2d_D2A #define bigtens bigtens_D2A @@ -532,9 +585,11 @@ extern void memcpy_D2A ANSI((void*, const void*, size_t)); #define trailz trailz_D2A #define ulp ulp_D2A + extern char *add_nanbits ANSI((char*, size_t, ULong*, int)); extern char *dtoa_result; extern CONST double bigtens[], tens[], tinytens[]; extern unsigned char hexdig[]; + extern const char *InfName[6], *NanName[3]; extern Bigint *Balloc ANSI((int)); extern void Bfree ANSI((Bigint*)); @@ -549,14 +604,14 @@ extern void memcpy_D2A ANSI((void*, const void*, size_t)); extern int cmp ANSI((Bigint*, Bigint*)); extern void copybits ANSI((ULong*, int, Bigint*)); extern Bigint *d2b ANSI((double, int*, int*)); - extern int decrement ANSI((Bigint*)); + extern void decrement ANSI((Bigint*)); extern Bigint *diff ANSI((Bigint*, Bigint*)); extern char *dtoa ANSI((double d, int mode, int ndigits, int *decpt, int *sign, char **rve)); - extern char *g__fmt ANSI((char*, char*, char*, int, ULong)); - extern int gethex ANSI((CONST char**, CONST FPI*, Long*, Bigint**, int)); + extern char *g__fmt ANSI((char*, char*, char*, int, ULong, size_t)); + extern int gethex ANSI((CONST char**, FPI*, Long*, Bigint**, int)); extern void hexdig_init_D2A(Void); - extern int hexnan ANSI((CONST char**, CONST FPI*, ULong*)); + extern int hexnan ANSI((CONST char**, FPI*, ULong*)); extern int hi0bits_D2A ANSI((ULong)); extern Bigint *i2b ANSI((int)); extern Bigint *increment ANSI((Bigint*)); @@ -571,14 +626,14 @@ extern void memcpy_D2A ANSI((void*, const void*, size_t)); extern double ratio ANSI((Bigint*, Bigint*)); extern void rshift ANSI((Bigint*, int)); extern char *rv_alloc ANSI((int)); - extern Bigint *s2b ANSI((CONST char*, int, int, ULong)); + extern Bigint *s2b ANSI((CONST char*, int, int, ULong, int)); extern Bigint *set_ones ANSI((Bigint*, int)); extern char *strcp ANSI((char*, const char*)); - extern int strtoIg ANSI((CONST char*, char**, CONST FPI*, Long*, Bigint**, int*)); - extern double strtod ANSI((const char *s00, char **se)); + extern int strtoIg ANSI((CONST char*, char**, FPI*, Long*, Bigint**, int*)); +// extern double strtod ANSI((const char *s00, char **se)); extern Bigint *sum ANSI((Bigint*, Bigint*)); extern int trailz ANSI((Bigint*)); - extern double ulp ANSI((double)); + extern double ulp ANSI((U*)); #ifdef __cplusplus } @@ -593,6 +648,10 @@ extern void memcpy_D2A ANSI((void*, const void*, size_t)); * (On HP Series 700/800 machines, -DNAN_WORD0=0x7ff40000 works.) */ #ifdef IEEE_Arith +#ifndef NO_INFNAN_CHECK +#undef INFNAN_CHECK +#define INFNAN_CHECK +#endif #ifdef IEEE_MC68k #define _0 0 #define _1 1 diff --git a/gdtoa/gethex.c b/gdtoa/gethex.c index 7273a6c3b..72da9d326 100644 --- a/gdtoa/gethex.c +++ b/gdtoa/gethex.c @@ -40,22 +40,34 @@ THIS SOFTWARE. gethex(sp, fpi, exp, bp, sign) CONST char **sp; FPI *fpi; Long *exp; Bigint **bp; int sign; #else -gethex( CONST char **sp, CONST FPI *fpi, Long *exp, Bigint **bp, int sign) +gethex( CONST char **sp, FPI *fpi, Long *exp, Bigint **bp, int sign) #endif { Bigint *b; CONST unsigned char *decpt, *s0, *s, *s1; - int esign, havedig, irv, k, n, nbits, up, zret; + int big, esign, havedig, irv, j, k, n, n0, nbits, up, zret; ULong L, lostbits, *x; Long e, e1; #ifdef USE_LOCALE - unsigned char decimalpoint = *localeconv()->decimal_point; + int i; +#ifdef NO_LOCALE_CACHE + const unsigned char *decimalpoint = (unsigned char*)localeconv()->decimal_point; #else -#define decimalpoint '.' + const unsigned char *decimalpoint; + static unsigned char *decimalpoint_cache; + if (!(s0 = decimalpoint_cache)) { + s0 = (unsigned char*)localeconv()->decimal_point; + if ((decimalpoint_cache = (char*)MALLOC(strlen(s0) + 1))) { + strcpy(decimalpoint_cache, s0); + s0 = decimalpoint_cache; + } + } + decimalpoint = s0; +#endif #endif - if (!hexdig['0']) - hexdig_init_D2A(); + /**** if (!hexdig['0']) hexdig_init_D2A(); ****/ + *bp = 0; havedig = 0; s0 = *(CONST unsigned char **)sp + 2; while(s0[havedig] == '0') @@ -65,11 +77,21 @@ gethex( CONST char **sp, CONST FPI *fpi, Long *exp, Bigint **bp, int sign) decpt = 0; zret = 0; e = 0; - if (!hexdig[*s]) { + if (hexdig[*s]) + havedig++; + else { zret = 1; - if (*s != decimalpoint) +#ifdef USE_LOCALE + for(i = 0; decimalpoint[i]; ++i) { + if (s[i] != decimalpoint[i]) + goto pcheck; + } + decpt = s += i; +#else + if (*s != '.') goto pcheck; decpt = ++s; +#endif if (!hexdig[*s]) goto pcheck; while(*s == '0') @@ -81,19 +103,28 @@ gethex( CONST char **sp, CONST FPI *fpi, Long *exp, Bigint **bp, int sign) } while(hexdig[*s]) s++; - if (*s == decimalpoint && !decpt) { +#ifdef USE_LOCALE + if (*s == *decimalpoint && !decpt) { + for(i = 1; decimalpoint[i]; ++i) { + if (s[i] != decimalpoint[i]) + goto pcheck; + } + decpt = s += i; +#else + if (*s == '.' && !decpt) { decpt = ++s; +#endif while(hexdig[*s]) s++; - } + }/*}*/ if (decpt) e = -(((Long)(s-decpt)) << 2); pcheck: s1 = s; + big = esign = 0; switch(*s) { case 'p': case 'P': - esign = 0; switch(*++s) { case '-': esign = 1; @@ -106,29 +137,87 @@ gethex( CONST char **sp, CONST FPI *fpi, Long *exp, Bigint **bp, int sign) break; } e1 = n - 0x10; - while((n = hexdig[*++s]) !=0 && n <= 0x19) + while((n = hexdig[*++s]) !=0 && n <= 0x19) { + if (e1 & 0xf8000000) + big = 1; e1 = 10*e1 + n - 0x10; + } if (esign) e1 = -e1; e += e1; } *sp = (char*)s; - if (zret) { - if (!havedig) - *sp = s0 - 1; + if (!havedig) + *sp = (char*)s0 - 1; + if (zret) return STRTOG_Zero; + if (big) { + if (esign) { + switch(fpi->rounding) { + case FPI_Round_up: + if (sign) + break; + goto ret_tiny; + case FPI_Round_down: + if (!sign) + break; + goto ret_tiny; + } + goto retz; + ret_tiny: + b = Balloc(0); + b->wds = 1; + b->x[0] = 1; + goto dret; + } + switch(fpi->rounding) { + case FPI_Round_near: + goto ovfl1; + case FPI_Round_up: + if (!sign) + goto ovfl1; + goto ret_big; + case FPI_Round_down: + if (sign) + goto ovfl1; + goto ret_big; + } + ret_big: + nbits = fpi->nbits; + n0 = n = nbits >> kshift; + if (nbits & kmask) + ++n; + for(j = n, k = 0; j >>= 1; ++k); + *bp = b = Balloc(k); + b->wds = n; + for(j = 0; j < n0; ++j) + b->x[j] = ALL_ON; + if (n > n0) + b->x[j] = ULbits >> (ULbits - (nbits & kmask)); + *exp = fpi->emin; + return STRTOG_Normal | STRTOG_Inexlo; } - n = (int)(s1 - s0 - 1); - for(k = 0; n > 7; n >>= 1) + n = s1 - s0 - 1; + for(k = 0; n > (1 << (kshift-2)) - 1; n >>= 1) k++; b = Balloc(k); x = b->x; n = 0; L = 0; +#ifdef USE_LOCALE + for(i = 0; decimalpoint[i+1]; ++i); +#endif while(s1 > s0) { - if (*--s1 == decimalpoint) +#ifdef USE_LOCALE + if (*--s1 == decimalpoint[i]) { + s1 -= i; continue; - if (n == 32) { + } +#else + if (*--s1 == '.') + continue; +#endif + if (n == ULbits) { *x++ = L; L = 0; n = 0; @@ -137,8 +226,8 @@ gethex( CONST char **sp, CONST FPI *fpi, Long *exp, Bigint **bp, int sign) n += 4; } *x++ = L; - b->wds = n = (int)(x - b->x); - n = 32*n - hi0bits(L); + b->wds = n = x - b->x; + n = ULbits*n - hi0bits(L); nbits = fpi->nbits; lostbits = 0; x = b->x; @@ -149,7 +238,7 @@ gethex( CONST char **sp, CONST FPI *fpi, Long *exp, Bigint **bp, int sign) k = n - 1; if (x[k>>kshift] & 1 << (k & kmask)) { lostbits = 2; - if (k > 1 && any_on(b,k-1)) + if (k > 0 && any_on(b,k)) lostbits = 3; } } @@ -165,7 +254,10 @@ gethex( CONST char **sp, CONST FPI *fpi, Long *exp, Bigint **bp, int sign) if (e > fpi->emax) { ovfl: Bfree(b); - *bp = 0; + ovfl1: +#ifndef NO_ERRNO + errno = ERANGE; +#endif return STRTOG_Infinite | STRTOG_Overflow | STRTOG_Inexhi; } irv = STRTOG_Normal; @@ -185,15 +277,22 @@ gethex( CONST char **sp, CONST FPI *fpi, Long *exp, Bigint **bp, int sign) case FPI_Round_down: if (sign) { one_bit: - *exp = fpi->emin; x[0] = b->wds = 1; + dret: *bp = b; + *exp = fpi->emin; +#ifndef NO_ERRNO + errno = ERANGE; +#endif return STRTOG_Denormal | STRTOG_Inexhi | STRTOG_Underflow; } } Bfree(b); - *bp = 0; + retz: +#ifndef NO_ERRNO + errno = ERANGE; +#endif return STRTOG_Zero | STRTOG_Inexlo | STRTOG_Underflow; } k = n - 1; @@ -214,7 +313,7 @@ gethex( CONST char **sp, CONST FPI *fpi, Long *exp, Bigint **bp, int sign) break; case FPI_Round_near: if (lostbits & 2 - && (lostbits & 1) | x[0] & 1) + && (lostbits | x[0]) & 1) up = 1; break; case FPI_Round_up: @@ -233,8 +332,8 @@ gethex( CONST char **sp, CONST FPI *fpi, Long *exp, Bigint **bp, int sign) irv = STRTOG_Normal; } else if (b->wds > k - || (n = nbits & kmask) !=0 - && hi0bits(x[k-1]) < 32-n) { + || ((n = nbits & kmask) !=0 + && hi0bits(x[k-1]) < 32-n)) { rshift(b,1); if (++e > fpi->emax) goto ovfl; diff --git a/gdtoa/gmisc.c b/gdtoa/gmisc.c index 988d3bfbb..8270ef944 100644 --- a/gdtoa/gmisc.c +++ b/gdtoa/gmisc.c @@ -60,7 +60,7 @@ rshift(Bigint *b, int k) while(x < xe) *x1++ = *x++; } - if ((b->wds = (int)(x1 - b->x)) == 0) + if ((b->wds = x1 - b->x) == 0) b->x[0] = 0; } diff --git a/gdtoa/hd_init.c b/gdtoa/hd_init.c index fa6e18dee..d79ae2ec8 100644 --- a/gdtoa/hd_init.c +++ b/gdtoa/hd_init.c @@ -31,6 +31,7 @@ THIS SOFTWARE. #include "gdtoaimp.h" +#if 0 unsigned char hexdig[256]; static void @@ -46,10 +47,31 @@ htinit(unsigned char *h, unsigned char *s, int inc) } void -hexdig_init_D2A(Void) +hexdig_init_D2A(Void) /* Use of hexdig_init omitted 20121220 to avoid a */ + /* race condition when multiple threads are used. */ { #define USC (unsigned char *) htinit(hexdig, USC "0123456789", 0x10); htinit(hexdig, USC "abcdef", 0x10 + 10); htinit(hexdig, USC "ABCDEF", 0x10 + 10); } +#else + unsigned char hexdig[256] = { + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 16,17,18,19,20,21,22,23,24,25,0,0,0,0,0,0, + 0,26,27,28,29,30,31,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,26,27,28,29,30,31,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + }; +#endif diff --git a/gdtoa/hexnan.c b/gdtoa/hexnan.c index 0ee127f56..80721e97a 100644 --- a/gdtoa/hexnan.c +++ b/gdtoa/hexnan.c @@ -54,15 +54,14 @@ L_shift(ULong *x, ULong *x1, int i) hexnan(sp, fpi, x0) CONST char **sp; FPI *fpi; ULong *x0; #else -hexnan( CONST char **sp, CONST FPI *fpi, ULong *x0) +hexnan( CONST char **sp, FPI *fpi, ULong *x0) #endif { ULong c, h, *x, *x1, *xe; CONST char *s; int havedig, hd0, i, nbits; - if (!hexdig['0']) - hexdig_init_D2A(); + /**** if (!hexdig['0']) hexdig_init_D2A(); ****/ nbits = fpi->nbits; x = x0 + (nbits >> kshift); if (nbits & kmask) @@ -72,12 +71,15 @@ hexnan( CONST char **sp, CONST FPI *fpi, ULong *x0) havedig = hd0 = i = 0; s = *sp; /* allow optional initial 0x or 0X */ - while((c = *(CONST unsigned char*)(s+1)) && c <= ' ') + while((c = *(CONST unsigned char*)(s+1)) && c <= ' ') { + if (!c) + goto retnan; ++s; + } if (s[1] == '0' && (s[2] == 'x' || s[2] == 'X') && *(CONST unsigned char*)(s+3) > ' ') s += 2; - while(c = *(CONST unsigned char*)++s) { + while((c = *(CONST unsigned char*)++s)) { if (!(h = hexdig[c])) { if (c <= ' ') { if (hd0 < havedig) { @@ -92,8 +94,11 @@ hexnan( CONST char **sp, CONST FPI *fpi, ULong *x0) x1 = x; i = 0; } - while(*(CONST unsigned char*)(s+1) <= ' ') + while((c = *(CONST unsigned char*)(s+1)) <= ' ') { + if (!c) + goto retnan; ++s; + } if (s[1] == '0' && (s[2] == 'x' || s[2] == 'X') && *(CONST unsigned char*)(s+3) > ' ') s += 2; @@ -107,10 +112,11 @@ hexnan( CONST char **sp, CONST FPI *fpi, ULong *x0) do { if (/*(*/ c == ')') { *sp = s + 1; - break; + goto break2; } - } while(c = *++s); + } while((c = *++s)); #endif + retnan: return STRTOG_NaN; } havedig++; @@ -120,8 +126,11 @@ hexnan( CONST char **sp, CONST FPI *fpi, ULong *x0) i = 1; *--x = 0; } - *x = (*x << 4) | h & 0xf; + *x = (*x << 4) | (h & 0xf); } +#ifndef GDTOA_NON_PEDANTIC_NANCHECK + break2: +#endif if (!havedig) return STRTOG_NaN; if (x < x1 && i < 8) diff --git a/gdtoa/misc.c b/gdtoa/misc.c index 51f8f52fe..d13046732 100644 --- a/gdtoa/misc.c +++ b/gdtoa/misc.c @@ -38,11 +38,6 @@ THIS SOFTWARE. #endif #define PRIVATE_mem ((PRIVATE_MEM+sizeof(double)-1)/sizeof(double)) static double private_mem[PRIVATE_mem], *pmem_next = private_mem; -#endif - -#ifdef MULTIPLE_THREADS -static void ACQUIRE_DTOA_LOCK(int n); -static void FREE_DTOA_LOCK(int n); #endif Bigint * @@ -60,7 +55,9 @@ Balloc #endif ACQUIRE_DTOA_LOCK(0); - if ( (rv = freelist[k]) !=0) { + /* The k > Kmax case does not need ACQUIRE_DTOA_LOCK(0), */ + /* but this case seems very unlikely. */ + if (k <= Kmax && (rv = freelist[k]) !=0) { freelist[k] = rv->next; } else { @@ -70,7 +67,7 @@ Balloc #else len = (sizeof(Bigint) + (x-1)*sizeof(ULong) + sizeof(double) - 1) /sizeof(double); - if (pmem_next - private_mem + len <= PRIVATE_mem) { + if (k <= Kmax && pmem_next - private_mem + len <= PRIVATE_mem) { rv = (Bigint*)pmem_next; pmem_next += len; } @@ -94,10 +91,18 @@ Bfree #endif { if (v) { - ACQUIRE_DTOA_LOCK(0); - v->next = freelist[v->k]; - freelist[v->k] = v; - FREE_DTOA_LOCK(0); + if (v->k > Kmax) +#ifdef FREE + FREE((void*)v); +#else + free((void*)v); +#endif + else { + ACQUIRE_DTOA_LOCK(0); + v->next = freelist[v->k]; + freelist[v->k] = v; + FREE_DTOA_LOCK(0); + } } } @@ -109,8 +114,8 @@ lo0bits (ULong *y) #endif { - register int k; - register ULong x = *y; + int k; + ULong x = *y; if (x & 7) { if (x & 1) @@ -209,12 +214,12 @@ multadd int hi0bits_D2A #ifdef KR_headers - (x) register ULong x; + (x) ULong x; #else - (register ULong x) + (ULong x) #endif { - register int k = 0; + int k = 0; if (!(x & 0xffff0000)) { k = 16; @@ -621,8 +626,8 @@ b2d #ifdef VAX ULong d0, d1; #else -#define d0 word0(d) -#define d1 word1(d) +#define d0 word0(&d) +#define d1 word1(&d) #endif xa0 = a->x; @@ -635,16 +640,16 @@ b2d *e = 32 - k; #ifdef Pack_32 if (k < Ebits) { - d0 = Exp_1 | y >> Ebits - k; + d0 = Exp_1 | y >> (Ebits - k); w = xa > xa0 ? *--xa : 0; - d1 = y << (32-Ebits) + k | w >> Ebits - k; + d1 = y << ((32-Ebits) + k) | w >> (Ebits - k); goto ret_d; } z = xa > xa0 ? *--xa : 0; if (k -= Ebits) { - d0 = Exp_1 | y << k | z >> 32 - k; + d0 = Exp_1 | y << k | z >> (32 - k); y = xa > xa0 ? *--xa : 0; - d1 = z << k | y >> 32 - k; + d1 = z << k | y >> (32 - k); } else { d0 = Exp_1 | y; @@ -668,10 +673,10 @@ b2d #endif ret_d: #ifdef VAX - word0(d) = d0 >> 16 | d0 << 16; - word1(d) = d1 >> 16 | d1 << 16; + word0(&d) = d0 >> 16 | d0 << 16; + word1(&d) = d1 >> 16 | d1 << 16; #endif - return dval(d); + return dval(&d); } #undef d0 #undef d1 @@ -679,29 +684,28 @@ b2d Bigint * d2b #ifdef KR_headers - (d, e, bits) double d; int *e, *bits; + (dd, e, bits) double dd; int *e, *bits; #else - (double _d, int *e, int *bits) + (double dd, int *e, int *bits) #endif { Bigint *b; + U d; #ifndef Sudden_Underflow int i; #endif int de, k; ULong *x, y, z; - U d; #ifdef VAX ULong d0, d1; #else -#define d0 word0(d) -#define d1 word1(d) +#define d0 word0(&d) +#define d1 word1(&d) #endif - - dval(d) = _d; + d.d = dd; #ifdef VAX - d0 = word0(d) >> 16 | word0(d) << 16; - d1 = word1(d) >> 16 | word1(d) << 16; + d0 = word0(&d) >> 16 | word0(&d) << 16; + d1 = word1(&d) >> 16 | word1(&d) << 16; #endif #ifdef Pack_32 @@ -725,7 +729,7 @@ d2b #ifdef Pack_32 if ( (y = d1) !=0) { if ( (k = lo0bits(&y)) !=0) { - x[0] = y | z << 32 - k; + x[0] = y | z << (32 - k); z >>= k; } else @@ -736,10 +740,6 @@ d2b b->wds = (x[1] = z) !=0 ? 2 : 1; } else { -#ifdef DEBUG - if (!z) - Bug("Zero passed to d2b"); -#endif k = lo0bits(&z); x[0] = z; #ifndef Sudden_Underflow @@ -798,7 +798,7 @@ d2b #endif #ifdef IBM *e = (de - Bias - (P-1) << 2) + k; - *bits = 4*P + 8 - k - hi0bits(word0(d) & Frac_mask); + *bits = 4*P + 8 - k - hi0bits(word0(&d) & Frac_mask); #else *e = de - Bias - (P-1) + k; *bits = P - k; @@ -851,71 +851,25 @@ strcp_D2A(a, b) char *a; char *b; strcp_D2A(char *a, CONST char *b) #endif { - while(*a = *b++) + while((*a = *b++)) a++; return a; } #ifdef NO_STRING_H - KR_VOID * + Char * #ifdef KR_headers -memcpy_D2A(a, b, len) char *a; char *b; size_t len; +memcpy_D2A(a, b, len) Char *a; Char *b; size_t len; #else memcpy_D2A(void *a1, void *b1, size_t len) #endif { - register char *a = (char*)a1, *ae = a + len; - register char *b = (char*)b1, *a0 = a; + char *a = (char*)a1, *ae = a + len; + char *b = (char*)b1, *a0 = a; while(a < ae) *a++ = *b++; return a0; } #endif /* NO_STRING_H */ - - -#ifdef MULTIPLE_THREADS -#ifdef _WIN32 - -#undef Bias -#define WIN32_LEAN_AND_MEAN -#include - -static CRITICAL_SECTION dtoa_lock[2]; -static int did_init; - -void ACQUIRE_DTOA_LOCK(int n) -{ - if (!did_init) - { - did_init = 1; - InitializeCriticalSection(&dtoa_lock[0]); - InitializeCriticalSection(&dtoa_lock[1]); - } - EnterCriticalSection(&dtoa_lock[n]); -} - -void FREE_DTOA_LOCK(int n) -{ - LeaveCriticalSection(&dtoa_lock[n]); -} - -#else - -#include - -static pthread_mutex_t dtoa_lock[2] = { PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER }; - -void ACQUIRE_DTOA_LOCK(int n) -{ - pthread_mutex_lock(&dtoa_lock[n]); -} - -void FREE_DTOA_LOCK(int n) -{ - pthread_mutex_unlock(&dtoa_lock[n]); -} - -#endif -#endif diff --git a/gdtoa/qnan.c b/gdtoa/qnan.c index 118e74921..ea7e8745b 100644 --- a/gdtoa/qnan.c +++ b/gdtoa/qnan.c @@ -55,11 +55,19 @@ typedef unsigned Long Ulong; #ifdef IEEE_8087 #define _0 1 #define _1 0 +#define _3 3 +#if defined(Gen_ld_QNAN) && !defined(NO_LONG_LONG) +static int perm[4] = { 0, 1, 2, 3 }; +#endif #define HAVE_IEEE #endif #ifdef IEEE_MC68k #define _0 0 #define _1 1 +#define _3 0 +#if defined(Gen_ld_QNAN) && !defined(NO_LONG_LONG) +static int perm[4] = { 3, 2, 1, 0 }; +#endif #define HAVE_IEEE #endif @@ -79,31 +87,32 @@ main(void) #endif } U; U a, b, c; +#if defined(Gen_ld_QNAN) && !defined(NO_LONG_LONG) int i; +#endif a.L[0] = b.L[0] = 0x7f800000; c.f = a.f - b.f; - printf("#define f_QNAN 0x%lx\n", UL c.L[0]); + printf("#define f_QNAN 0x%lx\n", UL (c.L[0] & 0x7fffffff)); a.L[_0] = b.L[_0] = 0x7ff00000; a.L[_1] = b.L[_1] = 0; c.d = a.d - b.d; /* quiet NaN */ - printf("#define d_QNAN0 0x%lx\n", UL c.L[0]); - printf("#define d_QNAN1 0x%lx\n", UL c.L[1]); -#ifdef NO_LONG_LONG - for(i = 0; i < 4; i++) - printf("#define ld_QNAN%d 0xffffffff\n", i); - for(i = 0; i < 5; i++) - printf("#define ldus_QNAN%d 0xffff\n", i); -#else - b.D = c.D = a.d; - if (printf("") < 0) - c.D = 37; /* never executed; just defeat optimization */ - a.L[2] = a.L[3] = 0; - a.D = b.D - c.D; - for(i = 0; i < 4; i++) - printf("#define ld_QNAN%d 0x%lx\n", i, UL a.L[i]); - for(i = 0; i < 5; i++) - printf("#define ldus_QNAN%d 0x%x\n", i, a.u[i]); + c.L[_0] &= 0x7fffffff; + printf("#define d_QNAN0 0x%lx\n", UL c.L[_0]); + printf("#define d_QNAN1 0x%lx\n", UL c.L[_1]); +#ifndef NO_LONG_LONG +#ifdef Gen_ld_QNAN + if (sizeof(a.D) >= 16) { + b.D = c.D = a.d; + if (printf("") < 0) + c.D = 37; /* never executed; just defeat optimization */ + a.L[0] = a.L[1] = a.L[2] = a.L[3] = 0; + a.D = b.D - c.D; + a.L[_3] &= 0x7fffffff; + for(i = 0; i < 4; i++) + printf("#define ld_QNAN%d 0x%lx\n", i, UL a.L[perm[i]]); + } +#endif #endif #endif /* HAVE_IEEE */ return 0; diff --git a/gdtoa/smisc.c b/gdtoa/smisc.c index 858024c9e..f4dbafb21 100644 --- a/gdtoa/smisc.c +++ b/gdtoa/smisc.c @@ -34,9 +34,9 @@ THIS SOFTWARE. Bigint * s2b #ifdef KR_headers - (s, nd0, nd, y9) CONST char *s; int nd0, nd; ULong y9; + (s, nd0, nd, y9, dplen) CONST char *s; int dplen, nd0, nd; ULong y9; #else - (CONST char *s, int nd0, int nd, ULong y9) + (CONST char *s, int nd0, int nd, ULong y9, int dplen) #endif { Bigint *b; @@ -60,10 +60,10 @@ s2b s += 9; do b = multadd(b, 10, *s++ - '0'); while(++i < nd0); - s++; + s += dplen; } else - s += 10; + s += dplen + 9; for(; i < nd; i++) b = multadd(b, 10, *s++ - '0'); return b; @@ -80,30 +80,30 @@ ratio U da, db; int k, ka, kb; - dval(da) = b2d(a, &ka); - dval(db) = b2d(b, &kb); + dval(&da) = b2d(a, &ka); + dval(&db) = b2d(b, &kb); k = ka - kb + ULbits*(a->wds - b->wds); #ifdef IBM if (k > 0) { - word0(da) += (k >> 2)*Exp_msk1; + word0(&da) += (k >> 2)*Exp_msk1; if (k &= 3) - dval(da) *= 1 << k; + dval(&da) *= 1 << k; } else { k = -k; - word0(db) += (k >> 2)*Exp_msk1; + word0(&db) += (k >> 2)*Exp_msk1; if (k &= 3) - dval(db) *= 1 << k; + dval(&db) *= 1 << k; } #else if (k > 0) - word0(da) += k*Exp_msk1; + word0(&da) += k*Exp_msk1; else { k = -k; - word0(db) += k*Exp_msk1; + word0(&db) += k*Exp_msk1; } #endif - return dval(da) / dval(db); + return dval(&da) / dval(&db); } #ifdef INFNAN_CHECK diff --git a/gdtoa/strtoIQ.c b/gdtoa/strtoIQ.c index 000fa3645..9ce5120e6 100644 --- a/gdtoa/strtoIQ.c +++ b/gdtoa/strtoIQ.c @@ -38,7 +38,7 @@ strtoIQ(s, sp, a, b) CONST char *s; char **sp; void *a; void *b; strtoIQ(CONST char *s, char **sp, void *a, void *b) #endif { - static CONST FPI fpi = { 113, 1-16383-113+1, 32766-16383-113+1, 1, SI }; + static FPI fpi = { 113, 1-16383-113+1, 32766-16383-113+1, 1, SI }; Long exp[2]; Bigint *B[2]; int k, rv[2]; diff --git a/gdtoa/strtoId.c b/gdtoa/strtoId.c index d34a278ee..1c97d382d 100644 --- a/gdtoa/strtoId.c +++ b/gdtoa/strtoId.c @@ -38,7 +38,7 @@ strtoId(s, sp, f0, f1) CONST char *s; char **sp; double *f0, *f1; strtoId(CONST char *s, char **sp, double *f0, double *f1) #endif { - static CONST FPI fpi = { 53, 1-1023-53+1, 2046-1023-53+1, 1, SI }; + static FPI fpi = { 53, 1-1023-53+1, 2046-1023-53+1, 1, SI }; Long exp[2]; Bigint *B[2]; int k, rv[2]; diff --git a/gdtoa/strtoIdd.c b/gdtoa/strtoIdd.c index 921597fe7..40b7936bc 100644 --- a/gdtoa/strtoIdd.c +++ b/gdtoa/strtoIdd.c @@ -39,9 +39,9 @@ strtoIdd(CONST char *s, char **sp, double *f0, double *f1) #endif { #ifdef Sudden_Underflow - static CONST FPI fpi = { 106, 1-1023, 2046-1023-106+1, 1, 1 }; + static FPI fpi = { 106, 1-1023, 2046-1023-106+1, 1, 1 }; #else - static CONST FPI fpi = { 106, 1-1023-53+1, 2046-1023-106+1, 1, 0 }; + static FPI fpi = { 106, 1-1023-53+1, 2046-1023-106+1, 1, 0 }; #endif Long exp[2]; Bigint *B[2]; diff --git a/gdtoa/strtoIf.c b/gdtoa/strtoIf.c index b937ff079..65ecab2e0 100644 --- a/gdtoa/strtoIf.c +++ b/gdtoa/strtoIf.c @@ -38,7 +38,7 @@ strtoIf(s, sp, f0, f1) CONST char *s; char **sp; float *f0, *f1; strtoIf(CONST char *s, char **sp, float *f0, float *f1) #endif { - static CONST FPI fpi = { 24, 1-127-24+1, 254-127-24+1, 1, SI }; + static FPI fpi = { 24, 1-127-24+1, 254-127-24+1, 1, SI }; Long exp[2]; Bigint *B[2]; int k, rv[2]; diff --git a/gdtoa/strtoIg.c b/gdtoa/strtoIg.c index fd181fc9b..6a17760cf 100644 --- a/gdtoa/strtoIg.c +++ b/gdtoa/strtoIg.c @@ -35,7 +35,7 @@ THIS SOFTWARE. #ifdef KR_headers strtoIg(s00, se, fpi, exp, B, rvp) CONST char *s00; char **se; FPI *fpi; Long *exp; Bigint **B; int *rvp; #else -strtoIg(CONST char *s00, char **se, CONST FPI *fpi, Long *exp, Bigint **B, int *rvp) +strtoIg(CONST char *s00, char **se, FPI *fpi, Long *exp, Bigint **B, int *rvp) #endif { Bigint *b, *b1; @@ -61,16 +61,20 @@ strtoIg(CONST char *s00, char **se, CONST FPI *fpi, Long *exp, Bigint **B, int * if (rv & STRTOG_Inexlo) { swap = 0; b1 = increment(b1); - if (fpi->sudden_underflow - && (rv & STRTOG_Retmask) == STRTOG_Zero) { - b1->x[0] = 0; - b1->x[nw1] = 1L << nb11; - rv1 += STRTOG_Normal - STRTOG_Zero; - rv1 &= ~STRTOG_Underflow; + if ((rv & STRTOG_Retmask) == STRTOG_Zero) { + if (fpi->sudden_underflow) { + b1->x[0] = 0; + b1->x[nw1] = 1L << nb11; + rv1 += STRTOG_Normal - STRTOG_Zero; + rv1 &= ~STRTOG_Underflow; + goto swapcheck; + } + rv1 &= STRTOG_Inexlo | STRTOG_Underflow | STRTOG_Zero; + rv1 |= STRTOG_Inexhi | STRTOG_Denormal; goto swapcheck; } if (b1->wds > nw - || nb1 && b1->x[nw1] & 1L << nb1) { + || (nb1 && b1->x[nw1] & 1L << nb1)) { if (++e1 > fpi->emax) rv1 = STRTOG_Infinite | STRTOG_Inexhi; rshift(b1, 1); diff --git a/gdtoa/strtoIx.c b/gdtoa/strtoIx.c index 8e972c976..783a631f0 100644 --- a/gdtoa/strtoIx.c +++ b/gdtoa/strtoIx.c @@ -38,7 +38,7 @@ strtoIx(s, sp, a, b) CONST char *s; char **sp; void *a; void *b; strtoIx(CONST char *s, char **sp, void *a, void *b) #endif { - static CONST FPI fpi = { 64, 1-16383-64+1, 32766 - 16383 - 64 + 1, 1, SI }; + static FPI fpi = { 64, 1-16383-64+1, 32766 - 16383 - 64 + 1, 1, SI }; Long exp[2]; Bigint *B[2]; int k, rv[2]; diff --git a/gdtoa/strtoIxL.c b/gdtoa/strtoIxL.c index 86dbc744a..869bfd16f 100644 --- a/gdtoa/strtoIxL.c +++ b/gdtoa/strtoIxL.c @@ -38,7 +38,7 @@ strtoIxL(s, sp, a, b) CONST char *s; char **sp; void *a; void *b; strtoIxL(CONST char *s, char **sp, void *a, void *b) #endif { - static CONST FPI fpi = { 64, 1-16383-64+1, 32766 - 16383 - 64 + 1, 1, SI }; + static FPI fpi = { 64, 1-16383-64+1, 32766 - 16383 - 64 + 1, 1, SI }; Long exp[2]; Bigint *B[2]; int k, rv[2]; diff --git a/gdtoa/strtod.c b/gdtoa/strtod.c index 1f01921a4..3c2230053 100644 --- a/gdtoa/strtod.c +++ b/gdtoa/strtod.c @@ -42,24 +42,43 @@ THIS SOFTWARE. #ifndef NO_IEEE_Scale #define Avoid_Underflow #undef tinytens -/* The factor of 2^53 in tinytens[4] helps us avoid setting the underflow */ +/* The factor of 2^106 in tinytens[4] helps us avoid setting the underflow */ /* flag unnecessarily. It leads to a song and dance at the end of strtod. */ static CONST double tinytens[] = { 1e-16, 1e-32, 1e-64, 1e-128, - 9007199254740992.e-256 + 9007199254740992.*9007199254740992.e-256 }; #endif #endif -#include - #ifdef Honor_FLT_ROUNDS -#define Rounding rounding #undef Check_FLT_ROUNDS #define Check_FLT_ROUNDS #else #define Rounding Flt_Rounds #endif +#ifdef Avoid_Underflow /*{*/ + static double +sulp +#ifdef KR_headers + (x, scale) U *x; int scale; +#else + (U *x, int scale) +#endif +{ + U u; + double rv; + int i; + + rv = ulp(x); + if (!scale || (i = 2*P + 1 - ((word0(x) & Exp_mask) >> Exp_shift)) <= 0) + return rv; /* Is there an example where i <= 0 ? */ + word0(&u) = Exp_1 + (i << Exp_shift); + word1(&u) = 0; + return rv * u.d; + } +#endif /*}*/ + double strtod #ifdef KR_headers @@ -74,21 +93,55 @@ strtod int bb2, bb5, bbe, bd2, bd5, bbbits, bs2, c, decpt, dsign, e, e1, esign, i, j, k, nd, nd0, nf, nz, nz0, sign; CONST char *s, *s0, *s1; - double aadj, adj; - U rv, rv0, aadj1; + double aadj; Long L; + U adj, aadj1, rv, rv0; ULong y, z; Bigint *bb, *bb1, *bd, *bd0, *bs, *delta; +#ifdef Avoid_Underflow + ULong Lsb, Lsb1; +#endif #ifdef SET_INEXACT int inexact, oldinexact; #endif -#ifdef Honor_FLT_ROUNDS - int rounding; -#endif +#ifdef USE_LOCALE /*{{*/ +#ifdef NO_LOCALE_CACHE + char *decimalpoint = localeconv()->decimal_point; + int dplen = strlen(decimalpoint); +#else + char *decimalpoint; + static char *decimalpoint_cache; + static int dplen; + if (!(s0 = decimalpoint_cache)) { + s0 = localeconv()->decimal_point; + if ((decimalpoint_cache = (char*)MALLOC(strlen(s0) + 1))) { + strcpy(decimalpoint_cache, s0); + s0 = decimalpoint_cache; + } + dplen = strlen(s0); + } + decimalpoint = (char*)s0; +#endif /*NO_LOCALE_CACHE*/ +#else /*USE_LOCALE}{*/ +#define dplen 1 +#endif /*USE_LOCALE}}*/ + +#ifdef Honor_FLT_ROUNDS /*{*/ + int Rounding; +#ifdef Trust_FLT_ROUNDS /*{{ only define this if FLT_ROUNDS really works! */ + Rounding = Flt_Rounds; +#else /*}{*/ + Rounding = 1; + switch(fegetround()) { + case FE_TOWARDZERO: Rounding = 0; break; + case FE_UPWARD: Rounding = 2; break; + case FE_DOWNWARD: Rounding = 3; + } +#endif /*}}*/ +#endif /*}*/ - //_control87(_PC_53, _MCW_PC); sign = nz0 = nz = decpt = 0; - dval(rv) = 0.; + dval(&rv) = 0.; for(s = s00;;s++) switch(*s) { case '-': sign = 1; @@ -111,22 +164,18 @@ strtod } break2: if (*s == '0') { -#ifndef NO_HEX_FP +#ifndef NO_HEX_FP /*{*/ { - static CONST FPI fpi = { 53, 1-1023-53+1, 2046-1023-53+1, 1, SI }; + static FPI fpi = { 53, 1-1023-53+1, 2046-1023-53+1, 1, SI }; Long exp; ULong bits[2]; switch(s[1]) { case 'x': case 'X': { -#if defined(FE_DOWNWARD) && defined(FE_TONEAREST) && defined(FE_TOWARDZERO) && defined(FE_UPWARD) +#ifdef Honor_FLT_ROUNDS FPI fpi1 = fpi; - switch(fegetround()) { - case FE_TOWARDZERO: fpi1.rounding = 0; break; - case FE_UPWARD: fpi1.rounding = 2; break; - case FE_DOWNWARD: fpi1.rounding = 3; - } + fpi1.rounding = Rounding; #else #define fpi1 fpi #endif @@ -146,7 +195,7 @@ strtod goto ret; } } -#endif +#endif /*}*/ nz0 = 1; while(*++s == '0') ; if (!*s) @@ -161,13 +210,17 @@ strtod z = 10*z + c - '0'; nd0 = nd; #ifdef USE_LOCALE - if (c == *localeconv()->decimal_point) + if (c == *decimalpoint) { + for(i = 1; decimalpoint[i]; ++i) + if (s[i] != decimalpoint[i]) + goto dig_done; + s += i; + c = *s; #else - if (c == '.') -#endif - { - decpt = 1; + if (c == '.') { c = *++s; +#endif + decpt = 1; if (!nd) { for(; c == '0'; c = *++s) nz++; @@ -196,7 +249,7 @@ strtod nz = 0; } } - } + }/*}*/ dig_done: e = 0; if (c == 'e' || c == 'E') { @@ -240,7 +293,7 @@ strtod #ifdef INFNAN_CHECK /* Check for Nan and Infinity */ ULong bits[2]; - static CONST FPI fpinan = /* only 52 explicit bits */ + static FPI fpinan = /* only 52 explicit bits */ { 52, 1-1023-53+1, 2046-1023-53+1, 1, SI }; if (!decpt) switch(c) { @@ -250,8 +303,8 @@ strtod --s; if (!match(&s,"inity")) ++s; - word0(rv) = 0x7ff00000; - word1(rv) = 0; + word0(&rv) = 0x7ff00000; + word1(&rv) = 0; goto ret; } break; @@ -262,13 +315,13 @@ strtod if (*s == '(' /*)*/ && hexnan(&s, &fpinan, bits) == STRTOG_NaNbits) { - word0(rv) = 0x7ff00000 | bits[1]; - word1(rv) = bits[0]; + word0(&rv) = 0x7ff00000 | bits[1]; + word1(&rv) = bits[0]; } else { #endif - word0(rv) = NAN_WORD0; - word1(rv) = NAN_WORD1; + word0(&rv) = NAN_WORD0; + word1(&rv) = NAN_WORD1; #ifndef No_Hex_NaN } #endif @@ -292,13 +345,13 @@ strtod if (!nd0) nd0 = nd; k = nd < DBL_DIG + 1 ? nd : DBL_DIG + 1; - dval(rv) = y; + dval(&rv) = y; if (k > 9) { #ifdef SET_INEXACT if (k > DBL_DIG) oldinexact = get_inexact(); #endif - dval(rv) = tens[k - 9] * dval(rv) + z; + dval(&rv) = tens[k - 9] * dval(&rv) + z; } bd0 = 0; if (nd <= DBL_DIG @@ -310,6 +363,7 @@ strtod ) { if (!e) goto ret; +#ifndef ROUND_BIASED_without_Round_Up if (e > 0) { if (e <= Ten_pmax) { #ifdef VAX @@ -318,11 +372,11 @@ strtod #ifdef Honor_FLT_ROUNDS /* round correctly FLT_ROUNDS = 2 or 3 */ if (sign) { - rv = -rv; + rv.d = -rv.d; sign = 0; } #endif - /* rv = */ rounded_product(dval(rv), tens[e]); + /* rv = */ rounded_product(dval(&rv), tens[e]); goto ret; #endif } @@ -334,25 +388,25 @@ strtod #ifdef Honor_FLT_ROUNDS /* round correctly FLT_ROUNDS = 2 or 3 */ if (sign) { - rv = -rv; + rv.d = -rv.d; sign = 0; } #endif e -= i; - dval(rv) *= tens[i]; + dval(&rv) *= tens[i]; #ifdef VAX /* VAX exponent range is so narrow we must * worry about overflow here... */ vax_ovfl_check: - word0(rv) -= P*Exp_msk1; - /* rv = */ rounded_product(dval(rv), tens[e]); - if ((word0(rv) & Exp_mask) + word0(&rv) -= P*Exp_msk1; + /* rv = */ rounded_product(dval(&rv), tens[e]); + if ((word0(&rv) & Exp_mask) > Exp_msk1*(DBL_MAX_EXP+Bias-1-P)) goto ovfl; - word0(rv) += P*Exp_msk1; + word0(&rv) += P*Exp_msk1; #else - /* rv = */ rounded_product(dval(rv), tens[e]); + /* rv = */ rounded_product(dval(&rv), tens[e]); #endif goto ret; } @@ -362,14 +416,15 @@ strtod #ifdef Honor_FLT_ROUNDS /* round correctly FLT_ROUNDS = 2 or 3 */ if (sign) { - rv = -rv; + rv.d = -rv.d; sign = 0; } #endif - /* rv = */ rounded_quotient(dval(rv), tens[-e]); + /* rv = */ rounded_quotient(dval(&rv), tens[-e]); goto ret; } #endif +#endif /* ROUND_BIASED_without_Round_Up */ } e1 += nd - k; @@ -383,12 +438,12 @@ strtod scale = 0; #endif #ifdef Honor_FLT_ROUNDS - if ((rounding = Flt_Rounds) >= 2) { + if (Rounding >= 2) { if (sign) - rounding = rounding == 2 ? 0 : 2; + Rounding = Rounding == 2 ? 0 : 2; else - if (rounding != 2) - rounding = 0; + if (Rounding != 2) + Rounding = 0; } #endif #endif /*IEEE_Arith*/ @@ -397,67 +452,73 @@ strtod if (e1 > 0) { if ( (i = e1 & 15) !=0) - dval(rv) *= tens[i]; + dval(&rv) *= tens[i]; if (e1 &= ~15) { if (e1 > DBL_MAX_10_EXP) { ovfl: -#ifndef NO_ERRNO - errno = ERANGE; -#endif /* Can't trust HUGE_VAL */ #ifdef IEEE_Arith #ifdef Honor_FLT_ROUNDS - switch(rounding) { + switch(Rounding) { case 0: /* toward 0 */ case 3: /* toward -infinity */ - word0(rv) = Big0; - word1(rv) = Big1; + word0(&rv) = Big0; + word1(&rv) = Big1; break; default: - word0(rv) = Exp_mask; - word1(rv) = 0; + word0(&rv) = Exp_mask; + word1(&rv) = 0; } #else /*Honor_FLT_ROUNDS*/ - word0(rv) = Exp_mask; - word1(rv) = 0; + word0(&rv) = Exp_mask; + word1(&rv) = 0; #endif /*Honor_FLT_ROUNDS*/ #ifdef SET_INEXACT /* set overflow bit */ - dval(rv0) = 1e300; - dval(rv0) *= dval(rv0); + dval(&rv0) = 1e300; + dval(&rv0) *= dval(&rv0); #endif #else /*IEEE_Arith*/ - word0(rv) = Big0; - word1(rv) = Big1; + word0(&rv) = Big0; + word1(&rv) = Big1; #endif /*IEEE_Arith*/ - if (bd0) - goto retfree; + range_err: + if (bd0) { + Bfree(bb); + Bfree(bd); + Bfree(bs); + Bfree(bd0); + Bfree(delta); + } +#ifndef NO_ERRNO + errno = ERANGE; +#endif goto ret; } e1 >>= 4; for(j = 0; e1 > 1; j++, e1 >>= 1) if (e1 & 1) - dval(rv) *= bigtens[j]; + dval(&rv) *= bigtens[j]; /* The last multiplication could overflow. */ - word0(rv) -= P*Exp_msk1; - dval(rv) *= bigtens[j]; - if ((z = word0(rv) & Exp_mask) + word0(&rv) -= P*Exp_msk1; + dval(&rv) *= bigtens[j]; + if ((z = word0(&rv) & Exp_mask) > Exp_msk1*(DBL_MAX_EXP+Bias-P)) goto ovfl; if (z > Exp_msk1*(DBL_MAX_EXP+Bias-1-P)) { /* set to largest number */ /* (Can't trust DBL_MAX) */ - word0(rv) = Big0; - word1(rv) = Big1; + word0(&rv) = Big0; + word1(&rv) = Big1; } else - word0(rv) += P*Exp_msk1; + word0(&rv) += P*Exp_msk1; } } else if (e1 < 0) { e1 = -e1; if ( (i = e1 & 15) !=0) - dval(rv) /= tens[i]; + dval(&rv) /= tens[i]; if (e1 >>= 4) { if (e1 >= 1 << n_bigtens) goto undfl; @@ -466,44 +527,39 @@ strtod scale = 2*P; for(j = 0; e1 > 0; j++, e1 >>= 1) if (e1 & 1) - dval(rv) *= tinytens[j]; - if (scale && (j = 2*P + 1 - ((word0(rv) & Exp_mask) + dval(&rv) *= tinytens[j]; + if (scale && (j = 2*P + 1 - ((word0(&rv) & Exp_mask) >> Exp_shift)) > 0) { /* scaled rv is denormal; zap j low bits */ if (j >= 32) { - word1(rv) = 0; + word1(&rv) = 0; if (j >= 53) - word0(rv) = (P+2)*Exp_msk1; + word0(&rv) = (P+2)*Exp_msk1; else - word0(rv) &= 0xffffffff << j-32; + word0(&rv) &= 0xffffffff << (j-32); } else - word1(rv) &= 0xffffffff << j; + word1(&rv) &= 0xffffffff << j; } #else for(j = 0; e1 > 1; j++, e1 >>= 1) if (e1 & 1) - dval(rv) *= tinytens[j]; + dval(&rv) *= tinytens[j]; /* The last multiplication could underflow. */ - dval(rv0) = dval(rv); - dval(rv) *= tinytens[j]; - if (!dval(rv)) { - dval(rv) = 2.*dval(rv0); - dval(rv) *= tinytens[j]; + dval(&rv0) = dval(&rv); + dval(&rv) *= tinytens[j]; + if (!dval(&rv)) { + dval(&rv) = 2.*dval(&rv0); + dval(&rv) *= tinytens[j]; #endif - if (!dval(rv)) { + if (!dval(&rv)) { undfl: - dval(rv) = 0.; -#ifndef NO_ERRNO - errno = ERANGE; -#endif - if (bd0) - goto retfree; - goto ret; + dval(&rv) = 0.; + goto range_err; } #ifndef Avoid_Underflow - word0(rv) = Tiny0; - word1(rv) = Tiny1; + word0(&rv) = Tiny0; + word1(&rv) = Tiny1; /* The refinement below will clean * this approximation up. */ @@ -516,12 +572,12 @@ strtod /* Put digits into bd: true value = bd * 10^e */ - bd0 = s2b(s0, nd0, nd, y); + bd0 = s2b(s0, nd0, nd, y, dplen); for(;;) { bd = Balloc(bd0->k); Bcopy(bd, bd0); - bb = d2b(dval(rv), &bbe, &bbbits); /* rv = bb * 2^bbe */ + bb = d2b(dval(&rv), &bbe, &bbbits); /* rv = bb * 2^bbe */ bs = i2b(1); if (e >= 0) { @@ -538,16 +594,23 @@ strtod bd2 -= bbe; bs2 = bb2; #ifdef Honor_FLT_ROUNDS - if (rounding != 1) + if (Rounding != 1) bs2++; #endif #ifdef Avoid_Underflow + Lsb = LSB; + Lsb1 = 0; j = bbe - scale; i = j + bbbits - 1; /* logb(rv) */ - if (i < Emin) /* denormal */ - j += P - Emin; - else - j = P + 1 - bbbits; + j = P + 1 - bbbits; + if (i < Emin) { /* denormal */ + i = Emin - i; + j -= i; + if (i < 32) + Lsb <<= i; + else + Lsb1 = Lsb << (i-32); + } #else /*Avoid_Underflow*/ #ifdef Sudden_Underflow #ifdef IBM @@ -557,7 +620,7 @@ strtod #endif #else /*Sudden_Underflow*/ j = bbe; - i = j + bbbits - 1; /* logb(rv) */ + i = j + bbbits - 1; /* logb(&rv) */ if (i < Emin) /* denormal */ j += P - Emin; else @@ -596,7 +659,7 @@ strtod delta->sign = 0; i = cmp(delta, bs); #ifdef Honor_FLT_ROUNDS - if (rounding != 1) { + if (Rounding != 1) { if (i < 0) { /* Error is less than an ulp */ if (!delta->x[0] && delta->wds <= 1) { @@ -606,17 +669,17 @@ strtod #endif break; } - if (rounding) { + if (Rounding) { if (dsign) { - adj = 1.; + dval(&adj) = 1.; goto apply_adj; } } else if (!dsign) { - adj = -1.; - if (!word1(rv) - && !(word0(rv) & Frac_mask)) { - y = word0(rv) & Exp_mask; + dval(&adj) = -1.; + if (!word1(&rv) + && !(word0(&rv) & Frac_mask)) { + y = word0(&rv) & Exp_mask; #ifdef Avoid_Underflow if (!scale || y > 2*P*Exp_msk1) #else @@ -625,63 +688,66 @@ strtod { delta = lshift(delta,Log2P); if (cmp(delta, bs) <= 0) - adj = -0.5; + dval(&adj) = -0.5; } } apply_adj: #ifdef Avoid_Underflow - if (scale && (y = word0(rv) & Exp_mask) + if (scale && (y = word0(&rv) & Exp_mask) <= 2*P*Exp_msk1) - word0(adj) += (2*P+1)*Exp_msk1 - y; + word0(&adj) += (2*P+1)*Exp_msk1 - y; #else #ifdef Sudden_Underflow - if ((word0(rv) & Exp_mask) <= + if ((word0(&rv) & Exp_mask) <= P*Exp_msk1) { - word0(rv) += P*Exp_msk1; - dval(rv) += adj*ulp(dval(rv)); - word0(rv) -= P*Exp_msk1; + word0(&rv) += P*Exp_msk1; + dval(&rv) += adj*ulp(&rv); + word0(&rv) -= P*Exp_msk1; } else #endif /*Sudden_Underflow*/ #endif /*Avoid_Underflow*/ - dval(rv) += adj*ulp(dval(rv)); + dval(&rv) += adj.d*ulp(&rv); } break; } - adj = ratio(delta, bs); - if (adj < 1.) - adj = 1.; - if (adj <= 0x7ffffffe) { - /* adj = rounding ? ceil(adj) : floor(adj); */ - y = adj; - if (y != adj) { - if (!((rounding>>1) ^ dsign)) + dval(&adj) = ratio(delta, bs); + if (adj.d < 1.) + dval(&adj) = 1.; + if (adj.d <= 0x7ffffffe) { + /* dval(&adj) = Rounding ? ceil(&adj) : floor(&adj); */ + y = adj.d; + if (y != adj.d) { + if (!((Rounding>>1) ^ dsign)) y++; - adj = y; + dval(&adj) = y; } } #ifdef Avoid_Underflow - if (scale && (y = word0(rv) & Exp_mask) <= 2*P*Exp_msk1) - word0(adj) += (2*P+1)*Exp_msk1 - y; + if (scale && (y = word0(&rv) & Exp_mask) <= 2*P*Exp_msk1) + word0(&adj) += (2*P+1)*Exp_msk1 - y; #else #ifdef Sudden_Underflow - if ((word0(rv) & Exp_mask) <= P*Exp_msk1) { - word0(rv) += P*Exp_msk1; - adj *= ulp(dval(rv)); + if ((word0(&rv) & Exp_mask) <= P*Exp_msk1) { + word0(&rv) += P*Exp_msk1; + dval(&adj) *= ulp(&rv); if (dsign) - dval(rv) += adj; + dval(&rv) += adj; else - dval(rv) -= adj; - word0(rv) -= P*Exp_msk1; + dval(&rv) -= adj; + word0(&rv) -= P*Exp_msk1; goto cont; } #endif /*Sudden_Underflow*/ #endif /*Avoid_Underflow*/ - adj *= ulp(dval(rv)); - if (dsign) - dval(rv) += adj; + dval(&adj) *= ulp(&rv); + if (dsign) { + if (word0(&rv) == Big0 && word1(&rv) == Big1) + goto ovfl; + dval(&rv) += adj.d; + } else - dval(rv) -= adj; + dval(&rv) -= adj.d; goto cont; } #endif /*Honor_FLT_ROUNDS*/ @@ -690,12 +756,12 @@ strtod /* Error is less than half an ulp -- check for * special case of mantissa a power of two. */ - if (dsign || word1(rv) || word0(rv) & Bndry_mask + if (dsign || word1(&rv) || word0(&rv) & Bndry_mask #ifdef IEEE_Arith #ifdef Avoid_Underflow - || (word0(rv) & Exp_mask) <= (2*P+1)*Exp_msk1 + || (word0(&rv) & Exp_mask) <= (2*P+1)*Exp_msk1 #else - || (word0(rv) & Exp_mask) <= Exp_msk1 + || (word0(&rv) & Exp_mask) <= Exp_msk1 #endif #endif ) { @@ -720,32 +786,34 @@ strtod if (i == 0) { /* exactly half-way between */ if (dsign) { - if ((word0(rv) & Bndry_mask1) == Bndry_mask1 - && word1(rv) == ( + if ((word0(&rv) & Bndry_mask1) == Bndry_mask1 + && word1(&rv) == ( #ifdef Avoid_Underflow - (scale && (y = word0(rv) & Exp_mask) <= 2*P*Exp_msk1) + (scale && (y = word0(&rv) & Exp_mask) <= 2*P*Exp_msk1) ? (0xffffffff & (0xffffffff << (2*P+1-(y>>Exp_shift)))) : #endif 0xffffffff)) { /*boundary case -- increment exponent*/ - word0(rv) = (word0(rv) & Exp_mask) + if (word0(&rv) == Big0 && word1(&rv) == Big1) + goto ovfl; + word0(&rv) = (word0(&rv) & Exp_mask) + Exp_msk1 #ifdef IBM | Exp_msk1 >> 4 #endif ; - word1(rv) = 0; + word1(&rv) = 0; #ifdef Avoid_Underflow dsign = 0; #endif break; } } - else if (!(word0(rv) & Bndry_mask) && !word1(rv)) { + else if (!(word0(&rv) & Bndry_mask) && !word1(&rv)) { drop_down: /* boundary case -- decrement exponent */ #ifdef Sudden_Underflow /*{{*/ - L = word0(rv) & Exp_mask; + L = word0(&rv) & Exp_mask; #ifdef IBM if (L < Exp_msk1) #else @@ -760,7 +828,7 @@ strtod #else /*Sudden_Underflow}{*/ #ifdef Avoid_Underflow if (scale) { - L = word0(rv) & Exp_mask; + L = word0(&rv) & Exp_mask; if (L <= (2*P+1)*Exp_msk1) { if (L > (P+2)*Exp_msk1) /* round even ==> */ @@ -771,10 +839,10 @@ strtod } } #endif /*Avoid_Underflow*/ - L = (word0(rv) & Exp_mask) - Exp_msk1; -#endif /*Sudden_Underflow}*/ - word0(rv) = L | Bndry_mask1; - word1(rv) = 0xffffffff; + L = (word0(&rv) & Exp_mask) - Exp_msk1; +#endif /*Sudden_Underflow}}*/ + word0(&rv) = L | Bndry_mask1; + word1(&rv) = 0xffffffff; #ifdef IBM goto cont; #else @@ -782,16 +850,33 @@ strtod #endif } #ifndef ROUND_BIASED - if (!(word1(rv) & LSB)) +#ifdef Avoid_Underflow + if (Lsb1) { + if (!(word0(&rv) & Lsb1)) + break; + } + else if (!(word1(&rv) & Lsb)) + break; +#else + if (!(word1(&rv) & LSB)) break; +#endif #endif if (dsign) - dval(rv) += ulp(dval(rv)); +#ifdef Avoid_Underflow + dval(&rv) += sulp(&rv, scale); +#else + dval(&rv) += ulp(&rv); +#endif #ifndef ROUND_BIASED else { - dval(rv) -= ulp(dval(rv)); +#ifdef Avoid_Underflow + dval(&rv) -= sulp(&rv, scale); +#else + dval(&rv) -= ulp(&rv); +#endif #ifndef Sudden_Underflow - if (!dval(rv)) + if (!dval(&rv)) goto undfl; #endif } @@ -803,14 +888,14 @@ strtod } if ((aadj = ratio(delta, bs)) <= 2.) { if (dsign) - aadj = dval(aadj1) = 1.; - else if (word1(rv) || word0(rv) & Bndry_mask) { + aadj = dval(&aadj1) = 1.; + else if (word1(&rv) || word0(&rv) & Bndry_mask) { #ifndef Sudden_Underflow - if (word1(rv) == Tiny1 && !word0(rv)) + if (word1(&rv) == Tiny1 && !word0(&rv)) goto undfl; #endif aadj = 1.; - dval(aadj1) = -1.; + dval(&aadj1) = -1.; } else { /* special case -- power of FLT_RADIX to be */ @@ -820,45 +905,45 @@ strtod aadj = 1./FLT_RADIX; else aadj *= 0.5; - dval(aadj1) = -aadj; + dval(&aadj1) = -aadj; } } else { aadj *= 0.5; - dval(aadj1) = dsign ? aadj : -aadj; + dval(&aadj1) = dsign ? aadj : -aadj; #ifdef Check_FLT_ROUNDS switch(Rounding) { case 2: /* towards +infinity */ - aadj1 -= 0.5; + dval(&aadj1) -= 0.5; break; case 0: /* towards 0 */ case 3: /* towards -infinity */ - aadj1 += 0.5; + dval(&aadj1) += 0.5; } #else if (Flt_Rounds == 0) - dval(aadj1) += 0.5; + dval(&aadj1) += 0.5; #endif /*Check_FLT_ROUNDS*/ } - y = word0(rv) & Exp_mask; + y = word0(&rv) & Exp_mask; /* Check for overflow */ if (y == Exp_msk1*(DBL_MAX_EXP+Bias-1)) { - dval(rv0) = dval(rv); - word0(rv) -= P*Exp_msk1; - adj = dval(aadj1) * ulp(dval(rv)); - dval(rv) += adj; - if ((word0(rv) & Exp_mask) >= + dval(&rv0) = dval(&rv); + word0(&rv) -= P*Exp_msk1; + dval(&adj) = dval(&aadj1) * ulp(&rv); + dval(&rv) += dval(&adj); + if ((word0(&rv) & Exp_mask) >= Exp_msk1*(DBL_MAX_EXP+Bias-P)) { - if (word0(rv0) == Big0 && word1(rv0) == Big1) + if (word0(&rv0) == Big0 && word1(&rv0) == Big1) goto ovfl; - word0(rv) = Big0; - word1(rv) = Big1; + word0(&rv) = Big0; + word1(&rv) = Big1; goto cont; } else - word0(rv) += P*Exp_msk1; + word0(&rv) += P*Exp_msk1; } else { #ifdef Avoid_Underflow @@ -867,58 +952,58 @@ strtod if ((z = (ULong)aadj) <= 0) z = 1; aadj = z; - dval(aadj1) = dsign ? aadj : -aadj; + dval(&aadj1) = dsign ? aadj : -aadj; } - word0(aadj1) += (2*P+1)*Exp_msk1 - y; + word0(&aadj1) += (2*P+1)*Exp_msk1 - y; } - adj = dval(aadj1) * ulp(dval(rv)); - dval(rv) += adj; + dval(&adj) = dval(&aadj1) * ulp(&rv); + dval(&rv) += dval(&adj); #else #ifdef Sudden_Underflow - if ((word0(rv) & Exp_mask) <= P*Exp_msk1) { - dval(rv0) = dval(rv); - word0(rv) += P*Exp_msk1; - adj = aadj1 * ulp(dval(rv)); - dval(rv) += adj; + if ((word0(&rv) & Exp_mask) <= P*Exp_msk1) { + dval(&rv0) = dval(&rv); + word0(&rv) += P*Exp_msk1; + dval(&adj) = dval(&aadj1) * ulp(&rv); + dval(&rv) += adj; #ifdef IBM - if ((word0(rv) & Exp_mask) < P*Exp_msk1) + if ((word0(&rv) & Exp_mask) < P*Exp_msk1) #else - if ((word0(rv) & Exp_mask) <= P*Exp_msk1) + if ((word0(&rv) & Exp_mask) <= P*Exp_msk1) #endif { - if (word0(rv0) == Tiny0 - && word1(rv0) == Tiny1) + if (word0(&rv0) == Tiny0 + && word1(&rv0) == Tiny1) goto undfl; - word0(rv) = Tiny0; - word1(rv) = Tiny1; + word0(&rv) = Tiny0; + word1(&rv) = Tiny1; goto cont; } else - word0(rv) -= P*Exp_msk1; + word0(&rv) -= P*Exp_msk1; } else { - adj = aadj1 * ulp(dval(rv)); - dval(rv) += adj; + dval(&adj) = dval(&aadj1) * ulp(&rv); + dval(&rv) += adj; } #else /*Sudden_Underflow*/ - /* Compute adj so that the IEEE rounding rules will - * correctly round rv + adj in some half-way cases. - * If rv * ulp(rv) is denormalized (i.e., + /* Compute dval(&adj) so that the IEEE rounding rules will + * correctly round rv + dval(&adj) in some half-way cases. + * If rv * ulp(&rv) is denormalized (i.e., * y <= (P-1)*Exp_msk1), we must adjust aadj to avoid * trouble from bits lost to denormalization; * example: 1.2e-307 . */ if (y <= (P-1)*Exp_msk1 && aadj > 1.) { - aadj1 = (double)(int)(aadj + 0.5); + dval(&aadj1) = (double)(int)(aadj + 0.5); if (!dsign) - aadj1 = -aadj1; + dval(&aadj1) = -dval(&aadj1); } - adj = aadj1 * ulp(dval(rv)); - dval(rv) += adj; + dval(&adj) = dval(&aadj1) * ulp(&rv); + dval(&rv) += adj; #endif /*Sudden_Underflow*/ #endif /*Avoid_Underflow*/ } - z = word0(rv) & Exp_mask; + z = word0(&rv) & Exp_mask; #ifndef SET_INEXACT #ifdef Avoid_Underflow if (!scale) @@ -928,7 +1013,7 @@ strtod L = (Long)aadj; aadj -= L; /* The tolerances below are conservative. */ - if (dsign || word1(rv) || word0(rv) & Bndry_mask) { + if (dsign || word1(&rv) || word0(&rv) & Bndry_mask) { if (aadj < .4999999 || aadj > .5000001) break; } @@ -942,12 +1027,17 @@ strtod Bfree(bs); Bfree(delta); } + Bfree(bb); + Bfree(bd); + Bfree(bs); + Bfree(bd0); + Bfree(delta); #ifdef SET_INEXACT if (inexact) { if (!oldinexact) { - word0(rv0) = Exp_1 + (70 << Exp_shift); - word1(rv0) = 0; - dval(rv0) += 1.; + word0(&rv0) = Exp_1 + (70 << Exp_shift); + word1(&rv0) = 0; + dval(&rv0) += 1.; } } else if (!oldinexact) @@ -955,32 +1045,30 @@ strtod #endif #ifdef Avoid_Underflow if (scale) { - word0(rv0) = Exp_1 - 2*P*Exp_msk1; - word1(rv0) = 0; - dval(rv) *= dval(rv0); + word0(&rv0) = Exp_1 - 2*P*Exp_msk1; + word1(&rv0) = 0; + dval(&rv) *= dval(&rv0); #ifndef NO_ERRNO /* try to avoid the bug of testing an 8087 register value */ - if (word0(rv) == 0 && word1(rv) == 0) +#ifdef IEEE_Arith + if (!(word0(&rv) & Exp_mask)) +#else + if (word0(&rv) == 0 && word1(&rv) == 0) +#endif errno = ERANGE; #endif } #endif /* Avoid_Underflow */ #ifdef SET_INEXACT - if (inexact && !(word0(rv) & Exp_mask)) { + if (inexact && !(word0(&rv) & Exp_mask)) { /* set underflow bit */ - dval(rv0) = 1e-300; - dval(rv0) *= dval(rv0); + dval(&rv0) = 1e-300; + dval(&rv0) *= dval(&rv0); } #endif - retfree: - Bfree(bb); - Bfree(bd); - Bfree(bs); - Bfree(bd0); - Bfree(delta); ret: if (se) *se = (char *)s; - return sign ? -dval(rv) : dval(rv); + return sign ? -dval(&rv) : dval(&rv); } diff --git a/gdtoa/strtodI.c b/gdtoa/strtodI.c index 992702e25..0b7b8a45c 100644 --- a/gdtoa/strtodI.c +++ b/gdtoa/strtodI.c @@ -33,16 +33,16 @@ THIS SOFTWARE. static double #ifdef KR_headers -ulpdown(d) double *d; +ulpdown(d) U *d; #else -ulpdown(double *d) +ulpdown(U *d) #endif { double u; - ULong *L = (ULong*)d; + ULong *L = d->L; - u = ulp(*d); - if (!(L[_1] | L[_0] & 0xfffff) + u = ulp(d); + if (!(L[_1] | (L[_0] & 0xfffff)) && (L[_0] & 0x7ff00000) > 0x00100000) u *= 0.5; return u; @@ -55,14 +55,10 @@ strtodI(s, sp, dd) CONST char *s; char **sp; double *dd; strtodI(CONST char *s, char **sp, double *dd) #endif { - static CONST FPI fpi = { 53, 1-1023-53+1, 2046-1023-53+1, 1, SI }; + static FPI fpi = { 53, 1-1023-53+1, 2046-1023-53+1, 1, SI }; ULong bits[2], sign; Long exp; int j, k; - typedef union { - double d[2]; - ULong L[4]; - } U; U *u; k = strtodg(s, sp, &fpi, &exp, bits); @@ -70,17 +66,17 @@ strtodI(CONST char *s, char **sp, double *dd) sign = k & STRTOG_Neg ? 0x80000000L : 0; switch(k & STRTOG_Retmask) { case STRTOG_NoNumber: - u->d[0] = u->d[1] = 0.; + dval(&u[0]) = dval(&u[1]) = 0.; break; case STRTOG_Zero: - u->d[0] = u->d[1] = 0.; + dval(&u[0]) = dval(&u[1]) = 0.; #ifdef Sudden_Underflow if (k & STRTOG_Inexact) { if (sign) - u->L[_0] = 0x80100000L; + word0(&u[0]) = 0x80100000L; else - u->L[2+_0] = 0x100000L; + word0(&u[1]) = 0x100000L; } break; #else @@ -88,80 +84,80 @@ strtodI(CONST char *s, char **sp, double *dd) #endif case STRTOG_Denormal: - u->L[_1] = bits[0]; - u->L[_0] = bits[1]; + word1(&u[0]) = bits[0]; + word0(&u[0]) = bits[1]; goto contain; case STRTOG_Normal: - u->L[_1] = bits[0]; - u->L[_0] = (bits[1] & ~0x100000) | ((exp + 0x3ff + 52) << 20); + word1(&u[0]) = bits[0]; + word0(&u[0]) = (bits[1] & ~0x100000) | ((exp + 0x3ff + 52) << 20); contain: j = k & STRTOG_Inexact; if (sign) { - u->L[_0] |= sign; + word0(&u[0]) |= sign; j = STRTOG_Inexact - j; } switch(j) { case STRTOG_Inexlo: #ifdef Sudden_Underflow if ((u->L[_0] & 0x7ff00000) < 0x3500000) { - u->L[2+_0] = u->L[_0] + 0x3500000; - u->L[2+_1] = u->L[_1]; - u->d[1] += ulp(u->d[1]); - u->L[2+_0] -= 0x3500000; - if (!(u->L[2+_0] & 0x7ff00000)) { - u->L[2+_0] = sign; - u->L[2+_1] = 0; + word0(&u[1]) = word0(&u[0]) + 0x3500000; + word1(&u[1]) = word1(&u[0]); + dval(&u[1]) += ulp(&u[1]); + word0(&u[1]) -= 0x3500000; + if (!(word0(&u[1]) & 0x7ff00000)) { + word0(&u[1]) = sign; + word1(&u[1]) = 0; } } else #endif - u->d[1] = u->d[0] + ulp(u->d[0]); + dval(&u[1]) = dval(&u[0]) + ulp(&u[0]); break; case STRTOG_Inexhi: - u->d[1] = u->d[0]; + dval(&u[1]) = dval(&u[0]); #ifdef Sudden_Underflow - if ((u->L[_0] & 0x7ff00000) < 0x3500000) { - u->L[_0] += 0x3500000; - u->d[0] -= ulpdown(u->d); - u->L[_0] -= 0x3500000; - if (!(u->L[_0] & 0x7ff00000)) { - u->L[_0] = sign; - u->L[_1] = 0; + if ((word0(&u[0]) & 0x7ff00000) < 0x3500000) { + word0(&u[0]) += 0x3500000; + dval(&u[0]) -= ulpdown(u); + word0(&u[0]) -= 0x3500000; + if (!(word0(&u[0]) & 0x7ff00000)) { + word0(&u[0]) = sign; + word1(&u[0]) = 0; } } else #endif - u->d[0] -= ulpdown(u->d); + dval(&u[0]) -= ulpdown(u); break; default: - u->d[1] = u->d[0]; + dval(&u[1]) = dval(&u[0]); } break; case STRTOG_Infinite: - u->L[_0] = u->L[2+_0] = sign | 0x7ff00000; - u->L[_1] = u->L[2+_1] = 0; + word0(&u[0]) = word0(&u[1]) = sign | 0x7ff00000; + word1(&u[0]) = word1(&u[1]) = 0; if (k & STRTOG_Inexact) { if (sign) { - u->L[2+_0] = 0xffefffffL; - u->L[2+_1] = 0xffffffffL; + word0(&u[1]) = 0xffefffffL; + word1(&u[1]) = 0xffffffffL; } else { - u->L[_0] = 0x7fefffffL; - u->L[_1] = 0xffffffffL; + word0(&u[0]) = 0x7fefffffL; + word1(&u[0]) = 0xffffffffL; } } break; case STRTOG_NaN: - u->L[0] = u->L[2] = d_QNAN0; - u->L[1] = u->L[3] = d_QNAN1; + u->L[0] = (u+1)->L[0] = d_QNAN0; + u->L[1] = (u+1)->L[1] = d_QNAN1; break; case STRTOG_NaNbits: - u->L[_0] = u->L[2+_0] = 0x7ff00000 | sign | bits[1]; - u->L[_1] = u->L[2+_1] = bits[0]; + word0(&u[0]) = word0(&u[1]) = 0x7ff00000 | sign | bits[1]; + word1(&u[0]) = word1(&u[1]) = bits[0]; } return k; } diff --git a/gdtoa/strtodg.c b/gdtoa/strtodg.c index 2d154148d..c2e3365c7 100644 --- a/gdtoa/strtodg.c +++ b/gdtoa/strtodg.c @@ -89,7 +89,7 @@ increment(Bigint *b) return b; } - int + void #ifdef KR_headers decrement(b) Bigint *b; #else @@ -119,7 +119,6 @@ decrement(Bigint *b) *x++ = y & 0xffff; } while(borrow && x < xe); #endif - return STRTOG_Inexlo; } static int @@ -173,9 +172,9 @@ set_ones(Bigint *b, int n) rvOK #ifdef KR_headers (d, fpi, exp, bits, exact, rd, irv) - double d; FPI *fpi; Long *exp; ULong *bits; int exact, rd, *irv; + U *d; FPI *fpi; Long *exp; ULong *bits; int exact, rd, *irv; #else - (double d, CONST FPI *fpi, Long *exp, ULong *bits, int exact, int rd, int *irv) + (U *d, FPI *fpi, Long *exp, ULong *bits, int exact, int rd, int *irv) #endif { Bigint *b; @@ -183,7 +182,7 @@ rvOK int bdif, e, j, k, k1, nb, rv; carry = rv = 0; - b = d2b(d, &e, &bdif); + b = d2b(dval(d), &e, &bdif); bdif -= nb = fpi->nbits; e += bdif; if (bdif <= 0) { @@ -206,9 +205,9 @@ rvOK goto ret; } switch(rd) { - case 1: + case 1: /* round down (toward -Infinity) */ goto trunc; - case 2: + case 2: /* round up (toward +Infinity) */ break; default: /* round near */ k = bdif - 1; @@ -292,15 +291,12 @@ rvOK static int #ifdef KR_headers -mantbits(d) double d; +mantbits(d) U *d; #else -mantbits(double _d) +mantbits(U *d) #endif { ULong L; - U d; - - dval(d) = _d; #ifdef VAX L = word1(d) << 16 | word1(d) >> 16; if (L) @@ -322,7 +318,7 @@ strtodg (s00, se, fpi, exp, bits) CONST char *s00; char **se; FPI *fpi; Long *exp; ULong *bits; #else - (CONST char *s00, char **se, CONST FPI *fpi, Long *exp, ULong *bits) + (CONST char *s00, char **se, FPI *fpi, Long *exp, ULong *bits) #endif { int abe, abits, asub; @@ -332,14 +328,35 @@ strtodg int sudden_underflow; CONST char *s, *s0, *s1; double adj0, tol; - U adj, rv; Long L; - ULong y, z; + U adj, rv; + ULong *b, *be, y, z; Bigint *ab, *bb, *bb1, *bd, *bd0, *bs, *delta, *rvb, *rvb0; +#ifdef USE_LOCALE /*{{*/ +#ifdef NO_LOCALE_CACHE + char *decimalpoint = localeconv()->decimal_point; + int dplen = strlen(decimalpoint); +#else + char *decimalpoint; + static char *decimalpoint_cache; + static int dplen; + if (!(s0 = decimalpoint_cache)) { + s0 = localeconv()->decimal_point; + if ((decimalpoint_cache = (char*)MALLOC(strlen(s0) + 1))) { + strcpy(decimalpoint_cache, s0); + s0 = decimalpoint_cache; + } + dplen = strlen(s0); + } + decimalpoint = (char*)s0; +#endif /*NO_LOCALE_CACHE*/ +#else /*USE_LOCALE}{*/ +#define dplen 1 +#endif /*USE_LOCALE}}*/ irv = STRTOG_Zero; denorm = sign = nz0 = nz = 0; - dval(rv) = 0.; + dval(&rv) = 0.; rvb = 0; nbits = fpi->nbits; for(s = s00;;s++) switch(*s) { @@ -394,13 +411,17 @@ strtodg z = 10*z + c - '0'; nd0 = nd; #ifdef USE_LOCALE - if (c == *localeconv()->decimal_point) + if (c == *decimalpoint) { + for(i = 1; decimalpoint[i]; ++i) + if (s[i] != decimalpoint[i]) + goto dig_done; + s += i; + c = *s; #else - if (c == '.') -#endif - { - decpt = 1; + if (c == '.') { c = *++s; +#endif + decpt = 1; if (!nd) { for(; c == '0'; c = *++s) nz++; @@ -429,7 +450,7 @@ strtodg nz = 0; } } - } + }/*}*/ dig_done: e = 0; if (c == 'e' || c == 'E') { @@ -527,13 +548,13 @@ strtodg if (!nd0) nd0 = nd; k = nd < DBL_DIG + 1 ? nd : DBL_DIG + 1; - dval(rv) = y; + dval(&rv) = y; if (k > 9) - dval(rv) = tens[k - 9] * dval(rv) + z; + dval(&rv) = tens[k - 9] * dval(&rv) + z; bd0 = 0; if (nbits <= P && nd <= DBL_DIG) { if (!e) { - if (rvOK(dval(rv), fpi, exp, bits, 1, rd, &irv)) + if (rvOK(&rv, fpi, exp, bits, 1, rd, &irv)) goto ret; } else if (e > 0) { @@ -541,9 +562,9 @@ strtodg #ifdef VAX goto vax_ovfl_check; #else - i = fivesbits[e] + mantbits(dval(rv)) <= P; - /* rv = */ rounded_product(dval(rv), tens[e]); - if (rvOK(dval(rv), fpi, exp, bits, i, rd, &irv)) + i = fivesbits[e] + mantbits(&rv) <= P; + /* rv = */ rounded_product(dval(&rv), tens[e]); + if (rvOK(&rv, fpi, exp, bits, i, rd, &irv)) goto ret; e1 -= e; goto rv_notOK; @@ -556,32 +577,32 @@ strtodg */ e2 = e - i; e1 -= i; - dval(rv) *= tens[i]; + dval(&rv) *= tens[i]; #ifdef VAX /* VAX exponent range is so narrow we must * worry about overflow here... */ vax_ovfl_check: - dval(adj) = dval(rv); - word0(adj) -= P*Exp_msk1; - /* adj = */ rounded_product(dval(adj), tens[e2]); - if ((word0(adj) & Exp_mask) + dval(&adj) = dval(&rv); + word0(&adj) -= P*Exp_msk1; + /* adj = */ rounded_product(dval(&adj), tens[e2]); + if ((word0(&adj) & Exp_mask) > Exp_msk1*(DBL_MAX_EXP+Bias-1-P)) goto rv_notOK; - word0(adj) += P*Exp_msk1; - dval(rv) = dval(adj); + word0(&adj) += P*Exp_msk1; + dval(&rv) = dval(&adj); #else - /* rv = */ rounded_product(dval(rv), tens[e2]); + /* rv = */ rounded_product(dval(&rv), tens[e2]); #endif - if (rvOK(dval(rv), fpi, exp, bits, 0, rd, &irv)) + if (rvOK(&rv, fpi, exp, bits, 0, rd, &irv)) goto ret; e1 -= e2; } } #ifndef Inaccurate_Divide else if (e >= -Ten_pmax) { - /* rv = */ rounded_quotient(dval(rv), tens[-e]); - if (rvOK(dval(rv), fpi, exp, bits, 0, rd, &irv)) + /* rv = */ rounded_quotient(dval(&rv), tens[-e]); + if (rvOK(&rv, fpi, exp, bits, 0, rd, &irv)) goto ret; e1 -= e; } @@ -595,45 +616,45 @@ strtodg e2 = 0; if (e1 > 0) { if ( (i = e1 & 15) !=0) - dval(rv) *= tens[i]; + dval(&rv) *= tens[i]; if (e1 &= ~15) { e1 >>= 4; - while(e1 >= (1 << n_bigtens-1)) { - e2 += ((word0(rv) & Exp_mask) + while(e1 >= (1 << (n_bigtens-1))) { + e2 += ((word0(&rv) & Exp_mask) >> Exp_shift1) - Bias; - word0(rv) &= ~Exp_mask; - word0(rv) |= Bias << Exp_shift1; - dval(rv) *= bigtens[n_bigtens-1]; - e1 -= 1 << n_bigtens-1; + word0(&rv) &= ~Exp_mask; + word0(&rv) |= Bias << Exp_shift1; + dval(&rv) *= bigtens[n_bigtens-1]; + e1 -= 1 << (n_bigtens-1); } - e2 += ((word0(rv) & Exp_mask) >> Exp_shift1) - Bias; - word0(rv) &= ~Exp_mask; - word0(rv) |= Bias << Exp_shift1; + e2 += ((word0(&rv) & Exp_mask) >> Exp_shift1) - Bias; + word0(&rv) &= ~Exp_mask; + word0(&rv) |= Bias << Exp_shift1; for(j = 0; e1 > 0; j++, e1 >>= 1) if (e1 & 1) - dval(rv) *= bigtens[j]; + dval(&rv) *= bigtens[j]; } } else if (e1 < 0) { e1 = -e1; if ( (i = e1 & 15) !=0) - dval(rv) /= tens[i]; + dval(&rv) /= tens[i]; if (e1 &= ~15) { e1 >>= 4; - while(e1 >= (1 << n_bigtens-1)) { - e2 += ((word0(rv) & Exp_mask) + while(e1 >= (1 << (n_bigtens-1))) { + e2 += ((word0(&rv) & Exp_mask) >> Exp_shift1) - Bias; - word0(rv) &= ~Exp_mask; - word0(rv) |= Bias << Exp_shift1; - dval(rv) *= tinytens[n_bigtens-1]; - e1 -= 1 << n_bigtens-1; + word0(&rv) &= ~Exp_mask; + word0(&rv) |= Bias << Exp_shift1; + dval(&rv) *= tinytens[n_bigtens-1]; + e1 -= 1 << (n_bigtens-1); } - e2 += ((word0(rv) & Exp_mask) >> Exp_shift1) - Bias; - word0(rv) &= ~Exp_mask; - word0(rv) |= Bias << Exp_shift1; + e2 += ((word0(&rv) & Exp_mask) >> Exp_shift1) - Bias; + word0(&rv) &= ~Exp_mask; + word0(&rv) |= Bias << Exp_shift1; for(j = 0; e1 > 0; j++, e1 >>= 1) if (e1 & 1) - dval(rv) *= tinytens[j]; + dval(&rv) *= tinytens[j]; } } #ifdef IBM @@ -644,7 +665,7 @@ strtodg */ e2 <<= 2; #endif - rvb = d2b(dval(rv), &rve, &rvbits); /* rv = rvb * 2^rve */ + rvb = d2b(dval(&rv), &rve, &rvbits); /* rv = rvb * 2^rve */ rve += e2; if ((j = rvbits - nbits) > 0) { rshift(rvb, j); @@ -688,7 +709,7 @@ strtodg /* Put digits into bd: true value = bd * 10^e */ - bd0 = s2b(s0, nd0, nd, y); + bd0 = s2b(s0, nd0, nd, y, dplen); for(;;) { bd = Balloc(bd0->k); @@ -822,7 +843,7 @@ strtodg } else irv = STRTOG_Normal | STRTOG_Inexhi; - if (bbbits < nbits && !denorm || !(rvb->x[0] & 1)) + if ((bbbits < nbits && !denorm) || !(rvb->x[0] & 1)) break; if (dsign) { rvb = increment(rvb); @@ -839,7 +860,7 @@ strtodg } break; } - if ((dval(adj) = ratio(delta, bs)) <= 2.) { + if ((dval(&adj) = ratio(delta, bs)) <= 2.) { adj1: inex = STRTOG_Inexlo; if (dsign) { @@ -853,15 +874,15 @@ strtodg irv = STRTOG_Underflow | STRTOG_Inexlo; break; } - adj0 = dval(adj) = 1.; + adj0 = dval(&adj) = 1.; } else { - adj0 = dval(adj) *= 0.5; + adj0 = dval(&adj) *= 0.5; if (dsign) { asub = 0; inex = STRTOG_Inexlo; } - if (dval(adj) < 2147483647.) { + if (dval(&adj) < 2147483647.) { L = (Long)adj0; adj0 -= L; switch(rd) { @@ -880,12 +901,12 @@ strtodg inex = STRTOG_Inexact - inex; } } - dval(adj) = L; + dval(&adj) = L; } } y = rve + rvbits; - /* adj *= ulp(dval(rv)); */ + /* adj *= ulp(dval(&rv)); */ /* if (asub) rv -= adj; else rv += adj; */ if (!denorm && rvbits < nbits) { @@ -893,7 +914,7 @@ strtodg rve -= j; rvbits = nbits; } - ab = d2b(dval(adj), &abe, &abits); + ab = d2b(dval(&adj), &abe, &abits); if (abe < 0) rshift(ab, -abe); else if (abe > 0) @@ -947,15 +968,15 @@ strtodg z = rve + rvbits; if (y == z && L) { /* Can we stop now? */ - tol = dval(adj) * 5e-16; /* > max rel error */ - dval(adj) = adj0 - .5; - if (dval(adj) < -tol) { + tol = dval(&adj) * 5e-16; /* > max rel error */ + dval(&adj) = adj0 - .5; + if (dval(&adj) < -tol) { if (adj0 > tol) { irv |= inex; break; } } - else if (dval(adj) > tol && adj0 < 1. - tol) { + else if (dval(&adj) > tol && adj0 < 1. - tol) { irv |= inex; break; } @@ -980,6 +1001,29 @@ strtodg Bfree(bd0); Bfree(delta); if (rve > fpi->emax) { + switch(fpi->rounding & 3) { + case FPI_Round_near: + goto huge; + case FPI_Round_up: + if (!sign) + goto huge; + break; + case FPI_Round_down: + if (sign) + goto huge; + } + /* Round to largest representable magnitude */ + Bfree(rvb); + rvb = 0; + irv = STRTOG_Normal | STRTOG_Inexlo; + *exp = fpi->emax; + b = bits; + be = b + ((fpi->nbits + 31) >> 5); + while(b < be) + *b++ = -1; + if ((j = fpi->nbits & 0x1f)) + *--be >>= (32 - j); + goto ret; huge: rvb->wds = 0; irv = STRTOG_Infinite | STRTOG_Overflow | STRTOG_Inexhi; @@ -994,12 +1038,19 @@ strtodg if (sudden_underflow) { rvb->wds = 0; irv = STRTOG_Underflow | STRTOG_Inexlo; +#ifndef NO_ERRNO + errno = ERANGE; +#endif } else { irv = (irv & ~STRTOG_Retmask) | (rvb->wds > 0 ? STRTOG_Denormal : STRTOG_Zero); - if (irv & STRTOG_Inexact) + if (irv & STRTOG_Inexact) { irv |= STRTOG_Underflow; +#ifndef NO_ERRNO + errno = ERANGE; +#endif + } } } if (se) diff --git a/gdtoa/strtodnrp.c b/gdtoa/strtodnrp.c index 3d0297f52..19a769f0b 100644 --- a/gdtoa/strtodnrp.c +++ b/gdtoa/strtodnrp.c @@ -44,7 +44,7 @@ strtod(s, sp) CONST char *s; char **sp; strtod(CONST char *s, char **sp) #endif { - static CONST FPI fpi = { 53, 1-1023-53+1, 2046-1023-53+1, 1, SI }; + static FPI fpi = { 53, 1-1023-53+1, 2046-1023-53+1, 1, SI }; ULong bits[2]; Long exp; int k; diff --git a/gdtoa/strtof.c b/gdtoa/strtof.c index 561264a1d..a8beb3520 100644 --- a/gdtoa/strtof.c +++ b/gdtoa/strtof.c @@ -38,13 +38,18 @@ strtof(s, sp) CONST char *s; char **sp; strtof(CONST char *s, char **sp) #endif { - static CONST FPI fpi = { 24, 1-127-24+1, 254-127-24+1, 1, SI }; + static FPI fpi0 = { 24, 1-127-24+1, 254-127-24+1, 1, SI }; ULong bits[1]; Long exp; int k; union { ULong L[1]; float f; } u; +#ifdef Honor_FLT_ROUNDS +#include "gdtoa_fltrnds.h" +#else +#define fpi &fpi0 +#endif - k = strtodg(s, sp, &fpi, &exp, bits); + k = strtodg(s, sp, fpi, &exp, bits); switch(k & STRTOG_Retmask) { case STRTOG_NoNumber: case STRTOG_Zero: @@ -53,7 +58,7 @@ strtof(CONST char *s, char **sp) case STRTOG_Normal: case STRTOG_NaNbits: - u.L[0] = bits[0] & 0x7fffff | exp + 0x7f + 23 << 23; + u.L[0] = (bits[0] & 0x7fffff) | ((exp + 0x7f + 23) << 23); break; case STRTOG_Denormal: diff --git a/gdtoa/strtopQ.c b/gdtoa/strtopQ.c index 9eefd768f..2acf7e910 100644 --- a/gdtoa/strtopQ.c +++ b/gdtoa/strtopQ.c @@ -49,6 +49,9 @@ THIS SOFTWARE. #define _3 0 #endif + extern ULong NanDflt_Q_D2A[4]; + + int #ifdef KR_headers strtopQ(s, sp, V) CONST char *s; char **sp; void *V; @@ -56,13 +59,18 @@ strtopQ(s, sp, V) CONST char *s; char **sp; void *V; strtopQ(CONST char *s, char **sp, void *V) #endif { - static CONST FPI fpi = { 113, 1-16383-113+1, 32766 - 16383 - 113 + 1, 1, SI }; + static FPI fpi0 = { 113, 1-16383-113+1, 32766 - 16383 - 113 + 1, 1, SI }; ULong bits[4]; Long exp; int k; ULong *L = (ULong*)V; +#ifdef Honor_FLT_ROUNDS +#include "gdtoa_fltrnds.h" +#else +#define fpi &fpi0 +#endif - k = strtodg(s, sp, &fpi, &exp, bits); + k = strtodg(s, sp, fpi, &exp, bits); switch(k & STRTOG_Retmask) { case STRTOG_NoNumber: case STRTOG_Zero: @@ -90,10 +98,10 @@ strtopQ(CONST char *s, char **sp, void *V) break; case STRTOG_NaN: - L[0] = ld_QNAN0; - L[1] = ld_QNAN1; - L[2] = ld_QNAN2; - L[3] = ld_QNAN3; + L[_0] = NanDflt_Q_D2A[3]; + L[_1] = NanDflt_Q_D2A[2]; + L[_2] = NanDflt_Q_D2A[1]; + L[_3] = NanDflt_Q_D2A[0]; } if (k & STRTOG_Neg) L[_0] |= 0x80000000L; diff --git a/gdtoa/strtopd.c b/gdtoa/strtopd.c index 4c8bbaf42..0fb35daea 100644 --- a/gdtoa/strtopd.c +++ b/gdtoa/strtopd.c @@ -38,12 +38,17 @@ strtopd(s, sp, d) char *s; char **sp; double *d; strtopd(CONST char *s, char **sp, double *d) #endif { - static CONST FPI fpi0 = { 53, 1-1023-53+1, 2046-1023-53+1, 1, SI }; + static FPI fpi0 = { 53, 1-1023-53+1, 2046-1023-53+1, 1, SI }; ULong bits[2]; Long exp; int k; +#ifdef Honor_FLT_ROUNDS +#include "gdtoa_fltrnds.h" +#else +#define fpi &fpi0 +#endif - k = strtodg(s, sp, &fpi0, &exp, bits); + k = strtodg(s, sp, fpi, &exp, bits); ULtod((ULong*)d, bits, exp, k); return k; } diff --git a/gdtoa/strtopdd.c b/gdtoa/strtopdd.c index d2c6d9b89..738372d88 100644 --- a/gdtoa/strtopdd.c +++ b/gdtoa/strtopdd.c @@ -39,9 +39,9 @@ strtopdd(CONST char *s, char **sp, double *dd) #endif { #ifdef Sudden_Underflow - static CONST FPI fpi = { 106, 1-1023, 2046-1023-106+1, 1, 1 }; + static FPI fpi0 = { 106, 1-1023, 2046-1023-106+1, 1, 1 }; #else - static CONST FPI fpi = { 106, 1-1023-53+1, 2046-1023-106+1, 1, 0 }; + static FPI fpi0 = { 106, 1-1023-53+1, 2046-1023-106+1, 1, 0 }; #endif ULong bits[4]; Long exp; @@ -51,8 +51,13 @@ strtopdd(CONST char *s, char **sp, double *dd) ULong L[4]; } U; U *u; +#ifdef Honor_FLT_ROUNDS +#include "gdtoa_fltrnds.h" +#else +#define fpi &fpi0 +#endif - rv = strtodg(s, sp, &fpi, &exp, bits); + rv = strtodg(s, sp, fpi, &exp, bits); u = (U*)dd; switch(rv & STRTOG_Retmask) { case STRTOG_NoNumber: @@ -62,8 +67,8 @@ strtopdd(CONST char *s, char **sp, double *dd) case STRTOG_Normal: u->L[_1] = (bits[1] >> 21 | bits[2] << 11) & 0xffffffffL; - u->L[_0] = bits[2] >> 21 | bits[3] << 11 & 0xfffff - | exp + 0x3ff + 105 << 20; + u->L[_0] = (bits[2] >> 21) | ((bits[3] << 11) & 0xfffff) + | ((exp + 0x3ff + 105) << 20); exp += 0x3ff + 52; if (bits[1] &= 0x1fffff) { i = hi0bits(bits[1]) - 11; @@ -74,7 +79,7 @@ strtopdd(CONST char *s, char **sp, double *dd) else exp -= i; if (i > 0) { - bits[1] = bits[1] << i | bits[0] >> 32-i; + bits[1] = bits[1] << i | bits[0] >> (32-i); bits[0] = bits[0] << i & 0xffffffffL; } } @@ -87,11 +92,11 @@ strtopdd(CONST char *s, char **sp, double *dd) else exp -= i; if (i < 32) { - bits[1] = bits[0] >> 32 - i; + bits[1] = bits[0] >> (32 - i); bits[0] = bits[0] << i & 0xffffffffL; } else { - bits[1] = bits[0] << i - 32; + bits[1] = bits[0] << (i - 32); bits[0] = 0; } } @@ -100,7 +105,7 @@ strtopdd(CONST char *s, char **sp, double *dd) break; } u->L[2+_1] = bits[0]; - u->L[2+_0] = bits[1] & 0xfffff | exp << 20; + u->L[2+_0] = (bits[1] & 0xfffff) | (exp << 20); break; case STRTOG_Denormal: @@ -119,10 +124,10 @@ strtopdd(CONST char *s, char **sp, double *dd) nearly_normal: i = hi0bits(bits[3]) - 11; /* i >= 12 */ j = 32 - i; - u->L[_0] = (bits[3] << i | bits[2] >> j) & 0xfffff - | 65 - i << 20; + u->L[_0] = ((bits[3] << i | bits[2] >> j) & 0xfffff) + | ((65 - i) << 20); u->L[_1] = (bits[2] << i | bits[1] >> j) & 0xffffffffL; - u->L[2+_0] = bits[1] & (1L << j) - 1; + u->L[2+_0] = bits[1] & ((1L << j) - 1); u->L[2+_1] = bits[0]; break; @@ -131,34 +136,34 @@ strtopdd(CONST char *s, char **sp, double *dd) if (i < 0) { j = -i; i += 32; - u->L[_0] = bits[2] >> j & 0xfffff | (33 + j) << 20; - u->L[_1] = (bits[2] << i | bits[1] >> j) & 0xffffffffL; - u->L[2+_0] = bits[1] & (1L << j) - 1; + u->L[_0] = (bits[2] >> j & 0xfffff) | (33 + j) << 20; + u->L[_1] = ((bits[2] << i) | (bits[1] >> j)) & 0xffffffffL; + u->L[2+_0] = bits[1] & ((1L << j) - 1); u->L[2+_1] = bits[0]; break; } if (i == 0) { - u->L[_0] = bits[2] & 0xfffff | 33 << 20; + u->L[_0] = (bits[2] & 0xfffff) | (33 << 20); u->L[_1] = bits[1]; u->L[2+_0] = 0; u->L[2+_1] = bits[0]; break; } j = 32 - i; - u->L[_0] = (bits[2] << i | bits[1] >> j) & 0xfffff - | j + 1 << 20; + u->L[_0] = (((bits[2] << i) | (bits[1] >> j)) & 0xfffff) + | ((j + 1) << 20); u->L[_1] = (bits[1] << i | bits[0] >> j) & 0xffffffffL; u->L[2+_0] = 0; - u->L[2+_1] = bits[0] & (1L << j) - 1; + u->L[2+_1] = bits[0] & ((1L << j) - 1); break; hardly_normal: j = 11 - hi0bits(bits[1]); i = 32 - j; - u->L[_0] = bits[1] >> j & 0xfffff | j + 1 << 20; + u->L[_0] = (bits[1] >> j & 0xfffff) | ((j + 1) << 20); u->L[_1] = (bits[1] << i | bits[0] >> j) & 0xffffffffL; u->L[2+_0] = 0; - u->L[2+_1] = bits[0] & (1L << j) - 1; + u->L[2+_1] = bits[0] & ((1L << j) - 1); break; case STRTOG_Infinite: diff --git a/gdtoa/strtopf.c b/gdtoa/strtopf.c index 806e14f6f..23ca5cbe5 100644 --- a/gdtoa/strtopf.c +++ b/gdtoa/strtopf.c @@ -38,12 +38,17 @@ strtopf(s, sp, f) CONST char *s; char **sp; float *f; strtopf(CONST char *s, char **sp, float *f) #endif { - static CONST FPI fpi = { 24, 1-127-24+1, 254-127-24+1, 1, SI }; + static FPI fpi0 = { 24, 1-127-24+1, 254-127-24+1, 1, SI }; ULong bits[1], *L; Long exp; int k; +#ifdef Honor_FLT_ROUNDS +#include "gdtoa_fltrnds.h" +#else +#define fpi &fpi0 +#endif - k = strtodg(s, sp, &fpi, &exp, bits); + k = strtodg(s, sp, fpi, &exp, bits); L = (ULong*)f; switch(k & STRTOG_Retmask) { case STRTOG_NoNumber: @@ -53,7 +58,7 @@ strtopf(CONST char *s, char **sp, float *f) case STRTOG_Normal: case STRTOG_NaNbits: - L[0] = bits[0] & 0x7fffff | exp + 0x7f + 23 << 23; + L[0] = (bits[0] & 0x7fffff) | ((exp + 0x7f + 23) << 23); break; case STRTOG_Denormal: diff --git a/gdtoa/strtopx.c b/gdtoa/strtopx.c index ecd0b3991..32192c572 100644 --- a/gdtoa/strtopx.c +++ b/gdtoa/strtopx.c @@ -31,6 +31,8 @@ THIS SOFTWARE. #include "gdtoaimp.h" + extern UShort NanDflt_ldus_D2A[5]; + #undef _0 #undef _1 @@ -58,13 +60,18 @@ strtopx(s, sp, V) CONST char *s; char **sp; void *V; strtopx(CONST char *s, char **sp, void *V) #endif { - static CONST FPI fpi = { 64, 1-16383-64+1, 32766 - 16383 - 64 + 1, 1, SI }; + static FPI fpi0 = { 64, 1-16383-64+1, 32766 - 16383 - 64 + 1, 1, SI }; ULong bits[2]; Long exp; int k; UShort *L = (UShort*)V; +#ifdef Honor_FLT_ROUNDS +#include "gdtoa_fltrnds.h" +#else +#define fpi &fpi0 +#endif - k = strtodg(s, sp, &fpi, &exp, bits); + k = strtodg(s, sp, fpi, &exp, bits); switch(k & STRTOG_Retmask) { case STRTOG_NoNumber: case STRTOG_Zero: @@ -87,15 +94,16 @@ strtopx(CONST char *s, char **sp, void *V) case STRTOG_Infinite: L[_0] = 0x7fff; - L[_1] = L[_2] = L[_3] = L[_4] = 0; + L[_1] = 0x8000; + L[_2] = L[_3] = L[_4] = 0; break; case STRTOG_NaN: - L[0] = ldus_QNAN0; - L[1] = ldus_QNAN1; - L[2] = ldus_QNAN2; - L[3] = ldus_QNAN3; - L[4] = ldus_QNAN4; + L[_4] = NanDflt_ldus_D2A[0]; + L[_3] = NanDflt_ldus_D2A[1]; + L[_2] = NanDflt_ldus_D2A[2]; + L[_1] = NanDflt_ldus_D2A[3]; + L[_0] = NanDflt_ldus_D2A[4]; } if (k & STRTOG_Neg) L[_0] |= 0x8000; diff --git a/gdtoa/strtopxL.c b/gdtoa/strtopxL.c index 00810fa35..6166c1e62 100644 --- a/gdtoa/strtopxL.c +++ b/gdtoa/strtopxL.c @@ -31,6 +31,8 @@ THIS SOFTWARE. #include "gdtoaimp.h" + extern ULong NanDflt_xL_D2A[3]; + #undef _0 #undef _1 @@ -54,13 +56,18 @@ strtopxL(s, sp, V) CONST char *s; char **sp; void *V; strtopxL(CONST char *s, char **sp, void *V) #endif { - static CONST FPI fpi = { 64, 1-16383-64+1, 32766 - 16383 - 64 + 1, 1, SI }; + static FPI fpi0 = { 64, 1-16383-64+1, 32766 - 16383 - 64 + 1, 1, SI }; ULong bits[2]; Long exp; int k; ULong *L = (ULong*)V; +#ifdef Honor_FLT_ROUNDS +#include "gdtoa_fltrnds.h" +#else +#define fpi &fpi0 +#endif - k = strtodg(s, sp, &fpi, &exp, bits); + k = strtodg(s, sp, fpi, &exp, bits); switch(k & STRTOG_Retmask) { case STRTOG_NoNumber: case STRTOG_Zero: @@ -77,13 +84,14 @@ strtopxL(CONST char *s, char **sp, void *V) case STRTOG_Infinite: L[_0] = 0x7fff << 16; - L[_1] = L[_2] = 0; + L[_1] = 0x80000000; + L[_2] = 0; break; case STRTOG_NaN: - L[0] = ld_QNAN0; - L[1] = ld_QNAN1; - L[2] = ld_QNAN2; + L[_0] = NanDflt_xL_D2A[2]; + L[_1] = NanDflt_xL_D2A[1]; + L[_2] = NanDflt_xL_D2A[0]; } if (k & STRTOG_Neg) L[_0] |= 0x80000000L; diff --git a/gdtoa/strtorQ.c b/gdtoa/strtorQ.c index 1cb157890..f5fd7bba9 100644 --- a/gdtoa/strtorQ.c +++ b/gdtoa/strtorQ.c @@ -49,6 +49,8 @@ THIS SOFTWARE. #define _3 0 #endif + extern ULong NanDflt_Q_D2A[4]; + void #ifdef KR_headers ULtoQ(L, bits, exp, k) ULong *L; ULong *bits; Long exp; int k; @@ -83,10 +85,10 @@ ULtoQ(ULong *L, ULong *bits, Long exp, int k) break; case STRTOG_NaN: - L[0] = ld_QNAN0; - L[1] = ld_QNAN1; - L[2] = ld_QNAN2; - L[3] = ld_QNAN3; + L[_0] = NanDflt_Q_D2A[3]; + L[_1] = NanDflt_Q_D2A[2]; + L[_2] = NanDflt_Q_D2A[1]; + L[_3] = NanDflt_Q_D2A[0]; } if (k & STRTOG_Neg) L[_0] |= 0x80000000L; @@ -99,9 +101,8 @@ strtorQ(s, sp, rounding, L) CONST char *s; char **sp; int rounding; void *L; strtorQ(CONST char *s, char **sp, int rounding, void *L) #endif { - static CONST FPI fpi0 = { 113, 1-16383-113+1, 32766-16383-113+1, 1, SI }; - CONST FPI *fpi; - FPI fpi1; + static FPI fpi0 = { 113, 1-16383-113+1, 32766-16383-113+1, 1, SI }; + FPI *fpi, fpi1; ULong bits[4]; Long exp; int k; diff --git a/gdtoa/strtord.c b/gdtoa/strtord.c index 1aa7aefe3..dd0769698 100644 --- a/gdtoa/strtord.c +++ b/gdtoa/strtord.c @@ -31,6 +31,8 @@ THIS SOFTWARE. #include "gdtoaimp.h" + extern ULong NanDflt_d_D2A[2]; + void #ifdef KR_headers ULtod(L, bits, exp, k) ULong *L; ULong *bits; Long exp; int k; @@ -61,8 +63,8 @@ ULtod(ULong *L, ULong *bits, Long exp, int k) break; case STRTOG_NaN: - L[0] = d_QNAN0; - L[1] = d_QNAN1; + L[_0] = NanDflt_d_D2A[1]; + L[_1] = NanDflt_d_D2A[0]; } if (k & STRTOG_Neg) L[_0] |= 0x80000000L; @@ -75,9 +77,8 @@ strtord(s, sp, rounding, d) CONST char *s; char **sp; int rounding; double *d; strtord(CONST char *s, char **sp, int rounding, double *d) #endif { - static CONST FPI fpi0 = { 53, 1-1023-53+1, 2046-1023-53+1, 1, SI }; - CONST FPI *fpi; - FPI fpi1; + static FPI fpi0 = { 53, 1-1023-53+1, 2046-1023-53+1, 1, SI }; + FPI *fpi, fpi1; ULong bits[2]; Long exp; int k; diff --git a/gdtoa/strtordd.c b/gdtoa/strtordd.c index 5b505f1b8..62152dbd4 100644 --- a/gdtoa/strtordd.c +++ b/gdtoa/strtordd.c @@ -31,6 +31,8 @@ THIS SOFTWARE. #include "gdtoaimp.h" + extern ULong NanDflt_d_D2A[2]; + void #ifdef KR_headers ULtodd(L, bits, exp, k) ULong *L; ULong *bits; Long exp; int k; @@ -48,8 +50,8 @@ ULtodd(ULong *L, ULong *bits, Long exp, int k) case STRTOG_Normal: L[_1] = (bits[1] >> 21 | bits[2] << 11) & (ULong)0xffffffffL; - L[_0] = bits[2] >> 21 | bits[3] << 11 & 0xfffff - | exp + 0x3ff + 105 << 20; + L[_0] = (bits[2] >> 21) | (bits[3] << 11 & 0xfffff) + | ((exp + 0x3ff + 105) << 20); exp += 0x3ff + 52; if (bits[1] &= 0x1fffff) { i = hi0bits(bits[1]) - 11; @@ -60,7 +62,7 @@ ULtodd(ULong *L, ULong *bits, Long exp, int k) else exp -= i; if (i > 0) { - bits[1] = bits[1] << i | bits[0] >> 32-i; + bits[1] = bits[1] << i | bits[0] >> (32-i); bits[0] = bits[0] << i & (ULong)0xffffffffL; } } @@ -73,11 +75,11 @@ ULtodd(ULong *L, ULong *bits, Long exp, int k) else exp -= i; if (i < 32) { - bits[1] = bits[0] >> 32 - i; + bits[1] = bits[0] >> (32 - i); bits[0] = bits[0] << i & (ULong)0xffffffffL; } else { - bits[1] = bits[0] << i - 32; + bits[1] = bits[0] << (i - 32); bits[0] = 0; } } @@ -86,7 +88,7 @@ ULtodd(ULong *L, ULong *bits, Long exp, int k) break; } L[2+_1] = bits[0]; - L[2+_0] = bits[1] & 0xfffff | exp << 20; + L[2+_0] = (bits[1] & 0xfffff) | (exp << 20); break; case STRTOG_Denormal: @@ -105,10 +107,10 @@ ULtodd(ULong *L, ULong *bits, Long exp, int k) nearly_normal: i = hi0bits(bits[3]) - 11; /* i >= 12 */ j = 32 - i; - L[_0] = (bits[3] << i | bits[2] >> j) & 0xfffff - | 65 - i << 20; + L[_0] = ((bits[3] << i | bits[2] >> j) & 0xfffff) + | ((65 - i) << 20); L[_1] = (bits[2] << i | bits[1] >> j) & 0xffffffffL; - L[2+_0] = bits[1] & ((ULong)1L << j) - 1; + L[2+_0] = bits[1] & (((ULong)1L << j) - 1); L[2+_1] = bits[0]; break; @@ -117,34 +119,34 @@ ULtodd(ULong *L, ULong *bits, Long exp, int k) if (i < 0) { j = -i; i += 32; - L[_0] = bits[2] >> j & 0xfffff | (33 + j) << 20; + L[_0] = (bits[2] >> j & 0xfffff) | ((33 + j) << 20); L[_1] = (bits[2] << i | bits[1] >> j) & 0xffffffffL; - L[2+_0] = bits[1] & ((ULong)1L << j) - 1; + L[2+_0] = bits[1] & (((ULong)1L << j) - 1); L[2+_1] = bits[0]; break; } if (i == 0) { - L[_0] = bits[2] & 0xfffff | 33 << 20; + L[_0] = (bits[2] & 0xfffff) | (33 << 20); L[_1] = bits[1]; L[2+_0] = 0; L[2+_1] = bits[0]; break; } j = 32 - i; - L[_0] = (bits[2] << i | bits[1] >> j) & 0xfffff - | j + 1 << 20; + L[_0] = (((bits[2] << i) | (bits[1] >> j)) & 0xfffff) + | ((j + 1) << 20); L[_1] = (bits[1] << i | bits[0] >> j) & 0xffffffffL; L[2+_0] = 0; - L[2+_1] = bits[0] & (1L << j) - 1; + L[2+_1] = bits[0] & ((1L << j) - 1); break; hardly_normal: j = 11 - hi0bits(bits[1]); i = 32 - j; - L[_0] = bits[1] >> j & 0xfffff | j + 1 << 20; + L[_0] = (bits[1] >> j & 0xfffff) | ((j + 1) << 20); L[_1] = (bits[1] << i | bits[0] >> j) & 0xffffffffL; L[2+_0] = 0; - L[2+_1] = bits[0] & ((ULong)1L << j) - 1; + L[2+_1] = bits[0] & (((ULong)1L << j) - 1); break; case STRTOG_Infinite: @@ -153,16 +155,17 @@ ULtodd(ULong *L, ULong *bits, Long exp, int k) break; case STRTOG_NaN: - L[0] = L[2] = d_QNAN0; - L[1] = L[3] = d_QNAN1; + L[_0] = L[_0+2] = NanDflt_d_D2A[1]; + L[_1] = L[_1+2] = NanDflt_d_D2A[0]; break; case STRTOG_NaNbits: - L[_1] = (bits[1] >> 21 | bits[2] << 11) & (ULong)0xffffffffL; - L[_0] = bits[2] >> 21 | bits[3] << 11 - | (ULong)0x7ff00000L; - L[2+_1] = bits[0]; - L[2+_0] = bits[1] | (ULong)0x7ff00000L; + L[_1] = (bits[1] >> 20 | bits[2] << 12) & (ULong)0xffffffffL; + L[_0] = bits[2] >> 20 | bits[3] << 12; + L[_0] |= (L[_1] | L[_0]) ? (ULong)0x7ff00000L : (ULong)0x7ff80000L; + L[2+_1] = bits[0] & (ULong)0xffffffffL; + L[2+_0] = bits[1] & 0xfffffL; + L[2+_0] |= (L[2+_1] | L[2+_0]) ? (ULong)0x7ff00000L : (ULong)0x7ff80000L; } if (k & STRTOG_Neg) { L[_0] |= 0x80000000L; @@ -178,12 +181,11 @@ strtordd(CONST char *s, char **sp, int rounding, double *dd) #endif { #ifdef Sudden_Underflow - static CONST FPI fpi0 = { 106, 1-1023, 2046-1023-106+1, 1, 1 }; + static FPI fpi0 = { 106, 1-1023, 2046-1023-106+1, 1, 1 }; #else - static CONST FPI fpi0 = { 106, 1-1023-53+1, 2046-1023-106+1, 1, 0 }; + static FPI fpi0 = { 106, 1-1023-53+1, 2046-1023-106+1, 1, 0 }; #endif - CONST FPI *fpi; - FPI fpi1; + FPI *fpi, fpi1; ULong bits[4]; Long exp; int k; diff --git a/gdtoa/strtorf.c b/gdtoa/strtorf.c index 3892d68d6..99b4ab710 100644 --- a/gdtoa/strtorf.c +++ b/gdtoa/strtorf.c @@ -31,6 +31,8 @@ THIS SOFTWARE. #include "gdtoaimp.h" + extern ULong NanDflt_f_D2A[1]; + void #ifdef KR_headers ULtof(L, bits, exp, k) ULong *L; ULong *bits; Long exp; int k; @@ -46,7 +48,7 @@ ULtof(ULong *L, ULong *bits, Long exp, int k) case STRTOG_Normal: case STRTOG_NaNbits: - L[0] = bits[0] & 0x7fffff | exp + 0x7f + 23 << 23; + L[0] = (bits[0] & 0x7fffff) | ((exp + 0x7f + 23) << 23); break; case STRTOG_Denormal: @@ -58,7 +60,7 @@ ULtof(ULong *L, ULong *bits, Long exp, int k) break; case STRTOG_NaN: - L[0] = f_QNAN; + L[0] = NanDflt_f_D2A[0]; } if (k & STRTOG_Neg) L[0] |= 0x80000000L; @@ -71,9 +73,8 @@ strtorf(s, sp, rounding, f) CONST char *s; char **sp; int rounding; float *f; strtorf(CONST char *s, char **sp, int rounding, float *f) #endif { - static CONST FPI fpi0 = { 24, 1-127-24+1, 254-127-24+1, 1, SI }; - CONST FPI *fpi; - FPI fpi1; + static FPI fpi0 = { 24, 1-127-24+1, 254-127-24+1, 1, SI }; + FPI *fpi, fpi1; ULong bits[1]; Long exp; int k; diff --git a/gdtoa/strtorx.c b/gdtoa/strtorx.c index cc3c0700f..994ce8e63 100644 --- a/gdtoa/strtorx.c +++ b/gdtoa/strtorx.c @@ -51,6 +51,8 @@ THIS SOFTWARE. #define _4 0 #endif + extern UShort NanDflt_ldus_D2A[5]; + void #ifdef KR_headers ULtox(L, bits, exp, k) UShort *L; ULong *bits; Long exp; int k; @@ -80,15 +82,16 @@ ULtox(UShort *L, ULong *bits, Long exp, int k) case STRTOG_Infinite: L[_0] = 0x7fff; - L[_1] = L[_2] = L[_3] = L[_4] = 0; + L[_1] = 0x8000; + L[_2] = L[_3] = L[_4] = 0; break; case STRTOG_NaN: - L[0] = ldus_QNAN0; - L[1] = ldus_QNAN1; - L[2] = ldus_QNAN2; - L[3] = ldus_QNAN3; - L[4] = ldus_QNAN4; + L[_4] = NanDflt_ldus_D2A[0]; + L[_3] = NanDflt_ldus_D2A[1]; + L[_2] = NanDflt_ldus_D2A[2]; + L[_1] = NanDflt_ldus_D2A[3]; + L[_0] = NanDflt_ldus_D2A[4]; } if (k & STRTOG_Neg) L[_0] |= 0x8000; @@ -101,9 +104,8 @@ strtorx(s, sp, rounding, L) CONST char *s; char **sp; int rounding; void *L; strtorx(CONST char *s, char **sp, int rounding, void *L) #endif { - static CONST FPI fpi0 = { 64, 1-16383-64+1, 32766 - 16383 - 64 + 1, 1, SI }; - CONST FPI *fpi; - FPI fpi1; + static FPI fpi0 = { 64, 1-16383-64+1, 32766 - 16383 - 64 + 1, 1, SI }; + FPI *fpi, fpi1; ULong bits[2]; Long exp; int k; diff --git a/gdtoa/strtorxL.c b/gdtoa/strtorxL.c index ffcafa907..bac4a0bb1 100644 --- a/gdtoa/strtorxL.c +++ b/gdtoa/strtorxL.c @@ -47,6 +47,8 @@ THIS SOFTWARE. #define _2 0 #endif + extern ULong NanDflt_xL_D2A[3]; + void #ifdef KR_headers ULtoxL(L, bits, exp, k) ULong *L; ULong *bits; Long exp; int k; @@ -69,14 +71,15 @@ ULtoxL(ULong *L, ULong *bits, Long exp, int k) break; case STRTOG_Infinite: - L[_0] = 0x7fff << 16; - L[_1] = L[_2] = 0; + L[_0] = 0x7fff0000; + L[_1] = 0x80000000; + L[_2] = 0; break; case STRTOG_NaN: - L[0] = ld_QNAN0; - L[1] = ld_QNAN1; - L[2] = ld_QNAN2; + L[_0] = NanDflt_xL_D2A[2]; + L[_1] = NanDflt_xL_D2A[1]; + L[_2] = NanDflt_xL_D2A[0]; } if (k & STRTOG_Neg) L[_0] |= 0x80000000L; @@ -89,9 +92,8 @@ strtorxL(s, sp, rounding, L) CONST char *s; char **sp; int rounding; void *L; strtorxL(CONST char *s, char **sp, int rounding, void *L) #endif { - static CONST FPI fpi0 = { 64, 1-16383-64+1, 32766 - 16383 - 64 + 1, 1, SI }; - CONST FPI *fpi; - FPI fpi1; + static FPI fpi0 = { 64, 1-16383-64+1, 32766 - 16383 - 64 + 1, 1, SI }; + FPI *fpi, fpi1; ULong bits[2]; Long exp; int k; diff --git a/gdtoa/ulp.c b/gdtoa/ulp.c index 27639d19e..17e9f862c 100644 --- a/gdtoa/ulp.c +++ b/gdtoa/ulp.c @@ -34,15 +34,14 @@ THIS SOFTWARE. double ulp #ifdef KR_headers - (x) double x; + (x) U *x; #else - (double _x) + (U *x) #endif { Long L; - U x, a; + U a; - dval(x) = _x; L = (word0(x) & Exp_mask) - (P-1)*Exp_msk1; #ifndef Sudden_Underflow if (L > 0) { @@ -50,22 +49,22 @@ ulp #ifdef IBM L |= Exp_msk1 >> 4; #endif - word0(a) = L; - word1(a) = 0; + word0(&a) = L; + word1(&a) = 0; #ifndef Sudden_Underflow } else { L = -L >> Exp_shift; if (L < Exp_shift) { - word0(a) = 0x80000 >> L; - word1(a) = 0; + word0(&a) = 0x80000 >> L; + word1(&a) = 0; } else { - word0(a) = 0; + word0(&a) = 0; L -= Exp_shift; - word1(a) = L >= 31 ? 1 : 1 << 31 - L; + word1(&a) = L >= 31 ? 1 : 1 << (31 - L); } } #endif - return dval(a); + return dval(&a); } diff --git a/jpeg-6b/CMakeLists.txt b/jpeg-6b/CMakeLists.txt index 5c8b5972e..dd5055f9b 100644 --- a/jpeg-6b/CMakeLists.txt +++ b/jpeg-6b/CMakeLists.txt @@ -1,7 +1,9 @@ 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" ) + set( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -Wno-unused-parameter -fomit-frame-pointer" ) endif( "${CMAKE_C_COMPILER_ID}" STREQUAL "GNU" OR "${CMAKE_C_COMPILER_ID}" STREQUAL "Clang" ) add_library( jpeg diff --git a/launcher-templates/genericlauncher.cmd.in b/launcher-templates/genericlauncher.cmd.in new file mode 100644 index 000000000..9a19bbc7a --- /dev/null +++ b/launcher-templates/genericlauncher.cmd.in @@ -0,0 +1,14 @@ +cd @USERFILE_WORKING_DIRECTORY@ +@USERFILE_ENV_COMMANDS@ + +IF NOT [x%1]==[x--debugger] GOTO SkipDebuggingMess + +ECHO Need to ditch the debugger! +SHIFT /1 +%1 %2 %3 %4 %5 %6 %7 %8 %9 +GOTO EOF + +:SkipDebuggingMess +%* + +:EOF \ No newline at end of file diff --git a/launcher-templates/launcher.env.cmd.in b/launcher-templates/launcher.env.cmd.in new file mode 100644 index 000000000..72a24e67e --- /dev/null +++ b/launcher-templates/launcher.env.cmd.in @@ -0,0 +1 @@ +set @_arg@ diff --git a/launcher-templates/perconfig.vcproj.user.in b/launcher-templates/perconfig.vcproj.user.in new file mode 100644 index 000000000..95cacecff --- /dev/null +++ b/launcher-templates/perconfig.vcproj.user.in @@ -0,0 +1,28 @@ + + + diff --git a/launcher-templates/perconfig.vcxproj.user.in b/launcher-templates/perconfig.vcxproj.user.in new file mode 100644 index 000000000..ef0237999 --- /dev/null +++ b/launcher-templates/perconfig.vcxproj.user.in @@ -0,0 +1,7 @@ + + @USERFILE_ENVIRONMENT@ + WindowsLocalDebugger + ${USERFILE_@USERFILE_CONFIGNAME@_COMMAND} + @USERFILE_COMMAND_ARGUMENTS@ + @USERFILE_WORKING_DIRECTORY@ + diff --git a/launcher-templates/targetlauncher.cmd.in b/launcher-templates/targetlauncher.cmd.in new file mode 100644 index 000000000..c5715d679 --- /dev/null +++ b/launcher-templates/targetlauncher.cmd.in @@ -0,0 +1,8 @@ +cd @USERFILE_WORKING_DIRECTORY@ +@USERFILE_ENV_COMMANDS@ +if [%1]==[--debugger] ( + SHIFT +) + +"@USERFILE_COMMAND@" @LAUNCHERSCRIPT_COMMAND_ARGUMENTS@ +pause diff --git a/launcher-templates/vcproj.user.in b/launcher-templates/vcproj.user.in new file mode 100644 index 000000000..117473d70 --- /dev/null +++ b/launcher-templates/vcproj.user.in @@ -0,0 +1,10 @@ + + + +@USERFILE_CONFIGSECTIONS@ + + diff --git a/launcher-templates/vcxproj.user.in b/launcher-templates/vcxproj.user.in new file mode 100644 index 000000000..f3e423835 --- /dev/null +++ b/launcher-templates/vcxproj.user.in @@ -0,0 +1,4 @@ + + +@USERFILE_CONFIGSECTIONS@ + diff --git a/lzma/C/7z.h b/lzma/C/7z.h new file mode 100644 index 000000000..b7edd3ba5 --- /dev/null +++ b/lzma/C/7z.h @@ -0,0 +1,203 @@ +/* 7z.h -- 7z interface +2010-03-11 : Igor Pavlov : Public domain */ + +#ifndef __7Z_H +#define __7Z_H + +#include "7zBuf.h" + +EXTERN_C_BEGIN + +#define k7zStartHeaderSize 0x20 +#define k7zSignatureSize 6 +extern Byte k7zSignature[k7zSignatureSize]; +#define k7zMajorVersion 0 + +enum EIdEnum +{ + k7zIdEnd, + k7zIdHeader, + k7zIdArchiveProperties, + k7zIdAdditionalStreamsInfo, + k7zIdMainStreamsInfo, + k7zIdFilesInfo, + k7zIdPackInfo, + k7zIdUnpackInfo, + k7zIdSubStreamsInfo, + k7zIdSize, + k7zIdCRC, + k7zIdFolder, + k7zIdCodersUnpackSize, + k7zIdNumUnpackStream, + k7zIdEmptyStream, + k7zIdEmptyFile, + k7zIdAnti, + k7zIdName, + k7zIdCTime, + k7zIdATime, + k7zIdMTime, + k7zIdWinAttributes, + k7zIdComment, + k7zIdEncodedHeader, + k7zIdStartPos, + k7zIdDummy +}; + +typedef struct +{ + UInt32 NumInStreams; + UInt32 NumOutStreams; + UInt64 MethodID; + CBuf Props; +} CSzCoderInfo; + +void SzCoderInfo_Init(CSzCoderInfo *p); +void SzCoderInfo_Free(CSzCoderInfo *p, ISzAlloc *alloc); + +typedef struct +{ + UInt32 InIndex; + UInt32 OutIndex; +} CSzBindPair; + +typedef struct +{ + CSzCoderInfo *Coders; + CSzBindPair *BindPairs; + UInt32 *PackStreams; + UInt64 *UnpackSizes; + UInt32 NumCoders; + UInt32 NumBindPairs; + UInt32 NumPackStreams; + int UnpackCRCDefined; + UInt32 UnpackCRC; + + UInt32 NumUnpackStreams; +} CSzFolder; + +void SzFolder_Init(CSzFolder *p); +UInt64 SzFolder_GetUnpackSize(CSzFolder *p); +int SzFolder_FindBindPairForInStream(CSzFolder *p, UInt32 inStreamIndex); +UInt32 SzFolder_GetNumOutStreams(CSzFolder *p); +UInt64 SzFolder_GetUnpackSize(CSzFolder *p); + +SRes SzFolder_Decode(const CSzFolder *folder, const UInt64 *packSizes, + ILookInStream *stream, UInt64 startPos, + Byte *outBuffer, size_t outSize, ISzAlloc *allocMain); + +typedef struct +{ + UInt32 Low; + UInt32 High; +} CNtfsFileTime; + +typedef struct +{ + CNtfsFileTime MTime; + UInt64 Size; + UInt32 Crc; + UInt32 Attrib; + Byte HasStream; + Byte IsDir; + Byte IsAnti; + Byte CrcDefined; + Byte MTimeDefined; + Byte AttribDefined; +} CSzFileItem; + +void SzFile_Init(CSzFileItem *p); + +typedef struct +{ + UInt64 *PackSizes; + Byte *PackCRCsDefined; + UInt32 *PackCRCs; + CSzFolder *Folders; + CSzFileItem *Files; + UInt32 NumPackStreams; + UInt32 NumFolders; + UInt32 NumFiles; +} CSzAr; + +void SzAr_Init(CSzAr *p); +void SzAr_Free(CSzAr *p, ISzAlloc *alloc); + + +/* + SzExtract extracts file from archive + + *outBuffer must be 0 before first call for each new archive. + + Extracting cache: + If you need to decompress more than one file, you can send + these values from previous call: + *blockIndex, + *outBuffer, + *outBufferSize + You can consider "*outBuffer" as cache of solid block. If your archive is solid, + it will increase decompression speed. + + If you use external function, you can declare these 3 cache variables + (blockIndex, outBuffer, outBufferSize) as static in that external function. + + Free *outBuffer and set *outBuffer to 0, if you want to flush cache. +*/ + +typedef struct +{ + CSzAr db; + + UInt64 startPosAfterHeader; + UInt64 dataPos; + + UInt32 *FolderStartPackStreamIndex; + UInt64 *PackStreamStartPositions; + UInt32 *FolderStartFileIndex; + UInt32 *FileIndexToFolderIndexMap; + + size_t *FileNameOffsets; /* in 2-byte steps */ + CBuf FileNames; /* UTF-16-LE */ +} CSzArEx; + +void SzArEx_Init(CSzArEx *p); +void SzArEx_Free(CSzArEx *p, ISzAlloc *alloc); +UInt64 SzArEx_GetFolderStreamPos(const CSzArEx *p, UInt32 folderIndex, UInt32 indexInFolder); +int SzArEx_GetFolderFullPackSize(const CSzArEx *p, UInt32 folderIndex, UInt64 *resSize); + +/* +if dest == NULL, the return value specifies the required size of the buffer, + in 16-bit characters, including the null-terminating character. +if dest != NULL, the return value specifies the number of 16-bit characters that + are written to the dest, including the null-terminating character. */ + +size_t SzArEx_GetFileNameUtf16(const CSzArEx *p, size_t fileIndex, UInt16 *dest); + +SRes SzArEx_Extract( + const CSzArEx *db, + ILookInStream *inStream, + UInt32 fileIndex, /* index of file */ + UInt32 *blockIndex, /* index of solid block */ + Byte **outBuffer, /* pointer to pointer to output buffer (allocated with allocMain) */ + size_t *outBufferSize, /* buffer size for output buffer */ + size_t *offset, /* offset of stream for required file in *outBuffer */ + size_t *outSizeProcessed, /* size of file in *outBuffer */ + ISzAlloc *allocMain, + ISzAlloc *allocTemp); + + +/* +SzArEx_Open Errors: +SZ_ERROR_NO_ARCHIVE +SZ_ERROR_ARCHIVE +SZ_ERROR_UNSUPPORTED +SZ_ERROR_MEM +SZ_ERROR_CRC +SZ_ERROR_INPUT_EOF +SZ_ERROR_FAIL +*/ + +SRes SzArEx_Open(CSzArEx *p, ILookInStream *inStream, ISzAlloc *allocMain, ISzAlloc *allocTemp); + +EXTERN_C_END + +#endif diff --git a/lzma/C/7zBuf.h b/lzma/C/7zBuf.h index 49b2354bd..88ff0c2f2 100644 --- a/lzma/C/7zBuf.h +++ b/lzma/C/7zBuf.h @@ -1,11 +1,15 @@ /* 7zBuf.h -- Byte Buffer -2008-10-04 : Igor Pavlov : Public domain */ +2009-02-07 : Igor Pavlov : Public domain */ #ifndef __7Z_BUF_H #define __7Z_BUF_H #include "Types.h" +#ifdef __cplusplus +extern "C" { +#endif + typedef struct { Byte *data; @@ -28,4 +32,8 @@ void DynBuf_SeekToBeg(CDynBuf *p); int DynBuf_Write(CDynBuf *p, const Byte *buf, size_t size, ISzAlloc *alloc); void DynBuf_Free(CDynBuf *p, ISzAlloc *alloc); +#ifdef __cplusplus +} +#endif + #endif diff --git a/lzma/C/7zCrc.c b/lzma/C/7zCrc.c index 92c47de0d..5801dabfc 100644 --- a/lzma/C/7zCrc.c +++ b/lzma/C/7zCrc.c @@ -1,35 +1,74 @@ /* 7zCrc.c -- CRC32 calculation -2008-08-05 -Igor Pavlov -Public domain */ +2009-11-23 : Igor Pavlov : Public domain */ #include "7zCrc.h" +#include "CpuArch.h" #define kCrcPoly 0xEDB88320 -UInt32 g_CrcTable[256]; -void MY_FAST_CALL CrcGenerateTable(void) +#ifdef MY_CPU_LE +#define CRC_NUM_TABLES 8 +#else +#define CRC_NUM_TABLES 1 +#endif + +typedef UInt32 (MY_FAST_CALL *CRC_FUNC)(UInt32 v, const void *data, size_t size, const UInt32 *table); + +static CRC_FUNC g_CrcUpdate; +UInt32 g_CrcTable[256 * CRC_NUM_TABLES]; + +#if CRC_NUM_TABLES == 1 + +#define CRC_UPDATE_BYTE_2(crc, b) (table[((crc) ^ (b)) & 0xFF] ^ ((crc) >> 8)) + +static UInt32 MY_FAST_CALL CrcUpdateT1(UInt32 v, const void *data, size_t size, const UInt32 *table) +{ + const Byte *p = (const Byte *)data; + for (; size > 0; size--, p++) + v = CRC_UPDATE_BYTE_2(v, *p); + return v; +} + +#else + +UInt32 MY_FAST_CALL CrcUpdateT4(UInt32 v, const void *data, size_t size, const UInt32 *table); +UInt32 MY_FAST_CALL CrcUpdateT8(UInt32 v, const void *data, size_t size, const UInt32 *table); + +#endif + +UInt32 MY_FAST_CALL CrcUpdate(UInt32 v, const void *data, size_t size) +{ + return g_CrcUpdate(v, data, size, g_CrcTable); +} + +UInt32 MY_FAST_CALL CrcCalc(const void *data, size_t size) +{ + return g_CrcUpdate(CRC_INIT_VAL, data, size, g_CrcTable) ^ CRC_INIT_VAL; +} + +void MY_FAST_CALL CrcGenerateTable() { UInt32 i; for (i = 0; i < 256; i++) { UInt32 r = i; - int j; + unsigned j; for (j = 0; j < 8; j++) r = (r >> 1) ^ (kCrcPoly & ~((r & 1) - 1)); g_CrcTable[i] = r; } -} - -UInt32 MY_FAST_CALL CrcUpdate(UInt32 v, const void *data, size_t size) -{ - const Byte *p = (const Byte *)data; - for (; size > 0 ; size--, p++) - v = CRC_UPDATE_BYTE(v, *p); - return v; -} - -UInt32 MY_FAST_CALL CrcCalc(const void *data, size_t size) -{ - return CrcUpdate(CRC_INIT_VAL, data, size) ^ 0xFFFFFFFF; + #if CRC_NUM_TABLES == 1 + g_CrcUpdate = CrcUpdateT1; + #else + for (; i < 256 * CRC_NUM_TABLES; i++) + { + UInt32 r = g_CrcTable[i - 256]; + g_CrcTable[i] = g_CrcTable[r & 0xFF] ^ (r >> 8); + } + g_CrcUpdate = CrcUpdateT4; + #ifdef MY_CPU_X86_OR_AMD64 + if (!CPU_Is_InOrder()) + g_CrcUpdate = CrcUpdateT8; + #endif + #endif } diff --git a/lzma/C/7zCrc.h b/lzma/C/7zCrc.h index ae230991e..4a1ec38c9 100644 --- a/lzma/C/7zCrc.h +++ b/lzma/C/7zCrc.h @@ -1,24 +1,25 @@ /* 7zCrc.h -- CRC32 calculation -2008-03-13 -Igor Pavlov -Public domain */ +2009-11-21 : Igor Pavlov : Public domain */ #ifndef __7Z_CRC_H #define __7Z_CRC_H -#include - #include "Types.h" +EXTERN_C_BEGIN + extern UInt32 g_CrcTable[]; +/* Call CrcGenerateTable one time before other CRC functions */ void MY_FAST_CALL CrcGenerateTable(void); #define CRC_INIT_VAL 0xFFFFFFFF -#define CRC_GET_DIGEST(crc) ((crc) ^ 0xFFFFFFFF) +#define CRC_GET_DIGEST(crc) ((crc) ^ CRC_INIT_VAL) #define CRC_UPDATE_BYTE(crc, b) (g_CrcTable[((crc) ^ (b)) & 0xFF] ^ ((crc) >> 8)) UInt32 MY_FAST_CALL CrcUpdate(UInt32 crc, const void *data, size_t size); UInt32 MY_FAST_CALL CrcCalc(const void *data, size_t size); +EXTERN_C_END + #endif diff --git a/lzma/C/7zCrcOpt.c b/lzma/C/7zCrcOpt.c new file mode 100644 index 000000000..6205d7161 --- /dev/null +++ b/lzma/C/7zCrcOpt.c @@ -0,0 +1,34 @@ +/* 7zCrcOpt.c -- CRC32 calculation : optimized version +2009-11-23 : Igor Pavlov : Public domain */ + +#include "CpuArch.h" + +#ifdef MY_CPU_LE + +#define CRC_UPDATE_BYTE_2(crc, b) (table[((crc) ^ (b)) & 0xFF] ^ ((crc) >> 8)) + +UInt32 MY_FAST_CALL CrcUpdateT4(UInt32 v, const void *data, size_t size, const UInt32 *table) +{ + const Byte *p = (const Byte *)data; + for (; size > 0 && ((unsigned)(ptrdiff_t)p & 3) != 0; size--, p++) + v = CRC_UPDATE_BYTE_2(v, *p); + for (; size >= 4; size -= 4, p += 4) + { + v ^= *(const UInt32 *)p; + v = + table[0x300 + (v & 0xFF)] ^ + table[0x200 + ((v >> 8) & 0xFF)] ^ + table[0x100 + ((v >> 16) & 0xFF)] ^ + table[0x000 + ((v >> 24))]; + } + for (; size > 0; size--, p++) + v = CRC_UPDATE_BYTE_2(v, *p); + return v; +} + +UInt32 MY_FAST_CALL CrcUpdateT8(UInt32 v, const void *data, size_t size, const UInt32 *table) +{ + return CrcUpdateT4(v, data, size, table); +} + +#endif diff --git a/lzma/C/7zDec.c b/lzma/C/7zDec.c new file mode 100644 index 000000000..338680747 --- /dev/null +++ b/lzma/C/7zDec.c @@ -0,0 +1,470 @@ +/* 7zDec.c -- Decoding from 7z folder +2010-11-02 : Igor Pavlov : Public domain */ + +#include + +/* #define _7ZIP_PPMD_SUPPPORT */ + +#include "7z.h" + +#include "Bcj2.h" +#include "Bra.h" +#include "CpuArch.h" +#include "LzmaDec.h" +#include "Lzma2Dec.h" +#ifdef _7ZIP_PPMD_SUPPPORT +#include "Ppmd7.h" +#endif + +#define k_Copy 0 +#define k_LZMA2 0x21 +#define k_LZMA 0x30101 +#define k_BCJ 0x03030103 +#define k_PPC 0x03030205 +#define k_ARM 0x03030501 +#define k_ARMT 0x03030701 +#define k_SPARC 0x03030805 +#define k_BCJ2 0x0303011B + +#ifdef _7ZIP_PPMD_SUPPPORT + +#define k_PPMD 0x30401 + +typedef struct +{ + IByteIn p; + const Byte *cur; + const Byte *end; + const Byte *begin; + UInt64 processed; + Bool extra; + SRes res; + ILookInStream *inStream; +} CByteInToLook; + +static Byte ReadByte(void *pp) +{ + CByteInToLook *p = (CByteInToLook *)pp; + if (p->cur != p->end) + return *p->cur++; + if (p->res == SZ_OK) + { + size_t size = p->cur - p->begin; + p->processed += size; + p->res = p->inStream->Skip(p->inStream, size); + size = (1 << 25); + p->res = p->inStream->Look(p->inStream, (const void **)&p->begin, &size); + p->cur = p->begin; + p->end = p->begin + size; + if (size != 0) + return *p->cur++;; + } + p->extra = True; + return 0; +} + +static SRes SzDecodePpmd(CSzCoderInfo *coder, UInt64 inSize, ILookInStream *inStream, + Byte *outBuffer, SizeT outSize, ISzAlloc *allocMain) +{ + CPpmd7 ppmd; + CByteInToLook s; + SRes res = SZ_OK; + + s.p.Read = ReadByte; + s.inStream = inStream; + s.begin = s.end = s.cur = NULL; + s.extra = False; + s.res = SZ_OK; + s.processed = 0; + + if (coder->Props.size != 5) + return SZ_ERROR_UNSUPPORTED; + + { + unsigned order = coder->Props.data[0]; + UInt32 memSize = GetUi32(coder->Props.data + 1); + if (order < PPMD7_MIN_ORDER || + order > PPMD7_MAX_ORDER || + memSize < PPMD7_MIN_MEM_SIZE || + memSize > PPMD7_MAX_MEM_SIZE) + return SZ_ERROR_UNSUPPORTED; + Ppmd7_Construct(&ppmd); + if (!Ppmd7_Alloc(&ppmd, memSize, allocMain)) + return SZ_ERROR_MEM; + Ppmd7_Init(&ppmd, order); + } + { + CPpmd7z_RangeDec rc; + Ppmd7z_RangeDec_CreateVTable(&rc); + rc.Stream = &s.p; + if (!Ppmd7z_RangeDec_Init(&rc)) + res = SZ_ERROR_DATA; + else if (s.extra) + res = (s.res != SZ_OK ? s.res : SZ_ERROR_DATA); + else + { + SizeT i; + for (i = 0; i < outSize; i++) + { + int sym = Ppmd7_DecodeSymbol(&ppmd, &rc.p); + if (s.extra || sym < 0) + break; + outBuffer[i] = (Byte)sym; + } + if (i != outSize) + res = (s.res != SZ_OK ? s.res : SZ_ERROR_DATA); + else if (s.processed + (s.cur - s.begin) != inSize || !Ppmd7z_RangeDec_IsFinishedOK(&rc)) + res = SZ_ERROR_DATA; + } + } + Ppmd7_Free(&ppmd, allocMain); + return res; +} + +#endif + + +static SRes SzDecodeLzma(CSzCoderInfo *coder, UInt64 inSize, ILookInStream *inStream, + Byte *outBuffer, SizeT outSize, ISzAlloc *allocMain) +{ + CLzmaDec state; + SRes res = SZ_OK; + + LzmaDec_Construct(&state); + RINOK(LzmaDec_AllocateProbs(&state, coder->Props.data, (unsigned)coder->Props.size, allocMain)); + state.dic = outBuffer; + state.dicBufSize = outSize; + LzmaDec_Init(&state); + + for (;;) + { + Byte *inBuf = NULL; + size_t lookahead = (1 << 18); + if (lookahead > inSize) + lookahead = (size_t)inSize; + res = inStream->Look((void *)inStream, (const void **)&inBuf, &lookahead); + if (res != SZ_OK) + break; + + { + SizeT inProcessed = (SizeT)lookahead, dicPos = state.dicPos; + ELzmaStatus status; + res = LzmaDec_DecodeToDic(&state, outSize, inBuf, &inProcessed, LZMA_FINISH_END, &status); + lookahead -= inProcessed; + inSize -= inProcessed; + if (res != SZ_OK) + break; + if (state.dicPos == state.dicBufSize || (inProcessed == 0 && dicPos == state.dicPos)) + { + if (state.dicBufSize != outSize || lookahead != 0 || + (status != LZMA_STATUS_FINISHED_WITH_MARK && + status != LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK)) + res = SZ_ERROR_DATA; + break; + } + res = inStream->Skip((void *)inStream, inProcessed); + if (res != SZ_OK) + break; + } + } + + LzmaDec_FreeProbs(&state, allocMain); + return res; +} + +static SRes SzDecodeLzma2(CSzCoderInfo *coder, UInt64 inSize, ILookInStream *inStream, + Byte *outBuffer, SizeT outSize, ISzAlloc *allocMain) +{ + CLzma2Dec state; + SRes res = SZ_OK; + + Lzma2Dec_Construct(&state); + if (coder->Props.size != 1) + return SZ_ERROR_DATA; + RINOK(Lzma2Dec_AllocateProbs(&state, coder->Props.data[0], allocMain)); + state.decoder.dic = outBuffer; + state.decoder.dicBufSize = outSize; + Lzma2Dec_Init(&state); + + for (;;) + { + Byte *inBuf = NULL; + size_t lookahead = (1 << 18); + if (lookahead > inSize) + lookahead = (size_t)inSize; + res = inStream->Look((void *)inStream, (const void **)&inBuf, &lookahead); + if (res != SZ_OK) + break; + + { + SizeT inProcessed = (SizeT)lookahead, dicPos = state.decoder.dicPos; + ELzmaStatus status; + res = Lzma2Dec_DecodeToDic(&state, outSize, inBuf, &inProcessed, LZMA_FINISH_END, &status); + lookahead -= inProcessed; + inSize -= inProcessed; + if (res != SZ_OK) + break; + if (state.decoder.dicPos == state.decoder.dicBufSize || (inProcessed == 0 && dicPos == state.decoder.dicPos)) + { + if (state.decoder.dicBufSize != outSize || lookahead != 0 || + (status != LZMA_STATUS_FINISHED_WITH_MARK)) + res = SZ_ERROR_DATA; + break; + } + res = inStream->Skip((void *)inStream, inProcessed); + if (res != SZ_OK) + break; + } + } + + Lzma2Dec_FreeProbs(&state, allocMain); + return res; +} + +static SRes SzDecodeCopy(UInt64 inSize, ILookInStream *inStream, Byte *outBuffer) +{ + while (inSize > 0) + { + void *inBuf; + size_t curSize = (1 << 18); + if (curSize > inSize) + curSize = (size_t)inSize; + RINOK(inStream->Look((void *)inStream, (const void **)&inBuf, &curSize)); + if (curSize == 0) + return SZ_ERROR_INPUT_EOF; + memcpy(outBuffer, inBuf, curSize); + outBuffer += curSize; + inSize -= curSize; + RINOK(inStream->Skip((void *)inStream, curSize)); + } + return SZ_OK; +} + +static Bool IS_MAIN_METHOD(UInt32 m) +{ + switch(m) + { + case k_Copy: + case k_LZMA: + case k_LZMA2: + #ifdef _7ZIP_PPMD_SUPPPORT + case k_PPMD: + #endif + return True; + } + return False; +} + +static Bool IS_SUPPORTED_CODER(const CSzCoderInfo *c) +{ + return + c->NumInStreams == 1 && + c->NumOutStreams == 1 && + c->MethodID <= (UInt32)0xFFFFFFFF && + IS_MAIN_METHOD((UInt32)c->MethodID); +} + +#define IS_BCJ2(c) ((c)->MethodID == k_BCJ2 && (c)->NumInStreams == 4 && (c)->NumOutStreams == 1) + +static SRes CheckSupportedFolder(const CSzFolder *f) +{ + if (f->NumCoders < 1 || f->NumCoders > 4) + return SZ_ERROR_UNSUPPORTED; + if (!IS_SUPPORTED_CODER(&f->Coders[0])) + return SZ_ERROR_UNSUPPORTED; + if (f->NumCoders == 1) + { + if (f->NumPackStreams != 1 || f->PackStreams[0] != 0 || f->NumBindPairs != 0) + return SZ_ERROR_UNSUPPORTED; + return SZ_OK; + } + if (f->NumCoders == 2) + { + CSzCoderInfo *c = &f->Coders[1]; + if (c->MethodID > (UInt32)0xFFFFFFFF || + c->NumInStreams != 1 || + c->NumOutStreams != 1 || + f->NumPackStreams != 1 || + f->PackStreams[0] != 0 || + f->NumBindPairs != 1 || + f->BindPairs[0].InIndex != 1 || + f->BindPairs[0].OutIndex != 0) + return SZ_ERROR_UNSUPPORTED; + switch ((UInt32)c->MethodID) + { + case k_BCJ: + case k_ARM: + break; + default: + return SZ_ERROR_UNSUPPORTED; + } + return SZ_OK; + } + if (f->NumCoders == 4) + { + if (!IS_SUPPORTED_CODER(&f->Coders[1]) || + !IS_SUPPORTED_CODER(&f->Coders[2]) || + !IS_BCJ2(&f->Coders[3])) + return SZ_ERROR_UNSUPPORTED; + if (f->NumPackStreams != 4 || + f->PackStreams[0] != 2 || + f->PackStreams[1] != 6 || + f->PackStreams[2] != 1 || + f->PackStreams[3] != 0 || + f->NumBindPairs != 3 || + f->BindPairs[0].InIndex != 5 || f->BindPairs[0].OutIndex != 0 || + f->BindPairs[1].InIndex != 4 || f->BindPairs[1].OutIndex != 1 || + f->BindPairs[2].InIndex != 3 || f->BindPairs[2].OutIndex != 2) + return SZ_ERROR_UNSUPPORTED; + return SZ_OK; + } + return SZ_ERROR_UNSUPPORTED; +} + +static UInt64 GetSum(const UInt64 *values, UInt32 index) +{ + UInt64 sum = 0; + UInt32 i; + for (i = 0; i < index; i++) + sum += values[i]; + return sum; +} + +#define CASE_BRA_CONV(isa) case k_ ## isa: isa ## _Convert(outBuffer, outSize, 0, 0); break; + +static SRes SzFolder_Decode2(const CSzFolder *folder, const UInt64 *packSizes, + ILookInStream *inStream, UInt64 startPos, + Byte *outBuffer, SizeT outSize, ISzAlloc *allocMain, + Byte *tempBuf[]) +{ + UInt32 ci; + SizeT tempSizes[3] = { 0, 0, 0}; + SizeT tempSize3 = 0; + Byte *tempBuf3 = 0; + + RINOK(CheckSupportedFolder(folder)); + + for (ci = 0; ci < folder->NumCoders; ci++) + { + CSzCoderInfo *coder = &folder->Coders[ci]; + + if (IS_MAIN_METHOD((UInt32)coder->MethodID)) + { + UInt32 si = 0; + UInt64 offset; + UInt64 inSize; + Byte *outBufCur = outBuffer; + SizeT outSizeCur = outSize; + if (folder->NumCoders == 4) + { + UInt32 indices[] = { 3, 2, 0 }; + UInt64 unpackSize = folder->UnpackSizes[ci]; + si = indices[ci]; + if (ci < 2) + { + Byte *temp; + outSizeCur = (SizeT)unpackSize; + if (outSizeCur != unpackSize) + return SZ_ERROR_MEM; + temp = (Byte *)IAlloc_Alloc(allocMain, outSizeCur); + if (temp == 0 && outSizeCur != 0) + return SZ_ERROR_MEM; + outBufCur = tempBuf[1 - ci] = temp; + tempSizes[1 - ci] = outSizeCur; + } + else if (ci == 2) + { + if (unpackSize > outSize) /* check it */ + return SZ_ERROR_PARAM; + tempBuf3 = outBufCur = outBuffer + (outSize - (size_t)unpackSize); + tempSize3 = outSizeCur = (SizeT)unpackSize; + } + else + return SZ_ERROR_UNSUPPORTED; + } + offset = GetSum(packSizes, si); + inSize = packSizes[si]; + RINOK(LookInStream_SeekTo(inStream, startPos + offset)); + + if (coder->MethodID == k_Copy) + { + if (inSize != outSizeCur) /* check it */ + return SZ_ERROR_DATA; + RINOK(SzDecodeCopy(inSize, inStream, outBufCur)); + } + else if (coder->MethodID == k_LZMA) + { + RINOK(SzDecodeLzma(coder, inSize, inStream, outBufCur, outSizeCur, allocMain)); + } + else if (coder->MethodID == k_LZMA2) + { + RINOK(SzDecodeLzma2(coder, inSize, inStream, outBufCur, outSizeCur, allocMain)); + } + else + { + #ifdef _7ZIP_PPMD_SUPPPORT + RINOK(SzDecodePpmd(coder, inSize, inStream, outBufCur, outSizeCur, allocMain)); + #else + return SZ_ERROR_UNSUPPORTED; + #endif + } + } + else if (coder->MethodID == k_BCJ2) + { + UInt64 offset = GetSum(packSizes, 1); + UInt64 s3Size = packSizes[1]; + SRes res; + if (ci != 3) + return SZ_ERROR_UNSUPPORTED; + RINOK(LookInStream_SeekTo(inStream, startPos + offset)); + tempSizes[2] = (SizeT)s3Size; + if (tempSizes[2] != s3Size) + return SZ_ERROR_MEM; + tempBuf[2] = (Byte *)IAlloc_Alloc(allocMain, tempSizes[2]); + if (tempBuf[2] == 0 && tempSizes[2] != 0) + return SZ_ERROR_MEM; + res = SzDecodeCopy(s3Size, inStream, tempBuf[2]); + RINOK(res) + + res = Bcj2_Decode( + tempBuf3, tempSize3, + tempBuf[0], tempSizes[0], + tempBuf[1], tempSizes[1], + tempBuf[2], tempSizes[2], + outBuffer, outSize); + RINOK(res) + } + else + { + if (ci != 1) + return SZ_ERROR_UNSUPPORTED; + switch(coder->MethodID) + { + case k_BCJ: + { + UInt32 state; + x86_Convert_Init(state); + x86_Convert(outBuffer, outSize, 0, &state, 0); + break; + } + CASE_BRA_CONV(ARM) + default: + return SZ_ERROR_UNSUPPORTED; + } + } + } + return SZ_OK; +} + +SRes SzFolder_Decode(const CSzFolder *folder, const UInt64 *packSizes, + ILookInStream *inStream, UInt64 startPos, + Byte *outBuffer, size_t outSize, ISzAlloc *allocMain) +{ + Byte *tempBuf[3] = { 0, 0, 0}; + int i; + SRes res = SzFolder_Decode2(folder, packSizes, inStream, startPos, + outBuffer, (SizeT)outSize, allocMain, tempBuf); + for (i = 0; i < 3; i++) + IAlloc_Free(allocMain, tempBuf[i]); + return res; +} diff --git a/lzma/C/Archive/7z/7zIn.c b/lzma/C/7zIn.c similarity index 75% rename from lzma/C/Archive/7z/7zIn.c rename to lzma/C/7zIn.c index 75b0bcd1d..f1a44928e 100644 --- a/lzma/C/Archive/7z/7zIn.c +++ b/lzma/C/7zIn.c @@ -1,17 +1,134 @@ /* 7zIn.c -- 7z Input functions -2008-12-31 : Igor Pavlov : Public domain */ +2010-10-29 : Igor Pavlov : Public domain */ -#include "../../7zCrc.h" -#include "../../CpuArch.h" +#include -#include "7zDecode.h" -#include "7zIn.h" +#include "7z.h" +#include "7zCrc.h" +#include "CpuArch.h" + +Byte k7zSignature[k7zSignatureSize] = {'7', 'z', 0xBC, 0xAF, 0x27, 0x1C}; #define RINOM(x) { if ((x) == 0) return SZ_ERROR_MEM; } #define NUM_FOLDER_CODERS_MAX 32 #define NUM_CODER_STREAMS_MAX 32 +void SzCoderInfo_Init(CSzCoderInfo *p) +{ + Buf_Init(&p->Props); +} + +void SzCoderInfo_Free(CSzCoderInfo *p, ISzAlloc *alloc) +{ + Buf_Free(&p->Props, alloc); + SzCoderInfo_Init(p); +} + +void SzFolder_Init(CSzFolder *p) +{ + p->Coders = 0; + p->BindPairs = 0; + p->PackStreams = 0; + p->UnpackSizes = 0; + p->NumCoders = 0; + p->NumBindPairs = 0; + p->NumPackStreams = 0; + p->UnpackCRCDefined = 0; + p->UnpackCRC = 0; + p->NumUnpackStreams = 0; +} + +void SzFolder_Free(CSzFolder *p, ISzAlloc *alloc) +{ + UInt32 i; + if (p->Coders) + for (i = 0; i < p->NumCoders; i++) + SzCoderInfo_Free(&p->Coders[i], alloc); + IAlloc_Free(alloc, p->Coders); + IAlloc_Free(alloc, p->BindPairs); + IAlloc_Free(alloc, p->PackStreams); + IAlloc_Free(alloc, p->UnpackSizes); + SzFolder_Init(p); +} + +UInt32 SzFolder_GetNumOutStreams(CSzFolder *p) +{ + UInt32 result = 0; + UInt32 i; + for (i = 0; i < p->NumCoders; i++) + result += p->Coders[i].NumOutStreams; + return result; +} + +int SzFolder_FindBindPairForInStream(CSzFolder *p, UInt32 inStreamIndex) +{ + UInt32 i; + for (i = 0; i < p->NumBindPairs; i++) + if (p->BindPairs[i].InIndex == inStreamIndex) + return i; + return -1; +} + + +int SzFolder_FindBindPairForOutStream(CSzFolder *p, UInt32 outStreamIndex) +{ + UInt32 i; + for (i = 0; i < p->NumBindPairs; i++) + if (p->BindPairs[i].OutIndex == outStreamIndex) + return i; + return -1; +} + +UInt64 SzFolder_GetUnpackSize(CSzFolder *p) +{ + int i = (int)SzFolder_GetNumOutStreams(p); + if (i == 0) + return 0; + for (i--; i >= 0; i--) + if (SzFolder_FindBindPairForOutStream(p, i) < 0) + return p->UnpackSizes[i]; + /* throw 1; */ + return 0; +} + +void SzFile_Init(CSzFileItem *p) +{ + p->HasStream = 1; + p->IsDir = 0; + p->IsAnti = 0; + p->CrcDefined = 0; + p->MTimeDefined = 0; +} + +void SzAr_Init(CSzAr *p) +{ + p->PackSizes = 0; + p->PackCRCsDefined = 0; + p->PackCRCs = 0; + p->Folders = 0; + p->Files = 0; + p->NumPackStreams = 0; + p->NumFolders = 0; + p->NumFiles = 0; +} + +void SzAr_Free(CSzAr *p, ISzAlloc *alloc) +{ + UInt32 i; + if (p->Folders) + for (i = 0; i < p->NumFolders; i++) + SzFolder_Free(&p->Folders[i], alloc); + + IAlloc_Free(alloc, p->PackSizes); + IAlloc_Free(alloc, p->PackCRCsDefined); + IAlloc_Free(alloc, p->PackCRCs); + IAlloc_Free(alloc, p->Folders); + IAlloc_Free(alloc, p->Files); + SzAr_Init(p); +} + + void SzArEx_Init(CSzArEx *p) { SzAr_Init(&p->db); @@ -19,6 +136,8 @@ void SzArEx_Init(CSzArEx *p) p->PackStreamStartPositions = 0; p->FolderStartFileIndex = 0; p->FileIndexToFolderIndexMap = 0; + p->FileNameOffsets = 0; + Buf_Init(&p->FileNames); } void SzArEx_Free(CSzArEx *p, ISzAlloc *alloc) @@ -27,6 +146,10 @@ void SzArEx_Free(CSzArEx *p, ISzAlloc *alloc) IAlloc_Free(alloc, p->PackStreamStartPositions); IAlloc_Free(alloc, p->FolderStartFileIndex); IAlloc_Free(alloc, p->FileIndexToFolderIndexMap); + + IAlloc_Free(alloc, p->FileNameOffsets); + Buf_Free(&p->FileNames, alloc); + SzAr_Free(&p->db, alloc); SzArEx_Init(p); } @@ -488,11 +611,11 @@ static SRes SzGetNextFolderItem(CSzData *sd, CSzFolder *folder, ISzAlloc *alloc) return SZ_ERROR_UNSUPPORTED; folder->NumBindPairs = numBindPairs = numOutStreams - 1; - MY_ALLOC(CBindPair, folder->BindPairs, (size_t)numBindPairs, alloc); + MY_ALLOC(CSzBindPair, folder->BindPairs, (size_t)numBindPairs, alloc); for (i = 0; i < numBindPairs; i++) { - CBindPair *bp = folder->BindPairs + i; + CSzBindPair *bp = folder->BindPairs + i; RINOK(SzReadNumber32(sd, &bp->InIndex)); RINOK(SzReadNumber32(sd, &bp->OutIndex)); } @@ -780,81 +903,38 @@ static SRes SzReadStreamsInfo( } } -Byte kUtf8Limits[5] = { 0xC0, 0xE0, 0xF0, 0xF8, 0xFC }; +size_t SzArEx_GetFileNameUtf16(const CSzArEx *p, size_t fileIndex, UInt16 *dest) +{ + size_t len = p->FileNameOffsets[fileIndex + 1] - p->FileNameOffsets[fileIndex]; + if (dest != 0) + { + size_t i; + const Byte *src = p->FileNames.data + (p->FileNameOffsets[fileIndex] * 2); + for (i = 0; i < len; i++) + dest[i] = GetUi16(src + i * 2); + } + return len; +} -static SRes SzReadFileNames(CSzData *sd, UInt32 numFiles, CSzFileItem *files, ISzAlloc *alloc) +static SRes SzReadFileNames(const Byte *p, size_t size, UInt32 numFiles, size_t *sizes) { UInt32 i; + size_t pos = 0; for (i = 0; i < numFiles; i++) { - UInt32 len = 0; - UInt32 pos = 0; - CSzFileItem *file = files + i; - while (pos + 2 <= sd->Size) + sizes[i] = pos; + for (;;) { - int numAdds; - UInt32 value = (UInt32)(sd->Data[pos] | (((UInt32)sd->Data[pos + 1]) << 8)); - pos += 2; - len++; - if (value == 0) + if (pos >= size) + return SZ_ERROR_ARCHIVE; + if (p[pos * 2] == 0 && p[pos * 2 + 1] == 0) break; - if (value < 0x80) - continue; - if (value >= 0xD800 && value < 0xE000) - { - UInt32 c2; - if (value >= 0xDC00) - return SZ_ERROR_ARCHIVE; - if (pos + 2 > sd->Size) - return SZ_ERROR_ARCHIVE; - c2 = (UInt32)(sd->Data[pos] | (((UInt32)sd->Data[pos + 1]) << 8)); - pos += 2; - if (c2 < 0xDC00 || c2 >= 0xE000) - return SZ_ERROR_ARCHIVE; - value = ((value - 0xD800) << 10) | (c2 - 0xDC00); - } - for (numAdds = 1; numAdds < 5; numAdds++) - if (value < (((UInt32)1) << (numAdds * 5 + 6))) - break; - len += numAdds; - } - - MY_ALLOC(char, file->Name, (size_t)len, alloc); - - len = 0; - while (2 <= sd->Size) - { - int numAdds; - UInt32 value = (UInt32)(sd->Data[0] | (((UInt32)sd->Data[1]) << 8)); - SzSkeepDataSize(sd, 2); - if (value < 0x80) - { - file->Name[len++] = (char)value; - if (value == 0) - break; - continue; - } - if (value >= 0xD800 && value < 0xE000) - { - UInt32 c2 = (UInt32)(sd->Data[0] | (((UInt32)sd->Data[1]) << 8)); - SzSkeepDataSize(sd, 2); - value = ((value - 0xD800) << 10) | (c2 - 0xDC00); - } - for (numAdds = 1; numAdds < 5; numAdds++) - if (value < (((UInt32)1) << (numAdds * 5 + 6))) - break; - file->Name[len++] = (char)(kUtf8Limits[numAdds - 1] + (value >> (6 * numAdds))); - do - { - numAdds--; - file->Name[len++] = (char)(0x80 + ((value >> (6 * numAdds)) & 0x3F)); - } - while (numAdds > 0); - - len += numAdds; + pos++; } + pos++; } - return SZ_OK; + sizes[i] = pos; + return (pos == size) ? SZ_OK : SZ_ERROR_ARCHIVE; } static SRes SzReadHeader2( @@ -920,7 +1000,8 @@ static SRes SzReadHeader2( if (type == k7zIdEnd) break; RINOK(SzReadNumber(sd, &size)); - + if (size > sd->Size) + return SZ_ERROR_ARCHIVE; if ((UInt64)(int)type != type) { RINOK(SzSkeepDataSize(sd, size)); @@ -930,8 +1011,17 @@ static SRes SzReadHeader2( { case k7zIdName: { + size_t namesSize; RINOK(SzReadSwitch(sd)); - RINOK(SzReadFileNames(sd, numFiles, files, allocMain)) + namesSize = (size_t)size - 1; + if ((namesSize & 1) != 0) + return SZ_ERROR_ARCHIVE; + if (!Buf_Create(&p->FileNames, namesSize, allocMain)) + return SZ_ERROR_MEM; + MY_ALLOC(size_t, p->FileNameOffsets, numFiles + 1, allocMain); + memcpy(p->FileNames.data, sd->Data, namesSize); + RINOK(SzReadFileNames(sd->Data, namesSize >> 1, numFiles, p->FileNameOffsets)) + RINOK(SzSkeepDataSize(sd, namesSize)); break; } case k7zIdEmptyStream: @@ -948,6 +1038,25 @@ static SRes SzReadHeader2( RINOK(SzReadBoolVector(sd, numEmptyStreams, emptyFileVector, allocTemp)); break; } + case k7zIdWinAttributes: + { + RINOK(SzReadBoolVector2(sd, numFiles, lwtVector, allocTemp)); + RINOK(SzReadSwitch(sd)); + for (i = 0; i < numFiles; i++) + { + CSzFileItem *f = &files[i]; + Byte defined = (*lwtVector)[i]; + f->AttribDefined = defined; + f->Attrib = 0; + if (defined) + { + RINOK(SzReadUInt32(sd, &f->Attrib)); + } + } + IAlloc_Free(allocTemp, *lwtVector); + *lwtVector = NULL; + break; + } case k7zIdMTime: { RINOK(SzReadBoolVector2(sd, numFiles, lwtVector, allocTemp)); @@ -964,6 +1073,8 @@ static SRes SzReadHeader2( RINOK(SzReadUInt32(sd, &f->MTime.High)); } } + IAlloc_Free(allocTemp, *lwtVector); + *lwtVector = NULL; break; } default: @@ -988,8 +1099,8 @@ static SRes SzReadHeader2( { file->IsDir = 0; file->Size = (*unpackSizes)[sizeIndex]; - file->FileCRC = (*digests)[sizeIndex]; - file->FileCRCDefined = (Byte)(*digestsDefined)[sizeIndex]; + file->Crc = (*digests)[sizeIndex]; + file->CrcDefined = (Byte)(*digestsDefined)[sizeIndex]; sizeIndex++; } else @@ -1000,7 +1111,8 @@ static SRes SzReadHeader2( file->IsDir = (Byte)((*emptyFileVector)[emptyFileIndex] ? 0 : 1); emptyFileIndex++; file->Size = 0; - file->FileCRCDefined = 0; + file->Crc = 0; + file->CrcDefined = 0; } } } @@ -1066,7 +1178,7 @@ static SRes SzReadAndDecodePackedStreams2( if (!Buf_Create(outBuffer, (size_t)unpackSize, allocTemp)) return SZ_ERROR_MEM; - res = SzDecode(p->PackSizes, folder, + res = SzFolder_Decode(folder, p->PackSizes, inStream, dataStartPos, outBuffer->data, (size_t)unpackSize, allocTemp); RINOK(res); @@ -1106,12 +1218,16 @@ static SRes SzArEx_Open2( ISzAlloc *allocTemp) { Byte header[k7zStartHeaderSize]; + Int64 startArcPos; UInt64 nextHeaderOffset, nextHeaderSize; size_t nextHeaderSizeT; UInt32 nextHeaderCRC; CBuf buffer; SRes res; + startArcPos = 0; + RINOK(inStream->Seek(inStream, &startArcPos, SZ_SEEK_CUR)); + RINOK(LookInStream_Read2(inStream, header, k7zStartHeaderSize, SZ_ERROR_NO_ARCHIVE)); if (!TestSignatureCandidate(header)) @@ -1123,7 +1239,7 @@ static SRes SzArEx_Open2( nextHeaderSize = GetUi64(header + 20); nextHeaderCRC = GetUi32(header + 28); - p->startPosAfterHeader = k7zStartHeaderSize; + p->startPosAfterHeader = startArcPos + k7zStartHeaderSize; if (CrcCalc(header + 12, 20) != GetUi32(header + 8)) return SZ_ERROR_CRC; @@ -1140,13 +1256,13 @@ static SRes SzArEx_Open2( { Int64 pos = 0; RINOK(inStream->Seek(inStream, &pos, SZ_SEEK_END)); - if ((UInt64)pos < nextHeaderOffset || - (UInt64)pos < k7zStartHeaderSize + nextHeaderOffset || - (UInt64)pos < k7zStartHeaderSize + nextHeaderOffset + nextHeaderSize) + if ((UInt64)pos < startArcPos + nextHeaderOffset || + (UInt64)pos < startArcPos + k7zStartHeaderSize + nextHeaderOffset || + (UInt64)pos < startArcPos + k7zStartHeaderSize + nextHeaderOffset + nextHeaderSize) return SZ_ERROR_INPUT_EOF; } - RINOK(LookInStream_SeekTo(inStream, k7zStartHeaderSize + nextHeaderOffset)); + RINOK(LookInStream_SeekTo(inStream, startArcPos + k7zStartHeaderSize + nextHeaderOffset)); if (!Buf_Create(&buffer, nextHeaderSizeT, allocTemp)) return SZ_ERROR_MEM; @@ -1202,3 +1318,85 @@ SRes SzArEx_Open(CSzArEx *p, ILookInStream *inStream, ISzAlloc *allocMain, ISzAl SzArEx_Free(p, allocMain); return res; } + +SRes SzArEx_Extract( + const CSzArEx *p, + ILookInStream *inStream, + UInt32 fileIndex, + UInt32 *blockIndex, + Byte **outBuffer, + size_t *outBufferSize, + size_t *offset, + size_t *outSizeProcessed, + ISzAlloc *allocMain, + ISzAlloc *allocTemp) +{ + UInt32 folderIndex = p->FileIndexToFolderIndexMap[fileIndex]; + SRes res = SZ_OK; + *offset = 0; + *outSizeProcessed = 0; + if (folderIndex == (UInt32)-1) + { + IAlloc_Free(allocMain, *outBuffer); + *blockIndex = folderIndex; + *outBuffer = 0; + *outBufferSize = 0; + return SZ_OK; + } + + if (*outBuffer == 0 || *blockIndex != folderIndex) + { + CSzFolder *folder = p->db.Folders + folderIndex; + UInt64 unpackSizeSpec = SzFolder_GetUnpackSize(folder); + size_t unpackSize = (size_t)unpackSizeSpec; + UInt64 startOffset = SzArEx_GetFolderStreamPos(p, folderIndex, 0); + + if (unpackSize != unpackSizeSpec) + return SZ_ERROR_MEM; + *blockIndex = folderIndex; + IAlloc_Free(allocMain, *outBuffer); + *outBuffer = 0; + + RINOK(LookInStream_SeekTo(inStream, startOffset)); + + if (res == SZ_OK) + { + *outBufferSize = unpackSize; + if (unpackSize != 0) + { + *outBuffer = (Byte *)IAlloc_Alloc(allocMain, unpackSize); + if (*outBuffer == 0) + res = SZ_ERROR_MEM; + } + if (res == SZ_OK) + { + res = SzFolder_Decode(folder, + p->db.PackSizes + p->FolderStartPackStreamIndex[folderIndex], + inStream, startOffset, + *outBuffer, unpackSize, allocTemp); + if (res == SZ_OK) + { + if (folder->UnpackCRCDefined) + { + if (CrcCalc(*outBuffer, unpackSize) != folder->UnpackCRC) + res = SZ_ERROR_CRC; + } + } + } + } + } + if (res == SZ_OK) + { + UInt32 i; + CSzFileItem *fileItem = p->db.Files + fileIndex; + *offset = 0; + for (i = p->FolderStartFileIndex[folderIndex]; i < fileIndex; i++) + *offset += (UInt32)p->db.Files[i].Size; + *outSizeProcessed = (size_t)fileItem->Size; + if (*offset + *outSizeProcessed > *outBufferSize) + return SZ_ERROR_FAIL; + if (fileItem->CrcDefined && CrcCalc(*outBuffer + *offset, *outSizeProcessed) != fileItem->Crc) + res = SZ_ERROR_CRC; + } + return res; +} diff --git a/lzma/C/7zStream.c b/lzma/C/7zStream.c index a0a2405d0..f0959fb07 100644 --- a/lzma/C/7zStream.c +++ b/lzma/C/7zStream.c @@ -1,5 +1,5 @@ /* 7zStream.c -- 7z Stream functions -2008-11-23 : Igor Pavlov : Public domain */ +2010-03-11 : Igor Pavlov : Public domain */ #include @@ -39,7 +39,7 @@ SRes LookInStream_SeekTo(ILookInStream *stream, UInt64 offset) SRes LookInStream_LookRead(ILookInStream *stream, void *buf, size_t *size) { - void *lookBuf; + const void *lookBuf; if (*size == 0) return SZ_OK; RINOK(stream->Look(stream, &lookBuf, size)); @@ -66,7 +66,7 @@ SRes LookInStream_Read(ILookInStream *stream, void *buf, size_t size) return LookInStream_Read2(stream, buf, size, SZ_ERROR_INPUT_EOF); } -static SRes LookToRead_Look_Lookahead(void *pp, void **buf, size_t *size) +static SRes LookToRead_Look_Lookahead(void *pp, const void **buf, size_t *size) { SRes res = SZ_OK; CLookToRead *p = (CLookToRead *)pp; @@ -84,7 +84,7 @@ static SRes LookToRead_Look_Lookahead(void *pp, void **buf, size_t *size) return res; } -static SRes LookToRead_Look_Exact(void *pp, void **buf, size_t *size) +static SRes LookToRead_Look_Exact(void *pp, const void **buf, size_t *size) { SRes res = SZ_OK; CLookToRead *p = (CLookToRead *)pp; diff --git a/lzma/C/7zVersion.h b/lzma/C/7zVersion.h index 5a6bcadac..d4ac470e2 100644 --- a/lzma/C/7zVersion.h +++ b/lzma/C/7zVersion.h @@ -1,7 +1,7 @@ -#define MY_VER_MAJOR 4 -#define MY_VER_MINOR 65 +#define MY_VER_MAJOR 9 +#define MY_VER_MINOR 20 #define MY_VER_BUILD 0 -#define MY_VERSION "4.65" -#define MY_DATE "2009-02-03" +#define MY_VERSION "9.20" +#define MY_DATE "2010-11-18" #define MY_COPYRIGHT ": Igor Pavlov : Public domain" #define MY_VERSION_COPYRIGHT_DATE MY_VERSION " " MY_COPYRIGHT " : " MY_DATE diff --git a/lzma/C/Alloc.c b/lzma/C/Alloc.c deleted file mode 100644 index bb24a772b..000000000 --- a/lzma/C/Alloc.c +++ /dev/null @@ -1,127 +0,0 @@ -/* Alloc.c -- Memory allocation functions -2008-09-24 -Igor Pavlov -Public domain */ - -#ifdef _WIN32 -#include -#endif -#include - -#include "Alloc.h" - -/* #define _SZ_ALLOC_DEBUG */ - -/* use _SZ_ALLOC_DEBUG to debug alloc/free operations */ -#ifdef _SZ_ALLOC_DEBUG -#include -int g_allocCount = 0; -int g_allocCountMid = 0; -int g_allocCountBig = 0; -#endif - -void *MyAlloc(size_t size) -{ - if (size == 0) - return 0; - #ifdef _SZ_ALLOC_DEBUG - { - void *p = malloc(size); - fprintf(stderr, "\nAlloc %10d bytes, count = %10d, addr = %8X", size, g_allocCount++, (unsigned)p); - return p; - } - #else - return malloc(size); - #endif -} - -void MyFree(void *address) -{ - #ifdef _SZ_ALLOC_DEBUG - if (address != 0) - fprintf(stderr, "\nFree; count = %10d, addr = %8X", --g_allocCount, (unsigned)address); - #endif - free(address); -} - -#ifdef _WIN32 - -void *MidAlloc(size_t size) -{ - if (size == 0) - return 0; - #ifdef _SZ_ALLOC_DEBUG - fprintf(stderr, "\nAlloc_Mid %10d bytes; count = %10d", size, g_allocCountMid++); - #endif - return VirtualAlloc(0, size, MEM_COMMIT, PAGE_READWRITE); -} - -void MidFree(void *address) -{ - #ifdef _SZ_ALLOC_DEBUG - if (address != 0) - fprintf(stderr, "\nFree_Mid; count = %10d", --g_allocCountMid); - #endif - if (address == 0) - return; - VirtualFree(address, 0, MEM_RELEASE); -} - -#ifndef MEM_LARGE_PAGES -#undef _7ZIP_LARGE_PAGES -#endif - -#ifdef _7ZIP_LARGE_PAGES -SIZE_T g_LargePageSize = 0; -typedef SIZE_T (WINAPI *GetLargePageMinimumP)(); -#endif - -void SetLargePageSize() -{ - #ifdef _7ZIP_LARGE_PAGES - SIZE_T size = 0; - GetLargePageMinimumP largePageMinimum = (GetLargePageMinimumP) - GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")), "GetLargePageMinimum"); - if (largePageMinimum == 0) - return; - size = largePageMinimum(); - if (size == 0 || (size & (size - 1)) != 0) - return; - g_LargePageSize = size; - #endif -} - - -void *BigAlloc(size_t size) -{ - if (size == 0) - return 0; - #ifdef _SZ_ALLOC_DEBUG - fprintf(stderr, "\nAlloc_Big %10d bytes; count = %10d", size, g_allocCountBig++); - #endif - - #ifdef _7ZIP_LARGE_PAGES - if (g_LargePageSize != 0 && g_LargePageSize <= (1 << 30) && size >= (1 << 18)) - { - void *res = VirtualAlloc(0, (size + g_LargePageSize - 1) & (~(g_LargePageSize - 1)), - MEM_COMMIT | MEM_LARGE_PAGES, PAGE_READWRITE); - if (res != 0) - return res; - } - #endif - return VirtualAlloc(0, size, MEM_COMMIT, PAGE_READWRITE); -} - -void BigFree(void *address) -{ - #ifdef _SZ_ALLOC_DEBUG - if (address != 0) - fprintf(stderr, "\nFree_Big; count = %10d", --g_allocCountBig); - #endif - - if (address == 0) - return; - VirtualFree(address, 0, MEM_RELEASE); -} - -#endif diff --git a/lzma/C/Alloc.h b/lzma/C/Alloc.h deleted file mode 100644 index a396c6b9e..000000000 --- a/lzma/C/Alloc.h +++ /dev/null @@ -1,32 +0,0 @@ -/* Alloc.h -- Memory allocation functions -2008-03-13 -Igor Pavlov -Public domain */ - -#ifndef __COMMON_ALLOC_H -#define __COMMON_ALLOC_H - -#include - -void *MyAlloc(size_t size); -void MyFree(void *address); - -#ifdef _WIN32 - -void SetLargePageSize(); - -void *MidAlloc(size_t size); -void MidFree(void *address); -void *BigAlloc(size_t size); -void BigFree(void *address); - -#else - -#define MidAlloc(size) MyAlloc(size) -#define MidFree(address) MyFree(address) -#define BigAlloc(size) MyAlloc(size) -#define BigFree(address) MyFree(address) - -#endif - -#endif diff --git a/lzma/C/Archive/7z/7zDecode.c b/lzma/C/Archive/7z/7zDecode.c deleted file mode 100644 index 097d2ea3c..000000000 --- a/lzma/C/Archive/7z/7zDecode.c +++ /dev/null @@ -1,254 +0,0 @@ -/* 7zDecode.c -- Decoding from 7z folder -2008-11-23 : Igor Pavlov : Public domain */ - -#include - -#include "../../Bcj2.h" -#include "../../Bra.h" -#include "../../LzmaDec.h" -#include "7zDecode.h" - -#define k_Copy 0 -#define k_LZMA 0x30101 -#define k_BCJ 0x03030103 -#define k_BCJ2 0x0303011B - -static SRes SzDecodeLzma(CSzCoderInfo *coder, UInt64 inSize, ILookInStream *inStream, - Byte *outBuffer, SizeT outSize, ISzAlloc *allocMain) -{ - CLzmaDec state; - SRes res = SZ_OK; - - LzmaDec_Construct(&state); - RINOK(LzmaDec_AllocateProbs(&state, coder->Props.data, (unsigned)coder->Props.size, allocMain)); - state.dic = outBuffer; - state.dicBufSize = outSize; - LzmaDec_Init(&state); - - for (;;) - { - Byte *inBuf = NULL; - size_t lookahead = (1 << 18); - if (lookahead > inSize) - lookahead = (size_t)inSize; - res = inStream->Look((void *)inStream, (void **)&inBuf, &lookahead); - if (res != SZ_OK) - break; - - { - SizeT inProcessed = (SizeT)lookahead, dicPos = state.dicPos; - ELzmaStatus status; - res = LzmaDec_DecodeToDic(&state, outSize, inBuf, &inProcessed, LZMA_FINISH_END, &status); - lookahead -= inProcessed; - inSize -= inProcessed; - if (res != SZ_OK) - break; - if (state.dicPos == state.dicBufSize || (inProcessed == 0 && dicPos == state.dicPos)) - { - if (state.dicBufSize != outSize || lookahead != 0 || - (status != LZMA_STATUS_FINISHED_WITH_MARK && - status != LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK)) - res = SZ_ERROR_DATA; - break; - } - res = inStream->Skip((void *)inStream, inProcessed); - if (res != SZ_OK) - break; - } - } - - LzmaDec_FreeProbs(&state, allocMain); - return res; -} - -static SRes SzDecodeCopy(UInt64 inSize, ILookInStream *inStream, Byte *outBuffer) -{ - while (inSize > 0) - { - void *inBuf; - size_t curSize = (1 << 18); - if (curSize > inSize) - curSize = (size_t)inSize; - RINOK(inStream->Look((void *)inStream, (void **)&inBuf, &curSize)); - if (curSize == 0) - return SZ_ERROR_INPUT_EOF; - memcpy(outBuffer, inBuf, curSize); - outBuffer += curSize; - inSize -= curSize; - RINOK(inStream->Skip((void *)inStream, curSize)); - } - return SZ_OK; -} - -#define IS_UNSUPPORTED_METHOD(m) ((m) != k_Copy && (m) != k_LZMA) -#define IS_UNSUPPORTED_CODER(c) (IS_UNSUPPORTED_METHOD(c.MethodID) || c.NumInStreams != 1 || c.NumOutStreams != 1) -#define IS_NO_BCJ(c) (c.MethodID != k_BCJ || c.NumInStreams != 1 || c.NumOutStreams != 1) -#define IS_NO_BCJ2(c) (c.MethodID != k_BCJ2 || c.NumInStreams != 4 || c.NumOutStreams != 1) - -SRes CheckSupportedFolder(const CSzFolder *f) -{ - if (f->NumCoders < 1 || f->NumCoders > 4) - return SZ_ERROR_UNSUPPORTED; - if (IS_UNSUPPORTED_CODER(f->Coders[0])) - return SZ_ERROR_UNSUPPORTED; - if (f->NumCoders == 1) - { - if (f->NumPackStreams != 1 || f->PackStreams[0] != 0 || f->NumBindPairs != 0) - return SZ_ERROR_UNSUPPORTED; - return SZ_OK; - } - if (f->NumCoders == 2) - { - if (IS_NO_BCJ(f->Coders[1]) || - f->NumPackStreams != 1 || f->PackStreams[0] != 0 || - f->NumBindPairs != 1 || - f->BindPairs[0].InIndex != 1 || f->BindPairs[0].OutIndex != 0) - return SZ_ERROR_UNSUPPORTED; - return SZ_OK; - } - if (f->NumCoders == 4) - { - if (IS_UNSUPPORTED_CODER(f->Coders[1]) || - IS_UNSUPPORTED_CODER(f->Coders[2]) || - IS_NO_BCJ2(f->Coders[3])) - return SZ_ERROR_UNSUPPORTED; - if (f->NumPackStreams != 4 || - f->PackStreams[0] != 2 || - f->PackStreams[1] != 6 || - f->PackStreams[2] != 1 || - f->PackStreams[3] != 0 || - f->NumBindPairs != 3 || - f->BindPairs[0].InIndex != 5 || f->BindPairs[0].OutIndex != 0 || - f->BindPairs[1].InIndex != 4 || f->BindPairs[1].OutIndex != 1 || - f->BindPairs[2].InIndex != 3 || f->BindPairs[2].OutIndex != 2) - return SZ_ERROR_UNSUPPORTED; - return SZ_OK; - } - return SZ_ERROR_UNSUPPORTED; -} - -UInt64 GetSum(const UInt64 *values, UInt32 index) -{ - UInt64 sum = 0; - UInt32 i; - for (i = 0; i < index; i++) - sum += values[i]; - return sum; -} - -SRes SzDecode2(const UInt64 *packSizes, const CSzFolder *folder, - ILookInStream *inStream, UInt64 startPos, - Byte *outBuffer, SizeT outSize, ISzAlloc *allocMain, - Byte *tempBuf[]) -{ - UInt32 ci; - SizeT tempSizes[3] = { 0, 0, 0}; - SizeT tempSize3 = 0; - Byte *tempBuf3 = 0; - - RINOK(CheckSupportedFolder(folder)); - - for (ci = 0; ci < folder->NumCoders; ci++) - { - CSzCoderInfo *coder = &folder->Coders[ci]; - - if (coder->MethodID == k_Copy || coder->MethodID == k_LZMA) - { - UInt32 si = 0; - UInt64 offset; - UInt64 inSize; - Byte *outBufCur = outBuffer; - SizeT outSizeCur = outSize; - if (folder->NumCoders == 4) - { - UInt32 indices[] = { 3, 2, 0 }; - UInt64 unpackSize = folder->UnpackSizes[ci]; - si = indices[ci]; - if (ci < 2) - { - Byte *temp; - outSizeCur = (SizeT)unpackSize; - if (outSizeCur != unpackSize) - return SZ_ERROR_MEM; - temp = (Byte *)IAlloc_Alloc(allocMain, outSizeCur); - if (temp == 0 && outSizeCur != 0) - return SZ_ERROR_MEM; - outBufCur = tempBuf[1 - ci] = temp; - tempSizes[1 - ci] = outSizeCur; - } - else if (ci == 2) - { - if (unpackSize > outSize) /* check it */ - return SZ_ERROR_PARAM; - tempBuf3 = outBufCur = outBuffer + (outSize - (size_t)unpackSize); - tempSize3 = outSizeCur = (SizeT)unpackSize; - } - else - return SZ_ERROR_UNSUPPORTED; - } - offset = GetSum(packSizes, si); - inSize = packSizes[si]; - RINOK(LookInStream_SeekTo(inStream, startPos + offset)); - - if (coder->MethodID == k_Copy) - { - if (inSize != outSizeCur) /* check it */ - return SZ_ERROR_DATA; - RINOK(SzDecodeCopy(inSize, inStream, outBufCur)); - } - else - { - RINOK(SzDecodeLzma(coder, inSize, inStream, outBufCur, outSizeCur, allocMain)); - } - } - else if (coder->MethodID == k_BCJ) - { - UInt32 state; - if (ci != 1) - return SZ_ERROR_UNSUPPORTED; - x86_Convert_Init(state); - x86_Convert(outBuffer, outSize, 0, &state, 0); - } - else if (coder->MethodID == k_BCJ2) - { - UInt64 offset = GetSum(packSizes, 1); - UInt64 s3Size = packSizes[1]; - SRes res; - if (ci != 3) - return SZ_ERROR_UNSUPPORTED; - RINOK(LookInStream_SeekTo(inStream, startPos + offset)); - tempSizes[2] = (SizeT)s3Size; - if (tempSizes[2] != s3Size) - return SZ_ERROR_MEM; - tempBuf[2] = (Byte *)IAlloc_Alloc(allocMain, tempSizes[2]); - if (tempBuf[2] == 0 && tempSizes[2] != 0) - return SZ_ERROR_MEM; - res = SzDecodeCopy(s3Size, inStream, tempBuf[2]); - RINOK(res) - - res = Bcj2_Decode( - tempBuf3, tempSize3, - tempBuf[0], tempSizes[0], - tempBuf[1], tempSizes[1], - tempBuf[2], tempSizes[2], - outBuffer, outSize); - RINOK(res) - } - else - return SZ_ERROR_UNSUPPORTED; - } - return SZ_OK; -} - -SRes SzDecode(const UInt64 *packSizes, const CSzFolder *folder, - ILookInStream *inStream, UInt64 startPos, - Byte *outBuffer, size_t outSize, ISzAlloc *allocMain) -{ - Byte *tempBuf[3] = { 0, 0, 0}; - int i; - SRes res = SzDecode2(packSizes, folder, inStream, startPos, - outBuffer, (SizeT)outSize, allocMain, tempBuf); - for (i = 0; i < 3; i++) - IAlloc_Free(allocMain, tempBuf[i]); - return res; -} diff --git a/lzma/C/Archive/7z/7zDecode.h b/lzma/C/Archive/7z/7zDecode.h deleted file mode 100644 index 9607915bf..000000000 --- a/lzma/C/Archive/7z/7zDecode.h +++ /dev/null @@ -1,13 +0,0 @@ -/* 7zDecode.h -- Decoding from 7z folder -2008-11-23 : Igor Pavlov : Public domain */ - -#ifndef __7Z_DECODE_H -#define __7Z_DECODE_H - -#include "7zItem.h" - -SRes SzDecode(const UInt64 *packSizes, const CSzFolder *folder, - ILookInStream *stream, UInt64 startPos, - Byte *outBuffer, size_t outSize, ISzAlloc *allocMain); - -#endif diff --git a/lzma/C/Archive/7z/7zExtract.c b/lzma/C/Archive/7z/7zExtract.c deleted file mode 100644 index 0f957add1..000000000 --- a/lzma/C/Archive/7z/7zExtract.c +++ /dev/null @@ -1,93 +0,0 @@ -/* 7zExtract.c -- Extracting from 7z archive -2008-11-23 : Igor Pavlov : Public domain */ - -#include "../../7zCrc.h" -#include "7zDecode.h" -#include "7zExtract.h" - -SRes SzAr_Extract( - const CSzArEx *p, - ILookInStream *inStream, - UInt32 fileIndex, - UInt32 *blockIndex, - Byte **outBuffer, - size_t *outBufferSize, - size_t *offset, - size_t *outSizeProcessed, - ISzAlloc *allocMain, - ISzAlloc *allocTemp) -{ - UInt32 folderIndex = p->FileIndexToFolderIndexMap[fileIndex]; - SRes res = SZ_OK; - *offset = 0; - *outSizeProcessed = 0; - if (folderIndex == (UInt32)-1) - { - IAlloc_Free(allocMain, *outBuffer); - *blockIndex = folderIndex; - *outBuffer = 0; - *outBufferSize = 0; - return SZ_OK; - } - - if (*outBuffer == 0 || *blockIndex != folderIndex) - { - CSzFolder *folder = p->db.Folders + folderIndex; - UInt64 unpackSizeSpec = SzFolder_GetUnpackSize(folder); - size_t unpackSize = (size_t)unpackSizeSpec; - UInt64 startOffset = SzArEx_GetFolderStreamPos(p, folderIndex, 0); - - if (unpackSize != unpackSizeSpec) - return SZ_ERROR_MEM; - *blockIndex = folderIndex; - IAlloc_Free(allocMain, *outBuffer); - *outBuffer = 0; - - RINOK(LookInStream_SeekTo(inStream, startOffset)); - - if (res == SZ_OK) - { - *outBufferSize = unpackSize; - if (unpackSize != 0) - { - *outBuffer = (Byte *)IAlloc_Alloc(allocMain, unpackSize); - if (*outBuffer == 0) - res = SZ_ERROR_MEM; - } - if (res == SZ_OK) - { - res = SzDecode(p->db.PackSizes + - p->FolderStartPackStreamIndex[folderIndex], folder, - inStream, startOffset, - *outBuffer, unpackSize, allocTemp); - if (res == SZ_OK) - { - if (folder->UnpackCRCDefined) - { - if (CrcCalc(*outBuffer, unpackSize) != folder->UnpackCRC) - res = SZ_ERROR_CRC; - } - } - } - } - } - if (res == SZ_OK) - { - UInt32 i; - CSzFileItem *fileItem = p->db.Files + fileIndex; - *offset = 0; - for (i = p->FolderStartFileIndex[folderIndex]; i < fileIndex; i++) - *offset += (UInt32)p->db.Files[i].Size; - *outSizeProcessed = (size_t)fileItem->Size; - if (*offset + *outSizeProcessed > *outBufferSize) - return SZ_ERROR_FAIL; - { - if (fileItem->FileCRCDefined) - { - if (CrcCalc(*outBuffer + *offset, *outSizeProcessed) != fileItem->FileCRC) - res = SZ_ERROR_CRC; - } - } - } - return res; -} diff --git a/lzma/C/Archive/7z/7zExtract.h b/lzma/C/Archive/7z/7zExtract.h deleted file mode 100644 index e171f4ab8..000000000 --- a/lzma/C/Archive/7z/7zExtract.h +++ /dev/null @@ -1,41 +0,0 @@ -/* 7zExtract.h -- Extracting from 7z archive -2008-11-23 : Igor Pavlov : Public domain */ - -#ifndef __7Z_EXTRACT_H -#define __7Z_EXTRACT_H - -#include "7zIn.h" - -/* - SzExtract extracts file from archive - - *outBuffer must be 0 before first call for each new archive. - - Extracting cache: - If you need to decompress more than one file, you can send - these values from previous call: - *blockIndex, - *outBuffer, - *outBufferSize - You can consider "*outBuffer" as cache of solid block. If your archive is solid, - it will increase decompression speed. - - If you use external function, you can declare these 3 cache variables - (blockIndex, outBuffer, outBufferSize) as static in that external function. - - Free *outBuffer and set *outBuffer to 0, if you want to flush cache. -*/ - -SRes SzAr_Extract( - const CSzArEx *db, - ILookInStream *inStream, - UInt32 fileIndex, /* index of file */ - UInt32 *blockIndex, /* index of solid block */ - Byte **outBuffer, /* pointer to pointer to output buffer (allocated with allocMain) */ - size_t *outBufferSize, /* buffer size for output buffer */ - size_t *offset, /* offset of stream for required file in *outBuffer */ - size_t *outSizeProcessed, /* size of file in *outBuffer */ - ISzAlloc *allocMain, - ISzAlloc *allocTemp); - -#endif diff --git a/lzma/C/Archive/7z/7zHeader.c b/lzma/C/Archive/7z/7zHeader.c deleted file mode 100644 index c44ff4a48..000000000 --- a/lzma/C/Archive/7z/7zHeader.c +++ /dev/null @@ -1,6 +0,0 @@ -/* 7zHeader.c -- 7z Headers -2008-10-04 : Igor Pavlov : Public domain */ - -#include "7zHeader.h" - -Byte k7zSignature[k7zSignatureSize] = {'7', 'z', 0xBC, 0xAF, 0x27, 0x1C}; diff --git a/lzma/C/Archive/7z/7zHeader.h b/lzma/C/Archive/7z/7zHeader.h deleted file mode 100644 index 1ef8c0196..000000000 --- a/lzma/C/Archive/7z/7zHeader.h +++ /dev/null @@ -1,57 +0,0 @@ -/* 7zHeader.h -- 7z Headers -2008-10-04 : Igor Pavlov : Public domain */ - -#ifndef __7Z_HEADER_H -#define __7Z_HEADER_H - -#include "../../Types.h" - -#define k7zSignatureSize 6 -extern Byte k7zSignature[k7zSignatureSize]; - -#define k7zMajorVersion 0 - -#define k7zStartHeaderSize 0x20 - -enum EIdEnum -{ - k7zIdEnd, - - k7zIdHeader, - - k7zIdArchiveProperties, - - k7zIdAdditionalStreamsInfo, - k7zIdMainStreamsInfo, - k7zIdFilesInfo, - - k7zIdPackInfo, - k7zIdUnpackInfo, - k7zIdSubStreamsInfo, - - k7zIdSize, - k7zIdCRC, - - k7zIdFolder, - - k7zIdCodersUnpackSize, - k7zIdNumUnpackStream, - - k7zIdEmptyStream, - k7zIdEmptyFile, - k7zIdAnti, - - k7zIdName, - k7zIdCTime, - k7zIdATime, - k7zIdMTime, - k7zIdWinAttributes, - k7zIdComment, - - k7zIdEncodedHeader, - - k7zIdStartPos, - k7zIdDummy -}; - -#endif diff --git a/lzma/C/Archive/7z/7zIn.h b/lzma/C/Archive/7z/7zIn.h deleted file mode 100644 index 717fe52c9..000000000 --- a/lzma/C/Archive/7z/7zIn.h +++ /dev/null @@ -1,41 +0,0 @@ -/* 7zIn.h -- 7z Input functions -2008-11-23 : Igor Pavlov : Public domain */ - -#ifndef __7Z_IN_H -#define __7Z_IN_H - -#include "7zHeader.h" -#include "7zItem.h" - -typedef struct -{ - CSzAr db; - - UInt64 startPosAfterHeader; - UInt64 dataPos; - - UInt32 *FolderStartPackStreamIndex; - UInt64 *PackStreamStartPositions; - UInt32 *FolderStartFileIndex; - UInt32 *FileIndexToFolderIndexMap; -} CSzArEx; - -void SzArEx_Init(CSzArEx *p); -void SzArEx_Free(CSzArEx *p, ISzAlloc *alloc); -UInt64 SzArEx_GetFolderStreamPos(const CSzArEx *p, UInt32 folderIndex, UInt32 indexInFolder); -int SzArEx_GetFolderFullPackSize(const CSzArEx *p, UInt32 folderIndex, UInt64 *resSize); - -/* -Errors: -SZ_ERROR_NO_ARCHIVE -SZ_ERROR_ARCHIVE -SZ_ERROR_UNSUPPORTED -SZ_ERROR_MEM -SZ_ERROR_CRC -SZ_ERROR_INPUT_EOF -SZ_ERROR_FAIL -*/ - -SRes SzArEx_Open(CSzArEx *p, ILookInStream *inStream, ISzAlloc *allocMain, ISzAlloc *allocTemp); - -#endif diff --git a/lzma/C/Archive/7z/7zItem.c b/lzma/C/Archive/7z/7zItem.c deleted file mode 100644 index a11d5008f..000000000 --- a/lzma/C/Archive/7z/7zItem.c +++ /dev/null @@ -1,127 +0,0 @@ -/* 7zItem.c -- 7z Items -2008-10-04 : Igor Pavlov : Public domain */ - -#include "7zItem.h" - -void SzCoderInfo_Init(CSzCoderInfo *p) -{ - Buf_Init(&p->Props); -} - -void SzCoderInfo_Free(CSzCoderInfo *p, ISzAlloc *alloc) -{ - Buf_Free(&p->Props, alloc); - SzCoderInfo_Init(p); -} - -void SzFolder_Init(CSzFolder *p) -{ - p->Coders = 0; - p->BindPairs = 0; - p->PackStreams = 0; - p->UnpackSizes = 0; - p->NumCoders = 0; - p->NumBindPairs = 0; - p->NumPackStreams = 0; - p->UnpackCRCDefined = 0; - p->UnpackCRC = 0; - p->NumUnpackStreams = 0; -} - -void SzFolder_Free(CSzFolder *p, ISzAlloc *alloc) -{ - UInt32 i; - if (p->Coders) - for (i = 0; i < p->NumCoders; i++) - SzCoderInfo_Free(&p->Coders[i], alloc); - IAlloc_Free(alloc, p->Coders); - IAlloc_Free(alloc, p->BindPairs); - IAlloc_Free(alloc, p->PackStreams); - IAlloc_Free(alloc, p->UnpackSizes); - SzFolder_Init(p); -} - -UInt32 SzFolder_GetNumOutStreams(CSzFolder *p) -{ - UInt32 result = 0; - UInt32 i; - for (i = 0; i < p->NumCoders; i++) - result += p->Coders[i].NumOutStreams; - return result; -} - -int SzFolder_FindBindPairForInStream(CSzFolder *p, UInt32 inStreamIndex) -{ - UInt32 i; - for (i = 0; i < p->NumBindPairs; i++) - if (p->BindPairs[i].InIndex == inStreamIndex) - return i; - return -1; -} - - -int SzFolder_FindBindPairForOutStream(CSzFolder *p, UInt32 outStreamIndex) -{ - UInt32 i; - for (i = 0; i < p->NumBindPairs; i++) - if (p->BindPairs[i].OutIndex == outStreamIndex) - return i; - return -1; -} - -UInt64 SzFolder_GetUnpackSize(CSzFolder *p) -{ - int i = (int)SzFolder_GetNumOutStreams(p); - if (i == 0) - return 0; - for (i--; i >= 0; i--) - if (SzFolder_FindBindPairForOutStream(p, i) < 0) - return p->UnpackSizes[i]; - /* throw 1; */ - return 0; -} - -void SzFile_Init(CSzFileItem *p) -{ - p->HasStream = 1; - p->IsDir = 0; - p->IsAnti = 0; - p->FileCRCDefined = 0; - p->MTimeDefined = 0; - p->Name = 0; -} - -static void SzFile_Free(CSzFileItem *p, ISzAlloc *alloc) -{ - IAlloc_Free(alloc, p->Name); - SzFile_Init(p); -} - -void SzAr_Init(CSzAr *p) -{ - p->PackSizes = 0; - p->PackCRCsDefined = 0; - p->PackCRCs = 0; - p->Folders = 0; - p->Files = 0; - p->NumPackStreams = 0; - p->NumFolders = 0; - p->NumFiles = 0; -} - -void SzAr_Free(CSzAr *p, ISzAlloc *alloc) -{ - UInt32 i; - if (p->Folders) - for (i = 0; i < p->NumFolders; i++) - SzFolder_Free(&p->Folders[i], alloc); - if (p->Files) - for (i = 0; i < p->NumFiles; i++) - SzFile_Free(&p->Files[i], alloc); - IAlloc_Free(alloc, p->PackSizes); - IAlloc_Free(alloc, p->PackCRCsDefined); - IAlloc_Free(alloc, p->PackCRCs); - IAlloc_Free(alloc, p->Folders); - IAlloc_Free(alloc, p->Files); - SzAr_Init(p); -} diff --git a/lzma/C/Archive/7z/7zItem.h b/lzma/C/Archive/7z/7zItem.h deleted file mode 100644 index 190b2e2a9..000000000 --- a/lzma/C/Archive/7z/7zItem.h +++ /dev/null @@ -1,84 +0,0 @@ -/* 7zItem.h -- 7z Items -2008-10-04 : Igor Pavlov : Public domain */ - -#ifndef __7Z_ITEM_H -#define __7Z_ITEM_H - -#include "../../7zBuf.h" - -typedef struct -{ - UInt32 NumInStreams; - UInt32 NumOutStreams; - UInt64 MethodID; - CBuf Props; -} CSzCoderInfo; - -void SzCoderInfo_Init(CSzCoderInfo *p); -void SzCoderInfo_Free(CSzCoderInfo *p, ISzAlloc *alloc); - -typedef struct -{ - UInt32 InIndex; - UInt32 OutIndex; -} CBindPair; - -typedef struct -{ - CSzCoderInfo *Coders; - CBindPair *BindPairs; - UInt32 *PackStreams; - UInt64 *UnpackSizes; - UInt32 NumCoders; - UInt32 NumBindPairs; - UInt32 NumPackStreams; - int UnpackCRCDefined; - UInt32 UnpackCRC; - - UInt32 NumUnpackStreams; -} CSzFolder; - -void SzFolder_Init(CSzFolder *p); -UInt64 SzFolder_GetUnpackSize(CSzFolder *p); -int SzFolder_FindBindPairForInStream(CSzFolder *p, UInt32 inStreamIndex); -UInt32 SzFolder_GetNumOutStreams(CSzFolder *p); -UInt64 SzFolder_GetUnpackSize(CSzFolder *p); - -typedef struct CNtfsFileTime -{ - UInt32 Low; - UInt32 High; -} CNtfsFileTime; - -typedef struct CSzFileItem -{ - CNtfsFileTime MTime; - UInt64 Size; - char *Name; - UInt32 FileCRC; - - Byte HasStream; - Byte IsDir; - Byte IsAnti; - Byte FileCRCDefined; - Byte MTimeDefined; -} CSzFileItem; - -void SzFile_Init(CSzFileItem *p); - -typedef struct CSzAr -{ - UInt64 *PackSizes; - Byte *PackCRCsDefined; - UInt32 *PackCRCs; - CSzFolder *Folders; - CSzFileItem *Files; - UInt32 NumPackStreams; - UInt32 NumFolders; - UInt32 NumFiles; -} CSzAr; - -void SzAr_Init(CSzAr *p); -void SzAr_Free(CSzAr *p, ISzAlloc *alloc); - -#endif diff --git a/lzma/C/Bcj2.h b/lzma/C/Bcj2.h index f58e3bcb4..d9d857bc3 100644 --- a/lzma/C/Bcj2.h +++ b/lzma/C/Bcj2.h @@ -1,11 +1,15 @@ /* Bcj2.h -- Converter for x86 code (BCJ2) -2008-10-04 : Igor Pavlov : Public domain */ +2009-02-07 : Igor Pavlov : Public domain */ #ifndef __BCJ2_H #define __BCJ2_H #include "Types.h" +#ifdef __cplusplus +extern "C" { +#endif + /* Conditions: outSize <= FullOutputSize, @@ -27,4 +31,8 @@ int Bcj2_Decode( const Byte *buf3, SizeT size3, Byte *outBuf, SizeT outSize); +#ifdef __cplusplus +} +#endif + #endif diff --git a/lzma/C/Bra.c b/lzma/C/Bra.c new file mode 100644 index 000000000..2a0f147b2 --- /dev/null +++ b/lzma/C/Bra.c @@ -0,0 +1,133 @@ +/* Bra.c -- Converters for RISC code +2010-04-16 : Igor Pavlov : Public domain */ + +#include "Bra.h" + +SizeT ARM_Convert(Byte *data, SizeT size, UInt32 ip, int encoding) +{ + SizeT i; + if (size < 4) + return 0; + size -= 4; + ip += 8; + for (i = 0; i <= size; i += 4) + { + if (data[i + 3] == 0xEB) + { + UInt32 dest; + UInt32 src = ((UInt32)data[i + 2] << 16) | ((UInt32)data[i + 1] << 8) | (data[i + 0]); + src <<= 2; + if (encoding) + dest = ip + (UInt32)i + src; + else + dest = src - (ip + (UInt32)i); + dest >>= 2; + data[i + 2] = (Byte)(dest >> 16); + data[i + 1] = (Byte)(dest >> 8); + data[i + 0] = (Byte)dest; + } + } + return i; +} + +SizeT ARMT_Convert(Byte *data, SizeT size, UInt32 ip, int encoding) +{ + SizeT i; + if (size < 4) + return 0; + size -= 4; + ip += 4; + for (i = 0; i <= size; i += 2) + { + if ((data[i + 1] & 0xF8) == 0xF0 && + (data[i + 3] & 0xF8) == 0xF8) + { + UInt32 dest; + UInt32 src = + (((UInt32)data[i + 1] & 0x7) << 19) | + ((UInt32)data[i + 0] << 11) | + (((UInt32)data[i + 3] & 0x7) << 8) | + (data[i + 2]); + + src <<= 1; + if (encoding) + dest = ip + (UInt32)i + src; + else + dest = src - (ip + (UInt32)i); + dest >>= 1; + + data[i + 1] = (Byte)(0xF0 | ((dest >> 19) & 0x7)); + data[i + 0] = (Byte)(dest >> 11); + data[i + 3] = (Byte)(0xF8 | ((dest >> 8) & 0x7)); + data[i + 2] = (Byte)dest; + i += 2; + } + } + return i; +} + +SizeT PPC_Convert(Byte *data, SizeT size, UInt32 ip, int encoding) +{ + SizeT i; + if (size < 4) + return 0; + size -= 4; + for (i = 0; i <= size; i += 4) + { + if ((data[i] >> 2) == 0x12 && (data[i + 3] & 3) == 1) + { + UInt32 src = ((UInt32)(data[i + 0] & 3) << 24) | + ((UInt32)data[i + 1] << 16) | + ((UInt32)data[i + 2] << 8) | + ((UInt32)data[i + 3] & (~3)); + + UInt32 dest; + if (encoding) + dest = ip + (UInt32)i + src; + else + dest = src - (ip + (UInt32)i); + data[i + 0] = (Byte)(0x48 | ((dest >> 24) & 0x3)); + data[i + 1] = (Byte)(dest >> 16); + data[i + 2] = (Byte)(dest >> 8); + data[i + 3] &= 0x3; + data[i + 3] |= dest; + } + } + return i; +} + +SizeT SPARC_Convert(Byte *data, SizeT size, UInt32 ip, int encoding) +{ + UInt32 i; + if (size < 4) + return 0; + size -= 4; + for (i = 0; i <= size; i += 4) + { + if ((data[i] == 0x40 && (data[i + 1] & 0xC0) == 0x00) || + (data[i] == 0x7F && (data[i + 1] & 0xC0) == 0xC0)) + { + UInt32 src = + ((UInt32)data[i + 0] << 24) | + ((UInt32)data[i + 1] << 16) | + ((UInt32)data[i + 2] << 8) | + ((UInt32)data[i + 3]); + UInt32 dest; + + src <<= 2; + if (encoding) + dest = ip + i + src; + else + dest = src - (ip + i); + dest >>= 2; + + dest = (((0 - ((dest >> 22) & 1)) << 22) & 0x3FFFFFFF) | (dest & 0x3FFFFF) | 0x40000000; + + data[i + 0] = (Byte)(dest >> 24); + data[i + 1] = (Byte)(dest >> 16); + data[i + 2] = (Byte)(dest >> 8); + data[i + 3] = (Byte)dest; + } + } + return i; +} diff --git a/lzma/C/Bra.h b/lzma/C/Bra.h index b9018eb99..9c91e332d 100644 --- a/lzma/C/Bra.h +++ b/lzma/C/Bra.h @@ -1,11 +1,15 @@ /* Bra.h -- Branch converters for executables -2008-10-04 : Igor Pavlov : Public domain */ +2009-02-07 : Igor Pavlov : Public domain */ #ifndef __BRA_H #define __BRA_H #include "Types.h" +#ifdef __cplusplus +extern "C" { +#endif + /* These functions convert relative addresses to absolute addresses in CALL instructions to increase the compression ratio. @@ -57,4 +61,8 @@ SizeT PPC_Convert(Byte *data, SizeT size, UInt32 ip, int encoding); SizeT SPARC_Convert(Byte *data, SizeT size, UInt32 ip, int encoding); SizeT IA64_Convert(Byte *data, SizeT size, UInt32 ip, int encoding); +#ifdef __cplusplus +} +#endif + #endif diff --git a/lzma/C/CpuArch.c b/lzma/C/CpuArch.c new file mode 100644 index 000000000..925edbeb8 --- /dev/null +++ b/lzma/C/CpuArch.c @@ -0,0 +1,188 @@ +/* CpuArch.c -- CPU specific code +2010-10-26: Igor Pavlov : Public domain */ + +#include "CpuArch.h" + +#ifdef _WIN32 +#include +#endif + +#ifdef MY_CPU_X86_OR_AMD64 + +#if (defined(_MSC_VER) && !defined(MY_CPU_AMD64)) || defined(__GNUC__) +#define USE_ASM +#endif + +#if defined(USE_ASM) && !defined(MY_CPU_AMD64) +static UInt32 CheckFlag(UInt32 flag) +{ + #ifdef _MSC_VER + __asm pushfd; + __asm pop EAX; + __asm mov EDX, EAX; + __asm xor EAX, flag; + __asm push EAX; + __asm popfd; + __asm pushfd; + __asm pop EAX; + __asm xor EAX, EDX; + __asm push EDX; + __asm popfd; + __asm and flag, EAX; + #else + __asm__ __volatile__ ( + "pushf\n\t" + "pop %%EAX\n\t" + "movl %%EAX,%%EDX\n\t" + "xorl %0,%%EAX\n\t" + "push %%EAX\n\t" + "popf\n\t" + "pushf\n\t" + "pop %%EAX\n\t" + "xorl %%EDX,%%EAX\n\t" + "push %%EDX\n\t" + "popf\n\t" + "andl %%EAX, %0\n\t": + "=c" (flag) : "c" (flag)); + #endif + return flag; +} +#define CHECK_CPUID_IS_SUPPORTED if (CheckFlag(1 << 18) == 0 || CheckFlag(1 << 21) == 0) return False; +#else +#define CHECK_CPUID_IS_SUPPORTED +#endif + +static void MyCPUID(UInt32 function, UInt32 *a, UInt32 *b, UInt32 *c, UInt32 *d) +{ + #ifdef USE_ASM + + #ifdef _MSC_VER + + UInt32 a2, b2, c2, d2; + __asm xor EBX, EBX; + __asm xor ECX, ECX; + __asm xor EDX, EDX; + __asm mov EAX, function; + __asm cpuid; + __asm mov a2, EAX; + __asm mov b2, EBX; + __asm mov c2, ECX; + __asm mov d2, EDX; + + *a = a2; + *b = b2; + *c = c2; + *d = d2; + + #elif __PIC__ + + /* GCC or Clang WITH position-independent code generation */ + + __asm__ __volatile__ ( + "xchgl %%ebx, %1\n" + "cpuid\n" + "xchgl %%ebx, %1\n" + : "=a" (*a) , + "=r" (*b) , + "=c" (*c) , + "=d" (*d) + : "0" (function)) ; + + #else + + /* GCC or Clang WITHOUT position-independent code generation */ + + __asm__ __volatile__ ( + "cpuid" + : "=a" (*a) , + "=b" (*b) , + "=c" (*c) , + "=d" (*d) + : "0" (function)) ; + + #endif + + #else + + int CPUInfo[4]; + __cpuid(CPUInfo, function); + *a = CPUInfo[0]; + *b = CPUInfo[1]; + *c = CPUInfo[2]; + *d = CPUInfo[3]; + + #endif +} + +Bool x86cpuid_CheckAndRead(Cx86cpuid *p) +{ + CHECK_CPUID_IS_SUPPORTED + MyCPUID(0, &p->maxFunc, &p->vendor[0], &p->vendor[2], &p->vendor[1]); + MyCPUID(1, &p->ver, &p->b, &p->c, &p->d); + return True; +} + +static UInt32 kVendors[][3] = +{ + { 0x756E6547, 0x49656E69, 0x6C65746E}, + { 0x68747541, 0x69746E65, 0x444D4163}, + { 0x746E6543, 0x48727561, 0x736C7561} +}; + +int x86cpuid_GetFirm(const Cx86cpuid *p) +{ + unsigned i; + for (i = 0; i < sizeof(kVendors) / sizeof(kVendors[i]); i++) + { + const UInt32 *v = kVendors[i]; + if (v[0] == p->vendor[0] && + v[1] == p->vendor[1] && + v[2] == p->vendor[2]) + return (int)i; + } + return -1; +} + +Bool CPU_Is_InOrder() +{ + Cx86cpuid p; + int firm; + UInt32 family, model; + if (!x86cpuid_CheckAndRead(&p)) + return True; + family = x86cpuid_GetFamily(&p); + model = x86cpuid_GetModel(&p); + firm = x86cpuid_GetFirm(&p); + switch (firm) + { + case CPU_FIRM_INTEL: return (family < 6 || (family == 6 && model == 0x100C)); + case CPU_FIRM_AMD: return (family < 5 || (family == 5 && (model < 6 || model == 0xA))); + case CPU_FIRM_VIA: return (family < 6 || (family == 6 && model < 0xF)); + } + return True; +} + +#if !defined(MY_CPU_AMD64) && defined(_WIN32) +static Bool CPU_Sys_Is_SSE_Supported() +{ + OSVERSIONINFO vi; + vi.dwOSVersionInfoSize = sizeof(vi); + if (!GetVersionEx(&vi)) + return False; + return (vi.dwMajorVersion >= 5); +} +#define CHECK_SYS_SSE_SUPPORT if (!CPU_Sys_Is_SSE_Supported()) return False; +#else +#define CHECK_SYS_SSE_SUPPORT +#endif + +Bool CPU_Is_Aes_Supported() +{ + Cx86cpuid p; + CHECK_SYS_SSE_SUPPORT + if (!x86cpuid_CheckAndRead(&p)) + return False; + return (p.c >> 25) & 1; +} + +#endif diff --git a/lzma/C/CpuArch.h b/lzma/C/CpuArch.h index db441641b..0a709bb26 100644 --- a/lzma/C/CpuArch.h +++ b/lzma/C/CpuArch.h @@ -1,29 +1,73 @@ -/* CpuArch.h -2008-08-05 -Igor Pavlov -Public domain */ +/* CpuArch.h -- CPU specific code +2010-10-26: Igor Pavlov : Public domain */ -#ifndef __CPUARCH_H -#define __CPUARCH_H +#ifndef __CPU_ARCH_H +#define __CPU_ARCH_H + +#include "Types.h" + +EXTERN_C_BEGIN /* -LITTLE_ENDIAN_UNALIGN means: - 1) CPU is LITTLE_ENDIAN - 2) it's allowed to make unaligned memory accesses -if LITTLE_ENDIAN_UNALIGN is not defined, it means that we don't know -about these properties of platform. +MY_CPU_LE means that CPU is LITTLE ENDIAN. +If MY_CPU_LE is not defined, we don't know about that property of platform (it can be LITTLE ENDIAN). + +MY_CPU_LE_UNALIGN means that CPU is LITTLE ENDIAN and CPU supports unaligned memory accesses. +If MY_CPU_LE_UNALIGN is not defined, we don't know about these properties of platform. */ -#if defined(_M_IX86) || defined(_M_X64) || defined(_M_AMD64) || defined(__i386__) || defined(__x86_64__) -#define LITTLE_ENDIAN_UNALIGN +#if defined(_M_X64) || defined(_M_AMD64) || defined(__x86_64__) +#define MY_CPU_AMD64 #endif -#ifdef LITTLE_ENDIAN_UNALIGN +#if defined(MY_CPU_AMD64) || defined(_M_IA64) +#define MY_CPU_64BIT +#endif + +#if defined(_M_IX86) || defined(__i386__) +#define MY_CPU_X86 +#endif + +#if defined(MY_CPU_X86) || defined(MY_CPU_AMD64) +#define MY_CPU_X86_OR_AMD64 +#endif + +#if defined(MY_CPU_X86) || defined(_M_ARM) +#define MY_CPU_32BIT +#endif + +#if defined(_WIN32) && defined(_M_ARM) +#define MY_CPU_ARM_LE +#endif + +#if defined(_WIN32) && defined(_M_IA64) +#define MY_CPU_IA64_LE +#endif + +#if defined(MY_CPU_X86_OR_AMD64) +#define MY_CPU_LE_UNALIGN +#endif + +#if defined(MY_CPU_X86_OR_AMD64) || defined(MY_CPU_ARM_LE) || defined(MY_CPU_IA64_LE) || defined(__ARMEL__) || defined(__MIPSEL__) || defined(__LITTLE_ENDIAN__) +#define MY_CPU_LE +#endif + +#if defined(__BIG_ENDIAN__) +#define MY_CPU_BE +#endif + +#if defined(MY_CPU_LE) && defined(MY_CPU_BE) +Stop_Compiling_Bad_Endian +#endif + +#ifdef MY_CPU_LE_UNALIGN #define GetUi16(p) (*(const UInt16 *)(p)) #define GetUi32(p) (*(const UInt32 *)(p)) #define GetUi64(p) (*(const UInt64 *)(p)) +#define SetUi16(p, d) *(UInt16 *)(p) = (d); #define SetUi32(p, d) *(UInt32 *)(p) = (d); +#define SetUi64(p, d) *(UInt64 *)(p) = (d); #else @@ -37,18 +81,24 @@ about these properties of platform. #define GetUi64(p) (GetUi32(p) | ((UInt64)GetUi32(((const Byte *)(p)) + 4) << 32)) +#define SetUi16(p, d) { UInt32 _x_ = (d); \ + ((Byte *)(p))[0] = (Byte)_x_; \ + ((Byte *)(p))[1] = (Byte)(_x_ >> 8); } + #define SetUi32(p, d) { UInt32 _x_ = (d); \ ((Byte *)(p))[0] = (Byte)_x_; \ ((Byte *)(p))[1] = (Byte)(_x_ >> 8); \ ((Byte *)(p))[2] = (Byte)(_x_ >> 16); \ ((Byte *)(p))[3] = (Byte)(_x_ >> 24); } +#define SetUi64(p, d) { UInt64 _x64_ = (d); \ + SetUi32(p, (UInt32)_x64_); \ + SetUi32(((Byte *)(p)) + 4, (UInt32)(_x64_ >> 32)); } + #endif -#if defined(LITTLE_ENDIAN_UNALIGN) && defined(_WIN64) && (_MSC_VER >= 1300) +#if defined(MY_CPU_LE_UNALIGN) && defined(_WIN64) && (_MSC_VER >= 1300) -unsigned long _byteswap_ulong(unsigned long); -unsigned __int64 _byteswap_uint64(unsigned __int64); #pragma intrinsic(_byteswap_ulong) #pragma intrinsic(_byteswap_uint64) #define GetBe32(p) _byteswap_ulong(*(const UInt32 *)(const Byte *)(p)) @@ -68,4 +118,38 @@ unsigned __int64 _byteswap_uint64(unsigned __int64); #define GetBe16(p) (((UInt16)((const Byte *)(p))[0] << 8) | ((const Byte *)(p))[1]) + +#ifdef MY_CPU_X86_OR_AMD64 + +typedef struct +{ + UInt32 maxFunc; + UInt32 vendor[3]; + UInt32 ver; + UInt32 b; + UInt32 c; + UInt32 d; +} Cx86cpuid; + +enum +{ + CPU_FIRM_INTEL, + CPU_FIRM_AMD, + CPU_FIRM_VIA +}; + +Bool x86cpuid_CheckAndRead(Cx86cpuid *p); +int x86cpuid_GetFirm(const Cx86cpuid *p); + +#define x86cpuid_GetFamily(p) (((p)->ver >> 8) & 0xFF00F) +#define x86cpuid_GetModel(p) (((p)->ver >> 4) & 0xF00F) +#define x86cpuid_GetStepping(p) ((p)->ver & 0xF) + +Bool CPU_Is_InOrder(); +Bool CPU_Is_Aes_Supported(); + +#endif + +EXTERN_C_END + #endif diff --git a/lzma/C/LzFind.c b/lzma/C/LzFind.c index e0ebe6235..f6c9e66d5 100644 --- a/lzma/C/LzFind.c +++ b/lzma/C/LzFind.c @@ -1,5 +1,5 @@ /* LzFind.c -- Match finder for LZ algorithms -2008-10-04 : Igor Pavlov : Public domain */ +2009-04-22 : Igor Pavlov : Public domain */ #include @@ -58,6 +58,17 @@ static void MatchFinder_ReadBlock(CMatchFinder *p) { if (p->streamEndWasReached || p->result != SZ_OK) return; + if (p->directInput) + { + UInt32 curSize = 0xFFFFFFFF - p->streamPos; + if (curSize > p->directInputRem) + curSize = (UInt32)p->directInputRem; + p->directInputRem -= curSize; + p->streamPos += curSize; + if (p->directInputRem == 0) + p->streamEndWasReached = 1; + return; + } for (;;) { Byte *dest = p->buffer + (p->streamPos - p->pos); @@ -88,6 +99,8 @@ void MatchFinder_MoveBlock(CMatchFinder *p) int MatchFinder_NeedMove(CMatchFinder *p) { + if (p->directInput) + return 0; /* if (p->streamEndWasReached) return 0; */ return ((size_t)(p->bufferBase + p->blockSize - p->buffer) <= p->keepSizeAfter); } @@ -112,8 +125,6 @@ static void MatchFinder_SetDefaultSettings(CMatchFinder *p) p->cutValue = 32; p->btMode = 1; p->numHashBytes = 4; - /* p->skipModeBits = 0; */ - p->directInput = 0; p->bigHash = 0; } @@ -177,7 +188,7 @@ int MatchFinder_Create(CMatchFinder *p, UInt32 historySize, /* we need one additional byte, since we use MoveBlock after pos++ and before dictionary using */ if (LzInWindow_Create(p, sizeReserv, alloc)) { - UInt32 newCyclicBufferSize = (historySize /* >> p->skipModeBits */) + 1; + UInt32 newCyclicBufferSize = historySize + 1; UInt32 hs; p->matchMaxLen = matchMaxLen; { @@ -192,7 +203,6 @@ int MatchFinder_Create(CMatchFinder *p, UInt32 historySize, hs |= (hs >> 4); hs |= (hs >> 8); hs >>= 1; - /* hs >>= p->skipModeBits; */ hs |= 0xFFFF; /* don't change it! It's required for Deflate */ if (hs > (1 << 24)) { diff --git a/lzma/C/LzFind.h b/lzma/C/LzFind.h index 423d67e0c..7ebdfa446 100644 --- a/lzma/C/LzFind.h +++ b/lzma/C/LzFind.h @@ -1,11 +1,15 @@ /* LzFind.h -- Match finder for LZ algorithms -2008-10-04 : Igor Pavlov : Public domain */ +2009-04-22 : Igor Pavlov : Public domain */ -#ifndef __LZFIND_H -#define __LZFIND_H +#ifndef __LZ_FIND_H +#define __LZ_FIND_H #include "Types.h" +#ifdef __cplusplus +extern "C" { +#endif + typedef UInt32 CLzRef; typedef struct _CMatchFinder @@ -35,8 +39,8 @@ typedef struct _CMatchFinder UInt32 numHashBytes; int directInput; + size_t directInputRem; int btMode; - /* int skipModeBits; */ int bigHash; UInt32 historySize; UInt32 fixedHashSize; @@ -104,4 +108,8 @@ UInt32 Hc3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances); void Bt3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num); void Hc3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num); +#ifdef __cplusplus +} +#endif + #endif diff --git a/lzma/C/LzFindMt.c b/lzma/C/LzFindMt.c index a67899ab0..db95590c3 100644 --- a/lzma/C/LzFindMt.c +++ b/lzma/C/LzFindMt.c @@ -1,5 +1,5 @@ /* LzFindMt.c -- multithreaded Match finder for LZ algorithms -2008-10-04 : Igor Pavlov : Public domain */ +2009-09-20 : Igor Pavlov : Public domain */ #include "LzHash.h" @@ -97,7 +97,7 @@ void MtSync_Destruct(CMtSync *p) #define RINOK_THREAD(x) { if ((x) != 0) return SZ_ERROR_THREAD; } -static SRes MtSync_Create2(CMtSync *p, unsigned (THREAD_FUNC_CALL_TYPE *startAddress)(void *), void *obj, UInt32 numBlocks) +static SRes MtSync_Create2(CMtSync *p, unsigned (MY_STD_CALL *startAddress)(void *), void *obj, UInt32 numBlocks) { if (p->wasCreated) return SZ_OK; @@ -119,7 +119,7 @@ static SRes MtSync_Create2(CMtSync *p, unsigned (THREAD_FUNC_CALL_TYPE *startAdd return SZ_OK; } -static SRes MtSync_Create(CMtSync *p, unsigned (THREAD_FUNC_CALL_TYPE *startAddress)(void *), void *obj, UInt32 numBlocks) +static SRes MtSync_Create(CMtSync *p, unsigned (MY_STD_CALL *startAddress)(void *), void *obj, UInt32 numBlocks) { SRes res = MtSync_Create2(p, startAddress, obj, numBlocks); if (res != SZ_OK) @@ -143,7 +143,7 @@ DEF_GetHeads2(2, (p[0] | ((UInt32)p[1] << 8)), hashMask = hashMask; crc = crc; DEF_GetHeads(3, (crc[p[0]] ^ p[1] ^ ((UInt32)p[2] << 8)) & hashMask) DEF_GetHeads(4, (crc[p[0]] ^ p[1] ^ ((UInt32)p[2] << 8) ^ (crc[p[3]] << 5)) & hashMask) DEF_GetHeads(4b, (crc[p[0]] ^ p[1] ^ ((UInt32)p[2] << 8) ^ ((UInt32)p[3] << 16)) & hashMask) -DEF_GetHeads(5, (crc[p[0]] ^ p[1] ^ ((UInt32)p[2] << 8) ^ (crc[p[3]] << 5) ^ (crc[p[4]] << 3)) & hashMask) +/* DEF_GetHeads(5, (crc[p[0]] ^ p[1] ^ ((UInt32)p[2] << 8) ^ (crc[p[3]] << 5) ^ (crc[p[4]] << 3)) & hashMask) */ void HashThreadFunc(CMatchFinderMt *mt) { @@ -451,8 +451,8 @@ void MatchFinderMt_Destruct(CMatchFinderMt *p, ISzAlloc *alloc) #define kHashBufferSize (kMtHashBlockSize * kMtHashNumBlocks) #define kBtBufferSize (kMtBtBlockSize * kMtBtNumBlocks) -static unsigned THREAD_FUNC_CALL_TYPE HashThreadFunc2(void *p) { HashThreadFunc((CMatchFinderMt *)p); return 0; } -static unsigned THREAD_FUNC_CALL_TYPE BtThreadFunc2(void *p) +static unsigned MY_STD_CALL HashThreadFunc2(void *p) { HashThreadFunc((CMatchFinderMt *)p); return 0; } +static unsigned MY_STD_CALL BtThreadFunc2(void *p) { Byte allocaDummy[0x180]; int i = 0; @@ -711,47 +711,47 @@ UInt32 MatchFinderMt_GetMatches(CMatchFinderMt *p, UInt32 *distances) return len; } -#define SKIP_HEADER2 do { GET_NEXT_BLOCK_IF_REQUIRED -#define SKIP_HEADER(n) SKIP_HEADER2 if (p->btNumAvailBytes-- >= (n)) { const Byte *cur = p->pointerToCurPos; UInt32 *hash = p->hash; -#define SKIP_FOOTER } INCREASE_LZ_POS p->btBufPos += p->btBuf[p->btBufPos] + 1; } while (--num != 0); +#define SKIP_HEADER2_MT do { GET_NEXT_BLOCK_IF_REQUIRED +#define SKIP_HEADER_MT(n) SKIP_HEADER2_MT if (p->btNumAvailBytes-- >= (n)) { const Byte *cur = p->pointerToCurPos; UInt32 *hash = p->hash; +#define SKIP_FOOTER_MT } INCREASE_LZ_POS p->btBufPos += p->btBuf[p->btBufPos] + 1; } while (--num != 0); void MatchFinderMt0_Skip(CMatchFinderMt *p, UInt32 num) { - SKIP_HEADER2 { p->btNumAvailBytes--; - SKIP_FOOTER + SKIP_HEADER2_MT { p->btNumAvailBytes--; + SKIP_FOOTER_MT } void MatchFinderMt2_Skip(CMatchFinderMt *p, UInt32 num) { - SKIP_HEADER(2) + SKIP_HEADER_MT(2) UInt32 hash2Value; MT_HASH2_CALC hash[hash2Value] = p->lzPos; - SKIP_FOOTER + SKIP_FOOTER_MT } void MatchFinderMt3_Skip(CMatchFinderMt *p, UInt32 num) { - SKIP_HEADER(3) + SKIP_HEADER_MT(3) UInt32 hash2Value, hash3Value; MT_HASH3_CALC hash[kFix3HashSize + hash3Value] = hash[ hash2Value] = p->lzPos; - SKIP_FOOTER + SKIP_FOOTER_MT } /* void MatchFinderMt4_Skip(CMatchFinderMt *p, UInt32 num) { - SKIP_HEADER(4) + SKIP_HEADER_MT(4) UInt32 hash2Value, hash3Value, hash4Value; MT_HASH4_CALC hash[kFix4HashSize + hash4Value] = hash[kFix3HashSize + hash3Value] = hash[ hash2Value] = p->lzPos; - SKIP_FOOTER + SKIP_FOOTER_MT } */ diff --git a/lzma/C/LzFindMt.h b/lzma/C/LzFindMt.h index b7ead2d47..17ed237d6 100644 --- a/lzma/C/LzFindMt.h +++ b/lzma/C/LzFindMt.h @@ -1,11 +1,15 @@ /* LzFindMt.h -- multithreaded Match finder for LZ algorithms -2008-10-04 : Igor Pavlov : Public domain */ +2009-02-07 : Igor Pavlov : Public domain */ -#ifndef __LZFINDMT_H -#define __LZFINDMT_H +#ifndef __LZ_FIND_MT_H +#define __LZ_FIND_MT_H -#include "Threads.h" #include "LzFind.h" +#include "Threads.h" + +#ifdef __cplusplus +extern "C" { +#endif #define kMtHashBlockSize (1 << 13) #define kMtHashNumBlocks (1 << 3) @@ -94,4 +98,8 @@ SRes MatchFinderMt_Create(CMatchFinderMt *p, UInt32 historySize, UInt32 keepAddB void MatchFinderMt_CreateVTable(CMatchFinderMt *p, IMatchFinder *vTable); void MatchFinderMt_ReleaseStream(CMatchFinderMt *p); +#ifdef __cplusplus +} +#endif + #endif diff --git a/lzma/C/LzHash.h b/lzma/C/LzHash.h index c92341750..b2f0e3c24 100644 --- a/lzma/C/LzHash.h +++ b/lzma/C/LzHash.h @@ -1,8 +1,8 @@ /* LzHash.h -- HASH functions for LZ algorithms -2008-10-04 : Igor Pavlov : Public domain */ +2009-02-07 : Igor Pavlov : Public domain */ -#ifndef __LZHASH_H -#define __LZHASH_H +#ifndef __LZ_HASH_H +#define __LZ_HASH_H #define kHash2Size (1 << 10) #define kHash3Size (1 << 16) diff --git a/lzma/C/Lzma2Dec.c b/lzma/C/Lzma2Dec.c new file mode 100644 index 000000000..8f2406755 --- /dev/null +++ b/lzma/C/Lzma2Dec.c @@ -0,0 +1,356 @@ +/* Lzma2Dec.c -- LZMA2 Decoder +2009-05-03 : Igor Pavlov : Public domain */ + +/* #define SHOW_DEBUG_INFO */ + +#ifdef SHOW_DEBUG_INFO +#include +#endif + +#include + +#include "Lzma2Dec.h" + +/* +00000000 - EOS +00000001 U U - Uncompressed Reset Dic +00000010 U U - Uncompressed No Reset +100uuuuu U U P P - LZMA no reset +101uuuuu U U P P - LZMA reset state +110uuuuu U U P P S - LZMA reset state + new prop +111uuuuu U U P P S - LZMA reset state + new prop + reset dic + + u, U - Unpack Size + P - Pack Size + S - Props +*/ + +#define LZMA2_CONTROL_LZMA (1 << 7) +#define LZMA2_CONTROL_COPY_NO_RESET 2 +#define LZMA2_CONTROL_COPY_RESET_DIC 1 +#define LZMA2_CONTROL_EOF 0 + +#define LZMA2_IS_UNCOMPRESSED_STATE(p) (((p)->control & LZMA2_CONTROL_LZMA) == 0) + +#define LZMA2_GET_LZMA_MODE(p) (((p)->control >> 5) & 3) +#define LZMA2_IS_THERE_PROP(mode) ((mode) >= 2) + +#define LZMA2_LCLP_MAX 4 +#define LZMA2_DIC_SIZE_FROM_PROP(p) (((UInt32)2 | ((p) & 1)) << ((p) / 2 + 11)) + +#ifdef SHOW_DEBUG_INFO +#define PRF(x) x +#else +#define PRF(x) +#endif + +typedef enum +{ + LZMA2_STATE_CONTROL, + LZMA2_STATE_UNPACK0, + LZMA2_STATE_UNPACK1, + LZMA2_STATE_PACK0, + LZMA2_STATE_PACK1, + LZMA2_STATE_PROP, + LZMA2_STATE_DATA, + LZMA2_STATE_DATA_CONT, + LZMA2_STATE_FINISHED, + LZMA2_STATE_ERROR +} ELzma2State; + +static SRes Lzma2Dec_GetOldProps(Byte prop, Byte *props) +{ + UInt32 dicSize; + if (prop > 40) + return SZ_ERROR_UNSUPPORTED; + dicSize = (prop == 40) ? 0xFFFFFFFF : LZMA2_DIC_SIZE_FROM_PROP(prop); + props[0] = (Byte)LZMA2_LCLP_MAX; + props[1] = (Byte)(dicSize); + props[2] = (Byte)(dicSize >> 8); + props[3] = (Byte)(dicSize >> 16); + props[4] = (Byte)(dicSize >> 24); + return SZ_OK; +} + +SRes Lzma2Dec_AllocateProbs(CLzma2Dec *p, Byte prop, ISzAlloc *alloc) +{ + Byte props[LZMA_PROPS_SIZE]; + RINOK(Lzma2Dec_GetOldProps(prop, props)); + return LzmaDec_AllocateProbs(&p->decoder, props, LZMA_PROPS_SIZE, alloc); +} + +SRes Lzma2Dec_Allocate(CLzma2Dec *p, Byte prop, ISzAlloc *alloc) +{ + Byte props[LZMA_PROPS_SIZE]; + RINOK(Lzma2Dec_GetOldProps(prop, props)); + return LzmaDec_Allocate(&p->decoder, props, LZMA_PROPS_SIZE, alloc); +} + +void Lzma2Dec_Init(CLzma2Dec *p) +{ + p->state = LZMA2_STATE_CONTROL; + p->needInitDic = True; + p->needInitState = True; + p->needInitProp = True; + LzmaDec_Init(&p->decoder); +} + +static ELzma2State Lzma2Dec_UpdateState(CLzma2Dec *p, Byte b) +{ + switch(p->state) + { + case LZMA2_STATE_CONTROL: + p->control = b; + PRF(printf("\n %4X ", p->decoder.dicPos)); + PRF(printf(" %2X", b)); + if (p->control == 0) + return LZMA2_STATE_FINISHED; + if (LZMA2_IS_UNCOMPRESSED_STATE(p)) + { + if ((p->control & 0x7F) > 2) + return LZMA2_STATE_ERROR; + p->unpackSize = 0; + } + else + p->unpackSize = (UInt32)(p->control & 0x1F) << 16; + return LZMA2_STATE_UNPACK0; + + case LZMA2_STATE_UNPACK0: + p->unpackSize |= (UInt32)b << 8; + return LZMA2_STATE_UNPACK1; + + case LZMA2_STATE_UNPACK1: + p->unpackSize |= (UInt32)b; + p->unpackSize++; + PRF(printf(" %8d", p->unpackSize)); + return (LZMA2_IS_UNCOMPRESSED_STATE(p)) ? LZMA2_STATE_DATA : LZMA2_STATE_PACK0; + + case LZMA2_STATE_PACK0: + p->packSize = (UInt32)b << 8; + return LZMA2_STATE_PACK1; + + case LZMA2_STATE_PACK1: + p->packSize |= (UInt32)b; + p->packSize++; + PRF(printf(" %8d", p->packSize)); + return LZMA2_IS_THERE_PROP(LZMA2_GET_LZMA_MODE(p)) ? LZMA2_STATE_PROP: + (p->needInitProp ? LZMA2_STATE_ERROR : LZMA2_STATE_DATA); + + case LZMA2_STATE_PROP: + { + int lc, lp; + if (b >= (9 * 5 * 5)) + return LZMA2_STATE_ERROR; + lc = b % 9; + b /= 9; + p->decoder.prop.pb = b / 5; + lp = b % 5; + if (lc + lp > LZMA2_LCLP_MAX) + return LZMA2_STATE_ERROR; + p->decoder.prop.lc = lc; + p->decoder.prop.lp = lp; + p->needInitProp = False; + return LZMA2_STATE_DATA; + } + } + return LZMA2_STATE_ERROR; +} + +static void LzmaDec_UpdateWithUncompressed(CLzmaDec *p, const Byte *src, SizeT size) +{ + memcpy(p->dic + p->dicPos, src, size); + p->dicPos += size; + if (p->checkDicSize == 0 && p->prop.dicSize - p->processedPos <= size) + p->checkDicSize = p->prop.dicSize; + p->processedPos += (UInt32)size; +} + +void LzmaDec_InitDicAndState(CLzmaDec *p, Bool initDic, Bool initState); + +SRes Lzma2Dec_DecodeToDic(CLzma2Dec *p, SizeT dicLimit, + const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status) +{ + SizeT inSize = *srcLen; + *srcLen = 0; + *status = LZMA_STATUS_NOT_SPECIFIED; + + while (p->state != LZMA2_STATE_FINISHED) + { + SizeT dicPos = p->decoder.dicPos; + if (p->state == LZMA2_STATE_ERROR) + return SZ_ERROR_DATA; + if (dicPos == dicLimit && finishMode == LZMA_FINISH_ANY) + { + *status = LZMA_STATUS_NOT_FINISHED; + return SZ_OK; + } + if (p->state != LZMA2_STATE_DATA && p->state != LZMA2_STATE_DATA_CONT) + { + if (*srcLen == inSize) + { + *status = LZMA_STATUS_NEEDS_MORE_INPUT; + return SZ_OK; + } + (*srcLen)++; + p->state = Lzma2Dec_UpdateState(p, *src++); + continue; + } + { + SizeT destSizeCur = dicLimit - dicPos; + SizeT srcSizeCur = inSize - *srcLen; + ELzmaFinishMode curFinishMode = LZMA_FINISH_ANY; + + if (p->unpackSize <= destSizeCur) + { + destSizeCur = (SizeT)p->unpackSize; + curFinishMode = LZMA_FINISH_END; + } + + if (LZMA2_IS_UNCOMPRESSED_STATE(p)) + { + if (*srcLen == inSize) + { + *status = LZMA_STATUS_NEEDS_MORE_INPUT; + return SZ_OK; + } + + if (p->state == LZMA2_STATE_DATA) + { + Bool initDic = (p->control == LZMA2_CONTROL_COPY_RESET_DIC); + if (initDic) + p->needInitProp = p->needInitState = True; + else if (p->needInitDic) + return SZ_ERROR_DATA; + p->needInitDic = False; + LzmaDec_InitDicAndState(&p->decoder, initDic, False); + } + + if (srcSizeCur > destSizeCur) + srcSizeCur = destSizeCur; + + if (srcSizeCur == 0) + return SZ_ERROR_DATA; + + LzmaDec_UpdateWithUncompressed(&p->decoder, src, srcSizeCur); + + src += srcSizeCur; + *srcLen += srcSizeCur; + p->unpackSize -= (UInt32)srcSizeCur; + p->state = (p->unpackSize == 0) ? LZMA2_STATE_CONTROL : LZMA2_STATE_DATA_CONT; + } + else + { + SizeT outSizeProcessed; + SRes res; + + if (p->state == LZMA2_STATE_DATA) + { + int mode = LZMA2_GET_LZMA_MODE(p); + Bool initDic = (mode == 3); + Bool initState = (mode > 0); + if ((!initDic && p->needInitDic) || (!initState && p->needInitState)) + return SZ_ERROR_DATA; + + LzmaDec_InitDicAndState(&p->decoder, initDic, initState); + p->needInitDic = False; + p->needInitState = False; + p->state = LZMA2_STATE_DATA_CONT; + } + if (srcSizeCur > p->packSize) + srcSizeCur = (SizeT)p->packSize; + + res = LzmaDec_DecodeToDic(&p->decoder, dicPos + destSizeCur, src, &srcSizeCur, curFinishMode, status); + + src += srcSizeCur; + *srcLen += srcSizeCur; + p->packSize -= (UInt32)srcSizeCur; + + outSizeProcessed = p->decoder.dicPos - dicPos; + p->unpackSize -= (UInt32)outSizeProcessed; + + RINOK(res); + if (*status == LZMA_STATUS_NEEDS_MORE_INPUT) + return res; + + if (srcSizeCur == 0 && outSizeProcessed == 0) + { + if (*status != LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK || + p->unpackSize != 0 || p->packSize != 0) + return SZ_ERROR_DATA; + p->state = LZMA2_STATE_CONTROL; + } + if (*status == LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK) + *status = LZMA_STATUS_NOT_FINISHED; + } + } + } + *status = LZMA_STATUS_FINISHED_WITH_MARK; + return SZ_OK; +} + +SRes Lzma2Dec_DecodeToBuf(CLzma2Dec *p, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status) +{ + SizeT outSize = *destLen, inSize = *srcLen; + *srcLen = *destLen = 0; + for (;;) + { + SizeT srcSizeCur = inSize, outSizeCur, dicPos; + ELzmaFinishMode curFinishMode; + SRes res; + if (p->decoder.dicPos == p->decoder.dicBufSize) + p->decoder.dicPos = 0; + dicPos = p->decoder.dicPos; + if (outSize > p->decoder.dicBufSize - dicPos) + { + outSizeCur = p->decoder.dicBufSize; + curFinishMode = LZMA_FINISH_ANY; + } + else + { + outSizeCur = dicPos + outSize; + curFinishMode = finishMode; + } + + res = Lzma2Dec_DecodeToDic(p, outSizeCur, src, &srcSizeCur, curFinishMode, status); + src += srcSizeCur; + inSize -= srcSizeCur; + *srcLen += srcSizeCur; + outSizeCur = p->decoder.dicPos - dicPos; + memcpy(dest, p->decoder.dic + dicPos, outSizeCur); + dest += outSizeCur; + outSize -= outSizeCur; + *destLen += outSizeCur; + if (res != 0) + return res; + if (outSizeCur == 0 || outSize == 0) + return SZ_OK; + } +} + +SRes Lzma2Decode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, + Byte prop, ELzmaFinishMode finishMode, ELzmaStatus *status, ISzAlloc *alloc) +{ + CLzma2Dec decoder; + SRes res; + SizeT outSize = *destLen, inSize = *srcLen; + Byte props[LZMA_PROPS_SIZE]; + + Lzma2Dec_Construct(&decoder); + + *destLen = *srcLen = 0; + *status = LZMA_STATUS_NOT_SPECIFIED; + decoder.decoder.dic = dest; + decoder.decoder.dicBufSize = outSize; + + RINOK(Lzma2Dec_GetOldProps(prop, props)); + RINOK(LzmaDec_AllocateProbs(&decoder.decoder, props, LZMA_PROPS_SIZE, alloc)); + + *srcLen = inSize; + res = Lzma2Dec_DecodeToDic(&decoder, outSize, src, srcLen, finishMode, status); + *destLen = decoder.decoder.dicPos; + if (res == SZ_OK && *status == LZMA_STATUS_NEEDS_MORE_INPUT) + res = SZ_ERROR_INPUT_EOF; + + LzmaDec_FreeProbs(&decoder.decoder, alloc); + return res; +} diff --git a/lzma/C/Lzma2Dec.h b/lzma/C/Lzma2Dec.h new file mode 100644 index 000000000..827698dee --- /dev/null +++ b/lzma/C/Lzma2Dec.h @@ -0,0 +1,84 @@ +/* Lzma2Dec.h -- LZMA2 Decoder +2009-05-03 : Igor Pavlov : Public domain */ + +#ifndef __LZMA2_DEC_H +#define __LZMA2_DEC_H + +#include "LzmaDec.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* ---------- State Interface ---------- */ + +typedef struct +{ + CLzmaDec decoder; + UInt32 packSize; + UInt32 unpackSize; + int state; + Byte control; + Bool needInitDic; + Bool needInitState; + Bool needInitProp; +} CLzma2Dec; + +#define Lzma2Dec_Construct(p) LzmaDec_Construct(&(p)->decoder) +#define Lzma2Dec_FreeProbs(p, alloc) LzmaDec_FreeProbs(&(p)->decoder, alloc); +#define Lzma2Dec_Free(p, alloc) LzmaDec_Free(&(p)->decoder, alloc); + +SRes Lzma2Dec_AllocateProbs(CLzma2Dec *p, Byte prop, ISzAlloc *alloc); +SRes Lzma2Dec_Allocate(CLzma2Dec *p, Byte prop, ISzAlloc *alloc); +void Lzma2Dec_Init(CLzma2Dec *p); + + +/* +finishMode: + It has meaning only if the decoding reaches output limit (*destLen or dicLimit). + LZMA_FINISH_ANY - use smallest number of input bytes + LZMA_FINISH_END - read EndOfStream marker after decoding + +Returns: + SZ_OK + status: + LZMA_STATUS_FINISHED_WITH_MARK + LZMA_STATUS_NOT_FINISHED + LZMA_STATUS_NEEDS_MORE_INPUT + SZ_ERROR_DATA - Data error +*/ + +SRes Lzma2Dec_DecodeToDic(CLzma2Dec *p, SizeT dicLimit, + const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status); + +SRes Lzma2Dec_DecodeToBuf(CLzma2Dec *p, Byte *dest, SizeT *destLen, + const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status); + + +/* ---------- One Call Interface ---------- */ + +/* +finishMode: + It has meaning only if the decoding reaches output limit (*destLen). + LZMA_FINISH_ANY - use smallest number of input bytes + LZMA_FINISH_END - read EndOfStream marker after decoding + +Returns: + SZ_OK + status: + LZMA_STATUS_FINISHED_WITH_MARK + LZMA_STATUS_NOT_FINISHED + SZ_ERROR_DATA - Data error + SZ_ERROR_MEM - Memory allocation error + SZ_ERROR_UNSUPPORTED - Unsupported properties + SZ_ERROR_INPUT_EOF - It needs more bytes in input buffer (src). +*/ + +SRes Lzma2Decode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, + Byte prop, ELzmaFinishMode finishMode, ELzmaStatus *status, ISzAlloc *alloc); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lzma/C/LzmaDec.c b/lzma/C/LzmaDec.c index eb5250174..4fdc11d4b 100644 --- a/lzma/C/LzmaDec.c +++ b/lzma/C/LzmaDec.c @@ -1,5 +1,5 @@ /* LzmaDec.c -- LZMA Decoder -2008-11-06 : Igor Pavlov : Public domain */ +2009-09-20 : Igor Pavlov : Public domain */ #include "LzmaDec.h" @@ -113,12 +113,6 @@ StopCompilingDueBUG #endif -static const Byte kLiteralNextStates[kNumStates * 2] = -{ - 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 4, 5, - 7, 7, 7, 7, 7, 7, 7, 10, 10, 10, 10, 10 -}; - #define LZMA_DIC_MIN (1 << 12) /* First LZMA-symbol is always decoded. @@ -175,6 +169,7 @@ static int MY_FAST_CALL LzmaDec_DecodeReal(CLzmaDec *p, SizeT limit, const Byte if (state < kNumLitStates) { + state -= (state < 4) ? state : 3; symbol = 1; do { GET_BIT(prob + symbol, symbol) } while (symbol < 0x100); } @@ -182,6 +177,7 @@ static int MY_FAST_CALL LzmaDec_DecodeReal(CLzmaDec *p, SizeT limit, const Byte { unsigned matchByte = p->dic[(dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0)]; unsigned offs = 0x100; + state -= (state < 10) ? 3 : 6; symbol = 1; do { @@ -196,9 +192,6 @@ static int MY_FAST_CALL LzmaDec_DecodeReal(CLzmaDec *p, SizeT limit, const Byte } dic[dicPos++] = (Byte)symbol; processedPos++; - - state = kLiteralNextStates[state]; - /* if (state < 4) state = 0; else if (state < 10) state -= 3; else state -= 6; */ continue; } else @@ -378,7 +371,6 @@ static int MY_FAST_CALL LzmaDec_DecodeReal(CLzmaDec *p, SizeT limit, const Byte else if (distance >= checkDicSize) return SZ_ERROR_DATA; state = (state < kNumStates + kNumLitStates) ? kNumLitStates : kNumLitStates + 3; - /* state = kLiteralNextStates[state]; */ } len += kMatchMinLen; diff --git a/lzma/C/LzmaDec.h b/lzma/C/LzmaDec.h index 9ec549c86..6741a644b 100644 --- a/lzma/C/LzmaDec.h +++ b/lzma/C/LzmaDec.h @@ -1,11 +1,15 @@ /* LzmaDec.h -- LZMA Decoder -2008-10-04 : Igor Pavlov : Public domain */ +2009-02-07 : Igor Pavlov : Public domain */ -#ifndef __LZMADEC_H -#define __LZMADEC_H +#ifndef __LZMA_DEC_H +#define __LZMA_DEC_H #include "Types.h" +#ifdef __cplusplus +extern "C" { +#endif + /* #define _LZMA_PROB32 */ /* _LZMA_PROB32 can increase the speed on some CPUs, but memory usage for CLzmaDec::probs will be doubled in that case */ @@ -66,13 +70,7 @@ typedef struct #define LzmaDec_Construct(p) { (p)->dic = 0; (p)->probs = 0; } -#ifdef __cplusplus -extern "C" { -#endif void LzmaDec_Init(CLzmaDec *p); -#ifdef __cplusplus -} -#endif /* There are two types of LZMA streams: 0) Stream with end mark. That end mark adds about 6 bytes to compressed size. @@ -132,11 +130,7 @@ LzmaDec_Allocate* can return: SZ_ERROR_MEM - Memory allocation error SZ_ERROR_UNSUPPORTED - Unsupported properties */ - -#ifdef __cplusplus -extern "C" { -#endif - + SRes LzmaDec_AllocateProbs(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAlloc *alloc); void LzmaDec_FreeProbs(CLzmaDec *p, ISzAlloc *alloc); diff --git a/lzma/C/LzmaEnc.c b/lzma/C/LzmaEnc.c index 529fd98f8..9e6dbdbe2 100644 --- a/lzma/C/LzmaEnc.c +++ b/lzma/C/LzmaEnc.c @@ -1,5 +1,5 @@ /* LzmaEnc.c -- LZMA Encoder -2009-02-02 : Igor Pavlov : Public domain */ +2010-04-16 : Igor Pavlov : Public domain */ #include @@ -13,7 +13,7 @@ #include "LzmaEnc.h" #include "LzFind.h" -#ifdef COMPRESS_MF_MT +#ifndef _7ZIP_ST #include "LzFindMt.h" #endif @@ -66,7 +66,7 @@ void LzmaEncProps_Normalize(CLzmaEncProps *p) if (p->mc == 0) p->mc = (16 + (p->fb >> 1)) >> (p->btMode ? 0 : 1); if (p->numThreads < 0) p->numThreads = - #ifdef COMPRESS_MF_MT + #ifndef _7ZIP_ST ((p->btMode && p->algo) ? 2 : 1); #else 1; @@ -139,7 +139,7 @@ void LzmaEnc_FastPosInit(Byte *g_FastPos) typedef unsigned CState; -typedef struct _COptimal +typedef struct { UInt32 price; @@ -172,7 +172,7 @@ typedef struct _COptimal #define kEndPosModelIndex 14 #define kNumPosModels (kEndPosModelIndex - kStartPosModelIndex) -#define kNumFullDistances (1 << (kEndPosModelIndex / 2)) +#define kNumFullDistances (1 << (kEndPosModelIndex >> 1)) #ifdef _LZMA_PROB32 #define CLzmaProb UInt32 @@ -218,7 +218,7 @@ typedef struct UInt32 counters[LZMA_NUM_PB_STATES_MAX]; } CLenPriceEnc; -typedef struct _CRangeEnc +typedef struct { UInt32 range; Byte cache; @@ -232,26 +232,6 @@ typedef struct _CRangeEnc SRes res; } CRangeEnc; -typedef struct _CSeqInStreamBuf -{ - ISeqInStream funcTable; - const Byte *data; - SizeT rem; -} CSeqInStreamBuf; - -static SRes MyRead(void *pp, void *data, size_t *size) -{ - size_t curSize = *size; - CSeqInStreamBuf *p = (CSeqInStreamBuf *)pp; - if (p->rem < curSize) - curSize = p->rem; - memcpy(data, p->data, curSize); - p->rem -= curSize; - p->data += curSize; - *size = curSize; - return SZ_OK; -} - typedef struct { CLzmaProb *litProbs; @@ -274,19 +254,19 @@ typedef struct UInt32 state; } CSaveState; -typedef struct _CLzmaEnc +typedef struct { IMatchFinder matchFinder; void *matchFinderObj; - #ifdef COMPRESS_MF_MT + #ifndef _7ZIP_ST Bool mtMode; CMatchFinderMt matchFinderMt; #endif CMatchFinder matchFinderBase; - #ifdef COMPRESS_MF_MT + #ifndef _7ZIP_ST Byte pad[128]; #endif @@ -351,8 +331,7 @@ typedef struct _CLzmaEnc UInt32 dictSize; UInt32 matchFinderCycles; - ISeqInStream *inStream; - CSeqInStreamBuf seqBufInStream; + int needInit; CSaveState saveState; } CLzmaEnc; @@ -416,7 +395,7 @@ SRes LzmaEnc_SetProps(CLzmaEncHandle pp, const CLzmaEncProps *props2) LzmaEncProps_Normalize(&props); if (props.lc > LZMA_LC_MAX || props.lp > LZMA_LP_MAX || props.pb > LZMA_PB_MAX || - props.dictSize > (1 << kDicLogSizeMaxCompress) || props.dictSize > (1 << 30)) + props.dictSize > ((UInt32)1 << kDicLogSizeMaxCompress) || props.dictSize > ((UInt32)1 << 30)) return SZ_ERROR_PARAM; p->dictSize = props.dictSize; p->matchFinderCycles = props.mc; @@ -449,7 +428,7 @@ SRes LzmaEnc_SetProps(CLzmaEncHandle pp, const CLzmaEncProps *props2) p->writeEndMark = props.writeEndMark; - #ifdef COMPRESS_MF_MT + #ifndef _7ZIP_ST /* if (newMultiThread != _multiThread) { @@ -1698,7 +1677,7 @@ void LzmaEnc_Construct(CLzmaEnc *p) { RangeEnc_Construct(&p->rc); MatchFinder_Construct(&p->matchFinderBase); - #ifdef COMPRESS_MF_MT + #ifndef _7ZIP_ST MatchFinderMt_Construct(&p->matchFinderMt); p->matchFinderMt.MatchFinder = &p->matchFinderBase; #endif @@ -1737,7 +1716,7 @@ void LzmaEnc_FreeLits(CLzmaEnc *p, ISzAlloc *alloc) void LzmaEnc_Destruct(CLzmaEnc *p, ISzAlloc *alloc, ISzAlloc *allocBig) { - #ifdef COMPRESS_MF_MT + #ifndef _7ZIP_ST MatchFinderMt_Destruct(&p->matchFinderMt, allocBig); #endif MatchFinder_Free(&p->matchFinderBase, allocBig); @@ -1754,11 +1733,10 @@ void LzmaEnc_Destroy(CLzmaEncHandle p, ISzAlloc *alloc, ISzAlloc *allocBig) static SRes LzmaEnc_CodeOneBlock(CLzmaEnc *p, Bool useLimits, UInt32 maxPackSize, UInt32 maxUnpackSize) { UInt32 nowPos32, startPos32; - if (p->inStream != 0) + if (p->needInit) { - p->matchFinderBase.stream = p->inStream; p->matchFinder.Init(p->matchFinderObj); - p->inStream = 0; + p->needInit = 0; } if (p->finished) @@ -1923,7 +1901,7 @@ static SRes LzmaEnc_Alloc(CLzmaEnc *p, UInt32 keepWindowSize, ISzAlloc *alloc, I if (!RangeEnc_Alloc(&p->rc, alloc)) return SZ_ERROR_MEM; btMode = (p->matchFinderBase.btMode != 0); - #ifdef COMPRESS_MF_MT + #ifndef _7ZIP_ST p->mtMode = (p->multiThread && !p->fastMode && btMode); #endif @@ -1948,7 +1926,7 @@ static SRes LzmaEnc_Alloc(CLzmaEnc *p, UInt32 keepWindowSize, ISzAlloc *alloc, I if (beforeSize + p->dictSize < keepWindowSize) beforeSize = keepWindowSize - p->dictSize; - #ifdef COMPRESS_MF_MT + #ifndef _7ZIP_ST if (p->mtMode) { RINOK(MatchFinderMt_Create(&p->matchFinderMt, p->dictSize, beforeSize, p->numFastBytes, LZMA_MATCH_LEN_MAX, allocBig)); @@ -2056,11 +2034,12 @@ static SRes LzmaEnc_AllocAndInit(CLzmaEnc *p, UInt32 keepWindowSize, ISzAlloc *a return SZ_OK; } -static SRes LzmaEnc_Prepare(CLzmaEncHandle pp, ISeqInStream *inStream, ISeqOutStream *outStream, +static SRes LzmaEnc_Prepare(CLzmaEncHandle pp, ISeqOutStream *outStream, ISeqInStream *inStream, ISzAlloc *alloc, ISzAlloc *allocBig) { CLzmaEnc *p = (CLzmaEnc *)pp; - p->inStream = inStream; + p->matchFinderBase.stream = inStream; + p->needInit = 1; p->rc.outStream = outStream; return LzmaEnc_AllocAndInit(p, 0, alloc, allocBig); } @@ -2070,15 +2049,16 @@ SRes LzmaEnc_PrepareForLzma2(CLzmaEncHandle pp, ISzAlloc *alloc, ISzAlloc *allocBig) { CLzmaEnc *p = (CLzmaEnc *)pp; - p->inStream = inStream; + p->matchFinderBase.stream = inStream; + p->needInit = 1; return LzmaEnc_AllocAndInit(p, keepWindowSize, alloc, allocBig); } static void LzmaEnc_SetInputBuf(CLzmaEnc *p, const Byte *src, SizeT srcLen) { - p->seqBufInStream.funcTable.Read = MyRead; - p->seqBufInStream.data = src; - p->seqBufInStream.rem = srcLen; + p->matchFinderBase.directInput = 1; + p->matchFinderBase.bufferBase = (Byte *)src; + p->matchFinderBase.directInputRem = srcLen; } SRes LzmaEnc_MemPrepare(CLzmaEncHandle pp, const Byte *src, SizeT srcLen, @@ -2086,13 +2066,14 @@ SRes LzmaEnc_MemPrepare(CLzmaEncHandle pp, const Byte *src, SizeT srcLen, { CLzmaEnc *p = (CLzmaEnc *)pp; LzmaEnc_SetInputBuf(p, src, srcLen); - p->inStream = &p->seqBufInStream.funcTable; + p->needInit = 1; + return LzmaEnc_AllocAndInit(p, keepWindowSize, alloc, allocBig); } void LzmaEnc_Finish(CLzmaEncHandle pp) { - #ifdef COMPRESS_MF_MT + #ifndef _7ZIP_ST CLzmaEnc *p = (CLzmaEnc *)pp; if (p->mtMode) MatchFinderMt_ReleaseStream(&p->matchFinderMt); @@ -2101,7 +2082,7 @@ void LzmaEnc_Finish(CLzmaEncHandle pp) #endif } -typedef struct _CSeqOutStreamBuf +typedef struct { ISeqOutStream funcTable; Byte *data; @@ -2170,21 +2151,17 @@ SRes LzmaEnc_CodeOneMemBlock(CLzmaEncHandle pp, Bool reInit, return res; } -SRes LzmaEnc_Encode(CLzmaEncHandle pp, ISeqOutStream *outStream, ISeqInStream *inStream, ICompressProgress *progress, - ISzAlloc *alloc, ISzAlloc *allocBig) +static SRes LzmaEnc_Encode2(CLzmaEnc *p, ICompressProgress *progress) { - CLzmaEnc *p = (CLzmaEnc *)pp; SRes res = SZ_OK; - #ifdef COMPRESS_MF_MT + #ifndef _7ZIP_ST Byte allocaDummy[0x300]; int i = 0; for (i = 0; i < 16; i++) allocaDummy[i] = (Byte)i; #endif - RINOK(LzmaEnc_Prepare(pp, inStream, outStream, alloc, allocBig)); - for (;;) { res = LzmaEnc_CodeOneBlock(p, False, 0, 0); @@ -2200,10 +2177,17 @@ SRes LzmaEnc_Encode(CLzmaEncHandle pp, ISeqOutStream *outStream, ISeqInStream *i } } } - LzmaEnc_Finish(pp); + LzmaEnc_Finish(p); return res; } +SRes LzmaEnc_Encode(CLzmaEncHandle pp, ISeqOutStream *outStream, ISeqInStream *inStream, ICompressProgress *progress, + ISzAlloc *alloc, ISzAlloc *allocBig) +{ + RINOK(LzmaEnc_Prepare(pp, outStream, inStream, alloc, allocBig)); + return LzmaEnc_Encode2((CLzmaEnc *)pp, progress); +} + SRes LzmaEnc_WriteProperties(CLzmaEncHandle pp, Byte *props, SizeT *size) { CLzmaEnc *p = (CLzmaEnc *)pp; @@ -2249,8 +2233,11 @@ SRes LzmaEnc_MemEncode(CLzmaEncHandle pp, Byte *dest, SizeT *destLen, const Byte outStream.overflow = False; p->writeEndMark = writeEndMark; - res = LzmaEnc_Encode(pp, &outStream.funcTable, &p->seqBufInStream.funcTable, - progress, alloc, allocBig); + + p->rc.outStream = &outStream.funcTable; + res = LzmaEnc_MemPrepare(pp, src, srcLen, 0, alloc, allocBig); + if (res == SZ_OK) + res = LzmaEnc_Encode2(p, progress); *destLen -= outStream.rem; if (outStream.overflow) diff --git a/lzma/C/LzmaEnc.h b/lzma/C/LzmaEnc.h index e3d84fa35..999f5afff 100644 --- a/lzma/C/LzmaEnc.h +++ b/lzma/C/LzmaEnc.h @@ -1,11 +1,15 @@ /* LzmaEnc.h -- LZMA Encoder -2008-10-04 : Igor Pavlov : Public domain */ +2009-02-07 : Igor Pavlov : Public domain */ -#ifndef __LZMAENC_H -#define __LZMAENC_H +#ifndef __LZMA_ENC_H +#define __LZMA_ENC_H #include "Types.h" +#ifdef __cplusplus +extern "C" { +#endif + #define LZMA_PROPS_SIZE 5 typedef struct _CLzmaEncProps @@ -69,4 +73,8 @@ SRes LzmaEncode(Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen, const CLzmaEncProps *props, Byte *propsEncoded, SizeT *propsSize, int writeEndMark, ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig); +#ifdef __cplusplus +} +#endif + #endif diff --git a/lzma/C/LzmaLib.c b/lzma/C/LzmaLib.c deleted file mode 100644 index 3e3cf40ae..000000000 --- a/lzma/C/LzmaLib.c +++ /dev/null @@ -1,46 +0,0 @@ -/* LzmaLib.c -- LZMA library wrapper -2008-08-05 -Igor Pavlov -Public domain */ - -#include "LzmaEnc.h" -#include "LzmaDec.h" -#include "Alloc.h" -#include "LzmaLib.h" - -static void *SzAlloc(void *p, size_t size) { p = p; return MyAlloc(size); } -static void SzFree(void *p, void *address) { p = p; MyFree(address); } -static ISzAlloc g_Alloc = { SzAlloc, SzFree }; - -MY_STDAPI LzmaCompress(unsigned char *dest, size_t *destLen, const unsigned char *src, size_t srcLen, - unsigned char *outProps, size_t *outPropsSize, - int level, /* 0 <= level <= 9, default = 5 */ - unsigned dictSize, /* use (1 << N) or (3 << N). 4 KB < dictSize <= 128 MB */ - int lc, /* 0 <= lc <= 8, default = 3 */ - int lp, /* 0 <= lp <= 4, default = 0 */ - int pb, /* 0 <= pb <= 4, default = 2 */ - int fb, /* 5 <= fb <= 273, default = 32 */ - int numThreads /* 1 or 2, default = 2 */ -) -{ - CLzmaEncProps props; - LzmaEncProps_Init(&props); - props.level = level; - props.dictSize = dictSize; - props.lc = lc; - props.lp = lp; - props.pb = pb; - props.fb = fb; - props.numThreads = numThreads; - - return LzmaEncode(dest, destLen, src, srcLen, &props, outProps, outPropsSize, 0, - NULL, &g_Alloc, &g_Alloc); -} - - -MY_STDAPI LzmaUncompress(unsigned char *dest, size_t *destLen, const unsigned char *src, size_t *srcLen, - const unsigned char *props, size_t propsSize) -{ - ELzmaStatus status; - return LzmaDecode(dest, destLen, src, srcLen, props, (unsigned)propsSize, LZMA_FINISH_ANY, &status, &g_Alloc); -} diff --git a/lzma/C/LzmaLib.h b/lzma/C/LzmaLib.h deleted file mode 100644 index 849d347e9..000000000 --- a/lzma/C/LzmaLib.h +++ /dev/null @@ -1,135 +0,0 @@ -/* LzmaLib.h -- LZMA library interface -2008-08-05 -Igor Pavlov -Public domain */ - -#ifndef __LZMALIB_H -#define __LZMALIB_H - -#include "Types.h" - -#ifdef __cplusplus - #define MY_EXTERN_C extern "C" -#else - #define MY_EXTERN_C extern -#endif - -#define MY_STDAPI MY_EXTERN_C int MY_STD_CALL - -#define LZMA_PROPS_SIZE 5 - -/* -RAM requirements for LZMA: - for compression: (dictSize * 11.5 + 6 MB) + state_size - for decompression: dictSize + state_size - state_size = (4 + (1.5 << (lc + lp))) KB - by default (lc=3, lp=0), state_size = 16 KB. - -LZMA properties (5 bytes) format - Offset Size Description - 0 1 lc, lp and pb in encoded form. - 1 4 dictSize (little endian). -*/ - -/* -LzmaCompress ------------- - -outPropsSize - - In: the pointer to the size of outProps buffer; *outPropsSize = LZMA_PROPS_SIZE = 5. - Out: the pointer to the size of written properties in outProps buffer; *outPropsSize = LZMA_PROPS_SIZE = 5. - - LZMA Encoder will use defult values for any parameter, if it is - -1 for any from: level, loc, lp, pb, fb, numThreads - 0 for dictSize - -level - compression level: 0 <= level <= 9; - - level dictSize algo fb - 0: 16 KB 0 32 - 1: 64 KB 0 32 - 2: 256 KB 0 32 - 3: 1 MB 0 32 - 4: 4 MB 0 32 - 5: 16 MB 1 32 - 6: 32 MB 1 32 - 7+: 64 MB 1 64 - - The default value for "level" is 5. - - algo = 0 means fast method - algo = 1 means normal method - -dictSize - The dictionary size in bytes. The maximum value is - 128 MB = (1 << 27) bytes for 32-bit version - 1 GB = (1 << 30) bytes for 64-bit version - The default value is 16 MB = (1 << 24) bytes. - It's recommended to use the dictionary that is larger than 4 KB and - that can be calculated as (1 << N) or (3 << N) sizes. - -lc - The number of literal context bits (high bits of previous literal). - It can be in the range from 0 to 8. The default value is 3. - Sometimes lc=4 gives the gain for big files. - -lp - The number of literal pos bits (low bits of current position for literals). - It can be in the range from 0 to 4. The default value is 0. - The lp switch is intended for periodical data when the period is equal to 2^lp. - For example, for 32-bit (4 bytes) periodical data you can use lp=2. Often it's - better to set lc=0, if you change lp switch. - -pb - The number of pos bits (low bits of current position). - It can be in the range from 0 to 4. The default value is 2. - The pb switch is intended for periodical data when the period is equal 2^pb. - -fb - Word size (the number of fast bytes). - It can be in the range from 5 to 273. The default value is 32. - Usually, a big number gives a little bit better compression ratio and - slower compression process. - -numThreads - The number of thereads. 1 or 2. The default value is 2. - Fast mode (algo = 0) can use only 1 thread. - -Out: - destLen - processed output size -Returns: - SZ_OK - OK - SZ_ERROR_MEM - Memory allocation error - SZ_ERROR_PARAM - Incorrect paramater - SZ_ERROR_OUTPUT_EOF - output buffer overflow - SZ_ERROR_THREAD - errors in multithreading functions (only for Mt version) -*/ - -MY_STDAPI LzmaCompress(unsigned char *dest, size_t *destLen, const unsigned char *src, size_t srcLen, - unsigned char *outProps, size_t *outPropsSize, /* *outPropsSize must be = 5 */ - int level, /* 0 <= level <= 9, default = 5 */ - unsigned dictSize, /* default = (1 << 24) */ - int lc, /* 0 <= lc <= 8, default = 3 */ - int lp, /* 0 <= lp <= 4, default = 0 */ - int pb, /* 0 <= pb <= 4, default = 2 */ - int fb, /* 5 <= fb <= 273, default = 32 */ - int numThreads /* 1 or 2, default = 2 */ - ); - -/* -LzmaUncompress --------------- -In: - dest - output data - destLen - output data size - src - input data - srcLen - input data size -Out: - destLen - processed output size - srcLen - processed input size -Returns: - SZ_OK - OK - SZ_ERROR_DATA - Data error - SZ_ERROR_MEM - Memory allocation arror - SZ_ERROR_UNSUPPORTED - Unsupported properties - SZ_ERROR_INPUT_EOF - it needs more bytes in input buffer (src) -*/ - -MY_STDAPI LzmaUncompress(unsigned char *dest, size_t *destLen, const unsigned char *src, SizeT *srcLen, - const unsigned char *props, size_t propsSize); - -#endif diff --git a/lzma/C/Threads.c b/lzma/C/Threads.c index 64d871abe..4be44fb0f 100644 --- a/lzma/C/Threads.c +++ b/lzma/C/Threads.c @@ -1,13 +1,12 @@ /* Threads.c -- multithreading library -2008-08-05 -Igor Pavlov -Public domain */ +2009-09-20 : Igor Pavlov : Public domain */ + +#ifndef _WIN32_WCE +#include +#endif #include "Threads.h" -#ifdef _WIN32 -#include - static WRes GetError() { DWORD res = GetLastError(); @@ -17,276 +16,69 @@ static WRes GetError() WRes HandleToWRes(HANDLE h) { return (h != 0) ? 0 : GetError(); } WRes BOOLToWRes(BOOL v) { return v ? 0 : GetError(); } -static WRes MyCloseHandle(HANDLE *h) +WRes HandlePtr_Close(HANDLE *p) { - if (*h != NULL) - if (!CloseHandle(*h)) + if (*p != NULL) + if (!CloseHandle(*p)) return GetError(); - *h = NULL; + *p = NULL; return 0; } -WRes Thread_Create(CThread *thread, THREAD_FUNC_RET_TYPE (THREAD_FUNC_CALL_TYPE *startAddress)(void *), LPVOID parameter) +WRes Handle_WaitObject(HANDLE h) { return (WRes)WaitForSingleObject(h, INFINITE); } + +WRes Thread_Create(CThread *p, THREAD_FUNC_TYPE func, LPVOID param) { unsigned threadId; /* Windows Me/98/95: threadId parameter may not be NULL in _beginthreadex/CreateThread functions */ - thread->handle = - /* CreateThread(0, 0, startAddress, parameter, 0, &threadId); */ - (HANDLE)_beginthreadex(NULL, 0, startAddress, parameter, 0, &threadId); + *p = + #ifdef UNDER_CE + CreateThread(0, 0, func, param, 0, &threadId); + #else + (HANDLE)_beginthreadex(NULL, 0, func, param, 0, &threadId); + #endif /* maybe we must use errno here, but probably GetLastError() is also OK. */ - return HandleToWRes(thread->handle); + return HandleToWRes(*p); } -WRes WaitObject(HANDLE h) +WRes Event_Create(CEvent *p, BOOL manualReset, int signaled) { - return (WRes)WaitForSingleObject(h, INFINITE); + *p = CreateEvent(NULL, manualReset, (signaled ? TRUE : FALSE), NULL); + return HandleToWRes(*p); } -WRes Thread_Wait(CThread *thread) +WRes Event_Set(CEvent *p) { return BOOLToWRes(SetEvent(*p)); } +WRes Event_Reset(CEvent *p) { return BOOLToWRes(ResetEvent(*p)); } + +WRes ManualResetEvent_Create(CManualResetEvent *p, int signaled) { return Event_Create(p, TRUE, signaled); } +WRes AutoResetEvent_Create(CAutoResetEvent *p, int signaled) { return Event_Create(p, FALSE, signaled); } +WRes ManualResetEvent_CreateNotSignaled(CManualResetEvent *p) { return ManualResetEvent_Create(p, 0); } +WRes AutoResetEvent_CreateNotSignaled(CAutoResetEvent *p) { return AutoResetEvent_Create(p, 0); } + + +WRes Semaphore_Create(CSemaphore *p, UInt32 initCount, UInt32 maxCount) { - if (thread->handle == NULL) - return 1; - return WaitObject(thread->handle); + *p = CreateSemaphore(NULL, (LONG)initCount, (LONG)maxCount, NULL); + return HandleToWRes(*p); } -WRes Thread_Close(CThread *thread) -{ - return MyCloseHandle(&thread->handle); -} - -WRes Event_Create(CEvent *p, BOOL manualReset, int initialSignaled) -{ - p->handle = CreateEvent(NULL, manualReset, (initialSignaled ? TRUE : FALSE), NULL); - return HandleToWRes(p->handle); -} - -WRes ManualResetEvent_Create(CManualResetEvent *p, int initialSignaled) - { return Event_Create(p, TRUE, initialSignaled); } -WRes ManualResetEvent_CreateNotSignaled(CManualResetEvent *p) - { return ManualResetEvent_Create(p, 0); } - -WRes AutoResetEvent_Create(CAutoResetEvent *p, int initialSignaled) - { return Event_Create(p, FALSE, initialSignaled); } -WRes AutoResetEvent_CreateNotSignaled(CAutoResetEvent *p) - { return AutoResetEvent_Create(p, 0); } - -WRes Event_Set(CEvent *p) { return BOOLToWRes(SetEvent(p->handle)); } -WRes Event_Reset(CEvent *p) { return BOOLToWRes(ResetEvent(p->handle)); } -WRes Event_Wait(CEvent *p) { return WaitObject(p->handle); } -WRes Event_Close(CEvent *p) { return MyCloseHandle(&p->handle); } - - -WRes Semaphore_Create(CSemaphore *p, UInt32 initiallyCount, UInt32 maxCount) -{ - p->handle = CreateSemaphore(NULL, (LONG)initiallyCount, (LONG)maxCount, NULL); - return HandleToWRes(p->handle); -} - -WRes Semaphore_Release(CSemaphore *p, LONG releaseCount, LONG *previousCount) -{ - return BOOLToWRes(ReleaseSemaphore(p->handle, releaseCount, previousCount)); -} -WRes Semaphore_ReleaseN(CSemaphore *p, UInt32 releaseCount) -{ - return Semaphore_Release(p, (LONG)releaseCount, NULL); -} -WRes Semaphore_Release1(CSemaphore *p) -{ - return Semaphore_ReleaseN(p, 1); -} - -WRes Semaphore_Wait(CSemaphore *p) { return WaitObject(p->handle); } -WRes Semaphore_Close(CSemaphore *p) { return MyCloseHandle(&p->handle); } +static WRes Semaphore_Release(CSemaphore *p, LONG releaseCount, LONG *previousCount) + { return BOOLToWRes(ReleaseSemaphore(*p, releaseCount, previousCount)); } +WRes Semaphore_ReleaseN(CSemaphore *p, UInt32 num) + { return Semaphore_Release(p, (LONG)num, NULL); } +WRes Semaphore_Release1(CSemaphore *p) { return Semaphore_ReleaseN(p, 1); } WRes CriticalSection_Init(CCriticalSection *p) { /* InitializeCriticalSection can raise only STATUS_NO_MEMORY exception */ -#ifndef __GNUC__ + #ifdef _MSC_VER __try -#endif + #endif { InitializeCriticalSection(p); /* InitializeCriticalSectionAndSpinCount(p, 0); */ } -#ifndef __GNUC__ + #ifdef _MSC_VER __except (EXCEPTION_EXECUTE_HANDLER) { return 1; } -#endif + #endif return 0; } - -#else - -#include -#include - -#include - -#if defined(__linux__) -#define PTHREAD_MUTEX_ERRORCHECK PTHREAD_MUTEX_ERRORCHECK_NP -#endif - - -WRes Thread_Create(CThread *thread, THREAD_FUNC_RET_TYPE (THREAD_FUNC_CALL_TYPE *startAddress)(void *), void *parameter) -{ - pthread_attr_t attr; - int ret; - - thread->_created = 0; - - ret = pthread_attr_init(&attr); - if (ret) return ret; - - ret = pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_JOINABLE); - if (ret) return ret; - - ret = pthread_create(&thread->_tid, &attr, (void * (*)(void *))startAddress, parameter); - - /* ret2 = */ pthread_attr_destroy(&attr); - - if (ret) return ret; - - thread->_created = 1; - - return 0; // SZ_OK; -} - -WRes Thread_Wait(CThread *thread) -{ - void *thread_return; - int ret; - - if (thread->_created == 0) - return EINVAL; - - ret = pthread_join(thread->_tid,&thread_return); - thread->_created = 0; - - return ret; -} - -WRes Thread_Close(CThread *thread) -{ - if (!thread->_created) return SZ_OK; - - pthread_detach(thread->_tid); - thread->_tid = 0; - thread->_created = 0; - return SZ_OK; -} - -WRes Event_Create(CEvent *p, BOOL manualReset, int initialSignaled) -{ - pthread_mutex_init(&p->_mutex,0); - pthread_cond_init(&p->_cond,0); - p->_manual_reset = manualReset; - p->_state = (initialSignaled ? TRUE : FALSE); - p->_created = 1; - return 0; -} - -WRes Event_Set(CEvent *p) { - pthread_mutex_lock(&p->_mutex); - p->_state = TRUE; - pthread_cond_broadcast(&p->_cond); - pthread_mutex_unlock(&p->_mutex); - return 0; -} - -WRes Event_Reset(CEvent *p) { - pthread_mutex_lock(&p->_mutex); - p->_state = FALSE; - pthread_mutex_unlock(&p->_mutex); - return 0; -} - -WRes Event_Wait(CEvent *p) { - pthread_mutex_lock(&p->_mutex); - while (p->_state == FALSE) - { - pthread_cond_wait(&p->_cond, &p->_mutex); - } - if (p->_manual_reset == FALSE) - { - p->_state = FALSE; - } - pthread_mutex_unlock(&p->_mutex); - return 0; -} - -WRes Event_Close(CEvent *p) { - if (p->_created) - { - p->_created = 0; - pthread_mutex_destroy(&p->_mutex); - pthread_cond_destroy(&p->_cond); - } - return 0; -} - -WRes Semaphore_Create(CSemaphore *p, UInt32 initiallyCount, UInt32 maxCount) -{ - pthread_mutex_init(&p->_mutex,0); - pthread_cond_init(&p->_cond,0); - p->_count = initiallyCount; - p->_maxCount = maxCount; - p->_created = 1; - return 0; -} - -WRes Semaphore_ReleaseN(CSemaphore *p, UInt32 releaseCount) -{ - UInt32 newCount; - - if (releaseCount < 1) return EINVAL; - - pthread_mutex_lock(&p->_mutex); - - newCount = p->_count + releaseCount; - if (newCount > p->_maxCount) - { - pthread_mutex_unlock(&p->_mutex); - return EINVAL; - } - p->_count = newCount; - pthread_cond_broadcast(&p->_cond); - pthread_mutex_unlock(&p->_mutex); - return 0; -} - -WRes Semaphore_Wait(CSemaphore *p) { - pthread_mutex_lock(&p->_mutex); - while (p->_count < 1) - { - pthread_cond_wait(&p->_cond, &p->_mutex); - } - p->_count--; - pthread_mutex_unlock(&p->_mutex); - return 0; -} - -WRes Semaphore_Close(CSemaphore *p) { - if (p->_created) - { - p->_created = 0; - pthread_mutex_destroy(&p->_mutex); - pthread_cond_destroy(&p->_cond); - } - return 0; -} - -WRes CriticalSection_Init(CCriticalSection * lpCriticalSection) -{ - return pthread_mutex_init(&(lpCriticalSection->_mutex),0); -} - -WRes ManualResetEvent_Create(CManualResetEvent *p, int initialSignaled) - { return Event_Create(p, TRUE, initialSignaled); } - -WRes ManualResetEvent_CreateNotSignaled(CManualResetEvent *p) - { return ManualResetEvent_Create(p, 0); } - -WRes AutoResetEvent_Create(CAutoResetEvent *p, int initialSignaled) - { return Event_Create(p, FALSE, initialSignaled); } -WRes AutoResetEvent_CreateNotSignaled(CAutoResetEvent *p) - { return AutoResetEvent_Create(p, 0); } - -#endif diff --git a/lzma/C/Threads.h b/lzma/C/Threads.h index c895c7e51..b82214355 100644 --- a/lzma/C/Threads.h +++ b/lzma/C/Threads.h @@ -1,151 +1,66 @@ /* Threads.h -- multithreading library -2008-11-22 : Igor Pavlov : Public domain */ +2009-03-27 : Igor Pavlov : Public domain */ -#ifndef __7Z_THRESDS_H -#define __7Z_THRESDS_H +#ifndef __7Z_THREADS_H +#define __7Z_THREADS_H + +#include "Types.h" #ifdef _WIN32 #include typedef DWORD WRes; +#else +typedef int WRes; +#endif -#include "Types.h" +#ifdef __cplusplus +extern "C" { +#endif -typedef struct _CThread -{ - HANDLE handle; -} CThread; +WRes HandlePtr_Close(HANDLE *h); +WRes Handle_WaitObject(HANDLE h); -#define Thread_Construct(thread) (thread)->handle = NULL -#define Thread_WasCreated(thread) ((thread)->handle != NULL) - +typedef HANDLE CThread; +#define Thread_Construct(p) *(p) = NULL +#define Thread_WasCreated(p) (*(p) != NULL) +#define Thread_Close(p) HandlePtr_Close(p) +#define Thread_Wait(p) Handle_WaitObject(*(p)) typedef unsigned THREAD_FUNC_RET_TYPE; -#define THREAD_FUNC_CALL_TYPE __stdcall +#define THREAD_FUNC_CALL_TYPE MY_STD_CALL #define THREAD_FUNC_DECL THREAD_FUNC_RET_TYPE THREAD_FUNC_CALL_TYPE +typedef THREAD_FUNC_RET_TYPE (THREAD_FUNC_CALL_TYPE * THREAD_FUNC_TYPE)(void *); +WRes Thread_Create(CThread *p, THREAD_FUNC_TYPE func, LPVOID param); -WRes Thread_Create(CThread *thread, THREAD_FUNC_RET_TYPE (THREAD_FUNC_CALL_TYPE *startAddress)(void *), LPVOID parameter); -WRes Thread_Wait(CThread *thread); -WRes Thread_Close(CThread *thread); - -typedef struct _CEvent -{ - HANDLE handle; -} CEvent; - +typedef HANDLE CEvent; typedef CEvent CAutoResetEvent; typedef CEvent CManualResetEvent; +#define Event_Construct(p) *(p) = NULL +#define Event_IsCreated(p) (*(p) != NULL) +#define Event_Close(p) HandlePtr_Close(p) +#define Event_Wait(p) Handle_WaitObject(*(p)) +WRes Event_Set(CEvent *p); +WRes Event_Reset(CEvent *p); +WRes ManualResetEvent_Create(CManualResetEvent *p, int signaled); +WRes ManualResetEvent_CreateNotSignaled(CManualResetEvent *p); +WRes AutoResetEvent_Create(CAutoResetEvent *p, int signaled); +WRes AutoResetEvent_CreateNotSignaled(CAutoResetEvent *p); -#define Event_Construct(event) (event)->handle = NULL -#define Event_IsCreated(event) ((event)->handle != NULL) - -WRes ManualResetEvent_Create(CManualResetEvent *event, int initialSignaled); -WRes ManualResetEvent_CreateNotSignaled(CManualResetEvent *event); -WRes AutoResetEvent_Create(CAutoResetEvent *event, int initialSignaled); -WRes AutoResetEvent_CreateNotSignaled(CAutoResetEvent *event); -WRes Event_Set(CEvent *event); -WRes Event_Reset(CEvent *event); -WRes Event_Wait(CEvent *event); -WRes Event_Close(CEvent *event); - - -typedef struct _CSemaphore -{ - HANDLE handle; -} CSemaphore; - -#define Semaphore_Construct(p) (p)->handle = NULL - -WRes Semaphore_Create(CSemaphore *p, UInt32 initiallyCount, UInt32 maxCount); +typedef HANDLE CSemaphore; +#define Semaphore_Construct(p) (*p) = NULL +#define Semaphore_Close(p) HandlePtr_Close(p) +#define Semaphore_Wait(p) Handle_WaitObject(*(p)) +WRes Semaphore_Create(CSemaphore *p, UInt32 initCount, UInt32 maxCount); WRes Semaphore_ReleaseN(CSemaphore *p, UInt32 num); WRes Semaphore_Release1(CSemaphore *p); -WRes Semaphore_Wait(CSemaphore *p); -WRes Semaphore_Close(CSemaphore *p); - typedef CRITICAL_SECTION CCriticalSection; - WRes CriticalSection_Init(CCriticalSection *p); #define CriticalSection_Delete(p) DeleteCriticalSection(p) #define CriticalSection_Enter(p) EnterCriticalSection(p) #define CriticalSection_Leave(p) LeaveCriticalSection(p) -#else -typedef int WRes; - -#include "Types.h" -#include - -/* #define DEBUG_SYNCHRO 1 */ - -typedef struct _CThread -{ - pthread_t _tid; - int _created; - -} CThread; - -#define Thread_Construct(thread) (thread)->_created = 0 -#define Thread_WasCreated(thread) ((thread)->_created != 0) - -typedef unsigned THREAD_FUNC_RET_TYPE; -#define THREAD_FUNC_CALL_TYPE -#define THREAD_FUNC_DECL THREAD_FUNC_RET_TYPE THREAD_FUNC_CALL_TYPE - -WRes Thread_Create(CThread *thread, THREAD_FUNC_RET_TYPE (THREAD_FUNC_CALL_TYPE *startAddress)(void *), void *parameter); -WRes Thread_Wait(CThread *thread); -WRes Thread_Close(CThread *thread); - -typedef struct _CEvent -{ - int _created; - int _manual_reset; - int _state; - pthread_mutex_t _mutex; - pthread_cond_t _cond; -} CEvent; - -typedef CEvent CAutoResetEvent; -typedef CEvent CManualResetEvent; - -#define Event_Construct(event) (event)->_created = 0 -#define Event_IsCreated(event) ((event)->_created) - -WRes ManualResetEvent_Create(CManualResetEvent *event, int initialSignaled); -WRes ManualResetEvent_CreateNotSignaled(CManualResetEvent *event); -WRes AutoResetEvent_Create(CAutoResetEvent *event, int initialSignaled); -WRes AutoResetEvent_CreateNotSignaled(CAutoResetEvent *event); -WRes Event_Set(CEvent *event); -WRes Event_Reset(CEvent *event); -WRes Event_Wait(CEvent *event); -WRes Event_Close(CEvent *event); - - -typedef struct _CSemaphore -{ - int _created; - UInt32 _count; - UInt32 _maxCount; - pthread_mutex_t _mutex; - pthread_cond_t _cond; -} CSemaphore; - -#define Semaphore_Construct(p) (p)->_created = 0 - -WRes Semaphore_Create(CSemaphore *p, UInt32 initiallyCount, UInt32 maxCount); -WRes Semaphore_ReleaseN(CSemaphore *p, UInt32 num); -#define Semaphore_Release1(p) Semaphore_ReleaseN(p, 1) -WRes Semaphore_Wait(CSemaphore *p); -WRes Semaphore_Close(CSemaphore *p); - -typedef struct { - pthread_mutex_t _mutex; -} CCriticalSection; - -WRes CriticalSection_Init(CCriticalSection *p); -#define CriticalSection_Delete(p) pthread_mutex_destroy(&((p)->_mutex)) -#define CriticalSection_Enter(p) pthread_mutex_lock(&((p)->_mutex)) -#define CriticalSection_Leave(p) pthread_mutex_unlock(&((p)->_mutex)) - +#ifdef __cplusplus +} #endif #endif - diff --git a/lzma/C/Types.h b/lzma/C/Types.h index 958b2af2d..284991104 100644 --- a/lzma/C/Types.h +++ b/lzma/C/Types.h @@ -1,14 +1,22 @@ /* Types.h -- Basic types -2008-11-23 : Igor Pavlov : Public domain */ +2010-10-09 : Igor Pavlov : Public domain */ #ifndef __7Z_TYPES_H #define __7Z_TYPES_H #include +#ifndef EXTERN_C_BEGIN #ifdef __cplusplus -extern "C" { +#define EXTERN_C_BEGIN extern "C" { +#define EXTERN_C_END } +#else +#define EXTERN_C_BEGIN +#define EXTERN_C_END #endif +#endif + +EXTERN_C_BEGIN #define SZ_OK 0 @@ -37,10 +45,8 @@ typedef int SRes; #if defined(__APPLE__) && !__LP64__ #define _LZMA_UINT32_IS_ULONG #endif - -#ifndef ZCONF_H + typedef unsigned char Byte; -#endif typedef short Int16; typedef unsigned short UInt16; @@ -65,9 +71,11 @@ typedef unsigned long UInt64; #if defined(_MSC_VER) || defined(__BORLANDC__) typedef __int64 Int64; typedef unsigned __int64 UInt64; +#define UINT64_CONST(n) n #else typedef long long int Int64; typedef unsigned long long int UInt64; +#define UINT64_CONST(n) n ## ULL #endif #endif @@ -83,6 +91,12 @@ typedef int Bool; #define False 0 +#ifdef _WIN32 +#define MY_STD_CALL __stdcall +#else +#define MY_STD_CALL +#endif + #ifdef _MSC_VER #if _MSC_VER >= 1300 @@ -92,13 +106,11 @@ typedef int Bool; #endif #define MY_CDECL __cdecl -#define MY_STD_CALL __stdcall -#define MY_FAST_CALL MY_NO_INLINE __fastcall +#define MY_FAST_CALL __fastcall #else #define MY_CDECL -#define MY_STD_CALL #define MY_FAST_CALL #endif @@ -106,6 +118,16 @@ typedef int Bool; /* The following interfaces use first parameter as pointer to structure */ +typedef struct +{ + Byte (*Read)(void *p); /* reads one byte, returns 0 in case of EOF or error */ +} IByteIn; + +typedef struct +{ + void (*Write)(void *p, Byte b); +} IByteOut; + typedef struct { SRes (*Read)(void *p, void *buf, size_t *size); @@ -140,7 +162,7 @@ typedef struct typedef struct { - SRes (*Look)(void *p, void **buf, size_t *size); + SRes (*Look)(void *p, const void **buf, size_t *size); /* if (input(*size) != 0 && output(*size) == 0) means end_of_stream. (output(*size) > input(*size)) is not allowed (output(*size) < input(*size)) is allowed */ @@ -205,8 +227,22 @@ typedef struct #define IAlloc_Alloc(p, size) (p)->Alloc((p), size) #define IAlloc_Free(p, a) (p)->Free((p), a) -#ifdef __cplusplus -} -#endif +#ifdef _WIN32 + +#define CHAR_PATH_SEPARATOR '\\' +#define WCHAR_PATH_SEPARATOR L'\\' +#define STRING_PATH_SEPARATOR "\\" +#define WSTRING_PATH_SEPARATOR L"\\" + +#else + +#define CHAR_PATH_SEPARATOR '/' +#define WCHAR_PATH_SEPARATOR L'/' +#define STRING_PATH_SEPARATOR "/" +#define WSTRING_PATH_SEPARATOR L"/" + +#endif + +EXTERN_C_END #endif diff --git a/lzma/CMakeLists.txt b/lzma/CMakeLists.txt index 7582712fe..beebb0fde 100644 --- a/lzma/CMakeLists.txt +++ b/lzma/CMakeLists.txt @@ -1,29 +1,31 @@ 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" ) set( LZMA_FILES - C/Archive/7z/7zDecode.c - C/Archive/7z/7zExtract.c - C/Archive/7z/7zHeader.c - C/Archive/7z/7zIn.c - C/Archive/7z/7zItem.c C/7zBuf.c C/7zCrc.c + C/7zCrcOpt.c + C/7zDec.c + C/7zIn.c C/7zStream.c - C/Alloc.c - C/Bcj2.c - C/Bra86.c - C/LzFind.c - C/LzFindMt.c - C/LzmaDec.c - C/LzmaEnc.c - C/LzmaLib.c ) + C/Bcj2.c + C/Bra.c + C/Bra86.c + C/CpuArch.c + C/LzFind.c + C/Lzma2Dec.c + C/LzmaDec.c + C/LzmaEnc.c ) if( WIN32 ) - set( LZMA_FILES ${LZMA_FILES} C/Threads.c ) + set( LZMA_FILES ${LZMA_FILES} C/LzFindMt.c C/Threads.c ) +else( WIN32 ) + set( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -D_7ZIP_ST" ) endif( WIN32 ) add_library( lzma ${LZMA_FILES} ) diff --git a/lzma/history.txt b/lzma/history.txt old mode 100644 new mode 100755 index 9bed5ebbe..50ff40f02 --- a/lzma/history.txt +++ b/lzma/history.txt @@ -1,6 +1,41 @@ HISTORY of the LZMA SDK ----------------------- +9.18 beta 2010-11-02 +------------------------- +- New small SFX module for installers (SfxSetup). + + +9.12 beta 2010-03-24 +------------------------- +- The BUG in LZMA SDK 9.* was fixed: LZMA2 codec didn't work, + if more than 10 threads were used (or more than 20 threads in some modes). + + +9.11 beta 2010-03-15 +------------------------- +- PPMd compression method support + + +9.09 2009-12-12 +------------------------- +- The bug was fixed: + Utf16_To_Utf8 funstions in UTFConvert.cpp and 7zMain.c + incorrectly converted surrogate characters (the code >= 0x10000) to UTF-8. +- Some bugs were fixed + + +9.06 2009-08-17 +------------------------- +- Some changes in ANSI-C 7z Decoder interfaces. + + +9.04 2009-05-30 +------------------------- +- LZMA2 compression method support +- xz format support + + 4.65 2009-02-03 ------------------------- - Some minor fixes diff --git a/lzma/lzma.txt b/lzma/lzma.txt old mode 100644 new mode 100755 index d4f4af929..579f2ccd8 --- a/lzma/lzma.txt +++ b/lzma/lzma.txt @@ -1,4 +1,4 @@ -LZMA SDK 4.65 +LZMA SDK 9.20 ------------- LZMA SDK provides the documentation, samples, header files, libraries, @@ -20,6 +20,10 @@ LICENSE LZMA SDK is written and placed in the public domain by Igor Pavlov. +Some code in LZMA SDK is based on public domain code from another developers: + 1) PPMd var.H (2001): Dmitry Shkarin + 2) SHA-256: Wei Dai (Crypto++ library) + LZMA SDK Contents ----------------- @@ -33,7 +37,7 @@ LZMA SDK includes: UNIX/Linux version ------------------ To compile C++ version of file->file LZMA encoding, go to directory -C++/7zip/Compress/LZMA_Alone +CPP/7zip/Bundles/LzmaCon and call make to recompile it: make -f makefile.gcc clean all @@ -49,6 +53,7 @@ lzma.txt - LZMA SDK description (this file) 7zC.txt - 7z ANSI-C Decoder description methods.txt - Compression method IDs for .7z lzma.exe - Compiled file->file LZMA encoder/decoder for Windows +7zr.exe - 7-Zip with 7z/lzma/xz support. history.txt - history of the LZMA SDK @@ -66,7 +71,7 @@ C/ - C files LzmaEnc.* - LZMA encoding LzmaLib.* - LZMA Library for DLL calling Types.h - Basic types for another .c files - Threads.* - The code for multithreading. + Threads.* - The code for multithreading. LzmaLib - LZMA Library (.DLL for Windows) @@ -86,12 +91,6 @@ CPP/ -- CPP files Compress - files related to compression/decompression - Copy - Copy coder - RangeCoder - Range Coder (special code of compression/decompression) - LZMA - LZMA compression/decompression on C++ - LZMA_Alone - file->file LZMA compression/decompression - Branch - Filters for x86, IA-64, ARM, ARM-Thumb, PowerPC and SPARC code - Archive - files related to archiving Common - common files for archive handling @@ -100,6 +99,7 @@ CPP/ -- CPP files Bundles - Modules that are bundles of other modules Alone7z - 7zr.exe: Standalone version of 7z.exe that supports only 7z/LZMA/BCJ/BCJ2 + LzmaCon - lzma.exe: LZMA compression/decompression Format7zR - 7zr.dll: Reduced version of 7za.dll: extracting/compressing to 7z/LZMA/BCJ/BCJ2 Format7zExtractR - 7zxr.dll: Reduced version of 7zxa.dll: extracting from 7z/LZMA/BCJ/BCJ2. @@ -369,8 +369,8 @@ Interface: propData - LZMA properties (5 bytes) propSize - size of propData buffer (5 bytes) finishMode - It has meaning only if the decoding reaches output limit (*destLen). - LZMA_FINISH_ANY - Decode just destLen bytes. - LZMA_FINISH_END - Stream must be finished after (*destLen). + LZMA_FINISH_ANY - Decode just destLen bytes. + LZMA_FINISH_END - Stream must be finished after (*destLen). You can use LZMA_FINISH_END, when you know that current output buffer covers last bytes of stream. alloc - Memory allocator. @@ -431,7 +431,7 @@ Memory Requirements: { ... int res = LzmaDec_DecodeToBuf(CLzmaDec *p, Byte *dest, SizeT *destLen, - const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode); + const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode); ... } @@ -527,7 +527,8 @@ static ISzAlloc g_Alloc = { SzAlloc, SzFree }; LzmaEnc_Destroy(enc, &g_Alloc, &g_Alloc); -If callback function return some error code, LzmaEnc_Encode also returns that code. +If callback function return some error code, LzmaEnc_Encode also returns that code +or it can return the code like SZ_ERROR_READ, SZ_ERROR_WRITE or SZ_ERROR_PROGRESS. Single-call RAM->RAM Compression @@ -549,8 +550,8 @@ Return code: -LZMA Defines ------------- +Defines +------- _LZMA_SIZE_OPT - Enable some optimizations in LZMA Decoder to get smaller executable code. @@ -562,6 +563,9 @@ _LZMA_UINT32_IS_ULONG - Define it if int is 16-bit on your compiler and long is _LZMA_NO_SYSTEM_SIZE_T - Define it if you don't want to use size_t type. +_7ZIP_PPMD_SUPPPORT - Define it if you don't want to support PPMD method in AMSI-C .7z decoder. + + C++ LZMA Encoder/Decoder ~~~~~~~~~~~~~~~~~~~~~~~~ C++ LZMA code use COM-like interfaces. So if you want to use it, diff --git a/lzma/lzmalib.vcproj b/lzma/lzmalib.vcproj index 414e26f8d..b37a52970 100644 --- a/lzma/lzmalib.vcproj +++ b/lzma/lzmalib.vcproj @@ -295,21 +295,37 @@ > + + + + + + + + @@ -318,6 +334,10 @@ RelativePath=".\C\LzFindMt.c" > + + @@ -326,10 +346,6 @@ RelativePath=".\C\LzmaEnc.c" > - - @@ -340,6 +356,10 @@ Filter="h;hpp;hxx;hm;inl;inc;xsd" UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}" > + + @@ -352,10 +372,6 @@ RelativePath=".\C\7zVersion.h" > - - @@ -380,6 +396,10 @@ RelativePath=".\C\LzHash.h" > + + @@ -388,10 +408,6 @@ RelativePath=".\C\LzmaEnc.h" > - - @@ -401,50 +417,6 @@ > - - - - - - - - - - - - - - - - - - - - - - diff --git a/specs/udmf_zdoom.txt b/specs/udmf_zdoom.txt index 3241bf4c8..1128b2e55 100644 --- a/specs/udmf_zdoom.txt +++ b/specs/udmf_zdoom.txt @@ -37,7 +37,7 @@ In addition to the base specification ZDoom recognizes the following lumps between the TEXTMAP and ENDMAP lumps: BEHAVIOR = contains compiled ACS code - DIALOGUE = contains compiled Strife conversation scripts. + DIALOGUE = contains compiled Strife or USDF conversation scripts. ZNODES = Nodes (must be stored as extended GL nodes. Compression is allowed but deprecated for portability reasons.) BLOCKMAP = blockmap. It is recommended not to include this lump in UDMF maps. @@ -117,6 +117,8 @@ Note: All fields default to false unless mentioned otherwise. locknumber = ; // Line special is locked arg0str = ; // Alternate string-based version of arg0 + transparent = ; // true = line is a Strife transparent line (alpha 0.25) + * Note about arg0str For lines with ACS specials (80-86 and 226), if arg0str is present and non-null, it @@ -164,6 +166,14 @@ Note: All fields default to false unless mentioned otherwise. yscaleceiling = ; // Y texture scale of ceiling texture, Default = 1.0. rotationfloor = ; // Rotation of floor texture in degrees, Default = 0.0. rotationceiling = ; // Rotation of ceiling texture in degrees, Default = 0.0. + ceilingplane_a = ; // Define the plane equation for the sector's ceiling. Default is a horizontal plane at 'heightceiling'. + ceilingplane_b = ; // 'heightceiling' will still be used to calculate texture alignment. + ceilingplane_c = ; // The plane equation will only be used if all 4 values are given. + ceilingplane_d = ; + floorplane_a = ; // Define the plane equation for the sector's floor. Default is a horizontal plane at 'heightfloor'. + floorplane_b = ; // 'heightfloor' will still be used to calculate texture alignment. + floorplane_c = ; // The plane equation will only be used if all 4 values are given. + floorplane_d = ; lightfloor = ; // The floor's light level. Default is 0. lightceiling = ; // The ceiling's light level. Default is 0. lightfloorabsolute = ; // true = 'lightfloor' is an absolute value. Default is @@ -207,6 +217,21 @@ Note: All fields default to false unless mentioned otherwise. arg0str = ; // Alternate string-based version of arg0 gravity = ; // Set per-actor gravity. Positive values are multiplied with the class's property, // negative values are used as their absolute. Default = 1.0. + + health = ; // Set per-actor health. Positive values are multiplied with the class's property, + // negative values are used as their absolute. Default = 1. + + renderstyle = ; // Set per-actor render style, overriding the class default. Possible values can be "normal", + // "none", "add" or "additive", "subtract" or "subtractive", "stencil", "translucentstencil", + // "translucent", "fuzzy", "optfuzzy", "soultrans". Default is an empty string for no change. + fillcolor = ; // Fill color used by the "stencil" and "translucentstencil" rendestyles, as RRGGBB value, default = 0x000000. + alpha = ; // Translucency of this actor (if applicable to renderstyle), default is 1.0. + score = ; // Score value of this actor, overriding the class default if not null. Default = 0. + pitch = ; // Pitch of thing in degrees. Default = 0 (horizontal). + roll = ; // Pitch of thing in degrees. Default = 0 (horizontal). + scalex = ; // Vertical scaling on thing. Default = 0 (ignored). + scaley = ; // Horizontal scaling on thing. Default = 0 (ignored). + scale = ; // Vertical and horizontal scaling on thing. Default = 0 (ignored). * Note about arg0str @@ -335,6 +360,13 @@ Added arg0str thing property. 1.21 09.08.2013 Added waterzone sector property. +1.22 12.04.2014 +Added transparent line property (to be folded back to core UDMF standard), and health, score, renderstyle, fillcolor, alpha, scale, scalex, scaley, pitch and roll thing properties. + +1.24 14.05.2014 +Added plane equations for sector slopes. (Please read carefully to ensure proper use!) +Changed language describing the DIALOGUE lump to mention USDF as an option. + =============================================================================== EOF =============================================================================== diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 43572ff14..2a74d865e 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -24,7 +24,7 @@ if( "${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" OR "${CMAKE_CXX_COMPILER_ID}" STRE endif( APPLE ) endif( "${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" OR "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang" ) -option( DYN_FLUIDSYNTH "Dynamically load fluidsynth" ) +option( DYN_FLUIDSYNTH "Dynamically load fluidsynth" ON ) if( CMAKE_SIZEOF_VOID_P MATCHES "8" ) set( X64 64 ) @@ -50,6 +50,20 @@ set( MINOR_VERSIONS "50" "49" "48" "47" "46" "45" "44" "43" "42" "41" "15" "14" "13" "12" "11" "10" "09" "08" "07" "06" "05" "04" "03" "02" "01" "00" ) set( MAJOR_VERSIONS "44" "34" "28" "26" "24" "22" "20" ) + +if( NOT FMOD_DIR_VERSIONS ) + set( FMOD_DIR_VERSIONS "" ) +endif( NOT FMOD_DIR_VERSIONS ) +if( NOT FMOD_VERSIONS ) + set( FMOD_VERSIONS "" ) +endif( NOT FMOD_VERSIONS ) +if( NOT FMOD_LOCAL_INC_DIRS ) + set( FMOD_LOCAL_INC_DIRS "" ) +endif( NOT FMOD_LOCAL_INC_DIRS ) +if( NOT FMOD_LOCAL_LIB_DIRS ) + set( FMOD_LOCAL_LIB_DIRS "" ) +endif( NOT FMOD_LOCAL_LIB_DIRS ) + set( FMOD_DIR_VERSIONS ${FMOD_DIR_VERSIONS} "../fmod" ) foreach( majver ${MAJOR_VERSIONS} ) foreach( minver ${MINOR_VERSIONS} ) @@ -62,6 +76,10 @@ foreach( majver ${MAJOR_VERSIONS} ) endforeach( dir ${FMOD_DIR_VERSIONS} ) endforeach( majver ${MAJOR_VERSIONS} ) +if( NOT ZDOOM_LIBS ) + set( ZDOOM_LIBS "" ) +endif( NOT ZDOOM_LIBS ) + if( WIN32 ) if( X64 ) set( WIN_TYPE Win64 ) @@ -104,9 +122,6 @@ if( WIN32 ) include_directories( ${XINPUT_INCLUDE_DIR} ) endif( NOT XINPUT_INCLUDE_DIR ) - find_library( DX_ddraw_LIBRARY ddraw - PATHS ENV DXSDK_DIR - PATH_SUFFIXES Lib Lib/${XBITS} ) find_library( DX_dxguid_LIBRARY dxguid PATHS ENV DXSDK_DIR PATH_SUFFIXES Lib Lib/${XBITS} ) @@ -115,9 +130,6 @@ if( WIN32 ) PATH_SUFFIXES Lib Lib/${XBITS} ) set( DX_LIBS_FOUND YES ) - if( NOT DX_ddraw_LIBRARY ) - set( DX_LIBS_FOUND NO ) - endif( NOT DX_ddraw_LIBRARY ) if( NOT DX_dxguid_LIBRARY ) set( DX_LIBS_FOUND NO ) endif( NOT DX_dxguid_LIBRARY ) @@ -132,7 +144,6 @@ if( WIN32 ) set( ZDOOM_LIBS wsock32 winmm - "${DX_ddraw_LIBRARY}" "${DX_dxguid_LIBRARY}" "${DX_dinput8_LIBRARY}" ole32 @@ -142,7 +153,8 @@ if( WIN32 ) comdlg32 ws2_32 setupapi - oleaut32 ) + oleaut32 + DelayImp ) else( WIN32 ) if( APPLE ) set( FMOD_SEARCH_PATHS "/Developer/FMOD Programmers API Mac/api" ) @@ -377,12 +389,16 @@ if( NOT NO_ASM ) endif( UNIX ) if( WIN32 ) set( FIXRTEXT fixrtext ) + else( WIN32 ) + set( FIXRTEXT "" ) endif( WIN32 ) message( STATUS "Selected assembler: ${ASSEMBLER}" ) MACRO( ADD_ASM_FILE indir infile ) set( ASM_OUTPUT_${infile} "${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/zdoom.dir/${indir}/${infile}${ASM_OUTPUT_EXTENSION}" ) if( WIN32 ) set( FIXRTEXT_${infile} COMMAND ${FIXRTEXT} "${ASM_OUTPUT_${infile}}" ) + else( WIN32 ) + set( FIXRTEXT_${infile} COMMAND "" ) endif( WIN32 ) add_custom_command( OUTPUT ${ASM_OUTPUT_${infile}} COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/zdoom.dir/${indir} @@ -397,20 +413,23 @@ endif( NOT NO_ASM ) set( SSE_MATTERS NO ) -# SSE only matters on 32-bit targets. We check compiler flags to know if we can do it. -if( CMAKE_SIZEOF_VOID_P MATCHES "4" AND NOT CMAKE_OSX_ARCHITECTURES MATCHES ppc ) - CHECK_CXX_COMPILER_FLAG( "-msse2 -mfpmath=sse" CAN_DO_MFPMATH ) - CHECK_CXX_COMPILER_FLAG( -arch:SSE2 CAN_DO_ARCHSSE2 ) - if( CAN_DO_MFPMATH ) - set( SSE1_ENABLE "-msse -mfpmath=sse" ) - set( SSE2_ENABLE "-msse2 -mfpmath=sse" ) - set( SSE_MATTERS YES ) - elseif( CAN_DO_ARCHSSE2 ) - set( SSE1_ENABLE -arch:SSE ) - set( SSE2_ENABLE -arch:SSE2 ) - set( SSE_MATTERS YES ) - endif( CAN_DO_MFPMATH ) -endif( CMAKE_SIZEOF_VOID_P MATCHES "4" AND NOT CMAKE_OSX_ARCHITECTURES MATCHES ppc ) +# with global use of SSE 2 we do not need special handling for selected files +if (NOT ZDOOM_USE_SSE2) + # SSE only matters on 32-bit targets. We check compiler flags to know if we can do it. + if( CMAKE_SIZEOF_VOID_P MATCHES "4" AND NOT CMAKE_OSX_ARCHITECTURES MATCHES ppc ) + CHECK_CXX_COMPILER_FLAG( "-msse2 -mfpmath=sse" CAN_DO_MFPMATH ) + CHECK_CXX_COMPILER_FLAG( -arch:SSE2 CAN_DO_ARCHSSE2 ) + if( CAN_DO_MFPMATH ) + set( SSE1_ENABLE "-msse -mfpmath=sse" ) + set( SSE2_ENABLE "-msse2 -mfpmath=sse" ) + set( SSE_MATTERS YES ) + elseif( CAN_DO_ARCHSSE2 ) + set( SSE1_ENABLE -arch:SSE ) + set( SSE2_ENABLE -arch:SSE2 ) + set( SSE_MATTERS YES ) + endif( CAN_DO_MFPMATH ) + endif( CMAKE_SIZEOF_VOID_P MATCHES "4" AND NOT CMAKE_OSX_ARCHITECTURES MATCHES ppc ) +endif (NOT ZDOOM_USE_SSE2) if( SSE_MATTERS ) if( WIN32 ) @@ -446,7 +465,7 @@ if( "${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" OR "${CMAKE_CXX_COMPILER_ID}" STRE set( CMAKE_CXX_FLAGS_MINSIZEREL "${REL_CXX_FLAGS} ${CMAKE_CXX_FLAGS_MINSIZEREL}" ) set( CMAKE_CXX_FLAGS_RELWITHDEBINFO "${REL_CXX_FLAGS} ${CMAKE_CXX_FLAGS_RELWITHDEBINFO}" ) - set( CMAKE_CXX_FLAGS "-Wall -Wno-unused -Wextra -Wno-missing-field-initializers ${CMAKE_CXX_FLAGS}" ) + set( CMAKE_CXX_FLAGS "-Wall -Wextra -Wno-unused -Wno-unused-parameter -Wno-missing-field-initializers ${CMAKE_CXX_FLAGS}" ) # Remove extra warnings when using the official DirectX headers. # Also, TDM-GCC 4.4.0 no longer accepts glibc-style printf formats as valid, @@ -534,40 +553,59 @@ add_custom_target( revision_check ALL # Libraries ZDoom needs message( STATUS "Fluid synth libs: ${FLUIDSYNTH_LIBRARIES}" ) -set( ZDOOM_LIBS ${ZDOOM_LIBS} "${ZLIB_LIBRARIES}" "${JPEG_LIBRARIES}" "${BZIP2_LIBRARIES}" "${FMOD_LIBRARY}" ) -include_directories( "${ZLIB_INCLUDE_DIR}" "${BZIP2_INCLUDE_DIR}" "${LZMA_INCLUDE_DIR}" "${JPEG_INCLUDE_DIR}" ) +set( ZDOOM_LIBS ${ZDOOM_LIBS} "${ZLIB_LIBRARIES}" "${JPEG_LIBRARIES}" "${BZIP2_LIBRARIES}" "${GME_LIBRARIES}" ) +include_directories( "${ZLIB_INCLUDE_DIR}" "${BZIP2_INCLUDE_DIR}" "${LZMA_INCLUDE_DIR}" "${JPEG_INCLUDE_DIR}" "${GME_INCLUDE_DIR}" ) -if( FLUIDSYNTH_FOUND ) - if( NOT DYN_FLUIDSYNTH) - set( ZDOOM_LIBS ${ZDOOM_LIBS} "${FLUIDSYNTH_LIBRARIES}" ) - include_directories( "${FLUIDSYNTH_INCLUDE_DIR}" ) - endif( NOT DYN_FLUIDSYNTH ) -endif( FLUIDSYNTH_FOUND ) +if( NOT DYN_FLUIDSYNTH) + if( FLUIDSYNTH_FOUND ) + set( ZDOOM_LIBS ${ZDOOM_LIBS} "${FLUIDSYNTH_LIBRARIES}" ) + include_directories( "${FLUIDSYNTH_INCLUDE_DIR}" ) + endif( FLUIDSYNTH_FOUND ) +else( NOT DYN_FLUIDSYNTH ) + set( ZDOOM_LIBS ${ZDOOM_LIBS} ${CMAKE_DL_LIBS} ) +endif( NOT DYN_FLUIDSYNTH ) # Start defining source files for ZDoom - +set( PLAT_WIN32_SOURCES + win32/eaxedit.cpp + win32/fb_d3d9.cpp + win32/fb_d3d9_wipe.cpp + win32/fb_ddraw.cpp + win32/hardware.cpp + win32/helperthread.cpp + win32/i_cd.cpp + win32/i_crash.cpp + win32/i_input.cpp + win32/i_keyboard.cpp + win32/i_mouse.cpp + win32/i_dijoy.cpp + win32/i_rawps2.cpp + win32/i_xinput.cpp + win32/i_main.cpp + win32/i_movie.cpp + win32/i_system.cpp + win32/st_start.cpp + win32/win32video.cpp ) +set( PLAT_SDL_SOURCES + sdl/crashcatcher.c + sdl/hardware.cpp + sdl/i_cd.cpp + sdl/i_input.cpp + sdl/i_joystick.cpp + sdl/i_main.cpp + sdl/i_movie.cpp + sdl/i_system.cpp + sdl/sdlvideo.cpp + sdl/st_start.cpp ) +set( PLAT_MAC_SOURCES + sdl/SDLMain.m + sdl/iwadpicker_cocoa.mm + sdl/i_system_cocoa.mm ) if( WIN32 ) set( SYSTEM_SOURCES_DIR win32 ) - set( SYSTEM_SOURCES - win32/eaxedit.cpp - win32/fb_d3d9.cpp - win32/fb_d3d9_wipe.cpp - win32/fb_ddraw.cpp - win32/hardware.cpp - win32/helperthread.cpp - win32/i_cd.cpp - win32/i_crash.cpp - win32/i_input.cpp - win32/i_keyboard.cpp - win32/i_mouse.cpp - win32/i_dijoy.cpp - win32/i_rawps2.cpp - win32/i_xinput.cpp - win32/i_main.cpp - win32/i_movie.cpp - win32/i_system.cpp - win32/st_start.cpp - win32/win32video.cpp ) + set( SYSTEM_SOURCES ${PLAT_WIN32_SOURCES} ) + set( OTHER_SYSTEM_SOURCES ${PLAT_SDL_SOURCES} ${PLAT_MAC_SOURCES} ) + if( "${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" OR "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang" ) # CMake is not set up to compile and link rc files with GCC. :( add_custom_command( OUTPUT zdoom-rc.o @@ -579,25 +617,21 @@ if( WIN32 ) endif( "${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" OR "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang" ) else( WIN32 ) set( SYSTEM_SOURCES_DIR sdl ) - set( SYSTEM_SOURCES - sdl/crashcatcher.c - sdl/hardware.cpp - sdl/i_cd.cpp - sdl/i_input.cpp - sdl/i_joystick.cpp - sdl/i_main.cpp - sdl/i_movie.cpp - sdl/i_system.cpp - sdl/sdlvideo.cpp - sdl/st_start.cpp ) + set( SYSTEM_SOURCES ${PLAT_SDL_SOURCES} ) if( APPLE ) - set( SYSTEM_SOURCES ${SYSTEM_SOURCES} sdl/SDLMain.m sdl/iwadpicker_cocoa.mm sdl/i_system_cocoa.mm ) + set( SYSTEM_SOURCES ${SYSTEM_SOURCES} ${PLAT_MAC_SOURCES} ) + set( OTHER_SYSTEM_SOURCES ${PLAT_WIN32_SOURCES} ) + else( APPLE ) + set( OTHER_SYSTEM_SOURCES ${PLAT_WIN32_SOURCES} ${PLAT_MAC_SOURCES} ) endif( APPLE ) endif( WIN32 ) if( NO_ASM ) add_definitions( -DNOASM ) else( NO_ASM ) + if( NOT ASM_SOURCES ) + set( ASM_SOURCES "" ) + endif( NOT ASM_SOURCES ) if( X64 ) ADD_ASM_FILE( asm_x86_64 tmap3 ) else( X64 ) @@ -661,8 +695,10 @@ file( GLOB HEADER_FILES intermission/*.h menu/*.h oplsynth/*.h + oplsynth/dosbox/*.h r_data/*.h resourcefiles/*.h + sdl/*.h sfmt/*.h sound/*.h textures/*.h @@ -671,9 +707,104 @@ file( GLOB HEADER_FILES *.h ) +# These files will be flagged as "headers" so that they appear in project files +# without being compiled. +set( NOT_COMPILED_SOURCE_FILES + ${OTHER_SYSTEM_SOURCES} + sc_man_scanner.h + sc_man_scanner.re + g_doom/a_arachnotron.cpp + g_doom/a_archvile.cpp + g_doom/a_bossbrain.cpp + g_doom/a_bruiser.cpp + g_doom/a_cacodemon.cpp + g_doom/a_cyberdemon.cpp + g_doom/a_demon.cpp + g_doom/a_doomimp.cpp + g_doom/a_doomweaps.cpp + g_doom/a_fatso.cpp + g_doom/a_keen.cpp + g_doom/a_lostsoul.cpp + g_doom/a_painelemental.cpp + g_doom/a_possessed.cpp + g_doom/a_revenant.cpp + g_doom/a_scriptedmarine.cpp + g_doom/a_spidermaster.cpp + g_heretic/a_chicken.cpp + g_heretic/a_dsparil.cpp + g_heretic/a_hereticartifacts.cpp + g_heretic/a_hereticimp.cpp + g_heretic/a_hereticweaps.cpp + g_heretic/a_ironlich.cpp + g_heretic/a_knight.cpp + g_heretic/a_wizard.cpp + g_hexen/a_bats.cpp + g_hexen/a_bishop.cpp + g_hexen/a_blastradius.cpp + g_hexen/a_boostarmor.cpp + g_hexen/a_centaur.cpp + g_hexen/a_clericflame.cpp + g_hexen/a_clericholy.cpp + g_hexen/a_clericmace.cpp + g_hexen/a_clericstaff.cpp + g_hexen/a_dragon.cpp + g_hexen/a_fighteraxe.cpp + g_hexen/a_fighterhammer.cpp + g_hexen/a_fighterplayer.cpp + g_hexen/a_fighterquietus.cpp + g_hexen/a_firedemon.cpp + g_hexen/a_flechette.cpp + g_hexen/a_fog.cpp + g_hexen/a_healingradius.cpp + g_hexen/a_heresiarch.cpp + g_hexen/a_hexenspecialdecs.cpp + g_hexen/a_iceguy.cpp + g_hexen/a_korax.cpp + g_hexen/a_magecone.cpp + g_hexen/a_magelightning.cpp + g_hexen/a_magestaff.cpp + g_hexen/a_pig.cpp + g_hexen/a_serpent.cpp + g_hexen/a_spike.cpp + g_hexen/a_summon.cpp + g_hexen/a_teleportother.cpp + g_hexen/a_wraith.cpp + g_strife/a_acolyte.cpp + g_strife/a_alienspectres.cpp + g_strife/a_coin.cpp + g_strife/a_crusader.cpp + g_strife/a_entityboss.cpp + g_strife/a_inquisitor.cpp + g_strife/a_oracle.cpp + g_strife/a_programmer.cpp + g_strife/a_reaver.cpp + g_strife/a_rebels.cpp + g_strife/a_sentinel.cpp + g_strife/a_stalker.cpp + g_strife/a_strifeitems.cpp + g_strife/a_strifeweapons.cpp + g_strife/a_templar.cpp + g_strife/a_thingstoblowup.cpp + g_shared/sbarinfo_commands.cpp + xlat/xlat_parser.y + xlat_parser.c + xlat_parser.h + + # We could have the ASM macro add these files, but it wouldn't add all + # platforms. + asm_ia32/a.asm + asm_ia32/misc.asm + asm_ia32/tmap.asm + asm_ia32/tmap2.asm + asm_ia32/tmap3.asm + asm_x86_64/tmap3.asm + asm_x86_64/tmap3.s +) + add_executable( zdoom WIN32 ${HEADER_FILES} - autostart.cpp + ${NOT_COMPILED_SOURCE_FILES} + __autostart.cpp ${ASM_SOURCES} ${SYSTEM_SOURCES} ${X86_SOURCES} @@ -689,6 +820,7 @@ add_executable( zdoom WIN32 c_bind.cpp c_cmds.cpp c_console.cpp + c_consolebuffer.cpp c_cvars.cpp c_dispatch.cpp c_expr.cpp @@ -735,6 +867,7 @@ add_executable( zdoom WIN32 m_misc.cpp m_png.cpp m_random.cpp + m_specialpaths.cpp memarena.cpp md5.cpp name.cpp @@ -977,18 +1110,19 @@ add_executable( zdoom WIN32 r_data/renderstyle.cpp r_data/r_interpolate.cpp r_data/r_translate.cpp - autozend.cpp + zzautozend.cpp ) set_source_files_properties( xlat/parse_xlat.cpp PROPERTIES OBJECT_DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/xlat_parser.c" ) set_source_files_properties( sc_man.cpp PROPERTIES OBJECT_DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/sc_man_scanner.h" ) +set_source_files_properties( ${NOT_COMPILED_SOURCE_FILES} PROPERTIES HEADER_FILE_ONLY TRUE ) if(${CMAKE_SYSTEM_NAME} STREQUAL "SunOS") # [BL] Solaris requires these to be explicitly linked. set( ZDOOM_LIBS ${ZDOOM_LIBS} nsl socket) endif(${CMAKE_SYSTEM_NAME} STREQUAL "SunOS") -target_link_libraries( zdoom ${ZDOOM_LIBS} gme gdtoa dumb lzma ) +target_link_libraries( zdoom ${ZDOOM_LIBS} gdtoa dumb lzma ) include_directories( . g_doom g_heretic @@ -1002,7 +1136,6 @@ include_directories( . thingdef timidity xlat - ../game-music-emu/gme ../gdtoa ../dumb/include ${CMAKE_BINARY_DIR}/gdtoa @@ -1010,10 +1143,40 @@ include_directories( . add_dependencies( zdoom revision_check ) -# RUNTIME_OUTPUT_DIRECTORY does not exist in CMake 2.4. -# Linux distributions are slow to adopt 2.6. :( -set_target_properties( zdoom PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${ZDOOM_OUTPUT_DIR} ) -set_target_properties( zdoom PROPERTIES OUTPUT_NAME ${ZDOOM_EXE_NAME} ) +# Due to some quirks, we need to do this in this order +if( NOT ZDOOM_OUTPUT_OLDSTYLE OR NO_GENERATOR_EXPRESSIONS ) + # RUNTIME_OUTPUT_DIRECTORY does not exist in CMake 2.4. + # Linux distributions are slow to adopt 2.6. :( + set_target_properties( zdoom PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${ZDOOM_OUTPUT_DIR} ) + set_target_properties( zdoom PROPERTIES OUTPUT_NAME ${ZDOOM_EXE_NAME} ) +else( NOT ZDOOM_OUTPUT_OLDSTYLE OR NO_GENERATOR_EXPRESSIONS ) + set_target_properties( zdoom PROPERTIES + RUNTIME_OUTPUT_NAME ${ZDOOM_EXE_NAME} + RUNTIME_OUTPUT_DIRECTORY_RELEASE ${ZDOOM_OUTPUT_DIR} + RUNTIME_OUTPUT_NAME_DEBUG ${ZDOOM_EXE_NAME}d + RUNTIME_OUTPUT_DIRECTORY_DEBUG ${ZDOOM_OUTPUT_DIR} + RUNTIME_OUTPUT_NAME_MINSIZEREL ${ZDOOM_EXE_NAME}msr + RUNTIME_OUTPUT_DIRECTORY_MINSIZEREL ${ZDOOM_OUTPUT_DIR} + RUNTIME_OUTPUT_NAME_RELWITHDEBINFO ${ZDOOM_EXE_NAME}rd + RUNTIME_OUTPUT_DIRECTORY_RELWITHDEBINFO ${ZDOOM_OUTPUT_DIR} + ) +endif( NOT ZDOOM_OUTPUT_OLDSTYLE OR NO_GENERATOR_EXPRESSIONS ) + +if( MSVC ) + option( ZDOOM_GENERATE_MAPFILE "Generate .map file for debugging." OFF ) + if( ZDOOM_GENERATE_MAPFILE ) + set_target_properties(zdoom PROPERTIES LINK_FLAGS "/MANIFEST:NO /DELAYLOAD:\"fmodex${X64}.dll\" /MAP") + else( ZDOOM_GENERATE_MAPFILE ) + set_target_properties(zdoom PROPERTIES LINK_FLAGS "/MANIFEST:NO /DELAYLOAD:\"fmodex${X64}.dll\"") + endif( ZDOOM_GENERATE_MAPFILE ) + + add_custom_command(TARGET zdoom POST_BUILD + COMMAND "mt.exe" -manifest \"${CMAKE_CURRENT_SOURCE_DIR}\\win32\\zdoom.exe.manifest\" -outputresource:\"$(TargetDir)$(TargetFileName)\"\;\#1 + COMMENT "Adding manifest..." + ) + + create_default_target_launcher( zdoom WORKING_DIRECTORY ${ZDOOM_OUTPUT_DIR} ) +endif( MSVC ) if( NOT WIN32 ) FILE( WRITE ${CMAKE_CURRENT_BINARY_DIR}/link-make "if [ ! -e ${ZDOOM_OUTPUT_DIR}/${ZDOOM_EXE_NAME} ]; then ln -sf ${CMAKE_CURRENT_BINARY_DIR}/${ZDOOM_EXE_NAME} ${ZDOOM_OUTPUT_DIR}/${ZDOOM_EXE_NAME}; fi" ) @@ -1021,16 +1184,44 @@ if( NOT WIN32 ) COMMAND chmod +x ${CMAKE_CURRENT_BINARY_DIR}/link-make COMMAND /bin/sh -c ${CMAKE_CURRENT_BINARY_DIR}/link-make ) endif( NOT WIN32 ) -if( "${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" OR "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang" ) +if( "${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" ) # GCC misoptimizes this file set_source_files_properties( oplsynth/fmopl.cpp PROPERTIES COMPILE_FLAGS "-fno-tree-dominator-opts -fno-tree-fre" ) - +endif( "${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" ) +if( "${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" OR "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang" ) # Need to enable intrinsics for this file. if( SSE_MATTERS ) set_source_files_properties( x86.cpp PROPERTIES COMPILE_FLAGS "-msse2 -mmmx" ) endif( SSE_MATTERS ) endif( "${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" OR "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang" ) -if( MSVC ) - set_target_properties(zdoom PROPERTIES LINK_FLAGS "/MANIFEST:NO") -endif( MSVC ) +source_group("Assembly Files\\ia32" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/asm_ia32/.+") +source_group("Assembly Files\\x86_64" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/asm_x86_64/.+") +source_group("Audio Files" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/sound/.+") +source_group("Audio Files\\OPL Synth" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/oplsynth/.+") +source_group("Audio Files\\OPL Synth\\DOSBox" FILES oplsynth/dosbox/opl.cpp oplsynth/dosbox/opl.h) +source_group("Audio Files\\Timidity\\Headers" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/timidity/.+\\.h$") +source_group("Audio Files\\Timidity\\Source" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/timidity/.+\\.cpp$") +source_group("Decorate++" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/thingdef/.+") +source_group("FraggleScript" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/fragglescript/.+") +source_group("Games\\Doom Game" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/g_doom/.+") +source_group("Games\\Heretic Game" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/g_heretic/.+") +source_group("Games\\Hexen Game" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/g_hexen/.+") +source_group("Games\\Raven Shared" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/g_raven/.+") +source_group("Games\\Strife Game" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/g_strife/.+") +source_group("Intermission" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/intermission/.+") +source_group("Menu" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/menu/.+") +source_group("Render Core\\Render Headers" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/r_.+\\.h$") +source_group("Render Core\\Render Sources" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/r_.+\\.cpp$") +source_group("Render Data\\Resource Headers" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/r_data/.+\\.h$") +source_group("Render Data\\Resource Sources" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/r_data/.+\\.cpp$") +source_group("Render Data\\Textures" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/textures/.+") +source_group("Render Interface" FILES r_defs.h r_renderer.h r_sky.cpp r_sky.h r_state.h r_utility.cpp r_utility.h) +source_group("Resource Files" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/resourcefiles/.+") +source_group("SDL Files" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/sdl/.+") +source_group("SFMT" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/sfmt/.+") +source_group("Shared Game" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/g_shared/.+") +source_group("Versioning" FILES version.h win32/zdoom.rc) +source_group("Win32 Files" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/win32/.+") +source_group("Xlat" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/xlat/.+" FILES ${CMAKE_CURRENT_BINARY_DIR}/xlat_parser.c ${CMAKE_CURRENT_BINARY_DIR}/xlat_parser.h) +source_group("Source Files" FILES ${CMAKE_CURRENT_BINARY_DIR}/sc_man_scanner.h sc_man_scanner.re) diff --git a/src/autostart.cpp b/src/__autostart.cpp similarity index 100% rename from src/autostart.cpp rename to src/__autostart.cpp diff --git a/src/actor.h b/src/actor.h index 768008182..0dd20c14f 100644 --- a/src/actor.h +++ b/src/actor.h @@ -236,7 +236,7 @@ enum MF4_RANDOMIZE = 0x00000010, // Missile has random initial tic count MF4_NOSKIN = 0x00000020, // Player cannot use skins MF4_FIXMAPTHINGPOS = 0x00000040, // Fix this actor's position when spawned as a map thing - MF4_ACTLIKEBRIDGE = 0x00000080, // Pickups can "stand" on this actor + MF4_ACTLIKEBRIDGE = 0x00000080, // Pickups can "stand" on this actor / cannot be moved by any sector action. MF4_STRIFEDAMAGE = 0x00000100, // Strife projectiles only do up to 4x damage, not 8x MF4_CANUSEWALLS = 0x00000200, // Can activate 'use' specials @@ -266,7 +266,7 @@ enum // --- mobj.flags5 --- MF5_DONTDRAIN = 0x00000001, // cannot be drained health from. - /* = 0x00000002, */ + /* = 0x00000002, reserved for use by scripting branch */ MF5_NODROPOFF = 0x00000004, // cannot drop off under any circumstances. MF5_NOFORWARDFALL = 0x00000008, // Does not make any actor fall forward by being damaged by this MF5_COUNTSECRET = 0x00000010, // From Doom 64: actor acts like a secret @@ -284,7 +284,7 @@ enum MF5_NEVERFAST = 0x00010000, // never uses 'fast' attacking logic MF5_ALWAYSRESPAWN = 0x00020000, // always respawns, regardless of skill setting MF5_NEVERRESPAWN = 0x00040000, // never respawns, regardless of skill setting - MF5_DONTRIP = 0x00080000, // Ripping projectiles explode when hittin this actor + MF5_DONTRIP = 0x00080000, // Ripping projectiles explode when hitting this actor MF5_NOINFIGHTING = 0x00100000, // This actor doesn't switch target when it's hurt MF5_NOINTERACTION = 0x00200000, // Thing is completely excluded from any gameplay related checks MF5_NOTIMEFREEZE = 0x00400000, // Actor is not affected by time freezer @@ -332,6 +332,14 @@ enum MF6_INTRYMOVE = 0x10000000, // Executing P_TryMove MF6_NOTAUTOAIMED = 0x20000000, // Do not subject actor to player autoaim. MF6_NOTONAUTOMAP = 0x40000000, // will not be shown on automap with the 'scanner' powerup. + MF6_RELATIVETOFLOOR = 0x80000000, // [RC] Make flying actors be affected by lifts. + +// --- mobj.flags7 --- + + MF7_NEVERTARGET = 0x00000001, // can not be targetted at all, even if monster friendliness is considered. + MF7_NOTELESTOMP = 0x00000002, // cannot telefrag under any circumstances (even when set by MAPINFO) + MF7_ALWAYSTELEFRAG = 0x00000004, // will unconditionally be telefragged when in the way. Overrides all other settings. + MF7_HANDLENODELAY = 0x00000008, // respect NoDelay state flag // --- mobj.renderflags --- @@ -756,6 +764,10 @@ public: return (PalEntry)GetClass()->Meta.GetMetaInt(AMETA_BloodColor); } + // These also set CF_INTERPVIEW for players. + void SetPitch(int p, bool interpolate); + void SetAngle(angle_t ang, bool interpolate); + const PClass *GetBloodType(int type = 0) const { const PClass *bloodcls; @@ -837,6 +849,7 @@ public: DWORD flags4; // [RH] Even more flags! DWORD flags5; // OMG! We need another one. DWORD flags6; // Shit! Where did all the flags go? + DWORD flags7; // // [BB] If 0, everybody can see the actor, if > 0, only members of team (VisibleToTeam-1) can see it. DWORD VisibleToTeam; @@ -860,6 +873,7 @@ public: TObjPtr LastLookActor; // Actor last looked for (if TIDtoHate != 0) fixed_t SpawnPoint[3]; // For nightmare respawn WORD SpawnAngle; + int StartHealth; BYTE WeaveIndexXY; // Separated from special2 because it's used by globally accessible functions. BYTE WeaveIndexZ; int skillrespawncount; @@ -994,8 +1008,11 @@ public: bool SetState (FState *newstate, bool nofunction=false); virtual bool UpdateWaterLevel (fixed_t oldz, bool splash=true); bool isFast(); + bool isSlow(); void SetIdle(); void ClearCounters(); + FState *GetRaiseState(); + void Revive(); FState *FindState (FName label) const { diff --git a/src/am_map.cpp b/src/am_map.cpp index ad34995d0..904593dfb 100644 --- a/src/am_map.cpp +++ b/src/am_map.cpp @@ -68,12 +68,83 @@ #include "a_keys.h" #include "r_data/colormaps.h" + +//============================================================================= +// +// CVARs +// +//============================================================================= + +CVAR (Int, am_rotate, 0, CVAR_ARCHIVE); +CVAR (Int, am_overlay, 0, CVAR_ARCHIVE); +CVAR (Bool, am_showsecrets, true, CVAR_ARCHIVE); +CVAR (Bool, am_showmonsters, true, CVAR_ARCHIVE); +CVAR (Bool, am_showitems, false, CVAR_ARCHIVE); +CVAR (Bool, am_showtime, true, CVAR_ARCHIVE); +CVAR (Bool, am_showtotaltime, false, CVAR_ARCHIVE); +CVAR (Int, am_colorset, 0, CVAR_ARCHIVE); +CVAR (Bool, am_customcolors, true, CVAR_ARCHIVE); +CVAR (Int, am_map_secrets, 1, CVAR_ARCHIVE); +CVAR (Int, am_drawmapback, 1, CVAR_ARCHIVE); +CVAR (Bool, am_showkeys, true, CVAR_ARCHIVE); +CVAR (Bool, am_showtriggerlines, false, CVAR_ARCHIVE); +CVAR (Int, am_showthingsprites, 0, CVAR_ARCHIVE); + //============================================================================= // // Automap colors // //============================================================================= +CVAR (Color, am_backcolor, 0x6c5440, CVAR_ARCHIVE); +CVAR (Color, am_yourcolor, 0xfce8d8, CVAR_ARCHIVE); +CVAR (Color, am_wallcolor, 0x2c1808, CVAR_ARCHIVE); +CVAR (Color, am_secretwallcolor, 0x000000, CVAR_ARCHIVE); +CVAR (Color, am_specialwallcolor, 0xffffff, CVAR_ARCHIVE); +CVAR (Color, am_tswallcolor, 0x888888, CVAR_ARCHIVE); +CVAR (Color, am_fdwallcolor, 0x887058, CVAR_ARCHIVE); +CVAR (Color, am_cdwallcolor, 0x4c3820, CVAR_ARCHIVE); +CVAR (Color, am_efwallcolor, 0x665555, CVAR_ARCHIVE); +CVAR (Color, am_thingcolor, 0xfcfcfc, CVAR_ARCHIVE); +CVAR (Color, am_gridcolor, 0x8b5a2b, CVAR_ARCHIVE); +CVAR (Color, am_xhaircolor, 0x808080, CVAR_ARCHIVE); +CVAR (Color, am_notseencolor, 0x6c6c6c, CVAR_ARCHIVE); +CVAR (Color, am_lockedcolor, 0x007800, CVAR_ARCHIVE); +CVAR (Color, am_intralevelcolor, 0x0000ff, CVAR_ARCHIVE); +CVAR (Color, am_interlevelcolor, 0xff0000, CVAR_ARCHIVE); +CVAR (Color, am_secretsectorcolor, 0xff00ff, CVAR_ARCHIVE); +CVAR (Color, am_thingcolor_friend, 0xfcfcfc, CVAR_ARCHIVE); +CVAR (Color, am_thingcolor_monster, 0xfcfcfc, CVAR_ARCHIVE); +CVAR (Color, am_thingcolor_ncmonster, 0xfcfcfc, CVAR_ARCHIVE); +CVAR (Color, am_thingcolor_item, 0xfcfcfc, CVAR_ARCHIVE); +CVAR (Color, am_thingcolor_citem, 0xfcfcfc, CVAR_ARCHIVE); + +CVAR (Color, am_ovyourcolor, 0xfce8d8, CVAR_ARCHIVE); +CVAR (Color, am_ovwallcolor, 0x00ff00, CVAR_ARCHIVE); +CVAR (Color, am_ovsecretwallcolor, 0x008844, CVAR_ARCHIVE); +CVAR (Color, am_ovspecialwallcolor, 0xffffff, CVAR_ARCHIVE); +CVAR (Color, am_ovotherwallscolor, 0x008844, CVAR_ARCHIVE); +CVAR (Color, am_ovlockedcolor, 0x008844, CVAR_ARCHIVE); +CVAR (Color, am_ovefwallcolor, 0x008844, CVAR_ARCHIVE); +CVAR (Color, am_ovfdwallcolor, 0x008844, CVAR_ARCHIVE); +CVAR (Color, am_ovcdwallcolor, 0x008844, CVAR_ARCHIVE); +CVAR (Color, am_ovunseencolor, 0x00226e, CVAR_ARCHIVE); +CVAR (Color, am_ovtelecolor, 0xffff00, CVAR_ARCHIVE); +CVAR (Color, am_ovinterlevelcolor, 0xffff00, CVAR_ARCHIVE); +CVAR (Color, am_ovsecretsectorcolor,0x00ffff, CVAR_ARCHIVE); +CVAR (Color, am_ovthingcolor, 0xe88800, CVAR_ARCHIVE); +CVAR (Color, am_ovthingcolor_friend, 0xe88800, CVAR_ARCHIVE); +CVAR (Color, am_ovthingcolor_monster, 0xe88800, CVAR_ARCHIVE); +CVAR (Color, am_ovthingcolor_ncmonster, 0xe88800, CVAR_ARCHIVE); +CVAR (Color, am_ovthingcolor_item, 0xe88800, CVAR_ARCHIVE); +CVAR (Color, am_ovthingcolor_citem, 0xe88800, CVAR_ARCHIVE); + +//============================================================================= +// +// internal representation of a single color +// +//============================================================================= + struct AMColor { int Index; @@ -90,48 +161,374 @@ struct AMColor RGB = MAKEARGB(255, r, g, b); Index = ColorMatcher.Pick(r, g, b); } -}; -static AMColor Background, YourColor, WallColor, TSWallColor, - FDWallColor, CDWallColor, EFWallColor, ThingColor, - ThingColor_Item, ThingColor_CountItem, ThingColor_Monster, ThingColor_Friend, - SpecialWallColor, SecretWallColor, GridColor, XHairColor, - NotSeenColor, - LockedColor, - AlmostBackground, - IntraTeleportColor, InterTeleportColor, - SecretSectorColor; + void setInvalid() + { + Index = -1; + RGB = -1; + } -static AMColor DoomColors[11]; -static BYTE DoomPaletteVals[11*3] = -{ - 0x00,0x00,0x00, 0xff,0xff,0xff, 0x10,0x10,0x10, - 0xfc,0x00,0x00, 0x80,0x80,0x80, 0xbc,0x78,0x48, - 0xfc,0xfc,0x00, 0x74,0xfc,0x6c, 0x4c,0x4c,0x4c, - 0x80,0x80,0x80, 0x6c,0x6c,0x6c -}; - -static AMColor StrifeColors[11]; -static BYTE StrifePaletteVals[11*3] = -{ - 0x00,0x00,0x00, 239, 239, 0, 0x10,0x10,0x10, - 199, 195, 195, 119, 115, 115, 55, 59, 91, - 119, 115, 115, 0xfc,0x00,0x00, 0x4c,0x4c,0x4c, - 187, 59, 0, 219, 171, 0 -}; - -static AMColor RavenColors[11]; -static BYTE RavenPaletteVals[11*3] = -{ - 0x6c,0x54,0x40, 255, 255, 255, 0x74,0x5c,0x48, - 75, 50, 16, 88, 93, 86, 208, 176, 133, - 103, 59, 31, 236, 236, 236, 0, 0, 0, - 0, 0, 0, 0, 0, 0, + bool isValid() const + { + return Index > -1; + } }; //============================================================================= // -// globals +// a complete color set +// +//============================================================================= + +static const char *ColorNames[] = { + "Background", + "YourColor", + "WallColor", + "TwoSidedWallColor", + "FloorDiffWallColor", + "CeilingDiffWallColor", + "ExtraFloorWallColor", + "ThingColor", + "ThingColor_Item", + "ThingColor_CountItem", + "ThingColor_Monster", + "ThingColor_NocountMonster", + "ThingColor_Friend", + "SpecialWallColor", + "SecretWallColor", + "GridColor", + "XHairColor", + "NotSeenColor", + "LockedColor", + "IntraTeleportColor", + "InterTeleportColor", + "SecretSectorColor", + "AlmostBackgroundColor", + NULL +}; + +struct AMColorset +{ + enum + { + Background, + YourColor, + WallColor, + TSWallColor, + FDWallColor, + CDWallColor, + EFWallColor, + ThingColor, + ThingColor_Item, + ThingColor_CountItem, + ThingColor_Monster, + ThingColor_NocountMonster, + ThingColor_Friend, + SpecialWallColor, + SecretWallColor, + GridColor, + XHairColor, + NotSeenColor, + LockedColor, + IntraTeleportColor, + InterTeleportColor, + SecretSectorColor, + AlmostBackgroundColor, + AM_NUM_COLORS + }; + + AMColor c[AM_NUM_COLORS]; + bool displayLocks; + bool forcebackground; + bool defined; // only for mod specific colorsets: must be true to be usable + + void initFromCVars(FColorCVar **values) + { + for(int i=0;i MapArrow; static TArray CheatMapArrow; static TArray CheatKey; @@ -345,15 +707,11 @@ static mline_t square_guy[] = { -EXTERN_CVAR (Bool, sv_cheats) -CUSTOM_CVAR (Int, am_cheat, 0, 0) -{ - // No automap cheat in net games when cheats are disabled! - if (netgame && !sv_cheats && self != 0) - { - self = 0; - } -} +//============================================================================= +// +// +// +//============================================================================= static int grid = 0; @@ -563,21 +921,6 @@ void AM_StaticInit() } markpointnum = 0; mapback.SetInvalid(); - - static DWORD *lastpal = NULL; - //static int lastback = -1; - DWORD *palette; - - palette = (DWORD *)GPalette.BaseColors; - - int i, j; - - for (i = j = 0; i < 11; i++, j += 3) - { - DoomColors[i].FromRGB(DoomPaletteVals[j], DoomPaletteVals[j+1], DoomPaletteVals[j+2]); - StrifeColors[i].FromRGB(StrifePaletteVals[j], StrifePaletteVals[j+1], StrifePaletteVals[j+2]); - RavenColors[i].FromRGB(RavenPaletteVals[j], RavenPaletteVals[j+1], RavenPaletteVals[j+2]); - } } //============================================================================= @@ -913,133 +1256,39 @@ static void AM_initColors (bool overlayed) { if (overlayed) { - YourColor.FromCVar (am_ovyourcolor); - WallColor.FromCVar (am_ovwallcolor); - SpecialWallColor.FromCVar(am_ovspecialwallcolor); - SecretWallColor = WallColor; - SecretSectorColor.FromCVar (am_ovsecretsectorcolor); - ThingColor_Item.FromCVar (am_ovthingcolor_item); - ThingColor_CountItem.FromCVar (am_ovthingcolor_citem); - ThingColor_Friend.FromCVar (am_ovthingcolor_friend); - ThingColor_Monster.FromCVar (am_ovthingcolor_monster); - ThingColor.FromCVar (am_ovthingcolor); - LockedColor.FromCVar (am_ovotherwallscolor); - EFWallColor.FromCVar (am_ovefwallcolor); - FDWallColor.FromCVar (am_ovfdwallcolor); - CDWallColor.FromCVar (am_ovcdwallcolor); - TSWallColor.FromCVar (am_ovunseencolor); - NotSeenColor = TSWallColor; - InterTeleportColor.FromCVar (am_ovtelecolor); - IntraTeleportColor = InterTeleportColor; + if (am_customcolors && AMModOverlay.defined) + { + AMColors = AMModOverlay; + } + else + { + AMColors.initFromCVars(cv_overlay); + } + } + else if (am_customcolors && AMMod.defined) + { + AMColors = AMMod; } else switch(am_colorset) { default: - { /* Use the custom colors in the am_* cvars */ - Background.FromCVar (am_backcolor); - YourColor.FromCVar (am_yourcolor); - SecretWallColor.FromCVar (am_secretwallcolor); - SpecialWallColor.FromCVar (am_specialwallcolor); - WallColor.FromCVar (am_wallcolor); - TSWallColor.FromCVar (am_tswallcolor); - FDWallColor.FromCVar (am_fdwallcolor); - CDWallColor.FromCVar (am_cdwallcolor); - EFWallColor.FromCVar (am_efwallcolor); - ThingColor_Item.FromCVar (am_thingcolor_item); - ThingColor_CountItem.FromCVar (am_thingcolor_citem); - ThingColor_Friend.FromCVar (am_thingcolor_friend); - ThingColor_Monster.FromCVar (am_thingcolor_monster); - ThingColor.FromCVar (am_thingcolor); - GridColor.FromCVar (am_gridcolor); - XHairColor.FromCVar (am_xhaircolor); - NotSeenColor.FromCVar (am_notseencolor); - LockedColor.FromCVar (am_lockedcolor); - InterTeleportColor.FromCVar (am_interlevelcolor); - IntraTeleportColor.FromCVar (am_intralevelcolor); - SecretSectorColor.FromCVar (am_secretsectorcolor); - - DWORD ba = am_backcolor; - - int r = RPART(ba) - 16; - int g = GPART(ba) - 16; - int b = BPART(ba) - 16; - - if (r < 0) - r += 32; - if (g < 0) - g += 32; - if (b < 0) - b += 32; - - AlmostBackground.FromRGB(r, g, b); + AMColors.initFromCVars(cv_standard); break; - } case 1: // Doom // Use colors corresponding to the original Doom's - Background = DoomColors[0]; - YourColor = DoomColors[1]; - AlmostBackground = DoomColors[2]; - SecretSectorColor = - SecretWallColor = - SpecialWallColor = - WallColor = DoomColors[3]; - TSWallColor = DoomColors[4]; - EFWallColor = FDWallColor = DoomColors[5]; - LockedColor = - CDWallColor = DoomColors[6]; - ThingColor_Item = - ThingColor_Friend = - ThingColor_Monster = - ThingColor = DoomColors[7]; - GridColor = DoomColors[8]; - XHairColor = DoomColors[9]; - NotSeenColor = DoomColors[10]; + AMColors.initFromColors(DoomColors, false); break; case 2: // Strife // Use colors corresponding to the original Strife's - Background = StrifeColors[0]; - YourColor = StrifeColors[1]; - AlmostBackground = DoomColors[2]; - SecretSectorColor = - SecretWallColor = - SpecialWallColor = - WallColor = StrifeColors[3]; - TSWallColor = StrifeColors[4]; - EFWallColor = FDWallColor = StrifeColors[5]; - LockedColor = - CDWallColor = StrifeColors[6]; - ThingColor_Item = StrifeColors[10]; - ThingColor_Friend = - ThingColor_Monster = StrifeColors[7]; - ThingColor = StrifeColors[9]; - GridColor = StrifeColors[8]; - XHairColor = DoomColors[9]; - NotSeenColor = DoomColors[10]; + AMColors.initFromColors(StrifeColors, false); break; case 3: // Raven // Use colors corresponding to the original Raven's - Background = RavenColors[0]; - YourColor = RavenColors[1]; - AlmostBackground = DoomColors[2]; - SecretSectorColor = - SecretWallColor = - SpecialWallColor = - WallColor = RavenColors[3]; - TSWallColor = RavenColors[4]; - EFWallColor = FDWallColor = RavenColors[5]; - LockedColor = - CDWallColor = RavenColors[6]; - ThingColor = - ThingColor_Item = - ThingColor_Friend = - ThingColor_Monster = RavenColors[7]; - GridColor = RavenColors[4]; - XHairColor = RavenColors[9]; - NotSeenColor = RavenColors[10]; + AMColors.initFromColors(RavenColors, true); break; } @@ -1067,8 +1316,14 @@ bool AM_clearMarks () void AM_LevelInit () { - const char *autopage = level.info->mapbg[0] == 0? "AUTOPAGE" : (const char*)&level.info->mapbg[0]; - mapback = TexMan.CheckForTexture(autopage, FTexture::TEX_MiscPatch); + if (level.info->MapBackground.Len() == 0) + { + mapback = TexMan.CheckForTexture("AUTOPAGE", FTexture::TEX_MiscPatch); + } + else + { + mapback = TexMan.CheckForTexture(level.info->MapBackground, FTexture::TEX_MiscPatch); + } AM_clearMarks(); @@ -1368,7 +1623,17 @@ void AM_Ticker () void AM_clearFB (const AMColor &color) { - if (!mapback.isValid() || !am_drawmapback) + bool drawback = mapback.isValid() && am_drawmapback != 0; + if (am_drawmapback == 2) + { + // only draw background when using a mod defined custom color set or Raven colors, if am_drawmapback is 2. + if (!am_customcolors || !AMMod.defined) + { + drawback &= (am_colorset == 3); + } + } + + if (!drawback) { screen->Clear (0, 0, f_w, f_h, color.Index, color.RGB); } @@ -1541,13 +1806,18 @@ void AM_drawMline (mline_t *ml, const AMColor &color) } } +inline void AM_drawMline (mline_t *ml, int colorindex) +{ + AM_drawMline(ml, AMColors[colorindex]); +} + //============================================================================= // // Draws flat (floor/ceiling tile) aligned grid lines. // //============================================================================= -void AM_drawGrid (const AMColor &color) +void AM_drawGrid (int color) { fixed_t x, y; fixed_t start, end; @@ -1786,20 +2056,23 @@ void AM_drawSubsectors() static bool AM_CheckSecret(line_t *line) { - if (line->frontsector != NULL) + if (AMColors.isValid(AMColors.SecretSectorColor)) { - if (line->frontsector->secretsector) + if (line->frontsector != NULL) { - if (am_map_secrets!=0 && !(line->frontsector->special&SECRET_MASK)) return true; - if (am_map_secrets==2 && !(line->flags & ML_SECRET)) return true; + if (line->frontsector->secretsector) + { + if (am_map_secrets!=0 && !(line->frontsector->special&SECRET_MASK)) return true; + if (am_map_secrets==2 && !(line->flags & ML_SECRET)) return true; + } } - } - if (line->backsector != NULL) - { - if (line->backsector->secretsector) + if (line->backsector != NULL) { - if (am_map_secrets!=0 && !(line->backsector->special&SECRET_MASK)) return true; - if (am_map_secrets==2 && !(line->flags & ML_SECRET)) return true; + if (line->backsector->secretsector) + { + if (am_map_secrets!=0 && !(line->backsector->special&SECRET_MASK)) return true; + if (am_map_secrets==2 && !(line->flags & ML_SECRET)) return true; + } } } return false; @@ -1971,7 +2244,7 @@ void AM_drawWalls (bool allmap) if (am_cheat != 0 || (lines[i].flags & ML_MAPPED)) { - if ((lines[i].flags & ML_DONTDRAW) && am_cheat == 0) + if ((lines[i].flags & ML_DONTDRAW) && (am_cheat == 0 || am_cheat >= 4)) { if (!am_showallenabled || CheckCheatmode(false)) { @@ -1982,39 +2255,42 @@ void AM_drawWalls (bool allmap) if (AM_CheckSecret(&lines[i])) { // map secret sectors like Boom - AM_drawMline(&l, SecretSectorColor); + AM_drawMline(&l, AMColors.SecretSectorColor); } else if (lines[i].flags & ML_SECRET) { // secret door if (am_cheat != 0 && lines[i].backsector != NULL) - AM_drawMline(&l, SecretWallColor); + AM_drawMline(&l, AMColors.SecretWallColor); else - AM_drawMline(&l, WallColor); - } else if (lines[i].locknumber > 0) { // [Dusk] specials w/ locknumbers + AM_drawMline(&l, AMColors.WallColor); + } + else if (lines[i].locknumber > 0 && AMColors.displayLocks) + { // [Dusk] specials w/ locknumbers lock = lines[i].locknumber; color = P_GetMapColorForLock(lock); AMColor c; if (color >= 0) c.FromRGB(RPART(color), GPART(color), BPART(color)); - else c = LockedColor; + else c = AMColors[AMColors.LockedColor]; AM_drawMline (&l, c); - } else if ((lines[i].special == Teleport || + } + else if ((lines[i].special == Teleport || lines[i].special == Teleport_NoFog || lines[i].special == Teleport_ZombieChanger || lines[i].special == Teleport_Line) && (lines[i].activation & SPAC_PlayerActivate) && - am_colorset == 0) + AMColors.isValid(AMColors.IntraTeleportColor)) { // intra-level teleporters - AM_drawMline(&l, IntraTeleportColor); + AM_drawMline(&l, AMColors.IntraTeleportColor); } else if ((lines[i].special == Teleport_NewMap || lines[i].special == Teleport_EndGame || lines[i].special == Exit_Normal || lines[i].special == Exit_Secret) && - am_colorset == 0) + AMColors.isValid(AMColors.InterTeleportColor)) { // inter-level/game-ending teleporters - AM_drawMline(&l, InterTeleportColor); + AM_drawMline(&l, AMColors.InterTeleportColor); } else if (lines[i].special == Door_LockedRaise || lines[i].special == ACS_LockedExecute || @@ -2022,7 +2298,7 @@ void AM_drawWalls (bool allmap) (lines[i].special == Door_Animated && lines[i].args[3] != 0) || (lines[i].special == Generic_Door && lines[i].args[4] != 0)) { - if (am_colorset == 0 || am_colorset == 3) // Raven games show door colors + if (AMColors.displayLocks) { int P_GetMapColorForLock(int lock); @@ -2035,16 +2311,16 @@ void AM_drawWalls (bool allmap) AMColor c; if (color >= 0) c.FromRGB(RPART(color), GPART(color), BPART(color)); - else c = LockedColor; + else c = AMColors[AMColors.LockedColor]; AM_drawMline (&l, c); } else { - AM_drawMline (&l, LockedColor); // locked special + AM_drawMline (&l, AMColors.LockedColor); // locked special } } - else if (am_showtriggerlines && am_colorset == 0 && lines[i].special != 0 + else if (am_showtriggerlines && AMColors.isValid(AMColors.SpecialWallColor) && lines[i].special != 0 && lines[i].special != Door_Open && lines[i].special != Door_Close && lines[i].special != Door_CloseWaitOpen @@ -2053,43 +2329,43 @@ void AM_drawWalls (bool allmap) && lines[i].special != Generic_Door && (lines[i].activation & SPAC_PlayerActivate)) { - AM_drawMline(&l, SpecialWallColor); // wall with special non-door action the player can do + AM_drawMline(&l, AMColors.SpecialWallColor); // wall with special non-door action the player can do } else if (lines[i].backsector == NULL) { - AM_drawMline(&l, WallColor); // one-sided wall + AM_drawMline(&l, AMColors.WallColor); // one-sided wall } else if (lines[i].backsector->floorplane != lines[i].frontsector->floorplane) { - AM_drawMline(&l, FDWallColor); // floor level change + AM_drawMline(&l, AMColors.FDWallColor); // floor level change } else if (lines[i].backsector->ceilingplane != lines[i].frontsector->ceilingplane) { - AM_drawMline(&l, CDWallColor); // ceiling level change + AM_drawMline(&l, AMColors.CDWallColor); // ceiling level change } #ifdef _3DFLOORS else if (AM_Check3DFloors(&lines[i])) { - AM_drawMline(&l, EFWallColor); // Extra floor border + AM_drawMline(&l, AMColors.EFWallColor); // Extra floor border } #endif - else if (am_cheat != 0) + else if (am_cheat > 0 && am_cheat < 4) { - AM_drawMline(&l, TSWallColor); + AM_drawMline(&l, AMColors.TSWallColor); } } else if (allmap) { - if ((lines[i].flags & ML_DONTDRAW) && am_cheat == 0) + if ((lines[i].flags & ML_DONTDRAW) && (am_cheat == 0 || am_cheat >= 4)) { if (!am_showallenabled || CheckCheatmode(false)) { continue; } } - AM_drawMline(&l, NotSeenColor); + AM_drawMline(&l, AMColors.NotSeenColor); } } } @@ -2202,7 +2478,7 @@ AM_drawLineCharacter void AM_drawPlayers () { - if (am_cheat >= 2 && am_showthingsprites > 0) + if (am_cheat >= 2 && am_cheat != 4 && am_showthingsprites > 0) { // Player sprites are drawn with the others return; @@ -2239,7 +2515,7 @@ void AM_drawPlayers () arrow = &MapArrow[0]; numarrowlines = MapArrow.Size(); } - AM_drawLineCharacter(arrow, numarrowlines, 0, angle, YourColor, pt.x, pt.y); + AM_drawLineCharacter(arrow, numarrowlines, 0, angle, AMColors[AMColors.YourColor], pt.x, pt.y); return; } @@ -2266,7 +2542,7 @@ void AM_drawPlayers () if (p->mo->alpha < OPAQUE) { - color = AlmostBackground; + color = AMColors[AMColors.AlmostBackgroundColor]; } else { @@ -2322,7 +2598,6 @@ void AM_drawKeys () angle += ANG90 - players[consoleplayer].camera->angle; } - color = ThingColor; if (key->flags & MF_SPECIAL) { // Find the key's own color. @@ -2332,7 +2607,7 @@ void AM_drawKeys () int c = P_GetMapColorForKey(key); if (c >= 0) color.FromRGB(RPART(c), GPART(c), BPART(c)); - else color = ThingColor_CountItem; + else color = AMColors[AMColors.ThingColor_CountItem]; AM_drawLineCharacter(&EasyKey[0], EasyKey.Size(), 0, 0, color, p.x, p.y); } } @@ -2405,13 +2680,14 @@ void AM_drawThings () angle += ANG90 - players[consoleplayer].camera->angle; } - color = ThingColor; + color = AMColors[AMColors.ThingColor]; // use separate colors for special thing types if (t->flags3&MF3_ISMONSTER && !(t->flags&MF_CORPSE)) { - if (t->flags & MF_FRIENDLY || !(t->flags & MF_COUNTKILL)) color = ThingColor_Friend; - else color = ThingColor_Monster; + if (t->flags & MF_FRIENDLY) color = AMColors[AMColors.ThingColor_Friend]; + else if (!(t->flags & MF_COUNTKILL)) color = AMColors[AMColors.ThingColor_NocountMonster]; + else color = AMColors[AMColors.ThingColor_Monster]; } else if (t->flags&MF_SPECIAL) { @@ -2431,19 +2707,19 @@ void AM_drawThings () int c = P_GetMapColorForKey(static_cast(t)); if (c >= 0) color.FromRGB(RPART(c), GPART(c), BPART(c)); - else color = ThingColor_CountItem; + else color = AMColors[AMColors.ThingColor_CountItem]; AM_drawLineCharacter(&CheatKey[0], CheatKey.Size(), 0, 0, color, p.x, p.y); color.Index = -1; } else { - color = ThingColor_Item; + color = AMColors[AMColors.ThingColor_Item]; } } else if (t->flags&MF_COUNTITEM) - color = ThingColor_CountItem; + color = AMColors[AMColors.ThingColor_CountItem]; else - color = ThingColor_Item; + color = AMColors[AMColors.ThingColor_Item]; } if (color.Index != -1) @@ -2453,7 +2729,7 @@ void AM_drawThings () 16<= 3) + if (am_cheat == 3 || am_cheat == 6) { static const mline_t box[4] = { @@ -2629,7 +2905,7 @@ void AM_Drawer () f_h = ST_Y; f_p = screen->GetPitch (); - AM_clearFB(Background); + AM_clearFB(AMColors[AMColors.Background]); } else { @@ -2645,19 +2921,19 @@ void AM_Drawer () AM_drawSubsectors(); if (grid) - AM_drawGrid(GridColor); + AM_drawGrid(AMColors.GridColor); AM_drawWalls(allmap); AM_drawPlayers(); if (G_SkillProperty(SKILLP_EasyKey)) AM_drawKeys(); - if (am_cheat >= 2 || allthings) + if ((am_cheat >= 2 && am_cheat != 4) || allthings) AM_drawThings(); AM_drawAuthorMarkers(); if (!viewactive) - AM_drawCrosshair(XHairColor); + AM_drawCrosshair(AMColors[AMColors.XHairColor]); AM_drawMarks(); diff --git a/src/b_game.cpp b/src/b_game.cpp index a4c0a1842..f3878b8bb 100644 --- a/src/b_game.cpp +++ b/src/b_game.cpp @@ -505,31 +505,13 @@ bool FCajunMaster::LoadBots () bool gotteam = false; bglobal.ForgetBots (); -#ifndef unix - tmp = progdir; - tmp += "zcajun/" BOTFILENAME; - if (!FileExists (tmp)) + tmp = M_GetCajunPath(BOTFILENAME); + if (tmp.IsEmpty()) { DPrintf ("No " BOTFILENAME ", so no bots\n"); return false; } -#else - tmp = GetUserFile (BOTFILENAME); - if (!FileExists (tmp)) - { - if (!FileExists (SHARE_DIR BOTFILENAME)) - { - DPrintf ("No " BOTFILENAME ", so no bots\n"); - return false; - } - else - sc.OpenFile (SHARE_DIR BOTFILENAME); - } -#endif - else - { - sc.OpenFile (tmp); - } + sc.OpenFile(tmp); while (sc.GetString ()) { diff --git a/src/c_cmds.cpp b/src/c_cmds.cpp index cdf615ef4..89005dbc7 100644 --- a/src/c_cmds.cpp +++ b/src/c_cmds.cpp @@ -441,27 +441,33 @@ CCMD (exec) } } +void execLogfile(const char *fn) +{ + if ((Logfile = fopen(fn, "w"))) + { + const char *timestr = myasctime(); + Printf("Log started: %s\n", timestr); + } + else + { + Printf("Could not start log\n"); + } +} + CCMD (logfile) { - const char *timestr = myasctime (); if (Logfile) { - Printf ("Log stopped: %s\n", timestr); + const char *timestr = myasctime(); + Printf("Log stopped: %s\n", timestr); fclose (Logfile); Logfile = NULL; } if (argv.argc() >= 2) { - if ( (Logfile = fopen (argv[1], "w")) ) - { - Printf ("Log started: %s\n", timestr); - } - else - { - Printf ("Could not start log\n"); - } + execLogfile(argv[1]); } } @@ -940,8 +946,15 @@ CCMD(changesky) sky1name = argv[1]; if (sky1name[0] != 0) { - strncpy (level.skypic1, sky1name, 8); - sky1texture = TexMan.GetTexture (sky1name, FTexture::TEX_Wall, FTextureManager::TEXMAN_Overridable); + FTextureID newsky = TexMan.GetTexture(sky1name, FTexture::TEX_Wall, FTextureManager::TEXMAN_Overridable | FTextureManager::TEXMAN_ReturnFirst); + if (newsky.Exists()) + { + sky1texture = level.skytexture1 = newsky; + } + else + { + Printf("changesky: Texture '%s' not found\n", sky1name); + } } R_InitSkyMap (); } @@ -973,14 +986,10 @@ CCMD(nextmap) TEXTCOLOR_NORMAL " is for single-player only.\n"); return; } - char *next = NULL; - if (*level.nextmap) - next = level.nextmap; - - if (next != NULL && strncmp(next, "enDSeQ", 6)) + if (level.NextMap.Len() > 0 && level.NextMap.Compare("enDSeQ", 6)) { - G_DeferedInitNew(next); + G_DeferedInitNew(level.NextMap); } else { @@ -1003,12 +1012,9 @@ CCMD(nextsecret) } char *next = NULL; - if (*level.secretmap) - next = level.secretmap; - - if (next != NULL && strncmp(next, "enDSeQ", 6)) + if (level.NextSecretMap.Len() > 0 && level.NextSecretMap.Compare("enDSeQ", 6)) { - G_DeferedInitNew(next); + G_DeferedInitNew(level.NextSecretMap); } else { @@ -1094,8 +1100,8 @@ static void PrintSecretString(const char *string, bool thislevel) CCMD(secret) { - const char *mapname = argv.argc() < 2? level.mapname : argv[1]; - bool thislevel = !stricmp(mapname, level.mapname); + const char *mapname = argv.argc() < 2? level.MapName.GetChars() : argv[1]; + bool thislevel = !stricmp(mapname, level.MapName); bool foundsome = false; int lumpno=Wads.CheckNumForName("SECRETS"); diff --git a/src/c_console.cpp b/src/c_console.cpp index e5d3d97ab..4dabdb9e1 100644 --- a/src/c_console.cpp +++ b/src/c_console.cpp @@ -41,6 +41,7 @@ #include "version.h" #include "g_game.h" +#include "c_bind.h" #include "c_console.h" #include "c_cvars.h" #include "c_dispatch.h" @@ -64,22 +65,29 @@ #include "g_level.h" #include "d_event.h" #include "d_player.h" +#include "c_consolebuffer.h" #include "gi.h" -#define CONSOLESIZE 16384 // Number of characters to store in console -#define CONSOLELINES 256 // Max number of lines of console text -#define LINEMASK (CONSOLELINES-1) - #define LEFTMARGIN 8 #define RIGHTMARGIN 8 #define BOTTOMARGIN 12 + +CUSTOM_CVAR(Int, con_buffersize, -1, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) +{ + // ensure a minimum size + if (self >= 0 && self < 128) self = 128; +} + +FConsoleBuffer *conbuffer; + static void C_TabComplete (bool goForward); static bool C_TabCompleteList (); static bool TabbedLast; // True if last key pressed was tab static bool TabbedList; // True if tab list was shown -CVAR (Bool, con_notablist, false, CVAR_ARCHIVE) +CVAR(Bool, con_notablist, false, CVAR_ARCHIVE) + static FTextureID conback; static DWORD conshade; @@ -93,18 +101,15 @@ extern FBaseCVar *CVars; extern FConsoleCommand *Commands[FConsoleCommand::HASH_SIZE]; int ConCols, PhysRows; +int ConWidth; bool vidactive = false; bool cursoron = false; int ConBottom, ConScroll, RowAdjust; int CursorTicker; constate_e ConsoleState = c_up; -static char ConsoleBuffer[CONSOLESIZE]; -static char *Lines[CONSOLELINES]; -static bool LineJoins[CONSOLELINES]; static int TopLine, InsertLine; -static char *BufferRover = ConsoleBuffer; static void ClearConsole (); static void C_PasteText(FString clip, BYTE *buffer, int len); @@ -181,7 +186,6 @@ static struct NotifyText static int NotifyTop, NotifyTopGoal; -#define PRINTLEVELS 5 int PrintColors[PRINTLEVELS+2] = { CR_RED, CR_GOLD, CR_GRAY, CR_GREEN, CR_GREEN, CR_GOLD }; static void setmsgcolor (int index, int color); @@ -302,7 +306,7 @@ void C_InitConback() if (!conback.isValid()) { - conback = TexMan.GetTexture (gameinfo.titlePage, FTexture::TEX_MiscPatch); + conback = TexMan.GetTexture (gameinfo.TitlePage, FTexture::TEX_MiscPatch); conshade = MAKEARGB(175,0,0,0); conline = true; } @@ -327,78 +331,11 @@ void C_InitConsole (int width, int height, bool ingame) { cwidth = cheight = 8; } - ConCols = (width - LEFTMARGIN - RIGHTMARGIN) / cwidth; + ConWidth = (width - LEFTMARGIN - RIGHTMARGIN); + ConCols = ConWidth / cwidth; PhysRows = height / cheight; - // If there is some text in the console buffer, reformat it - // for the new resolution. - if (TopLine != InsertLine) - { - // Note: Don't use new here, because we attach a handler to new in - // i_main.cpp that calls I_FatalError if the allocation fails, - // but we can gracefully handle such a condition here by just - // clearing the console buffer. (OTOH, what are the chances that - // any other memory allocations would succeed if we can't get - // these mallocs here?) - - char *fmtBuff = (char *)malloc (CONSOLESIZE); - char **fmtLines = (char **)malloc (CONSOLELINES*sizeof(char*)*4); - int out = 0; - - if (fmtBuff && fmtLines) - { - int in; - char *fmtpos; - bool newline = true; - - fmtpos = fmtBuff; - memset (fmtBuff, 0, CONSOLESIZE); - - for (in = TopLine; in != InsertLine; in = (in + 1) & LINEMASK) - { - size_t len = strlen (Lines[in]); - - if (fmtpos + len + 2 - fmtBuff > CONSOLESIZE) - { - break; - } - if (newline) - { - newline = false; - fmtLines[out++] = fmtpos; - } - strcpy (fmtpos, Lines[in]); - fmtpos += len; - if (!LineJoins[in]) - { - *fmtpos++ = '\n'; - fmtpos++; - if (out == CONSOLELINES*4) - { - break; - } - newline = true; - } - } - } - - ClearConsole (); - - if (fmtBuff && fmtLines) - { - int i; - - for (i = 0; i < out; i++) - { - AddToConsole (-1, fmtLines[i]); - } - } - - if (fmtBuff) - free (fmtBuff); - if (fmtLines) - free (fmtLines); - } + if (conbuffer == NULL) conbuffer = new FConsoleBuffer; } //========================================================================== @@ -506,16 +443,21 @@ void C_DeinitConsole () work = NULL; worklen = 0; } + + if (conbuffer != NULL) + { + delete conbuffer; + conbuffer = NULL; + } } static void ClearConsole () { - RowAdjust = 0; + if (conbuffer != NULL) + { + conbuffer->Clear(); + } TopLine = InsertLine = 0; - BufferRover = ConsoleBuffer; - memset (ConsoleBuffer, 0, CONSOLESIZE); - memset (Lines, 0, sizeof(Lines)); - memset (LineJoins, 0, sizeof(LineJoins)); } static void setmsgcolor (int index, int color) @@ -595,225 +537,9 @@ void C_AddNotifyString (int printlevel, const char *source) NotifyTopGoal = 0; } -static int FlushLines (const char *start, const char *stop) -{ - int i; - - for (i = TopLine; i != InsertLine; i = (i + 1) & LINEMASK) - { - if (Lines[i] < stop && Lines[i] + strlen (Lines[i]) > start) - { - Lines[i] = NULL; - } - else - { - break; - } - } - if (i != TopLine) - i = i; - return i; -} - -static void AddLine (const char *text, bool more, size_t len) -{ - if (BufferRover + len + 1 - ConsoleBuffer > CONSOLESIZE) - { - TopLine = FlushLines (BufferRover, ConsoleBuffer + CONSOLESIZE); - BufferRover = ConsoleBuffer; - } - if (len >= CONSOLESIZE - 1) - { - text = text + len - CONSOLESIZE + 1; - len = CONSOLESIZE - 1; - } - TopLine = FlushLines (BufferRover, BufferRover + len + 1); - memcpy (BufferRover, text, len); - BufferRover[len] = 0; - Lines[InsertLine] = BufferRover; - BufferRover += len + 1; - LineJoins[InsertLine] = more; - InsertLine = (InsertLine + 1) & LINEMASK; - if (InsertLine == TopLine) - { - TopLine = (TopLine + 1) & LINEMASK; - } -} - void AddToConsole (int printlevel, const char *text) { - static enum - { - NEWLINE, - APPENDLINE, - REPLACELINE - } addtype = NEWLINE; - - char *work_p; - char *linestart; - FString cc('A' + char(CR_TAN)); - int size, len; - int x; - int maxwidth; - - if (ConsoleDrawing) - { - EnqueueConsoleText (false, printlevel, text); - return; - } - - len = (int)strlen (text); - size = len + 20; - - if (addtype != NEWLINE) - { - InsertLine = (InsertLine - 1) & LINEMASK; - if (Lines[InsertLine] == NULL) - { - InsertLine = (InsertLine + 1) & LINEMASK; - addtype = NEWLINE; - } - else - { - BufferRover = Lines[InsertLine]; - } - } - if (addtype == APPENDLINE) - { - size += (int)strlen (Lines[InsertLine]); - } - if (size > worklen) - { - work = (char *)M_Realloc (work, size); - worklen = size; - } - if (work == NULL) - { - static char oom[] = TEXTCOLOR_RED "*** OUT OF MEMORY ***"; - work = oom; - worklen = 0; - } - else - { - if (addtype == APPENDLINE) - { - strcpy (work, Lines[InsertLine]); - strcat (work, text); - } - else if (printlevel >= 0) - { - work[0] = TEXTCOLOR_ESCAPE; - work[1] = 'A' + (printlevel == PRINT_HIGH ? CR_TAN : - printlevel == 200 ? CR_GREEN : - printlevel < PRINTLEVELS ? PrintColors[printlevel] : - CR_TAN); - cc = work[1]; - strcpy (work + 2, text); - } - else - { - strcpy (work, text); - } - } - - work_p = linestart = work; - - if (ConFont != NULL && screen != NULL) - { - x = 0; - maxwidth = screen->GetWidth() - LEFTMARGIN - RIGHTMARGIN; - - while (*work_p) - { - if (*work_p == TEXTCOLOR_ESCAPE) - { - work_p++; - if (*work_p == '[') - { - char *start = work_p; - while (*work_p != ']' && *work_p != '\0') - { - work_p++; - } - if (*work_p != '\0') - { - work_p++; - } - cc = FString(start, work_p - start); - } - else if (*work_p != '\0') - { - cc = *work_p++; - } - continue; - } - int w = ConFont->GetCharWidth (*work_p); - if (*work_p == '\n' || x + w > maxwidth) - { - AddLine (linestart, *work_p != '\n', work_p - linestart); - if (*work_p == '\n') - { - x = 0; - work_p++; - } - else - { - x = w; - } - if (*work_p) - { - linestart = work_p - 1 - cc.Len(); - if (linestart < work) - { - // The line start is outside the buffer. - // Make space for the newly inserted stuff. - size_t movesize = work-linestart; - memmove(work + movesize, work, strlen(work)+1); - work_p += movesize; - linestart = work; - } - linestart[0] = TEXTCOLOR_ESCAPE; - strncpy (linestart + 1, cc, cc.Len()); - } - else - { - linestart = work_p; - } - } - else - { - x += w; - work_p++; - } - } - - if (*linestart) - { - AddLine (linestart, true, work_p - linestart); - } - } - else - { - while (*work_p) - { - if (*work_p++ == '\n') - { - AddLine (linestart, false, work_p - linestart - 1); - linestart = work_p; - } - } - if (*linestart) - { - AddLine (linestart, true, work_p - linestart); - } - } - - switch (text[len-1]) - { - case '\r': addtype = REPLACELINE; break; - case '\n': addtype = NEWLINE; break; - default: addtype = APPENDLINE; break; - } + conbuffer->AddText(printlevel, text, Logfile); } /* Adds a string to the console and also to the notify buffer */ @@ -824,34 +550,6 @@ int PrintString (int printlevel, const char *outline) return 0; } - if (Logfile) - { - // Strip out any color escape sequences before writing to the log file - char * copy = new char[strlen(outline)+1]; - const char * srcp = outline; - char * dstp = copy; - - while (*srcp != 0) - { - if (*srcp!=0x1c) - { - *dstp++=*srcp++; - } - else - { - if (srcp[1]!=0) srcp+=2; - else break; - } - } - *dstp=0; - - fputs (copy, Logfile); - delete [] copy; -//#ifdef _DEBUG - fflush (Logfile); -//#endif - } - if (printlevel != PRINT_LOG) { I_PrintStr (outline); @@ -950,6 +648,11 @@ void C_Ticker () if (lasttic == 0) lasttic = gametic - 1; + if (con_buffersize > 0) + { + conbuffer->ResizeBuffer(con_buffersize); + } + if (ConsoleState != c_up) { if (ConsoleState == c_falling) @@ -1237,38 +940,22 @@ void C_DrawConsole (bool hw2d) if (lines > 0) { + // No more enqueuing because adding new text to the console won't touch the actual print data. + conbuffer->FormatText(ConFont, ConWidth); + unsigned int consolelines = conbuffer->GetFormattedLineCount(); + FBrokenLines **blines = conbuffer->GetLines(); + FBrokenLines **printline = blines + consolelines - 1 - RowAdjust; + int bottomline = ConBottom - ConFont->GetHeight()*2 - 4; - int pos = (InsertLine - 1) & LINEMASK; - int i; ConsoleDrawing = true; - for (i = RowAdjust; i; i--) + for(FBrokenLines **p = printline; p >= blines && lines > 0; p--, lines--) { - if (pos == TopLine) - { - RowAdjust = RowAdjust - i; - break; - } - else - { - pos = (pos - 1) & LINEMASK; - } + screen->DrawText(ConFont, CR_TAN, LEFTMARGIN, offset + lines * ConFont->GetHeight(), (*p)->Text, TAG_DONE); } - pos++; - do - { - pos = (pos - 1) & LINEMASK; - if (Lines[pos] != NULL) - { - screen->DrawText (ConFont, CR_TAN, LEFTMARGIN, offset + lines * ConFont->GetHeight(), - Lines[pos], TAG_DONE); - } - lines--; - } while (pos != TopLine && lines > 0); ConsoleDrawing = false; - DequeueConsoleText (); if (ConBottom >= 20) { @@ -1294,7 +981,7 @@ void C_DrawConsole (bool hw2d) { // Indicate that the view has been scrolled up (10) // and if we can scroll no further (12) - screen->DrawChar (ConFont, CR_GREEN, 0, bottomline, pos == TopLine ? 12 : 10, TAG_DONE); + screen->DrawChar (ConFont, CR_GREEN, 0, bottomline, RowAdjust == conbuffer->GetFormattedLineCount() ? 12 : 10, TAG_DONE); } } } @@ -1446,7 +1133,7 @@ static bool C_HandleKey (event_t *ev, BYTE *buffer, int len) RowAdjust += (SCREENHEIGHT-4) / ((gamestate == GS_FULLCONSOLE || gamestate == GS_STARTUP) ? ConFont->GetHeight() : ConFont->GetHeight()*2) - 3; } - else if (RowAdjust < CONSOLELINES) + else if (RowAdjust < conbuffer->GetFormattedLineCount()) { // Scroll console buffer up if (ev->subtype == EV_GUI_WheelUp) { @@ -1456,6 +1143,10 @@ static bool C_HandleKey (event_t *ev, BYTE *buffer, int len) { RowAdjust++; } + if (RowAdjust > conbuffer->GetFormattedLineCount()) + { + RowAdjust = conbuffer->GetFormattedLineCount(); + } } break; @@ -1489,7 +1180,7 @@ static bool C_HandleKey (event_t *ev, BYTE *buffer, int len) case GK_HOME: if (ev->data3 & GKM_CTRL) { // Move to top of console buffer - RowAdjust = CONSOLELINES; + RowAdjust = conbuffer->GetFormattedLineCount(); } else { // Move cursor to start of line @@ -1698,6 +1389,12 @@ static bool C_HandleKey (event_t *ev, BYTE *buffer, int len) break; case '`': + // Check to see if we have ` bound to the console before accepting + // it as a way to close the console. + if (Bindings.GetBinding(KEY_GRAVE).CompareNoCase("toggleconsole")) + { + break; + } case GK_ESCAPE: // Close console and clear command line. But if we're in the // fullscreen console mode, there's nothing to fall back on @@ -1742,7 +1439,7 @@ static bool C_HandleKey (event_t *ev, BYTE *buffer, int len) } break; -#ifdef unix +#ifdef __unix__ case EV_GUI_MButtonDown: C_PasteText(I_GetFromClipboard(true), buffer, len); break; diff --git a/src/c_console.h b/src/c_console.h index 8560d6779..2c2e553f9 100644 --- a/src/c_console.h +++ b/src/c_console.h @@ -47,6 +47,9 @@ typedef enum cstate_t } constate_e; +#define PRINTLEVELS 5 +extern int PrintColors[PRINTLEVELS + 2]; + extern constate_e ConsoleState; extern int ConBottom; diff --git a/src/c_consolebuffer.cpp b/src/c_consolebuffer.cpp new file mode 100644 index 000000000..3f64f34e4 --- /dev/null +++ b/src/c_consolebuffer.cpp @@ -0,0 +1,317 @@ +/* +** consolebuffer.cpp +** +** manages the text for the console +** +**--------------------------------------------------------------------------- +** Copyright 2014 Christoph Oelckers +** All rights reserved. +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** +** 1. Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** 2. Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** 3. The name of the author may not be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +**--------------------------------------------------------------------------- +** +*/ + +#include "c_console.h" +#include "c_consolebuffer.h" + + +//========================================================================== +// +// +// +//========================================================================== + +FConsoleBuffer::FConsoleBuffer() +{ + mLogFile = NULL; + mAddType = NEWLINE; + mLastFont = NULL; + mLastDisplayWidth = -1; + mLastLineNeedsUpdate = false; + mTextLines = 0; + mBufferWasCleared = true; + mBrokenStart.Push(0); +} + +//========================================================================== +// +// +// +//========================================================================== + +FConsoleBuffer::~FConsoleBuffer() +{ + FreeBrokenText(); +} + +//========================================================================== +// +// +// +//========================================================================== + +void FConsoleBuffer::FreeBrokenText(unsigned start, unsigned end) +{ + if (end > mBrokenConsoleText.Size()) end = mBrokenConsoleText.Size(); + for (unsigned i = start; i < end; i++) + { + if (mBrokenConsoleText[i] != NULL) V_FreeBrokenLines(mBrokenConsoleText[i]); + mBrokenConsoleText[i] = NULL; + } +} + +//========================================================================== +// +// Adds a new line of text to the console +// This is kept as simple as possible. This function does not: +// - remove old text if the buffer gets larger than the specified size +// - format the text for the current screen layout +// +// These tasks will only be be performed once per frame because they are +// relatively expensive. The old console did them each time text was added +// resulting in extremely bad performance with a high output rate. +// +//========================================================================== + +void FConsoleBuffer::AddText(int printlevel, const char *text, FILE *logfile) +{ + FString build = TEXTCOLOR_TAN; + + if (mAddType == REPLACELINE) + { + // Just wondering: Do we actually need this case? If so, it may need some work. + mConsoleText.Pop(); // remove the line to be replaced + mLastLineNeedsUpdate = true; + } + else if (mAddType == APPENDLINE) + { + mConsoleText.Pop(build); + printlevel = -1; + mLastLineNeedsUpdate = true; + } + + if (printlevel >= 0 && printlevel != PRINT_HIGH) + { + if (printlevel == 200) build = TEXTCOLOR_GREEN; + else if (printlevel < PRINTLEVELS) build.Format("%c%c", TEXTCOLOR_ESCAPE, PrintColors[printlevel]); + } + + size_t textsize = strlen(text); + + if (text[textsize-1] == '\r') + { + textsize--; + mAddType = REPLACELINE; + } + else if (text[textsize-1] == '\n') + { + textsize--; + mAddType = NEWLINE; + } + else + { + mAddType = APPENDLINE; + } + + // don't bother about linefeeds etc. inside the text, we'll let the formatter sort this out later. + build.AppendCStrPart(text, textsize); + mConsoleText.Push(build); + if (logfile != NULL) WriteLineToLog(logfile, text); +} + +//========================================================================== +// +// +// +//========================================================================== + +void FConsoleBuffer::WriteLineToLog(FILE *LogFile, const char *outline) +{ + // Strip out any color escape sequences before writing to the log file + char * copy = new char[strlen(outline)+1]; + const char * srcp = outline; + char * dstp = copy; + + while (*srcp != 0) + { + + if (*srcp != TEXTCOLOR_ESCAPE) + { + switch (*srcp) + { + case '\35': + *dstp++ = '<'; + break; + + case '\36': + *dstp++ = '-'; + break; + + case '\37': + *dstp++ = '>'; + break; + + default: + *dstp++=*srcp; + break; + } + srcp++; + } + else if (srcp[1] == '[') + { + srcp+=2; + while (*srcp != ']' && *srcp != 0) srcp++; + if (*srcp == ']') srcp++; + } + else + { + if (srcp[1]!=0) srcp+=2; + else break; + } + } + *dstp=0; + + fputs (copy, LogFile); + delete [] copy; + fflush (LogFile); +} + +//========================================================================== +// +// +// +//========================================================================== + +void FConsoleBuffer::WriteContentToLog(FILE *LogFile) +{ + if (LogFile != NULL) + { + for (unsigned i = 0; i < mConsoleText.Size(); i++) + { + WriteLineToLog(LogFile, mConsoleText[i]); + } + } +} + +//========================================================================== +// +// ensures that the following text is not appended to the current line. +// +//========================================================================== + +void FConsoleBuffer::Linefeed(FILE *Logfile) +{ + if (mAddType != NEWLINE && Logfile != NULL) fputc('\n', Logfile); + mAddType = NEWLINE; +} + +//========================================================================== +// +// +// +//========================================================================== + +static const char bar1[] = TEXTCOLOR_RED "\35\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36" + "\36\36\36\36\36\36\36\36\36\36\36\36\37" TEXTCOLOR_TAN "\n"; +static const char bar2[] = TEXTCOLOR_RED "\35\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36" + "\36\36\36\36\36\36\36\36\36\36\36\36\37" TEXTCOLOR_GREEN "\n"; +static const char bar3[] = TEXTCOLOR_RED "\35\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36" + "\36\36\36\36\36\36\36\36\36\36\36\36\37" TEXTCOLOR_NORMAL "\n"; +static const char logbar[] = "\n<------------------------------->\n"; + +void FConsoleBuffer::AddMidText(const char *string, bool bold, FILE *Logfile) +{ + Linefeed(Logfile); + AddText (-1, bold? bar2 : bar1, Logfile); + AddText (-1, string, Logfile); + Linefeed(Logfile); + AddText(-1, bar3, Logfile); +} + +//========================================================================== +// +// Format the text for output +// +//========================================================================== + +void FConsoleBuffer::FormatText(FFont *formatfont, int displaywidth) +{ + if (formatfont != mLastFont || displaywidth != mLastDisplayWidth || mBufferWasCleared) + { + FreeBrokenText(); + mBrokenConsoleText.Clear(); + mBrokenStart.Clear(); + mBrokenStart.Push(0); + mBrokenLines.Clear(); + mLastFont = formatfont; + mLastDisplayWidth = displaywidth; + mBufferWasCleared = false; + } + unsigned brokensize = mBrokenConsoleText.Size(); + if (brokensize == mConsoleText.Size()) + { + // The last line got text appended. We have to wait until here to format it because + // it is possible that during display new text will be added from the NetUpdate calls in the software version of DrawTextureV. + if (mLastLineNeedsUpdate) + { + brokensize--; + V_FreeBrokenLines(mBrokenConsoleText[brokensize]); + mBrokenConsoleText.Resize(brokensize); + } + } + mBrokenLines.Resize(mBrokenStart[brokensize]); + mBrokenStart.Resize(brokensize); + for (unsigned i = brokensize; i < mConsoleText.Size(); i++) + { + FBrokenLines *bl = V_BreakLines(formatfont, displaywidth, mConsoleText[i], true); + mBrokenConsoleText.Push(bl); + mBrokenStart.Push(mBrokenLines.Size()); + while (bl->Width != -1) + { + mBrokenLines.Push(bl); + bl++; + } + } + mTextLines = mBrokenLines.Size(); + mBrokenStart.Push(mTextLines); + mLastLineNeedsUpdate = false; +} + +//========================================================================== +// +// Delete old content if number of lines gets too large +// +//========================================================================== + +void FConsoleBuffer::ResizeBuffer(unsigned newsize) +{ + if (mConsoleText.Size() > newsize) + { + unsigned todelete = mConsoleText.Size() - newsize; + mConsoleText.Delete(0, todelete); + mBufferWasCleared = true; + } +} + diff --git a/src/c_consolebuffer.h b/src/c_consolebuffer.h new file mode 100644 index 000000000..710423012 --- /dev/null +++ b/src/c_consolebuffer.h @@ -0,0 +1,85 @@ +/* +** consolebuffer.h +** +** manages the text for the console +** +**--------------------------------------------------------------------------- +** Copyright 2014 Christoph Oelckers +** All rights reserved. +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** +** 1. Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** 2. Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** 3. The name of the author may not be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +**--------------------------------------------------------------------------- +** +*/ + +#include +#include +#include "zstring.h" +#include "tarray.h" +#include "v_text.h" + +enum EAddType +{ + NEWLINE, + APPENDLINE, + REPLACELINE +}; + +class FConsoleBuffer +{ + TArray mConsoleText; + TArray mBrokenConsoleText; // This holds the structures returned by V_BreakLines and is used for memory management. + TArray mBrokenStart; + TArray mBrokenLines; // This holds the single lines, indexed by mBrokenStart and is used for printing. + FILE * mLogFile; + EAddType mAddType; + int mTextLines; + bool mBufferWasCleared; + + FFont *mLastFont; + int mLastDisplayWidth; + bool mLastLineNeedsUpdate; + + void WriteLineToLog(FILE *LogFile, const char *outline); + void FreeBrokenText(unsigned int start = 0, unsigned int end = INT_MAX); + + void Linefeed(FILE *Logfile); + +public: + FConsoleBuffer(); + ~FConsoleBuffer(); + void AddText(int printlevel, const char *string, FILE *logfile = NULL); + void AddMidText(const char *string, bool bold, FILE *logfile); + void FormatText(FFont *formatfont, int displaywidth); + void ResizeBuffer(unsigned newsize); + void WriteContentToLog(FILE *logfile); + void Clear() + { + mBufferWasCleared = true; + mConsoleText.Clear(); + } + int GetFormattedLineCount() { return mTextLines; } + FBrokenLines **GetLines() { return &mBrokenLines[0]; } +}; + diff --git a/src/c_dispatch.cpp b/src/c_dispatch.cpp index 2bd255405..105d8c0d3 100644 --- a/src/c_dispatch.cpp +++ b/src/c_dispatch.cpp @@ -1513,7 +1513,7 @@ CCMD (pullin) { const char *lastSlash; -#ifdef unix +#ifdef __unix__ lastSlash = strrchr (PullinFile, '/'); #else const char *lastSlash1, *lastSlash2; diff --git a/src/c_dispatch.h b/src/c_dispatch.h index 96dc50644..f4518608d 100644 --- a/src/c_dispatch.h +++ b/src/c_dispatch.h @@ -168,4 +168,6 @@ extern unsigned int MakeKey (const char *s); extern unsigned int MakeKey (const char *s, size_t len); extern unsigned int SuperFastHash (const char *data, size_t len); +void execLogfile(const char *fn); + #endif //__C_DISPATCH_H__ diff --git a/src/compatibility.cpp b/src/compatibility.cpp index dca0d3485..7339a0f19 100644 --- a/src/compatibility.cpp +++ b/src/compatibility.cpp @@ -106,6 +106,7 @@ static FCompatOption Options[] = { "ignoreteleporttags", BCOMPATF_BADTELEPORTERS, SLOT_BCOMPAT }, { "rebuildnodes", BCOMPATF_REBUILDNODES, SLOT_BCOMPAT }, { "linkfrozenprops", BCOMPATF_LINKFROZENPROPS, SLOT_BCOMPAT }, + { "disablepushwindowcheck", BCOMPATF_NOWINDOWCHECK, SLOT_BCOMPAT }, // list copied from g_mapinfo.cpp { "shorttex", COMPATF_SHORTTEX, SLOT_COMPAT }, diff --git a/src/ct_chat.cpp b/src/ct_chat.cpp index d99acda42..c0c1f13f0 100644 --- a/src/ct_chat.cpp +++ b/src/ct_chat.cpp @@ -169,7 +169,7 @@ bool CT_Responder (event_t *ev) } return true; } -#ifdef unix +#ifdef __unix__ else if (ev->subtype == EV_GUI_MButtonDown) { CT_PasteChat(I_GetFromClipboard(true)); diff --git a/src/d_dehacked.cpp b/src/d_dehacked.cpp index 82ba21eba..e6376a589 100644 --- a/src/d_dehacked.cpp +++ b/src/d_dehacked.cpp @@ -1755,21 +1755,21 @@ static int PatchCheats (int dummy) static int PatchMisc (int dummy) { static const struct Key keys[] = { - { "Initial Health", myoffsetof(struct DehInfo,StartHealth) }, - { "Initial Bullets", myoffsetof(struct DehInfo,StartBullets) }, - { "Max Health", myoffsetof(struct DehInfo,MaxHealth) }, - { "Max Armor", myoffsetof(struct DehInfo,MaxArmor) }, - { "Green Armor Class", myoffsetof(struct DehInfo,GreenAC) }, - { "Blue Armor Class", myoffsetof(struct DehInfo,BlueAC) }, - { "Max Soulsphere", myoffsetof(struct DehInfo,MaxSoulsphere) }, - { "Soulsphere Health", myoffsetof(struct DehInfo,SoulsphereHealth) }, - { "Megasphere Health", myoffsetof(struct DehInfo,MegasphereHealth) }, - { "God Mode Health", myoffsetof(struct DehInfo,GodHealth) }, - { "IDFA Armor", myoffsetof(struct DehInfo,FAArmor) }, - { "IDFA Armor Class", myoffsetof(struct DehInfo,FAAC) }, - { "IDKFA Armor", myoffsetof(struct DehInfo,KFAArmor) }, - { "IDKFA Armor Class", myoffsetof(struct DehInfo,KFAAC) }, - { "No Autofreeze", myoffsetof(struct DehInfo,NoAutofreeze) }, + { "Initial Health", static_cast(myoffsetof(struct DehInfo,StartHealth)) }, + { "Initial Bullets", static_cast(myoffsetof(struct DehInfo,StartBullets)) }, + { "Max Health", static_cast(myoffsetof(struct DehInfo,MaxHealth)) }, + { "Max Armor", static_cast(myoffsetof(struct DehInfo,MaxArmor)) }, + { "Green Armor Class", static_cast(myoffsetof(struct DehInfo,GreenAC)) }, + { "Blue Armor Class", static_cast(myoffsetof(struct DehInfo,BlueAC)) }, + { "Max Soulsphere", static_cast(myoffsetof(struct DehInfo,MaxSoulsphere)) }, + { "Soulsphere Health", static_cast(myoffsetof(struct DehInfo,SoulsphereHealth)) }, + { "Megasphere Health", static_cast(myoffsetof(struct DehInfo,MegasphereHealth)) }, + { "God Mode Health", static_cast(myoffsetof(struct DehInfo,GodHealth)) }, + { "IDFA Armor", static_cast(myoffsetof(struct DehInfo,FAArmor)) }, + { "IDFA Armor Class", static_cast(myoffsetof(struct DehInfo,FAAC)) }, + { "IDKFA Armor", static_cast(myoffsetof(struct DehInfo,KFAArmor)) }, + { "IDKFA Armor Class", static_cast(myoffsetof(struct DehInfo,KFAAC)) }, + { "No Autofreeze", static_cast(myoffsetof(struct DehInfo,NoAutofreeze)) }, { NULL, 0 } }; int result; @@ -2329,6 +2329,18 @@ static int DoInclude (int dummy) return GetLine(); } +CVAR(Int, dehload, 0, CVAR_ARCHIVE) // Autoloading of .DEH lumps is disabled by default. + +// checks if lump is a .deh or .bex file. Only lumps in the root directory are considered valid. +static bool isDehFile(int lumpnum) +{ + const char* const fullName = Wads.GetLumpFullName(lumpnum); + const char* const extension = strrchr(fullName, '.'); + + return NULL != extension && strchr(fullName, '/') == NULL + && (0 == stricmp(extension, ".deh") || 0 == stricmp(extension, ".bex")); +} + int D_LoadDehLumps() { int lastlump = 0, lumpnum, count = 0; @@ -2338,28 +2350,32 @@ int D_LoadDehLumps() count += D_LoadDehLump(lumpnum); } -#if 0 // commented out for 'maint' version. - if (0 == PatchSize) + if (0 == PatchSize && dehload > 0) { // No DEH/BEX patch is loaded yet, try to find lump(s) with specific extensions - for (lumpnum = 0, lastlump = Wads.GetNumLumps(); - lumpnum < lastlump; - ++lumpnum) + if (dehload == 1) // load all .DEH lumps that are found. { - const char* const fullName = Wads.GetLumpFullName(lumpnum); - const char* const extension = strrchr(fullName, '.'); - - const bool isDehOrBex = NULL != extension - && (0 == stricmp(extension, ".deh") || 0 == stricmp(extension, ".bex")); - - if (isDehOrBex) + for (lumpnum = 0, lastlump = Wads.GetNumLumps(); lumpnum < lastlump; ++lumpnum) { - count += D_LoadDehLump(lumpnum); + if (isDehFile(lumpnum)) + { + count += D_LoadDehLump(lumpnum); + } + } + } + else // only load the last .DEH lump that is found. + { + for (lumpnum = Wads.GetNumLumps()-1; lumpnum >=0; --lumpnum) + { + if (isDehFile(lumpnum)) + { + count += D_LoadDehLump(lumpnum); + break; + } } } } -#endif return count; } @@ -2929,7 +2945,7 @@ void FinishDehPatch () PClass *subclass = RUNTIME_CLASS(ADehackedPickup)->CreateDerivedClass (typeNameBuilder, sizeof(ADehackedPickup)); AActor *defaults2 = GetDefaultByType (subclass); - memcpy (defaults2, defaults1, sizeof(AActor)); + memcpy ((void *)defaults2, (void *)defaults1, sizeof(AActor)); // Make a copy of the replaced class's state labels FStateDefinitions statedef; diff --git a/src/d_main.cpp b/src/d_main.cpp index f0e7e7676..93e6368c1 100644 --- a/src/d_main.cpp +++ b/src/d_main.cpp @@ -38,7 +38,7 @@ #endif #include -#if defined(unix) || defined(__APPLE__) +#if defined(__unix__) || defined(__APPLE__) #include #endif @@ -856,7 +856,7 @@ void D_Display () FTexture *tex; int x; - tex = TexMan[gameinfo.PauseSign]; + tex = TexMan(gameinfo.PauseSign); x = (SCREENWIDTH - tex->GetScaledWidth() * CleanXfac)/2 + tex->GetScaledLeftOffset() * CleanXfac; screen->DrawTexture (tex, x, 4, DTA_CleanNoMove, true, TAG_DONE); @@ -1234,7 +1234,7 @@ void D_DoAdvanceDemo (void) static char demoname[8] = "DEMO1"; static int democount = 0; static int pagecount; - const char *pagename = NULL; + FString pagename; advancedemo = false; @@ -1299,7 +1299,7 @@ void D_DoAdvanceDemo (void) default: case 0: gamestate = GS_DEMOSCREEN; - pagename = gameinfo.titlePage; + pagename = gameinfo.TitlePage; pagetic = (int)(gameinfo.titleTime * TICRATE); S_ChangeMusic (gameinfo.titleMusic, gameinfo.titleOrder, false); demosequence = 3; @@ -1807,19 +1807,23 @@ static FString ParseGameInfo(TArray &pwads, const char *fn, const char // Try looking for the wad in the same directory as the .wad // before looking for it in the current directory. + FString checkpath; if (lastSlash != NULL) { - FString checkpath(fn, (lastSlash - fn) + 1); + checkpath = FString(fn, (lastSlash - fn) + 1); checkpath += sc.String; - - if (!FileExists (checkpath)) - { - pos += D_AddFile(pwads, sc.String, true, pos); - } - else - { - pos += D_AddFile(pwads, checkpath, true, pos); - } + } + else + { + checkpath = sc.String; + } + if (!FileExists(checkpath)) + { + pos += D_AddFile(pwads, sc.String, true, pos); + } + else + { + pos += D_AddFile(pwads, checkpath, true, pos); } } while (sc.CheckToken(',')); @@ -1861,6 +1865,15 @@ static FString ParseGameInfo(TArray &pwads, const char *fn, const char sc.MustGetString(); DoomStartupInfo.Song = sc.String; } + else + { + // Silently ignore unknown properties + do + { + sc.MustGetAnyToken(); + } + while(sc.CheckToken(',')); + } } return iwad; } @@ -1980,7 +1993,19 @@ static void D_DoomInit() SetLanguageIDs (); - rngseed = I_MakeRNGSeed(); + const char *v = Args->CheckValue("-rngseed"); + if (v) + { + rngseed = staticrngseed = atoi(v); + use_staticrng = true; + Printf("D_DoomInit: Static RNGseed %d set.\n", rngseed); + } + else + { + rngseed = I_MakeRNGSeed(); + use_staticrng = false; + } + FRandom::StaticClearRandom (); Printf ("M_LoadDefaults: Load system defaults.\n"); @@ -2010,7 +2035,7 @@ static void AddAutoloadFiles(const char *gamesection) D_AddFile (allwads, wad); // [RH] Add any .wad files in the skins directory -#ifdef unix +#ifdef __unix__ file = SHARE_DIR; #else file = progdir; @@ -2018,7 +2043,7 @@ static void AddAutoloadFiles(const char *gamesection) file += "skins"; D_AddDirectory (allwads, file); -#ifdef unix +#ifdef __unix__ file = NicePath("~/" GAME_DIR "/skins"); D_AddDirectory (allwads, file); #endif @@ -2138,17 +2163,6 @@ static void CheckCmdLine() Printf ("%s", GStrings("D_DEVSTR")); } -#if !defined(unix) && !defined(__APPLE__) - // We do not need to support -cdrom under Unix, because all the files - // that would go to c:\\zdoomdat are already stored in .zdoom inside - // the user's home directory. - if (Args->CheckParm("-cdrom")) - { - Printf ("%s", GStrings("D_CDROM")); - mkdir (CDROM_DIR, 0); - } -#endif - // turbo option // [RH] (now a cvar) v = Args->CheckValue("-turbo"); if (v != NULL) @@ -2221,6 +2235,13 @@ void D_DoomMain (void) FString *args; int argcount; + // +logfile gets checked too late to catch the full startup log in the logfile so do some extra check for it here. + FString logfile = Args->TakeValue("+logfile"); + if (logfile != NULL) + { + execLogfile(logfile); + } + D_DoomInit(); PClass::StaticInit (); atterm(FinalGC); diff --git a/src/d_net.cpp b/src/d_net.cpp index 0ea8e58c5..60a2b61c4 100644 --- a/src/d_net.cpp +++ b/src/d_net.cpp @@ -704,8 +704,6 @@ void GetPackets (void) } continue; // extra setup packet } - - lastglobalrecvtime = I_GetTime (false); //Update the last time a packet was recieved netnode = doomcom.remotenode; netconsole = playerfornode[netnode] & ~PL_DRONE; @@ -1054,6 +1052,12 @@ void NetUpdate (void) if (singletics) return; // singletic update is synchronous + if (demoplayback) + { + resendto[0] = nettics[0] = (maketic / ticdup); + return; // Don't touch netcmd data while playing a demo, as it'll already exist. + } + // If maketic didn't cross a ticdup boundary, only send packets // to players waiting for resends. resendOnly = (maketic / ticdup) == (maketic - i) / ticdup; @@ -1381,7 +1385,7 @@ bool DoArbitrate (void *userdata) stream = &netbuffer[4]; s = ReadString (&stream); - startmap = FString(s, 8); + startmap = s; delete[] s; rngseed = ReadLong (&stream); C_ReadCVars (&stream); @@ -1749,6 +1753,8 @@ void TryRunTics (void) if (counts == 0 && !doWait) { + // Check possible stall conditions + Net_CheckLastRecieved(counts); return; } @@ -1826,32 +1832,8 @@ void TryRunTics (void) if (lowtic < gametic) I_Error ("TryRunTics: lowtic < gametic"); - // [Ed850] Check to see the last time a packet was recieved. - // If it's longer then 3 seconds, a node has likely stalled. Check which one and re-request its last packet. - if(I_GetTime(false) - lastglobalrecvtime >= TICRATE*3) - { - int latenode = 0; // Node 0 is the local player, and should always be the highest - lastglobalrecvtime = I_GetTime(false); //Bump the count - - if(NetMode == NET_PeerToPeer || consoleplayer == Net_Arbitrator) - { - for (i = 0; i < doomcom.numnodes; i++) - if (nodeingame[i] && nettics[i] < nettics[latenode]) - latenode = i; - } - else if (nodeingame[nodeforplayer[Net_Arbitrator]] && - nettics[nodeforplayer[Net_Arbitrator]] < nettics[0]) - { // Likely a packet server game. Only check the packet host. - latenode = Net_Arbitrator; - } - - if (debugfile) - fprintf (debugfile, "lost tics from %i (%i to %i)\n", - latenode, nettics[latenode], gametic); - - if(latenode != 0) // Send resend request to late node (if not yourself... somehow). Also mark the node as waiting to display it in the hud. - remoteresend[latenode] = players[playerfornode[latenode]].waiting = hadlate = true; - } + // Check possible stall conditions + Net_CheckLastRecieved (counts); // don't stay in here forever -- give the menu a chance to work if (I_GetTime (false) - entertic >= TICRATE/3) @@ -1862,12 +1844,11 @@ void TryRunTics (void) } } - if (hadlate) - { - hadlate = false; - for (i = 0; i < MAXPLAYERS; i++) - players[i].waiting = false; - } + //Tic lowtic is high enough to process this gametic. Clear all possible waiting info + hadlate = false; + for (i = 0; i < MAXPLAYERS; i++) + players[i].waiting = false; + lastglobalrecvtime = I_GetTime (false); //Update the last time the game tic'd over // run the count tics if (counts > 0) @@ -1895,6 +1876,44 @@ void TryRunTics (void) } } +void Net_CheckLastRecieved (int counts) +{ + // [Ed850] Check to see the last time a packet was recieved. + // If it's longer then 3 seconds, a node has likely stalled. + if (I_GetTime(false) - lastglobalrecvtime >= TICRATE * 3) + { + lastglobalrecvtime = I_GetTime(false); //Bump the count + + if (NetMode == NET_PeerToPeer || consoleplayer == Net_Arbitrator) + { + //Keep the local node in the for loop so we can still log any cases where the local node is /somehow/ late. + //However, we don't send a resend request for sanity reasons. + for (int i = 0; i < doomcom.numnodes; i++) + { + if (nodeingame[i] && nettics[i] <= gametic + counts) + { + if (debugfile && !players[playerfornode[i]].waiting) + fprintf(debugfile, "%i is slow (%i to %i)\n", + i, nettics[i], gametic + counts); + //Send resend request to the late node. Also mark the node as waiting to display it in the hud. + if (i != 0) + remoteresend[i] = players[playerfornode[i]].waiting = hadlate = true; + } + else + players[playerfornode[i]].waiting = false; + } + } + else + { //Send a resend request to the Arbitrator, as it's obvious we are stuck here. + if (debugfile && !players[playerfornode[Net_Arbitrator]].waiting) + fprintf(debugfile, "Arbitrator is slow (%i to %i)\n", + nettics[Net_Arbitrator], gametic + counts); + //Send resend request to the Arbitrator. Also mark the Arbitrator as waiting to display it in the hud. + remoteresend[Net_Arbitrator] = players[playerfornode[Net_Arbitrator]].waiting = hadlate = true; + } + } +} + void Net_NewMakeTic (void) { specials.NewMakeTic (); @@ -2554,7 +2573,7 @@ static void RunScript(BYTE **stream, APlayerPawn *pawn, int snum, int argn, int arg[i] = argval; } } - P_StartScript(pawn, NULL, snum, level.mapname, arg, MIN(countof(arg), argn), ACS_NET | always); + P_StartScript(pawn, NULL, snum, level.MapName, arg, MIN(countof(arg), argn), ACS_NET | always); } void Net_SkipCommand (int type, BYTE **stream) diff --git a/src/d_net.h b/src/d_net.h index 507723d53..4cd3e66f5 100644 --- a/src/d_net.h +++ b/src/d_net.h @@ -115,6 +115,9 @@ void D_QuitNetGame (void); //? how many ticks to run? void TryRunTics (void); +//Use for checking to see if the netgame has stalled +void Net_CheckLastRecieved(int); + // [RH] Functions for making and using special "ticcmds" void Net_NewMakeTic (); void Net_WriteByte (BYTE); diff --git a/src/d_netinfo.cpp b/src/d_netinfo.cpp index 12fb187ae..f3f83e25e 100644 --- a/src/d_netinfo.cpp +++ b/src/d_netinfo.cpp @@ -387,7 +387,7 @@ void D_SetupUserInfo () { // Some cvars don't copy their original value directly. case NAME_Team: coninfo->TeamChanged(team); break; - case NAME_Skin: coninfo->SkinChanged(skin); break; + case NAME_Skin: coninfo->SkinChanged(skin, players[consoleplayer].CurrentPlayerClass); break; case NAME_Gender: coninfo->GenderChanged(gender); break; case NAME_PlayerClass: coninfo->PlayerClassChanged(playerclass); break; // The rest do. @@ -447,9 +447,9 @@ int userinfo_t::TeamChanged(int team) return team; } -int userinfo_t::SkinChanged(const char *skinname) +int userinfo_t::SkinChanged(const char *skinname, int playerclass) { - int skinnum = R_FindSkin(skinname, 0); + int skinnum = R_FindSkin(skinname, playerclass); *static_cast((*this)[NAME_Skin]) = skinnum; return skinnum; } @@ -821,7 +821,7 @@ void D_ReadUserInfoStrings (int pnum, BYTE **stream, bool update) break; case NAME_Skin: - info->SkinChanged(value); + info->SkinChanged(value, players[pnum].CurrentPlayerClass); if (players[pnum].mo != NULL) { if (players[pnum].cls != NULL && @@ -861,7 +861,7 @@ void D_ReadUserInfoStrings (int pnum, BYTE **stream, bool update) val.String = CleanseString(value.LockBuffer()); (*cvar_ptr)->SetGenericRep(val, CVAR_String); value.UnlockBuffer(); - if (keyname == NAME_Name && update && oldname != value) + if (keyname == NAME_Name && update && oldname.Compare (value)) { Printf("%s is now known as %s\n", oldname.GetChars(), value.GetChars()); } @@ -941,14 +941,21 @@ void WriteUserInfo(FArchive &arc, userinfo_t &info) arc << name; } -void ReadUserInfo(FArchive &arc, userinfo_t &info) +void ReadUserInfo(FArchive &arc, userinfo_t &info, FString &skin) { FName name; FBaseCVar **cvar; char *str = NULL; UCVarValue val; + if (SaveVersion < 4253) + { + ReadCompatibleUserInfo(arc, info); + return; + } + info.Reset(); + skin = NULL; for (arc << name; name != NAME_None; arc << name) { cvar = info.CheckKey(name); @@ -958,7 +965,7 @@ void ReadUserInfo(FArchive &arc, userinfo_t &info) switch (name) { case NAME_Team: info.TeamChanged(atoi(str)); break; - case NAME_Skin: info.SkinChanged(str); break; + case NAME_Skin: skin = str; break; // Caller must call SkinChanged() once current calss is known case NAME_PlayerClass: info.PlayerClassChanged(str); break; default: val.String = str; @@ -973,23 +980,6 @@ void ReadUserInfo(FArchive &arc, userinfo_t &info) } } -FArchive &operator<< (FArchive &arc, userinfo_t &info) -{ - if (SaveVersion < 4253) - { - ReadCompatibleUserInfo(arc, info); - } - else if (arc.IsStoring()) - { - WriteUserInfo(arc, info); - } - else - { - ReadUserInfo(arc, info); - } - return arc; -} - CCMD (playerinfo) { if (argv.argc() < 2) @@ -1018,6 +1008,7 @@ CCMD (playerinfo) if (!playeringame[i]) { Printf(TEXTCOLOR_ORANGE "Player %d is not in the game\n", i); + return; } // Print special info diff --git a/src/d_player.h b/src/d_player.h index f6f7674d7..f50db97b1 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -198,6 +198,7 @@ typedef enum CF_INSTANTWEAPSWITCH= 1 << 11, // [RH] Switch weapons instantly CF_TOTALLYFROZEN = 1 << 12, // [RH] All players can do is press +use CF_PREDICTING = 1 << 13, // [RH] Player movement is being predicted + CF_INTERPVIEW = 1 << 14, // [RH] view was changed outside of input, so interpolate one frame CF_DRAIN = 1 << 16, // Player owns a drain powerup CF_HIGHJUMP = 1 << 18, // more Skulltag flags. Implementation not guaranteed though. ;) CF_REFLECTION = 1 << 19, @@ -332,7 +333,7 @@ struct userinfo_t : TMap void Reset(); int TeamChanged(int team); - int SkinChanged(const char *skinname); + int SkinChanged(const char *skinname, int playerclass); int SkinNumChanged(int skinnum); int GenderChanged(const char *gendername); int PlayerClassChanged(const char *classname); @@ -342,8 +343,8 @@ struct userinfo_t : TMap int ColorSetChanged(int setnum); }; -FArchive &operator<< (FArchive &arc, userinfo_t &info); - +void ReadUserInfo(FArchive &arc, userinfo_t &info, FString &skin); +void WriteUserInfo(FArchive &arc, userinfo_t &info); // // Extended player object info: player_t @@ -433,6 +434,7 @@ public: TObjPtr PremorphWeapon; // ready weapon before morphing int chickenPeck; // chicken peck countdown int jumpTics; // delay the next jump for a moment + bool onground; // Identifies if this player is on the ground or other object int respawn_time; // [RH] delay respawning until this tic TObjPtr camera; // [RH] Whose eyes this player sees through diff --git a/src/decallib.cpp b/src/decallib.cpp index c8fe6c593..91827409b 100644 --- a/src/decallib.cpp +++ b/src/decallib.cpp @@ -452,7 +452,7 @@ void FDecalLib::ParseDecal (FScanner &sc) decalNum = GetDecalID (sc); sc.MustGetStringName ("{"); - memset (&newdecal, 0, sizeof(newdecal)); + memset ((void *)&newdecal, 0, sizeof(newdecal)); newdecal.PicNum.SetInvalid(); newdecal.ScaleX = newdecal.ScaleY = FRACUNIT; newdecal.RenderFlags = RF_WALLSPRITE; diff --git a/src/dobject.h b/src/dobject.h index 2ae5493c6..40b47ee5c 100644 --- a/src/dobject.h +++ b/src/dobject.h @@ -473,7 +473,7 @@ public: // use this method. virtual size_t PointerSubstitution (DObject *old, DObject *notOld); static size_t StaticPointerSubstitution (DObject *old, DObject *notOld); - + PClass *GetClass() const { if (Class == NULL) diff --git a/src/doomdata.h b/src/doomdata.h index 55903170a..215c2a263 100644 --- a/src/doomdata.h +++ b/src/doomdata.h @@ -85,6 +85,14 @@ struct mapsidedef_t short sector; // Front sector, towards viewer. }; +struct intmapsidedef_t +{ + FString toptexture; + FString bottomtexture; + FString midtexture; +}; + + // A LineDef, as used for editing, and as input to the BSP builder. struct maplinedef_t { @@ -192,9 +200,10 @@ enum EMapLineFlags // These are flags that use different values internally ML_RESERVED_ETERNITY = 0x0800, // [RH] Extra flags for Strife - ML_TRANSLUCENT_STRIFE = 0x1000, ML_RAILING_STRIFE = 0x0200, ML_BLOCK_FLOATERS_STRIFE = 0x0400, + ML_TRANSPARENT_STRIFE = 0x0800, + ML_TRANSLUCENT_STRIFE = 0x1000, }; @@ -344,6 +353,15 @@ struct FMapThing int args[5]; int Conversation; fixed_t gravity; + fixed_t alpha; + DWORD fillcolor; + fixed_t scaleX; + fixed_t scaleY; + int health; + int score; + short pitch; + short roll; + DWORD RenderStyle; void Serialize (FArchive &); }; @@ -385,6 +403,7 @@ enum EMapThingFlags MTF_SECRET = 0x080000, // Secret pickup MTF_NOINFIGHTING = 0x100000, + // BOOM and DOOM compatible versions of some of the above BTF_NOTSINGLE = 0x0010, // (TF_COOPERATIVE|TF_DEATHMATCH) diff --git a/src/doomdef.h b/src/doomdef.h index 675923b4a..6ef9fcd04 100644 --- a/src/doomdef.h +++ b/src/doomdef.h @@ -130,6 +130,7 @@ enum ESkillLevels #define KEY_F10 0x44 // DIK_F10 #define KEY_F11 0x57 // DIK_F11 #define KEY_F12 0x58 // DIK_F12 +#define KEY_GRAVE 0x29 // DIK_GRAVE #define KEY_BACKSPACE 0x0e // DIK_BACK @@ -350,6 +351,7 @@ enum BCOMPATF_BADPORTALS = 1 << 4, // Restores the old unstable portal behavior BCOMPATF_REBUILDNODES = 1 << 5, // Force node rebuild BCOMPATF_LINKFROZENPROPS = 1 << 6, // Clearing PROP_TOTALLYFROZEN or PROP_FROZEN also clears the other + BCOMPATF_NOWINDOWCHECK = 1 << 7, // Disable the window check in CheckForPushSpecial() }; // phares 3/20/98: diff --git a/src/doomtype.h b/src/doomtype.h index 31f96d2ab..d201ca71d 100644 --- a/src/doomtype.h +++ b/src/doomtype.h @@ -34,6 +34,10 @@ // source files, so we can't use it. So define PATH_MAX to be what MAX_PATH // currently is: #define PATH_MAX 260 + +// Disable warning about using unsized arrays in structs. It supports it just +// fine, and so do Clang and GCC, but the latter two don't warn about it. +#pragma warning(disable:4200) #endif #include diff --git a/src/dthinker.cpp b/src/dthinker.cpp index 5405051e7..9ab8d5e31 100644 --- a/src/dthinker.cpp +++ b/src/dthinker.cpp @@ -454,7 +454,7 @@ int DThinker::TickThinkers (FThinkerList *list, FThinkerList *dest) node->PostBeginPlay(); } else if (dest != NULL) - { // Move thinker from this list to the destination list + { I_Error("There is a thinker in the fresh list that has already ticked.\n"); } diff --git a/src/files.cpp b/src/files.cpp index 80f0f8303..d7dfc2cbe 100644 --- a/src/files.cpp +++ b/src/files.cpp @@ -370,8 +370,8 @@ extern "C" void bz_internal_error (int errcode) // //========================================================================== -static void *SzAlloc(void *p, size_t size) { p = p; return malloc(size); } -static void SzFree(void *p, void *address) { p = p; free(address); } +static void *SzAlloc(void *, size_t size) { return malloc(size); } +static void SzFree(void *, void *address) { free(address); } ISzAlloc g_Alloc = { SzAlloc, SzFree }; FileReaderLZMA::FileReaderLZMA (FileReader &file, size_t uncompressed_size, bool zip) diff --git a/src/fragglescript/t_fspic.cpp b/src/fragglescript/t_fspic.cpp index d5e6e5aec..9da3cf15c 100644 --- a/src/fragglescript/t_fspic.cpp +++ b/src/fragglescript/t_fspic.cpp @@ -73,6 +73,7 @@ public: ~DHUDPicManager() {} void Serialize(FArchive & ar); virtual void DoDraw (int linenum, int x, int y, int hudheight, float translucent); + void DoDraw (int, int, int, bool, int) { assert(false); } } ; IMPLEMENT_CLASS(DHUDPicManager) diff --git a/src/fragglescript/t_func.cpp b/src/fragglescript/t_func.cpp index 448c200d8..2513a68a8 100644 --- a/src/fragglescript/t_func.cpp +++ b/src/fragglescript/t_func.cpp @@ -73,7 +73,6 @@ static FRandom pr_script("FScript"); #define AngleToFixed(x) ((((double) x) / ((double) ANG45/45)) * FRACUNIT) #define FixedToAngle(x) ((((double) x) / FRACUNIT) * ANG45/45) -#define FIXED_TO_FLOAT(f) ((f)/(float)FRACUNIT) // functions. FParser::SF_ means Script Function not, well.. heh, me @@ -1417,11 +1416,11 @@ void FParser::SF_PointToDist(void) if (CheckArgs(4)) { // Doing this in floating point is actually faster with modern computers! - float x = floatvalue(t_argv[2]) - floatvalue(t_argv[0]); - float y = floatvalue(t_argv[3]) - floatvalue(t_argv[1]); + double x = floatvalue(t_argv[2]) - floatvalue(t_argv[0]); + double y = floatvalue(t_argv[3]) - floatvalue(t_argv[1]); t_return.type = svt_fixed; - t_return.value.f = (fixed_t)(sqrtf(x*x+y*y)*65536.f); + t_return.value.f = FLOAT2FIXED(sqrt(x*x+y*y)*65536.f); } } diff --git a/src/fragglescript/t_load.cpp b/src/fragglescript/t_load.cpp index d9b4f2d04..eedb68f7c 100644 --- a/src/fragglescript/t_load.cpp +++ b/src/fragglescript/t_load.cpp @@ -183,10 +183,7 @@ void FScriptLoader::ParseInfoCmd(char *line, FString &scriptsrc) sc.MustGetStringName("="); sc.MustGetString(); - strncpy(level.skypic1, sc.String, 8); - strncpy(level.skypic2, sc.String, 8); - level.skypic1[8]=level.skypic2[8]=0; - sky2texture = sky1texture = TexMan.GetTexture (sc.String, FTexture::TEX_Wall, FTextureManager::TEXMAN_Overridable); + sky2texture = sky1texture = level.skytexture1 = level.skytexture2 = TexMan.GetTexture (sc.String, FTexture::TEX_Wall, FTextureManager::TEXMAN_Overridable|FTextureManager::TEXMAN_ReturnFirst); R_InitSkyMap (); } else if (sc.Compare("interpic")) @@ -205,15 +202,13 @@ void FScriptLoader::ParseInfoCmd(char *line, FString &scriptsrc) { sc.MustGetStringName("="); sc.MustGetString(); - strncpy(level.nextmap, sc.String, 8); - level.nextmap[8]=0; + level.NextMap = sc.String; } else if (sc.Compare("nextsecret")) { sc.MustGetStringName("="); sc.MustGetString(); - strncpy(level.secretmap, sc.String, 8); - level.secretmap[8]=0; + level.NextSecretMap = sc.String; } else if (sc.Compare("drown")) { diff --git a/src/fragglescript/t_script.h b/src/fragglescript/t_script.h index e3db7da3d..ffa2dae3c 100644 --- a/src/fragglescript/t_script.h +++ b/src/fragglescript/t_script.h @@ -110,7 +110,7 @@ struct svalue_t int intvalue(const svalue_t & v); fixed_t fixedvalue(const svalue_t & v); -float floatvalue(const svalue_t & v); +double floatvalue(const svalue_t & v); const char *stringvalue(const svalue_t & v); AActor *actorvalue(const svalue_t &svalue); diff --git a/src/fragglescript/t_variable.cpp b/src/fragglescript/t_variable.cpp index 7326fe4eb..7076a395b 100644 --- a/src/fragglescript/t_variable.cpp +++ b/src/fragglescript/t_variable.cpp @@ -89,11 +89,12 @@ fixed_t fixedvalue(const svalue_t &v) // //========================================================================== -float floatvalue(const svalue_t &v) +double floatvalue(const svalue_t &v) { - return (float)( (v.type == svt_string ? atof(v.string) : - v.type == svt_fixed ? (float)(v.value.f / (float)FRACUNIT) : - v.type == svt_mobj ? -1.f : (float)v.value.i )); + return + v.type == svt_string ? atof(v.string) : + v.type == svt_fixed ? FIXED2DBL(v.value.f) : + v.type == svt_mobj ? -1. : (double)v.value.i; } //========================================================================== diff --git a/src/g_game.cpp b/src/g_game.cpp index 506b8e24b..b84ac890d 100644 --- a/src/g_game.cpp +++ b/src/g_game.cpp @@ -565,7 +565,7 @@ void G_BuildTiccmd (ticcmd_t *cmd) int tspeed = speed; if (turnheld < SLOWTURNTICS) - tspeed *= 2; // slow turn + tspeed += 2; // slow turn if (Button_Right.bDown) { @@ -775,7 +775,7 @@ void G_AddViewPitch (int look) else if (look > 0) { // Avoid overflowing - if (LocalViewPitch + look <= LocalViewPitch) + if (LocalViewPitch > INT_MAX - look) { LocalViewPitch = 0x78000000; } @@ -787,7 +787,7 @@ void G_AddViewPitch (int look) else if (look < 0) { // Avoid overflowing - if (LocalViewPitch + look >= LocalViewPitch) + if (LocalViewPitch < INT_MIN - look) { LocalViewPitch = -0x78000000; } @@ -1307,7 +1307,7 @@ void G_PlayerFinishLevel (int player, EFinishLevelType mode, int flags) } // Clears the entire inventory and gives back the defaults for starting a game - if (flags & CHANGELEVEL_RESETINVENTORY) + if ((flags & CHANGELEVEL_RESETINVENTORY) && p->playerstate != PST_DEAD) { p->mo->ClearInventory(); p->mo->GiveDefaultInventory(); @@ -1621,7 +1621,7 @@ void G_DoReborn (int playernum, bool freshbot) { // Reload the level from scratch bool indemo = demoplayback; BackupSaveName = ""; - G_InitNew (level.mapname, false); + G_InitNew (level.MapName, false); demoplayback = indemo; // gameaction = ga_loadlevel; } @@ -1919,32 +1919,10 @@ FString G_BuildSaveName (const char *prefix, int slot) leader = Args->CheckValue ("-savedir"); if (leader.IsEmpty()) { -#if !defined(unix) && !defined(__APPLE__) - if (Args->CheckParm ("-cdrom")) - { - leader = CDROM_DIR "/"; - } - else -#endif - { - leader = save_dir; - } + leader = save_dir; if (leader.IsEmpty()) { -#ifdef unix - leader = "~/" GAME_DIR; -#elif defined(__APPLE__) - char cpath[PATH_MAX]; - FSRef folder; - - if (noErr == FSFindFolder(kUserDomain, kDocumentsFolderType, kCreateFolder, &folder) && - noErr == FSRefMakePath(&folder, (UInt8*)cpath, PATH_MAX)) - { - leader << cpath << "/" GAME_DIR "/Savegames/"; - } -#else - leader = progdir; -#endif + leader = M_GetSavegamesPath(); } } size_t len = leader.Len(); @@ -2049,7 +2027,7 @@ static void PutSaveComment (FILE *file) // Get level name //strcpy (comment, level.level_name); - mysnprintf(comment, countof(comment), "%s - %s", level.mapname, level.LevelName.GetChars()); + mysnprintf(comment, countof(comment), "%s - %s", level.MapName.GetChars(), level.LevelName.GetChars()); len = (WORD)strlen (comment); comment[len] = '\n'; @@ -2110,7 +2088,7 @@ void G_DoSaveGame (bool okForQuicksave, FString filename, const char *descriptio M_AppendPNGText (stdfile, "Engine", GAMESIG); M_AppendPNGText (stdfile, "ZDoom Save Version", SAVESIG); M_AppendPNGText (stdfile, "Title", description); - M_AppendPNGText (stdfile, "Current Map", level.mapname); + M_AppendPNGText (stdfile, "Current Map", level.MapName); PutSaveWads (stdfile); PutSaveComment (stdfile); @@ -2311,7 +2289,7 @@ void G_BeginRecording (const char *startmap) if (startmap == NULL) { - startmap = level.mapname; + startmap = level.MapName; } demo_p = demobuffer; @@ -2324,11 +2302,10 @@ void G_BeginRecording (const char *startmap) WriteWord (DEMOGAMEVERSION, &demo_p); // Write ZDoom version *demo_p++ = 2; // Write minimum version needed to use this demo. *demo_p++ = 3; // (Useful?) - for (i = 0; i < 8; i++) // Write name of map demo was recorded on. - { - *demo_p++ = startmap[i]; - } - WriteLong (rngseed, &demo_p); // Write RNG seed + + strcpy((char*)demo_p, startmap); // Write name of map demo was recorded on. + demo_p += strlen(startmap) + 1; + WriteLong(rngseed, &demo_p); // Write RNG seed *demo_p++ = consoleplayer; FinishChunk (&demo_p); @@ -2407,7 +2384,7 @@ CCMD (timedemo) // [RH] Process all the information in a FORM ZDEM // until a BODY chunk is entered. -bool G_ProcessIFFDemo (char *mapname) +bool G_ProcessIFFDemo (FString &mapname) { bool headerHit = false; bool bodyHit = false; @@ -2463,9 +2440,16 @@ bool G_ProcessIFFDemo (char *mapname) Printf ("Demo requires a newer version of ZDoom!\n"); return true; } - memcpy (mapname, demo_p, 8); // Read map name - mapname[8] = 0; - demo_p += 8; + if (demover >= 0x21a) + { + mapname = (char*)demo_p; + demo_p += mapname.Len() + 1; + } + else + { + mapname = FString((char*)demo_p, 8); + demo_p += 8; + } rngseed = ReadLong (&demo_p); // Only reset the RNG if this demo is not in conjunction with a savegame. if (mapname[0] != 0) @@ -2547,7 +2531,7 @@ bool G_ProcessIFFDemo (char *mapname) void G_DoPlayDemo (void) { - char mapname[9]; + FString mapname; int demolump; gameaction = ga_nothing; @@ -2600,7 +2584,7 @@ void G_DoPlayDemo (void) // don't spend a lot of time in loadlevel precache = false; demonew = true; - if (mapname[0] != 0) + if (mapname.Len() != 0) { G_InitNew (mapname, false); } diff --git a/src/g_hexen/a_fighteraxe.cpp b/src/g_hexen/a_fighteraxe.cpp index 50b378e50..f80af876b 100644 --- a/src/g_hexen/a_fighteraxe.cpp +++ b/src/g_hexen/a_fighteraxe.cpp @@ -26,8 +26,6 @@ void A_FAxeAttack (AActor *actor); extern void AdjustPlayerAngle (AActor *pmo, AActor *linetarget); -EXTERN_CVAR (Int, cl_bloodtype) - // The Fighter's Axe -------------------------------------------------------- class AFWeapAxe : public AFighterWeapon diff --git a/src/g_hexen/a_heresiarch.cpp b/src/g_hexen/a_heresiarch.cpp index b5bbced2f..15e6da9c1 100644 --- a/src/g_hexen/a_heresiarch.cpp +++ b/src/g_hexen/a_heresiarch.cpp @@ -88,7 +88,7 @@ void AHeresiarch::Die (AActor *source, AActor *inflictor, int dmgflags) if (script != 0) { - P_StartScript (this, NULL, script, level.mapname, NULL, 0, 0); + P_StartScript (this, NULL, script, level.MapName, NULL, 0, 0); } } diff --git a/src/g_level.cpp b/src/g_level.cpp index 0b07ae2b5..c4aafda4b 100644 --- a/src/g_level.cpp +++ b/src/g_level.cpp @@ -387,7 +387,7 @@ void G_InitNew (const char *mapname, bool bTitleLevel) StatusBar->NewGame (); setsizeneeded = true; - if (gameinfo.gametype == GAME_Strife || (SBarInfoScript != NULL && SBarInfoScript[SCRIPT_CUSTOM]->GetGameType() == GAME_Strife)) + if (gameinfo.gametype == GAME_Strife || (SBarInfoScript[SCRIPT_CUSTOM] != NULL && SBarInfoScript[SCRIPT_CUSTOM]->GetGameType() == GAME_Strife)) { // Set the initial quest log text for Strife. for (i = 0; i < MAXPLAYERS; ++i) @@ -408,9 +408,11 @@ void G_InitNew (const char *mapname, bool bTitleLevel) if (!savegamerestore) { - if (!netgame) - { // [RH] Change the random seed for each new single player game - rngseed = rngseed + 1; + if (!netgame && !demorecording && !demoplayback) + { + // [RH] Change the random seed for each new single player game + // [ED850] The demo already sets the RNG. + rngseed = use_staticrng ? staticrngseed : (rngseed + 1); } FRandom::StaticClearRandom (); P_ClearACSVars(true); @@ -443,10 +445,7 @@ void G_InitNew (const char *mapname, bool bTitleLevel) bglobal.Init (); } - if (mapname != level.mapname) - { - strcpy (level.mapname, mapname); - } + level.MapName = mapname; if (bTitleLevel) { gamestate = GS_TITLELEVEL; @@ -489,9 +488,9 @@ void G_ChangeLevel(const char *levelname, int position, int flags, int nextSkill { // end the game levelname = NULL; - if (!strncmp(level.nextmap, "enDSeQ",6)) + if (!level.NextMap.Compare("enDSeQ",6)) { - levelname = level.nextmap; // If there is already an end sequence please leave it alone! + nextlevel = level.NextMap; // If there is already an end sequence please leave it alone! } else { @@ -507,12 +506,14 @@ void G_ChangeLevel(const char *levelname, int position, int flags, int nextSkill if (nextredir != NULL) { nextinfo = nextredir; - levelname = nextinfo->mapname; } } + nextlevel = nextinfo->MapName; + } + else + { + nextlevel = levelname; } - - if (levelname != NULL) nextlevel = levelname; if (nextSkill != -1) NextSkill = nextSkill; @@ -594,18 +595,18 @@ void G_ChangeLevel(const char *levelname, int position, int flags, int nextSkill const char *G_GetExitMap() { - return level.nextmap; + return level.NextMap; } const char *G_GetSecretExitMap() { - const char *nextmap = level.nextmap; + const char *nextmap = level.NextMap; - if (level.secretmap[0] != 0) + if (level.NextSecretMap.Len() > 0) { - if (P_CheckMapData(level.secretmap)) + if (P_CheckMapData(level.NextSecretMap)) { - nextmap = level.secretmap; + nextmap = level.NextSecretMap; } } return nextmap; @@ -639,7 +640,7 @@ void G_DoCompleted (void) if (gamestate == GS_TITLELEVEL) { - strncpy (level.mapname, nextlevel, 255); + level.MapName = nextlevel; G_DoLoadLevel (startpos, false); startpos = 0; viewactive = true; @@ -648,20 +649,20 @@ void G_DoCompleted (void) // [RH] Mark this level as having been visited if (!(level.flags & LEVEL_CHANGEMAPCHEAT)) - FindLevelInfo (level.mapname)->flags |= LEVEL_VISITED; + FindLevelInfo (level.MapName)->flags |= LEVEL_VISITED; if (automapactive) AM_Stop (); wminfo.finished_ep = level.cluster - 1; - wminfo.LName0 = TexMan[TexMan.CheckForTexture(level.info->pname, FTexture::TEX_MiscPatch)]; - wminfo.current = level.mapname; + wminfo.LName0 = TexMan[TexMan.CheckForTexture(level.info->PName, FTexture::TEX_MiscPatch)]; + wminfo.current = level.MapName; if (deathmatch && (dmflags & DF_SAME_LEVEL) && !(level.flags & LEVEL_CHANGEMAPCHEAT)) { - wminfo.next = level.mapname; + wminfo.next = level.MapName; wminfo.LName1 = wminfo.LName0; } else @@ -674,8 +675,8 @@ void G_DoCompleted (void) } else { - wminfo.next = nextinfo->mapname; - wminfo.LName1 = TexMan[TexMan.CheckForTexture(nextinfo->pname, FTexture::TEX_MiscPatch)]; + wminfo.next = nextinfo->MapName; + wminfo.LName1 = TexMan[TexMan.CheckForTexture(nextinfo->PName, FTexture::TEX_MiscPatch)]; } } @@ -848,7 +849,7 @@ void G_DoLoadLevel (int position, bool autosave) "\n\35\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36" "\36\36\36\36\36\36\36\36\36\36\36\36\37\n\n" TEXTCOLOR_BOLD "%s - %s\n\n", - level.mapname, level.LevelName.GetChars()); + level.MapName.GetChars(), level.LevelName.GetChars()); if (wipegamestate == GS_LEVEL) wipegamestate = GS_FORCEWIPE; @@ -868,8 +869,8 @@ void G_DoLoadLevel (int position, bool autosave) // DOOM determines the sky texture to be used // depending on the current episode and the game version. // [RH] Fetch sky parameters from FLevelLocals. - sky1texture = TexMan.GetTexture (level.skypic1, FTexture::TEX_Wall, FTextureManager::TEXMAN_Overridable|FTextureManager::TEXMAN_ReturnFirst); - sky2texture = TexMan.GetTexture (level.skypic2, FTexture::TEX_Wall, FTextureManager::TEXMAN_Overridable|FTextureManager::TEXMAN_ReturnFirst); + sky1texture = level.skytexture1; + sky2texture = level.skytexture2; // [RH] Set up details about sky rendering R_InitSkyMap (); @@ -897,7 +898,7 @@ void G_DoLoadLevel (int position, bool autosave) } level.maptime = 0; - P_SetupLevel (level.mapname, position); + P_SetupLevel (level.MapName, position); AM_LevelInit(); @@ -1054,7 +1055,7 @@ void G_DoWorldDone (void) } else { - strncpy (level.mapname, nextlevel, 255); + level.MapName = nextlevel; } G_StartTravel (); G_DoLoadLevel (startpos, true); @@ -1084,6 +1085,7 @@ void G_StartTravel () { AActor *pawn = players[i].mo; AInventory *inv; + players[i].camera = NULL; // Only living players travel. Dead ones get a new body on the new level. if (players[i].health > 0) @@ -1214,20 +1216,21 @@ void G_InitLevelLocals () level.flags = 0; level.flags2 = 0; - info = FindLevelInfo (level.mapname); + info = FindLevelInfo (level.MapName); level.info = info; level.skyspeed1 = info->skyspeed1; level.skyspeed2 = info->skyspeed2; - strncpy (level.skypic2, info->skypic2, 8); + level.skytexture1 = TexMan.GetTexture(info->SkyPic1, FTexture::TEX_Wall, FTextureManager::TEXMAN_Overridable | FTextureManager::TEXMAN_ReturnFirst); + level.skytexture2 = TexMan.GetTexture(info->SkyPic2, FTexture::TEX_Wall, FTextureManager::TEXMAN_Overridable | FTextureManager::TEXMAN_ReturnFirst); level.fadeto = info->fadeto; level.cdtrack = info->cdtrack; level.cdid = info->cdid; level.FromSnapshot = false; if (level.fadeto == 0) { - R_SetDefaultColormap (info->fadetable); - if (strnicmp (info->fadetable, "COLORMAP", 8) != 0) + R_SetDefaultColormap (info->FadeTable); + if (strnicmp (info->FadeTable, "COLORMAP", 8) != 0) { level.flags |= LEVEL_HASFADETABLE; } @@ -1270,15 +1273,8 @@ void G_InitLevelLocals () level.musicorder = info->musicorder; level.LevelName = level.info->LookupLevelName(); - strncpy (level.nextmap, info->nextmap, 10); - level.nextmap[10] = 0; - strncpy (level.secretmap, info->secretmap, 10); - level.secretmap[10] = 0; - strncpy (level.skypic1, info->skypic1, 8); - level.skypic1[8] = 0; - if (!level.skypic2[0]) - strncpy (level.skypic2, level.skypic1, 8); - level.skypic2[8] = 0; + level.NextMap = info->NextMap; + level.NextSecretMap = info->NextSecretMap; compatflags.Callback(); compatflags2.Callback(); @@ -1403,18 +1399,20 @@ void G_SerializeLevel (FArchive &arc, bool hubLoad) if (!hubLoad) level.totaltime = i; - if (arc.IsStoring ()) + if (SaveVersion >= 4507) { - arc.WriteName (level.skypic1); - arc.WriteName (level.skypic2); + arc << level.skytexture1 << level.skytexture2; } else { - strncpy (level.skypic1, arc.ReadName(), 8); - strncpy (level.skypic2, arc.ReadName(), 8); - sky1texture = TexMan.GetTexture (level.skypic1, FTexture::TEX_Wall, FTextureManager::TEXMAN_Overridable|FTextureManager::TEXMAN_ReturnFirst); - sky2texture = TexMan.GetTexture (level.skypic2, FTexture::TEX_Wall, FTextureManager::TEXMAN_Overridable|FTextureManager::TEXMAN_ReturnFirst); - R_InitSkyMap (); + level.skytexture1 = TexMan.GetTexture(arc.ReadName(), FTexture::TEX_Wall, FTextureManager::TEXMAN_Overridable | FTextureManager::TEXMAN_ReturnFirst); + level.skytexture2 = TexMan.GetTexture(arc.ReadName(), FTexture::TEX_Wall, FTextureManager::TEXMAN_Overridable | FTextureManager::TEXMAN_ReturnFirst); + } + if (arc.IsLoading()) + { + sky1texture = level.skytexture1; + sky2texture = level.skytexture2; + R_InitSkyMap(); } G_AirControlChanged (); @@ -1599,30 +1597,9 @@ void G_UnSnapshotLevel (bool hubLoad) // //========================================================================== -static void writeMapName (FArchive &arc, const char *name) -{ - BYTE size; - if (name[7] != 0) - { - size = 8; - } - else - { - size = (BYTE)strlen (name); - } - arc << size; - arc.Write (name, size); -} - -//========================================================================== -// -// -//========================================================================== - static void writeSnapShot (FArchive &arc, level_info_t *i) { - arc << i->snapshotVer; - writeMapName (arc, i->mapname); + arc << i->snapshotVer << i->MapName; i->snapshot->Serialize (arc); } @@ -1660,14 +1637,14 @@ void G_WriteSnapshots (FILE *file) { arc = new FPNGChunkArchive (file, VIST_ID); } - writeMapName (*arc, wadlevelinfos[i].mapname); + (*arc) << wadlevelinfos[i].MapName; } } if (arc != NULL) { - BYTE zero = 0; - *arc << zero; + FString empty = ""; + (*arc) << empty; delete arc; } @@ -1708,6 +1685,7 @@ void G_ReadSnapshots (PNGHandle *png) DWORD chunkLen; BYTE namelen; char mapname[256]; + FString MapName; level_info_t *i; G_ClearSnapshots (); @@ -1719,10 +1697,15 @@ void G_ReadSnapshots (PNGHandle *png) DWORD snapver; arc << snapver; - arc << namelen; - arc.Read (mapname, namelen); - mapname[namelen] = 0; - i = FindLevelInfo (mapname); + if (SaveVersion < 4508) + { + arc << namelen; + arc.Read(mapname, namelen); + mapname[namelen] = 0; + MapName = mapname; + } + else arc << MapName; + i = FindLevelInfo (MapName); i->snapshotVer = snapver; i->snapshot = new FCompressedMemFile; i->snapshot->Serialize (arc); @@ -1748,14 +1731,25 @@ void G_ReadSnapshots (PNGHandle *png) { FPNGChunkArchive arc (png->File->GetFile(), VIST_ID, chunkLen); - arc << namelen; - while (namelen != 0) + if (SaveVersion < 4508) { - arc.Read (mapname, namelen); - mapname[namelen] = 0; - i = FindLevelInfo (mapname); - i->flags |= LEVEL_VISITED; arc << namelen; + while (namelen != 0) + { + arc.Read(mapname, namelen); + mapname[namelen] = 0; + i = FindLevelInfo(mapname); + i->flags |= LEVEL_VISITED; + arc << namelen; + } + } + else + { + while (arc << MapName, MapName.Len() > 0) + { + i = FindLevelInfo(MapName); + i->flags |= LEVEL_VISITED; + } } } @@ -1799,7 +1793,7 @@ CCMD(listsnapshots) { unsigned int comp, uncomp; snapshot->GetSizes(comp, uncomp); - Printf("%s (%u -> %u bytes)\n", wadlevelinfos[i].mapname, comp, uncomp); + Printf("%s (%u -> %u bytes)\n", wadlevelinfos[i].MapName.GetChars(), comp, uncomp); } } } @@ -1811,8 +1805,7 @@ CCMD(listsnapshots) static void writeDefereds (FArchive &arc, level_info_t *i) { - writeMapName (arc, i->mapname); - arc << i->defered; + arc << i->MapName << i->defered; } //========================================================================== @@ -1839,8 +1832,8 @@ void P_WriteACSDefereds (FILE *file) if (arc != NULL) { // Signal end of defereds - BYTE zero = 0; - *arc << zero; + FString empty = ""; + (*arc) << empty; delete arc; } } @@ -1854,6 +1847,7 @@ void P_ReadACSDefereds (PNGHandle *png) { BYTE namelen; char mapname[256]; + FString MapName; size_t chunklen; P_RemoveDefereds (); @@ -1862,18 +1856,33 @@ void P_ReadACSDefereds (PNGHandle *png) { FPNGChunkArchive arc (png->File->GetFile(), ACSD_ID, chunklen); - arc << namelen; - while (namelen) + if (SaveVersion < 4508) { - arc.Read (mapname, namelen); - mapname[namelen] = 0; - level_info_t *i = FindLevelInfo (mapname); - if (i == NULL) - { - I_Error ("Unknown map '%s' in savegame", mapname); - } - arc << i->defered; arc << namelen; + while (namelen != 0) + { + arc.Read(mapname, namelen); + mapname[namelen] = 0; + level_info_t *i = FindLevelInfo(mapname); + if (i == NULL) + { + I_Error("Unknown map '%s' in savegame", mapname); + } + arc << i->defered; + arc << namelen; + } + } + else + { + while (arc << MapName, MapName.Len() > 0) + { + level_info_t *i = FindLevelInfo(MapName); + if (i == NULL) + { + I_Error("Unknown map '%s' in savegame", MapName.GetChars()); + } + arc << i->defered; + } } } png->File->ResetFilePtr(); @@ -1923,11 +1932,11 @@ CCMD(listmaps) for(unsigned i = 0; i < wadlevelinfos.Size(); i++) { level_info_t *info = &wadlevelinfos[i]; - MapData *map = P_OpenMapData(info->mapname, true); + MapData *map = P_OpenMapData(info->MapName, true); if (map != NULL) { - Printf("%s: '%s' (%s)\n", info->mapname, info->LookupLevelName().GetChars(), + Printf("%s: '%s' (%s)\n", info->MapName.GetChars(), info->LookupLevelName().GetChars(), Wads.GetWadName(Wads.GetLumpFile(map->lumpnum))); delete map; } diff --git a/src/g_level.h b/src/g_level.h index e7d1cbbd2..0cd366798 100644 --- a/src/g_level.h +++ b/src/g_level.h @@ -38,6 +38,7 @@ #include "doomdef.h" #include "sc_man.h" #include "s_sound.h" +#include "textures/textures.h" struct level_info_t; struct cluster_info_t; @@ -78,11 +79,11 @@ struct FMapInfoParser bool ParseLookupName(FString &dest); void ParseMusic(FString &name, int &order); - void ParseLumpOrTextureName(char *name); + //void ParseLumpOrTextureName(char *name); void ParseLumpOrTextureName(FString &name); void ParseCluster(); - void ParseNextMap(char *mapname); + void ParseNextMap(FString &mapname); level_info_t *ParseMapHeader(level_info_t &defaultinfo); void ParseMapDefinition(level_info_t &leveldef); void ParseGameInfo(); @@ -103,6 +104,7 @@ struct FMapInfoParser void ParseIntermissionAction(FIntermissionDescriptor *Desc); void ParseIntermission(); + void ParseAMColors(bool); FName CheckEndSequence(); FName ParseEndGame(); }; @@ -267,16 +269,16 @@ struct level_info_t { int levelnum; - char mapname[9]; - char pname[9]; - char nextmap[11]; - char secretmap[11]; - char skypic1[9]; - char skypic2[9]; - char fadetable[9]; - char f1[9]; - char bordertexture[9]; - char mapbg[9]; + FString MapName; + FString NextMap; + FString NextSecretMap; + FString PName; + FString SkyPic1; + FString SkyPic2; + FString FadeTable; + FString F1Pic; + FString BorderTexture; + FString MapBackground; int cluster; int partime; @@ -311,7 +313,7 @@ struct level_info_t // Redirection: If any player is carrying the specified item, then // you go to the RedirectMap instead of this one. FName RedirectType; - char RedirectMap[9]; + FString RedirectMapName; FString EnterPic; FString ExitPic; @@ -389,9 +391,9 @@ struct FLevelLocals int levelnum; int lumpnum; FString LevelName; - char mapname[256]; // the lump name (E1M1, MAP01, etc) - char nextmap[11]; // go here when using the regular exit - char secretmap[11]; // map to go to when used secret exit + FString MapName; // the lump name (E1M1, MAP01, etc) + FString NextMap; // go here when using the regular exit + FString NextSecretMap; // map to go to when used secret exit EMapType maptype; DWORD flags; @@ -405,8 +407,8 @@ struct FLevelLocals int cdtrack; unsigned int cdid; int nextmusic; // For MUSINFO purposes - char skypic1[9]; - char skypic2[9]; + FTextureID skytexture1; + FTextureID skytexture2; float skyspeed1; // Scrolling speed of sky textures, in pixels per ms float skyspeed2; @@ -553,6 +555,7 @@ enum ESkillProperty SKILLP_NoPain, SKILLP_ArmorFactor, SKILLP_EasyKey, + SKILLP_SlowMonsters, }; int G_SkillProperty(ESkillProperty prop); const char * G_SkillName(); @@ -567,6 +570,7 @@ struct FSkillInfo fixed_t AmmoFactor, DoubleAmmoFactor, DropAmmoFactor; fixed_t DamageFactor; bool FastMonsters; + bool SlowMonsters; bool DisableCheats; bool AutoUseHealth; diff --git a/src/g_mapinfo.cpp b/src/g_mapinfo.cpp index 7a8075174..b7aa77e1c 100644 --- a/src/g_mapinfo.cpp +++ b/src/g_mapinfo.cpp @@ -71,9 +71,10 @@ extern TMap HexenMusic; static int FindWadLevelInfo (const char *name) { for (unsigned int i = 0; i < wadlevelinfos.Size(); i++) - if (!strnicmp (name, wadlevelinfos[i].mapname, 8)) + { + if (!wadlevelinfos[i].MapName.CompareNoCase(name)) return i; - + } return -1; } @@ -94,8 +95,7 @@ level_info_t *FindLevelInfo (const char *mapname, bool allowdefault) { if (TheDefaultLevelInfo.LevelName.IsEmpty()) { - uppercopy(TheDefaultLevelInfo.skypic1, "SKY1"); - uppercopy(TheDefaultLevelInfo.skypic2, "SKY1"); + TheDefaultLevelInfo.SkyPic2 = TheDefaultLevelInfo.SkyPic1 = "SKY1"; TheDefaultLevelInfo.LevelName = "Unnamed"; } return &TheDefaultLevelInfo; @@ -145,7 +145,7 @@ bool CheckWarpTransMap (FString &mapname, bool substitute) level_info_t *lev = FindLevelByWarpTrans (atoi (&mapname[4])); if (lev != NULL) { - mapname = lev->mapname; + mapname = lev->MapName; return true; } else if (substitute) @@ -225,14 +225,13 @@ void P_RemoveDefereds (void) void level_info_t::Reset() { - mapname[0] = 0; - mapbg[0] = 0; + MapName = ""; + MapBackground = ""; levelnum = 0; - pname[0] = 0; - nextmap[0] = 0; - secretmap[0] = 0; - strcpy (skypic1, "-NOFLAT-"); - strcpy (skypic2, "-NOFLAT-"); + PName = ""; + NextMap = ""; + NextSecretMap = ""; + SkyPic1 = SkyPic2 = "-NOFLAT-"; cluster = 0; partime = 0; sucktime = 0; @@ -243,10 +242,10 @@ void level_info_t::Reset() flags2 = LEVEL2_LAXMONSTERACTIVATION; Music = ""; LevelName = ""; - strcpy (fadetable, "COLORMAP"); + FadeTable = "COLORMAP"; WallHorizLight = -8; WallVertLight = +8; - f1[0] = 0; + F1Pic = ""; musicorder = 0; snapshot = NULL; snapshotVer = 0; @@ -264,14 +263,14 @@ void level_info_t::Reset() compatmask = compatmask2 = 0; Translator = ""; RedirectType = 0; - RedirectMap[0] = 0; + RedirectMapName = ""; EnterPic = ""; ExitPic = ""; InterMusic = ""; intermusicorder = 0; SoundInfo = ""; SndSeq = ""; - bordertexture[0] = 0; + BorderTexture = ""; teamdamage = 0.f; specialactions.Clear(); DefaultEnvironment = 0; @@ -301,17 +300,17 @@ FString level_info_t::LookupLevelName() char checkstring[32]; // Strip out the header from the localized string - if (mapname[0] == 'E' && mapname[2] == 'M') + if (MapName.Len() > 3 && MapName[0] == 'E' && MapName[2] == 'M') { - mysnprintf (checkstring, countof(checkstring), "%s: ", mapname); + mysnprintf (checkstring, countof(checkstring), "%s: ", MapName.GetChars()); } - else if (mapname[0] == 'M' && mapname[1] == 'A' && mapname[2] == 'P') + else if (MapName.Len() > 3 && MapName[0] == 'M' && MapName[1] == 'A' && MapName[2] == 'P') { - mysnprintf (checkstring, countof(checkstring), "%d: ", atoi(mapname + 3)); + mysnprintf (checkstring, countof(checkstring), "%d: ", atoi(&MapName[3])); } - else if (mapname[0] == 'L' && mapname[1] == 'E' && mapname[2] == 'V' && mapname[3] == 'E' && mapname[4] == 'L') + else if (MapName.Len() > 5 && MapName[0] == 'L' && MapName[1] == 'E' && MapName[2] == 'V' && MapName[3] == 'E' && MapName[4] == 'L') { - mysnprintf (checkstring, countof(checkstring), "%d: ", atoi(mapname + 5)); + mysnprintf (checkstring, countof(checkstring), "%d: ", atoi(&MapName[5])); } thename = strstr (lookedup, checkstring); if (thename == NULL) @@ -374,9 +373,9 @@ level_info_t *level_info_t::CheckLevelRedirect () if (playeringame[i] && players[i].mo->FindInventory (type)) { // check for actual presence of the map. - if (P_CheckMapData(RedirectMap)) + if (P_CheckMapData(RedirectMapName)) { - return FindLevelInfo(RedirectMap); + return FindLevelInfo(RedirectMapName); } break; } @@ -393,7 +392,7 @@ level_info_t *level_info_t::CheckLevelRedirect () bool level_info_t::isValid() { - return mapname[0] != 0 || this == &TheDefaultLevelInfo; + return MapName.Len() != 0 || this == &TheDefaultLevelInfo; } //========================================================================== @@ -623,12 +622,14 @@ bool FMapInfoParser::ParseLookupName(FString &dest) // //========================================================================== +/* void FMapInfoParser::ParseLumpOrTextureName(char *name) { sc.MustGetString(); uppercopy(name, sc.String); name[8]=0; } +*/ void FMapInfoParser::ParseLumpOrTextureName(FString &name) { @@ -766,29 +767,27 @@ void FMapInfoParser::ParseCluster() // //========================================================================== -void FMapInfoParser::ParseNextMap(char *mapname) +void FMapInfoParser::ParseNextMap(FString &mapname) { if (sc.CheckNumber()) { if (HexenHack) { - mysnprintf (mapname, 9, "&wt@%02d", sc.Number); + mapname.Format("&wt@%02d", sc.Number); } else { - mysnprintf (mapname, 9, "MAP%02d", sc.Number); + mapname.Format("MAP%02d", sc.Number); } } else { - *mapname = 0; sc.MustGetString(); - strncpy (mapname, sc.String, 8); - mapname[8] = 0; + mapname = sc.String; FName seq = CheckEndSequence(); if (seq != NAME_None) { - mysnprintf(mapname, 11, "enDSeQ%04x", int(seq)); + mapname.Format("enDSeQ%04x", int(seq)); } } } @@ -809,19 +808,19 @@ DEFINE_MAP_OPTION(levelnum, true) DEFINE_MAP_OPTION(next, true) { parse.ParseAssign(); - parse.ParseNextMap(info->nextmap); + parse.ParseNextMap(info->NextMap); } DEFINE_MAP_OPTION(secretnext, true) { parse.ParseAssign(); - parse.ParseNextMap(info->secretmap); + parse.ParseNextMap(info->NextSecretMap); } DEFINE_MAP_OPTION(secret, true) // Just an alias for secretnext, for Vavoom compatibility { parse.ParseAssign(); - parse.ParseNextMap(info->secretmap); + parse.ParseNextMap(info->NextSecretMap); } DEFINE_MAP_OPTION(cluster, true) @@ -850,7 +849,7 @@ DEFINE_MAP_OPTION(cluster, true) DEFINE_MAP_OPTION(sky1, true) { parse.ParseAssign(); - parse.ParseLumpOrTextureName(info->skypic1); + parse.ParseLumpOrTextureName(info->SkyPic1); if (parse.CheckFloat()) { if (parse.HexenHack) @@ -864,7 +863,7 @@ DEFINE_MAP_OPTION(sky1, true) DEFINE_MAP_OPTION(sky2, true) { parse.ParseAssign(); - parse.ParseLumpOrTextureName(info->skypic2); + parse.ParseLumpOrTextureName(info->SkyPic2); if (parse.CheckFloat()) { if (parse.HexenHack) @@ -879,7 +878,7 @@ DEFINE_MAP_OPTION(sky2, true) DEFINE_MAP_OPTION(skybox, true) { parse.ParseAssign(); - parse.ParseLumpOrTextureName(info->skypic1); + parse.ParseLumpOrTextureName(info->SkyPic1); info->skyspeed1 = 0; } @@ -900,7 +899,7 @@ DEFINE_MAP_OPTION(outsidefog, true) DEFINE_MAP_OPTION(titlepatch, true) { parse.ParseAssign(); - parse.ParseLumpOrTextureName(info->pname); + parse.ParseLumpOrTextureName(info->PName); } DEFINE_MAP_OPTION(partime, true) @@ -939,7 +938,7 @@ DEFINE_MAP_OPTION(intermusic, true) DEFINE_MAP_OPTION(fadetable, true) { parse.ParseAssign(); - parse.ParseLumpOrTextureName(info->fadetable); + parse.ParseLumpOrTextureName(info->FadeTable); } DEFINE_MAP_OPTION(evenlighting, true) @@ -1074,7 +1073,7 @@ DEFINE_MAP_OPTION(redirect, true) parse.sc.MustGetString(); info->RedirectType = parse.sc.String; parse.ParseComma(); - parse.ParseLumpOrTextureName(info->RedirectMap); + parse.ParseNextMap(info->RedirectMapName); } DEFINE_MAP_OPTION(sndseq, true) @@ -1122,13 +1121,13 @@ DEFINE_MAP_OPTION(slideshow, false) DEFINE_MAP_OPTION(bordertexture, true) { parse.ParseAssign(); - parse.ParseLumpOrTextureName(info->bordertexture); + parse.ParseLumpOrTextureName(info->BorderTexture); } DEFINE_MAP_OPTION(f1, true) { parse.ParseAssign(); - parse.ParseLumpOrTextureName(info->f1); + parse.ParseLumpOrTextureName(info->F1Pic); } DEFINE_MAP_OPTION(teamdamage, true) @@ -1141,7 +1140,7 @@ DEFINE_MAP_OPTION(teamdamage, true) DEFINE_MAP_OPTION(mapbackground, true) { parse.ParseAssign(); - parse.ParseLumpOrTextureName(info->mapbg); + parse.ParseLumpOrTextureName(info->MapBackground); } DEFINE_MAP_OPTION(defaultenvironment, false) @@ -1524,8 +1523,8 @@ level_info_t *FMapInfoParser::ParseMapHeader(level_info_t &defaultinfo) } - uppercopy (levelinfo->mapname, mapname); - levelinfo->mapname[8] = 0; + levelinfo->MapName = mapname; + levelinfo->MapName.ToUpper(); sc.MustGetString (); if (sc.String[0] == '$') { @@ -1545,7 +1544,7 @@ level_info_t *FMapInfoParser::ParseMapHeader(level_info_t &defaultinfo) // Set up levelnum now so that you can use Teleport_NewMap specials // to teleport to maps with standard names without needing a levelnum. - levelinfo->levelnum = GetDefaultLevelNum(levelinfo->mapname); + levelinfo->levelnum = GetDefaultLevelNum(levelinfo->MapName); // Does this map have a song defined via SNDINFO's $map command? // Set that as this map's default music if it does. @@ -1575,7 +1574,7 @@ level_info_t *FMapInfoParser::ParseMapHeader(level_info_t &defaultinfo) void FMapInfoParser::ParseEpisodeInfo () { unsigned int i; - char map[9]; + FString map; FString pic; FString name; bool remove = false; @@ -1586,15 +1585,14 @@ void FMapInfoParser::ParseEpisodeInfo () // Get map name sc.MustGetString (); - uppercopy (map, sc.String); - map[8] = 0; + map = sc.String; if (sc.CheckString ("teaser")) { sc.MustGetString (); if (gameinfo.flags & GI_SHAREWARE) { - uppercopy (map, sc.String); + map = sc.String; } } @@ -1789,9 +1787,9 @@ void FMapInfoParser::ParseMapInfo (int lump, level_info_t &gamedefaults, level_i ParseMapDefinition(*levelinfo); // When the second sky is -NOFLAT-, make it a copy of the first sky - if (strcmp (levelinfo->skypic2, "-NOFLAT-") == 0) + if (!levelinfo->SkyPic2.CompareNoCase("-NOFLAT-")) { - strcpy (levelinfo->skypic2, levelinfo->skypic1); + levelinfo->SkyPic2 = levelinfo->SkyPic1; } SetLevelNum (levelinfo, levelinfo->levelnum); // Wipe out matching levelnums from other maps. } @@ -1842,6 +1840,18 @@ void FMapInfoParser::ParseMapInfo (int lump, level_info_t &gamedefaults, level_i sc.ScriptError("intermission definitions not supported with old MAPINFO syntax"); } } + else if (sc.Compare("automap") || sc.Compare("automap_overlay")) + { + if (format_type != FMT_Old) + { + format_type = FMT_New; + ParseAMColors(sc.Compare("automap_overlay")); + } + else + { + sc.ScriptError("automap colorset definitions not supported with old MAPINFO syntax"); + } + } else { sc.ScriptError("%s: Unknown top level keyword", sc.String); diff --git a/src/g_shared/a_armor.cpp b/src/g_shared/a_armor.cpp index 664a56307..6b90a6a78 100644 --- a/src/g_shared/a_armor.cpp +++ b/src/g_shared/a_armor.cpp @@ -42,9 +42,9 @@ void ABasicArmor::Tick () AbsorbCount = 0; if (!Icon.isValid()) { - const char *icon = gameinfo.ArmorIcon1; + FString icon = gameinfo.ArmorIcon1; - if (SavePercent >= gameinfo.Armor2Percent && gameinfo.ArmorIcon2[0] != 0) + if (SavePercent >= gameinfo.Armor2Percent && gameinfo.ArmorIcon2.Len() != 0) icon = gameinfo.ArmorIcon2; if (icon[0] != 0) diff --git a/src/g_shared/a_artifacts.cpp b/src/g_shared/a_artifacts.cpp index 2ef2b03c5..8891c8674 100644 --- a/src/g_shared/a_artifacts.cpp +++ b/src/g_shared/a_artifacts.cpp @@ -605,7 +605,13 @@ void APowerInvisibility::DoEffect () case (NAME_Stencil): Owner->RenderStyle = STYLE_Stencil; break; - case (NAME_None): + case (NAME_AddStencil) : + Owner->RenderStyle = STYLE_AddStencil; + break; + case (NAME_TranslucentStencil) : + Owner->RenderStyle = STYLE_TranslucentStencil; + break; + case (NAME_None) : case (NAME_Cumulative): case (NAME_Translucent): Owner->RenderStyle = STYLE_Translucent; @@ -685,7 +691,13 @@ int APowerInvisibility::AlterWeaponSprite (visstyle_t *vis) case (NAME_Stencil): vis->RenderStyle = STYLE_Stencil; break; - case (NAME_None): + case (NAME_TranslucentStencil) : + vis->RenderStyle = STYLE_TranslucentStencil; + break; + case (NAME_AddStencil) : + vis->RenderStyle = STYLE_AddStencil; + break; + case (NAME_None) : case (NAME_Cumulative): case (NAME_Translucent): default: diff --git a/src/g_shared/a_keys.cpp b/src/g_shared/a_keys.cpp index e7f1b286b..67d0ffb10 100644 --- a/src/g_shared/a_keys.cpp +++ b/src/g_shared/a_keys.cpp @@ -19,12 +19,29 @@ struct OneKey bool check(AActor * owner) { - // P_GetMapColorForKey() checks the key directly - if (owner->IsKindOf (RUNTIME_CLASS(AKey))) + if (owner->IsKindOf(RUNTIME_CLASS(AKey))) + { + // P_GetMapColorForKey() checks the key directly return owner->IsA(key); - // Other calls check an actor that may have a key in its inventory. - else - return !!owner->FindInventory(key); + } + else + { + // Other calls check an actor that may have a key in its inventory. + AInventory *item; + + for (item = owner->Inventory; item != NULL; item = item->Inventory) + { + if (item->IsA(key)) + { + return true; + } + else if (item->GetSpecies() == key->TypeName) + { + return true; + } + } + return false; + } } }; diff --git a/src/g_shared/a_pickups.cpp b/src/g_shared/a_pickups.cpp index cc559ea94..f14e7f4c7 100644 --- a/src/g_shared/a_pickups.cpp +++ b/src/g_shared/a_pickups.cpp @@ -1018,7 +1018,7 @@ void AInventory::Touch (AActor *toucher) if (flags5 & MF5_COUNTSECRET) { - P_GiveSecret(toucher, true, true); + P_GiveSecret(toucher, true, true, -1); } //Added by MC: Check if item taken was the roam destination of any bot diff --git a/src/g_shared/a_pickups.h b/src/g_shared/a_pickups.h index 6c68990d1..22d1e009f 100644 --- a/src/g_shared/a_pickups.h +++ b/src/g_shared/a_pickups.h @@ -134,6 +134,8 @@ enum IF_RESTRICTABSOLUTELY = 1<<19, // RestrictedTo and ForbiddenTo do not allow pickup in any form by other classes IF_NEVERRESPAWN = 1<<20, // Never, ever respawns IF_NOSCREENFLASH = 1<<21, // No pickup flash on the player's screen + IF_TOSSED = 1<<22, // Was spawned by P_DropItem (i.e. as a monster drop) + }; diff --git a/src/g_shared/a_secrettrigger.cpp b/src/g_shared/a_secrettrigger.cpp index 4484340db..24c6f0db4 100644 --- a/src/g_shared/a_secrettrigger.cpp +++ b/src/g_shared/a_secrettrigger.cpp @@ -42,8 +42,6 @@ #include "v_font.h" #include "p_spec.h" -EXTERN_CVAR(String, secretmessage) - class ASecretTrigger : public AActor { DECLARE_CLASS (ASecretTrigger, AActor) @@ -62,7 +60,7 @@ void ASecretTrigger::PostBeginPlay () void ASecretTrigger::Activate (AActor *activator) { - P_GiveSecret(activator, args[0] <= 1, (args[0] == 0 || args[0] == 2)); + P_GiveSecret(activator, args[0] <= 1, (args[0] == 0 || args[0] == 2), -1); Destroy (); } diff --git a/src/g_shared/a_sectoraction.cpp b/src/g_shared/a_sectoraction.cpp index ed73b5ae7..570818e19 100644 --- a/src/g_shared/a_sectoraction.cpp +++ b/src/g_shared/a_sectoraction.cpp @@ -82,10 +82,22 @@ void ASectorAction::Deactivate (AActor *source) flags2 |= MF2_DORMANT; // Projectiles can trigger } -bool ASectorAction::TriggerAction (AActor *triggerer, int activationType) +bool ASectorAction::TriggerAction(AActor *triggerer, int activationType) +{ + if (DoTriggerAction(triggerer, activationType)) + { + if (flags4 & MF4_STANDSTILL) + { + Destroy(); + } + } + return false; +} + +bool ASectorAction::DoTriggerAction (AActor *triggerer, int activationType) { if (tracer != NULL) - return barrier_cast(tracer)->TriggerAction (triggerer, activationType); + return barrier_cast(tracer)->DoTriggerAction (triggerer, activationType); else return false; } @@ -93,7 +105,7 @@ bool ASectorAction::TriggerAction (AActor *triggerer, int activationType) bool ASectorAction::CheckTrigger (AActor *triggerer) const { if (special && - (triggerer->player || + ((triggerer->player && !(flags & MF_FRIENDLY)) || ((flags & MF_AMBUSH) && (triggerer->flags2 & MF2_MCROSS)) || ((flags2 & MF2_DORMANT) && (triggerer->flags2 & MF2_PCROSS)))) { @@ -110,16 +122,16 @@ class ASecActEnter : public ASectorAction { DECLARE_CLASS (ASecActEnter, ASectorAction) public: - bool TriggerAction (AActor *triggerer, int activationType); + bool DoTriggerAction (AActor *triggerer, int activationType); }; IMPLEMENT_CLASS (ASecActEnter) -bool ASecActEnter::TriggerAction (AActor *triggerer, int activationType) +bool ASecActEnter::DoTriggerAction (AActor *triggerer, int activationType) { bool didit = (activationType & SECSPAC_Enter) ? CheckTrigger (triggerer) : false; - return didit | Super::TriggerAction (triggerer, activationType); + return didit | Super::DoTriggerAction (triggerer, activationType); } // Triggered when leaving sector -------------------------------------------- @@ -128,16 +140,16 @@ class ASecActExit : public ASectorAction { DECLARE_CLASS (ASecActExit, ASectorAction) public: - bool TriggerAction (AActor *triggerer, int activationType); + bool DoTriggerAction (AActor *triggerer, int activationType); }; IMPLEMENT_CLASS (ASecActExit) -bool ASecActExit::TriggerAction (AActor *triggerer, int activationType) +bool ASecActExit::DoTriggerAction (AActor *triggerer, int activationType) { bool didit = (activationType & SECSPAC_Exit) ? CheckTrigger (triggerer) : false; - return didit | Super::TriggerAction (triggerer, activationType); + return didit | Super::DoTriggerAction (triggerer, activationType); } // Triggered when hitting sector's floor ------------------------------------ @@ -146,7 +158,7 @@ class ASecActHitFloor : public ASectorAction { DECLARE_CLASS (ASecActHitFloor, ASectorAction) public: - bool TriggerAction (AActor *triggerer, int activationType); + bool DoTriggerAction (AActor *triggerer, int activationType); }; // Skull Tag uses 9999 for a special that is triggered whenever @@ -154,10 +166,10 @@ public: IMPLEMENT_CLASS (ASecActHitFloor) -bool ASecActHitFloor::TriggerAction (AActor *triggerer, int activationType) +bool ASecActHitFloor::DoTriggerAction (AActor *triggerer, int activationType) { bool didit = (activationType & SECSPAC_HitFloor) ? CheckTrigger (triggerer) : false; - return didit | Super::TriggerAction (triggerer, activationType); + return didit | Super::DoTriggerAction (triggerer, activationType); } // Triggered when hitting sector's ceiling ---------------------------------- @@ -166,16 +178,16 @@ class ASecActHitCeil : public ASectorAction { DECLARE_CLASS (ASecActHitCeil, ASectorAction) public: - bool TriggerAction (AActor *triggerer, int activationType); + bool DoTriggerAction (AActor *triggerer, int activationType); }; IMPLEMENT_CLASS (ASecActHitCeil) -bool ASecActHitCeil::TriggerAction (AActor *triggerer, int activationType) +bool ASecActHitCeil::DoTriggerAction (AActor *triggerer, int activationType) { bool didit = (activationType & SECSPAC_HitCeiling) ? CheckTrigger (triggerer) : false; - return didit | Super::TriggerAction (triggerer, activationType); + return didit | Super::DoTriggerAction (triggerer, activationType); } // Triggered when using inside sector --------------------------------------- @@ -184,16 +196,16 @@ class ASecActUse : public ASectorAction { DECLARE_CLASS (ASecActUse, ASectorAction) public: - bool TriggerAction (AActor *triggerer, int activationType); + bool DoTriggerAction (AActor *triggerer, int activationType); }; IMPLEMENT_CLASS (ASecActUse) -bool ASecActUse::TriggerAction (AActor *triggerer, int activationType) +bool ASecActUse::DoTriggerAction (AActor *triggerer, int activationType) { bool didit = (activationType & SECSPAC_Use) ? CheckTrigger (triggerer) : false; - return didit | Super::TriggerAction (triggerer, activationType); + return didit | Super::DoTriggerAction (triggerer, activationType); } // Triggered when using a sector's wall ------------------------------------- @@ -202,16 +214,16 @@ class ASecActUseWall : public ASectorAction { DECLARE_CLASS (ASecActUseWall, ASectorAction) public: - bool TriggerAction (AActor *triggerer, int activationType); + bool DoTriggerAction (AActor *triggerer, int activationType); }; IMPLEMENT_CLASS (ASecActUseWall) -bool ASecActUseWall::TriggerAction (AActor *triggerer, int activationType) +bool ASecActUseWall::DoTriggerAction (AActor *triggerer, int activationType) { bool didit = (activationType & SECSPAC_UseWall) ? CheckTrigger (triggerer) : false; - return didit | Super::TriggerAction (triggerer, activationType); + return didit | Super::DoTriggerAction (triggerer, activationType); } // Triggered when eyes go below fake floor ---------------------------------- @@ -220,16 +232,16 @@ class ASecActEyesDive : public ASectorAction { DECLARE_CLASS (ASecActEyesDive, ASectorAction) public: - bool TriggerAction (AActor *triggerer, int activationType); + bool DoTriggerAction (AActor *triggerer, int activationType); }; IMPLEMENT_CLASS (ASecActEyesDive) -bool ASecActEyesDive::TriggerAction (AActor *triggerer, int activationType) +bool ASecActEyesDive::DoTriggerAction (AActor *triggerer, int activationType) { bool didit = (activationType & SECSPAC_EyesDive) ? CheckTrigger (triggerer) : false; - return didit | Super::TriggerAction (triggerer, activationType); + return didit | Super::DoTriggerAction (triggerer, activationType); } // Triggered when eyes go above fake floor ---------------------------------- @@ -238,16 +250,16 @@ class ASecActEyesSurface : public ASectorAction { DECLARE_CLASS (ASecActEyesSurface, ASectorAction) public: - bool TriggerAction (AActor *triggerer, int activationType); + bool DoTriggerAction (AActor *triggerer, int activationType); }; IMPLEMENT_CLASS (ASecActEyesSurface) -bool ASecActEyesSurface::TriggerAction (AActor *triggerer, int activationType) +bool ASecActEyesSurface::DoTriggerAction (AActor *triggerer, int activationType) { bool didit = (activationType & SECSPAC_EyesSurface) ? CheckTrigger (triggerer) : false; - return didit | Super::TriggerAction (triggerer, activationType); + return didit | Super::DoTriggerAction (triggerer, activationType); } // Triggered when eyes go below fake floor ---------------------------------- @@ -256,16 +268,16 @@ class ASecActEyesBelowC : public ASectorAction { DECLARE_CLASS (ASecActEyesBelowC, ASectorAction) public: - bool TriggerAction (AActor *triggerer, int activationType); + bool DoTriggerAction (AActor *triggerer, int activationType); }; IMPLEMENT_CLASS (ASecActEyesBelowC) -bool ASecActEyesBelowC::TriggerAction (AActor *triggerer, int activationType) +bool ASecActEyesBelowC::DoTriggerAction (AActor *triggerer, int activationType) { bool didit = (activationType & SECSPAC_EyesBelowC) ? CheckTrigger (triggerer) : false; - return didit | Super::TriggerAction (triggerer, activationType); + return didit | Super::DoTriggerAction (triggerer, activationType); } // Triggered when eyes go above fake floor ---------------------------------- @@ -274,16 +286,16 @@ class ASecActEyesAboveC : public ASectorAction { DECLARE_CLASS (ASecActEyesAboveC, ASectorAction) public: - bool TriggerAction (AActor *triggerer, int activationType); + bool DoTriggerAction (AActor *triggerer, int activationType); }; IMPLEMENT_CLASS (ASecActEyesAboveC) -bool ASecActEyesAboveC::TriggerAction (AActor *triggerer, int activationType) +bool ASecActEyesAboveC::DoTriggerAction (AActor *triggerer, int activationType) { bool didit = (activationType & SECSPAC_EyesAboveC) ? CheckTrigger (triggerer) : false; - return didit | Super::TriggerAction (triggerer, activationType); + return didit | Super::DoTriggerAction (triggerer, activationType); } // Triggered when eyes go below fake floor ---------------------------------- @@ -292,14 +304,14 @@ class ASecActHitFakeFloor : public ASectorAction { DECLARE_CLASS (ASecActHitFakeFloor, ASectorAction) public: - bool TriggerAction (AActor *triggerer, int activationType); + bool DoTriggerAction (AActor *triggerer, int activationType); }; IMPLEMENT_CLASS (ASecActHitFakeFloor) -bool ASecActHitFakeFloor::TriggerAction (AActor *triggerer, int activationType) +bool ASecActHitFakeFloor::DoTriggerAction (AActor *triggerer, int activationType) { bool didit = (activationType & SECSPAC_HitFakeFloor) ? CheckTrigger (triggerer) : false; - return didit | Super::TriggerAction (triggerer, activationType); + return didit | Super::DoTriggerAction (triggerer, activationType); } diff --git a/src/g_shared/a_weapons.cpp b/src/g_shared/a_weapons.cpp index 6caf42b7d..fae232557 100644 --- a/src/g_shared/a_weapons.cpp +++ b/src/g_shared/a_weapons.cpp @@ -1143,7 +1143,7 @@ AWeapon *FWeaponSlots::PickNextWeapon(player_t *player) return weap; } } - while ((slot != startslot || index != startindex) && slotschecked < NUM_WEAPON_SLOTS); + while ((slot != startslot || index != startindex) && slotschecked <= NUM_WEAPON_SLOTS); } return player->ReadyWeapon; } @@ -1198,7 +1198,7 @@ AWeapon *FWeaponSlots::PickPrevWeapon (player_t *player) return weap; } } - while ((slot != startslot || index != startindex) && slotschecked < NUM_WEAPON_SLOTS); + while ((slot != startslot || index != startindex) && slotschecked <= NUM_WEAPON_SLOTS); } return player->ReadyWeapon; } diff --git a/src/g_shared/sbar.h b/src/g_shared/sbar.h index 3d8c62001..b8dde5850 100644 --- a/src/g_shared/sbar.h +++ b/src/g_shared/sbar.h @@ -444,6 +444,20 @@ void ST_LoadCrosshair(bool alwaysload=false); void ST_Clear(); extern FTexture *CrosshairImage; -FTextureID GetWeaponIcon(AWeapon *weapon); +FTextureID GetInventoryIcon(AInventory *item, DWORD flags, bool *applyscale); + +enum DI_Flags +{ + DI_SKIPICON = 0x1, + DI_SKIPALTICON = 0x2, + DI_SKIPSPAWN = 0x4, + DI_SKIPREADY = 0x8, + DI_ALTICONFIRST = 0x10, + + DI_DRAWINBOX = 0x20, // Set when either width or height is not zero + + DI_FORCESCALE = 0x40, + DI_ALTERNATEONFAIL = 0x80 +}; #endif /* __SBAR_H__ */ diff --git a/src/g_shared/sbar_mugshot.cpp b/src/g_shared/sbar_mugshot.cpp index 0849fd354..96dd07265 100644 --- a/src/g_shared/sbar_mugshot.cpp +++ b/src/g_shared/sbar_mugshot.cpp @@ -263,7 +263,7 @@ void FMugShot::Tick(player_t *player) CurrentState = NULL; } } - if ((player->cmd.ucmd.buttons & (BT_ATTACK|BT_ALTATTACK)) && !(player->cheats & (CF_FROZEN | CF_TOTALLYFROZEN)) && player->ReadyWeapon) + if (player->attackdown && !(player->cheats & (CF_FROZEN | CF_TOTALLYFROZEN)) && player->ReadyWeapon) { if (RampageTimer != ST_RAMPAGEDELAY) { diff --git a/src/g_shared/sbarinfo.cpp b/src/g_shared/sbarinfo.cpp index 09be47363..a738a5aad 100644 --- a/src/g_shared/sbarinfo.cpp +++ b/src/g_shared/sbarinfo.cpp @@ -303,6 +303,8 @@ class SBarInfoMainBlock : public SBarInfoCommandFlowControl int Alpha() const { return currentAlpha; } // Same as Draw but takes into account ForceScaled and temporarily sets the scaling if needed. void DrawAux(const SBarInfoMainBlock *block, DSBarInfo *statusBar, int xOffset, int yOffset, int alpha); + // Silence hidden overload warning since this is a special use class. + using SBarInfoCommandFlowControl::Draw; void Draw(const SBarInfoMainBlock *block, const DSBarInfo *statusBar, int xOffset, int yOffset, int alpha) { this->xOffset = xOffset; @@ -1187,8 +1189,12 @@ public: if((offsetflags & SBarInfoCommand::CENTER) == SBarInfoCommand::CENTER) { - dx -= (texture->GetScaledWidthDouble()/2.0)-texture->GetScaledLeftOffsetDouble(); - dy -= (texture->GetScaledHeightDouble()/2.0)-texture->GetScaledTopOffsetDouble(); + if (forceWidth < 0) dx -= (texture->GetScaledWidthDouble()/2.0)-texture->GetScaledLeftOffsetDouble(); + else dx -= forceWidth*(0.5-(texture->GetScaledLeftOffsetDouble()/texture->GetScaledWidthDouble())); + //Unoptimalized formula is dx -= forceWidth/2.0-(texture->GetScaledLeftOffsetDouble()*forceWidth/texture->GetScaledWidthDouble()); + + if (forceHeight < 0) dy -= (texture->GetScaledHeightDouble()/2.0)-texture->GetScaledTopOffsetDouble(); + else dy -= forceHeight*(0.5-(texture->GetScaledTopOffsetDouble()/texture->GetScaledHeightDouble())); } dx += xOffset; diff --git a/src/g_shared/sbarinfo_commands.cpp b/src/g_shared/sbarinfo_commands.cpp index febf32b80..629c31cb4 100644 --- a/src/g_shared/sbarinfo_commands.cpp +++ b/src/g_shared/sbarinfo_commands.cpp @@ -41,28 +41,65 @@ // classes. //////////////////////////////////////////////////////////////////////////////// - -class CommandDrawImage : public SBarInfoCommand +class CommandDrawImage : public SBarInfoCommandFlowControl { public: - CommandDrawImage(SBarInfo *script) : SBarInfoCommand(script), - translatable(false), type(NORMAL_IMAGE), image(-1), offset(static_cast (TOP|LEFT)), + CommandDrawImage(SBarInfo *script) : SBarInfoCommandFlowControl(script), + translatable(false), type(NORMAL_IMAGE), image(-1), maxwidth(-1), + maxheight(-1), spawnScaleX(1.0f), spawnScaleY(1.0f), flags(0), + applyscale(false), offset(static_cast (TOP|LEFT)), texture(NULL), alpha(FRACUNIT) { } void Draw(const SBarInfoMainBlock *block, const DSBarInfo *statusBar) { + if(flags & DI_ALTERNATEONFAIL) + SBarInfoCommandFlowControl::Draw(block, statusBar); + if(texture == NULL) return; + int w = maxwidth, h = maxheight; + // We must calculate this per frame in order to prevent glitches with cl_capfps true. fixed_t frameAlpha = block->Alpha(); if(alpha != FRACUNIT) frameAlpha = fixed_t(((double) block->Alpha() / (double) FRACUNIT) * ((double) alpha / (double) OPAQUE) * FRACUNIT); - + + if(flags & DI_DRAWINBOX) + { + double scale1, scale2; + scale1 = scale2 = 1.0f; + double texwidth = (int) (texture->GetScaledWidthDouble()*spawnScaleX); + double texheight = (int) (texture->GetScaledHeightDouble()*spawnScaleY); + + if (w != -1 && (wGetScaledWidthDouble()*spawnScaleX); + h=(int) (texture->GetScaledHeightDouble()*spawnScaleY); + } statusBar->DrawGraphic(texture, imgx, imgy, block->XOffset(), block->YOffset(), frameAlpha, block->FullScreenOffsets(), - translatable, false, offset); + translatable, false, offset, false, w, h); } void Parse(FScanner &sc, bool fullScreenOffsets) { @@ -98,7 +135,7 @@ class CommandDrawImage : public SBarInfoCommand type = HEXENARMOR_AMULET; else { - sc.ScriptMessage("Unkown armor type: '%s'", sc.String); + sc.ScriptMessage("Unknown armor type: '%s'", sc.String); type = HEXENARMOR_ARMOR; } sc.MustGetToken(','); @@ -136,53 +173,100 @@ class CommandDrawImage : public SBarInfoCommand GetCoordinates(sc, fullScreenOffsets, imgx, imgy); if(sc.CheckToken(',')) { - sc.MustGetToken(TK_Identifier); - if(sc.Compare("center")) - offset = CENTER; - else if(sc.Compare("centerbottom")) - offset = static_cast (HMIDDLE|BOTTOM); - else - sc.ScriptError("'%s' is not a valid alignment.", sc.String); + // Use none instead of topleft in case we decide we want to use + // alignments to remove the offset from images. + if(!sc.CheckToken(TK_None)) + { + sc.MustGetToken(TK_Identifier); + if(sc.Compare("center")) + offset = CENTER; + else if(sc.Compare("centerbottom")) + offset = static_cast (HMIDDLE|BOTTOM); + else + sc.ScriptError("'%s' is not a valid alignment.", sc.String); + } } - sc.MustGetToken(';'); + if(sc.CheckToken(',')) + { + sc.MustGetToken(TK_IntConst); + if((maxwidth = sc.Number) > 0) + flags |= DI_DRAWINBOX; + else + maxwidth = -1; + sc.MustGetToken(','); + sc.MustGetToken(TK_IntConst); + if ((maxheight = sc.Number) > 0) + flags |= DI_DRAWINBOX; + else + maxheight = -1; + } + if(sc.CheckToken(',')) + { + while(sc.CheckToken(TK_Identifier)) + { + if(sc.Compare("skipicon")) + flags |= DI_SKIPICON; + else if(sc.Compare("skipalticon")) + flags |= DI_SKIPALTICON; + else if(sc.Compare("skipspawn")) + flags |= DI_SKIPSPAWN; + else if(sc.Compare("skipready")) + flags |= DI_SKIPREADY; + else if(sc.Compare("alticonfirst")) + flags |= DI_ALTICONFIRST; + else if(sc.Compare("forcescale")) + { + if(flags & DI_DRAWINBOX) + flags |= DI_FORCESCALE; + } + else if(sc.Compare("alternateonfail")) + flags |= DI_ALTERNATEONFAIL; + else + sc.ScriptError("Unknown flag '%s'.", sc.String); + if(!sc.CheckToken('|') && !sc.CheckToken(',')) break; + } + } + if(flags & DI_ALTERNATEONFAIL) + SBarInfoCommandFlowControl::Parse(sc, fullScreenOffsets); + else + sc.MustGetToken(';'); } void Tick(const SBarInfoMainBlock *block, const DSBarInfo *statusBar, bool hudChanged) { + SBarInfoCommandFlowControl::Tick(block, statusBar, hudChanged); + texture = NULL; alpha = FRACUNIT; + if (applyscale) + { + spawnScaleX = spawnScaleY = 1.0f; + applyscale = false; + } if(type == PLAYERICON) texture = TexMan[statusBar->CPlayer->mo->ScoreIcon]; else if(type == AMMO1) { - if(statusBar->ammo1 != NULL) - texture = TexMan[statusBar->ammo1->Icon]; + AAmmo *ammo = statusBar->ammo1; + if(ammo != NULL) + GetIcon(ammo); } else if(type == AMMO2) { - if(statusBar->ammo2 != NULL) - texture = TexMan[statusBar->ammo2->Icon]; + AAmmo *ammo = statusBar->ammo2; + if(ammo != NULL) + GetIcon(ammo); } else if(type == ARMOR) { - if(statusBar->armor != NULL && statusBar->armor->Amount != 0) - texture = TexMan(statusBar->armor->Icon); + ABasicArmor *armor = statusBar->armor; + if(armor != NULL && armor->Amount != 0) + GetIcon(armor); } else if(type == WEAPONICON) { AWeapon *weapon = statusBar->CPlayer->ReadyWeapon; if(weapon != NULL) - { - FTextureID icon; - if (weapon->Icon.isValid()) - { - icon = weapon->Icon; - } - else - { - icon = GetWeaponIcon(weapon); - } - texture = TexMan[icon]; - } + GetIcon(weapon); } else if(type == SIGIL) { @@ -213,8 +297,26 @@ class CommandDrawImage : public SBarInfoCommand texture = TexMan(statusBar->CPlayer->mo->InvSel->Icon); else if(image >= 0) texture = statusBar->Images[image]; + + if (flags & DI_ALTERNATEONFAIL) + { + SetTruth(texture == NULL || texture->UseType == FTexture::TEX_Null, block, statusBar); + } } protected: + void GetIcon(AInventory *item) + { + FTextureID icon = GetInventoryIcon(item, flags, &applyscale); + + if (applyscale) + { + spawnScaleX = FIXED2FLOAT(item->scaleX); + spawnScaleY = FIXED2FLOAT(item->scaleY); + } + + texture = TexMan[icon]; + } + enum ImageType { PLAYERICON, @@ -238,6 +340,12 @@ class CommandDrawImage : public SBarInfoCommand ImageType type; int image; FTextureID sprite; + int maxwidth; + int maxheight; + double spawnScaleX; + double spawnScaleY; + DWORD flags; + bool applyscale; //Set remotely from from GetInventoryIcon when selected sprite comes from Spawn state // I'm using imgx/imgy here so that I can inherit drawimage with drawnumber for some commands. SBarInfoCoordinate imgx; SBarInfoCoordinate imgy; @@ -722,7 +830,7 @@ class CommandDrawString : public SBarInfoCommand if(level.lumpnum != cache) { cache = level.lumpnum; - str = level.mapname; + str = level.MapName; str.ToUpper(); RealignString(); } @@ -1479,11 +1587,11 @@ class CommandDrawMugShot : public SBarInfoCommand //////////////////////////////////////////////////////////////////////////////// -class CommandDrawSelectedInventory : public SBarInfoCommandFlowControl, private CommandDrawImage, private CommandDrawNumber +class CommandDrawSelectedInventory : public CommandDrawImage, private CommandDrawNumber { public: - CommandDrawSelectedInventory(SBarInfo *script) : SBarInfoCommandFlowControl(script), - CommandDrawImage(script), CommandDrawNumber(script), alternateOnEmpty(false), + CommandDrawSelectedInventory(SBarInfo *script) : CommandDrawImage(script), + CommandDrawNumber(script), alternateOnEmpty(false), artiflash(false), alwaysShowCounter(false) { length = INT_MAX; // Counter size @@ -1639,10 +1747,20 @@ class CommandGameMode : public SBarInfoCommandFlowControl void Parse(FScanner &sc, bool fullScreenOffsets) { + static bool warnUnknown = true; do { sc.MustGetToken(TK_Identifier); - modes |= static_cast (1<= 0) + modes |= static_cast (1<newImage(sc.String); diff --git a/src/g_shared/shared_hud.cpp b/src/g_shared/shared_hud.cpp index 3416bb82d..964a28e2b 100644 --- a/src/g_shared/shared_hud.cpp +++ b/src/g_shared/shared_hud.cpp @@ -135,12 +135,12 @@ static void DrawImageToBox(FTexture * tex, int x, int y, int w, int h, int trans if (tex) { - int texwidth=tex->GetWidth(); - int texheight=tex->GetHeight(); + double texwidth=tex->GetScaledWidthDouble(); + double texheight=tex->GetScaledHeightDouble(); - if (wGetClass()); + FTextureID picnum, AltIcon = GetHUDIcon(item->GetClass()); FState * state=NULL, *ReadyState; - FTextureID picnum = !AltIcon.isNull()? AltIcon : weapon->Icon; - - if (picnum.isNull()) + picnum.SetNull(); + if (flags & DI_ALTICONFIRST) { - if (weapon->SpawnState && weapon->SpawnState->sprite!=0) + if (!(flags & DI_SKIPALTICON) && AltIcon.isValid()) + picnum = AltIcon; + else if (!(flags & DI_SKIPICON)) + picnum = item->Icon; + } + else + { + if (!(flags & DI_SKIPICON) && item->Icon.isValid()) + picnum = item->Icon; + else if (!(flags & DI_SKIPALTICON)) + picnum = AltIcon; + } + + if (!picnum.isValid()) //isNull() is bad for checking, because picnum could be also invalid (-1) + { + if (!(flags & DI_SKIPSPAWN) && item->SpawnState && item->SpawnState->sprite!=0) { - state = weapon->SpawnState; + state = item->SpawnState; + + if (applyscale != NULL && !(flags & DI_FORCESCALE)) + { + *applyscale = true; + } } - // no spawn state - now try the ready state - else if ((ReadyState = weapon->FindState(NAME_Ready)) && ReadyState->sprite!=0) + // no spawn state - now try the ready state if it's weapon + else if (!(flags & DI_SKIPREADY) && item->GetClass()->IsDescendantOf(RUNTIME_CLASS(AWeapon)) && (ReadyState = item->FindState(NAME_Ready)) && ReadyState->sprite!=0) { state = ReadyState; } @@ -651,7 +669,7 @@ static void DrawOneWeapon(player_t * CPlayer, int x, int & y, AWeapon * weapon) if (weapon==CPlayer->ReadyWeapon || weapon==CPlayer->ReadyWeapon->SisterWeapon) trans=0xd999; } - FTextureID picnum = GetWeaponIcon(weapon); + FTextureID picnum = GetInventoryIcon(weapon, DI_ALTICONFIRST); if (picnum.isValid()) { diff --git a/src/g_shared/shared_sbar.cpp b/src/g_shared/shared_sbar.cpp index 547f6534e..6b2f609b7 100644 --- a/src/g_shared/shared_sbar.cpp +++ b/src/g_shared/shared_sbar.cpp @@ -131,7 +131,7 @@ void ST_FormatMapName(FString &mapname, const char *mapnamecolor) if (am_showmaplabel == 1 || (am_showmaplabel == 2 && !ishub)) { - mapname << level.mapname << ": "; + mapname << level.MapName << ": "; } mapname << mapnamecolor << level.LevelName; } @@ -1090,12 +1090,12 @@ void DBaseStatusBar::RefreshBackground () const if (setblocks >= 10) { - const gameborder_t *border = gameinfo.border; - FTexture *p; - - p = TexMan[border->b]; - screen->FlatFill(0, y, x, y + p->GetHeight(), p, true); - screen->FlatFill(x2, y, SCREENWIDTH, y + p->GetHeight(), p, true); + FTexture *p = TexMan[gameinfo.Border.b]; + if (p != NULL) + { + screen->FlatFill(0, y, x, y + p->GetHeight(), p, true); + screen->FlatFill(x2, y, SCREENWIDTH, y + p->GetHeight(), p, true); + } } } } diff --git a/src/g_skill.cpp b/src/g_skill.cpp index 46b9a1702..ddfdbb4cc 100644 --- a/src/g_skill.cpp +++ b/src/g_skill.cpp @@ -64,6 +64,7 @@ void FMapInfoParser::ParseSkill () skill.DropAmmoFactor = -1; skill.DamageFactor = FRACUNIT; skill.FastMonsters = false; + skill.SlowMonsters = false; skill.DisableCheats = false; skill.EasyBossBrain = false; skill.EasyKey = false; @@ -118,6 +119,10 @@ void FMapInfoParser::ParseSkill () { skill.FastMonsters = true; } + else if (sc.Compare ("slowmonsters")) + { + skill.SlowMonsters = true; + } else if (sc.Compare ("disablecheats")) { skill.DisableCheats = true; @@ -336,6 +341,9 @@ int G_SkillProperty(ESkillProperty prop) case SKILLP_FastMonsters: return AllSkills[gameskill].FastMonsters || (dmflags & DF_FAST_MONSTERS); + case SKILLP_SlowMonsters: + return AllSkills[gameskill].SlowMonsters; + case SKILLP_Respawn: if (dmflags & DF_MONSTERS_RESPAWN && AllSkills[gameskill].RespawnCounter==0) return TICRATE * gameinfo.defaultrespawntime; @@ -433,6 +441,7 @@ FSkillInfo &FSkillInfo::operator=(const FSkillInfo &other) DropAmmoFactor = other.DropAmmoFactor; DamageFactor = other.DamageFactor; FastMonsters = other.FastMonsters; + SlowMonsters = other.SlowMonsters; DisableCheats = other.DisableCheats; AutoUseHealth = other.AutoUseHealth; EasyBossBrain = other.EasyBossBrain; diff --git a/src/g_strife/a_entityboss.cpp b/src/g_strife/a_entityboss.cpp index 58a88121e..fafb3b862 100644 --- a/src/g_strife/a_entityboss.cpp +++ b/src/g_strife/a_entityboss.cpp @@ -91,7 +91,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_EntityDeath) fixed_t SpawnX = spot->x; fixed_t SpawnY = spot->y; - fixed_t SpawnZ = spot->z + self->tracer? 70*FRACUNIT : 0; + fixed_t SpawnZ = spot->z + (self->tracer? 70*FRACUNIT : 0); an = self->angle >> ANGLETOFINESHIFT; second = Spawn("EntitySecond", SpawnX + FixedMul (secondRadius, finecosine[an]), diff --git a/src/g_strife/a_strifeweapons.cpp b/src/g_strife/a_strifeweapons.cpp index 82560e6f7..a41058492 100644 --- a/src/g_strife/a_strifeweapons.cpp +++ b/src/g_strife/a_strifeweapons.cpp @@ -137,18 +137,40 @@ DEFINE_ACTION_FUNCTION(AActor, A_JabDagger) // //============================================================================ +enum +{ + AMF_TARGETEMITTER = 1, + AMF_TARGETNONPLAYER = 2, + AMF_EMITFROMTARGET = 4, +}; + DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_AlertMonsters) { ACTION_PARAM_START(1); ACTION_PARAM_FIXED(maxdist, 0); + ACTION_PARAM_INT(Flags, 1); - if (self->player != NULL) + AActor * target = NULL; + AActor * emitter = self; + + if (self->player != NULL || (Flags & AMF_TARGETEMITTER)) { - P_NoiseAlert(self, self, false, maxdist); + target = self; + } + else if (self->target != NULL && (Flags & AMF_TARGETNONPLAYER)) + { + target = self->target; } else if (self->target != NULL && self->target->player != NULL) { - P_NoiseAlert (self->target, self, false, maxdist); + target = self->target; + } + + if (Flags & AMF_EMITFROMTARGET) emitter = target; + + if (target != NULL && emitter != NULL) + { + P_NoiseAlert(target, emitter, false, maxdist); } } diff --git a/src/g_strife/a_thingstoblowup.cpp b/src/g_strife/a_thingstoblowup.cpp index 7d2c1ceee..d27260451 100644 --- a/src/g_strife/a_thingstoblowup.cpp +++ b/src/g_strife/a_thingstoblowup.cpp @@ -89,8 +89,11 @@ DEFINE_ACTION_FUNCTION(AActor, A_LightGoesOut) sec->SetLightLevel(0); - newheight = sec->FindLowestFloorSurrounding (&spot); + fixed_t oldtheight = sec->floorplane.Zat0(); + newheight = sec->FindLowestFloorSurrounding(&spot); sec->floorplane.d = sec->floorplane.PointToDist (spot, newheight); + fixed_t newtheight = sec->floorplane.Zat0(); + sec->ChangePlaneTexZ(sector_t::floor, newtheight - oldtheight); for (int i = 0; i < 8; ++i) { diff --git a/src/gameconfigfile.cpp b/src/gameconfigfile.cpp index 5c6fb0ce2..f679bec3d 100644 --- a/src/gameconfigfile.cpp +++ b/src/gameconfigfile.cpp @@ -42,8 +42,6 @@ #ifdef _WIN32 #define WIN32_LEAN_AND_MEAN #include -#include -#include extern HWND Window; #define USE_WINDOWS_DWORD #endif @@ -135,7 +133,7 @@ FGameConfigFile::FGameConfigFile () local_app_support << cpath << "/" GAME_DIR; SetValueForKey("Path", local_app_support, true); } -#elif !defined(unix) +#elif !defined(__unix__) SetValueForKey ("Path", "$HOME", true); SetValueForKey ("Path", "$PROGDIR", true); #else @@ -153,7 +151,7 @@ FGameConfigFile::FGameConfigFile () SetValueForKey ("Path", user_app_support, true); SetValueForKey ("Path", "$PROGDIR", true); SetValueForKey ("Path", local_app_support, true); -#elif !defined(unix) +#elif !defined(__unix__) SetValueForKey ("Path", "$PROGDIR", true); #else SetValueForKey ("Path", "~/" GAME_DIR, true); @@ -588,106 +586,20 @@ void FGameConfigFile::ArchiveGlobalData () FString FGameConfigFile::GetConfigPath (bool tryProg) { const char *pathval; - FString path; pathval = Args->CheckValue ("-config"); if (pathval != NULL) { return FString(pathval); } -#ifdef _WIN32 - path = NULL; - HRESULT hr; - - TCHAR uname[UNLEN+1]; - DWORD unamelen = countof(uname); - - // Because people complained, try for a user-specific .ini in the program directory first. - // If that is not writeable, use the one in the home directory instead. - hr = GetUserName (uname, &unamelen); - if (SUCCEEDED(hr) && uname[0] != 0) - { - // Is it valid for a user name to have slashes? - // Check for them and substitute just in case. - char *probe = uname; - while (*probe != 0) - { - if (*probe == '\\' || *probe == '/') - *probe = '_'; - ++probe; - } - - path = progdir; - path += "zdoom-"; - path += uname; - path += ".ini"; - if (tryProg) - { - if (!FileExists (path.GetChars())) - { - path = ""; - } - } - else - { // check if writeable - FILE *checker = fopen (path.GetChars(), "a"); - if (checker == NULL) - { - path = ""; - } - else - { - fclose (checker); - } - } - } - - if (path.IsEmpty()) - { - if (Args->CheckParm ("-cdrom")) - return CDROM_DIR "\\zdoom.ini"; - - path = progdir; - path += "zdoom.ini"; - } - return path; -#elif defined(__APPLE__) - char cpath[PATH_MAX]; - FSRef folder; - - if (noErr == FSFindFolder(kUserDomain, kPreferencesFolderType, kCreateFolder, &folder) && - noErr == FSRefMakePath(&folder, (UInt8*)cpath, PATH_MAX)) - { - path = cpath; - path += "/zdoom.ini"; - return path; - } - // Ungh. - return "zdoom.ini"; -#else - return GetUserFile ("zdoom.ini"); -#endif + return M_GetConfigPath(tryProg); } void FGameConfigFile::CreateStandardAutoExec(const char *section, bool start) { if (!SetSection(section)) { - FString path; -#ifdef __APPLE__ - char cpath[PATH_MAX]; - FSRef folder; - - if (noErr == FSFindFolder(kUserDomain, kDocumentsFolderType, kCreateFolder, &folder) && - noErr == FSRefMakePath(&folder, (UInt8*)cpath, PATH_MAX)) - { - path << cpath << "/" GAME_DIR "/autoexec.cfg"; - } -#elif !defined(unix) - path = "$PROGDIR/autoexec.cfg"; -#else - path = GetUserFile ("autoexec.cfg"); -#endif + FString path = M_GetAutoexecPath(); SetSection (section, true); SetValueForKey ("Path", path.GetChars()); } @@ -794,6 +706,6 @@ void FGameConfigFile::SetRavenDefaults (bool isHexen) CCMD (whereisini) { - FString path = GameConfig->GetConfigPath (false); + FString path = M_GetConfigPath(false); Printf ("%s\n", path.GetChars()); } diff --git a/src/gi.cpp b/src/gi.cpp index d9d58dc9e..4e64dd425 100644 --- a/src/gi.cpp +++ b/src/gi.cpp @@ -51,7 +51,7 @@ const char *GameNames[17] = }; -static gameborder_t DoomBorder = +static staticgameborder_t DoomBorder = { 8, 8, "brdr_tl", "brdr_t", "brdr_tr", @@ -59,7 +59,7 @@ static gameborder_t DoomBorder = "brdr_bl", "brdr_b", "brdr_br" }; -static gameborder_t HereticBorder = +static staticgameborder_t HereticBorder = { 4, 16, "bordtl", "bordt", "bordtr", @@ -67,7 +67,7 @@ static gameborder_t HereticBorder = "bordbl", "bordb", "bordbr" }; -static gameborder_t StrifeBorder = +static staticgameborder_t StrifeBorder = { 8, 8, "brdr_tl", "brdr_t", "brdr_tr", @@ -231,56 +231,51 @@ void FMapInfoParser::ParseGameInfo() } else if(nextKey.CompareNoCase("border") == 0) { - if(sc.CheckToken(TK_Identifier)) + staticgameborder_t *b; + if (sc.CheckToken(TK_Identifier)) { switch(sc.MustMatchString(GameInfoBorders)) { default: - gameinfo.border = &DoomBorder; + b = &DoomBorder; break; case 1: - gameinfo.border = &HereticBorder; + b = &HereticBorder; break; case 2: - gameinfo.border = &StrifeBorder; + b = &StrifeBorder; break; } + gameinfo.Border = *b; } else { // border = {size, offset, tr, t, tl, r, l ,br, b, bl}; - char *graphics[8] = {DoomBorder.tr, DoomBorder.t, DoomBorder.tl, DoomBorder.r, DoomBorder.l, DoomBorder.br, DoomBorder.b, DoomBorder.bl}; + FString *graphics[8] = { &gameinfo.Border.tr, &gameinfo.Border.t, &gameinfo.Border.tl, &gameinfo.Border.r, &gameinfo.Border.l, &gameinfo.Border.br, &gameinfo.Border.b, &gameinfo.Border.bl }; sc.MustGetToken(TK_IntConst); - DoomBorder.offset = sc.Number; + gameinfo.Border.offset = sc.Number; sc.MustGetToken(','); sc.MustGetToken(TK_IntConst); - DoomBorder.size = sc.Number; + gameinfo.Border.size = sc.Number; for(int i = 0;i < 8;i++) { sc.MustGetToken(','); sc.MustGetToken(TK_StringConst); - int len = int(strlen(sc.String)); - if(len > 8) - sc.ScriptError("Border graphic can not be more than 8 characters long.\n"); - memcpy(graphics[i], sc.String, len); - if(len < 8) // end with a null byte if the string is less than 8 chars. - graphics[i][len] = 0; + (*graphics[i]) = sc.String; } } } else if(nextKey.CompareNoCase("armoricons") == 0) { sc.MustGetToken(TK_StringConst); - strncpy(gameinfo.ArmorIcon1, sc.String, 8); - gameinfo.ArmorIcon1[8] = 0; + gameinfo.ArmorIcon1 = sc.String; if (sc.CheckToken(',')) { sc.MustGetToken(TK_FloatConst); gameinfo.Armor2Percent = FLOAT2FIXED(sc.Float); sc.MustGetToken(','); sc.MustGetToken(TK_StringConst); - strncpy(gameinfo.ArmorIcon2, sc.String, 8); - gameinfo.ArmorIcon2[8] = 0; + gameinfo.ArmorIcon2 = sc.String; } } else if(nextKey.CompareNoCase("maparrow") == 0) @@ -295,7 +290,7 @@ void FMapInfoParser::ParseGameInfo() else gameinfo.mCheatMapArrow = ""; } // Insert valid keys here. - GAMEINFOKEY_CSTRING(titlePage, "titlePage", 8) + GAMEINFOKEY_STRING(TitlePage, "titlePage") GAMEINFOKEY_STRINGARRAY(creditPages, "addcreditPage", 8, false) GAMEINFOKEY_STRINGARRAY(creditPages, "CreditPage", 8, true) GAMEINFOKEY_STRINGARRAY(PlayerClasses, "addplayerclasses", 0, false) @@ -306,17 +301,17 @@ void FMapInfoParser::ParseGameInfo() GAMEINFOKEY_FLOAT(pageTime, "pageTime") GAMEINFOKEY_STRING(chatSound, "chatSound") GAMEINFOKEY_MUSIC(finaleMusic, finaleOrder, "finaleMusic") - GAMEINFOKEY_CSTRING(finaleFlat, "finaleFlat", 8) + GAMEINFOKEY_STRING(FinaleFlat, "finaleFlat") GAMEINFOKEY_STRINGARRAY(finalePages, "finalePage", 8, true) GAMEINFOKEY_STRINGARRAY(infoPages, "addinfoPage", 8, false) GAMEINFOKEY_STRINGARRAY(infoPages, "infoPage", 8, true) - GAMEINFOKEY_CSTRING(PauseSign, "pausesign", 8) + GAMEINFOKEY_STRING(PauseSign, "pausesign") GAMEINFOKEY_STRING(quitSound, "quitSound") - GAMEINFOKEY_CSTRING(borderFlat, "borderFlat", 8) + GAMEINFOKEY_STRING(BorderFlat, "borderFlat") GAMEINFOKEY_FIXED(telefogheight, "telefogheight") GAMEINFOKEY_FIXED(gibfactor, "gibfactor") GAMEINFOKEY_INT(defKickback, "defKickback") - GAMEINFOKEY_CSTRING(SkyFlatName, "SkyFlatName", 8) + GAMEINFOKEY_STRING(SkyFlatName, "SkyFlatName") GAMEINFOKEY_STRING(translator, "translator") GAMEINFOKEY_COLOR(pickupcolor, "pickupcolor") GAMEINFOKEY_COLOR(defaultbloodcolor, "defaultbloodcolor") @@ -328,6 +323,7 @@ void FMapInfoParser::ParseGameInfo() GAMEINFOKEY_BOOL(noloopfinalemusic, "noloopfinalemusic") GAMEINFOKEY_BOOL(drawreadthis, "drawreadthis") GAMEINFOKEY_BOOL(swapmenu, "swapmenu") + GAMEINFOKEY_BOOL(dontcrunchcorpses, "dontcrunchcorpses") GAMEINFOKEY_BOOL(intermissioncounter, "intermissioncounter") GAMEINFOKEY_BOOL(nightmarefast, "nightmarefast") GAMEINFOKEY_COLOR(dimcolor, "dimcolor") @@ -336,7 +332,7 @@ void FMapInfoParser::ParseGameInfo() GAMEINFOKEY_INT(defaultrespawntime, "defaultrespawntime") GAMEINFOKEY_INT(defaultrespawntime, "defaultrespawntime") GAMEINFOKEY_INT(defaultdropstyle, "defaultdropstyle") - GAMEINFOKEY_CSTRING(Endoom, "endoom", 8) + GAMEINFOKEY_STRING(Endoom, "endoom") GAMEINFOKEY_INT(player5start, "player5start") GAMEINFOKEY_STRINGARRAY(quitmessages, "addquitmessages", 0, false) GAMEINFOKEY_STRINGARRAY(quitmessages, "quitmessages", 0, true) @@ -347,7 +343,7 @@ void FMapInfoParser::ParseGameInfo() GAMEINFOKEY_STRING(mFontColorHeader, "menufontcolor_header") GAMEINFOKEY_STRING(mFontColorHighlight, "menufontcolor_highlight") GAMEINFOKEY_STRING(mFontColorSelection, "menufontcolor_selection") - GAMEINFOKEY_CSTRING(mBackButton, "menubackbutton", 8) + GAMEINFOKEY_STRING(mBackButton, "menubackbutton") GAMEINFOKEY_INT(TextScreenX, "textscreenx") GAMEINFOKEY_INT(TextScreenY, "textscreeny") GAMEINFOKEY_STRING(DefaultEndSequence, "defaultendsequence") diff --git a/src/gi.h b/src/gi.h index 6b887e1dd..bbfbe73ff 100644 --- a/src/gi.h +++ b/src/gi.h @@ -52,7 +52,7 @@ extern const char *GameNames[17]; -struct gameborder_t +struct staticgameborder_t { BYTE offset; BYTE size; @@ -66,6 +66,35 @@ struct gameborder_t char br[8]; }; +struct gameborder_t +{ + BYTE offset; + BYTE size; + FString tl; + FString t; + FString tr; + FString l; + FString r; + FString bl; + FString b; + FString br; + + gameborder_t &operator=(staticgameborder_t &other) + { + offset = other.offset; + size = other.size; + tl = other.tl; + t = other.t; + tr = other.tr; + l = other.l; + r = other.r; + bl = other.bl; + b = other.b; + br = other.br; + return *this; + } +}; + struct FGIFont { FName fontname; @@ -78,12 +107,13 @@ struct gameinfo_t EGameType gametype; FString ConfigName; - char titlePage[9]; + FString TitlePage; bool drawreadthis; bool noloopfinalemusic; bool intermissioncounter; bool nightmarefast; bool swapmenu; + bool dontcrunchcorpses; TArray creditPages; TArray finalePages; TArray infoPages; @@ -98,16 +128,16 @@ struct gameinfo_t FString chatSound; FString finaleMusic; int finaleOrder; - char finaleFlat[9]; - char borderFlat[9]; - char SkyFlatName[9]; - char ArmorIcon1[9]; - char ArmorIcon2[9]; - char PauseSign[9]; - char Endoom[9]; + FString FinaleFlat; + FString BorderFlat; + FString SkyFlatName; + FString ArmorIcon1; + FString ArmorIcon2; + FString PauseSign; + FString Endoom; fixed_t Armor2Percent; FString quitSound; - gameborder_t *border; + gameborder_t Border; int telefogheight; int defKickback; FString translator; @@ -133,7 +163,7 @@ struct gameinfo_t FName mFontColorHeader; FName mFontColorHighlight; FName mFontColorSelection; - char mBackButton[9]; + FString mBackButton; fixed_t gibfactor; int TextScreenX; int TextScreenY; diff --git a/src/i_net.cpp b/src/i_net.cpp index 2c01f407d..889688b48 100644 --- a/src/i_net.cpp +++ b/src/i_net.cpp @@ -293,7 +293,7 @@ void PacketGet (void) return; } } - else if (c > 0) + else if (node >= 0 && c > 0) { doomcom.data[0] = TransmitBuffer[0] & ~NCMD_COMPRESSED; if (TransmitBuffer[0] & NCMD_COMPRESSED) @@ -316,6 +316,12 @@ void PacketGet (void) memcpy(doomcom.data + 1, TransmitBuffer + 1, c - 1); } } + else if (c > 0) + { //The packet is not from any in-game node, so we might as well discard it. + Printf("Dropped packet: Unknown host (%s:%d)\n", inet_ntoa(fromaddress.sin_addr), fromaddress.sin_port); + doomcom.remotenode = -1; + return; + } doomcom.remotenode = node; doomcom.datalength = (short)c; diff --git a/src/info.h b/src/info.h index 24bbb5fea..51c4bd629 100644 --- a/src/info.h +++ b/src/info.h @@ -76,6 +76,8 @@ struct FState BYTE SameFrame:1; // Ignore Frame (except when spawning actor) BYTE Fast:1; BYTE NoDelay:1; // Spawn states executes its action normally + BYTE CanRaise:1; // Allows a monster to be resurrected without waiting for an infinate frame + BYTE Slow:1; // Inverse of fast int ParameterIndex; inline int GetFrame() const @@ -114,6 +116,10 @@ struct FState { return NoDelay; } + inline bool GetCanRaise() const + { + return CanRaise; + } inline void SetFrame(BYTE frame) { Frame = frame - 'A'; diff --git a/src/intermission/intermission.cpp b/src/intermission/intermission.cpp index 91090e432..2a52df58a 100644 --- a/src/intermission/intermission.cpp +++ b/src/intermission/intermission.cpp @@ -104,7 +104,7 @@ void DIntermissionScreen::Init(FIntermissionAction *desc, bool first) } else { - texname = gameinfo.titlePage; + texname = gameinfo.TitlePage.GetChars(); } } else if (*texname == '$') diff --git a/src/m_cheat.cpp b/src/m_cheat.cpp index 07c467bac..5d9d48bea 100644 --- a/src/m_cheat.cpp +++ b/src/m_cheat.cpp @@ -311,6 +311,7 @@ void cht_DoCheat (player_t *player, int cheat) player->mo->flags4 = player->mo->GetDefault()->flags4; player->mo->flags5 = player->mo->GetDefault()->flags5; player->mo->flags6 = player->mo->GetDefault()->flags6; + player->mo->flags7 = player->mo->GetDefault()->flags7; player->mo->renderflags &= ~RF_INVISIBLE; player->mo->height = player->mo->GetDefault()->height; player->mo->radius = player->mo->GetDefault()->radius; diff --git a/src/m_misc.cpp b/src/m_misc.cpp index a8c6b7380..c550c4593 100644 --- a/src/m_misc.cpp +++ b/src/m_misc.cpp @@ -31,9 +31,6 @@ #include #include #include -#ifdef __APPLE__ -#include -#endif #include "doomtype.h" #include "version.h" @@ -333,65 +330,6 @@ static long ParseCommandLine (const char *args, int *argc, char **argv) } -#if defined(unix) -FString GetUserFile (const char *file) -{ - FString path; - struct stat info; - - path = NicePath("~/" GAME_DIR "/"); - - if (stat (path, &info) == -1) - { - struct stat extrainfo; - - // Sanity check for ~/.config - FString configPath = NicePath("~/.config/"); - if (stat (configPath, &extrainfo) == -1) - { - if (mkdir (configPath, S_IRUSR | S_IWUSR | S_IXUSR) == -1) - { - I_FatalError ("Failed to create ~/.config directory:\n%s", strerror(errno)); - } - } - else if (!S_ISDIR(extrainfo.st_mode)) - { - I_FatalError ("~/.config must be a directory"); - } - - // This can be removed after a release or two - // Transfer the old zdoom directory to the new location - bool moved = false; - FString oldpath = NicePath("~/.zdoom/"); - if (stat (oldpath, &extrainfo) != -1) - { - if (rename(oldpath, path) == -1) - { - I_Error ("Failed to move old zdoom directory (%s) to new location (%s).", - oldpath.GetChars(), path.GetChars()); - } - else - moved = true; - } - - if (!moved && mkdir (path, S_IRUSR | S_IWUSR | S_IXUSR) == -1) - { - I_FatalError ("Failed to create %s directory:\n%s", - path.GetChars(), strerror (errno)); - } - } - else - { - if (!S_ISDIR(info.st_mode)) - { - I_FatalError ("%s must be a directory", path.GetChars()); - } - } - path += file; - return path; -} -#endif - // // M_SaveDefaults // @@ -698,48 +636,23 @@ void M_ScreenShot (const char *filename) // find a file name to save it to if (filename == NULL || filename[0] == '\0') { -#if !defined(unix) && !defined(__APPLE__) - if (Args->CheckParm ("-cdrom")) + size_t dirlen; + autoname = Args->CheckValue("-shotdir"); + if (autoname.IsEmpty()) { - autoname = CDROM_DIR "\\"; + autoname = screenshot_dir; } - else -#endif + dirlen = autoname.Len(); + if (dirlen == 0) { - size_t dirlen; - autoname = Args->CheckValue("-shotdir"); - if (autoname.IsEmpty()) - { - autoname = screenshot_dir; - } + autoname = M_GetScreenshotsPath(); dirlen = autoname.Len(); - if (dirlen == 0) + } + if (dirlen > 0) + { + if (autoname[dirlen-1] != '/' && autoname[dirlen-1] != '\\') { -#ifdef unix - autoname = "~/" GAME_DIR "/screenshots/"; -#elif defined(__APPLE__) - char cpath[PATH_MAX]; - FSRef folder; - - if (noErr == FSFindFolder(kUserDomain, kDocumentsFolderType, kCreateFolder, &folder) && - noErr == FSRefMakePath(&folder, (UInt8*)cpath, PATH_MAX)) - { - autoname << cpath << "/" GAME_DIR "/Screenshots/"; - } - else - { - autoname = "~"; - } -#else - autoname = progdir; -#endif - } - else if (dirlen > 0) - { - if (autoname[dirlen-1] != '/' && autoname[dirlen-1] != '\\') - { - autoname += '/'; - } + autoname += '/'; } } autoname = NicePath(autoname); diff --git a/src/m_misc.h b/src/m_misc.h index 27006cf87..90844221f 100644 --- a/src/m_misc.h +++ b/src/m_misc.h @@ -24,6 +24,7 @@ #define __M_MISC__ #include "basictypes.h" +#include "zstring.h" class FConfigFile; class FGameConfigFile; @@ -44,9 +45,19 @@ bool M_SaveDefaults (const char *filename); void M_SaveCustomKeys (FConfigFile *config, char *section, char *subsection, size_t sublen); -// Prepends ~/.zdoom to path -FString GetUserFile (const char *path); FString M_ZLibError(int zerrnum); +// Get special directory paths (defined in m_specialpaths.cpp) + +#ifdef __unix__ +FString GetUserFile (const char *path); // Prepends ~/.zdoom to path +#endif +FString M_GetCachePath(bool create); +FString M_GetAutoexecPath(); +FString M_GetCajunPath(const char *filename); +FString M_GetConfigPath(bool for_reading); +FString M_GetScreenshotsPath(); +FString M_GetSavegamesPath(); + #endif diff --git a/src/m_random.cpp b/src/m_random.cpp index 763410111..f1e39faf9 100644 --- a/src/m_random.cpp +++ b/src/m_random.cpp @@ -96,6 +96,42 @@ FRandom M_Random; // Global seed. This is modified predictably to initialize every RNG. DWORD rngseed; +// Static RNG marker. This is only used when the RNG is set for each new game. +DWORD staticrngseed; +bool use_staticrng; + +// Allows checking or staticly setting the global seed. +CCMD(rngseed) +{ + if (argv.argc() == 1) + { + Printf("Usage: rngseed get|set|clear\n"); + return; + } + if (stricmp(argv[1], "get") == 0) + { + Printf("rngseed is %d\n", rngseed); + } + else if (stricmp(argv[1], "set") == 0) + { + if (argv.argc() == 2) + { + Printf("You need to specify a value to set\n"); + } + else + { + staticrngseed = atoi(argv[2]); + use_staticrng = true; + Printf("Static rngseed %d will be set for next game\n", staticrngseed); + } + } + else if (stricmp(argv[1], "clear") == 0) + { + use_staticrng = false; + Printf("Static rngseed cleared\n"); + } +} + // PRIVATE DATA DEFINITIONS ------------------------------------------------ FRandom *FRandom::RNGList; diff --git a/src/m_random.h b/src/m_random.h index 5b124c50e..b5e21c63c 100644 --- a/src/m_random.h +++ b/src/m_random.h @@ -215,6 +215,10 @@ private: extern DWORD rngseed; // The starting seed (not part of state) +extern DWORD staticrngseed; // Static rngseed that can be set by the user +extern bool use_staticrng; + + // M_Random can be used for numbers that do not affect gameplay extern FRandom M_Random; diff --git a/src/m_specialpaths.cpp b/src/m_specialpaths.cpp new file mode 100644 index 000000000..e6f74eda6 --- /dev/null +++ b/src/m_specialpaths.cpp @@ -0,0 +1,630 @@ +#ifdef __APPLE__ +#include +#endif + +#ifdef _WIN32 +#include +#include +#include +#define USE_WINDOWS_DWORD +#endif + +#include "cmdlib.h" +#include "m_misc.h" + +#if !defined(__APPLE__) && !defined(_WIN32) +#include +#include +#include "i_system.h" +#endif + +#include "version.h" // for GAMENAME + +#if defined(_WIN32) + +typedef HRESULT (WINAPI *GKFP)(REFKNOWNFOLDERID, DWORD, HANDLE, PWSTR *); + +//=========================================================================== +// +// IsProgramDirectoryWritable +// +// If the program directory is writable, then dump everything in there for +// historical reasons. Otherwise, known folders get used instead. +// +//=========================================================================== + +bool UseKnownFolders() +{ + // Cache this value so the semantics don't change during a single run + // of the program. (e.g. Somebody could add write access while the + // program is running.) + static INTBOOL iswritable = -1; + FString testpath; + HANDLE file; + + if (iswritable >= 0) + { + return !iswritable; + } + testpath << progdir << "writest"; + file = CreateFile(testpath, GENERIC_READ | GENERIC_WRITE, 0, NULL, + CREATE_ALWAYS, + FILE_ATTRIBUTE_TEMPORARY | FILE_FLAG_DELETE_ON_CLOSE, NULL); + if (file != INVALID_HANDLE_VALUE) + { + CloseHandle(file); + Printf("Using program directory for storage\n"); + iswritable = true; + return false; + } + Printf("Using known folders for storage\n"); + iswritable = false; + return true; +} + +//=========================================================================== +// +// GetKnownFolder +// +// Returns the known_folder if SHGetKnownFolderPath is available, otherwise +// returns the shell_folder using SHGetFolderPath. +// +//=========================================================================== + +bool GetKnownFolder(int shell_folder, REFKNOWNFOLDERID known_folder, bool create, FString &path) +{ + static GKFP SHGetKnownFolderPath = NULL; + static bool tested = false; + + if (!tested) + { + tested = true; + HMODULE shell32 = GetModuleHandle("shell32.dll"); + if (shell32 != NULL) + { + SHGetKnownFolderPath = (GKFP)GetProcAddress(shell32, "SHGetKnownFolderPath"); + } + } + + char pathstr[MAX_PATH]; + + // SHGetKnownFolderPath knows about more folders than SHGetFolderPath, but is + // new to Vista, hence the reason we support both. + if (SHGetKnownFolderPath == NULL) + { + if (shell_folder < 0) + { // Not supported by SHGetFolderPath + return false; + } + if (create) + { + shell_folder |= CSIDL_FLAG_CREATE; + } + if (FAILED(SHGetFolderPathA(NULL, shell_folder, NULL, 0, pathstr))) + { + return false; + } + path = pathstr; + return true; + } + else + { + PWSTR wpath; + if (FAILED(SHGetKnownFolderPath(known_folder, create ? KF_FLAG_CREATE : 0, NULL, &wpath))) + { + return false; + } + // FIXME: Support Unicode, at least for filenames. This function + // has no MBCS equivalent, so we have to convert it since we don't + // support Unicode. :( + bool converted = false; + if (WideCharToMultiByte(GetACP(), WC_NO_BEST_FIT_CHARS, wpath, -1, + pathstr, countof(pathstr), NULL, NULL) > 0) + { + path = pathstr; + converted = true; + } + CoTaskMemFree(wpath); + return converted; + } +} + +//=========================================================================== +// +// M_GetCachePath Windows +// +// Returns the path for cache GL nodes. +// +//=========================================================================== + +FString M_GetCachePath(bool create) +{ + FString path; + + if (!GetKnownFolder(CSIDL_LOCAL_APPDATA, FOLDERID_LocalAppData, create, path)) + { // Failed (e.g. On Win9x): use program directory + path = progdir; + } + // Don't use GAME_DIR and such so that ZDoom and its child ports can + // share the node cache. + path += "/zdoom/cache"; + return path; +} + +//=========================================================================== +// +// M_GetAutoexecPath Windows +// +// Returns the expected location of autoexec.cfg. +// +//=========================================================================== + +FString M_GetAutoexecPath() +{ + return "$PROGDIR/autoexec.cfg"; +} + +//=========================================================================== +// +// M_GetCajunPath Windows +// +// Returns the location of the Cajun Bot definitions. +// +//=========================================================================== + +FString M_GetCajunPath(const char *botfilename) +{ + FString path; + + path << progdir << "zcajun/" << botfilename; + if (!FileExists(path)) + { + path = ""; + } + return path; +} + +//=========================================================================== +// +// M_GetConfigPath Windows +// +// Returns the path to the config file. On Windows, this can vary for reading +// vs writing. i.e. If $PROGDIR/zdoom-.ini does not exist, it will try +// to read from $PROGDIR/zdoom.ini, but it will never write to zdoom.ini. +// +//=========================================================================== + +FString M_GetConfigPath(bool for_reading) +{ + FString path; + HRESULT hr; + + // Construct a user-specific config name + if (UseKnownFolders() && GetKnownFolder(CSIDL_APPDATA, FOLDERID_RoamingAppData, true, path)) + { + path += "/" GAME_DIR; + CreatePath(path); + path += "/zdoom.ini"; + } + else + { // construct "$PROGDIR/zdoom-$USER.ini" + TCHAR uname[UNLEN+1]; + DWORD unamelen = countof(uname); + + path = progdir; + hr = GetUserName(uname, &unamelen); + if (SUCCEEDED(hr) && uname[0] != 0) + { + // Is it valid for a user name to have slashes? + // Check for them and substitute just in case. + char *probe = uname; + while (*probe != 0) + { + if (*probe == '\\' || *probe == '/') + *probe = '_'; + ++probe; + } + path << "zdoom-" << uname << ".ini"; + } + else + { // Couldn't get user name, so just use zdoom.ini + path += "zdoom.ini"; + } + } + + // If we are reading the config file, check if it exists. If not, fallback + // to $PROGDIR/zdoom.ini + if (for_reading) + { + if (!FileExists(path)) + { + path = progdir; + path << "zdoom.ini"; + } + } + + return path; +} + +//=========================================================================== +// +// M_GetScreenshotsPath Windows +// +// Returns the path to the default screenshots directory. +// +//=========================================================================== + +// I'm not sure when FOLDERID_Screenshots was added, but it was probably +// for Windows 8, since it's not in the v7.0 Windows SDK. +static const GUID MyFOLDERID_Screenshots = { 0xb7bede81, 0xdf94, 0x4682, 0xa7, 0xd8, 0x57, 0xa5, 0x26, 0x20, 0xb8, 0x6f }; + +FString M_GetScreenshotsPath() +{ + FString path; + + if (!UseKnownFolders()) + { + return progdir; + } + else if (GetKnownFolder(-1, MyFOLDERID_Screenshots, true, path)) + { + path << "/" GAMENAME; + } + else if (GetKnownFolder(CSIDL_MYPICTURES, FOLDERID_Pictures, true, path)) + { + path << "/Screenshots/" GAMENAME; + } + else + { + return progdir; + } + CreatePath(path); + return path; +} + +//=========================================================================== +// +// M_GetSavegamesPath Windows +// +// Returns the path to the default save games directory. +// +//=========================================================================== + +FString M_GetSavegamesPath() +{ + FString path; + + if (!UseKnownFolders()) + { + return progdir; + } + // Try standard Saved Games folder + else if (GetKnownFolder(-1, FOLDERID_SavedGames, true, path)) + { + path << "/" GAMENAME; + } + // Try defacto My Documents/My Games folder + else if (GetKnownFolder(CSIDL_PERSONAL, FOLDERID_Documents, true, path)) + { + // I assume since this isn't a standard folder, it doesn't have + // a localized name either. + path << "/My Games/" GAMENAME; + CreatePath(path); + } + else + { + path = progdir; + } + return path; +} + +#elif defined(__APPLE__) + +//=========================================================================== +// +// M_GetCachePath Mac OS X +// +// Returns the path for cache GL nodes. +// +//=========================================================================== + +FString M_GetCachePath(bool create) +{ + FString path; + + char pathstr[PATH_MAX]; + FSRef folder; + + if (noErr == FSFindFolder(kUserDomain, kApplicationSupportFolderType, create ? kCreateFolder : 0, &folder) && + noErr == FSRefMakePath(&folder, (UInt8*)pathstr, PATH_MAX)) + { + path = pathstr; + } + else + { + path = progdir; + } + path += "/zdoom/cache"; + return path; +} + +//=========================================================================== +// +// M_GetAutoexecPath Mac OS X +// +// Returns the expected location of autoexec.cfg. +// +//=========================================================================== + +FString M_GetAutoexecPath() +{ + FString path; + + char cpath[PATH_MAX]; + FSRef folder; + + if (noErr == FSFindFolder(kUserDomain, kDocumentsFolderType, kCreateFolder, &folder) && + noErr == FSRefMakePath(&folder, (UInt8*)cpath, PATH_MAX)) + { + path << cpath << "/" GAME_DIR "/autoexec.cfg"; + } + return path; +} + +//=========================================================================== +// +// M_GetCajunPath Mac OS X +// +// Returns the location of the Cajun Bot definitions. +// +//=========================================================================== + +FString M_GetCajunPath(const char *botfilename) +{ + FString path; + + // Just copies the Windows code. Should this be more Mac-specific? + path << progdir << "zcajun/" << botfilename; + if (!FileExists(path)) + { + path = ""; + } + return path; +} + +//=========================================================================== +// +// M_GetConfigPath Mac OS X +// +// Returns the path to the config file. On Windows, this can vary for reading +// vs writing. i.e. If $PROGDIR/zdoom-.ini does not exist, it will try +// to read from $PROGDIR/zdoom.ini, but it will never write to zdoom.ini. +// +//=========================================================================== + +FString M_GetConfigPath(bool for_reading) +{ + char cpath[PATH_MAX]; + FSRef folder; + + if (noErr == FSFindFolder(kUserDomain, kPreferencesFolderType, kCreateFolder, &folder) && + noErr == FSRefMakePath(&folder, (UInt8*)cpath, PATH_MAX)) + { + FString path; + path << cpath << "/zdoom.ini"; + return path; + } + // Ungh. + return "zdoom.ini"; +} + +//=========================================================================== +// +// M_GetScreenshotsPath Mac OS X +// +// Returns the path to the default screenshots directory. +// +//=========================================================================== + +FString M_GetScreenshotsPath() +{ + FString path; + char cpath[PATH_MAX]; + FSRef folder; + + if (noErr == FSFindFolder(kUserDomain, kDocumentsFolderType, kCreateFolder, &folder) && + noErr == FSRefMakePath(&folder, (UInt8*)cpath, PATH_MAX)) + { + path << cpath << "/" GAME_DIR "/Screenshots/"; + } + else + { + path = "~/"; + } + return path; +} + +//=========================================================================== +// +// M_GetSavegamesPath Mac OS X +// +// Returns the path to the default save games directory. +// +//=========================================================================== + +FString M_GetSavegamesPath() +{ + FString path; + char cpath[PATH_MAX]; + FSRef folder; + + if (noErr == FSFindFolder(kUserDomain, kDocumentsFolderType, kCreateFolder, &folder) && + noErr == FSRefMakePath(&folder, (UInt8*)cpath, PATH_MAX)) + { + path << cpath << "/" GAME_DIR "/Savegames/"; + } + return path; +} + +#else // Linux, et al. + + +FString GetUserFile (const char *file) +{ + FString path; + struct stat info; + + path = NicePath("~/" GAME_DIR "/"); + + if (stat (path, &info) == -1) + { + struct stat extrainfo; + + // Sanity check for ~/.config + FString configPath = NicePath("~/.config/"); + if (stat (configPath, &extrainfo) == -1) + { + if (mkdir (configPath, S_IRUSR | S_IWUSR | S_IXUSR) == -1) + { + I_FatalError ("Failed to create ~/.config directory:\n%s", strerror(errno)); + } + } + else if (!S_ISDIR(extrainfo.st_mode)) + { + I_FatalError ("~/.config must be a directory"); + } + + // This can be removed after a release or two + // Transfer the old zdoom directory to the new location + bool moved = false; + FString oldpath = NicePath("~/.zdoom/"); + if (stat (oldpath, &extrainfo) != -1) + { + if (rename(oldpath, path) == -1) + { + I_Error ("Failed to move old zdoom directory (%s) to new location (%s).", + oldpath.GetChars(), path.GetChars()); + } + else + moved = true; + } + + if (!moved && mkdir (path, S_IRUSR | S_IWUSR | S_IXUSR) == -1) + { + I_FatalError ("Failed to create %s directory:\n%s", + path.GetChars(), strerror (errno)); + } + } + else + { + if (!S_ISDIR(info.st_mode)) + { + I_FatalError ("%s must be a directory", path.GetChars()); + } + } + path += file; + return path; +} + +//=========================================================================== +// +// M_GetCachePath Unix +// +// Returns the path for cache GL nodes. +// +//=========================================================================== + +FString M_GetCachePath(bool create) +{ + // Don't use GAME_DIR and such so that ZDoom and its child ports can + // share the node cache. + FString path = NicePath("~/.config/zdoom/cache"); + if (create) + { + CreatePath(path); + } + return path; +} + +//=========================================================================== +// +// M_GetAutoexecPath Unix +// +// Returns the expected location of autoexec.cfg. +// +//=========================================================================== + +FString M_GetAutoexecPath() +{ + return GetUserFile("autoexec.cfg"); +} + +//=========================================================================== +// +// M_GetCajunPath Unix +// +// Returns the location of the Cajun Bot definitions. +// +//=========================================================================== + +FString M_GetCajunPath(const char *botfilename) +{ + FString path; + + // Check first in ~/.config/zdoom/botfilename. + path = GetUserFile(botfilename); + if (!FileExists(path)) + { + // Then check in SHARE_DIR/botfilename. + path = SHARE_DIR; + path << botfilename; + if (!FileExists(path)) + { + path = ""; + } + } + return path; +} + +//=========================================================================== +// +// M_GetConfigPath Unix +// +// Returns the path to the config file. On Windows, this can vary for reading +// vs writing. i.e. If $PROGDIR/zdoom-.ini does not exist, it will try +// to read from $PROGDIR/zdoom.ini, but it will never write to zdoom.ini. +// +//=========================================================================== + +FString M_GetConfigPath(bool for_reading) +{ + return GetUserFile("zdoom.ini"); +} + +//=========================================================================== +// +// M_GetScreenshotsPath Unix +// +// Returns the path to the default screenshots directory. +// +//=========================================================================== + +FString M_GetScreenshotsPath() +{ + return NicePath("~/" GAME_DIR "/screenshots/"); +} + +//=========================================================================== +// +// M_GetSavegamesPath Unix +// +// Returns the path to the default save games directory. +// +//=========================================================================== + +FString M_GetSavegamesPath() +{ + return NicePath("~/" GAME_DIR); +} + +#endif diff --git a/src/menu/joystickmenu.cpp b/src/menu/joystickmenu.cpp index 6be728865..a7d950ed5 100644 --- a/src/menu/joystickmenu.cpp +++ b/src/menu/joystickmenu.cpp @@ -74,12 +74,12 @@ public: { } - double GetValue() + double GetSliderValue() { return SELECTED_JOYSTICK->GetSensitivity(); } - void SetValue(double val) + void SetSliderValue(double val) { SELECTED_JOYSTICK->SetSensitivity(float(val)); } @@ -104,14 +104,14 @@ public: mNeg = 1; } - double GetValue() + double GetSliderValue() { double d = SELECTED_JOYSTICK->GetAxisScale(mAxis); mNeg = d < 0? -1:1; return d; } - void SetValue(double val) + void SetSliderValue(double val) { SELECTED_JOYSTICK->SetAxisScale(mAxis, float(val * mNeg)); } @@ -136,14 +136,14 @@ public: mNeg = 1; } - double GetValue() + double GetSliderValue() { double d = SELECTED_JOYSTICK->GetAxisDeadZone(mAxis); mNeg = d < 0? -1:1; return d; } - void SetValue(double val) + void SetSliderValue(double val) { SELECTED_JOYSTICK->SetAxisDeadZone(mAxis, float(val * mNeg)); } diff --git a/src/menu/loadsavemenu.cpp b/src/menu/loadsavemenu.cpp index 9a87bb806..f16e1cbc2 100644 --- a/src/menu/loadsavemenu.cpp +++ b/src/menu/loadsavemenu.cpp @@ -345,7 +345,7 @@ void DLoadSaveMenu::NotifyNewSave (const char *file, const char *title, bool okF for (unsigned i=0; iFilename.Compare (file) == 0) #else if (node->Filename.CompareNoCase (file) == 0) diff --git a/src/menu/menu.cpp b/src/menu/menu.cpp index dc1b8ccd8..d01f0807f 100644 --- a/src/menu/menu.cpp +++ b/src/menu/menu.cpp @@ -207,7 +207,7 @@ bool DMenu::MouseEventBack(int type, int x, int y) { if (m_show_backbutton >= 0) { - FTexture *tex = TexMan[gameinfo.mBackButton]; + FTexture *tex = TexMan(gameinfo.mBackButton); if (tex != NULL) { if (m_show_backbutton&1) x -= screen->GetWidth() - tex->GetScaledWidth() * CleanXfac; @@ -263,7 +263,7 @@ void DMenu::Drawer () { if (this == DMenu::CurrentMenu && BackbuttonAlpha > 0 && m_show_backbutton >= 0 && m_use_mouse) { - FTexture *tex = TexMan[gameinfo.mBackButton]; + FTexture *tex = TexMan(gameinfo.mBackButton); int w = tex->GetScaledWidth() * CleanXfac; int h = tex->GetScaledHeight() * CleanYfac; int x = (!(m_show_backbutton&1))? 0:screen->GetWidth() - w; @@ -909,6 +909,11 @@ CCMD (openmenu) M_SetMenu(argv[1], -1); } +CCMD (closemenu) +{ + M_ClearMenus(); +} + // // Toggle messages on/off // diff --git a/src/menu/menu.h b/src/menu/menu.h index 1388a33bb..3712c9065 100644 --- a/src/menu/menu.h +++ b/src/menu/menu.h @@ -553,7 +553,6 @@ public: } ~FOptionMenuItem(); - virtual bool CheckCoordinate(FOptionMenuDescriptor *desc, int x, int y); virtual int Draw(FOptionMenuDescriptor *desc, int y, int indent, bool selected); virtual bool Selectable(); virtual int GetIndent(); diff --git a/src/menu/menudef.cpp b/src/menu/menudef.cpp index 4fa4e09e3..b1db3cf2e 100644 --- a/src/menu/menudef.cpp +++ b/src/menu/menudef.cpp @@ -160,7 +160,7 @@ static bool CheckSkipOptionBlock(FScanner &sc) } else if (sc.Compare("unix")) { - #ifdef unix + #ifdef __unix__ filter = true; #endif } diff --git a/src/menu/optionmenu.cpp b/src/menu/optionmenu.cpp index 08489fe23..eff53fc49 100644 --- a/src/menu/optionmenu.cpp +++ b/src/menu/optionmenu.cpp @@ -468,11 +468,6 @@ FOptionMenuItem::~FOptionMenuItem() if (mLabel != NULL) delete [] mLabel; } -bool FOptionMenuItem::CheckCoordinate(FOptionMenuDescriptor *desc, int x, int y) -{ - return false; -} - int FOptionMenuItem::Draw(FOptionMenuDescriptor *desc, int y, int indent, bool selected) { return indent; diff --git a/src/menu/optionmenuitems.h b/src/menu/optionmenuitems.h index d57e13d05..439ed7ffc 100644 --- a/src/menu/optionmenuitems.h +++ b/src/menu/optionmenuitems.h @@ -560,8 +560,8 @@ public: mSliderShort = 0; } - virtual double GetValue() = 0; - virtual void SetValue(double val) = 0; + virtual double GetSliderValue() = 0; + virtual void SetSliderValue(double val) = 0; //============================================================================= // @@ -614,14 +614,14 @@ public: { drawLabel(indent, y, selected? OptionSettings.mFontColorSelection : OptionSettings.mFontColor); mDrawX = indent + CURSORSPACE; - DrawSlider (mDrawX, y, mMin, mMax, GetValue(), mShowValue, indent); + DrawSlider (mDrawX, y, mMin, mMax, GetSliderValue(), mShowValue, indent); return indent; } //============================================================================= bool MenuEvent (int mkey, bool fromcontroller) { - double value = GetValue(); + double value = GetSliderValue(); if (mkey == MKEY_Left) { @@ -635,7 +635,7 @@ public: { return FOptionMenuItem::MenuEvent(mkey, fromcontroller); } - SetValue(clamp(value, mMin, mMax)); + SetSliderValue(clamp(value, mMin, mMax)); S_Sound (CHAN_VOICE | CHAN_UI, "menu/change", snd_menuvolume, ATTN_NONE); return true; } @@ -662,9 +662,9 @@ public: x = clamp(x, slide_left, slide_right); double v = mMin + ((x - slide_left) * (mMax - mMin)) / (slide_right - slide_left); - if (v != GetValue()) + if (v != GetSliderValue()) { - SetValue(v); + SetSliderValue(v); //S_Sound (CHAN_VOICE | CHAN_UI, "menu/change", snd_menuvolume, ATTN_NONE); } if (type == DMenu::MOUSE_Click) @@ -692,7 +692,7 @@ public: mCVar = FindCVar(menu, NULL); } - double GetValue() + double GetSliderValue() { if (mCVar != NULL) { @@ -704,7 +704,7 @@ public: } } - void SetValue(double val) + void SetSliderValue(double val) { if (mCVar != NULL) { @@ -732,12 +732,12 @@ public: mPVal = pVal; } - double GetValue() + double GetSliderValue() { return *mPVal; } - void SetValue(double val) + void SetSliderValue(double val) { *mPVal = (float)val; } @@ -763,7 +763,7 @@ public: : FOptionMenuItem(label, menu) { FBaseCVar *cv = FindCVar(menu, NULL); - if (cv->GetRealType() == CVAR_Color) + if (cv != NULL && cv->GetRealType() == CVAR_Color) { mCVar = (FColorCVar*)cv; } diff --git a/src/menu/playermenu.cpp b/src/menu/playermenu.cpp index 641b0699f..58b08fc38 100644 --- a/src/menu/playermenu.cpp +++ b/src/menu/playermenu.cpp @@ -996,7 +996,10 @@ bool DPlayerMenu::MenuEvent (int mkey, bool fromcontroller) // item specific handling comes here case NAME_Playerbox: - PlayerNameChanged(li); + if (mkey == MKEY_Input) + { + PlayerNameChanged(li); + } break; case NAME_Team: diff --git a/src/menu/readthis.cpp b/src/menu/readthis.cpp index 197981ad3..a00843440 100644 --- a/src/menu/readthis.cpp +++ b/src/menu/readthis.cpp @@ -82,9 +82,9 @@ void DReadThisMenu::Drawer() fixed_t alpha; // Did the mapper choose a custom help page via MAPINFO? - if ((level.info != NULL) && level.info->f1[0] != 0) + if ((level.info != NULL) && level.info->F1Pic.Len() != 0) { - tex = TexMan.FindTexture(level.info->f1); + tex = TexMan.FindTexture(level.info->F1Pic); mScreen = 1; } @@ -122,7 +122,7 @@ bool DReadThisMenu::MenuEvent(int mkey, bool fromcontroller) S_Sound (CHAN_VOICE | CHAN_UI, "menu/choose", snd_menuvolume, ATTN_NONE); mScreen++; mInfoTic = gametic; - if ((level.info != NULL && level.info->f1[0] != 0) || mScreen > int(gameinfo.infoPages.Size())) + if ((level.info != NULL && level.info->F1Pic.Len() != 0) || mScreen > int(gameinfo.infoPages.Size())) { Close(); } diff --git a/src/namedef.h b/src/namedef.h index 14e4ec7ac..32251560b 100644 --- a/src/namedef.h +++ b/src/namedef.h @@ -30,6 +30,20 @@ xx(Cumulative) xx(Fuzzy) xx(Opaque) xx(Stencil) +xx(AddStencil) + +// Render styles +xx(Normal) +xx(SoulTrans) +xx(OptFuzzy) +xx(Add) +xx(Shaded) +xx(AddShaded) +xx(TranslucentStencil) +xx(Shadow) +xx(Subtract) +xx(Subtractive) +xx(FillColor) // Healingradius types xx(Mana) @@ -373,6 +387,11 @@ xx(Friend) xx(Strifeally) xx(Standing) xx(Countsecret) +xx(Score) +xx(Roll) +xx(Scale) +xx(ScaleX) +xx(ScaleY) xx(Blocking) xx(Blockmonsters) @@ -469,6 +488,15 @@ xx(blockhitscan) xx(Renderstyle) +xx(ceilingplane_a) +xx(ceilingplane_b) +xx(ceilingplane_c) +xx(ceilingplane_d) +xx(floorplane_a) +xx(floorplane_b) +xx(floorplane_c) +xx(floorplane_d) + // USDF keywords xx(Amount) xx(Text) diff --git a/src/nodebuild.cpp b/src/nodebuild.cpp index c13527d87..210f0f3de 100644 --- a/src/nodebuild.cpp +++ b/src/nodebuild.cpp @@ -90,7 +90,7 @@ FNodeBuilder::~FNodeBuilder() } if (OldVertexTable != NULL) { - delete OldVertexTable; + delete[] OldVertexTable; } } @@ -125,12 +125,10 @@ void FNodeBuilder::BuildTree () { fixed_t bbox[4]; - C_InitTicker ("Building BSP", FRACUNIT); HackSeg = DWORD_MAX; HackMate = DWORD_MAX; CreateNode (0, Segs.Size(), bbox); CreateSubsectorsForReal (); - C_InitTicker (NULL, 0); } int FNodeBuilder::CreateNode (DWORD set, unsigned int count, fixed_t bbox[4]) @@ -199,10 +197,6 @@ int FNodeBuilder::CreateSubsector (DWORD set, fixed_t bbox[4]) } SegsStuffed += count; - if ((SegsStuffed & ~127) != ((SegsStuffed - count) & ~127)) - { - C_SetTicker (MulScale16 (SegsStuffed, (SDWORD)Segs.Size())); - } D(Printf (PRINT_LOG, "bbox (%d,%d)-(%d,%d)\n", bbox[BOXLEFT]>>16, bbox[BOXBOTTOM]>>16, bbox[BOXRIGHT]>>16, bbox[BOXTOP]>>16)); @@ -504,10 +498,6 @@ int FNodeBuilder::SelectSplitter (DWORD set, node_t &node, DWORD &splitseg, int nosplitters = true; } } - else - { - pseg = pseg; - } } seg = pseg->next; diff --git a/src/nodebuild.h b/src/nodebuild.h index 81c7b1345..ce68c4682 100644 --- a/src/nodebuild.h +++ b/src/nodebuild.h @@ -347,7 +347,7 @@ inline int FNodeBuilder::ClassifyLine (node_t &node, const FPrivVert *v1, const #ifdef DISABLE_SSE return ClassifyLine2 (node, v1, v2, sidev); #else -#if defined(__SSE2__) || defined(_M_IX64) +#if defined(__SSE2__) || defined(_M_X64) // If compiling with SSE2 support everywhere, just use the SSE2 version. return ClassifyLineSSE2 (node, v1, v2, sidev); #elif defined(_MSC_VER) && _MSC_VER < 1300 diff --git a/src/oplsynth/music_opldumper_mididevice.cpp b/src/oplsynth/music_opldumper_mididevice.cpp index 0bb9ac14d..74bef0677 100644 --- a/src/oplsynth/music_opldumper_mididevice.cpp +++ b/src/oplsynth/music_opldumper_mididevice.cpp @@ -139,7 +139,7 @@ DiskWriterIO::~DiskWriterIO() // //========================================================================== -int DiskWriterIO::OPLinit(uint numchips, bool dontcare) +int DiskWriterIO::OPLinit(uint numchips, bool, bool) { // If the file extension is unknown or not present, the default format // is RAW. Otherwise, you can use DRO. diff --git a/src/oplsynth/muslib.h b/src/oplsynth/muslib.h index 404ce1e63..6cfb5bd55 100644 --- a/src/oplsynth/muslib.h +++ b/src/oplsynth/muslib.h @@ -195,7 +195,7 @@ struct DiskWriterIO : public OPLio DiskWriterIO(const char *filename); ~DiskWriterIO(); - int OPLinit(uint numchips, bool notused=false); + int OPLinit(uint numchips, bool notused=false, bool notused2=false); void OPLdeinit(); void OPLwriteReg(int which, uint reg, uchar data); void SetClockRate(double samples_per_tick); diff --git a/src/oplsynth/opl.h b/src/oplsynth/opl.h index eb46c9955..661258a26 100644 --- a/src/oplsynth/opl.h +++ b/src/oplsynth/opl.h @@ -15,7 +15,6 @@ public: virtual void WriteReg(int reg, int v) = 0; virtual void Update(float *buffer, int length) = 0; virtual void SetPanning(int c, float left, float right) = 0; - virtual FString GetVoiceString() { return FString(); } }; OPLEmul *YM3812Create(bool stereo); diff --git a/src/oplsynth/opl_mus_player.cpp b/src/oplsynth/opl_mus_player.cpp index 335e6d66e..a528c10e2 100644 --- a/src/oplsynth/opl_mus_player.cpp +++ b/src/oplsynth/opl_mus_player.cpp @@ -96,7 +96,7 @@ fail: delete[] scoredata; else if (((DWORD *)scoredata)[0] == MAKE_ID('D','B','R','A') && ((DWORD *)scoredata)[1] == MAKE_ID('W','O','P','L')) { - if (((DWORD *)scoredata)[2] == MAKE_ID(0,0,1,0)) + if (LittleShort(((WORD *)scoredata)[5]) == 1) { RawPlayer = DosBox1; SamplesPerTick = OPL_SAMPLE_RATE / 1000; @@ -104,16 +104,19 @@ fail: delete[] scoredata; } else if (((DWORD *)scoredata)[2] == MAKE_ID(2,0,0,0)) { - if (scoredata[20] != 0) - { - Printf("Unsupported DOSBox Raw OPL format %d\n", scoredata[20]); - goto fail; - } + bool okay = true; if (scoredata[21] != 0) { - Printf("Unsupported DOSBox Raw OPL compression %d\n", scoredata[21]); - goto fail; + Printf("Unsupported DOSBox Raw OPL format %d\n", scoredata[20]); + okay = false; } + if (scoredata[22] != 0) + { + Printf("Unsupported DOSBox Raw OPL compression %d\n", scoredata[21]); + okay = false; + } + if (!okay) + goto fail; RawPlayer = DosBox2; SamplesPerTick = OPL_SAMPLE_RATE / 1000; int headersize = 0x1A + scoredata[0x19]; @@ -264,7 +267,7 @@ bool OPLmusicBlock::ServiceStream (void *buff, int numbytes) { for (i = 0; i < io->NumChips; ++i) { - io->chips[i]->Update(samples1, samplesleft); + io->chips[i]->Update(samples1, numsamples); } OffsetSamples(samples1, numsamples << stereoshift); } diff --git a/src/p_3dfloors.cpp b/src/p_3dfloors.cpp index 56b34ca0f..95ced549a 100644 --- a/src/p_3dfloors.cpp +++ b/src/p_3dfloors.cpp @@ -60,7 +60,7 @@ FDynamicColormap *F3DFloor::GetColormap() { // If there's no fog in either model or target sector this is easy and fast. - if ((target->ColorMap->Fade == 0 && model->ColorMap->Fade == 0) || (flags & FF_FADEWALLS)) + if ((target->ColorMap->Fade == 0 && model->ColorMap->Fade == 0) || (flags & (FF_FADEWALLS|FF_FOG))) { return model->ColorMap; } @@ -293,8 +293,9 @@ static int P_Set3DFloor(line_t * line, int param, int param2, int alpha) FTextureID tex = line->sidedef[0]->GetTexture(side_t::top); if (!tex.Exists() && alpha<255) { - alpha=clamp(-tex.GetIndex(), 0, 255); + alpha = -tex.GetIndex(); } + alpha = clamp(alpha, 0, 255); if (alpha==0) flags&=~(FF_RENDERALL|FF_BOTHPLANES|FF_ALLSIDES); else if (alpha!=255) flags|=FF_TRANSLUCENT; diff --git a/src/p_acs.cpp b/src/p_acs.cpp index 32a70cd15..981870a36 100644 --- a/src/p_acs.cpp +++ b/src/p_acs.cpp @@ -3529,7 +3529,8 @@ enum APROP_ReactionTime = 37, APROP_MeleeRange = 38, APROP_ViewHeight = 39, - APROP_AttackZOffset = 40 + APROP_AttackZOffset = 40, + APROP_StencilColor = 41 }; // These are needed for ACS's APROP_RenderStyle @@ -3541,10 +3542,14 @@ static const int LegacyRenderStyleIndices[] = 3, // STYLE_SoulTrans, 4, // STYLE_OptFuzzy, 5, // STYLE_Stencil, + 6, // STYLE_AddStencil + 7, // STYLE_AddShaded 64, // STYLE_Translucent 65, // STYLE_Add, 66, // STYLE_Shaded, 67, // STYLE_TranslucentStencil, + 68, // STYLE_Shadow, + 69, // STYLE_Subtract, -1 }; @@ -3755,6 +3760,10 @@ void DLevelScript::DoSetActorProperty (AActor *actor, int property, int value) static_cast(actor)->AttackZOffset = value; break; + case APROP_StencilColor: + actor->SetShade(value); + break; + default: // do nothing. break; @@ -3852,6 +3861,7 @@ int DLevelScript::GetActorProperty (int tid, int property, const SDWORD *stack, case APROP_ActiveSound: return GlobalACSStrings.AddString(actor->ActiveSound, stack, stackdepth); case APROP_Species: return GlobalACSStrings.AddString(actor->GetSpecies(), stack, stackdepth); case APROP_NameTag: return GlobalACSStrings.AddString(actor->GetTag(), stack, stackdepth); + case APROP_StencilColor:return actor->fillcolor; default: return 0; } @@ -3898,6 +3908,7 @@ int DLevelScript::CheckActorProperty (int tid, int property, int value) case APROP_MeleeRange: case APROP_ViewHeight: case APROP_AttackZOffset: + case APROP_StencilColor: return (GetActorProperty(tid, property, NULL, 0) == value); // Boolean values need to compare to a binary version of value @@ -3933,7 +3944,9 @@ bool DLevelScript::DoCheckActorTexture(int tid, AActor *activator, int string, b { return 0; } - FTexture *tex = TexMan.FindTexture(FBehavior::StaticLookupString(string)); + FTexture *tex = TexMan.FindTexture(FBehavior::StaticLookupString(string), FTexture::TEX_Flat, + FTextureManager::TEXMAN_Overridable|FTextureManager::TEXMAN_TryAny|FTextureManager::TEXMAN_DontCreate); + if (tex == NULL) { // If the texture we want to check against doesn't exist, then // they're obviously not the same. @@ -4250,6 +4263,22 @@ enum EACSFunctions ACSF_SpawnDecal, ACSF_CheckFont, ACSF_DropItem, + ACSF_CheckFlag, + ACSF_SetLineActivation, + ACSF_GetLineActivation, + ACSF_GetActorPowerupTics, + ACSF_ChangeActorAngle, + ACSF_ChangeActorPitch, // 80 + + /* Zandronum's - these must be skipped when we reach 99! + -100:ResetMap(0), + -101 : PlayerIsSpectator(1), + -102 : ConsolePlayerNumber(0), + -103 : GetTeamProperty(2), + -104 : GetPlayerLivesLeft(1), + -105 : SetPlayerLivesLeft(2), + -106 : KickFromGame(2), + */ // ZDaemon ACSF_GetTeamScore = 19620, // (int team) @@ -4509,6 +4538,50 @@ static bool DoSpawnDecal(AActor *actor, const FDecalTemplate *tpl, int flags, an angle, distance, !!(flags & SDF_PERMANENT)); } +static void SetActorAngle(AActor *activator, int tid, int angle, bool interpolate) +{ + if (tid == 0) + { + if (activator != NULL) + { + activator->SetAngle(angle << 16, interpolate); + } + } + else + { + FActorIterator iterator(tid); + AActor *actor; + + while ((actor = iterator.Next())) + { + actor->SetAngle(angle << 16, interpolate); + } + } +} + +static void SetActorPitch(AActor *activator, int tid, int angle, bool interpolate) +{ + if (tid == 0) + { + if (activator != NULL) + { + activator->SetPitch(angle << 16, interpolate); + } + } + else + { + FActorIterator iterator(tid); + AActor *actor; + + while ((actor = iterator.Next())) + { + actor->SetPitch(angle << 16, interpolate); + } + } +} + + + int DLevelScript::CallFunction(int argCount, int funcIndex, SDWORD *args, const SDWORD *stack, int stackdepth) { AActor *actor; @@ -4933,7 +5006,7 @@ int DLevelScript::CallFunction(int argCount, int funcIndex, SDWORD *args, const break; case ACSF_UniqueTID: - return P_FindUniqueTID(argCount > 0 ? args[0] : 0, argCount > 1 ? args[1] : 0); + return P_FindUniqueTID(argCount > 0 ? args[0] : 0, (argCount > 1 && args[1] >= 0) ? args[1] : 0); case ACSF_IsTIDUsed: return P_IsTIDUsed(args[0]); @@ -5285,6 +5358,71 @@ doplaysound: if (funcIndex == ACSF_PlayActorSound) break; } + case ACSF_CheckFlag: + { + AActor *actor = SingleActorFromTID(args[0], activator); + if (actor != NULL) + { + return !!CheckActorFlag(actor, FBehavior::StaticLookupString(args[1])); + } + break; + } + + case ACSF_SetLineActivation: + if (argCount >= 2) + { + int line = -1; + + while ((line = P_FindLineFromID(args[0], line)) >= 0) + { + lines[line].activation = args[1]; + } + } + break; + + case ACSF_GetLineActivation: + if (argCount > 0) + { + int line = P_FindLineFromID(args[0], -1); + return line >= 0 ? lines[line].activation : 0; + } + break; + + case ACSF_GetActorPowerupTics: + if (argCount >= 2) + { + const PClass *powerupclass = PClass::FindClass(FBehavior::StaticLookupString(args[1])); + if (powerupclass == NULL || !RUNTIME_CLASS(APowerup)->IsAncestorOf(powerupclass)) + { + Printf("'%s' is not a type of Powerup.\n", FBehavior::StaticLookupString(args[1])); + return 0; + } + + AActor *actor = SingleActorFromTID(args[0], activator); + if (actor != NULL) + { + APowerup* powerup = (APowerup*)actor->FindInventory(powerupclass); + if (powerup != NULL) + return powerup->EffectTics; + } + return 0; + } + break; + + case ACSF_ChangeActorAngle: + if (argCount >= 2) + { + SetActorAngle(activator, args[0], args[1], argCount > 2 ? !!args[2] : false); + } + break; + + case ACSF_ChangeActorPitch: + if (argCount >= 2) + { + SetActorPitch(activator, args[0], args[1], argCount > 2 ? !!args[2] : false); + } + break; + default: break; } @@ -6796,7 +6934,22 @@ scriptwait: break; case PCD_PRINTBINARY: +#if (defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && (__GNUC_MINOR__ >= 6)))) || defined(__clang__) +#define HAS_DIAGNOSTIC_PRAGMA +#endif +#ifdef HAS_DIAGNOSTIC_PRAGMA +#pragma GCC diagnostic push +#ifdef __clang__ +#pragma GCC diagnostic ignored "-Wformat-invalid-specifier" +#else +#pragma GCC diagnostic ignored "-Wformat=" +#endif +#pragma GCC diagnostic ignored "-Wformat-extra-args" +#endif work.AppendFormat ("%B", STACK(1)); +#ifdef HAS_DIAGNOSTIC_PRAGMA +#pragma GCC diagnostic pop +#endif --sp; break; @@ -6830,7 +6983,7 @@ scriptwait: break; case PRINTNAME_LEVEL: - work += level.mapname; + work += level.MapName; break; case PRINTNAME_SKILL: @@ -7826,14 +7979,22 @@ scriptwait: case PCD_GETSECTORCEILINGZ: // Arguments are (tag, x, y). If you don't use slopes, then (x, y) don't // really matter and can be left as (0, 0) if you like. + // [Dusk] If tag = 0, then this returns the z height at whatever sector + // is in x, y. { - int secnum = P_FindSectorFromTag (STACK(3), -1); + int tag = STACK(3); + int secnum; + fixed_t x = STACK(2) << FRACBITS; + fixed_t y = STACK(1) << FRACBITS; fixed_t z = 0; + if (tag != 0) + secnum = P_FindSectorFromTag (tag, -1); + else + secnum = int(P_PointInSector (x, y) - sectors); + if (secnum >= 0) { - fixed_t x = STACK(2) << FRACBITS; - fixed_t y = STACK(1) << FRACBITS; if (pcd == PCD_GETSECTORFLOORZ) { z = sectors[secnum].floorplane.ZatPoint (x, y); @@ -8191,13 +8352,11 @@ scriptwait: sky2name = FBehavior::StaticLookupString (STACK(1)); if (sky1name[0] != 0) { - strncpy (level.skypic1, sky1name, 8); - sky1texture = TexMan.GetTexture (sky1name, FTexture::TEX_Wall, FTextureManager::TEXMAN_Overridable|FTextureManager::TEXMAN_ReturnFirst); + sky1texture = level.skytexture1 = TexMan.GetTexture (sky1name, FTexture::TEX_Wall, FTextureManager::TEXMAN_Overridable|FTextureManager::TEXMAN_ReturnFirst); } if (sky2name[0] != 0) { - strncpy (level.skypic2, sky2name, 8); - sky2texture = TexMan.GetTexture (sky2name, FTexture::TEX_Wall, FTextureManager::TEXMAN_Overridable|FTextureManager::TEXMAN_ReturnFirst); + sky2texture = level.skytexture2 = TexMan.GetTexture (sky2name, FTexture::TEX_Wall, FTextureManager::TEXMAN_Overridable|FTextureManager::TEXMAN_ReturnFirst); } R_InitSkyMap (); sp -= 2; @@ -8236,40 +8395,12 @@ scriptwait: break; case PCD_SETACTORANGLE: // [GRB] - if (STACK(2) == 0) - { - if (activator != NULL) - activator->angle = STACK(1) << 16; - } - else - { - FActorIterator iterator (STACK(2)); - AActor *actor; - - while ( (actor = iterator.Next ()) ) - { - actor->angle = STACK(1) << 16; - } - } + SetActorAngle(activator, STACK(2), STACK(1), false); sp -= 2; break; case PCD_SETACTORPITCH: - if (STACK(2) == 0) - { - if (activator != NULL) - activator->pitch = STACK(1) << 16; - } - else - { - FActorIterator iterator (STACK(2)); - AActor *actor; - - while ( (actor = iterator.Next ()) ) - { - actor->pitch = STACK(1) << 16; - } - } + SetActorPitch(activator, STACK(2), STACK(1), false); sp -= 2; break; @@ -8813,7 +8944,7 @@ static void addDefered (level_info_t *i, acsdefered_t::EType type, int script, c def->playernum = -1; } i->defered = def; - DPrintf ("%s on map %s deferred\n", ScriptPresentation(script).GetChars(), i->mapname); + DPrintf ("%s on map %s deferred\n", ScriptPresentation(script).GetChars(), i->MapName.GetChars()); } } @@ -8821,7 +8952,7 @@ EXTERN_CVAR (Bool, sv_cheats) int P_StartScript (AActor *who, line_t *where, int script, const char *map, const int *args, int argcount, int flags) { - if (map == NULL || 0 == strnicmp (level.mapname, map, 8)) + if (map == NULL || 0 == strnicmp (level.MapName, map, 8)) { FBehavior *module = NULL; const ScriptPtr *scriptdata; @@ -8874,17 +9005,17 @@ int P_StartScript (AActor *who, line_t *where, int script, const char *map, cons return false; } -void P_SuspendScript (int script, char *map) +void P_SuspendScript (int script, const char *map) { - if (strnicmp (level.mapname, map, 8)) + if (strnicmp (level.MapName, map, 8)) addDefered (FindLevelInfo (map), acsdefered_t::defsuspend, script, NULL, 0, NULL); else SetScriptState (script, DLevelScript::SCRIPT_Suspended); } -void P_TerminateScript (int script, char *map) +void P_TerminateScript (int script, const char *map) { - if (strnicmp (level.mapname, map, 8)) + if (strnicmp (level.MapName, map, 8)) addDefered (FindLevelInfo (map), acsdefered_t::defterminate, script, NULL, 0, NULL); else SetScriptState (script, DLevelScript::SCRIPT_PleaseRemove); diff --git a/src/p_conversation.cpp b/src/p_conversation.cpp index e51389ce8..09f2d49d6 100644 --- a/src/p_conversation.cpp +++ b/src/p_conversation.cpp @@ -522,19 +522,8 @@ static void ParseReplies (FStrifeDialogueReply **replyptr, Response *responses) // If the first item check has a positive amount required, then // add that to the reply string. Otherwise, use the reply as-is. - if (rsp->Count[0] > 0) - { - char moneystr[128]; - - mysnprintf (moneystr, countof(moneystr), "%s for %u", rsp->Reply, rsp->Count[0]); - reply->Reply = copystring (moneystr); - reply->NeedsGold = true; - } - else - { - reply->Reply = copystring (rsp->Reply); - reply->NeedsGold = false; - } + reply->Reply = copystring (rsp->Reply); + reply->NeedsGold = (rsp->Count[0] > 0); // QuickYes messages are shown when you meet the item checks. // QuickNo messages are shown when you don't. @@ -666,7 +655,14 @@ static void TakeStrifeItem (player_t *player, const PClass *itemtype, int amount item->Amount -= amount; if (item->Amount <= 0) { - item->Destroy (); + if (item->ItemFlags & IF_KEEPDEPLETED) + { + item->Amount = 0; + } + else + { + item->Destroy (); + } } } } diff --git a/src/p_doors.cpp b/src/p_doors.cpp index b530f688d..7c6952d7f 100644 --- a/src/p_doors.cpp +++ b/src/p_doors.cpp @@ -297,7 +297,7 @@ void DDoor::DoorSound(bool raise, DSeqNode *curseq) const continue; FTexture *tex = TexMan[line->sidedef[0]->GetTexture(side_t::top)]; - texname = tex? tex->Name : NULL; + texname = tex ? tex->Name.GetChars() : NULL; if (texname != NULL && texname[0] == 'D' && texname[1] == 'O' && texname[2] == 'R') { switch (texname[3]) diff --git a/src/p_enemy.cpp b/src/p_enemy.cpp index 359b49f9c..bdc72b0c8 100644 --- a/src/p_enemy.cpp +++ b/src/p_enemy.cpp @@ -1425,6 +1425,9 @@ AActor *LookForEnemiesInBlock (AActor *lookee, int index, void *extparam) if (!(link->flags3 & MF3_ISMONSTER)) continue; // don't target it if it isn't a monster (could be a barrel) + if (link->flags7 & MF7_NEVERTARGET) + continue; + other = NULL; if (link->flags & MF_FRIENDLY) { @@ -1539,7 +1542,6 @@ bool P_LookForEnemies (AActor *actor, INTBOOL allaround, FLookExParams *params) bool P_LookForPlayers (AActor *actor, INTBOOL allaround, FLookExParams *params) { int c; - int stop; int pnum; player_t* player; bool chasegoal = params? (!(params->flags & LOF_DONTCHASEGOAL)) : true; @@ -1612,20 +1614,22 @@ bool P_LookForPlayers (AActor *actor, INTBOOL allaround, FLookExParams *params) { pnum = actor->LastLookPlayerNumber; } - stop = (pnum - 1) & (MAXPLAYERS-1); for (;;) { - pnum = (pnum + 1) & (MAXPLAYERS-1); - if (!playeringame[pnum]) - continue; - - if (actor->TIDtoHate == 0) + // [ED850] Each and every player should only ever be checked once. + if (c++ < MAXPLAYERS) { - actor->LastLookPlayerNumber = pnum; - } + pnum = (pnum + 1) & (MAXPLAYERS - 1); + if (!playeringame[pnum]) + continue; - if (++c == MAXPLAYERS-1 || pnum == stop) + if (actor->TIDtoHate == 0) + { + actor->LastLookPlayerNumber = pnum; + } + } + else { // done looking if (actor->target == NULL) @@ -1689,11 +1693,11 @@ bool P_LookForPlayers (AActor *actor, INTBOOL allaround, FLookExParams *params) && P_AproxDistance (player->mo->velx, player->mo->vely) < 5*FRACUNIT) { // Player is sneaking - can't detect - return false; + continue; } if (pr_lookforplayers() < 225) { // Player isn't sneaking, but still didn't detect - return false; + continue; } } } @@ -2516,149 +2520,126 @@ static bool P_CheckForResurrection(AActor *self, bool usevilestates) fixed_t viletryx = self->x + FixedMul (absSpeed, xspeed[self->movedir]); fixed_t viletryy = self->y + FixedMul (absSpeed, yspeed[self->movedir]); AActor *corpsehit; - FState *raisestate; FBlockThingsIterator it(FBoundingBox(viletryx, viletryy, 32*FRACUNIT)); while ((corpsehit = it.Next())) { - if (!(corpsehit->flags & MF_CORPSE) ) - continue; // not a monster - - if (corpsehit->tics != -1) - continue; // not lying still yet - - raisestate = corpsehit->FindState(NAME_Raise); - if (raisestate == NULL) - continue; // monster doesn't have a raise state - - if (corpsehit->IsKindOf(RUNTIME_CLASS(APlayerPawn))) - continue; // do not resurrect players - - // use the current actor's radius instead of the Arch Vile's default. - fixed_t maxdist = corpsehit->GetDefault()->radius + self->radius; - - maxdist = corpsehit-> GetDefault()->radius + self->radius; - - if ( abs(corpsehit-> x - viletryx) > maxdist || - abs(corpsehit-> y - viletryy) > maxdist ) - continue; // not actually touching -#ifdef _3DFLOORS - // Let's check if there are floors in between the archvile and its target - sector_t *vilesec = self->Sector; - sector_t *corpsec = corpsehit->Sector; - // We only need to test if at least one of the sectors has a 3D floor. - sector_t *testsec = vilesec->e->XFloor.ffloors.Size() ? vilesec : - (vilesec != corpsec && corpsec->e->XFloor.ffloors.Size()) ? corpsec : NULL; - if (testsec) + FState *raisestate = corpsehit->GetRaiseState(); + if (raisestate != NULL) { - fixed_t zdist1, zdist2; - if (P_Find3DFloor(testsec, corpsehit->x, corpsehit->y, corpsehit->z, false, true, zdist1) - != P_Find3DFloor(testsec, self->x, self->y, self->z, false, true, zdist2)) + // use the current actor's radius instead of the Arch Vile's default. + fixed_t maxdist = corpsehit->GetDefault()->radius + self->radius; + + maxdist = corpsehit->GetDefault()->radius + self->radius; + + if (abs(corpsehit->x - viletryx) > maxdist || + abs(corpsehit->y - viletryy) > maxdist) + continue; // not actually touching +#ifdef _3DFLOORS + // Let's check if there are floors in between the archvile and its target + sector_t *vilesec = self->Sector; + sector_t *corpsec = corpsehit->Sector; + // We only need to test if at least one of the sectors has a 3D floor. + sector_t *testsec = vilesec->e->XFloor.ffloors.Size() ? vilesec : + (vilesec != corpsec && corpsec->e->XFloor.ffloors.Size()) ? corpsec : NULL; + if (testsec) { - // Not on same floor - if (vilesec == corpsec || abs(zdist1 - self->z) > self->height) + fixed_t zdist1, zdist2; + if (P_Find3DFloor(testsec, corpsehit->x, corpsehit->y, corpsehit->z, false, true, zdist1) + != P_Find3DFloor(testsec, self->x, self->y, self->z, false, true, zdist2)) + { + // Not on same floor + if (vilesec == corpsec || abs(zdist1 - self->z) > self->height) continue; + } } - } #endif - corpsehit->velx = corpsehit->vely = 0; - // [RH] Check against real height and radius + corpsehit->velx = corpsehit->vely = 0; + // [RH] Check against real height and radius - fixed_t oldheight = corpsehit->height; - fixed_t oldradius = corpsehit->radius; - int oldflags = corpsehit->flags; + fixed_t oldheight = corpsehit->height; + fixed_t oldradius = corpsehit->radius; + int oldflags = corpsehit->flags; - corpsehit->flags |= MF_SOLID; - corpsehit->height = corpsehit->GetDefault()->height; - bool check = P_CheckPosition (corpsehit, corpsehit->x, corpsehit->y); - corpsehit->flags = oldflags; - corpsehit->radius = oldradius; - corpsehit->height = oldheight; - if (!check) continue; + corpsehit->flags |= MF_SOLID; + corpsehit->height = corpsehit->GetDefault()->height; + bool check = P_CheckPosition(corpsehit, corpsehit->x, corpsehit->y); + corpsehit->flags = oldflags; + corpsehit->radius = oldradius; + corpsehit->height = oldheight; + if (!check) continue; - // got one! - temp = self->target; - self->target = corpsehit; - A_FaceTarget (self); - if (self->flags & MF_FRIENDLY) - { - // If this is a friendly Arch-Vile (which is turning the resurrected monster into its friend) - // and the Arch-Vile is currently targetting the resurrected monster the target must be cleared. - if (self->lastenemy == temp) self->lastenemy = NULL; - if (self->lastenemy == corpsehit) self->lastenemy = NULL; - if (temp == self->target) temp = NULL; - } - self->target = temp; - - // Make the state the monster enters customizable. - FState * state = self->FindState(NAME_Heal); - if (state != NULL) - { - self->SetState (state); - } - else if (usevilestates) - { - // For Dehacked compatibility this has to use the Arch Vile's - // heal state as a default if the actor doesn't define one itself. - const PClass *archvile = PClass::FindClass("Archvile"); - if (archvile != NULL) + // got one! + temp = self->target; + self->target = corpsehit; + A_FaceTarget(self); + if (self->flags & MF_FRIENDLY) { - self->SetState (archvile->ActorInfo->FindState(NAME_Heal)); + // If this is a friendly Arch-Vile (which is turning the resurrected monster into its friend) + // and the Arch-Vile is currently targetting the resurrected monster the target must be cleared. + if (self->lastenemy == temp) self->lastenemy = NULL; + if (self->lastenemy == corpsehit) self->lastenemy = NULL; + if (temp == self->target) temp = NULL; } - } - S_Sound (corpsehit, CHAN_BODY, "vile/raise", 1, ATTN_IDLE); - info = corpsehit->GetDefault (); - - if (corpsehit->state == corpsehit->FindState(NAME_GenericCrush)) - { - corpsehit->Translation = info->Translation; // Clean up bloodcolor translation from crushed corpses - } - if (ib_compatflags & BCOMPATF_VILEGHOSTS) - { - corpsehit->height <<= 2; - // [GZ] This was a commented-out feature, so let's make use of it, - // but only for ghost monsters so that they are visibly different. - if (corpsehit->height == 0) + self->target = temp; + + // Make the state the monster enters customizable. + FState * state = self->FindState(NAME_Heal); + if (state != NULL) { - // Make raised corpses look ghostly - if (corpsehit->alpha > TRANSLUC50) + self->SetState(state); + } + else if (usevilestates) + { + // For Dehacked compatibility this has to use the Arch Vile's + // heal state as a default if the actor doesn't define one itself. + const PClass *archvile = PClass::FindClass("Archvile"); + if (archvile != NULL) { - corpsehit->alpha /= 2; - } - // This will only work if the render style is changed as well. - if (corpsehit->RenderStyle == LegacyRenderStyles[STYLE_Normal]) - { - corpsehit->RenderStyle = STYLE_Translucent; + self->SetState(archvile->ActorInfo->FindState(NAME_Heal)); } } - } - else - { - corpsehit->height = info->height; // [RH] Use real mobj height - corpsehit->radius = info->radius; // [RH] Use real radius - } - corpsehit->flags = info->flags; - corpsehit->flags2 = info->flags2; - corpsehit->flags3 = info->flags3; - corpsehit->flags4 = info->flags4; - corpsehit->flags5 = info->flags5; - corpsehit->flags6 = info->flags6; - corpsehit->health = info->health; - corpsehit->target = NULL; - corpsehit->lastenemy = NULL; + S_Sound(corpsehit, CHAN_BODY, "vile/raise", 1, ATTN_IDLE); + info = corpsehit->GetDefault(); - // [RH] If it's a monster, it gets to count as another kill - if (corpsehit->CountsAsKill()) - { - level.total_monsters++; + if (corpsehit->state == corpsehit->FindState(NAME_GenericCrush)) + { + corpsehit->Translation = info->Translation; // Clean up bloodcolor translation from crushed corpses + } + if (ib_compatflags & BCOMPATF_VILEGHOSTS) + { + corpsehit->height <<= 2; + // [GZ] This was a commented-out feature, so let's make use of it, + // but only for ghost monsters so that they are visibly different. + if (corpsehit->height == 0) + { + // Make raised corpses look ghostly + if (corpsehit->alpha > TRANSLUC50) + { + corpsehit->alpha /= 2; + } + // This will only work if the render style is changed as well. + if (corpsehit->RenderStyle == LegacyRenderStyles[STYLE_Normal]) + { + corpsehit->RenderStyle = STYLE_Translucent; + } + } + } + else + { + corpsehit->height = info->height; // [RH] Use real mobj height + corpsehit->radius = info->radius; // [RH] Use real radius + } + + corpsehit->Revive(); + + // You are the Archvile's minion now, so hate what it hates + corpsehit->CopyFriendliness(self, false); + corpsehit->SetState(raisestate); + + return true; } - - // You are the Archvile's minion now, so hate what it hates - corpsehit->CopyFriendliness (self, false); - corpsehit->SetState (raisestate); - - return true; } } return false; @@ -3087,6 +3068,7 @@ AInventory *P_DropItem (AActor *source, const PClass *type, int dropamount, int { AInventory * inv = static_cast(mo); ModifyDropAmount(inv, dropamount); + inv->ItemFlags |= IF_TOSSED; if (inv->SpecialDropAction (source)) { // The special action indicates that the item should not spawn diff --git a/src/p_glnodes.cpp b/src/p_glnodes.cpp index 2665f69ba..899005ffa 100644 --- a/src/p_glnodes.cpp +++ b/src/p_glnodes.cpp @@ -43,17 +43,6 @@ #define rmdir _rmdir -// TODO, maybe: stop using DWORD so I don't need to worry about conflicting -// with Windows' typedef. Then I could just include the header file instead -// of declaring everything here. -#define MAX_PATH 260 -#define CSIDL_LOCAL_APPDATA 0x001c -extern "C" __declspec(dllimport) long __stdcall SHGetFolderPathA(void *hwnd, int csidl, void *hToken, unsigned long dwFlags, char *pszPath); - -#endif - -#ifdef __APPLE__ -#include #endif #include "templates.h" @@ -75,6 +64,7 @@ extern "C" __declspec(dllimport) long __stdcall SHGetFolderPathA(void *hwnd, int #include "x86.h" #include "version.h" #include "md5.h" +#include "m_misc.h" void P_GetPolySpots (MapData * lump, TArray &spots, TArray &anchors); @@ -734,9 +724,10 @@ static bool DoLoadGLNodes(FileReader ** lumps) static bool MatchHeader(const char * label, const char * hdata) { - if (!memcmp(hdata, "LEVEL=", 6) == 0) + if (memcmp(hdata, "LEVEL=", 6) == 0) { size_t labellen = strlen(label); + labellen = MIN(size_t(8), labellen); if (strnicmp(hdata+6, label, labellen)==0 && (hdata[6+labellen]==0xa || hdata[6+labellen]==0xd)) @@ -781,7 +772,7 @@ static int FindGLNodesInWAD(int labellump) if (Wads.GetLumpFile(lump)==wadfile) { FMemLump mem = Wads.ReadLump(lump); - if (MatchHeader(Wads.GetLumpFullName(labellump), (const char *)mem.GetMem())) return true; + if (MatchHeader(Wads.GetLumpFullName(labellump), (const char *)mem.GetMem())) return lump; } } } @@ -791,7 +782,7 @@ static int FindGLNodesInWAD(int labellump) //=========================================================================== // -// FindGLNodesInWAD +// FindGLNodesInFile // // Looks for GL nodes in the same WAD as the level itself // Function returns the lump number within the file. Returns -1 if the input @@ -939,13 +930,13 @@ bool P_LoadGLNodes(MapData * map) result=true; for(unsigned i=0; i<4;i++) { - if (strnicmp(f_gwa->GetLump(i)->Name, check[i], 8)) + if (strnicmp(f_gwa->GetLump(i+1)->Name, check[i], 8)) { result=false; break; } else - gwalumps[i] = f_gwa->GetLump(i)->NewReader(); + gwalumps[i] = f_gwa->GetLump(i+1)->NewReader(); } if (result) result = DoLoadGLNodes(gwalumps); } @@ -968,6 +959,7 @@ bool P_LoadGLNodes(MapData * map) bool P_CheckNodes(MapData * map, bool rebuilt, int buildtime) { bool ret = false; + bool loaded = false; // If the map loading code has performed a node rebuild we don't need to check for it again. if (!rebuilt && !P_CheckForGLNodes()) @@ -987,7 +979,8 @@ bool P_CheckNodes(MapData * map, bool rebuilt, int buildtime) numsegs = 0; // Try to load GL nodes (cached or GWA) - if (!P_LoadGLNodes(map)) + loaded = P_LoadGLNodes(map); + if (!loaded) { // none found - we have to build new ones! unsigned int startTime, endTime; @@ -1015,20 +1008,22 @@ bool P_CheckNodes(MapData * map, bool rebuilt, int buildtime) } } + if (!loaded) + { #ifdef DEBUG - // Building nodes in debug is much slower so let's cache them only if cachetime is 0 - buildtime = 0; + // Building nodes in debug is much slower so let's cache them only if cachetime is 0 + buildtime = 0; #endif - if (gl_cachenodes && buildtime/1000.f >= gl_cachetime) - { - DPrintf("Caching nodes\n"); - CreateCachedNodes(map); + if (gl_cachenodes && buildtime/1000.f >= gl_cachetime) + { + DPrintf("Caching nodes\n"); + CreateCachedNodes(map); + } + else + { + DPrintf("Not caching nodes (time = %f)\n", buildtime/1000.f); + } } - else - { - DPrintf("Not caching nodes (time = %f)\n", buildtime/1000.f); - } - if (!gamenodes) { @@ -1048,45 +1043,10 @@ bool P_CheckNodes(MapData * map, bool rebuilt, int buildtime) typedef TArray MemFile; -static FString GetCachePath() -{ - FString path; - -#ifdef _WIN32 - char pathstr[MAX_PATH]; - if (0 != SHGetFolderPathA(NULL, CSIDL_LOCAL_APPDATA, NULL, 0, pathstr)) - { // Failed (e.g. On Win9x): use program directory - path = progdir; - } - else - { - path = pathstr; - } - path += "/zdoom/cache"; -#elif defined(__APPLE__) - char pathstr[PATH_MAX]; - FSRef folder; - - if (noErr == FSFindFolder(kLocalDomain, kApplicationSupportFolderType, kCreateFolder, &folder) && - noErr == FSRefMakePath(&folder, (UInt8*)pathstr, PATH_MAX)) - { - path = pathstr; - } - else - { - path = progdir; - } - path += "/zdoom/cache"; -#else - // Don't use GAME_DIR and such so that ZDoom and its child ports can share the node cache. - path = NicePath("~/.config/zdoom/cache"); -#endif - return path; -} static FString CreateCacheName(MapData *map, bool create) { - FString path = GetCachePath(); + FString path = M_GetCachePath(create); FString lumpname = Wads.GetLumpFullPath(map->lumpnum); int separator = lumpname.IndexOf(':'); path << '/' << lumpname.Left(separator); @@ -1212,8 +1172,21 @@ static void CreateCachedNodes(MapData *map) FString path = CreateCacheName(map, true); FILE *f = fopen(path, "wb"); - fwrite(compressed, 1, outlen+offset, f); - fclose(f); + + if (f != NULL) + { + if (fwrite(compressed, outlen+offset, 1, f) != 1) + { + Printf("Error saving nodes to file %s\n", path.GetChars()); + } + + fclose(f); + } + else + { + Printf("Cannot open nodes file %s for writing\n", path.GetChars()); + } + delete [] compressed; } @@ -1299,7 +1272,7 @@ errorout: CCMD(clearnodecache) { TArray list; - FString path = GetCachePath(); + FString path = M_GetCachePath(false); path += "/"; try diff --git a/src/p_interaction.cpp b/src/p_interaction.cpp index 0ee955a82..0eae78632 100644 --- a/src/p_interaction.cpp +++ b/src/p_interaction.cpp @@ -320,6 +320,10 @@ void ClientObituary (AActor *self, AActor *inflictor, AActor *attacker, int dmgf message = GStrings("OB_DEFAULT"); } + // [CK] Don't display empty strings + if (message == NULL || strlen(message) <= 0) + return; + SexMessage (message, gendermessage, gender, self->player->userinfo.GetName(), attacker->player->userinfo.GetName()); Printf (PRINT_MEDIUM, "%s\n", gendermessage); @@ -364,8 +368,6 @@ void AActor::Die (AActor *source, AActor *inflictor, int dmgflags) { static int dieticks[MAXPLAYERS]; int pnum = int(this->player-players); - if (dieticks[pnum] == gametic) - gametic=gametic; dieticks[pnum] = gametic; fprintf (debugfile, "died (%d) on tic %d (%s)\n", pnum, gametic, this->player->cheats&CF_PREDICTING?"predicting":"real"); @@ -1508,6 +1510,9 @@ bool AActor::OkayToSwitchTarget (AActor *other) if (other == this) return false; // [RH] Don't hate self (can happen when shooting barrels) + if (other->flags7 & MF7_NEVERTARGET) + return false; // never EVER target me! + if (!(other->flags & MF_SHOOTABLE)) return false; // Don't attack things that can't be hurt diff --git a/src/p_lnspec.cpp b/src/p_lnspec.cpp index 12c877116..7cb5ca7e6 100644 --- a/src/p_lnspec.cpp +++ b/src/p_lnspec.cpp @@ -863,7 +863,7 @@ FUNC(LS_Teleport_NewMap) if (info && CheckIfExitIsGood (it, info)) { - G_ChangeLevel(info->mapname, arg1, arg2 ? CHANGELEVEL_KEEPFACING : 0); + G_ChangeLevel(info->MapName, arg1, arg2 ? CHANGELEVEL_KEEPFACING : 0); return true; } } @@ -1644,11 +1644,11 @@ FUNC(LS_ACS_Execute) if (arg1 == 0) { - mapname = level.mapname; + mapname = level.MapName; } else if ((info = FindLevelByNum(arg1)) != NULL) { - mapname = info->mapname; + mapname = info->MapName; } else { @@ -1667,11 +1667,11 @@ FUNC(LS_ACS_ExecuteAlways) if (arg1 == 0) { - mapname = level.mapname; + mapname = level.MapName; } else if ((info = FindLevelByNum(arg1)) != NULL) { - mapname = info->mapname; + mapname = info->MapName; } else { @@ -1707,7 +1707,7 @@ FUNC(LS_ACS_ExecuteWithResult) int args[4] = { arg1, arg2, arg3, arg4 }; int flags = (backSide ? ACS_BACKSIDE : 0) | ACS_ALWAYS | ACS_WANTRESULT; - return P_StartScript (it, ln, arg0, level.mapname, args, 4, flags); + return P_StartScript (it, ln, arg0, level.MapName, args, 4, flags); } FUNC(LS_ACS_Suspend) @@ -1716,9 +1716,9 @@ FUNC(LS_ACS_Suspend) level_info_t *info; if (arg1 == 0) - P_SuspendScript (arg0, level.mapname); + P_SuspendScript (arg0, level.MapName); else if ((info = FindLevelByNum (arg1)) ) - P_SuspendScript (arg0, info->mapname); + P_SuspendScript (arg0, info->MapName); return true; } @@ -1729,9 +1729,9 @@ FUNC(LS_ACS_Terminate) level_info_t *info; if (arg1 == 0) - P_TerminateScript (arg0, level.mapname); + P_TerminateScript (arg0, level.MapName); else if ((info = FindLevelByNum (arg1)) ) - P_TerminateScript (arg0, info->mapname); + P_TerminateScript (arg0, info->MapName); return true; } diff --git a/src/p_map.cpp b/src/p_map.cpp index 8b0b605c6..45eb0d95c 100644 --- a/src/p_map.cpp +++ b/src/p_map.cpp @@ -329,8 +329,7 @@ bool P_TeleportMove (AActor *thing, fixed_t x, fixed_t y, fixed_t z, bool telefr spechit.Clear (); - bool StompAlwaysFrags = (thing->flags2 & MF2_TELESTOMP) || - (level.flags & LEVEL_MONSTERSTELEFRAG) || telefrag; + bool StompAlwaysFrags = ((thing->flags2 & MF2_TELESTOMP) || (level.flags & LEVEL_MONSTERSTELEFRAG) || telefrag) && !(thing->flags7 & MF7_NOTELESTOMP); FBoundingBox box(x, y, thing->radius); FBlockLinesIterator it(box); @@ -378,7 +377,8 @@ bool P_TeleportMove (AActor *thing, fixed_t x, fixed_t y, fixed_t z, bool telefr // monsters don't stomp things except on boss level // [RH] Some Heretic/Hexen monsters can telestomp - if (StompAlwaysFrags && !(th->flags6 & MF6_NOTELEFRAG)) + // ... and some items can never be telefragged while others will be telefragged by everything that teleports upon them. + if ((StompAlwaysFrags && !(th->flags6 & MF6_NOTELEFRAG)) || (th->flags7 & MF7_ALWAYSTELEFRAG)) { P_DamageMobj (th, thing, thing, TELEFRAG_DAMAGE, NAME_Telefrag, DMG_THRUSTLESS); continue; @@ -914,34 +914,34 @@ bool PIT_CheckThing (AActor *thing, FCheckPosition &tm) } } - // touchy object is alive, toucher is solid - if (thing->flags6 & MF6_TOUCHY && tm.thing->flags & MF_SOLID && thing->health > 0 && - // Thing is an armed mine or a sentient thing - (thing->flags6 & MF6_ARMED || thing->IsSentient()) && - // either different classes or players - (thing->player || thing->GetClass() != tm.thing->GetClass()) && - // or different species if DONTHARMSPECIES - (!(thing->flags6 & MF6_DONTHARMSPECIES) || thing->GetSpecies() != tm.thing->GetSpecies()) && - // touches vertically - thing->z + thing->height >= tm.thing->z && tm.thing->z + tm.thing->height >= thing->z && - // prevents lost souls from exploding when fired by pain elementals - (thing->master != tm.thing && tm.thing->master != thing)) - // Difference with MBF: MBF hardcodes the LS/PE check and lets actors of the same species - // but different classes trigger the touchiness, but that seems less straightforwards. + if (tm.thing->player == NULL || !(tm.thing->player->cheats & CF_PREDICTING)) { - thing->flags6 &= ~MF6_ARMED; // Disarm - P_DamageMobj (thing, NULL, NULL, thing->health, NAME_None, DMG_FORCED); // kill object - return true; - } + // touchy object is alive, toucher is solid + if (thing->flags6 & MF6_TOUCHY && tm.thing->flags & MF_SOLID && thing->health > 0 && + // Thing is an armed mine or a sentient thing + (thing->flags6 & MF6_ARMED || thing->IsSentient()) && + // either different classes or players + (thing->player || thing->GetClass() != tm.thing->GetClass()) && + // or different species if DONTHARMSPECIES + (!(thing->flags6 & MF6_DONTHARMSPECIES) || thing->GetSpecies() != tm.thing->GetSpecies()) && + // touches vertically + thing->z + thing->height >= tm.thing->z && tm.thing->z + tm.thing->height >= thing->z && + // prevents lost souls from exploding when fired by pain elementals + (thing->master != tm.thing && tm.thing->master != thing)) + // Difference with MBF: MBF hardcodes the LS/PE check and lets actors of the same species + // but different classes trigger the touchiness, but that seems less straightforwards. + { + thing->flags6 &= ~MF6_ARMED; // Disarm + P_DamageMobj(thing, NULL, NULL, thing->health, NAME_None, DMG_FORCED); // kill object + return true; + } - // Check for MF6_BUMPSPECIAL - // By default, only players can activate things by bumping into them - if ((thing->flags6 & MF6_BUMPSPECIAL) && ((tm.thing->player != NULL) - || ((thing->activationtype & THINGSPEC_MonsterTrigger) && (tm.thing->flags3 & MF3_ISMONSTER)) - || ((thing->activationtype & THINGSPEC_MissileTrigger) && (tm.thing->flags & MF_MISSILE)) - ) && (level.maptime > thing->lastbump)) // Leave the bumper enough time to go away - { - if (tm.thing->player == NULL || !(tm.thing->player->cheats & CF_PREDICTING)) + // Check for MF6_BUMPSPECIAL + // By default, only players can activate things by bumping into them + if ((thing->flags6 & MF6_BUMPSPECIAL) && ((tm.thing->player != NULL) + || ((thing->activationtype & THINGSPEC_MonsterTrigger) && (tm.thing->flags3 & MF3_ISMONSTER)) + || ((thing->activationtype & THINGSPEC_MissileTrigger) && (tm.thing->flags & MF_MISSILE)) + ) && (level.maptime > thing->lastbump)) // Leave the bumper enough time to go away { if (P_ActivateThingSpecial(thing, tm.thing)) thing->lastbump = level.maptime + TICRATE; @@ -955,6 +955,17 @@ bool PIT_CheckThing (AActor *thing, FCheckPosition &tm) tm.thing->BlockingMobj = NULL; return res; } + + // [ED850] Player Prediction ends here. There is nothing else they could/should do. + if (tm.thing->player != NULL && (tm.thing->player->cheats & CF_PREDICTING)) + { + solid = (thing->flags & MF_SOLID) && + !(thing->flags & MF_NOCLIP) && + ((tm.thing->flags & MF_SOLID) || (tm.thing->flags6 & MF6_BLOCKEDBYSOLIDACTORS)); + + return !solid || unblocking; + } + // Check for blasted thing running into another if ((tm.thing->flags2 & MF2_BLASTED) && (thing->flags & MF_SHOOTABLE)) { @@ -1203,8 +1214,7 @@ bool PIT_CheckThing (AActor *thing, FCheckPosition &tm) } return false; // don't traverse any more } - if (thing->flags2 & MF2_PUSHABLE && !(tm.thing->flags2 & MF2_CANNOTPUSH) && - (tm.thing->player == NULL || !(tm.thing->player->cheats & CF_PREDICTING))) + if (thing->flags2 & MF2_PUSHABLE && !(tm.thing->flags2 & MF2_CANNOTPUSH)) { // Push thing if (thing->lastpush != tm.PushTime) { @@ -1640,7 +1650,7 @@ static void CheckForPushSpecial (line_t *line, int side, AActor *mobj, bool wind { if (line->special && !(mobj->flags6 & MF6_NOTRIGGER)) { - if (windowcheck && line->backsector != NULL) + if (windowcheck && !(ib_compatflags & BCOMPATF_NOWINDOWCHECK) && line->backsector != NULL) { // Make sure this line actually blocks us and is not a window // or similar construct we are standing inside of. fixed_t fzt = line->frontsector->ceilingplane.ZatPoint(mobj->x, mobj->y); @@ -4879,7 +4889,8 @@ void P_DoCrunch (AActor *thing, FChangePosition *cpos) const PClass *bloodcls = thing->GetBloodType(); P_TraceBleed (newdam > 0 ? newdam : cpos->crushchange, thing); - if (cl_bloodtype <= 1 && bloodcls != NULL) + + if (bloodcls != NULL) { AActor *mo; @@ -4892,14 +4903,15 @@ void P_DoCrunch (AActor *thing, FChangePosition *cpos) { mo->Translation = TRANSLATION(TRANSLATION_Blood, bloodcolor.a); } + + if (!(cl_bloodtype <= 1)) mo->renderflags |= RF_INVISIBLE; } + + angle_t an; + an = (M_Random () - 128) << 24; if (cl_bloodtype >= 1) { - angle_t an; - - an = (M_Random () - 128) << 24; - P_DrawSplash2 (32, thing->x, thing->y, - thing->z + thing->height/2, an, 2, bloodcolor); + P_DrawSplash2(32, thing->x, thing->y, thing->z + thing->height / 2, an, 2, bloodcolor); } } if (thing->CrushPainSound != 0 && !S_GetSoundPlayingInfo(thing, thing->CrushPainSound)) @@ -5042,6 +5054,15 @@ void PIT_FloorDrop (AActor *thing, FChangePosition *cpos) P_CheckFakeFloorTriggers (thing, oldz); } } + else if ((thing->z != oldfloorz && !(thing->flags & MF_NOLIFTDROP))) + { + fixed_t oldz = thing->z; + if ((thing->flags & MF_NOGRAVITY) && (thing->flags6 & MF6_RELATIVETOFLOOR)) + { + thing->z = thing->z - oldfloorz + thing->floorz; + P_CheckFakeFloorTriggers (thing, oldz); + } + } } //============================================================================= @@ -5053,6 +5074,7 @@ void PIT_FloorDrop (AActor *thing, FChangePosition *cpos) void PIT_FloorRaise (AActor *thing, FChangePosition *cpos) { fixed_t oldfloorz = thing->floorz; + fixed_t oldz = thing->z; P_AdjustFloorCeil (thing, cpos); @@ -5067,22 +5089,30 @@ void PIT_FloorRaise (AActor *thing, FChangePosition *cpos) return; // do not move bridge things } intersectors.Clear (); - fixed_t oldz = thing->z; thing->z = thing->floorz; - switch (P_PushUp (thing, cpos)) + } + else + { + if((thing->flags & MF_NOGRAVITY) && (thing->flags6 & MF6_RELATIVETOFLOOR)) { - default: - P_CheckFakeFloorTriggers (thing, oldz); - break; - case 1: - P_DoCrunch (thing, cpos); - P_CheckFakeFloorTriggers (thing, oldz); - break; - case 2: - P_DoCrunch (thing, cpos); - thing->z = oldz; - break; + intersectors.Clear (); + thing->z = thing->z - oldfloorz + thing->floorz; } + else return; + } + switch (P_PushUp (thing, cpos)) + { + default: + P_CheckFakeFloorTriggers (thing, oldz); + break; + case 1: + P_DoCrunch (thing, cpos); + P_CheckFakeFloorTriggers (thing, oldz); + break; + case 2: + P_DoCrunch (thing, cpos); + thing->z = oldz; + break; } } diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index 03bbb4d8d..72679ef71 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -1,4 +1,5 @@ // Emacs style mode select -*- C++ -*- +// Emacs style mode select -*- C++ -*- //----------------------------------------------------------------------------- // // $Id:$ @@ -200,8 +201,12 @@ void AActor::Serialize (FArchive &arc) << flags3 << flags4 << flags5 - << flags6 - << special1 + << flags6; + if (SaveVersion >= 4504) + { + arc << flags7; + } + arc << special1 << special2 << health << movedir @@ -215,8 +220,12 @@ void AActor::Serialize (FArchive &arc) << threshold << player << SpawnPoint[0] << SpawnPoint[1] << SpawnPoint[2] - << SpawnAngle - << skillrespawncount + << SpawnAngle; + if (SaveVersion >= 4506) + { + arc << StartHealth; + } + arc << skillrespawncount << tracer << floorclip << tid @@ -397,7 +406,7 @@ bool AActor::InStateSequence(FState * newstate, FState * basestate) // // Get the actual duration of the next state // We are using a state flag now to indicate a state that should be -// accelerated in Fast mode. +// accelerated in Fast mode or slowed in Slow mode. // //========================================================================== @@ -408,6 +417,10 @@ int AActor::GetTics(FState * newstate) { return tics - (tics>>1); } + else if (isSlow() && newstate->Slow) + { + return tics<<1; + } return tics; } @@ -826,7 +839,7 @@ void AActor::CopyFriendliness (AActor *other, bool changeTarget, bool resetHealt flags4 = (flags4 & ~(MF4_NOHATEPLAYERS | MF4_BOSSSPAWNED)) | (other->flags4 & (MF4_NOHATEPLAYERS | MF4_BOSSSPAWNED)); FriendPlayer = other->FriendPlayer; DesignatedTeam = other->DesignatedTeam; - if (changeTarget && other->target != NULL && !(other->target->flags3 & MF3_NOTARGET)) + if (changeTarget && other->target != NULL && !(other->target->flags3 & MF3_NOTARGET) && !(other->target->flags7 & MF7_NEVERTARGET)) { // LastHeard must be set as well so that A_Look can react to the new target if called LastHeard = target = other->target; @@ -997,6 +1010,16 @@ bool AActor::Grind(bool items) if ((flags & MF_CORPSE) && !(flags3 & MF3_DONTGIB) && (health <= 0)) { FState * state = FindState(NAME_Crush); + + // In Heretic and Chex Quest we don't change the actor's sprite, just its size. + if (state == NULL && gameinfo.dontcrunchcorpses) + { + flags &= ~MF_SOLID; + flags3 |= MF3_DONTGIB; + height = radius = 0; + return false; + } + bool isgeneric = false; // ZDoom behavior differs from standard as crushed corpses cannot be raised. // The reason for the change was originally because of a problem with players, @@ -2134,7 +2157,7 @@ void P_ZMovement (AActor *mo, fixed_t oldfloorz) fixed_t oldz = mo->z; fixed_t grav = mo->GetGravity(); -// +// // check for smooth step up // if (mo->player && mo->player->mo == mo && mo->z < mo->floorz) @@ -2722,11 +2745,14 @@ int P_FindUniqueTID(int start_tid, int limit) if (start_tid != 0) { // Do a linear search. - limit = start_tid + limit - 1; - if (limit < start_tid) - { // If it overflowed, clamp to INT_MAX + if (start_tid > INT_MAX-limit+1) + { // If 'limit+start_tid-1' overflows, clamp 'limit' to INT_MAX limit = INT_MAX; } + else + { + limit += start_tid-1; + } for (tid = start_tid; tid <= limit; ++tid) { if (tid != 0 && !P_IsTIDUsed(tid)) @@ -2765,7 +2791,7 @@ CCMD(utid) { Printf("%d\n", P_FindUniqueTID(argv.argc() > 1 ? atoi(argv[1]) : 0, - argv.argc() > 2 ? atoi(argv[2]) : 0)); + (argv.argc() > 2 && atoi(argv[2]) >= 0) ? atoi(argv[2]) : 0)); } //========================================================================== @@ -2929,7 +2955,7 @@ bool AActor::IsOkayToAttack (AActor *link) if (P_CheckSight (this, link)) { // AMageStaffFX2::IsOkayToAttack had an extra check here, generalized with a flag, - // to only allow the check to succeed if the enemy was in a ~84° FOV of the player + // to only allow the check to succeed if the enemy was in a ~84� FOV of the player if (flags3 & MF3_SCREENSEEKER) { angle_t angle = R_PointToAngle2(Friend->x, @@ -2958,6 +2984,30 @@ void AActor::SetShade (int r, int g, int b) fillcolor = MAKEARGB(ColorMatcher.Pick (r, g, b), r, g, b); } +void AActor::SetPitch(int p, bool interpolate) +{ + if (p != pitch) + { + pitch = p; + if (player != NULL && interpolate) + { + player->cheats |= CF_INTERPVIEW; + } + } +} + +void AActor::SetAngle(angle_t ang, bool interpolate) +{ + if (ang != angle) + { + angle = ang; + if (player != NULL && interpolate) + { + player->cheats |= CF_INTERPVIEW; + } + } +} + // // P_MobjThinker // @@ -3521,19 +3571,23 @@ void AActor::Tick () Destroy(); return; } - if (ObjectFlags & OF_JustSpawned && state->GetNoDelay()) + if ((flags7 & MF7_HANDLENODELAY) && !(flags2 & MF2_DORMANT)) { - // For immediately spawned objects with the NoDelay flag set for their - // Spawn state, explicitly set the current state so that it calls its - // action and chains 0-tic states. - int starttics = tics; - if (!SetState(state)) - return; // freed itself - // If the initial state had a duration of 0 tics, let the next state run - // normally. Otherwise, increment tics by 1 so that we don't double up ticks. - if (starttics > 0 && tics >= 0) + flags7 &= ~MF7_HANDLENODELAY; + if (state->GetNoDelay()) { - tics++; + // For immediately spawned objects with the NoDelay flag set for their + // Spawn state, explicitly set the current state so that it calls its + // action and chains 0-tic states. + int starttics = tics; + if (!SetState(state)) + return; // freed itself + // If the initial state had a duration of 0 tics, let the next state run + // normally. Otherwise, increment tics by 1 so that we don't double up ticks. + else if (starttics > 0 && tics >= 0) + { + tics++; + } } } // cycle through states, calling action functions at transitions @@ -4020,6 +4074,7 @@ void AActor::PostBeginPlay () Renderer->StateChanged(this); } PrevAngle = angle; + flags7 |= MF7_HANDLENODELAY; } void AActor::MarkPrecacheSounds() const @@ -4042,6 +4097,11 @@ bool AActor::isFast() return !!G_SkillProperty(SKILLP_FastMonsters); } +bool AActor::isSlow() +{ + return !!G_SkillProperty(SKILLP_SlowMonsters); +} + void AActor::Activate (AActor *activator) { if ((flags3 & MF3_ISMONSTER) && (health > 0 || (flags & MF_ICECORPSE))) @@ -4639,6 +4699,12 @@ AActor *P_SpawnMapThing (FMapThing *mthing, int position) if (defaults->SpawnState == NULL || sprites[defaults->SpawnState->sprite].numframes == 0) { + // We don't load mods for shareware games so we'll just ignore + // missing actors. Heretic needs this since the shareware includes + // the retail weapons in Deathmatch. + if (gameinfo.flags & GI_SHAREWARE) + return NULL; + Printf ("%s at (%i, %i) has no frames\n", i->TypeName.GetChars(), mthing->x>>FRACBITS, mthing->y>>FRACBITS); i = PClass::FindClass("Unknown"); @@ -4747,11 +4813,39 @@ AActor *P_SpawnMapThing (FMapThing *mthing, int position) } } + // Set various UDMF options + if (mthing->alpha != -1) + mobj->alpha = mthing->alpha; + if (mthing->RenderStyle != STYLE_Count) + mobj->RenderStyle = (ERenderStyle)mthing->RenderStyle; + if (mthing->scaleX) + mobj->scaleX = FixedMul(mthing->scaleX, mobj->scaleX); + if (mthing->scaleY) + mobj->scaleY = FixedMul(mthing->scaleY, mobj->scaleY); + if (mthing->pitch) + mobj->pitch = ANGLE_1 * mthing->pitch; + if (mthing->roll) + mobj->roll = ANGLE_1 * mthing->roll; + if (mthing->score) + mobj->Score = mthing->score; + if (mthing->fillcolor) + mobj->fillcolor = mthing->fillcolor; + mobj->BeginPlay (); if (!(mobj->ObjectFlags & OF_EuthanizeMe)) { mobj->LevelSpawned (); } + + if (mthing->health > 0) + mobj->health *= mthing->health; + else + mobj->health = -mthing->health; + if (mthing->health == 0) + mobj->Die(NULL, NULL); + else if (mthing->health != 1) + mobj->StartHealth = mobj->health; + return mobj; } @@ -4841,7 +4935,7 @@ void P_SpawnBlood (fixed_t x, fixed_t y, fixed_t z, angle_t dir, int damage, AAc if (bloodcls != NULL && !(GetDefaultByType(bloodcls)->flags4 & MF4_ALLOWPARTICLES)) bloodtype = 0; - if (bloodcls!=NULL && bloodtype <= 1) + if (bloodcls != NULL) { z += pr_spawnblood.Random2 () << 10; th = Spawn (bloodcls, x, y, z, NO_REPLACE); // GetBloodType already performed the replacement @@ -4912,7 +5006,7 @@ void P_SpawnBlood (fixed_t x, fixed_t y, fixed_t z, angle_t dir, int damage, AAc } statedone: - + if (!(bloodtype <= 1)) th->renderflags |= RF_INVISIBLE; if (bloodtype >= 1) P_DrawSplash2 (40, x, y, z, dir, 2, bloodcolor); } @@ -4933,7 +5027,7 @@ void P_BloodSplatter (fixed_t x, fixed_t y, fixed_t z, AActor *originator) if (bloodcls != NULL && !(GetDefaultByType(bloodcls)->flags4 & MF4_ALLOWPARTICLES)) bloodtype = 0; - if (bloodcls!=NULL && bloodtype <= 1) + if (bloodcls != NULL) { AActor *mo; @@ -4948,6 +5042,8 @@ void P_BloodSplatter (fixed_t x, fixed_t y, fixed_t z, AActor *originator) { mo->Translation = TRANSLATION(TRANSLATION_Blood, bloodcolor.a); } + + if (!(bloodtype <= 1)) mo->renderflags |= RF_INVISIBLE; } if (bloodtype >= 1) { @@ -4971,7 +5067,7 @@ void P_BloodSplatter2 (fixed_t x, fixed_t y, fixed_t z, AActor *originator) if (bloodcls != NULL && !(GetDefaultByType(bloodcls)->flags4 & MF4_ALLOWPARTICLES)) bloodtype = 0; - if (bloodcls!=NULL && bloodtype <= 1) + if (bloodcls != NULL) { AActor *mo; @@ -4986,6 +5082,8 @@ void P_BloodSplatter2 (fixed_t x, fixed_t y, fixed_t z, AActor *originator) { mo->Translation = TRANSLATION(TRANSLATION_Blood, bloodcolor.a); } + + if (!(bloodtype <= 1)) mo->renderflags |= RF_INVISIBLE; } if (bloodtype >= 1) { @@ -5014,7 +5112,7 @@ void P_RipperBlood (AActor *mo, AActor *bleeder) if (bloodcls != NULL && !(GetDefaultByType(bloodcls)->flags4 & MF4_ALLOWPARTICLES)) bloodtype = 0; - if (bloodcls!=NULL && bloodtype <= 1) + if (bloodcls != NULL) { AActor *th; th = Spawn (bloodcls, x, y, z, NO_REPLACE); // GetBloodType already performed the replacement @@ -5031,6 +5129,8 @@ void P_RipperBlood (AActor *mo, AActor *bleeder) { th->Translation = TRANSLATION(TRANSLATION_Blood, bloodcolor.a); } + + if (!(bloodtype <= 1)) th->renderflags |= RF_INVISIBLE; } if (bloodtype >= 1) { @@ -5120,7 +5220,7 @@ bool P_HitWater (AActor * thing, sector_t * sec, fixed_t x, fixed_t y, fixed_t z } } planez = rover->bottom.plane->ZatPoint(x, y); - if (planez < z) return false; + if (planez < z && !(planez < thing->floorz)) return false; } #endif hsec = sec->GetHeightSec(); @@ -5968,22 +6068,66 @@ void AActor::SetIdle() int AActor::SpawnHealth() { - if (!(flags3 & MF3_ISMONSTER) || GetDefault()->health == 0) + int defhealth = StartHealth ? StartHealth : GetDefault()->health; + if (!(flags3 & MF3_ISMONSTER) || defhealth == 0) { - return GetDefault()->health; + return defhealth; } else if (flags & MF_FRIENDLY) { - int adj = FixedMul(GetDefault()->health, G_SkillProperty(SKILLP_FriendlyHealth)); + int adj = FixedMul(defhealth, G_SkillProperty(SKILLP_FriendlyHealth)); return (adj <= 0) ? 1 : adj; } else { - int adj = FixedMul(GetDefault()->health, G_SkillProperty(SKILLP_MonsterHealth)); + int adj = FixedMul(defhealth, G_SkillProperty(SKILLP_MonsterHealth)); return (adj <= 0) ? 1 : adj; } } +FState *AActor::GetRaiseState() +{ + if (!(flags & MF_CORPSE)) + { + return NULL; // not a monster + } + + if (tics != -1 && // not lying still yet + !state->GetCanRaise()) // or not ready to be raised yet + { + return NULL; + } + + if (IsKindOf(RUNTIME_CLASS(APlayerPawn))) + { + return NULL; // do not resurrect players + } + + return FindState(NAME_Raise); +} + +void AActor::Revive() +{ + AActor *info = GetDefault(); + flags = info->flags; + flags2 = info->flags2; + flags3 = info->flags3; + flags4 = info->flags4; + flags5 = info->flags5; + flags6 = info->flags6; + flags7 = info->flags7; + DamageType = info->DamageType; + health = SpawnHealth(); + target = NULL; + lastenemy = NULL; + + // [RH] If it's a monster, it gets to count as another kill + if (CountsAsKill()) + { + level.total_monsters++; + } +} + FDropItem *AActor::GetDropItems() { unsigned int index = GetClass()->Meta.GetMetaInt (ACMETA_DropItems) - 1; @@ -6119,24 +6263,27 @@ void PrintMiscActorInfo(AActor *query) static const char * renderstyles[]= {"None", "Normal", "Fuzzy", "SoulTrans", "OptFuzzy", "Stencil", "Translucent", "Add", "Shaded", "TranslucentStencil"}; - Printf("%s @ %p has the following flags:\n\tflags: %x", query->GetTag(), query, query->flags); + Printf("%s @ %p has the following flags:\n flags: %x", query->GetTag(), query, query->flags); for (flagi = 0; flagi <= 31; flagi++) if (query->flags & 1<flags2); + Printf("\n flags2: %x", query->flags2); for (flagi = 0; flagi <= 31; flagi++) if (query->flags2 & 1<flags3); + Printf("\n flags3: %x", query->flags3); for (flagi = 0; flagi <= 31; flagi++) if (query->flags3 & 1<flags4); + Printf("\n flags4: %x", query->flags4); for (flagi = 0; flagi <= 31; flagi++) if (query->flags4 & 1<flags5); + Printf("\n flags5: %x", query->flags5); for (flagi = 0; flagi <= 31; flagi++) if (query->flags5 & 1<flags6); + Printf("\n flags6: %x", query->flags6); for (flagi = 0; flagi <= 31; flagi++) if (query->flags6 & 1<flags7); + for (flagi = 0; flagi <= 31; flagi++) + if (query->flags7 & 1<BounceFlags, FIXED2FLOAT(query->bouncefactor), FIXED2FLOAT(query->wallbouncefactor)); diff --git a/src/p_pspr.cpp b/src/p_pspr.cpp index 85830ac55..49f8bcb84 100644 --- a/src/p_pspr.cpp +++ b/src/p_pspr.cpp @@ -208,6 +208,9 @@ void P_BringUpWeapon (player_t *player) player->psprites[ps_weapon].sy = player->cheats & CF_INSTANTWEAPSWITCH ? WEAPONTOP : WEAPONBOTTOM; P_SetPsprite (player, ps_weapon, newstate); + // make sure that the previous weapon's flash state is terminated. + // When coming here from a weapon drop it may still be active. + P_SetPsprite(player, ps_flash, NULL); } diff --git a/src/p_sectors.cpp b/src/p_sectors.cpp index d90466fec..699350839 100644 --- a/src/p_sectors.cpp +++ b/src/p_sectors.cpp @@ -230,8 +230,6 @@ fixed_t sector_t::FindNextLowestFloor (vertex_t **v) const check = lines[i]; if (NULL != (other = getNextSector (check, this))) { - if (other - sectors == 6) - other = other; ofloor = other->floorplane.ZatPoint (check->v1); floor = floorplane.ZatPoint (check->v1); if (ofloor < floor && floor - ofloor < heightdiff && !IsLinked(other, false)) diff --git a/src/p_setup.cpp b/src/p_setup.cpp index 3693e9f7e..a6462f31c 100644 --- a/src/p_setup.cpp +++ b/src/p_setup.cpp @@ -272,11 +272,12 @@ MapData *P_OpenMapData(const char * mapname, bool justcheck) FString fmt; int lump_wad; int lump_map; - int lump_name; + int lump_name = -1; // Check for both *.wad and *.map in order to load Build maps // as well. The higher one will take precedence. - lump_name = Wads.CheckNumForName(mapname); + // Names with more than 8 characters will only be checked as .wad and .map. + if (strlen(mapname) <= 8) lump_name = Wads.CheckNumForName(mapname); fmt.Format("maps/%s.wad", mapname); lump_wad = Wads.CheckNumForFullName(fmt); fmt.Format("maps/%s.map", mapname); @@ -576,13 +577,11 @@ void MapData::GetChecksum(BYTE cksum[16]) // //=========================================================================== -static void SetTexture (side_t *side, int position, const char *name8, FMissingTextureTracker &track) +static void SetTexture (side_t *side, int position, const char *name, FMissingTextureTracker &track) { static const char *positionnames[] = { "top", "middle", "bottom" }; static const char *sidenames[] = { "first", "second" }; - char name[9]; - strncpy (name, name8, 8); - name[8] = 0; + FTextureID texture = TexMan.CheckForTexture (name, FTexture::TEX_Wall, FTextureManager::TEXMAN_Overridable|FTextureManager::TEXMAN_TryAny); @@ -618,12 +617,17 @@ static void SetTexture (side_t *side, int position, const char *name8, FMissingT // //=========================================================================== -void SetTexture (sector_t *sector, int index, int position, const char *name8, FMissingTextureTracker &track) +void SetTexture (sector_t *sector, int index, int position, const char *name, FMissingTextureTracker &track, bool truncate) { static const char *positionnames[] = { "floor", "ceiling" }; - char name[9]; - strncpy (name, name8, 8); - name[8] = 0; + char name8[9]; + if (truncate) + { + strncpy(name8, name, 8); + name8[8] = 0; + name = name8; + } + FTextureID texture = TexMan.CheckForTexture (name, FTexture::TEX_Flat, FTextureManager::TEXMAN_Overridable|FTextureManager::TEXMAN_TryAny); @@ -673,11 +677,8 @@ static void SummarizeMissingTextures(const FMissingTextureTracker &missing) // //=========================================================================== -static void SetTexture (side_t *side, int position, DWORD *blend, char *name8) +static void SetTexture (side_t *side, int position, DWORD *blend, const char *name) { - char name[9]; - strncpy (name, name8, 8); - name[8] = 0; FTextureID texture; if ((*blend = R_ColormapNumForName (name)) == 0) { @@ -704,12 +705,9 @@ static void SetTexture (side_t *side, int position, DWORD *blend, char *name8) side->SetTexture(position, texture); } -static void SetTextureNoErr (side_t *side, int position, DWORD *color, char *name8, bool *validcolor, bool isFog) +static void SetTextureNoErr (side_t *side, int position, DWORD *color, const char *name, bool *validcolor, bool isFog) { - char name[9]; FTextureID texture; - strncpy (name, name8, 8); - name[8] = 0; *validcolor = false; texture = TexMan.CheckForTexture (name, FTexture::TEX_Wall, FTextureManager::TEXMAN_Overridable|FTextureManager::TEXMAN_TryAny); @@ -1514,8 +1512,8 @@ void P_LoadSectors (MapData *map, FMissingTextureTracker &missingtex) ss->ceilingplane.d = ss->GetPlaneTexZ(sector_t::ceiling); ss->ceilingplane.c = -FRACUNIT; ss->ceilingplane.ic = -FRACUNIT; - SetTexture(ss, i, sector_t::floor, ms->floorpic, missingtex); - SetTexture(ss, i, sector_t::ceiling, ms->ceilingpic, missingtex); + SetTexture(ss, i, sector_t::floor, ms->floorpic, missingtex, true); + SetTexture(ss, i, sector_t::ceiling, ms->ceilingpic, missingtex, true); ss->lightlevel = LittleShort(ms->lightlevel); if (map->HasBehavior) ss->special = LittleShort(ms->special); @@ -1764,6 +1762,9 @@ void P_LoadThings (MapData * map) mti[i].Conversation = 0; mti[i].SkillFilter = MakeSkill(flags); mti[i].ClassFilter = 0xffff; // Doom map format doesn't have class flags so spawn for all player classes + mti[i].RenderStyle = STYLE_Count; + mti[i].alpha = -1; + mti[i].health = 1; flags &= ~MTF_SKILLMASK; mti[i].flags = (short)((flags & 0xf) | 0x7e0); if (gameinfo.gametype == GAME_Strife) @@ -1823,6 +1824,8 @@ void P_LoadThings2 (MapData * map) for(int i = 0; i< numthings; i++) { + memset (&mti[i], 0, sizeof(mti[i])); + mti[i].thingid = LittleShort(mth[i].thingid); mti[i].x = LittleShort(mth[i].x)<> MTF_CLASS_SHIFT; mti[i].flags &= ~(MTF_SKILLMASK|MTF_CLASS_MASK); - mti[i].Conversation = 0; mti[i].gravity = FRACUNIT; + mti[i].RenderStyle = STYLE_Count; + mti[i].alpha = -1; + mti[i].health = 1; } delete[] mtp; } @@ -2465,11 +2470,8 @@ int P_DetermineTranslucency (int lumpnum) return newcolor.r; } -void P_ProcessSideTextures(bool checktranmap, side_t *sd, sector_t *sec, mapsidedef_t *msd, int special, int tag, short *alpha, FMissingTextureTracker &missingtex) +void P_ProcessSideTextures(bool checktranmap, side_t *sd, sector_t *sec, intmapsidedef_t *msd, int special, int tag, short *alpha, FMissingTextureTracker &missingtex) { - char name[9]; - name[8] = 0; - switch (special) { case Transfer_Heights: // variable colormap via 242 linedef @@ -2495,7 +2497,6 @@ void P_ProcessSideTextures(bool checktranmap, side_t *sd, sector_t *sec, mapside SetTextureNoErr (sd, side_t::bottom, &fog, msd->bottomtexture, &foggood, true); SetTextureNoErr (sd, side_t::top, &color, msd->toptexture, &colorgood, false); - strncpy (name, msd->midtexture, 8); SetTexture(sd, side_t::mid, msd->midtexture, missingtex); if (colorgood | foggood) @@ -2526,8 +2527,7 @@ void P_ProcessSideTextures(bool checktranmap, side_t *sd, sector_t *sec, mapside case Sector_Set3DFloor: if (msd->toptexture[0]=='#') { - strncpy (name, msd->toptexture, 8); - sd->SetTexture(side_t::top, FNullTextureID() +(-strtol(name+1, NULL, 10))); // store the alpha as a negative texture index + sd->SetTexture(side_t::top, FNullTextureID() +(-strtol(&msd->toptexture[1], NULL, 10))); // store the alpha as a negative texture index // This will be sorted out by the 3D-floor code later. } else @@ -2621,7 +2621,13 @@ void P_LoadSideDefs2 (MapData *map, FMissingTextureTracker &missingtex) { sd->sector = sec = §ors[LittleShort(msd->sector)]; } - P_ProcessSideTextures(!map->HasBehavior, sd, sec, msd, + + intmapsidedef_t imsd; + imsd.toptexture.CopyCStrPart(msd->toptexture, 8); + imsd.midtexture.CopyCStrPart(msd->midtexture, 8); + imsd.bottomtexture.CopyCStrPart(msd->bottomtexture, 8); + + P_ProcessSideTextures(!map->HasBehavior, sd, sec, &imsd, sidetemp[i].a.special, sidetemp[i].a.tag, &sidetemp[i].a.alpha, missingtex); } delete[] msdf; @@ -3552,7 +3558,7 @@ void P_FreeExtraLevelData() // // [RH] position indicates the start spot to spawn at -void P_SetupLevel (char *lumpname, int position) +void P_SetupLevel (const char *lumpname, int position) { cycle_t times[20]; FMapThing *buildthings; @@ -3754,7 +3760,9 @@ void P_SetupLevel (char *lumpname, int position) } else { + times[0].Clock(); P_ParseTextMap(map, missingtex); + times[0].Unclock(); } times[6].Clock(); diff --git a/src/p_setup.h b/src/p_setup.h index 4a41a76f9..ee26f4c57 100644 --- a/src/p_setup.h +++ b/src/p_setup.h @@ -103,7 +103,7 @@ bool P_CheckMapData(const char * mapname); // [RH] The only parameter used is mapname, so I removed playermask and skill. // On September 1, 1998, I added the position to indicate which set // of single-player start spots should be spawned in the level. -void P_SetupLevel (char *mapname, int position); +void P_SetupLevel (const char *mapname, int position); void P_FreeLevelData(); void P_FreeExtraLevelData(); diff --git a/src/p_slopes.cpp b/src/p_slopes.cpp index 07ddf2e0d..af0ad7a20 100644 --- a/src/p_slopes.cpp +++ b/src/p_slopes.cpp @@ -178,6 +178,12 @@ void P_SetSlope (secplane_t *plane, bool setCeil, int xyangi, int zangi, } zang >>= ANGLETOFINESHIFT; + // Sanitize xyangi to [0,360) range + xyangi = xyangi % 360; + if (xyangi < 0) + { + xyangi = 360 + xyangi; + } xyang = (angle_t)Scale (xyangi, ANGLE_90, 90 << ANGLETOFINESHIFT); FVector3 norm; @@ -446,11 +452,11 @@ void P_SpawnSlopeMakers (FMapThing *firstmt, FMapThing *lastmt, const int *oldve P_VavoomSlope(sec, mt->thingid, x, y, mt->z, mt->type & 1); } else if (mt->type <= THING_SlopeCeilingPointLine) - { + { // THING_SlopeFloorPointLine and THING_SlopCeilingPointLine P_SlopeLineToPoint (mt->args[0], x, y, z, mt->type & 1); } else - { + { // THING_SetFloorSlope and THING_SetCeilingSlope P_SetSlope (refplane, mt->type & 1, mt->angle, mt->args[0], x, y, z); } mt->type = 0; diff --git a/src/p_spec.cpp b/src/p_spec.cpp index 63f7c1c89..e66dc2ab4 100644 --- a/src/p_spec.cpp +++ b/src/p_spec.cpp @@ -61,6 +61,7 @@ #include "a_sharedglobal.h" #include "farchive.h" #include "a_keys.h" +#include "c_dispatch.h" // State. #include "r_state.h" @@ -73,9 +74,6 @@ static FRandom pr_playerinspecialsector ("PlayerInSpecialSector"); void P_SetupPortals(); -// [GrafZahl] Make this message changable by the user! ;) -CVAR(String, secretmessage, "A Secret is revealed!", CVAR_ARCHIVE) - IMPLEMENT_POINTY_CLASS (DScroller) DECLARE_POINTER (m_Interpolations[0]) DECLARE_POINTER (m_Interpolations[1]) @@ -581,7 +579,7 @@ void P_PlayerInSpecialSector (player_t *player, sector_t * sector) if (sector->special & SECRET_MASK) { sector->special &= ~SECRET_MASK; - P_GiveSecret(player->mo, true, true); + P_GiveSecret(player->mo, true, true, int(sector - sectors)); } } @@ -672,7 +670,9 @@ void P_SectorDamage(int tag, int amount, FName type, const PClass *protectClass, // //============================================================================ -void P_GiveSecret(AActor *actor, bool printmessage, bool playsound) +CVAR(Bool, showsecretsector, false, 0) + +void P_GiveSecret(AActor *actor, bool printmessage, bool playsound, int sectornum) { if (actor != NULL) { @@ -682,7 +682,16 @@ void P_GiveSecret(AActor *actor, bool printmessage, bool playsound) } if (actor->CheckLocalView (consoleplayer)) { - if (printmessage) C_MidPrint (SmallFont, secretmessage); + if (printmessage) + { + if (!showsecretsector || sectornum < 0) C_MidPrint(SmallFont, GStrings["SECRETMESSAGE"]); + else + { + FString s = GStrings["SECRETMESSAGE"]; + s.AppendFormat(" (Sector %d)", sectornum); + C_MidPrint(SmallFont, s); + } + } if (playsound) S_Sound (CHAN_AUTO | CHAN_UI, "misc/secret", 1, ATTN_NORM); } } diff --git a/src/p_spec.h b/src/p_spec.h index 57d216972..245c699d7 100644 --- a/src/p_spec.h +++ b/src/p_spec.h @@ -172,7 +172,7 @@ void P_PlayerOnSpecialFlat (player_t *player, int floorType); void P_SectorDamage(int tag, int amount, FName type, const PClass *protectClass, int flags); void P_SetSectorFriction (int tag, int amount, bool alterFlag); -void P_GiveSecret(AActor *actor, bool printmessage, bool playsound); +void P_GiveSecret(AActor *actor, bool printmessage, bool playsound, int sectornum); // // getSide() @@ -902,8 +902,8 @@ bool EV_TeleportSector (int tag, int source_tid, int dest_tid, bool fog, int gro #define ACS_NET 8 int P_StartScript (AActor *who, line_t *where, int script, const char *map, const int *args, int argcount, int flags); -void P_SuspendScript (int script, char *map); -void P_TerminateScript (int script, char *map); +void P_SuspendScript (int script, const char *map); +void P_TerminateScript (int script, const char *map); void P_DoDeferedScripts (void); // diff --git a/src/p_things.cpp b/src/p_things.cpp index a0f905a7f..e62c65ae7 100644 --- a/src/p_things.cpp +++ b/src/p_things.cpp @@ -410,18 +410,11 @@ void P_RemoveThing(AActor * actor) bool P_Thing_Raise(AActor *thing) { - if (thing == NULL) - return false; // not valid - - if (!(thing->flags & MF_CORPSE) ) - return true; // not a corpse - - if (thing->tics != -1) - return true; // not lying still yet - - FState * RaiseState = thing->FindState(NAME_Raise); + FState * RaiseState = thing->GetRaiseState(); if (RaiseState == NULL) + { return true; // monster doesn't have a raise state + } AActor *info = thing->GetDefault (); @@ -443,24 +436,12 @@ bool P_Thing_Raise(AActor *thing) return false; } - S_Sound (thing, CHAN_BODY, "vile/raise", 1, ATTN_IDLE); - - thing->SetState (RaiseState); - thing->flags = info->flags; - thing->flags2 = info->flags2; - thing->flags3 = info->flags3; - thing->flags4 = info->flags4; - thing->flags5 = info->flags5; - thing->flags6 = info->flags6; - thing->health = info->health; - thing->target = NULL; - thing->lastenemy = NULL; - // [RH] If it's a monster, it gets to count as another kill - if (thing->CountsAsKill()) - { - level.total_monsters++; - } + S_Sound (thing, CHAN_BODY, "vile/raise", 1, ATTN_IDLE); + + thing->Revive(); + + thing->SetState (RaiseState); return true; } diff --git a/src/p_udmf.cpp b/src/p_udmf.cpp index fc5964737..7588199b4 100644 --- a/src/p_udmf.cpp +++ b/src/p_udmf.cpp @@ -118,8 +118,8 @@ enum // namespace for each game }; -void SetTexture (sector_t *sector, int index, int position, const char *name8, FMissingTextureTracker &); -void P_ProcessSideTextures(bool checktranmap, side_t *sd, sector_t *sec, mapsidedef_t *msd, int special, int tag, short *alpha, FMissingTextureTracker &); +void SetTexture (sector_t *sector, int index, int position, const char *name, FMissingTextureTracker &, bool truncate); +void P_ProcessSideTextures(bool checktranmap, side_t *sd, sector_t *sec, intmapsidedef_t *msd, int special, int tag, short *alpha, FMissingTextureTracker &); void P_AdjustLine (line_t *ld); void P_FinishLoadingLineDef(line_t *ld, int alpha); void SpawnMapThing(int index, FMapThing *mt, int position); @@ -394,7 +394,7 @@ class UDMFParser : public UDMFParserBase TArray ParsedLines; TArray ParsedSides; - TArray ParsedSideTextures; + TArray ParsedSideTextures; TArray ParsedSectors; TArray ParsedVertices; TArray ParsedVertexDatas; @@ -476,6 +476,9 @@ public: memset(th, 0, sizeof(*th)); th->gravity = FRACUNIT; + th->RenderStyle = STYLE_Count; + th->alpha = -1; + th->health = 1; sc.MustGetToken('{'); while (!sc.CheckToken('}')) { @@ -632,6 +635,96 @@ public: Flag(th->flags, MTF_SECRET, key); break; + case NAME_Renderstyle: + { + FName style = CheckString(key); + switch (style) + { + case NAME_None: + th->RenderStyle = STYLE_None; + break; + case NAME_Normal: + th->RenderStyle = STYLE_Normal; + break; + case NAME_Fuzzy: + th->RenderStyle = STYLE_Fuzzy; + break; + case NAME_SoulTrans: + th->RenderStyle = STYLE_SoulTrans; + break; + case NAME_OptFuzzy: + th->RenderStyle = STYLE_OptFuzzy; + break; + case NAME_Stencil: + th->RenderStyle = STYLE_Stencil; + break; + case NAME_AddStencil: + th->RenderStyle = STYLE_AddStencil; + break; + case NAME_Translucent: + th->RenderStyle = STYLE_Translucent; + break; + case NAME_Add: + case NAME_Additive: + th->RenderStyle = STYLE_Add; + break; + case NAME_Shaded: + th->RenderStyle = STYLE_Shaded; + break; + case NAME_AddShaded: + th->RenderStyle = STYLE_AddShaded; + break; + case NAME_TranslucentStencil: + th->RenderStyle = STYLE_TranslucentStencil; + break; + case NAME_Shadow: + th->RenderStyle = STYLE_Shadow; + break; + case NAME_Subtract: + case NAME_Subtractive: + th->RenderStyle = STYLE_Subtract; + break; + default: + break; + } + } + break; + + case NAME_Alpha: + th->alpha = CheckFixed(key); + break; + + case NAME_FillColor: + th->fillcolor = CheckInt(key); + + case NAME_Health: + th->health = CheckInt(key); + break; + + case NAME_Score: + th->score = CheckInt(key); + break; + + case NAME_Pitch: + th->pitch = (short)CheckInt(key); + break; + + case NAME_Roll: + th->roll = (short)CheckInt(key); + break; + + case NAME_ScaleX: + th->scaleX = CheckFixed(key); + break; + + case NAME_ScaleY: + th->scaleY = CheckFixed(key); + break; + + case NAME_Scale: + th->scaleX = th->scaleY = CheckFixed(key); + break; + default: if (0 == strnicmp("user_", key.GetChars(), 5)) { // Custom user key - Sets an actor's user variable directly @@ -686,6 +779,7 @@ public: { bool passuse = false; bool strifetrans = false; + bool strifetrans2 = false; FString arg0str, arg1str; memset(ld, 0, sizeof(*ld)); @@ -803,6 +897,11 @@ public: strifetrans = CheckBool(key); continue; + case NAME_Transparent: + CHECK_N(St | Zd | Zdt | Va) + strifetrans2 = CheckBool(key); + continue; + case NAME_Passuse: CHECK_N(Dm | Zd | Zdt | Va) passuse = CheckBool(key); @@ -965,6 +1064,10 @@ public: { ld->Alpha = FRACUNIT * 3/4; } + if (strifetrans2 && ld->Alpha == FRACUNIT) + { + ld->Alpha = FRACUNIT * 1/4; + } if (ld->sidedef[0] == NULL) { ld->sidedef[0] = (side_t*)(intptr_t)(1); @@ -986,14 +1089,14 @@ public: // //=========================================================================== - void ParseSidedef(side_t *sd, mapsidedef_t *sdt, int index) + void ParseSidedef(side_t *sd, intmapsidedef_t *sdt, int index) { fixed_t texofs[2]={0,0}; memset(sd, 0, sizeof(*sd)); - strncpy(sdt->bottomtexture, "-", 8); - strncpy(sdt->toptexture, "-", 8); - strncpy(sdt->midtexture, "-", 8); + sdt->bottomtexture = "-"; + sdt->toptexture = "-"; + sdt->midtexture = "-"; sd->SetTextureXScale(FRACUNIT); sd->SetTextureYScale(FRACUNIT); @@ -1012,15 +1115,15 @@ public: continue; case NAME_Texturetop: - strncpy(sdt->toptexture, CheckString(key), 8); + sdt->toptexture = CheckString(key); continue; case NAME_Texturebottom: - strncpy(sdt->bottomtexture, CheckString(key), 8); + sdt->bottomtexture = CheckString(key); continue; case NAME_Texturemiddle: - strncpy(sdt->midtexture, CheckString(key), 8); + sdt->midtexture = CheckString(key); continue; case NAME_Sector: @@ -1142,6 +1245,8 @@ public: int lightcolor = -1; int fadecolor = -1; int desaturation = -1; + int fplaneflags = 0, cplaneflags = 0; + double fp[4] = { 0 }, cp[4] = { 0 }; memset(sec, 0, sizeof(*sec)); sec->lightlevel = 160; @@ -1183,11 +1288,11 @@ public: continue; case NAME_Texturefloor: - SetTexture(sec, index, sector_t::floor, CheckString(key), missingTex); + SetTexture(sec, index, sector_t::floor, CheckString(key), missingTex, false); continue; case NAME_Textureceiling: - SetTexture(sec, index, sector_t::ceiling, CheckString(key), missingTex); + SetTexture(sec, index, sector_t::ceiling, CheckString(key), missingTex, false); continue; case NAME_Lightlevel: @@ -1343,6 +1448,46 @@ public: Flag(sec->MoreFlags, SECF_UNDERWATER, key); break; + case NAME_floorplane_a: + fplaneflags |= 1; + fp[0] = CheckFloat(key); + break; + + case NAME_floorplane_b: + fplaneflags |= 2; + fp[1] = CheckFloat(key); + break; + + case NAME_floorplane_c: + fplaneflags |= 4; + fp[2] = CheckFloat(key); + break; + + case NAME_floorplane_d: + fplaneflags |= 8; + fp[3] = CheckFloat(key); + break; + + case NAME_ceilingplane_a: + cplaneflags |= 1; + cp[0] = CheckFloat(key); + break; + + case NAME_ceilingplane_b: + cplaneflags |= 2; + cp[1] = CheckFloat(key); + break; + + case NAME_ceilingplane_c: + cplaneflags |= 4; + cp[2] = CheckFloat(key); + break; + + case NAME_ceilingplane_d: + cplaneflags |= 8; + cp[3] = CheckFloat(key); + break; + default: break; } @@ -1354,12 +1499,44 @@ public: } sec->secretsector = !!(sec->special&SECRET_MASK); - sec->floorplane.d = -sec->GetPlaneTexZ(sector_t::floor); - sec->floorplane.c = FRACUNIT; - sec->floorplane.ic = FRACUNIT; - sec->ceilingplane.d = sec->GetPlaneTexZ(sector_t::ceiling); - sec->ceilingplane.c = -FRACUNIT; - sec->ceilingplane.ic = -FRACUNIT; + + // Reset the planes to their defaults if not all of the plane equation's parameters were found. + if (fplaneflags != 15) + { + sec->floorplane.a = sec->floorplane.b = 0; + sec->floorplane.d = -sec->GetPlaneTexZ(sector_t::floor); + sec->floorplane.c = FRACUNIT; + sec->floorplane.ic = FRACUNIT; + } + else + { + double ulen = TVector3(fp[0], fp[1], fp[2]).Length(); + + // normalize the vector, it must have a length of 1 + sec->floorplane.a = FLOAT2FIXED(fp[0] / ulen); + sec->floorplane.b = FLOAT2FIXED(fp[1] / ulen); + sec->floorplane.c = FLOAT2FIXED(fp[2] / ulen); + sec->floorplane.d = FLOAT2FIXED(fp[3] / ulen); + sec->floorplane.ic = FLOAT2FIXED(ulen / fp[2]); + } + if (cplaneflags != 15) + { + sec->ceilingplane.a = sec->ceilingplane.b = 0; + sec->ceilingplane.d = sec->GetPlaneTexZ(sector_t::ceiling); + sec->ceilingplane.c = -FRACUNIT; + sec->ceilingplane.ic = -FRACUNIT; + } + else + { + double ulen = TVector3(cp[0], cp[1], cp[2]).Length(); + + // normalize the vector, it must have a length of 1 + sec->floorplane.a = FLOAT2FIXED(cp[0] / ulen); + sec->floorplane.b = FLOAT2FIXED(cp[1] / ulen); + sec->floorplane.c = FLOAT2FIXED(cp[2] / ulen); + sec->floorplane.d = FLOAT2FIXED(cp[3] / ulen); + sec->floorplane.ic = FLOAT2FIXED(ulen / cp[2]); + } if (lightcolor == -1 && fadecolor == -1 && desaturation == -1) { @@ -1643,7 +1820,7 @@ public: else if (sc.Compare("sidedef")) { side_t si; - mapsidedef_t st; + intmapsidedef_t st; ParseSidedef(&si, &st, ParsedSides.Size()); ParsedSides.Push(si); ParsedSideTextures.Push(st); diff --git a/src/p_usdf.cpp b/src/p_usdf.cpp index 6ea32b308..2ab52e380 100644 --- a/src/p_usdf.cpp +++ b/src/p_usdf.cpp @@ -310,12 +310,16 @@ class USDFParser : public UDMFParserBase case NAME_Voice: { - FString soundname = (namespace_bits == St? "svox/" : ""); const char * name = CheckString(key); if (name[0] != 0) { + FString soundname = "svox/"; soundname += name; node->SpeakerVoice = FSoundID(S_FindSound(soundname)); + if (node->SpeakerVoice == 0 && namespace_bits == Zd) + { + node->SpeakerVoice = FSoundID(S_FindSound(name)); + } } } break; diff --git a/src/p_user.cpp b/src/p_user.cpp index 901f6cfaa..ea7b315d8 100644 --- a/src/p_user.cpp +++ b/src/p_user.cpp @@ -65,6 +65,8 @@ CVAR (Bool, cl_noprediction, false, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) static player_t PredictionPlayerBackup; static BYTE PredictionActorBackup[sizeof(AActor)]; static TArray PredictionTouchingSectorsBackup; +static TArray PredictionSectorListBackup; +static TArray PredictionSector_sprev_Backup; // [GRB] Custom player classes TArray PlayerClasses; @@ -210,8 +212,6 @@ CCMD (playerclasses) // 16 pixels of bob #define MAXBOB 0x100000 -bool onground; - FArchive &operator<< (FArchive &arc, player_t *&p) { return arc.SerializePointer (players, (BYTE **)&p, sizeof(*players)); @@ -268,6 +268,7 @@ player_t::player_t() PremorphWeapon(0), chickenPeck(0), jumpTics(0), + onground(0), respawn_time(0), camera(0), air_finished(0), @@ -375,6 +376,7 @@ player_t &player_t::operator=(const player_t &p) PremorphWeapon = p.PremorphWeapon; chickenPeck = p.chickenPeck; jumpTics = p.jumpTics; + onground = p.onground; respawn_time = p.respawn_time; camera = p.camera; air_finished = p.air_finished; @@ -1747,7 +1749,7 @@ void P_CalcHeight (player_t *player) { player->bob = 0; } - else if ((player->mo->flags & MF_NOGRAVITY) && !onground) + else if ((player->mo->flags & MF_NOGRAVITY) && !player->onground) { player->bob = FRACUNIT / 2; } @@ -1872,7 +1874,7 @@ void P_MovePlayer (player_t *player) mo->angle += cmd->ucmd.yaw << 16; } - onground = (mo->z <= mo->floorz) || (mo->flags2 & MF2_ONMOBJ) || (mo->BounceFlags & BOUNCE_MBF) || (player->cheats & CF_NOCLIP2); + player->onground = (mo->z <= mo->floorz) || (mo->flags2 & MF2_ONMOBJ) || (mo->BounceFlags & BOUNCE_MBF) || (player->cheats & CF_NOCLIP2); // killough 10/98: // @@ -1890,7 +1892,7 @@ void P_MovePlayer (player_t *player) movefactor = P_GetMoveFactor (mo, &friction); bobfactor = friction < ORIG_FRICTION ? movefactor : ORIG_FRICTION_FACTOR; - if (!onground && !(player->mo->flags & MF_NOGRAVITY) && !player->mo->waterlevel) + if (!player->onground && !(player->mo->flags & MF_NOGRAVITY) && !player->mo->waterlevel) { // [RH] allow very limited movement if not on ground. movefactor = FixedMul (movefactor, level.aircontrol); @@ -2061,12 +2063,12 @@ void P_DeathThink (player_t *player) P_MovePsprites (player); - onground = (player->mo->z <= player->mo->floorz); + player->onground = (player->mo->z <= player->mo->floorz); if (player->mo->IsKindOf (RUNTIME_CLASS(APlayerChunk))) { // Flying bloody skull or flying ice chunk player->viewheight = 6 * FRACUNIT; player->deltaviewheight = 0; - if (onground) + if (player->onground) { if (player->mo->pitch > -(int)ANGLE_1*19) { @@ -2252,6 +2254,9 @@ void P_PlayerThink (player_t *player) { player->inventorytics--; } + // Don't interpolate the view for more than one tic + player->cheats &= ~CF_INTERPVIEW; + // No-clip cheat if ((player->cheats & (CF_NOCLIP | CF_NOCLIP2)) == CF_NOCLIP2) { // No noclip2 without noclip @@ -2362,7 +2367,7 @@ void P_PlayerThink (player_t *player) if (player->jumpTics != 0) { player->jumpTics--; - if (onground && player->jumpTics < -18) + if (player->onground && player->jumpTics < -18) { player->jumpTics = 0; } @@ -2462,7 +2467,7 @@ void P_PlayerThink (player_t *player) { player->mo->velz = 3*FRACUNIT; } - else if (level.IsJumpingAllowed() && onground && player->jumpTics == 0) + else if (level.IsJumpingAllowed() && player->onground && player->jumpTics == 0) { fixed_t jumpvelz = player->mo->JumpZ * 35 / TICRATE; @@ -2470,9 +2475,10 @@ void P_PlayerThink (player_t *player) if ( player->cheats & CF_HIGHJUMP ) jumpvelz *= 2; player->mo->velz += jumpvelz; - S_Sound (player->mo, CHAN_BODY, "*jump", 1, ATTN_NORM); player->mo->flags2 &= ~MF2_ONMOBJ; player->jumpTics = -1; + if (!(player->cheats & CF_PREDICTING)) + S_Sound(player->mo, CHAN_BODY, "*jump", 1, ATTN_NORM); } } @@ -2499,7 +2505,7 @@ void P_PlayerThink (player_t *player) { player->mo->flags2 |= MF2_FLY; player->mo->flags |= MF_NOGRAVITY; - if (player->mo->velz <= -39*FRACUNIT) + if ((player->mo->velz <= -39 * FRACUNIT) && !(player->cheats & CF_PREDICTING)) { // Stop falling scream S_StopSound (player->mo, CHAN_VOICE); } @@ -2657,15 +2663,41 @@ void P_PredictPlayer (player_t *player) player->cheats |= CF_PREDICTING; // The ordering of the touching_sectorlist needs to remain unchanged + // Also store a copy of all previous sector_thinglist nodes msecnode_t *mnode = act->touching_sectorlist; + msecnode_t *snode; + PredictionSector_sprev_Backup.Clear(); PredictionTouchingSectorsBackup.Clear (); while (mnode != NULL) { PredictionTouchingSectorsBackup.Push (mnode->m_sector); + + for (snode = mnode->m_sector->touching_thinglist; snode; snode = snode->m_snext) + { + if (snode->m_thing == act) + { + PredictionSector_sprev_Backup.Push(snode->m_sprev); + break; + } + } + mnode = mnode->m_tnext; } + // Keep an ordered list off all actors in the linked sector. + PredictionSectorListBackup.Clear(); + if (!(act->flags & MF_NOSECTOR)) + { + AActor *link = act->Sector->thinglist; + + while (link != NULL) + { + PredictionSectorListBackup.Push(link); + link = link->snext; + } + } + // Blockmap ordering also needs to stay the same, so unlink the block nodes // without releasing them. (They will be used again in P_UnpredictPlayer). FBlockNode *block = act->BlockNode; @@ -2697,6 +2729,7 @@ void P_UnPredictPlayer () if (player->cheats & CF_PREDICTING) { + unsigned int i; AActor *act = player->mo; AActor *savedcamera = player->camera; @@ -2706,23 +2739,80 @@ void P_UnPredictPlayer () // could cause it to change during prediction. player->camera = savedcamera; - act->UnlinkFromWorld (); - memcpy (&act->x, PredictionActorBackup, sizeof(AActor)-((BYTE *)&act->x-(BYTE *)act)); + act->UnlinkFromWorld(); + memcpy(&act->x, PredictionActorBackup, sizeof(AActor)-((BYTE *)&act->x - (BYTE *)act)); // Make the sector_list match the player's touching_sectorlist before it got predicted. - P_DelSeclist (sector_list); + P_DelSeclist(sector_list); sector_list = NULL; - for (unsigned int i = PredictionTouchingSectorsBackup.Size (); i-- > 0; ) + for (i = PredictionTouchingSectorsBackup.Size(); i-- > 0;) { - sector_list = P_AddSecnode (PredictionTouchingSectorsBackup[i], act, sector_list); + sector_list = P_AddSecnode(PredictionTouchingSectorsBackup[i], act, sector_list); } // The blockmap ordering needs to remain unchanged, too. Right now, act has the right // pointers, so temporarily set its MF_NOBLOCKMAP flag so that LinkToWorld() does not // mess with them. - act->flags |= MF_NOBLOCKMAP; - act->LinkToWorld (); - act->flags &= ~MF_NOBLOCKMAP; + { + DWORD keepflags = act->flags; + act->flags |= MF_NOBLOCKMAP; + act->LinkToWorld(); + act->flags = keepflags; + } + + // Restore sector links. + if (!(act->flags & MF_NOSECTOR)) + { + sector_t *sec = act->Sector; + AActor *me, *next; + AActor **link;// , **prev; + + // The thinglist is just a pointer chain. We are restoring the exact same things, so we can NULL the head safely + sec->thinglist = NULL; + + for (i = PredictionSectorListBackup.Size(); i-- > 0;) + { + me = PredictionSectorListBackup[i]; + link = &sec->thinglist; + next = *link; + if ((me->snext = next)) + next->sprev = &me->snext; + me->sprev = link; + *link = me; + } + + msecnode_t *snode; + + // Restore sector thinglist order + for (i = PredictionTouchingSectorsBackup.Size(); i-- > 0;) + { + // If we were already the head node, then nothing needs to change + if (PredictionSector_sprev_Backup[i] == NULL) + continue; + + for (snode = PredictionTouchingSectorsBackup[i]->touching_thinglist; snode; snode = snode->m_snext) + { + if (snode->m_thing == act) + { + if (snode->m_sprev) + snode->m_sprev->m_snext = snode->m_snext; + else + snode->m_sector->touching_thinglist = snode->m_snext; + if (snode->m_snext) + snode->m_snext->m_sprev = snode->m_sprev; + + snode->m_sprev = PredictionSector_sprev_Backup[i]; + + // At the moment, we don't exist in the list anymore, but we do know what our previous node is, so we set its current m_snext->m_sprev to us. + if (snode->m_sprev->m_snext) + snode->m_sprev->m_snext->m_sprev = snode; + snode->m_snext = snode->m_sprev->m_snext; + snode->m_sprev->m_snext = snode; + break; + } + } + } + } // Now fix the pointers in the blocknode chain FBlockNode *block = act->BlockNode; @@ -2742,14 +2832,22 @@ void P_UnPredictPlayer () void player_t::Serialize (FArchive &arc) { int i; + FString skinname; arc << cls << mo << camera << playerstate - << cmd - << userinfo - << DesiredFOV << FOV + << cmd; + if (arc.IsLoading()) + { + ReadUserInfo(arc, userinfo, skinname); + } + else + { + WriteUserInfo(arc, userinfo); + } + arc << DesiredFOV << FOV << viewz << viewheight << deltaviewheight @@ -2865,6 +2963,14 @@ void player_t::Serialize (FArchive &arc) { settings_controller = (this - players == Net_Arbitrator); } + if (SaveVersion >= 4505) + { + arc << onground; + } + else + { + onground = (mo->z <= mo->floorz) || (mo->flags2 & MF2_ONMOBJ) || (mo->BounceFlags & BOUNCE_MBF) || (cheats & CF_NOCLIP2); + } if (isbot) { @@ -2900,6 +3006,10 @@ void player_t::Serialize (FArchive &arc) oldbuttons = ~0; original_oldbuttons = ~0; } + if (skinname.IsNotEmpty()) + { + userinfo.SkinChanged(skinname, CurrentPlayerClass); + } } diff --git a/src/p_xlat.cpp b/src/p_xlat.cpp index 7ece27ae8..be2d154c3 100644 --- a/src/p_xlat.cpp +++ b/src/p_xlat.cpp @@ -89,6 +89,9 @@ void P_TranslateLineDef (line_t *ld, maplinedef_t *mld) case -2: ld->Alpha = FRACUNIT*3/4; break; + case -3: + ld->Alpha = FRACUNIT / 4; + break; default: newflags |= LineFlagTranslations[i].newvalue; break; diff --git a/src/parsecontext.cpp b/src/parsecontext.cpp index 6fa36b2a8..21b7a0ea6 100644 --- a/src/parsecontext.cpp +++ b/src/parsecontext.cpp @@ -157,6 +157,10 @@ loop: { return TokenTrans[NUM]; } +#if __GNUC__ == 4 && __GNUC_MINOR__ == 8 + // Work around GCC 4.8 bug 54570 causing release build crashes. + asm("" : "+g" (yylval)); +#endif strcpy (yylval->sym, token); return TokenTrans[SYM]; } diff --git a/src/r_data/colormaps.cpp b/src/r_data/colormaps.cpp index c3004a4da..b7e1b904b 100644 --- a/src/r_data/colormaps.cpp +++ b/src/r_data/colormaps.cpp @@ -396,7 +396,7 @@ void R_SetDefaultColormap (const char *name) BYTE unremap[256]; BYTE remap[256]; - lump = Wads.CheckNumForName (name, ns_colormaps); + lump = Wads.CheckNumForFullName (name, true, ns_colormaps); if (lump == -1) lump = Wads.CheckNumForName (name, ns_global); diff --git a/src/r_data/renderstyle.cpp b/src/r_data/renderstyle.cpp index 4b1d9fed4..81524aabb 100644 --- a/src/r_data/renderstyle.cpp +++ b/src/r_data/renderstyle.cpp @@ -47,17 +47,20 @@ CVAR (Int, r_drawfuzz, 1, CVAR_ARCHIVE) #ifndef __APPLE__ FRenderStyle LegacyRenderStyles[STYLE_Count] = { - /* STYLE_None */ {{ STYLEOP_None, STYLEALPHA_Zero, STYLEALPHA_Zero, 0 }}, - /* STYLE_Normal */ {{ STYLEOP_Add, STYLEALPHA_Src, STYLEALPHA_InvSrc, STYLEF_Alpha1 }}, - /* STYLE_Fuzzy */ {{ STYLEOP_Fuzz, STYLEALPHA_Src, STYLEALPHA_InvSrc, 0 }}, - /* STYLE_SoulTrans */ {{ STYLEOP_Add, STYLEALPHA_Src, STYLEALPHA_InvSrc, STYLEF_TransSoulsAlpha }}, - /* STYLE_OptFuzzy */ {{ STYLEOP_FuzzOrAdd, STYLEALPHA_Src, STYLEALPHA_InvSrc, 0 }}, - /* STYLE_Stencil */ {{ STYLEOP_Add, STYLEALPHA_Src, STYLEALPHA_InvSrc, STYLEF_Alpha1 | STYLEF_ColorIsFixed }}, - /* STYLE_Translucent */ {{ STYLEOP_Add, STYLEALPHA_Src, STYLEALPHA_InvSrc, 0 }}, - /* STYLE_Add */ {{ STYLEOP_Add, STYLEALPHA_Src, STYLEALPHA_One, 0 }}, - /* STYLE_Shaded */ {{ STYLEOP_Add, STYLEALPHA_Src, STYLEALPHA_InvSrc, STYLEF_RedIsAlpha | STYLEF_ColorIsFixed }}, -/* STYLE_TranslucentStencil */{{ STYLEOP_Add, STYLEALPHA_Src, STYLEALPHA_InvSrc, STYLEF_ColorIsFixed }}, - /* STYLE_Shadow */{{ STYLEOP_Shadow, 0, 0, 0 }}, + { { STYLEOP_None, STYLEALPHA_Zero, STYLEALPHA_Zero, 0 } }, /* STYLE_None */ + { { STYLEOP_Add, STYLEALPHA_Src, STYLEALPHA_InvSrc, STYLEF_Alpha1 } }, /* STYLE_Normal */ + { { STYLEOP_Fuzz, STYLEALPHA_Src, STYLEALPHA_InvSrc, 0 } }, /* STYLE_Fuzzy */ + { { STYLEOP_Add, STYLEALPHA_Src, STYLEALPHA_InvSrc, STYLEF_TransSoulsAlpha } }, /* STYLE_SoulTrans */ + { { STYLEOP_FuzzOrAdd, STYLEALPHA_Src, STYLEALPHA_InvSrc, 0 } }, /* STYLE_OptFuzzy */ + { { STYLEOP_Add, STYLEALPHA_Src, STYLEALPHA_InvSrc, STYLEF_Alpha1 | STYLEF_ColorIsFixed } }, /* STYLE_Stencil */ + { { STYLEOP_Add, STYLEALPHA_Src, STYLEALPHA_InvSrc, 0 } }, /* STYLE_Translucent */ + { { STYLEOP_Add, STYLEALPHA_Src, STYLEALPHA_One, 0 } }, /* STYLE_Add */ + { { STYLEOP_Add, STYLEALPHA_Src, STYLEALPHA_InvSrc, STYLEF_RedIsAlpha | STYLEF_ColorIsFixed } }, /* STYLE_Shaded */ + { { STYLEOP_Add, STYLEALPHA_Src, STYLEALPHA_InvSrc, STYLEF_ColorIsFixed } }, /* STYLE_TranslucentStencil */ + { { STYLEOP_Shadow, 0, 0, 0 } }, /* STYLE_Shadow */ + { { STYLEOP_RevSub, STYLEALPHA_Src, STYLEALPHA_One, 0 } }, /* STYLE_Subtract*/ + { { STYLEOP_Add, STYLEALPHA_Src, STYLEALPHA_One, STYLEF_ColorIsFixed } }, /* STYLE_AddStencil */ + { { STYLEOP_Add, STYLEALPHA_Src, STYLEALPHA_One, STYLEF_RedIsAlpha | STYLEF_ColorIsFixed } }, /* STYLE_AddShaded */ }; #else FRenderStyle LegacyRenderStyles[STYLE_Count]; @@ -74,7 +77,10 @@ static const BYTE Styles[STYLE_Count * 4] = STYLEOP_Add, STYLEALPHA_Src, STYLEALPHA_One, 0, STYLEOP_Add, STYLEALPHA_Src, STYLEALPHA_InvSrc, STYLEF_RedIsAlpha | STYLEF_ColorIsFixed, STYLEOP_Add, STYLEALPHA_Src, STYLEALPHA_InvSrc, STYLEF_ColorIsFixed, - STYLEOP_Shadow, 0, 0, 0 + STYLEOP_Shadow, 0, 0, 0, + STYLEOP_RevSub, STYLEALPHA_Src, STYLEALPHA_One, 0, + STYLEOP_Add, STYLEALPHA_Src, STYLEALPHA_One, STYLEF_Alpha1 | STYLEF_ColorIsFixed, + STYLEOP_Add, STYLEALPHA_Src, STYLEALPHA_One, STYLEF_RedIsAlpha | STYLEF_ColorIsFixed, }; static struct LegacyInit diff --git a/src/r_data/renderstyle.h b/src/r_data/renderstyle.h index 8133557d5..3d617eff2 100644 --- a/src/r_data/renderstyle.h +++ b/src/r_data/renderstyle.h @@ -49,6 +49,9 @@ enum ERenderStyle STYLE_Shaded, // Treat patch data as alpha values for alphacolor STYLE_TranslucentStencil, STYLE_Shadow, + STYLE_Subtract, // Actually this is 'reverse subtract' but this is what normal people would expect by 'subtract'. + STYLE_AddStencil, // Fill image interior with alphacolor + STYLE_AddShaded, // Treat patch data as alpha values for alphacolor STYLE_Count }; diff --git a/src/r_data/sprites.cpp b/src/r_data/sprites.cpp index 012abb2f6..c1e59c415 100644 --- a/src/r_data/sprites.cpp +++ b/src/r_data/sprites.cpp @@ -63,7 +63,7 @@ static bool R_InstallSpriteLump (FTextureID lump, unsigned frame, char rot, bool if (frame >= MAX_SPRITE_FRAMES || rotation > 16) { - Printf (TEXTCOLOR_RED"R_InstallSpriteLump: Bad frame characters in lump %s\n", TexMan[lump]->Name); + Printf (TEXTCOLOR_RED"R_InstallSpriteLump: Bad frame characters in lump %s\n", TexMan[lump]->Name.GetChars()); return false; } @@ -249,6 +249,8 @@ static void R_InstallSprite (int num) // letter/number appended. // The rotation character can be 0 to signify no rotations. // +#define TEX_DWNAME(tex) MAKE_ID(tex->Name[0], tex->Name[1], tex->Name[2], tex->Name[3]) + void R_InitSpriteDefs () { struct Hasher @@ -272,7 +274,7 @@ void R_InitSpriteDefs () FTexture *tex = TexMan.ByIndex(i); if (tex->UseType == FTexture::TEX_Sprite && strlen(tex->Name) >= 6) { - size_t bucket = tex->dwName % smax; + size_t bucket = TEX_DWNAME(tex) % smax; hashes[i].Next = hashes[bucket].Head; hashes[bucket].Head = i; } @@ -352,7 +354,7 @@ void R_InitSpriteDefs () while (hash != -1) { FTexture *tex = TexMan[hash]; - if (tex->dwName == intname) + if (TEX_DWNAME(tex) == intname) { bool res = R_InstallSpriteLump (FTextureID(hash), tex->Name[4] - 'A', tex->Name[5], false); @@ -996,4 +998,4 @@ void R_DeinitSpriteData() delete[] skins; skins = NULL; } -} \ No newline at end of file +} diff --git a/src/r_defs.h b/src/r_defs.h index c2f3e5b34..2e9c0876b 100644 --- a/src/r_defs.h +++ b/src/r_defs.h @@ -198,9 +198,10 @@ public: void BeginPlay (); void Activate (AActor *source); void Deactivate (AActor *source); - virtual bool TriggerAction (AActor *triggerer, int activationType); + bool TriggerAction(AActor *triggerer, int activationType); protected: - bool CheckTrigger (AActor *triggerer) const; + virtual bool DoTriggerAction(AActor *triggerer, int activationType); + bool CheckTrigger(AActor *triggerer) const; }; class ASkyViewpoint; diff --git a/src/r_main.cpp b/src/r_main.cpp index edb13d326..a726bc714 100644 --- a/src/r_main.cpp +++ b/src/r_main.cpp @@ -706,10 +706,6 @@ void R_EnterMirror (drawseg_t *ds, int depth) R_EnterMirror (drawsegs + WallMirrors[mirrorsAtStart], depth + 1); } } - else - { - depth = depth; - } viewangle = startang; viewx = startx; diff --git a/src/r_plane.cpp b/src/r_plane.cpp index 986d99203..6572c1f0b 100644 --- a/src/r_plane.cpp +++ b/src/r_plane.cpp @@ -558,9 +558,9 @@ static visplane_t *new_visplane (unsigned hash) if (check == NULL) { - check = (visplane_t *)M_Malloc (sizeof(*check) + sizeof(*check->top)*(MAXWIDTH*2)); - memset(check, 0, sizeof(*check) + sizeof(*check->top)*(MAXWIDTH*2)); - check->bottom = &check->top[MAXWIDTH+2]; + check = (visplane_t *)M_Malloc (sizeof(*check) + 3 + sizeof(*check->top)*(MAXWIDTH*2)); + memset(check, 0, sizeof(*check) + 3 + sizeof(*check->top)*(MAXWIDTH*2)); + check->bottom = check->top + MAXWIDTH+2; } else if (NULL == (freetail = freetail->next)) { @@ -607,8 +607,7 @@ visplane_t *R_FindPlane (const secplane_t &height, FTextureID picnum, int lightl // same visplane, then only the floor sky will be drawn. plane.c = height.c; plane.ic = height.ic; - isskybox = skybox != NULL && !skybox->bInSkybox && - (skybox->bAlways || picnum == skyflatnum); + isskybox = skybox != NULL && !skybox->bInSkybox; } else if (skybox != NULL && skybox->bAlways && !skybox->bInSkybox) { diff --git a/src/r_plane.h b/src/r_plane.h index 7ad711bcc..231fa3ad4 100644 --- a/src/r_plane.h +++ b/src/r_plane.h @@ -63,7 +63,7 @@ struct visplane_s unsigned short *bottom; // [RH] bottom and top arrays are dynamically unsigned short pad; // allocated immediately after the - unsigned short top[3]; // visplane. + unsigned short top[]; // visplane. }; typedef struct visplane_s visplane_t; diff --git a/src/r_things.cpp b/src/r_things.cpp index 9bdba99f9..7243ac6f9 100644 --- a/src/r_things.cpp +++ b/src/r_things.cpp @@ -608,6 +608,11 @@ void R_ProjectSprite (AActor *thing, int fakeside, F3DFloor *fakefloor, F3DFloor } } } + if (spritescaleX < 0) + { + spritescaleX = -spritescaleX; + flip = !flip; + } if (voxel == NULL && (tex == NULL || tex->UseType == FTexture::TEX_Null)) { return; diff --git a/src/r_utility.cpp b/src/r_utility.cpp index 0b51578ed..5bf38ad26 100644 --- a/src/r_utility.cpp +++ b/src/r_utility.cpp @@ -89,6 +89,11 @@ CVAR (Bool, r_deathcamera, false, CVAR_ARCHIVE) CVAR (Int, r_clearbuffer, 0, 0) CVAR (Bool, r_drawvoxels, true, 0) CVAR (Bool, r_drawplayersprites, true, 0) // [RH] Draw player sprites? +CUSTOM_CVAR(Float, r_quakeintensity, 1.0f, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) +{ + if (self < 0.f) self = 0.f; + else if (self > 1.f) self = 1.f; +} DCanvas *RenderTarget; // [RH] canvas to render to @@ -581,6 +586,7 @@ void R_InterpolateView (player_t *player, fixed_t frac, InterpolationViewer *ivi viewy = iview->oviewy + FixedMul (frac, iview->nviewy - iview->oviewy); viewz = iview->oviewz + FixedMul (frac, iview->nviewz - iview->oviewz); if (player != NULL && + !(player->cheats & CF_INTERPVIEW) && player - players == consoleplayer && camera == player->mo && !demoplayback && @@ -602,7 +608,7 @@ void R_InterpolateView (player_t *player, fixed_t frac, InterpolationViewer *ivi if (delta > 0) { // Avoid overflowing viewpitch (can happen when a netgame is stalled) - if (viewpitch + delta <= viewpitch) + if (viewpitch > INT_MAX - delta) { viewpitch = player->MaxPitch; } @@ -614,7 +620,7 @@ void R_InterpolateView (player_t *player, fixed_t frac, InterpolationViewer *ivi else if (delta < 0) { // Avoid overflowing viewpitch (can happen when a netgame is stalled) - if (viewpitch + delta >= viewpitch) + if (viewpitch < INT_MIN - delta) { viewpitch = player->MinPitch; } @@ -836,10 +842,10 @@ void R_SetupFrame (AActor *actor) int intensity = DEarthquake::StaticGetQuakeIntensity (camera); if (intensity != 0) { - viewx += ((pr_torchflicker() % (intensity<<2)) - -(intensity<<1))<(TexMan[picnum]); if (!texture->bHasCanvas) { - Printf ("%s is not a valid target for a camera\n", texture->Name); + Printf ("%s is not a valid target for a camera\n", texture->Name.GetChars()); return; } diff --git a/src/resourcefiles/file_7z.cpp b/src/resourcefiles/file_7z.cpp index 8b1c23b67..53653bb59 100644 --- a/src/resourcefiles/file_7z.cpp +++ b/src/resourcefiles/file_7z.cpp @@ -41,12 +41,8 @@ #include "i_system.h" #include "w_wad.h" -extern "C" { -#include "Archive/7z/7zHeader.h" -#include "Archive/7z/7zExtract.h" -#include "Archive/7z/7zIn.h" +#include "7z.h" #include "7zCrc.h" -} //----------------------------------------------------------------------- @@ -151,7 +147,7 @@ struct C7zArchive SRes Extract(UInt32 file_index, char *buffer) { size_t offset, out_size_processed; - SRes res = SzAr_Extract(&DB, &LookStream.s, file_index, + SRes res = SzArEx_Extract(&DB, &LookStream.s, file_index, &BlockIndex, &OutBuffer, &OutBufferSize, &offset, &out_size_processed, &g_Alloc, &g_Alloc); @@ -268,6 +264,8 @@ bool F7ZFile::Open(bool quiet) Lumps = new F7ZLump[NumLumps]; F7ZLump *lump_p = Lumps; + TArray nameUTF16; + TArray nameASCII; for (DWORD i = 0; i < NumLumps; ++i) { CSzFileItem *file = &Archive->DB.db.Files[i]; @@ -279,8 +277,24 @@ bool F7ZFile::Open(bool quiet) continue; } - FString name = file->Name; - FixPathSeperator(name); + const size_t nameLength = SzArEx_GetFileNameUtf16(&Archive->DB, i, NULL); + + if (0 == nameLength) + { + ++skipped; + continue; + } + + nameUTF16.Resize(nameLength); + nameASCII.Resize(nameLength); + SzArEx_GetFileNameUtf16(&Archive->DB, i, &nameUTF16[0]); + for (size_t c = 0; c < nameLength; ++c) + { + nameASCII[c] = static_cast(nameUTF16[c]); + } + FixPathSeperator(&nameASCII[0]); + + FString name = &nameASCII[0]; name.ToLower(); lump_p->LumpNameSetup(name); @@ -293,6 +307,21 @@ bool F7ZFile::Open(bool quiet) } // Resize the lump record array to its actual size NumLumps -= skipped; + + if (NumLumps > 0) + { + // Quick check for unsupported compression method + + TArray temp; + temp.Resize(Lumps[0].LumpSize); + + if (SZ_OK != Archive->Extract(Lumps[0].Position, &temp[0])) + { + if (!quiet) Printf("\n%s: unsupported 7z/LZMA file!\n", Filename); + return false; + } + } + if (!quiet) Printf(", %d lumps\n", NumLumps); // Entries in archives are sorted alphabetically @@ -351,6 +380,8 @@ FResourceFile *Check7Z(const char *filename, FileReader *file, bool quiet) { FResourceFile *rf = new F7ZFile(filename, file); if (rf->Open(quiet)) return rf; + + rf->Reader = NULL; // to avoid destruction of reader delete rf; } } diff --git a/src/resourcefiles/file_directory.cpp b/src/resourcefiles/file_directory.cpp index e9076ae9b..024ef0633 100644 --- a/src/resourcefiles/file_directory.cpp +++ b/src/resourcefiles/file_directory.cpp @@ -198,7 +198,7 @@ int FDirectory::AddDirectory(const char *dirpath) return count; } -#elif defined(__sun) +#elif defined(__sun) || defined(__APPLE__) int FDirectory::AddDirectory(const char *dirpath) { diff --git a/src/resourcefiles/file_grp.cpp b/src/resourcefiles/file_grp.cpp index dc4c97812..63738d7e6 100644 --- a/src/resourcefiles/file_grp.cpp +++ b/src/resourcefiles/file_grp.cpp @@ -147,6 +147,8 @@ FResourceFile *CheckGRP(const char *filename, FileReader *file, bool quiet) { FResourceFile *rf = new FGrpFile(filename, file); if (rf->Open(quiet)) return rf; + + rf->Reader = NULL; // to avoid destruction of reader delete rf; } } diff --git a/src/resourcefiles/file_pak.cpp b/src/resourcefiles/file_pak.cpp index 099e8046c..9ea01767b 100644 --- a/src/resourcefiles/file_pak.cpp +++ b/src/resourcefiles/file_pak.cpp @@ -139,6 +139,8 @@ FResourceFile *CheckPak(const char *filename, FileReader *file, bool quiet) { FResourceFile *rf = new FPakFile(filename, file); if (rf->Open(quiet)) return rf; + + rf->Reader = NULL; // to avoid destruction of reader delete rf; } } diff --git a/src/resourcefiles/file_rff.cpp b/src/resourcefiles/file_rff.cpp index 2e6a3bc5a..682df985d 100644 --- a/src/resourcefiles/file_rff.cpp +++ b/src/resourcefiles/file_rff.cpp @@ -260,6 +260,8 @@ FResourceFile *CheckRFF(const char *filename, FileReader *file, bool quiet) { FResourceFile *rf = new FRFFFile(filename, file); if (rf->Open(quiet)) return rf; + + rf->Reader = NULL; // to avoid destruction of reader delete rf; } } diff --git a/src/resourcefiles/file_wad.cpp b/src/resourcefiles/file_wad.cpp index ea8cac15b..384290782 100644 --- a/src/resourcefiles/file_wad.cpp +++ b/src/resourcefiles/file_wad.cpp @@ -651,6 +651,8 @@ FResourceFile *CheckWad(const char *filename, FileReader *file, bool quiet) { FResourceFile *rf = new FWadFile(filename, file); if (rf->Open(quiet)) return rf; + + rf->Reader = NULL; // to avoid destruction of reader delete rf; } } diff --git a/src/resourcefiles/file_zip.cpp b/src/resourcefiles/file_zip.cpp index 7e59bd35a..7ae0e90a5 100644 --- a/src/resourcefiles/file_zip.cpp +++ b/src/resourcefiles/file_zip.cpp @@ -259,6 +259,13 @@ bool FZipFile::Open(bool quiet) lump_p->CompressedSize = LittleLong(zip_fh->CompressedSize); lump_p->Position = LittleLong(zip_fh->LocalHeaderOffset); lump_p->CheckEmbedded(); + + // Ignore some very specific names + if (0 == stricmp("dehacked.exe", name)) + { + memset(lump_p->Name, 0, sizeof(lump_p->Name)); + } + lump_p++; } // Resize the lump record array to its actual size @@ -416,6 +423,8 @@ FResourceFile *CheckZip(const char *filename, FileReader *file, bool quiet) { FResourceFile *rf = new FZipFile(filename, file); if (rf->Open(quiet)) return rf; + + rf->Reader = NULL; // to avoid destruction of reader delete rf; } } diff --git a/src/resourcefiles/resourcefile.h b/src/resourcefiles/resourcefile.h index e531ddbb3..517b5eef4 100644 --- a/src/resourcefiles/resourcefile.h +++ b/src/resourcefiles/resourcefile.h @@ -6,6 +6,7 @@ #include "files.h" class FResourceFile; +class FTexture; struct FResourceLump { @@ -24,6 +25,7 @@ struct FResourceLump SBYTE RefCount; char * Cache; FResourceFile * Owner; + FTexture * LinkedTexture; int Namespace; FResourceLump() @@ -35,6 +37,7 @@ struct FResourceLump RefCount = 0; Namespace = 0; // ns_global *Name = 0; + LinkedTexture = NULL; } virtual ~FResourceLump(); diff --git a/src/sdl/crashcatcher.c b/src/sdl/crashcatcher.c index 37511f63a..a4f68d9a3 100644 --- a/src/sdl/crashcatcher.c +++ b/src/sdl/crashcatcher.c @@ -192,7 +192,7 @@ static size_t safe_write(int fd, const void *buf, size_t len) static void crash_catcher(int signum, siginfo_t *siginfo, void *context) { - ucontext_t *ucontext = (ucontext_t*)context; + //ucontext_t *ucontext = (ucontext_t*)context; pid_t dbg_pid; int fd[2]; diff --git a/src/sdl/i_joystick.cpp b/src/sdl/i_joystick.cpp index 48ae0e385..7a529861f 100644 --- a/src/sdl/i_joystick.cpp +++ b/src/sdl/i_joystick.cpp @@ -1,8 +1,12 @@ #include #include "doomdef.h" +#include "templates.h" #include "m_joy.h" +// Very small deadzone so that floating point magic doesn't happen +#define MIN_DEADZONE 0.000001f + class SDLInputJoystick: public IJoystickConfig { public: @@ -65,7 +69,7 @@ public: void SetAxisDeadZone(int axis, float zone) { - Axes[axis].DeadZone = zone; + Axes[axis].DeadZone = clamp(zone, MIN_DEADZONE, 1.f); } void SetAxisMap(int axis, EJoyAxis gameaxis) { @@ -83,7 +87,7 @@ public: } bool IsAxisDeadZoneDefault(int axis) { - return Axes[axis].DeadZone == 0.0f; + return Axes[axis].DeadZone <= MIN_DEADZONE; } bool IsAxisMapDefault(int axis) { @@ -105,7 +109,7 @@ public: info.Name.Format("Axis %d", i+1); else info.Name.Format("Hat %d (%c)", (i-NumAxes)/2 + 1, (i-NumAxes)%2 == 0 ? 'x' : 'y'); - info.DeadZone = 0.0f; + info.DeadZone = MIN_DEADZONE; info.Multiplier = 1.0f; info.Value = 0.0; info.ButtonValue = 0; @@ -141,7 +145,7 @@ public: { buttonstate = 0; - Axes[i].Value = SDL_JoystickGetAxis(Device, i)/32768.0; + Axes[i].Value = SDL_JoystickGetAxis(Device, i)/32767.0; Axes[i].Value = Joy_RemoveDeadZone(Axes[i].Value, Axes[i].DeadZone, &buttonstate); // Map button to axis diff --git a/src/sdl/i_main.cpp b/src/sdl/i_main.cpp index 65b992f6a..3c721ae51 100644 --- a/src/sdl/i_main.cpp +++ b/src/sdl/i_main.cpp @@ -172,11 +172,7 @@ static int DoomSpecificInfo (char *buffer, char *end) } else { - char name[9]; - - strncpy (name, level.mapname, 8); - name[8] = 0; - p += snprintf (buffer+p, size-p, "\n\nCurrent map: %s", name); + p += snprintf (buffer+p, size-p, "\n\nCurrent map: %s", level.MapName.GetChars()); if (!viewactive) { @@ -257,7 +253,12 @@ int main (int argc, char **argv) #if defined(__MACH__) && !defined(NOASM) unprotect_rtext(); #endif - + + // Set LC_NUMERIC environment variable in case some library decides to + // clear the setlocale call at least this will be correct. + // Note that the LANG environment variable is overridden by LC_* + setenv ("LC_NUMERIC", "C", 1); + #ifndef NO_GTK GtkAvailable = gtk_init_check (&argc, &argv); #endif diff --git a/src/sdl/i_system.cpp b/src/sdl/i_system.cpp index def35606a..e46b8e59d 100644 --- a/src/sdl/i_system.cpp +++ b/src/sdl/i_system.cpp @@ -422,7 +422,27 @@ void I_SetIWADInfo () void I_PrintStr (const char *cp) { - fputs (cp, stdout); + // Strip out any color escape sequences before writing to the log file + char * copy = new char[strlen(cp)+1]; + const char * srcp = cp; + char * dstp = copy; + + while (*srcp != 0) + { + if (*srcp!=0x1c && *srcp!=0x1d && *srcp!=0x1e && *srcp!=0x1f) + { + *dstp++=*srcp++; + } + else + { + if (srcp[1]!=0) srcp+=2; + else break; + } + } + *dstp=0; + + fputs (copy, stdout); + delete [] copy; fflush (stdout); } @@ -684,8 +704,7 @@ int I_PickIWad (WadStuff *wads, int numwads, bool showwin, int defaultiwad) printf ("%d. %s (%s)\n", i+1, wads[i].Name.GetChars(), filepart); } printf ("Which one? "); - scanf ("%d", &i); - if (i > numwads) + if (scanf ("%d", &i) != 1 || i > numwads) return -1; return i-1; } @@ -699,7 +718,7 @@ bool I_WriteIniFailed () static const char *pattern; -#ifdef __APPLE__ +#if defined(__APPLE__) && MAC_OS_X_VERSION_MAX_ALLOWED < 1080 static int matchfile (struct dirent *ent) #else static int matchfile (const struct dirent *ent) diff --git a/src/sdl/i_video.h b/src/sdl/i_video.h deleted file mode 100644 index 2865df02f..000000000 --- a/src/sdl/i_video.h +++ /dev/null @@ -1,64 +0,0 @@ -// Emacs style mode select -*- C++ -*- -//----------------------------------------------------------------------------- -// -// $Id:$ -// -// Copyright (C) 1993-1996 by id Software, Inc. -// -// This source is available for distribution and/or modification -// only under the terms of the DOOM Source Code License as -// published by id Software. All rights reserved. -// -// The source is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License -// for more details. -// -// DESCRIPTION: -// System specific interface stuff. -// -//----------------------------------------------------------------------------- - - -#ifndef __I_VIDEO_H__ -#define __I_VIDEO_H__ - -#include "basictypes.h" - -class DCanvas; - -// [RH] Set the display mode -void I_SetMode (int &width, int &height, int &bits); - -// Takes full 8 bit values. -void I_SetPalette (DWORD *palette); - -void I_BeginUpdate (void); // [RH] Locks screen[0] -void I_FinishUpdate (void); -void I_FinishUpdateNoBlit (void); - -// Wait for vertical retrace or pause a bit. -void I_WaitVBL(int count); - -void I_ReadScreen (BYTE *scr); - -bool I_CheckResolution (int width, int height, int bits); -void I_ClosestResolution (int *width, int *height, int bits); -bool I_SetResolution (int width, int height, int bits); - -bool I_AllocateScreen (DCanvas *canvas, int width, int height, int bits); -void I_FreeScreen (DCanvas *canvas); - -void I_LockScreen (DCanvas *canvas); -void I_UnlockScreen (DCanvas *canvas); -void I_Blit (DCanvas *from, int srcx, int srcy, int srcwidth, int srcheight, - DCanvas *to, int destx, int desty, int destwidth, int destheight); - -enum EDisplayType -{ - DISPLAY_WindowOnly, - DISPLAY_FullscreenOnly, - DISPLAY_Both -}; - -#endif // __I_VIDEO_H__ diff --git a/src/sdl/iwadpicker_cocoa.mm b/src/sdl/iwadpicker_cocoa.mm index a0469ac7a..3b414d5e8 100644 --- a/src/sdl/iwadpicker_cocoa.mm +++ b/src/sdl/iwadpicker_cocoa.mm @@ -48,13 +48,16 @@ enum static const char* const tableHeaders[NUM_COLUMNS] = { "IWAD", "Game" }; // Class to convert the IWAD data into a form that Cocoa can use. -@interface IWADTableData : NSObject// +@interface IWADTableData : NSObject +#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1060 + +#endif { NSMutableArray *data; } - (void)dealloc; -- (IWADTableData *)init:(WadStuff *) wads:(int) numwads; +- (IWADTableData *)init:(WadStuff *) wads num:(int) numwads; - (int)numberOfRowsInTableView:(NSTableView *)aTableView; - (id)tableView:(NSTableView *)aTableView objectValueForTableColumn:(NSTableColumn *)aTableColumn row:(int)rowIndex; @@ -69,7 +72,7 @@ static const char* const tableHeaders[NUM_COLUMNS] = { "IWAD", "Game" }; [super dealloc]; } -- (IWADTableData *)init:(WadStuff *) wads:(int) numwads +- (IWADTableData *)init:(WadStuff *) wads num:(int) numwads { data = [[NSMutableArray alloc] initWithCapacity:numwads]; @@ -116,13 +119,13 @@ static const char* const tableHeaders[NUM_COLUMNS] = { "IWAD", "Game" }; - (void)buttonPressed:(id) sender; - (void)doubleClicked:(id) sender; -- (void)makeLabel:(NSTextField *)label:(const char*) str; -- (int)pickIWad:(WadStuff *)wads:(int) numwads:(bool) showwin:(int) defaultiwad; +- (void)makeLabel:(NSTextField *)label withString:(const char*) str; +- (int)pickIWad:(WadStuff *)wads num:(int) numwads showWindow:(bool) showwin defaultWad:(int) defaultiwad; @end @implementation IWADPicker -- (void)buttonPressed:(id) sender; +- (void)buttonPressed:(id) sender { if(sender == cancelButton) cancelled = true; @@ -131,7 +134,7 @@ static const char* const tableHeaders[NUM_COLUMNS] = { "IWAD", "Game" }; [app stopModal]; } -- (void)doubleClicked:(id) sender; +- (void)doubleClicked:(id) sender { if ([sender clickedRow] >= 0) { @@ -142,7 +145,7 @@ static const char* const tableHeaders[NUM_COLUMNS] = { "IWAD", "Game" }; // Apparently labels in Cocoa are uneditable text fields, so lets make this a // little more automated. -- (void)makeLabel:(NSTextField *)label:(const char*) str +- (void)makeLabel:(NSTextField *)label withString:(const char*) str { [label setStringValue:[NSString stringWithUTF8String:str]]; [label setBezeled:NO]; @@ -151,7 +154,7 @@ static const char* const tableHeaders[NUM_COLUMNS] = { "IWAD", "Game" }; [label setSelectable:NO]; } -- (int)pickIWad:(WadStuff *)wads:(int) numwads:(bool) showwin:(int) defaultiwad +- (int)pickIWad:(WadStuff *)wads num:(int) numwads showWindow:(bool) showwin defaultWad:(int) defaultiwad { cancelled = false; @@ -163,7 +166,7 @@ static const char* const tableHeaders[NUM_COLUMNS] = { "IWAD", "Game" }; [window setTitle:windowTitle]; NSTextField *description = [[NSTextField alloc] initWithFrame:NSMakeRect(22, 379, 412, 50)]; - [self makeLabel:description:"ZDoom found more than one IWAD\nSelect from the list below to determine which one to use:"]; + [self makeLabel:description withString:"ZDoom found more than one IWAD\nSelect from the list below to determine which one to use:"]; [[window contentView] addSubview:description]; [description release]; @@ -171,7 +174,7 @@ static const char* const tableHeaders[NUM_COLUMNS] = { "IWAD", "Game" }; //NSScrollView *iwadScroller = [[NSScrollView alloc] initWithFrame:NSMakeRect(20, 103, 412, 288)]; NSScrollView *iwadScroller = [[NSScrollView alloc] initWithFrame:NSMakeRect(20, 50, 412, 341)]; NSTableView *iwadTable = [[NSTableView alloc] initWithFrame:[iwadScroller bounds]]; - IWADTableData *tableData = [[IWADTableData alloc] init:wads:numwads]; + IWADTableData *tableData = [[IWADTableData alloc] init:wads num:numwads]; for(int i = 0;i < NUM_COLUMNS;i++) { NSTableColumn *column = [[NSTableColumn alloc] initWithIdentifier:[NSString stringWithUTF8String:tableHeaders[i]]]; @@ -242,7 +245,7 @@ static const char* const tableHeaders[NUM_COLUMNS] = { "IWAD", "Game" }; int I_PickIWad_Cocoa (WadStuff *wads, int numwads, bool showwin, int defaultiwad) { IWADPicker *picker = [IWADPicker alloc]; - int ret = [picker pickIWad:wads:numwads:showwin:defaultiwad]; + int ret = [picker pickIWad:wads num:numwads showWindow:showwin defaultWad:defaultiwad]; [picker release]; return ret; } diff --git a/src/sdl/sdlvideo.cpp b/src/sdl/sdlvideo.cpp index 2f11b8bbd..92741d325 100644 --- a/src/sdl/sdlvideo.cpp +++ b/src/sdl/sdlvideo.cpp @@ -87,6 +87,10 @@ EXTERN_CVAR (Bool, cl_capfps) CVAR (Int, vid_displaybits, 8, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) +// vid_asyncblit needs a restart to work. SDL doesn't seem to change if the +// frame buffer is changed at run time. +CVAR (Bool, vid_asyncblit, 1, CVAR_NOINITCALL|CVAR_ARCHIVE|CVAR_GLOBALCONFIG) + CUSTOM_CVAR (Float, rgamma, 1.f, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) { if (screen != NULL) @@ -301,9 +305,8 @@ SDLFB::SDLFB (int width, int height, bool fullscreen) UpdatePending = false; NotPaletted = false; FlashAmount = 0; - Screen = SDL_SetVideoMode (width, height, vid_displaybits, - SDL_HWSURFACE|SDL_HWPALETTE|SDL_DOUBLEBUF|SDL_ANYFORMAT| + (vid_asyncblit ? SDL_ASYNCBLIT : 0)|SDL_HWSURFACE|SDL_HWPALETTE|SDL_DOUBLEBUF|SDL_ANYFORMAT| (fullscreen ? SDL_FULLSCREEN : 0)); if (Screen == NULL) diff --git a/src/sound/fmodsound.cpp b/src/sound/fmodsound.cpp index 1bd98a16b..081401300 100644 --- a/src/sound/fmodsound.cpp +++ b/src/sound/fmodsound.cpp @@ -63,7 +63,7 @@ extern HWND Window; #include "cmdlib.h" #include "s_sound.h" -#if FMOD_VERSION > 0x42899 && FMOD_VERSION < 0x43800 +#if FMOD_VERSION > 0x42899 && FMOD_VERSION < 0x43600 #error You are trying to compile with an unsupported version of FMOD. #endif @@ -630,7 +630,9 @@ bool FMODSoundRenderer::IsValid() // //========================================================================== +#ifndef FACILITY_VISUALCPP #define FACILITY_VISUALCPP ((LONG)0x6d) +#endif #define VcppException(sev,err) ((sev) | (FACILITY_VISUALCPP<<16) | err) static int CheckException(DWORD code) @@ -817,7 +819,7 @@ bool FMODSoundRenderer::Init() } result = Sys->getNumDrivers(&driver); -#ifdef unix +#ifdef __unix__ if (result == FMOD_OK) { // On Linux, FMOD defaults to OSS. If OSS is not present, it doesn't @@ -857,7 +859,7 @@ bool FMODSoundRenderer::Init() result = Sys->setDriver(driver); } result = Sys->getDriver(&driver); -#if FMOD_VERSION >= 0x43700 +#if FMOD_VERSION >= 0x43600 // We were built with an FMOD that only returns the control panel frequency result = Sys->getDriverCaps(driver, &Driver_Caps, &Driver_MinFrequency, &speakermode); Driver_MaxFrequency = Driver_MinFrequency; @@ -1042,7 +1044,7 @@ bool FMODSoundRenderer::Init() } // Create DSP units for underwater effect -#if FMOD_VERSION < 0x43701 +#if FMOD_VERSION < 0x43600 result = Sys->createDSPByType(FMOD_DSP_TYPE_LOWPASS, &WaterLP); if (result != FMOD_OK) { @@ -1105,7 +1107,7 @@ bool FMODSoundRenderer::Init() WaterLP->setActive(false); WaterLP->setParameter(FMOD_DSP_LOWPASS_CUTOFF, snd_waterlp); WaterLP->setParameter(FMOD_DSP_LOWPASS_RESONANCE, 2); -#if FMOD_VERSION < 0x43701 +#if FMOD_VERSION < 0x43600 if (WaterReverb != NULL) { FMOD::DSPConnection *dry; diff --git a/src/sound/i_musicinterns.h b/src/sound/i_musicinterns.h index 3c1134c63..fa04cfa51 100644 --- a/src/sound/i_musicinterns.h +++ b/src/sound/i_musicinterns.h @@ -709,7 +709,7 @@ class OPLMUSDumper : public OPLMUSSong { public: OPLMUSDumper(const OPLMUSSong *original, const char *filename); - void Play(bool looping); + void Play(bool looping, int); }; // CD track/disk played through the multimedia system ----------------------- diff --git a/src/sound/music_fluidsynth_mididevice.cpp b/src/sound/music_fluidsynth_mididevice.cpp index 53a93fe09..af8fe6667 100644 --- a/src/sound/music_fluidsynth_mididevice.cpp +++ b/src/sound/music_fluidsynth_mididevice.cpp @@ -295,7 +295,7 @@ FluidSynthMIDIDevice::FluidSynthMIDIDevice() fluid_chorus_speed, fluid_chorus_depth, fluid_chorus_type); if (0 == LoadPatchSets(fluid_patchset)) { -#ifdef unix +#ifdef __unix__ // This is the standard location on Ubuntu. if (0 == LoadPatchSets("/usr/share/sounds/sf2/FluidR3_GS.sf2:/usr/share/sounds/sf2/FluidR3_GM.sf2")) { @@ -322,7 +322,7 @@ FluidSynthMIDIDevice::FluidSynthMIDIDevice() } } #endif -#ifdef unix +#ifdef __unix__ } #endif } diff --git a/src/sound/music_gme.cpp b/src/sound/music_gme.cpp index 0c3d8c8c3..7f017b7d2 100644 --- a/src/sound/music_gme.cpp +++ b/src/sound/music_gme.cpp @@ -40,7 +40,7 @@ #include "i_musicinterns.h" #include "c_cvars.h" #include "critsec.h" -#include "gme.h" +#include #include "v_text.h" // MACROS ------------------------------------------------------------------ diff --git a/src/sound/music_mus_opl.cpp b/src/sound/music_mus_opl.cpp index 156094e1b..fb0d78df5 100644 --- a/src/sound/music_mus_opl.cpp +++ b/src/sound/music_mus_opl.cpp @@ -100,7 +100,7 @@ OPLMUSDumper::OPLMUSDumper(const OPLMUSSong *original, const char *filename) { } -void OPLMUSDumper::Play(bool looping) +void OPLMUSDumper::Play(bool looping, int) { Music->Dump(); } diff --git a/src/st_stuff.cpp b/src/st_stuff.cpp index 8679e967c..84982300c 100644 --- a/src/st_stuff.cpp +++ b/src/st_stuff.cpp @@ -484,7 +484,7 @@ static bool Cht_ChangeStartSpot (cheatseq_t *cheat) { char cmd[64]; - mysnprintf (cmd, countof(cmd), "changemap %s %c", level.mapname, cheat->Args[0]); + mysnprintf (cmd, countof(cmd), "changemap %s %c", level.MapName.GetChars(), cheat->Args[0]); C_DoCommand (cmd); return true; } diff --git a/src/statistics.cpp b/src/statistics.cpp index 81cd88983..acd8440e8 100644 --- a/src/statistics.cpp +++ b/src/statistics.cpp @@ -408,12 +408,13 @@ static void StoreLevelStats() { for(i=0;i 0) { - entry = (StringEntry *)M_Malloc (sizeof(*entry) + strText.Len() + strName.Len()); + entry = (StringEntry *)M_Malloc (sizeof(*entry) + strText.Len() + strName.Len() + 2); entry->Next = *pentry; *pentry = entry; strcpy (entry->String, strText.GetChars()); @@ -409,7 +409,7 @@ void FStringTable::SetString (const char *name, const char *newString) size_t namelen = strlen (name); // Create a new string entry - StringEntry *entry = (StringEntry *)M_Malloc (sizeof(*entry) + newlen + namelen); + StringEntry *entry = (StringEntry *)M_Malloc (sizeof(*entry) + newlen + namelen + 2); strcpy (entry->String, newString); strcpy (entry->Name = entry->String + newlen + 1, name); entry->PassNum = 0; diff --git a/src/textures/animations.cpp b/src/textures/animations.cpp index 5a6f0729a..58ef7a5ca 100644 --- a/src/textures/animations.cpp +++ b/src/textures/animations.cpp @@ -231,8 +231,8 @@ void FTextureManager::InitAnimated (void) if (debuganimated) { Printf("Defining animation '%s' (texture %d, lump %d, file %d) to '%s' (texture %d, lump %d, file %d)\n", - tex1->Name, pic1.GetIndex(), tex1->GetSourceLump(), Wads.GetLumpFile(tex1->GetSourceLump()), - tex2->Name, pic2.GetIndex(), tex2->GetSourceLump(), Wads.GetLumpFile(tex2->GetSourceLump())); + tex1->Name.GetChars(), pic1.GetIndex(), tex1->GetSourceLump(), Wads.GetLumpFile(tex1->GetSourceLump()), + tex2->Name.GetChars(), pic2.GetIndex(), tex2->GetSourceLump(), Wads.GetLumpFile(tex2->GetSourceLump())); } if (pic1 == pic2) @@ -551,7 +551,7 @@ void FTextureManager::ParseTime (FScanner &sc, DWORD &min, DWORD &max) void FTextureManager::ParseWarp(FScanner &sc) { - const BITFIELD texflags = TEXMAN_Overridable | TEXMAN_TryAny; + const BITFIELD texflags = TEXMAN_Overridable | TEXMAN_TryAny | TEXMAN_ShortNameOnly; bool isflat = false; bool type2 = sc.Compare ("warp2"); // [GRB] sc.MustGetString (); @@ -616,7 +616,7 @@ void FTextureManager::ParseWarp(FScanner &sc) void FTextureManager::ParseCameraTexture(FScanner &sc) { - const BITFIELD texflags = TEXMAN_Overridable | TEXMAN_TryAny; + const BITFIELD texflags = TEXMAN_Overridable | TEXMAN_TryAny | TEXMAN_ShortNameOnly; int width, height; int fitwidth, fitheight; FString picname; @@ -749,8 +749,11 @@ void FTextureManager::ParseAnimatedDoor(FScanner &sc) { error = true; } - - while (sc.GetString ()) + else + { + Texture(anim.BaseTexture)->bNoDecals = true; + } + while (sc.GetString()) { if (sc.Compare ("opensound")) { @@ -776,8 +779,12 @@ void FTextureManager::ParseAnimatedDoor(FScanner &sc) { sc.ScriptError ("Unknown texture %s", sc.String); } - frames.Push (v); } + frames.Push(v); + } + else if (sc.Compare("allowdecals")) + { + if (anim.BaseTexture.Exists()) Texture(anim.BaseTexture)->bNoDecals = false; } else { diff --git a/src/textures/buildtexture.cpp b/src/textures/buildtexture.cpp index e534ca9c8..ee5f66fab 100644 --- a/src/textures/buildtexture.cpp +++ b/src/textures/buildtexture.cpp @@ -78,7 +78,7 @@ FBuildTexture::FBuildTexture (int tilenum, const BYTE *pixels, int width, int he LeftOffset = left; TopOffset = top; CalcBitSize (); - mysnprintf (Name, countof(Name), "BTIL%04d", tilenum); + Name.Format("BTIL%04d", tilenum); UseType = TEX_Build; } diff --git a/src/textures/canvastexture.cpp b/src/textures/canvastexture.cpp index a6e1918df..8bfd1946b 100644 --- a/src/textures/canvastexture.cpp +++ b/src/textures/canvastexture.cpp @@ -41,8 +41,7 @@ FCanvasTexture::FCanvasTexture (const char *name, int width, int height) { - strncpy (Name, name, 8); - Name[8] = 0; + Name = name; Width = width; Height = height; LeftOffset = TopOffset = 0; diff --git a/src/textures/imgztexture.cpp b/src/textures/imgztexture.cpp index 36f954b95..153880d67 100644 --- a/src/textures/imgztexture.cpp +++ b/src/textures/imgztexture.cpp @@ -106,7 +106,6 @@ FIMGZTexture::FIMGZTexture (int lumpnum, WORD w, WORD h, SWORD l, SWORD t) : FTexture(NULL, lumpnum), Pixels(0), Spans(0) { Wads.GetLumpName (Name, lumpnum); - Name[8] = 0; Width = w; Height = h; LeftOffset = l; diff --git a/src/textures/jpegtexture.cpp b/src/textures/jpegtexture.cpp index 3a87f70af..849cec645 100644 --- a/src/textures/jpegtexture.cpp +++ b/src/textures/jpegtexture.cpp @@ -448,7 +448,7 @@ void FJPEGTexture::MakeTexture () } catch (int) { - Printf (TEXTCOLOR_ORANGE " in texture %s\n", Name); + Printf (TEXTCOLOR_ORANGE " in texture %s\n", Name.GetChars()); jpeg_destroy_decompress(&cinfo); } if (buff != NULL) @@ -532,7 +532,7 @@ int FJPEGTexture::CopyTrueColorPixels(FBitmap *bmp, int x, int y, int rotate, FC } catch(int) { - Printf (TEXTCOLOR_ORANGE " in JPEG texture %s\n", Name); + Printf (TEXTCOLOR_ORANGE " in JPEG texture %s\n", Name.GetChars()); } jpeg_destroy_decompress(&cinfo); if (buff != NULL) delete [] buff; diff --git a/src/textures/multipatchtexture.cpp b/src/textures/multipatchtexture.cpp index fd2b59fb1..348ad3a98 100644 --- a/src/textures/multipatchtexture.cpp +++ b/src/textures/multipatchtexture.cpp @@ -47,6 +47,7 @@ #include "colormatcher.h" #include "v_palette.h" #include "v_video.h" +#include "v_text.h" #include "m_fixed.h" #include "textures/textures.h" #include "r_data/colormaps.h" @@ -136,7 +137,7 @@ struct strifemaptexture_t struct FPatchLookup { - char Name[9]; + FString Name; FTexture *Texture; }; @@ -242,9 +243,7 @@ FMultiPatchTexture::FMultiPatchTexture (const void *texdef, FPatchLookup *patchl Parts = NumParts > 0 ? new TexPart[NumParts] : NULL; Width = SAFESHORT(mtexture.d->width); Height = SAFESHORT(mtexture.d->height); - strncpy (Name, (const char *)mtexture.d->name, 8); - Name[8] = 0; - + Name = (char *)mtexture.d->name; CalcBitSize (); xScale = mtexture.d->ScaleX ? mtexture.d->ScaleX*(FRACUNIT/8) : FRACUNIT; @@ -269,17 +268,21 @@ FMultiPatchTexture::FMultiPatchTexture (const void *texdef, FPatchLookup *patchl if (unsigned(LittleShort(mpatch.d->patch)) >= unsigned(maxpatchnum)) { I_FatalError ("Bad PNAMES and/or texture directory:\n\nPNAMES has %d entries, but\n%s wants to use entry %d.", - maxpatchnum, Name, LittleShort(mpatch.d->patch)+1); + maxpatchnum, Name.GetChars(), LittleShort(mpatch.d->patch)+1); } Parts[i].OriginX = LittleShort(mpatch.d->originx); Parts[i].OriginY = LittleShort(mpatch.d->originy); Parts[i].Texture = patchlookup[LittleShort(mpatch.d->patch)].Texture; if (Parts[i].Texture == NULL) { - Printf ("Unknown patch %s in texture %s\n", patchlookup[LittleShort(mpatch.d->patch)].Name, Name); + Printf(TEXTCOLOR_RED "Unknown patch %s in texture %s\n", patchlookup[LittleShort(mpatch.d->patch)].Name.GetChars(), Name.GetChars()); NumParts--; i--; } + else + { + Parts[i].Texture->bKeepAround = true; + } if (strife) mpatch.s++; else @@ -287,7 +290,7 @@ FMultiPatchTexture::FMultiPatchTexture (const void *texdef, FPatchLookup *patchl } if (NumParts == 0) { - Printf ("Texture %s is left without any patches\n", Name); + Printf ("Texture %s is left without any patches\n", Name.GetChars()); } CheckForHacks (); @@ -820,7 +823,7 @@ FMultiPatchTexture::TexPart::TexPart() void FTextureManager::AddTexturesLump (const void *lumpdata, int lumpsize, int deflumpnum, int patcheslump, int firstdup, bool texture1) { - FPatchLookup *patchlookup; + FPatchLookup *patchlookup = NULL; int i; DWORD numpatches; @@ -853,13 +856,13 @@ void FTextureManager::AddTexturesLump (const void *lumpdata, int lumpsize, int d // Catalog the patches these textures use so we know which // textures they represent. - patchlookup = (FPatchLookup *)alloca (numpatches * sizeof(*patchlookup)); - + patchlookup = new FPatchLookup[numpatches]; for (DWORD i = 0; i < numpatches; ++i) { - pnames.Read (patchlookup[i].Name, 8); - patchlookup[i].Name[8] = 0; - + char pname[9]; + pnames.Read(pname, 8); + pname[8] = '\0'; + patchlookup[i].Name = pname; FTextureID j = CheckForTexture (patchlookup[i].Name, FTexture::TEX_WallPatch); if (j.isValid()) { @@ -889,6 +892,7 @@ void FTextureManager::AddTexturesLump (const void *lumpdata, int lumpsize, int d if (maxoff < DWORD(numtextures+1)*4) { Printf ("Texture directory is too short"); + delete[] patchlookup; return; } @@ -899,6 +903,7 @@ void FTextureManager::AddTexturesLump (const void *lumpdata, int lumpsize, int d if (offset > maxoff) { Printf ("Bad texture directory"); + delete[] patchlookup; return; } @@ -934,6 +939,7 @@ void FTextureManager::AddTexturesLump (const void *lumpdata, int lumpsize, int d if (offset > maxoff) { Printf ("Bad texture directory"); + delete[] patchlookup; return; } @@ -957,6 +963,7 @@ void FTextureManager::AddTexturesLump (const void *lumpdata, int lumpsize, int d StartScreen->Progress(); } } + delete[] patchlookup; } @@ -999,21 +1006,7 @@ void FMultiPatchTexture::ParsePatch(FScanner &sc, TexPart & part, bool silent, i if (!texno.isValid()) { - int lumpnum = Wads.CheckNumForFullName(sc.String); - if (lumpnum >= 0) - { - texno = TexMan.FindTextureByLumpNum(lumpnum); - if (texno.isValid ()) - { - part.Texture = TexMan[texno]; - } - else - { - part.Texture = FTexture::CreateTexture("", lumpnum, usetype); - TexMan.AddTexture(part.Texture); - } - } - else if (strlen(sc.String) <= 8 && !strpbrk(sc.String, "./")) + if (strlen(sc.String) <= 8 && !strpbrk(sc.String, "./")) { int lumpnum = Wads.CheckNumForName(sc.String, usetype == TEX_MiscPatch? ns_graphics : ns_patches); if (lumpnum >= 0) @@ -1030,7 +1023,7 @@ void FMultiPatchTexture::ParsePatch(FScanner &sc, TexPart & part, bool silent, i } if (part.Texture == NULL) { - if (!silent) Printf("Unknown patch '%s' in texture '%s'\n", sc.String, Name); + if (!silent) Printf(TEXTCOLOR_RED "Unknown patch '%s' in texture '%s'\n", sc.String, Name.GetChars()); } sc.MustGetStringName(","); sc.MustGetNumber(); @@ -1232,8 +1225,8 @@ FMultiPatchTexture::FMultiPatchTexture (FScanner &sc, int usetype) bSilent = false; } } - uppercopy(Name, !textureName ? sc.String : textureName); - Name[8] = 0; + Name = !textureName ? sc.String : textureName; + Name.ToUpper(); sc.MustGetStringName(","); sc.MustGetNumber(); Width = sc.Number; @@ -1251,13 +1244,13 @@ FMultiPatchTexture::FMultiPatchTexture (FScanner &sc, int usetype) { sc.MustGetFloat(); xScale = FLOAT2FIXED(sc.Float); - if (xScale == 0) sc.ScriptError("Texture %s is defined with null x-scale\n", Name); + if (xScale == 0) sc.ScriptError("Texture %s is defined with null x-scale\n", Name.GetChars()); } else if (sc.Compare("YScale")) { sc.MustGetFloat(); yScale = FLOAT2FIXED(sc.Float); - if (yScale == 0) sc.ScriptError("Texture %s is defined with null y-scale\n", Name); + if (yScale == 0) sc.ScriptError("Texture %s is defined with null y-scale\n", Name.GetChars()); } else if (sc.Compare("WorldPanning")) { @@ -1325,7 +1318,7 @@ FMultiPatchTexture::FMultiPatchTexture (FScanner &sc, int usetype) if (Width <= 0 || Height <= 0) { UseType = FTexture::TEX_Null; - Printf("Texture %s has invalid dimensions (%d, %d)\n", Name, Width, Height); + Printf("Texture %s has invalid dimensions (%d, %d)\n", Name.GetChars(), Width, Height); Width = Height = 1; } CalcBitSize (); diff --git a/src/textures/texture.cpp b/src/textures/texture.cpp index 093bf303b..6ee6ccb0a 100644 --- a/src/textures/texture.cpp +++ b/src/textures/texture.cpp @@ -137,7 +137,10 @@ FTexture * FTexture::CreateTexture (int lumpnum, int usetype) FTexture * FTexture::CreateTexture (const char *name, int lumpnum, int usetype) { FTexture *tex = CreateTexture(lumpnum, usetype); - if (tex != NULL && name != NULL) uppercopy(tex->Name, name); + if (tex != NULL && name != NULL) { + tex->Name = name; + tex->Name.ToUpper(); + } return tex; } @@ -146,27 +149,29 @@ FTexture::FTexture (const char *name, int lumpnum) : LeftOffset(0), TopOffset(0), WidthBits(0), HeightBits(0), xScale(FRACUNIT), yScale(FRACUNIT), SourceLump(lumpnum), UseType(TEX_Any), bNoDecals(false), bNoRemap0(false), bWorldPanning(false), - bMasked(true), bAlphaTexture(false), bHasCanvas(false), bWarped(0), bComplex(false), bMultiPatch(false), + bMasked(true), bAlphaTexture(false), bHasCanvas(false), bWarped(0), bComplex(false), bMultiPatch(false), bKeepAround(false), Rotations(0xFFFF), SkyOffset(0), Width(0), Height(0), WidthMask(0), Native(NULL) { id.SetInvalid(); if (name != NULL) { - uppercopy(Name, name); + Name = name; + Name.ToUpper(); } else if (lumpnum < 0) { - *Name = 0; + Name = FString(); } else { Wads.GetLumpName (Name, lumpnum); - Name[8] = 0; } } FTexture::~FTexture () { + FTexture *link = Wads.GetLinkedTexture(SourceLump); + if (link == this) Wads.SetLinkedTexture(SourceLump, NULL); KillNative(); } @@ -572,7 +577,6 @@ FDummyTexture::FDummyTexture () HeightBits = 6; WidthBits = 6; WidthMask = 63; - Name[0] = 0; UseType = TEX_Null; } diff --git a/src/textures/texturemanager.cpp b/src/textures/texturemanager.cpp index f28026f19..a79769c3d 100644 --- a/src/textures/texturemanager.cpp +++ b/src/textures/texturemanager.cpp @@ -220,8 +220,38 @@ FTextureID FTextureManager::CheckForTexture (const char *name, int usetype, BITF { if (firsttype == FTexture::TEX_Null) return FTextureID(0); if (firsttype == FTexture::TEX_FirstDefined && !(flags & TEXMAN_ReturnFirst)) return FTextureID(0); + return FTextureID(firstfound); + } + } + + + if (!(flags & TEXMAN_ShortNameOnly)) + { + // We intentionally only look for textures in subdirectories. + // Any graphic being placed in the zip's root directory can not be found by this. + if (strchr(name, '/')) + { + FTexture *const NO_TEXTURE = (FTexture*)-1; + int lump = Wads.CheckNumForFullName(name); + if (lump >= 0) + { + FTexture *tex = Wads.GetLinkedTexture(lump); + if (tex == NO_TEXTURE) return FTextureID(-1); + if (tex != NULL) return tex->id; + if (flags & TEXMAN_DontCreate) return FTextureID(-1); // we only want to check, there's no need to create a texture if we don't have one yet. + tex = FTexture::CreateTexture("", lump, FTexture::TEX_Override); + if (tex != NULL) + { + Wads.SetLinkedTexture(lump, tex); + return AddTexture(tex); + } + else + { + // mark this lump as having no valid texture so that we don't have to retry creating one later. + Wads.SetLinkedTexture(lump, NO_TEXTURE); + } + } } - return FTextureID(firstfound); } return FTextureID(-1); @@ -273,30 +303,6 @@ int FTextureManager::ListTextures (const char *name, TArray &list) return list.Size(); } -//========================================================================== -// -// FTextureManager :: FindTextureByLumpNum -// -//========================================================================== - -FTextureID FTextureManager::FindTextureByLumpNum (int lumpnum) -{ - if (lumpnum < 0) - { - return FTextureID(-1); - } - // This can't use hashing because using ReplaceTexture would break the hash chains. :( - for(unsigned i = 0; i SourceLump == lumpnum) - { - return FTextureID(i); - } - } - return FTextureID(-1); -} - - //========================================================================== // // FTextureManager :: GetTextures @@ -367,7 +373,7 @@ FTextureID FTextureManager::AddTexture (FTexture *texture) // Later textures take precedence over earlier ones // Textures without name can't be looked for - if (texture->Name[0] != 0) + if (texture->Name[0] != '\0') { bucket = int(MakeKey (texture->Name) % HASH_SIZE); hash = HashFirst[bucket]; @@ -423,12 +429,12 @@ void FTextureManager::ReplaceTexture (FTextureID picnum, FTexture *newtexture, b FTexture *oldtexture = Textures[index].Texture; - strcpy (newtexture->Name, oldtexture->Name); + newtexture->Name = oldtexture->Name; newtexture->UseType = oldtexture->UseType; Textures[index].Texture = newtexture; newtexture->id = oldtexture->id; - if (free) + if (free && !oldtexture->bKeepAround) { delete oldtexture; } @@ -482,9 +488,7 @@ void FTextureManager::AddGroup(int wadnum, int ns, int usetype) { int firsttx = Wads.GetFirstLump(wadnum); int lasttx = Wads.GetLastLump(wadnum); - char name[9]; - - name[8] = 0; + FString Name; // Go from first to last so that ANIMDEFS work as expected. However, // to avoid duplicates (and to keep earlier entries from overriding @@ -495,9 +499,9 @@ void FTextureManager::AddGroup(int wadnum, int ns, int usetype) { if (Wads.GetLumpNamespace(firsttx) == ns) { - Wads.GetLumpName (name, firsttx); + Wads.GetLumpName (Name, firsttx); - if (Wads.CheckNumForName (name, ns) == firsttx) + if (Wads.CheckNumForName (Name, ns) == firsttx) { CreateTexture (firsttx, usetype); } @@ -505,7 +509,7 @@ void FTextureManager::AddGroup(int wadnum, int ns, int usetype) } else if (ns == ns_flats && Wads.GetLumpFlags(firsttx) & LUMPF_MAYBEFLAT) { - if (Wads.CheckNumForName (name, ns) < firsttx) + if (Wads.CheckNumForName (Name, ns) < firsttx) { CreateTexture (firsttx, usetype); } @@ -525,7 +529,7 @@ void FTextureManager::AddHiresTextures (int wadnum) int firsttx = Wads.GetFirstLump(wadnum); int lasttx = Wads.GetLastLump(wadnum); - char name[9]; + FString Name; TArray tlist; if (firsttx == -1 || lasttx == -1) @@ -533,18 +537,16 @@ void FTextureManager::AddHiresTextures (int wadnum) return; } - name[8] = 0; - for (;firsttx <= lasttx; ++firsttx) { if (Wads.GetLumpNamespace(firsttx) == ns_hires) { - Wads.GetLumpName (name, firsttx); + Wads.GetLumpName (Name, firsttx); - if (Wads.CheckNumForName (name, ns_hires) == firsttx) + if (Wads.CheckNumForName (Name, ns_hires) == firsttx) { tlist.Clear(); - int amount = ListTextures(name, tlist); + int amount = ListTextures(Name, tlist); if (amount == 0) { // A texture with this name does not yet exist @@ -588,14 +590,13 @@ void FTextureManager::AddHiresTextures (int wadnum) void FTextureManager::LoadTextureDefs(int wadnum, const char *lumpname) { int remapLump, lastLump; - char src[9]; + FString src; bool is32bit; int width, height; int type, mode; TArray tlist; lastLump = 0; - src[8] = '\0'; while ((remapLump = Wads.FindLump(lumpname, &lastLump)) != -1) { @@ -672,7 +673,7 @@ void FTextureManager::LoadTextureDefs(int wadnum, const char *lumpname) FString base = ExtractFileBase(sc.String, false); if (!base.IsEmpty()) { - strncpy(src, base, 8); + src = base.Left(8); int lumpnum = Wads.CheckNumForFullName(sc.String, true, ns_patches); if (lumpnum == -1) lumpnum = Wads.CheckNumForFullName(sc.String, true, ns_graphics); @@ -695,7 +696,7 @@ void FTextureManager::LoadTextureDefs(int wadnum, const char *lumpname) // Replace the entire texture and adjust the scaling and offset factors. newtex->bWorldPanning = true; newtex->SetScaledSize(width, height); - memcpy(newtex->Name, src, sizeof(newtex->Name)); + newtex->Name = src; FTextureID oldtex = TexMan.CheckForTexture(src, FTexture::TEX_MiscPatch); if (oldtex.isValid()) @@ -751,7 +752,7 @@ void FTextureManager::AddPatches (int lumpnum) char name[9]; *file >> numpatches; - name[8] = 0; + name[8] = '\0'; for (i = 0; i < numpatches; ++i) { @@ -833,9 +834,8 @@ void FTextureManager::AddTexturesForWad(int wadnum) for (int i= firsttx; i <= lasttx; i++) { bool skin = false; - char name[9]; - Wads.GetLumpName(name, i); - name[8]=0; + FString Name; + Wads.GetLumpName(Name, i); // Ignore anything not in the global namespace int ns = Wads.GetLumpNamespace(i); @@ -861,20 +861,20 @@ void FTextureManager::AddTexturesForWad(int wadnum) if (Wads.CheckLumpName(i, "BEHAVIOR")) continue; // Don't bother looking at this lump if something later overrides it. - if (Wads.CheckNumForName(name, ns_graphics) != i) continue; + if (Wads.CheckNumForName(Name, ns_graphics) != i) continue; // skip this if it has already been added as a wall patch. - if (CheckForTexture(name, FTexture::TEX_WallPatch, 0).Exists()) continue; + if (CheckForTexture(Name, FTexture::TEX_WallPatch, 0).Exists()) continue; } else if (ns == ns_graphics) { // Don't bother looking this lump if something later overrides it. - if (Wads.CheckNumForName(name, ns_graphics) != i) continue; + if (Wads.CheckNumForName(Name, ns_graphics) != i) continue; } else if (ns >= ns_firstskin) { // Don't bother looking this lump if something later overrides it. - if (Wads.CheckNumForName(name, ns) != i) continue; + if (Wads.CheckNumForName(Name, ns) != i) continue; skin = true; } else continue; @@ -949,7 +949,7 @@ void FTextureManager::SortTexturesByType(int start, int end) { if (newtextures[j] != NULL) { - Printf("Texture %s has unknown type!\n", newtextures[j]->Name); + Printf("Texture %s has unknown type!\n", newtextures[j]->Name.GetChars()); AddTexture(newtextures[j]); } } @@ -1004,7 +1004,7 @@ void FTextureManager::Init() { if (wadlevelinfos[i].flags & LEVEL_DOUBLESKY) { - FTextureID picnum = CheckForTexture (wadlevelinfos[i].skypic1, FTexture::TEX_Wall, false); + FTextureID picnum = CheckForTexture (wadlevelinfos[i].SkyPic1, FTexture::TEX_Wall, false); if (picnum.isValid()) { Textures[picnum.GetIndex()].Texture->SetFrontSkyLayer (); @@ -1093,8 +1093,15 @@ void FTextureManager::WriteTexture (FArchive &arc, int picnum) pic = Textures[picnum].Texture; } - arc.WriteName (pic->Name); - arc.WriteCount (pic->UseType); + if (Wads.GetLinkedTexture(pic->SourceLump) == pic) + { + arc.WriteName(Wads.GetLumpFullName(pic->SourceLump)); + } + else + { + arc.WriteName(pic->Name); + } + arc.WriteCount(pic->UseType); } //========================================================================== diff --git a/src/textures/textures.h b/src/textures/textures.h index 100ba31e9..9dbd85a55 100644 --- a/src/textures/textures.h +++ b/src/textures/textures.h @@ -107,8 +107,6 @@ struct FDoorAnimation FName CloseSound; }; - - // Patches. // A patch holds one or more columns. // Patches are used for sprites and all masked pictures, and we compose @@ -119,7 +117,7 @@ struct patch_t SWORD height; SWORD leftoffset; // pixels to the left of origin SWORD topoffset; // pixels below the origin - DWORD columnofs[8]; // only [width] used + DWORD columnofs[]; // only [width] used // the [0] is &columnofs[width] }; @@ -159,11 +157,7 @@ public: int SourceLump; FTextureID id; - union - { - char Name[9]; - DWORD dwName; // Used with sprites - }; + FString Name; BYTE UseType; // This texture's primary purpose BYTE bNoDecals:1; // Decals should not stick to texture @@ -177,6 +171,7 @@ public: // fully composited before subjected to any kind of postprocessing instead of // doing it per patch. BYTE bMultiPatch:1; // This is a multipatch texture (we really could use real type info for textures...) + BYTE bKeepAround:1; // This texture was used as part of a multi-patch texture. Do not free it. WORD Rotations; SWORD SkyOffset; @@ -218,7 +213,6 @@ public: virtual int GetSourceLump() { return SourceLump; } virtual FTexture *GetRedirect(bool wantwarped); virtual FTexture *GetRawTexture(); // for FMultiPatchTexture to override - FTextureID GetID() const { return id; } virtual void Unload () = 0; @@ -364,12 +358,13 @@ public: TEXMAN_TryAny = 1, TEXMAN_Overridable = 2, TEXMAN_ReturnFirst = 4, - TEXMAN_AllowSkins = 8 + TEXMAN_AllowSkins = 8, + TEXMAN_ShortNameOnly = 16, + TEXMAN_DontCreate = 32 }; FTextureID CheckForTexture (const char *name, int usetype, BITFIELD flags=TEXMAN_TryAny); FTextureID GetTexture (const char *name, int usetype, BITFIELD flags=0); - FTextureID FindTextureByLumpNum (int lumpnum); int ListTextures (const char *name, TArray &list); void AddTexturesLump (const void *lumpdata, int lumpsize, int deflumpnum, int patcheslump, int firstdup=0, bool texture1=false); diff --git a/src/textures/tgatexture.cpp b/src/textures/tgatexture.cpp index 374861699..cff89603c 100644 --- a/src/textures/tgatexture.cpp +++ b/src/textures/tgatexture.cpp @@ -145,7 +145,6 @@ FTGATexture::FTGATexture (int lumpnum, TGAHeader * hdr) : FTexture(NULL, lumpnum), Pixels(0), Spans(0) { Wads.GetLumpName (Name, lumpnum); - Name[8] = 0; Width = hdr->width; Height = hdr->height; // Alpha channel is used only for 32 bit RGBA and paletted images with RGBA palettes. diff --git a/src/thingdef/thingdef.h b/src/thingdef/thingdef.h index 08264e0a8..c388a8544 100644 --- a/src/thingdef/thingdef.h +++ b/src/thingdef/thingdef.h @@ -31,6 +31,7 @@ bool CheckDeprecatedFlags(const AActor *actor, FActorInfo *info, int index); const char *GetFlagName(unsigned int flagnum, int flagoffset); void ModActorFlag(AActor *actor, FFlagDef *fd, bool set); INTBOOL CheckActorFlag(const AActor *actor, FFlagDef *fd); +INTBOOL CheckActorFlag(const AActor *owner, const char *flagname, bool printerror = true); #define FLAG_NAME(flagnum, flagvar) GetFlagName(flagnum, myoffsetof(AActor, flagvar)) @@ -354,11 +355,11 @@ int MatchString (const char *in, const char **strings); MSVC_MSEG FVariableInfo *infoptr_GlobalDef__##name GCC_MSEG = &GlobalDef__##name; #define DEFINE_MEMBER_VARIABLE(name, cls) \ - static FVariableInfo GlobalDef__##name = { #name, myoffsetof(cls, name), RUNTIME_CLASS(cls) }; \ + static FVariableInfo GlobalDef__##name = { #name, static_cast(myoffsetof(cls, name)), RUNTIME_CLASS(cls) }; \ MSVC_MSEG FVariableInfo *infoptr_GlobalDef__##name GCC_MSEG = &GlobalDef__##name; #define DEFINE_MEMBER_VARIABLE_ALIAS(name, alias, cls) \ - static FVariableInfo GlobalDef__##name = { #name, myoffsetof(cls, alias), RUNTIME_CLASS(cls) }; \ + static FVariableInfo GlobalDef__##name = { #name, static_cast(myoffsetof(cls, alias)), RUNTIME_CLASS(cls) }; \ MSVC_MSEG FVariableInfo *infoptr_GlobalDef__##name GCC_MSEG = &GlobalDef__##name; diff --git a/src/thingdef/thingdef_codeptr.cpp b/src/thingdef/thingdef_codeptr.cpp index c97aee39c..43cb34c8d 100644 --- a/src/thingdef/thingdef_codeptr.cpp +++ b/src/thingdef/thingdef_codeptr.cpp @@ -2205,7 +2205,8 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Log) ACTION_PARAM_STRING(text, 0); if (text[0] == '$') text = GStrings(text+1); - Printf("%s\n", text); + FString formatted = strbin1(text); + Printf("%s\n", formatted.GetChars()); ACTION_SET_RESULT(false); // Prints should never set the result for inventory state chains! } @@ -3776,32 +3777,10 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CheckFlag) COPY_AAPTR_NOT_NULL(self, owner, checkpointer); - const char *dot = strchr (flagname, '.'); - FFlagDef *fd; - const PClass *cls = owner->GetClass(); - - if (dot != NULL) + if (CheckActorFlag(owner, flagname)) { - FString part1(flagname, dot-flagname); - fd = FindFlag (cls, part1, dot+1); + ACTION_JUMP(jumpto); } - else - { - fd = FindFlag (cls, flagname, NULL); - } - - if (fd != NULL) - { - if (CheckActorFlag(owner, fd)) - { - ACTION_JUMP(jumpto); - } - } - else - { - Printf("Unknown flag '%s' in '%s'\n", flagname, cls->TypeName.GetChars()); - } - } @@ -3952,12 +3931,19 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_MonsterRefire) // Set actor's angle (in degrees). // //=========================================================================== +enum +{ + SPF_FORCECLAMP = 1, // players always clamp + SPF_INTERPOLATE = 2, +}; + DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SetAngle) { - ACTION_PARAM_START(1); + ACTION_PARAM_START(2); ACTION_PARAM_ANGLE(angle, 0); - self->angle = angle; + ACTION_PARAM_INT(flags, 1) + self->SetAngle(angle, !!(flags & SPF_INTERPOLATE)); } //=========================================================================== @@ -3968,11 +3954,6 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SetAngle) // //=========================================================================== -enum -{ - SPF_FORCECLAMP = 1, // players always clamp -}; - DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SetPitch) { ACTION_PARAM_START(2); @@ -3995,8 +3976,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SetPitch) } pitch = clamp(pitch, min, max); } - - self->pitch = pitch; + self->SetPitch(pitch, !!(flags & SPF_INTERPOLATE)); } //=========================================================================== diff --git a/src/thingdef/thingdef_data.cpp b/src/thingdef/thingdef_data.cpp index ef0cf2fe1..bf0bf2e13 100644 --- a/src/thingdef/thingdef_data.cpp +++ b/src/thingdef/thingdef_data.cpp @@ -235,6 +235,11 @@ static FFlagDef ActorFlags[]= DEFINE_FLAG(MF6, POISONALWAYS, AActor, flags6), DEFINE_FLAG(MF6, NOTAUTOAIMED, AActor, flags6), DEFINE_FLAG(MF6, NOTONAUTOMAP, AActor, flags6), + DEFINE_FLAG(MF6, RELATIVETOFLOOR, AActor, flags6), + + DEFINE_FLAG(MF7, NEVERTARGET, AActor, flags7), + DEFINE_FLAG(MF7, NOTELESTOMP, AActor, flags7), + DEFINE_FLAG(MF7, ALWAYSTELEFRAG, AActor, flags7), // Effect flags DEFINE_FLAG(FX, VISIBILITYPULSE, AActor, effects), @@ -304,6 +309,7 @@ static FFlagDef InventoryFlags[] = DEFINE_FLAG(IF, RESTRICTABSOLUTELY, AInventory, ItemFlags), DEFINE_FLAG(IF, NEVERRESPAWN, AInventory, ItemFlags), DEFINE_FLAG(IF, NOSCREENFLASH, AInventory, ItemFlags), + DEFINE_FLAG(IF, TOSSED, AInventory, ItemFlags), DEFINE_DEPRECATED_FLAG(PICKUPFLASH), DEFINE_DEPRECATED_FLAG(INTERHUBSTRIP),}; diff --git a/src/thingdef/thingdef_properties.cpp b/src/thingdef/thingdef_properties.cpp index dc08db361..3b61bedca 100644 --- a/src/thingdef/thingdef_properties.cpp +++ b/src/thingdef/thingdef_properties.cpp @@ -180,6 +180,33 @@ INTBOOL CheckActorFlag(const AActor *owner, FFlagDef *fd) #endif } +INTBOOL CheckActorFlag(const AActor *owner, const char *flagname, bool printerror) +{ + const char *dot = strchr (flagname, '.'); + FFlagDef *fd; + const PClass *cls = owner->GetClass(); + + if (dot != NULL) + { + FString part1(flagname, dot-flagname); + fd = FindFlag (cls, part1, dot+1); + } + else + { + fd = FindFlag (cls, flagname, NULL); + } + + if (fd != NULL) + { + return CheckActorFlag(owner, fd); + } + else + { + if (printerror) Printf("Unknown flag '%s' in '%s'\n", flagname, cls->TypeName.GetChars()); + return false; + } +} + //=========================================================================== // // HandleDeprecatedFlags @@ -433,7 +460,7 @@ DEFINE_PROPERTY(skip_super, 0, Actor) return; } - memcpy (defaults, GetDefault(), sizeof(AActor)); + memcpy ((void *)defaults, (void *)GetDefault(), sizeof(AActor)); if (bag.DropItemList != NULL) { FreeDropItemChain (bag.DropItemList); @@ -769,11 +796,13 @@ DEFINE_PROPERTY(renderstyle, S, Actor) { PROP_STRING_PARM(str, 0); static const char * renderstyles[]={ - "NONE","NORMAL","FUZZY","SOULTRANS","OPTFUZZY","STENCIL","TRANSLUCENT", "ADD","SHADED", NULL}; + "NONE", "NORMAL", "FUZZY", "SOULTRANS", "OPTFUZZY", "STENCIL", + "TRANSLUCENT", "ADD", "SHADED", "SHADOW", "SUBTRACT", "ADDSTENCIL", "ADDSHADED", NULL }; static const int renderstyle_values[]={ STYLE_None, STYLE_Normal, STYLE_Fuzzy, STYLE_SoulTrans, STYLE_OptFuzzy, - STYLE_TranslucentStencil, STYLE_Translucent, STYLE_Add, STYLE_Shaded}; + STYLE_TranslucentStencil, STYLE_Translucent, STYLE_Add, STYLE_Shaded, + STYLE_Shadow, STYLE_Subtract, STYLE_AddStencil, STYLE_AddShaded}; // make this work for old style decorations, too. if (!strnicmp(str, "style_", 6)) str+=6; @@ -1286,7 +1315,8 @@ DEFINE_PROPERTY(clearflags, 0, Actor) defaults->flags3 = defaults->flags4 = defaults->flags5 = - defaults->flags6 = 0; + defaults->flags6 = + defaults->flags7 = 0; defaults->flags2 &= MF2_ARGSDEFINED; // this flag must not be cleared } diff --git a/src/thingdef/thingdef_states.cpp b/src/thingdef/thingdef_states.cpp index 1d643e33c..6a28e54cd 100644 --- a/src/thingdef/thingdef_states.cpp +++ b/src/thingdef/thingdef_states.cpp @@ -275,6 +275,11 @@ do_stop: state.Fast = true; continue; } + if (sc.Compare("SLOW")) + { + state.Slow = true; + continue; + } if (sc.Compare("NODELAY")) { if (bag.statedef.GetStateLabelIndex(NAME_Spawn) == bag.statedef.GetStateCount()) @@ -313,6 +318,11 @@ do_stop: sc.MustGetStringName(")"); continue; } + if (sc.Compare("CANRAISE")) + { + state.CanRaise = true; + continue; + } // Make the action name lowercase strlwr (sc.String); diff --git a/src/timidity/instrum.cpp b/src/timidity/instrum.cpp index 55683cb4e..5ab55201e 100644 --- a/src/timidity/instrum.cpp +++ b/src/timidity/instrum.cpp @@ -166,7 +166,7 @@ static Instrument *load_instrument(Renderer *song, const char *name, int percuss tmp += ".pat"; if ((fp = open_filereader(tmp, openmode, NULL)) == NULL) { -#ifdef unix // Windows isn't case-sensitive. +#ifdef __unix__ // Windows isn't case-sensitive. tmp.ToUpper(); if ((fp = open_filereader(tmp, openmode, NULL)) == NULL) #endif diff --git a/src/v_draw.cpp b/src/v_draw.cpp index cd07b44a1..5db99e674 100644 --- a/src/v_draw.cpp +++ b/src/v_draw.cpp @@ -1407,7 +1407,7 @@ void V_SetBorderNeedRefresh() void V_DrawFrame (int left, int top, int width, int height) { FTexture *p; - const gameborder_t *border = gameinfo.border; + const gameborder_t *border = &gameinfo.Border; // Sanity check for incomplete gameinfo if (border == NULL) return; @@ -1444,13 +1444,13 @@ void V_DrawBorder (int x1, int y1, int x2, int y2) { FTextureID picnum; - if (level.info != NULL && level.info->bordertexture[0] != 0) + if (level.info != NULL && level.info->BorderTexture.Len() != 0) { - picnum = TexMan.CheckForTexture (level.info->bordertexture, FTexture::TEX_Flat); + picnum = TexMan.CheckForTexture (level.info->BorderTexture, FTexture::TEX_Flat); } else { - picnum = TexMan.CheckForTexture (gameinfo.borderFlat, FTexture::TEX_Flat); + picnum = TexMan.CheckForTexture (gameinfo.BorderFlat, FTexture::TEX_Flat); } if (picnum.isValid()) @@ -1513,28 +1513,28 @@ static void V_DrawTopBorder () if (viewwidth == SCREENWIDTH) return; - offset = gameinfo.border->offset; + offset = gameinfo.Border.offset; if (viewwindowy < 34) { V_DrawBorder (0, 0, viewwindowx, 34); V_DrawBorder (viewwindowx, 0, viewwindowx + viewwidth, viewwindowy); V_DrawBorder (viewwindowx + viewwidth, 0, SCREENWIDTH, 34); - p = TexMan(gameinfo.border->t); + p = TexMan(gameinfo.Border.t); screen->FlatFill(viewwindowx, viewwindowy - p->GetHeight(), viewwindowx + viewwidth, viewwindowy, p, true); - p = TexMan(gameinfo.border->l); + p = TexMan(gameinfo.Border.l); screen->FlatFill(viewwindowx - p->GetWidth(), viewwindowy, viewwindowx, 35, p, true); - p = TexMan(gameinfo.border->r); + p = TexMan(gameinfo.Border.r); screen->FlatFill(viewwindowx + viewwidth, viewwindowy, viewwindowx + viewwidth + p->GetWidth(), 35, p, true); - p = TexMan(gameinfo.border->tl); + p = TexMan(gameinfo.Border.tl); screen->DrawTexture (p, viewwindowx - offset, viewwindowy - offset, TAG_DONE); - p = TexMan(gameinfo.border->tr); + p = TexMan(gameinfo.Border.tr); screen->DrawTexture (p, viewwindowx + viewwidth, viewwindowy - offset, TAG_DONE); } else diff --git a/src/v_font.cpp b/src/v_font.cpp index d34b08be5..5fc2994fb 100644 --- a/src/v_font.cpp +++ b/src/v_font.cpp @@ -2009,26 +2009,20 @@ void FSpecialFont::LoadTranslations() } // exclude the non-translated colors from the translation calculation - if (notranslate != NULL) - { - for (i = 0; i < 256; i++) - if (notranslate[i]) - usedcolors[i] = false; - } + for (i = 0; i < 256; i++) + if (notranslate[i]) + usedcolors[i] = false; TotalColors = ActiveColors = SimpleTranslation (usedcolors, PatchRemap, identity, &luminosity); // Map all untranslated colors into the table of used colors - if (notranslate != NULL) + for (i = 0; i < 256; i++) { - for (i = 0; i < 256; i++) + if (notranslate[i]) { - if (notranslate[i]) - { - PatchRemap[i] = TotalColors; - identity[TotalColors] = i; - TotalColors++; - } + PatchRemap[i] = TotalColors; + identity[TotalColors] = i; + TotalColors++; } } @@ -2199,19 +2193,6 @@ void V_InitCustomFonts() FTexture **p = &lumplist[*(unsigned char*)sc.String]; sc.MustGetString(); FTextureID texid = TexMan.CheckForTexture(sc.String, FTexture::TEX_MiscPatch); - if (!texid.Exists()) - { - int lumpno = Wads.CheckNumForFullName (sc.String); - if (lumpno >= 0) - { - texid = TexMan.FindTextureByLumpNum(lumpno); - if (!texid.Exists()) - { - FTexture *tex = FTexture::CreateTexture("", lumpno, FTexture::TEX_MiscPatch); - texid = TexMan.AddTexture(tex); - } - } - } if (texid.Exists()) { *p = TexMan[texid]; diff --git a/src/v_text.cpp b/src/v_text.cpp index c5208be36..64b95c041 100644 --- a/src/v_text.cpp +++ b/src/v_text.cpp @@ -336,7 +336,7 @@ static void breakit (FBrokenLines *line, FFont *font, const BYTE *start, const B line->Width = font->StringWidth (line->Text); } -FBrokenLines *V_BreakLines (FFont *font, int maxwidth, const BYTE *string) +FBrokenLines *V_BreakLines (FFont *font, int maxwidth, const BYTE *string, bool preservecolor) { FBrokenLines lines[128]; // Support up to 128 lines (should be plenty) @@ -397,7 +397,7 @@ FBrokenLines *V_BreakLines (FFont *font, int maxwidth, const BYTE *string) space = string - 1; breakit (&lines[i], font, start, space, linecolor); - if (c == '\n') + if (c == '\n' && !preservecolor) { lastcolor = ""; // Why, oh why, did I do it like this? } diff --git a/src/v_text.h b/src/v_text.h index 29dfa627b..f1426b30a 100644 --- a/src/v_text.h +++ b/src/v_text.h @@ -75,9 +75,9 @@ struct FBrokenLines #define TEXTCOLOR_CHAT "\034*" #define TEXTCOLOR_TEAMCHAT "\034!" -FBrokenLines *V_BreakLines (FFont *font, int maxwidth, const BYTE *str); +FBrokenLines *V_BreakLines (FFont *font, int maxwidth, const BYTE *str, bool preservecolor = false); void V_FreeBrokenLines (FBrokenLines *lines); -inline FBrokenLines *V_BreakLines (FFont *font, int maxwidth, const char *str) - { return V_BreakLines (font, maxwidth, (const BYTE *)str); } +inline FBrokenLines *V_BreakLines (FFont *font, int maxwidth, const char *str, bool preservecolor = false) + { return V_BreakLines (font, maxwidth, (const BYTE *)str, preservecolor); } #endif //__V_TEXT_H__ diff --git a/src/v_video.cpp b/src/v_video.cpp index 855b9fda3..fa94cd49f 100644 --- a/src/v_video.cpp +++ b/src/v_video.cpp @@ -795,7 +795,7 @@ bool DSimpleCanvas::IsValid () // //========================================================================== -bool DSimpleCanvas::Lock () +bool DSimpleCanvas::Lock (bool) { if (LockCount == 0) { diff --git a/src/v_video.h b/src/v_video.h index 09022d9ff..b0885f360 100644 --- a/src/v_video.h +++ b/src/v_video.h @@ -157,8 +157,7 @@ public: virtual bool IsValid (); // Access control - virtual bool Lock () = 0; // Returns true if the surface was lost since last time - virtual bool Lock (bool usesimplecanvas) { return Lock(); } + virtual bool Lock (bool buffered=true) = 0; // Returns true if the surface was lost since last time virtual void Unlock () = 0; virtual bool IsLocked () { return Buffer != NULL; } // Returns true if the surface is locked @@ -287,7 +286,7 @@ public: ~DSimpleCanvas (); bool IsValid (); - bool Lock (); + bool Lock (bool buffered=true); void Unlock (); protected: diff --git a/src/version.h b/src/version.h index 01fbc7a88..6c94bf3e6 100644 --- a/src/version.h +++ b/src/version.h @@ -61,7 +61,7 @@ const char *GetVersionString(); // Protocol version used in demos. // Bump it if you change existing DEM_ commands or add new ones. // Otherwise, it should be safe to leave it alone. -#define DEMOGAMEVERSION 0x219 +#define DEMOGAMEVERSION 0x21A // Minimum demo version we can play. // Bump it whenever you change or remove existing DEM_ commands. @@ -76,7 +76,7 @@ const char *GetVersionString(); // Use 4500 as the base git save version, since it's higher than the // SVN revision ever got. -#define SAVEVER 4503 +#define SAVEVER 4508 #define SAVEVERSTRINGIFY2(x) #x #define SAVEVERSTRINGIFY(x) SAVEVERSTRINGIFY2(x) @@ -91,12 +91,10 @@ const char *GetVersionString(); #define FORUM_URL "http://forum.zdoom.org" #define BUGS_FORUM_URL "http://forum.zdoom.org/index.php?c=3" -#ifdef unix -#define GAME_DIR ".config/zdoom" -#elif defined(__APPLE__) +#if defined(__APPLE__) || defined(_WIN32) #define GAME_DIR GAMENAME #else -#define CDROM_DIR "C:\\ZDOOMDAT" +#define GAME_DIR ".config/zdoom" #endif diff --git a/src/w_wad.cpp b/src/w_wad.cpp index 11a9b4213..9455817db 100644 --- a/src/w_wad.cpp +++ b/src/w_wad.cpp @@ -492,7 +492,7 @@ int FWadCollection::CheckNumForFullName (const char *name, bool trynormal, int n return -1; } - i = FirstLumpIndex_FullName[MakeKey (name) % NumLumps]; + i = FirstLumpIndex_FullName[MakeKey(name) % NumLumps]; while (i != NULL_INDEX && stricmp(name, LumpInfo[i].lump->FullName)) { @@ -548,6 +548,37 @@ int FWadCollection::GetNumForFullName (const char *name) return i; } +//========================================================================== +// +// link a texture with a given lump +// +//========================================================================== + +void FWadCollection::SetLinkedTexture(int lump, FTexture *tex) +{ + if ((size_t)lump < NumLumps) + { + FResourceLump *reslump = LumpInfo[lump].lump; + reslump->LinkedTexture = tex; + } +} + +//========================================================================== +// +// retrieve linked texture +// +//========================================================================== + +FTexture *FWadCollection::GetLinkedTexture(int lump) +{ + if ((size_t)lump < NumLumps) + { + FResourceLump *reslump = LumpInfo[lump].lump; + return reslump->LinkedTexture; + } + return NULL; +} + //========================================================================== // // W_LumpLength @@ -984,6 +1015,16 @@ void FWadCollection::GetLumpName (char *to, int lump) const uppercopy (to, LumpInfo[lump].lump->Name); } +void FWadCollection::GetLumpName(FString &to, int lump) const +{ + if ((size_t)lump >= NumLumps) + to = FString(); + else { + to = LumpInfo[lump].lump->Name; + to.ToUpper(); + } +} + //========================================================================== // // FWadCollection :: GetLumpFullName diff --git a/src/w_wad.h b/src/w_wad.h index e0b21b66c..4dfe3434d 100644 --- a/src/w_wad.h +++ b/src/w_wad.h @@ -29,6 +29,7 @@ class FResourceFile; struct FResourceLump; +class FTexture; struct wadinfo_t { @@ -171,6 +172,9 @@ public: int CheckNumForFullName (const char *name, int wadfile); int GetNumForFullName (const char *name); + void SetLinkedTexture(int lump, FTexture *tex); + FTexture *GetLinkedTexture(int lump); + void ReadLump (int lump, void *dest); FMemLump ReadLump (int lump); @@ -192,6 +196,7 @@ public: int GetLumpOffset (int lump); // [RH] Returns offset of lump in the wadfile int GetLumpFlags (int lump); // Return the flags for this lump void GetLumpName (char *to, int lump) const; // [RH] Copies the lump name to to using uppercopy + void GetLumpName (FString &to, int lump) const; const char *GetLumpFullName (int lump) const; // [RH] Returns the lump's full name FString GetLumpFullPath (int lump) const; // [RH] Returns wad's name + lump's full name int GetLumpFile (int lump) const; // [RH] Returns wadnum for a specified lump diff --git a/src/wi_stuff.cpp b/src/wi_stuff.cpp index 7aef939b1..982668566 100644 --- a/src/wi_stuff.cpp +++ b/src/wi_stuff.cpp @@ -314,7 +314,7 @@ static bool IsExMy(const char * name) void WI_LoadBackground(bool isenterpic) { - const char * lumpname = NULL; + const char *lumpname = NULL; char buffer[10]; in_anim_t an; lnode_t pt; @@ -399,7 +399,7 @@ void WI_LoadBackground(bool isenterpic) default: // Strife doesn't have an intermission pic so choose something neutral. if (isenterpic) return; - lumpname = gameinfo.borderFlat; + lumpname = gameinfo.BorderFlat; break; } } diff --git a/src/win32/fb_d3d9.cpp b/src/win32/fb_d3d9.cpp index 648104271..ac8102cd2 100644 --- a/src/win32/fb_d3d9.cpp +++ b/src/win32/fb_d3d9.cpp @@ -1033,11 +1033,6 @@ bool D3DFB::IsFullscreen () // //========================================================================== -bool D3DFB::Lock () -{ - return Lock(true); -} - bool D3DFB::Lock (bool buffered) { if (LockCount++ > 0) diff --git a/src/win32/fb_ddraw.cpp b/src/win32/fb_ddraw.cpp index 9fb65c2a7..71d37d564 100644 --- a/src/win32/fb_ddraw.cpp +++ b/src/win32/fb_ddraw.cpp @@ -815,11 +815,6 @@ HRESULT DDrawFB::GetHR () return LastHR; } -bool DDrawFB::Lock () -{ - return Lock (false); -} - bool DDrawFB::Lock (bool useSimpleCanvas) { static int lock_num; diff --git a/src/win32/i_crash.cpp b/src/win32/i_crash.cpp index d629bacc9..68d78295d 100644 --- a/src/win32/i_crash.cpp +++ b/src/win32/i_crash.cpp @@ -842,10 +842,15 @@ HANDLE WriteTextReport () Writef (file, "\r\nFPU State:\r\n ControlWord=%04x StatusWord=%04x TagWord=%04x\r\n" " ErrorOffset=%08x\r\n ErrorSelector=%08x\r\n DataOffset=%08x\r\n DataSelector=%08x\r\n" - " Cr0NpxState=%08x\r\n\r\n", + // Cr0NpxState was renamed in recent Windows headers so better skip it here. Its meaning is unknown anyway. + //" Cr0NpxState=%08x\r\n" + "\r\n" + , (WORD)ctxt->FloatSave.ControlWord, (WORD)ctxt->FloatSave.StatusWord, (WORD)ctxt->FloatSave.TagWord, ctxt->FloatSave.ErrorOffset, ctxt->FloatSave.ErrorSelector, ctxt->FloatSave.DataOffset, - ctxt->FloatSave.DataSelector, ctxt->FloatSave.Cr0NpxState); + ctxt->FloatSave.DataSelector + //, ctxt->FloatSave.Cr0NpxState + ); for (i = 0; i < 8; ++i) { diff --git a/src/win32/i_main.cpp b/src/win32/i_main.cpp index 472080423..8cfa7e23a 100644 --- a/src/win32/i_main.cpp +++ b/src/win32/i_main.cpp @@ -1061,11 +1061,7 @@ void DoomSpecificInfo (char *buffer, size_t bufflen) } else { - char name[9]; - - strncpy (name, level.mapname, 8); - name[8] = 0; - buffer += mysnprintf (buffer, buffend - buffer, "\r\n\r\nCurrent map: %s", name); + buffer += mysnprintf (buffer, buffend - buffer, "\r\n\r\nCurrent map: %s", level.MapName.GetChars()); if (!viewactive) { diff --git a/src/win32/i_system.cpp b/src/win32/i_system.cpp index a82cb65f9..4690c253d 100644 --- a/src/win32/i_system.cpp +++ b/src/win32/i_system.cpp @@ -581,6 +581,18 @@ void I_DetectOS(void) osname = "Server 2008 R2"; } } + else if (info.dwMinorVersion == 2) + { + // Microsoft broke this API for 8.1 so without jumping through hoops it won't be possible anymore to detect never versions aside from the build number, especially for older compilers. + if (info.wProductType == VER_NT_WORKSTATION) + { + osname = "8 (or higher)"; + } + else + { + osname = "Server 2012 (or higher)"; + } + } } break; diff --git a/src/win32/st_start.cpp b/src/win32/st_start.cpp index 7ffe846e6..04b52925e 100644 --- a/src/win32/st_start.cpp +++ b/src/win32/st_start.cpp @@ -1086,12 +1086,12 @@ void ST_Endoom() { if (showendoom == 0) exit(0); - if (gameinfo.Endoom[0] == 0) + if (gameinfo.Endoom.Len() == 0) { exit(0); } - int endoom_lump = Wads.CheckNumForName (gameinfo.Endoom); + int endoom_lump = Wads.CheckNumForFullName (gameinfo.Endoom, true); BYTE endoom_screen[4000]; BYTE *font; diff --git a/src/win32/win32iface.h b/src/win32/win32iface.h index 07151fb02..2704de0fa 100644 --- a/src/win32/win32iface.h +++ b/src/win32/win32iface.h @@ -148,7 +148,6 @@ public: ~DDrawFB (); bool IsValid (); - bool Lock (); bool Lock (bool buffer); void Unlock (); void ForceBuffering (bool force); @@ -231,7 +230,6 @@ public: ~D3DFB (); bool IsValid (); - bool Lock (); bool Lock (bool buffered); void Unlock (); void Update (); diff --git a/src/x86.cpp b/src/x86.cpp index e03b4795e..89d88333d 100644 --- a/src/x86.cpp +++ b/src/x86.cpp @@ -57,7 +57,7 @@ void CheckCPUID(CPUInfo *cpu) #if defined(_M_IX86) || defined(__i386__) // Old 486s do not have CPUID, so we must test for its presence. // This code is adapted from the samples in AMD's document - // entitled "AMD-K6™ MMX Processor Multimedia Extensions." + // entitled "AMD-K6 MMX Processor Multimedia Extensions." #ifndef __GNUC__ __asm { @@ -299,7 +299,7 @@ void DoBlending_SSE2(const PalEntry *from, PalEntry *to, int count, int r, int g } #endif -#if defined(__amd64__) || defined(_M_IX64) +#if defined(__amd64__) || defined(_M_X64) long long color; blending256 = _mm_set_epi64x(0x10001000100ll, 0x10001000100ll); diff --git a/src/zstring.cpp b/src/zstring.cpp index dc171f398..14d19f46f 100644 --- a/src/zstring.cpp +++ b/src/zstring.cpp @@ -349,7 +349,14 @@ FString &FString::AppendCStrPart (const char *tail, size_t tailLen) return *this; } -void FString::Truncate (long newlen) +FString &FString::CopyCStrPart(const char *tail, size_t tailLen) +{ + ReallocBuffer(tailLen); + StrCopy(Chars, tail, tailLen); + return *this; +} + +void FString::Truncate(long newlen) { if (newlen >= 0 && newlen < (long)Len()) { diff --git a/src/zstring.h b/src/zstring.h index 6dd80b92c..1736f3421 100644 --- a/src/zstring.h +++ b/src/zstring.h @@ -167,6 +167,7 @@ public: FString &operator += (char tail); FString &operator += (const FName &name) { return *this += name.GetChars(); } FString &AppendCStrPart (const char *tail, size_t tailLen); + FString &CopyCStrPart(const char *tail, size_t tailLen); FString &operator << (const FString &tail) { return *this += tail; } FString &operator << (const char *tail) { return *this += tail; } @@ -252,9 +253,13 @@ public: int Compare (const FString &other) const { return strcmp (Chars, other.Chars); } int Compare (const char *other) const { return strcmp (Chars, other); } + int Compare(const FString &other, int len) const { return strncmp(Chars, other.Chars, len); } + int Compare(const char *other, int len) const { return strncmp(Chars, other, len); } int CompareNoCase (const FString &other) const { return stricmp (Chars, other.Chars); } int CompareNoCase (const char *other) const { return stricmp (Chars, other); } + int CompareNoCase(const FString &other, int len) const { return strnicmp(Chars, other.Chars, len); } + int CompareNoCase(const char *other, int len) const { return strnicmp(Chars, other, len); } protected: const FStringData *Data() const { return (FStringData *)Chars - 1; } diff --git a/src/autozend.cpp b/src/zzautozend.cpp similarity index 100% rename from src/autozend.cpp rename to src/zzautozend.cpp diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt index 1d1de65e5..08a1c4f4b 100644 --- a/tools/CMakeLists.txt +++ b/tools/CMakeLists.txt @@ -7,3 +7,5 @@ if( WIN32 ) endif( WIN32 ) add_subdirectory( updaterevision ) add_subdirectory( zipdir ) + +set( CROSS_EXPORTS ${CROSS_EXPORTS} PARENT_SCOPE ) diff --git a/tools/fixrtext/CMakeLists.txt b/tools/fixrtext/CMakeLists.txt index 9af8eb7f4..2b0ab2cda 100644 --- a/tools/fixrtext/CMakeLists.txt +++ b/tools/fixrtext/CMakeLists.txt @@ -1,2 +1,6 @@ cmake_minimum_required( VERSION 2.4 ) -add_executable( fixrtext fixrtext.c ) + +if( NOT CMAKE_CROSSCOMPILING ) + add_executable( fixrtext fixrtext.c ) + set( CROSS_EXPORTS ${CROSS_EXPORTS} fixrtext PARENT_SCOPE ) +endif( NOT CMAKE_CROSSCOMPILING ) diff --git a/tools/lemon/CMakeLists.txt b/tools/lemon/CMakeLists.txt index 91b144575..0a9b558ee 100644 --- a/tools/lemon/CMakeLists.txt +++ b/tools/lemon/CMakeLists.txt @@ -1,17 +1,20 @@ cmake_minimum_required( VERSION 2.4 ) -set( CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -D_DEBUG" ) +if( NOT CMAKE_CROSSCOMPILING ) + set( CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -D_DEBUG" ) -add_executable( lemon lemon.c ) + add_executable( lemon lemon.c ) + set( CROSS_EXPORTS ${CROSS_EXPORTS} lemon PARENT_SCOPE ) +endif( NOT CMAKE_CROSSCOMPILING ) # Lemon wants lempar.c in its directory -if( MSVC ) +if( NOT NO_GENERATOR_EXPRESSIONS ) add_custom_command( TARGET lemon POST_BUILD COMMAND echo $ COMMAND ${CMAKE_COMMAND} -E copy_if_different ${CMAKE_CURRENT_SOURCE_DIR}/lempar.c $ ) -else( MSVC ) +else( NOT NO_GENERATOR_EXPRESSIONS ) add_custom_command( TARGET lemon POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_if_different ${CMAKE_CURRENT_SOURCE_DIR}/lempar.c ${CMAKE_CURRENT_BINARY_DIR} ) -endif( MSVC ) \ No newline at end of file +endif( NOT NO_GENERATOR_EXPRESSIONS ) \ No newline at end of file diff --git a/tools/re2c/CMakeLists.txt b/tools/re2c/CMakeLists.txt index e6068a28d..1284f3506 100644 --- a/tools/re2c/CMakeLists.txt +++ b/tools/re2c/CMakeLists.txt @@ -1,4 +1,7 @@ cmake_minimum_required( VERSION 2.4 ) + +if( NOT CMAKE_CROSSCOMPILING ) + include( CheckFunctionExists ) include( CheckTypeSize ) @@ -30,3 +33,7 @@ add_executable( re2c scanner.cc substr.cc translate.cc ) + +set( CROSS_EXPORTS ${CROSS_EXPORTS} re2c PARENT_SCOPE ) + +endif( NOT CMAKE_CROSSCOMPILING ) diff --git a/tools/updaterevision/CMakeLists.txt b/tools/updaterevision/CMakeLists.txt index d985b9e3f..2500f64fb 100644 --- a/tools/updaterevision/CMakeLists.txt +++ b/tools/updaterevision/CMakeLists.txt @@ -15,9 +15,14 @@ if( WIN32 ) set( TRUSTINFO trustinfo.rc ) endif( MSVC_VERSION GREATER 1399 ) endif( "${CMAKE_C_COMPILER_ID}" STREQUAL "GNU" OR "${CMAKE_C_COMPILER_ID}" STREQUAL "Clang" OR "${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" OR "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang" ) +else( WIN32 ) + set( TRUSTINFO "" ) endif( WIN32 ) -add_executable( updaterevision updaterevision.c ${TRUSTINFO} ) +if( NOT CMAKE_CROSSCOMPILING ) + add_executable( updaterevision updaterevision.c ${TRUSTINFO} ) + set( CROSS_EXPORTS ${CROSS_EXPORTS} updaterevision PARENT_SCOPE ) +endif( NOT CMAKE_CROSSCOMPILING ) if( MT_MERGE ) get_target_property( UPDATEREVISION_EXE updaterevision LOCATION ) diff --git a/tools/updaterevision/updaterevision.c b/tools/updaterevision/updaterevision.c index 90127130a..6ccf174d0 100644 --- a/tools/updaterevision/updaterevision.c +++ b/tools/updaterevision/updaterevision.c @@ -34,7 +34,7 @@ void stripnl(char *str) int main(int argc, char **argv) { - char vertag[64], lastlog[64], lasthash[64], *hash = NULL; + char vertag[128], lastlog[128], lasthash[128], *hash = NULL; FILE *stream = NULL; int gotrev = 0, needupdate = 1; diff --git a/tools/zipdir/CMakeLists.txt b/tools/zipdir/CMakeLists.txt index 40c4042b9..3ee22ddc3 100644 --- a/tools/zipdir/CMakeLists.txt +++ b/tools/zipdir/CMakeLists.txt @@ -1,8 +1,12 @@ cmake_minimum_required( VERSION 2.4 ) -message(STATUS "${ZLIB_INCLUDE_DIR}" ) -message(STATUS "${BZIP2_INCLUDE_DIR}" ) -message(STATUS "${LZMA_INCLUDE_DIR}" ) -include_directories( "${ZLIB_INCLUDE_DIR}" "${BZIP2_INCLUDE_DIR}" "${LZMA_INCLUDE_DIR}" ) -add_executable( zipdir - zipdir.c ) -target_link_libraries( zipdir ${ZLIB_LIBRARIES} ${BZIP2_LIBRARIES} lzma ) + +if(NOT CMAKE_CROSSCOMPILING) + message(STATUS "${ZLIB_INCLUDE_DIR}" ) + message(STATUS "${BZIP2_INCLUDE_DIR}" ) + message(STATUS "${LZMA_INCLUDE_DIR}" ) + include_directories( "${ZLIB_INCLUDE_DIR}" "${BZIP2_INCLUDE_DIR}" "${LZMA_INCLUDE_DIR}" ) + add_executable( zipdir + zipdir.c ) + target_link_libraries( zipdir ${ZLIB_LIBRARIES} ${BZIP2_LIBRARIES} lzma ) + set( CROSS_EXPORTS ${CROSS_EXPORTS} zipdir PARENT_SCOPE ) +endif(NOT CMAKE_CROSSCOMPILING) diff --git a/wadsrc/static/actors/actor.txt b/wadsrc/static/actors/actor.txt index 3ba47a5c1..1eb00440c 100644 --- a/wadsrc/static/actors/actor.txt +++ b/wadsrc/static/actors/actor.txt @@ -180,7 +180,7 @@ ACTOR Actor native //: Thinker action native A_TurretLook(); action native A_KlaxonBlare(); action native A_Countdown(); - action native A_AlertMonsters(float maxdist = 0); + action native A_AlertMonsters(float maxdist = 0, int flags = 0); action native A_ClearSoundTarget(); action native A_FireAssaultGun(); action native A_CheckTerrain(); @@ -289,7 +289,7 @@ ACTOR Actor native //: Thinker action native A_DropWeaponPieces(class p1, class p2, class p3); action native A_PigPain (); action native A_MonsterRefire(int chance, state label); - action native A_SetAngle(float angle = 0); + action native A_SetAngle(float angle = 0, int flags = 0); action native A_SetPitch(float pitch, int flags = 0); action native A_ScaleVelocity(float scale); action native A_ChangeVelocity(float x = 0, float y = 0, float z = 0, int flags = 0); diff --git a/wadsrc/static/actors/constants.txt b/wadsrc/static/actors/constants.txt index cd9b088ab..0ea5060e2 100644 --- a/wadsrc/static/actors/constants.txt +++ b/wadsrc/static/actors/constants.txt @@ -221,7 +221,10 @@ enum CHAN_VOICE = 2, CHAN_ITEM = 3, CHAN_BODY = 4, - + CHAN_5 = 5, + CHAN_6 = 6, + CHAN_7 = 7, + // modifier flags CHAN_LISTENERZ = 8, CHAN_MAYBE_LOCAL = 16, @@ -304,8 +307,9 @@ Const Int WARPF_STOP = 0x80; Const Int WARPF_TOFLOOR = 0x100; Const Int WARPF_TESTONLY = 0x200; -// flags for A_SetPitch +// flags for A_SetPitch/SetAngle const int SPF_FORCECLAMP = 1; +const int SPF_INTERPOLATE = 2; // flags for A_CheckLOF @@ -348,5 +352,12 @@ enum CLOFF_NOAIM = CLOFF_NOAIM_VERT|CLOFF_NOAIM_HORZ }; + +// Flags for A_AlertMonsters +const int AMF_TARGETEMITTER = 1; +const int AMF_TARGETNONPLAYER = 2; +const int AMF_EMITFROMTARGET = 4; + + // This is only here to provide one global variable for testing. native int testglobalvar; diff --git a/wadsrc/static/actors/doom/doommisc.txt b/wadsrc/static/actors/doom/doommisc.txt index 131bb273d..fadab2b05 100644 --- a/wadsrc/static/actors/doom/doommisc.txt +++ b/wadsrc/static/actors/doom/doommisc.txt @@ -27,8 +27,8 @@ ACTOR ExplosiveBarrel 2035 BEXP C 5 BRIGHT BEXP D 5 BRIGHT A_Explode BEXP E 10 BRIGHT - BEXP E 1050 BRIGHT A_BarrelDestroy - BEXP E 5 A_Respawn + TNT1 A 1050 BRIGHT A_BarrelDestroy + TNT1 A 5 A_Respawn Wait } } diff --git a/wadsrc/static/actors/heretic/hereticammo.txt b/wadsrc/static/actors/heretic/hereticammo.txt index 96a20352b..8f02cce0a 100644 --- a/wadsrc/static/actors/heretic/hereticammo.txt +++ b/wadsrc/static/actors/heretic/hereticammo.txt @@ -221,6 +221,7 @@ ACTOR BagOfHolding : BackpackItem 8 Inventory.PickupMessage "$TXT_ITEMBAGOFHOLDING" +COUNTITEM +FLOATBOB + +NOGRAVITY States { Spawn: diff --git a/wadsrc/static/actors/heretic/hereticarmor.txt b/wadsrc/static/actors/heretic/hereticarmor.txt index e027f4f47..40ca671da 100644 --- a/wadsrc/static/actors/heretic/hereticarmor.txt +++ b/wadsrc/static/actors/heretic/hereticarmor.txt @@ -6,6 +6,7 @@ Actor SilverShield : BasicArmorPickup 85 Game Heretic SpawnID 68 +FLOATBOB + +NOGRAVITY Inventory.Pickupmessage "$TXT_ITEMSHIELD1" Inventory.Icon "SHLDA0" Armor.Savepercent 50 @@ -25,6 +26,7 @@ Actor EnchantedShield : BasicArmorPickup 31 Game Heretic SpawnID 69 +FLOATBOB + +NOGRAVITY Inventory.Pickupmessage "$TXT_ITEMSHIELD2" Inventory.Icon "SHD2A0" Armor.Savepercent 75 diff --git a/wadsrc/static/actors/heretic/hereticartifacts.txt b/wadsrc/static/actors/heretic/hereticartifacts.txt index 67d3946b9..404e5ba39 100644 --- a/wadsrc/static/actors/heretic/hereticartifacts.txt +++ b/wadsrc/static/actors/heretic/hereticartifacts.txt @@ -7,6 +7,7 @@ ACTOR SuperMap : MapRevealer 35 +COUNTITEM +INVENTORY.ALWAYSPICKUP +FLOATBOB + +NOGRAVITY Inventory.MaxAmount 0 Inventory.PickupMessage "$TXT_ITEMSUPERMAP" States @@ -26,6 +27,7 @@ ACTOR ArtiInvisibility : PowerupGiver 75 SpawnID 135 +COUNTITEM +FLOATBOB + +NOGRAVITY +INVENTORY.PICKUPFLASH RenderStyle Translucent Alpha 0.4 @@ -51,6 +53,7 @@ ACTOR ArtiTomeOfPower : PowerupGiver 86 native SpawnID 134 +COUNTITEM +FLOATBOB + +NOGRAVITY +INVENTORY.PICKUPFLASH Inventory.Icon "ARTIPWBK" Powerup.Type Weaponlevel2 @@ -94,6 +97,7 @@ ACTOR ArtiTimeBomb : Inventory 34 native SpawnID 72 +COUNTITEM +FLOATBOB + +NOGRAVITY +INVENTORY.PICKUPFLASH +INVENTORY.INVBAR +INVENTORY.FANCYPICKUPSOUND diff --git a/wadsrc/static/actors/heretic/hereticimp.txt b/wadsrc/static/actors/heretic/hereticimp.txt index 25f64a2ea..2659d248a 100644 --- a/wadsrc/static/actors/heretic/hereticimp.txt +++ b/wadsrc/static/actors/heretic/hereticimp.txt @@ -82,6 +82,7 @@ ACTOR HereticImpLeader : HereticImp 5 { Game Heretic SpawnID 7 + Species "HereticImpLeader" Health 80 -MISSILEMORE AttackSound "himp/leaderattack" diff --git a/wadsrc/static/actors/heretic/mummy.txt b/wadsrc/static/actors/heretic/mummy.txt index c6cc2389b..af4ff0c23 100644 --- a/wadsrc/static/actors/heretic/mummy.txt +++ b/wadsrc/static/actors/heretic/mummy.txt @@ -55,6 +55,7 @@ ACTOR MummyLeader : Mummy 45 { Game Heretic SpawnID 2 + Species "MummyLeader" Health 100 Painchance 64 Obituary "$OB_MUMMYLEADER" @@ -89,6 +90,7 @@ ACTOR MummyLeaderGhost : MummyLeader 46 { Game Heretic SpawnID 9 + Species "MummyLeaderGhost" +SHADOW +GHOST RenderStyle Translucent diff --git a/wadsrc/static/actors/hexen/blastradius.txt b/wadsrc/static/actors/hexen/blastradius.txt index ad98d7ecc..28af3e698 100644 --- a/wadsrc/static/actors/hexen/blastradius.txt +++ b/wadsrc/static/actors/hexen/blastradius.txt @@ -4,6 +4,7 @@ ACTOR ArtiBlastRadius : CustomInventory 10110 Game Hexen SpawnID 74 +FLOATBOB + +NOGRAVITY Inventory.DefMaxAmount Inventory.PickupFlash "PickupFlash" +INVBAR +FANCYPICKUPSOUND diff --git a/wadsrc/static/actors/hexen/boostarmor.txt b/wadsrc/static/actors/hexen/boostarmor.txt index 607c8d66a..8aa6b6eeb 100644 --- a/wadsrc/static/actors/hexen/boostarmor.txt +++ b/wadsrc/static/actors/hexen/boostarmor.txt @@ -7,6 +7,7 @@ ACTOR ArtiBoostArmor : Inventory 8041 native SpawnID 22 +COUNTITEM +FLOATBOB + +NOGRAVITY Inventory.DefMaxAmount Inventory.PickupFlash "PickupFlash" +INVBAR +FANCYPICKUPSOUND diff --git a/wadsrc/static/actors/hexen/clericholy.txt b/wadsrc/static/actors/hexen/clericholy.txt index e97be8b17..cebc44610 100644 --- a/wadsrc/static/actors/hexen/clericholy.txt +++ b/wadsrc/static/actors/hexen/clericholy.txt @@ -8,6 +8,7 @@ ACTOR ClericWeaponPiece : WeaponPiece Inventory.ForbiddenTo FighterPlayer, MagePlayer WeaponPiece.Weapon CWeapWraithverge +FLOATBOB + +NOGRAVITY } // Cleric Weapon Piece 1 ---------------------------------------------------- diff --git a/wadsrc/static/actors/hexen/fighterquietus.txt b/wadsrc/static/actors/hexen/fighterquietus.txt index a77e851d8..b5ecd22e4 100644 --- a/wadsrc/static/actors/hexen/fighterquietus.txt +++ b/wadsrc/static/actors/hexen/fighterquietus.txt @@ -8,6 +8,7 @@ ACTOR FighterWeaponPiece : WeaponPiece Inventory.ForbiddenTo ClericPlayer, MagePlayer WeaponPiece.Weapon FWeapQuietus +FLOATBOB + +NOGRAVITY } // Fighter Weapon Piece 1 --------------------------------------------------- diff --git a/wadsrc/static/actors/hexen/flechette.txt b/wadsrc/static/actors/hexen/flechette.txt index 6e12bff53..74c7a0a6a 100644 --- a/wadsrc/static/actors/hexen/flechette.txt +++ b/wadsrc/static/actors/hexen/flechette.txt @@ -99,6 +99,7 @@ ACTOR ArtiPoisonBag : Inventory 8000 native Game Hexen SpawnID 72 +FLOATBOB + +NOGRAVITY Inventory.DefMaxAmount Inventory.PickupFlash "PickupFlash" +INVBAR +FANCYPICKUPSOUND diff --git a/wadsrc/static/actors/hexen/fog.txt b/wadsrc/static/actors/hexen/fog.txt index 81f5aeea5..91fdfc3ee 100644 --- a/wadsrc/static/actors/hexen/fog.txt +++ b/wadsrc/static/actors/hexen/fog.txt @@ -6,6 +6,7 @@ ACTOR FogSpawner 10000 Game Hexen +NOSECTOR +NOBLOCKMAP +FLOATBOB + +NOGRAVITY +INVISIBLE action native A_FogSpawn(); diff --git a/wadsrc/static/actors/hexen/healingradius.txt b/wadsrc/static/actors/hexen/healingradius.txt index e0556915b..97efc0449 100644 --- a/wadsrc/static/actors/hexen/healingradius.txt +++ b/wadsrc/static/actors/hexen/healingradius.txt @@ -6,6 +6,7 @@ ACTOR ArtiHealingRadius : Inventory 10120 native Game Hexen +COUNTITEM +FLOATBOB + +NOGRAVITY Inventory.DefMaxAmount +INVENTORY.INVBAR +INVENTORY.PICKUPFLASH diff --git a/wadsrc/static/actors/hexen/heresiarch.txt b/wadsrc/static/actors/hexen/heresiarch.txt index 999f50540..5a77240fc 100644 --- a/wadsrc/static/actors/hexen/heresiarch.txt +++ b/wadsrc/static/actors/hexen/heresiarch.txt @@ -18,6 +18,7 @@ ACTOR Heresiarch 10080 native +NOTARGET +NOICEDEATH +DEFLECT + +NOBLOOD SeeSound "SorcererSight" PainSound "SorcererPain" DeathSound "SorcererDeathScream" diff --git a/wadsrc/static/actors/hexen/magestaff.txt b/wadsrc/static/actors/hexen/magestaff.txt index aa75ed446..a8584aae7 100644 --- a/wadsrc/static/actors/hexen/magestaff.txt +++ b/wadsrc/static/actors/hexen/magestaff.txt @@ -8,6 +8,7 @@ ACTOR MageWeaponPiece : WeaponPiece Inventory.ForbiddenTo FighterPlayer, ClericPlayer WeaponPiece.Weapon MWeapBloodscourge +FLOATBOB + +NOGRAVITY } // Mage Weapon Piece 1 ------------------------------------------------------ diff --git a/wadsrc/static/actors/hexen/mana.txt b/wadsrc/static/actors/hexen/mana.txt index ee7ddd37c..97bc419c8 100644 --- a/wadsrc/static/actors/hexen/mana.txt +++ b/wadsrc/static/actors/hexen/mana.txt @@ -11,6 +11,7 @@ ACTOR Mana1 : Ammo 122 Radius 8 Height 8 +FLOATBOB + +NOGRAVITY Inventory.Icon "MAN1I0" Inventory.PickupMessage "$TXT_MANA_1" States @@ -34,6 +35,7 @@ ACTOR Mana2 : Ammo 124 Radius 8 Height 8 +FLOATBOB + +NOGRAVITY Inventory.Icon "MAN2G0" Inventory.PickupMessage "$TXT_MANA_2" States @@ -53,6 +55,7 @@ ACTOR Mana3 : CustomInventory 8004 Radius 8 Height 8 +FLOATBOB + +NOGRAVITY Inventory.PickupMessage "$TXT_MANA_BOTH" States { @@ -73,6 +76,7 @@ ACTOR ArtiBoostMana : CustomInventory 8003 Game Hexen SpawnID 26 +FLOATBOB + +NOGRAVITY +COUNTITEM +INVENTORY.INVBAR +INVENTORY.PICKUPFLASH diff --git a/wadsrc/static/actors/hexen/speedboots.txt b/wadsrc/static/actors/hexen/speedboots.txt index 5fd6703b8..c22699b62 100644 --- a/wadsrc/static/actors/hexen/speedboots.txt +++ b/wadsrc/static/actors/hexen/speedboots.txt @@ -5,6 +5,7 @@ ACTOR ArtiSpeedBoots : PowerupGiver 8002 Game Hexen SpawnID 13 +FLOATBOB + +NOGRAVITY +COUNTITEM +INVENTORY.PICKUPFLASH Inventory.Icon ARTISPED diff --git a/wadsrc/static/actors/hexen/summon.txt b/wadsrc/static/actors/hexen/summon.txt index a4b3b8584..28c3c3267 100644 --- a/wadsrc/static/actors/hexen/summon.txt +++ b/wadsrc/static/actors/hexen/summon.txt @@ -7,6 +7,7 @@ ACTOR ArtiDarkServant : Inventory 86 native SpawnID 16 +COUNTITEM +FLOATBOB + +NOGRAVITY Inventory.RespawnTics 4230 Inventory.DefMaxAmount Inventory.PickupFlash "PickupFlash" diff --git a/wadsrc/static/actors/hexen/teleportother.txt b/wadsrc/static/actors/hexen/teleportother.txt index 77a05f6af..49b20a0bd 100644 --- a/wadsrc/static/actors/hexen/teleportother.txt +++ b/wadsrc/static/actors/hexen/teleportother.txt @@ -7,6 +7,7 @@ ACTOR ArtiTeleportOther : Inventory 10040 native SpawnID 17 +COUNTITEM +FLOATBOB + +NOGRAVITY +INVENTORY.INVBAR +INVENTORY.PICKUPFLASH +INVENTORY.FANCYPICKUPSOUND diff --git a/wadsrc/static/actors/raven/artiegg.txt b/wadsrc/static/actors/raven/artiegg.txt index d94f00151..2a9c6867e 100644 --- a/wadsrc/static/actors/raven/artiegg.txt +++ b/wadsrc/static/actors/raven/artiegg.txt @@ -31,6 +31,7 @@ ACTOR ArtiEgg : CustomInventory 30 SpawnID 14 +COUNTITEM +FLOATBOB + +NOGRAVITY +INVENTORY.INVBAR +INVENTORY.PICKUPFLASH +INVENTORY.FANCYPICKUPSOUND @@ -85,6 +86,7 @@ ACTOR ArtiPork : CustomInventory 30 SpawnID 14 +COUNTITEM +FLOATBOB + +NOGRAVITY +INVENTORY.INVBAR +INVENTORY.PICKUPFLASH +INVENTORY.FANCYPICKUPSOUND diff --git a/wadsrc/static/actors/raven/artitele.txt b/wadsrc/static/actors/raven/artitele.txt index 79811fd53..b0eedf1cd 100644 --- a/wadsrc/static/actors/raven/artitele.txt +++ b/wadsrc/static/actors/raven/artitele.txt @@ -7,6 +7,7 @@ ACTOR ArtiTeleport : Inventory 36 native SpawnID 18 +COUNTITEM +FLOATBOB + +NOGRAVITY +INVENTORY.INVBAR +INVENTORY.PICKUPFLASH +INVENTORY.FANCYPICKUPSOUND diff --git a/wadsrc/static/actors/raven/ravenartifacts.txt b/wadsrc/static/actors/raven/ravenartifacts.txt index c02c19c3b..4f31ad5fb 100644 --- a/wadsrc/static/actors/raven/ravenartifacts.txt +++ b/wadsrc/static/actors/raven/ravenartifacts.txt @@ -8,6 +8,7 @@ ACTOR ArtiHealth : HealthPickup 82 Health 25 +COUNTITEM +FLOATBOB + +NOGRAVITY +INVENTORY.PICKUPFLASH +INVENTORY.FANCYPICKUPSOUND Inventory.Icon ARTIPTN2 @@ -32,6 +33,7 @@ ACTOR ArtiSuperHealth : HealthPickup 32 Health 100 +COUNTITEM +FLOATBOB + +NOGRAVITY +INVENTORY.PICKUPFLASH +INVENTORY.FANCYPICKUPSOUND Inventory.Icon ARTISPHL @@ -55,6 +57,7 @@ ACTOR ArtiFly : PowerupGiver 83 SpawnID 15 +COUNTITEM +FLOATBOB + +NOGRAVITY +INVENTORY.PICKUPFLASH +INVENTORY.INTERHUBSTRIP Inventory.RespawnTics 4230 @@ -78,6 +81,7 @@ ACTOR ArtiInvulnerability : PowerupGiver 84 SpawnID 133 +COUNTITEM +FLOATBOB + +NOGRAVITY +INVENTORY.PICKUPFLASH Inventory.RespawnTics 4230 Inventory.Icon ARTIINVU @@ -101,6 +105,7 @@ ACTOR ArtiInvulnerability2 : PowerupGiver 84 SpawnID 133 +COUNTITEM +FLOATBOB + +NOGRAVITY +INVENTORY.PICKUPFLASH Inventory.RespawnTics 4230 Inventory.Icon ARTIDEFN @@ -123,6 +128,7 @@ ACTOR ArtiTorch : PowerupGiver 33 SpawnID 73 +COUNTITEM +FLOATBOB + +NOGRAVITY +INVENTORY.PICKUPFLASH Inventory.Icon ARTITRCH Inventory.PickupMessage "$TXT_ARTITORCH" diff --git a/wadsrc/static/actors/raven/ravenhealth.txt b/wadsrc/static/actors/raven/ravenhealth.txt index af951be1b..45cbe59b9 100644 --- a/wadsrc/static/actors/raven/ravenhealth.txt +++ b/wadsrc/static/actors/raven/ravenhealth.txt @@ -3,6 +3,7 @@ ACTOR CrystalVial : Health 81 Game Raven SpawnID 23 +FLOATBOB + +NOGRAVITY Inventory.Amount 10 Inventory.PickupMessage "$TXT_ITEMHEALTH" States diff --git a/wadsrc/static/actors/strife/acolyte.txt b/wadsrc/static/actors/strife/acolyte.txt index 1d04147f0..3ca1dec62 100644 --- a/wadsrc/static/actors/strife/acolyte.txt +++ b/wadsrc/static/actors/strife/acolyte.txt @@ -39,16 +39,16 @@ ACTOR Acolyte : StrifeHumanoid AGRD ABCDABCD 5 A_Wander Loop See: - AGRD A 6 A_AcolyteBits - AGRD BCD 6 A_Chase + AGRD A 6 Fast Slow A_AcolyteBits + AGRD BCD 6 Fast Slow A_Chase Loop Missile: - AGRD E 8 A_FaceTarget - AGRD FE 4 A_ShootGun - AGRD F 6 A_ShootGun + AGRD E 8 Fast Slow A_FaceTarget + AGRD FE 4 Fast Slow A_ShootGun + AGRD F 6 Fast Slow A_ShootGun Goto See Pain: - AGRD O 8 A_Pain + AGRD O 8 Fast Slow A_Pain Goto See Death: AGRD G 4 @@ -170,8 +170,8 @@ ACTOR AcolyteShadow : Acolyte 58 AGRD A 6 A_BeShadowyFoe Goto Super::See+1 Pain: - AGRD O 0 A_SetShadow - AGRD O 8 A_Pain + AGRD O 0 Fast Slow A_SetShadow + AGRD O 8 Fast Slow A_Pain Goto See } } diff --git a/wadsrc/static/actors/strife/crusader.txt b/wadsrc/static/actors/strife/crusader.txt index 36d89ed57..7f7a0d0c5 100644 --- a/wadsrc/static/actors/strife/crusader.txt +++ b/wadsrc/static/actors/strife/crusader.txt @@ -42,19 +42,16 @@ ACTOR Crusader 3005 ROB2 AABBCCDD 3 A_Chase Loop Missile: - ROB2 E 3 A_FaceTarget - ROB2 F 2 Bright A_CrusaderChoose - ROB2 E 2 Bright A_CrusaderSweepLeft - ROB2 F 3 Bright A_CrusaderSweepLeft - ROB2 E 2 Bright A_CrusaderSweepLeft - ROB2 F 2 Bright A_CrusaderSweepLeft - ROB2 E 2 Bright A_CrusaderSweepRight - ROB2 F 2 Bright A_CrusaderSweepRight - ROB2 E 2 Bright A_CrusaderSweepRight - ROB2 F 2 A_CrusaderRefire + ROB2 E 3 Slow A_FaceTarget + ROB2 F 2 Slow Bright A_CrusaderChoose + ROB2 E 2 Slow Bright A_CrusaderSweepLeft + ROB2 F 3 Slow Bright A_CrusaderSweepLeft + ROB2 EF 2 Slow Bright A_CrusaderSweepLeft + ROB2 EFE 2 Slow Bright A_CrusaderSweepRight + ROB2 F 2 Slow A_CrusaderRefire Loop Pain: - ROB2 D 1 A_Pain + ROB2 D 1 Slow A_Pain Goto See Death: ROB2 G 3 A_Scream diff --git a/wadsrc/static/actors/strife/reaver.txt b/wadsrc/static/actors/strife/reaver.txt index 23439b9ba..a69947373 100644 --- a/wadsrc/static/actors/strife/reaver.txt +++ b/wadsrc/static/actors/strife/reaver.txt @@ -32,16 +32,16 @@ ACTOR Reaver 3001 ROB1 BBCCDDEE 3 A_Chase Loop Melee: - ROB1 H 6 A_FaceTarget - ROB1 I 8 A_CustomMeleeAttack(random[ReaverMelee](1,8)*3, "reaver/blade") - ROB1 H 6 + ROB1 H 6 Slow A_FaceTarget + ROB1 I 8 Slow A_CustomMeleeAttack(random[ReaverMelee](1,8)*3, "reaver/blade") + ROB1 H 6 Slow Goto See Missile: - ROB1 F 8 A_FaceTarget - ROB1 G 11 BRIGHT A_ReaverRanged + ROB1 F 8 Slow A_FaceTarget + ROB1 G 11 Slow BRIGHT A_ReaverRanged Goto See Pain: - ROB1 A 2 + ROB1 A 2 Slow ROB1 A 2 A_Pain Goto See Death: diff --git a/wadsrc/static/actors/strife/stalker.txt b/wadsrc/static/actors/strife/stalker.txt index 80732131e..0a537c762 100644 --- a/wadsrc/static/actors/strife/stalker.txt +++ b/wadsrc/static/actors/strife/stalker.txt @@ -45,14 +45,14 @@ ACTOR Stalker 186 STLK J 10 A_Look Loop See: - STLK A 1 A_StalkerChaseDecide - STLK ABB 3 A_Chase - STLK C 3 A_StalkerWalk - STLK C 3 A_Chase + STLK A 1 Slow A_StalkerChaseDecide + STLK ABB 3 Slow A_Chase + STLK C 3 Slow A_StalkerWalk + STLK C 3 Slow A_Chase Loop Melee: - STLK J 3 A_FaceTarget - STLK K 3 A_StalkerAttack + STLK J 3 Slow A_FaceTarget + STLK K 3 Slow A_StalkerAttack SeeFloor: STLK J 3 A_StalkerWalk STLK KK 3 A_Chase diff --git a/wadsrc/static/actors/strife/strifestuff.txt b/wadsrc/static/actors/strife/strifestuff.txt index b0f4024f4..ef762cbb6 100644 --- a/wadsrc/static/actors/strife/strifestuff.txt +++ b/wadsrc/static/actors/strife/strifestuff.txt @@ -1786,8 +1786,8 @@ ACTOR CeilingTurret 27 Loop Missile: Pain: - TURT B 4 A_ShootGun - TURT D 3 A_SentinelRefire + TURT B 4 Slow A_ShootGun + TURT D 3 Slow A_SentinelRefire TURT A 4 A_SentinelRefire Loop Death: diff --git a/wadsrc/static/compatibility.txt b/wadsrc/static/compatibility.txt index 4b75dfaba..1c2307ec0 100644 --- a/wadsrc/static/compatibility.txt +++ b/wadsrc/static/compatibility.txt @@ -332,7 +332,7 @@ F481922F4881F74760F3C0437FD5EDD0 // map03 setactivation 455 16 // SPAC_Push } - +8B2AC8D4DB4A49A5DCCBB067E04434D6 // The Hell Factory Hub One, map04 65A1EB4C87386F290816660A52932FF1 // Master Levels, garrison.wad { rebuildnodes @@ -375,4 +375,9 @@ D62DCA9EC226DE49108D5DD9271F7631 // Cheogsh 2 map04 setthingz 1647 528 setthingz 1648 528 setthingz 1649 528 -} \ No newline at end of file +} + +B9DFF13207EACAC675C71D82624D0007 // XtheaterIII map01 +{ + DisablePushWindowCheck +} diff --git a/wadsrc/static/iwadinfo.txt b/wadsrc/static/iwadinfo.txt index e47951d31..a2f8ef6c0 100644 --- a/wadsrc/static/iwadinfo.txt +++ b/wadsrc/static/iwadinfo.txt @@ -189,7 +189,7 @@ IWad IWad { - Name = "Freedoom" + Name = "Freedoom: Phase 2" Autoname = "Freedoom" Game = "Doom" Config = "Doom" @@ -200,7 +200,7 @@ IWad IWad { - Name = "Ultimate Freedoom" + Name = "Freedoom: Phase 1" Autoname = "Freedoom1" Game = "Doom" Config = "Doom" @@ -348,9 +348,10 @@ Names "strife1.wad" "strife0.wad" "strife.wad" - "freedoom.wad" "freedoom1.wad" + "freedoom2.wad" "freedoomu.wad" + "freedoom.wad" "freedm.wad" "blasphem.wad" "blasphemer.wad" diff --git a/wadsrc/static/language.enu b/wadsrc/static/language.enu index 5695ad502..76ba7c0d7 100644 --- a/wadsrc/static/language.enu +++ b/wadsrc/static/language.enu @@ -2,6 +2,8 @@ [enu default] +SECRETMESSAGE = "A secret is revealed!"; + D_DEVSTR = "Useless mode ON.\n"; D_CDROM = "CD-ROM Version: zdoom.ini from c:\\zdoomdat\n"; PRESSKEY = "press a key."; diff --git a/wadsrc/static/mapinfo/chex.txt b/wadsrc/static/mapinfo/chex.txt index edc5b4f29..1edaf9256 100644 --- a/wadsrc/static/mapinfo/chex.txt +++ b/wadsrc/static/mapinfo/chex.txt @@ -40,6 +40,7 @@ gameinfo definventorymaxamount = 25 defaultrespawntime = 12 defaultdropstyle = 1 + dontcrunchcorpses = true endoom = "ENDOOM" player5start = 4001 drawreadthis = true diff --git a/wadsrc/static/mapinfo/hereticsw.txt b/wadsrc/static/mapinfo/hereticsw.txt index 89b6c0762..5a37ccbef 100644 --- a/wadsrc/static/mapinfo/hereticsw.txt +++ b/wadsrc/static/mapinfo/hereticsw.txt @@ -4,5 +4,6 @@ gameinfo { finalepage = "ORDER" infopage = "ORDER", "HELP1", "HELP2", "CREDIT" + borderflat = "FLOOR04" } diff --git a/wadsrc/static/mapinfo/strife.txt b/wadsrc/static/mapinfo/strife.txt index 83c2285e6..5a25f3779 100644 --- a/wadsrc/static/mapinfo/strife.txt +++ b/wadsrc/static/mapinfo/strife.txt @@ -238,6 +238,7 @@ skill baby AmmoFactor = 2 DamageFactor = 0.5 EasyBossBrain + SlowMonsters SpawnFilter = Baby PicName = "M_JKILL" Name = "$SSKILL_BABY" diff --git a/wadsrc/static/menudef.txt b/wadsrc/static/menudef.txt index bc34ee33e..cefb19feb 100644 --- a/wadsrc/static/menudef.txt +++ b/wadsrc/static/menudef.txt @@ -686,6 +686,7 @@ OptionMenu "VideoOptions" Option "Show player sprites", "r_drawplayersprites", "OnOff" Option "Death camera", "r_deathcamera", "OnOff" Option "Teleporter zoom", "telezoom", "OnOff" + Slider "Earthquake shake intensity", "r_quakeintensity", 0.0, 1.0, 0.05, 2 Option "Interpolate monster movement", "nomonsterinterpolation", "NoYes" } @@ -850,6 +851,13 @@ OptionValue Autosave 2, "Never" } +OptionValue dehopt +{ + 0, "Never" + 1, "All" + 2, "Only last one" +} + OptionMenu "MiscOptions" { Title "Miscellaneous Options" @@ -864,6 +872,7 @@ OptionMenu "MiscOptions" Option "Enable cheats from all games", "allcheats", "OnOff" Option "Enable autosaves", "disableautosave", "Autosave" Slider "Number of autosaves", "autosavecount", 1, 20, 1, 0 + Option "Load *.deh/*.bex lumps", "dehload", "dehopt" StaticText " " Option "Cache nodes", "gl_cachenodes", "OnOff" Slider "Time threshold for node caching", "gl_cachetime", 0.0, 2.0, 0.1 @@ -920,10 +929,18 @@ OptionValue STSTypes 3, "Rotated" } +OptionValue MapBackTypes +{ + 0, "Off" + 1, "On" + 2, "Map defined colors only" +} + OptionMenu AutomapOptions { Title "AUTOMAP OPTIONS" Option "Map color set", "am_colorset", "MapColorTypes" + Option "Allow map defined colors", "am_customcolors", "YesNo" Submenu "Set custom colors", "MapColorMenu" Submenu "Customize map controls", "MapControlsMenu" StaticText " " @@ -939,7 +956,7 @@ OptionMenu AutomapOptions Option "Show total time elapsed", "am_showtotaltime", "OnOff" Option "Show secrets on map", "am_map_secrets", "SecretTypes" Option "Show map label", "am_showmaplabel", "MaplabelTypes" - Option "Draw map background", "am_drawmapback", "OnOff" + Option "Draw map background", "am_drawmapback", "MapBackTypes" Option "Show keys (cheat)", "am_showkeys", "OnOff" Option "Show trigger lines", "am_showtriggerlines", "OnOff" Option "Show things as sprites", "am_showthingsprites", "STSTypes" @@ -1003,6 +1020,7 @@ OptionMenu MapColorMenu ColorPicker "Secret walls", "am_secretwallcolor" ColorPicker "Actors", "am_thingcolor" ColorPicker "Monsters", "am_thingcolor_monster" + ColorPicker "non-counting Monsters", "am_thingcolor_ncmonster" ColorPicker "Friends", "am_thingcolor_friend" ColorPicker "Items", "am_thingcolor_item" ColorPicker "Count Items", "am_thingcolor_citem" @@ -1014,14 +1032,18 @@ OptionMenu MapColorMenu ColorPicker "2-sided walls with different ceilings", "am_ovcdwallcolor" ColorPicker "2-sided walls with 3D floors", "am_ovefwallcolor" ColorPicker "Not-yet-seen walls", "am_ovunseencolor" - ColorPicker "Locked doors", "am_ovotherwallscolor" - ColorPicker "Teleporter", "am_ovtelecolor" + ColorPicker "Locked doors", "am_ovlockedcolor" + ColorPicker "Teleporter to the same map", "am_ovtelecolor" + ColorPicker "Teleporter to a different map", "am_ovinterlevelcolor" ColorPicker "Secret sector", "am_ovsecretsectorcolor" ColorPicker "Special trigger lines", "am_ovspecialwallcolor" StaticText " " StaticText "Overlay Cheat Mode", 1 + ColorPicker "Invisible 2-sided walls", "am_ovotherwallscolor" + ColorPicker "Secret walls", "am_ovsecretwallcolor" ColorPicker "Actors", "am_ovthingcolor" ColorPicker "Monsters", "am_ovthingcolor_monster" + ColorPicker "non-counting Monsters", "am_ovthingcolor_ncmonster" ColorPicker "Friends", "am_ovthingcolor_friend" ColorPicker "Items", "am_ovthingcolor_item" ColorPicker "Count Items", "am_ovthingcolor_citem" diff --git a/wadsrc/static/sndinfo.txt b/wadsrc/static/sndinfo.txt index 49c6279b0..5508cd89b 100644 --- a/wadsrc/static/sndinfo.txt +++ b/wadsrc/static/sndinfo.txt @@ -634,7 +634,7 @@ $limit misc/spawn 1 // minotaur/sight minsit -minotaur/melee stfhit +minotaur/melee stfpow minotaur/attack1 minat1 minotaur/attack2 minat2 minotaur/attack3 minat3 diff --git a/wadsrc/static/xlat/defines.i b/wadsrc/static/xlat/defines.i index 60d582f70..04c8b21cc 100644 --- a/wadsrc/static/xlat/defines.i +++ b/wadsrc/static/xlat/defines.i @@ -239,5 +239,6 @@ enum // ML_PASSTHROUGH = -1, - ML_TRANSLUCENT = -2 + ML_TRANSLUCENT = -2, + ML_TRANSPARENT = -3 } \ No newline at end of file diff --git a/wadsrc/static/xlat/strife.txt b/wadsrc/static/xlat/strife.txt index 710fa1fad..159933c80 100644 --- a/wadsrc/static/xlat/strife.txt +++ b/wadsrc/static/xlat/strife.txt @@ -363,5 +363,6 @@ lineflag 7 = ML_DONTDRAW; lineflag 8 = ML_MAPPED; lineflag 9 = ML_RAILING; lineflag 10 = ML_BLOCK_FLOATERS; +lineflag 11 = ML_TRANSPARENT; lineflag 12 = ML_TRANSLUCENT; diff --git a/zdoom.vcproj b/zdoom.vcproj index 81168a193..8f9834b85 100644 --- a/zdoom.vcproj +++ b/zdoom.vcproj @@ -56,7 +56,7 @@ FavorSizeOrSpeed="1" OmitFramePointers="true" WholeProgramOptimization="false" - AdditionalIncludeDirectories="src\win32;src\sound;src;zlib;src\g_shared;src\g_doom;src\g_raven;src\g_heretic;src\g_hexen;src\g_strife;"jpeg-6b";"game-music-emu\gme";gdtoa;bzip2;lzma\C" + AdditionalIncludeDirectories="src\win32;src\sound;src;zlib;src\g_shared;src\g_doom;src\g_raven;src\g_heretic;src\g_hexen;src\g_strife;"jpeg-6b";"game-music-emu";gdtoa;bzip2;lzma\C" PreprocessorDefinitions="NDEBUG,WIN32,_WIN32,_WINDOWS,HAVE_STRUPR,HAVE_FILELENGTH;NO_VA_COPY,BACKPATCH,HAVE_FLUIDSYNTH,DYN_FLUIDSYNTH" StringPooling="true" ExceptionHandling="1" @@ -178,7 +178,7 @@ EnableIntrinsicFunctions="true" FavorSizeOrSpeed="1" OmitFramePointers="true" - AdditionalIncludeDirectories="src\win32;src\sound;src;zlib;src\g_shared;src\g_doom;src\g_raven;src\g_heretic;src\g_hexen;src\g_strife;"jpeg-6b";game-music-emu\gme;gdtoa;bzip2;lzma\C" + AdditionalIncludeDirectories="src\win32;src\sound;src;zlib;src\g_shared;src\g_doom;src\g_raven;src\g_heretic;src\g_hexen;src\g_strife;"jpeg-6b";game-music-emu;gdtoa;bzip2;lzma\C" PreprocessorDefinitions="NDEBUG,WIN32,_WIN32,_WINDOWS,HAVE_STRUPR,HAVE_FILELENGTH;NO_VA_COPY" StringPooling="true" RuntimeLibrary="0" @@ -287,7 +287,7 @@ + + @@ -482,14 +486,6 @@ RelativePath=".\src\am_map.cpp" > - - - - @@ -710,6 +706,10 @@ RelativePath=".\src\m_random.cpp" > + + @@ -1090,6 +1090,10 @@ RelativePath=".\src\zstring.cpp" > + +