diff --git a/.gitignore b/.gitignore index 9e31a3bbc..596fe5182 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 @@ -28,4 +29,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 0858ecab5..65e2d223f 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,32 +70,78 @@ 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 ) + +# Replacement variables for a possible long list of C/C++ compilers compatible with GCC +if( "${CMAKE_C_COMPILER_ID}" STREQUAL "GNU" OR "${CMAKE_C_COMPILER_ID}" STREQUAL "Clang" ) + set( ZD_CMAKE_COMPILER_IS_GNUC_COMPATIBLE TRUE ) +else( "${CMAKE_C_COMPILER_ID}" STREQUAL "GNU" OR "${CMAKE_C_COMPILER_ID}" STREQUAL "Clang" ) + set( ZD_CMAKE_COMPILER_IS_GNUC_COMPATIBLE FALSE ) +endif( "${CMAKE_C_COMPILER_ID}" STREQUAL "GNU" OR "${CMAKE_C_COMPILER_ID}" STREQUAL "Clang" ) 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." ) + set( ZD_CMAKE_COMPILER_IS_GNUCXX_COMPATIBLE TRUE ) +else( "${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" OR "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang" ) + set( ZD_CMAKE_COMPILER_IS_GNUCXX_COMPATIBLE FALSE ) endif( "${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" OR "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang" ) +if( ZD_CMAKE_COMPILER_IS_GNUCXX_COMPATIBLE ) + set( PROFILE 0 CACHE BOOL "Enable profiling with gprof for Debug and RelWithDebInfo build types." ) +endif( ZD_CMAKE_COMPILER_IS_GNUCXX_COMPATIBLE ) + set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}") 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 ) @@ -78,10 +152,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}" ) @@ -103,6 +184,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" ) @@ -134,11 +216,25 @@ 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" ) +if( NOT CMAKE_CROSSCOMPILING ) + if( NOT CROSS_EXPORTS ) + set( CROSS_EXPORTS "" ) + endif( NOT CROSS_EXPORTS ) +endif( NOT CMAKE_CROSSCOMPILING ) + add_subdirectory( lzma ) add_subdirectory( tools ) -add_subdirectory( game-music-emu ) add_subdirectory( dumb ) add_subdirectory( gdtoa ) add_subdirectory( wadsrc ) @@ -147,3 +243,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..05dab7ec2 100644 --- a/bzip2/CMakeLists.txt +++ b/bzip2/CMakeLists.txt @@ -1,8 +1,10 @@ cmake_minimum_required( VERSION 2.4 ) -if( "${CMAKE_C_COMPILER_ID}" STREQUAL "GNU" OR "${CMAKE_C_COMPILER_ID}" STREQUAL "Clang" ) +make_release_only() + +if( ZD_CMAKE_COMPILER_IS_GNUC_COMPATIBLE ) 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" ) +endif( ZD_CMAKE_COMPILER_IS_GNUC_COMPATIBLE ) add_definitions( -DBZ_NO_STDIO ) add_library( bz2 diff --git a/dumb/CMakeLists.txt b/dumb/CMakeLists.txt index ee50c4a0a..2b70ee412 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 @@ -11,9 +13,9 @@ endif( NOT CMAKE_BUILD_TYPE MATCHES "Release" ) set( CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -D_DEBUG -DDEBUGMODE=1" ) -if( "${CMAKE_C_COMPILER_ID}" STREQUAL "GNU" OR "${CMAKE_C_COMPILER_ID}" STREQUAL "Clang" ) +if( ZD_CMAKE_COMPILER_IS_GNUC_COMPATIBLE ) set( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wno-pointer-sign -Wno-uninitialized" ) -endif( "${CMAKE_C_COMPILER_ID}" STREQUAL "GNU" OR "${CMAKE_C_COMPILER_ID}" STREQUAL "Clang" ) +endif( ZD_CMAKE_COMPILER_IS_GNUC_COMPATIBLE ) CHECK_FUNCTION_EXISTS( itoa ITOA_EXISTS ) if( NOT ITOA_EXISTS ) @@ -101,6 +103,6 @@ add_library( dumb src/it/xmeffect.c ) target_link_libraries( dumb ) -if( "${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" OR "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang" ) +if( ZD_CMAKE_COMPILER_IS_GNUCXX_COMPATIBLE ) set_source_files_properties( src/it/filter.cpp PROPERTIES COMPILE_FLAGS -msse ) -endif( "${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" OR "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang" ) +endif( ZD_CMAKE_COMPILER_IS_GNUCXX_COMPATIBLE ) 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..79c528fa3 100644 --- a/game-music-emu/CMakeLists.txt +++ b/game-music-emu/CMakeLists.txt @@ -1,12 +1,24 @@ -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" ) set( CMAKE_BUILD_TYPE "RelWithDebInfo" ) endif( NOT CMAKE_BUILD_TYPE MATCHES "Release" ) -if( "${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" OR "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang" ) +if( ZD_CMAKE_COMPILER_IS_GNUCXX_COMPATIBLE ) set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra" ) if( NOT PROFILE ) set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fomit-frame-pointer" ) @@ -15,53 +27,82 @@ if( "${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" OR "${CMAKE_CXX_COMPILER_ID}" STRE if( HAVE_NO_ARRAY_BOUNDS ) set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-array-bounds" ) endif( HAVE_NO_ARRAY_BOUNDS ) -endif( "${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" OR "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang" ) +endif( ZD_CMAKE_COMPILER_IS_GNUCXX_COMPATIBLE ) -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..45de9ebfb 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 +708,10 @@ RelativePath=".\gme\Gme_File.h" > + + @@ -823,6 +832,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..9ec7c2f61 100644 --- a/gdtoa/CMakeLists.txt +++ b/gdtoa/CMakeLists.txt @@ -8,71 +8,41 @@ if( MSVC ) set( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /wd4554 /wd4102" ) endif( MSVC ) -if( "${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" OR "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang" ) +if( ZD_CMAKE_COMPILER_IS_GNUCXX_COMPATIBLE ) set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra" ) -endif( "${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" OR "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang" ) +endif( ZD_CMAKE_COMPILER_IS_GNUCXX_COMPATIBLE ) 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 ) + set( GEN_FP_DEPS ${CMAKE_CURRENT_BINARY_DIR}/arith.h ${CMAKE_CURRENT_BINARY_DIR}/gd_qnan.h ) +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..c70892770 100644 --- a/jpeg-6b/CMakeLists.txt +++ b/jpeg-6b/CMakeLists.txt @@ -1,8 +1,10 @@ cmake_minimum_required( VERSION 2.4 ) -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" ) +make_release_only() + +if( ZD_CMAKE_COMPILER_IS_GNUC_COMPATIBLE ) + set( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -Wno-unused-parameter -fomit-frame-pointer" ) +endif( ZD_CMAKE_COMPILER_IS_GNUC_COMPATIBLE ) add_library( jpeg jcomapi.c 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..6993a6988 100644 --- a/lzma/C/7zCrc.c +++ b/lzma/C/7zCrc.c @@ -1,35 +1,83 @@ -/* 7zCrc.c -- CRC32 calculation -2008-08-05 -Igor Pavlov -Public domain */ +/* 7zCrc.c -- CRC32 init +2010-12-01 : 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_X86_OR_AMD64 + #define CRC_NUM_TABLES 8 + UInt32 MY_FAST_CALL CrcUpdateT8(UInt32 v, const void *data, size_t size, const UInt32 *table); +#elif defined(MY_CPU_LE) + #define CRC_NUM_TABLES 4 +#else + #define CRC_NUM_TABLES 5 + #define CRC_UINT32_SWAP(v) ((v >> 24) | ((v >> 8) & 0xFF00) | ((v << 8) & 0xFF0000) | (v << 24)) + UInt32 MY_FAST_CALL CrcUpdateT1_BeT4(UInt32 v, const void *data, size_t size, const UInt32 *table); +#endif + +#ifndef MY_CPU_BE + UInt32 MY_FAST_CALL CrcUpdateT4(UInt32 v, const void *data, size_t size, const UInt32 *table); +#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]; + +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; } -} + for (; i < 256 * CRC_NUM_TABLES; i++) + { + UInt32 r = g_CrcTable[i - 256]; + g_CrcTable[i] = g_CrcTable[r & 0xFF] ^ (r >> 8); + } + + #ifdef MY_CPU_LE -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; -} + g_CrcUpdate = CrcUpdateT4; + + #if CRC_NUM_TABLES == 8 + if (!CPU_Is_InOrder()) + g_CrcUpdate = CrcUpdateT8; + #endif -UInt32 MY_FAST_CALL CrcCalc(const void *data, size_t size) -{ - return CrcUpdate(CRC_INIT_VAL, data, size) ^ 0xFFFFFFFF; + #else + { + #ifndef MY_CPU_BE + UInt32 k = 1; + if (*(const Byte *)&k == 1) + g_CrcUpdate = CrcUpdateT4; + else + #endif + { + for (i = 256 * CRC_NUM_TABLES - 1; i >= 256; i--) + { + UInt32 x = g_CrcTable[i - 256]; + g_CrcTable[i] = CRC_UINT32_SWAP(x); + } + g_CrcUpdate = CrcUpdateT1_BeT4; + } + } + #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..85405ccfc --- /dev/null +++ b/lzma/C/7zCrcOpt.c @@ -0,0 +1,64 @@ +/* 7zCrcOpt.c -- CRC32 calculation +2010-12-01 : Igor Pavlov : Public domain */ + +#include "CpuArch.h" + +#define CRC_UPDATE_BYTE_2(crc, b) (table[((crc) ^ (b)) & 0xFF] ^ ((crc) >> 8)) + +#ifndef MY_CPU_BE + +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 + + +#ifndef MY_CPU_LE + +#define CRC_UINT32_SWAP(v) ((v >> 24) | ((v >> 8) & 0xFF00) | ((v << 8) & 0xFF0000) | (v << 24)) + +UInt32 MY_FAST_CALL CrcUpdateT1_BeT4(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); + v = CRC_UINT32_SWAP(v); + table += 0x100; + for (; size >= 4; size -= 4, p += 4) + { + v ^= *(const UInt32 *)p; + v = + table[0x000 + (v & 0xFF)] ^ + table[0x100 + ((v >> 8) & 0xFF)] ^ + table[0x200 + ((v >> 16) & 0xFF)] ^ + table[0x300 + ((v >> 24))]; + } + table -= 0x100; + v = CRC_UINT32_SWAP(v); + for (; size > 0; size--, p++) + v = CRC_UPDATE_BYTE_2(v, *p); + return v; +} + +#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..43f0fef6f 100644 --- a/lzma/C/7zVersion.h +++ b/lzma/C/7zVersion.h @@ -1,7 +1,8 @@ -#define MY_VER_MAJOR 4 -#define MY_VER_MINOR 65 -#define MY_VER_BUILD 0 -#define MY_VERSION "4.65" -#define MY_DATE "2009-02-03" +#define MY_VER_MAJOR 9 +#define MY_VER_MINOR 22 +#define MY_VER_BUILD 00 +#define MY_VERSION "9.22 beta" +#define MY_7ZIP_VERSION "9.22 beta" +#define MY_DATE "2011-04-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..425d18923 --- /dev/null +++ b/lzma/C/CpuArch.c @@ -0,0 +1,184 @@ +/* CpuArch.c -- CPU specific code +2010-10-26: Igor Pavlov : Public domain */ + +#include "CpuArch.h" + +#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..1cd7c29c5 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-12-01: 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__) || defined(__m68k__) || defined(__ARMEB__) || defined(__MIPSEB__) +#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..7c4eb4449 --- /dev/null +++ b/lzma/C/Lzma2Dec.c @@ -0,0 +1,350 @@ +/* Lzma2Dec.c -- LZMA2 Decoder +2010-12-15 : 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 p; + SRes res; + SizeT outSize = *destLen, inSize = *srcLen; + *destLen = *srcLen = 0; + *status = LZMA_STATUS_NOT_SPECIFIED; + Lzma2Dec_Construct(&p); + RINOK(Lzma2Dec_AllocateProbs(&p, prop, alloc)); + p.decoder.dic = dest; + p.decoder.dicBufSize = outSize; + Lzma2Dec_Init(&p); + *srcLen = inSize; + res = Lzma2Dec_DecodeToDic(&p, outSize, src, srcLen, finishMode, status); + *destLen = p.decoder.dicPos; + if (res == SZ_OK && *status == LZMA_STATUS_NEEDS_MORE_INPUT) + res = SZ_ERROR_INPUT_EOF; + Lzma2Dec_FreeProbs(&p, 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..72451d1ff 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 */ +2010-12-15 : 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; @@ -450,8 +442,9 @@ static void MY_FAST_CALL LzmaDec_WriteRem(CLzmaDec *p, SizeT limit) p->processedPos += len; p->remainLen -= len; - while (len-- != 0) + while (len != 0) { + len--; dic[dicPos] = dic[(dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0)]; dicPos++; } @@ -980,28 +973,21 @@ SRes LzmaDecode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, { CLzmaDec p; SRes res; - SizeT inSize = *srcLen; - SizeT outSize = *destLen; - *srcLen = *destLen = 0; + SizeT outSize = *destLen, inSize = *srcLen; + *destLen = *srcLen = 0; + *status = LZMA_STATUS_NOT_SPECIFIED; if (inSize < RC_INIT_SIZE) return SZ_ERROR_INPUT_EOF; - LzmaDec_Construct(&p); - res = LzmaDec_AllocateProbs(&p, propData, propSize, alloc); - if (res != 0) - return res; + RINOK(LzmaDec_AllocateProbs(&p, propData, propSize, alloc)); p.dic = dest; p.dicBufSize = outSize; - LzmaDec_Init(&p); - *srcLen = inSize; res = LzmaDec_DecodeToDic(&p, outSize, src, srcLen, finishMode, status); - + *destLen = p.dicPos; if (res == SZ_OK && *status == LZMA_STATUS_NEEDS_MORE_INPUT) res = SZ_ERROR_INPUT_EOF; - - (*destLen) = p.dicPos; LzmaDec_FreeProbs(&p, alloc); return res; } 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..da39520c6 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 */ +2011-01-27 : 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 @@ -46,6 +46,7 @@ void LzmaEncProps_Init(CLzmaEncProps *p) { p->level = 5; p->dictSize = p->mc = 0; + p->reduceSize = (UInt32)(Int32)-1; p->lc = p->lp = p->pb = p->algo = p->fb = p->btMode = p->numHashBytes = p->numThreads = -1; p->writeEndMark = 0; } @@ -56,6 +57,15 @@ void LzmaEncProps_Normalize(CLzmaEncProps *p) if (level < 0) level = 5; p->level = level; if (p->dictSize == 0) p->dictSize = (level <= 5 ? (1 << (level * 2 + 14)) : (level == 6 ? (1 << 25) : (1 << 26))); + if (p->dictSize > p->reduceSize) + { + unsigned i; + for (i = 15; i <= 30; i++) + { + if (p->reduceSize <= ((UInt32)2 << i)) { p->dictSize = ((UInt32)2 << i); break; } + if (p->reduceSize <= ((UInt32)3 << i)) { p->dictSize = ((UInt32)3 << i); break; } + } + } if (p->lc < 0) p->lc = 3; if (p->lp < 0) p->lp = 0; if (p->pb < 0) p->pb = 2; @@ -66,7 +76,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 +149,7 @@ void LzmaEnc_FastPosInit(Byte *g_FastPos) typedef unsigned CState; -typedef struct _COptimal +typedef struct { UInt32 price; @@ -172,7 +182,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 +228,7 @@ typedef struct UInt32 counters[LZMA_NUM_PB_STATES_MAX]; } CLenPriceEnc; -typedef struct _CRangeEnc +typedef struct { UInt32 range; Byte cache; @@ -232,26 +242,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 +264,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 @@ -349,10 +339,8 @@ typedef struct _CLzmaEnc SRes result; UInt32 dictSize; - UInt32 matchFinderCycles; - ISeqInStream *inStream; - CSeqInStreamBuf seqBufInStream; + int needInit; CSaveState saveState; } CLzmaEnc; @@ -416,10 +404,9 @@ 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; { unsigned fb = props.fb; if (fb < 5) @@ -449,7 +436,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 +1685,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 +1724,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 +1741,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 +1909,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 +1934,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 +2042,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 +2057,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 +2074,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 +2090,7 @@ void LzmaEnc_Finish(CLzmaEncHandle pp) #endif } -typedef struct _CSeqOutStreamBuf +typedef struct { ISeqOutStream funcTable; Byte *data; @@ -2170,21 +2159,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 +2185,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 +2241,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..7573ba01b 100644 --- a/lzma/C/LzmaEnc.h +++ b/lzma/C/LzmaEnc.h @@ -1,11 +1,13 @@ /* LzmaEnc.h -- LZMA Encoder -2008-10-04 : Igor Pavlov : Public domain */ +2011-01-27 : Igor Pavlov : Public domain */ -#ifndef __LZMAENC_H -#define __LZMAENC_H +#ifndef __LZMA_ENC_H +#define __LZMA_ENC_H #include "Types.h" +EXTERN_C_BEGIN + #define LZMA_PROPS_SIZE 5 typedef struct _CLzmaEncProps @@ -14,6 +16,8 @@ typedef struct _CLzmaEncProps UInt32 dictSize; /* (1 << 12) <= dictSize <= (1 << 27) for 32-bit version (1 << 12) <= dictSize <= (1 << 30) for 64-bit version default = (1 << 24) */ + UInt32 reduceSize; /* estimated size of data that will be compressed. default = 0xFFFFFFFF. + Encoder uses this value to reduce dictionary size */ int lc; /* 0 <= lc <= 8, default = 3 */ int lp; /* 0 <= lp <= 4, default = 0 */ int pb; /* 0 <= pb <= 4, default = 2 */ @@ -69,4 +73,6 @@ 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); +EXTERN_C_END + #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..6a7afa829 100644 --- a/lzma/C/Threads.h +++ b/lzma/C/Threads.h @@ -1,151 +1,59 @@ /* 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 - -#ifdef _WIN32 -#include -typedef DWORD WRes; +#ifndef __7Z_THREADS_H +#define __7Z_THREADS_H #include "Types.h" -typedef struct _CThread -{ - HANDLE handle; -} CThread; +#ifdef __cplusplus +extern "C" { +#endif -#define Thread_Construct(thread) (thread)->handle = NULL -#define Thread_WasCreated(thread) ((thread)->handle != NULL) - +WRes HandlePtr_Close(HANDLE *h); +WRes Handle_WaitObject(HANDLE h); + +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..f193ce2f5 100644 --- a/lzma/C/Types.h +++ b/lzma/C/Types.h @@ -1,15 +1,27 @@ /* 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 -#ifdef __cplusplus -extern "C" { +#ifdef _WIN32 +#include #endif +#ifndef EXTERN_C_BEGIN +#ifdef __cplusplus +#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 #define SZ_ERROR_DATA 1 @@ -30,17 +42,17 @@ extern "C" { typedef int SRes; +#ifdef _WIN32 +typedef DWORD WRes; +#else +typedef int WRes; +#endif + #ifndef RINOK #define RINOK(x) { int __result__ = (x); if (__result__ != 0) return __result__; } #endif -#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 +77,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 +97,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 +112,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 +124,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 +168,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 +233,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..7cd330cc8 100644 --- a/lzma/CMakeLists.txt +++ b/lzma/CMakeLists.txt @@ -1,29 +1,31 @@ cmake_minimum_required( VERSION 2.4 ) -if( "${CMAKE_C_COMPILER_ID}" STREQUAL "GNU" OR "${CMAKE_C_COMPILER_ID}" STREQUAL "Clang" ) +make_release_only() + +if( ZD_CMAKE_COMPILER_IS_GNUC_COMPATIBLE ) 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" ) +endif( ZD_CMAKE_COMPILER_IS_GNUC_COMPATIBLE ) 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 index 9bed5ebbe..36d01d7d9 100644 --- a/lzma/history.txt +++ b/lzma/history.txt @@ -1,6 +1,49 @@ HISTORY of the LZMA SDK ----------------------- +9.21 beta 2011-04-11 +------------------------- +- New class FString for file names at file systems. +- Speed optimization in CRC code for big-endian CPUs. +- The BUG in Lzma2Dec.c was fixed: + Lzma2Decode function didn't work. + + +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 index d4f4af929..9d3cef003 100644 --- a/lzma/lzma.txt +++ b/lzma/lzma.txt @@ -1,4 +1,4 @@ -LZMA SDK 4.65 +LZMA SDK 9.22 ------------- LZMA SDK provides the documentation, samples, header files, libraries, @@ -20,6 +20,16 @@ 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) + +You can copy, modify, distribute and perform LZMA SDK code, even for commercial purposes, +all without asking permission. + +LZMA SDK code is compatible with open source licenses, for example, you can +include it to GNU GPL or GNU LGPL code. + LZMA SDK Contents ----------------- @@ -33,7 +43,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 +59,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 +77,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 +97,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 +105,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 +375,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 +437,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 +533,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 +556,8 @@ Return code: -LZMA Defines ------------- +Defines +------- _LZMA_SIZE_OPT - Enable some optimizations in LZMA Decoder to get smaller executable code. @@ -562,6 +569,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..2736f31a6 100644 --- a/lzma/lzmalib.vcproj +++ b/lzma/lzmalib.vcproj @@ -1,11 +1,12 @@ + + + + + + + + @@ -318,6 +335,10 @@ RelativePath=".\C\LzFindMt.c" > + + @@ -326,10 +347,6 @@ RelativePath=".\C\LzmaEnc.c" > - - @@ -340,6 +357,10 @@ Filter="h;hpp;hxx;hm;inl;inc;xsd" UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}" > + + @@ -352,10 +373,6 @@ RelativePath=".\C\7zVersion.h" > - - @@ -380,6 +397,10 @@ RelativePath=".\C\LzHash.h" > + + @@ -388,10 +409,6 @@ RelativePath=".\C\LzmaEnc.h" > - - @@ -401,50 +418,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 152425353..8c57d74be 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -15,16 +15,16 @@ else( NOT APPLE ) # At the moment asm code doesn't work with OS X, so disable by default option( NO_ASM "Disable assembly code" ON ) endif( NOT APPLE ) -if( "${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" OR "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang" ) +if( ZD_CMAKE_COMPILER_IS_GNUCXX_COMPATIBLE ) option( NO_STRIP "Do not strip Release or MinSizeRel builds" ) # At least some versions of Xcode fail if you strip with the linker # instead of the separate strip utility. if( APPLE ) set( NO_STRIP ON ) endif( APPLE ) -endif( "${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" OR "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang" ) +endif( ZD_CMAKE_COMPILER_IS_GNUCXX_COMPATIBLE ) -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 ) @@ -76,8 +94,11 @@ if( WIN32 ) set( FMOD_SEARCH_PATHS "C:/Program Files/FMOD SoundSystem/FMOD Programmers API ${WIN_TYPE}/api" "C:/Program Files (x86)/FMOD SoundSystem/FMOD Programmers API ${WIN_TYPE}/api" - # This next one is for me. - "E:/Software/Dev/FMOD/${WIN_TYPE}/api" ) + # This next one is for Randy. + "E:/Software/Dev/FMOD/${WIN_TYPE}/api" + # .. and this one for Graf Zahl + "D:/portable/FMOD SoundSystem 4.26/FMOD Programmers API WIN32/api" + ) set( FMOD_INC_PATH_SUFFIXES PATH_SUFFIXES inc ) set( FMOD_LIB_PATH_SUFFIXES PATH_SUFFIXES lib ) set( NASM_NAMES nasmw nasm ) @@ -101,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} ) @@ -112,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 ) @@ -129,7 +144,6 @@ if( WIN32 ) set( ZDOOM_LIBS wsock32 winmm - "${DX_ddraw_LIBRARY}" "${DX_dxguid_LIBRARY}" "${DX_dinput8_LIBRARY}" ole32 @@ -139,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" ) @@ -343,12 +358,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} @@ -363,20 +382,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 ) @@ -396,7 +418,7 @@ endif( SSE_MATTERS ) # Set up flags for GCC -if( "${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" OR "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang" ) +if( ZD_CMAKE_COMPILER_IS_GNUCXX_COMPATIBLE ) if( PROFILE ) set( CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -pg" ) set( CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -pg" ) @@ -412,7 +434,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, @@ -425,7 +447,7 @@ if( "${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" OR "${CMAKE_CXX_COMPILER_ID}" STRE set (CMAKE_EXE_LINKER_FLAGS_RELEASE "${CMAKE_EXE_LINKER_FLAGS_RELEASE} -s" ) set (CMAKE_EXE_LINKER_FLAGS_MINSIZEREL "${CMAKE_EXE_LINKER_FLAGS_MINSIZEREL} -s" ) endif( NOT NO_STRIP ) -endif( "${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" OR "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang" ) +endif( ZD_CMAKE_COMPILER_IS_GNUCXX_COMPATIBLE ) # Check for functions that may or may not exist. @@ -500,67 +522,83 @@ 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}" "${FMOD_INCLUDE_DIR}" "${BZIP2_INCLUDE_DIR}" "${LZMA_INCLUDE_DIR}" "${JPEG_INCLUDE_DIR}" ) +set( ZDOOM_LIBS ${ZDOOM_LIBS} "${ZLIB_LIBRARIES}" "${JPEG_LIBRARIES}" "${BZIP2_LIBRARIES}" "${GME_LIBRARIES}" "${FMOD_LIBRARY}" ) +include_directories( "${ZLIB_INCLUDE_DIR}" "${FMOD_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 ) - if( "${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" OR "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang" ) + set( SYSTEM_SOURCES ${PLAT_WIN32_SOURCES} ) + set( OTHER_SYSTEM_SOURCES ${PLAT_SDL_SOURCES} ${PLAT_MAC_SOURCES} ) + + if( ZD_CMAKE_COMPILER_IS_GNUCXX_COMPATIBLE ) # CMake is not set up to compile and link rc files with GCC. :( add_custom_command( OUTPUT zdoom-rc.o COMMAND windres -o zdoom-rc.o -i ${CMAKE_CURRENT_SOURCE_DIR}/win32/zdoom.rc DEPENDS win32/zdoom.rc ) set( SYSTEM_SOURCES ${SYSTEM_SOURCES} zdoom-rc.o ) - else( "${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" OR "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang" ) + else( ZD_CMAKE_COMPILER_IS_GNUCXX_COMPATIBLE ) set( SYSTEM_SOURCES ${SYSTEM_SOURCES} win32/zdoom.rc ) - endif( "${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" OR "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang" ) + endif( ZD_CMAKE_COMPILER_IS_GNUCXX_COMPATIBLE ) 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( NOT ASM_SOURCES ) + set( ASM_SOURCES "" ) +endif( NOT ASM_SOURCES ) + if( NO_ASM ) add_definitions( -DNOASM ) else( NO_ASM ) @@ -584,9 +622,9 @@ add_custom_command( OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/xlat_parser.c ${CMAKE_CUR WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} DEPENDS lemon ${CMAKE_CURRENT_SOURCE_DIR}/xlat/xlat_parser.y ) -add_custom_command( OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/zcc-parse.c ${CMAKE_CURRENT_BINARY_DIR}/zcc-parse.h +add_custom_command( OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/zcc-parse.lemon ${CMAKE_CURRENT_BINARY_DIR}/zcc-parse.h COMMAND ${CMAKE_COMMAND} -E copy_if_different ${CMAKE_CURRENT_SOURCE_DIR}/zscript/zcc-parse.lemon . - COMMAND ${CMAKE_BINARY_DIR}/tools/lemon/lemon zcc-parse.lemon + COMMAND ${LEMON_EXE} zcc-parse.lemon WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} DEPENDS lemon ${CMAKE_CURRENT_SOURCE_DIR}/zscript/zcc-parse.lemon ) @@ -633,19 +671,120 @@ 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 thingdef/*.h xlat/*.h + zcript/*.h *.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 + zscript/zcc-parse.lemon + zcc-parse.c + zcc-parse.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} @@ -661,6 +800,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 @@ -707,6 +847,7 @@ add_executable( zdoom WIN32 m_misc.cpp m_png.cpp m_random.cpp + m_specialpaths.cpp memarena.cpp md5.cpp name.cpp @@ -765,7 +906,6 @@ add_executable( zdoom WIN32 r_drawt.cpp r_main.cpp r_plane.cpp - r_polymost.cpp r_segs.cpp r_sky.cpp r_things.cpp @@ -918,6 +1058,7 @@ add_executable( zdoom WIN32 thingdef/thingdef_data.cpp thingdef/thingdef_exp.cpp thingdef/thingdef_expression.cpp + thingdef/thingdef_function.cpp thingdef/thingdef_parse.cpp thingdef/thingdef_properties.cpp thingdef/thingdef_states.cpp @@ -955,19 +1096,19 @@ add_executable( zdoom WIN32 zscript/zcc_compile.cpp zscript/zcc_expr.cpp zscript/zcc_parser.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( zscript/zcc_parser.cpp PROPERTIES OBJECT_DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/zcc-parse.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 @@ -981,8 +1122,7 @@ include_directories( . thingdef timidity xlat - zscript - ../game-music-emu/gme + zcript ../gdtoa ../dumb/include ${CMAKE_BINARY_DIR}/gdtoa @@ -990,10 +1130,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" ) @@ -1001,16 +1171,45 @@ 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_COMPILER_IS_GNUCXX ) # GCC misoptimizes this file set_source_files_properties( oplsynth/fmopl.cpp PROPERTIES COMPILE_FLAGS "-fno-tree-dominator-opts -fno-tree-fre" ) - +endif( CMAKE_COMPILER_IS_GNUCXX ) +if( ZD_CMAKE_COMPILER_IS_GNUCXX_COMPATIBLE ) # 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" ) +endif( ZD_CMAKE_COMPILER_IS_GNUCXX_COMPATIBLE ) -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("ZScript" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/zscript/.+") +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 6e5b10f4c..555743f8d 100644 --- a/src/actor.h +++ b/src/actor.h @@ -336,11 +336,13 @@ enum 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.flags6 --- +// --- 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 + MF7_WEAPONSPAWN = 0x00000010, // subject to DF_NO_COOP_WEAPON_SPAWN dmflag // --- mobj.renderflags --- @@ -730,6 +732,10 @@ public: return GetClass()->BloodColor; } + // These also set CF_INTERPVIEW for players. + void SetPitch(int p, bool interpolate); + void SetAngle(angle_t ang, bool interpolate); + PClassActor *GetBloodType(int type = 0) const { PClassActor *bloodcls; @@ -838,6 +844,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; @@ -869,6 +876,7 @@ public: fixed_t wallbouncefactor; // The bounce factor for walls can be different. int bouncecount; // Strife's grenades only bounce twice before exploding fixed_t gravity; // [GRB] Gravity factor + fixed_t Friction; int FastChaseStrafeCount; fixed_t pushfactor; int lastpush; @@ -972,8 +980,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 e52d39211..904593dfb 100644 --- a/src/am_map.cpp +++ b/src/am_map.cpp @@ -1316,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(); diff --git a/src/b_game.cpp b/src/b_game.cpp index ed3a5c848..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 0a94587dd..2cff38145 100644 --- a/src/c_cmds.cpp +++ b/src/c_cmds.cpp @@ -439,27 +439,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]); } } @@ -938,8 +944,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 (); } @@ -971,14 +984,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 { @@ -1001,12 +1010,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 { @@ -1120,8 +1126,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 0c02d0489..e7c7dc30b 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); @@ -943,18 +641,25 @@ void C_NewModeAdjust () C_AdjustBottom (); } +int consoletic = 0; void C_Ticker () { static int lasttic = 0; + consoletic++; if (lasttic == 0) - lasttic = gametic - 1; + lasttic = consoletic - 1; + + if (con_buffersize > 0) + { + conbuffer->ResizeBuffer(con_buffersize); + } if (ConsoleState != c_up) { if (ConsoleState == c_falling) { - ConBottom += (gametic - lasttic) * (SCREENHEIGHT*2/25); + ConBottom += (consoletic - lasttic) * (SCREENHEIGHT * 2 / 25); if (ConBottom >= SCREENHEIGHT / 2) { ConBottom = SCREENHEIGHT / 2; @@ -963,7 +668,7 @@ void C_Ticker () } else if (ConsoleState == c_rising) { - ConBottom -= (gametic - lasttic) * (SCREENHEIGHT*2/25); + ConBottom -= (consoletic - lasttic) * (SCREENHEIGHT * 2 / 25); if (ConBottom <= 0) { ConsoleState = c_up; @@ -978,7 +683,7 @@ void C_Ticker () CursorTicker = C_BLINKRATE; } - lasttic = gametic; + lasttic = consoletic; if (NotifyTopGoal > NotifyTop) { @@ -1237,38 +942,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 +983,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 +1135,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 +1145,10 @@ static bool C_HandleKey (event_t *ev, BYTE *buffer, int len) { RowAdjust++; } + if (RowAdjust > conbuffer->GetFormattedLineCount()) + { + RowAdjust = conbuffer->GetFormattedLineCount(); + } } break; @@ -1489,7 +1182,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 +1391,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 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 88dbc5d64..105d8c0d3 100644 --- a/src/c_dispatch.cpp +++ b/src/c_dispatch.cpp @@ -627,7 +627,14 @@ void C_DoCommand (const char *cmd, int keynum) } else { - new DStoredCommand (com, beg); + if (len == 4 && strnicmp(beg, "warp", 4) == 0) + { + StoredWarp = beg; + } + else + { + new DStoredCommand (com, beg); + } } } else 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/d_main.cpp b/src/d_main.cpp index e7fe56f78..edebba6d9 100644 --- a/src/d_main.cpp +++ b/src/d_main.cpp @@ -108,10 +108,6 @@ #include "r_renderer.h" #include "p_local.h" -#ifdef USE_POLYMOST -#include "r_polymost.h" -#endif - EXTERN_CVAR(Bool, hud_althud) void DrawHUD(); @@ -186,9 +182,6 @@ CUSTOM_CVAR (Int, fraglimit, 0, CVAR_SERVERINFO) } } -#ifdef USE_POLYMOST -CVAR(Bool, testpolymost, false, 0) -#endif CVAR (Float, timelimit, 0.f, CVAR_SERVERINFO); CVAR (Int, wipetype, 1, CVAR_ARCHIVE); CVAR (Int, snd_drawoutput, 0, 0); @@ -218,6 +211,7 @@ int NoWipe; // [RH] Allow wipe? (Needs to be set each time) bool singletics = false; // debug flag to cancel adaptiveness FString startmap; bool autostart; +FString StoredWarp; bool advancedemo; FILE *debugfile; event_t events[MAXEVENTS]; @@ -281,10 +275,6 @@ void D_ProcessEvents (void) continue; // console ate the event if (M_Responder (ev)) continue; // menu ate the event - #ifdef USE_POLYMOST - if (testpolymost) - Polymost_Responder (ev); - #endif G_Responder (ev); } } @@ -306,9 +296,6 @@ void D_PostEvent (const event_t *ev) } events[eventhead] = *ev; if (ev->type == EV_Mouse && !paused && menuactive == MENU_Off && ConsoleState != c_down && ConsoleState != c_falling -#ifdef USE_POLYMOST - && !testpolymost -#endif ) { if (Button_Mlook.bDown || freelook) @@ -421,7 +408,7 @@ CVAR (Flag, sv_fastmonsters, dmflags, DF_FAST_MONSTERS); CVAR (Flag, sv_nojump, dmflags, DF_NO_JUMP); CVAR (Flag, sv_allowjump, dmflags, DF_YES_JUMP); CVAR (Flag, sv_nofreelook, dmflags, DF_NO_FREELOOK); -CVAR (Flag, sv_respawnsuper, dmflags, DF_RESPAWN_SUPER); +CVAR (Flag, sv_allowfreelook, dmflags, DF_YES_FREELOOK); CVAR (Flag, sv_nofov, dmflags, DF_NO_FOV); CVAR (Flag, sv_noweaponspawn, dmflags, DF_NO_COOP_WEAPON_SPAWN); CVAR (Flag, sv_nocrouch, dmflags, DF_NO_CROUCH); @@ -438,6 +425,7 @@ CVAR (Flag, sv_coophalveammo, dmflags, DF_COOP_HALVE_AMMO); CVAR (Mask, sv_crouch, dmflags, DF_NO_CROUCH|DF_YES_CROUCH); CVAR (Mask, sv_jump, dmflags, DF_NO_JUMP|DF_YES_JUMP); CVAR (Mask, sv_fallingdamage, dmflags, DF_FORCE_FALLINGHX|DF_FORCE_FALLINGZD); +CVAR (Mask, sv_freelook, dmflags, DF_NO_FREELOOK|DF_YES_FREELOOK); //========================================================================== // @@ -509,6 +497,8 @@ CVAR (Flag, sv_noautoaim, dmflags2, DF2_NOAUTOAIM); CVAR (Flag, sv_dontcheckammo, dmflags2, DF2_DONTCHECKAMMO); CVAR (Flag, sv_killbossmonst, dmflags2, DF2_KILLBOSSMONST); CVAR (Flag, sv_nocountendmonst, dmflags2, DF2_NOCOUNTENDMONST); +CVAR (Flag, sv_respawnsuper, dmflags2, DF2_RESPAWN_SUPER); + //========================================================================== // // CVAR compatflags @@ -739,15 +729,7 @@ void D_Display () hw2d = false; -#ifdef USE_POLYMOST - if (testpolymost) - { - drawpolymosttest(); - C_DrawConsole(hw2d); - M_Drawer(); - } - else -#endif + { unsigned int nowtime = I_FPSTime(); TexMan.UpdateAnimations(nowtime); @@ -1233,7 +1215,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; @@ -1298,7 +1280,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; @@ -1318,7 +1300,7 @@ void D_DoAdvanceDemo (void) break; } - if (pagename) + if (pagename.IsNotEmpty()) { if (Page != NULL) { @@ -1597,7 +1579,7 @@ void D_AddConfigWads (TArray &wadfiles, const char *section) { // D_AddWildFile resets GameConfig's position, so remember it GameConfig->GetPosition (pos); - D_AddWildFile (wadfiles, value); + D_AddWildFile (wadfiles, ExpandEnvVars(value)); // Reset GameConfig's position to get next wad GameConfig->SetPosition (pos); } @@ -1806,19 +1788,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(',')); @@ -1860,6 +1846,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; } @@ -1993,13 +1988,23 @@ static void D_DoomInit() Args->CollectFiles("-playdemo", ".lmp"); Args->CollectFiles("-file", NULL); // anything left goes after -file - atterm (C_DeinitConsole); - gamestate = GS_STARTUP; 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"); @@ -2101,7 +2106,7 @@ static void CheckCmdLine() { startmap = "&wt@01"; } - autostart = false; + autostart = StoredWarp.IsNotEmpty(); const char *val = Args->CheckValue ("-skill"); if (val) @@ -2157,17 +2162,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) @@ -2225,6 +2219,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.IsNotEmpty()) + { + execLogfile(logfile); + } + D_DoomInit(); // [RH] Make sure zdoom.pk3 is always loaded, @@ -2255,7 +2256,7 @@ void D_DoomMain (void) // The IWAD selection dialogue does not show in fullscreen so if the // restart is initiated without a defined IWAD assume for now that it's not going to change. - if (iwad.Len() == 0) iwad = lastIWAD; + if (iwad.IsEmpty()) iwad = lastIWAD; FIWadManager *iwad_man = new FIWadManager; const FIWADInfo *iwad_info = iwad_man->FindIWAD(allwads, iwad, basewad); @@ -2283,8 +2284,6 @@ void D_DoomMain (void) execFiles = Args->GatherFiles ("-exec"); D_MultiExec (execFiles, true); - C_ExecCmdLineParams (); // [RH] do all +set commands on the command line - CopyFiles(allwads, pwads); // Since this function will never leave we must delete this array here manually. @@ -2300,6 +2299,8 @@ void D_DoomMain (void) // Now that wads are loaded, define mod-specific cvars. ParseCVarInfo(); + C_ExecCmdLineParams (); // [RH] do all +set commands on the command line + // [RH] Initialize localizable strings. GStrings.LoadStrings (false); @@ -2530,6 +2531,11 @@ void D_DoomMain (void) if (demorecording) G_BeginRecording (startmap); G_InitNew (startmap, false); + if (StoredWarp.IsNotEmpty()) + { + AddCommandString(StoredWarp.LockBuffer()); + StoredWarp = NULL; + } } else { diff --git a/src/d_net.cpp b/src/d_net.cpp index e86642d91..586040d4b 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; @@ -1271,6 +1275,55 @@ void NetUpdate (void) // listen for other packets GetPackets (); + + if (!resendOnly) + { + // ideally nettics[0] should be 1 - 3 tics above lowtic + // if we are consistantly slower, speed up time + + // [RH] I had erroneously assumed frameskip[] had 4 entries + // because there were 4 players, but that's not the case at + // all. The game is comparing the lag behind the master for + // four runs of TryRunTics. If our tic count is ahead of the + // master all 4 times, the next run of NetUpdate will not + // process any new input. If we have less input than the + // master, the next run of NetUpdate will process extra tics + // (because gametime gets decremented here). + + // the key player does not adapt + if (consoleplayer != Net_Arbitrator) + { + // I'm not sure about this when using a packet server, because + // if left unmodified from the P2P version, it can make the game + // very jerky. The way I have it written right now basically means + // that it won't adapt. Fortunately, player prediction helps + // alleviate the lag somewhat. + + if (NetMode != NET_PacketServer) + { + mastertics = nettics[nodeforplayer[Net_Arbitrator]]; + } + if (nettics[0] <= mastertics) + { + gametime--; + if (debugfile) fprintf(debugfile, "-"); + } + if (NetMode != NET_PacketServer) + { + frameskip[(maketic / ticdup) & 3] = (oldnettics > mastertics); + } + else + { + frameskip[(maketic / ticdup) & 3] = (oldnettics - mastertics) > 3; + } + if (frameskip[0] && frameskip[1] && frameskip[2] && frameskip[3]) + { + skiptics = 1; + if (debugfile) fprintf(debugfile, "+"); + } + oldnettics = nettics[0]; + } + } } @@ -1381,7 +1434,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); @@ -1747,70 +1800,27 @@ void TryRunTics (void) else counts = availabletics; + // Uncapped framerate needs seprate checks if (counts == 0 && !doWait) { + // Check possible stall conditions + Net_CheckLastRecieved(counts); + if (realtics >= 1) + { + C_Ticker(); + M_Ticker(); + } return; } if (counts < 1) counts = 1; - frameon++; - if (debugfile) fprintf (debugfile, "=======real: %i avail: %i game: %i\n", realtics, availabletics, counts); - if (!demoplayback) - { - // ideally nettics[0] should be 1 - 3 tics above lowtic - // if we are consistantly slower, speed up time - - // [RH] I had erroneously assumed frameskip[] had 4 entries - // because there were 4 players, but that's not the case at - // all. The game is comparing the lag behind the master for - // four runs of TryRunTics. If our tic count is ahead of the - // master all 4 times, the next run of NetUpdate will not - // process any new input. If we have less input than the - // master, the next run of NetUpdate will process extra tics - // (because gametime gets decremented here). - - // the key player does not adapt - if (consoleplayer != Net_Arbitrator) - { - // I'm not sure about this when using a packet server, because - // if left unmodified from the P2P version, it can make the game - // very jerky. The way I have it written right now basically means - // that it won't adapt. Fortunately, player prediction helps - // alleviate the lag somewhat. - - if (NetMode != NET_PacketServer) - { - mastertics = nettics[nodeforplayer[Net_Arbitrator]]; - } - if (nettics[0] <= mastertics) - { - gametime--; - if (debugfile) fprintf (debugfile, "-"); - } - if (NetMode != NET_PacketServer) - { - frameskip[frameon&3] = (oldnettics > mastertics); - } - else - { - frameskip[frameon&3] = (oldnettics - mastertics) > 3; - } - if (frameskip[0] && frameskip[1] && frameskip[2] && frameskip[3]) - { - skiptics = 1; - if (debugfile) fprintf (debugfile, "+"); - } - oldnettics = nettics[0]; - } - }// !demoplayback - // wait for new tics if needed while (lowtic < gametic + counts) { @@ -1826,35 +1836,11 @@ 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) + if (I_GetTime (false) - entertic >= 1) { C_Ticker (); M_Ticker (); @@ -1862,12 +1848,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 +1880,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 (); @@ -2144,7 +2167,8 @@ void Net_DoCommand (int type, BYTE **stream, int player) { DWORD which = ReadLong (stream); - if (gamestate == GS_LEVEL && !paused) + if (gamestate == GS_LEVEL && !paused + && players[player].playerstate != PST_DEAD) { AInventory *item = players[player].mo->Inventory; while (item != NULL && item->InventoryID != which) @@ -2554,7 +2578,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 8101c5248..730016c25 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 @@ -1058,4 +1049,5 @@ userinfo_t::~userinfo_t() { delete pair->Value; } + this->Clear(); } diff --git a/src/d_player.h b/src/d_player.h index 190689ca0..fc62e5531 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -219,6 +219,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, @@ -346,10 +347,14 @@ struct userinfo_t : TMap { return *static_cast(*CheckKey(NAME_Gender)); } + bool GetNoAutostartMap() const + { + return *static_cast(*CheckKey(NAME_Wi_NoAutostartMap)); + } 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); @@ -359,8 +364,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 @@ -369,6 +374,7 @@ class player_t { public: player_t(); + player_t &operator= (const player_t &p); void Serialize (FArchive &arc); size_t FixPointers (const DObject *obj, DObject *replacement); @@ -449,6 +455,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/dobject.h b/src/dobject.h index e96b7d6c2..40445c8a0 100644 --- a/src/dobject.h +++ b/src/dobject.h @@ -474,7 +474,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..3e00975cf 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 @@ -253,7 +254,7 @@ enum DF_NO_JUMP = 1 << 16, // Don't allow jumping DF_YES_JUMP = 2 << 16, DF_NO_FREELOOK = 1 << 18, // Don't allow freelook - DF_RESPAWN_SUPER = 1 << 19, // Respawn invulnerability and invisibility + DF_YES_FREELOOK = 2 << 18, DF_NO_FOV = 1 << 20, // Only let the arbitrator set FOV (for all players) DF_NO_COOP_WEAPON_SPAWN = 1 << 21, // Don't spawn multiplayer weapons in coop games DF_NO_CROUCH = 1 << 22, // Don't allow crouching @@ -297,6 +298,7 @@ enum DF2_DONTCHECKAMMO = 1 << 24, // Don't Check ammo when switching weapons. DF2_KILLBOSSMONST = 1 << 25, // Kills all monsters spawned by a boss cube when the boss dies DF2_NOCOUNTENDMONST = 1 << 26, // Do not count monsters in 'end level when dying' sectors towards kill count + DF2_RESPAWN_SUPER = 1 << 27, // Respawn invulnerability and invisibility }; // [RH] Compatibility flags. @@ -350,6 +352,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/doomstat.h b/src/doomstat.h index 2819f1bf0..92ab5b8f8 100644 --- a/src/doomstat.h +++ b/src/doomstat.h @@ -59,6 +59,8 @@ extern FString startmap; // [RH] Actual map name now extern bool autostart; +extern FString StoredWarp; // [RH] +warp at the command line + // Selected by user. EXTERN_CVAR (Int, gameskill); extern int NextSkill; // [RH] Skill to use at next level load 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 704d7a2d9..c186bb7cc 100644 --- a/src/dthinker.cpp +++ b/src/dthinker.cpp @@ -358,12 +358,10 @@ void DThinker::DestroyThinkersInList (FThinkerList &list) { if (list.Sentinel != NULL) { - DThinker *node = list.Sentinel->NextThinker; - while (node != list.Sentinel) + for (DThinker *node = list.Sentinel->NextThinker; node != list.Sentinel; node = list.Sentinel->NextThinker) { - DThinker *next = node->NextThinker; + assert(node != NULL); node->Destroy(); - node = next; } list.Sentinel->Destroy(); list.Sentinel = NULL; @@ -381,9 +379,8 @@ void DThinker::DestroyMostThinkersInList (FThinkerList &list, int stat) // it from the list. G_FinishTravel() will find it later from // a players[].mo link and destroy it then, after copying various // information to a new player. - for (DThinker *probe = list.Sentinel->NextThinker, *next; probe != list.Sentinel; probe = next) + for (DThinker *probe = list.Sentinel->NextThinker; probe != list.Sentinel; probe = list.Sentinel->NextThinker) { - next = probe->NextThinker; if (!probe->IsKindOf(RUNTIME_CLASS(APlayerPawn)) || // <- should not happen static_cast(probe)->player == NULL || static_cast(probe)->player->mo != probe) @@ -459,7 +456,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..d7dad642e 100644 --- a/src/files.cpp +++ b/src/files.cpp @@ -33,11 +33,17 @@ ** */ +#ifdef _WIN32 +#define USE_WINDOWS_DWORD +#endif +#include "LzmaDec.h" + #include "files.h" #include "i_system.h" #include "templates.h" #include "m_misc.h" + //========================================================================== // // FileReader @@ -370,8 +376,17 @@ 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); } +// This is retarded but necessary to work around the inclusion of windows.h in recent +// LZMA versions, meaning it's no longer possible to include the LZMA headers in files.h. +// As a result we cannot declare the CLzmaDec member in the header so we work around +// it my wrapping it into another struct that can be declared anonymously in the header. +struct FileReaderLZMA::StreamPointer +{ + CLzmaDec Stream; +}; + +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) @@ -398,20 +413,22 @@ FileReaderLZMA::FileReaderLZMA (FileReader &file, size_t uncompressed_size, bool FillBuffer(); - LzmaDec_Construct(&Stream); - err = LzmaDec_Allocate(&Stream, header + 4, LZMA_PROPS_SIZE, &g_Alloc); + Streamp = new StreamPointer; + LzmaDec_Construct(&Streamp->Stream); + err = LzmaDec_Allocate(&Streamp->Stream, header + 4, LZMA_PROPS_SIZE, &g_Alloc); if (err != SZ_OK) { I_Error("FileReaderLZMA: LzmaDec_Allocate failed: %d\n", err); } - LzmaDec_Init(&Stream); + LzmaDec_Init(&Streamp->Stream); } FileReaderLZMA::~FileReaderLZMA () { - LzmaDec_Free(&Stream, &g_Alloc); + LzmaDec_Free(&Streamp->Stream, &g_Alloc); + delete Streamp; } long FileReaderLZMA::Read (void *buffer, long len) @@ -426,7 +443,7 @@ long FileReaderLZMA::Read (void *buffer, long len) size_t out_processed = len; size_t in_processed = InSize; - err = LzmaDec_DecodeToBuf(&Stream, next_out, &out_processed, InBuff + InPos, &in_processed, finish_mode, &status); + err = LzmaDec_DecodeToBuf(&Streamp->Stream, next_out, &out_processed, InBuff + InPos, &in_processed, finish_mode, &status); InPos += in_processed; InSize -= in_processed; next_out += out_processed; diff --git a/src/files.h b/src/files.h index ebe9665a4..f7d061c8e 100644 --- a/src/files.h +++ b/src/files.h @@ -4,7 +4,6 @@ #include #include #include "bzlib.h" -#include "LzmaDec.h" #include "doomtype.h" #include "m_swap.h" @@ -257,6 +256,8 @@ private: // Wraps around a FileReader to decompress a lzma stream class FileReaderLZMA : public FileReaderBase { + struct StreamPointer; + public: FileReaderLZMA (FileReader &file, size_t uncompressed_size, bool zip); ~FileReaderLZMA (); @@ -308,7 +309,7 @@ private: FileReader &File; bool SawEOF; - CLzmaDec Stream; + StreamPointer *Streamp; // anonymous pointer to LKZA decoder struct - to avoid including the LZMA headers globally size_t Size; size_t InPos, InSize; size_t OutProcessed; 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 ae7918920..f83528bb3 100644 --- a/src/fragglescript/t_func.cpp +++ b/src/fragglescript/t_func.cpp @@ -154,7 +154,7 @@ static const char * const ActorNames_init[]= "RocketAmmo", "RocketBox", "Cell", - "CellBox", + "CellPack", "Shell", "ShellBox", "Backpack", @@ -3530,8 +3530,17 @@ void FParser::SF_MapThingNumExist() } else { + // Inventory items in the player's inventory have to be considered non-present. + if (SpawnedThings[intval]->IsKindOf(RUNTIME_CLASS(AInventory)) && + barrier_cast(SpawnedThings[intval])->Owner != NULL) + { + t_return.value.i = 0; + } + else + { + t_return.value.i = 1; + } t_return.type = svt_int; - t_return.value.i = 1; } } } @@ -3770,11 +3779,14 @@ void FParser::SF_ObjType() mo = Script->trigger; } - for(unsigned int i=0;iGetClass() == ActorTypes[i]) + if (mo != NULL) { - t_return.type = svt_int; - t_return.value.i = i; - return; + for (unsigned int i = 0; i < countof(ActorTypes); i++) if (mo->GetClass() == ActorTypes[i]) + { + t_return.type = svt_int; + t_return.value.i = i; + return; + } } t_return.type = svt_int; t_return.value.i = -1; 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/g_doom/a_doomweaps.cpp b/src/g_doom/a_doomweaps.cpp index 7227b50f4..108e40f96 100644 --- a/src/g_doom/a_doomweaps.cpp +++ b/src/g_doom/a_doomweaps.cpp @@ -55,7 +55,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_Punch) angle += pr_punch.Random2() << 18; pitch = P_AimLineAttack (self, angle, MELEERANGE, &linetarget); - P_LineAttack (self, angle, MELEERANGE, pitch, damage, NAME_Melee, NAME_BulletPuff, true, &linetarget); + P_LineAttack (self, angle, MELEERANGE, pitch, damage, NAME_Melee, NAME_BulletPuff, LAF_ISMELEEATTACK, &linetarget); // turn to face target if (linetarget) diff --git a/src/g_game.cpp b/src/g_game.cpp index e1e88d0d1..405b42b99 100644 --- a/src/g_game.cpp +++ b/src/g_game.cpp @@ -568,7 +568,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) { @@ -778,7 +778,7 @@ void G_AddViewPitch (int look) else if (look > 0) { // Avoid overflowing - if (LocalViewPitch + look <= LocalViewPitch) + if (LocalViewPitch > INT_MAX - look) { LocalViewPitch = 0x78000000; } @@ -790,7 +790,7 @@ void G_AddViewPitch (int look) else if (look < 0) { // Avoid overflowing - if (LocalViewPitch + look >= LocalViewPitch) + if (LocalViewPitch < INT_MIN - look) { LocalViewPitch = -0x78000000; } @@ -1310,7 +1310,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(); @@ -1624,7 +1624,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; } @@ -1838,6 +1838,13 @@ void G_DoLoadGame () BYTE *vars_p = (BYTE *)text; C_ReadCVars (&vars_p); delete[] text; + if (SaveVersion <= 4509) + { + // account for the flag shuffling for making freelook a 3-state option + INTBOOL flag = dmflags & DF_YES_FREELOOK; + dmflags = dmflags & ~DF_YES_FREELOOK; + if (flag) dmflags2 = dmflags2 | DF2_RESPAWN_SUPER; + } } // dearchive all the modifications @@ -1922,32 +1929,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(); @@ -2052,7 +2037,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'; @@ -2113,7 +2098,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); @@ -2314,7 +2299,7 @@ void G_BeginRecording (const char *startmap) if (startmap == NULL) { - startmap = level.mapname; + startmap = level.MapName; } demo_p = demobuffer; @@ -2327,11 +2312,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); @@ -2410,7 +2394,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; @@ -2466,9 +2450,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) @@ -2550,7 +2541,7 @@ bool G_ProcessIFFDemo (char *mapname) void G_DoPlayDemo (void) { - char mapname[9]; + FString mapname; int demolump; gameaction = ga_nothing; @@ -2603,7 +2594,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_heretic/a_hereticmisc.cpp b/src/g_heretic/a_hereticmisc.cpp index fa33c1297..9d6468495 100644 --- a/src/g_heretic/a_hereticmisc.cpp +++ b/src/g_heretic/a_hereticmisc.cpp @@ -202,7 +202,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_VolcBallImpact) { PARAM_ACTION_PROLOGUE; - int i; + unsigned int i; AActor *tiny; angle_t angle; diff --git a/src/g_heretic/a_hereticweaps.cpp b/src/g_heretic/a_hereticweaps.cpp index 6fd883a43..8143a4aaf 100644 --- a/src/g_heretic/a_hereticweaps.cpp +++ b/src/g_heretic/a_hereticweaps.cpp @@ -839,7 +839,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_SpawnRippers) { PARAM_ACTION_PROLOGUE; - int i; + unsigned int i; angle_t angle; AActor *ripper; diff --git a/src/g_heretic/a_ironlich.cpp b/src/g_heretic/a_ironlich.cpp index 2dae04546..c5a74ac7b 100644 --- a/src/g_heretic/a_ironlich.cpp +++ b/src/g_heretic/a_ironlich.cpp @@ -179,7 +179,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_LichIceImpact) { PARAM_ACTION_PROLOGUE; - int i; + unsigned int i; angle_t angle; AActor *shard; diff --git a/src/g_hexen/a_fighteraxe.cpp b/src/g_hexen/a_fighteraxe.cpp index ea3d33305..6a2c841a7 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_fighterquietus.cpp b/src/g_hexen/a_fighterquietus.cpp index 68a8711cb..269381b76 100644 --- a/src/g_hexen/a_fighterquietus.cpp +++ b/src/g_hexen/a_fighterquietus.cpp @@ -59,12 +59,12 @@ class AFSwordMissile : public AActor { DECLARE_CLASS (AFSwordMissile, AActor) public: - int DoSpecialDamage(AActor *victim, AActor *source, int damage, FName damagetype); + int DoSpecialDamage(AActor *victim, int damage, FName damagetype); }; IMPLEMENT_CLASS (AFSwordMissile) -int AFSwordMissile::DoSpecialDamage(AActor *victim, AActor *source, int damage, FName damagetype) +int AFSwordMissile::DoSpecialDamage(AActor *victim, int damage, FName damagetype) { if (victim->player) { diff --git a/src/g_hexen/a_heresiarch.cpp b/src/g_hexen/a_heresiarch.cpp index 1b3214b77..3176fe799 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_hexen/a_iceguy.cpp b/src/g_hexen/a_iceguy.cpp index c5f43ba30..3acc6b3d0 100644 --- a/src/g_hexen/a_iceguy.cpp +++ b/src/g_hexen/a_iceguy.cpp @@ -139,7 +139,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_IceGuyMissileExplode) PARAM_ACTION_PROLOGUE; AActor *mo; - int i; + unsigned int i; for (i = 0; i < 8; i++) { diff --git a/src/g_level.cpp b/src/g_level.cpp index 0b07ae2b5..69bee5de1 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(); @@ -1324,11 +1320,11 @@ bool FLevelLocals::IsCrouchingAllowed() const bool FLevelLocals::IsFreelookAllowed() const { - if (level.flags & LEVEL_FREELOOK_NO) + if (dmflags & DF_NO_FREELOOK) return false; - if (level.flags & LEVEL_FREELOOK_YES) + if (dmflags & DF_YES_FREELOOK) return true; - return !(dmflags & DF_NO_FREELOOK); + return !(level.flags & LEVEL_FREELOOK_NO); } //========================================================================== @@ -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 a6b1f5aa1..527f477c1 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; @@ -76,11 +77,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(); @@ -266,16 +267,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; @@ -310,7 +311,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; @@ -388,9 +389,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; @@ -404,8 +405,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; @@ -552,6 +553,7 @@ enum ESkillProperty SKILLP_NoPain, SKILLP_ArmorFactor, SKILLP_EasyKey, + SKILLP_SlowMonsters, }; int G_SkillProperty(ESkillProperty prop); const char * G_SkillName(); @@ -566,6 +568,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 6c5bea456..b4026b7cd 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. } diff --git a/src/g_shared/a_armor.cpp b/src/g_shared/a_armor.cpp index 89be479c6..d137f5c16 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 d4690139f..88ab0c797 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_bridge.cpp b/src/g_shared/a_bridge.cpp index 583656dd1..3c2cb6316 100644 --- a/src/g_shared/a_bridge.cpp +++ b/src/g_shared/a_bridge.cpp @@ -38,6 +38,7 @@ class ACustomBridge : public AActor DECLARE_CLASS (ACustomBridge, AActor) public: void BeginPlay (); + void Destroy(); }; IMPLEMENT_CLASS(ACustomBridge) @@ -58,6 +59,25 @@ void ACustomBridge::BeginPlay () } } +void ACustomBridge::Destroy() +{ + // Hexen originally just set a flag to make the bridge balls remove themselves in A_BridgeOrbit. + // But this is not safe with custom bridge balls that do not necessarily call that function. + // So the best course of action is to look for all bridge balls here and destroy them ourselves. + + TThinkerIterator it; + AActor *thing; + + while ((thing = it.Next())) + { + if (thing->target == this) + { + thing->Destroy(); + } + } + Super::Destroy(); +} + // Action functions for the non-Doom bridge -------------------------------- #define ORBIT_RADIUS 15 @@ -91,10 +111,6 @@ DEFINE_ACTION_FUNCTION(AActor, A_BridgeOrbit) // Set rotation radius if (self->target->args[4]) rotationradius = ((self->target->args[4] * self->target->radius) / (100 * FRACUNIT)); - if (self->target->special1) - { - self->SetState (NULL); - } self->angle += rotationspeed; self->x = self->target->x + rotationradius * finecosine[self->angle >> ANGLETOFINESHIFT]; self->y = self->target->y + rotationradius * finesine[self->angle >> ANGLETOFINESHIFT]; @@ -121,7 +137,6 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_BridgeInit) cy = self->y; cz = self->z; startangle = pr_orbit() << 24; - self->special1 = 0; // Spawn triad into world -- may be more than a triad now. int ballcount = self->args[2]==0 ? 3 : self->args[2]; @@ -136,14 +151,6 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_BridgeInit) return 0; } -/* never used -void A_BridgeRemove (AActor *self) -{ - self->special1 = true; // Removing the bridge - self->flags &= ~MF_SOLID; - self->SetState (&ABridge::States[S_FREE_BRIDGE]); -} -*/ // Invisible bridge -------------------------------------------------------- diff --git a/src/g_shared/a_keys.cpp b/src/g_shared/a_keys.cpp index bdf8e66e7..d0fcc9e3f 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 98ecf9e61..0261d09d7 100644 --- a/src/g_shared/a_pickups.cpp +++ b/src/g_shared/a_pickups.cpp @@ -543,7 +543,7 @@ bool AInventory::SpecialDropAction (AActor *dropper) bool AInventory::ShouldRespawn () { - if ((ItemFlags & IF_BIGPOWERUP) && !(dmflags & DF_RESPAWN_SUPER)) return false; + if ((ItemFlags & IF_BIGPOWERUP) && !(dmflags2 & DF2_RESPAWN_SUPER)) return false; if (ItemFlags & IF_NEVERRESPAWN) return false; return !!(dmflags & DF_ITEMS_RESPAWN); } @@ -831,7 +831,7 @@ void AInventory::BecomePickup () LinkToWorld (); P_FindFloorCeiling (this); } - flags = GetDefault()->flags | MF_DROPPED; + flags = (GetDefault()->flags | MF_DROPPED) & ~MF_COUNTITEM; renderflags &= ~RF_INVISIBLE; SetState (SpawnState); } @@ -1064,7 +1064,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 @@ -1868,7 +1868,10 @@ bool ABackpackItem::HandlePickup (AInventory *item) AInventory *ABackpackItem::CreateTossable () { ABackpackItem *pack = static_cast(Super::CreateTossable()); - pack->bDepleted = true; + if (pack != NULL) + { + pack->bDepleted = true; + } return pack; } 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 11759cad7..94461d9e2 100644 --- a/src/g_shared/a_weapons.cpp +++ b/src/g_shared/a_weapons.cpp @@ -1161,7 +1161,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; } @@ -1216,7 +1216,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 09045cd57..e234a2ead 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 ce69af37f..e24811c85 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 f6e3b10d9..77dab48dc 100644 --- a/src/g_shared/shared_hud.cpp +++ b/src/g_shared/shared_hud.cpp @@ -70,6 +70,7 @@ CVAR (Bool, hud_showmonsters, true,CVAR_ARCHIVE); // Show monster stats on HUD CVAR (Bool, hud_showitems, false,CVAR_ARCHIVE); // Show item stats on HUD CVAR (Bool, hud_showstats, false, CVAR_ARCHIVE); // for stamina and accuracy. CVAR (Bool, hud_showscore, false, CVAR_ARCHIVE); // for user maintained score +CVAR (Bool, hud_showweapons, true, CVAR_ARCHIVE); // Show weapons collected CVAR (Int , hud_showtime, 0, CVAR_ARCHIVE); // Show time on HUD CVAR (Int , hud_timecolor, CR_GOLD,CVAR_ARCHIVE); // Color of in-game time on HUD @@ -133,12 +134,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; } @@ -650,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()) { @@ -953,7 +972,7 @@ void DrawHUD() CPlayer->mo->FindInventory(), 5, hudheight-20); i=DrawKeys(CPlayer, hudwidth-4, hudheight-10); i=DrawAmmo(CPlayer, hudwidth-5, i); - DrawWeapons(CPlayer, hudwidth-5, i); + if (hud_showweapons) DrawWeapons(CPlayer, hudwidth - 5, i); DrawInventory(CPlayer, 144, hudheight-28); if (CPlayer->camera && CPlayer->camera->player) { diff --git a/src/g_shared/shared_sbar.cpp b/src/g_shared/shared_sbar.cpp index 86f5adc92..aafc0ec19 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 e52db1f3c..c4c0c34fb 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 c1094af2b..3343f7325 100644 --- a/src/g_strife/a_entityboss.cpp +++ b/src/g_strife/a_entityboss.cpp @@ -102,7 +102,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_thingstoblowup.cpp b/src/g_strife/a_thingstoblowup.cpp index 018f4d589..a64daa911 100644 --- a/src/g_strife/a_thingstoblowup.cpp +++ b/src/g_strife/a_thingstoblowup.cpp @@ -102,8 +102,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 211ef96c6..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 @@ -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/hu_scores.cpp b/src/hu_scores.cpp index afbb7a35d..af5d1bbaa 100644 --- a/src/hu_scores.cpp +++ b/src/hu_scores.cpp @@ -82,9 +82,7 @@ CVAR (Int, sb_deathmatch_otherplayercolor, CR_GREY, CVAR_ARCHIVE) CVAR (Bool, sb_teamdeathmatch_enable, true, CVAR_ARCHIVE) CVAR (Int, sb_teamdeathmatch_headingcolor, CR_RED, CVAR_ARCHIVE) -// PRIVATE DATA DEFINITIONS ------------------------------------------------ - -static int STACK_ARGS comparepoints (const void *arg1, const void *arg2) +int STACK_ARGS comparepoints (const void *arg1, const void *arg2) { // Compare first be frags/kills, then by name. player_t *p1 = *(player_t **)arg1; @@ -99,7 +97,7 @@ static int STACK_ARGS comparepoints (const void *arg1, const void *arg2) return diff; } -static int STACK_ARGS compareteams (const void *arg1, const void *arg2) +int STACK_ARGS compareteams (const void *arg1, const void *arg2) { // Compare first by teams, then by frags, then by name. player_t *p1 = *(player_t **)arg1; @@ -118,6 +116,8 @@ static int STACK_ARGS compareteams (const void *arg1, const void *arg2) return diff; } +// PRIVATE DATA DEFINITIONS ------------------------------------------------ + // CODE -------------------------------------------------------------------- //========================================================================== @@ -247,7 +247,7 @@ static void HU_DoDrawScores (player_t *player, player_t *sortedplayers[MAXPLAYER lineheight = MAX(height, maxiconheight * CleanYfac); ypadding = (lineheight - height + 1) / 2; - bottom = gamestate != GS_INTERMISSION ? ST_Y : SCREENHEIGHT; + bottom = ST_Y; y = MAX(48*CleanYfac, (bottom - MAXPLAYERS * (height + CleanYfac + 1)) / 2); HU_DrawTimeRemaining (bottom - height); @@ -255,10 +255,6 @@ static void HU_DoDrawScores (player_t *player, player_t *sortedplayers[MAXPLAYER if (teamplay && deathmatch) { y -= (BigFont->GetHeight() + 8) * CleanYfac; - if (gamestate == GS_INTERMISSION) - { - y = MAX(BigFont->GetHeight() * 4, y); - } for (i = 0; i < Teams.Size (); i++) { diff --git a/src/hu_stuff.h b/src/hu_stuff.h index c8e76fee0..dc22a2adc 100644 --- a/src/hu_stuff.h +++ b/src/hu_stuff.h @@ -21,6 +21,8 @@ #ifndef __HU_STUFF_H__ #define __HU_STUFF_H__ +#include "doomtype.h" + struct event_t; class player_t; @@ -50,4 +52,9 @@ void HU_GetPlayerWidths(int &maxnamewidth, int &maxscorewidth, int &maxiconheigh void HU_DrawColorBar(int x, int y, int height, int playernum); int HU_GetRowColor(player_t *player, bool hightlight); +// Sorting routines + +int STACK_ARGS comparepoints(const void *arg1, const void *arg2); +int STACK_ARGS compareteams(const void *arg1, const void *arg2); + #endif 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 afed14f1f..4b63bd475 100644 --- a/src/info.h +++ b/src/info.h @@ -78,6 +78,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 inline int GetFrame() const { @@ -115,6 +117,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 95f5dc07e..151815549 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_bbox.cpp b/src/m_bbox.cpp index 6d3a5b744..199da8d68 100644 --- a/src/m_bbox.cpp +++ b/src/m_bbox.cpp @@ -54,19 +54,8 @@ int FBoundingBox::BoxOnLineSide (const line_t *ld) const int p1; int p2; - switch (ld->slopetype) - { - case ST_HORIZONTAL: - p1 = m_Box[BOXTOP] > ld->v1->y; - p2 = m_Box[BOXBOTTOM] > ld->v1->y; - if (ld->dx < 0) - { - p1 ^= 1; - p2 ^= 1; - } - break; - - case ST_VERTICAL: + if (ld->dx == 0) + { // ST_VERTICAL p1 = m_Box[BOXRIGHT] < ld->v1->x; p2 = m_Box[BOXLEFT] < ld->v1->x; if (ld->dy < 0) @@ -74,18 +63,26 @@ int FBoundingBox::BoxOnLineSide (const line_t *ld) const p1 ^= 1; p2 ^= 1; } - break; - - case ST_POSITIVE: + } + else if (ld->dy == 0) + { // ST_HORIZONTAL: + p1 = m_Box[BOXTOP] > ld->v1->y; + p2 = m_Box[BOXBOTTOM] > ld->v1->y; + if (ld->dx < 0) + { + p1 ^= 1; + p2 ^= 1; + } + } + else if ((ld->dy ^ ld->dx) >= 0) + { // ST_POSITIVE: p1 = P_PointOnLineSide (m_Box[BOXLEFT], m_Box[BOXTOP], ld); p2 = P_PointOnLineSide (m_Box[BOXRIGHT], m_Box[BOXBOTTOM], ld); - break; - - case ST_NEGATIVE: - default: // Just to assure GCC that p1 and p2 really do get initialized + } + else + { // ST_NEGATIVE: p1 = P_PointOnLineSide (m_Box[BOXRIGHT], m_Box[BOXTOP], ld); p2 = P_PointOnLineSide (m_Box[BOXLEFT], m_Box[BOXBOTTOM], ld); - break; } return (p1 == p2) ? p1 : -1; diff --git a/src/m_misc.cpp b/src/m_misc.cpp index e218cadc4..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/m_swap.h b/src/m_swap.h index 6e0bc88cc..82751fd47 100644 --- a/src/m_swap.h +++ b/src/m_swap.h @@ -29,51 +29,51 @@ // WAD files are stored little endian. #ifdef __APPLE__ -#include +#include inline short LittleShort(short x) { - return (short)CFSwapInt16LittleToHost((uint16_t)x); + return (short)OSSwapLittleToHostInt16((uint16_t)x); } inline unsigned short LittleShort(unsigned short x) { - return CFSwapInt16LittleToHost(x); + return OSSwapLittleToHostInt16(x); } inline short LittleShort(int x) { - return CFSwapInt16LittleToHost((uint16_t)x); + return OSSwapLittleToHostInt16((uint16_t)x); } inline int LittleLong(int x) { - return CFSwapInt32LittleToHost((uint32_t)x); + return OSSwapLittleToHostInt32((uint32_t)x); } inline unsigned int LittleLong(unsigned int x) { - return CFSwapInt32LittleToHost(x); + return OSSwapLittleToHostInt32(x); } inline short BigShort(short x) { - return (short)CFSwapInt16BigToHost((uint16_t)x); + return (short)OSSwapBigToHostInt16((uint16_t)x); } inline unsigned short BigShort(unsigned short x) { - return CFSwapInt16BigToHost(x); + return OSSwapBigToHostInt16(x); } inline int BigLong(int x) { - return CFSwapInt32BigToHost((uint32_t)x); + return OSSwapBigToHostInt32((uint32_t)x); } inline unsigned int BigLong(unsigned int x) { - return CFSwapInt32BigToHost(x); + return OSSwapBigToHostInt32(x); } #else 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/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/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 ff3eb016a..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; } diff --git a/src/menu/playermenu.cpp b/src/menu/playermenu.cpp index 84748785c..b42cf13b4 100644 --- a/src/menu/playermenu.cpp +++ b/src/menu/playermenu.cpp @@ -995,7 +995,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/menu/videomenu.cpp b/src/menu/videomenu.cpp index 8a6e6720d..1d1d02383 100644 --- a/src/menu/videomenu.cpp +++ b/src/menu/videomenu.cpp @@ -166,15 +166,18 @@ public: NewWidth = SCREENWIDTH; NewHeight = SCREENHEIGHT; } - OldWidth = SCREENWIDTH; - OldHeight = SCREENHEIGHT; - OldBits = DisplayBits; - NewBits = BitTranslate[DummyDepthCvar]; - setmodeneeded = true; - testingmode = I_GetTime(false) + 5 * TICRATE; - S_Sound (CHAN_VOICE | CHAN_UI, "menu/choose", snd_menuvolume, ATTN_NONE); - SetModesMenu (NewWidth, NewHeight, NewBits); - return true; + else + { + OldWidth = SCREENWIDTH; + OldHeight = SCREENHEIGHT; + OldBits = DisplayBits; + NewBits = BitTranslate[DummyDepthCvar]; + setmodeneeded = true; + testingmode = I_GetTime(false) + 5 * TICRATE; + S_Sound (CHAN_VOICE | CHAN_UI, "menu/choose", snd_menuvolume, ATTN_NONE); + SetModesMenu (NewWidth, NewHeight, NewBits); + return true; + } } return Super::Responder(ev); } @@ -348,7 +351,7 @@ void M_InitVideoModesMenu () static bool GetSelectedSize (int *width, int *height) { FOptionMenuDescriptor *opt = GetVideoModeMenu(); - if (opt != NULL) + if (opt != NULL && (unsigned)opt->mSelectedItem < opt->mItems.Size()) { int line = opt->mSelectedItem; int hsel; diff --git a/src/namedef.h b/src/namedef.h index 53c2a9327..db96b56c8 100644 --- a/src/namedef.h +++ b/src/namedef.h @@ -32,6 +32,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) @@ -375,6 +389,11 @@ xx(Friend) xx(Strifeally) xx(Standing) xx(Countsecret) +xx(Score) +xx(Roll) +xx(Scale) +xx(ScaleX) +xx(ScaleY) xx(Blocking) xx(Blockmonsters) @@ -471,6 +490,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) @@ -569,6 +597,7 @@ xx(NeverSwitchOnPickup) xx(MoveBob) xx(StillBob) xx(PlayerClass) +xx(Wi_NoAutostartMap) // Decorate compatibility functions xx(DecoRandom) 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 51ac24229..bdeb45d78 100644 --- a/src/p_3dfloors.cpp +++ b/src/p_3dfloors.cpp @@ -226,11 +226,11 @@ static int P_Set3DFloor(line_t * line, int param, int param2, int alpha) if (param==0) { flags=FF_EXISTS|FF_RENDERALL|FF_SOLID|FF_INVERTSECTOR; + alpha = 255; for (i=0;ilinecount;i++) { line_t * l=sec->lines[i]; - alpha=255; if (l->special==Sector_SetContents && l->frontsector==sec) { alpha=clamp(l->args[1], 0, 100); @@ -252,9 +252,8 @@ static int P_Set3DFloor(line_t * line, int param, int param2, int alpha) l->frontsector->ColorMap = GetSpecialLights (l->frontsector->ColorMap->Color, - (unsigned int)(vavoomcolors[l->args[0]]&VC_COLORMASK), - (unsigned int)(vavoomcolors[l->args[0]]&VC_ALPHAMASK)>>24); - // l->frontsector->ColorMap->Desaturate); + vavoomcolors[l->args[0]], + l->frontsector->ColorMap->Desaturate); } alpha=(alpha*255)/100; break; @@ -293,8 +292,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 745b66761..737721563 100644 --- a/src/p_acs.cpp +++ b/src/p_acs.cpp @@ -122,10 +122,11 @@ FRandom pr_acs ("ACS"); struct CallReturn { - CallReturn(int pc, ScriptFunction *func, FBehavior *module, SDWORD *locals, bool discard, unsigned int runaway) + CallReturn(int pc, ScriptFunction *func, FBehavior *module, SDWORD *locals, ACSLocalArrays *arrays, bool discard, unsigned int runaway) : ReturnFunction(func), ReturnModule(module), ReturnLocals(locals), + ReturnArrays(arrays), ReturnAddress(pc), bDiscardResult(discard), EntryInstrCount(runaway) @@ -134,6 +135,7 @@ struct CallReturn ScriptFunction *ReturnFunction; FBehavior *ReturnModule; SDWORD *ReturnLocals; + ACSLocalArrays *ReturnArrays; int ReturnAddress; int bDiscardResult; unsigned int EntryInstrCount; @@ -1673,6 +1675,26 @@ void FBehavior::SerializeVarSet (FArchive &arc, SDWORD *vars, int max) } } +static int ParseLocalArrayChunk(void *chunk, ACSLocalArrays *arrays, int offset) +{ + unsigned count = (LittleShort(static_cast(((unsigned *)chunk)[1]) - 2)) / 4; + int *sizes = (int *)((BYTE *)chunk + 10); + arrays->Count = count; + if (count > 0) + { + ACSLocalArrayInfo *info = new ACSLocalArrayInfo[count]; + arrays->Info = info; + for (unsigned i = 0; i < count; ++i) + { + info[i].Size = LittleLong(sizes[i]); + info[i].Offset = offset; + offset += info[i].Size; + } + } + // Return the new local variable size, with space for the arrays + return offset; +} + FBehavior::FBehavior (int lumpnum, FileReader * fr, int len) { BYTE *object; @@ -1822,12 +1844,45 @@ FBehavior::FBehavior (int lumpnum, FileReader * fr, int len) { DWORD *chunk; - Functions = FindChunk (MAKE_ID('F','U','N','C')); - if (Functions != NULL) + // Load functions + BYTE *funcs; + Functions = NULL; + funcs = FindChunk (MAKE_ID('F','U','N','C')); + if (funcs != NULL) { - NumFunctions = LittleLong(((DWORD *)Functions)[1]) / 8; - Functions += 8; + NumFunctions = LittleLong(((DWORD *)funcs)[1]) / 8; + funcs += 8; FunctionProfileData = new ACSProfileInfo[NumFunctions]; + Functions = new ScriptFunction[NumFunctions]; + for (i = 0; i < NumFunctions; ++i) + { + ScriptFunctionInFile *funcf = &((ScriptFunctionInFile *)funcs)[i]; + ScriptFunction *funcm = &Functions[i]; + funcm->ArgCount = funcf->ArgCount; + funcm->HasReturnValue = funcf->HasReturnValue; + funcm->ImportNum = funcf->ImportNum; + funcm->LocalCount = funcf->LocalCount; + funcm->Address = funcf->Address; + } + } + + // Load local arrays for functions + if (NumFunctions > 0) + { + for (chunk = (DWORD *)FindChunk(MAKE_ID('F','A','R','Y')); chunk != NULL; chunk = (DWORD *)NextChunk((BYTE *)chunk)) + { + int size = LittleLong(chunk[1]); + if (size >= 6) + { + unsigned int func_num = LittleShort(((WORD *)chunk)[4]); + if (func_num < (unsigned int)NumFunctions) + { + ScriptFunction *func = &Functions[func_num]; + // Unlike scripts, functions do not include their arg count in their local count. + func->LocalCount = ParseLocalArrayChunk(chunk, &func->LocalArrays, func->LocalCount + func->ArgCount) - func->ArgCount; + } + } + } } // Load JUMP points @@ -2135,6 +2190,11 @@ FBehavior::~FBehavior () delete[] ArrayStore; ArrayStore = NULL; } + if (Functions != NULL) + { + delete[] Functions; + Functions = NULL; + } if (FunctionProfileData != NULL) { delete[] FunctionProfileData; @@ -2302,6 +2362,21 @@ void FBehavior::LoadScriptsDirectory () } } + // Load script array sizes. (One chunk per script that uses arrays.) + for (scripts.b = FindChunk(MAKE_ID('S','A','R','Y')); scripts.dw != NULL; scripts.b = NextChunk(scripts.b)) + { + int size = LittleLong(scripts.dw[1]); + if (size >= 6) + { + int script_num = LittleShort(scripts.w[4]); + ScriptPtr *ptr = const_cast(FindScript(script_num)); + if (ptr != NULL) + { + ptr->VarCount = ParseLocalArrayChunk(scripts.b, &ptr->LocalArrays, ptr->VarCount); + } + } + } + // Load script names (if any) scripts.b = FindChunk(MAKE_ID('S','N','A','M')); if (scripts.dw != NULL) @@ -3528,7 +3603,9 @@ enum APROP_ReactionTime = 37, APROP_MeleeRange = 38, APROP_ViewHeight = 39, - APROP_AttackZOffset = 40 + APROP_AttackZOffset = 40, + APROP_StencilColor = 41, + APROP_Friction = 42, }; // These are needed for ACS's APROP_RenderStyle @@ -3544,6 +3621,10 @@ static const int LegacyRenderStyleIndices[] = 65, // STYLE_Add, 66, // STYLE_Shaded, 67, // STYLE_TranslucentStencil, + 68, // STYLE_Shadow, + 69, // STYLE_Subtract, + 6, // STYLE_AddStencil + 7, // STYLE_AddShaded -1 }; @@ -3754,6 +3835,13 @@ void DLevelScript::DoSetActorProperty (AActor *actor, int property, int value) static_cast(actor)->AttackZOffset = value; break; + case APROP_StencilColor: + actor->SetShade(value); + break; + + case APROP_Friction: + actor->Friction = value; + default: // do nothing. break; @@ -3851,6 +3939,8 @@ 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; + case APROP_Friction: return actor->Friction; default: return 0; } @@ -3897,6 +3987,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 @@ -3932,7 +4023,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 +4343,21 @@ enum EACSFunctions 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) @@ -4502,6 +4610,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; @@ -4926,7 +5078,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]); @@ -5025,7 +5177,7 @@ int DLevelScript::CallFunction(int argCount, int funcIndex, SDWORD *args, const while ((source = it.Next()) != NULL) { - P_LineAttack(activator, angle, range, pitch, damage, damagetype, pufftype, fhflags); + P_LineAttack(source, angle, range, pitch, damage, damagetype, pufftype, fhflags); } } } @@ -5288,6 +5440,61 @@ doplaysound: if (funcIndex == ACSF_PlayActorSound) 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) + { + PClassActor *powerupclass = PClass::FindActor(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; } @@ -5325,14 +5532,50 @@ inline int getshort (int *&pc) return res; } +static bool CharArrayParms(int &capacity, int &offset, int &a, int *Stack, int &sp, bool ranged) +{ + if (ranged) + { + capacity = STACK(1); + offset = STACK(2); + if (capacity < 1 || offset < 0) + { + sp -= 4; + return false; + } + sp -= 2; + } + else + { + capacity = INT_MAX; + offset = 0; + } + a = STACK(1); + offset += STACK(2); + sp -= 2; + return true; +} + int DLevelScript::RunScript () { DACSThinker *controller = DACSThinker::ActiveThinker; SDWORD *locals = localvars; + ACSLocalArrays noarrays; + ACSLocalArrays *localarrays = &noarrays; ScriptFunction *activeFunction = NULL; FRemapTable *translation = 0; int resultValue = 1; + if (InModuleScriptNumber >= 0) + { + ScriptPtr *ptr = activeBehavior->GetScriptPtr(InModuleScriptNumber); + assert(ptr != NULL); + if (ptr != NULL) + { + localarrays = &ptr->LocalArrays; + } + } + // Hexen truncates all special arguments to bytes (only when using an old MAPINFO and old ACS format const int specialargmask = ((level.flags2 & LEVEL2_HEXENHACK) && activeBehavior->GetFormat() == ACS_Old) ? 255 : ~0; @@ -5697,9 +5940,10 @@ int DLevelScript::RunScript () } sp += i; ::new(&Stack[sp]) CallReturn(activeBehavior->PC2Ofs(pc), activeFunction, - activeBehavior, mylocals, pcd == PCD_CALLDISCARD, runaway); + activeBehavior, mylocals, localarrays, pcd == PCD_CALLDISCARD, runaway); sp += (sizeof(CallReturn) + sizeof(int) - 1) / sizeof(int); pc = module->Ofs2PC (func->Address); + localarrays = &func->LocalArrays; activeFunction = func; activeBehavior = module; fmt = module->GetFormat(); @@ -5733,6 +5977,7 @@ int DLevelScript::RunScript () activeBehavior = ret->ReturnModule; fmt = activeBehavior->GetFormat(); locals = ret->ReturnLocals; + localarrays = ret->ReturnArrays; if (!ret->bDiscardResult) { Stack[sp++] = value; @@ -5831,6 +6076,11 @@ int DLevelScript::RunScript () sp--; break; + case PCD_ASSIGNSCRIPTARRAY: + localarrays->Set(locals, NEXTBYTE, STACK(2), STACK(1)); + sp -= 2; + break; + case PCD_ASSIGNMAPARRAY: activeBehavior->SetArrayVal (*(activeBehavior->MapVars[NEXTBYTE]), STACK(2), STACK(1)); sp -= 2; @@ -5862,6 +6112,10 @@ int DLevelScript::RunScript () PushToStack (ACS_GlobalVars[NEXTBYTE]); break; + case PCD_PUSHSCRIPTARRAY: + STACK(1) = localarrays->Get(locals, NEXTBYTE, STACK(1)); + break; + case PCD_PUSHMAPARRAY: STACK(1) = activeBehavior->GetArrayVal (*(activeBehavior->MapVars[NEXTBYTE]), STACK(1)); break; @@ -5894,6 +6148,14 @@ int DLevelScript::RunScript () sp--; break; + case PCD_ADDSCRIPTARRAY: + { + int a = NEXTBYTE, i = STACK(2); + localarrays->Set(locals, a, i, localarrays->Get(locals, a, i) + STACK(1)); + sp -= 2; + } + break; + case PCD_ADDMAPARRAY: { int a = *(activeBehavior->MapVars[NEXTBYTE]); @@ -5939,6 +6201,14 @@ int DLevelScript::RunScript () sp--; break; + case PCD_SUBSCRIPTARRAY: + { + int a = NEXTBYTE, i = STACK(2); + localarrays->Set(locals, a, i, localarrays->Get(locals, a, i) - STACK(1)); + sp -= 2; + } + break; + case PCD_SUBMAPARRAY: { int a = *(activeBehavior->MapVars[NEXTBYTE]); @@ -5984,6 +6254,14 @@ int DLevelScript::RunScript () sp--; break; + case PCD_MULSCRIPTARRAY: + { + int a = NEXTBYTE, i = STACK(2); + localarrays->Set(locals, a, i, localarrays->Get(locals, a, i) * STACK(1)); + sp -= 2; + } + break; + case PCD_MULMAPARRAY: { int a = *(activeBehavior->MapVars[NEXTBYTE]); @@ -6057,6 +6335,19 @@ int DLevelScript::RunScript () } break; + case PCD_DIVSCRIPTARRAY: + if (STACK(1) == 0) + { + state = SCRIPT_DivideBy0; + } + else + { + int a = NEXTBYTE, i = STACK(2); + localarrays->Set(locals, a, i, localarrays->Get(locals, a, i) / STACK(1)); + sp -= 2; + } + break; + case PCD_DIVMAPARRAY: if (STACK(1) == 0) { @@ -6145,6 +6436,19 @@ int DLevelScript::RunScript () } break; + case PCD_MODSCRIPTARRAY: + if (STACK(1) == 0) + { + state = SCRIPT_ModulusBy0; + } + else + { + int a = NEXTBYTE, i = STACK(2); + localarrays->Set(locals, a, i, localarrays->Get(locals, a, i) % STACK(1)); + sp -= 2; + } + break; + case PCD_MODMAPARRAY: if (STACK(1) == 0) { @@ -6206,6 +6510,14 @@ int DLevelScript::RunScript () sp--; break; + case PCD_ANDSCRIPTARRAY: + { + int a = NEXTBYTE, i = STACK(2); + localarrays->Set(locals, a, i, localarrays->Get(locals, a, i) & STACK(1)); + sp -= 2; + } + break; + case PCD_ANDMAPARRAY: { int a = *(activeBehavior->MapVars[NEXTBYTE]); @@ -6251,6 +6563,14 @@ int DLevelScript::RunScript () sp--; break; + case PCD_EORSCRIPTARRAY: + { + int a = NEXTBYTE, i = STACK(2); + localarrays->Set(locals, a, i, localarrays->Get(locals, a, i) ^ STACK(1)); + sp -= 2; + } + break; + case PCD_EORMAPARRAY: { int a = *(activeBehavior->MapVars[NEXTBYTE]); @@ -6296,6 +6616,14 @@ int DLevelScript::RunScript () sp--; break; + case PCD_ORSCRIPTARRAY: + { + int a = NEXTBYTE, i = STACK(2); + localarrays->Set(locals, a, i, localarrays->Get(locals, a, i) | STACK(1)); + sp -= 2; + } + break; + case PCD_ORMAPARRAY: { int a = *(activeBehavior->MapVars[NEXTBYTE]); @@ -6342,6 +6670,14 @@ int DLevelScript::RunScript () sp--; break; + case PCD_LSSCRIPTARRAY: + { + int a = NEXTBYTE, i = STACK(2); + localarrays->Set(locals, a, i, localarrays->Get(locals, a, i) << STACK(1)); + sp -= 2; + } + break; + case PCD_LSMAPARRAY: { int a = *(activeBehavior->MapVars[NEXTBYTE]); @@ -6387,6 +6723,14 @@ int DLevelScript::RunScript () sp--; break; + case PCD_RSSCRIPTARRAY: + { + int a = NEXTBYTE, i = STACK(2); + localarrays->Set(locals, a, i, localarrays->Get(locals, a, i) >> STACK(1)); + sp -= 2; + } + break; + case PCD_RSMAPARRAY: { int a = *(activeBehavior->MapVars[NEXTBYTE]); @@ -6429,6 +6773,14 @@ int DLevelScript::RunScript () ++ACS_GlobalVars[NEXTBYTE]; break; + case PCD_INCSCRIPTARRAY: + { + int a = NEXTBYTE, i = STACK(1); + localarrays->Set(locals, a, i, localarrays->Get(locals, a, i) + 1); + sp--; + } + break; + case PCD_INCMAPARRAY: { int a = *(activeBehavior->MapVars[NEXTBYTE]); @@ -6470,6 +6822,14 @@ int DLevelScript::RunScript () --ACS_GlobalVars[NEXTBYTE]; break; + case PCD_DECSCRIPTARRAY: + { + int a = NEXTBYTE, i = STACK(1); + localarrays->Set(locals, a, i, localarrays->Get(locals, a, i) - 1); + sp--; + } + break; + case PCD_DECMAPARRAY: { int a = *(activeBehavior->MapVars[NEXTBYTE]); @@ -6799,7 +7159,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; @@ -6833,7 +7208,7 @@ scriptwait: break; case PRINTNAME_LEVEL: - work += level.mapname; + work += level.MapName; break; case PRINTNAME_SKILL: @@ -6881,37 +7256,35 @@ scriptwait: } break; + // Print script character array + case PCD_PRINTSCRIPTCHARARRAY: + case PCD_PRINTSCRIPTCHRANGE: + { + int capacity, offset, a, c; + if (CharArrayParms(capacity, offset, a, Stack, sp, pcd == PCD_PRINTSCRIPTCHRANGE)) + { + while (capacity-- && (c = localarrays->Get(locals, a, offset)) != '\0') + { + work += (char)c; + offset++; + } + } + } + break; + // [JB] Print map character array case PCD_PRINTMAPCHARARRAY: case PCD_PRINTMAPCHRANGE: { - int capacity, offset; - - if (pcd == PCD_PRINTMAPCHRANGE) + int capacity, offset, a, c; + if (CharArrayParms(capacity, offset, a, Stack, sp, pcd == PCD_PRINTMAPCHRANGE)) { - capacity = STACK(1); - offset = STACK(2); - if (capacity < 1 || offset < 0) + while (capacity-- && (c = activeBehavior->GetArrayVal (a, offset)) != '\0') { - sp -= 4; - break; + work += (char)c; + offset++; } - sp -= 2; } - else - { - capacity = 0x7FFFFFFF; - offset = 0; - } - - int a = *(activeBehavior->MapVars[STACK(1)]); - offset += STACK(2); - int c; - while(capacity-- && (c = activeBehavior->GetArrayVal (a, offset)) != '\0') { - work += (char)c; - offset++; - } - sp-= 2; } break; @@ -6919,32 +7292,15 @@ scriptwait: case PCD_PRINTWORLDCHARARRAY: case PCD_PRINTWORLDCHRANGE: { - int capacity, offset; - if (pcd == PCD_PRINTWORLDCHRANGE) + int capacity, offset, a, c; + if (CharArrayParms(capacity, offset, a, Stack, sp, pcd == PCD_PRINTWORLDCHRANGE)) { - capacity = STACK(1); - offset = STACK(2); - if (capacity < 1 || offset < 0) + while (capacity-- && (c = ACS_WorldArrays[a][offset]) != '\0') { - sp -= 4; - break; + work += (char)c; + offset++; } - sp -= 2; } - else - { - capacity = 0x7FFFFFFF; - offset = 0; - } - - int a = STACK(1); - offset += STACK(2); - int c; - while(capacity-- && (c = ACS_WorldArrays[a][offset]) != '\0') { - work += (char)c; - offset++; - } - sp-= 2; } break; @@ -6952,32 +7308,15 @@ scriptwait: case PCD_PRINTGLOBALCHARARRAY: case PCD_PRINTGLOBALCHRANGE: { - int capacity, offset; - if (pcd == PCD_PRINTGLOBALCHRANGE) + int capacity, offset, a, c; + if (CharArrayParms(capacity, offset, a, Stack, sp, pcd == PCD_PRINTGLOBALCHRANGE)) { - capacity = STACK(1); - offset = STACK(2); - if (capacity < 1 || offset < 0) + while (capacity-- && (c = ACS_GlobalArrays[a][offset]) != '\0') { - sp -= 4; - break; + work += (char)c; + offset++; } - sp -= 2; } - else - { - capacity = 0x7FFFFFFF; - offset = 0; - } - - int a = STACK(1); - offset += STACK(2); - int c; - while(capacity-- && (c = ACS_GlobalArrays[a][offset]) != '\0') { - work += (char)c; - offset++; - } - sp-= 2; } break; @@ -7829,14 +8168,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); @@ -8194,13 +8541,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; @@ -8239,40 +8584,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; @@ -8546,6 +8863,7 @@ scriptwait: } break; + case PCD_STRCPYTOSCRIPTCHRANGE: case PCD_STRCPYTOMAPCHRANGE: case PCD_STRCPYTOWORLDCHRANGE: case PCD_STRCPYTOGLOBALCHRANGE: @@ -8576,7 +8894,7 @@ scriptwait: break; } - for (int i = 0;i < STACK(1); i++) + for (int i = 0; i < STACK(1); i++) { if (! (*(lookup++))) { @@ -8587,43 +8905,55 @@ scriptwait: switch (pcd) { - case PCD_STRCPYTOMAPCHRANGE: - { - int a = STACK(5); - if (a < NUM_MAPVARS && a > 0 && - activeBehavior->MapVars[a]) - { - Stack[sp-6] = activeBehavior->CopyStringToArray(*(activeBehavior->MapVars[a]), index, capacity, lookup); - } - } - break; - case PCD_STRCPYTOWORLDCHRANGE: - { - int a = STACK(5); + case PCD_STRCPYTOSCRIPTCHRANGE: + { + int a = STACK(5); - while (capacity-- > 0) - { - ACS_WorldArrays[a][index++] = *lookup; - if (! (*(lookup++))) goto STRCPYTORANGECOMPLETE; // complete with terminating 0 - } - - Stack[sp-6] = !(*lookup); // true/success if only terminating 0 was not copied - } - break; - case PCD_STRCPYTOGLOBALCHRANGE: + while (capacity-- > 0) { - int a = STACK(5); - - while (capacity-- > 0) - { - ACS_GlobalArrays[a][index++] = *lookup; - if (! (*(lookup++))) goto STRCPYTORANGECOMPLETE; // complete with terminating 0 - } - - Stack[sp-6] = !(*lookup); // true/success if only terminating 0 was not copied + localarrays->Set(locals, a, index++, *lookup); + if (! (*(lookup++))) goto STRCPYTORANGECOMPLETE; // complete with terminating 0 } - break; - + + Stack[sp-6] = !(*lookup); // true/success if only terminating 0 was not copied + } + break; + case PCD_STRCPYTOMAPCHRANGE: + { + int a = STACK(5); + if (a < NUM_MAPVARS && a > 0 && + activeBehavior->MapVars[a]) + { + Stack[sp-6] = activeBehavior->CopyStringToArray(*(activeBehavior->MapVars[a]), index, capacity, lookup); + } + } + break; + case PCD_STRCPYTOWORLDCHRANGE: + { + int a = STACK(5); + + while (capacity-- > 0) + { + ACS_WorldArrays[a][index++] = *lookup; + if (! (*(lookup++))) goto STRCPYTORANGECOMPLETE; // complete with terminating 0 + } + + Stack[sp-6] = !(*lookup); // true/success if only terminating 0 was not copied + } + break; + case PCD_STRCPYTOGLOBALCHRANGE: + { + int a = STACK(5); + + while (capacity-- > 0) + { + ACS_GlobalArrays[a][index++] = *lookup; + if (! (*(lookup++))) goto STRCPYTORANGECOMPLETE; // complete with terminating 0 + } + + Stack[sp-6] = !(*lookup); // true/success if only terminating 0 was not copied + } + break; } sp -= 5; } @@ -8816,7 +9146,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()); } } @@ -8824,7 +9154,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; @@ -8877,17 +9207,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_acs.h b/src/p_acs.h index ec41ab886..02544e367 100644 --- a/src/p_acs.h +++ b/src/p_acs.h @@ -144,6 +144,51 @@ struct ProfileCollector int Index; }; +struct ACSLocalArrayInfo +{ + unsigned int Size; + int Offset; +}; + +struct ACSLocalArrays +{ + unsigned int Count; + ACSLocalArrayInfo *Info; + + ACSLocalArrays() + { + Count = 0; + Info = NULL; + } + ~ACSLocalArrays() + { + if (Info != NULL) + { + delete[] Info; + Info = NULL; + } + } + + // Bounds-checking Set and Get for local arrays + void Set(int *locals, int arraynum, int arrayentry, int value) + { + if ((unsigned int)arraynum < Count && + (unsigned int)arrayentry < Info[arraynum].Size) + { + locals[Info[arraynum].Offset + arrayentry] = value; + } + } + int Get(int *locals, int arraynum, int arrayentry) + { + if ((unsigned int)arraynum < Count && + (unsigned int)arrayentry < Info[arraynum].Size) + { + return locals[Info[arraynum].Offset + arrayentry]; + } + return 0; + } +}; + // The in-memory version struct ScriptPtr { @@ -153,6 +198,7 @@ struct ScriptPtr BYTE ArgCount; WORD VarCount; WORD Flags; + ACSLocalArrays LocalArrays; ACSProfileInfo ProfileData; }; @@ -189,7 +235,7 @@ struct ScriptFlagsPtr WORD Flags; }; -struct ScriptFunction +struct ScriptFunctionInFile { BYTE ArgCount; BYTE LocalCount; @@ -198,6 +244,16 @@ struct ScriptFunction DWORD Address; }; +struct ScriptFunction +{ + BYTE ArgCount; + BYTE HasReturnValue; + BYTE ImportNum; + int LocalCount; + DWORD Address; + ACSLocalArrays LocalArrays; +}; + // Script types enum { @@ -285,7 +341,7 @@ private: BYTE *Chunks; ScriptPtr *Scripts; int NumScripts; - BYTE *Functions; + ScriptFunction *Functions; ACSProfileInfo *FunctionProfileData; int NumFunctions; ArrayInfo *ArrayStore; @@ -694,8 +750,25 @@ public: PCD_SCRIPTWAITNAMED, PCD_TRANSLATIONRANGE3, PCD_GOTOSTACK, + PCD_ASSIGNSCRIPTARRAY, + PCD_PUSHSCRIPTARRAY, + PCD_ADDSCRIPTARRAY, + PCD_SUBSCRIPTARRAY, + PCD_MULSCRIPTARRAY, + PCD_DIVSCRIPTARRAY, +/*370*/ PCD_MODSCRIPTARRAY, + PCD_INCSCRIPTARRAY, + PCD_DECSCRIPTARRAY, + PCD_ANDSCRIPTARRAY, + PCD_EORSCRIPTARRAY, + PCD_ORSCRIPTARRAY, + PCD_LSSCRIPTARRAY, + PCD_RSSCRIPTARRAY, + PCD_PRINTSCRIPTCHARARRAY, + PCD_PRINTSCRIPTCHRANGE, +/*380*/ PCD_STRCPYTOSCRIPTCHRANGE, -/*363*/ PCODE_COMMAND_COUNT +/*381*/ PCODE_COMMAND_COUNT }; // Some constants used by ACS scripts diff --git a/src/p_buildmap.cpp b/src/p_buildmap.cpp index 136667b37..a097b4b03 100644 --- a/src/p_buildmap.cpp +++ b/src/p_buildmap.cpp @@ -16,11 +16,12 @@ #include "p_setup.h" #include "g_level.h" #include "r_data/colormaps.h" +#include "gi.h" // MACROS ------------------------------------------------------------------ -//#define SHADE2LIGHT(s) (clamp (160-2*(s), 0, 255)) -#define SHADE2LIGHT(s) (clamp (255-2*s, 0, 255)) +//#define SHADE2LIGHT(s) (160-2*(s)) +#define SHADE2LIGHT(s) (255-2*s) // TYPES ------------------------------------------------------------------- @@ -248,7 +249,7 @@ static bool P_LoadBloodMap (BYTE *data, size_t len, FMapThing **mapthings, int * BYTE infoBlock[37]; int mapver = data[5]; DWORD matt; - int numRevisions, numWalls, numsprites, skyLen; + int numRevisions, numWalls, numsprites, skyLen, visibility, parallaxType; int i; int k; @@ -268,11 +269,14 @@ static bool P_LoadBloodMap (BYTE *data, size_t len, FMapThing **mapthings, int * { memcpy (infoBlock, data + 6, 37); } + skyLen = 2 << LittleShort(*(WORD *)(infoBlock + 16)); + visibility = LittleLong(*(DWORD *)(infoBlock + 18)); + parallaxType = infoBlock[26]; numRevisions = LittleLong(*(DWORD *)(infoBlock + 27)); numsectors = LittleShort(*(WORD *)(infoBlock + 31)); numWalls = LittleShort(*(WORD *)(infoBlock + 33)); numsprites = LittleShort(*(WORD *)(infoBlock + 35)); - skyLen = 2 << LittleShort(*(WORD *)(infoBlock + 16)); + Printf("Visibility: %d\n", visibility); if (mapver == 7) { @@ -361,9 +365,8 @@ static bool P_LoadBloodMap (BYTE *data, size_t len, FMapThing **mapthings, int * // BUILD info from the map we need. (Sprites are ignored.) LoadSectors (bsec); LoadWalls (bwal, numWalls, bsec); - *mapthings = new FMapThing[numsprites + 1]; - CreateStartSpot ((fixed_t *)infoBlock, *mapthings); - *numspr = 1 + LoadSprites (bspr, xspr, numsprites, bsec, *mapthings + 1); + *mapthings = new FMapThing[numsprites]; + *numspr = LoadSprites (bspr, xspr, numsprites, bsec, *mapthings); delete[] bsec; delete[] bwal; @@ -687,6 +690,8 @@ static int LoadSprites (spritetype *sprites, Xsprite *xsprites, int numsprites, { int count = 0; + memset(mapthings, 0, sizeof(*mapthings)*numsprites); + for (int i = 0; i < numsprites; ++i) { mapthings[count].thingid = 0; @@ -699,29 +704,41 @@ static int LoadSprites (spritetype *sprites, Xsprite *xsprites, int numsprites, mapthings[count].flags = MTF_SINGLE|MTF_COOPERATIVE|MTF_DEATHMATCH; mapthings[count].special = 0; mapthings[count].gravity = FRACUNIT; + mapthings[count].RenderStyle = STYLE_Count; + mapthings[count].alpha = -1; + mapthings[count].health = -1; if (xsprites != NULL && sprites[i].lotag == 710) { // Blood ambient sound mapthings[count].args[0] = xsprites[i].Data3; - // I am totally guessing abount the volume level. 50 seems to be a pretty + // I am totally guessing about the volume level. 50 seems to be a pretty // typical value for Blood's standard maps, so I assume it's 100-based. mapthings[count].args[1] = xsprites[i].Data4; mapthings[count].args[2] = xsprites[i].Data1; mapthings[count].args[3] = xsprites[i].Data2; - mapthings[count].args[4] = 0; mapthings[count].type = 14065; } + else if (xsprites != NULL && sprites[i].lotag == 1) + { // Blood player start + if (xsprites[i].Data1 < 4) + mapthings[count].type = 1 + xsprites[i].Data1; + else + mapthings[count].type = gameinfo.player5start + xsprites[i].Data1 - 4; + } + else if (xsprites != NULL && sprites[i].lotag == 2) + { // Bloodbath start + mapthings[count].type = 11; + } else { - if (sprites[i].cstat & (16|32|32768)) continue; + if (sprites[i].cstat & 32768) continue; if (sprites[i].xrepeat == 0 || sprites[i].yrepeat == 0) continue; mapthings[count].type = 9988; - mapthings[count].args[0] = sprites[i].picnum & 255; - mapthings[count].args[1] = sprites[i].picnum >> 8; + mapthings[count].args[0] = sprites[i].picnum; mapthings[count].args[2] = sprites[i].xrepeat; mapthings[count].args[3] = sprites[i].yrepeat; - mapthings[count].args[4] = (sprites[i].cstat & 14) | ((sprites[i].cstat >> 9) & 1); + mapthings[count].args[4] = sprites[i].cstat; } count++; } @@ -859,22 +876,23 @@ void ACustomSprite::BeginPlay () char name[9]; Super::BeginPlay (); - mysnprintf (name, countof(name), "BTIL%04d", (args[0] + args[1]*256) & 0xffff); + mysnprintf (name, countof(name), "BTIL%04d", args[0] & 0xffff); picnum = TexMan.GetTexture (name, FTexture::TEX_Build); scaleX = args[2] * (FRACUNIT/64); scaleY = args[3] * (FRACUNIT/64); - if (args[4] & 2) + int cstat = args[4]; + if (cstat & 2) { RenderStyle = STYLE_Translucent; - if (args[4] & 1) - alpha = TRANSLUC66; - else - alpha = TRANSLUC33; + alpha = (cstat & 512) ? TRANSLUC66 : TRANSLUC33; } - if (args[4] & 4) + if (cstat & 4) renderflags |= RF_XFLIP; - if (args[4] & 8) + if (cstat & 8) renderflags |= RF_YFLIP; -} + + // set face/wall/floor flags + renderflags |= ((cstat >> 4) & 3) << 12; +} diff --git a/src/p_conversation.cpp b/src/p_conversation.cpp index fb33248de..4442d231e 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, PClassActor *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 cd758933a..ee4e2e124 100644 --- a/src/p_enemy.cpp +++ b/src/p_enemy.cpp @@ -915,7 +915,7 @@ void P_NewChaseDir(AActor * actor) // MBF's monster_backing option. Made an actor flag instead. Also cleaned the code up to make it readable. // Todo: implement the movement logic AActor *target = actor->target; - if (target->health > 0 && !actor->IsFriend(target)) + if (target->health > 0 && !actor->IsFriend(target) && target != actor->goal) { // Live enemy target if (actor->flags3 & MF3_AVOIDMELEE) @@ -1542,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; @@ -1615,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) @@ -1692,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; } } } @@ -2531,150 +2532,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 PClassActor *archvile = PClass::FindActor("Archvile"); - if (archvile != NULL) + // got one! + temp = self->target; + self->target = corpsehit; + A_FaceTarget(self); + if (self->flags & MF_FRIENDLY) { - self->SetState (archvile->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. + PClassActor *archvile = PClass::FindActor("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->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->flags7 = info->flags7; - 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; diff --git a/src/p_glnodes.cpp b/src/p_glnodes.cpp index 2665f69ba..15b97b9e6 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 (level.maptype != MAPTYPE_BUILD && 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 1d6e05a53..437d598e1 100644 --- a/src/p_interaction.cpp +++ b/src/p_interaction.cpp @@ -316,6 +316,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); @@ -359,8 +363,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"); @@ -1248,7 +1250,9 @@ int P_DamageMobj (AActor *target, AActor *inflictor, AActor *source, int damage, // This does not save the player if damage >= TELEFRAG_DAMAGE, still need to // telefrag him right? ;) (Unfortunately the damage is "absorbed" by armor, // but telefragging should still do enough damage to kill the player) - if ((player->cheats & CF_BUDDHA) && damage < TELEFRAG_DAMAGE) + if ((player->cheats & CF_BUDDHA) && damage < TELEFRAG_DAMAGE + // Ignore players that are already dead. + && player->playerstate != PST_DEAD) { // If this is a voodoo doll we need to handle the real player as well. player->mo->health = target->health = player->health = 1; diff --git a/src/p_lnspec.cpp b/src/p_lnspec.cpp index a17ef83d7..fc112963e 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; } } @@ -1562,9 +1562,21 @@ FUNC(LS_Thing_SetGoal) ok = true; if (self->flags & MF_SHOOTABLE) { + if (self->target == self->goal) + { // Targeting a goal already? -> don't target it anymore. + // A_Look will set it to the goal, presuming no real targets + // come into view by then. + self->target = NULL; + } self->goal = goal; - if (arg3 == 0) self->flags5 &=~ MF5_CHASEGOAL; - else self->flags5 |= MF5_CHASEGOAL; + if (arg3 == 0) + { + self->flags5 &= ~MF5_CHASEGOAL; + } + else + { + self->flags5 |= MF5_CHASEGOAL; + } if (self->target == NULL) { self->reactiontime = arg2 * TICRATE; @@ -1632,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 { @@ -1655,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 { @@ -1695,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) @@ -1704,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; } @@ -1717,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_local.h b/src/p_local.h index 05b9d34c0..872ad29ed 100644 --- a/src/p_local.h +++ b/src/p_local.h @@ -504,6 +504,7 @@ void P_RadiusAttack (AActor *spot, AActor *source, int damage, int distance, void P_DelSector_List(); void P_DelSeclist(msecnode_t *); // phares 3/16/98 +msecnode_t* P_DelSecnode(msecnode_t *); void P_CreateSecNodeList(AActor*,fixed_t,fixed_t); // phares 3/14/98 int P_GetMoveFactor(const AActor *mo, int *frictionp); // phares 3/6/98 int P_GetFriction(const AActor *mo, int *frictionfactor); diff --git a/src/p_map.cpp b/src/p_map.cpp index 4011be75e..6236c696e 100644 --- a/src/p_map.cpp +++ b/src/p_map.cpp @@ -53,19 +53,19 @@ #include "r_data/r_translate.h" #include "g_level.h" -CVAR (Bool, cl_bloodsplats, true, CVAR_ARCHIVE) -CVAR (Int, sv_smartaim, 0, CVAR_ARCHIVE|CVAR_SERVERINFO) -CVAR (Bool, cl_doautoaim, false, CVAR_ARCHIVE) +CVAR(Bool, cl_bloodsplats, true, CVAR_ARCHIVE) +CVAR(Int, sv_smartaim, 0, CVAR_ARCHIVE | CVAR_SERVERINFO) +CVAR(Bool, cl_doautoaim, false, CVAR_ARCHIVE) -static void CheckForPushSpecial (line_t *line, int side, AActor *mobj, bool windowcheck); -static void SpawnShootDecal (AActor *t1, const FTraceResults &trace); -static void SpawnDeepSplash (AActor *t1, const FTraceResults &trace, AActor *puff, - fixed_t vx, fixed_t vy, fixed_t vz, fixed_t shootz, bool ffloor = false); +static void CheckForPushSpecial(line_t *line, int side, AActor *mobj, bool windowcheck); +static void SpawnShootDecal(AActor *t1, const FTraceResults &trace); +static void SpawnDeepSplash(AActor *t1, const FTraceResults &trace, AActor *puff, + fixed_t vx, fixed_t vy, fixed_t vz, fixed_t shootz, bool ffloor = false); -static FRandom pr_tracebleed ("TraceBleed"); -static FRandom pr_checkthing ("CheckThing"); -static FRandom pr_lineattack ("LineAttack"); -static FRandom pr_crunch ("DoCrunch"); +static FRandom pr_tracebleed("TraceBleed"); +static FRandom pr_checkthing("CheckThing"); +static FRandom pr_lineattack("LineAttack"); +static FRandom pr_crunch("DoCrunch"); // keep track of special lines as they are hit, // but don't process them until the move is proven valid @@ -82,19 +82,19 @@ msecnode_t* sector_list = NULL; // phares 3/16/98 // //========================================================================== -static bool PIT_FindFloorCeiling (line_t *ld, const FBoundingBox &box, FCheckPosition &tmf, int flags) +static bool PIT_FindFloorCeiling(line_t *ld, const FBoundingBox &box, FCheckPosition &tmf, int flags) { if (box.Right() <= ld->bbox[BOXLEFT] || box.Left() >= ld->bbox[BOXRIGHT] || box.Top() <= ld->bbox[BOXBOTTOM] - || box.Bottom() >= ld->bbox[BOXTOP] ) + || box.Bottom() >= ld->bbox[BOXTOP]) return true; - if (box.BoxOnLineSide (ld) != -1) + if (box.BoxOnLineSide(ld) != -1) return true; // A line has been hit - + if (!ld->backsector) { // One sided line return true; @@ -105,33 +105,33 @@ static bool PIT_FindFloorCeiling (line_t *ld, const FBoundingBox &box, FCheckPos // set openrange, opentop, openbottom if ((((ld->frontsector->floorplane.a | ld->frontsector->floorplane.b) | - (ld->backsector->floorplane.a | ld->backsector->floorplane.b) | - (ld->frontsector->ceilingplane.a | ld->frontsector->ceilingplane.b) | - (ld->backsector->ceilingplane.a | ld->backsector->ceilingplane.b)) == 0) - && ld->backsector->e->XFloor.ffloors.Size()==0 && ld->frontsector->e->XFloor.ffloors.Size()==0) + (ld->backsector->floorplane.a | ld->backsector->floorplane.b) | + (ld->frontsector->ceilingplane.a | ld->frontsector->ceilingplane.b) | + (ld->backsector->ceilingplane.a | ld->backsector->ceilingplane.b)) == 0) + && ld->backsector->e->XFloor.ffloors.Size() == 0 && ld->frontsector->e->XFloor.ffloors.Size() == 0) { - P_LineOpening (open, tmf.thing, ld, sx=tmf.x, sy=tmf.y, tmf.x, tmf.y, flags); + P_LineOpening(open, tmf.thing, ld, sx = tmf.x, sy = tmf.y, tmf.x, tmf.y, flags); } else { // Find the point on the line closest to the actor's center, and use - // that to calculate openings + // that to calculate openings double dx = ld->dx; double dy = ld->dy; fixed_t r = xs_CRoundToInt(((double)(tmf.x - ld->v1->x) * dx + - (double)(tmf.y - ld->v1->y) * dy) / - (dx*dx + dy*dy) * 16777216.f); + (double)(tmf.y - ld->v1->y) * dy) / + (dx*dx + dy*dy) * 16777216.f); if (r <= 0) { - P_LineOpening (open, tmf.thing, ld, sx=ld->v1->x, sy=ld->v1->y, tmf.x, tmf.y, flags); + P_LineOpening(open, tmf.thing, ld, sx = ld->v1->x, sy = ld->v1->y, tmf.x, tmf.y, flags); } - else if (r >= (1<<24)) + else if (r >= (1 << 24)) { - P_LineOpening (open, tmf.thing, ld, sx=ld->v2->x, sy=ld->v2->y, tmf.thing->x, tmf.thing->y, flags); + P_LineOpening(open, tmf.thing, ld, sx = ld->v2->x, sy = ld->v2->y, tmf.thing->x, tmf.thing->y, flags); } else { - P_LineOpening (open, tmf.thing, ld, sx=ld->v1->x + MulScale24 (r, ld->dx), - sy=ld->v1->y + MulScale24 (r, ld->dy), tmf.x, tmf.y, flags); + P_LineOpening(open, tmf.thing, ld, sx = ld->v1->x + MulScale24(r, ld->dx), + sy = ld->v1->y + MulScale24(r, ld->dy), tmf.x, tmf.y, flags); } } @@ -156,7 +156,7 @@ static bool PIT_FindFloorCeiling (line_t *ld, const FBoundingBox &box, FCheckPos if (open.lowfloor < tmf.dropoffz) tmf.dropoffz = open.lowfloor; - + return true; } @@ -172,12 +172,12 @@ void P_GetFloorCeilingZ(FCheckPosition &tmf, int flags) sector_t *sec; if (!(flags & FFCF_ONLYSPAWNPOS)) { - sec = !(flags & FFCF_SAMESECTOR) ? P_PointInSector (tmf.x, tmf.y) : tmf.thing->Sector; + sec = !(flags & FFCF_SAMESECTOR) ? P_PointInSector(tmf.x, tmf.y) : tmf.thing->Sector; tmf.floorsector = sec; tmf.ceilingsector = sec; - tmf.floorz = tmf.dropoffz = sec->floorplane.ZatPoint (tmf.x, tmf.y); - tmf.ceilingz = sec->ceilingplane.ZatPoint (tmf.x, tmf.y); + tmf.floorz = tmf.dropoffz = sec->floorplane.ZatPoint(tmf.x, tmf.y); + tmf.ceilingz = sec->ceilingplane.ZatPoint(tmf.x, tmf.y); tmf.floorpic = sec->GetTexture(sector_t::floor); tmf.ceilingpic = sec->GetTexture(sector_t::ceiling); } @@ -187,7 +187,7 @@ void P_GetFloorCeilingZ(FCheckPosition &tmf, int flags) } #ifdef _3DFLOORS - for(unsigned int i=0;ie->XFloor.ffloors.Size();i++) + for (unsigned int i = 0; ie->XFloor.ffloors.Size(); i++) { F3DFloor* rover = sec->e->XFloor.ffloors[i]; @@ -204,7 +204,7 @@ void P_GetFloorCeilingZ(FCheckPosition &tmf, int flags) tmf.floorpic = *rover->top.texture; } } - if (ff_bottom <= tmf.ceilingz && ff_bottom > tmf.z + tmf.thing->height) + if (ff_bottom <= tmf.ceilingz && ff_bottom > tmf.z + tmf.thing->height) { tmf.ceilingz = ff_bottom; tmf.ceilingpic = *rover->bottom.texture; @@ -219,7 +219,7 @@ void P_GetFloorCeilingZ(FCheckPosition &tmf, int flags) // //========================================================================== -void P_FindFloorCeiling (AActor *actor, int flags) +void P_FindFloorCeiling(AActor *actor, int flags) { FCheckPosition tmf; @@ -309,14 +309,14 @@ void P_FindFloorCeiling (AActor *actor, int flags) // //========================================================================== -bool P_TeleportMove (AActor *thing, fixed_t x, fixed_t y, fixed_t z, bool telefrag) +bool P_TeleportMove(AActor *thing, fixed_t x, fixed_t y, fixed_t z, bool telefrag) { FCheckPosition tmf; sector_t *oldsec = thing->Sector; - + // kill anything occupying the position - - + + // The base floor/ceiling is from the subsector that contains the point. // Any contacted lines the step closer together will adjust them. tmf.thing = thing; @@ -326,8 +326,8 @@ bool P_TeleportMove (AActor *thing, fixed_t x, fixed_t y, fixed_t z, bool telefr tmf.touchmidtex = false; tmf.abovemidtex = false; P_GetFloorCeilingZ(tmf, 0); - - spechit.Clear (); + + spechit.Clear(); bool StompAlwaysFrags = ((thing->flags2 & MF2_TELESTOMP) || (level.flags & LEVEL_MONSTERSTELEFRAG) || telefrag) && !(thing->flags7 & MF7_NOTELESTOMP); @@ -359,7 +359,7 @@ bool P_TeleportMove (AActor *thing, fixed_t x, fixed_t y, fixed_t z, bool telefr continue; fixed_t blockdist = th->radius + tmf.thing->radius; - if ( abs(th->x - tmf.x) >= blockdist || abs(th->y - tmf.y) >= blockdist) + if (abs(th->x - tmf.x) >= blockdist || abs(th->y - tmf.y) >= blockdist) continue; // [RH] Z-Check @@ -370,7 +370,7 @@ bool P_TeleportMove (AActor *thing, fixed_t x, fixed_t y, fixed_t z, bool telefr if (!(th->flags3 & thing->flags3 & MF3_DONTOVERLAP)) { if (z > th->z + th->height || // overhead - z+thing->height < th->z) // underneath + z + thing->height < th->z) // underneath continue; } } @@ -380,14 +380,14 @@ bool P_TeleportMove (AActor *thing, fixed_t x, fixed_t y, fixed_t z, bool telefr // ... 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); + P_DamageMobj(th, thing, thing, TELEFRAG_DAMAGE, NAME_Telefrag, DMG_THRUSTLESS); continue; } return false; } - + // the move is ok, so link the thing into its new position - thing->SetOrigin (x, y, z); + thing->SetOrigin(x, y, z); thing->floorz = tmf.floorz; thing->ceilingz = tmf.ceilingz; thing->floorsector = tmf.floorsector; @@ -399,12 +399,12 @@ bool P_TeleportMove (AActor *thing, fixed_t x, fixed_t y, fixed_t z, bool telefr if (thing->flags2 & MF2_FLOORCLIP) { - thing->AdjustFloorClip (); + thing->AdjustFloorClip(); } if (thing == players[consoleplayer].camera) { - R_ResetViewInterpolation (); + R_ResetViewInterpolation(); } thing->PrevX = x; @@ -430,7 +430,7 @@ bool P_TeleportMove (AActor *thing, fixed_t x, fixed_t y, fixed_t z, bool telefr // //========================================================================== -void P_PlayerStartStomp (AActor *actor) +void P_PlayerStartStomp(AActor *actor) { AActor *th; FBlockThingsIterator it(FBoundingBox(actor->x, actor->y, actor->radius)); @@ -456,7 +456,7 @@ void P_PlayerStartStomp (AActor *actor) if (actor->z + actor->height < th->z) continue; // underneath - P_DamageMobj (th, actor, actor, TELEFRAG_DAMAGE, NAME_Telefrag); + P_DamageMobj(th, actor, actor, TELEFRAG_DAMAGE, NAME_Telefrag); } } @@ -466,13 +466,13 @@ void P_PlayerStartStomp (AActor *actor) // //========================================================================== -inline fixed_t secfriction (const sector_t *sec) +inline fixed_t secfriction(const sector_t *sec) { fixed_t friction = Terrains[TerrainTypes[sec->GetTexture(sector_t::floor)]].Friction; return friction != 0 ? friction : sec->friction; } -inline fixed_t secmovefac (const sector_t *sec) +inline fixed_t secmovefac(const sector_t *sec) { fixed_t movefactor = Terrains[TerrainTypes[sec->GetTexture(sector_t::floor)]].MoveFactor; return movefactor != 0 ? movefactor : sec->movefactor; @@ -488,7 +488,7 @@ inline fixed_t secmovefac (const sector_t *sec) // //========================================================================== -int P_GetFriction (const AActor *mo, int *frictionfactor) +int P_GetFriction(const AActor *mo, int *frictionfactor) { int friction = ORIG_FRICTION; int movefactor = ORIG_FRICTION_FACTOR; @@ -505,12 +505,12 @@ int P_GetFriction (const AActor *mo, int *frictionfactor) friction = FRICTION_FLY; } else if ((!(mo->flags & MF_NOGRAVITY) && mo->waterlevel > 1) || - (mo->waterlevel == 1 && mo->z > mo->floorz + 6*FRACUNIT)) + (mo->waterlevel == 1 && mo->z > mo->floorz + 6 * FRACUNIT)) { friction = secfriction(mo->Sector); movefactor = secmovefac(mo->Sector) >> 1; } - else if (var_friction && !(mo->flags & (MF_NOCLIP|MF_NOGRAVITY))) + else if (var_friction && !(mo->flags & (MF_NOCLIP | MF_NOGRAVITY))) { // When the object is straddling sectors with the same // floor height that have different frictions, use the lowest // friction value (muddy has precedence over icy). @@ -528,7 +528,7 @@ int P_GetFriction (const AActor *mo, int *frictionfactor) if (!(rover->flags & FF_SOLID)) continue; // Player must be on top of the floor to be affected... - if (mo->z != rover->top.plane->ZatPoint(mo->x,mo->y)) continue; + if (mo->z != rover->top.plane->ZatPoint(mo->x, mo->y)) continue; newfriction = secfriction(rover->model); if (newfriction < friction || friction == ORIG_FRICTION) { @@ -547,14 +547,20 @@ int P_GetFriction (const AActor *mo, int *frictionfactor) if ((newfriction < friction || friction == ORIG_FRICTION) && (mo->z <= sec->floorplane.ZatPoint(mo->x, mo->y) || (sec->GetHeightSec() != NULL && - mo->z <= sec->heightsec->floorplane.ZatPoint(mo->x, mo->y)))) + mo->z <= sec->heightsec->floorplane.ZatPoint(mo->x, mo->y)))) { friction = newfriction; movefactor = secmovefac(sec); } } } - + + if (mo->Friction != FRACUNIT) + { + friction = clamp(FixedMul(friction, mo->Friction), 0, FRACUNIT); + movefactor = FrictionToMoveFactor(friction); + } + if (frictionfactor) *frictionfactor = movefactor; @@ -571,7 +577,7 @@ int P_GetFriction (const AActor *mo, int *frictionfactor) // //========================================================================== -int P_GetMoveFactor (const AActor *mo, int *frictionp) +int P_GetMoveFactor(const AActor *mo, int *frictionp) { int movefactor, friction; @@ -586,9 +592,9 @@ int P_GetMoveFactor (const AActor *mo, int *frictionp) int velocity = P_AproxDistance(mo->velx, mo->vely); - if (velocity > MORE_FRICTION_VELOCITY<<2) + if (velocity > MORE_FRICTION_VELOCITY << 2) movefactor <<= 3; - else if (velocity > MORE_FRICTION_VELOCITY<<1) + else if (velocity > MORE_FRICTION_VELOCITY << 1) movefactor <<= 2; else if (velocity > MORE_FRICTION_VELOCITY) movefactor <<= 1; @@ -614,37 +620,37 @@ int P_GetMoveFactor (const AActor *mo, int *frictionp) //========================================================================== static // killough 3/26/98: make static -bool PIT_CheckLine (line_t *ld, const FBoundingBox &box, FCheckPosition &tm) +bool PIT_CheckLine(line_t *ld, const FBoundingBox &box, FCheckPosition &tm) { bool rail = false; if (box.Right() <= ld->bbox[BOXLEFT] || box.Left() >= ld->bbox[BOXRIGHT] || box.Top() <= ld->bbox[BOXBOTTOM] - || box.Bottom() >= ld->bbox[BOXTOP] ) + || box.Bottom() >= ld->bbox[BOXTOP]) return true; - if (box.BoxOnLineSide (ld) != -1) + if (box.BoxOnLineSide(ld) != -1) return true; // A line has been hit -/* -= -= The moving thing's destination position will cross the given line. -= If this should not be allowed, return false. -= If the line is special, keep track of it to process later if the move -= is proven ok. NOTE: specials are NOT sorted by order, so two special lines -= that are only 8 pixels apart could be crossed in either order. -*/ - + /* + = + = The moving thing's destination position will cross the given line. + = If this should not be allowed, return false. + = If the line is special, keep track of it to process later if the move + = is proven ok. NOTE: specials are NOT sorted by order, so two special lines + = that are only 8 pixels apart could be crossed in either order. + */ + if (!ld->backsector) { // One sided line if (tm.thing->flags2 & MF2_BLASTED) { - P_DamageMobj (tm.thing, NULL, NULL, tm.thing->Mass >> 5, NAME_Melee); + P_DamageMobj(tm.thing, NULL, NULL, tm.thing->Mass >> 5, NAME_Melee); } tm.thing->BlockingLine = ld; - CheckForPushSpecial (ld, 0, tm.thing, false); + CheckForPushSpecial(ld, 0, tm.thing, false); return false; } @@ -657,13 +663,13 @@ bool PIT_CheckLine (line_t *ld, const FBoundingBox &box, FCheckPosition &tm) bool NotBlocked = ((tm.thing->flags3 & MF3_NOBLOCKMONST) || ((i_compatflags & COMPATF_NOBLOCKFRIENDS) && (tm.thing->flags & MF_FRIENDLY))); - if (!(Projectile) || (ld->flags & (ML_BLOCKEVERYTHING|ML_BLOCKPROJECTILE))) + if (!(Projectile) || (ld->flags & (ML_BLOCKEVERYTHING | ML_BLOCKPROJECTILE))) { if (ld->flags & ML_RAILING) { rail = true; } - else if ((ld->flags & (ML_BLOCKING|ML_BLOCKEVERYTHING)) || // explicitly blocking everything + else if ((ld->flags & (ML_BLOCKING | ML_BLOCKEVERYTHING)) || // explicitly blocking everything (!(NotBlocked) && (ld->flags & ML_BLOCKMONSTERS)) || // block monsters only (tm.thing->player != NULL && (ld->flags & ML_BLOCK_PLAYERS)) || // block players ((Projectile) && (ld->flags & ML_BLOCKPROJECTILE)) || // block projectiles @@ -671,21 +677,21 @@ bool PIT_CheckLine (line_t *ld, const FBoundingBox &box, FCheckPosition &tm) { if (tm.thing->flags2 & MF2_BLASTED) { - P_DamageMobj (tm.thing, NULL, NULL, tm.thing->Mass >> 5, NAME_Melee); + P_DamageMobj(tm.thing, NULL, NULL, tm.thing->Mass >> 5, NAME_Melee); } tm.thing->BlockingLine = ld; // Calculate line side based on the actor's original position, not the new one. - CheckForPushSpecial (ld, P_PointOnLineSide(tm.thing->x, tm.thing->y, ld), tm.thing, false); + CheckForPushSpecial(ld, P_PointOnLineSide(tm.thing->x, tm.thing->y, ld), tm.thing, false); return false; } } // [RH] Steep sectors count as dropoffs (unless already in one) if (!(tm.thing->flags & MF_DROPOFF) && - !(tm.thing->flags & (MF_NOGRAVITY|MF_NOCLIP))) + !(tm.thing->flags & (MF_NOGRAVITY | MF_NOCLIP))) { secplane_t frontplane = ld->frontsector->floorplane; - secplane_t backplane = ld->backsector->floorplane; + secplane_t backplane = ld->backsector->floorplane; #ifdef _3DFLOORS // Check 3D floors as well frontplane = P_FindFloorPlane(ld->frontsector, tm.thing->x, tm.thing->y, tm.thing->floorz); @@ -713,57 +719,57 @@ bool PIT_CheckLine (line_t *ld, const FBoundingBox &box, FCheckPosition &tm) } } - fixed_t sx=0, sy=0; + fixed_t sx = 0, sy = 0; FLineOpening open; // set openrange, opentop, openbottom if ((((ld->frontsector->floorplane.a | ld->frontsector->floorplane.b) | - (ld->backsector->floorplane.a | ld->backsector->floorplane.b) | - (ld->frontsector->ceilingplane.a | ld->frontsector->ceilingplane.b) | - (ld->backsector->ceilingplane.a | ld->backsector->ceilingplane.b)) == 0) - && ld->backsector->e->XFloor.ffloors.Size()==0 && ld->frontsector->e->XFloor.ffloors.Size()==0) + (ld->backsector->floorplane.a | ld->backsector->floorplane.b) | + (ld->frontsector->ceilingplane.a | ld->frontsector->ceilingplane.b) | + (ld->backsector->ceilingplane.a | ld->backsector->ceilingplane.b)) == 0) + && ld->backsector->e->XFloor.ffloors.Size() == 0 && ld->frontsector->e->XFloor.ffloors.Size() == 0) { - P_LineOpening (open, tm.thing, ld, sx=tm.x, sy=tm.y, tm.x, tm.y); + P_LineOpening(open, tm.thing, ld, sx = tm.x, sy = tm.y, tm.x, tm.y); } else { // Find the point on the line closest to the actor's center, and use - // that to calculate openings + // that to calculate openings float dx = (float)ld->dx; float dy = (float)ld->dy; fixed_t r = (fixed_t)(((float)(tm.x - ld->v1->x) * dx + - (float)(tm.y - ld->v1->y) * dy) / - (dx*dx + dy*dy) * 16777216.f); -/* Printf ("%d:%d: %d (%d %d %d %d) (%d %d %d %d)\n", level.time, ld-lines, r, - ld->frontsector->floorplane.a, - ld->frontsector->floorplane.b, - ld->frontsector->floorplane.c, - ld->frontsector->floorplane.ic, - ld->backsector->floorplane.a, - ld->backsector->floorplane.b, - ld->backsector->floorplane.c, - ld->backsector->floorplane.ic);*/ + (float)(tm.y - ld->v1->y) * dy) / + (dx*dx + dy*dy) * 16777216.f); + /* Printf ("%d:%d: %d (%d %d %d %d) (%d %d %d %d)\n", level.time, ld-lines, r, + ld->frontsector->floorplane.a, + ld->frontsector->floorplane.b, + ld->frontsector->floorplane.c, + ld->frontsector->floorplane.ic, + ld->backsector->floorplane.a, + ld->backsector->floorplane.b, + ld->backsector->floorplane.c, + ld->backsector->floorplane.ic);*/ if (r <= 0) { - P_LineOpening (open, tm.thing, ld, sx=ld->v1->x, sy=ld->v1->y, tm.x, tm.y); + P_LineOpening(open, tm.thing, ld, sx = ld->v1->x, sy = ld->v1->y, tm.x, tm.y); } - else if (r >= (1<<24)) + else if (r >= (1 << 24)) { - P_LineOpening (open, tm.thing, ld, sx=ld->v2->x, sy=ld->v2->y, tm.thing->x, tm.thing->y); + P_LineOpening(open, tm.thing, ld, sx = ld->v2->x, sy = ld->v2->y, tm.thing->x, tm.thing->y); } else { - P_LineOpening (open, tm.thing, ld, sx=ld->v1->x + MulScale24 (r, ld->dx), - sy=ld->v1->y + MulScale24 (r, ld->dy), tm.x, tm.y); + P_LineOpening(open, tm.thing, ld, sx = ld->v1->x + MulScale24(r, ld->dx), + sy = ld->v1->y + MulScale24(r, ld->dy), tm.x, tm.y); } // the floorplane on both sides is identical with the current one // so don't mess around with the z-position - if (ld->frontsector->floorplane==ld->backsector->floorplane && - ld->frontsector->floorplane==tm.thing->Sector->floorplane && + if (ld->frontsector->floorplane == ld->backsector->floorplane && + ld->frontsector->floorplane == tm.thing->Sector->floorplane && !ld->frontsector->e->XFloor.ffloors.Size() && !ld->backsector->e->XFloor.ffloors.Size() && !open.abovemidtex) { - open.bottom=INT_MIN; + open.bottom = INT_MIN; } /* Printf (" %d %d %d\n", sx, sy, openbottom);*/ } @@ -777,9 +783,9 @@ bool PIT_CheckLine (line_t *ld, const FBoundingBox &box, FCheckPosition &tm) // from either side. How long until somebody reports this as a bug and I'm // forced to say, "It's not a bug. It's a feature?" Ugh. (!(level.flags2 & LEVEL2_RAILINGHACK) || - open.bottom == tm.thing->Sector->floorplane.ZatPoint (sx, sy))) + open.bottom == tm.thing->Sector->floorplane.ZatPoint(sx, sy))) { - open.bottom += 32*FRACUNIT; + open.bottom += 32 * FRACUNIT; } // adjust floor / ceiling heights @@ -809,11 +815,11 @@ bool PIT_CheckLine (line_t *ld, const FBoundingBox &box, FCheckPosition &tm) if (open.lowfloor < tm.dropoffz) tm.dropoffz = open.lowfloor; - + // if contacted a special line, add it to the list if (ld->special) { - spechit.Push (ld); + spechit.Push(ld); } return true; @@ -825,24 +831,24 @@ bool PIT_CheckLine (line_t *ld, const FBoundingBox &box, FCheckPosition &tm) // //========================================================================== -bool PIT_CheckThing (AActor *thing, FCheckPosition &tm) +bool PIT_CheckThing(AActor *thing, FCheckPosition &tm) { fixed_t topz; bool solid; int damage; - if (!((thing->flags & (MF_SOLID|MF_SPECIAL|MF_SHOOTABLE)) || thing->flags6 & MF6_TOUCHY)) + if (!((thing->flags & (MF_SOLID | MF_SPECIAL | MF_SHOOTABLE)) || thing->flags6 & MF6_TOUCHY)) return true; // can't hit thing fixed_t blockdist = thing->radius + tm.thing->radius; - if ( abs(thing->x - tm.x) >= blockdist || abs(thing->y - tm.y) >= blockdist) + if (abs(thing->x - tm.x) >= blockdist || abs(thing->y - tm.y) >= blockdist) return true; // don't clip against self if (thing == tm.thing) return true; - if ((thing->flags2 | tm.thing->flags2) & MF2_THRUACTORS) + if ((thing->flags2 | tm.thing->flags2) & MF2_THRUACTORS) return true; if ((tm.thing->flags6 & MF6_THRUSPECIES) && (tm.thing->GetSpecies() == thing->GetSpecies())) @@ -850,7 +856,7 @@ bool PIT_CheckThing (AActor *thing, FCheckPosition &tm) tm.thing->BlockingMobj = thing; topz = thing->z + thing->height; - if (!(i_compatflags & COMPATF_NO_PASSMOBJ) && !(tm.thing->flags & (MF_FLOAT|MF_MISSILE|MF_SKULLFLY|MF_NOGRAVITY)) && + if (!(i_compatflags & COMPATF_NO_PASSMOBJ) && !(tm.thing->flags & (MF_FLOAT | MF_MISSILE | MF_SKULLFLY | MF_NOGRAVITY)) && (thing->flags & MF_SOLID) && (thing->flags4 & MF4_ACTLIKEBRIDGE)) { // [RH] Let monsters walk on actors as well as floors @@ -862,8 +868,8 @@ bool PIT_CheckThing (AActor *thing, FCheckPosition &tm) // way to do this, so I restrict them to only walking on bridges instead. // Uncommenting the if here makes it almost impossible for them to walk on // anything, bridge or otherwise. -// if (abs(thing->x - tmx) <= thing->radius && -// abs(thing->y - tmy) <= thing->radius) + // if (abs(thing->x - tmx) <= thing->radius && + // abs(thing->y - tmy) <= thing->radius) { tm.stepthing = thing; tm.floorz = topz; @@ -891,7 +897,7 @@ bool PIT_CheckThing (AActor *thing, FCheckPosition &tm) { // ... but not if they did not overlap in z-direction before but would after the move. unblocking = !((tm.thing->z >= thing->z + thing->height && tm.z < thing->z + thing->height) || - (tm.thing->z + tm.thing->height <= thing->z && tm.z + tm.thing->height > thing->z)); + (tm.thing->z + tm.thing->height <= thing->z && tm.z + tm.thing->height > thing->z)); } } } @@ -914,34 +920,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; @@ -951,10 +957,21 @@ bool PIT_CheckThing (AActor *thing, FCheckPosition &tm) // Check for skulls slamming into things if (tm.thing->flags & MF_SKULLFLY) { - bool res = tm.thing->Slam (tm.thing->BlockingMobj); + bool res = tm.thing->Slam(tm.thing->BlockingMobj); 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)) { @@ -963,15 +980,15 @@ bool PIT_CheckThing (AActor *thing, FCheckPosition &tm) // ideally this should take the mass factor into account thing->velx += tm.thing->velx; thing->vely += tm.thing->vely; - if ((thing->velx + thing->vely) > 3*FRACUNIT) + if ((thing->velx + thing->vely) > 3 * FRACUNIT) { int newdam; damage = (tm.thing->Mass / 100) + 1; - newdam = P_DamageMobj (thing, tm.thing, tm.thing, damage, tm.thing->DamageType); - P_TraceBleed (newdam > 0 ? newdam : damage, thing, tm.thing); + newdam = P_DamageMobj(thing, tm.thing, tm.thing, damage, tm.thing->DamageType); + P_TraceBleed(newdam > 0 ? newdam : damage, thing, tm.thing); damage = (thing->Mass / 100) + 1; - newdam = P_DamageMobj (tm.thing, thing, thing, damage >> 2, tm.thing->DamageType); - P_TraceBleed (newdam > 0 ? newdam : damage, tm.thing, thing); + newdam = P_DamageMobj(tm.thing, thing, thing, damage >> 2, tm.thing->DamageType); + P_TraceBleed(newdam > 0 ? newdam : damage, tm.thing, thing); } return false; } @@ -990,7 +1007,7 @@ bool PIT_CheckThing (AActor *thing, FCheckPosition &tm) return true; } - if ((tm.thing->flags6 & MF6_MTHRUSPECIES) + if ((tm.thing->flags6 & MF6_MTHRUSPECIES) && tm.thing->target // NULL pointer check && (tm.thing->target->GetSpecies() == thing->GetSpecies())) return true; @@ -1002,8 +1019,8 @@ bool PIT_CheckThing (AActor *thing, FCheckPosition &tm) } int clipheight; - - if (thing->projectilepassheight > 0) + + if (thing->projectilepassheight > 0) { clipheight = thing->projectilepassheight; } @@ -1021,7 +1038,7 @@ bool PIT_CheckThing (AActor *thing, FCheckPosition &tm) { // Over thing return true; } - if (tm.thing->z+tm.thing->height < thing->z) + if (tm.thing->z + tm.thing->height < thing->z) { // Under thing return true; } @@ -1034,7 +1051,7 @@ bool PIT_CheckThing (AActor *thing, FCheckPosition &tm) return (tm.thing->target == thing || !(thing->flags & MF_SOLID)); } - switch (tm.thing->SpecialMissileHit (thing)) + switch (tm.thing->SpecialMissileHit(thing)) { case 0: return false; case 1: return true; @@ -1046,7 +1063,7 @@ bool PIT_CheckThing (AActor *thing, FCheckPosition &tm) // [Graf Zahl] Why do I have the feeling that this didn't really work anymore now // that ZDoom supports friendly monsters? - + if (tm.thing->target != NULL) { @@ -1060,10 +1077,10 @@ bool PIT_CheckThing (AActor *thing, FCheckPosition &tm) if (!thing->player && !tm.thing->target->player) { int infight; - if (level.flags2 & LEVEL2_TOTALINFIGHTING) infight=1; - else if (level.flags2 & LEVEL2_NOINFIGHTING) infight=-1; + if (level.flags2 & LEVEL2_TOTALINFIGHTING) infight = 1; + else if (level.flags2 & LEVEL2_NOINFIGHTING) infight = -1; else infight = infighting; - + if (infight < 0) { // -1: Monsters cannot hurt each other, but make exceptions for @@ -1075,7 +1092,7 @@ bool PIT_CheckThing (AActor *thing, FCheckPosition &tm) if (thing->flags3 & MF3_ISMONSTER) { // Monsters that are clearly hostile can always hurt each other - if (!thing->IsHostile (tm.thing->target)) + if (!thing->IsHostile(tm.thing->target)) { // The same if the shooter hates the target if (thing->tid == 0 || tm.thing->target->TIDtoHate != thing->tid) @@ -1090,7 +1107,7 @@ bool PIT_CheckThing (AActor *thing, FCheckPosition &tm) { // 0: Monsters cannot hurt same species except // cases where they are clearly supposed to do that - if (thing->IsFriend (tm.thing->target)) + if (thing->IsFriend(tm.thing->target)) { // Friends never harm each other return false; @@ -1104,7 +1121,7 @@ bool PIT_CheckThing (AActor *thing, FCheckPosition &tm) { // Don't hurt same species or any relative - // but only if the target isn't one's hostile. - if (!thing->IsHostile (tm.thing->target)) + if (!thing->IsHostile(tm.thing->target)) { // Allow hurting monsters the shooter hates. if (thing->tid == 0 || tm.thing->target->TIDtoHate != thing->tid) @@ -1135,11 +1152,11 @@ bool PIT_CheckThing (AActor *thing, FCheckPosition &tm) if (!(thing->flags & MF_NOBLOOD) && !(thing->flags2 & MF2_REFLECTIVE) && !(tm.thing->flags3 & MF3_BLOODLESSIMPACT) && - !(thing->flags2 & (MF2_INVULNERABLE|MF2_DORMANT))) + !(thing->flags2 & (MF2_INVULNERABLE | MF2_DORMANT))) { // Ok to spawn blood - P_RipperBlood (tm.thing, thing); + P_RipperBlood(tm.thing, thing); } - S_Sound (tm.thing, CHAN_BODY, "misc/ripslop", 1, ATTN_IDLE); + S_Sound(tm.thing, CHAN_BODY, "misc/ripslop", 1, ATTN_IDLE); // Do poisoning (if using new style poison) if (tm.thing->PoisonDamage > 0 && tm.thing->PoisonDuration != INT_MIN) @@ -1147,11 +1164,11 @@ bool PIT_CheckThing (AActor *thing, FCheckPosition &tm) P_PoisonMobj(thing, tm.thing, tm.thing->target, tm.thing->PoisonDamage, tm.thing->PoisonDuration, tm.thing->PoisonPeriod, tm.thing->PoisonDamageType); } - damage = tm.thing->GetMissileDamage (3, 2); - int newdam = P_DamageMobj (thing, tm.thing, tm.thing->target, damage, tm.thing->DamageType); + damage = tm.thing->GetMissileDamage(3, 2); + int newdam = P_DamageMobj(thing, tm.thing, tm.thing->target, damage, tm.thing->DamageType); if (!(tm.thing->flags3 & MF3_BLOODLESSIMPACT)) { - P_TraceBleed (newdam > 0 ? newdam : damage, thing, tm.thing); + P_TraceBleed(newdam > 0 ? newdam : damage, thing, tm.thing); } if (thing->flags2 & MF2_PUSHABLE && !(tm.thing->flags2 & MF2_CANNOTPUSH)) @@ -1164,7 +1181,7 @@ bool PIT_CheckThing (AActor *thing, FCheckPosition &tm) } } } - spechit.Clear (); + spechit.Clear(); return true; } } @@ -1176,35 +1193,34 @@ bool PIT_CheckThing (AActor *thing, FCheckPosition &tm) } // Do damage - damage = tm.thing->GetMissileDamage ((tm.thing->flags4 & MF4_STRIFEDAMAGE) ? 3 : 7, 1); - if ((damage > 0) || (tm.thing->flags6 & MF6_FORCEPAIN)) + damage = tm.thing->GetMissileDamage((tm.thing->flags4 & MF4_STRIFEDAMAGE) ? 3 : 7, 1); + if ((damage > 0) || (tm.thing->flags6 & MF6_FORCEPAIN)) { - int newdam = P_DamageMobj (thing, tm.thing, tm.thing->target, damage, tm.thing->DamageType); + int newdam = P_DamageMobj(thing, tm.thing, tm.thing->target, damage, tm.thing->DamageType); if (damage > 0) { if ((tm.thing->flags5 & MF5_BLOODSPLATTER) && !(thing->flags & MF_NOBLOOD) && !(thing->flags2 & MF2_REFLECTIVE) && - !(thing->flags2 & (MF2_INVULNERABLE|MF2_DORMANT)) && + !(thing->flags2 & (MF2_INVULNERABLE | MF2_DORMANT)) && !(tm.thing->flags3 & MF3_BLOODLESSIMPACT) && (pr_checkthing() < 192)) { - P_BloodSplatter (tm.thing->x, tm.thing->y, tm.thing->z, thing); + P_BloodSplatter(tm.thing->x, tm.thing->y, tm.thing->z, thing); } if (!(tm.thing->flags3 & MF3_BLOODLESSIMPACT)) { - P_TraceBleed (newdam > 0 ? newdam : damage, thing, tm.thing); + P_TraceBleed(newdam > 0 ? newdam : damage, thing, tm.thing); } } } else { - P_GiveBody (thing, -damage); + P_GiveBody(thing, -damage); } 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) { @@ -1214,8 +1230,8 @@ bool PIT_CheckThing (AActor *thing, FCheckPosition &tm) } } solid = (thing->flags & MF_SOLID) && - !(thing->flags & MF_NOCLIP) && - ((tm.thing->flags & MF_SOLID) || (tm.thing->flags6 & MF6_BLOCKEDBYSOLIDACTORS)); + !(thing->flags & MF_NOCLIP) && + ((tm.thing->flags & MF_SOLID) || (tm.thing->flags6 & MF6_BLOCKEDBYSOLIDACTORS)); // Check for special pickup if ((thing->flags & MF_SPECIAL) && (tm.thing->flags & MF_PICKUP) @@ -1224,7 +1240,7 @@ bool PIT_CheckThing (AActor *thing, FCheckPosition &tm) // up things that are above your true height. && thing->z < tm.thing->z + tm.thing->height - tm.thing->MaxStepHeight) { // Can be picked up by tmthing - P_TouchSpecialThing (thing, tm.thing); // can remove thing + P_TouchSpecialThing(thing, tm.thing); // can remove thing } // killough 3/16/98: Allow non-solid moving objects to move through solid @@ -1242,7 +1258,7 @@ bool PIT_CheckThing (AActor *thing, FCheckPosition &tm) /* =============================================================================== - MOVEMENT CLIPPING +MOVEMENT CLIPPING =============================================================================== */ @@ -1274,7 +1290,7 @@ bool PIT_CheckThing (AActor *thing, FCheckPosition &tm) // //========================================================================== -bool P_CheckPosition (AActor *thing, fixed_t x, fixed_t y, FCheckPosition &tm, bool actorsonly) +bool P_CheckPosition(AActor *thing, fixed_t x, fixed_t y, FCheckPosition &tm, bool actorsonly) { sector_t *newsec; AActor *thingblocker; @@ -1285,13 +1301,13 @@ bool P_CheckPosition (AActor *thing, fixed_t x, fixed_t y, FCheckPosition &tm, b tm.x = x; tm.y = y; - newsec = P_PointInSector (x,y); + newsec = P_PointInSector(x, y); tm.ceilingline = thing->BlockingLine = NULL; - -// The base floor / ceiling is from the subsector that contains the point. -// Any contacted lines the step closer together will adjust them. - tm.floorz = tm.dropoffz = newsec->floorplane.ZatPoint (x, y); - tm.ceilingz = newsec->ceilingplane.ZatPoint (x, y); + + // The base floor / ceiling is from the subsector that contains the point. + // Any contacted lines the step closer together will adjust them. + tm.floorz = tm.dropoffz = newsec->floorplane.ZatPoint(x, y); + tm.ceilingz = newsec->ceilingplane.ZatPoint(x, y); tm.floorpic = newsec->GetTexture(sector_t::floor); tm.floorsector = newsec; tm.ceilingpic = newsec->GetTexture(sector_t::ceiling); @@ -1301,7 +1317,7 @@ bool P_CheckPosition (AActor *thing, fixed_t x, fixed_t y, FCheckPosition &tm, b //Added by MC: Fill the tmsector. tm.sector = newsec; - + #ifdef _3DFLOORS //Check 3D floors if (!thing->IsNoClip2() && newsec->e->XFloor.ffloors.Size()) @@ -1309,25 +1325,25 @@ bool P_CheckPosition (AActor *thing, fixed_t x, fixed_t y, FCheckPosition &tm, b F3DFloor* rover; fixed_t delta1; fixed_t delta2; - int thingtop = thing->z + (thing->height==0? 1:thing->height); - - for(unsigned i=0;ie->XFloor.ffloors.Size();i++) + int thingtop = thing->z + (thing->height == 0 ? 1 : thing->height); + + for (unsigned i = 0; ie->XFloor.ffloors.Size(); i++) { rover = newsec->e->XFloor.ffloors[i]; - if(!(rover->flags & FF_SOLID) || !(rover->flags & FF_EXISTS)) continue; + if (!(rover->flags & FF_SOLID) || !(rover->flags & FF_EXISTS)) continue; - fixed_t ff_bottom=rover->bottom.plane->ZatPoint(x, y); - fixed_t ff_top=rover->top.plane->ZatPoint(x, y); - - delta1 = thing->z - (ff_bottom + ((ff_top-ff_bottom)/2)); - delta2 = thingtop - (ff_bottom + ((ff_top-ff_bottom)/2)); + fixed_t ff_bottom = rover->bottom.plane->ZatPoint(x, y); + fixed_t ff_top = rover->top.plane->ZatPoint(x, y); - if(ff_top > tm.floorz && abs(delta1) < abs(delta2)) + delta1 = thing->z - (ff_bottom + ((ff_top - ff_bottom) / 2)); + delta2 = thingtop - (ff_bottom + ((ff_top - ff_bottom) / 2)); + + if (ff_top > tm.floorz && abs(delta1) < abs(delta2)) { tm.floorz = tm.dropoffz = ff_top; tm.floorpic = *rover->top.texture; } - if(ff_bottom < tm.ceilingz && abs(delta1) >= abs(delta2)) + if (ff_bottom < tm.ceilingz && abs(delta1) >= abs(delta2)) { tm.ceilingz = ff_bottom; tm.ceilingpic = *rover->bottom.texture; @@ -1335,13 +1351,13 @@ bool P_CheckPosition (AActor *thing, fixed_t x, fixed_t y, FCheckPosition &tm, b } } #endif - + validcount++; - spechit.Clear (); + spechit.Clear(); if ((thing->flags & MF_NOCLIP) && !(thing->flags & MF_SKULLFLY)) return true; - + // Check things first, possibly picking things up. thing->BlockingMobj = NULL; thingblocker = NULL; @@ -1360,9 +1376,9 @@ bool P_CheckPosition (AActor *thing, fixed_t x, fixed_t y, FCheckPosition &tm, b { if (!PIT_CheckThing(th, tm)) { // [RH] If a thing can be stepped up on, we need to continue checking - // other things in the blocks and see if we hit something that is - // definitely blocking. Otherwise, we need to check the lines, or we - // could end up stuck inside a wall. + // other things in the blocks and see if we hit something that is + // definitely blocking. Otherwise, we need to check the lines, or we + // could end up stuck inside a wall. AActor *BlockingMobj = thing->BlockingMobj; if (BlockingMobj == NULL || (i_compatflags & COMPATF_NO_PASSMOBJ)) @@ -1370,8 +1386,8 @@ bool P_CheckPosition (AActor *thing, fixed_t x, fixed_t y, FCheckPosition &tm, b thing->height = realheight; return false; } - else if (!BlockingMobj->player && !(thing->flags & (MF_FLOAT|MF_MISSILE|MF_SKULLFLY)) && - BlockingMobj->z+BlockingMobj->height-thing->z <= thing->MaxStepHeight) + else if (!BlockingMobj->player && !(thing->flags & (MF_FLOAT | MF_MISSILE | MF_SKULLFLY)) && + BlockingMobj->z + BlockingMobj->height - thing->z <= thing->MaxStepHeight) { if (thingblocker == NULL || BlockingMobj->z > thingblocker->z) @@ -1385,7 +1401,7 @@ bool P_CheckPosition (AActor *thing, fixed_t x, fixed_t y, FCheckPosition &tm, b { if (thingblocker) { // There is something to step up on. Return this thing as - // the blocker so that we don't step up. + // the blocker so that we don't step up. thing->height = realheight; return false; } @@ -1453,7 +1469,7 @@ bool P_CheckPosition (AActor *thing, fixed_t x, fixed_t y, FCheckPosition &tm, b return (thing->BlockingMobj = thingblocker) == NULL; } -bool P_CheckPosition (AActor *thing, fixed_t x, fixed_t y, bool actorsonly) +bool P_CheckPosition(AActor *thing, fixed_t x, fixed_t y, bool actorsonly) { FCheckPosition tm; return P_CheckPosition(thing, x, y, tm, actorsonly); @@ -1468,7 +1484,7 @@ bool P_CheckPosition (AActor *thing, fixed_t x, fixed_t y, bool actorsonly) // //---------------------------------------------------------------------------- -bool P_TestMobjLocation (AActor *mobj) +bool P_TestMobjLocation(AActor *mobj) { int flags; @@ -1495,15 +1511,15 @@ bool P_TestMobjLocation (AActor *mobj) // Checks if the new Z position is legal //============================================================================= -AActor *P_CheckOnmobj (AActor *thing) +AActor *P_CheckOnmobj(AActor *thing) { fixed_t oldz; bool good; AActor *onmobj; oldz = thing->z; - P_FakeZMovement (thing); - good = P_TestMobjZ (thing, false, &onmobj); + P_FakeZMovement(thing); + good = P_TestMobjZ(thing, false, &onmobj); thing->z = oldz; return good ? NULL : onmobj; @@ -1515,7 +1531,7 @@ AActor *P_CheckOnmobj (AActor *thing) // //============================================================================= -bool P_TestMobjZ (AActor *actor, bool quick, AActor **pOnmobj) +bool P_TestMobjZ(AActor *actor, bool quick, AActor **pOnmobj) { AActor *onmobj = NULL; if (actor->flags & MF_NOCLIP) @@ -1545,7 +1561,7 @@ bool P_TestMobjZ (AActor *actor, bool quick, AActor **pOnmobj) { // Can't hit thing continue; } - if (thing->flags & (MF_SPECIAL|MF_NOCLIP)) + if (thing->flags & (MF_SPECIAL | MF_NOCLIP)) { // [RH] Specials and noclippers don't block moves continue; } @@ -1566,11 +1582,11 @@ bool P_TestMobjZ (AActor *actor, bool quick, AActor **pOnmobj) { // Don't clip against whoever shot the missile. continue; } - if (actor->z > thing->z+thing->height) + if (actor->z > thing->z + thing->height) { // over thing continue; } - else if (actor->z+actor->height <= thing->z) + else if (actor->z + actor->height <= thing->z) { // under thing continue; } @@ -1593,32 +1609,32 @@ bool P_TestMobjZ (AActor *actor, bool quick, AActor **pOnmobj) // Fake the zmovement so that we can check if a move is legal //============================================================================= -void P_FakeZMovement (AActor *mo) +void P_FakeZMovement(AActor *mo) { -// -// adjust height -// + // + // adjust height + // mo->z += mo->velz; if ((mo->flags&MF_FLOAT) && mo->target) { // float down towards target if too close if (!(mo->flags & MF_SKULLFLY) && !(mo->flags & MF_INFLOAT)) { - fixed_t dist = P_AproxDistance (mo->x - mo->target->x, mo->y - mo->target->y); - fixed_t delta = (mo->target->z + (mo->height>>1)) - mo->z; - if (delta < 0 && dist < -(delta*3)) + fixed_t dist = P_AproxDistance(mo->x - mo->target->x, mo->y - mo->target->y); + fixed_t delta = (mo->target->z + (mo->height >> 1)) - mo->z; + if (delta < 0 && dist < -(delta * 3)) mo->z -= mo->FloatSpeed; - else if (delta > 0 && dist < (delta*3)) + else if (delta > 0 && dist < (delta * 3)) mo->z += mo->FloatSpeed; } } if (mo->player && mo->flags&MF_NOGRAVITY && (mo->z > mo->floorz) && !mo->IsNoClip2()) { - mo->z += finesine[(FINEANGLES/80*level.maptime)&FINEMASK]/8; + mo->z += finesine[(FINEANGLES / 80 * level.maptime)&FINEMASK] / 8; } -// -// clip movement -// + // + // clip movement + // if (mo->z <= mo->floorz) { // hit the floor mo->z = mo->floorz; @@ -1636,13 +1652,13 @@ void P_FakeZMovement (AActor *mo) // //=========================================================================== -static void CheckForPushSpecial (line_t *line, int side, AActor *mobj, bool windowcheck) +static void CheckForPushSpecial(line_t *line, int side, AActor *mobj, bool windowcheck) { 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. + // or similar construct we are standing inside of. fixed_t fzt = line->frontsector->ceilingplane.ZatPoint(mobj->x, mobj->y); fixed_t fzb = line->frontsector->floorplane.ZatPoint(mobj->x, mobj->y); fixed_t bzt = line->backsector->ceilingplane.ZatPoint(mobj->x, mobj->y); @@ -1651,29 +1667,29 @@ static void CheckForPushSpecial (line_t *line, int side, AActor *mobj, bool wind fzb <= mobj->z && bzb <= mobj->z) { // we must also check if some 3D floor in the backsector may be blocking - #ifdef _3DFLOORS - for(unsigned int i=0;ibacksector->e->XFloor.ffloors.Size();i++) +#ifdef _3DFLOORS + for (unsigned int i = 0; ibacksector->e->XFloor.ffloors.Size(); i++) + { + F3DFloor* rover = line->backsector->e->XFloor.ffloors[i]; + + if (!(rover->flags & FF_SOLID) || !(rover->flags & FF_EXISTS)) continue; + + fixed_t ff_bottom = rover->bottom.plane->ZatPoint(mobj->x, mobj->y); + fixed_t ff_top = rover->top.plane->ZatPoint(mobj->x, mobj->y); + + if (ff_bottom < mobj->z + mobj->height && ff_top > mobj->z) { - F3DFloor* rover = line->backsector->e->XFloor.ffloors[i]; - - if (!(rover->flags & FF_SOLID) || !(rover->flags & FF_EXISTS)) continue; - - fixed_t ff_bottom = rover->bottom.plane->ZatPoint(mobj->x, mobj->y); - fixed_t ff_top = rover->top.plane->ZatPoint(mobj->x, mobj->y); - - if (ff_bottom < mobj->z + mobj->height && ff_top > mobj->z) - { - goto isblocking; - } + goto isblocking; } - #endif + } +#endif return; } } -isblocking: + isblocking: if (mobj->flags2 & MF2_PUSHWALL) { - P_ActivateLine (line, mobj, side, SPAC_Push); + P_ActivateLine(line, mobj, side, SPAC_Push); } else if (mobj->flags2 & MF2_IMPACT) { @@ -1681,13 +1697,13 @@ isblocking: !(mobj->flags & MF_MISSILE) || (mobj->target == NULL)) { - P_ActivateLine (line, mobj, side, SPAC_Impact); + P_ActivateLine(line, mobj, side, SPAC_Impact); } else { - P_ActivateLine (line, mobj->target, side, SPAC_Impact); + P_ActivateLine(line, mobj->target, side, SPAC_Impact); } - } + } } } @@ -1699,11 +1715,11 @@ isblocking: // //========================================================================== -bool P_TryMove (AActor *thing, fixed_t x, fixed_t y, - int dropoff, // killough 3/15/98: allow dropoff as option - const secplane_t *onfloor, // [RH] Let P_TryMove keep the thing on the floor - FCheckPosition &tm, - bool missileCheck) // [GZ] Fired missiles ignore the drop-off test +bool P_TryMove(AActor *thing, fixed_t x, fixed_t y, + int dropoff, // killough 3/15/98: allow dropoff as option + const secplane_t *onfloor, // [RH] Let P_TryMove keep the thing on the floor + FCheckPosition &tm, + bool missileCheck) // [GZ] Fired missiles ignore the drop-off test { fixed_t oldx; fixed_t oldy; @@ -1718,10 +1734,10 @@ bool P_TryMove (AActor *thing, fixed_t x, fixed_t y, oldz = thing->z; if (onfloor) { - thing->z = onfloor->ZatPoint (x, y); + thing->z = onfloor->ZatPoint(x, y); } thing->flags6 |= MF6_INTRYMOVE; - if (!P_CheckPosition (thing, x, y, tm)) + if (!P_CheckPosition(thing, x, y, tm)) { AActor *BlockingMobj = thing->BlockingMobj; // Solid wall or thing @@ -1735,11 +1751,11 @@ bool P_TryMove (AActor *thing, fixed_t x, fixed_t y, { goto pushline; } - else if (BlockingMobj->z+BlockingMobj->height-thing->z + else if (BlockingMobj->z + BlockingMobj->height - thing->z > thing->MaxStepHeight - || (BlockingMobj->Sector->ceilingplane.ZatPoint (x, y) - - (BlockingMobj->z+BlockingMobj->height) < thing->height) - || (tm.ceilingz-(BlockingMobj->z+BlockingMobj->height) + || (BlockingMobj->Sector->ceilingplane.ZatPoint(x, y) + - (BlockingMobj->z + BlockingMobj->height) < thing->height) + || (tm.ceilingz - (BlockingMobj->z + BlockingMobj->height) < thing->height)) { goto pushline; @@ -1774,7 +1790,7 @@ bool P_TryMove (AActor *thing, fixed_t x, fixed_t y, } tm.floatok = true; - + if (!(thing->flags & MF_TELEPORT) && tm.ceilingz - thing->z < thing->height && !(thing->flags3 & MF3_CEILINGHUGGER) @@ -1785,19 +1801,19 @@ bool P_TryMove (AActor *thing, fixed_t x, fixed_t y, if (thing->flags2 & MF2_FLY && thing->flags & MF_NOGRAVITY) { #if 1 - if (thing->z+thing->height > tm.ceilingz) + if (thing->z + thing->height > tm.ceilingz) goto pushline; #else // When flying, slide up or down blocking lines until the actor // is not blocked. - if (thing->z+thing->height > tm.ceilingz) + if (thing->z + thing->height > tm.ceilingz) { - thing->velz = -8*FRACUNIT; + thing->velz = -8 * FRACUNIT; goto pushline; } - else if (thing->z < tm.floorz && tm.floorz-tm.dropoffz > thing->MaxDropOffHeight) + else if (thing->z < tm.floorz && tm.floorz - tm.dropoffz > thing->MaxDropOffHeight) { - thing->velz = 8*FRACUNIT; + thing->velz = 8 * FRACUNIT; goto pushline; } #endif @@ -1808,7 +1824,7 @@ bool P_TryMove (AActor *thing, fixed_t x, fixed_t y, { // [RH] Don't let normal missiles climb steps goto pushline; } - if (tm.floorz-thing->z > thing->MaxStepHeight) + if (tm.floorz - thing->z > thing->MaxStepHeight) { // too big a step up goto pushline; } @@ -1817,7 +1833,7 @@ bool P_TryMove (AActor *thing, fixed_t x, fixed_t y, fixed_t savedz = thing->z; bool good; thing->z = tm.floorz; - good = P_TestMobjZ (thing); + good = P_TestMobjZ(thing); thing->z = savedz; if (!good) { @@ -1832,7 +1848,7 @@ bool P_TryMove (AActor *thing, fixed_t x, fixed_t y, // If it's a bouncer, let it bounce off its new floor, too. if (thing->BounceFlags & BOUNCE_Floors) { - thing->FloorBounceMissile (tm.floorsector->floorplane); + thing->FloorBounceMissile(tm.floorsector->floorplane); } else { @@ -1850,15 +1866,15 @@ bool P_TryMove (AActor *thing, fixed_t x, fixed_t y, dropoff = false; } - if (dropoff==2 && // large jump down (e.g. dogs) - (tm.floorz-tm.dropoffz > 128*FRACUNIT || thing->target == NULL || thing->target->z >tm.dropoffz)) + if (dropoff == 2 && // large jump down (e.g. dogs) + (tm.floorz - tm.dropoffz > 128 * FRACUNIT || thing->target == NULL || thing->target->z >tm.dropoffz)) { dropoff = false; } // killough 3/15/98: Allow certain objects to drop off - if ((!dropoff && !(thing->flags & (MF_DROPOFF|MF_FLOAT|MF_MISSILE))) || (thing->flags5&MF5_NODROPOFF)) + if ((!dropoff && !(thing->flags & (MF_DROPOFF | MF_FLOAT | MF_MISSILE))) || (thing->flags5&MF5_NODROPOFF)) { if (!(thing->flags5&MF5_AVOIDINGDROPOFF)) { @@ -1869,11 +1885,11 @@ bool P_TryMove (AActor *thing, fixed_t x, fixed_t y, { floorz = MAX(thing->z, tm.floorz); } - + if (floorz - tm.dropoffz > thing->MaxDropOffHeight && - !(thing->flags2 & MF2_BLASTED) && !missileCheck) + !(thing->flags2 & MF2_BLASTED) && !missileCheck) { // Can't move over a dropoff unless it's been blasted - // [GZ] Or missile-spawned + // [GZ] Or missile-spawned thing->z = oldz; thing->flags6 &= ~MF6_INTRYMOVE; return false; @@ -1893,18 +1909,18 @@ bool P_TryMove (AActor *thing, fixed_t x, fixed_t y, } if (thing->flags2 & MF2_CANTLEAVEFLOORPIC && (tm.floorpic != thing->floorpic - || tm.floorz - thing->z != 0)) + || tm.floorz - thing->z != 0)) { // must stay within a sector of a certain floor type thing->z = oldz; thing->flags6 &= ~MF6_INTRYMOVE; return false; } - + //Added by MC: To prevent bot from getting into dangerous sectors. if (thing->player && thing->player->isbot && thing->flags & MF_SHOOTABLE) { if (tm.sector != thing->Sector - && bglobal.IsDangerous (tm.sector)) + && bglobal.IsDangerous(tm.sector)) { thing->player->prev = thing->player->dest; thing->player->dest = NULL; @@ -1914,7 +1930,7 @@ bool P_TryMove (AActor *thing, fixed_t x, fixed_t y, thing->flags6 &= ~MF6_INTRYMOVE; return false; } - } + } } // [RH] Check status of eyes against fake floor/ceiling in case @@ -1922,7 +1938,7 @@ bool P_TryMove (AActor *thing, fixed_t x, fixed_t y, bool oldAboveFakeFloor, oldAboveFakeCeiling; fixed_t viewheight; - + viewheight = thing->player ? thing->player->viewheight : thing->height / 2; oldAboveFakeFloor = oldAboveFakeCeiling = false; // pacify GCC @@ -1930,21 +1946,21 @@ bool P_TryMove (AActor *thing, fixed_t x, fixed_t y, { fixed_t eyez = oldz + viewheight; - oldAboveFakeFloor = eyez > oldsec->heightsec->floorplane.ZatPoint (thing->x, thing->y); - oldAboveFakeCeiling = eyez > oldsec->heightsec->ceilingplane.ZatPoint (thing->x, thing->y); + oldAboveFakeFloor = eyez > oldsec->heightsec->floorplane.ZatPoint(thing->x, thing->y); + oldAboveFakeCeiling = eyez > oldsec->heightsec->ceilingplane.ZatPoint(thing->x, thing->y); } // Borrowed from MBF: if (thing->BounceFlags & BOUNCE_MBF && // killough 8/13/98 - !(thing->flags & (MF_MISSILE|MF_NOGRAVITY)) && - !thing->IsSentient() && tm.floorz - thing->z > 16*FRACUNIT) + !(thing->flags & (MF_MISSILE | MF_NOGRAVITY)) && + !thing->IsSentient() && tm.floorz - thing->z > 16 * FRACUNIT) { // too big a step up for MBF bouncers under gravity thing->flags6 &= ~MF6_INTRYMOVE; return false; } // the move is ok, so link the thing into its new position - thing->UnlinkFromWorld (); + thing->UnlinkFromWorld(); oldx = thing->x; oldy = thing->y; @@ -1958,11 +1974,11 @@ bool P_TryMove (AActor *thing, fixed_t x, fixed_t y, thing->x = x; thing->y = y; - thing->LinkToWorld (); + thing->LinkToWorld(); if (thing->flags2 & MF2_FLOORCLIP) { - thing->AdjustFloorClip (); + thing->AdjustFloorClip(); } // [RH] Don't activate anything if just predicting @@ -1973,36 +1989,36 @@ bool P_TryMove (AActor *thing, fixed_t x, fixed_t y, } // if any special lines were hit, do the effect - if (!(thing->flags & (MF_TELEPORT|MF_NOCLIP))) + if (!(thing->flags & (MF_TELEPORT | MF_NOCLIP))) { - while (spechit.Pop (ld)) + while (spechit.Pop(ld)) { // see if the line was crossed - side = P_PointOnLineSide (thing->x, thing->y, ld); - oldside = P_PointOnLineSide (oldx, oldy, ld); + side = P_PointOnLineSide(thing->x, thing->y, ld); + oldside = P_PointOnLineSide(oldx, oldy, ld); if (side != oldside && ld->special && !(thing->flags6 & MF6_NOTRIGGER)) { if (thing->player) { - P_ActivateLine (ld, thing, oldside, SPAC_Cross); + P_ActivateLine(ld, thing, oldside, SPAC_Cross); } else if (thing->flags2 & MF2_MCROSS) { - P_ActivateLine (ld, thing, oldside, SPAC_MCross); + P_ActivateLine(ld, thing, oldside, SPAC_MCross); } else if (thing->flags2 & MF2_PCROSS) { - P_ActivateLine (ld, thing, oldside, SPAC_PCross); + P_ActivateLine(ld, thing, oldside, SPAC_PCross); } else if ((ld->special == Teleport || - ld->special == Teleport_NoFog || - ld->special == Teleport_Line)) + ld->special == Teleport_NoFog || + ld->special == Teleport_Line)) { // [RH] Just a little hack for BOOM compatibility - P_ActivateLine (ld, thing, oldside, SPAC_MCross); + P_ActivateLine(ld, thing, oldside, SPAC_MCross); } else { - P_ActivateLine (ld, thing, oldside, SPAC_AnyCross); + P_ActivateLine(ld, thing, oldside, SPAC_AnyCross); } } } @@ -2014,27 +2030,27 @@ bool P_TryMove (AActor *thing, fixed_t x, fixed_t y, { const sector_t *hs = newsec->heightsec; fixed_t eyez = thing->z + viewheight; - fixed_t fakez = hs->floorplane.ZatPoint (x, y); + fixed_t fakez = hs->floorplane.ZatPoint(x, y); if (!oldAboveFakeFloor && eyez > fakez) { // View went above fake floor - newsec->SecActTarget->TriggerAction (thing, SECSPAC_EyesSurface); + newsec->SecActTarget->TriggerAction(thing, SECSPAC_EyesSurface); } else if (oldAboveFakeFloor && eyez <= fakez) { // View went below fake floor - newsec->SecActTarget->TriggerAction (thing, SECSPAC_EyesDive); + newsec->SecActTarget->TriggerAction(thing, SECSPAC_EyesDive); } if (!(hs->MoreFlags & SECF_FAKEFLOORONLY)) { - fakez = hs->ceilingplane.ZatPoint (x, y); + fakez = hs->ceilingplane.ZatPoint(x, y); if (!oldAboveFakeCeiling && eyez > fakez) { // View went above fake ceiling - newsec->SecActTarget->TriggerAction (thing, SECSPAC_EyesAboveC); + newsec->SecActTarget->TriggerAction(thing, SECSPAC_EyesAboveC); } else if (oldAboveFakeCeiling && eyez <= fakez) { // View went below fake ceiling - newsec->SecActTarget->TriggerAction (thing, SECSPAC_EyesBelowC); + newsec->SecActTarget->TriggerAction(thing, SECSPAC_EyesBelowC); } } } @@ -2054,29 +2070,29 @@ pushline: } thing->z = oldz; - if (!(thing->flags&(MF_TELEPORT|MF_NOCLIP))) + if (!(thing->flags&(MF_TELEPORT | MF_NOCLIP))) { int numSpecHitTemp; if (tm.thing->flags2 & MF2_BLASTED) { - P_DamageMobj (tm.thing, NULL, NULL, tm.thing->Mass >> 5, NAME_Melee); + P_DamageMobj(tm.thing, NULL, NULL, tm.thing->Mass >> 5, NAME_Melee); } - numSpecHitTemp = (int)spechit.Size (); + numSpecHitTemp = (int)spechit.Size(); while (numSpecHitTemp > 0) { // see which lines were pushed ld = spechit[--numSpecHitTemp]; - side = P_PointOnLineSide (thing->x, thing->y, ld); - CheckForPushSpecial (ld, side, thing, true); + side = P_PointOnLineSide(thing->x, thing->y, ld); + CheckForPushSpecial(ld, side, thing, true); } } return false; } -bool P_TryMove (AActor *thing, fixed_t x, fixed_t y, - int dropoff, // killough 3/15/98: allow dropoff as option - const secplane_t *onfloor) // [RH] Let P_TryMove keep the thing on the floor +bool P_TryMove(AActor *thing, fixed_t x, fixed_t y, + int dropoff, // killough 3/15/98: allow dropoff as option + const secplane_t *onfloor) // [RH] Let P_TryMove keep the thing on the floor { FCheckPosition tm; return P_TryMove(thing, x, y, dropoff, onfloor, tm); @@ -2096,7 +2112,7 @@ bool P_CheckMove(AActor *thing, fixed_t x, fixed_t y) FCheckPosition tm; fixed_t newz = thing->z; - if (!P_CheckPosition (thing, x, y, tm)) + if (!P_CheckPosition(thing, x, y, tm)) { return false; } @@ -2126,12 +2142,12 @@ bool P_CheckMove(AActor *thing, fixed_t x, fixed_t y) } if (thing->flags2 & MF2_FLY && thing->flags & MF_NOGRAVITY) { - if (thing->z+thing->height > tm.ceilingz) + if (thing->z + thing->height > tm.ceilingz) return false; } if (!(thing->flags & MF_TELEPORT) && !(thing->flags3 & MF3_FLOORHUGGER)) { - if (tm.floorz-newz > thing->MaxStepHeight) + if (tm.floorz - newz > thing->MaxStepHeight) { // too big a step up return false; } @@ -2143,7 +2159,7 @@ bool P_CheckMove(AActor *thing, fixed_t x, fixed_t y) { // [RH] Check to make sure there's nothing in the way for the step up fixed_t savedz = thing->z; thing->z = newz = tm.floorz; - bool good = P_TestMobjZ (thing); + bool good = P_TestMobjZ(thing); thing->z = savedz; if (!good) { @@ -2154,7 +2170,7 @@ bool P_CheckMove(AActor *thing, fixed_t x, fixed_t y) if (thing->flags2 & MF2_CANTLEAVEFLOORPIC && (tm.floorpic != thing->floorpic - || tm.floorz - newz != 0)) + || tm.floorz - newz != 0)) { // must stay within a sector of a certain floor type return false; } @@ -2186,12 +2202,12 @@ struct FSlide fixed_t tmymove; void HitSlideLine(line_t *ld); - void SlideTraverse (fixed_t startx, fixed_t starty, fixed_t endx, fixed_t endy); - void SlideMove (AActor *mo, fixed_t tryx, fixed_t tryy, int numsteps); + void SlideTraverse(fixed_t startx, fixed_t starty, fixed_t endx, fixed_t endy); + void SlideMove(AActor *mo, fixed_t tryx, fixed_t tryy, int numsteps); // The bouncing code uses the same data structure - bool BounceTraverse (fixed_t startx, fixed_t starty, fixed_t endx, fixed_t endy); - bool BounceWall (AActor *mo); + bool BounceTraverse(fixed_t startx, fixed_t starty, fixed_t endx, fixed_t endy); + bool BounceWall(AActor *mo); }; //========================================================================== @@ -2203,17 +2219,17 @@ struct FSlide // //========================================================================== -void FSlide::HitSlideLine (line_t* ld) +void FSlide::HitSlideLine(line_t* ld) { int side; angle_t lineangle; angle_t moveangle; angle_t deltaangle; - + fixed_t movelen; bool icyfloor; // is floor icy? // phares - // | + // | // Under icy conditions, if the angle of approach to the wall // V // is more than 45 degrees, then you'll bounce and lose half // your velocity. If less than 45 degrees, you'll slide along @@ -2222,37 +2238,21 @@ void FSlide::HitSlideLine (line_t* ld) // Check for the special cases of horz or vert walls. // killough 10/98: only bounce if hit hard (prevents wobbling) - icyfloor = - (P_AproxDistance(tmxmove, tmymove) > 4*FRACUNIT) && + icyfloor = + (P_AproxDistance(tmxmove, tmymove) > 4 * FRACUNIT) && var_friction && // killough 8/28/98: calc friction on demand slidemo->z <= slidemo->floorz && - P_GetFriction (slidemo, NULL) > ORIG_FRICTION; + P_GetFriction(slidemo, NULL) > ORIG_FRICTION; - if (ld->slopetype == ST_HORIZONTAL) - { - if (icyfloor && (abs(tmymove) > abs(tmxmove))) - { - tmxmove /= 2; // absorb half the velocity - tmymove = -tmymove/2; - if (slidemo->player && slidemo->health > 0 && !(slidemo->player->cheats & CF_PREDICTING)) - { - S_Sound (slidemo, CHAN_VOICE, "*grunt", 1, ATTN_IDLE); // oooff! - } - } - else - tmymove = 0; // no more movement in the Y direction - return; - } - - if (ld->slopetype == ST_VERTICAL) - { + if (ld->dx == 0) + { // ST_VERTICAL if (icyfloor && (abs(tmxmove) > abs(tmymove))) { - tmxmove = -tmxmove/2; // absorb half the velocity + tmxmove = -tmxmove / 2; // absorb half the velocity tmymove /= 2; if (slidemo->player && slidemo->health > 0 && !(slidemo->player->cheats & CF_PREDICTING)) { - S_Sound (slidemo, CHAN_VOICE, "*grunt", 1, ATTN_IDLE); // oooff!// ^ + S_Sound(slidemo, CHAN_VOICE, "*grunt", 1, ATTN_IDLE); // oooff!// ^ } } // | else // phares @@ -2260,33 +2260,49 @@ void FSlide::HitSlideLine (line_t* ld) return; } + if (ld->dy == 0) + { // ST_HORIZONTAL + if (icyfloor && (abs(tmymove) > abs(tmxmove))) + { + tmxmove /= 2; // absorb half the velocity + tmymove = -tmymove / 2; + if (slidemo->player && slidemo->health > 0 && !(slidemo->player->cheats & CF_PREDICTING)) + { + S_Sound(slidemo, CHAN_VOICE, "*grunt", 1, ATTN_IDLE); // oooff! + } + } + else + tmymove = 0; // no more movement in the Y direction + return; + } + // The wall is angled. Bounce if the angle of approach is // phares // less than 45 degrees. // phares - side = P_PointOnLineSide (slidemo->x, slidemo->y, ld); + side = P_PointOnLineSide(slidemo->x, slidemo->y, ld); - lineangle = R_PointToAngle2 (0,0, ld->dx, ld->dy); + lineangle = R_PointToAngle2(0, 0, ld->dx, ld->dy); if (side == 1) lineangle += ANG180; - moveangle = R_PointToAngle2 (0,0, tmxmove, tmymove); + moveangle = R_PointToAngle2(0, 0, tmxmove, tmymove); moveangle += 10; // prevents sudden path reversal due to // phares - // rounding error // | - deltaangle = moveangle-lineangle; // V - movelen = P_AproxDistance (tmxmove, tmymove); - if (icyfloor && (deltaangle > ANG45) && (deltaangle < ANG90+ANG45)) + // rounding error // | + deltaangle = moveangle - lineangle; // V + movelen = P_AproxDistance(tmxmove, tmymove); + if (icyfloor && (deltaangle > ANG45) && (deltaangle < ANG90 + ANG45)) { moveangle = lineangle - deltaangle; movelen /= 2; // absorb if (slidemo->player && slidemo->health > 0 && !(slidemo->player->cheats & CF_PREDICTING)) { - S_Sound (slidemo, CHAN_VOICE, "*grunt", 1, ATTN_IDLE); // oooff! + S_Sound(slidemo, CHAN_VOICE, "*grunt", 1, ATTN_IDLE); // oooff! } moveangle >>= ANGLETOFINESHIFT; - tmxmove = FixedMul (movelen, finecosine[moveangle]); - tmymove = FixedMul (movelen, finesine[moveangle]); + tmxmove = FixedMul(movelen, finecosine[moveangle]); + tmymove = FixedMul(movelen, finesine[moveangle]); } // ^ else // | { // phares @@ -2295,7 +2311,7 @@ void FSlide::HitSlideLine (line_t* ld) if (i_compatflags & COMPATF_WALLRUN) { fixed_t newlen; - + if (deltaangle > ANG180) deltaangle += ANG180; // I_Error ("SlideLine: ang>ANG180"); @@ -2303,17 +2319,17 @@ void FSlide::HitSlideLine (line_t* ld) lineangle >>= ANGLETOFINESHIFT; deltaangle >>= ANGLETOFINESHIFT; - newlen = FixedMul (movelen, finecosine[deltaangle]); + newlen = FixedMul(movelen, finecosine[deltaangle]); - tmxmove = FixedMul (newlen, finecosine[lineangle]); - tmymove = FixedMul (newlen, finesine[lineangle]); + tmxmove = FixedMul(newlen, finecosine[lineangle]); + tmymove = FixedMul(newlen, finesine[lineangle]); } else { divline_t dll, dlv; fixed_t inter1, inter2, inter3; - P_MakeDivline (ld, &dll); + P_MakeDivline(ld, &dll); dlv.x = slidemo->x; dlv.y = slidemo->y; @@ -2324,13 +2340,13 @@ void FSlide::HitSlideLine (line_t* ld) dlv.dx = tmxmove; dlv.dy = tmymove; - inter2 = P_InterceptVector (&dll, &dlv); - inter3 = P_InterceptVector (&dlv, &dll); + inter2 = P_InterceptVector(&dll, &dlv); + inter3 = P_InterceptVector(&dlv, &dll); if (inter3 != 0) { - tmxmove = Scale (inter2-inter1, dll.dx, inter3); - tmymove = Scale (inter2-inter1, dll.dy, inter3); + tmxmove = Scale(inter2 - inter1, dll.dx, inter3); + tmymove = Scale(inter2 - inter1, dll.dy, inter3); } else { @@ -2347,7 +2363,7 @@ void FSlide::HitSlideLine (line_t* ld) // //========================================================================== -void FSlide::SlideTraverse (fixed_t startx, fixed_t starty, fixed_t endx, fixed_t endy) +void FSlide::SlideTraverse(fixed_t startx, fixed_t starty, fixed_t endx, fixed_t endy) { FLineOpening open; FPathTraverse it(startx, starty, endx, endy, PT_ADDLINES); @@ -2356,26 +2372,26 @@ void FSlide::SlideTraverse (fixed_t startx, fixed_t starty, fixed_t endx, fixed_ while ((in = it.Next())) { line_t* li; - + if (!in->isaline) { // should never happen - Printf ("PTR_SlideTraverse: not a line?"); + Printf("PTR_SlideTraverse: not a line?"); continue; } - + li = in->d.line; - - if ( !(li->flags & ML_TWOSIDED) || !li->backsector ) + + if (!(li->flags & ML_TWOSIDED) || !li->backsector) { - if (P_PointOnLineSide (slidemo->x, slidemo->y, li)) + if (P_PointOnLineSide(slidemo->x, slidemo->y, li)) { // don't hit the back side - continue; + continue; } goto isblocking; } - if (li->flags & (ML_BLOCKING|ML_BLOCKEVERYTHING)) + if (li->flags & (ML_BLOCKING | ML_BLOCKEVERYTHING)) { goto isblocking; } @@ -2390,12 +2406,12 @@ void FSlide::SlideTraverse (fixed_t startx, fixed_t starty, fixed_t endx, fixed_ } // set openrange, opentop, openbottom - P_LineOpening (open, slidemo, li, it.Trace().x + FixedMul (it.Trace().dx, in->frac), - it.Trace().y + FixedMul (it.Trace().dy, in->frac)); - + P_LineOpening(open, slidemo, li, it.Trace().x + FixedMul(it.Trace().dx, in->frac), + it.Trace().y + FixedMul(it.Trace().dy, in->frac)); + if (open.range < slidemo->height) goto isblocking; // doesn't fit - + if (open.top - slidemo->z < slidemo->height) goto isblocking; // mobj is too high @@ -2407,7 +2423,7 @@ void FSlide::SlideTraverse (fixed_t startx, fixed_t starty, fixed_t endx, fixed_ { // [RH] Check to make sure there's nothing in the way for the step up fixed_t savedz = slidemo->z; slidemo->z = open.bottom; - bool good = P_TestMobjZ (slidemo); + bool good = P_TestMobjZ(slidemo); slidemo->z = savedz; if (!good) { @@ -2416,11 +2432,11 @@ void FSlide::SlideTraverse (fixed_t startx, fixed_t starty, fixed_t endx, fixed_ } // this line doesn't block movement - continue; - + continue; + // the line does block movement, // see if it is closer than best so far - isblocking: + isblocking: if (in->frac < bestslidefrac) { secondslidefrac = bestslidefrac; @@ -2428,7 +2444,7 @@ void FSlide::SlideTraverse (fixed_t startx, fixed_t starty, fixed_t endx, fixed_ bestslidefrac = in->frac; bestslideline = li; } - + return; // stop } } @@ -2447,7 +2463,7 @@ void FSlide::SlideTraverse (fixed_t startx, fixed_t starty, fixed_t endx, fixed_ // //========================================================================== -void FSlide::SlideMove (AActor *mo, fixed_t tryx, fixed_t tryy, int numsteps) +void FSlide::SlideMove(AActor *mo, fixed_t tryx, fixed_t tryy, int numsteps) { fixed_t leadx, leady; fixed_t trailx, traily; @@ -2461,11 +2477,11 @@ void FSlide::SlideMove (AActor *mo, fixed_t tryx, fixed_t tryy, int numsteps) if (mo->player && mo->player->mo == mo && mo->reactiontime > 0) return; // player coming right out of a teleporter. - - retry: + +retry: if (!--hitcount) goto stairstep; // don't loop forever - + // trace along the three leading corners if (tryx > 0) { @@ -2489,42 +2505,42 @@ void FSlide::SlideMove (AActor *mo, fixed_t tryx, fixed_t tryy, int numsteps) traily = mo->y + mo->radius; } - bestslidefrac = FRACUNIT+1; - - SlideTraverse (leadx, leady, leadx+tryx, leady+tryy); - SlideTraverse (trailx, leady, trailx+tryx, leady+tryy); - SlideTraverse (leadx, traily, leadx+tryx, traily+tryy); + bestslidefrac = FRACUNIT + 1; + + SlideTraverse(leadx, leady, leadx + tryx, leady + tryy); + SlideTraverse(trailx, leady, trailx + tryx, leady + tryy); + SlideTraverse(leadx, traily, leadx + tryx, traily + tryy); // move up to the wall - if (bestslidefrac == FRACUNIT+1) + if (bestslidefrac == FRACUNIT + 1) { // the move must have hit the middle, so stairstep - stairstep: + stairstep: // killough 3/15/98: Allow objects to drop off ledges xmove = 0, ymove = tryy; - walkplane = P_CheckSlopeWalk (mo, xmove, ymove); - if (!P_TryMove (mo, mo->x + xmove, mo->y + ymove, true, walkplane)) + walkplane = P_CheckSlopeWalk(mo, xmove, ymove); + if (!P_TryMove(mo, mo->x + xmove, mo->y + ymove, true, walkplane)) { xmove = tryx, ymove = 0; - walkplane = P_CheckSlopeWalk (mo, xmove, ymove); - P_TryMove (mo, mo->x + xmove, mo->y + ymove, true, walkplane); + walkplane = P_CheckSlopeWalk(mo, xmove, ymove); + P_TryMove(mo, mo->x + xmove, mo->y + ymove, true, walkplane); } return; } // fudge a bit to make sure it doesn't hit - bestslidefrac -= FRACUNIT/32; + bestslidefrac -= FRACUNIT / 32; if (bestslidefrac > 0) { - newx = FixedMul (tryx, bestslidefrac); - newy = FixedMul (tryy, bestslidefrac); + newx = FixedMul(tryx, bestslidefrac); + newy = FixedMul(tryy, bestslidefrac); // [BL] We need to abandon this function if we end up going through a teleporter const fixed_t startvelx = mo->velx; const fixed_t startvely = mo->vely; // killough 3/15/98: Allow objects to drop off ledges - if (!P_TryMove (mo, mo->x+newx, mo->y+newy, true)) + if (!P_TryMove(mo, mo->x + newx, mo->y + newy, true)) goto stairstep; if (mo->velx != startvelx || mo->vely != startvely) @@ -2532,16 +2548,16 @@ void FSlide::SlideMove (AActor *mo, fixed_t tryx, fixed_t tryy, int numsteps) } // Now continue along the wall. - bestslidefrac = FRACUNIT - (bestslidefrac + FRACUNIT/32); // remainder + bestslidefrac = FRACUNIT - (bestslidefrac + FRACUNIT / 32); // remainder if (bestslidefrac > FRACUNIT) bestslidefrac = FRACUNIT; else if (bestslidefrac <= 0) return; - tryx = tmxmove = FixedMul (tryx, bestslidefrac); - tryy = tmymove = FixedMul (tryy, bestslidefrac); + tryx = tmxmove = FixedMul(tryx, bestslidefrac); + tryy = tmymove = FixedMul(tryy, bestslidefrac); - HitSlideLine (bestslideline); // clip the moves + HitSlideLine(bestslideline); // clip the moves mo->velx = tmxmove * numsteps; mo->vely = tmymove * numsteps; @@ -2555,16 +2571,16 @@ void FSlide::SlideMove (AActor *mo, fixed_t tryx, fixed_t tryy, int numsteps) mo->player->vely = mo->vely; } - walkplane = P_CheckSlopeWalk (mo, tmxmove, tmymove); + walkplane = P_CheckSlopeWalk(mo, tmxmove, tmymove); // killough 3/15/98: Allow objects to drop off ledges - if (!P_TryMove (mo, mo->x+tmxmove, mo->y+tmymove, true, walkplane)) + if (!P_TryMove(mo, mo->x + tmxmove, mo->y + tmymove, true, walkplane)) { goto retry; } } -void P_SlideMove (AActor *mo, fixed_t tryx, fixed_t tryy, int numsteps) +void P_SlideMove(AActor *mo, fixed_t tryx, fixed_t tryy, int numsteps) { FSlide slide; slide.SlideMove(mo, tryx, tryy, numsteps); @@ -2576,7 +2592,7 @@ void P_SlideMove (AActor *mo, fixed_t tryx, fixed_t tryy, int numsteps) // //============================================================================ -const secplane_t * P_CheckSlopeWalk (AActor *actor, fixed_t &xmove, fixed_t &ymove) +const secplane_t * P_CheckSlopeWalk(AActor *actor, fixed_t &xmove, fixed_t &ymove) { static secplane_t copyplane; if (actor->flags & MF_NOGRAVITY) @@ -2585,40 +2601,40 @@ const secplane_t * P_CheckSlopeWalk (AActor *actor, fixed_t &xmove, fixed_t &ymo } const secplane_t *plane = &actor->floorsector->floorplane; - fixed_t planezhere = plane->ZatPoint (actor->x, actor->y); + fixed_t planezhere = plane->ZatPoint(actor->x, actor->y); #ifdef _3DFLOORS - for(unsigned int i=0;ifloorsector->e->XFloor.ffloors.Size();i++) + for (unsigned int i = 0; ifloorsector->e->XFloor.ffloors.Size(); i++) { - F3DFloor * rover= actor->floorsector->e->XFloor.ffloors[i]; - if(!(rover->flags & FF_SOLID) || !(rover->flags & FF_EXISTS)) continue; + F3DFloor * rover = actor->floorsector->e->XFloor.ffloors[i]; + if (!(rover->flags & FF_SOLID) || !(rover->flags & FF_EXISTS)) continue; fixed_t thisplanez = rover->top.plane->ZatPoint(actor->x, actor->y); - if (thisplanez>planezhere && thisplanez<=actor->z + actor->MaxStepHeight) + if (thisplanez>planezhere && thisplanez <= actor->z + actor->MaxStepHeight) { copyplane = *rover->top.plane; if (copyplane.c<0) copyplane.FlipVert(); plane = ©plane; - planezhere=thisplanez; + planezhere = thisplanez; } } if (actor->floorsector != actor->Sector) { - for(unsigned int i=0;iSector->e->XFloor.ffloors.Size();i++) + for (unsigned int i = 0; iSector->e->XFloor.ffloors.Size(); i++) { - F3DFloor * rover= actor->Sector->e->XFloor.ffloors[i]; - if(!(rover->flags & FF_SOLID) || !(rover->flags & FF_EXISTS)) continue; + F3DFloor * rover = actor->Sector->e->XFloor.ffloors[i]; + if (!(rover->flags & FF_SOLID) || !(rover->flags & FF_EXISTS)) continue; fixed_t thisplanez = rover->top.plane->ZatPoint(actor->x, actor->y); - if (thisplanez>planezhere && thisplanez<=actor->z + actor->MaxStepHeight) + if (thisplanez>planezhere && thisplanez <= actor->z + actor->MaxStepHeight) { copyplane = *rover->top.plane; if (copyplane.c<0) copyplane.FlipVert(); plane = ©plane; - planezhere=thisplanez; + planezhere = thisplanez; } } } @@ -2627,7 +2643,7 @@ const secplane_t * P_CheckSlopeWalk (AActor *actor, fixed_t &xmove, fixed_t &ymo if (actor->floorsector != actor->Sector) { // this additional check prevents sliding on sloped dropoffs - if (planezhere>actor->floorz+4*FRACUNIT) + if (planezhere>actor->floorz + 4 * FRACUNIT) return NULL; } @@ -2643,10 +2659,10 @@ const secplane_t * P_CheckSlopeWalk (AActor *actor, fixed_t &xmove, fixed_t &ymo destx = actor->x + xmove; desty = actor->y + ymove; - t = TMulScale16 (plane->a, destx, plane->b, desty, plane->c, actor->z) + plane->d; + t = TMulScale16(plane->a, destx, plane->b, desty, plane->c, actor->z) + plane->d; if (t < 0) { // Desired location is behind (below) the plane - // (i.e. Walking up the plane) + // (i.e. Walking up the plane) if (plane->c < STEEPSLOPE) { // Can't climb up slopes of ~45 degrees or more if (actor->flags & MF_NOCLIP) @@ -2658,14 +2674,14 @@ const secplane_t * P_CheckSlopeWalk (AActor *actor, fixed_t &xmove, fixed_t &ymo const msecnode_t *node; bool dopush = true; - if (plane->c > STEEPSLOPE*2/3) + if (plane->c > STEEPSLOPE * 2 / 3) { for (node = actor->touching_sectorlist; node; node = node->m_tnext) { const sector_t *sec = node->m_sector; if (sec->floorplane.c >= STEEPSLOPE) { - if (sec->floorplane.ZatPoint (destx, desty) >= actor->z - actor->MaxStepHeight) + if (sec->floorplane.ZatPoint(destx, desty) >= actor->z - actor->MaxStepHeight) { dopush = false; break; @@ -2683,8 +2699,8 @@ const secplane_t * P_CheckSlopeWalk (AActor *actor, fixed_t &xmove, fixed_t &ymo } // Slide the desired location along the plane's normal // so that it lies on the plane's surface - destx -= FixedMul (plane->a, t); - desty -= FixedMul (plane->b, t); + destx -= FixedMul(plane->a, t); + desty -= FixedMul(plane->b, t); xmove = destx - actor->x; ymove = desty - actor->y; return (actor->floorsector == actor->Sector) ? plane : NULL; @@ -2693,9 +2709,9 @@ const secplane_t * P_CheckSlopeWalk (AActor *actor, fixed_t &xmove, fixed_t &ymo { // Desired location is in front of (above) the plane if (planezhere == actor->z) { // Actor's current spot is on/in the plane, so walk down it - // Same principle as walking up, except reversed - destx += FixedMul (plane->a, t); - desty += FixedMul (plane->b, t); + // Same principle as walking up, except reversed + destx += FixedMul(plane->a, t); + desty += FixedMul(plane->b, t); xmove = destx - actor->x; ymove = desty - actor->y; return (actor->floorsector == actor->Sector) ? plane : NULL; @@ -2711,7 +2727,7 @@ const secplane_t * P_CheckSlopeWalk (AActor *actor, fixed_t &xmove, fixed_t &ymo // //============================================================================ -bool FSlide::BounceTraverse (fixed_t startx, fixed_t starty, fixed_t endx, fixed_t endy) +bool FSlide::BounceTraverse(fixed_t startx, fixed_t starty, fixed_t endx, fixed_t endy) { FLineOpening open; FPathTraverse it(startx, starty, endx, endy, PT_ADDLINES); @@ -2724,7 +2740,7 @@ bool FSlide::BounceTraverse (fixed_t startx, fixed_t starty, fixed_t endx, fixed if (!in->isaline) { - Printf ("PTR_BounceTraverse: not a line?"); + Printf("PTR_BounceTraverse: not a line?"); continue; } @@ -2736,14 +2752,14 @@ bool FSlide::BounceTraverse (fixed_t startx, fixed_t starty, fixed_t endx, fixed } if (!(li->flags&ML_TWOSIDED) || !li->backsector) { - if (P_PointOnLineSide (slidemo->x, slidemo->y, li)) + if (P_PointOnLineSide(slidemo->x, slidemo->y, li)) continue; // don't hit the back side goto bounceblocking; } - P_LineOpening (open, slidemo, li, it.Trace().x + FixedMul (it.Trace().dx, in->frac), - it.Trace().y + FixedMul (it.Trace().dy, in->frac)); // set openrange, opentop, openbottom + P_LineOpening(open, slidemo, li, it.Trace().x + FixedMul(it.Trace().dx, in->frac), + it.Trace().y + FixedMul(it.Trace().dy, in->frac)); // set openrange, opentop, openbottom if (open.range < slidemo->height) goto bounceblocking; // doesn't fit @@ -2755,7 +2771,7 @@ bool FSlide::BounceTraverse (fixed_t startx, fixed_t starty, fixed_t endx, fixed continue; // this line doesn't block movement - // the line does block movement, see if it is closer than best so far + // the line does block movement, see if it is closer than best so far bounceblocking: if (in->frac < bestslidefrac) { @@ -2775,7 +2791,7 @@ bool FSlide::BounceTraverse (fixed_t startx, fixed_t starty, fixed_t endx, fixed // //============================================================================ -bool FSlide::BounceWall (AActor *mo) +bool FSlide::BounceWall(AActor *mo) { fixed_t leadx, leady; int side; @@ -2789,39 +2805,39 @@ bool FSlide::BounceWall (AActor *mo) } slidemo = mo; -// -// trace along the three leading corners -// + // + // trace along the three leading corners + // if (mo->velx > 0) { - leadx = mo->x+mo->radius; + leadx = mo->x + mo->radius; } else { - leadx = mo->x-mo->radius; + leadx = mo->x - mo->radius; } if (mo->vely > 0) { - leady = mo->y+mo->radius; + leady = mo->y + mo->radius; } else { - leady = mo->y-mo->radius; + leady = mo->y - mo->radius; } - bestslidefrac = FRACUNIT+1; + bestslidefrac = FRACUNIT + 1; bestslideline = mo->BlockingLine; - if (BounceTraverse(leadx, leady, leadx+mo->velx, leady+mo->vely) && mo->BlockingLine == NULL) + if (BounceTraverse(leadx, leady, leadx + mo->velx, leady + mo->vely) && mo->BlockingLine == NULL) { // Could not find a wall, so bounce off the floor/ceiling instead. fixed_t floordist = mo->z - mo->floorz; fixed_t ceildist = mo->ceilingz - mo->z; if (floordist <= ceildist) { - mo->FloorBounceMissile (mo->Sector->floorplane); + mo->FloorBounceMissile(mo->Sector->floorplane); return true; } else { - mo->FloorBounceMissile (mo->Sector->ceilingplane); + mo->FloorBounceMissile(mo->Sector->ceilingplane); return true; } } @@ -2835,7 +2851,7 @@ bool FSlide::BounceWall (AActor *mo) } // The amount of bounces is limited - if (mo->bouncecount>0 && --mo->bouncecount==0) + if (mo->bouncecount>0 && --mo->bouncecount == 0) { if (mo->flags & MF_MISSILE) P_ExplodeMissile(mo, line, NULL); @@ -2844,14 +2860,14 @@ bool FSlide::BounceWall (AActor *mo) return true; } - side = P_PointOnLineSide (mo->x, mo->y, line); - lineangle = R_PointToAngle2 (0, 0, line->dx, line->dy); + side = P_PointOnLineSide(mo->x, mo->y, line); + lineangle = R_PointToAngle2(0, 0, line->dx, line->dy); if (side == 1) { lineangle += ANG180; } - moveangle = R_PointToAngle2 (0, 0, mo->velx, mo->vely); - deltaangle = (2*lineangle)-moveangle; + moveangle = R_PointToAngle2(0, 0, mo->velx, mo->vely); + deltaangle = (2 * lineangle) - moveangle; mo->angle = deltaangle; lineangle >>= ANGLETOFINESHIFT; @@ -2861,14 +2877,14 @@ bool FSlide::BounceWall (AActor *mo) movelen = FixedMul(movelen, mo->wallbouncefactor); FBoundingBox box(mo->x, mo->y, mo->radius); - if (box.BoxOnLineSide (line) == -1) + if (box.BoxOnLineSide(line) == -1) { - mo->SetOrigin (mo->x + FixedMul(mo->radius, + mo->SetOrigin(mo->x + FixedMul(mo->radius, finecosine[deltaangle]), mo->y + FixedMul(mo->radius, finesine[deltaangle]), mo->z); } if (movelen < FRACUNIT) { - movelen = 2*FRACUNIT; + movelen = 2 * FRACUNIT; } mo->velx = FixedMul(movelen, finecosine[deltaangle]); mo->vely = FixedMul(movelen, finesine[deltaangle]); @@ -2883,7 +2899,7 @@ bool FSlide::BounceWall (AActor *mo) return true; } -bool P_BounceWall (AActor *mo) +bool P_BounceWall(AActor *mo) { FSlide slide; return slide.BounceWall(mo); @@ -2896,7 +2912,7 @@ bool P_BounceWall (AActor *mo) //========================================================================== extern FRandom pr_bounce; -bool P_BounceActor (AActor *mo, AActor *BlockingMobj, bool ontop) +bool P_BounceActor(AActor *mo, AActor *BlockingMobj, bool ontop) { if (mo && BlockingMobj && ((mo->BounceFlags & BOUNCE_AllActors) || ((mo->flags & MF_MISSILE) && (!(mo->flags2 & MF2_RIP) || (BlockingMobj->flags5 & MF5_DONTRIP) || ((mo->flags6 & MF6_NOBOSSRIP) && (BlockingMobj->flags2 & MF2_BOSS))) && (BlockingMobj->flags2 & MF2_REFLECTIVE)) @@ -2908,21 +2924,21 @@ bool P_BounceActor (AActor *mo, AActor *BlockingMobj, bool ontop) if (!ontop) { fixed_t speed; - angle_t angle = R_PointToAngle2 (BlockingMobj->x, - BlockingMobj->y, mo->x, mo->y) + ANGLE_1*((pr_bounce()%16)-8); - speed = P_AproxDistance (mo->velx, mo->vely); - speed = FixedMul (speed, mo->wallbouncefactor); // [GZ] was 0.75, using wallbouncefactor seems more consistent + angle_t angle = R_PointToAngle2(BlockingMobj->x, + BlockingMobj->y, mo->x, mo->y) + ANGLE_1*((pr_bounce() % 16) - 8); + speed = P_AproxDistance(mo->velx, mo->vely); + speed = FixedMul(speed, mo->wallbouncefactor); // [GZ] was 0.75, using wallbouncefactor seems more consistent mo->angle = angle; angle >>= ANGLETOFINESHIFT; - mo->velx = FixedMul (speed, finecosine[angle]); - mo->vely = FixedMul (speed, finesine[angle]); + mo->velx = FixedMul(speed, finecosine[angle]); + mo->vely = FixedMul(speed, finesine[angle]); mo->PlayBounceSound(true); if (mo->BounceFlags & BOUNCE_UseBounceState) { FName names[] = { NAME_Bounce, NAME_Actor, NAME_Creature }; FState *bouncestate; int count = 2; - + if ((BlockingMobj->flags & MF_SHOOTABLE) && !(BlockingMobj->flags & MF_NOBLOOD)) { count = 3; @@ -2940,7 +2956,7 @@ bool P_BounceActor (AActor *mo, AActor *BlockingMobj, bool ontop) if (mo->BounceFlags & (BOUNCE_HereticType | BOUNCE_MBF)) { - mo->velz -= MulScale15 (FRACUNIT, dot); + mo->velz -= MulScale15(FRACUNIT, dot); if (!(mo->BounceFlags & BOUNCE_MBF)) // Heretic projectiles die, MBF projectiles don't. { mo->flags |= MF_INBOUNCE; @@ -2965,9 +2981,9 @@ bool P_BounceActor (AActor *mo, AActor *BlockingMobj, bool ontop) if (abs(mo->velz) < (fixed_t)(mo->Mass * mo->GetGravity() / 64)) mo->velz = 0; } - else if (mo->BounceFlags & (BOUNCE_AutoOff|BOUNCE_AutoOffFloorOnly)) + else if (mo->BounceFlags & (BOUNCE_AutoOff | BOUNCE_AutoOffFloorOnly)) { - if (!(mo->flags & MF_NOGRAVITY) && (mo->velz < 3*FRACUNIT)) + if (!(mo->flags & MF_NOGRAVITY) && (mo->velz < 3 * FRACUNIT)) mo->BounceFlags &= ~BOUNCE_TypeMask; } } @@ -2992,7 +3008,7 @@ struct aim_t fixed_t toppitch, bottompitch; AActor * linetarget; - AActor * thing_friend, * thing_other; + AActor * thing_friend, *thing_other; angle_t pitch_friend, pitch_other; int flags; #ifdef _3DFLOORS @@ -3005,7 +3021,7 @@ struct aim_t bool AimTraverse3DFloors(const divline_t &trace, intercept_t * in); #endif - void AimTraverse (fixed_t startx, fixed_t starty, fixed_t endx, fixed_t endy, AActor *target=NULL); + void AimTraverse(fixed_t startx, fixed_t starty, fixed_t endx, fixed_t endy, AActor *target = NULL); }; @@ -3018,100 +3034,100 @@ struct aim_t bool aim_t::AimTraverse3DFloors(const divline_t &trace, intercept_t * in) { sector_t * nextsector; - secplane_t * nexttopplane, * nextbottomplane; - line_t * li=in->d.line; + secplane_t * nexttopplane, *nextbottomplane; + line_t * li = in->d.line; - nextsector=NULL; - nexttopplane=nextbottomplane=NULL; + nextsector = NULL; + nexttopplane = nextbottomplane = NULL; if (li->backsector == NULL) return true; // shouldn't really happen but crashed once for me... - if (li->frontsector->e->XFloor.ffloors.Size() || li->backsector->e->XFloor.ffloors.Size()) - { + if (li->frontsector->e->XFloor.ffloors.Size() || li->backsector->e->XFloor.ffloors.Size()) + { int frontflag; F3DFloor* rover; int highpitch, lowpitch; - fixed_t trX = trace.x + FixedMul (trace.dx, in->frac); - fixed_t trY = trace.y + FixedMul (trace.dy, in->frac); - fixed_t dist = FixedMul (attackrange, in->frac); + fixed_t trX = trace.x + FixedMul(trace.dx, in->frac); + fixed_t trY = trace.y + FixedMul(trace.dy, in->frac); + fixed_t dist = FixedMul(attackrange, in->frac); + - int dir = aimpitch < 0 ? 1 : aimpitch > 0 ? -1 : 0; - + frontflag = P_PointOnLineSide(shootthing->x, shootthing->y, li); - + // 3D floor check. This is not 100% accurate but normally sufficient when // combined with a final sight check - for(int i=1;i<=2;i++) + for (int i = 1; i <= 2; i++) { - sector_t * s=i==1? li->frontsector:li->backsector; + sector_t * s = i == 1 ? li->frontsector : li->backsector; - for(unsigned k=0;ke->XFloor.ffloors.Size();k++) + for (unsigned k = 0; ke->XFloor.ffloors.Size(); k++) { - crossedffloors=true; - rover=s->e->XFloor.ffloors[k]; - - if((rover->flags & FF_SHOOTTHROUGH) || !(rover->flags & FF_EXISTS)) continue; - - fixed_t ff_bottom=rover->bottom.plane->ZatPoint(trX, trY); - fixed_t ff_top=rover->top.plane->ZatPoint(trX, trY); - + crossedffloors = true; + rover = s->e->XFloor.ffloors[k]; - highpitch = -(int)R_PointToAngle2 (0, shootz, dist, ff_top); - lowpitch = -(int)R_PointToAngle2 (0, shootz, dist, ff_bottom); + if ((rover->flags & FF_SHOOTTHROUGH) || !(rover->flags & FF_EXISTS)) continue; - if (highpitch<=toppitch) + fixed_t ff_bottom = rover->bottom.plane->ZatPoint(trX, trY); + fixed_t ff_top = rover->top.plane->ZatPoint(trX, trY); + + + highpitch = -(int)R_PointToAngle2(0, shootz, dist, ff_top); + lowpitch = -(int)R_PointToAngle2(0, shootz, dist, ff_bottom); + + if (highpitch <= toppitch) { // blocks completely - if (lowpitch>=bottompitch) return false; + if (lowpitch >= bottompitch) return false; // blocks upper edge of view - if (lowpitch>toppitch) + if (lowpitch>toppitch) { - toppitch=lowpitch; - if (frontflag!=i-1) + toppitch = lowpitch; + if (frontflag != i - 1) { - nexttopplane=rover->bottom.plane; + nexttopplane = rover->bottom.plane; } } } - else if (lowpitch>=bottompitch) + else if (lowpitch >= bottompitch) { // blocks lower edge of view - if (highpitchtop.plane; + nextbottomplane = rover->top.plane; } } } // trace is leaving a sector with a 3d-floor - if (frontflag==i-1) + if (frontflag == i - 1) { - if (s==lastsector) + if (s == lastsector) { // upper slope intersects with this 3d-floor - if (rover->bottom.plane==lastceilingplane && lowpitch > toppitch) + if (rover->bottom.plane == lastceilingplane && lowpitch > toppitch) { - toppitch=lowpitch; + toppitch = lowpitch; } // lower slope intersects with this 3d-floor - if (rover->top.plane==lastfloorplane && highpitch < bottompitch) + if (rover->top.plane == lastfloorplane && highpitch < bottompitch) { - bottompitch=highpitch; + bottompitch = highpitch; } } } if (toppitch >= bottompitch) return false; // stop } } - } + } - lastsector=nextsector; - lastceilingplane=nexttopplane; - lastfloorplane=nextbottomplane; + lastsector = nextsector; + lastceilingplane = nexttopplane; + lastfloorplane = nextbottomplane; return true; } #endif @@ -3123,9 +3139,9 @@ bool aim_t::AimTraverse3DFloors(const divline_t &trace, intercept_t * in) // //============================================================================ -void aim_t::AimTraverse (fixed_t startx, fixed_t starty, fixed_t endx, fixed_t endy, AActor *target) +void aim_t::AimTraverse(fixed_t startx, fixed_t starty, fixed_t endx, fixed_t endy, AActor *target) { - FPathTraverse it(startx, starty, endx, endy, PT_ADDLINES|PT_ADDTHINGS|PT_COMPATIBLE); + FPathTraverse it(startx, starty, endx, endy, PT_ADDLINES | PT_ADDTHINGS | PT_COMPATIBLE); intercept_t *in; while ((in = it.Next())) @@ -3138,35 +3154,35 @@ void aim_t::AimTraverse (fixed_t startx, fixed_t starty, fixed_t endx, fixed_t e fixed_t dist; int thingpitch; - if (in->isaline) + if (in->isaline) { li = in->d.line; - if ( !(li->flags & ML_TWOSIDED) || (li->flags & ML_BLOCKEVERYTHING) ) + if (!(li->flags & ML_TWOSIDED) || (li->flags & ML_BLOCKEVERYTHING)) return; // stop // Crosses a two sided line. // A two sided line will restrict the possible target ranges. FLineOpening open; - P_LineOpening (open, NULL, li, it.Trace().x + FixedMul (it.Trace().dx, in->frac), - it.Trace().y + FixedMul (it.Trace().dy, in->frac)); + P_LineOpening(open, NULL, li, it.Trace().x + FixedMul(it.Trace().dx, in->frac), + it.Trace().y + FixedMul(it.Trace().dy, in->frac)); if (open.bottom >= open.top) return; // stop - dist = FixedMul (attackrange, in->frac); + dist = FixedMul(attackrange, in->frac); - pitch = -(int)R_PointToAngle2 (0, shootz, dist, open.bottom); + pitch = -(int)R_PointToAngle2(0, shootz, dist, open.bottom); if (pitch < bottompitch) bottompitch = pitch; - pitch = -(int)R_PointToAngle2 (0, shootz, dist, open.top); + pitch = -(int)R_PointToAngle2(0, shootz, dist, open.top); if (pitch > toppitch) toppitch = pitch; if (toppitch >= bottompitch) return; // stop - + #ifdef _3DFLOORS if (!AimTraverse3DFloors(it.Trace(), in)) return; #endif @@ -3187,11 +3203,11 @@ void aim_t::AimTraverse (fixed_t startx, fixed_t starty, fixed_t endx, fixed_t e { if (!(flags & ALF_CHECKNONSHOOTABLE)) // For info CCMD, ignore stuff about GHOST and SHOOTABLE flags { - if (!(th->flags&MF_SHOOTABLE)) + if (!(th->flags&MF_SHOOTABLE)) continue; // corpse or something // check for physical attacks on a ghost - if ((th->flags3 & MF3_GHOST) && + if ((th->flags3 & MF3_GHOST) && shootthing->player && // [RH] Be sure shootthing is a player shootthing->player->ReadyWeapon && (shootthing->player->ReadyWeapon->flags2 & MF2_THRUGHOST)) @@ -3200,7 +3216,7 @@ void aim_t::AimTraverse (fixed_t startx, fixed_t starty, fixed_t endx, fixed_t e } } } - dist = FixedMul (attackrange, in->frac); + dist = FixedMul(attackrange, in->frac); // Don't autoaim certain special actors if (!cl_doautoaim && th->flags6 & MF6_NOTAUTOAIMED) @@ -3210,26 +3226,26 @@ void aim_t::AimTraverse (fixed_t startx, fixed_t starty, fixed_t endx, fixed_t e #ifdef _3DFLOORS // we must do one last check whether the trace has crossed a 3D floor - if (lastsector==th->Sector && th->Sector->e->XFloor.ffloors.Size()) + if (lastsector == th->Sector && th->Sector->e->XFloor.ffloors.Size()) { if (lastceilingplane) { - fixed_t ff_top=lastceilingplane->ZatPoint(th->x, th->y); - fixed_t pitch = -(int)R_PointToAngle2 (0, shootz, dist, ff_top); + fixed_t ff_top = lastceilingplane->ZatPoint(th->x, th->y); + fixed_t pitch = -(int)R_PointToAngle2(0, shootz, dist, ff_top); // upper slope intersects with this 3d-floor if (pitch > toppitch) { - toppitch=pitch; + toppitch = pitch; } } if (lastfloorplane) { - fixed_t ff_bottom=lastfloorplane->ZatPoint(th->x, th->y); - fixed_t pitch = -(int)R_PointToAngle2 (0, shootz, dist, ff_bottom); + fixed_t ff_bottom = lastfloorplane->ZatPoint(th->x, th->y); + fixed_t pitch = -(int)R_PointToAngle2(0, shootz, dist, ff_bottom); // lower slope intersects with this 3d-floor if (pitch < bottompitch) { - bottompitch=pitch; + bottompitch = pitch; } } } @@ -3237,30 +3253,30 @@ void aim_t::AimTraverse (fixed_t startx, fixed_t starty, fixed_t endx, fixed_t e // check angles to see if the thing can be aimed at - thingtoppitch = -(int)R_PointToAngle2 (0, shootz, dist, th->z + th->height); + thingtoppitch = -(int)R_PointToAngle2(0, shootz, dist, th->z + th->height); if (thingtoppitch > bottompitch) continue; // shot over the thing - thingbottompitch = -(int)R_PointToAngle2 (0, shootz, dist, th->z); + thingbottompitch = -(int)R_PointToAngle2(0, shootz, dist, th->z); if (thingbottompitch < toppitch) continue; // shot under the thing - + #ifdef _3DFLOORS if (crossedffloors) { // if 3D floors were in the way do an extra visibility check for safety - if (!P_CheckSight(shootthing, th, SF_IGNOREVISIBILITY|SF_IGNOREWATERBOUNDARY)) + if (!P_CheckSight(shootthing, th, SF_IGNOREVISIBILITY | SF_IGNOREWATERBOUNDARY)) { // the thing can't be seen so we can safely exclude its range from our aiming field - if (thingtoppitchtoppitch) toppitch=thingbottompitch; + if (thingbottompitch>toppitch) toppitch = thingbottompitch; } else if (thingbottompitch>bottompitch) { - if (thingtoppitch bottompitch) thingbottompitch = bottompitch; - - thingpitch = thingtoppitch/2 + thingbottompitch/2; - + + thingpitch = thingtoppitch / 2 + thingbottompitch / 2; + if (flags & ALF_CHECK3D) { // We need to do a 3D distance check here because this is nearly always used in @@ -3286,7 +3302,7 @@ void aim_t::AimTraverse (fixed_t startx, fixed_t starty, fixed_t endx, fixed_t e fixed_t cosine = finecosine[thingpitch >> ANGLETOFINESHIFT]; if (cosine != 0) { - fixed_t d3 = FixedDiv( FixedMul( P_AproxDistance(it.Trace().dx, it.Trace().dy), in->frac), cosine); + fixed_t d3 = FixedDiv(FixedMul(P_AproxDistance(it.Trace().dx, it.Trace().dy), in->frac), cosine); if (d3 > attackrange) { return; @@ -3342,8 +3358,8 @@ void aim_t::AimTraverse (fixed_t startx, fixed_t starty, fixed_t endx, fixed_t e // //============================================================================ -fixed_t P_AimLineAttack (AActor *t1, angle_t angle, fixed_t distance, AActor **pLineTarget, fixed_t vrange, - int flags, AActor *target, AActor *friender) +fixed_t P_AimLineAttack(AActor *t1, angle_t angle, fixed_t distance, AActor **pLineTarget, fixed_t vrange, + int flags, AActor *target, AActor *friender) { fixed_t x2; fixed_t y2; @@ -3354,16 +3370,16 @@ fixed_t P_AimLineAttack (AActor *t1, angle_t angle, fixed_t distance, AActor **p aim.shootthing = t1; aim.friender = (friender == NULL) ? t1 : friender; - x2 = t1->x + (distance>>FRACBITS)*finecosine[angle]; - y2 = t1->y + (distance>>FRACBITS)*finesine[angle]; - aim.shootz = t1->z + (t1->height>>1) - t1->floorclip; + x2 = t1->x + (distance >> FRACBITS)*finecosine[angle]; + y2 = t1->y + (distance >> FRACBITS)*finesine[angle]; + aim.shootz = t1->z + (t1->height >> 1) - t1->floorclip; if (t1->player != NULL) { - aim.shootz += FixedMul (t1->player->mo->AttackZOffset, t1->player->crouchfactor); + aim.shootz += FixedMul(t1->player->mo->AttackZOffset, t1->player->crouchfactor); } else { - aim.shootz += 8*FRACUNIT; + aim.shootz += 8 * FRACUNIT; } // can't shoot outside view angles @@ -3371,15 +3387,15 @@ fixed_t P_AimLineAttack (AActor *t1, angle_t angle, fixed_t distance, AActor **p { if (t1->player == NULL || !level.IsFreelookAllowed()) { - vrange = ANGLE_1*35; + vrange = ANGLE_1 * 35; } else { // [BB] Disable autoaim on weapons with WIF_NOAUTOAIM. AWeapon *weapon = t1->player->ReadyWeapon; - if ( weapon && (weapon->WeaponFlags & WIF_NOAUTOAIM) ) + if (weapon && (weapon->WeaponFlags & WIF_NOAUTOAIM)) { - vrange = ANGLE_1/2; + vrange = ANGLE_1 / 2; } else { @@ -3387,7 +3403,7 @@ fixed_t P_AimLineAttack (AActor *t1, angle_t angle, fixed_t distance, AActor **p // vrange of 0 degrees, because then toppitch and bottompitch will // be equal, and PTR_AimTraverse will never find anything to shoot at // if it crosses a line. - vrange = clamp (t1->player->userinfo.GetAimDist(), ANGLE_1/2, ANGLE_1*35); + vrange = clamp(t1->player->userinfo.GetAimDist(), ANGLE_1 / 2, ANGLE_1 * 35); } } } @@ -3398,32 +3414,32 @@ fixed_t P_AimLineAttack (AActor *t1, angle_t angle, fixed_t distance, AActor **p aim.linetarget = NULL; // for smart aiming - aim.thing_friend=aim.thing_other=NULL; + aim.thing_friend = aim.thing_other = NULL; // Information for tracking crossed 3D floors - aim.aimpitch=t1->pitch; + aim.aimpitch = t1->pitch; #ifdef _3DFLOORS - aim.crossedffloors=t1->Sector->e->XFloor.ffloors.Size()!=0; - aim.lastsector=t1->Sector; - aim.lastfloorplane=aim.lastceilingplane=NULL; + aim.crossedffloors = t1->Sector->e->XFloor.ffloors.Size() != 0; + aim.lastsector = t1->Sector; + aim.lastfloorplane = aim.lastceilingplane = NULL; // set initial 3d-floor info - for(unsigned i=0;iSector->e->XFloor.ffloors.Size();i++) + for (unsigned i = 0; iSector->e->XFloor.ffloors.Size(); i++) { - F3DFloor * rover=t1->Sector->e->XFloor.ffloors[i]; - fixed_t bottomz=rover->bottom.plane->ZatPoint(t1->x, t1->y); + F3DFloor * rover = t1->Sector->e->XFloor.ffloors[i]; + fixed_t bottomz = rover->bottom.plane->ZatPoint(t1->x, t1->y); - if (bottomz>=t1->z+t1->height) aim.lastceilingplane=rover->bottom.plane; + if (bottomz >= t1->z + t1->height) aim.lastceilingplane = rover->bottom.plane; - bottomz=rover->top.plane->ZatPoint(t1->x, t1->y); - if (bottomz<=t1->z) aim.lastfloorplane=rover->top.plane; + bottomz = rover->top.plane->ZatPoint(t1->x, t1->y); + if (bottomz <= t1->z) aim.lastfloorplane = rover->top.plane; } #endif - aim.AimTraverse (t1->x, t1->y, x2, y2, target); + aim.AimTraverse(t1->x, t1->y, x2, y2, target); - if (!aim.linetarget) + if (!aim.linetarget) { if (aim.thing_other) { @@ -3450,31 +3466,33 @@ fixed_t P_AimLineAttack (AActor *t1, angle_t angle, fixed_t distance, AActor **p // //========================================================================== -static ETraceStatus CheckForGhost (FTraceResults &res, void *userdata) +struct Origin +{ + AActor *Caller; + bool hitGhosts; + bool hitSameSpecies; +}; + +static ETraceStatus CheckForActor(FTraceResults &res, void *userdata) { if (res.HitType != TRACE_HitActor) { return TRACE_Stop; } - // check for physical attacks on a ghost - if (res.Actor->flags3 & MF3_GHOST || res.Actor->flags4 & MF4_SPECTRAL) + Origin *data = (Origin *)userdata; + + // check for physical attacks on spectrals + if (res.Actor->flags4 & MF4_SPECTRAL) { return TRACE_Skip; } - return TRACE_Stop; -} - -static ETraceStatus CheckForSpectral (FTraceResults &res, void *userdata) -{ - if (res.HitType != TRACE_HitActor) + if (data->hitSameSpecies && res.Actor->GetSpecies() == data->Caller->GetSpecies()) { - return TRACE_Stop; + return TRACE_Skip; } - - // check for physical attacks on spectrals - if (res.Actor->flags4 & MF4_SPECTRAL) + if (data->hitGhosts && res.Actor->flags3 & MF3_GHOST) { return TRACE_Skip; } @@ -3490,18 +3508,19 @@ static ETraceStatus CheckForSpectral (FTraceResults &res, void *userdata) // //========================================================================== -AActor *P_LineAttack (AActor *t1, angle_t angle, fixed_t distance, - int pitch, int damage, FName damageType, PClassActor *pufftype, int flags, AActor **victim, int *actualdamage) +AActor *P_LineAttack(AActor *t1, angle_t angle, fixed_t distance, + int pitch, int damage, FName damageType, PClassActor *pufftype, int flags, AActor **victim, int *actualdamage) { fixed_t vx, vy, vz, shootz; FTraceResults trace; + Origin TData; + TData.Caller = t1; angle_t srcangle = angle; int srcpitch = pitch; - bool hitGhosts; bool killPuff = false; AActor *puff = NULL; int pflag = 0; - int puffFlags = (flags & LAF_ISMELEEATTACK)? PF_MELEERANGE : 0; + int puffFlags = (flags & LAF_ISMELEEATTACK) ? PF_MELEERANGE : 0; if (flags & LAF_NORANDOMPUFFZ) puffFlags |= PF_NORANDOMZ; @@ -3517,14 +3536,14 @@ AActor *P_LineAttack (AActor *t1, angle_t angle, fixed_t distance, angle >>= ANGLETOFINESHIFT; pitch = (angle_t)(pitch) >> ANGLETOFINESHIFT; - vx = FixedMul (finecosine[pitch], finecosine[angle]); - vy = FixedMul (finecosine[pitch], finesine[angle]); + vx = FixedMul(finecosine[pitch], finecosine[angle]); + vy = FixedMul(finecosine[pitch], finesine[angle]); vz = -finesine[pitch]; - shootz = t1->z - t1->floorclip + (t1->height>>1); + shootz = t1->z - t1->floorclip + (t1->height >> 1); if (t1->player != NULL) { - shootz += FixedMul (t1->player->mo->AttackZOffset, t1->player->crouchfactor); + shootz += FixedMul(t1->player->mo->AttackZOffset, t1->player->crouchfactor); if (damageType == NAME_Melee || damageType == NAME_Hitscan) { // this is coming from a weapon attack function which needs to transfer information to the obituary code, @@ -3534,17 +3553,19 @@ AActor *P_LineAttack (AActor *t1, angle_t angle, fixed_t distance, } else { - shootz += 8*FRACUNIT; + shootz += 8 * FRACUNIT; } // We need to check the defaults of the replacement here AActor *puffDefaults = GetDefaultByType(pufftype->GetReplacement()); - hitGhosts = (t1->player != NULL && + TData.hitGhosts = (t1->player != NULL && t1->player->ReadyWeapon != NULL && (t1->player->ReadyWeapon->flags2 & MF2_THRUGHOST)) || (puffDefaults && (puffDefaults->flags2 & MF2_THRUGHOST)); + TData.hitSameSpecies = (puffDefaults && (puffDefaults->flags6 & MF6_MTHRUSPECIES)); + // if the puff uses a non-standard damage type, this will override default, hitscan and melee damage type. // All other explicitly passed damage types (currenty only MDK) will be preserved. if ((damageType == NAME_None || damageType == NAME_Melee || damageType == NAME_Hitscan) && @@ -3555,22 +3576,22 @@ AActor *P_LineAttack (AActor *t1, angle_t angle, fixed_t distance, int tflags; if (puffDefaults != NULL && puffDefaults->flags6 & MF6_NOTRIGGER) tflags = TRACE_NoSky; - else tflags = TRACE_NoSky|TRACE_Impact; + else tflags = TRACE_NoSky | TRACE_Impact; - if (!Trace (t1->x, t1->y, shootz, t1->Sector, vx, vy, vz, distance, - MF_SHOOTABLE, ML_BLOCKEVERYTHING|ML_BLOCKHITSCAN, t1, trace, - tflags, hitGhosts ? CheckForGhost : CheckForSpectral)) + if (!Trace(t1->x, t1->y, shootz, t1->Sector, vx, vy, vz, distance, + MF_SHOOTABLE, ML_BLOCKEVERYTHING | ML_BLOCKHITSCAN, t1, trace, + tflags, CheckForActor, &TData)) { // hit nothing if (puffDefaults == NULL) { } else if (puffDefaults->ActiveSound) { // Play miss sound - S_Sound (t1, CHAN_WEAPON, puffDefaults->ActiveSound, 1, ATTN_NORM); + S_Sound(t1, CHAN_WEAPON, puffDefaults->ActiveSound, 1, ATTN_NORM); } if (puffDefaults != NULL && puffDefaults->flags3 & MF3_ALWAYSPUFF) { // Spawn the puff anyway - puff = P_SpawnPuff (t1, pufftype, trace.X, trace.Y, trace.Z, angle - ANG180, 2, puffFlags); + puff = P_SpawnPuff(t1, pufftype, trace.X, trace.Y, trace.Z, angle - ANG180, 2, puffFlags); } else { @@ -3586,32 +3607,32 @@ AActor *P_LineAttack (AActor *t1, angle_t angle, fixed_t distance, // position a bit closer for puffs if (trace.HitType != TRACE_HitWall || trace.Line->special != Line_Horizon) { - fixed_t closer = trace.Distance - 4*FRACUNIT; - puff = P_SpawnPuff (t1, pufftype, t1->x + FixedMul (vx, closer), - t1->y + FixedMul (vy, closer), - shootz + FixedMul (vz, closer), angle - ANG90, 0, puffFlags); + fixed_t closer = trace.Distance - 4 * FRACUNIT; + puff = P_SpawnPuff(t1, pufftype, t1->x + FixedMul(vx, closer), + t1->y + FixedMul(vy, closer), + shootz + FixedMul(vz, closer), angle - ANG90, 0, puffFlags); } // [RH] Spawn a decal if (trace.HitType == TRACE_HitWall && trace.Line->special != Line_Horizon) - { + { // [TN] If the actor or weapon has a decal defined, use that one. - if(t1->DecalGenerator != NULL || + if (t1->DecalGenerator != NULL || (t1->player != NULL && t1->player->ReadyWeapon != NULL && t1->player->ReadyWeapon->DecalGenerator != NULL)) { - SpawnShootDecal (t1, trace); + SpawnShootDecal(t1, trace); } // Else, look if the bulletpuff has a decal defined. - else if(puff != NULL && puff->DecalGenerator) + else if (puff != NULL && puff->DecalGenerator) { - SpawnShootDecal (puff, trace); - } - + SpawnShootDecal(puff, trace); + } + else { - SpawnShootDecal (t1, trace); - } + SpawnShootDecal(t1, trace); + } } else if (puff != NULL && trace.CrossedWater == NULL && @@ -3620,17 +3641,17 @@ AActor *P_LineAttack (AActor *t1, angle_t angle, fixed_t distance, { // Using the puff's position is not accurate enough. // Instead make it splash at the actual hit position - hitx = t1->x + FixedMul (vx, trace.Distance); - hity = t1->y + FixedMul (vy, trace.Distance); - hitz = shootz + FixedMul (vz, trace.Distance); - P_HitWater (puff, P_PointInSector(hitx, hity), hitx, hity, hitz); + hitx = t1->x + FixedMul(vx, trace.Distance); + hity = t1->y + FixedMul(vy, trace.Distance); + hitz = shootz + FixedMul(vz, trace.Distance); + P_HitWater(puff, P_PointInSector(hitx, hity), hitx, hity, hitz); } } else { bool bloodsplatter = (t1->flags5 & MF5_BLOODSPLATTER) || - (t1->player != NULL && t1->player->ReadyWeapon != NULL && - (t1->player->ReadyWeapon->WeaponFlags & WIF_AXEBLOOD)); + (t1->player != NULL && t1->player->ReadyWeapon != NULL && + (t1->player->ReadyWeapon->WeaponFlags & WIF_AXEBLOOD)); bool axeBlood = (t1->player != NULL && t1->player->ReadyWeapon != NULL && @@ -3639,21 +3660,21 @@ AActor *P_LineAttack (AActor *t1, angle_t angle, fixed_t distance, // Hit a thing, so it could be either a puff or blood fixed_t dist = trace.Distance; // position a bit closer for puffs/blood if using compatibility mode. - if (i_compatflags & COMPATF_HITSCAN) dist -= 10*FRACUNIT; - hitx = t1->x + FixedMul (vx, dist); - hity = t1->y + FixedMul (vy, dist); - hitz = shootz + FixedMul (vz, dist); + if (i_compatflags & COMPATF_HITSCAN) dist -= 10 * FRACUNIT; + hitx = t1->x + FixedMul(vx, dist); + hity = t1->y + FixedMul(vy, dist); + hitz = shootz + FixedMul(vz, dist); // Spawn bullet puffs or blood spots, depending on target type. if ((puffDefaults != NULL && puffDefaults->flags3 & MF3_PUFFONACTORS) || (trace.Actor->flags & MF_NOBLOOD) || - (trace.Actor->flags2 & (MF2_INVULNERABLE|MF2_DORMANT))) + (trace.Actor->flags2 & (MF2_INVULNERABLE | MF2_DORMANT))) { if (!(trace.Actor->flags & MF_NOBLOOD)) puffFlags |= PF_HITTHINGBLEED; // We must pass the unreplaced puff type here - puff = P_SpawnPuff (t1, pufftype, hitx, hity, hitz, angle - ANG180, 2, puffFlags|PF_HITTHING); + puff = P_SpawnPuff(t1, pufftype, hitx, hity, hitz, angle - ANG180, 2, puffFlags | PF_HITTHING); } // Allow puffs to inflict poison damage, so that hitscans can poison, too. @@ -3674,15 +3695,15 @@ AActor *P_LineAttack (AActor *t1, angle_t angle, fixed_t distance, { dmgflags |= DMG_NO_ARMOR; } - + if (puff == NULL) - { + { // Since the puff is the damage inflictor we need it here // regardless of whether it is displayed or not. - puff = P_SpawnPuff (t1, pufftype, hitx, hity, hitz, angle - ANG180, 2, puffFlags|PF_HITTHING|PF_TEMPORARY); + puff = P_SpawnPuff(t1, pufftype, hitx, hity, hitz, angle - ANG180, 2, puffFlags | PF_HITTHING | PF_TEMPORARY); killPuff = true; } - newdam = P_DamageMobj (trace.Actor, puff ? puff : t1, t1, damage, damageType, dmgflags); + newdam = P_DamageMobj(trace.Actor, puff ? puff : t1, t1, damage, damageType, dmgflags); if (actualdamage != NULL) { *actualdamage = newdam; @@ -3692,30 +3713,30 @@ AActor *P_LineAttack (AActor *t1, angle_t angle, fixed_t distance, { if (!bloodsplatter && !axeBlood && !(trace.Actor->flags & MF_NOBLOOD) && - !(trace.Actor->flags2 & (MF2_INVULNERABLE|MF2_DORMANT))) + !(trace.Actor->flags2 & (MF2_INVULNERABLE | MF2_DORMANT))) { - P_SpawnBlood (hitx, hity, hitz, angle - ANG180, newdam > 0 ? newdam : damage, trace.Actor); + P_SpawnBlood(hitx, hity, hitz, angle - ANG180, newdam > 0 ? newdam : damage, trace.Actor); } - + if (damage) { if (bloodsplatter || axeBlood) { if (!(trace.Actor->flags&MF_NOBLOOD) && - !(trace.Actor->flags2&(MF2_INVULNERABLE|MF2_DORMANT))) + !(trace.Actor->flags2&(MF2_INVULNERABLE | MF2_DORMANT))) { if (axeBlood) { - P_BloodSplatter2 (hitx, hity, hitz, trace.Actor); + P_BloodSplatter2(hitx, hity, hitz, trace.Actor); } if (pr_lineattack() < 192) { - P_BloodSplatter (hitx, hity, hitz, trace.Actor); + P_BloodSplatter(hitx, hity, hitz, trace.Actor); } } } // [RH] Stick blood to walls - P_TraceBleed (newdam > 0 ? newdam : damage, trace.X, trace.Y, trace.Z, + P_TraceBleed(newdam > 0 ? newdam : damage, trace.X, trace.Y, trace.Z, trace.Actor, srcangle, srcpitch); } } @@ -3729,10 +3750,10 @@ AActor *P_LineAttack (AActor *t1, angle_t angle, fixed_t distance, if (puff == NULL) { // Spawn puff just to get a mass for the splash - puff = P_SpawnPuff (t1, pufftype, hitx, hity, hitz, angle - ANG180, 2, puffFlags|PF_HITTHING|PF_TEMPORARY); + puff = P_SpawnPuff(t1, pufftype, hitx, hity, hitz, angle - ANG180, 2, puffFlags | PF_HITTHING | PF_TEMPORARY); killPuff = true; } - SpawnDeepSplash (t1, trace, puff, vx, vy, vz, shootz, trace.Crossed3DWater != NULL); + SpawnDeepSplash(t1, trace, puff, vx, vy, vz, shootz, trace.Crossed3DWater != NULL); } } if (killPuff && puff != NULL) @@ -3743,8 +3764,8 @@ AActor *P_LineAttack (AActor *t1, angle_t angle, fixed_t distance, return puff; } -AActor *P_LineAttack (AActor *t1, angle_t angle, fixed_t distance, - int pitch, int damage, FName damageType, FName pufftype, int flags, AActor **victim, int *actualdamage) +AActor *P_LineAttack(AActor *t1, angle_t angle, fixed_t distance, + int pitch, int damage, FName damageType, FName pufftype, int flags, AActor **victim, int *actualdamage) { PClassActor *type = PClass::FindActor(pufftype); if (victim != NULL) @@ -3768,7 +3789,7 @@ AActor *P_LineAttack (AActor *t1, angle_t angle, fixed_t distance, // //========================================================================== -void P_TraceBleed (int damage, fixed_t x, fixed_t y, fixed_t z, AActor *actor, angle_t angle, int pitch) +void P_TraceBleed(int damage, fixed_t x, fixed_t y, fixed_t z, AActor *actor, angle_t angle, int pitch) { if (!cl_bloodsplats) return; @@ -3780,7 +3801,7 @@ void P_TraceBleed (int damage, fixed_t x, fixed_t y, fixed_t z, AActor *actor, a if ((actor->flags & MF_NOBLOOD) || (actor->flags5 & MF5_NOBLOODDECALS) || - (actor->flags2 & (MF2_INVULNERABLE|MF2_DORMANT)) || + (actor->flags2 & (MF2_INVULNERABLE | MF2_DORMANT)) || (actor->player && actor->player->cheats & CF_GODMODE)) { return; @@ -3821,28 +3842,28 @@ void P_TraceBleed (int damage, fixed_t x, fixed_t y, fixed_t z, AActor *actor, a { FTraceResults bleedtrace; - angle_t bleedang = (angle + ((pr_tracebleed()-128) << noise)) >> ANGLETOFINESHIFT; - angle_t bleedpitch = (angle_t)(pitch + ((pr_tracebleed()-128) << noise)) >> ANGLETOFINESHIFT; - fixed_t vx = FixedMul (finecosine[bleedpitch], finecosine[bleedang]); - fixed_t vy = FixedMul (finecosine[bleedpitch], finesine[bleedang]); + angle_t bleedang = (angle + ((pr_tracebleed() - 128) << noise)) >> ANGLETOFINESHIFT; + angle_t bleedpitch = (angle_t)(pitch + ((pr_tracebleed() - 128) << noise)) >> ANGLETOFINESHIFT; + fixed_t vx = FixedMul(finecosine[bleedpitch], finecosine[bleedang]); + fixed_t vy = FixedMul(finecosine[bleedpitch], finesine[bleedang]); fixed_t vz = -finesine[bleedpitch]; - if (Trace (x, y, z, actor->Sector, - vx, vy, vz, 172*FRACUNIT, 0, ML_BLOCKEVERYTHING, actor, - bleedtrace, TRACE_NoSky)) + if (Trace(x, y, z, actor->Sector, + vx, vy, vz, 172 * FRACUNIT, 0, ML_BLOCKEVERYTHING, actor, + bleedtrace, TRACE_NoSky)) { if (bleedtrace.HitType == TRACE_HitWall) { PalEntry bloodcolor = actor->GetBloodColor(); if (bloodcolor != 0) { - bloodcolor.r>>=1; // the full color is too bright for blood decals - bloodcolor.g>>=1; - bloodcolor.b>>=1; - bloodcolor.a=1; + bloodcolor.r >>= 1; // the full color is too bright for blood decals + bloodcolor.g >>= 1; + bloodcolor.b >>= 1; + bloodcolor.a = 1; } - DImpactDecal::StaticCreate (bloodType, + DImpactDecal::StaticCreate(bloodType, bleedtrace.X, bleedtrace.Y, bleedtrace.Z, bleedtrace.Line->sidedef[bleedtrace.Side], bleedtrace.ffloor, @@ -3852,9 +3873,9 @@ void P_TraceBleed (int damage, fixed_t x, fixed_t y, fixed_t z, AActor *actor, a } } -void P_TraceBleed (int damage, AActor *target, angle_t angle, int pitch) +void P_TraceBleed(int damage, AActor *target, angle_t angle, int pitch) { - P_TraceBleed (damage, target->x, target->y, target->z + target->height/2, + P_TraceBleed(damage, target->x, target->y, target->z + target->height / 2, target, angle, pitch); } @@ -3864,7 +3885,7 @@ void P_TraceBleed (int damage, AActor *target, angle_t angle, int pitch) // //========================================================================== -void P_TraceBleed (int damage, AActor *target, AActor *missile) +void P_TraceBleed(int damage, AActor *target, AActor *missile) { int pitch; @@ -3877,15 +3898,15 @@ void P_TraceBleed (int damage, AActor *target, AActor *missile) { double aim; - aim = atan ((double)missile->velz / (double)P_AproxDistance (missile->x - target->x, missile->y - target->y)); - pitch = -(int)(aim * ANGLE_180/PI); + aim = atan((double)missile->velz / (double)P_AproxDistance(missile->x - target->x, missile->y - target->y)); + pitch = -(int)(aim * ANGLE_180 / PI); } else { pitch = 0; } - P_TraceBleed (damage, target->x, target->y, target->z + target->height/2, - target, R_PointToAngle2 (missile->x, missile->y, target->x, target->y), + P_TraceBleed(damage, target->x, target->y, target->z + target->height / 2, + target, R_PointToAngle2(missile->x, missile->y, target->x, target->y), pitch); } @@ -3895,14 +3916,14 @@ void P_TraceBleed (int damage, AActor *target, AActor *missile) // //========================================================================== -void P_TraceBleed (int damage, AActor *target) +void P_TraceBleed(int damage, AActor *target) { if (target != NULL) { fixed_t one = pr_tracebleed() << 24; - fixed_t two = (pr_tracebleed()-128) << 16; + fixed_t two = (pr_tracebleed() - 128) << 16; - P_TraceBleed (damage, target->x, target->y, target->z + target->height/2, + P_TraceBleed(damage, target->x, target->y, target->z + target->height / 2, target, one, two); } } @@ -3925,7 +3946,7 @@ struct RailData bool StopAtInvul; }; -static ETraceStatus ProcessRailHit (FTraceResults &res, void *userdata) +static ETraceStatus ProcessRailHit(FTraceResults &res, void *userdata) { RailData *data = (RailData *)userdata; if (res.HitType != TRACE_HitActor) @@ -3942,8 +3963,8 @@ static ETraceStatus ProcessRailHit (FTraceResults &res, void *userdata) // Save this thing for damaging later, and continue the trace SRailHit newhit; newhit.HitActor = res.Actor; - newhit.Distance = res.Distance - 10*FRACUNIT; // put blood in front - data->RailHits.Push (newhit); + newhit.Distance = res.Distance - 10 * FRACUNIT; // put blood in front + data->RailHits.Push(newhit); return data->StopAtOne ? TRACE_Stop : TRACE_Continue; } @@ -3953,7 +3974,7 @@ static ETraceStatus ProcessRailHit (FTraceResults &res, void *userdata) // // //========================================================================== -void P_RailAttack (AActor *source, int damage, int offset_xy, fixed_t offset_z, int color1, int color2, double maxdiff, int railflags, PClassActor *puffclass, angle_t angleoffset, angle_t pitchoffset, fixed_t distance, int duration, double sparsity, double drift, PClassActor *spawnclass) +void P_RailAttack(AActor *source, int damage, int offset_xy, fixed_t offset_z, int color1, int color2, double maxdiff, int railflags, PClassActor *puffclass, angle_t angleoffset, angle_t pitchoffset, fixed_t distance, int duration, double sparsity, double drift, PClassActor *spawnclass) { fixed_t vx, vy, vz; angle_t angle, pitch; @@ -3970,8 +3991,8 @@ void P_RailAttack (AActor *source, int damage, int offset_xy, fixed_t offset_z, pitch = ((angle_t)(-source->pitch) + pitchoffset) >> ANGLETOFINESHIFT; angle = (source->angle + angleoffset) >> ANGLETOFINESHIFT; - vx = FixedMul (finecosine[pitch], finecosine[angle]); - vy = FixedMul (finecosine[pitch], finesine[angle]); + vx = FixedMul(finecosine[pitch], finecosine[angle]); + vy = FixedMul(finecosine[pitch], finesine[angle]); vz = finesine[pitch]; x1 = source->x; @@ -3983,11 +4004,11 @@ void P_RailAttack (AActor *source, int damage, int offset_xy, fixed_t offset_z, { if (source->player != NULL) { - shootz += FixedMul (source->player->mo->AttackZOffset, source->player->crouchfactor); + shootz += FixedMul(source->player->mo->AttackZOffset, source->player->crouchfactor); } else { - shootz += 8*FRACUNIT; + shootz += 8 * FRACUNIT; } } @@ -4005,12 +4026,12 @@ void P_RailAttack (AActor *source, int damage, int offset_xy, fixed_t offset_z, int flags; assert(puffclass != NULL); // Because we set it to a default above - AActor *puffDefaults = GetDefaultByType (puffclass->GetReplacement()); + AActor *puffDefaults = GetDefaultByType(puffclass->GetReplacement()); - flags = (puffDefaults->flags6 & MF6_NOTRIGGER) ? 0 : TRACE_PCross|TRACE_Impact; + flags = (puffDefaults->flags6 & MF6_NOTRIGGER) ? 0 : TRACE_PCross | TRACE_Impact; rail_data.StopAtInvul = (puffDefaults->flags3 & MF3_FOILINVUL) ? false : true; - Trace (x1, y1, shootz, source->Sector, vx, vy, vz, + Trace(x1, y1, shootz, source->Sector, vx, vy, vz, distance, MF_SHOOTABLE, ML_BLOCKEVERYTHING, source, trace, flags, ProcessRailHit, &rail_data); @@ -4020,10 +4041,10 @@ void P_RailAttack (AActor *source, int damage, int offset_xy, fixed_t offset_z, // used as damage inflictor AActor *thepuff = NULL; - - if (puffclass != NULL) thepuff = Spawn (puffclass, source->x, source->y, source->z, ALLOW_REPLACE); - for (i = 0; i < rail_data.RailHits.Size (); i++) + if (puffclass != NULL) thepuff = Spawn(puffclass, source->x, source->y, source->z, ALLOW_REPLACE); + + for (i = 0; i < rail_data.RailHits.Size(); i++) { fixed_t x, y, z; bool spawnpuff; @@ -4038,7 +4059,7 @@ void P_RailAttack (AActor *source, int damage, int offset_xy, fixed_t offset_z, z = shootz + FixedMul(hitdist, vz); if ((hitactor->flags & MF_NOBLOOD) || - (hitactor->flags2 & (MF2_DORMANT|MF2_INVULNERABLE))) + (hitactor->flags2 & (MF2_DORMANT | MF2_INVULNERABLE))) { spawnpuff = (puffclass != NULL); } @@ -4046,7 +4067,7 @@ void P_RailAttack (AActor *source, int damage, int offset_xy, fixed_t offset_z, { spawnpuff = (puffclass != NULL && puffDefaults->flags3 & MF3_ALWAYSPUFF); puffflags |= PF_HITTHINGBLEED; // [XA] Allow for puffs to jump to XDeath state. - if (!(puffDefaults->flags3 & MF3_BLOODLESSIMPACT)) + if (!(puffDefaults->flags3 & MF3_BLOODLESSIMPACT)) { bleed = true; } @@ -4059,7 +4080,7 @@ void P_RailAttack (AActor *source, int damage, int offset_xy, fixed_t offset_z, { P_PoisonMobj(hitactor, thepuff ? thepuff : source, source, puffDefaults->PoisonDamage, puffDefaults->PoisonDuration, puffDefaults->PoisonPeriod, puffDefaults->PoisonDamageType); } - int newdam = P_DamageMobj(hitactor, thepuff? thepuff:source, source, damage, damagetype, DMG_INFLICTOR_IS_PUFF); + int newdam = P_DamageMobj(hitactor, thepuff ? thepuff : source, source, damage, damagetype, DMG_INFLICTOR_IS_PUFF); if (bleed) { P_SpawnBlood(x, y, z, (source->angle + angleoffset) - ANG180, newdam > 0 ? newdam : damage, hitactor); @@ -4070,34 +4091,34 @@ void P_RailAttack (AActor *source, int damage, int offset_xy, fixed_t offset_z, // Spawn a decal or puff at the point where the trace ended. if (trace.HitType == TRACE_HitWall) { - SpawnShootDecal (source, trace); - if (puffclass != NULL && puffDefaults->flags3 & MF3_ALWAYSPUFF) + SpawnShootDecal(source, trace); + if (puffclass != NULL && puffDefaults->flags3 & MF3_ALWAYSPUFF) { - P_SpawnPuff (source, puffclass, trace.X, trace.Y, trace.Z, (source->angle + angleoffset) - ANG90, 1, 0); + P_SpawnPuff(source, puffclass, trace.X, trace.Y, trace.Z, (source->angle + angleoffset) - ANG90, 1, 0); } } - if(thepuff != NULL) + if (thepuff != NULL) { if (trace.HitType == TRACE_HitFloor && trace.CrossedWater == NULL && trace.Sector->heightsec == NULL) { thepuff->SetOrigin(trace.X, trace.Y, trace.Z); - P_HitWater (thepuff, trace.Sector); + P_HitWater(thepuff, trace.Sector); } if (trace.Crossed3DWater || trace.CrossedWater) { - SpawnDeepSplash (source, trace, thepuff, vx, vy, vz, shootz, trace.Crossed3DWater != NULL); + SpawnDeepSplash(source, trace, thepuff, vx, vy, vz, shootz, trace.Crossed3DWater != NULL); } - thepuff->Destroy (); + thepuff->Destroy(); } // Draw the slug's trail. end.X = FIXED2FLOAT(trace.X); end.Y = FIXED2FLOAT(trace.Y); end.Z = FIXED2FLOAT(trace.Z); - P_DrawRailTrail (source, start, end, color1, color2, maxdiff, railflags, spawnclass, source->angle + angleoffset, duration, sparsity, drift); + P_DrawRailTrail(source, start, end, color1, color2, maxdiff, railflags, spawnclass, source->angle + angleoffset, duration, sparsity, drift); } //========================================================================== @@ -4106,10 +4127,10 @@ void P_RailAttack (AActor *source, int damage, int offset_xy, fixed_t offset_z, // //========================================================================== -CVAR (Float, chase_height, -8.f, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) -CVAR (Float, chase_dist, 90.f, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) +CVAR(Float, chase_height, -8.f, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) +CVAR(Float, chase_dist, 90.f, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) -void P_AimCamera (AActor *t1, fixed_t &CameraX, fixed_t &CameraY, fixed_t &CameraZ, sector_t *&CameraSector) +void P_AimCamera(AActor *t1, fixed_t &CameraX, fixed_t &CameraY, fixed_t &CameraZ, sector_t *&CameraSector) { fixed_t distance = (fixed_t)(chase_dist * FRACUNIT); angle_t angle = (t1->angle - ANG180) >> ANGLETOFINESHIFT; @@ -4117,21 +4138,21 @@ void P_AimCamera (AActor *t1, fixed_t &CameraX, fixed_t &CameraY, fixed_t &Camer FTraceResults trace; fixed_t vx, vy, vz, sz; - vx = FixedMul (finecosine[pitch], finecosine[angle]); - vy = FixedMul (finecosine[pitch], finesine[angle]); + vx = FixedMul(finecosine[pitch], finecosine[angle]); + vy = FixedMul(finecosine[pitch], finesine[angle]); vz = finesine[pitch]; sz = t1->z - t1->floorclip + t1->height + (fixed_t)(chase_height * FRACUNIT); - if (Trace (t1->x, t1->y, sz, t1->Sector, + if (Trace(t1->x, t1->y, sz, t1->Sector, vx, vy, vz, distance, 0, 0, NULL, trace) && - trace.Distance > 10*FRACUNIT) + trace.Distance > 10 * FRACUNIT) { // Position camera slightly in front of hit thing - fixed_t dist = trace.Distance - 5*FRACUNIT; - CameraX = t1->x + FixedMul (vx, dist); - CameraY = t1->y + FixedMul (vy, dist); - CameraZ = sz + FixedMul (vz, dist); + fixed_t dist = trace.Distance - 5 * FRACUNIT; + CameraX = t1->x + FixedMul(vx, dist); + CameraY = t1->y + FixedMul(vy, dist); + CameraZ = sz + FixedMul(vz, dist); } else { @@ -4156,13 +4177,13 @@ bool P_TalkFacing(AActor *player) { AActor *linetarget; - P_AimLineAttack(player, player->angle, TALKRANGE, &linetarget, ANGLE_1*35, ALF_FORCENOSMART|ALF_CHECKCONVERSATION); + P_AimLineAttack(player, player->angle, TALKRANGE, &linetarget, ANGLE_1 * 35, ALF_FORCENOSMART | ALF_CHECKCONVERSATION); if (linetarget == NULL) { - P_AimLineAttack(player, player->angle + (ANGLE_90 >> 4), TALKRANGE, &linetarget, ANGLE_1*35, ALF_FORCENOSMART|ALF_CHECKCONVERSATION); + P_AimLineAttack(player, player->angle + (ANGLE_90 >> 4), TALKRANGE, &linetarget, ANGLE_1 * 35, ALF_FORCENOSMART | ALF_CHECKCONVERSATION); if (linetarget == NULL) { - P_AimLineAttack(player, player->angle - (ANGLE_90 >> 4), TALKRANGE, &linetarget, ANGLE_1*35, ALF_FORCENOSMART|ALF_CHECKCONVERSATION); + P_AimLineAttack(player, player->angle - (ANGLE_90 >> 4), TALKRANGE, &linetarget, ANGLE_1 * 35, ALF_FORCENOSMART | ALF_CHECKCONVERSATION); if (linetarget == NULL) { return false; @@ -4182,8 +4203,8 @@ bool P_TalkFacing(AActor *player) if (linetarget->Conversation != NULL) { // Give the NPC a chance to play a brief animation - linetarget->ConversationAnimation (0); - P_StartConversation (linetarget, player, true, true); + linetarget->ConversationAnimation(0); + P_StartConversation(linetarget, player, true, true); return true; } return false; @@ -4197,7 +4218,7 @@ bool P_TalkFacing(AActor *player) bool P_UseTraverse(AActor *usething, fixed_t endx, fixed_t endy, bool &foundline) { - FPathTraverse it(usething->x, usething->y, endx, endy, PT_ADDLINES|PT_ADDTHINGS); + FPathTraverse it(usething->x, usething->y, endx, endy, PT_ADDLINES | PT_ADDTHINGS); intercept_t *in; while ((in = it.Next())) @@ -4220,17 +4241,17 @@ bool P_UseTraverse(AActor *usething, fixed_t endx, fixed_t endy, bool &foundline } FLineOpening open; - if (in->d.line->special == 0 || !(in->d.line->activation & (SPAC_Use|SPAC_UseThrough|SPAC_UseBack))) + if (in->d.line->special == 0 || !(in->d.line->activation & (SPAC_Use | SPAC_UseThrough | SPAC_UseBack))) { - blocked: - if (in->d.line->flags & (ML_BLOCKEVERYTHING|ML_BLOCKUSE)) + blocked: + if (in->d.line->flags & (ML_BLOCKEVERYTHING | ML_BLOCKUSE)) { open.range = 0; } else { - P_LineOpening (open, NULL, in->d.line, it.Trace().x + FixedMul (it.Trace().dx, in->frac), - it.Trace().y + FixedMul (it.Trace().dy, in->frac)); + P_LineOpening(open, NULL, in->d.line, it.Trace().x + FixedMul(it.Trace().dx, in->frac), + it.Trace().y + FixedMul(it.Trace().dy, in->frac)); } if (open.range <= 0 || (in->d.line->special != 0 && (i_compatflags & COMPATF_USEBLOCKING))) @@ -4241,31 +4262,31 @@ bool P_UseTraverse(AActor *usething, fixed_t endx, fixed_t endy, bool &foundline sec = usething->Sector; - if (sec->SecActTarget && sec->SecActTarget->TriggerAction (usething, SECSPAC_Use)) + if (sec->SecActTarget && sec->SecActTarget->TriggerAction(usething, SECSPAC_Use)) { return true; } - sec = P_PointOnLineSide(usething->x, usething->y, in->d.line) == 0? + sec = P_PointOnLineSide(usething->x, usething->y, in->d.line) == 0 ? in->d.line->frontsector : in->d.line->backsector; if (sec != NULL && sec->SecActTarget && - sec->SecActTarget->TriggerAction (usething, SECSPAC_UseWall)) + sec->SecActTarget->TriggerAction(usething, SECSPAC_UseWall)) { return true; } if (usething->player) { - S_Sound (usething, CHAN_VOICE, "*usefail", 1, ATTN_IDLE); + S_Sound(usething, CHAN_VOICE, "*usefail", 1, ATTN_IDLE); } return true; // can't use through a wall } foundline = true; continue; // not a special line, but keep checking } - - if (P_PointOnLineSide (usething->x, usething->y, in->d.line) == 1) + + if (P_PointOnLineSide(usething->x, usething->y, in->d.line) == 1) { if (!(in->d.line->activation & SPAC_UseBack)) { @@ -4275,18 +4296,18 @@ bool P_UseTraverse(AActor *usething, fixed_t endx, fixed_t endy, bool &foundline } else { - P_ActivateLine (in->d.line, usething, 1, SPAC_UseBack); + P_ActivateLine(in->d.line, usething, 1, SPAC_UseBack); return true; } } - else + else { - if ((in->d.line->activation & (SPAC_Use|SPAC_UseThrough|SPAC_UseBack)) == SPAC_UseBack) + if ((in->d.line->activation & (SPAC_Use | SPAC_UseThrough | SPAC_UseBack)) == SPAC_UseBack) { goto blocked; // Line cannot be used from front side so treat it as a non-trigger line } - P_ActivateLine (in->d.line, usething, 0, SPAC_Use); + P_ActivateLine(in->d.line, usething, 0, SPAC_Use); //WAS can't use more than one special line in a row //jff 3/21/98 NOW multiple use allowed with enabling line flag @@ -4323,7 +4344,7 @@ bool P_UseTraverse(AActor *usething, fixed_t endx, fixed_t endy, bool &foundline // //========================================================================== -bool P_NoWayTraverse (AActor *usething, fixed_t endx, fixed_t endy) +bool P_NoWayTraverse(AActor *usething, fixed_t endx, fixed_t endy) { FPathTraverse it(usething->x, usething->y, endx, endy, PT_ADDLINES); intercept_t *in; @@ -4336,9 +4357,9 @@ bool P_NoWayTraverse (AActor *usething, fixed_t endx, fixed_t endy) // [GrafZahl] de-obfuscated. Was I the only one who was unable to make sense out of // this convoluted mess? if (ld->special) continue; - if (ld->flags&(ML_BLOCKING|ML_BLOCKEVERYTHING|ML_BLOCK_PLAYERS)) return true; - P_LineOpening(open, NULL, ld, it.Trace().x+FixedMul(it.Trace().dx, in->frac), - it.Trace().y+FixedMul(it.Trace().dy, in->frac)); + if (ld->flags&(ML_BLOCKING | ML_BLOCKEVERYTHING | ML_BLOCK_PLAYERS)) return true; + P_LineOpening(open, NULL, ld, it.Trace().x + FixedMul(it.Trace().dx, in->frac), + it.Trace().y + FixedMul(it.Trace().dy, in->frac)); if (open.range <= 0 || open.bottom > usething->z + usething->MaxStepHeight || open.top < usething->z + usething->height) return true; @@ -4354,7 +4375,7 @@ bool P_NoWayTraverse (AActor *usething, fixed_t endx, fixed_t endy) // //========================================================================== -void P_UseLines (player_t *player) +void P_UseLines(player_t *player) { angle_t angle; fixed_t x1, y1, usedist; @@ -4375,15 +4396,15 @@ void P_UseLines (player_t *player) // // This added test makes the "oof" sound work on 2s lines -- killough: - if (!P_UseTraverse (player->mo, x1, y1, foundline)) + if (!P_UseTraverse(player->mo, x1, y1, foundline)) { // [RH] Give sector a chance to eat the use sector_t *sec = player->mo->Sector; int spac = SECSPAC_Use; if (foundline) spac |= SECSPAC_UseWall; - if ((!sec->SecActTarget || !sec->SecActTarget->TriggerAction (player->mo, spac)) && - P_NoWayTraverse (player->mo, x1, y1)) + if ((!sec->SecActTarget || !sec->SecActTarget->TriggerAction(player->mo, spac)) && + P_NoWayTraverse(player->mo, x1, y1)) { - S_Sound (player->mo, CHAN_VOICE, "*usefail", 1, ATTN_IDLE); + S_Sound(player->mo, CHAN_VOICE, "*usefail", 1, ATTN_IDLE); } } } @@ -4396,12 +4417,12 @@ void P_UseLines (player_t *player) // //========================================================================== -bool P_UsePuzzleItem (AActor *PuzzleItemUser, int PuzzleItemType) +bool P_UsePuzzleItem(AActor *PuzzleItemUser, int PuzzleItemType) { int angle; fixed_t x1, y1, x2, y2, usedist; - angle = PuzzleItemUser->angle>>ANGLETOFINESHIFT; + angle = PuzzleItemUser->angle >> ANGLETOFINESHIFT; x1 = PuzzleItemUser->x; y1 = PuzzleItemUser->y; @@ -4414,7 +4435,7 @@ bool P_UsePuzzleItem (AActor *PuzzleItemUser, int PuzzleItemType) x2 = x1 + FixedMul(usedist, finecosine[angle]); y2 = y1 + FixedMul(usedist, finesine[angle]); - FPathTraverse it(x1, y1, x2, y2, PT_ADDLINES|PT_ADDTHINGS); + FPathTraverse it(x1, y1, x2, y2, PT_ADDLINES | PT_ADDTHINGS); intercept_t *in; while ((in = it.Next())) @@ -4426,15 +4447,15 @@ bool P_UsePuzzleItem (AActor *PuzzleItemUser, int PuzzleItemType) { // Check line if (in->d.line->special != UsePuzzleItem) { - P_LineOpening (open, NULL, in->d.line, it.Trace().x + FixedMul (it.Trace().dx, in->frac), - it.Trace().y + FixedMul (it.Trace().dy, in->frac)); + P_LineOpening(open, NULL, in->d.line, it.Trace().x + FixedMul(it.Trace().dx, in->frac), + it.Trace().y + FixedMul(it.Trace().dy, in->frac)); if (open.range <= 0) { return false; // can't use through a wall } continue; } - if (P_PointOnLineSide (PuzzleItemUser->x, PuzzleItemUser->y, in->d.line) == 1) + if (P_PointOnLineSide(PuzzleItemUser->x, PuzzleItemUser->y, in->d.line) == 1) { // Don't use back sides return false; } @@ -4443,7 +4464,7 @@ bool P_UsePuzzleItem (AActor *PuzzleItemUser, int PuzzleItemType) return false; } int args[3] = { in->d.line->args[2], in->d.line->args[3], in->d.line->args[4] }; - P_StartScript (PuzzleItemUser, in->d.line, in->d.line->args[1], NULL, args, 3, ACS_ALWAYS); + P_StartScript(PuzzleItemUser, in->d.line, in->d.line->args[1], NULL, args, 3, ACS_ALWAYS); in->d.line->special = 0; return true; } @@ -4458,7 +4479,7 @@ bool P_UsePuzzleItem (AActor *PuzzleItemUser, int PuzzleItemType) continue; } int args[3] = { mobj->args[2], mobj->args[3], mobj->args[4] }; - P_StartScript (PuzzleItemUser, NULL, mobj->args[1], NULL, args, 3, ACS_ALWAYS); + P_StartScript(PuzzleItemUser, NULL, mobj->args[1], NULL, args, 3, ACS_ALWAYS); mobj->special = 0; return true; } @@ -4476,7 +4497,7 @@ bool P_UsePuzzleItem (AActor *PuzzleItemUser, int PuzzleItemType) // [RH] Damage scale to apply to thing that shot the missile. static float selfthrustscale; -CUSTOM_CVAR (Float, splashfactor, 1.f, CVAR_SERVERINFO) +CUSTOM_CVAR(Float, splashfactor, 1.f, CVAR_SERVERINFO) { if (self <= 0.f) self = 1.f; @@ -4491,19 +4512,19 @@ CUSTOM_CVAR (Float, splashfactor, 1.f, CVAR_SERVERINFO) // //========================================================================== -void P_RadiusAttack (AActor *bombspot, AActor *bombsource, int bombdamage, int bombdistance, FName bombmod, +void P_RadiusAttack(AActor *bombspot, AActor *bombsource, int bombdamage, int bombdistance, FName bombmod, int flags, int fulldamagedistance) { if (bombdistance <= 0) return; - fulldamagedistance = clamp(fulldamagedistance, 0, bombdistance-1); + fulldamagedistance = clamp(fulldamagedistance, 0, bombdistance - 1); double bombdistancefloat = 1.f / (double)(bombdistance - fulldamagedistance); double bombdamagefloat = (double)bombdamage; FVector3 bombvec(FIXED2FLOAT(bombspot->x), FIXED2FLOAT(bombspot->y), FIXED2FLOAT(bombspot->z)); - FBlockThingsIterator it(FBoundingBox(bombspot->x, bombspot->y, bombdistance<x, bombspot->y, bombdistance << FRACBITS)); AActor *thing; if (flags & RADF_SOURCEISSPOT) @@ -4532,12 +4553,12 @@ void P_RadiusAttack (AActor *bombspot, AActor *bombsource, int bombdamage, int b // be hurt by projectiles fired by a monster of the same type. // Controlled by the DONTHARMCLASS and DONTHARMSPECIES flags. if ((bombsource && !thing->player) // code common to both checks - && ( // Class check first + && ( // Class check first ((bombsource->flags4 & MF4_DONTHARMCLASS) && (thing->GetClass() == bombsource->GetClass())) || // Nigh-identical species check second ((bombsource->flags6 & MF6_DONTHARMSPECIES) && (thing->GetSpecies() == bombsource->GetSpecies())) ) - ) continue; + ) continue; // Barrels always use the original code, since this makes // them far too "active." BossBrains also use the old code @@ -4552,12 +4573,12 @@ void P_RadiusAttack (AActor *bombspot, AActor *bombsource, int bombdamage, int b fixed_t dx, dy; double boxradius; - dx = abs (thing->x - bombspot->x); - dy = abs (thing->y - bombspot->y); - boxradius = double (thing->radius); + dx = abs(thing->x - bombspot->x); + dy = abs(thing->y - bombspot->y); + boxradius = double(thing->radius); // The damage pattern is square, not circular. - len = double (dx > dy ? dx : dy); + len = double(dx > dy ? dx : dy); if (bombspot->z < thing->z || bombspot->z >= thing->z + thing->height) { @@ -4565,11 +4586,11 @@ void P_RadiusAttack (AActor *bombspot, AActor *bombsource, int bombdamage, int b if (bombspot->z > thing->z) { - dz = double (bombspot->z - thing->z - thing->height); + dz = double(bombspot->z - thing->z - thing->height); } else { - dz = double (thing->z - bombspot->z); + dz = double(thing->z - bombspot->z); } if (len <= boxradius) { @@ -4578,7 +4599,7 @@ void P_RadiusAttack (AActor *bombspot, AActor *bombsource, int bombdamage, int b else { len -= boxradius; - len = sqrt (len*len + dz*dz); + len = sqrt(len*len + dz*dz); } } else @@ -4597,7 +4618,7 @@ void P_RadiusAttack (AActor *bombspot, AActor *bombsource, int bombdamage, int b points *= thing->GetClass()->RDFactor / (float)FRACUNIT; // points and bombdamage should be the same sign - if ((points * bombdamage) > 0 && P_CheckSight (thing, bombspot, SF_IGNOREVISIBILITY|SF_IGNOREWATERBOUNDARY)) + if ((points * bombdamage) > 0 && P_CheckSight(thing, bombspot, SF_IGNOREVISIBILITY | SF_IGNOREWATERBOUNDARY)) { // OK to damage; target is in direct path double velz; double thrust; @@ -4605,14 +4626,14 @@ void P_RadiusAttack (AActor *bombspot, AActor *bombsource, int bombdamage, int b int newdam = damage; if (!(flags & RADF_NODAMAGE)) - newdam = P_DamageMobj (thing, bombspot, bombsource, damage, bombmod); + newdam = P_DamageMobj(thing, bombspot, bombsource, damage, bombmod); else if (thing->player == NULL && !(flags & RADF_NOIMPACTDAMAGE)) thing->flags2 |= MF2_BLASTED; if (!(thing->flags & MF_ICECORPSE)) { if (!(flags & RADF_NODAMAGE) && !(bombspot->flags3 & MF3_BLOODLESSIMPACT)) - P_TraceBleed (newdam > 0 ? newdam : damage, thing, bombspot); + P_TraceBleed(newdam > 0 ? newdam : damage, thing, bombspot); if ((flags & RADF_NODAMAGE) || !(bombspot->flags2 & MF2_NODMGTHRUST)) { @@ -4623,7 +4644,7 @@ void P_RadiusAttack (AActor *bombspot, AActor *bombsource, int bombdamage, int b { thrust *= selfthrustscale; } - velz = (double)(thing->z + (thing->height>>1) - bombspot->z) * thrust; + velz = (double)(thing->z + (thing->height >> 1) - bombspot->z) * thrust; if (bombsource != thing) { velz *= 0.5f; @@ -4632,9 +4653,9 @@ void P_RadiusAttack (AActor *bombspot, AActor *bombsource, int bombdamage, int b { velz *= 0.8f; } - angle_t ang = R_PointToAngle2 (bombspot->x, bombspot->y, thing->x, thing->y) >> ANGLETOFINESHIFT; - thing->velx += fixed_t (finecosine[ang] * thrust); - thing->vely += fixed_t (finesine[ang] * thrust); + angle_t ang = R_PointToAngle2(bombspot->x, bombspot->y, thing->x, thing->y) >> ANGLETOFINESHIFT; + thing->velx += fixed_t(finecosine[ang] * thrust); + thing->vely += fixed_t(finesine[ang] * thrust); if (!(flags & RADF_NODAMAGE)) thing->velz += (fixed_t)velz; // this really doesn't work well } @@ -4647,8 +4668,8 @@ void P_RadiusAttack (AActor *bombspot, AActor *bombsource, int bombdamage, int b // [RH] Old code just for barrels fixed_t dx, dy, dist; - dx = abs (thing->x - bombspot->x); - dy = abs (thing->y - bombspot->y); + dx = abs(thing->x - bombspot->x); + dy = abs(thing->y - bombspot->y); dist = dx>dy ? dx : dy; dist = (dist - thing->radius) >> FRACBITS; @@ -4659,17 +4680,17 @@ void P_RadiusAttack (AActor *bombspot, AActor *bombsource, int bombdamage, int b if (dist >= bombdistance) continue; // out of range - if (P_CheckSight (thing, bombspot, SF_IGNOREVISIBILITY|SF_IGNOREWATERBOUNDARY)) + if (P_CheckSight(thing, bombspot, SF_IGNOREVISIBILITY | SF_IGNOREWATERBOUNDARY)) { // OK to damage; target is in direct path dist = clamp(dist - fulldamagedistance, 0, dist); - int damage = Scale (bombdamage, bombdistance-dist, bombdistance); + int damage = Scale(bombdamage, bombdistance - dist, bombdistance); damage = (int)((double)damage * splashfactor); damage = Scale(damage, thing->GetClass()->RDFactor, FRACUNIT); if (damage > 0) { - int newdam = P_DamageMobj (thing, bombspot, bombsource, damage, bombmod); - P_TraceBleed (newdam > 0 ? newdam : damage, thing, bombspot); + int newdam = P_DamageMobj(thing, bombspot, bombsource, damage, bombmod); + P_TraceBleed(newdam > 0 ? newdam : damage, thing, bombspot); } } } @@ -4709,7 +4730,7 @@ struct FChangePosition TArray intersectors; -EXTERN_CVAR (Int, cl_bloodtype) +EXTERN_CVAR(Int, cl_bloodtype) //============================================================================= // @@ -4717,7 +4738,7 @@ EXTERN_CVAR (Int, cl_bloodtype) // //============================================================================= -bool P_AdjustFloorCeil (AActor *thing, FChangePosition *cpos) +bool P_AdjustFloorCeil(AActor *thing, FChangePosition *cpos) { int flags2 = thing->flags2 & MF2_PASSMOBJ; FCheckPosition tm; @@ -4735,7 +4756,7 @@ bool P_AdjustFloorCeil (AActor *thing, FChangePosition *cpos) thing->flags2 |= MF2_PASSMOBJ; } - bool isgood = P_CheckPosition (thing, thing->x, thing->y, tm); + bool isgood = P_CheckPosition(thing, thing->x, thing->y, tm); thing->floorz = tm.floorz; thing->ceilingz = tm.ceilingz; thing->dropoffz = tm.dropoffz; // killough 11/98: remember dropoffs @@ -4756,7 +4777,7 @@ bool P_AdjustFloorCeil (AActor *thing, FChangePosition *cpos) // //============================================================================= -void P_FindAboveIntersectors (AActor *actor) +void P_FindAboveIntersectors(AActor *actor) { if (actor->flags & MF_NOCLIP) return; @@ -4799,7 +4820,7 @@ void P_FindAboveIntersectors (AActor *actor) if (thing->z >= actor->z && thing->z <= actor->z + actor->height) { // Thing intersects above the base - intersectors.Push (thing); + intersectors.Push(thing); } } } @@ -4810,7 +4831,7 @@ void P_FindAboveIntersectors (AActor *actor) // //============================================================================= -void P_FindBelowIntersectors (AActor *actor) +void P_FindBelowIntersectors(AActor *actor) { if (actor->flags & MF_NOCLIP) return; @@ -4853,7 +4874,7 @@ void P_FindBelowIntersectors (AActor *actor) if (thing->z + thing->height <= actor->z + actor->height && thing->z + thing->height > actor->z) { // Thing intersects below the base - intersectors.Push (thing); + intersectors.Push(thing); } } } @@ -4864,17 +4885,17 @@ void P_FindBelowIntersectors (AActor *actor) // //============================================================================= -void P_DoCrunch (AActor *thing, FChangePosition *cpos) +void P_DoCrunch(AActor *thing, FChangePosition *cpos) { if (!(thing && thing->Grind(true) && cpos)) return; cpos->nofit = true; if ((cpos->crushchange > 0) && !(level.maptime & 3)) { - int newdam = P_DamageMobj (thing, NULL, NULL, cpos->crushchange, NAME_Crush); + int newdam = P_DamageMobj(thing, NULL, NULL, cpos->crushchange, NAME_Crush); // spray blood in a random direction - if (!(thing->flags2&(MF2_INVULNERABLE|MF2_DORMANT))) + if (!(thing->flags2&(MF2_INVULNERABLE | MF2_DORMANT))) { if (!(thing->flags&MF_NOBLOOD)) { @@ -4882,27 +4903,28 @@ void P_DoCrunch (AActor *thing, FChangePosition *cpos) PClassActor *bloodcls = thing->GetBloodType(); P_TraceBleed (newdam > 0 ? newdam : cpos->crushchange, thing); - if (cl_bloodtype <= 1 && bloodcls != NULL) + if (bloodcls != NULL) { AActor *mo; - mo = Spawn (bloodcls, thing->x, thing->y, - thing->z + thing->height/2, ALLOW_REPLACE); + mo = Spawn(bloodcls, thing->x, thing->y, + thing->z + thing->height / 2, ALLOW_REPLACE); - mo->velx = pr_crunch.Random2 () << 12; - mo->vely = pr_crunch.Random2 () << 12; + mo->velx = pr_crunch.Random2() << 12; + mo->vely = pr_crunch.Random2() << 12; if (bloodcolor != 0 && !(mo->flags2 & MF2_DONTTRANSLATE)) { 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)) @@ -4924,9 +4946,9 @@ void P_DoCrunch (AActor *thing, FChangePosition *cpos) // above it didn't fit. //============================================================================= -int P_PushUp (AActor *thing, FChangePosition *cpos) +int P_PushUp(AActor *thing, FChangePosition *cpos) { - unsigned int firstintersect = intersectors.Size (); + unsigned int firstintersect = intersectors.Size(); unsigned int lastintersect; int mymass = thing->Mass; @@ -4937,8 +4959,8 @@ int P_PushUp (AActor *thing, FChangePosition *cpos) // [GZ] Skip thing intersect test for THRUACTORS things. if (thing->flags2 & MF2_THRUACTORS) return 0; - P_FindAboveIntersectors (thing); - lastintersect = intersectors.Size (); + P_FindAboveIntersectors(thing); + lastintersect = intersectors.Size(); for (; firstintersect < lastintersect; firstintersect++) { AActor *intersect = intersectors[firstintersect]; @@ -4951,17 +4973,17 @@ int P_PushUp (AActor *thing, FChangePosition *cpos) if (!(intersect->flags2 & MF2_PASSMOBJ) || (!(intersect->flags3 & MF3_ISMONSTER) && intersect->Mass > mymass) || (intersect->flags4 & MF4_ACTLIKEBRIDGE) - ) - { + ) + { // Can't push bridges or things more massive than ourself return 2; } fixed_t oldz = intersect->z; - P_AdjustFloorCeil (intersect, cpos); + P_AdjustFloorCeil(intersect, cpos); intersect->z = thing->z + thing->height + 1; - if (P_PushUp (intersect, cpos)) + if (P_PushUp(intersect, cpos)) { // Move blocked - P_DoCrunch (intersect, cpos); + P_DoCrunch(intersect, cpos); intersect->z = oldz; return 2; } @@ -4977,9 +4999,9 @@ int P_PushUp (AActor *thing, FChangePosition *cpos) // below it didn't fit. //============================================================================= -int P_PushDown (AActor *thing, FChangePosition *cpos) +int P_PushDown(AActor *thing, FChangePosition *cpos) { - unsigned int firstintersect = intersectors.Size (); + unsigned int firstintersect = intersectors.Size(); unsigned int lastintersect; int mymass = thing->Mass; @@ -4987,27 +5009,27 @@ int P_PushDown (AActor *thing, FChangePosition *cpos) { return 1; } - P_FindBelowIntersectors (thing); - lastintersect = intersectors.Size (); + P_FindBelowIntersectors(thing); + lastintersect = intersectors.Size(); for (; firstintersect < lastintersect; firstintersect++) { AActor *intersect = intersectors[firstintersect]; if (!(intersect->flags2 & MF2_PASSMOBJ) || (!(intersect->flags3 & MF3_ISMONSTER) && intersect->Mass > mymass) || (intersect->flags4 & MF4_ACTLIKEBRIDGE) - ) - { + ) + { // Can't push bridges or things more massive than ourself return 2; } fixed_t oldz = intersect->z; - P_AdjustFloorCeil (intersect, cpos); + P_AdjustFloorCeil(intersect, cpos); if (oldz > thing->z - intersect->height) { // Only push things down, not up. intersect->z = thing->z - intersect->height; - if (P_PushDown (intersect, cpos)) + if (P_PushDown(intersect, cpos)) { // Move blocked - P_DoCrunch (intersect, cpos); + P_DoCrunch(intersect, cpos); intersect->z = oldz; return 2; } @@ -5022,27 +5044,27 @@ int P_PushDown (AActor *thing, FChangePosition *cpos) // //============================================================================= -void PIT_FloorDrop (AActor *thing, FChangePosition *cpos) +void PIT_FloorDrop(AActor *thing, FChangePosition *cpos) { fixed_t oldfloorz = thing->floorz; - P_AdjustFloorCeil (thing, cpos); + P_AdjustFloorCeil(thing, cpos); if (oldfloorz == thing->floorz) return; if (thing->flags4 & MF4_ACTLIKEBRIDGE) return; // do not move bridge things if (thing->velz == 0 && (!(thing->flags & MF_NOGRAVITY) || - (thing->z == oldfloorz && !(thing->flags & MF_NOLIFTDROP)))) + (thing->z == oldfloorz && !(thing->flags & MF_NOLIFTDROP)))) { fixed_t oldz = thing->z; if ((thing->flags & MF_NOGRAVITY) || (thing->flags5 & MF5_MOVEWITHSECTOR) || - (((cpos->sector->Flags & SECF_FLOORDROP) || cpos->moveamt < 9*FRACUNIT) - && thing->z - thing->floorz <= cpos->moveamt)) + (((cpos->sector->Flags & SECF_FLOORDROP) || cpos->moveamt < 9 * FRACUNIT) + && thing->z - thing->floorz <= cpos->moveamt)) { thing->z = thing->floorz; - P_CheckFakeFloorTriggers (thing, oldz); + P_CheckFakeFloorTriggers(thing, oldz); } } else if ((thing->z != oldfloorz && !(thing->flags & MF_NOLIFTDROP))) @@ -5051,7 +5073,7 @@ void PIT_FloorDrop (AActor *thing, FChangePosition *cpos) if ((thing->flags & MF_NOGRAVITY) && (thing->flags6 & MF6_RELATIVETOFLOOR)) { thing->z = thing->z - oldfloorz + thing->floorz; - P_CheckFakeFloorTriggers (thing, oldz); + P_CheckFakeFloorTriggers(thing, oldz); } } } @@ -5062,46 +5084,46 @@ void PIT_FloorDrop (AActor *thing, FChangePosition *cpos) // //============================================================================= -void PIT_FloorRaise (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); + P_AdjustFloorCeil(thing, cpos); if (oldfloorz == thing->floorz) return; // Move things intersecting the floor up if (thing->z <= thing->floorz) { - if (thing->flags4 & MF4_ACTLIKEBRIDGE) + if (thing->flags4 & MF4_ACTLIKEBRIDGE) { cpos->nofit = true; return; // do not move bridge things } - intersectors.Clear (); + intersectors.Clear(); thing->z = thing->floorz; } else { - if((thing->flags & MF_NOGRAVITY) && (thing->flags6 & MF6_RELATIVETOFLOOR)) + if ((thing->flags & MF_NOGRAVITY) && (thing->flags6 & MF6_RELATIVETOFLOOR)) { - intersectors.Clear (); + intersectors.Clear(); thing->z = thing->z - oldfloorz + thing->floorz; } else return; } - switch (P_PushUp (thing, cpos)) + switch (P_PushUp(thing, cpos)) { default: - P_CheckFakeFloorTriggers (thing, oldz); + P_CheckFakeFloorTriggers(thing, oldz); break; case 1: - P_DoCrunch (thing, cpos); - P_CheckFakeFloorTriggers (thing, oldz); + P_DoCrunch(thing, cpos); + P_CheckFakeFloorTriggers(thing, oldz); break; case 2: - P_DoCrunch (thing, cpos); + P_DoCrunch(thing, cpos); thing->z = oldz; break; } @@ -5113,21 +5135,21 @@ void PIT_FloorRaise (AActor *thing, FChangePosition *cpos) // //============================================================================= -void PIT_CeilingLower (AActor *thing, FChangePosition *cpos) +void PIT_CeilingLower(AActor *thing, FChangePosition *cpos) { bool onfloor; onfloor = thing->z <= thing->floorz; - P_AdjustFloorCeil (thing, cpos); + P_AdjustFloorCeil(thing, cpos); if (thing->z + thing->height > thing->ceilingz) { - if (thing->flags4 & MF4_ACTLIKEBRIDGE) + if (thing->flags4 & MF4_ACTLIKEBRIDGE) { cpos->nofit = true; return; // do not move bridge things } - intersectors.Clear (); + intersectors.Clear(); fixed_t oldz = thing->z; if (thing->ceilingz - thing->height >= thing->floorz) { @@ -5137,18 +5159,18 @@ void PIT_CeilingLower (AActor *thing, FChangePosition *cpos) { thing->z = thing->floorz; } - switch (P_PushDown (thing, cpos)) + switch (P_PushDown(thing, cpos)) { case 2: // intentional fall-through case 1: if (onfloor) thing->z = thing->floorz; - P_DoCrunch (thing, cpos); - P_CheckFakeFloorTriggers (thing, oldz); + P_DoCrunch(thing, cpos); + P_CheckFakeFloorTriggers(thing, oldz); break; default: - P_CheckFakeFloorTriggers (thing, oldz); + P_CheckFakeFloorTriggers(thing, oldz); break; } } @@ -5160,9 +5182,9 @@ void PIT_CeilingLower (AActor *thing, FChangePosition *cpos) // //============================================================================= -void PIT_CeilingRaise (AActor *thing, FChangePosition *cpos) +void PIT_CeilingRaise(AActor *thing, FChangePosition *cpos) { - bool isgood = P_AdjustFloorCeil (thing, cpos); + bool isgood = P_AdjustFloorCeil(thing, cpos); if (thing->flags4 & MF4_ACTLIKEBRIDGE) return; // do not move bridge things @@ -5179,15 +5201,15 @@ void PIT_CeilingRaise (AActor *thing, FChangePosition *cpos) { thing->z = thing->ceilingz - thing->height; } - P_CheckFakeFloorTriggers (thing, oldz); + P_CheckFakeFloorTriggers(thing, oldz); } else if ((thing->flags2 & MF2_PASSMOBJ) && !isgood && thing->z + thing->height < thing->ceilingz) { AActor *onmobj; - if (!P_TestMobjZ (thing, true, &onmobj) && onmobj->z <= thing->z) + if (!P_TestMobjZ(thing, true, &onmobj) && onmobj->z <= thing->z) { - thing->z = MIN (thing->ceilingz - thing->height, - onmobj->z + onmobj->height); + thing->z = MIN(thing->ceilingz - thing->height, + onmobj->z + onmobj->height); } } } @@ -5202,23 +5224,23 @@ void PIT_CeilingRaise (AActor *thing, FChangePosition *cpos) // //============================================================================= -bool P_ChangeSector (sector_t *sector, int crunch, int amt, int floorOrCeil, bool isreset) +bool P_ChangeSector(sector_t *sector, int crunch, int amt, int floorOrCeil, bool isreset) { FChangePosition cpos; - void (*iterator)(AActor *, FChangePosition *); - void (*iterator2)(AActor *, FChangePosition *) = NULL; + void(*iterator)(AActor *, FChangePosition *); + void(*iterator2)(AActor *, FChangePosition *) = NULL; msecnode_t *n; cpos.nofit = false; cpos.crushchange = crunch; - cpos.moveamt = abs (amt); + cpos.moveamt = abs(amt); cpos.movemidtex = false; cpos.sector = sector; #ifdef _3DFLOORS // Also process all sectors that have 3D floors transferred from the // changed sector. - if(sector->e->XFloor.attached.Size()) + if (sector->e->XFloor.attached.Size()) { unsigned i; sector_t* sec; @@ -5227,30 +5249,30 @@ bool P_ChangeSector (sector_t *sector, int crunch, int amt, int floorOrCeil, boo // Use different functions for the four different types of sector movement. // for 3D-floors the meaning of floor and ceiling is inverted!!! if (floorOrCeil == 1) - { + { iterator = (amt >= 0) ? PIT_FloorRaise : PIT_FloorDrop; } else - { - iterator = (amt >=0) ? PIT_CeilingRaise : PIT_CeilingLower; + { + iterator = (amt >= 0) ? PIT_CeilingRaise : PIT_CeilingLower; } - for(i = 0; i < sector->e->XFloor.attached.Size(); i ++) + for (i = 0; i < sector->e->XFloor.attached.Size(); i++) { sec = sector->e->XFloor.attached[i]; P_Recalculate3DFloors(sec); // Must recalculate the 3d floor and light lists // no thing checks for attached sectors because of heightsec - if (sec->heightsec==sector) continue; + if (sec->heightsec == sector) continue; - for (n=sec->touching_thinglist; n; n=n->m_snext) n->visited = false; - do + for (n = sec->touching_thinglist; n; n = n->m_snext) n->visited = false; + do { - for (n=sec->touching_thinglist; n; n=n->m_snext) + for (n = sec->touching_thinglist; n; n = n->m_snext) { if (!n->visited) { - n->visited = true; + n->visited = true; if (!(n->m_thing->flags & MF_NOBLOCKMAP) || //jff 4/7/98 don't do these (n->m_thing->flags5 & MF5_MOVEWITHSECTOR)) { @@ -5259,8 +5281,7 @@ bool P_ChangeSector (sector_t *sector, int crunch, int amt, int floorOrCeil, boo break; } } - } - while (n); + } while (n); } } P_Recalculate3DFloors(sector); // Must recalculate the 3d floor and light lists @@ -5318,8 +5339,8 @@ bool P_ChangeSector (sector_t *sector, int crunch, int amt, int floorOrCeil, boo if (!(n->m_thing->flags & MF_NOBLOCKMAP) || //jff 4/7/98 don't do these (n->m_thing->flags5 & MF5_MOVEWITHSECTOR)) { - iterator (n->m_thing, &cpos); // process it - if (iterator2 != NULL) iterator2 (n->m_thing, &cpos); + iterator(n->m_thing, &cpos); // process it + if (iterator2 != NULL) iterator2(n->m_thing, &cpos); } break; // exit and start over } @@ -5333,7 +5354,7 @@ bool P_ChangeSector (sector_t *sector, int crunch, int amt, int floorOrCeil, boo // execute appropriate sector actions. // Only check if the sector move was successful. TArray & secs = sector->e->FakeFloor.Sectors; - for(unsigned i = 0; i < secs.Size(); i++) + for (unsigned i = 0; i < secs.Size(); i++) { sector_t * s = secs[i]; @@ -5388,7 +5409,7 @@ msecnode_t *P_GetSecnode() } else { - node = (msecnode_t *)M_Malloc (sizeof(*node)); + node = (msecnode_t *)M_Malloc(sizeof(*node)); } return node; } @@ -5401,7 +5422,7 @@ msecnode_t *P_GetSecnode() // //============================================================================= -void P_PutSecnode (msecnode_t *node) +void P_PutSecnode(msecnode_t *node) { node->m_snext = headsecnode; headsecnode = node; @@ -5419,13 +5440,13 @@ void P_PutSecnode (msecnode_t *node) // //============================================================================= -msecnode_t *P_AddSecnode (sector_t *s, AActor *thing, msecnode_t *nextnode) +msecnode_t *P_AddSecnode(sector_t *s, AActor *thing, msecnode_t *nextnode) { msecnode_t *node; if (s == 0) { - I_FatalError ("AddSecnode of 0 for %s\n", thing->GetClass()->TypeName.GetChars()); + I_FatalError("AddSecnode of 0 for %s\n", thing->GetClass()->TypeName.GetChars()); } node = nextnode; @@ -5448,16 +5469,16 @@ msecnode_t *P_AddSecnode (sector_t *s, AActor *thing, msecnode_t *nextnode) node->visited = 0; node->m_sector = s; // sector - node->m_thing = thing; // mobj - node->m_tprev = NULL; // prev node on Thing thread - node->m_tnext = nextnode; // next node on Thing thread + node->m_thing = thing; // mobj + node->m_tprev = NULL; // prev node on Thing thread + node->m_tnext = nextnode; // next node on Thing thread if (nextnode) nextnode->m_tprev = node; // set back link on Thing // Add new node at head of sector thread starting at s->touching_thinglist - node->m_sprev = NULL; // prev node on sector thread - node->m_snext = s->touching_thinglist; // next node on sector thread + node->m_sprev = NULL; // prev node on sector thread + node->m_snext = s->touching_thinglist; // next node on sector thread if (s->touching_thinglist) node->m_snext->m_sprev = node; s->touching_thinglist = node; @@ -5474,7 +5495,7 @@ msecnode_t *P_AddSecnode (sector_t *s, AActor *thing, msecnode_t *nextnode) // //============================================================================= -msecnode_t *P_DelSecnode (msecnode_t *node) +msecnode_t *P_DelSecnode(msecnode_t *node) { msecnode_t* tp; // prev node on thing thread msecnode_t* tn; // next node on thing thread @@ -5521,11 +5542,11 @@ msecnode_t *P_DelSecnode (msecnode_t *node) // //============================================================================= -void P_DelSector_List () +void P_DelSector_List() { if (sector_list != NULL) { - P_DelSeclist (sector_list); + P_DelSeclist(sector_list); sector_list = NULL; } } @@ -5538,10 +5559,10 @@ void P_DelSector_List () // //============================================================================= -void P_DelSeclist (msecnode_t *node) +void P_DelSeclist(msecnode_t *node) { while (node) - node = P_DelSecnode (node); + node = P_DelSecnode(node); } //============================================================================= @@ -5553,7 +5574,7 @@ void P_DelSeclist (msecnode_t *node) // //============================================================================= -void P_CreateSecNodeList (AActor *thing, fixed_t x, fixed_t y) +void P_CreateSecNodeList(AActor *thing, fixed_t x, fixed_t y) { msecnode_t *node; @@ -5575,13 +5596,13 @@ void P_CreateSecNodeList (AActor *thing, fixed_t x, fixed_t y) while ((ld = it.Next())) { - if (box.Right() <= ld->bbox[BOXLEFT] || - box.Left() >= ld->bbox[BOXRIGHT] || - box.Top() <= ld->bbox[BOXBOTTOM] || + if (box.Right() <= ld->bbox[BOXLEFT] || + box.Left() >= ld->bbox[BOXRIGHT] || + box.Top() <= ld->bbox[BOXBOTTOM] || box.Bottom() >= ld->bbox[BOXTOP]) continue; - if (box.BoxOnLineSide (ld) != -1) + if (box.BoxOnLineSide(ld) != -1) continue; // This line crosses through the object. @@ -5591,7 +5612,7 @@ void P_CreateSecNodeList (AActor *thing, fixed_t x, fixed_t y) // allowed to move to this position, then the sector_list // will be attached to the Thing's AActor at touching_sectorlist. - sector_list = P_AddSecnode (ld->frontsector,thing,sector_list); + sector_list = P_AddSecnode(ld->frontsector, thing, sector_list); // Don't assume all lines are 2-sided, since some Things // like MT_TFOG are allowed regardless of whether their radius takes @@ -5606,7 +5627,7 @@ void P_CreateSecNodeList (AActor *thing, fixed_t x, fixed_t y) // Add the sector of the (x,y) point to sector_list. - sector_list = P_AddSecnode (thing->Sector, thing, sector_list); + sector_list = P_AddSecnode(thing->Sector, thing, sector_list); // Now delete any nodes that won't be used. These are the ones where // m_thing is still NULL. @@ -5618,7 +5639,7 @@ void P_CreateSecNodeList (AActor *thing, fixed_t x, fixed_t y) { if (node == sector_list) sector_list = node->m_tnext; - node = P_DelSecnode (node); + node = P_DelSecnode(node); } else { @@ -5633,7 +5654,7 @@ void P_CreateSecNodeList (AActor *thing, fixed_t x, fixed_t y) // //========================================================================== -void SpawnShootDecal (AActor *t1, const FTraceResults &trace) +void SpawnShootDecal(AActor *t1, const FTraceResults &trace) { FDecalBase *decalbase = NULL; @@ -5647,7 +5668,7 @@ void SpawnShootDecal (AActor *t1, const FTraceResults &trace) } if (decalbase != NULL) { - DImpactDecal::StaticCreate (decalbase->GetDecal (), + DImpactDecal::StaticCreate(decalbase->GetDecal(), trace.X, trace.Y, trace.Z, trace.Line->sidedef[trace.Side], trace.ffloor); } } @@ -5658,10 +5679,10 @@ void SpawnShootDecal (AActor *t1, const FTraceResults &trace) // //========================================================================== -static void SpawnDeepSplash (AActor *t1, const FTraceResults &trace, AActor *puff, +static void SpawnDeepSplash(AActor *t1, const FTraceResults &trace, AActor *puff, fixed_t vx, fixed_t vy, fixed_t vz, fixed_t shootz, bool ffloor) { - const secplane_t *plane; + const secplane_t *plane; if (ffloor && trace.Crossed3DWater) plane = trace.Crossed3DWater->top.plane; else if (trace.CrossedWater && trace.CrossedWater->heightsec) @@ -5669,19 +5690,19 @@ static void SpawnDeepSplash (AActor *t1, const FTraceResults &trace, AActor *puf else return; fixed_t num, den, hitdist; - den = TMulScale16 (plane->a, vx, plane->b, vy, plane->c, vz); + den = TMulScale16(plane->a, vx, plane->b, vy, plane->c, vz); if (den != 0) { - num = TMulScale16 (plane->a, t1->x, plane->b, t1->y, plane->c, shootz) + plane->d; - hitdist = FixedDiv (-num, den); + num = TMulScale16(plane->a, t1->x, plane->b, t1->y, plane->c, shootz) + plane->d; + hitdist = FixedDiv(-num, den); if (hitdist >= 0 && hitdist <= trace.Distance) { - fixed_t hitx = t1->x+FixedMul (vx, hitdist); - fixed_t hity = t1->y+FixedMul (vy, hitdist); - fixed_t hitz = shootz+FixedMul (vz, hitdist); + fixed_t hitx = t1->x + FixedMul(vx, hitdist); + fixed_t hity = t1->y + FixedMul(vy, hitdist); + fixed_t hitz = shootz + FixedMul(vz, hitdist); - P_HitWater (puff != NULL? puff:t1, P_PointInSector(hitx, hity), hitx, hity, hitz); + P_HitWater(puff != NULL ? puff : t1, P_PointInSector(hitx, hity), hitx, hity, hitz); } } } @@ -5703,12 +5724,12 @@ bool P_ActivateThingSpecial(AActor * thing, AActor * trigger, bool death) if (thing->activationtype & THINGSPEC_TriggerTargets) trigger->target = thing; // State change mechanism. The thing needs to be not dead and to have at least one of the relevant flags - if (!death && (thing->activationtype & (THINGSPEC_Activate|THINGSPEC_Deactivate|THINGSPEC_Switch))) + if (!death && (thing->activationtype & (THINGSPEC_Activate | THINGSPEC_Deactivate | THINGSPEC_Switch))) { // If a switchable thing does not know whether it should be activated // or deactivated, the default is to activate it. - if ((thing->activationtype & THINGSPEC_Switch) - && !(thing->activationtype & (THINGSPEC_Activate|THINGSPEC_Deactivate))) + if ((thing->activationtype & THINGSPEC_Switch) + && !(thing->activationtype & (THINGSPEC_Activate | THINGSPEC_Deactivate))) { thing->activationtype |= THINGSPEC_Activate; } @@ -5735,11 +5756,11 @@ bool P_ActivateThingSpecial(AActor * thing, AActor * trigger, bool death) // Run the special, if any if (thing->special) { - res = !! P_ExecuteSpecial(thing->special, NULL, + res = !!P_ExecuteSpecial(thing->special, NULL, // TriggerActs overrides the level flag, which only concerns thing activated by death (((death && level.flags & LEVEL_ACTOWNSPECIAL && !(thing->activationtype & THINGSPEC_TriggerActs)) || (thing->activationtype & THINGSPEC_ThingActs)) // Who triggers? - ? thing : trigger), + ? thing : trigger), false, thing->args[0], thing->args[1], thing->args[2], thing->args[3], thing->args[4]); // Clears the special if it was run on thing's death or if flag is set. diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index 59c07638b..d364cc0cd 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:$ @@ -304,8 +305,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 @@ -394,6 +399,10 @@ void AActor::Serialize (FArchive &arc) arc << PoisonDamageType << PoisonDamageTypeReceived; } arc << ConversationRoot << Conversation; + if (SaveVersion >= 4509) + { + arc << FriendPlayer; + } { FString tagstr; @@ -486,7 +495,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. // //========================================================================== @@ -497,6 +506,10 @@ int AActor::GetTics(FState * newstate) { return tics - (tics>>1); } + else if (isSlow() && newstate->Slow) + { + return tics<<1; + } return tics; } @@ -1096,6 +1109,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, @@ -2233,7 +2256,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) @@ -2821,11 +2844,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)) @@ -2864,7 +2890,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)); } //========================================================================== @@ -3041,7 +3067,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, @@ -3070,6 +3096,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 // @@ -3634,19 +3684,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 @@ -4132,6 +4186,7 @@ void AActor::PostBeginPlay () Renderer->StateChanged(this); } PrevAngle = angle; + flags7 |= MF7_HANDLENODELAY; } void AActor::MarkPrecacheSounds() const @@ -4154,6 +4209,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))) @@ -4752,6 +4812,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::FindActor("Unknown"); @@ -4768,7 +4834,7 @@ AActor *P_SpawnMapThing (FMapThing *mthing, int position) // [RH] don't spawn extra weapons in coop if so desired if (multiplayer && !deathmatch && (dmflags & DF_NO_COOP_WEAPON_SPAWN)) { - if (i->IsDescendantOf (RUNTIME_CLASS(AWeapon))) + if (GetDefaultByType(i)->flags7 & MF7_WEAPONSPAWN) { if ((mthing->flags & (MTF_DEATHMATCH|MTF_SINGLE)) == MTF_DEATHMATCH) return NULL; @@ -4861,11 +4927,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; } @@ -4955,7 +5049,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 @@ -5027,7 +5121,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); } @@ -5048,7 +5142,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; @@ -5063,6 +5157,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) { @@ -5086,7 +5182,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; @@ -5101,6 +5197,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) { @@ -5129,7 +5227,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 @@ -5146,6 +5244,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) { @@ -5235,7 +5335,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(); @@ -6079,22 +6179,66 @@ void AActor::SetIdle() int AActor::SpawnHealth() const { - 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++; + } +} + int AActor::GetGibHealth() const { int gibhealth = GetClass()->GibHealth; @@ -6221,25 +6365,25 @@ 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); + Printf("\n flags7: %x", query->flags7); for (flagi = 0; flagi <= 31; flagi++) if (query->flags7 & 1<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 dadcdff5c..fcd514f20 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); @@ -311,7 +312,6 @@ MapData *P_OpenMapData(const char * mapname, bool justcheck) if (map->Encrypted) { // If it's encrypted, then it's a Blood file, presumably a map. - map->MapLumps[0].Reader = map->file = Wads.ReopenLumpNum(lump_name); if (!P_IsBuildMap(map)) { delete map; @@ -576,13 +576,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 +616,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 +676,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 +704,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 +1511,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); @@ -1761,6 +1758,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) @@ -1820,6 +1820,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; } @@ -1881,13 +1885,6 @@ void P_AdjustLine (line_t *ld) ld->dx = v2->x - v1->x; ld->dy = v2->y - v1->y; - if (ld->dx == 0) - ld->slopetype = ST_VERTICAL; - else if (ld->dy == 0) - ld->slopetype = ST_HORIZONTAL; - else - ld->slopetype = ((ld->dy ^ ld->dx) >= 0) ? ST_POSITIVE : ST_NEGATIVE; - if (v1->x < v2->x) { ld->bbox[BOXLEFT] = v1->x; @@ -2462,11 +2459,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 @@ -2492,7 +2486,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) @@ -2523,8 +2516,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 @@ -2618,7 +2610,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; @@ -3549,7 +3547,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; @@ -3751,7 +3749,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 86977e197..377e5959b 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]) @@ -254,7 +252,7 @@ bool P_ActivateLine (line_t *line, AActor *mo, int side, int activationType) if (buttonSuccess) { - if (activationType == SPAC_Use || activationType == SPAC_Impact) + if (activationType == SPAC_Use || activationType == SPAC_Impact || activationType == SPAC_Push) { P_ChangeSwitchTexture (line->sidedef[0], repeat, special); } @@ -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, PClassActor *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); } } @@ -1981,26 +1990,12 @@ void P_SetSectorFriction (int tag, int amount, bool alterFlag) friction = (0x1EB8*amount)/0x80 + 0xD001; // killough 8/28/98: prevent odd situations - if (friction > FRACUNIT) - friction = FRACUNIT; - if (friction < 0) - friction = 0; + friction = clamp(friction, 0, FRACUNIT); // The following check might seem odd. At the time of movement, // the move distance is multiplied by 'friction/0x10000', so a // higher friction value actually means 'less friction'. - - // [RH] Twiddled these values so that velocity on ice (with - // friction 0xf900) is the same as in Heretic/Hexen. - if (friction >= ORIG_FRICTION) // ice -// movefactor = ((0x10092 - friction)*(0x70))/0x158; - movefactor = ((0x10092 - friction) * 1024) / 4352 + 568; - else - movefactor = ((friction - 0xDB34)*(0xA))/0x80; - - // killough 8/28/98: prevent odd situations - if (movefactor < 32) - movefactor = 32; + movefactor = FrictionToMoveFactor(friction); for (s = -1; (s = P_FindSectorFromTag (tag,s)) >= 0; ) { diff --git a/src/p_spec.h b/src/p_spec.h index 488a475d8..c94064ae7 100644 --- a/src/p_spec.h +++ b/src/p_spec.h @@ -172,7 +172,26 @@ void P_PlayerOnSpecialFlat (player_t *player, int floorType); void P_SectorDamage(int tag, int amount, FName type, PClassActor *protectClass, int flags); void P_SetSectorFriction (int tag, int amount, bool alterFlag); -void P_GiveSecret(AActor *actor, bool printmessage, bool playsound); +inline fixed_t FrictionToMoveFactor(fixed_t friction) +{ + fixed_t movefactor; + + // [RH] Twiddled these values so that velocity on ice (with + // friction 0xf900) is the same as in Heretic/Hexen. + if (friction >= ORIG_FRICTION) // ice +// movefactor = ((0x10092 - friction)*(0x70))/0x158; + movefactor = ((0x10092 - friction) * 1024) / 4352 + 568; + else + movefactor = ((friction - 0xDB34)*(0xA))/0x80; + + // killough 8/28/98: prevent odd situations + if (movefactor < 32) + movefactor = 32; + + return movefactor; +} + +void P_GiveSecret(AActor *actor, bool printmessage, bool playsound, int sectornum); // // getSide() @@ -902,8 +921,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_terrain.cpp b/src/p_terrain.cpp index fdd98c96a..a1a9ea25b 100644 --- a/src/p_terrain.cpp +++ b/src/p_terrain.cpp @@ -189,41 +189,38 @@ static const char *TerrainKeywords[] = NULL }; -// Alternate offsetof macro to shut GCC up -#define theoffsetof(type,field) ((size_t)&((type*)1)->field - 1) - static FGenericParse SplashParser[] = { { GEN_End, {0} }, - { GEN_Sound, {theoffsetof(FSplashDef, SmallSplashSound)} }, - { GEN_Fixed, {theoffsetof(FSplashDef, SmallSplashClip)} }, - { GEN_Sound, {theoffsetof(FSplashDef, NormalSplashSound)} }, - { GEN_Class, {theoffsetof(FSplashDef, SmallSplash)} }, - { GEN_Class, {theoffsetof(FSplashDef, SplashBase)} }, - { GEN_Class, {theoffsetof(FSplashDef, SplashChunk)} }, - { GEN_Byte, {theoffsetof(FSplashDef, ChunkXVelShift)} }, - { GEN_Byte, {theoffsetof(FSplashDef, ChunkYVelShift)} }, - { GEN_Byte, {theoffsetof(FSplashDef, ChunkZVelShift)} }, - { GEN_Fixed, {theoffsetof(FSplashDef, ChunkBaseZVel)} }, - { GEN_Bool, {theoffsetof(FSplashDef, NoAlert)} } + { GEN_Sound, {myoffsetof(FSplashDef, SmallSplashSound)} }, + { GEN_Fixed, {myoffsetof(FSplashDef, SmallSplashClip)} }, + { GEN_Sound, {myoffsetof(FSplashDef, NormalSplashSound)} }, + { GEN_Class, {myoffsetof(FSplashDef, SmallSplash)} }, + { GEN_Class, {myoffsetof(FSplashDef, SplashBase)} }, + { GEN_Class, {myoffsetof(FSplashDef, SplashChunk)} }, + { GEN_Byte, {myoffsetof(FSplashDef, ChunkXVelShift)} }, + { GEN_Byte, {myoffsetof(FSplashDef, ChunkYVelShift)} }, + { GEN_Byte, {myoffsetof(FSplashDef, ChunkZVelShift)} }, + { GEN_Fixed, {myoffsetof(FSplashDef, ChunkBaseZVel)} }, + { GEN_Bool, {myoffsetof(FSplashDef, NoAlert)} } }; static FGenericParse TerrainParser[] = { { GEN_End, {0} }, - { GEN_Splash, {theoffsetof(FTerrainDef, Splash)} }, - { GEN_Int, {theoffsetof(FTerrainDef, DamageAmount)} }, + { GEN_Splash, {myoffsetof(FTerrainDef, Splash)} }, + { GEN_Int, {myoffsetof(FTerrainDef, DamageAmount)} }, { GEN_Custom, {(size_t)ParseDamage} }, - { GEN_Int, {theoffsetof(FTerrainDef, DamageTimeMask)} }, - { GEN_Fixed, {theoffsetof(FTerrainDef, FootClip)} }, - { GEN_Float, {theoffsetof(FTerrainDef, StepVolume)} }, - { GEN_Time, {theoffsetof(FTerrainDef, WalkStepTics)} }, - { GEN_Time, {theoffsetof(FTerrainDef, RunStepTics)} }, - { GEN_Sound, {theoffsetof(FTerrainDef, LeftStepSound)} }, - { GEN_Sound, {theoffsetof(FTerrainDef, RightStepSound)} }, - { GEN_Bool, {theoffsetof(FTerrainDef, IsLiquid)} }, + { GEN_Int, {myoffsetof(FTerrainDef, DamageTimeMask)} }, + { GEN_Fixed, {myoffsetof(FTerrainDef, FootClip)} }, + { GEN_Float, {myoffsetof(FTerrainDef, StepVolume)} }, + { GEN_Time, {myoffsetof(FTerrainDef, WalkStepTics)} }, + { GEN_Time, {myoffsetof(FTerrainDef, RunStepTics)} }, + { GEN_Sound, {myoffsetof(FTerrainDef, LeftStepSound)} }, + { GEN_Sound, {myoffsetof(FTerrainDef, RightStepSound)} }, + { GEN_Bool, {myoffsetof(FTerrainDef, IsLiquid)} }, { GEN_Custom, {(size_t)ParseFriction} }, - { GEN_Bool, {theoffsetof(FTerrainDef, AllowProtection)} }, + { GEN_Bool, {myoffsetof(FTerrainDef, AllowProtection)} }, }; diff --git a/src/p_things.cpp b/src/p_things.cpp index 33e510a69..d8a49a828 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,25 +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->flags7 = info->flags7; - 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 0573589cd..279f9b8c4 100644 --- a/src/p_usdf.cpp +++ b/src/p_usdf.cpp @@ -306,12 +306,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 5cb505a7f..d5896ca7f 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; @@ -209,8 +211,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)); @@ -267,6 +267,7 @@ player_t::player_t() PremorphWeapon(0), chickenPeck(0), jumpTics(0), + onground(0), respawn_time(0), camera(0), air_finished(0), @@ -313,6 +314,116 @@ player_t::player_t() memset (&skill, 0, sizeof(skill)); } +player_t &player_t::operator=(const player_t &p) +{ + mo = p.mo; + playerstate = p.playerstate; + cmd = p.cmd; + original_cmd = p.original_cmd; + original_oldbuttons = p.original_oldbuttons; + // Intentionally not copying userinfo! + cls = p.cls; + DesiredFOV = p.DesiredFOV; + FOV = p.FOV; + viewz = p.viewz; + viewheight = p.viewheight; + deltaviewheight = p.deltaviewheight; + bob = p.bob; + velx = p.velx; + vely = p.vely; + centering = p.centering; + turnticks = p.turnticks; + attackdown = p.attackdown; + usedown = p.usedown; + oldbuttons = p.oldbuttons; + health = p.health; + inventorytics = p.inventorytics; + CurrentPlayerClass = p.CurrentPlayerClass; + backpack = p.backpack; + memcpy(frags, &p.frags, sizeof(frags)); + fragcount = p.fragcount; + lastkilltime = p.lastkilltime; + multicount = p.multicount; + spreecount = p.spreecount; + WeaponState = p.WeaponState; + ReadyWeapon = p.ReadyWeapon; + PendingWeapon = p.PendingWeapon; + cheats = p.cheats; + timefreezer = p.timefreezer; + refire = p.refire; + inconsistant = p.inconsistant; + waiting = p.waiting; + killcount = p.killcount; + itemcount = p.itemcount; + secretcount = p.secretcount; + damagecount = p.damagecount; + bonuscount = p.bonuscount; + hazardcount = p.hazardcount; + poisoncount = p.poisoncount; + poisontype = p.poisontype; + poisonpaintype = p.poisonpaintype; + poisoner = p.poisoner; + attacker = p.attacker; + extralight = p.extralight; + fixedcolormap = p.fixedcolormap; + fixedlightlevel = p.fixedlightlevel; + memcpy(psprites, &p.psprites, sizeof(psprites)); + morphTics = p.morphTics; + MorphedPlayerClass = p.MorphedPlayerClass; + MorphStyle = p.MorphStyle; + MorphExitFlash = p.MorphExitFlash; + 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; + LastDamageType = p.LastDamageType; + savedyaw = p.savedyaw; + savedpitch = p.savedpitch; + angle = p.angle; + dest = p.dest; + prev = p.prev; + enemy = p.enemy; + missile = p.missile; + mate = p.mate; + last_mate = p.last_mate; + settings_controller = p.settings_controller; + skill = p.skill; + t_active = p.t_active; + t_respawn = p.t_respawn; + t_strafe = p.t_strafe; + t_react = p.t_react; + t_fight = p.t_fight; + t_roam = p.t_roam; + t_rocket = p.t_rocket; + isbot = p.isbot; + first_shot = p.first_shot; + sleft = p.sleft; + allround = p.allround; + oldx = p.oldx; + oldy = p.oldy; + BlendR = p.BlendR; + BlendG = p.BlendG; + BlendB = p.BlendB; + BlendA = p.BlendA; + LogText = p.LogText; + MinPitch = p.MinPitch; + MaxPitch = p.MaxPitch; + crouching = p.crouching; + crouchdir = p.crouchdir; + crouchfactor = p.crouchfactor; + crouchoffset = p.crouchoffset; + crouchviewdelta = p.crouchviewdelta; + weapons = p.weapons; + ConversationNPC = p.ConversationNPC; + ConversationPC = p.ConversationPC; + ConversationNPCAngle = p.ConversationNPCAngle; + ConversationFaceTalker = p.ConversationFaceTalker; + return *this; +} + // This function supplements the pointer cleanup in dobject.cpp, because // player_t is not derived from DObject. (I tried it, and DestroyScan was // unable to properly determine the player object's type--possibly @@ -1725,7 +1836,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; } @@ -1850,7 +1961,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: // @@ -1868,7 +1979,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); @@ -2039,12 +2150,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) { @@ -2230,6 +2341,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 @@ -2340,7 +2454,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; } @@ -2440,7 +2554,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; @@ -2448,9 +2562,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); } } @@ -2477,7 +2592,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); } @@ -2635,15 +2750,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; @@ -2675,6 +2816,7 @@ void P_UnPredictPlayer () if (player->cheats & CF_PREDICTING) { + unsigned int i; AActor *act = player->mo; AActor *savedcamera = player->camera; @@ -2684,23 +2826,99 @@ 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); - sector_list = NULL; - for (unsigned int i = PredictionTouchingSectorsBackup.Size (); i-- > 0; ) + // The blockmap ordering needs to remain unchanged, too. + // Restore sector links and refrences. + // [ED850] This is somewhat of a duplicate of LinkToWorld(), but we need to keep every thing the same, + // otherwise we end up fixing bugs in blockmap logic (i.e undefined behaviour with polyobject collisions), + // which we really don't want to do here. + if (!(act->flags & MF_NOSECTOR)) { - sector_list = P_AddSecnode (PredictionTouchingSectorsBackup[i], act, sector_list); - } + sector_t *sec = act->Sector; + AActor *me, *next; + AActor **link;// , **prev; - // 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; + // 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; + } + + // Destroy old refrences + msecnode_t *node = sector_list; + while (node) + { + node->m_thing = NULL; + node = node->m_tnext; + } + + // Make the sector_list match the player's touching_sectorlist before it got predicted. + P_DelSeclist(sector_list); + sector_list = NULL; + for (i = PredictionTouchingSectorsBackup.Size(); i-- > 0;) + { + sector_list = P_AddSecnode(PredictionTouchingSectorsBackup[i], act, sector_list); + } + act->touching_sectorlist = sector_list; // Attach to thing + sector_list = NULL; // clear for next time + + node = sector_list; + while (node) + { + if (node->m_thing == NULL) + { + if (node == sector_list) + sector_list = node->m_tnext; + node = P_DelSecnode(node); + } + else + { + node = node->m_tnext; + } + } + + 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; @@ -2720,14 +2938,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 @@ -2843,6 +3069,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) { @@ -2878,6 +3112,10 @@ void player_t::Serialize (FArchive &arc) oldbuttons = ~0; original_oldbuttons = ~0; } + if (skinname.IsNotEmpty()) + { + userinfo.SkinChanged(skinname, CurrentPlayerClass); + } } bool P_IsPlayerTotallyFrozen(const player_t *player) 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/po_man.cpp b/src/po_man.cpp index d844133b0..e19acc53a 100644 --- a/src/po_man.cpp +++ b/src/po_man.cpp @@ -950,18 +950,6 @@ void FPolyObj::UpdateBBox () // Update the line's slopetype line->dx = line->v2->x - line->v1->x; line->dy = line->v2->y - line->v1->y; - if (!line->dx) - { - line->slopetype = ST_VERTICAL; - } - else if (!line->dy) - { - line->slopetype = ST_HORIZONTAL; - } - else - { - line->slopetype = ((line->dy ^ line->dx) >= 0) ? ST_POSITIVE : ST_NEGATIVE; - } } CalcCenter(); } diff --git a/src/r_bsp.cpp b/src/r_bsp.cpp index 31dfe9907..bf0ac910f 100644 --- a/src/r_bsp.cpp +++ b/src/r_bsp.cpp @@ -51,13 +51,12 @@ #include "doomstat.h" #include "r_state.h" #include "r_bsp.h" +#include "r_segs.h" #include "v_palette.h" #include "r_sky.h" #include "po_man.h" #include "r_data/colormaps.h" -int WallMost (short *mostbuf, const secplane_t &plane); - seg_t* curline; side_t* sidedef; line_t* linedef; @@ -92,18 +91,8 @@ drawseg_t* ds_p; size_t FirstInterestingDrawseg; TArray InterestingDrawsegs; -fixed_t WallTX1, WallTX2; // x coords at left, right of wall in view space -fixed_t WallTY1, WallTY2; // y coords at left, right of wall in view space - -fixed_t WallCX1, WallCX2; // x coords at left, right of wall in camera space -fixed_t WallCY1, WallCY2; // y coords at left, right of wall in camera space - -int WallSX1, WallSX2; // x coords at left, right of wall in screen space -fixed_t WallSZ1, WallSZ2; // depth at left, right of wall in screen space - -float WallDepthOrg, WallDepthScale; -float WallUoverZorg, WallUoverZstep; -float WallInvZorg, WallInvZstep; +FWallCoords WallC; +FWallTmapVals WallT; static BYTE FakeSide; @@ -419,7 +408,7 @@ sector_t *R_FakeFlat(sector_t *sec, sector_t *tempsec, rw_frontcz2 <= s->floorplane.ZatPoint (curline->v2->x, curline->v2->y)) { // Check that the window is actually visible - for (int z = WallSX1; z < WallSX2; ++z) + for (int z = WallC.sx1; z < WallC.sx2; ++z) { if (floorclip[z] > ceilingclip[z]) { @@ -549,66 +538,15 @@ void R_AddLine (seg_t *line) if (DMulScale32 (ty1, tx1-tx2, tx1, ty2-ty1) >= 0) return; - WallTX1 = DMulScale20 (tx1, viewsin, -ty1, viewcos); - WallTX2 = DMulScale20 (tx2, viewsin, -ty2, viewcos); - - WallTY1 = DMulScale20 (tx1, viewtancos, ty1, viewtansin); - WallTY2 = DMulScale20 (tx2, viewtancos, ty2, viewtansin); - - if (MirrorFlags & RF_XFLIP) - { - int t = 256-WallTX1; - WallTX1 = 256-WallTX2; - WallTX2 = t; - swapvalues (WallTY1, WallTY2); - } - - if (WallTX1 >= -WallTY1) - { - if (WallTX1 > WallTY1) return; // left edge is off the right side - if (WallTY1 == 0) return; - WallSX1 = (centerxfrac + Scale (WallTX1, centerxfrac, WallTY1)) >> FRACBITS; - if (WallTX1 >= 0) WallSX1 = MIN (viewwidth, WallSX1+1); // fix for signed divide - WallSZ1 = WallTY1; - } - else - { - if (WallTX2 < -WallTY2) return; // wall is off the left side - fixed_t den = WallTX1 - WallTX2 - WallTY2 + WallTY1; - if (den == 0) return; - WallSX1 = 0; - WallSZ1 = WallTY1 + Scale (WallTY2 - WallTY1, WallTX1 + WallTY1, den); - } - - if (WallSZ1 < 32) + if (WallC.Init(tx1, ty1, tx2, ty2, 32)) return; - if (WallTX2 <= WallTY2) - { - if (WallTX2 < -WallTY2) return; // right edge is off the left side - if (WallTY2 == 0) return; - WallSX2 = (centerxfrac + Scale (WallTX2, centerxfrac, WallTY2)) >> FRACBITS; - if (WallTX2 >= 0) WallSX2 = MIN (viewwidth, WallSX2+1); // fix for signed divide - WallSZ2 = WallTY2; - } - else - { - if (WallTX1 > WallTY1) return; // wall is off the right side - fixed_t den = WallTY2 - WallTY1 - WallTX2 + WallTX1; - if (den == 0) return; - WallSX2 = viewwidth; - WallSZ2 = WallTY1 + Scale (WallTY2 - WallTY1, WallTX1 - WallTY1, den); - } - - if (WallSZ2 < 32 || WallSX2 <= WallSX1) - return; - - if (WallSX1 > WindowRight || WallSX2 < WindowLeft) + if (WallC.sx1 > WindowRight || WallC.sx2 < WindowLeft) return; if (line->linedef == NULL) { - if (R_CheckClipWallSegment (WallSX1, WallSX2)) + if (R_CheckClipWallSegment (WallC.sx1, WallC.sx2)) { InSubsector->flags |= SSECF_DRAWN; } @@ -622,20 +560,7 @@ void R_AddLine (seg_t *line) if ((v1 == line->v1 && v2 == line->v2) || (v2 == line->v1 && v1 == line->v2)) { // The seg is the entire wall. - if (MirrorFlags & RF_XFLIP) - { - WallUoverZorg = (float)WallTX2 * WallTMapScale; - WallUoverZstep = (float)(-WallTY2) * 32.f; - WallInvZorg = (float)(WallTX2 - WallTX1) * WallTMapScale; - WallInvZstep = (float)(WallTY1 - WallTY2) * 32.f; - } - else - { - WallUoverZorg = (float)WallTX1 * WallTMapScale; - WallUoverZstep = (float)(-WallTY1) * 32.f; - WallInvZorg = (float)(WallTX1 - WallTX2) * WallTMapScale; - WallInvZstep = (float)(WallTY2 - WallTY1) * 32.f; - } + WallT.InitFromWallCoords(&WallC); } else { // The seg is only part of the wall. @@ -643,29 +568,8 @@ void R_AddLine (seg_t *line) { swapvalues (v1, v2); } - tx1 = v1->x - viewx; - tx2 = v2->x - viewx; - ty1 = v1->y - viewy; - ty2 = v2->y - viewy; - - fixed_t fullx1 = DMulScale20 (tx1, viewsin, -ty1, viewcos); - fixed_t fullx2 = DMulScale20 (tx2, viewsin, -ty2, viewcos); - fixed_t fully1 = DMulScale20 (tx1, viewtancos, ty1, viewtansin); - fixed_t fully2 = DMulScale20 (tx2, viewtancos, ty2, viewtansin); - - if (MirrorFlags & RF_XFLIP) - { - fullx1 = -fullx1; - fullx2 = -fullx2; - } - - WallUoverZorg = (float)fullx1 * WallTMapScale; - WallUoverZstep = (float)(-fully1) * 32.f; - WallInvZorg = (float)(fullx1 - fullx2) * WallTMapScale; - WallInvZstep = (float)(fully2 - fully1) * 32.f; + WallT.InitFromLine(v1->x - viewx, v1->y - viewy, v2->x - viewx, v2->y - viewy); } - WallDepthScale = WallInvZstep * WallTMapScale2; - WallDepthOrg = -WallUoverZstep * WallTMapScale2; if (!(fake3D & FAKE3D_FAKEBACK)) { @@ -703,12 +607,12 @@ void R_AddLine (seg_t *line) if (rw_frontcz1 > rw_backcz1 || rw_frontcz2 > rw_backcz2) { rw_havehigh = true; - WallMost (wallupper, backsector->ceilingplane); + WallMost (wallupper, backsector->ceilingplane, &WallC); } if (rw_frontfz1 < rw_backfz1 || rw_frontfz2 < rw_backfz2) { rw_havelow = true; - WallMost (walllower, backsector->floorplane); + WallMost (walllower, backsector->floorplane, &WallC); } // Closed door. @@ -791,7 +695,7 @@ void R_AddLine (seg_t *line) // mark their subsectors as visible for automap texturing. if (hasglnodes && !(InSubsector->flags & SSECF_DRAWN)) { - if (R_CheckClipWallSegment(WallSX1, WallSX2)) + if (R_CheckClipWallSegment(WallC.sx1, WallC.sx2)) { InSubsector->flags |= SSECF_DRAWN; } @@ -805,13 +709,13 @@ void R_AddLine (seg_t *line) if (line->linedef->special == Line_Horizon) { // Be aware: Line_Horizon does not work properly with sloped planes - clearbufshort (walltop+WallSX1, WallSX2 - WallSX1, centery); - clearbufshort (wallbottom+WallSX1, WallSX2 - WallSX1, centery); + clearbufshort (walltop+WallC.sx1, WallC.sx2 - WallC.sx1, centery); + clearbufshort (wallbottom+WallC.sx1, WallC.sx2 - WallC.sx1, centery); } else { - rw_ceilstat = WallMost (walltop, frontsector->ceilingplane); - rw_floorstat = WallMost (wallbottom, frontsector->floorplane); + rw_ceilstat = WallMost (walltop, frontsector->ceilingplane, &WallC); + rw_floorstat = WallMost (wallbottom, frontsector->floorplane, &WallC); // [RH] treat off-screen walls as solid #if 0 // Maybe later... @@ -831,12 +735,112 @@ void R_AddLine (seg_t *line) #endif } - if (R_ClipWallSegment (WallSX1, WallSX2, solid)) + if (R_ClipWallSegment (WallC.sx1, WallC.sx2, solid)) { InSubsector->flags |= SSECF_DRAWN; } } +// +// FWallCoords :: Init +// +// Transform and clip coordinates. Returns true if it was clipped away +// +bool FWallCoords::Init(int x1, int y1, int x2, int y2, int too_close) +{ + tx1 = DMulScale20(x1, viewsin, -y1, viewcos); + tx2 = DMulScale20(x2, viewsin, -y2, viewcos); + + ty1 = DMulScale20(x1, viewtancos, y1, viewtansin); + ty2 = DMulScale20(x2, viewtancos, y2, viewtansin); + + if (MirrorFlags & RF_XFLIP) + { + int t = 256 - tx1; + tx1 = 256 - tx2; + tx2 = t; + swapvalues(ty1, ty2); + } + + if (tx1 >= -ty1) + { + if (tx1 > ty1) return true; // left edge is off the right side + if (ty1 == 0) return true; + sx1 = (centerxfrac + Scale(tx1, centerxfrac, ty1)) >> FRACBITS; + if (tx1 >= 0) sx1 = MIN(viewwidth, sx1+1); // fix for signed divide + sz1 = ty1; + } + else + { + if (tx2 < -ty2) return true; // wall is off the left side + fixed_t den = tx1 - tx2 - ty2 + ty1; + if (den == 0) return true; + sx1 = 0; + sz1 = ty1 + Scale(ty2 - ty1, tx1 + ty1, den); + } + + if (sz1 < too_close) + return true; + + if (tx2 <= ty2) + { + if (tx2 < -ty2) return true; // right edge is off the left side + if (ty2 == 0) return true; + sx2 = (centerxfrac + Scale(tx2, centerxfrac, ty2)) >> FRACBITS; + if (tx2 >= 0) sx2 = MIN(viewwidth, sx2+1); // fix for signed divide + sz2 = ty2; + } + else + { + if (tx1 > ty1) return true; // wall is off the right side + fixed_t den = ty2 - ty1 - tx2 + tx1; + if (den == 0) return true; + sx2 = viewwidth; + sz2 = ty1 + Scale(ty2 - ty1, tx1 - ty1, den); + } + + if (sz2 < too_close || sx2 <= sx1) + return true; + + return false; +} + +void FWallTmapVals::InitFromWallCoords(const FWallCoords *wallc) +{ + if (MirrorFlags & RF_XFLIP) + { + UoverZorg = (float)wallc->tx2 * centerx; + UoverZstep = (float)(-wallc->ty2); + InvZorg = (float)(wallc->tx2 - wallc->tx1) * centerx; + InvZstep = (float)(wallc->ty1 - wallc->ty2); + } + else + { + UoverZorg = (float)wallc->tx1 * centerx; + UoverZstep = (float)(-wallc->ty1); + InvZorg = (float)(wallc->tx1 - wallc->tx2) * centerx; + InvZstep = (float)(wallc->ty2 - wallc->ty1); + } +} + +void FWallTmapVals::InitFromLine(int tx1, int ty1, int tx2, int ty2) +{ // Coordinates should have already had viewx,viewy subtracted + fixed_t fullx1 = DMulScale20 (tx1, viewsin, -ty1, viewcos); + fixed_t fullx2 = DMulScale20 (tx2, viewsin, -ty2, viewcos); + fixed_t fully1 = DMulScale20 (tx1, viewtancos, ty1, viewtansin); + fixed_t fully2 = DMulScale20 (tx2, viewtancos, ty2, viewtansin); + + if (MirrorFlags & RF_XFLIP) + { + fullx1 = -fullx1; + fullx2 = -fullx2; + } + + UoverZorg = (float)fullx1 * centerx; + UoverZstep = (float)(-fully1); + InvZorg = (float)(fullx1 - fullx2) * centerx; + InvZstep = (float)(fully2 - fully1); +} // // R_CheckBBox diff --git a/src/r_bsp.h b/src/r_bsp.h index da20fb90c..acd519c62 100644 --- a/src/r_bsp.h +++ b/src/r_bsp.h @@ -26,6 +26,34 @@ #include "tarray.h" #include +// The 3072 below is just an arbitrary value picked to avoid +// drawing lines the player is too close to that would overflow +// the texture calculations. +#define TOO_CLOSE_Z 3072 + +struct FWallCoords +{ + fixed_t tx1, tx2; // x coords at left, right of wall in view space rx1,rx2 + fixed_t ty1, ty2; // y coords at left, right of wall in view space ry1,ry2 + + short sx1, sx2; // x coords at left, right of wall in screen space xb1,xb2 + fixed_t sz1, sz2; // depth at left, right of wall in screen space yb1,yb2 + + bool Init(int x1, int y1, int x2, int y2, int too_close); +}; + +struct FWallTmapVals +{ + float UoverZorg, UoverZstep; + float InvZorg, InvZstep; + + void InitFromWallCoords(const FWallCoords *wallc); + void InitFromLine(int x1, int y1, int x2, int y2); +}; + +extern FWallCoords WallC; +extern FWallTmapVals WallT; + enum { FAKED_Center, @@ -33,7 +61,6 @@ enum FAKED_AboveCeiling }; - struct drawseg_t { seg_t* curline; @@ -58,7 +85,7 @@ struct drawseg_t int fake; // ident fake drawseg, don't draw and clip sprites // backups ptrdiff_t bkup; // sprtopclip backup, for mid and fake textures - float WallUoverZorg, WallUoverZstep, WallInvZorg, WallInvZstep, WallDepthScale, WallDepthOrg; + FWallTmapVals tmapvals; }; 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 3f5b7a522..e01aad725 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); @@ -924,8 +926,6 @@ void R_InitSprites () numskins++; } - SpriteFrames.Clear(); - // [RH] Do some preliminary setup if (skins != NULL) delete [] skins; skins = new FPlayerSkin[numskins]; @@ -997,4 +997,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..dd2136508 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; @@ -881,18 +882,6 @@ struct side_t FArchive &operator<< (FArchive &arc, side_t::part &p); -// -// Move clipping aid for LineDefs. -// -enum slopetype_t -{ - ST_HORIZONTAL, - ST_VERTICAL, - ST_POSITIVE, - ST_NEGATIVE -}; - - struct line_t { vertex_t *v1, *v2; // vertices, from v1 to v2 @@ -907,7 +896,6 @@ struct line_t side_t *sidedef[2]; //DWORD sidenum[2]; // sidenum[1] will be NO_SIDE if one sided fixed_t bbox[4]; // bounding box, for the extent of the LineDef. - slopetype_t slopetype; // To aid move clipping. sector_t *frontsector, *backsector; int validcount; // if == validcount, already checked int locknumber; // [Dusk] lock number for special diff --git a/src/r_main.cpp b/src/r_main.cpp index edb13d326..dbf4cbeb5 100644 --- a/src/r_main.cpp +++ b/src/r_main.cpp @@ -72,8 +72,6 @@ // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- void R_SpanInitData (); -void RP_RenderBSPNode (void *node); -bool RP_SetupFrame (bool backside); void R_DeinitSprites(); // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- @@ -94,14 +92,12 @@ extern "C" int fuzzviewheight; static float CurrentVisibility = 8.f; static fixed_t MaxVisForWall; static fixed_t MaxVisForFloor; -static bool polyclipped; extern bool r_showviewer; bool r_dontmaplines; // PUBLIC DATA DEFINITIONS ------------------------------------------------- CVAR (String, r_viewsize, "", CVAR_NOSET) -CVAR (Int, r_polymost, 0, 0) CVAR (Bool, r_shadercolormaps, true, CVAR_ARCHIVE) fixed_t r_BaseVisibility; @@ -121,7 +117,6 @@ FDynamicColormap*basecolormap; // [RH] colormap currently drawing with int fixedlightlev; lighttable_t *fixedcolormap; FSpecialColormap *realfixedcolormap; -float WallTMapScale; float WallTMapScale2; @@ -390,8 +385,7 @@ void R_SWRSetWindow(int windowSize, int fullWidth, int fullHeight, int stHeight, iyaspectmulfloat = (float)virtwidth * r_Yaspect / 320.f / (float)virtheight; InvZtoScale = yaspectmul * centerx; - WallTMapScale = (float)centerx * 32.f; - WallTMapScale2 = iyaspectmulfloat * 2.f / (float)centerx; + WallTMapScale2 = iyaspectmulfloat * 64.f / (float)centerx; // psprite scales pspritexscale = (centerxwide << FRACBITS) / 160; @@ -612,14 +606,6 @@ void R_SetupFreelook() } } -void R_SetupPolymost() -{ - if (r_polymost) - { - polyclipped = RP_SetupFrame (false); - } -} - //========================================================================== // // R_EnterMirror @@ -706,10 +692,6 @@ void R_EnterMirror (drawseg_t *ds, int depth) R_EnterMirror (drawsegs + WallMirrors[mirrorsAtStart], depth + 1); } } - else - { - depth = depth; - } viewangle = startang; viewx = startx; @@ -816,11 +798,8 @@ void R_RenderActorView (AActor *actor, bool dontmaplines) } // Link the polyobjects right before drawing the scene to reduce the amounts of calls to this function PO_LinkToSubsectors(); - if (r_polymost < 2) - { - R_RenderBSPNode (nodes + numnodes - 1); // The head node is the last node output. - R_3D_ResetClip(); // reset clips (floor/ceiling) - } + R_RenderBSPNode (nodes + numnodes - 1); // The head node is the last node output. + R_3D_ResetClip(); // reset clips (floor/ceiling) camera->renderflags = savedflags; WallCycles.Unclock(); @@ -847,16 +826,6 @@ void R_RenderActorView (AActor *actor, bool dontmaplines) MaskedCycles.Unclock(); NetUpdate (); - - if (r_polymost) - { - RP_RenderBSPNode (nodes + numnodes - 1); - if (polyclipped) - { - RP_SetupFrame (true); - RP_RenderBSPNode (nodes + numnodes - 1); - } - } } WallMirrors.Clear (); interpolator.RestoreInterpolations (); diff --git a/src/r_main.h b/src/r_main.h index 0126d3906..715a60610 100644 --- a/src/r_main.h +++ b/src/r_main.h @@ -42,7 +42,6 @@ extern fixed_t FocalLengthX, FocalLengthY; extern float FocalLengthXfloat; extern fixed_t InvZtoScale; -extern float WallTMapScale; extern float WallTMapScale2; extern int viewwindowx; 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_polymost.cpp b/src/r_polymost.cpp deleted file mode 100644 index e7963faa2..000000000 --- a/src/r_polymost.cpp +++ /dev/null @@ -1,1599 +0,0 @@ -/************************************************************************************************** -"POLYMOST" code written by Ken Silverman -Ken Silverman's official web site: http://www.advsys.net/ken -This file has been modified (severely) from Ken Silverman's original release - -Motivation: -When 3D Realms released the Duke Nukem 3D source code, I thought somebody would do a OpenGL or -Direct3D port. Well, after a few months passed, I saw no sign of somebody working on a true -hardware-accelerated port of Build, just people saying it wasn't possible. Eventually, I realized -the only way this was going to happen was for me to do it myself. First, I needed to port Build to -Windows. I could have done it myself, but instead I thought I'd ask my Australian buddy, Jonathon -Fowler, if he would upgrade his Windows port to my favorite compiler (MSVC) - which he did. Once -that was done, I was ready to start the "POLYMOST" project. - -About: -This source file is basically a complete rewrite of the entire rendering part of the Build engine. -There are small pieces in ENGINE.C to activate this code, and other minor hacks in other source -files, but most of it is in here. If you're looking for polymost-related code in the other source -files, you should find most of them by searching for either "polymost" or "rendmode". Speaking of -rendmode, there are now 4 rendering modes in Build: - - rendmode 0: The original code I wrote from 1993-1997 - rendmode 1: Solid-color rendering: my debug code before I did texture mapping - rendmode 2: Software rendering before I started the OpenGL code (Note: this is just a quick - hack to make testing easier - it's not optimized to my usual standards!) - rendmode 3: The OpenGL code - -The original Build engine did hidden surface removal by using a vertical span buffer on the tops -and bottoms of walls. This worked nice back in the day, but it it's not suitable for a polygon -engine. So I decided to write a brand new hidden surface removal algorithm - using the same idea -as the original Build - but one that worked with vectors instead of already rasterized data. - -Brief history: -06/20/2000: I release Build Source code -04/01/2003: 3D Realms releases Duke Nukem 3D source code -10/04/2003: Jonathon Fowler gets his Windows port working in Visual C -10/04/2003: I start writing POLYMOST.BAS, a new hidden surface removal algorithm for Build that - works on a polygon level instead of spans. -10/16/2003: Ported POLYMOST.BAS to C inside JonoF KenBuild's ENGINE.C; later this code was split - out of ENGINE.C and put in this file, POLYMOST.C. -12/10/2003: Started OpenGL code for POLYMOST (rendmode 3) -12/23/2003: 1st public release -01/01/2004: 2nd public release: fixed stray lines, status bar, mirrors, sky, and lots of other bugs. - ----------------------------------------------------------------------------------------------------- - -Todo list (in approximate chronological order): - -High priority: - * BOTH: Do accurate software sorting/chopping for sprites: drawing in wrong order is bad :/ - * BOTH: Fix hall of mirrors near "zenith". Call polymost_drawrooms twice? - * OPENGL: drawmapview() - -Low priority: - * SOFT6D: Do back-face culling of sprites during up/down/tilt transformation (top of drawpoly) - * SOFT6D: Fix depth shading: use saturation&LUT - * SOFT6D: Optimize using hyperbolic mapping (similar to KUBE algo) - * SOFT6D: Slab6-style voxel sprites. How to accelerate? :/ - * OPENGL: KENBUILD: Write flipping code for floor mirrors - * BOTH: KENBUILD: Parallaxing sky modes 1&2 - * BOTH: Masked/1-way walls don't clip correctly to sectors of intersecting ceiling/floor slopes - * BOTH: Editart x-center is not working correctly with Duke's camera/turret sprites - * BOTH: Get rid of horizontal line above Duke full-screen status bar - * BOTH: Combine ceilings/floors into a single triangle strip (should lower poly count by 2x) - * BOTH: Optimize/clean up texture-map setup equations - -**************************************************************************************************/ - -#include -#include -#include -#include "doomtype.h" -#include "r_polymost.h" -#include "c_cvars.h" -#include "c_dispatch.h" -#include "r_main.h" -#include "r_draw.h" -#include "templates.h" -#include "r_sky.h" -#include "g_level.h" -#include "r_bsp.h" -#include "v_palette.h" -#include "v_font.h" -#include "v_video.h" -#include "r_data/colormaps.h" - -EXTERN_CVAR (Int, r_polymost) - -#define SCISDIST 1.0 //1.0: Close plane clipping distance - -static double gyxscale, gxyaspect, gviewxrange, ghalfx, grhalfxdown10, grhalfxdown10x, ghoriz; -static double gcosang, gsinang, gcosang2, gsinang2; -static double gchang, gshang, gctang, gstang; -//static float gtang = 0.0; -CVAR (Float, gtang, 0, 0); -double guo, gux, guy; //Screen-based texture mapping parameters -double gvo, gvx, gvy; -double gdo, gdx, gdy; - -#ifdef _MSC_VER -#pragma warning (disable:4244) -#endif - -PolyClipper::PolyClipper () - : vsps (&EmptyList) -{ - UsedList.Next = UsedList.Prev = &UsedList; -} - -PolyClipper::~PolyClipper () -{ - vspgroup *probe = vsps.NextGroup; - while (probe != NULL) - { - vspgroup *next = probe->NextGroup; - delete probe; - probe = next; - } -} - -PolyClipper::vspgroup::vspgroup (vsptype *sentinel) -{ - int i; - - NextGroup = NULL; - vsp[0].Prev = sentinel; - vsp[0].Next = &vsp[1]; - for (i = 1; i < GROUP_SIZE-1; ++i) - { - vsp[i].Next = &vsp[i+1]; - vsp[i].Prev = &vsp[i-1]; - } - vsp[i].Next = sentinel; - vsp[i].Prev = &vsp[i-1]; - sentinel->Next = &vsp[0]; - sentinel->Prev = &vsp[i]; -} - - /*Init viewport boundary (must be 4 point convex loop): - // (px[0],py[0]).----.(px[1],py[1]) - // / \ - // / \ - // (px[3],py[3]).--------------.(px[2],py[2]) - */ -void PolyClipper::InitMosts (double *px, double *py, int n) -{ - int i, j, k, imin; - int vcnt; - vsptype *vsp[8]; - - EmptyAll (); - vcnt = 1; // 0 is dummy solid node - - if (n < 3) return; - imin = (px[1] < px[0]); - for(i=n-1;i>=2;i--) if (px[i] < px[imin]) imin = i; - - vsp[0] = &UsedList; - vsp[vcnt] = GetVsp (); - vsp[vcnt]->X = px[imin]; - vsp[vcnt]->Cy[0] = vsp[vcnt]->Fy[0] = py[imin]; - vsp[vcnt]->CTag = vsp[vcnt]->FTag = 1; - vcnt++; - i = imin+1; if (i >= n) i = 0; - j = imin-1; if (j < 0) j = n-1; - do - { - if (px[i] < px[j]) - { - if ((vcnt > 1) && (px[i] - vsp[vcnt-1]->X < 0.00001)) vcnt--; - else vsp[vcnt] = GetVsp (); - vsp[vcnt]->X = px[i]; - vsp[vcnt]->Cy[0] = py[i]; - k = j+1; if (k >= n) k = 0; - //(px[k],py[k]) - //(px[i],?) - //(px[j],py[j]) - vsp[vcnt]->Fy[0] = (px[i]-px[k])*(py[j]-py[k])/(px[j]-px[k]) + py[k]; - if (vcnt > 1) - { - vsp[vcnt]->CTag = vsp[vcnt-1]->CTag + 1; - vsp[vcnt]->FTag = vsp[vcnt-1]->FTag; - } - vcnt++; - i++; if (i >= n) i = 0; - } - else if (px[j] < px[i]) - { - if ((vcnt > 1) && (px[j] - vsp[vcnt-1]->X < 0.00001)) vcnt--; - else vsp[vcnt] = GetVsp (); - vsp[vcnt]->X = px[j]; - vsp[vcnt]->Fy[0] = py[j]; - k = i-1; if (k < 0) k = n-1; - //(px[k],py[k]) - //(px[j],?) - //(px[i],py[i]) - vsp[vcnt]->Cy[0] = (px[j]-px[k])*(py[i]-py[k])/(px[i]-px[k]) + py[k]; - if (vcnt > 1) - { - vsp[vcnt]->FTag = vsp[vcnt-1]->FTag + 1; - vsp[vcnt]->CTag = vsp[vcnt-1]->CTag; - } - vcnt++; - j--; if (j < 0) j = n-1; - } - else - { - if ((vcnt > 1) && (px[i] - vsp[vcnt-1]->X < 0.00001)) vcnt--; - else vsp[vcnt] = GetVsp (); - vsp[vcnt]->X = px[i]; - vsp[vcnt]->Cy[0] = py[i]; - vsp[vcnt]->Fy[0] = py[j]; - if (vcnt > 1) - { - vsp[vcnt]->CTag = vsp[vcnt-1]->CTag + 1; - vsp[vcnt]->FTag = vsp[vcnt-1]->FTag + 1; - } - vcnt++; - i++; if (i >= n) i = 0; if (i == j) break; - j--; if (j < 0) j = n-1; - } - } while (i != j); - if (px[i] > vsp[vcnt-1]->X) - { - vsp[vcnt] = GetVsp (); - vsp[vcnt]->X = px[i]; - vsp[vcnt]->Cy[0] = vsp[vcnt]->Fy[0] = py[i]; - vsp[vcnt]->CTag = vsp[vcnt-1]->CTag + 1; - vsp[vcnt]->FTag = vsp[vcnt-1]->FTag + 1; - vcnt++; - } - - assert (vcnt < 8); - - vsp[vcnt-1]->CTag = vsp[vcnt-1]->FTag = vcnt-1; - for(i=0;iCy[1] = vsp[i+1]->Cy[0]; //vsp[i]->CTag = i; - vsp[i]->Fy[1] = vsp[i+1]->Fy[0]; //vsp[i]->FTag = i; - vsp[i]->Next = vsp[i+1]; vsp[i]->Prev = vsp[i-1]; - } - vsp[vcnt-1]->Next = &UsedList; UsedList.Prev = vsp[vcnt-1]; - GTag = vcnt; -} - -void PolyClipper::EmptyAll () -{ - if (UsedList.Next != &UsedList) - { - if (EmptyList.Next != &EmptyList) - { - // Move the used list to the start of the empty list - UsedList.Prev->Next = EmptyList.Next; - EmptyList.Next = UsedList.Next; - UsedList.Next->Prev = &EmptyList; - } - else - { - // The empty list is empty, so we can just move the - // used list to the empty list. - EmptyList.Next = UsedList.Next; - EmptyList.Prev = UsedList.Prev; - } - UsedList.Next = UsedList.Prev = &UsedList; - } -} - -void PolyClipper::AddGroup () -{ - vspgroup *group = new vspgroup (&EmptyList); - group->NextGroup = vsps.NextGroup; - vsps.NextGroup = group; -} - -PolyClipper::vsptype *PolyClipper::GetVsp () -{ - vsptype *vsp; - - if (EmptyList.Next == &EmptyList) - { - AddGroup (); - } - vsp = EmptyList.Next; - EmptyList.Next = vsp->Next; - vsp->Next->Prev = &EmptyList; - return vsp; -} - -void PolyClipper::FreeVsp (vsptype *vsp) -{ - vsp->Next->Prev = vsp->Prev; - vsp->Prev->Next = vsp->Next; - - vsp->Next = EmptyList.Next; - vsp->Next->Prev = vsp; - vsp->Prev = &EmptyList; - EmptyList.Next = vsp; -} - -PolyClipper::vsptype *PolyClipper::vsinsaft (vsptype *i) -{ - vsptype *r; - - // Get an element from the empty list - r = GetVsp (); - - *r = *i; // Copy i to r - - // Insert r after i - r->Prev = i; - r->Next = i->Next; - i->Next->Prev = r; - i->Next = r; - - return r; -} - -bool PolyClipper::TestVisibleMost (float x0, float x1) -{ - vsptype *i, *newi; - - for (i = UsedList.Next; i != &UsedList; i = newi) - { - newi = i->Next; - if ((x0 < newi->X) && (i->X < x1) && (i->CTag >= 0)) return true; - } - return false; -} - -int PolyClipper::DoMost (float x0, float y0, float x1, float y1, pmostcallbacktype callback, void *callbackdata) -{ - double dpx[4], dpy[4]; - float f, slop, dx0, dx1, nx, nx0, ny0, nx1, ny1; - double dx, d, n, t; - float spx[4], spy[4], cy[2], cv[2]; - int j, k, z, scnt, dir, spt[4]; - vsptype *vsp, *nvsp, *vcnt = NULL, *ni; - int did = 1; - - if (x0 < x1) - { - dir = 1; //clip dmost (floor) - y0 -= .01f; y1 -= .01f; - } - else - { - if (x0 == x1) return 0; - f = x0; x0 = x1; x1 = f; - f = y0; y0 = y1; y1 = f; - dir = 0; //clip umost (ceiling) - //y0 += .01f; y1 += .01f; //necessary? - } - - slop = (y1-y0)/(x1-x0); - for (vsp = UsedList.Next; vsp != &UsedList; vsp = nvsp) - { - nvsp = vsp->Next; nx0 = vsp->X; nx1 = nvsp->X; - if ((x0 >= nx1) || (nx0 >= x1) || (vsp->CTag <= 0)) continue; - dx = nx1-nx0; - cy[0] = vsp->Cy[0]; cv[0] = vsp->Cy[1]-cy[0]; - cy[1] = vsp->Fy[0]; cv[1] = vsp->Fy[1]-cy[1]; - - scnt = 0; - - //Test if left edge requires split (x0,y0) (nx0,cy(0)), - if ((x0 > nx0) && (x0 < nx1)) - { - t = (x0-nx0)*cv[dir] - (y0-cy[dir])*dx; - if (((!dir) && (t < 0)) || ((dir) && (t > 0))) - { spx[scnt] = x0; spy[scnt] = y0; spt[scnt] = -1; scnt++; } - } - - //Test for intersection on umost (j == 0) and dmost (j == 1) - for(j=0;j<2;j++) - { - d = (y0-y1)*dx - (x0-x1)*cv[j]; - n = (y0-cy[j])*dx - (x0-nx0)*cv[j]; - if ((fabsf(n) <= fabsf(d)) && (d*n >= 0) && (d != 0)) - { - t = n/d; nx = (x1-x0)*t + x0; - if ((nx > nx0) && (nx < nx1)) - { - spx[scnt] = nx; spy[scnt] = (y1-y0)*t + y0; - spt[scnt] = j; scnt++; - } - } - } - - //Nice hack to avoid full sort later :) - if ((scnt >= 2) && (spx[scnt-1] < spx[scnt-2])) - { - f = spx[scnt-1]; spx[scnt-1] = spx[scnt-2]; spx[scnt-2] = f; - f = spy[scnt-1]; spy[scnt-1] = spy[scnt-2]; spy[scnt-2] = f; - j = spt[scnt-1]; spt[scnt-1] = spt[scnt-2]; spt[scnt-2] = j; - } - - //Test if right edge requires split - if ((x1 > nx0) && (x1 < nx1)) - { - t = (x1-nx0)*cv[dir] - (y1-cy[dir])*dx; - if (((!dir) && (t < 0)) || ((dir) && (t > 0))) - { spx[scnt] = x1; spy[scnt] = y1; spt[scnt] = -1; scnt++; } - } - - vsp->Tag = nvsp->Tag = -1; - for(z = 0; z <= scnt; z++, vsp = vcnt) - { - if (z < scnt) - { - vcnt = vsinsaft(vsp); - t = (spx[z]-nx0)/dx; - vsp->Cy[1] = t*cv[0] + cy[0]; - vsp->Fy[1] = t*cv[1] + cy[1]; - vcnt->X = spx[z]; - vcnt->Cy[0] = vsp->Cy[1]; - vcnt->Fy[0] = vsp->Fy[1]; - vcnt->Tag = spt[z]; - } - - ni = vsp->Next; if (ni == &UsedList) continue; //this 'if' fixes many bugs! - dx0 = vsp->X; if (x0 > dx0) continue; - dx1 = ni->X; if (x1 < dx1) continue; - ny0 = (dx0-x0)*slop + y0; - ny1 = (dx1-x0)*slop + y0; - - // dx0 dx1 - // ³ ³ - //---------------------------- - // t0+=0 t1+=0 - // vsp[i].cy[0] vsp[i].cy[1] - //============================ - // t0+=1 t1+=3 - //============================ - // vsp[i].fy[0] vsp[i].fy[1] - // t0+=2 t1+=6 - // - // ny0 ? ny1 ? - - k = 1+3; - if ((vsp->Tag == 0) || (ny0 <= vsp->Cy[0]+.01)) k--; - if ((vsp->Tag == 1) || (ny0 >= vsp->Fy[0]-.01)) k++; - if ((ni->Tag == 0) || (ny1 <= vsp->Cy[1]+.01)) k -= 3; - if ((ni->Tag == 1) || (ny1 >= vsp->Fy[1]-.01)) k += 3; - - if (!dir) - { - switch(k) - { - case 1: case 2: - dpx[0] = dx0; dpy[0] = vsp->Cy[0]; - dpx[1] = dx1; dpy[1] = vsp->Cy[1]; - dpx[2] = dx0; dpy[2] = ny0; - if(callback) callback(dpx,dpy,3,callbackdata); - vsp->Cy[0] = ny0; vsp->CTag = GTag; break; - case 3: case 6: - dpx[0] = dx0; dpy[0] = vsp->Cy[0]; - dpx[1] = dx1; dpy[1] = vsp->Cy[1]; - dpx[2] = dx1; dpy[2] = ny1; - if(callback) callback(dpx,dpy,3,callbackdata); - vsp->Cy[1] = ny1; vsp->CTag = GTag; break; - case 4: case 5: case 7: - dpx[0] = dx0; dpy[0] = vsp->Cy[0]; - dpx[1] = dx1; dpy[1] = vsp->Cy[1]; - dpx[2] = dx1; dpy[2] = ny1; - dpx[3] = dx0; dpy[3] = ny0; - if(callback) callback(dpx,dpy,4,callbackdata); - vsp->Cy[0] = ny0; vsp->Cy[1] = ny1; vsp->CTag = GTag; break; - case 8: - dpx[0] = dx0; dpy[0] = vsp->Cy[0]; - dpx[1] = dx1; dpy[1] = vsp->Cy[1]; - dpx[2] = dx1; dpy[2] = vsp->Fy[1]; - dpx[3] = dx0; dpy[3] = vsp->Fy[0]; - if(callback) callback(dpx,dpy,4,callbackdata); - vsp->CTag = vsp->FTag = -1; break; - default: did = 0; break; - } - } - else - { - switch(k) - { - case 7: case 6: - dpx[0] = dx0; dpy[0] = ny0; - dpx[1] = dx1; dpy[1] = vsp->Fy[1]; - dpx[2] = dx0; dpy[2] = vsp->Fy[0]; - if(callback) callback(dpx,dpy,3,callbackdata); - vsp->Fy[0] = ny0; vsp->FTag = GTag; break; - case 5: case 2: - dpx[0] = dx0; dpy[0] = vsp->Fy[0]; - dpx[1] = dx1; dpy[1] = ny1; - dpx[2] = dx1; dpy[2] = vsp->Fy[1]; - if(callback) callback(dpx,dpy,3,callbackdata); - vsp->Fy[1] = ny1; vsp->FTag = GTag; break; - case 4: case 3: case 1: - dpx[0] = dx0; dpy[0] = ny0; - dpx[1] = dx1; dpy[1] = ny1; - dpx[2] = dx1; dpy[2] = vsp->Fy[1]; - dpx[3] = dx0; dpy[3] = vsp->Fy[0]; - if(callback) callback(dpx,dpy,4,callbackdata); - vsp->Fy[0] = ny0; vsp->Fy[1] = ny1; vsp->FTag = GTag; break; - case 0: - dpx[0] = dx0; dpy[0] = vsp->Cy[0]; - dpx[1] = dx1; dpy[1] = vsp->Cy[1]; - dpx[2] = dx1; dpy[2] = vsp->Fy[1]; - dpx[3] = dx0; dpy[3] = vsp->Fy[0]; - if(callback) callback(dpx,dpy,4,callbackdata); - vsp->CTag = vsp->FTag = -1; break; - default: did = 0; break; - } - } - } - } - - GTag++; - - //Combine neighboring vertical strips with matching collinear top&bottom edges - //This prevents x-splits from propagating through the entire scan - vsp = UsedList.Next; - while (vsp->Next != &UsedList) - { - ni = vsp->Next; - if ((vsp->Cy[0] >= vsp->Fy[0]) && (vsp->Cy[1] >= vsp->Fy[1])) - { vsp->CTag = vsp->FTag = -1; } - if ((vsp->CTag == ni->CTag) && (vsp->FTag == ni->FTag)) - { vsp->Cy[1] = ni->Cy[1]; vsp->Fy[1] = ni->Fy[1]; FreeVsp (ni); } - else vsp = ni; - } - return did; -} - -#include "d_event.h" -static int pmx, pmy; -static int pt, px0, py0, px1, py1; -static struct polypt { float x, y; } polypts[80]; -static BYTE polysize[32]; -static int numpoly, polypt; -PolyClipper TestPoly; - -void drawline2d (float x1, float y1, float x2, float y2, BYTE col) -{ - float dx, dy, fxresm1, fyresm1, f; - long i, x, y, xi, yi, xup16, yup16; - - //Always draw lines in same direction - if ((y2 > y1) || ((y2 == y1) && (x2 > x1))) { f = x1; x1 = x2; x2 = f; f = y1; y1 = y2; y2 = f; } - - dx = x2-x1; dy = y2-y1; if ((dx == 0) && (dy == 0)) return; - fxresm1 = (float)RenderTarget->GetWidth()-.5; fyresm1 = (float)RenderTarget->GetHeight()-.5; - if (x1 >= fxresm1) { if (x2 >= fxresm1) return; y1 += (fxresm1-x1)*dy/dx; x1 = fxresm1; } - else if (x1 < 0) { if (x2 < 0) return; y1 += ( 0-x1)*dy/dx; x1 = 0; } - if (x2 >= fxresm1) { y2 += (fxresm1-x2)*dy/dx; x2 = fxresm1; } - else if (x2 < 0) { y2 += ( 0-x2)*dy/dx; x2 = 0; } - if (y1 >= fyresm1) { if (y2 >= fyresm1) return; x1 += (fyresm1-y1)*dx/dy; y1 = fyresm1; } - else if (y1 < 0) { if (y2 < 0) return; x1 += ( 0-y1)*dx/dy; y1 = 0; } - if (y2 >= fyresm1) { x2 += (fyresm1-y2)*dx/dy; y2 = fyresm1; } - else if (y2 < 0) { x2 += ( 0-y2)*dx/dy; y2 = 0; } - - dx = x2-x1; dy = y2-y1; - i = (long)(MAX(fabsf(dx)+1,fabsf(dy)+1)); f = 65536.f/((float)i); - x = (long)(x1*65536.f)+32768; xi = (long)(dx*f); xup16 = (RenderTarget->GetWidth()<<16); - y = (long)(y1*65536.f)+32768; yi = (long)(dy*f); yup16 = (RenderTarget->GetHeight()<<16); - do - { - if (((unsigned long)x < (unsigned long)xup16) && ((unsigned long)y < (unsigned long)yup16)) - *(ylookup[y>>16]+(x>>16)+dc_destorg) = col; - x += xi; y += yi; i--; - } while (i >= 0); -} - -static int maskhack; - -void fillconvpoly (float x[], float y[], int n, int col, int bcol) -{ - int mini = y[0] >= y[1], maxi = 1 - mini; - int i, j, y2, oz, z, yy, zz, ncol; - float area, xi, xx; - static int lastx[MAXHEIGHT+2]; - - for (z = 2; z < n; ++z) - { - if (y[z] < y[mini]) mini = z; - if (y[z] > y[maxi]) maxi = z; - } - - area = 0; zz = n - 1; - for (z = 0; z < n; ++z) - { - area += (x[zz] - x[z]) * (y[z] + y[zz]); zz = z; - } - if (area <= 0) return; - - i = maxi; y2 = int(y[i]); - do - { - j = i + 1; if (j == n) j = 0; - yy = int(ceilf(y[j])); - if (yy < 0) yy = 0; - if (yy < y2) - { - xi = (x[j] - x[i]) / (y[j] - y[i]); - xx = (y2 - y[j]) * xi + x[j]; - if (y2 >= RenderTarget->GetHeight()) { xx = xx - (y2 - RenderTarget->GetHeight() + 1)*xi; y2 = RenderTarget->GetHeight()-1; } - for (; y2 >= yy; --y2) - { - lastx[y2] = MAX (0, int(ceilf(xx))); xx = xx - xi; - } - } - i = j; - } while (i != mini); - if (y2 == yy) lastx[yy] = lastx[yy+1]; - do - { - j = i + 1; if (j == n) j = 0; - y2 = int(y[j]); - if (y2 >= RenderTarget->GetHeight()) y2 = RenderTarget->GetHeight()-1; - if (y2 > yy) - { - xi = (x[j] - x[i]) / (y[j] - y[i]); - xx = (yy - y[i]) * xi + x[i]; - if (yy < 0) { xx = xx - xi*yy; yy = 0; } - ncol = col; if (yy & 1) ncol = ncol ^ maskhack; - for (; yy <= y2; ++yy) - { - //drawline2d(lastx[yy], yy, int(ceilf(xx)), yy, ncol); xx = xx + xi; - int xxx = MIN(RenderTarget->GetWidth(), int(ceilf(xx))); - if (yy < RenderTarget->GetHeight() && lastx[yy] < xxx) memset(RenderTarget->GetBuffer()+yy*RenderTarget->GetPitch()+lastx[yy], ncol, xxx-lastx[yy]); - xx = xx + xi; - ncol = ncol ^ maskhack; - } - } - i = j; - } while (i != maxi); - - if (col != bcol) - { - oz = n - 1; - for (z = 0; z < n; ++z) - { - drawline2d(x[oz], y[oz], x[z], y[z], bcol); - oz = z; - } - } -} - -void drawtri(float x0, float y0, float x1, float y1, float x2, float y2, int col, int bcol) -{ - float x[3], y[3]; - x[0] = x0; y[0] = y0; - x[1] = x1; y[1] = y1; - x[2] = x2; y[2] = y2; - fillconvpoly(x, y, 3, col, bcol); -} - -void drawquad(float x0, float y0, float x1, float y1, float x2, float y2, float x3, float y3, int col, int bcol) -{ - float x[4], y[4]; - x[0] = x0; y[0] = y0; - x[1] = x1; y[1] = y1; - x[2] = x2; y[2] = y2; - x[3] = x3; y[3] = y3; - fillconvpoly(x, y, 4, col, bcol); // 2 triangles - if (col != bcol) - { - if (fabsf(y0-y2) < fabsf(y1-y3)) - drawline2d(x0,y0,x2,y2,bcol); - else - drawline2d(x1,y1,x3,y3,bcol); - } -} - -void printnum(int x, int y, int num) -{ - char foo[16]; mysnprintf (foo, countof(foo), "%d", num); - RenderTarget->DrawText (SmallFont, CR_WHITE, x, y, foo, TAG_DONE); -} - -void drawpolymosttest() -{ - float cx0 = 0, cy0 = 0, fx0 = 0, fy0 = 0; - int ccol, fcol; - PolyClipper::vsptype *vsp, *ovsp = &TestPoly.UsedList, *nvsp; - - fcol = 0; ccol = 0; - - RenderTarget->Clear(0, 0, RenderTarget->GetWidth(), RenderTarget->GetHeight(), 0, 0); - for (vsp = ovsp->Next; vsp->Next != &TestPoly.UsedList; ovsp = vsp, vsp = nvsp) - { - nvsp = vsp->Next; - if (vsp->CTag == -1 && vsp->FTag == -1) - { // Hide spans that have been clipped away - vsp->Cy[0] = vsp->Cy[1] = vsp->Fy[0] = vsp->Fy[1] = RenderTarget->GetHeight()/2; - } - - if (vsp->CTag != ovsp->CTag) cx0 = vsp->X, cy0 = vsp->Cy[0]; - if (vsp->CTag != nvsp->CTag) - { // fill the ceiling region - maskhack = 0x18; - drawquad(cx0, 0, nvsp->X, 0, nvsp->X, vsp->Cy[1], cx0, cy0, ccol, ccol); - maskhack = 0; ccol ^= 0x18; - printnum(int(cx0 + nvsp->X) / 2, 2, vsp->CTag); - } - - if(vsp->FTag != ovsp->FTag) fx0 = vsp->X, fy0 = vsp->Fy[0]; - if(vsp->FTag != nvsp->FTag) - { // fill the floor region - maskhack = 0x78; - drawquad(fx0, fy0+1, nvsp->X, vsp->Fy[1]+1, nvsp->X, RenderTarget->GetHeight(), fx0, RenderTarget->GetHeight(), fcol, fcol); - maskhack = 0; fcol ^= 0x78; - printnum(int(fx0 + nvsp->X) / 2, RenderTarget->GetHeight()-10, vsp->FTag); - } - - // fill the unclipped middle region - drawquad(vsp->X, vsp->Cy[0], nvsp->X, vsp->Cy[1], nvsp->X, vsp->Fy[1], vsp->X, vsp->Fy[0], 0xC4, 0xE6); - } - - int x = (pmx + 3) & ~7, y = (pmy + 3) & ~7; - - drawline2d (x - 3, y, x + 3, y, 30); - drawline2d (x, y - 3, x, y + 3, 30); - printnum ( 0, 20, x); - printnum (50, 20, y); - - if (pt > 0 && px0 != px1) - { - if (px0 < px1) - { - drawline2d (px0, py0, px0, RenderTarget->GetHeight()-1, 47); - drawline2d (px1, py1, px1, RenderTarget->GetHeight()-1, 47); - } - else - { - drawline2d (px0, py0, px0, 0, 47); - drawline2d (px1, py1, px1, 0, 47); - } - drawline2d (px0, py0, px1, py1, 47); - } - if (pt == 2) - { - int i = 0; - for (x = 0; x < numpoly; ++x) - { - if (polysize[x] == 3) - { - drawtri (polypts[i ].x, polypts[i ].y, - polypts[i+1].x, polypts[i+1].y, - polypts[i+2].x, polypts[i+2].y, 0x7f, 0x9f); - i += 3; - } - else - { - drawquad (polypts[i ].x, polypts[i ].y, - polypts[i+1].x, polypts[i+1].y, - polypts[i+2].x, polypts[i+2].y, - polypts[i+3].x, polypts[i+3].y, 0x7f, 0x9f); - i += 4; - } - } - } -} - -CCMD(initpolymosttest) -{ - double px[4], py[4]; - int test = 0; - - if (argv.argc() > 1) - test = atoi(argv[1]); - - // Box - px[0] = px[3] = 0; - px[1] = px[2] = screen->GetWidth(); - py[0] = py[1] = screen->GetHeight()/4; - py[2] = py[3] = screen->GetHeight()*3/4; - - switch (test) - { - case 1: // Shorter top edge - px[0] = px[1]/6; - px[1] = px[1]*5/6; - break; - - case 2: // Shorter bottom edge - px[3] = px[2]/6; - px[2] = px[2]*5/6; - break; - - case 3: // Shorter left edge - py[0] = screen->GetHeight()*3/8; - py[3] = screen->GetHeight()*5/8; - break; - - case 4: // Shorter right edge - py[1] = screen->GetHeight()*3/8; - py[2] = screen->GetHeight()*5/8; - break; - - case 5: - px[0] = -1.0048981460288360/2+50; py[0] = -1.0/2+50; - px[1] = 643.00492866407262/2+50; py[1] = -1.0/2+50; - px[2] = 643.00492866407262/2+50; py[2] = 483/2+50; - px[3] = -1.0048981460288360/2+50; py[3] = 483/2+50; - break; - } - TestPoly.InitMosts (px, py, 4); - pmx = screen->GetWidth()/2; - pmy = screen->GetHeight()/2; - pt = 0; -} - -static void testpolycallback (double *dpx, double *dpy, int n, void *foo) -{ - if (numpoly == sizeof(polysize)) return; - if (size_t(polypt + n) > countof(polypts)) return; - polysize[numpoly++] = n; - for (int i = 0; i < n; ++i) - { - polypts[polypt + i].x = dpx[i]; - polypts[polypt + i].y = dpy[i]; - } - polypt += n; -} - -void Polymost_Responder (event_t *ev) -{ - if (ev->type == EV_Mouse && pt < 2) - { - pmx = clamp (pmx + ev->x, 0, screen->GetWidth()-1); - pmy = clamp (pmy - ev->y, 0, screen->GetHeight()-1); - int x = (pmx + 3) & ~7, y = (pmy + 3) & ~7; - if (pt == 0) px0 = x, py0 = y; - if (pt <= 1) px1 = x, py1 = y; - } - else if (ev->type == EV_KeyDown && ev->data1 == KEY_MOUSE1) - { - if (pt == 0) pt = 1; else pt = 0; - } - else if (ev->type == EV_KeyUp && ev->data1 == KEY_MOUSE1) - { - if (pt == 1) { if (px0 != px1) pt++; else pt--; } - if (pt == 2) - { - numpoly = polypt = 0; - TestPoly.DoMost (px0, py0, px1, py1, testpolycallback, NULL); - } - } -} - - - - - - - - -extern fixed_t WallSZ1, WallSZ2, WallTX1, WallTX2, WallTY1, WallTY2, WallCX1, WallCX2, WallCY1, WallCY2; -extern int WallSX1, WallSX2; -extern float WallUoverZorg, WallUoverZstep, WallInvZorg, WallInvZstep, WallDepthScale, WallDepthOrg; -extern fixed_t rw_backcz1, rw_backcz2; -extern fixed_t rw_backfz1, rw_backfz2; -extern fixed_t rw_frontcz1, rw_frontcz2; -extern fixed_t rw_frontfz1, rw_frontfz2; -extern fixed_t rw_offset; -extern bool rw_markmirror; -extern bool rw_havehigh; -extern bool rw_havelow; -extern bool markfloor; -extern bool markceiling; -extern FTexture *toptexture; -extern FTexture *bottomtexture; -extern FTexture *midtexture; -extern bool rw_mustmarkfloor, rw_mustmarkceiling; -extern void R_NewWall(bool); -//extern void R_GetExtraLight (int *light, const secplane_t &plane, FExtraLight *el); -extern int doorclosed; -extern int viewpitch; -#include "p_lnspec.h" - -PolyClipper Mosts; -static bool drawback; - -bool RP_SetupFrame (bool backside) -{ - double ox, oy, oz, ox2, oy2, oz2, r, px[6], py[6], pz[6], px2[6], py2[6], pz2[6], sx[6], sy[6]; - int i, j, n, n2; - - drawback = backside; - if (backside) - { - viewangle += ANGLE_180; - viewsin = finesine[viewangle>>ANGLETOFINESHIFT]; - viewcos = finecosine[viewangle>>ANGLETOFINESHIFT]; - viewtansin = FixedMul (FocalTangent, viewsin); - viewtancos = FixedMul (FocalTangent, viewcos); - } - //Polymost supports true look up/down :) Here, we convert horizon to angle. - //gchang&gshang are cos&sin of this angle (respectively) -// gyxscale = ((double)xdimenscale)/131072.0; - gyxscale = double(InvZtoScale)/65536.0;///131072.0/320.0; -// gxyaspect = ((double)xyaspect*(double)viewingrange)*(5.0/(65536.0*262144.0)); -// gviewxrange = ((double)viewingrange)*((double)xdimen)/(32768.0*128.0); - gcosang = double(viewcos)/65536.0; - gsinang = double(viewsin)/65536.0; - gcosang2 = gcosang*double(FocalTangent)/65536.0; - gsinang2 = gsinang*double(FocalTangent)/65536.0; - ghalfx = (double)viewwidth*0.5; grhalfxdown10 = 1.0/(((double)ghalfx)*1024); - - //global cos/sin height angle - angle_t pitch = (angle_t)viewpitch; - if (backside) pitch = ANGLE_180 - pitch; - - gshang = double(finesine[pitch>>ANGLETOFINESHIFT])/65536.0; - gchang = double(finecosine[pitch>>ANGLETOFINESHIFT])/65536.0; - ghoriz = double(viewheight)*0.5; - - //global cos/sin tilt angle - gctang = cos(gtang); - gstang = sin(gtang); - if (fabs(gstang) < .001) //This hack avoids nasty precision bugs in domost() - { gstang = 0; if (gctang > 0) gctang = 1.0; else gctang = -1.0; } - - // Generate viewport trapezoid - px[0] = px[3] = 0-1; px[1] = px[2] = viewwidth+3; - py[0] = py[1] = 0-1; py[2] = py[3] = viewheight+3; n = 4; - for(i=0;i= n) j = 0; - if (pz[i] >= SCISDIST/16) { px2[n2] = px[i]; py2[n2] = py[i]; pz2[n2] = pz[i]; n2++; } - if ((pz[i] >= SCISDIST/16) != (pz[j] >= SCISDIST/16)) - { - clipped = true; - r = (SCISDIST/16-pz[i])/(pz[j]-pz[i]); - px2[n2] = (px[j]-px[i])*r + px[i]; - py2[n2] = (py[j]-py[i])*r + py[i]; - pz2[n2] = SCISDIST/16; - if (backside) py2[n2] -= r; - n2++; - } - } - if (n2 < 3) { return true; } - for(i=0;i= (dpx[2]-dpx[1])*(dpy[0]-dpy[1])) return; //for triangle - } - else - { - f = 0; //f is area of polygon / 2 - for(i=n-2,j=n-1,k=0;klinedef == NULL) return; - - //Offset&Rotate 3D coordinates to screen 3D space - x = double(line->v1->x - viewx); y = double(line->v1->y - viewy); - xp0 = x*gsinang - y*gcosang; - yp0 = x*gcosang2 + y*gsinang2; - x = double(line->v2->x - viewx); y = double(line->v2->y - viewy); - xp1 = x*gsinang - y*gcosang; - yp1 = x*gcosang2 + y*gsinang2; - - oxp0 = xp0; oyp0 = yp0; - - //Clip to close parallel-screen plane - // [RH] Why oh why does clipping the left side of the wall against - // a small SCISDIST not work for me? Strictly speaking, it's not - // the clipping of the left side that's the problem, because if I - // rotate the view 180 degrees so the right side of the wall is on - // the left of the screen, then clipping the right side becomes - // problematic. -#define WCLIPDIST (SCISDIST*256.0) - if (yp0 < WCLIPDIST) - { - if (yp1 < WCLIPDIST) return; - t0 = (WCLIPDIST-yp0)/(yp1-yp0); - xp0 = (xp1-xp0)*t0+xp0; - yp0 = WCLIPDIST; - nx0 = (line->v2->x - line->v1->x)*t0 + line->v1->x; - ny0 = (line->v2->y - line->v1->y)*t0 + line->v1->y; - } - else { t0 = 0.f; nx0 = line->v1->x; ny0 = line->v1->y; } - if (yp1 < WCLIPDIST) - { - t1 = (WCLIPDIST-oyp0)/(yp1-oyp0); - xp1 = (xp1-oxp0)*t1+oxp0; - yp1 = WCLIPDIST; - nx1 = (line->v2->x - line->v1->x)*t1 + line->v1->x; - ny1 = (line->v2->y - line->v1->y)*t1 + line->v1->y; - } - else { t1 = 1.f; nx1 = line->v2->x; ny1 = line->v2->y; } - - ryp0 = 1.0/yp0; ryp1 = 1.0/yp1; - - //Generate screen coordinates for front side of wall - x0 = ghalfx*xp0*ryp0 + ghalfx; - x1 = ghalfx*xp1*ryp1 + ghalfx; - if (x1 <= x0) return; - - ryp0 *= gyxscale; ryp1 *= gyxscale; - fixed_t fnx0 = fixed_t(nx0), fny0 = fixed_t(ny0); - fixed_t fnx1 = fixed_t(nx1), fny1 = fixed_t(ny1); - - fcz0 = frontsector->ceilingplane.ZatPoint (fnx0, fny0); - ffz0 = frontsector->floorplane.ZatPoint (fnx0, fny0); - fcz1 = frontsector->ceilingplane.ZatPoint (fnx1, fny1); - ffz1 = frontsector->floorplane.ZatPoint (fnx1, fny1); - bool cc = (t0>0 && x1 > 0); - cy0 = ghoriz - double(fcz0 - viewz) * ryp0; - fy0 = ghoriz - double(ffz0 - viewz) * ryp0; - cy1 = ghoriz - double(fcz1 - viewz) * ryp1; - fy1 = ghoriz - double(ffz1 - viewz) * ryp1; - -/* - tx1 = line->v1->x - viewx; - tx2 = line->v2->x - viewx; - ty1 = line->v1->y - viewy; - ty2 = line->v2->y - viewy; - // Reject lines not facing viewer - if (DMulScale32 (ty1, tx1-tx2, tx1, ty2-ty1) >= 0) - return; - - WallTX1 = DMulScale20 (tx1, viewsin, -ty1, viewcos); - WallTX2 = DMulScale20 (tx2, viewsin, -ty2, viewcos); - - WallTY1 = DMulScale20 (tx1, viewtancos, ty1, viewtansin); - WallTY2 = DMulScale20 (tx2, viewtancos, ty2, viewtansin); - - if (MirrorFlags & RF_XFLIP) - { - int t = 256-WallTX1; - WallTX1 = 256-WallTX2; - WallTX2 = t; - swap (WallTY1, WallTY2); - } - - if (WallTX1 >= -WallTY1) - { - if (WallTX1 > WallTY1) return; // left edge is off the right side - if (WallTY1 == 0) return; - WallSX1 = (centerxfrac + Scale (WallTX1, centerxfrac, WallTY1)) >> FRACBITS; - if (WallTX1 >= 0) WallSX1 = MIN (viewwidth, WallSX1+1); // fix for signed divide - WallSZ1 = WallTY1; - } - else - { - if (WallTX2 < -WallTY2) return; // wall is off the left side - fixed_t den = WallTX1 - WallTX2 - WallTY2 + WallTY1; - if (den == 0) return; - WallSX1 = 0; - WallSZ1 = WallTY1 + Scale (WallTY2 - WallTY1, WallTX1 + WallTY1, den); - } - - if (WallSZ1 < 32) - return; - - if (WallTX2 <= WallTY2) - { - if (WallTX2 < -WallTY2) return; // right edge is off the left side - if (WallTY2 == 0) return; - WallSX2 = (centerxfrac + Scale (WallTX2, centerxfrac, WallTY2)) >> FRACBITS; - if (WallTX2 >= 0) WallSX2 = MIN (viewwidth, WallSX2+1); // fix for signed divide - WallSZ2 = WallTY2; - } - else - { - if (WallTX1 > WallTY1) return; // wall is off the right side - fixed_t den = WallTY2 - WallTY1 - WallTX2 + WallTX1; - if (den == 0) return; - WallSX2 = viewwidth; - WallSZ2 = WallTY1 + Scale (WallTY2 - WallTY1, WallTX1 - WallTY1, den); - } - - if (WallSZ2 < 32 || WallSX2 <= WallSX1) - return; - - if (WallSX1 > WindowRight || WallSX2 < WindowLeft) - return; - if (line->linedef == NULL) - { - return; - } -*/ - - vertex_t *v1, *v2; - - v1 = line->linedef->v1; - v2 = line->linedef->v2; - - if ((v1 == line->v1 && v2 == line->v2) || (v2 == line->v1 && v1 == line->v2)) - { // The seg is the entire wall. - if (MirrorFlags & RF_XFLIP) - { - WallUoverZorg = (float)WallTX2 * WallTMapScale; - WallUoverZstep = (float)(-WallTY2) * 32.f; - WallInvZorg = (float)(WallTX2 - WallTX1) * WallTMapScale; - WallInvZstep = (float)(WallTY1 - WallTY2) * 32.f; - } - else - { - WallUoverZorg = (float)WallTX1 * WallTMapScale; - WallUoverZstep = (float)(-WallTY1) * 32.f; - WallInvZorg = (float)(WallTX1 - WallTX2) * WallTMapScale; - WallInvZstep = (float)(WallTY2 - WallTY1) * 32.f; - } - } - else - { // The seg is only part of the wall. - if (line->linedef->sidedef[0] != line->sidedef) - { - swapvalues (v1, v2); - } - tx1 = v1->x - viewx; - tx2 = v2->x - viewx; - ty1 = v1->y - viewy; - ty2 = v2->y - viewy; - - fixed_t fullx1 = DMulScale20 (tx1, viewsin, -ty1, viewcos); - fixed_t fullx2 = DMulScale20 (tx2, viewsin, -ty2, viewcos); - fixed_t fully1 = DMulScale20 (tx1, viewtancos, ty1, viewtansin); - fixed_t fully2 = DMulScale20 (tx2, viewtancos, ty2, viewtansin); - - if (MirrorFlags & RF_XFLIP) - { - fullx1 = -fullx1; - fullx2 = -fullx2; - } - - WallUoverZorg = (float)fullx1 * WallTMapScale; - WallUoverZstep = (float)(-fully1) * 32.f; - WallInvZorg = (float)(fullx1 - fullx2) * WallTMapScale; - WallInvZstep = (float)(fully2 - fully1) * 32.f; - } - WallDepthScale = WallInvZstep * WallTMapScale2; - WallDepthOrg = -WallUoverZstep * WallTMapScale2; - - backsector = line->backsector; - - rw_mustmarkfloor = rw_mustmarkceiling = false; - rw_havehigh = rw_havelow = false; - - // Single sided line? - if (backsector == NULL) - { - solid = true; - } - else - { - // killough 3/8/98, 4/4/98: hack for invisible ceilings / deep water - backsector = R_FakeFlat (backsector, &tempsec, NULL, NULL, true); - - doorclosed = 0; // killough 4/16/98 - - bcz0 = backsector->ceilingplane.ZatPoint (fnx0, fny0); - bfz0 = backsector->floorplane.ZatPoint (fnx0, fny0); - bcz1 = backsector->ceilingplane.ZatPoint (fnx1, fny1); - bfz1 = backsector->floorplane.ZatPoint (fnx1, fny1); - ocy0 = ghoriz - double(bcz0 - viewz) * ryp0; - ofy0 = ghoriz - double(bfz0 - viewz) * ryp0; - ocy1 = ghoriz - double(bcz1 - viewz) * ryp1; - ofy1 = ghoriz - double(bfz1 - viewz) * ryp1; - - if (fcz0 > bcz0 || fcz1 > bcz1) - { - rw_havehigh = true; - } - if (ffz0 < bfz0 ||ffz1 < bfz1) - { - rw_havelow = true; - } - - // Closed door. - if ((bcz0 <= ffz0 && bcz1 <= ffz1) || (bfz0 >= fcz0 && bfz1 >= fcz1)) - { - solid = true; - } - else if ( - (backsector->GetTexture(sector_t::ceiling) != skyflatnum || - frontsector->GetTexture(sector_t::ceiling) != skyflatnum) - - // if door is closed because back is shut: - && bcz0 <= bfz0 && bcz1 <= bfz1 - - // preserve a kind of transparent door/lift special effect: - && bcz0 >= fcz0 && bcz1 >= fcz1 - - && ((bfz0 <= ffz0 && bfz1 <= ffz1) || line->sidedef->GetTexture(side_t::bottom).isValid())) - { - // killough 1/18/98 -- This function is used to fix the automap bug which - // showed lines behind closed doors simply because the door had a dropoff. - // - // It assumes that Doom has already ruled out a door being closed because - // of front-back closure (e.g. front floor is taller than back ceiling). - - // This fixes the automap floor height bug -- killough 1/18/98: - // killough 4/7/98: optimize: save result in doorclosed for use in r_segs.c - doorclosed = true; - solid = true; - } - else if (frontsector->ceilingplane != backsector->ceilingplane || - frontsector->floorplane != backsector->floorplane) - { - // Window. - solid = false; - } - else if (backsector->lightlevel != frontsector->lightlevel - || backsector->GetTexture(sector_t::floor) != frontsector->GetTexture(sector_t::floor) - || backsector->GetTexture(sector_t::ceiling) != frontsector->GetTexture(sector_t::ceiling) - || curline->sidedef->GetTexture(side_t::mid).isValid() - - // killough 3/7/98: Take flats offsets into account: - || backsector->GetXOffset(sector_t::floor) != frontsector->GetXOffset(sector_t::floor) - || backsector->GetYOffset(sector_t::floor) != frontsector->GetYOffset(sector_t::floor) - || backsector->GetXOffset(sector_t::ceiling) != frontsector->GetXOffset(sector_t::ceiling) - || backsector->GetYOffset(sector_t::ceiling) != frontsector->GetYOffset(sector_t::ceiling) - - || backsector->GetPlaneLight(sector_t::floor) != frontsector->GetPlaneLight(sector_t::floor) - || backsector->GetPlaneLight(sector_t::ceiling) != frontsector->GetPlaneLight(sector_t::ceiling) - || backsector->GetFlags(sector_t::floor) != frontsector->GetFlags(sector_t::floor) - || backsector->GetFlags(sector_t::ceiling) != frontsector->GetFlags(sector_t::ceiling) - - // [RH] Also consider colormaps - || backsector->ColorMap != frontsector->ColorMap - - // [RH] and scaling - || backsector->GetXScale(sector_t::floor) != frontsector->GetXScale(sector_t::floor) - || backsector->GetYScale(sector_t::floor) != frontsector->GetYScale(sector_t::floor) - || backsector->GetXScale(sector_t::ceiling) != frontsector->GetXScale(sector_t::ceiling) - || backsector->GetYScale(sector_t::ceiling) != frontsector->GetYScale(sector_t::ceiling) - - // [RH] and rotation - || backsector->GetAngle(sector_t::floor) != frontsector->GetAngle(sector_t::floor) - || backsector->GetAngle(sector_t::ceiling) != frontsector->GetAngle(sector_t::ceiling) - ) - { - solid = false; - } - else - { - // Reject empty lines used for triggers and special events. - // Identical floor and ceiling on both sides, identical light levels - // on both sides, and no middle texture. - return; - } - } - - if (line->linedef->special == Line_Horizon) - { - // Be aware: Line_Horizon does not work properly with sloped planes - fcz1 = fcz0 = ffz1 = ffz0 = viewz; - markceiling = markfloor = true; - } - - // must be fixed in case the polymost renderer ever gets developed further! - rw_offset = line->sidedef->GetTextureXOffset(side_t::mid); - - R_NewWall (false); - if (rw_markmirror) - { - WallMirrors.Push (ds_p - drawsegs); - } - - // render it - if (markceiling) - { - Mosts.DoMost (x1, cy1, x0, cy0, wireframe, !cc||1?(void *)0xc3:(void*)0xca); - } - if (markfloor) - { - Mosts.DoMost (x0, fy0, x1, fy1, wireframe, (void *)0xd3); - } - if (midtexture) - { // one sided line - //if(line->linedef-lines==1)Printf ("%g %g %g -> %g %g %g : %g %g -> %g %g\n", yp0, x0, fy0, yp1, x1, fy1, nx0, ny0, nx1, ny1); - if (viewpitch > 0) - Mosts.DoMost (x0, -10000, x1, -10000, wireframe, !cc||1?(void *)0x83:(void*)0x93); - else - Mosts.DoMost (x1, 10000, x0, 10000, wireframe, !cc||1?(void *)0x83:(void*)0x93); - } - else - { // two sided line - if (toptexture != NULL && toptexture->UseType != FTexture::TEX_Null) - { // top wall - Mosts.DoMost (x1, ocy1, x0, ocy0, wireframe, (void *)0xa3); - } - if (bottomtexture != NULL && bottomtexture->UseType != FTexture::TEX_Null) - { // bottom wall - Mosts.DoMost (x0, ofy0, x1, ofy1, wireframe, (void *)0x93); -/* float bfz2 = float(-(rw_backfz2 - viewz)) / 65536.f; - float bfz1 = float(-(rw_backfz1 - viewz)) / 65536.f; - Mosts.DoMost (WallSX1, bfz1 * izs / sz1 + ghoriz, - WallSX2, bfz2 * izs / sz2 + ghoriz, - wireframe, (void *)0x93);*/ - } - } -} - -void RP_Subsector (subsector_t *sub) -{ - int count; - seg_t* line; - sector_t tempsec; // killough 3/7/98: deep water hack - int floorlightlevel; // killough 3/16/98: set floor lightlevel - int ceilinglightlevel; // killough 4/11/98 - - frontsector = sub->sector; - count = sub->numlines; - line = sub->firstline; - - // killough 3/8/98, 4/4/98: Deep water / fake ceiling effect - frontsector = R_FakeFlat(frontsector, &tempsec, &floorlightlevel, - &ceilinglightlevel, false); // killough 4/11/98 - - basecolormap = frontsector->ColorMap; - //R_GetExtraLight (&ceilinglightlevel, frontsector->ceilingplane, frontsector->ExtraLights); - - // [RH] set foggy flag - foggy = level.fadeto || frontsector->ColorMap->Fade || (level.flags & LEVEL_HASFADETABLE); - r_actualextralight = foggy ? 0 : extralight << 4; - basecolormap = frontsector->ColorMap; -/* ceilingplane = frontsector->ceilingplane.ZatPoint (viewx, viewy) > viewz || - frontsector->ceilingpic == skyflatnum || - (frontsector->CeilingSkyBox != NULL && frontsector->CeilingSkyBox->bAlways) || - (frontsector->heightsec && - !(frontsector->heightsec->MoreFlags & SECF_IGNOREHEIGHTSEC) && - frontsector->heightsec->floorpic == skyflatnum) ? - R_FindPlane(frontsector->ceilingplane, // killough 3/8/98 - frontsector->ceilingpic, - ceilinglightlevel + r_actualextralight, // killough 4/11/98 - frontsector->ceiling_xoffs, // killough 3/7/98 - frontsector->ceiling_yoffs + frontsector->base_ceiling_yoffs, - frontsector->ceiling_xscale, - frontsector->ceiling_yscale, - frontsector->ceiling_angle + frontsector->base_ceiling_angle, - frontsector->sky, - frontsector->CeilingSkyBox, - ) : NULL;*/ - - basecolormap = frontsector->ColorMap; - //R_GetExtraLight (&floorlightlevel, frontsector->floorplane, frontsector->ExtraLights); - - // killough 3/7/98: Add (x,y) offsets to flats, add deep water check - // killough 3/16/98: add floorlightlevel - // killough 10/98: add support for skies transferred from sidedefs -/* floorplane = frontsector->floorplane.ZatPoint (viewx, viewy) < viewz || // killough 3/7/98 - frontsector->floorpic == skyflatnum || - (frontsector->FloorSkyBox != NULL && frontsector->FloorSkyBox->bAlways) || - (frontsector->heightsec && - !(frontsector->heightsec->MoreFlags & SECF_IGNOREHEIGHTSEC) && - frontsector->heightsec->ceilingpic == skyflatnum) ? - R_FindPlane(frontsector->floorplane, - frontsector->floorpic, - floorlightlevel + r_actualextralight, // killough 3/16/98 - frontsector->floor_xoffs, // killough 3/7/98 - frontsector->floor_yoffs + frontsector->base_floor_yoffs, - frontsector->floor_xscale, - frontsector->floor_yscale, - frontsector->floor_angle + frontsector->base_floor_angle, - frontsector->sky, - frontsector->FloorSkyBox - ) : NULL;*/ - - // killough 9/18/98: Fix underwater slowdown, by passing real sector - // instead of fake one. Improve sprite lighting by basing sprite - // lightlevels on floor & ceiling lightlevels in the surrounding area. - // [RH] Handle sprite lighting like Duke 3D: If the ceiling is a sky, sprites are lit by - // it, otherwise they are lit by the floor. -// R_AddSprites (sub->sector, frontsector->ceilingpic == skyflatnum ? -// ceilinglightlevel : floorlightlevel, FakeSide); - - // [RH] Add particles -// int shade = LIGHT2SHADE((floorlightlevel + ceilinglightlevel)/2 + r_actualextralight); -// for (WORD i = ParticlesInSubsec[sub-subsectors]; i != NO_PARTICLE; i = Particles[i].snext) -// { -// R_ProjectParticle (Particles + i, subsectors[sub-subsectors].sector, shade, FakeSide); -// } - -#if 0 - if (sub->poly) - { // Render the polyobj in the subsector first - int polyCount = sub->poly->numsegs; - seg_t **polySeg = sub->poly->segs; - while (polyCount--) - { - RP_AddLine (*polySeg++); - } - } -#endif - - while (count--) - { - if (line->sidedef == NULL || !(line->sidedef->Flags & WALLF_POLYOBJ)) - { - RP_AddLine (line); - } - line++; - } -} - -extern "C" const int checkcoord[12][4]; - -static bool RP_CheckBBox (fixed_t *bspcoord) -{ - int boxx; - int boxy; - int boxpos; - - fixed_t x1, y1, x2, y2; - double x, y, xp0, yp0, xp1, yp1, t, sx0, sx1; - - // Find the corners of the box - // that define the edges from current viewpoint. - if (viewx <= bspcoord[BOXLEFT]) - boxx = 0; - else if (viewx < bspcoord[BOXRIGHT]) - boxx = 1; - else - boxx = 2; - - if (viewy >= bspcoord[BOXTOP]) - boxy = 0; - else if (viewy > bspcoord[BOXBOTTOM]) - boxy = 1; - else - boxy = 2; - - boxpos = (boxy<<2)+boxx; - if (boxpos == 5) - return true; - - x1 = bspcoord[checkcoord[boxpos][0]] - viewx; - y1 = bspcoord[checkcoord[boxpos][1]] - viewy; - x2 = bspcoord[checkcoord[boxpos][2]] - viewx; - y2 = bspcoord[checkcoord[boxpos][3]] - viewy; - - // check clip list for an open space - - // Sitting on a line? - if (DMulScale32 (y1, x1-x2, x1, y2-y1) >= 0) - return true; - - //Offset&Rotate 3D coordinates to screen 3D space - x = double(x1); y = double(y1); - xp0 = x*gsinang - y*gcosang; - yp0 = x*gcosang2 + y*gsinang2; - x = double(x2); y = double(y2); - xp1 = x*gsinang - y*gcosang; - yp1 = x*gcosang2 + y*gsinang2; - - //Clip to close parallel-screen plane - if (yp0 < SCISDIST) - { - if (yp1 < SCISDIST) return false; - t = (SCISDIST-yp0)/(yp1-yp0); - xp0 = (xp1-xp0)*t+xp0; - yp0 = SCISDIST; - } - if (yp1 < SCISDIST) - { - t = (SCISDIST-yp0)/(yp1-yp0); - xp1 = (xp1-xp0)*t+xp0; - yp1 = SCISDIST; - } - - //Generate screen coordinates for front side of wall - sx0 = ghalfx*xp0/yp0 + ghalfx; - sx1 = ghalfx*xp1/yp1 + ghalfx; - - // Does not cross a pixel. - if (sx1 <= sx0) - return false; - - return Mosts.TestVisibleMost (sx0, sx1); -} - -void RP_RenderBSPNode (void *node) -{ - if (numnodes == 0) - { - RP_Subsector (subsectors); - return; - } - while (!((size_t)node & 1)) // Keep going until found a subsector - { - node_t *bsp = (node_t *)node; - - // Decide which side the view point is on. - int side = R_PointOnSide (viewx, viewy, bsp); - - // Recursively divide front space (toward the viewer). - RP_RenderBSPNode (bsp->children[side]); - - // Possibly divide back space (away from the viewer). - side ^= 1; - if (!RP_CheckBBox (bsp->bbox[side])) - return; - - node = bsp->children[side]; - } - RP_Subsector ((subsector_t *)((BYTE *)node - 1)); -} - diff --git a/src/r_polymost.h b/src/r_polymost.h deleted file mode 100644 index 8afbefb22..000000000 --- a/src/r_polymost.h +++ /dev/null @@ -1,55 +0,0 @@ -/************************************************************************************************** -"POLYMOST" code written by Ken Silverman -**************************************************************************************************/ - -#include "c_cvars.h" - -typedef void (*pmostcallbacktype)(double *dpx, double *dpy, int n, void *userdata); - -class PolyClipper -{ -public: - PolyClipper(); - ~PolyClipper(); - - void InitMosts (double *px, double *py, int n); - bool TestVisibleMost (float x0, float x1); - int DoMost (float x0, float y0, float x1, float y1, pmostcallbacktype callback, void *callbackdata); - -private: - struct vsptype - { - float X, Cy[2], Fy[2]; - int Tag, CTag, FTag; - vsptype *Next, *Prev; - }; - - enum { GROUP_SIZE = 128 }; - - struct vspgroup - { - vspgroup (vsptype *sentinel); - - vspgroup *NextGroup; - vsptype vsp[GROUP_SIZE]; - }; - - vsptype EmptyList; - vsptype UsedList; - vspgroup vsps; - vsptype Solid; - - int GTag; - - vsptype *vsinsaft (vsptype *vsp); - void EmptyAll (); - void AddGroup (); - vsptype *GetVsp (); - void FreeVsp (vsptype *vsp); - - friend void drawpolymosttest(); - -}; - -extern void drawpolymosttest(); -struct event_t; void Polymost_Responder (event_t *ev); diff --git a/src/r_segs.cpp b/src/r_segs.cpp index 4fec863ff..cf00abc45 100644 --- a/src/r_segs.cpp +++ b/src/r_segs.cpp @@ -64,11 +64,6 @@ CVAR(Bool, r_np2, true, 0) #define HEIGHTBITS 12 #define HEIGHTSHIFT (FRACBITS-HEIGHTBITS) -// The 3072 below is just an arbitrary value picked to avoid -// drawing lines the player is too close to that would overflow -// the texture calculations. -#define TOO_CLOSE_Z 3072 - extern fixed_t globaluclip, globaldclip; @@ -86,13 +81,6 @@ fixed_t rw_offset_top; fixed_t rw_offset_mid; fixed_t rw_offset_bottom; -int OWallMost (short *mostbuf, fixed_t z); -int WallMost (short *mostbuf, const secplane_t &plane); -void PrepWall (fixed_t *swall, fixed_t *lwall, fixed_t walxrepeat); -void PrepLWall (fixed_t *lwall, fixed_t walxrepeat); -extern fixed_t WallSZ1, WallSZ2, WallTX1, WallTX2, WallTY1, WallTY2, WallCX1, WallCX2, WallCY1, WallCY2; -extern int WallSX1, WallSX2; -extern float WallUoverZorg, WallUoverZstep, WallInvZorg, WallInvZstep, WallDepthScale, WallDepthOrg; int wallshade; @@ -142,7 +130,6 @@ static fixed_t rw_bottomtexturescaley; FTexture *rw_pic; static fixed_t *maskedtexturecol; -static FTexture *WallSpriteTile; static void R_RenderDecal (side_t *wall, DBaseDecal *first, drawseg_t *clipper, int pass); static void WallSpriteColumn (void (*drawfunc)(const BYTE *column, const FTexture::Span *spans)); @@ -218,13 +205,13 @@ void ClipMidtex(int x1, int x2) { short most[MAXWIDTH]; - WallMost(most, curline->frontsector->ceilingplane); + WallMost(most, curline->frontsector->ceilingplane, &WallC); for (int i = x1; i <= x2; ++i) { if (wallupper[i] < most[i]) wallupper[i] = most[i]; } - WallMost(most, curline->frontsector->floorplane); + WallMost(most, curline->frontsector->floorplane, &WallC); for (int i = x1; i <= x2; ++i) { if (walllower[i] > most[i]) @@ -389,26 +376,26 @@ void R_RenderMaskedSegRange (drawseg_t *ds, int x1, int x2) goto clearfog; } - WallSZ1 = ds->sz1; - WallSZ2 = ds->sz2; - WallSX1 = ds->sx1; - WallSX2 = ds->sx2; + WallC.sz1 = ds->sz1; + WallC.sz2 = ds->sz2; + WallC.sx1 = ds->sx1; + WallC.sx2 = ds->sx2; if (fake3D & FAKE3D_CLIPTOP) { - OWallMost (wallupper, textop < sclipTop - viewz ? textop : sclipTop - viewz); + OWallMost(wallupper, textop < sclipTop - viewz ? textop : sclipTop - viewz, &WallC); } else { - OWallMost (wallupper, textop); + OWallMost(wallupper, textop, &WallC); } if (fake3D & FAKE3D_CLIPBOTTOM) { - OWallMost (walllower, textop - texheight > sclipBottom - viewz ? textop - texheight : sclipBottom - viewz); + OWallMost(walllower, textop - texheight > sclipBottom - viewz ? textop - texheight : sclipBottom - viewz, &WallC); } else { - OWallMost (walllower, textop - texheight); + OWallMost(walllower, textop - texheight, &WallC); } for (i = x1; i <= x2; i++) @@ -480,10 +467,10 @@ void R_RenderMaskedSegRange (drawseg_t *ds, int x1, int x2) } else { // Texture does wrap vertically. - WallSZ1 = ds->sz1; - WallSZ2 = ds->sz2; - WallSX1 = ds->sx1; - WallSX2 = ds->sx2; + WallC.sz1 = ds->sz1; + WallC.sz2 = ds->sz2; + WallC.sx1 = ds->sx1; + WallC.sx2 = ds->sx2; if (CurrentSkybox) { // Midtex clipping doesn't work properly with skyboxes, since you're normally below the floor @@ -498,7 +485,7 @@ void R_RenderMaskedSegRange (drawseg_t *ds, int x1, int x2) if (fake3D & FAKE3D_CLIPTOP) { - OWallMost (wallupper, sclipTop - viewz); + OWallMost(wallupper, sclipTop - viewz, &WallC); for (i = x1; i <= x2; i++) { if (wallupper[i] < mceilingclip[i]) @@ -508,7 +495,7 @@ void R_RenderMaskedSegRange (drawseg_t *ds, int x1, int x2) } if (fake3D & FAKE3D_CLIPBOTTOM) { - OWallMost (walllower, sclipBottom - viewz); + OWallMost(walllower, sclipBottom - viewz, &WallC); for (i = x1; i <= x2; i++) { if (walllower[i] > mfloorclip[i]) @@ -600,23 +587,18 @@ void R_RenderFakeWall(drawseg_t *ds, int x1, int x2, F3DFloor *rover) else if (fixedcolormap != NULL) dc_colormap = fixedcolormap; - WallSZ1 = ds->sz1; - WallSZ2 = ds->sz2; - WallSX1 = ds->sx1; - WallSX2 = ds->sx2; - WallTX1 = ds->cx; - WallTY1 = ds->cy; - WallTX2 = WallTX1 + ds->cdx; - WallTY2 = WallTY1 + ds->cdy; - WallDepthScale = ds->WallDepthScale; - WallDepthOrg = ds->WallDepthOrg; - WallUoverZorg = ds->WallUoverZorg; - WallUoverZstep = ds->WallUoverZstep; - WallInvZorg = ds->WallInvZorg; - WallInvZstep = ds->WallInvZstep; + WallC.sz1 = ds->sz1; + WallC.sz2 = ds->sz2; + WallC.sx1 = ds->sx1; + WallC.sx2 = ds->sx2; + WallC.tx1 = ds->cx; + WallC.ty1 = ds->cy; + WallC.tx2 = ds->cx + ds->cdx; + WallC.ty2 = ds->cy + ds->cdy; + WallT = ds->tmapvals; - OWallMost(wallupper, sclipTop - viewz); - OWallMost(walllower, sclipBottom - viewz); + OWallMost(wallupper, sclipTop - viewz, &WallC); + OWallMost(walllower, sclipBottom - viewz, &WallC); for (i = x1; i <= x2; i++) { @@ -629,7 +611,7 @@ void R_RenderFakeWall(drawseg_t *ds, int x1, int x2, F3DFloor *rover) walllower[i] = mfloorclip[i]; } - PrepLWall (lwall, curline->sidedef->TexelLength*xscale); + PrepLWall (lwall, curline->sidedef->TexelLength*xscale, ds->sx1, ds->sx2); wallscan_np2_ds(ds, x1, x2, wallupper, walllower, MaskedSWall, lwall, yscale); R_FinishSetPatchStyle(); } @@ -1227,13 +1209,13 @@ void wallscan_striped (int x1, int x2, short *uwal, short *dwal, fixed_t *swal, up = uwal; down = most1; - assert(WallSX1 <= x1); - assert(WallSX2 > x2); + assert(WallC.sx1 <= x1); + assert(WallC.sx2 > x2); // kg3D - fake floors instead of zdoom light list for (unsigned int i = 0; i < frontsector->e->XFloor.lightlist.Size(); i++) { - int j = WallMost (most3, frontsector->e->XFloor.lightlist[i].plane); + int j = WallMost (most3, frontsector->e->XFloor.lightlist[i].plane, &WallC); if (j != 3) { for (int j = x1; j <= x2; ++j) @@ -1315,7 +1297,7 @@ void wallscan_np2(int x1, int x2, short *uwal, short *dwal, fixed_t *swal, fixed dc_texturemid = FixedMul(partition - viewz, yrepeat) + texheight; while (partition > bot) { - int j = OWallMost(most3, partition - viewz); + int j = OWallMost(most3, partition - viewz, &WallC); if (j != 3) { for (int j = x1; j <= x2; ++j) @@ -1339,7 +1321,7 @@ void wallscan_np2(int x1, int x2, short *uwal, short *dwal, fixed_t *swal, fixed dc_texturemid = FixedMul(partition - viewz, yrepeat) + texheight; while (partition < top) { - int j = OWallMost(most3, partition - viewz); + int j = OWallMost(most3, partition - viewz, &WallC); if (j != 12) { for (int j = x1; j <= x2; ++j) @@ -1839,7 +1821,7 @@ void R_RenderSegLoop () yscale = FixedMul(rw_pic->yScale, rw_midtexturescaley); if (xscale != lwallscale) { - PrepLWall (lwall, curline->sidedef->TexelLength*xscale); + PrepLWall (lwall, curline->sidedef->TexelLength*xscale, WallC.sx1, WallC.sx2); lwallscale = xscale; } if (midtexture->bWorldPanning) @@ -1882,7 +1864,7 @@ void R_RenderSegLoop () yscale = FixedMul(rw_pic->yScale, rw_toptexturescaley); if (xscale != lwallscale) { - PrepLWall (lwall, curline->sidedef->TexelLength*xscale); + PrepLWall (lwall, curline->sidedef->TexelLength*xscale, WallC.sx1, WallC.sx2); lwallscale = xscale; } if (toptexture->bWorldPanning) @@ -1928,7 +1910,7 @@ void R_RenderSegLoop () yscale = FixedMul(rw_pic->yScale, rw_bottomtexturescaley); if (xscale != lwallscale) { - PrepLWall (lwall, curline->sidedef->TexelLength*xscale); + PrepLWall (lwall, curline->sidedef->TexelLength*xscale, WallC.sx1, WallC.sx2); lwallscale = xscale; } if (bottomtexture->bWorldPanning) @@ -2048,7 +2030,7 @@ void R_NewWall (bool needlights) { if (rw_havehigh) { // front ceiling is above back ceiling - memcpy (&walltop[WallSX1], &wallupper[WallSX1], (WallSX2 - WallSX1)*sizeof(walltop[0])); + memcpy (&walltop[WallC.sx1], &wallupper[WallC.sx1], (WallC.sx2 - WallC.sx1)*sizeof(walltop[0])); rw_havehigh = false; } else if (rw_havelow && frontsector->ceilingplane != backsector->ceilingplane) @@ -2058,7 +2040,7 @@ void R_NewWall (bool needlights) // wall but nothing to draw for it. // Recalculate walltop so that the wall is clipped by the back sector's // ceiling instead of the front sector's ceiling. - WallMost (walltop, backsector->ceilingplane); + WallMost (walltop, backsector->ceilingplane, &WallC); } // Putting sky ceilings on the front and back of a line alters the way unpegged // positioning works. @@ -2273,15 +2255,15 @@ void R_NewWall (bool needlights) bottomtexture ? FixedMul(bottomtexture->xScale, sidedef->GetTextureXScale(side_t::bottom)) : FRACUNIT; - PrepWall (swall, lwall, sidedef->TexelLength * lwallscale); + PrepWall (swall, lwall, sidedef->TexelLength * lwallscale, WallC.sx1, WallC.sx2); if (fixedcolormap == NULL && fixedlightlev < 0) { wallshade = LIGHT2SHADE(curline->sidedef->GetLightLevel(foggy, frontsector->lightlevel) + r_actualextralight); GlobVis = r_WallVisibility; - rw_lightleft = SafeDivScale12 (GlobVis, WallSZ1); - rw_lightstep = (SafeDivScale12 (GlobVis, WallSZ2) - rw_lightleft) / (WallSX2 - WallSX1); + rw_lightleft = SafeDivScale12 (GlobVis, WallC.sz1); + rw_lightstep = (SafeDivScale12 (GlobVis, WallC.sz2) - rw_lightleft) / (WallC.sx2 - WallC.sx1); } else { @@ -2355,24 +2337,19 @@ void R_StoreWallRange (int start, int stop) } rw_offset = sidedef->GetTextureXOffset(side_t::mid); - rw_light = rw_lightleft + rw_lightstep * (start - WallSX1); + rw_light = rw_lightleft + rw_lightstep * (start - WallC.sx1); - ds_p->sx1 = WallSX1; - ds_p->sx2 = WallSX2; - ds_p->sz1 = WallSZ1; - ds_p->sz2 = WallSZ2; - ds_p->cx = WallTX1; - ds_p->cy = WallTY1; - ds_p->cdx = WallTX2 - WallTX1; - ds_p->cdy = WallTY2 - WallTY1; - ds_p->WallDepthScale = WallDepthScale; - ds_p->WallDepthOrg = WallDepthOrg; - ds_p->WallUoverZorg = WallUoverZorg; - ds_p->WallUoverZstep = WallUoverZstep; - ds_p->WallInvZorg = WallInvZorg; - ds_p->WallInvZstep = WallInvZstep; - ds_p->siz1 = (DWORD)DivScale32 (1, WallSZ1) >> 1; - ds_p->siz2 = (DWORD)DivScale32 (1, WallSZ2) >> 1; + ds_p->sx1 = WallC.sx1; + ds_p->sx2 = WallC.sx2; + ds_p->sz1 = WallC.sz1; + ds_p->sz2 = WallC.sz2; + ds_p->cx = WallC.tx1; + ds_p->cy = WallC.ty1; + ds_p->cdx = WallC.tx2 - WallC.tx1; + ds_p->cdy = WallC.ty2 - WallC.ty1; + ds_p->tmapvals = WallT; + ds_p->siz1 = (DWORD)DivScale32 (1, WallC.sz1) >> 1; + ds_p->siz2 = (DWORD)DivScale32 (1, WallC.sz2) >> 1; ds_p->x1 = rw_x = start; ds_p->x2 = stop-1; ds_p->curline = curline; @@ -2465,7 +2442,7 @@ void R_StoreWallRange (int start, int stop) if ((TexMan(sidedef->GetTexture(side_t::mid), true)->UseType != FTexture::TEX_Null || ds_p->bFakeBoundary || IsFogBoundary (frontsector, backsector)) && (rw_ceilstat != 12 || !sidedef->GetTexture(side_t::top).isValid()) && (rw_floorstat != 3 || !sidedef->GetTexture(side_t::bottom).isValid()) && - (WallSZ1 >= TOO_CLOSE_Z && WallSZ2 >= TOO_CLOSE_Z)) + (WallC.sz1 >= TOO_CLOSE_Z && WallC.sz2 >= TOO_CLOSE_Z)) { fixed_t *swal; fixed_t *lwal; @@ -2607,65 +2584,65 @@ void R_StoreWallRange (int start, int stop) ds_p++; } -int OWallMost (short *mostbuf, fixed_t z) +int OWallMost (short *mostbuf, fixed_t z, const FWallCoords *wallc) { int bad, y, ix1, ix2, iy1, iy2; fixed_t s1, s2, s3, s4; z = -(z >> 4); - s1 = MulScale16 (globaluclip, WallSZ1); s2 = MulScale16 (globaluclip, WallSZ2); - s3 = MulScale16 (globaldclip, WallSZ1); s4 = MulScale16 (globaldclip, WallSZ2); + s1 = MulScale16 (globaluclip, wallc->sz1); s2 = MulScale16 (globaluclip, wallc->sz2); + s3 = MulScale16 (globaldclip, wallc->sz1); s4 = MulScale16 (globaldclip, wallc->sz2); bad = (zs3)<<2)+((z>s4)<<3); #if 1 if ((bad&3) == 3) { - memset (&mostbuf[WallSX1], 0, (WallSX2 - WallSX1)*sizeof(mostbuf[0])); + memset (&mostbuf[wallc->sx1], 0, (wallc->sx2 - wallc->sx1)*sizeof(mostbuf[0])); return bad; } if ((bad&12) == 12) { - clearbufshort (&mostbuf[WallSX1], WallSX2 - WallSX1, viewheight); + clearbufshort (&mostbuf[wallc->sx1], wallc->sx2 - wallc->sx1, viewheight); return bad; } #endif - ix1 = WallSX1; iy1 = WallSZ1; - ix2 = WallSX2; iy2 = WallSZ2; + ix1 = wallc->sx1; iy1 = wallc->sz1; + ix2 = wallc->sx2; iy2 = wallc->sz2; #if 1 if (bad & 3) { int t = DivScale30 (z-s1, s2-s1); - int inty = WallSZ1 + MulScale30 (WallSZ2 - WallSZ1, t); - int xcross = WallSX1 + Scale (MulScale30 (WallSZ2, t), WallSX2 - WallSX1, inty); + int inty = wallc->sz1 + MulScale30 (wallc->sz2 - wallc->sz1, t); + int xcross = wallc->sx1 + Scale (MulScale30 (wallc->sz2, t), wallc->sx2 - wallc->sx1, inty); if ((bad & 3) == 2) { - if (WallSX1 <= xcross) { iy2 = inty; ix2 = xcross; } - if (WallSX2 > xcross) memset (&mostbuf[xcross], 0, (WallSX2-xcross)*sizeof(mostbuf[0])); + if (wallc->sx1 <= xcross) { iy2 = inty; ix2 = xcross; } + if (wallc->sx2 > xcross) memset (&mostbuf[xcross], 0, (wallc->sx2-xcross)*sizeof(mostbuf[0])); } else { - if (xcross <= WallSX2) { iy1 = inty; ix1 = xcross; } - if (xcross > WallSX1) memset (&mostbuf[WallSX1], 0, (xcross-WallSX1)*sizeof(mostbuf[0])); + if (xcross <= wallc->sx2) { iy1 = inty; ix1 = xcross; } + if (xcross > wallc->sx1) memset (&mostbuf[wallc->sx1], 0, (xcross-wallc->sx1)*sizeof(mostbuf[0])); } } if (bad & 12) { int t = DivScale30 (z-s3, s4-s3); - int inty = WallSZ1 + MulScale30 (WallSZ2 - WallSZ1, t); - int xcross = WallSX1 + Scale (MulScale30 (WallSZ2, t), WallSX2 - WallSX1, inty); + int inty = wallc->sz1 + MulScale30 (wallc->sz2 - wallc->sz1, t); + int xcross = wallc->sx1 + Scale (MulScale30 (wallc->sz2, t), wallc->sx2 - wallc->sx1, inty); if ((bad & 12) == 8) { - if (WallSX1 <= xcross) { iy2 = inty; ix2 = xcross; } - if (WallSX2 > xcross) clearbufshort (&mostbuf[xcross], WallSX2 - xcross, viewheight); + if (wallc->sx1 <= xcross) { iy2 = inty; ix2 = xcross; } + if (wallc->sx2 > xcross) clearbufshort (&mostbuf[xcross], wallc->sx2 - xcross, viewheight); } else { - if (xcross <= WallSX2) { iy1 = inty; ix1 = xcross; } - if (xcross > WallSX1) clearbufshort (&mostbuf[WallSX1], xcross - WallSX1, viewheight); + if (xcross <= wallc->sx2) { iy1 = inty; ix1 = xcross; } + if (xcross > wallc->sx1) clearbufshort (&mostbuf[wallc->sx1], xcross - wallc->sx1, viewheight); } } @@ -2683,12 +2660,12 @@ int OWallMost (short *mostbuf, fixed_t z) double max = viewheight; double zz = z / 65536.0; #if 0 - double z1 = zz * InvZtoScale / WallSZ1; - double z2 = zz * InvZtoScale / WallSZ2 - z1; - z2 /= (WallSX2 - WallSX1); + double z1 = zz * InvZtoScale / wallc->sz1; + double z2 = zz * InvZtoScale / wallc->sz2 - z1; + z2 /= (wallc->sx2 - wallc->sx1); z1 += centeryfrac / 65536.0; - for (int x = WallSX1; x < WallSX2; ++x) + for (int x = wallc->sx1; x < wallc->sx2; ++x) { mostbuf[x] = xs_RoundToInt(clamp(z1, 0.0, max)); z1 += z2; @@ -2696,18 +2673,18 @@ int OWallMost (short *mostbuf, fixed_t z) #else double top, bot, i; - i = WallSX1 - centerx; - top = WallUoverZorg + WallUoverZstep * i; - bot = WallInvZorg + WallInvZstep * i; + i = wallc->sx1 - centerx; + top = WallT.UoverZorg + WallT.UoverZstep * i; + bot = WallT.InvZorg + WallT.InvZstep * i; double cy = centeryfrac / 65536.0; - for (int x = WallSX1; x < WallSX2; x++) + for (int x = wallc->sx1; x < wallc->sx2; x++) { double frac = top / bot; - double scale = frac * WallDepthScale + WallDepthOrg; + double scale = frac * WallT.DepthScale + WallT.DepthOrg; mostbuf[x] = xs_RoundToInt(clamp(zz / scale + cy, 0.0, max)); - top += WallUoverZstep; - bot += WallInvZstep; + top += WallT.UoverZstep; + bot += WallT.InvZstep; } #endif #endif @@ -2719,11 +2696,11 @@ int OWallMost (short *mostbuf, fixed_t z) return bad; } -int WallMost (short *mostbuf, const secplane_t &plane) +int WallMost (short *mostbuf, const secplane_t &plane, const FWallCoords *wallc) { if ((plane.a | plane.b) == 0) { - return OWallMost (mostbuf, ((plane.c < 0) ? plane.d : -plane.d) - viewz); + return OWallMost (mostbuf, ((plane.c < 0) ? plane.d : -plane.d) - viewz, wallc); } fixed_t x, y, den, z1, z2, oz1, oz2; @@ -2734,21 +2711,21 @@ int WallMost (short *mostbuf, const secplane_t &plane) { x = curline->v2->x; y = curline->v2->y; - if (WallSX1 == 0 && 0 != (den = WallTX1 - WallTX2 + WallTY1 - WallTY2)) + if (wallc->sx1 == 0 && 0 != (den = wallc->tx1 - wallc->tx2 + wallc->ty1 - wallc->ty2)) { - int frac = SafeDivScale30 (WallTY1 + WallTX1, den); + int frac = SafeDivScale30 (wallc->ty1 + wallc->tx1, den); x -= MulScale30 (frac, x - curline->v1->x); y -= MulScale30 (frac, y - curline->v1->y); } z1 = viewz - plane.ZatPoint (x, y); - if (WallSX2 > WallSX1 + 1) + if (wallc->sx2 > wallc->sx1 + 1) { x = curline->v1->x; y = curline->v1->y; - if (WallSX2 == viewwidth && 0 != (den = WallTX1 - WallTX2 - WallTY1 + WallTY2)) + if (wallc->sx2 == viewwidth && 0 != (den = wallc->tx1 - wallc->tx2 - wallc->ty1 + wallc->ty2)) { - int frac = SafeDivScale30 (WallTY2 - WallTX2, den); + int frac = SafeDivScale30 (wallc->ty2 - wallc->tx2, den); x += MulScale30 (frac, curline->v2->x - x); y += MulScale30 (frac, curline->v2->y - y); } @@ -2763,21 +2740,21 @@ int WallMost (short *mostbuf, const secplane_t &plane) { x = curline->v1->x; y = curline->v1->y; - if (WallSX1 == 0 && 0 != (den = WallTX1 - WallTX2 + WallTY1 - WallTY2)) + if (wallc->sx1 == 0 && 0 != (den = wallc->tx1 - wallc->tx2 + wallc->ty1 - wallc->ty2)) { - int frac = SafeDivScale30 (WallTY1 + WallTX1, den); + int frac = SafeDivScale30 (wallc->ty1 + wallc->tx1, den); x += MulScale30 (frac, curline->v2->x - x); y += MulScale30 (frac, curline->v2->y - y); } z1 = viewz - plane.ZatPoint (x, y); - if (WallSX2 > WallSX1 + 1) + if (wallc->sx2 > wallc->sx1 + 1) { x = curline->v2->x; y = curline->v2->y; - if (WallSX2 == viewwidth && 0 != (den = WallTX1 - WallTX2 - WallTY1 + WallTY2)) + if (wallc->sx2 == viewwidth && 0 != (den = wallc->tx1 - wallc->tx2 - wallc->ty1 + wallc->ty2)) { - int frac = SafeDivScale30 (WallTY2 - WallTX2, den); + int frac = SafeDivScale30 (wallc->ty2 - wallc->tx2, den); x -= MulScale30 (frac, x - curline->v1->x); y -= MulScale30 (frac, y - curline->v1->y); } @@ -2789,12 +2766,12 @@ int WallMost (short *mostbuf, const secplane_t &plane) } } - s1 = MulScale12 (globaluclip, WallSZ1); s2 = MulScale12 (globaluclip, WallSZ2); - s3 = MulScale12 (globaldclip, WallSZ1); s4 = MulScale12 (globaldclip, WallSZ2); + s1 = MulScale12 (globaluclip, wallc->sz1); s2 = MulScale12 (globaluclip, wallc->sz2); + s3 = MulScale12 (globaldclip, wallc->sz1); s4 = MulScale12 (globaldclip, wallc->sz2); bad = (z1s3)<<2)+((z2>s4)<<3); - ix1 = WallSX1; ix2 = WallSX2; - iy1 = WallSZ1; iy2 = WallSZ2; + ix1 = wallc->sx1; ix2 = wallc->sx2; + iy1 = wallc->sz1; iy2 = wallc->sz2; oz1 = z1; oz2 = z2; if ((bad&3) == 3) @@ -2814,9 +2791,9 @@ int WallMost (short *mostbuf, const secplane_t &plane) { //inty = intz / (globaluclip>>16) int t = SafeDivScale30 (oz1-s1, s2-s1+oz1-oz2); - int inty = WallSZ1 + MulScale30 (WallSZ2-WallSZ1,t); + int inty = wallc->sz1 + MulScale30 (wallc->sz2-wallc->sz1,t); int intz = oz1 + MulScale30 (oz2-oz1,t); - int xcross = WallSX1 + Scale (MulScale30 (WallSZ2, t), WallSX2-WallSX1, inty); + int xcross = wallc->sx1 + Scale (MulScale30 (wallc->sz2, t), wallc->sx2-wallc->sx1, inty); //t = divscale30((x1<<4)-xcross*yb1[w],xcross*(yb2[w]-yb1[w])-((x2-x1)<<4)); //inty = yb1[w] + mulscale30(yb2[w]-yb1[w],t); @@ -2824,13 +2801,13 @@ int WallMost (short *mostbuf, const secplane_t &plane) if ((bad&3) == 2) { - if (WallSX1 <= xcross) { z2 = intz; iy2 = inty; ix2 = xcross; } - memset (&mostbuf[xcross], 0, (WallSX2-xcross)*sizeof(mostbuf[0])); + if (wallc->sx1 <= xcross) { z2 = intz; iy2 = inty; ix2 = xcross; } + memset (&mostbuf[xcross], 0, (wallc->sx2-xcross)*sizeof(mostbuf[0])); } else { - if (xcross <= WallSX2) { z1 = intz; iy1 = inty; ix1 = xcross; } - memset (&mostbuf[WallSX1], 0, (xcross-WallSX1)*sizeof(mostbuf[0])); + if (xcross <= wallc->sx2) { z1 = intz; iy1 = inty; ix1 = xcross; } + memset (&mostbuf[wallc->sx1], 0, (xcross-wallc->sx1)*sizeof(mostbuf[0])); } } @@ -2838,9 +2815,9 @@ int WallMost (short *mostbuf, const secplane_t &plane) { //inty = intz / (globaldclip>>16) int t = SafeDivScale30 (oz1-s3, s4-s3+oz1-oz2); - int inty = WallSZ1 + MulScale30 (WallSZ2-WallSZ1,t); + int inty = wallc->sz1 + MulScale30 (wallc->sz2-wallc->sz1,t); int intz = oz1 + MulScale30 (oz2-oz1,t); - int xcross = WallSX1 + Scale (MulScale30 (WallSZ2, t), WallSX2-WallSX1,inty); + int xcross = wallc->sx1 + Scale (MulScale30 (wallc->sz2, t), wallc->sx2-wallc->sx1,inty); //t = divscale30((x1<<4)-xcross*yb1[w],xcross*(yb2[w]-yb1[w])-((x2-x1)<<4)); //inty = yb1[w] + mulscale30(yb2[w]-yb1[w],t); @@ -2848,13 +2825,13 @@ int WallMost (short *mostbuf, const secplane_t &plane) if ((bad&12) == 8) { - if (WallSX1 <= xcross) { z2 = intz; iy2 = inty; ix2 = xcross; } - if (WallSX2 > xcross) clearbufshort (&mostbuf[xcross], WallSX2-xcross, viewheight); + if (wallc->sx1 <= xcross) { z2 = intz; iy2 = inty; ix2 = xcross; } + if (wallc->sx2 > xcross) clearbufshort (&mostbuf[xcross], wallc->sx2-xcross, viewheight); } else { - if (xcross <= WallSX2) { z1 = intz; iy1 = inty; ix1 = xcross; } - if (xcross > WallSX1) clearbufshort (&mostbuf[WallSX1], xcross-WallSX1, viewheight); + if (xcross <= wallc->sx2) { z1 = intz; iy1 = inty; ix1 = xcross; } + if (xcross > wallc->sx1) clearbufshort (&mostbuf[wallc->sx1], xcross-wallc->sx1, viewheight); } } @@ -2877,16 +2854,16 @@ int WallMost (short *mostbuf, const secplane_t &plane) return bad; } -static void PrepWallRoundFix(fixed_t *lwall, fixed_t walxrepeat) +static void PrepWallRoundFix(fixed_t *lwall, fixed_t walxrepeat, int x1, int x2) { // fix for rounding errors walxrepeat = abs(walxrepeat); fixed_t fix = (MirrorFlags & RF_XFLIP) ? walxrepeat-1 : 0; int x; - if (WallSX1 > 0) + if (x1 > 0) { - for (x = WallSX1; x < WallSX2; x++) + for (x = x1; x < x2; x++) { if ((unsigned)lwall[x] >= (unsigned)walxrepeat) { @@ -2899,7 +2876,7 @@ static void PrepWallRoundFix(fixed_t *lwall, fixed_t walxrepeat) } } fix = walxrepeat - 1 - fix; - for (x = WallSX2-1; x >= WallSX1; x--) + for (x = x2-1; x >= x1; x--) { if ((unsigned)lwall[x] >= (unsigned)walxrepeat) { @@ -2912,16 +2889,18 @@ static void PrepWallRoundFix(fixed_t *lwall, fixed_t walxrepeat) } } -void PrepWall (fixed_t *swall, fixed_t *lwall, fixed_t walxrepeat) +void PrepWall (fixed_t *swall, fixed_t *lwall, fixed_t walxrepeat, int x1, int x2) { // swall = scale, lwall = texturecolumn double top, bot, i; double xrepeat = fabs((double)walxrepeat); + double depth_scale = WallT.InvZstep * WallTMapScale2; + double depth_org = -WallT.UoverZstep * WallTMapScale2; - i = WallSX1 - centerx; - top = WallUoverZorg + WallUoverZstep * i; - bot = WallInvZorg + WallInvZstep * i; + i = x1 - centerx; + top = WallT.UoverZorg + WallT.UoverZstep * i; + bot = WallT.InvZorg + WallT.InvZstep * i; - for (int x = WallSX1; x < WallSX2; x++) + for (int x = x1; x < x2; x++) { double frac = top / bot; if (walxrepeat < 0) @@ -2932,27 +2911,27 @@ void PrepWall (fixed_t *swall, fixed_t *lwall, fixed_t walxrepeat) { lwall[x] = xs_RoundToInt(frac * xrepeat); } - swall[x] = xs_RoundToInt(frac * WallDepthScale + WallDepthOrg); - top += WallUoverZstep; - bot += WallInvZstep; + swall[x] = xs_RoundToInt(frac * depth_scale + depth_org); + top += WallT.UoverZstep; + bot += WallT.InvZstep; } - PrepWallRoundFix(lwall, walxrepeat); + PrepWallRoundFix(lwall, walxrepeat, x1, x2); } -void PrepLWall (fixed_t *lwall, fixed_t walxrepeat) +void PrepLWall (fixed_t *lwall, fixed_t walxrepeat, int x1, int x2) { // lwall = texturecolumn double top, bot, i; double xrepeat = fabs((double)walxrepeat); double topstep; - i = WallSX1 - centerx; - top = WallUoverZorg + WallUoverZstep * i; - bot = WallInvZorg + WallInvZstep * i; + i = x1 - centerx; + top = WallT.UoverZorg + WallT.UoverZstep * i; + bot = WallT.InvZorg + WallT.InvZstep * i; top *= xrepeat; - topstep = WallUoverZstep * xrepeat; + topstep = WallT.UoverZstep * xrepeat; - for (int x = WallSX1; x < WallSX2; x++) + for (int x = x1; x < x2; x++) { if (walxrepeat < 0) { @@ -2963,9 +2942,9 @@ void PrepLWall (fixed_t *lwall, fixed_t walxrepeat) lwall[x] = xs_RoundToInt(top / bot); } top += topstep; - bot += WallInvZstep; + bot += WallT.InvZstep; } - PrepWallRoundFix(lwall, walxrepeat); + PrepWallRoundFix(lwall, walxrepeat, x1, x2); } // pass = 0: when seg is first drawn @@ -3044,14 +3023,7 @@ static void R_RenderDecal (side_t *wall, DBaseDecal *decal, drawseg_t *clipper, // to a wall, we use the wall's angle instead of the decal's. This is // pretty much the same as what R_AddLine() does. - fixed_t savetx1, savetx2, savety1, savety2, savesz1, savesz2; - - savetx1 = WallTX1; - savetx2 = WallTX2; - savety1 = WallTY1; - savety2 = WallTY2; - savesz1 = WallSZ1; - savesz2 = WallSZ2; + FWallCoords savecoord = WallC; x2 = WallSpriteTile->GetWidth(); x1 = WallSpriteTile->LeftOffset; @@ -3068,76 +3040,16 @@ static void R_RenderDecal (side_t *wall, DBaseDecal *decal, drawseg_t *clipper, ly = decaly - FixedMul (x1, finesine[ang]) - viewy; ly2 = decaly + FixedMul (x2, finesine[ang]) - viewy; - WallTX1 = DMulScale20 (lx, viewsin, -ly, viewcos); - WallTX2 = DMulScale20 (lx2, viewsin, -ly2, viewcos); - - WallTY1 = DMulScale20 (lx, viewtancos, ly, viewtansin); - WallTY2 = DMulScale20 (lx2, viewtancos, ly2, viewtansin); - - if (MirrorFlags & RF_XFLIP) - { - int t = 256-WallTX1; - WallTX1 = 256-WallTX2; - WallTX2 = t; - swapvalues (WallTY1, WallTY2); - } - - if (WallTX1 >= -WallTY1) - { - if (WallTX1 > WallTY1) goto done; // left edge is off the right side - if (WallTY1 == 0) goto done; - x1 = (centerxfrac + Scale (WallTX1, centerxfrac, WallTY1)) >> FRACBITS; - if (WallTX1 >= 0) x1 = MIN (viewwidth, x1+1); // fix for signed divide - WallSZ1 = WallTY1; - } - else - { - if (WallTX2 < -WallTY2) goto done; // wall is off the left side - fixed_t den = WallTX1 - WallTX2 - WallTY2 + WallTY1; - if (den == 0) goto done; - x1 = 0; - WallSZ1 = WallTY1 + Scale (WallTY2 - WallTY1, WallTX1 + WallTY1, den); - } - - if (WallSZ1 < TOO_CLOSE_Z) + if (WallC.Init(lx, ly, lx2, ly2, TOO_CLOSE_Z)) goto done; - if (WallTX2 <= WallTY2) - { - if (WallTX2 < -WallTY2) goto done; // right edge is off the left side - if (WallTY2 == 0) goto done; - x2 = (centerxfrac + Scale (WallTX2, centerxfrac, WallTY2)) >> FRACBITS; - if (WallTX2 >= 0) x2 = MIN (viewwidth, x2+1); // fix for signed divide - WallSZ2 = WallTY2; - } - else - { - if (WallTX1 > WallTY1) goto done; // wall is off the right side - fixed_t den = WallTY2 - WallTY1 - WallTX2 + WallTX1; - if (den == 0) goto done; - x2 = viewwidth; - WallSZ2 = WallTY1 + Scale (WallTY2 - WallTY1, WallTX1 - WallTY1, den); - } + x1 = WallC.sx1; + x2 = WallC.sx2; - if (x1 >= x2 || x1 > clipper->x2 || x2 <= clipper->x1 || WallSZ2 < TOO_CLOSE_Z) + if (x1 > clipper->x2 || x2 <= clipper->x1) goto done; - if (MirrorFlags & RF_XFLIP) - { - WallUoverZorg = (float)WallTX2 * WallTMapScale; - WallUoverZstep = (float)(-WallTY2) * 32.f; - WallInvZorg = (float)(WallTX2 - WallTX1) * WallTMapScale; - WallInvZstep = (float)(WallTY1 - WallTY2) * 32.f; - } - else - { - WallUoverZorg = (float)WallTX1 * WallTMapScale; - WallUoverZstep = (float)(-WallTY1) * 32.f; - WallInvZorg = (float)(WallTX1 - WallTX2) * WallTMapScale; - WallInvZstep = (float)(WallTY2 - WallTY1) * 32.f; - } - WallDepthScale = WallInvZstep * WallTMapScale2; - WallDepthOrg = -WallUoverZstep * WallTMapScale2; + WallT.InitFromWallCoords(&WallC); // Get the top and bottom clipping arrays switch (decal->RenderFlags & RF_CLIPMASK) @@ -3210,11 +3122,7 @@ static void R_RenderDecal (side_t *wall, DBaseDecal *decal, drawseg_t *clipper, goto done; } - swapvalues (x1, WallSX1); - swapvalues (x2, WallSX2); - PrepWall (swall, lwall, WallSpriteTile->GetWidth() << FRACBITS); - swapvalues (x1, WallSX1); - swapvalues (x2, WallSX2); + PrepWall (swall, lwall, WallSpriteTile->GetWidth() << FRACBITS, x1, x2); if (flipx) { @@ -3239,7 +3147,7 @@ static void R_RenderDecal (side_t *wall, DBaseDecal *decal, drawseg_t *clipper, rereadcolormap = false; } - rw_light = rw_lightleft + (x1 - WallSX1) * rw_lightstep; + rw_light = rw_lightleft + (x1 - WallC.sx1) * rw_lightstep; if (fixedlightlev >= 0) dc_colormap = usecolormap->Maps + fixedlightlev; else if (fixedcolormap != NULL) @@ -3300,8 +3208,7 @@ static void R_RenderDecal (side_t *wall, DBaseDecal *decal, drawseg_t *clipper, { // calculate lighting dc_colormap = usecolormap->Maps + (GETPALOOKUP (rw_light, wallshade) << COLORMAPSHIFT); } - - WallSpriteColumn (R_DrawMaskedColumn); + R_WallSpriteColumn (R_DrawMaskedColumn); dc_x++; } @@ -3314,7 +3221,7 @@ static void R_RenderDecal (side_t *wall, DBaseDecal *decal, drawseg_t *clipper, rt_initcols(); for (int zz = 4; zz; --zz) { - WallSpriteColumn (R_DrawMaskedColumnHoriz); + R_WallSpriteColumn (R_DrawMaskedColumnHoriz); dc_x++; } rt_draw4cols (dc_x - 4); @@ -3326,8 +3233,7 @@ static void R_RenderDecal (side_t *wall, DBaseDecal *decal, drawseg_t *clipper, { // calculate lighting dc_colormap = usecolormap->Maps + (GETPALOOKUP (rw_light, wallshade) << COLORMAPSHIFT); } - - WallSpriteColumn (R_DrawMaskedColumn); + R_WallSpriteColumn (R_DrawMaskedColumn); dc_x++; } } @@ -3346,28 +3252,5 @@ static void R_RenderDecal (side_t *wall, DBaseDecal *decal, drawseg_t *clipper, R_FinishSetPatchStyle (); done: - WallTX1 = savetx1; - WallTX2 = savetx2; - WallTY1 = savety1; - WallTY2 = savety2; - WallSZ1 = savesz1; - WallSZ2 = savesz2; -} - -static void WallSpriteColumn (void (*drawfunc)(const BYTE *column, const FTexture::Span *spans)) -{ - unsigned int texturecolumn = lwall[dc_x] >> FRACBITS; - dc_iscale = MulScale16 (swall[dc_x], rw_offset); - spryscale = SafeDivScale32 (1, dc_iscale); - if (sprflipvert) - sprtopscreen = centeryfrac + FixedMul (dc_texturemid, spryscale); - else - sprtopscreen = centeryfrac - FixedMul (dc_texturemid, spryscale); - - const BYTE *column; - const FTexture::Span *spans; - column = WallSpriteTile->GetColumn (texturecolumn, &spans); - dc_texturefrac = 0; - drawfunc (column, spans); - rw_light += rw_lightstep; + WallC = savecoord; } diff --git a/src/r_segs.h b/src/r_segs.h index d46a3a523..b8bf96511 100644 --- a/src/r_segs.h +++ b/src/r_segs.h @@ -31,10 +31,22 @@ extern short *openings; extern ptrdiff_t lastopening; extern size_t maxopenings; +int OWallMost (short *mostbuf, fixed_t z, const FWallCoords *wallc); +int WallMost (short *mostbuf, const secplane_t &plane, const FWallCoords *wallc); +void PrepWall (fixed_t *swall, fixed_t *lwall, fixed_t walxrepeat, int x1, int x2); +void PrepLWall (fixed_t *lwall, fixed_t walxrepeat, int x1, int x2); + ptrdiff_t R_NewOpening (ptrdiff_t len); void R_CheckDrawSegs (); void R_RenderSegLoop (); +extern fixed_t swall[MAXWIDTH]; +extern fixed_t lwall[MAXWIDTH]; +extern fixed_t rw_light; // [RH] Scale lights with viewsize adjustments +extern fixed_t rw_lightstep; +extern fixed_t rw_lightleft; +extern fixed_t rw_offset; + #endif diff --git a/src/r_swrenderer.cpp b/src/r_swrenderer.cpp index 56f816d6f..fb54b6f0a 100644 --- a/src/r_swrenderer.cpp +++ b/src/r_swrenderer.cpp @@ -40,7 +40,6 @@ #include "r_bsp.h" #include "r_swrenderer.h" #include "r_3dfloors.h" -#include "r_polymost.h" #include "textures/textures.h" #include "r_data/voxels.h" @@ -49,7 +48,6 @@ class FArchive; void R_SWRSetWindow(int windowSize, int fullWidth, int fullHeight, int stHeight, int trueratio); void R_SetupColormap(player_t *); void R_SetupFreelook(); -void R_SetupPolymost(); void R_InitRenderer(); extern float LastFOV; @@ -245,7 +243,6 @@ void FSoftwareRenderer::SetupFrame(player_t *player) { R_SetupColormap(player); R_SetupFreelook(); - R_SetupPolymost(); } //========================================================================== diff --git a/src/r_things.cpp b/src/r_things.cpp index 518e22894..ca4f23999 100644 --- a/src/r_things.cpp +++ b/src/r_things.cpp @@ -114,6 +114,8 @@ FDynamicColormap *VisPSpritesBaseColormap[NUMPSPRITES]; static int spriteshade; +FTexture *WallSpriteTile; + // constant arrays // used for psprite clipping and initializing clipping short zeroarray[MAXWIDTH]; @@ -146,6 +148,8 @@ static vissprite_t **spritesorter; static int spritesortersize = 0; static int vsprcount; +static void R_ProjectWallSprite(AActor *thing, fixed_t fx, fixed_t fy, fixed_t fz, FTextureID picnum, fixed_t xscale, fixed_t yscale, INTBOOL flip); + void R_DeinitSprites() @@ -408,6 +412,154 @@ void R_DrawVisSprite (vissprite_t *vis) NetUpdate (); } +void R_DrawWallSprite(vissprite_t *spr) +{ + int x1, x2; + fixed_t yscale; + + x1 = MAX(spr->x1, spr->wallc.sx1); + x2 = MIN(spr->x2 + 1, spr->wallc.sx2 + 1); + if (x1 >= x2) + return; + WallT.InitFromWallCoords(&spr->wallc); + PrepWall(swall, lwall, spr->pic->GetWidth() << FRACBITS, x1, x2); + yscale = spr->yscale; + dc_texturemid = FixedDiv(spr->gzt - viewz, yscale); + if (spr->renderflags & RF_XFLIP) + { + int right = (spr->pic->GetWidth() << FRACBITS) - 1; + + for (int i = x1; i < x2; i++) + { + lwall[i] = right - lwall[i]; + } + } + // Prepare lighting + bool calclighting = false; + FDynamicColormap *usecolormap = basecolormap; + bool rereadcolormap = true; + + // Decals that are added to the scene must fade to black. + if (spr->Style.RenderStyle == LegacyRenderStyles[STYLE_Add] && usecolormap->Fade != 0) + { + usecolormap = GetSpecialLights(usecolormap->Color, 0, usecolormap->Desaturate); + rereadcolormap = false; + } + + int shade = LIGHT2SHADE(spr->sector->lightlevel + r_actualextralight); + GlobVis = r_WallVisibility; + rw_lightleft = SafeDivScale12(GlobVis, spr->wallc.sz1); + rw_lightstep = (SafeDivScale12(GlobVis, spr->wallc.sz2) - rw_lightleft) / (spr->wallc.sx2 - spr->wallc.sx1); + rw_light = rw_lightleft + (x1 - spr->wallc.sx1) * rw_lightstep; + if (fixedlightlev >= 0) + dc_colormap = usecolormap->Maps + fixedlightlev; + else if (fixedcolormap != NULL) + dc_colormap = fixedcolormap; + else if (!foggy && (spr->renderflags & RF_FULLBRIGHT)) + dc_colormap = usecolormap->Maps; + else + calclighting = true; + + // Draw it + WallSpriteTile = spr->pic; + if (spr->renderflags & RF_YFLIP) + { + sprflipvert = true; + yscale = -yscale; + dc_texturemid = dc_texturemid - (spr->pic->GetHeight() << FRACBITS); + } + else + { + sprflipvert = false; + } + + // rw_offset is used as the texture's vertical scale + rw_offset = SafeDivScale30(1, yscale); + + dc_x = x1; + ESPSResult mode; + + mode = R_SetPatchStyle (spr->Style.RenderStyle, spr->Style.alpha, spr->Translation, spr->FillColor); + + // R_SetPatchStyle can modify basecolormap. + if (rereadcolormap) + { + usecolormap = basecolormap; + } + + if (mode == DontDraw) + { + return; + } + else + { + int stop4; + + if (mode == DoDraw0) + { // 1 column at a time + stop4 = dc_x; + } + else // DoDraw1 + { // up to 4 columns at a time + stop4 = x2 & ~3; + } + + while ((dc_x < stop4) && (dc_x & 3)) + { + if (calclighting) + { // calculate lighting + dc_colormap = usecolormap->Maps + (GETPALOOKUP (rw_light, shade) << COLORMAPSHIFT); + } + R_WallSpriteColumn(R_DrawMaskedColumn); + dc_x++; + } + + while (dc_x < stop4) + { + if (calclighting) + { // calculate lighting + dc_colormap = usecolormap->Maps + (GETPALOOKUP (rw_light, shade) << COLORMAPSHIFT); + } + rt_initcols(); + for (int zz = 4; zz; --zz) + { + R_WallSpriteColumn(R_DrawMaskedColumnHoriz); + dc_x++; + } + rt_draw4cols(dc_x - 4); + } + + while (dc_x < x2) + { + if (calclighting) + { // calculate lighting + dc_colormap = usecolormap->Maps + (GETPALOOKUP (rw_light, shade) << COLORMAPSHIFT); + } + R_WallSpriteColumn(R_DrawMaskedColumn); + dc_x++; + } + } + R_FinishSetPatchStyle(); +} + +void R_WallSpriteColumn (void (*drawfunc)(const BYTE *column, const FTexture::Span *spans)) +{ + unsigned int texturecolumn = lwall[dc_x] >> FRACBITS; + dc_iscale = MulScale16 (swall[dc_x], rw_offset); + spryscale = SafeDivScale32 (1, dc_iscale); + if (sprflipvert) + sprtopscreen = centeryfrac + FixedMul (dc_texturemid, spryscale); + else + sprtopscreen = centeryfrac - FixedMul (dc_texturemid, spryscale); + + const BYTE *column; + const FTexture::Span *spans; + column = WallSpriteTile->GetColumn (texturecolumn, &spans); + dc_texturefrac = 0; + drawfunc (column, spans); + rw_light += rw_lightstep; +} + void R_DrawVisVoxel(vissprite_t *spr, int minslabz, int maxslabz, short *cliptop, short *clipbot) { ESPSResult mode; @@ -528,12 +680,6 @@ void R_ProjectSprite (AActor *thing, int fakeside, F3DFloor *fakefloor, F3DFloor fy = thing->PrevY + FixedMul (r_TicFrac, thing->y - thing->PrevY); fz = thing->PrevZ + FixedMul (r_TicFrac, thing->z - thing->PrevZ) + thing->GetBobOffset(r_TicFrac); - // transform the origin point - tr_x = fx - viewx; - tr_y = fy - viewy; - - tz = DMulScale20 (tr_x, viewtancos, tr_y, viewtansin); - tex = NULL; voxel = NULL; @@ -615,11 +761,28 @@ 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; } + if ((thing->renderflags & RF_SPRITETYPEMASK) == RF_WALLSPRITE) + { + R_ProjectWallSprite(thing, fx, fy, fz, picnum, spritescaleX, spritescaleY, flip); + return; + } + + // transform the origin point + tr_x = fx - viewx; + tr_y = fy - viewy; + + tz = DMulScale20 (tr_x, viewtancos, tr_y, viewtansin); + // thing is behind view plane? if (voxel == NULL && tz < MINZ) return; @@ -784,7 +947,6 @@ void R_ProjectSprite (AActor *thing, int fakeside, F3DFloor *fakefloor, F3DFloor vis->heightsec = heightsec; vis->sector = thing->Sector; - vis->cx = tx2; vis->depth = tz; vis->gx = fx; vis->gy = fy; @@ -809,12 +971,14 @@ void R_ProjectSprite (AActor *thing, int fakeside, F3DFloor *fakefloor, F3DFloor { vis->voxel = voxel->Voxel; vis->bIsVoxel = true; + vis->bWallSprite = false; DrewAVoxel = true; } else { vis->pic = tex; vis->bIsVoxel = false; + vis->bWallSprite = false; } // The software renderer cannot invert the source without inverting the overlay @@ -876,6 +1040,79 @@ void R_ProjectSprite (AActor *thing, int fakeside, F3DFloor *fakefloor, F3DFloor } } +static void R_ProjectWallSprite(AActor *thing, fixed_t fx, fixed_t fy, fixed_t fz, FTextureID picnum, fixed_t xscale, fixed_t yscale, INTBOOL flip) +{ + FWallCoords wallc; + int x1, x2; + fixed_t lx1, lx2, ly1, ly2; + fixed_t gzb, gzt, tz; + FTexture *pic = TexMan(picnum, true); + angle_t ang = (thing->angle + ANGLE_90) >> ANGLETOFINESHIFT; + vissprite_t *vis; + + // Determine left and right edges of sprite. The sprite's angle is its normal, + // so the edges are 90 degrees each side of it. + x2 = pic->GetScaledWidth(); + x1 = pic->GetScaledLeftOffset(); + + x1 *= xscale; + x2 *= xscale; + + lx1 = fx - FixedMul(x1, finecosine[ang]) - viewx; + ly1 = fy - FixedMul(x1, finesine[ang]) - viewy; + lx2 = lx1 + FixedMul(x2, finecosine[ang]); + ly2 = ly1 + FixedMul(x2, finesine[ang]); + + // Is it off-screen? + if (wallc.Init(lx1, ly1, lx2, ly2, TOO_CLOSE_Z)) + return; + + if (wallc.sx1 > WindowRight || wallc.sx2 <= WindowLeft) + return; + + // Sprite sorting should probably treat these as walls, not sprites, + // but right now, I just want to get them drawing. + tz = DMulScale20(fx - viewx, viewtancos, fy - viewy, viewtansin); + + int scaled_to = pic->GetScaledTopOffset(); + int scaled_bo = scaled_to - pic->GetScaledHeight(); + gzt = fz + yscale * scaled_to; + gzb = fz + yscale * scaled_bo; + + vis = R_NewVisSprite(); + vis->x1 = wallc.sx1 < WindowLeft ? WindowLeft : wallc.sx1; + vis->x2 = wallc.sx2 >= WindowRight ? WindowRight : wallc.sx2-1; + vis->yscale = yscale; + vis->idepth = (unsigned)DivScale32(1, tz) >> 1; + vis->depth = tz; + vis->sector = thing->Sector; + vis->heightsec = NULL; + vis->gx = fx; + vis->gy = fy; + vis->gz = fz; + vis->gzb = gzb; + vis->gzt = gzt; + vis->deltax = fx - viewx; + vis->deltay = fy - viewy; + vis->renderflags = thing->renderflags; + if(thing->flags5 & MF5_BRIGHT) vis->renderflags |= RF_FULLBRIGHT; // kg3D + vis->Style.RenderStyle = thing->RenderStyle; + vis->FillColor = thing->fillcolor; + vis->Translation = thing->Translation; + vis->FakeFlatStat = 0; + vis->Style.alpha = thing->alpha; + vis->fakefloor = NULL; + vis->fakeceiling = NULL; + vis->ColormapNum = 0; + vis->bInMirror = MirrorFlags & RF_XFLIP; + vis->pic = pic; + vis->bIsVoxel = false; + vis->bWallSprite = true; + vis->ColormapNum = GETPALOOKUP( + (fixed_t)DivScale12 (r_SpriteVisibility, MAX(tz, MINZ)), spriteshade); + vis->Style.colormap = basecolormap->Maps + (vis->ColormapNum << COLORMAPSHIFT); + vis->wallc = wallc; +} // // R_AddSprites @@ -1846,19 +2083,9 @@ void R_DrawSprite (vissprite_t *spr) r1 = MAX (ds->x1, x1); r2 = MIN (ds->x2, x2); - fixed_t neardepth, fardepth; - if (ds->sz1 < ds->sz2) - { - neardepth = ds->sz1, fardepth = ds->sz2; - } - else - { - neardepth = ds->sz2, fardepth = ds->sz1; - } - if (neardepth > spr->depth || (fardepth > spr->depth && - // Check if sprite is in front of draw seg: - DMulScale32(spr->gy - ds->curline->v1->y, ds->curline->v2->x - ds->curline->v1->x, - ds->curline->v1->x - spr->gx, ds->curline->v2->y - ds->curline->v1->y) <= 0)) + // Check if sprite is in front of draw seg: + if (DMulScale32(spr->gy - ds->curline->v1->y, ds->curline->v2->x - ds->curline->v1->x, + ds->curline->v1->x - spr->gx, ds->curline->v2->y - ds->curline->v1->y) <= 0) { // seg is behind sprite, so draw the mid texture if it has one if (ds->maskedtexturecol != -1 || ds->bFogBoundary) @@ -1906,7 +2133,14 @@ void R_DrawSprite (vissprite_t *spr) { mfloorclip = clipbot; mceilingclip = cliptop; - R_DrawVisSprite (spr); + if (!spr->bWallSprite) + { + R_DrawVisSprite(spr); + } + else + { + R_DrawWallSprite(spr); + } } else { @@ -2163,7 +2397,6 @@ void R_ProjectParticle (particle_t *particle, const sector_t *sector, int shade, vis->yscale = xscale; vis->depth = tz; vis->idepth = (DWORD)DivScale32 (1, tz) >> 1; - vis->cx = tx; vis->gx = particle->x; vis->gy = particle->y; vis->gz = particle->z; // kg3D diff --git a/src/r_things.h b/src/r_things.h index 2219eee20..3ce1a4d4d 100644 --- a/src/r_things.h +++ b/src/r_things.h @@ -23,6 +23,7 @@ #ifndef __R_THINGS__ #define __R_THINGS__ +#include "r_bsp.h" // A vissprite_t is a thing // that will be drawn during a refresh. @@ -31,7 +32,6 @@ struct vissprite_t { short x1, x2; - fixed_t cx; // for line side calculation fixed_t gx, gy, gz; // origin in world coordinates angle_t angle; fixed_t gzb, gzt; // global bottom / top for silhouette clipping @@ -43,18 +43,26 @@ struct vissprite_t fixed_t floorclip; union { - // Used by regular sprites + FTexture *pic; + struct FVoxel *voxel; + }; + union + { + // Used by face sprites struct { - FTexture *pic; fixed_t texturemid; fixed_t startfrac; // horizontal position of x1 fixed_t xiscale; // negative if flipped }; + // Used by wall sprites + struct + { + FWallCoords wallc; + }; // Used by voxels struct { - struct FVoxel *voxel; fixed_t vx, vy, vz; // view origin angle_t vang; // view angle }; @@ -64,6 +72,7 @@ struct vissprite_t F3DFloor *fakefloor; F3DFloor *fakeceiling; BYTE bIsVoxel:1; // [RH] Use voxel instead of pic + BYTE bWallSprite:1; // [RH] This is a wall sprite BYTE bSplitSprite:1; // [RH] Sprite was split by a drawseg BYTE bInMirror:1; // [RH] Sprite is "inside" a mirror BYTE FakeFlatStat; // [RH] which side of fake/floor ceiling sprite is on @@ -99,9 +108,11 @@ extern fixed_t pspritexscale; extern fixed_t pspriteyscale; extern fixed_t pspritexiscale; +extern FTexture *WallSpriteTile; + void R_DrawMaskedColumn (const BYTE *column, const FTexture::Span *spans); - +void R_WallSpriteColumn (void (*drawfunc)(const BYTE *column, const FTexture::Span *spans)); void R_CacheSprite (spritedef_t *sprite); void R_SortVisSprites (int (STACK_ARGS *compare)(const void *, const void *), size_t first); diff --git a/src/r_utility.cpp b/src/r_utility.cpp index ddc18145a..422598ae7 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..21c11ed25 100644 --- a/src/resourcefiles/file_7z.cpp +++ b/src/resourcefiles/file_7z.cpp @@ -32,6 +32,12 @@ ** ** */ +#ifdef _WIN32 +#define USE_WINDOWS_DWORD +#endif + +#include "7z.h" +#include "7zCrc.h" #include "resourcefile.h" #include "cmdlib.h" @@ -41,12 +47,6 @@ #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 "7zCrc.h" -} //----------------------------------------------------------------------- @@ -151,7 +151,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 +268,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 +281,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((unsigned)nameLength); + nameASCII.Resize((unsigned)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 +311,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 +384,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 101b51982..7ae0e90a5 100644 --- a/src/resourcefiles/file_zip.cpp +++ b/src/resourcefiles/file_zip.cpp @@ -423,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/s_advsound.cpp b/src/s_advsound.cpp index c2d567f29..5b2e4e7c1 100644 --- a/src/s_advsound.cpp +++ b/src/s_advsound.cpp @@ -511,8 +511,6 @@ int S_AddSoundLump (const char *logicalname, int lump) newsfx.LimitRange = 256*256; newsfx.bRandomHeader = false; newsfx.bPlayerReserve = false; - newsfx.bForce11025 = false; - newsfx.bForce22050 = false; newsfx.bLoadRAW = false; newsfx.bPlayerCompat = false; newsfx.b16bit = false; @@ -520,6 +518,7 @@ int S_AddSoundLump (const char *logicalname, int lump) newsfx.bSingular = false; newsfx.bTentative = false; newsfx.bPlayerSilent = false; + newsfx.RawRate = 0; newsfx.link = sfxinfo_t::NO_LINK; newsfx.Rolloff.RolloffType = ROLLOFF_Doom; newsfx.Rolloff.MinDistance = 0; @@ -1414,13 +1413,17 @@ static void S_AddBloodSFX (int lumpnum) { const char *name = Wads.GetLumpFullName(lumpnum); sfxnum = S_AddSound(name, rawlump); - if (sfx->Format == 5) - { - S_sfx[sfxnum].bForce22050 = true; + if (sfx->Format < 5 || sfx->Format > 12) + { // [0..4] + invalid formats + S_sfx[sfxnum].RawRate = 11025; } - else // I don't know any other formats for this - { - S_sfx[sfxnum].bForce11025 = true; + else if (sfx->Format < 9) + { // [5..8] + S_sfx[sfxnum].RawRate = 22050; + } + else + { // [9..12] + S_sfx[sfxnum].RawRate = 44100; } S_sfx[sfxnum].bLoadRAW = true; S_sfx[sfxnum].LoopStart = LittleLong(sfx->LoopStart); @@ -1433,7 +1436,7 @@ static void S_AddBloodSFX (int lumpnum) ambient->periodmax = 0; ambient->volume = 1; ambient->attenuation = 1; - ambient->sound = name; + ambient->sound = FSoundID(sfxnum); } } @@ -2231,7 +2234,7 @@ void AAmbientSound::BeginPlay () // // AmbientSound :: Activate // -// Starts playing a sound (or does nothing of the sound is already playing). +// Starts playing a sound (or does nothing if the sound is already playing). // //========================================================================== diff --git a/src/s_sound.cpp b/src/s_sound.cpp index bdc1a3928..030d4da66 100644 --- a/src/s_sound.cpp +++ b/src/s_sound.cpp @@ -1334,7 +1334,7 @@ sfxinfo_t *S_LoadSound(sfxinfo_t *sfx) if (sfx->bLoadRAW) { len = Wads.LumpLength (sfx->lumpnum); - frequency = (sfx->bForce22050 ? 22050 : 11025); + frequency = sfx->RawRate; } else { diff --git a/src/s_sound.h b/src/s_sound.h index 346e51ce1..da8bf3cbc 100644 --- a/src/s_sound.h +++ b/src/s_sound.h @@ -49,8 +49,6 @@ struct sfxinfo_t WORD bRandomHeader:1; WORD bPlayerReserve:1; - WORD bForce11025:1; - WORD bForce22050:1; WORD bLoadRAW:1; WORD bPlayerCompat:1; WORD b16bit:1; @@ -59,6 +57,8 @@ struct sfxinfo_t WORD bTentative:1; WORD bPlayerSilent:1; // This player sound is intentionally silent. + WORD RawRate; // Sample rate to use when bLoadRAW is true + int LoopStart; // -1 means no specific loop defined unsigned int link; 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..27324edf6 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 @@ -302,8 +303,8 @@ int main (int argc, char **argv) vid_defwidth = videoInfo->current_w; vid_defheight = videoInfo->current_h; vid_defbits = videoInfo->vfmt->BitsPerPixel; - vid_vsync = True; - fullscreen = True; + vid_vsync = true; + fullscreen = true; } #endif // __APPLE__ diff --git a/src/sdl/i_system.cpp b/src/sdl/i_system.cpp index ba126bf54..9b3027a7d 100644 --- a/src/sdl/i_system.cpp +++ b/src/sdl/i_system.cpp @@ -97,22 +97,14 @@ SDL_Cursor *X11Cursor; SDL_Cursor *FirstCursor; #endif -DWORD LanguageIDs[4] = -{ - MAKE_ID ('e','n','u',0), - MAKE_ID ('e','n','u',0), - MAKE_ID ('e','n','u',0), - MAKE_ID ('e','n','u',0) -}; +DWORD LanguageIDs[4]; int (*I_GetTime) (bool saveMS); int (*I_WaitForTic) (int); void (*I_FreezeTime) (bool frozen); -void I_Tactile (int on, int off, int total) +void I_Tactile (int /*on*/, int /*off*/, int /*total*/) { - // UNUSED. - on = off = total = 0; } ticcmd_t emptycmd; @@ -326,6 +318,13 @@ void I_WaitVBL (int count) // void SetLanguageIDs () { + size_t langlen = strlen(language); + + DWORD lang = (langlen < 2 || langlen > 3) ? + MAKE_ID('e','n','u','\0') : + MAKE_ID(language[0],language[1],language[2],'\0'); + + LanguageIDs[3] = LanguageIDs[2] = LanguageIDs[1] = LanguageIDs[0] = lang; } // @@ -354,6 +353,8 @@ void I_Quit (void) if (demorecording) G_CheckDemoStatus(); + + C_DeinitConsole(); } @@ -422,7 +423,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 +705,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 +719,7 @@ bool I_WriteIniFailed () static const char *pattern; -#if defined(__APPLE__) && !defined(__llvm__) +#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 f832183c0..648eb504e 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 @@ -212,8 +212,11 @@ static const FEnumList ResamplerNames[] = { "No Interpolation", FMOD_DSP_RESAMPLER_NOINTERP }, { "NoInterp", FMOD_DSP_RESAMPLER_NOINTERP }, { "Linear", FMOD_DSP_RESAMPLER_LINEAR }, + // [BL] 64-bit version of FMOD Ex 4.26 crashes with these resamplers. +#if !(defined(_M_X64) || defined(__amd64__)) || !(FMOD_VERSION >= 0x42600 && FMOD_VERSION <= 0x426FF) { "Cubic", FMOD_DSP_RESAMPLER_CUBIC }, { "Spline", FMOD_DSP_RESAMPLER_SPLINE }, +#endif { NULL, 0 } }; @@ -629,7 +632,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) @@ -856,7 +861,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; @@ -1041,7 +1046,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) { @@ -1104,7 +1109,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_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 aaf6d03d6..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; @@ -659,6 +659,17 @@ void FTextureManager::ParseCameraTexture(FScanner &sc) sc.UnGet (); } } + if (sc.GetString()) + { + if (sc.Compare("WorldPanning")) + { + viewer->bWorldPanning = true; + } + else + { + sc.UnGet(); + } + } viewer->SetScaledSize(fitwidth, fitheight); } @@ -738,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")) { @@ -765,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..b8256bc65 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]); } } @@ -964,6 +964,7 @@ void FTextureManager::SortTexturesByType(int start, int end) void FTextureManager::Init() { DeleteAll(); + SpriteFrames.Clear(); // Init Build Tile data if it hasn't been done already if (BuildTileFiles.Size() == 0) CountBuildTiles (); FTexture::InitGrayMap(); @@ -1004,7 +1005,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 +1094,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 9742960b9..16fa4ef07 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_codeptr.cpp b/src/thingdef/thingdef_codeptr.cpp index 20b24994d..f74924386 100644 --- a/src/thingdef/thingdef_codeptr.cpp +++ b/src/thingdef/thingdef_codeptr.cpp @@ -1399,6 +1399,11 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_FireBullets) // A_FireProjectile // //========================================================================== +enum FP_Flags +{ + FPF_AIMATANGLE = 1, + FPF_TRANSFERTRANSLATION = 2, +}; DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_FireCustomMissile) { PARAM_ACTION_PROLOGUE; @@ -1407,7 +1412,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_FireCustomMissile) PARAM_BOOL_OPT (useammo) { useammo = true; } PARAM_INT_OPT (spawnofs_xy) { spawnofs_xy = 0; } PARAM_FIXED_OPT (spawnheight) { spawnheight = 0; } - PARAM_BOOL_OPT (aimatangle) { aimatangle = false; } + PARAM_INT_OPT (flags) { flags = 0; } PARAM_ANGLE_OPT (pitch) { pitch = 0; } if (!self->player) @@ -1431,7 +1436,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_FireCustomMissile) fixed_t z = spawnheight; fixed_t shootangle = self->angle; - if (aimatangle) shootangle += angle; + if (flags & FPF_AIMATANGLE) shootangle += angle; // Temporarily adjusts the pitch fixed_t saved_player_pitch = self->pitch; @@ -1441,9 +1446,11 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_FireCustomMissile) // automatic handling of seeker missiles if (misl) { + if (flags & FPF_TRANSFERTRANSLATION) + misl->Translation = self->Translation; if (linetarget && (misl->flags2 & MF2_SEEKERMISSILE)) misl->tracer = linetarget; - if (!aimatangle) + if (!(flags & FPF_AIMATANGLE)) { // This original implementation is to aim straight ahead and then offset // the angle from the resulting direction. @@ -1515,7 +1522,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CustomPunch) if (pufftype == NULL) pufftype = PClass::FindActor(NAME_BulletPuff); - int puffFlags = LAF_ISMELEEATTACK | (flags & CPF_NORANDOMPUFFZ)? LAF_NORANDOMPUFFZ : 0; + int puffFlags = LAF_ISMELEEATTACK | ((flags & CPF_NORANDOMPUFFZ) ? LAF_NORANDOMPUFFZ : 0); P_LineAttack (self, angle, range, pitch, damage, NAME_Melee, pufftype, puffFlags, &linetarget, &actualdamage); @@ -1534,7 +1541,6 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CustomPunch) if (flags & CPF_PULLIN) self->flags |= MF_JUSTATTACKED; if (flags & CPF_DAGGER) P_DaggerAlert (self, linetarget); - } return 0; } @@ -2373,7 +2379,8 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Log) PARAM_STRING(text); 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! return numret; } @@ -4186,12 +4193,20 @@ 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) { PARAM_ACTION_PROLOGUE; PARAM_ANGLE_OPT(angle) { angle = 0; } - self->angle = angle; + PARAM_INT_OPT(flags) { flags = 0; } + + self->SetAngle(angle, !!(flags & SPF_INTERPOLATE)); return 0; } @@ -4203,11 +4218,6 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SetAngle) // //=========================================================================== -enum -{ - SPF_FORCECLAMP = 1, // players always clamp -}; - DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SetPitch) { PARAM_ACTION_PROLOGUE; @@ -4231,7 +4241,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SetPitch) pitch = clamp(pitch, min, max); } - self->pitch = pitch; + self->SetPitch(pitch, !!(flags & SPF_INTERPOLATE)); return 0; } diff --git a/src/thingdef/thingdef_data.cpp b/src/thingdef/thingdef_data.cpp index 9b069b7ae..686318680 100644 --- a/src/thingdef/thingdef_data.cpp +++ b/src/thingdef/thingdef_data.cpp @@ -240,6 +240,7 @@ static FFlagDef ActorFlags[]= DEFINE_FLAG(MF7, NEVERTARGET, AActor, flags7), DEFINE_FLAG(MF7, NOTELESTOMP, AActor, flags7), DEFINE_FLAG(MF7, ALWAYSTELEFRAG, AActor, flags7), + DEFINE_FLAG(MF7, WEAPONSPAWN, AActor, flags7), // Effect flags DEFINE_FLAG(FX, VISIBILITYPULSE, AActor, effects), diff --git a/src/thingdef/thingdef_properties.cpp b/src/thingdef/thingdef_properties.cpp index 787b758a4..8406918bd 100644 --- a/src/thingdef/thingdef_properties.cpp +++ b/src/thingdef/thingdef_properties.cpp @@ -181,7 +181,7 @@ INTBOOL CheckActorFlag(const AActor *owner, FFlagDef *fd) { return fd->flagbit & *(DWORD *)(((char*)owner) + fd->structoffset); } -#ifdef __BID_ENDIAN__ +#ifdef __BIG_ENDIAN__ else if (fd->fieldsize == 2) { return fd->flagbit & *(WORD *)(((char*)owner) + fd->structoffset); @@ -818,11 +818,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; @@ -1332,6 +1334,17 @@ DEFINE_PROPERTY(gravity, F, Actor) defaults->gravity = i; } +//========================================================================== +// +//========================================================================== +DEFINE_PROPERTY(friction, F, Actor) +{ + PROP_FIXED_PARM(i, 0); + + if (i < 0) I_Error ("Friction must not be negative."); + defaults->Friction = i; +} + //========================================================================== // //========================================================================== diff --git a/src/thingdef/thingdef_states.cpp b/src/thingdef/thingdef_states.cpp index dafe4d76c..fec49cc7c 100644 --- a/src/thingdef/thingdef_states.cpp +++ b/src/thingdef/thingdef_states.cpp @@ -265,6 +265,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()) @@ -303,6 +308,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/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 d7acf1e6a..6d24c3fe8 100644 --- a/src/version.h +++ b/src/version.h @@ -51,7 +51,7 @@ const char *GetVersionString(); // Version identifier for network games. // Bump it every time you do a release unless you're certain you // didn't change anything that will affect sync. -#define NETGAMEVERSION 229 +#define NETGAMEVERSION 230 // Version stored in the ini's [LastRun] section. // Bump it if you made some configuration change that you want to @@ -61,11 +61,11 @@ 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 0x21B // Minimum demo version we can play. // Bump it whenever you change or remove existing DEM_ commands. -#define MINDEMOVERSION 0x215 +#define MINDEMOVERSION 0x21B // SAVEVER is the version of the information stored in level snapshots. // Note that SAVEVER is not directly comparable to VERSION. @@ -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 4504 +#define SAVEVER 4510 #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 6ae9148af..e60fee303 100644 --- a/src/wi_stuff.cpp +++ b/src/wi_stuff.cpp @@ -45,6 +45,7 @@ #include "v_text.h" #include "gi.h" #include "d_player.h" +#include "d_netinf.h" #include "b_bot.h" #include "textures/textures.h" #include "r_data/r_translate.h" @@ -62,7 +63,8 @@ typedef enum CVAR (Bool, wi_percents, true, CVAR_ARCHIVE) CVAR (Bool, wi_showtotaltime, true, CVAR_ARCHIVE) -CVAR (Bool, wi_noautostartmap, false, CVAR_ARCHIVE) +CVAR (Bool, wi_noautostartmap, false, CVAR_USERINFO|CVAR_ARCHIVE) +CVAR (Int, wi_autoadvance, 0, CVAR_SERVERINFO) void WI_loadData (); @@ -190,6 +192,7 @@ static TArray anims; #define SHOWNEXTLOCDELAY 4 // in seconds static int acceleratestage; // used to accelerate or skip a stage +static bool playerready[MAXPLAYERS]; static int me; // wbs->pnum static stateenum_t state; // specifies current state static wbstartstruct_t *wbs; // contains information passed into intermission @@ -199,11 +202,17 @@ static int bcnt; // used for timing of background animation static int cnt_kills[MAXPLAYERS]; static int cnt_items[MAXPLAYERS]; static int cnt_secret[MAXPLAYERS]; +static int cnt_frags[MAXPLAYERS]; +static int cnt_deaths[MAXPLAYERS]; static int cnt_time; static int cnt_total_time; static int cnt_par; static int cnt_pause; +static int total_frags; +static int total_deaths; static bool noautostartmap; +static int dofrags; +static int ng_state; // // GRAPHICS @@ -314,7 +323,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 +408,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; } } @@ -1098,11 +1107,29 @@ void WI_updateNoState () { WI_updateAnimatedBack(); + if (acceleratestage) + { + cnt = 0; + } + else + { + bool noauto = noautostartmap; + bool autoskip = (wi_autoadvance > 0 && bcnt > (wi_autoadvance * TICRATE)); - if (!wi_noautostartmap && !noautostartmap) cnt--; - if (acceleratestage) cnt=0; + for (int i = 0; !noauto && i < MAXPLAYERS; ++i) + { + if (playeringame[i]) + { + noauto |= players[i].userinfo.GetNoAutostartMap(); + } + } + if (!noauto || autoskip) + { + cnt--; + } + } - if (cnt==0) + if (cnt == 0) { WI_End(); G_WorldDone(); @@ -1191,128 +1218,134 @@ int WI_fragSum (int playernum) return frags; } -static int dm_state; -static int dm_frags[MAXPLAYERS][MAXPLAYERS]; -static int dm_totals[MAXPLAYERS]; +static int player_deaths[MAXPLAYERS]; void WI_initDeathmatchStats (void) { - int i, j; state = StatCount; acceleratestage = 0; - dm_state = 1; + memset(playerready, 0, sizeof(playerready)); + memset(cnt_frags, 0, sizeof(cnt_frags)); + memset(cnt_deaths, 0, sizeof(cnt_frags)); + memset(player_deaths, 0, sizeof(player_deaths)); + total_frags = 0; + total_deaths = 0; + ng_state = 1; cnt_pause = TICRATE; for (i=0 ; i 0 && bcnt > (wi_autoadvance * TICRATE)); WI_updateAnimatedBack(); - if (acceleratestage && dm_state != 4) + if ((acceleratestage || autoskip) && ng_state != 6) { - /* acceleratestage = 0; - - for (i=0 ; i 99) - dm_frags[i][j] = 99; + cnt_frags[i] += 2; - if (dm_frags[i][j] < -99) - dm_frags[i][j] = -99; - - stillticking = true; - } - } - dm_totals[i] = WI_fragSum(i); + if (cnt_frags[i] > plrs[i].fragcount) + cnt_frags[i] = plrs[i].fragcount; + else + stillticking = true; + } - if (dm_totals[i] > 99) - dm_totals[i] = 99; - - if (dm_totals[i] < -99) - dm_totals[i] = -99; - } - + if (!stillticking) + { + S_Sound(CHAN_VOICE | CHAN_UI, "intermission/nextstage", 1, ATTN_NONE); + ng_state++; + } + } + else if (ng_state == 4) + { + if (!(bcnt & 3)) + S_Sound(CHAN_VOICE | CHAN_UI, "intermission/tick", 1, ATTN_NONE); + + stillticking = false; + + for (i = 0; i player_deaths[i]) + cnt_deaths[i] = player_deaths[i]; + else + stillticking = true; } if (!stillticking) { - S_Sound (CHAN_VOICE | CHAN_UI, "intermission/nextstage", 1, ATTN_NONE); - dm_state++; + S_Sound(CHAN_VOICE | CHAN_UI, "intermission/nextstage", 1, ATTN_NONE); + ng_state++; } - */ - dm_state = 3; } - else if (dm_state == 4) + else if (ng_state == 6) { - if (acceleratestage) + int i; + for (i = 0; i < MAXPLAYERS; i++) { - S_Sound (CHAN_VOICE | CHAN_UI, "intermission/pastdmstats", 1, ATTN_NONE); + // If the player is in the game and not ready, stop checking + if (playeringame[i] && !players[i].isbot && !playerready[i]) + break; + } + + // All players are ready; proceed. + if ((i == MAXPLAYERS && acceleratestage) || autoskip) + { + S_Sound(CHAN_VOICE | CHAN_UI, "intermission/pastdmstats", 1, ATTN_NONE); WI_initShowNextLoc(); } } - else if (dm_state & 1) + else if (ng_state & 1) { if (!--cnt_pause) { - dm_state++; + ng_state++; cnt_pause = TICRATE; } } @@ -1322,97 +1355,126 @@ void WI_updateDeathmatchStats () void WI_drawDeathmatchStats () { + int i, pnum, x, y, ypadding, height, lineheight; + int maxnamewidth, maxscorewidth, maxiconheight; + int pwidth = IntermissionFont->GetCharWidth('%'); + int icon_x, name_x, frags_x, deaths_x; + int deaths_len; + float h, s, v, r, g, b; + EColorRange color; + const char *text_deaths, *text_frags; + FTexture *readyico = TexMan.FindTexture("READYICO"); + player_t *sortedplayers[MAXPLAYERS]; // draw animated background - WI_drawBackground(); - WI_drawLF(); + WI_drawBackground(); - // [RH] Draw heads-up scores display - HU_DrawScores (&players[me]); + y = WI_drawLF(); -/* - int i; - int j; - int x; - int y; - int w; - - int lh; // line height + HU_GetPlayerWidths(maxnamewidth, maxscorewidth, maxiconheight); + // Use the readyico height if it's bigger. + height = readyico->GetScaledHeight() - readyico->GetScaledTopOffset(); + maxiconheight = MAX(height, maxiconheight); + height = SmallFont->GetHeight() * CleanYfac; + lineheight = MAX(height, maxiconheight * CleanYfac); + ypadding = (lineheight - height + 1) / 2; + y += CleanYfac; - lh = WI_SPACINGY; + text_deaths = GStrings("SCORE_DEATHS"); + //text_color = GStrings("SCORE_COLOR"); + text_frags = GStrings("SCORE_FRAGS"); - // draw stat titles (top line) - V_DrawPatchClean(DM_TOTALSX-LittleShort(total->width)/2, - DM_MATRIXY-WI_SPACINGY+10, - &FB, - total); - - V_DrawPatchClean(DM_KILLERSX, DM_KILLERSY, &FB, killers); - V_DrawPatchClean(DM_VICTIMSX, DM_VICTIMSY, &FB, victims); + icon_x = 8 * CleanXfac; + name_x = icon_x + maxscorewidth * CleanXfac; + frags_x = name_x + (maxnamewidth + MAX(SmallFont->StringWidth("XXXXX"), SmallFont->StringWidth(text_frags)) + 8) * CleanXfac; + deaths_x = frags_x + ((deaths_len = SmallFont->StringWidth(text_deaths)) + 8) * CleanXfac; - // draw P? - x = DM_MATRIXX + DM_SPACINGX; - y = DM_MATRIXY; + x = (SCREENWIDTH - deaths_x) >> 1; + icon_x += x; + name_x += x; + frags_x += x; + deaths_x += x; - for (i=0 ; iDrawText(SmallFont, color, name_x, y, GStrings("SCORE_NAME"), DTA_CleanNoMove, true, TAG_DONE); + screen->DrawText(SmallFont, color, frags_x - SmallFont->StringWidth(text_frags)*CleanXfac, y, text_frags, DTA_CleanNoMove, true, TAG_DONE); + screen->DrawText(SmallFont, color, deaths_x - deaths_len*CleanXfac, y, text_deaths, DTA_CleanNoMove, true, TAG_DONE); + y += height + 6 * CleanYfac; + + // Sort all players + for (i = 0; i < MAXPLAYERS; i++) { - if (playeringame[i]) - { - V_DrawPatchClean(x-LittleShort(p[i]->width)/2, - DM_MATRIXY - WI_SPACINGY, - &FB, - p[i]); - - V_DrawPatchClean(DM_MATRIXX-LittleShort(p[i]->width)/2, - y, - &FB, - p[i]); - - if (i == me) - { - V_DrawPatchClean(x-LittleShort(p[i]->width)/2, - DM_MATRIXY - WI_SPACINGY, - &FB, - bstar); - - V_DrawPatchClean(DM_MATRIXX-LittleShort(p[i]->width)/2, - y, - &FB, - star); - } - } - x += DM_SPACINGX; - y += WI_SPACINGY; + sortedplayers[i] = &players[i]; } - // draw stats - y = DM_MATRIXY+10; - w = LittleShort(num[0]->width); + if (teamplay) + qsort(sortedplayers, MAXPLAYERS, sizeof(player_t *), compareteams); + else + qsort(sortedplayers, MAXPLAYERS, sizeof(player_t *), comparepoints); - for (i=0 ; iDim(MAKERGB(clamp(int(r*255.f), 0, 255), + clamp(int(g*255.f), 0, 255), + clamp(int(b*255.f), 0, 255)), 0.8f, x, y - ypadding, (deaths_x - x) + (8 * CleanXfac), lineheight); + + if (playerready[pnum] || player->isbot) // Bots are automatically assumed ready, to prevent confusion + screen->DrawTexture(readyico, x - (readyico->GetWidth() * CleanXfac), y, DTA_CleanNoMove, true, TAG_DONE); + + color = (EColorRange)HU_GetRowColor(player, pnum == consoleplayer); + if (player->mo->ScoreIcon.isValid()) { - for (j=0 ; jmo->ScoreIcon]; + screen->DrawTexture(pic, icon_x, y, DTA_CleanNoMove, true, TAG_DONE); } - y += WI_SPACINGY; + screen->DrawText(SmallFont, color, name_x, y + ypadding, player->userinfo.GetName(), DTA_CleanNoMove, true, TAG_DONE); + WI_drawNum(SmallFont, frags_x, y + ypadding, cnt_frags[pnum], 0, false, color); + if (ng_state >= 2) + { + WI_drawNum(SmallFont, deaths_x, y + ypadding, cnt_deaths[pnum], 0, false, color); + } + y += lineheight + CleanYfac; } -*/ + + // Draw "TOTAL" line + y += height + 3 * CleanYfac; + color = (gameinfo.gametype & GAME_Raven) ? CR_GREEN : CR_UNTRANSLATED; + screen->DrawText(SmallFont, color, name_x, y, GStrings("SCORE_TOTAL"), DTA_CleanNoMove, true, TAG_DONE); + WI_drawNum(SmallFont, frags_x, y, total_frags, 0, false, color); + if (ng_state >= 4) + { + WI_drawNum(SmallFont, deaths_x, y, total_deaths, 0, false, color); + } + + // Draw game time + y += height + CleanYfac; + + int seconds = plrs[me].stime / TICRATE; + int hours = seconds / 3600; + int minutes = (seconds % 3600) / 60; + seconds = seconds % 60; + + FString leveltime = GStrings("SCORE_LVLTIME"); + leveltime += ": "; + + char timer[sizeof "HH:MM:SS"]; + mysnprintf(timer, sizeof(timer), "%02i:%02i:%02i", hours, minutes, seconds); + leveltime += timer; + + screen->DrawText(SmallFont, color, x, y, leveltime, DTA_CleanNoMove, true, TAG_DONE); } -static int cnt_frags[MAXPLAYERS]; -static int dofrags; -static int ng_state; - void WI_initNetgameStats () { @@ -1420,6 +1482,7 @@ void WI_initNetgameStats () state = StatCount; acceleratestage = 0; + memset(playerready, 0, sizeof(playerready)); ng_state = 1; cnt_pause = TICRATE; @@ -1443,10 +1506,11 @@ void WI_updateNetgameStats () int i; int fsum; bool stillticking; + bool autoskip = (wi_autoadvance > 0 && bcnt > (wi_autoadvance * TICRATE)); WI_updateAnimatedBack (); - if (acceleratestage && ng_state != 10) + if ((acceleratestage || autoskip) && ng_state != 10) { acceleratestage = 0; @@ -1570,7 +1634,16 @@ void WI_updateNetgameStats () } else if (ng_state == 10) { - if (acceleratestage) + int i; + for (i = 0; i < MAXPLAYERS; i++) + { + // If the player is in the game and not ready, stop checking + if (playeringame[i] && !players[i].isbot && !playerready[i]) + break; + } + + // All players are ready; proceed. + if ((i == MAXPLAYERS && acceleratestage) || autoskip) { S_Sound (CHAN_VOICE | CHAN_UI, "intermission/pastcoopstats", 1, ATTN_NONE); WI_initShowNextLoc(); @@ -1594,8 +1667,10 @@ void WI_drawNetgameStats () int icon_x, name_x, kills_x, bonus_x, secret_x; int bonus_len, secret_len; int missed_kills, missed_items, missed_secrets; + float h, s, v, r, g, b; EColorRange color; - const char *text_bonus, *text_color, *text_secret, *text_kills; + const char *text_bonus, *text_secret, *text_kills; + FTexture *readyico = TexMan.FindTexture("READYICO"); // draw animated background WI_drawBackground(); @@ -1603,17 +1678,22 @@ void WI_drawNetgameStats () y = WI_drawLF(); HU_GetPlayerWidths(maxnamewidth, maxscorewidth, maxiconheight); + // Use the readyico height if it's bigger. + height = readyico->GetScaledHeight() - readyico->GetScaledTopOffset(); + if (height > maxiconheight) + { + maxiconheight = height; + } height = SmallFont->GetHeight() * CleanYfac; lineheight = MAX(height, maxiconheight * CleanYfac); ypadding = (lineheight - height + 1) / 2; - y += 16*CleanYfac; + y += CleanYfac; text_bonus = GStrings((gameinfo.gametype & GAME_Raven) ? "SCORE_BONUS" : "SCORE_ITEMS"); - text_color = GStrings("SCORE_COLOR"); text_secret = GStrings("SCORE_SECRET"); text_kills = GStrings("SCORE_KILLS"); - icon_x = (SmallFont->StringWidth(text_color) + 8) * CleanXfac; + icon_x = 8 * CleanXfac; name_x = icon_x + maxscorewidth * CleanXfac; kills_x = name_x + (maxnamewidth + MAX(SmallFont->StringWidth("XXXXX"), SmallFont->StringWidth(text_kills)) + 8) * CleanXfac; bonus_x = kills_x + ((bonus_len = SmallFont->StringWidth(text_bonus)) + 8) * CleanXfac; @@ -1628,7 +1708,6 @@ void WI_drawNetgameStats () color = (gameinfo.gametype & GAME_Raven) ? CR_GREEN : CR_UNTRANSLATED; - screen->DrawText(SmallFont, color, x, y, text_color, DTA_CleanNoMove, true, TAG_DONE); screen->DrawText(SmallFont, color, name_x, y, GStrings("SCORE_NAME"), DTA_CleanNoMove, true, TAG_DONE); screen->DrawText(SmallFont, color, kills_x - SmallFont->StringWidth(text_kills)*CleanXfac, y, text_kills, DTA_CleanNoMove, true, TAG_DONE); screen->DrawText(SmallFont, color, bonus_x - bonus_len*CleanXfac, y, text_bonus, DTA_CleanNoMove, true, TAG_DONE); @@ -1648,7 +1727,17 @@ void WI_drawNetgameStats () continue; player = &players[i]; - HU_DrawColorBar(x, y, lineheight, i); + + D_GetPlayerColor(i, &h, &s, &v, NULL); + HSVtoRGB(&r, &g, &b, h, s, v); + + screen->Dim(MAKERGB(clamp(int(r*255.f), 0, 255), + clamp(int(g*255.f), 0, 255), + clamp(int(b*255.f), 0, 255)), 0.8f, x, y - ypadding, (secret_x - x) + (8 * CleanXfac), lineheight); + + if (playerready[i] || player->isbot) // Bots are automatically assumed ready, to prevent confusion + screen->DrawTexture(readyico, x - (readyico->GetWidth() * CleanXfac), y, DTA_CleanNoMove, true, TAG_DONE); + color = (EColorRange)HU_GetRowColor(player, i == consoleplayer); if (player->mo->ScoreIcon.isValid()) { @@ -1672,7 +1761,7 @@ void WI_drawNetgameStats () } // Draw "MISSED" line - y += 5 * CleanYfac; + y += 3 * CleanYfac; screen->DrawText(SmallFont, CR_DARKGRAY, name_x, y, GStrings("SCORE_MISSED"), DTA_CleanNoMove, true, TAG_DONE); WI_drawPercent(SmallFont, kills_x, y, missed_kills, wbs->maxkills, false, CR_DARKGRAY); if (ng_state >= 4) @@ -1685,7 +1774,7 @@ void WI_drawNetgameStats () } // Draw "TOTAL" line - y += height + 5 * CleanYfac; + y += height + 3 * CleanYfac; color = (gameinfo.gametype & GAME_Raven) ? CR_GREEN : CR_UNTRANSLATED; screen->DrawText(SmallFont, color, name_x, y, GStrings("SCORE_TOTAL"), DTA_CleanNoMove, true, TAG_DONE); WI_drawNum(SmallFont, kills_x, y, wbs->maxkills, 0, false, color); @@ -1922,6 +2011,7 @@ void WI_checkForAccelerate(void) == players[i].oldbuttons) && !player->isbot) { acceleratestage = 1; + playerready[i] = true; } player->oldbuttons = player->cmd.ucmd.buttons; } 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 211c0645a..2f31cea44 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..4248df274 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; @@ -769,6 +781,8 @@ void I_Quit() { G_CheckDemoStatus(); } + + C_DeinitConsole(); } 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/win32/zdoom.exe.manifest b/src/win32/zdoom.exe.manifest index e8fb80f97..4aee7a96c 100644 --- a/src/win32/zdoom.exe.manifest +++ b/src/win32/zdoom.exe.manifest @@ -2,7 +2,7 @@ - + \ No newline at end of file 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 0dfb99597..457a9ef3b 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..9e814a7d7 100644 --- a/tools/updaterevision/CMakeLists.txt +++ b/tools/updaterevision/CMakeLists.txt @@ -1,12 +1,12 @@ cmake_minimum_required( VERSION 2.4 ) if( WIN32 ) - if( "${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" ) + if( ZD_CMAKE_COMPILER_IS_GNUC_COMPATIBLE OR ZD_CMAKE_COMPILER_IS_GNUCXX_COMPATIBLE ) add_custom_command( OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/trustinfo.o COMMAND windres -o ${CMAKE_CURRENT_BINARY_DIR}/trustinfo.o -i ${CMAKE_CURRENT_SOURCE_DIR}/trustinfo.rc DEPENDS trustinfo.rc ) set( TRUSTINFO trustinfo.o ) - else( "${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( ZD_CMAKE_COMPILER_IS_GNUC_COMPATIBLE OR ZD_CMAKE_COMPILER_IS_GNUCXX_COMPATIBLE ) if( MSVC_VERSION GREATER 1399 ) # VC 8+ adds a manifest automatically to the executable. We need to # merge ours with it. @@ -14,10 +14,15 @@ if( WIN32 ) else( MSVC_VERSION GREATER 1399 ) 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" ) + endif( ZD_CMAKE_COMPILER_IS_GNUC_COMPATIBLE OR ZD_CMAKE_COMPILER_IS_GNUCXX_COMPATIBLE ) +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/tools/zipdir/zipdir.c b/tools/zipdir/zipdir.c index 9b521bedf..1479952e0 100644 --- a/tools/zipdir/zipdir.c +++ b/tools/zipdir/zipdir.c @@ -129,7 +129,7 @@ typedef struct compressor_s int method; } compressor_t; -typedef unsigned int DWORD; +typedef unsigned int UINT32; typedef unsigned short WORD; typedef unsigned char BYTE; @@ -139,49 +139,49 @@ typedef unsigned char BYTE; //#pragma pack(push,1) typedef struct { - DWORD Magic; // 0 + UINT32 Magic; // 0 BYTE VersionToExtract[2]; // 4 WORD Flags; // 6 WORD Method; // 8 WORD ModTime; // 10 WORD ModDate; // 12 - DWORD CRC32; // 14 - DWORD CompressedSize; // 18 - DWORD UncompressedSize; // 22 + UINT32 CRC32; // 14 + UINT32 CompressedSize; // 18 + UINT32 UncompressedSize; // 22 WORD NameLength; // 26 WORD ExtraLength; // 28 } LocalFileHeader; typedef struct { - DWORD Magic; + UINT32 Magic; BYTE VersionMadeBy[2]; BYTE VersionToExtract[2]; WORD Flags; WORD Method; WORD ModTime; WORD ModDate; - DWORD CRC32; - DWORD CompressedSize; - DWORD UncompressedSize; + UINT32 CRC32; + UINT32 CompressedSize; + UINT32 UncompressedSize; WORD NameLength; WORD ExtraLength; WORD CommentLength; WORD StartingDiskNumber; WORD InternalAttributes; - DWORD ExternalAttributes; - DWORD LocalHeaderOffset; + UINT32 ExternalAttributes; + UINT32 LocalHeaderOffset; } CentralDirectoryEntry; typedef struct { - DWORD Magic; + UINT32 Magic; WORD DiskNumber; WORD FirstDisk; WORD NumEntries; WORD NumEntriesOnAllDisks; - DWORD DirectorySize; - DWORD DirectoryOffset; + UINT32 DirectorySize; + UINT32 DirectoryOffset; WORD ZipCommentLength; } EndOfCentralDirectory; //#pragma pack(pop) @@ -1373,7 +1373,7 @@ BYTE *find_central_dir(FILE *fin) back_read = 4; while (back_read < max_back) { - DWORD read_size, read_pos; + UINT32 read_size, read_pos; int i; if (back_read + BUFREADCOMMENT > max_back) back_read = max_back; @@ -1420,12 +1420,12 @@ BYTE *find_central_dir(FILE *fin) free(dir); return NULL; } - if (*(DWORD *)dir != ZIP_CENTRALFILE) + if (*(UINT32 *)dir != ZIP_CENTRALFILE) { free(dir); return NULL; } - *(DWORD *)(dir + LittleLong(eod.DirectorySize)) = ZIP_ENDOFDIR; + *(UINT32 *)(dir + LittleLong(eod.DirectorySize)) = ZIP_ENDOFDIR; return dir; } @@ -1444,7 +1444,7 @@ CentralDirectoryEntry *find_file_in_zip(BYTE *dir, const char *path, unsigned in CentralDirectoryEntry *ent; int flags; - while (*(DWORD *)dir == ZIP_CENTRALFILE) + while (*(UINT32 *)dir == ZIP_CENTRALFILE) { ent = (CentralDirectoryEntry *)dir; if (pathlen == LittleShort(ent->NameLength) && @@ -1455,7 +1455,7 @@ CentralDirectoryEntry *find_file_in_zip(BYTE *dir, const char *path, unsigned in } dir += sizeof(*ent) + LittleShort(ent->NameLength) + LittleShort(ent->ExtraLength) + LittleShort(ent->CommentLength); } - if (*(DWORD *)dir != ZIP_CENTRALFILE) + if (*(UINT32 *)dir != ZIP_CENTRALFILE) { return NULL; } @@ -1495,7 +1495,7 @@ int copy_zip_file(FILE *zip, file_entry_t *file, FILE *ozip, CentralDirectoryEnt { LocalFileHeader lfh; BYTE *buf; - DWORD buf_size; + UINT32 buf_size; if (fseek(ozip, LittleLong(ent->LocalHeaderOffset), SEEK_SET) != 0) { diff --git a/wadsrc/static/actors/actor.txt b/wadsrc/static/actors/actor.txt index 0a2ed701a..185931277 100644 --- a/wadsrc/static/actors/actor.txt +++ b/wadsrc/static/actors/actor.txt @@ -18,6 +18,7 @@ ACTOR Actor native //: Thinker FloatSpeed 4 FloatBobPhase -1 // randomly initialize by default Gravity 1 + Friction 1 DamageFactor 1.0 PushFactor 0.25 WeaveIndexXY 0 @@ -289,7 +290,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/chex/chexweapons.txt b/wadsrc/static/actors/chex/chexweapons.txt index 97043f2ca..96d8b4c4b 100644 --- a/wadsrc/static/actors/chex/chexweapons.txt +++ b/wadsrc/static/actors/chex/chexweapons.txt @@ -18,7 +18,7 @@ actor SuperBootspork : Chainsaw 2005 actor MiniZorcher : Pistol { game Chex - obituary "$OP_MPZORCH" + obituary "$OB_MPZORCH" inventory.pickupmessage "$GOTMINIZORCHER" Tag "$TAG_MINIZORCHER" states @@ -31,7 +31,7 @@ actor MiniZorcher : Pistol actor LargeZorcher : Shotgun 2001 { game Chex - obituary "$OP_MPZORCH" + obituary "$OB_MPZORCH" inventory.pickupmessage "$GOTLARGEZORCHER" Tag "$TAG_LARGEZORCHER" } diff --git a/wadsrc/static/actors/constants.txt b/wadsrc/static/actors/constants.txt index 4061cbdc3..d14f865f8 100644 --- a/wadsrc/static/actors/constants.txt +++ b/wadsrc/static/actors/constants.txt @@ -164,6 +164,10 @@ const int CPF_DAGGER = 2; const int CPF_PULLIN = 4; const int CPF_NORANDOMPUFFZ = 8; +// Flags for A_CustomMissile +const int FPF_AIMATANGLE = 1; +const int FPF_TRANSFERTRANSLATION = 2; + // Flags for A_Teleport const int TF_TELEFRAG = 1;const int TF_RANDOMDECIDE = 2; @@ -221,7 +225,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 +311,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 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/shared/inventory.txt b/wadsrc/static/actors/shared/inventory.txt index 7ca7a058a..b6448ec71 100644 --- a/wadsrc/static/actors/shared/inventory.txt +++ b/wadsrc/static/actors/shared/inventory.txt @@ -335,6 +335,7 @@ Actor Weapon : Inventory native Weapon.BobSpeed 1.0 Weapon.BobRangeX 1.0 Weapon.BobRangeY 1.0 + +WEAPONSPAWN States { LightDone: @@ -362,4 +363,7 @@ Actor WeaponHolder : Inventory native +INVENTORY.UNDROPPABLE } -Actor WeaponPiece : Inventory native {} +Actor WeaponPiece : Inventory native +{ + +WEAPONSPAWN +} 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/graphics/readyico.png b/wadsrc/static/graphics/readyico.png new file mode 100644 index 000000000..5a9b20804 Binary files /dev/null and b/wadsrc/static/graphics/readyico.png differ 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..4990cb417 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."; @@ -836,8 +838,10 @@ SCORE_SECRET = "SECRET"; SCORE_NAME = "NAME"; SCORE_KILLS = "KILLS"; SCORE_FRAGS = "FRAGS"; +SCORE_DEATHS = "DEATHS"; SCORE_MISSED = "MISSED"; SCORE_TOTAL = "TOTAL"; +SCORE_LVLTIME = "LEVEL TIME"; // Item tags: Doom weapons TAG_FIST = "Brass Knuckles"; diff --git a/wadsrc/static/language.fr b/wadsrc/static/language.fr index 1533a1506..4e146955d 100644 --- a/wadsrc/static/language.fr +++ b/wadsrc/static/language.fr @@ -991,9 +991,9 @@ HHUSTR_E5M9 = "L ECHEVAUX DE D'SPARIL"; // Keys -TXT_GOTBLUEKEY = "CLE BLEUE"; -TXT_GOTYELLOWKEY = "CLE JAUNE"; -TXT_GOTGREENKEY = "CLE ROUGE"; +TXT_GOTBLUEKEY = "CLÉ BLEUE"; +TXT_GOTYELLOWKEY = "CLÉ JAUNE"; +TXT_GOTGREENKEY = "CLÉ VERTE"; // Artifacts 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 6457051bf..324c94e6b 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" } @@ -815,6 +816,7 @@ OptionMenu "AltHUDOptions" Option "Show item count", "hud_showitems", "OnOff" Option "Show stamina and accuracy", "hud_showstats", "OnOff" Option "Show berserk", "hud_berserk_health", "OnOff" + Option "Show weapons", "hud_showweapons", "OnOff" Option "Show time", "hud_showtime", "AltHUDTime" Option "Time color", "hud_timecolor", "TextColors" Slider "Red ammo display below %", "hud_ammo_red", 0, 100, 1, 0 @@ -1156,7 +1158,7 @@ OptionValue FallingDM 3, "Strife" } -OptionValue JumpCrouch +OptionValue JumpCrouchFreeLook { 0, "Default" 1, "Off" @@ -1188,9 +1190,9 @@ OptionMenu GameplayOptions Option "Degeneration", "sv_degeneration", "YesNo" Option "Allow Autoaim", "sv_noautoaim", "NoYes" Option "Allow Suicide", "sv_disallowsuicide", "NoYes" - Option "Allow jump", "sv_jump", "JumpCrouch" - Option "Allow crouch", "sv_crouch", "JumpCrouch" - Option "Allow freelook", "sv_nofreelook", "NoYes" + Option "Allow jump", "sv_jump", "JumpCrouchFreeLook" + Option "Allow crouch", "sv_crouch", "JumpCrouchFreeLook" + Option "Allow freelook", "sv_freelook", "JumpCrouchFreeLook" Option "Allow FOV", "sv_nofov", "NoYes" Option "Allow BFG aiming", "sv_nobfgaim", "NoYes" Option "Allow automap", "sv_noautomap", "NoYes" 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.sln b/zdoom.sln index 988e84d68..11dc1b075 100644 --- a/zdoom.sln +++ b/zdoom.sln @@ -162,8 +162,8 @@ Global {A7DE5C73-D623-4118-A48A-BDFD1FAE97D4}.Release|Win32.Build.0 = Release|Win32 {A7DE5C73-D623-4118-A48A-BDFD1FAE97D4}.Release|x64.ActiveCfg = Release|x64 {A7DE5C73-D623-4118-A48A-BDFD1FAE97D4}.Release|x64.Build.0 = Release|x64 - {9B465A9E-E5C7-4577-B559-3CA2F7AE7D96}.Debug|Win32.ActiveCfg = Release|Win32 - {9B465A9E-E5C7-4577-B559-3CA2F7AE7D96}.Debug|Win32.Build.0 = Release|Win32 + {9B465A9E-E5C7-4577-B559-3CA2F7AE7D96}.Debug|Win32.ActiveCfg = Debug|Win32 + {9B465A9E-E5C7-4577-B559-3CA2F7AE7D96}.Debug|Win32.Build.0 = Debug|Win32 {9B465A9E-E5C7-4577-B559-3CA2F7AE7D96}.Debug|x64.ActiveCfg = Release|x64 {9B465A9E-E5C7-4577-B559-3CA2F7AE7D96}.Debug|x64.Build.0 = Release|x64 {9B465A9E-E5C7-4577-B559-3CA2F7AE7D96}.Release|Win32.ActiveCfg = Release|Win32 diff --git a/zdoom.vcproj b/zdoom.vcproj index 597535708..cdc340984 100644 --- a/zdoom.vcproj +++ b/zdoom.vcproj @@ -56,7 +56,7 @@ FavorSizeOrSpeed="1" OmitFramePointers="true" WholeProgramOptimization="false" - AdditionalIncludeDirectories="src\zscript;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\zscript;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\zscript;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\zscript;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" > - - - - @@ -526,6 +522,10 @@ RelativePath=".\src\c_console.cpp" > + + @@ -710,6 +710,10 @@ RelativePath=".\src\m_random.cpp" > + + @@ -1090,6 +1094,10 @@ RelativePath=".\src\zstring.cpp" > + + - - @@ -2345,10 +2349,6 @@ RelativePath=".\src\r_plane.h" > - - diff --git a/zlib/CMakeLists.txt b/zlib/CMakeLists.txt index 7ac44940a..43795934d 100644 --- a/zlib/CMakeLists.txt +++ b/zlib/CMakeLists.txt @@ -1,6 +1,8 @@ cmake_minimum_required(VERSION 2.4.4) set(CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS ON) +make_release_only() + project(zlib C) set(VERSION "1.2.7")