Conflicts:
	src/CMakeLists.txt
	src/posix/sdl/hardware.cpp

Please note that this will NOT(!!!) compile on Linux without adjusting sdlglvideo.cpp!
This commit is contained in:
Christoph Oelckers 2014-12-25 22:50:15 +01:00
commit c39e962fd5
78 changed files with 4910 additions and 4153 deletions

180
FindSDL2.cmake Normal file
View File

@ -0,0 +1,180 @@
# Locate SDL2 library
# This module defines
# SDL2_LIBRARY, the name of the library to link against
# SDL2_FOUND, if false, do not try to link to SDL2
# SDL2_INCLUDE_DIR, where to find SDL.h
#
# This module responds to the the flag:
# SDL2_BUILDING_LIBRARY
# If this is defined, then no SDL2_main will be linked in because
# only applications need main().
# Otherwise, it is assumed you are building an application and this
# module will attempt to locate and set the the proper link flags
# as part of the returned SDL2_LIBRARY variable.
#
# Don't forget to include SDL2main.h and SDL2main.m your project for the
# OS X framework based version. (Other versions link to -lSDL2main which
# this module will try to find on your behalf.) Also for OS X, this
# module will automatically add the -framework Cocoa on your behalf.
#
#
# Additional Note: If you see an empty SDL2_LIBRARY_TEMP in your configuration
# and no SDL2_LIBRARY, it means CMake did not find your SDL2 library
# (SDL2.dll, libsdl2.so, SDL2.framework, etc).
# Set SDL2_LIBRARY_TEMP to point to your SDL2 library, and configure again.
# Similarly, if you see an empty SDL2MAIN_LIBRARY, you should set this value
# as appropriate. These values are used to generate the final SDL2_LIBRARY
# variable, but when these values are unset, SDL2_LIBRARY does not get created.
#
#
# $SDL2DIR is an environment variable that would
# correspond to the ./configure --prefix=$SDL2DIR
# used in building SDL2.
# l.e.galup 9-20-02
#
# Modified by Eric Wing.
# Added code to assist with automated building by using environmental variables
# and providing a more controlled/consistent search behavior.
# Added new modifications to recognize OS X frameworks and
# additional Unix paths (FreeBSD, etc).
# Also corrected the header search path to follow "proper" SDL2 guidelines.
# Added a search for SDL2main which is needed by some platforms.
# Added a search for threads which is needed by some platforms.
# Added needed compile switches for MinGW.
#
# On OSX, this will prefer the Framework version (if found) over others.
# People will have to manually change the cache values of
# SDL2_LIBRARY to override this selection or set the CMake environment
# CMAKE_INCLUDE_PATH to modify the search paths.
#
# Note that the header path has changed from SDL2/SDL.h to just SDL.h
# This needed to change because "proper" SDL2 convention
# is #include "SDL.h", not <SDL2/SDL.h>. This is done for portability
# reasons because not all systems place things in SDL2/ (see FreeBSD).
#
# Ported by Johnny Patterson. This is a literal port for SDL2 of the FindSDL.cmake
# module with the minor edit of changing "SDL" to "SDL2" where necessary. This
# was not created for redistribution, and exists temporarily pending official
# SDL2 CMake modules.
#=============================================================================
# Copyright 2003-2009 Kitware, Inc.
#
# Distributed under the OSI-approved BSD License (the "License");
# see accompanying file Copyright.txt for details.
#
# This software is distributed WITHOUT ANY WARRANTY; without even the
# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
# See the License for more information.
#=============================================================================
# (To distribute this file outside of CMake, substitute the full
# License text for the above reference.)
FIND_PATH(SDL2_INCLUDE_DIR SDL.h
HINTS
$ENV{SDL2DIR}
PATH_SUFFIXES include/SDL2 include
PATHS
~/Library/Frameworks
/Library/Frameworks
/usr/local/include/SDL2
/usr/include/SDL2
/sw # Fink
/opt/local # DarwinPorts
/opt/csw # Blastwave
/opt
)
#MESSAGE("SDL2_INCLUDE_DIR is ${SDL2_INCLUDE_DIR}")
FIND_LIBRARY(SDL2_LIBRARY_TEMP
NAMES SDL2
HINTS
$ENV{SDL2DIR}
PATH_SUFFIXES lib64 lib
PATHS
/sw
/opt/local
/opt/csw
/opt
)
#MESSAGE("SDL2_LIBRARY_TEMP is ${SDL2_LIBRARY_TEMP}")
IF(NOT SDL2_BUILDING_LIBRARY)
IF(NOT ${SDL2_INCLUDE_DIR} MATCHES ".framework")
# Non-OS X framework versions expect you to also dynamically link to
# SDL2main. This is mainly for Windows and OS X. Other (Unix) platforms
# seem to provide SDL2main for compatibility even though they don't
# necessarily need it.
FIND_LIBRARY(SDL2MAIN_LIBRARY
NAMES SDL2main
HINTS
$ENV{SDL2DIR}
PATH_SUFFIXES lib64 lib
PATHS
/sw
/opt/local
/opt/csw
/opt
)
ENDIF(NOT ${SDL2_INCLUDE_DIR} MATCHES ".framework")
ENDIF(NOT SDL2_BUILDING_LIBRARY)
# SDL2 may require threads on your system.
# The Apple build may not need an explicit flag because one of the
# frameworks may already provide it.
# But for non-OSX systems, I will use the CMake Threads package.
IF(NOT APPLE)
FIND_PACKAGE(Threads)
ENDIF(NOT APPLE)
# MinGW needs an additional library, mwindows
# It's total link flags should look like -lmingw32 -lSDL2main -lSDL2 -lmwindows
# (Actually on second look, I think it only needs one of the m* libraries.)
IF(MINGW)
SET(MINGW32_LIBRARY mingw32 CACHE STRING "mwindows for MinGW")
ENDIF(MINGW)
SET(SDL2_FOUND "NO")
IF(SDL2_LIBRARY_TEMP)
# For SDL2main
IF(NOT SDL2_BUILDING_LIBRARY)
IF(SDL2MAIN_LIBRARY)
SET(SDL2_LIBRARY_TEMP ${SDL2MAIN_LIBRARY} ${SDL2_LIBRARY_TEMP})
ENDIF(SDL2MAIN_LIBRARY)
ENDIF(NOT SDL2_BUILDING_LIBRARY)
# For OS X, SDL2 uses Cocoa as a backend so it must link to Cocoa.
# CMake doesn't display the -framework Cocoa string in the UI even
# though it actually is there if I modify a pre-used variable.
# I think it has something to do with the CACHE STRING.
# So I use a temporary variable until the end so I can set the
# "real" variable in one-shot.
IF(APPLE)
SET(SDL2_LIBRARY_TEMP ${SDL2_LIBRARY_TEMP} "-framework Cocoa")
ENDIF(APPLE)
# For threads, as mentioned Apple doesn't need this.
# In fact, there seems to be a problem if I used the Threads package
# and try using this line, so I'm just skipping it entirely for OS X.
IF(NOT APPLE)
SET(SDL2_LIBRARY_TEMP ${SDL2_LIBRARY_TEMP} ${CMAKE_THREAD_LIBS_INIT})
ENDIF(NOT APPLE)
# For MinGW library
IF(MINGW)
SET(SDL2_LIBRARY_TEMP ${MINGW32_LIBRARY} ${SDL2_LIBRARY_TEMP})
ENDIF(MINGW)
# Set the final string here so the GUI reflects the final state.
SET(SDL2_LIBRARY ${SDL2_LIBRARY_TEMP} CACHE STRING "Where the SDL2 Library can be found")
# Set the temp variable to INTERNAL so it is not seen in the CMake GUI
SET(SDL2_LIBRARY_TEMP "${SDL2_LIBRARY_TEMP}" CACHE INTERNAL "")
SET(SDL2_FOUND "YES")
ENDIF(SDL2_LIBRARY_TEMP)
INCLUDE(FindPackageHandleStandardArgs)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(SDL2
REQUIRED_VARS SDL2_LIBRARY SDL2_INCLUDE_DIR)

View File

@ -1,7 +1,7 @@
cmake_minimum_required( VERSION 2.4 ) cmake_minimum_required( VERSION 2.4 )
add_library( output_sdl MODULE output_sdl.c ) add_library( output_sdl MODULE output_sdl.c )
include_directories( ${FMOD_INCLUDE_DIR} ${SDL_INCLUDE_DIR} ) include_directories( ${FMOD_INCLUDE_DIR} ${SDL2_INCLUDE_DIR} )
target_link_libraries( output_sdl SDL ) target_link_libraries( output_sdl ${SDL2_LIBRARY} )
FILE( WRITE ${CMAKE_CURRENT_BINARY_DIR}/link-make "if [ ! -e ${ZDOOM_OUTPUT_DIR}/liboutput_sdl.so ]; then ln -sf output_sdl/liboutput_sdl.so ${ZDOOM_OUTPUT_DIR}/liboutput_sdl.so; fi" ) FILE( WRITE ${CMAKE_CURRENT_BINARY_DIR}/link-make "if [ ! -e ${ZDOOM_OUTPUT_DIR}/liboutput_sdl.so ]; then ln -sf output_sdl/liboutput_sdl.so ${ZDOOM_OUTPUT_DIR}/liboutput_sdl.so; fi" )
add_custom_command( TARGET output_sdl POST_BUILD add_custom_command( TARGET output_sdl POST_BUILD

View File

@ -192,19 +192,6 @@ else( WIN32 )
set( NO_GTK ON ) set( NO_GTK ON )
endif( GTK2_FOUND ) endif( GTK2_FOUND )
endif( NOT NO_GTK ) endif( NOT NO_GTK )
# Check for Xcursor library and header files
find_library( XCURSOR_LIB Xcursor )
if( XCURSOR_LIB )
find_file( XCURSOR_HEADER "X11/Xcursor/Xcursor.h" )
if( XCURSOR_HEADER )
add_definitions( -DUSE_XCURSOR=1 )
message( STATUS "Found Xcursor at ${XCURSOR_LIB}" )
set( ZDOOM_LIBS ${ZDOOM_LIBS} ${XCURSOR_LIB} )
else( XCURSOR_HEADER )
unset( XCURSOR_LIB )
endif( XCURSOR_HEADER )
endif( XCURSOR_LIB )
endif( APPLE ) endif( APPLE )
set( NASM_NAMES nasm ) set( NASM_NAMES nasm )
@ -212,15 +199,12 @@ else( WIN32 )
add_definitions( -DNO_GTK=1 ) add_definitions( -DNO_GTK=1 )
endif( NO_GTK ) endif( NO_GTK )
# Non-Windows version also needs SDL # Non-Windows version also needs SDL except native OS X backend
find_package( SDL )
if( NOT SDL_FOUND )
message( SEND_ERROR "SDL is required for building." )
endif( NOT SDL_FOUND )
if( NOT APPLE OR NOT OSX_COCOA_BACKEND ) if( NOT APPLE OR NOT OSX_COCOA_BACKEND )
set( ZDOOM_LIBS ${ZDOOM_LIBS} "${SDL_LIBRARY}" ) find_package( SDL2 REQUIRED )
include_directories( "${SDL2_INCLUDE_DIR}" )
set( ZDOOM_LIBS ${ZDOOM_LIBS} "${SDL2_LIBRARY}" )
endif( NOT APPLE OR NOT OSX_COCOA_BACKEND ) endif( NOT APPLE OR NOT OSX_COCOA_BACKEND )
include_directories( "${SDL_INCLUDE_DIR}" )
find_path( FPU_CONTROL_DIR fpu_control.h ) find_path( FPU_CONTROL_DIR fpu_control.h )
if( FPU_CONTROL_DIR ) if( FPU_CONTROL_DIR )
@ -586,58 +570,45 @@ set( PLAT_WIN32_SOURCES
win32/st_start.cpp win32/st_start.cpp
win32/win32gliface.cpp win32/win32gliface.cpp
win32/win32video.cpp ) win32/win32video.cpp )
set( PLAT_SDL_SYSTEM_SOURCES set( PLAT_POSIX_SOURCES
sdl/crashcatcher.c posix/i_cd.cpp
sdl/hardware.cpp posix/i_movie.cpp
sdl/i_cd.cpp posix/i_steam.cpp
sdl/i_main.cpp posix/i_system.cpp
sdl/i_movie.cpp posix/st_start.cpp )
sdl/i_steam.cpp set( PLAT_SDL_SOURCES
sdl/i_system.cpp posix/sdl/crashcatcher.c
sdl/sdlvideo.cpp posix/sdl/hardware.cpp
sdl/sdlglvideo.cpp posix/sdl/i_gui.cpp
sdl/st_start.cpp ) posix/sdl/i_input.cpp
set( PLAT_SDL_SPECIAL_SOURCES posix/sdl/i_joystick.cpp
sdl/i_gui.cpp posix/sdl/i_main.cpp
sdl/i_input.cpp posix/sdl/i_timer.cpp
sdl/i_joystick.cpp posix/sdl/sdlvideo.cpp )
sdl/i_timer.cpp ) set( PLAT_OSX_SOURCES
set( PLAT_MAC_SOURCES posix/osx/iwadpicker_cocoa.mm
sdl/iwadpicker_cocoa.mm posix/osx/zdoom.icns )
sdl/i_system_cocoa.mm )
# Fixme: This must be adjusted to the new way of doing things:
# sdl/sdlglvideo.cpp
set( PLAT_COCOA_SOURCES set( PLAT_COCOA_SOURCES
cocoa/HID_Config_Utilities.c posix/cocoa/hid/HID_Config_Utilities.c
cocoa/HID_Error_Handler.c posix/cocoa/hid/HID_Error_Handler.c
cocoa/HID_Name_Lookup.c posix/cocoa/hid/HID_Name_Lookup.c
cocoa/HID_Queue_Utilities.c posix/cocoa/hid/HID_Queue_Utilities.c
cocoa/HID_Utilities.c posix/cocoa/hid/HID_Utilities.c
cocoa/IOHIDDevice_.c posix/cocoa/hid/IOHIDDevice_.c
cocoa/IOHIDElement_.c posix/cocoa/hid/IOHIDElement_.c
cocoa/ImmrHIDUtilAddOn.c posix/cocoa/hid/ImmrHIDUtilAddOn.c
cocoa/i_backend_cocoa.mm posix/cocoa/critsec.cpp
cocoa/i_joystick.cpp posix/cocoa/i_backend_cocoa.mm
cocoa/i_timer.cpp posix/cocoa/i_joystick.cpp
cocoa/zdoom.icns ) posix/cocoa/i_timer.cpp )
if( APPLE )
set( PLAT_SDL_SOURCES ${PLAT_SDL_SYSTEM_SOURCES} "${FMOD_LIBRARY}" )
if( OSX_COCOA_BACKEND )
set( PLAT_MAC_SOURCES ${PLAT_MAC_SOURCES} ${PLAT_COCOA_SOURCES} )
else( OSX_COCOA_BACKEND )
set( PLAT_MAC_SOURCES ${PLAT_MAC_SOURCES} ${PLAT_SDL_SPECIAL_SOURCES} sdl/SDLMain.m )
endif( OSX_COCOA_BACKEND )
set_source_files_properties( cocoa/zdoom.icns PROPERTIES MACOSX_PACKAGE_LOCATION Resources )
set_source_files_properties( "${FMOD_LIBRARY}" PROPERTIES MACOSX_PACKAGE_LOCATION Frameworks )
else( APPLE )
set( PLAT_SDL_SOURCES ${PLAT_SDL_SYSTEM_SOURCES} ${PLAT_SDL_SPECIAL_SOURCES} )
endif( APPLE )
if( WIN32 ) if( WIN32 )
set( SYSTEM_SOURCES_DIR win32 ) set( SYSTEM_SOURCES_DIR win32 )
set( SYSTEM_SOURCES ${PLAT_WIN32_SOURCES} ) set( SYSTEM_SOURCES ${PLAT_WIN32_SOURCES} )
set( OTHER_SYSTEM_SOURCES ${PLAT_SDL_SOURCES} ${PLAT_MAC_SOURCES} ) set( OTHER_SYSTEM_SOURCES ${PLAT_POSIX_SOURCES} ${PLAT_SDL_SOURCES} ${PLAT_OSX_SOURCES} ${PLAT_COCOA_SOURCES} )
if( ZD_CMAKE_COMPILER_IS_GNUCXX_COMPATIBLE ) if( ZD_CMAKE_COMPILER_IS_GNUCXX_COMPATIBLE )
# CMake is not set up to compile and link rc files with GCC. :( # CMake is not set up to compile and link rc files with GCC. :(
@ -648,16 +619,26 @@ if( WIN32 )
else( ZD_CMAKE_COMPILER_IS_GNUCXX_COMPATIBLE ) else( ZD_CMAKE_COMPILER_IS_GNUCXX_COMPATIBLE )
set( SYSTEM_SOURCES ${SYSTEM_SOURCES} win32/zdoom.rc ) set( SYSTEM_SOURCES ${SYSTEM_SOURCES} win32/zdoom.rc )
endif( ZD_CMAKE_COMPILER_IS_GNUCXX_COMPATIBLE ) endif( ZD_CMAKE_COMPILER_IS_GNUCXX_COMPATIBLE )
elseif( APPLE )
if( OSX_COCOA_BACKEND )
set( SYSTEM_SOURCES_DIR posix posix/cocoa )
set( SYSTEM_SOURCES ${PLAT_COCOA_SOURCES} )
set( OTHER_SYSTEM_SOURCES ${PLAT_WIN32_SOURCES} ${PLAT_SDL_SOURCES} )
else( OSX_COCOA_BACKEND )
set( SYSTEM_SOURCES_DIR posix posix/sdl )
set( SYSTEM_SOURCES ${PLAT_SDL_SOURCES} )
set( PLAT_OSX_SOURCES ${PLAT_OSX_SOURCES} posix/sdl/i_system.mm )
set( OTHER_SYSTEM_SOURCES ${PLAT_WIN32_SOURCES} ${PLAT_COCOA_SOURCES} )
endif( OSX_COCOA_BACKEND )
set( SYSTEM_SOURCES ${SYSTEM_SOURCES} ${PLAT_POSIX_SOURCES} ${PLAT_OSX_SOURCES} "${FMOD_LIBRARY}" )
set_source_files_properties( posix/osx/zdoom.icns PROPERTIES MACOSX_PACKAGE_LOCATION Resources )
set_source_files_properties( "${FMOD_LIBRARY}" PROPERTIES MACOSX_PACKAGE_LOCATION Frameworks )
else( WIN32 ) else( WIN32 )
set( SYSTEM_SOURCES_DIR sdl ) set( SYSTEM_SOURCES_DIR posix posix/sdl )
set( SYSTEM_SOURCES ${PLAT_SDL_SOURCES} ) set( SYSTEM_SOURCES ${PLAT_POSIX_SOURCES} ${PLAT_SDL_SOURCES} )
if( APPLE ) set( OTHER_SYSTEM_SOURCES ${PLAT_WIN32_SOURCES} ${PLAT_OSX_SOURCES} ${PLAT_COCOA_SOURCES} )
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 ) endif( WIN32 )
if( NOT ASM_SOURCES ) if( NOT ASM_SOURCES )
@ -715,8 +696,14 @@ endif( DYN_FLUIDSYNTH )
# there's generally a new cpp for every header so this file will get changed # there's generally a new cpp for every header so this file will get changed
if( WIN32 ) if( WIN32 )
set( EXTRA_HEADER_DIRS win32/*.h ) set( EXTRA_HEADER_DIRS win32/*.h )
elseif( APPLE )
if( OSX_COCOA_BACKEND )
set( EXTRA_HEADER_DIRS posix/*.h posix/cocoa/*.h )
else( OSX_COCOA_BACKEND )
set( EXTRA_HEADER_DIRS posix/*.h posix/sdl/*.h )
endif( OSX_COCOA_BACKEND )
else( WIN32 ) else( WIN32 )
set( EXTRA_HEADER_DIRS sdl/*.h ) set( EXTRA_HEADER_DIRS posix/*.h posix/sdl/*.h )
endif( WIN32 ) endif( WIN32 )
file( GLOB HEADER_FILES file( GLOB HEADER_FILES
${EXTRA_HEADER_DIRS} ${EXTRA_HEADER_DIRS}
@ -731,9 +718,11 @@ file( GLOB HEADER_FILES
menu/*.h menu/*.h
oplsynth/*.h oplsynth/*.h
oplsynth/dosbox/*.h oplsynth/dosbox/*.h
posix/*.h
posix/cocoa/*.h
posix/sdl/*.h
r_data/*.h r_data/*.h
resourcefiles/*.h resourcefiles/*.h
sdl/*.h
sfmt/*.h sfmt/*.h
sound/*.h sound/*.h
textures/*.h textures/*.h
@ -1302,7 +1291,7 @@ endif( ZD_CMAKE_COMPILER_IS_GNUCXX_COMPATIBLE )
if( APPLE ) if( APPLE )
set_target_properties(zdoom PROPERTIES set_target_properties(zdoom PROPERTIES
LINK_FLAGS "-framework Carbon -framework Cocoa -framework IOKit -framework OpenGL" LINK_FLAGS "-framework Carbon -framework Cocoa -framework IOKit -framework OpenGL"
MACOSX_BUNDLE_INFO_PLIST "${CMAKE_CURRENT_SOURCE_DIR}/cocoa/zdoom-info.plist" ) MACOSX_BUNDLE_INFO_PLIST "${CMAKE_CURRENT_SOURCE_DIR}/posix/osx/zdoom-info.plist" )
# Fix fmod link so that it can be found in the app bundle. # Fix fmod link so that it can be found in the app bundle.
find_program( OTOOL otool HINTS "/usr/bin" "${OSX_DEVELOPER_ROOT}/usr/bin" ) find_program( OTOOL otool HINTS "/usr/bin" "${OSX_DEVELOPER_ROOT}/usr/bin" )
@ -1325,7 +1314,6 @@ source_group("Audio Files\\OPL Synth" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURC
source_group("Audio Files\\OPL Synth\\DOSBox" FILES oplsynth/dosbox/opl.cpp oplsynth/dosbox/opl.h) 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\\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("Audio Files\\Timidity\\Source" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/timidity/.+\\.cpp$")
source_group("Cocoa Files" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/cocoa/.+")
source_group("Decorate++" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/thingdef/.+") source_group("Decorate++" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/thingdef/.+")
source_group("FraggleScript" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/fragglescript/.+") 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\\Doom Game" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/g_doom/.+")
@ -1354,7 +1342,10 @@ source_group("Render Data\\Resource Sources" REGULAR_EXPRESSION "^${CMAKE_CURREN
source_group("Render Data\\Textures" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/textures/.+") 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("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("Resource Files" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/resourcefiles/.+")
source_group("SDL Files" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/sdl/.+") source_group("POSIX Files" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/posix/.+")
source_group("Cocoa Files" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/posix/cocoa/.+")
source_group("OS X Files" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/posix/osx/.+")
source_group("SDL Files" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/posix/sdl/.+")
source_group("SFMT" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/sfmt/.+") source_group("SFMT" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/sfmt/.+")
source_group("Shared Game" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/g_shared/.+") source_group("Shared Game" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/g_shared/.+")
source_group("Versioning" FILES version.h win32/zdoom.rc) source_group("Versioning" FILES version.h win32/zdoom.rc)

View File

@ -130,7 +130,6 @@ private:
protected: protected:
bool ctf; bool ctf;
int loaded_bots;
int t_join; int t_join;
bool observer; //Consoleplayer is observer. bool observer; //Consoleplayer is observer.
}; };
@ -188,12 +187,12 @@ public:
fixed_t oldy; fixed_t oldy;
private: private:
//(B_think.cpp) //(b_think.cpp)
void Think (); void Think ();
void ThinkForMove (ticcmd_t *cmd); void ThinkForMove (ticcmd_t *cmd);
void Set_enemy (); void Set_enemy ();
//(B_func.cpp) //(b_func.cpp)
bool Reachable (AActor *target); bool Reachable (AActor *target);
void Dofire (ticcmd_t *cmd); void Dofire (ticcmd_t *cmd);
AActor *Choose_Mate (); AActor *Choose_Mate ();

View File

@ -178,7 +178,10 @@ void FCajunMaster::End ()
{ {
for (i = 0; i < MAXPLAYERS; i++) for (i = 0; i < MAXPLAYERS; i++)
{ {
getspawned.Push(players[i].userinfo.GetName()); if (players[i].Bot != NULL)
{
getspawned.Push(players[i].userinfo.GetName());
}
} }
wanted_botnum = botnum; wanted_botnum = botnum;
@ -216,19 +219,16 @@ bool FCajunMaster::SpawnBot (const char *name, int color)
"\\color\\cf df 90" //10 = Bleached Bone "\\color\\cf df 90" //10 = Bleached Bone
}; };
botinfo_t *thebot; botinfo_t *thebot = botinfo;
int botshift; int botshift = 0;
if (name) if (name)
{ {
thebot = botinfo;
// Check if exist or already in the game. // Check if exist or already in the game.
botshift = 0;
while (thebot && stricmp (name, thebot->name)) while (thebot && stricmp (name, thebot->name))
{ {
thebot = thebot->next;
botshift++; botshift++;
thebot = thebot->next;
} }
if (thebot == NULL) if (thebot == NULL)
@ -246,27 +246,36 @@ bool FCajunMaster::SpawnBot (const char *name, int color)
return false; return false;
} }
} }
else if (botnum < loaded_bots)
{
bool vacant = false; //Spawn a random bot from bots.cfg if no name given.
while (!vacant)
{
int rnum = (pr_botspawn() % loaded_bots);
thebot = botinfo;
botshift = 0;
while (rnum)
{
--rnum, thebot = thebot->next;
botshift++;
}
if (thebot->inuse == BOTINUSE_No)
vacant = true;
}
}
else else
{ {
Printf ("Couldn't spawn bot; no bot left in %s\n", BOTFILENAME); //Spawn a random bot from bots.cfg if no name given.
return false; TArray<botinfo_t *> BotInfoAvailable;
while (thebot)
{
if (thebot->inuse == BOTINUSE_No)
BotInfoAvailable.Push (thebot);
thebot = thebot->next;
}
if (BotInfoAvailable.Size () == 0)
{
Printf ("Couldn't spawn bot; no bot left in %s\n", BOTFILENAME);
return false;
}
thebot = BotInfoAvailable[pr_botspawn() % BotInfoAvailable.Size ()];
botinfo_t *thebot2 = botinfo;
while (thebot2)
{
if (thebot == thebot2)
break;
botshift++;
thebot2 = thebot2->next;
}
} }
thebot->inuse = BOTINUSE_Waiting; thebot->inuse = BOTINUSE_Waiting;
@ -478,7 +487,6 @@ void FCajunMaster::ForgetBots ()
} }
botinfo = NULL; botinfo = NULL;
loaded_bots = 0;
} }
bool FCajunMaster::LoadBots () bool FCajunMaster::LoadBots ()
@ -486,6 +494,7 @@ bool FCajunMaster::LoadBots ()
FScanner sc; FScanner sc;
FString tmp; FString tmp;
bool gotteam = false; bool gotteam = false;
int loaded_bots = 0;
bglobal.ForgetBots (); bglobal.ForgetBots ();
tmp = M_GetCajunPath(BOTFILENAME); tmp = M_GetCajunPath(BOTFILENAME);
@ -602,9 +611,9 @@ bool FCajunMaster::LoadBots ()
newinfo->next = bglobal.botinfo; newinfo->next = bglobal.botinfo;
newinfo->lastteam = TEAM_NONE; newinfo->lastteam = TEAM_NONE;
bglobal.botinfo = newinfo; bglobal.botinfo = newinfo;
bglobal.loaded_bots++; loaded_bots++;
} }
Printf ("%d bots read from %s\n", bglobal.loaded_bots, BOTFILENAME); Printf ("%d bots read from %s\n", loaded_bots, BOTFILENAME);
return true; return true;
} }

View File

@ -343,6 +343,10 @@ static void CT_ClearChatMessage ()
static void ShoveChatStr (const char *str, BYTE who) static void ShoveChatStr (const char *str, BYTE who)
{ {
// Don't send empty messages
if (str == NULL || str[0] == '\0')
return;
FString substBuff; FString substBuff;
if (str[0] == '/' && if (str[0] == '/' &&

View File

@ -669,25 +669,38 @@ void PlayerIsGone (int netnode, int netconsole)
{ {
int i; int i;
if (!nodeingame[netnode]) if (nodeingame[netnode])
return; {
for (i = netnode + 1; i < doomcom.numnodes; ++i)
{
if (nodeingame[i])
break;
}
if (i == doomcom.numnodes)
{
doomcom.numnodes = netnode;
}
for (i = netnode + 1; i < doomcom.numnodes; ++i) if (playeringame[netconsole])
{ {
if (nodeingame[i]) players[netconsole].playerstate = PST_GONE;
break; }
nodeingame[netnode] = false;
nodejustleft[netnode] = false;
} }
if (i == doomcom.numnodes) else if (nodejustleft[netnode]) // Packet Server
{ {
doomcom.numnodes = netnode; if (netnode + 1 == doomcom.numnodes)
{
doomcom.numnodes = netnode;
}
if (playeringame[netconsole])
{
players[netconsole].playerstate = PST_GONE;
}
nodejustleft[netnode] = false;
} }
else return;
if (playeringame[netconsole])
{
players[netconsole].playerstate = PST_GONE;
}
nodeingame[netnode] = false;
nodejustleft[netnode] = false;
if (netconsole == Net_Arbitrator) if (netconsole == Net_Arbitrator)
{ {
@ -790,7 +803,6 @@ void GetPackets (void)
else else
{ {
nodeingame[netnode] = false; nodeingame[netnode] = false;
playeringame[netconsole] = false;
nodejustleft[netnode] = true; nodejustleft[netnode] = true;
} }
continue; continue;
@ -1064,16 +1076,16 @@ void NetUpdate (void)
if (consoleplayer == Net_Arbitrator) if (consoleplayer == Net_Arbitrator)
{ {
for (j = 0; j < doomcom.numnodes; j++)
{
if (nodeingame[j] && NetMode == NET_PacketServer)
{
count++;
}
}
if (NetMode == NET_PacketServer) if (NetMode == NET_PacketServer)
{ {
for (j = 0; j < MAXPLAYERS; j++)
{
if (playeringame[j] && players[j].Bot == NULL)
{
count++;
}
}
// The loop above added the local player to the count a second time, // The loop above added the local player to the count a second time,
// and it also added the player being sent the packet to the count. // and it also added the player being sent the packet to the count.
count -= 2; count -= 2;
@ -1203,12 +1215,15 @@ void NetUpdate (void)
netbuffer[0] |= NCMD_MULTI; netbuffer[0] |= NCMD_MULTI;
netbuffer[k++] = count; netbuffer[k++] = count;
for (l = 1, j = 0; j < doomcom.numnodes; j++) if (NetMode == NET_PacketServer)
{ {
if (nodeingame[j] && j != i && j != nodeforplayer[consoleplayer] && NetMode == NET_PacketServer) for (l = 1, j = 0; j < MAXPLAYERS; j++)
{ {
playerbytes[l++] = playerfornode[j]; if (playeringame[j] && players[j].Bot == NULL && j != playerfornode[i] && j != consoleplayer)
netbuffer[k++] = playerfornode[j]; {
playerbytes[l++] = j;
netbuffer[k++] = j;
}
} }
} }
} }

View File

@ -247,8 +247,12 @@ static void BuildModesList (int hiwidth, int hiheight, int hi_bits)
if (Video != NULL) if (Video != NULL)
{ {
while ((haveMode = Video->NextMode (&width, &height, &letterbox)) && while ((haveMode = Video->NextMode (&width, &height, &letterbox)) &&
(ratiomatch >= 0 && CheckRatio (width, height) != ratiomatch)) ratiomatch >= 0)
{ {
int ratio;
CheckRatio (width, height, &ratio);
if (ratio == ratiomatch)
break;
} }
} }

View File

@ -72,7 +72,8 @@ DECLARE_ACTION(A_FreezeDeathChunks)
DECLARE_ACTION(A_BossDeath) DECLARE_ACTION(A_BossDeath)
void A_Chase(AActor *self); void A_Chase(AActor *self);
void A_FaceTarget (AActor *actor, angle_t max_turn = 0, angle_t max_pitch = ANGLE_270); void A_FaceTarget(AActor *actor, angle_t max_turn = 0, angle_t max_pitch = ANGLE_270);
void A_Face(AActor *self, AActor *other, angle_t max_turn = 0, angle_t max_pitch = ANGLE_270);
bool A_RaiseMobj (AActor *, fixed_t speed); bool A_RaiseMobj (AActor *, fixed_t speed);
bool A_SinkMobj (AActor *, fixed_t speed); bool A_SinkMobj (AActor *, fixed_t speed);

View File

@ -4765,7 +4765,7 @@ void P_RadiusAttack(AActor *bombspot, AActor *bombsource, int bombdamage, int bo
points *= thing->GetClass()->Meta.GetMetaFixed(AMETA_RDFactor, FRACUNIT) / (double)FRACUNIT; points *= thing->GetClass()->Meta.GetMetaFixed(AMETA_RDFactor, FRACUNIT) / (double)FRACUNIT;
// points and bombdamage should be the same sign // points and bombdamage should be the same sign
if ((points * bombdamage) > 0 && P_CheckSight(thing, bombspot, SF_IGNOREVISIBILITY | SF_IGNOREWATERBOUNDARY)) if (((bombspot->flags7 & MF7_CAUSEPAIN) || (points * bombdamage) > 0) && P_CheckSight(thing, bombspot, SF_IGNOREVISIBILITY | SF_IGNOREWATERBOUNDARY))
{ // OK to damage; target is in direct path { // OK to damage; target is in direct path
double velz; double velz;
double thrust; double thrust;

View File

@ -569,7 +569,7 @@ void P_SerializePolyobjs (FArchive &arc)
I_Error ("UnarchivePolyobjs: Invalid polyobj tag"); I_Error ("UnarchivePolyobjs: Invalid polyobj tag");
} }
arc << angle; arc << angle;
po->RotatePolyobj (angle); po->RotatePolyobj (angle, true);
arc << deltaX << deltaY << po->interpolation; arc << deltaX << deltaY << po->interpolation;
deltaX -= po->StartSpot.x; deltaX -= po->StartSpot.x;
deltaY -= po->StartSpot.y; deltaY -= po->StartSpot.y;

View File

@ -49,11 +49,13 @@ public:
WORD operator [](FTextureID tex) const WORD operator [](FTextureID tex) const
{ {
if ((unsigned)tex.GetIndex() >= Types.Size()) return DefaultTerrainType;
WORD type = Types[tex.GetIndex()]; WORD type = Types[tex.GetIndex()];
return type == 0xffff? DefaultTerrainType : type; return type == 0xffff? DefaultTerrainType : type;
} }
WORD operator [](int texnum) const WORD operator [](int texnum) const
{ {
if ((unsigned)texnum >= Types.Size()) return DefaultTerrainType;
WORD type = Types[texnum]; WORD type = Types[texnum];
return type == 0xffff? DefaultTerrainType : type; return type == 0xffff? DefaultTerrainType : type;
} }

View File

@ -1051,7 +1051,7 @@ static void RotatePt (int an, fixed_t *x, fixed_t *y, fixed_t startSpotX, fixed_
// //
//========================================================================== //==========================================================================
bool FPolyObj::RotatePolyobj (angle_t angle) bool FPolyObj::RotatePolyobj (angle_t angle, bool fromsave)
{ {
int an; int an;
bool blocked; bool blocked;
@ -1073,23 +1073,27 @@ bool FPolyObj::RotatePolyobj (angle_t angle)
validcount++; validcount++;
UpdateBBox(); UpdateBBox();
for(unsigned i=0;i < Sidedefs.Size(); i++) // If we are loading a savegame we do not really want to damage actors and be blocked by them. This can also cause crashes when trying to damage incompletely deserialized player pawns.
if (!fromsave)
{ {
if (CheckMobjBlocking(Sidedefs[i])) for (unsigned i = 0; i < Sidedefs.Size(); i++)
{ {
blocked = true; if (CheckMobjBlocking(Sidedefs[i]))
{
blocked = true;
}
} }
} if (blocked)
if (blocked)
{
for(unsigned i=0;i < Vertices.Size(); i++)
{ {
Vertices[i]->x = PrevPts[i].x; for(unsigned i=0;i < Vertices.Size(); i++)
Vertices[i]->y = PrevPts[i].y; {
Vertices[i]->x = PrevPts[i].x;
Vertices[i]->y = PrevPts[i].y;
}
UpdateBBox();
LinkPolyobj();
return false;
} }
UpdateBBox();
LinkPolyobj();
return false;
} }
this->angle += angle; this->angle += angle;
LinkPolyobj(); LinkPolyobj();

View File

@ -74,7 +74,7 @@ struct FPolyObj
int GetMirror(); int GetMirror();
bool MovePolyobj (int x, int y, bool force = false); bool MovePolyobj (int x, int y, bool force = false);
bool RotatePolyobj (angle_t angle); bool RotatePolyobj (angle_t angle, bool fromsave = false);
void ClosestPoint(fixed_t fx, fixed_t fy, fixed_t &ox, fixed_t &oy, side_t **side) const; void ClosestPoint(fixed_t fx, fixed_t fy, fixed_t &ox, fixed_t &oy, side_t **side) const;
void LinkPolyobj (); void LinkPolyobj ();
void RecalcActorFloorCeil(FBoundingBox bounds) const; void RecalcActorFloorCeil(FBoundingBox bounds) const;

View File

@ -0,0 +1,62 @@
/*
** critsec.cpp
**
**---------------------------------------------------------------------------
** Copyright 2014 Alexey Lysiuk
** 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 "critsec.h"
// TODO: add error handling
FCriticalSection::FCriticalSection()
{
pthread_mutexattr_t attributes;
pthread_mutexattr_init(&attributes);
pthread_mutexattr_settype(&attributes, PTHREAD_MUTEX_RECURSIVE);
pthread_mutex_init(&m_mutex, &attributes);
pthread_mutexattr_destroy(&attributes);
}
FCriticalSection::~FCriticalSection()
{
pthread_mutex_destroy(&m_mutex);
}
void FCriticalSection::Enter()
{
pthread_mutex_lock(&m_mutex);
}
void FCriticalSection::Leave()
{
pthread_mutex_unlock(&m_mutex);
}

53
src/posix/cocoa/critsec.h Normal file
View File

@ -0,0 +1,53 @@
/*
** critsec.h
**
**---------------------------------------------------------------------------
** Copyright 2014 Alexey Lysiuk
** 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.
**---------------------------------------------------------------------------
**
*/
#ifndef CRITSEC_H
#define CRITSEC_H
#include <pthread.h>
class FCriticalSection
{
public:
FCriticalSection();
~FCriticalSection();
void Enter();
void Leave();
private:
pthread_mutex_t m_mutex;
};
#endif

View File

@ -37,7 +37,7 @@
#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1050 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1050
#include "HID_Utilities_External.h" #include "hid/HID_Utilities_External.h"
#include "d_event.h" #include "d_event.h"
#include "doomdef.h" #include "doomdef.h"

View File

View File

@ -4,8 +4,6 @@
#include <pthread.h> #include <pthread.h>
#include <libkern/OSAtomic.h> #include <libkern/OSAtomic.h>
#include <SDL.h>
#include "basictypes.h" #include "basictypes.h"
#include "basicinlines.h" #include "basicinlines.h"
#include "doomdef.h" #include "doomdef.h"
@ -13,23 +11,36 @@
#include "templates.h" #include "templates.h"
static timeval s_startTicks;
unsigned int I_MSTime() unsigned int I_MSTime()
{ {
return SDL_GetTicks(); timeval now;
gettimeofday(&now, NULL);
const uint32_t ticks =
(now.tv_sec - s_startTicks.tv_sec ) * 1000
+ (now.tv_usec - s_startTicks.tv_usec) / 1000;
return ticks;
} }
unsigned int I_FPSTime() unsigned int I_FPSTime()
{ {
return SDL_GetTicks(); timeval now;
gettimeofday(&now, NULL);
return static_cast<unsigned int>(
(now.tv_sec) * 1000 + (now.tv_usec) / 1000);
} }
bool g_isTicFrozen;
namespace namespace
{ {
bool s_isTicFrozen;
timespec GetNextTickTime() timespec GetNextTickTime()
{ {
static const long MILLISECONDS_IN_SECOND = 1000; static const long MILLISECONDS_IN_SECOND = 1000;
@ -91,7 +102,7 @@ void* TimerThreadFunc(void*)
pthread_mutex_lock(&s_timerMutex); pthread_mutex_lock(&s_timerMutex);
pthread_cond_timedwait(&s_timerEvent, &s_timerMutex, &timeToNextTick); pthread_cond_timedwait(&s_timerEvent, &s_timerMutex, &timeToNextTick);
if (!g_isTicFrozen) if (!s_isTicFrozen)
{ {
// The following GCC/Clang intrinsic can be used instead of OS X specific function: // The following GCC/Clang intrinsic can be used instead of OS X specific function:
// __sync_add_and_fetch(&s_tics, 1); // __sync_add_and_fetch(&s_tics, 1);
@ -101,7 +112,7 @@ void* TimerThreadFunc(void*)
OSAtomicIncrement32(&s_tics); OSAtomicIncrement32(&s_tics);
} }
s_timerStart = SDL_GetTicks(); s_timerStart = I_MSTime();
pthread_cond_broadcast(&s_timerEvent); pthread_cond_broadcast(&s_timerEvent);
pthread_mutex_unlock(&s_timerMutex); pthread_mutex_unlock(&s_timerMutex);
@ -122,7 +133,7 @@ int GetTimeThreaded(bool saveMS)
int WaitForTicThreaded(int prevTic) int WaitForTicThreaded(int prevTic)
{ {
assert(!g_isTicFrozen); assert(!s_isTicFrozen);
while (s_tics <= prevTic) while (s_tics <= prevTic)
{ {
@ -136,7 +147,7 @@ int WaitForTicThreaded(int prevTic)
void FreezeTimeThreaded(bool frozen) void FreezeTimeThreaded(bool frozen)
{ {
g_isTicFrozen = frozen; s_isTicFrozen = frozen;
} }
} // unnamed namespace } // unnamed namespace
@ -144,7 +155,7 @@ void FreezeTimeThreaded(bool frozen)
fixed_t I_GetTimeFrac(uint32* ms) fixed_t I_GetTimeFrac(uint32* ms)
{ {
const uint32_t now = SDL_GetTicks(); const uint32_t now = I_MSTime();
if (NULL != ms) if (NULL != ms)
{ {
@ -157,11 +168,13 @@ fixed_t I_GetTimeFrac(uint32* ms)
} }
void I_InitTimer () void I_InitTimer()
{ {
assert(!s_timerInitialized); assert(!s_timerInitialized);
s_timerInitialized = true; s_timerInitialized = true;
gettimeofday(&s_startTicks, NULL);
pthread_cond_init (&s_timerEvent, NULL); pthread_cond_init (&s_timerEvent, NULL);
pthread_mutex_init(&s_timerMutex, NULL); pthread_mutex_init(&s_timerMutex, NULL);
@ -172,7 +185,7 @@ void I_InitTimer ()
I_FreezeTime = FreezeTimeThreaded; I_FreezeTime = FreezeTimeThreaded;
} }
void I_ShutdownTimer () void I_ShutdownTimer()
{ {
if (!s_timerInitialized) if (!s_timerInitialized)
{ {

View File

@ -1,155 +1,155 @@
// ZDoom bases its keycodes on DirectInput's scan codes // ZDoom bases its keycodes on DirectInput's scan codes
// Why? Because it was Win32-only before porting to anything else, // Why? Because it was Win32-only before porting to anything else,
// so this made sense. AFAIK, it's primarily used under Win32 now, // so this made sense. AFAIK, it's primarily used under Win32 now,
// so it still makes sense. // so it still makes sense.
// //
// Actually, these key codes may only be used for key bindings now, // Actually, these key codes may only be used for key bindings now,
// in which case they're not really necessary--if we tweaked c_bind.cpp. // in which case they're not really necessary--if we tweaked c_bind.cpp.
enum enum
{ {
DIK_ESCAPE = 1, DIK_ESCAPE = 1,
DIK_1, DIK_1,
DIK_2, DIK_2,
DIK_3, DIK_3,
DIK_4, DIK_4,
DIK_5, DIK_5,
DIK_6, DIK_6,
DIK_7, DIK_7,
DIK_8, DIK_8,
DIK_9, DIK_9,
DIK_0, DIK_0,
DIK_MINUS, /* - on main keyboard */ DIK_MINUS, /* - on main keyboard */
DIK_EQUALS, DIK_EQUALS,
DIK_BACK, /* backspace */ DIK_BACK, /* backspace */
DIK_TAB, DIK_TAB,
DIK_Q, DIK_Q,
DIK_W, DIK_W,
DIK_E, DIK_E,
DIK_R, DIK_R,
DIK_T, DIK_T,
DIK_Y, DIK_Y,
DIK_U, DIK_U,
DIK_I, DIK_I,
DIK_O, DIK_O,
DIK_P, DIK_P,
DIK_LBRACKET, DIK_LBRACKET,
DIK_RBRACKET, DIK_RBRACKET,
DIK_RETURN, /* Enter on main keyboard */ DIK_RETURN, /* Enter on main keyboard */
DIK_LCONTROL, DIK_LCONTROL,
DIK_A, DIK_A,
DIK_S, DIK_S,
DIK_D, DIK_D,
DIK_F, DIK_F,
DIK_G, DIK_G,
DIK_H, DIK_H,
DIK_J, DIK_J,
DIK_K, DIK_K,
DIK_L, DIK_L,
DIK_SEMICOLON, DIK_SEMICOLON,
DIK_APOSTROPHE, DIK_APOSTROPHE,
DIK_GRAVE, /* accent grave */ DIK_GRAVE, /* accent grave */
DIK_LSHIFT, DIK_LSHIFT,
DIK_BACKSLASH, DIK_BACKSLASH,
DIK_Z, DIK_Z,
DIK_X, DIK_X,
DIK_C, DIK_C,
DIK_V, DIK_V,
DIK_B, DIK_B,
DIK_N, DIK_N,
DIK_M, DIK_M,
DIK_COMMA, DIK_COMMA,
DIK_PERIOD, /* . on main keyboard */ DIK_PERIOD, /* . on main keyboard */
DIK_SLASH, /* / on main keyboard */ DIK_SLASH, /* / on main keyboard */
DIK_RSHIFT, DIK_RSHIFT,
DIK_MULTIPLY, /* * on numeric keypad */ DIK_MULTIPLY, /* * on numeric keypad */
DIK_LMENU, /* left Alt */ DIK_LMENU, /* left Alt */
DIK_SPACE, DIK_SPACE,
DIK_CAPITAL, DIK_CAPITAL,
DIK_F1, DIK_F1,
DIK_F2, DIK_F2,
DIK_F3, DIK_F3,
DIK_F4, DIK_F4,
DIK_F5, DIK_F5,
DIK_F6, DIK_F6,
DIK_F7, DIK_F7,
DIK_F8, DIK_F8,
DIK_F9, DIK_F9,
DIK_F10, DIK_F10,
DIK_NUMLOCK, DIK_NUMLOCK,
DIK_SCROLL, /* Scroll Lock */ DIK_SCROLL, /* Scroll Lock */
DIK_NUMPAD7, DIK_NUMPAD7,
DIK_NUMPAD8, DIK_NUMPAD8,
DIK_NUMPAD9, DIK_NUMPAD9,
DIK_SUBTRACT, /* - on numeric keypad */ DIK_SUBTRACT, /* - on numeric keypad */
DIK_NUMPAD4, DIK_NUMPAD4,
DIK_NUMPAD5, DIK_NUMPAD5,
DIK_NUMPAD6, DIK_NUMPAD6,
DIK_ADD, /* + on numeric keypad */ DIK_ADD, /* + on numeric keypad */
DIK_NUMPAD1, DIK_NUMPAD1,
DIK_NUMPAD2, DIK_NUMPAD2,
DIK_NUMPAD3, DIK_NUMPAD3,
DIK_NUMPAD0, DIK_NUMPAD0,
DIK_DECIMAL, /* . on numeric keypad */ DIK_DECIMAL, /* . on numeric keypad */
DIK_OEM_102 = 0x56, /* < > | on UK/Germany keyboards */ DIK_OEM_102 = 0x56, /* < > | on UK/Germany keyboards */
DIK_F11, DIK_F11,
DIK_F12, DIK_F12,
DIK_F13 = 0x64, /* (NEC PC98) */ DIK_F13 = 0x64, /* (NEC PC98) */
DIK_F14, /* (NEC PC98) */ DIK_F14, /* (NEC PC98) */
DIK_F15, /* (NEC PC98) */ DIK_F15, /* (NEC PC98) */
DIK_KANA = 0x70, /* (Japanese keyboard) */ DIK_KANA = 0x70, /* (Japanese keyboard) */
DIK_ABNT_C1 = 0x73, /* / ? on Portugese (Brazilian) keyboards */ DIK_ABNT_C1 = 0x73, /* / ? on Portugese (Brazilian) keyboards */
DIK_CONVERT = 0x79, /* (Japanese keyboard) */ DIK_CONVERT = 0x79, /* (Japanese keyboard) */
DIK_NOCONVERT = 0x7B, /* (Japanese keyboard) */ DIK_NOCONVERT = 0x7B, /* (Japanese keyboard) */
DIK_YEN = 0x7D, /* (Japanese keyboard) */ DIK_YEN = 0x7D, /* (Japanese keyboard) */
DIK_ABNT_C2 = 0x7E, /* Numpad . on Portugese (Brazilian) keyboards */ DIK_ABNT_C2 = 0x7E, /* Numpad . on Portugese (Brazilian) keyboards */
DIK_NUMPAD_EQUALS = 0x8D, /* = on numeric keypad (NEC PC98) */ DIK_NUMPAD_EQUALS = 0x8D, /* = on numeric keypad (NEC PC98) */
DIK_PREVTRACK = 0x90, /* Previous Track (DIK_CIRCUMFLEX on Japanese keyboard) */ DIK_PREVTRACK = 0x90, /* Previous Track (DIK_CIRCUMFLEX on Japanese keyboard) */
DIK_AT, /* (NEC PC98) */ DIK_AT, /* (NEC PC98) */
DIK_COLON, /* (NEC PC98) */ DIK_COLON, /* (NEC PC98) */
DIK_UNDERLINE, /* (NEC PC98) */ DIK_UNDERLINE, /* (NEC PC98) */
DIK_KANJI, /* (Japanese keyboard) */ DIK_KANJI, /* (Japanese keyboard) */
DIK_STOP, /* (NEC PC98) */ DIK_STOP, /* (NEC PC98) */
DIK_AX, /* (Japan AX) */ DIK_AX, /* (Japan AX) */
DIK_UNLABELED, /* (J3100) */ DIK_UNLABELED, /* (J3100) */
DIK_NEXTTRACK = 0x99, /* Next Track */ DIK_NEXTTRACK = 0x99, /* Next Track */
DIK_NUMPADENTER = 0x9C, /* Enter on numeric keypad */ DIK_NUMPADENTER = 0x9C, /* Enter on numeric keypad */
DIK_RCONTROL = 0x9D, DIK_RCONTROL = 0x9D,
DIK_MUTE = 0xA0, /* Mute */ DIK_MUTE = 0xA0, /* Mute */
DIK_CALCULATOR = 0xA1, /* Calculator */ DIK_CALCULATOR = 0xA1, /* Calculator */
DIK_PLAYPAUSE = 0xA2, /* Play / Pause */ DIK_PLAYPAUSE = 0xA2, /* Play / Pause */
DIK_MEDIASTOP = 0xA4, /* Media Stop */ DIK_MEDIASTOP = 0xA4, /* Media Stop */
DIK_VOLUMEDOWN = 0xAE, /* Volume - */ DIK_VOLUMEDOWN = 0xAE, /* Volume - */
DIK_VOLUMEUP = 0xB0, /* Volume + */ DIK_VOLUMEUP = 0xB0, /* Volume + */
DIK_WEBHOME = 0xB2, /* Web home */ DIK_WEBHOME = 0xB2, /* Web home */
DIK_NUMPADCOMMA = 0xB3, /* , on numeric keypad (NEC PC98) */ DIK_NUMPADCOMMA = 0xB3, /* , on numeric keypad (NEC PC98) */
DIK_DIVIDE = 0xB5, /* / on numeric keypad */ DIK_DIVIDE = 0xB5, /* / on numeric keypad */
DIK_SYSRQ = 0xB7, DIK_SYSRQ = 0xB7,
DIK_RMENU = 0xB8, /* right Alt */ DIK_RMENU = 0xB8, /* right Alt */
DIK_PAUSE = 0xC5, /* Pause */ DIK_PAUSE = 0xC5, /* Pause */
DIK_HOME = 0xC7, /* Home on arrow keypad */ DIK_HOME = 0xC7, /* Home on arrow keypad */
DIK_UP = 0xC8, /* UpArrow on arrow keypad */ DIK_UP = 0xC8, /* UpArrow on arrow keypad */
DIK_PRIOR = 0xC9, /* PgUp on arrow keypad */ DIK_PRIOR = 0xC9, /* PgUp on arrow keypad */
DIK_LEFT = 0xCB, /* LeftArrow on arrow keypad */ DIK_LEFT = 0xCB, /* LeftArrow on arrow keypad */
DIK_RIGHT = 0xCD, /* RightArrow on arrow keypad */ DIK_RIGHT = 0xCD, /* RightArrow on arrow keypad */
DIK_END = 0xCF, /* End on arrow keypad */ DIK_END = 0xCF, /* End on arrow keypad */
DIK_DOWN = 0xD0, /* DownArrow on arrow keypad */ DIK_DOWN = 0xD0, /* DownArrow on arrow keypad */
DIK_NEXT = 0xD1, /* PgDn on arrow keypad */ DIK_NEXT = 0xD1, /* PgDn on arrow keypad */
DIK_INSERT = 0xD2, /* Insert on arrow keypad */ DIK_INSERT = 0xD2, /* Insert on arrow keypad */
DIK_DELETE = 0xD3, /* Delete on arrow keypad */ DIK_DELETE = 0xD3, /* Delete on arrow keypad */
DIK_LWIN = 0xDB, /* Left Windows key */ DIK_LWIN = 0xDB, /* Left Windows key */
DIK_RWIN = 0xDC, /* Right Windows key */ DIK_RWIN = 0xDC, /* Right Windows key */
DIK_APPS = 0xDD, /* AppMenu key */ DIK_APPS = 0xDD, /* AppMenu key */
DIK_POWER = 0xDE, /* System Power */ DIK_POWER = 0xDE, /* System Power */
DIK_SLEEP = 0xDF, /* System Sleep */ DIK_SLEEP = 0xDF, /* System Sleep */
DIK_WAKE = 0xE3, /* System Wake */ DIK_WAKE = 0xE3, /* System Wake */
DIK_WEBSEARCH = 0xE5, /* Web Search */ DIK_WEBSEARCH = 0xE5, /* Web Search */
DIK_WEBFAVORITES = 0xE6, /* Web Favorites */ DIK_WEBFAVORITES = 0xE6, /* Web Favorites */
DIK_WEBREFRESH = 0xE7, /* Web Refresh */ DIK_WEBREFRESH = 0xE7, /* Web Refresh */
DIK_WEBSTOP = 0xE8, /* Web Stop */ DIK_WEBSTOP = 0xE8, /* Web Stop */
DIK_WEBFORWARD = 0xE9, /* Web Forward */ DIK_WEBFORWARD = 0xE9, /* Web Forward */
DIK_WEBBACK = 0xEA, /* Web Back */ DIK_WEBBACK = 0xEA, /* Web Back */
DIK_MYCOMPUTER = 0xEB, /* My Computer */ DIK_MYCOMPUTER = 0xEB, /* My Computer */
DIK_MAIL = 0xEC, /* Mail */ DIK_MAIL = 0xEC, /* Mail */
DIK_MEDIASELECT = 0xED /* Media Select */ DIK_MEDIASELECT = 0xED /* Media Select */
}; };

View File

@ -1,96 +1,96 @@
/* /*
** hardware.h ** hardware.h
** **
**--------------------------------------------------------------------------- **---------------------------------------------------------------------------
** Copyright 1998-2006 Randy Heit ** Copyright 1998-2006 Randy Heit
** All rights reserved. ** All rights reserved.
** **
** Redistribution and use in source and binary forms, with or without ** Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions ** modification, are permitted provided that the following conditions
** are met: ** are met:
** **
** 1. Redistributions of source code must retain the above copyright ** 1. Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer. ** notice, this list of conditions and the following disclaimer.
** 2. Redistributions in binary form must reproduce the above copyright ** 2. Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in the ** notice, this list of conditions and the following disclaimer in the
** documentation and/or other materials provided with the distribution. ** documentation and/or other materials provided with the distribution.
** 3. The name of the author may not be used to endorse or promote products ** 3. The name of the author may not be used to endorse or promote products
** derived from this software without specific prior written permission. ** derived from this software without specific prior written permission.
** **
** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR ** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES ** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. ** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, ** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT ** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
**--------------------------------------------------------------------------- **---------------------------------------------------------------------------
** **
*/ */
#ifndef __HARDWARE_H__ #ifndef __HARDWARE_H__
#define __HARDWARE_H__ #define __HARDWARE_H__
#include "i_video.h" #include "i_video.h"
#include "v_video.h" #include "v_video.h"
// Semaphores // Semaphores
#ifdef __APPLE__ #ifdef __APPLE__
#include <mach/mach_init.h> #include <mach/mach_init.h>
#include <mach/semaphore.h> #include <mach/semaphore.h>
#include <mach/task.h> #include <mach/task.h>
typedef semaphore_t Semaphore; typedef semaphore_t Semaphore;
#define SEMAPHORE_WAIT(sem) \ #define SEMAPHORE_WAIT(sem) \
while(semaphore_wait(sem) != KERN_SUCCESS){} while(semaphore_wait(sem) != KERN_SUCCESS){}
#define SEMAPHORE_SIGNAL(sem) \ #define SEMAPHORE_SIGNAL(sem) \
semaphore_signal(sem); semaphore_signal(sem);
#define SEMAPHORE_INIT(sem, shared, value) \ #define SEMAPHORE_INIT(sem, shared, value) \
semaphore_create(mach_task_self(), &sem, shared, value); semaphore_create(mach_task_self(), &sem, shared, value);
#else #else
#include <semaphore.h> #include <semaphore.h>
typedef sem_t Semaphore; typedef sem_t Semaphore;
#define SEMAPHORE_WAIT(sem) \ #define SEMAPHORE_WAIT(sem) \
do { \ do { \
while(sem_wait(&sem) != 0); \ while(sem_wait(&sem) != 0); \
int semValue; \ int semValue; \
sem_getvalue(&sem, &semValue); \ sem_getvalue(&sem, &semValue); \
if(semValue < 1) \ if(semValue < 1) \
break; \ break; \
} while(true); } while(true);
#define SEMAPHORE_SIGNAL(sem) \ #define SEMAPHORE_SIGNAL(sem) \
sem_post(&sem); sem_post(&sem);
#define SEMAPHORE_INIT(sem, shared, value) \ #define SEMAPHORE_INIT(sem, shared, value) \
sem_init(&sem, shared, value); sem_init(&sem, shared, value);
#endif #endif
class IVideo class IVideo
{ {
public: public:
virtual ~IVideo () {} virtual ~IVideo () {}
virtual EDisplayType GetDisplayType () = 0; virtual EDisplayType GetDisplayType () = 0;
virtual void SetWindowedScale (float scale) = 0; virtual void SetWindowedScale (float scale) = 0;
virtual DFrameBuffer *CreateFrameBuffer (int width, int height, bool fs, DFrameBuffer *old) = 0; virtual DFrameBuffer *CreateFrameBuffer (int width, int height, bool fs, DFrameBuffer *old) = 0;
virtual void StartModeIterator (int bits, bool fs) = 0; virtual void StartModeIterator (int bits, bool fs) = 0;
virtual bool NextMode (int *width, int *height, bool *letterbox) = 0; virtual bool NextMode (int *width, int *height, bool *letterbox) = 0;
virtual bool SetResolution (int width, int height, int bits); virtual bool SetResolution (int width, int height, int bits);
virtual void DumpAdapters(); virtual void DumpAdapters();
}; };
void I_InitGraphics (); void I_InitGraphics ();
void I_ShutdownGraphics (); void I_ShutdownGraphics ();
void I_CreateRenderer(); void I_CreateRenderer();
extern Semaphore FPSLimitSemaphore; extern Semaphore FPSLimitSemaphore;
void I_SetFPSLimit(int limit); void I_SetFPSLimit(int limit);
extern IVideo *Video; extern IVideo *Video;
#endif // __HARDWARE_H__ #endif // __HARDWARE_H__

View File

@ -1,154 +1,154 @@
#include "i_cd.h" #include "i_cd.h"
//========================================================================== //==========================================================================
// //
// CD_Init // CD_Init
// //
//========================================================================== //==========================================================================
bool CD_Init () bool CD_Init ()
{ {
return false; return false;
} }
bool CD_Init (int device) bool CD_Init (int device)
{ {
return false; return false;
} }
//========================================================================== //==========================================================================
// //
// CD_InitID // CD_InitID
// //
//========================================================================== //==========================================================================
bool CD_InitID (unsigned int id, int guess) bool CD_InitID (unsigned int id, int guess)
{ {
return false; return false;
} }
//========================================================================== //==========================================================================
// //
// CD_Close // CD_Close
// //
//========================================================================== //==========================================================================
void CD_Close () void CD_Close ()
{ {
} }
//========================================================================== //==========================================================================
// //
// CD_Eject // CD_Eject
// //
//========================================================================== //==========================================================================
void CD_Eject () void CD_Eject ()
{ {
} }
//========================================================================== //==========================================================================
// //
// CD_UnEject // CD_UnEject
// //
//========================================================================== //==========================================================================
bool CD_UnEject () bool CD_UnEject ()
{ {
return false; return false;
} }
//========================================================================== //==========================================================================
// //
// CD_Stop // CD_Stop
// //
//========================================================================== //==========================================================================
void CD_Stop () void CD_Stop ()
{ {
} }
//========================================================================== //==========================================================================
// //
// CD_Play // CD_Play
// //
//========================================================================== //==========================================================================
bool CD_Play (int track, bool looping) bool CD_Play (int track, bool looping)
{ {
return false; return false;
} }
//========================================================================== //==========================================================================
// //
// CD_PlayNoWait // CD_PlayNoWait
// //
//========================================================================== //==========================================================================
void CD_PlayNoWait (int track, bool looping) void CD_PlayNoWait (int track, bool looping)
{ {
} }
//========================================================================== //==========================================================================
// //
// CD_PlayCD // CD_PlayCD
// //
//========================================================================== //==========================================================================
bool CD_PlayCD (bool looping) bool CD_PlayCD (bool looping)
{ {
return false; return false;
} }
//========================================================================== //==========================================================================
// //
// CD_PlayCDNoWait // CD_PlayCDNoWait
// //
//========================================================================== //==========================================================================
void CD_PlayCDNoWait (bool looping) void CD_PlayCDNoWait (bool looping)
{ {
} }
//========================================================================== //==========================================================================
// //
// CD_Pause // CD_Pause
// //
//========================================================================== //==========================================================================
void CD_Pause () void CD_Pause ()
{ {
} }
//========================================================================== //==========================================================================
// //
// CD_Resume // CD_Resume
// //
//========================================================================== //==========================================================================
bool CD_Resume () bool CD_Resume ()
{ {
return false; return false;
} }
//========================================================================== //==========================================================================
// //
// CD_GetMode // CD_GetMode
// //
//========================================================================== //==========================================================================
ECDModes CD_GetMode () ECDModes CD_GetMode ()
{ {
return CDMode_Unknown; return CDMode_Unknown;
} }
//========================================================================== //==========================================================================
// //
// CD_CheckTrack // CD_CheckTrack
// //
//========================================================================== //==========================================================================
bool CD_CheckTrack (int track) bool CD_CheckTrack (int track)
{ {
return false; return false;
} }

View File

@ -1,10 +1,10 @@
#ifndef __I_INPUT_H__ #ifndef __I_INPUT_H__
#define __I_INPUT_H__ #define __I_INPUT_H__
void I_PutInClipboard (const char *str); void I_PutInClipboard (const char *str);
FString I_GetFromClipboard (bool use_primary_selection); FString I_GetFromClipboard (bool use_primary_selection);
void I_SetMouseCapture(); void I_SetMouseCapture();
void I_ReleaseMouseCapture(); void I_ReleaseMouseCapture();
#endif #endif

View File

@ -1,7 +1,7 @@
#include "i_movie.h" #include "i_movie.h"
int I_PlayMovie (const char *movie) int I_PlayMovie (const char *movie)
{ {
return MOVIE_Failed; return MOVIE_Failed;
} }

View File

@ -34,6 +34,10 @@
#include <sys/stat.h> #include <sys/stat.h>
#ifdef __APPLE__
#include <CoreServices/CoreServices.h>
#endif // __APPLE__
#include "doomerrors.h" #include "doomerrors.h"
#include "d_main.h" #include "d_main.h"
#include "zstring.h" #include "zstring.h"
@ -167,9 +171,20 @@ TArray<FString> I_GetSteamPath()
// we need to figure out on an app-by-app basis where the game is installed. // we need to figure out on an app-by-app basis where the game is installed.
// To do so, we read the virtual registry. // To do so, we read the virtual registry.
#ifdef __APPLE__ #ifdef __APPLE__
FString OSX_FindApplicationSupport(); FString appSupportPath;
FString regPath = OSX_FindApplicationSupport() + "/Steam/config/config.vdf"; {
char cpath[PATH_MAX];
FSRef folder;
if (noErr == FSFindFolder(kUserDomain, kApplicationSupportFolderType, kCreateFolder, &folder) &&
noErr == FSRefMakePath(&folder, (UInt8*)cpath, PATH_MAX))
{
appSupportPath = cpath;
}
}
FString regPath = appSupportPath + "/Steam/config/config.vdf";
try try
{ {
SteamInstallFolders = ParseSteamRegistry(regPath); SteamInstallFolders = ParseSteamRegistry(regPath);
@ -180,7 +195,7 @@ TArray<FString> I_GetSteamPath()
return result; return result;
} }
SteamInstallFolders.Push(OSX_FindApplicationSupport() + "/Steam/SteamApps/common"); SteamInstallFolders.Push(appSupportPath + "/Steam/SteamApps/common");
#else #else
char* home = getenv("HOME"); char* home = getenv("HOME");
if(home != NULL && *home != '\0') if(home != NULL && *home != '\0')

View File

@ -41,7 +41,6 @@
#include "doomerrors.h" #include "doomerrors.h"
#include <math.h> #include <math.h>
#include "SDL.h"
#include "doomtype.h" #include "doomtype.h"
#include "doomstat.h" #include "doomstat.h"
#include "version.h" #include "version.h"

View File

@ -1,170 +1,170 @@
// Emacs style mode select -*- C++ -*- // Emacs style mode select -*- C++ -*-
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// //
// $Id:$ // $Id:$
// //
// Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1993-1996 by id Software, Inc.
// //
// This source is available for distribution and/or modification // This source is available for distribution and/or modification
// only under the terms of the DOOM Source Code License as // only under the terms of the DOOM Source Code License as
// published by id Software. All rights reserved. // published by id Software. All rights reserved.
// //
// The source is distributed in the hope that it will be useful, // The source is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License // FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License
// for more details. // for more details.
// //
// DESCRIPTION: // DESCRIPTION:
// System specific interface stuff. // System specific interface stuff.
// //
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
#ifndef __I_SYSTEM__ #ifndef __I_SYSTEM__
#define __I_SYSTEM__ #define __I_SYSTEM__
#include <dirent.h> #include <dirent.h>
#include <ctype.h> #include <ctype.h>
#include "doomtype.h" #include "doomtype.h"
struct ticcmd_t; struct ticcmd_t;
struct WadStuff; struct WadStuff;
#ifndef SHARE_DIR #ifndef SHARE_DIR
#define SHARE_DIR "/usr/local/share/" #define SHARE_DIR "/usr/local/share/"
#endif #endif
// Index values into the LanguageIDs array // Index values into the LanguageIDs array
enum enum
{ {
LANGIDX_UserPreferred, LANGIDX_UserPreferred,
LANGIDX_UserDefault, LANGIDX_UserDefault,
LANGIDX_SysPreferred, LANGIDX_SysPreferred,
LANGIDX_SysDefault LANGIDX_SysDefault
}; };
extern DWORD LanguageIDs[4]; extern DWORD LanguageIDs[4];
extern void SetLanguageIDs (); extern void SetLanguageIDs ();
// Called by DoomMain. // Called by DoomMain.
void I_Init (void); void I_Init (void);
// Called by D_DoomLoop, // Called by D_DoomLoop,
// returns current time in tics. // returns current time in tics.
extern int (*I_GetTime) (bool saveMS); extern int (*I_GetTime) (bool saveMS);
// like I_GetTime, except it waits for a new tic before returning // like I_GetTime, except it waits for a new tic before returning
extern int (*I_WaitForTic) (int); extern int (*I_WaitForTic) (int);
// Freezes tic counting temporarily. While frozen, calls to I_GetTime() // Freezes tic counting temporarily. While frozen, calls to I_GetTime()
// will always return the same value. This does not affect I_MSTime(). // will always return the same value. This does not affect I_MSTime().
// You must also not call I_WaitForTic() while freezing time, since the // You must also not call I_WaitForTic() while freezing time, since the
// tic will never arrive (unless it's the current one). // tic will never arrive (unless it's the current one).
extern void (*I_FreezeTime) (bool frozen); extern void (*I_FreezeTime) (bool frozen);
fixed_t I_GetTimeFrac (uint32 *ms); fixed_t I_GetTimeFrac (uint32 *ms);
// Return a seed value for the RNG. // Return a seed value for the RNG.
unsigned int I_MakeRNGSeed(); unsigned int I_MakeRNGSeed();
// //
// Called by D_DoomLoop, // Called by D_DoomLoop,
// called before processing any tics in a frame // called before processing any tics in a frame
// (just after displaying a frame). // (just after displaying a frame).
// Time consuming syncronous operations // Time consuming syncronous operations
// are performed here (joystick reading). // are performed here (joystick reading).
// Can call D_PostEvent. // Can call D_PostEvent.
// //
void I_StartFrame (void); void I_StartFrame (void);
// //
// Called by D_DoomLoop, // Called by D_DoomLoop,
// called before processing each tic in a frame. // called before processing each tic in a frame.
// Quick syncronous operations are performed here. // Quick syncronous operations are performed here.
// Can call D_PostEvent. // Can call D_PostEvent.
void I_StartTic (void); void I_StartTic (void);
// Asynchronous interrupt functions should maintain private queues // Asynchronous interrupt functions should maintain private queues
// that are read by the synchronous functions // that are read by the synchronous functions
// to be converted into events. // to be converted into events.
// Either returns a null ticcmd, // Either returns a null ticcmd,
// or calls a loadable driver to build it. // or calls a loadable driver to build it.
// This ticcmd will then be modified by the gameloop // This ticcmd will then be modified by the gameloop
// for normal input. // for normal input.
ticcmd_t *I_BaseTiccmd (void); ticcmd_t *I_BaseTiccmd (void);
// Called by M_Responder when quit is selected. // Called by M_Responder when quit is selected.
// Clean exit, displays sell blurb. // Clean exit, displays sell blurb.
void I_Quit (void); void I_Quit (void);
void I_Tactile (int on, int off, int total); void I_Tactile (int on, int off, int total);
void STACK_ARGS I_Error (const char *error, ...) GCCPRINTF(1,2); void STACK_ARGS I_Error (const char *error, ...) GCCPRINTF(1,2);
void STACK_ARGS I_FatalError (const char *error, ...) GCCPRINTF(1,2); void STACK_ARGS I_FatalError (const char *error, ...) GCCPRINTF(1,2);
void addterm (void (*func)(void), const char *name); void addterm (void (*func)(void), const char *name);
#define atterm(t) addterm (t, #t) #define atterm(t) addterm (t, #t)
void popterm (); void popterm ();
// Print a console string // Print a console string
void I_PrintStr (const char *str); void I_PrintStr (const char *str);
// Set the title string of the startup window // Set the title string of the startup window
void I_SetIWADInfo (); void I_SetIWADInfo ();
// Pick from multiple IWADs to use // Pick from multiple IWADs to use
int I_PickIWad (WadStuff *wads, int numwads, bool queryiwad, int defaultiwad); int I_PickIWad (WadStuff *wads, int numwads, bool queryiwad, int defaultiwad);
// [RH] Checks the registry for Steam's install path, so we can scan its // [RH] Checks the registry for Steam's install path, so we can scan its
// directories for IWADs if the user purchased any through Steam. // directories for IWADs if the user purchased any through Steam.
TArray<FString> I_GetSteamPath(); TArray<FString> I_GetSteamPath();
// The ini could not be saved at exit // The ini could not be saved at exit
bool I_WriteIniFailed (); bool I_WriteIniFailed ();
// [RH] Returns millisecond-accurate time // [RH] Returns millisecond-accurate time
unsigned int I_MSTime (void); unsigned int I_MSTime (void);
unsigned int I_FPSTime(); unsigned int I_FPSTime();
class FTexture; class FTexture;
bool I_SetCursor(FTexture *); bool I_SetCursor(FTexture *);
// Directory searching routines // Directory searching routines
struct findstate_t struct findstate_t
{ {
int count; int count;
struct dirent **namelist; struct dirent **namelist;
int current; int current;
}; };
void *I_FindFirst (const char *filespec, findstate_t *fileinfo); void *I_FindFirst (const char *filespec, findstate_t *fileinfo);
int I_FindNext (void *handle, findstate_t *fileinfo); int I_FindNext (void *handle, findstate_t *fileinfo);
int I_FindClose (void *handle); int I_FindClose (void *handle);
int I_FindAttr (findstate_t *fileinfo); int I_FindAttr (findstate_t *fileinfo);
#define I_FindName(a) ((a)->namelist[(a)->current]->d_name) #define I_FindName(a) ((a)->namelist[(a)->current]->d_name)
#define FA_RDONLY 1 #define FA_RDONLY 1
#define FA_HIDDEN 2 #define FA_HIDDEN 2
#define FA_SYSTEM 4 #define FA_SYSTEM 4
#define FA_DIREC 8 #define FA_DIREC 8
#define FA_ARCH 16 #define FA_ARCH 16
static inline char *strlwr(char *str) static inline char *strlwr(char *str)
{ {
char *ptr = str; char *ptr = str;
while(*ptr) while(*ptr)
{ {
*ptr = tolower(*ptr); *ptr = tolower(*ptr);
++ptr; ++ptr;
} }
return str; return str;
} }
#endif #endif

6
src/posix/readme.md Normal file
View File

@ -0,0 +1,6 @@
This directory contains files required to support POSIX-compatible OSes, like GNU/Linux, OS X or BSD.
Common files are placed in this directory directly.
SDL backend files are in `sdl` subdirectory.
Native OS X backend files are in `cocoa` subdirectory.
Shared files for both OS X backends are in `osx` subdirectory.

View File

@ -1,429 +1,429 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <unistd.h> #include <unistd.h>
#include <sys/types.h> #include <sys/types.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <sys/wait.h> #include <sys/wait.h>
#include <sys/param.h> #include <sys/param.h>
#include <sys/ucontext.h> #include <sys/ucontext.h>
#include <string.h> #include <string.h>
#include <errno.h> #include <errno.h>
#include <limits.h> #include <limits.h>
#ifdef __linux__ #ifdef __linux__
#include <sys/prctl.h> #include <sys/prctl.h>
#ifndef PR_SET_PTRACER #ifndef PR_SET_PTRACER
#define PR_SET_PTRACER 0x59616d61 #define PR_SET_PTRACER 0x59616d61
#endif #endif
#elif defined (__APPLE__) #elif defined (__APPLE__)
#include <signal.h> #include <signal.h>
#endif #endif
static const char crash_switch[] = "--cc-handle-crash"; static const char crash_switch[] = "--cc-handle-crash";
static const char fatal_err[] = "\n\n*** Fatal Error ***\n"; static const char fatal_err[] = "\n\n*** Fatal Error ***\n";
static const char pipe_err[] = "!!! Failed to create pipe\n"; static const char pipe_err[] = "!!! Failed to create pipe\n";
static const char fork_err[] = "!!! Failed to fork debug process\n"; static const char fork_err[] = "!!! Failed to fork debug process\n";
static const char exec_err[] = "!!! Failed to exec debug process\n"; static const char exec_err[] = "!!! Failed to exec debug process\n";
static char argv0[PATH_MAX]; static char argv0[PATH_MAX];
static char altstack[SIGSTKSZ]; static char altstack[SIGSTKSZ];
static struct { static struct {
int signum; int signum;
pid_t pid; pid_t pid;
int has_siginfo; int has_siginfo;
siginfo_t siginfo; siginfo_t siginfo;
char buf[1024]; char buf[1024];
} crash_info; } crash_info;
static const struct { static const struct {
const char *name; const char *name;
int signum; int signum;
} signals[] = { } signals[] = {
{ "Segmentation fault", SIGSEGV }, { "Segmentation fault", SIGSEGV },
{ "Illegal instruction", SIGILL }, { "Illegal instruction", SIGILL },
{ "FPU exception", SIGFPE }, { "FPU exception", SIGFPE },
{ "System BUS error", SIGBUS }, { "System BUS error", SIGBUS },
{ NULL, 0 } { NULL, 0 }
}; };
static const struct { static const struct {
int code; int code;
const char *name; const char *name;
} sigill_codes[] = { } sigill_codes[] = {
#ifndef __FreeBSD__ #ifndef __FreeBSD__
{ ILL_ILLOPC, "Illegal opcode" }, { ILL_ILLOPC, "Illegal opcode" },
{ ILL_ILLOPN, "Illegal operand" }, { ILL_ILLOPN, "Illegal operand" },
{ ILL_ILLADR, "Illegal addressing mode" }, { ILL_ILLADR, "Illegal addressing mode" },
{ ILL_ILLTRP, "Illegal trap" }, { ILL_ILLTRP, "Illegal trap" },
{ ILL_PRVOPC, "Privileged opcode" }, { ILL_PRVOPC, "Privileged opcode" },
{ ILL_PRVREG, "Privileged register" }, { ILL_PRVREG, "Privileged register" },
{ ILL_COPROC, "Coprocessor error" }, { ILL_COPROC, "Coprocessor error" },
{ ILL_BADSTK, "Internal stack error" }, { ILL_BADSTK, "Internal stack error" },
#endif #endif
{ 0, NULL } { 0, NULL }
}; };
static const struct { static const struct {
int code; int code;
const char *name; const char *name;
} sigfpe_codes[] = { } sigfpe_codes[] = {
{ FPE_INTDIV, "Integer divide by zero" }, { FPE_INTDIV, "Integer divide by zero" },
{ FPE_INTOVF, "Integer overflow" }, { FPE_INTOVF, "Integer overflow" },
{ FPE_FLTDIV, "Floating point divide by zero" }, { FPE_FLTDIV, "Floating point divide by zero" },
{ FPE_FLTOVF, "Floating point overflow" }, { FPE_FLTOVF, "Floating point overflow" },
{ FPE_FLTUND, "Floating point underflow" }, { FPE_FLTUND, "Floating point underflow" },
{ FPE_FLTRES, "Floating point inexact result" }, { FPE_FLTRES, "Floating point inexact result" },
{ FPE_FLTINV, "Floating point invalid operation" }, { FPE_FLTINV, "Floating point invalid operation" },
{ FPE_FLTSUB, "Subscript out of range" }, { FPE_FLTSUB, "Subscript out of range" },
{ 0, NULL } { 0, NULL }
}; };
static const struct { static const struct {
int code; int code;
const char *name; const char *name;
} sigsegv_codes[] = { } sigsegv_codes[] = {
#ifndef __FreeBSD__ #ifndef __FreeBSD__
{ SEGV_MAPERR, "Address not mapped to object" }, { SEGV_MAPERR, "Address not mapped to object" },
{ SEGV_ACCERR, "Invalid permissions for mapped object" }, { SEGV_ACCERR, "Invalid permissions for mapped object" },
#endif #endif
{ 0, NULL } { 0, NULL }
}; };
static const struct { static const struct {
int code; int code;
const char *name; const char *name;
} sigbus_codes[] = { } sigbus_codes[] = {
#ifndef __FreeBSD__ #ifndef __FreeBSD__
{ BUS_ADRALN, "Invalid address alignment" }, { BUS_ADRALN, "Invalid address alignment" },
{ BUS_ADRERR, "Non-existent physical address" }, { BUS_ADRERR, "Non-existent physical address" },
{ BUS_OBJERR, "Object specific hardware error" }, { BUS_OBJERR, "Object specific hardware error" },
#endif #endif
{ 0, NULL } { 0, NULL }
}; };
static int (*cc_user_info)(char*, char*); static int (*cc_user_info)(char*, char*);
static void gdb_info(pid_t pid) static void gdb_info(pid_t pid)
{ {
char respfile[64]; char respfile[64];
char cmd_buf[128]; char cmd_buf[128];
FILE *f; FILE *f;
int fd; int fd;
/* Create a temp file to put gdb commands into */ /* Create a temp file to put gdb commands into */
strcpy(respfile, "gdb-respfile-XXXXXX"); strcpy(respfile, "gdb-respfile-XXXXXX");
if((fd=mkstemp(respfile)) >= 0 && (f=fdopen(fd, "w")) != NULL) if((fd=mkstemp(respfile)) >= 0 && (f=fdopen(fd, "w")) != NULL)
{ {
fprintf(f, "attach %d\n" fprintf(f, "attach %d\n"
"shell echo \"\"\n" "shell echo \"\"\n"
"shell echo \"* Loaded Libraries\"\n" "shell echo \"* Loaded Libraries\"\n"
"info sharedlibrary\n" "info sharedlibrary\n"
"shell echo \"\"\n" "shell echo \"\"\n"
"shell echo \"* Threads\"\n" "shell echo \"* Threads\"\n"
"info threads\n" "info threads\n"
"shell echo \"\"\n" "shell echo \"\"\n"
"shell echo \"* FPU Status\"\n" "shell echo \"* FPU Status\"\n"
"info float\n" "info float\n"
"shell echo \"\"\n" "shell echo \"\"\n"
"shell echo \"* Registers\"\n" "shell echo \"* Registers\"\n"
"info registers\n" "info registers\n"
"shell echo \"\"\n" "shell echo \"\"\n"
"shell echo \"* Backtrace\"\n" "shell echo \"* Backtrace\"\n"
"thread apply all backtrace full\n" "thread apply all backtrace full\n"
"detach\n" "detach\n"
"quit\n", pid); "quit\n", pid);
fclose(f); fclose(f);
/* Run gdb and print process info. */ /* Run gdb and print process info. */
snprintf(cmd_buf, sizeof(cmd_buf), "gdb --quiet --batch --command=%s", respfile); snprintf(cmd_buf, sizeof(cmd_buf), "gdb --quiet --batch --command=%s", respfile);
printf("Executing: %s\n", cmd_buf); printf("Executing: %s\n", cmd_buf);
fflush(stdout); fflush(stdout);
system(cmd_buf); system(cmd_buf);
/* Clean up */ /* Clean up */
remove(respfile); remove(respfile);
} }
else else
{ {
/* Error creating temp file */ /* Error creating temp file */
if(fd >= 0) if(fd >= 0)
{ {
close(fd); close(fd);
remove(respfile); remove(respfile);
} }
printf("!!! Could not create gdb command file\n"); printf("!!! Could not create gdb command file\n");
} }
fflush(stdout); fflush(stdout);
} }
static void sys_info(void) static void sys_info(void)
{ {
#ifdef __unix__ #ifdef __unix__
system("echo \"System: `uname -a`\""); system("echo \"System: `uname -a`\"");
putchar('\n'); putchar('\n');
fflush(stdout); fflush(stdout);
#endif #endif
} }
static size_t safe_write(int fd, const void *buf, size_t len) static size_t safe_write(int fd, const void *buf, size_t len)
{ {
size_t ret = 0; size_t ret = 0;
while(ret < len) while(ret < len)
{ {
ssize_t rem; ssize_t rem;
if((rem=write(fd, (const char*)buf+ret, len-ret)) == -1) if((rem=write(fd, (const char*)buf+ret, len-ret)) == -1)
{ {
if(errno == EINTR) if(errno == EINTR)
continue; continue;
break; break;
} }
ret += rem; ret += rem;
} }
return ret; return ret;
} }
static void crash_catcher(int signum, siginfo_t *siginfo, void *context) 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; pid_t dbg_pid;
int fd[2]; int fd[2];
/* Make sure the effective uid is the real uid */ /* Make sure the effective uid is the real uid */
if(getuid() != geteuid()) if(getuid() != geteuid())
{ {
raise(signum); raise(signum);
return; return;
} }
safe_write(STDERR_FILENO, fatal_err, sizeof(fatal_err)-1); safe_write(STDERR_FILENO, fatal_err, sizeof(fatal_err)-1);
if(pipe(fd) == -1) if(pipe(fd) == -1)
{ {
safe_write(STDERR_FILENO, pipe_err, sizeof(pipe_err)-1); safe_write(STDERR_FILENO, pipe_err, sizeof(pipe_err)-1);
raise(signum); raise(signum);
return; return;
} }
crash_info.signum = signum; crash_info.signum = signum;
crash_info.pid = getpid(); crash_info.pid = getpid();
crash_info.has_siginfo = !!siginfo; crash_info.has_siginfo = !!siginfo;
if(siginfo) if(siginfo)
crash_info.siginfo = *siginfo; crash_info.siginfo = *siginfo;
if(cc_user_info) if(cc_user_info)
cc_user_info(crash_info.buf, crash_info.buf+sizeof(crash_info.buf)); cc_user_info(crash_info.buf, crash_info.buf+sizeof(crash_info.buf));
/* Fork off to start a crash handler */ /* Fork off to start a crash handler */
switch((dbg_pid=fork())) switch((dbg_pid=fork()))
{ {
/* Error */ /* Error */
case -1: case -1:
safe_write(STDERR_FILENO, fork_err, sizeof(fork_err)-1); safe_write(STDERR_FILENO, fork_err, sizeof(fork_err)-1);
raise(signum); raise(signum);
return; return;
case 0: case 0:
dup2(fd[0], STDIN_FILENO); dup2(fd[0], STDIN_FILENO);
close(fd[0]); close(fd[0]);
close(fd[1]); close(fd[1]);
execl(argv0, argv0, crash_switch, NULL); execl(argv0, argv0, crash_switch, NULL);
safe_write(STDERR_FILENO, exec_err, sizeof(exec_err)-1); safe_write(STDERR_FILENO, exec_err, sizeof(exec_err)-1);
_exit(1); _exit(1);
default: default:
#ifdef __linux__ #ifdef __linux__
prctl(PR_SET_PTRACER, dbg_pid, 0, 0, 0); prctl(PR_SET_PTRACER, dbg_pid, 0, 0, 0);
#endif #endif
safe_write(fd[1], &crash_info, sizeof(crash_info)); safe_write(fd[1], &crash_info, sizeof(crash_info));
close(fd[0]); close(fd[0]);
close(fd[1]); close(fd[1]);
/* Wait; we'll be killed when gdb is done */ /* Wait; we'll be killed when gdb is done */
do { do {
int status; int status;
if(waitpid(dbg_pid, &status, 0) == dbg_pid && if(waitpid(dbg_pid, &status, 0) == dbg_pid &&
(WIFEXITED(status) || WIFSIGNALED(status))) (WIFEXITED(status) || WIFSIGNALED(status)))
{ {
/* The debug process died before it could kill us */ /* The debug process died before it could kill us */
raise(signum); raise(signum);
break; break;
} }
} while(1); } while(1);
} }
} }
static void crash_handler(const char *logfile) static void crash_handler(const char *logfile)
{ {
const char *sigdesc = ""; const char *sigdesc = "";
int i; int i;
if(fread(&crash_info, sizeof(crash_info), 1, stdin) != 1) if(fread(&crash_info, sizeof(crash_info), 1, stdin) != 1)
{ {
fprintf(stderr, "!!! Failed to retrieve info from crashed process\n"); fprintf(stderr, "!!! Failed to retrieve info from crashed process\n");
exit(1); exit(1);
} }
/* Get the signal description */ /* Get the signal description */
for(i = 0;signals[i].name;++i) for(i = 0;signals[i].name;++i)
{ {
if(signals[i].signum == crash_info.signum) if(signals[i].signum == crash_info.signum)
{ {
sigdesc = signals[i].name; sigdesc = signals[i].name;
break; break;
} }
} }
if(crash_info.has_siginfo) if(crash_info.has_siginfo)
{ {
switch(crash_info.signum) switch(crash_info.signum)
{ {
case SIGSEGV: case SIGSEGV:
for(i = 0;sigsegv_codes[i].name;++i) for(i = 0;sigsegv_codes[i].name;++i)
{ {
if(sigsegv_codes[i].code == crash_info.siginfo.si_code) if(sigsegv_codes[i].code == crash_info.siginfo.si_code)
{ {
sigdesc = sigsegv_codes[i].name; sigdesc = sigsegv_codes[i].name;
break; break;
} }
} }
break; break;
case SIGFPE: case SIGFPE:
for(i = 0;sigfpe_codes[i].name;++i) for(i = 0;sigfpe_codes[i].name;++i)
{ {
if(sigfpe_codes[i].code == crash_info.siginfo.si_code) if(sigfpe_codes[i].code == crash_info.siginfo.si_code)
{ {
sigdesc = sigfpe_codes[i].name; sigdesc = sigfpe_codes[i].name;
break; break;
} }
} }
break; break;
case SIGILL: case SIGILL:
for(i = 0;sigill_codes[i].name;++i) for(i = 0;sigill_codes[i].name;++i)
{ {
if(sigill_codes[i].code == crash_info.siginfo.si_code) if(sigill_codes[i].code == crash_info.siginfo.si_code)
{ {
sigdesc = sigill_codes[i].name; sigdesc = sigill_codes[i].name;
break; break;
} }
} }
break; break;
case SIGBUS: case SIGBUS:
for(i = 0;sigbus_codes[i].name;++i) for(i = 0;sigbus_codes[i].name;++i)
{ {
if(sigbus_codes[i].code == crash_info.siginfo.si_code) if(sigbus_codes[i].code == crash_info.siginfo.si_code)
{ {
sigdesc = sigbus_codes[i].name; sigdesc = sigbus_codes[i].name;
break; break;
} }
} }
break; break;
} }
} }
fprintf(stderr, "%s (signal %i)\n", sigdesc, crash_info.signum); fprintf(stderr, "%s (signal %i)\n", sigdesc, crash_info.signum);
if(crash_info.has_siginfo) if(crash_info.has_siginfo)
fprintf(stderr, "Address: %p\n", crash_info.siginfo.si_addr); fprintf(stderr, "Address: %p\n", crash_info.siginfo.si_addr);
fputc('\n', stderr); fputc('\n', stderr);
if(logfile) if(logfile)
{ {
/* Create crash log file and redirect shell output to it */ /* Create crash log file and redirect shell output to it */
if(freopen(logfile, "wa", stdout) != stdout) if(freopen(logfile, "wa", stdout) != stdout)
{ {
fprintf(stderr, "!!! Could not create %s following signal\n", logfile); fprintf(stderr, "!!! Could not create %s following signal\n", logfile);
exit(1); exit(1);
} }
fprintf(stderr, "Generating %s and killing process %d, please wait... ", logfile, crash_info.pid); fprintf(stderr, "Generating %s and killing process %d, please wait... ", logfile, crash_info.pid);
printf("*** Fatal Error ***\n" printf("*** Fatal Error ***\n"
"%s (signal %i)\n", sigdesc, crash_info.signum); "%s (signal %i)\n", sigdesc, crash_info.signum);
if(crash_info.has_siginfo) if(crash_info.has_siginfo)
printf("Address: %p\n", crash_info.siginfo.si_addr); printf("Address: %p\n", crash_info.siginfo.si_addr);
fputc('\n', stdout); fputc('\n', stdout);
fflush(stdout); fflush(stdout);
} }
sys_info(); sys_info();
crash_info.buf[sizeof(crash_info.buf)-1] = '\0'; crash_info.buf[sizeof(crash_info.buf)-1] = '\0';
printf("%s\n", crash_info.buf); printf("%s\n", crash_info.buf);
fflush(stdout); fflush(stdout);
if(crash_info.pid > 0) if(crash_info.pid > 0)
{ {
gdb_info(crash_info.pid); gdb_info(crash_info.pid);
kill(crash_info.pid, SIGKILL); kill(crash_info.pid, SIGKILL);
} }
if(logfile) if(logfile)
{ {
const char *str; const char *str;
char buf[512]; char buf[512];
if((str=getenv("KDE_FULL_SESSION")) && strcmp(str, "true") == 0) if((str=getenv("KDE_FULL_SESSION")) && strcmp(str, "true") == 0)
snprintf(buf, sizeof(buf), "kdialog --title \"Very Fatal Error\" --textbox \"%s\" 800 600", logfile); snprintf(buf, sizeof(buf), "kdialog --title \"Very Fatal Error\" --textbox \"%s\" 800 600", logfile);
else if((str=getenv("GNOME_DESKTOP_SESSION_ID")) && str[0] != '\0') else if((str=getenv("GNOME_DESKTOP_SESSION_ID")) && str[0] != '\0')
snprintf(buf, sizeof(buf), "gxmessage -buttons \"Okay:0\" -geometry 800x600 -title \"Very Fatal Error\" -center -file \"%s\"", logfile); snprintf(buf, sizeof(buf), "gxmessage -buttons \"Okay:0\" -geometry 800x600 -title \"Very Fatal Error\" -center -file \"%s\"", logfile);
else else
snprintf(buf, sizeof(buf), "xmessage -buttons \"Okay:0\" -center -file \"%s\"", logfile); snprintf(buf, sizeof(buf), "xmessage -buttons \"Okay:0\" -center -file \"%s\"", logfile);
system(buf); system(buf);
} }
exit(0); exit(0);
} }
int cc_install_handlers(int argc, char **argv, int num_signals, int *signals, const char *logfile, int (*user_info)(char*, char*)) int cc_install_handlers(int argc, char **argv, int num_signals, int *signals, const char *logfile, int (*user_info)(char*, char*))
{ {
struct sigaction sa; struct sigaction sa;
stack_t altss; stack_t altss;
int retval; int retval;
if(argc == 2 && strcmp(argv[1], crash_switch) == 0) if(argc == 2 && strcmp(argv[1], crash_switch) == 0)
crash_handler(logfile); crash_handler(logfile);
cc_user_info = user_info; cc_user_info = user_info;
if(argv[0][0] == '/') if(argv[0][0] == '/')
snprintf(argv0, sizeof(argv0), "%s", argv[0]); snprintf(argv0, sizeof(argv0), "%s", argv[0]);
else else
{ {
getcwd(argv0, sizeof(argv0)); getcwd(argv0, sizeof(argv0));
retval = strlen(argv0); retval = strlen(argv0);
snprintf(argv0+retval, sizeof(argv0)-retval, "/%s", argv[0]); snprintf(argv0+retval, sizeof(argv0)-retval, "/%s", argv[0]);
} }
/* Set an alternate signal stack so SIGSEGVs caused by stack overflows /* Set an alternate signal stack so SIGSEGVs caused by stack overflows
* still run */ * still run */
altss.ss_sp = altstack; altss.ss_sp = altstack;
altss.ss_flags = 0; altss.ss_flags = 0;
altss.ss_size = sizeof(altstack); altss.ss_size = sizeof(altstack);
sigaltstack(&altss, NULL); sigaltstack(&altss, NULL);
memset(&sa, 0, sizeof(sa)); memset(&sa, 0, sizeof(sa));
sa.sa_sigaction = crash_catcher; sa.sa_sigaction = crash_catcher;
sa.sa_flags = SA_RESETHAND | SA_NODEFER | SA_SIGINFO | SA_ONSTACK; sa.sa_flags = SA_RESETHAND | SA_NODEFER | SA_SIGINFO | SA_ONSTACK;
sigemptyset(&sa.sa_mask); sigemptyset(&sa.sa_mask);
retval = 0; retval = 0;
while(num_signals--) while(num_signals--)
{ {
if((*signals != SIGSEGV && *signals != SIGILL && *signals != SIGFPE && if((*signals != SIGSEGV && *signals != SIGILL && *signals != SIGFPE &&
*signals != SIGBUS) || sigaction(*signals, &sa, NULL) == -1) *signals != SIGBUS) || sigaction(*signals, &sa, NULL) == -1)
{ {
*signals = 0; *signals = 0;
retval = -1; retval = -1;
} }
++signals; ++signals;
} }
return retval; return retval;
} }

View File

@ -1,48 +1,48 @@
// Wraps an SDL mutex object. (A critical section is a Windows synchronization // Wraps an SDL mutex object. (A critical section is a Windows synchronization
// object similar to a mutex but optimized for access by threads belonging to // object similar to a mutex but optimized for access by threads belonging to
// only one process, hence the class name.) // only one process, hence the class name.)
#ifndef CRITSEC_H #ifndef CRITSEC_H
#define CRITSEC_H #define CRITSEC_H
#include "SDL.h" #include "SDL.h"
#include "SDL_thread.h" #include "SDL_thread.h"
#include "i_system.h" #include "i_system.h"
class FCriticalSection class FCriticalSection
{ {
public: public:
FCriticalSection() FCriticalSection()
{ {
CritSec = SDL_CreateMutex(); CritSec = SDL_CreateMutex();
if (CritSec == NULL) if (CritSec == NULL)
{ {
I_FatalError("Failed to create a critical section mutex."); I_FatalError("Failed to create a critical section mutex.");
} }
} }
~FCriticalSection() ~FCriticalSection()
{ {
if (CritSec != NULL) if (CritSec != NULL)
{ {
SDL_DestroyMutex(CritSec); SDL_DestroyMutex(CritSec);
} }
} }
void Enter() void Enter()
{ {
if (SDL_mutexP(CritSec) != 0) if (SDL_mutexP(CritSec) != 0)
{ {
I_FatalError("Failed entering a critical section."); I_FatalError("Failed entering a critical section.");
} }
} }
void Leave() void Leave()
{ {
if (SDL_mutexV(CritSec) != 0) if (SDL_mutexV(CritSec) != 0)
{ {
I_FatalError("Failed to leave a critical section."); I_FatalError("Failed to leave a critical section.");
} }
} }
private: private:
SDL_mutex *CritSec; SDL_mutex *CritSec;
}; };
#endif #endif

61
src/posix/sdl/i_gui.cpp Normal file
View File

@ -0,0 +1,61 @@
// Moved from sdl/i_system.cpp
#include <string.h>
#include <SDL.h>
#include "bitmap.h"
#include "v_palette.h"
#include "textures.h"
bool I_SetCursor(FTexture *cursorpic)
{
static SDL_Cursor *cursor;
static SDL_Surface *cursorSurface;
if (cursorpic != NULL && cursorpic->UseType != FTexture::TEX_Null)
{
// Must be no larger than 32x32.
if (cursorpic->GetWidth() > 32 || cursorpic->GetHeight() > 32)
{
return false;
}
if (cursorSurface == NULL)
cursorSurface = SDL_CreateRGBSurface (0, 32, 32, 32, MAKEARGB(0,255,0,0), MAKEARGB(0,0,255,0), MAKEARGB(0,0,0,255), MAKEARGB(255,0,0,0));
SDL_LockSurface(cursorSurface);
BYTE buffer[32*32*4];
memset(buffer, 0, 32*32*4);
FBitmap bmp(buffer, 32*4, 32, 32);
cursorpic->CopyTrueColorPixels(&bmp, 0, 0);
memcpy(cursorSurface->pixels, bmp.GetPixels(), 32*32*4);
SDL_UnlockSurface(cursorSurface);
if (cursor)
SDL_FreeCursor (cursor);
cursor = SDL_CreateColorCursor (cursorSurface, 0, 0);
SDL_SetCursor (cursor);
}
else
{
if (cursor)
{
SDL_SetCursor (NULL);
SDL_FreeCursor (cursor);
cursor = NULL;
}
if (cursorSurface != NULL)
{
SDL_FreeSurface(cursorSurface);
cursorSurface = NULL;
}
}
return true;
}
void I_SetMainWindowVisible(bool visible)
{
}

514
src/posix/sdl/i_input.cpp Normal file
View File

@ -0,0 +1,514 @@
#include <SDL.h>
#include <ctype.h>
#include "doomtype.h"
#include "c_dispatch.h"
#include "doomdef.h"
#include "doomstat.h"
#include "m_argv.h"
#include "i_input.h"
#include "v_video.h"
#include "d_main.h"
#include "d_event.h"
#include "d_gui.h"
#include "c_console.h"
#include "c_cvars.h"
#include "i_system.h"
#include "dikeys.h"
#include "templates.h"
#include "s_sound.h"
void ScaleWithAspect (int &w, int &h, int Width, int Height);
static void I_CheckGUICapture ();
static void I_CheckNativeMouse ();
bool GUICapture;
static bool NativeMouse = true;
extern int paused;
CVAR (Bool, use_mouse, true, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
CVAR (Bool, m_noprescale, false, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
CVAR (Bool, m_filter, false, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
EXTERN_CVAR (Bool, fullscreen)
extern int WaitingForKey, chatmodeon;
extern constate_e ConsoleState;
static bool DownState[SDL_NUM_SCANCODES];
static const SDL_Keycode DIKToKeySym[256] =
{
0, SDLK_ESCAPE, SDLK_1, SDLK_2, SDLK_3, SDLK_4, SDLK_5, SDLK_6,
SDLK_7, SDLK_8, SDLK_9, SDLK_0,SDLK_MINUS, SDLK_EQUALS, SDLK_BACKSPACE, SDLK_TAB,
SDLK_q, SDLK_w, SDLK_e, SDLK_r, SDLK_t, SDLK_y, SDLK_u, SDLK_i,
SDLK_o, SDLK_p, SDLK_LEFTBRACKET, SDLK_RIGHTBRACKET, SDLK_RETURN, SDLK_LCTRL, SDLK_a, SDLK_s,
SDLK_d, SDLK_f, SDLK_g, SDLK_h, SDLK_j, SDLK_k, SDLK_l, SDLK_SEMICOLON,
SDLK_QUOTE, SDLK_BACKQUOTE, SDLK_LSHIFT, SDLK_BACKSLASH, SDLK_z, SDLK_x, SDLK_c, SDLK_v,
SDLK_b, SDLK_n, SDLK_m, SDLK_COMMA, SDLK_PERIOD, SDLK_SLASH, SDLK_RSHIFT, SDLK_KP_MULTIPLY,
SDLK_LALT, SDLK_SPACE, SDLK_CAPSLOCK, SDLK_F1, SDLK_F2, SDLK_F3, SDLK_F4, SDLK_F5,
SDLK_F6, SDLK_F7, SDLK_F8, SDLK_F9, SDLK_F10, SDLK_NUMLOCKCLEAR, SDLK_SCROLLLOCK, SDLK_KP_7,
SDLK_KP_8, SDLK_KP_9, SDLK_KP_MINUS, SDLK_KP_4, SDLK_KP_5, SDLK_KP_6, SDLK_KP_PLUS, SDLK_KP_1,
SDLK_KP_2, SDLK_KP_3, SDLK_KP_0, SDLK_KP_PERIOD, 0, 0, 0, SDLK_F11,
SDLK_F12, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, SDLK_F13, SDLK_F14, SDLK_F15, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, SDLK_KP_EQUALS, 0, 0,
0, SDLK_AT, SDLK_COLON, 0, 0, 0, 0, 0,
0, 0, 0, 0, SDLK_KP_ENTER, SDLK_RCTRL, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, SDLK_KP_COMMA, 0, SDLK_KP_DIVIDE, 0, SDLK_SYSREQ,
SDLK_RALT, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, SDLK_PAUSE, 0, SDLK_HOME,
SDLK_UP, SDLK_PAGEUP, 0, SDLK_LEFT, 0, SDLK_RIGHT, 0, SDLK_END,
SDLK_DOWN, SDLK_PAGEDOWN, SDLK_INSERT, SDLK_DELETE, 0, 0, 0, 0,
0, 0, 0, SDLK_LGUI, SDLK_RGUI, SDLK_MENU, SDLK_POWER, SDLK_SLEEP,
0, 0, 0, 0, 0, SDLK_AC_SEARCH, SDLK_AC_BOOKMARKS, SDLK_AC_REFRESH,
SDLK_AC_STOP, SDLK_AC_FORWARD, SDLK_AC_BACK, SDLK_COMPUTER, SDLK_MAIL, SDLK_MEDIASELECT, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0
};
static const SDL_Scancode DIKToKeyScan[256] =
{
SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_ESCAPE, SDL_SCANCODE_1, SDL_SCANCODE_2, SDL_SCANCODE_3, SDL_SCANCODE_4, SDL_SCANCODE_5, SDL_SCANCODE_6,
SDL_SCANCODE_7, SDL_SCANCODE_8, SDL_SCANCODE_9, SDL_SCANCODE_0 ,SDL_SCANCODE_MINUS, SDL_SCANCODE_EQUALS, SDL_SCANCODE_BACKSPACE, SDL_SCANCODE_TAB,
SDL_SCANCODE_Q, SDL_SCANCODE_W, SDL_SCANCODE_E, SDL_SCANCODE_R, SDL_SCANCODE_T, SDL_SCANCODE_Y, SDL_SCANCODE_U, SDL_SCANCODE_I,
SDL_SCANCODE_O, SDL_SCANCODE_P, SDL_SCANCODE_LEFTBRACKET, SDL_SCANCODE_RIGHTBRACKET, SDL_SCANCODE_RETURN, SDL_SCANCODE_LCTRL, SDL_SCANCODE_A, SDL_SCANCODE_S,
SDL_SCANCODE_D, SDL_SCANCODE_F, SDL_SCANCODE_G, SDL_SCANCODE_H, SDL_SCANCODE_J, SDL_SCANCODE_K, SDL_SCANCODE_L, SDL_SCANCODE_SEMICOLON,
SDL_SCANCODE_APOSTROPHE, SDL_SCANCODE_GRAVE, SDL_SCANCODE_LSHIFT, SDL_SCANCODE_BACKSLASH, SDL_SCANCODE_Z, SDL_SCANCODE_X, SDL_SCANCODE_C, SDL_SCANCODE_V,
SDL_SCANCODE_B, SDL_SCANCODE_N, SDL_SCANCODE_M, SDL_SCANCODE_COMMA, SDL_SCANCODE_PERIOD, SDL_SCANCODE_SLASH, SDL_SCANCODE_RSHIFT, SDL_SCANCODE_KP_MULTIPLY,
SDL_SCANCODE_LALT, SDL_SCANCODE_SPACE, SDL_SCANCODE_CAPSLOCK, SDL_SCANCODE_F1, SDL_SCANCODE_F2, SDL_SCANCODE_F3, SDL_SCANCODE_F4, SDL_SCANCODE_F5,
SDL_SCANCODE_F6, SDL_SCANCODE_F7, SDL_SCANCODE_F8, SDL_SCANCODE_F9, SDL_SCANCODE_F10, SDL_SCANCODE_NUMLOCKCLEAR, SDL_SCANCODE_SCROLLLOCK, SDL_SCANCODE_KP_7,
SDL_SCANCODE_KP_8, SDL_SCANCODE_KP_9, SDL_SCANCODE_KP_MINUS, SDL_SCANCODE_KP_4, SDL_SCANCODE_KP_5, SDL_SCANCODE_KP_6, SDL_SCANCODE_KP_PLUS, SDL_SCANCODE_KP_1,
SDL_SCANCODE_KP_2, SDL_SCANCODE_KP_3, SDL_SCANCODE_KP_0, SDL_SCANCODE_KP_PERIOD, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_F11,
SDL_SCANCODE_F12, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN,
SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_F13, SDL_SCANCODE_F14, SDL_SCANCODE_F15, SDL_SCANCODE_UNKNOWN,
SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN,
SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN,
SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN,
SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN,
SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_KP_EQUALS, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN,
SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN,
SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_KP_ENTER, SDL_SCANCODE_RCTRL, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN,
SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN,
SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN,
SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_KP_COMMA, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_KP_DIVIDE, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_SYSREQ,
SDL_SCANCODE_RALT, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN,
SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_PAUSE, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_HOME,
SDL_SCANCODE_UP, SDL_SCANCODE_PAGEUP, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_LEFT, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_RIGHT, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_END,
SDL_SCANCODE_DOWN, SDL_SCANCODE_PAGEDOWN, SDL_SCANCODE_INSERT, SDL_SCANCODE_DELETE, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN,
SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_LGUI, SDL_SCANCODE_RGUI, SDL_SCANCODE_MENU, SDL_SCANCODE_POWER, SDL_SCANCODE_SLEEP,
SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_AC_SEARCH, SDL_SCANCODE_AC_BOOKMARKS, SDL_SCANCODE_AC_REFRESH,
SDL_SCANCODE_AC_STOP, SDL_SCANCODE_AC_FORWARD, SDL_SCANCODE_AC_BACK, SDL_SCANCODE_COMPUTER, SDL_SCANCODE_MAIL, SDL_SCANCODE_MEDIASELECT, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN,
SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN,
SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN
};
static TMap<SDL_Keycode, BYTE> InitKeySymMap ()
{
TMap<SDL_Keycode, BYTE> KeySymToDIK;
for (int i = 0; i < 256; ++i)
{
KeySymToDIK[DIKToKeySym[i]] = i;
}
KeySymToDIK[0] = 0;
KeySymToDIK[SDLK_RSHIFT] = DIK_LSHIFT;
KeySymToDIK[SDLK_RCTRL] = DIK_LCONTROL;
KeySymToDIK[SDLK_RALT] = DIK_LMENU;
// Depending on your Linux flavor, you may get SDLK_PRINT or SDLK_SYSREQ
KeySymToDIK[SDLK_PRINTSCREEN] = DIK_SYSRQ;
return KeySymToDIK;
}
static const TMap<SDL_Keycode, BYTE> KeySymToDIK(InitKeySymMap());
static TMap<SDL_Scancode, BYTE> InitKeyScanMap ()
{
TMap<SDL_Scancode, BYTE> KeyScanToDIK;
for (int i = 0; i < 256; ++i)
{
KeyScanToDIK[DIKToKeyScan[i]] = i;
}
return KeyScanToDIK;
}
static const TMap<SDL_Scancode, BYTE> KeyScanToDIK(InitKeyScanMap());
static void I_CheckGUICapture ()
{
bool wantCapt;
if (menuactive == MENU_Off)
{
wantCapt = ConsoleState == c_down || ConsoleState == c_falling || chatmodeon;
}
else
{
wantCapt = (menuactive == MENU_On || menuactive == MENU_OnNoPause);
}
if (wantCapt != GUICapture)
{
GUICapture = wantCapt;
if (wantCapt)
{
memset (DownState, 0, sizeof(DownState));
}
}
}
void I_SetMouseCapture()
{
// Clear out any mouse movement.
SDL_GetRelativeMouseState (NULL, NULL);
SDL_SetRelativeMouseMode (SDL_TRUE);
}
void I_ReleaseMouseCapture()
{
SDL_SetRelativeMouseMode (SDL_FALSE);
}
static void PostMouseMove (int x, int y)
{
static int lastx = 0, lasty = 0;
event_t ev = { 0,0,0,0,0,0,0 };
if (m_filter)
{
ev.x = (x + lastx) / 2;
ev.y = (y + lasty) / 2;
}
else
{
ev.x = x;
ev.y = y;
}
lastx = x;
lasty = y;
if (ev.x | ev.y)
{
ev.type = EV_Mouse;
D_PostEvent (&ev);
}
}
static void MouseRead ()
{
int x, y;
if (NativeMouse)
{
return;
}
SDL_GetRelativeMouseState (&x, &y);
if (!m_noprescale)
{
x *= 3;
y *= 2;
}
if (x | y)
{
PostMouseMove (x, -y);
}
}
CUSTOM_CVAR(Int, mouse_capturemode, 1, CVAR_GLOBALCONFIG|CVAR_ARCHIVE)
{
if (self < 0) self = 0;
else if (self > 2) self = 2;
}
static bool inGame()
{
switch (mouse_capturemode)
{
default:
case 0:
return gamestate == GS_LEVEL;
case 1:
return gamestate == GS_LEVEL || gamestate == GS_INTERMISSION || gamestate == GS_FINALE;
case 2:
return true;
}
}
static void I_CheckNativeMouse ()
{
bool focus = SDL_GetKeyboardFocus() != NULL;
bool fs = screen->IsFullscreen();
bool wantNative = !focus || (!use_mouse || GUICapture || paused || demoplayback || !inGame());
if (wantNative != NativeMouse)
{
NativeMouse = wantNative;
SDL_ShowCursor (wantNative);
if (wantNative)
I_ReleaseMouseCapture ();
else
I_SetMouseCapture ();
}
}
void MessagePump (const SDL_Event &sev)
{
static int lastx = 0, lasty = 0;
int x, y;
event_t event = { 0,0,0,0,0,0,0 };
switch (sev.type)
{
case SDL_QUIT:
exit (0);
case SDL_WINDOWEVENT:
switch (sev.window.event)
{
case SDL_WINDOWEVENT_FOCUS_GAINED:
case SDL_WINDOWEVENT_FOCUS_LOST:
S_SetSoundPaused(sev.window.event == SDL_WINDOWEVENT_FOCUS_GAINED);
break;
}
break;
case SDL_MOUSEBUTTONDOWN:
case SDL_MOUSEBUTTONUP:
case SDL_MOUSEMOTION:
if (!GUICapture || sev.button.button == 4 || sev.button.button == 5)
{
if(sev.type != SDL_MOUSEMOTION)
{
event.type = sev.type == SDL_MOUSEBUTTONDOWN ? EV_KeyDown : EV_KeyUp;
/* These button mappings work with my Gentoo system using the
* evdev driver and a Logitech MX510 mouse. Whether or not they
* carry over to other Linux systems, I have no idea, but I sure
* hope so. (Though buttons 11 and 12 are kind of useless, since
* they also trigger buttons 4 and 5.)
*/
switch (sev.button.button)
{
case SDL_BUTTON_LEFT: event.data1 = KEY_MOUSE1; break;
case SDL_BUTTON_MIDDLE: event.data1 = KEY_MOUSE3; break;
case SDL_BUTTON_RIGHT: event.data1 = KEY_MOUSE2; break;
case 8: event.data1 = KEY_MOUSE4; break; // For whatever reason my side mouse buttons are here.
case 9: event.data1 = KEY_MOUSE5; break;
case SDL_BUTTON_X1: event.data1 = KEY_MOUSE6; break; // And these don't exist
case SDL_BUTTON_X2: event.data1 = KEY_MOUSE7; break;
case 6: event.data1 = KEY_MOUSE8; break;
default: printf("SDL mouse button %s %d\n",
sev.type == SDL_MOUSEBUTTONDOWN ? "down" : "up", sev.button.button); break;
}
if (event.data1 != 0)
{
D_PostEvent(&event);
}
}
}
else if (sev.type == SDL_MOUSEMOTION || (sev.button.button >= 1 && sev.button.button <= 3))
{
int x, y;
SDL_GetMouseState (&x, &y);
// Detect if we're doing scaling in the Window and adjust the mouse
// coordinates accordingly. This could be more efficent, but I
// don't think performance is an issue in the menus.
SDL_Window *focus;
if (screen->IsFullscreen() && (focus = SDL_GetMouseFocus ()))
{
int w, h;
SDL_GetWindowSize (focus, &w, &h);
int realw = w, realh = h;
ScaleWithAspect (realw, realh, SCREENWIDTH, SCREENHEIGHT);
if (realw != SCREENWIDTH || realh != SCREENHEIGHT)
{
double xratio = (double)SCREENWIDTH/realw;
double yratio = (double)SCREENHEIGHT/realh;
if (realw < w)
{
x = (x - (w - realw)/2)*xratio;
y *= yratio;
}
else
{
y = (y - (h - realh)/2)*yratio;
x *= xratio;
}
}
}
event.data1 = x;
event.data2 = y;
event.type = EV_GUI_Event;
if(sev.type == SDL_MOUSEMOTION)
event.subtype = EV_GUI_MouseMove;
else
{
event.subtype = sev.type == SDL_MOUSEBUTTONDOWN ? EV_GUI_LButtonDown : EV_GUI_LButtonUp;
event.subtype += (sev.button.button - 1) * 3;
}
D_PostEvent(&event);
}
break;
case SDL_MOUSEWHEEL:
if (GUICapture)
{
event.type = EV_GUI_Event;
event.subtype = sev.wheel.y > 0 ? EV_GUI_WheelUp : EV_GUI_WheelDown;
D_PostEvent (&event);
}
else
{
event.type = EV_KeyDown;
event.data1 = sev.wheel.y > 0 ? KEY_MWHEELUP : KEY_MWHEELDOWN;
D_PostEvent (&event);
event.type = EV_KeyUp;
D_PostEvent (&event);
}
break;
case SDL_KEYDOWN:
case SDL_KEYUP:
if (!GUICapture)
{
event.type = sev.type == SDL_KEYDOWN ? EV_KeyDown : EV_KeyUp;
// Try to look up our key mapped key for conversion to DirectInput.
// If that fails, then we'll do a lookup against the scan code,
// which may not return the right key, but at least the key should
// work in the game.
if (const BYTE *dik = KeySymToDIK.CheckKey (sev.key.keysym.sym))
event.data1 = *dik;
else if (const BYTE *dik = KeyScanToDIK.CheckKey (sev.key.keysym.scancode))
event.data1 = *dik;
if (event.data1)
{
if (sev.key.keysym.sym < 256)
{
event.data2 = sev.key.keysym.sym;
}
D_PostEvent (&event);
}
}
else
{
event.type = EV_GUI_Event;
event.subtype = sev.type == SDL_KEYDOWN ? EV_GUI_KeyDown : EV_GUI_KeyUp;
event.data3 = ((sev.key.keysym.mod & KMOD_SHIFT) ? GKM_SHIFT : 0) |
((sev.key.keysym.mod & KMOD_CTRL) ? GKM_CTRL : 0) |
((sev.key.keysym.mod & KMOD_ALT) ? GKM_ALT : 0);
if (event.subtype == EV_GUI_KeyDown)
{
if (DownState[sev.key.keysym.scancode])
{
event.subtype = EV_GUI_KeyRepeat;
}
DownState[sev.key.keysym.scancode] = 1;
}
else
{
DownState[sev.key.keysym.scancode] = 0;
}
switch (sev.key.keysym.sym)
{
case SDLK_KP_ENTER: event.data1 = GK_RETURN; break;
case SDLK_PAGEUP: event.data1 = GK_PGUP; break;
case SDLK_PAGEDOWN: event.data1 = GK_PGDN; break;
case SDLK_END: event.data1 = GK_END; break;
case SDLK_HOME: event.data1 = GK_HOME; break;
case SDLK_LEFT: event.data1 = GK_LEFT; break;
case SDLK_RIGHT: event.data1 = GK_RIGHT; break;
case SDLK_UP: event.data1 = GK_UP; break;
case SDLK_DOWN: event.data1 = GK_DOWN; break;
case SDLK_DELETE: event.data1 = GK_DEL; break;
case SDLK_ESCAPE: event.data1 = GK_ESCAPE; break;
case SDLK_F1: event.data1 = GK_F1; break;
case SDLK_F2: event.data1 = GK_F2; break;
case SDLK_F3: event.data1 = GK_F3; break;
case SDLK_F4: event.data1 = GK_F4; break;
case SDLK_F5: event.data1 = GK_F5; break;
case SDLK_F6: event.data1 = GK_F6; break;
case SDLK_F7: event.data1 = GK_F7; break;
case SDLK_F8: event.data1 = GK_F8; break;
case SDLK_F9: event.data1 = GK_F9; break;
case SDLK_F10: event.data1 = GK_F10; break;
case SDLK_F11: event.data1 = GK_F11; break;
case SDLK_F12: event.data1 = GK_F12; break;
default:
if (sev.key.keysym.sym < 256)
{
event.data1 = sev.key.keysym.sym;
}
break;
}
if (event.data1 < 128)
{
event.data1 = toupper(event.data1);
D_PostEvent (&event);
}
}
break;
case SDL_TEXTINPUT:
if (GUICapture)
{
event.type = EV_GUI_Event;
event.subtype = EV_GUI_Char;
event.data1 = sev.text.text[0];
D_PostEvent (&event);
}
break;
case SDL_JOYBUTTONDOWN:
case SDL_JOYBUTTONUP:
if (!GUICapture)
{
event.type = sev.type == SDL_JOYBUTTONDOWN ? EV_KeyDown : EV_KeyUp;
event.data1 = KEY_FIRSTJOYBUTTON + sev.jbutton.button;
if(event.data1 != 0)
D_PostEvent(&event);
}
break;
}
}
void I_GetEvent ()
{
SDL_Event sev;
while (SDL_PollEvent (&sev))
{
MessagePump (sev);
}
if (use_mouse)
{
MouseRead ();
}
}
void I_StartTic ()
{
I_CheckGUICapture ();
I_CheckNativeMouse ();
I_GetEvent ();
}
void I_ProcessJoysticks ();
void I_StartFrame ()
{
I_ProcessJoysticks();
}

View File

@ -35,7 +35,7 @@ public:
FString GetName() FString GetName()
{ {
return SDL_JoystickName(DeviceIndex); return SDL_JoystickName(Device);
} }
float GetSensitivity() float GetSensitivity()
{ {

View File

@ -1,378 +1,338 @@
/* /*
** i_main.cpp ** i_main.cpp
** System-specific startup code. Eventually calls D_DoomMain. ** System-specific startup code. Eventually calls D_DoomMain.
** **
**--------------------------------------------------------------------------- **---------------------------------------------------------------------------
** Copyright 1998-2007 Randy Heit ** Copyright 1998-2007 Randy Heit
** All rights reserved. ** All rights reserved.
** **
** Redistribution and use in source and binary forms, with or without ** Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions ** modification, are permitted provided that the following conditions
** are met: ** are met:
** **
** 1. Redistributions of source code must retain the above copyright ** 1. Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer. ** notice, this list of conditions and the following disclaimer.
** 2. Redistributions in binary form must reproduce the above copyright ** 2. Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in the ** notice, this list of conditions and the following disclaimer in the
** documentation and/or other materials provided with the distribution. ** documentation and/or other materials provided with the distribution.
** 3. The name of the author may not be used to endorse or promote products ** 3. The name of the author may not be used to endorse or promote products
** derived from this software without specific prior written permission. ** derived from this software without specific prior written permission.
** **
** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR ** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES ** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. ** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, ** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT ** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
**--------------------------------------------------------------------------- **---------------------------------------------------------------------------
** **
*/ */
// HEADER FILES ------------------------------------------------------------ // HEADER FILES ------------------------------------------------------------
#include <SDL.h> #include <SDL.h>
#include <unistd.h> #include <unistd.h>
#include <stdlib.h> #include <stdlib.h>
#include <signal.h> #include <signal.h>
#include <new> #include <new>
#include <sys/param.h> #include <sys/param.h>
#ifndef NO_GTK #ifndef NO_GTK
#include <gtk/gtk.h> #include <gtk/gtk.h>
#endif #endif
#include <locale.h> #include <locale.h>
#if defined(__MACH__) && !defined(NOASM) #if defined(__MACH__) && !defined(NOASM)
#include <sys/types.h> #include <sys/types.h>
#include <sys/mman.h> #include <sys/mman.h>
#endif #endif
#include "doomerrors.h" #include "doomerrors.h"
#include "m_argv.h" #include "m_argv.h"
#include "d_main.h" #include "d_main.h"
#include "i_system.h" #include "i_system.h"
#include "i_video.h" #include "i_video.h"
#include "c_console.h" #include "c_console.h"
#include "errors.h" #include "errors.h"
#include "version.h" #include "version.h"
#include "w_wad.h" #include "w_wad.h"
#include "g_level.h" #include "g_level.h"
#include "r_state.h" #include "r_state.h"
#include "cmdlib.h" #include "cmdlib.h"
#include "r_utility.h" #include "r_utility.h"
#include "doomstat.h" #include "doomstat.h"
// MACROS ------------------------------------------------------------------ // MACROS ------------------------------------------------------------------
// The maximum number of functions that can be registered with atterm. // The maximum number of functions that can be registered with atterm.
#define MAX_TERMS 64 #define MAX_TERMS 64
// TYPES ------------------------------------------------------------------- // TYPES -------------------------------------------------------------------
// EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES --------------------------------------------
extern "C" int cc_install_handlers(int, char**, int, int*, const char*, int(*)(char*, char*)); extern "C" int cc_install_handlers(int, char**, int, int*, const char*, int(*)(char*, char*));
#ifdef __APPLE__ #ifdef __APPLE__
void Mac_I_FatalError(const char* errortext); void Mac_I_FatalError(const char* errortext);
#endif #endif
// PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ----------------------------------------------
// PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // PRIVATE FUNCTION PROTOTYPES ---------------------------------------------
// EXTERNAL DATA DECLARATIONS ---------------------------------------------- // EXTERNAL DATA DECLARATIONS ----------------------------------------------
#ifdef USE_XCURSOR // PUBLIC DATA DEFINITIONS -------------------------------------------------
extern bool UseXCursor;
#endif #ifndef NO_GTK
bool GtkAvailable;
// PUBLIC DATA DEFINITIONS ------------------------------------------------- #endif
#ifndef NO_GTK // The command line arguments.
bool GtkAvailable; DArgs *Args;
#endif
// PRIVATE DATA DEFINITIONS ------------------------------------------------
// The command line arguments.
DArgs *Args; static void (*TermFuncs[MAX_TERMS]) ();
static const char *TermNames[MAX_TERMS];
// PRIVATE DATA DEFINITIONS ------------------------------------------------ static int NumTerms;
static void (*TermFuncs[MAX_TERMS]) (); // CODE --------------------------------------------------------------------
static const char *TermNames[MAX_TERMS];
static int NumTerms; void addterm (void (*func) (), const char *name)
{
// CODE -------------------------------------------------------------------- // Make sure this function wasn't already registered.
for (int i = 0; i < NumTerms; ++i)
void addterm (void (*func) (), const char *name) {
{ if (TermFuncs[i] == func)
// Make sure this function wasn't already registered. {
for (int i = 0; i < NumTerms; ++i) return;
{ }
if (TermFuncs[i] == func) }
{ if (NumTerms == MAX_TERMS)
return; {
} func ();
} I_FatalError (
if (NumTerms == MAX_TERMS) "Too many exit functions registered.\n"
{ "Increase MAX_TERMS in i_main.cpp");
func (); }
I_FatalError ( TermNames[NumTerms] = name;
"Too many exit functions registered.\n" TermFuncs[NumTerms++] = func;
"Increase MAX_TERMS in i_main.cpp"); }
}
TermNames[NumTerms] = name; void popterm ()
TermFuncs[NumTerms++] = func; {
} if (NumTerms)
NumTerms--;
void popterm () }
{
if (NumTerms) void STACK_ARGS call_terms ()
NumTerms--; {
} while (NumTerms > 0)
{
void STACK_ARGS call_terms () // printf ("term %d - %s\n", NumTerms, TermNames[NumTerms-1]);
{ TermFuncs[--NumTerms] ();
while (NumTerms > 0) }
{ }
// printf ("term %d - %s\n", NumTerms, TermNames[NumTerms-1]);
TermFuncs[--NumTerms] (); static void STACK_ARGS NewFailure ()
} {
} I_FatalError ("Failed to allocate memory from system heap");
}
static void STACK_ARGS NewFailure ()
{ static int DoomSpecificInfo (char *buffer, char *end)
I_FatalError ("Failed to allocate memory from system heap"); {
} const char *arg;
int size = end-buffer-2;
static int DoomSpecificInfo (char *buffer, char *end) int i, p;
{
const char *arg; p = 0;
int size = end-buffer-2; p += snprintf (buffer+p, size-p, GAMENAME" version %s (%s)\n", GetVersionString(), GetGitHash());
int i, p; #ifdef __VERSION__
p += snprintf (buffer+p, size-p, "Compiler version: %s\n", __VERSION__);
p = 0; #endif
p += snprintf (buffer+p, size-p, GAMENAME" version %s (%s)\n", GetVersionString(), GetGitHash()); p += snprintf (buffer+p, size-p, "\nCommand line:");
#ifdef __VERSION__ for (i = 0; i < Args->NumArgs(); ++i)
p += snprintf (buffer+p, size-p, "Compiler version: %s\n", __VERSION__); {
#endif p += snprintf (buffer+p, size-p, " %s", Args->GetArg(i));
p += snprintf (buffer+p, size-p, "\nCommand line:"); }
for (i = 0; i < Args->NumArgs(); ++i) p += snprintf (buffer+p, size-p, "\n");
{
p += snprintf (buffer+p, size-p, " %s", Args->GetArg(i)); for (i = 0; (arg = Wads.GetWadName (i)) != NULL; ++i)
} {
p += snprintf (buffer+p, size-p, "\n"); p += snprintf (buffer+p, size-p, "\nWad %d: %s", i, arg);
}
for (i = 0; (arg = Wads.GetWadName (i)) != NULL; ++i)
{ if (gamestate != GS_LEVEL && gamestate != GS_TITLELEVEL)
p += snprintf (buffer+p, size-p, "\nWad %d: %s", i, arg); {
} p += snprintf (buffer+p, size-p, "\n\nNot in a level.");
}
if (gamestate != GS_LEVEL && gamestate != GS_TITLELEVEL) else
{ {
p += snprintf (buffer+p, size-p, "\n\nNot in a level."); p += snprintf (buffer+p, size-p, "\n\nCurrent map: %s", level.MapName.GetChars());
}
else if (!viewactive)
{ {
p += snprintf (buffer+p, size-p, "\n\nCurrent map: %s", level.MapName.GetChars()); p += snprintf (buffer+p, size-p, "\n\nView not active.");
}
if (!viewactive) else
{ {
p += snprintf (buffer+p, size-p, "\n\nView not active."); p += snprintf (buffer+p, size-p, "\n\nviewx = %d", (int)viewx);
} p += snprintf (buffer+p, size-p, "\nviewy = %d", (int)viewy);
else p += snprintf (buffer+p, size-p, "\nviewz = %d", (int)viewz);
{ p += snprintf (buffer+p, size-p, "\nviewangle = %x", (unsigned int)viewangle);
p += snprintf (buffer+p, size-p, "\n\nviewx = %d", (int)viewx); }
p += snprintf (buffer+p, size-p, "\nviewy = %d", (int)viewy); }
p += snprintf (buffer+p, size-p, "\nviewz = %d", (int)viewz); buffer[p++] = '\n';
p += snprintf (buffer+p, size-p, "\nviewangle = %x", (unsigned int)viewangle); buffer[p++] = '\0';
}
} return p;
buffer[p++] = '\n'; }
buffer[p++] = '\0';
#if defined(__MACH__) && !defined(NOASM)
return p; // NASM won't let us create custom sections for Mach-O. Whether that's a limitation of NASM
} // or of Mach-O, I don't know, but since we're using NASM for the assembly, it doesn't much
// matter.
#if defined(__MACH__) && !defined(NOASM) extern "C"
// NASM won't let us create custom sections for Mach-O. Whether that's a limitation of NASM {
// or of Mach-O, I don't know, but since we're using NASM for the assembly, it doesn't much extern void *rtext_a_start, *rtext_a_end;
// matter. extern void *rtext_tmap_start, *rtext_tmap_end;
extern "C" extern void *rtext_tmap2_start, *rtext_tmap2_end;
{ extern void *rtext_tmap3_start, *rtext_tmap3_end;
extern void *rtext_a_start, *rtext_a_end; };
extern void *rtext_tmap_start, *rtext_tmap_end;
extern void *rtext_tmap2_start, *rtext_tmap2_end; static void unprotect_pages(long pagesize, void *start, void *end)
extern void *rtext_tmap3_start, *rtext_tmap3_end; {
}; char *page = (char *)((intptr_t)start & ~(pagesize - 1));
size_t len = (char *)end - (char *)start;
static void unprotect_pages(long pagesize, void *start, void *end) if (mprotect(page, len, PROT_READ|PROT_WRITE|PROT_EXEC) != 0)
{ {
char *page = (char *)((intptr_t)start & ~(pagesize - 1)); fprintf(stderr, "mprotect failed\n");
size_t len = (char *)end - (char *)start; exit(1);
if (mprotect(page, len, PROT_READ|PROT_WRITE|PROT_EXEC) != 0) }
{ }
fprintf(stderr, "mprotect failed\n");
exit(1); static void unprotect_rtext()
} {
} static void *const pages[] =
{
static void unprotect_rtext() rtext_a_start, rtext_a_end,
{ rtext_tmap_start, rtext_tmap_end,
static void *const pages[] = rtext_tmap2_start, rtext_tmap2_end,
{ rtext_tmap3_start, rtext_tmap3_end
rtext_a_start, rtext_a_end, };
rtext_tmap_start, rtext_tmap_end, long pagesize = sysconf(_SC_PAGESIZE);
rtext_tmap2_start, rtext_tmap2_end, for (void *const *p = pages; p < &pages[countof(pages)]; p += 2)
rtext_tmap3_start, rtext_tmap3_end {
}; unprotect_pages(pagesize, p[0], p[1]);
long pagesize = sysconf(_SC_PAGESIZE); }
for (void *const *p = pages; p < &pages[countof(pages)]; p += 2) }
{ #endif
unprotect_pages(pagesize, p[0], p[1]);
} void I_StartupJoysticks();
} void I_ShutdownJoysticks();
#endif
int main (int argc, char **argv)
void I_StartupJoysticks(); {
void I_ShutdownJoysticks(); #if !defined (__APPLE__)
{
const char* I_GetBackEndName(); int s[4] = { SIGSEGV, SIGILL, SIGFPE, SIGBUS };
cc_install_handlers(argc, argv, 4, s, "zdoom-crash.log", DoomSpecificInfo);
int main (int argc, char **argv) }
{ #endif // !__APPLE__
#if !defined (__APPLE__)
{ printf(GAMENAME" %s - %s - SDL version\nCompiled on %s\n",
int s[4] = { SIGSEGV, SIGILL, SIGFPE, SIGBUS }; GetVersionString(), GetGitTime(), __DATE__);
cc_install_handlers(argc, argv, 4, s, "zdoom-crash.log", DoomSpecificInfo);
} seteuid (getuid ());
#endif // !__APPLE__ std::set_new_handler (NewFailure);
printf(GAMENAME" %s - %s - %s version\nCompiled on %s\n", #if defined(__MACH__) && !defined(NOASM)
GetVersionString(), GetGitTime(), I_GetBackEndName(), __DATE__); unprotect_rtext();
#endif
seteuid (getuid ());
std::set_new_handler (NewFailure); // Set LC_NUMERIC environment variable in case some library decides to
// clear the setlocale call at least this will be correct.
#if defined(__MACH__) && !defined(NOASM) // Note that the LANG environment variable is overridden by LC_*
unprotect_rtext(); setenv ("LC_NUMERIC", "C", 1);
#endif
#ifndef NO_GTK
// Set LC_NUMERIC environment variable in case some library decides to GtkAvailable = gtk_init_check (&argc, &argv);
// clear the setlocale call at least this will be correct. #endif
// Note that the LANG environment variable is overridden by LC_*
setenv ("LC_NUMERIC", "C", 1); setlocale (LC_ALL, "C");
#ifndef NO_GTK if (SDL_Init (SDL_INIT_VIDEO|SDL_INIT_TIMER|SDL_INIT_NOPARACHUTE|SDL_INIT_JOYSTICK) == -1)
GtkAvailable = gtk_init_check (&argc, &argv); {
#endif fprintf (stderr, "Could not initialize SDL:\n%s\n", SDL_GetError());
return -1;
setlocale (LC_ALL, "C"); }
atterm (SDL_Quit);
if (SDL_Init (SDL_INIT_VIDEO|SDL_INIT_TIMER|SDL_INIT_NOPARACHUTE|SDL_INIT_JOYSTICK) == -1)
{ printf("Using video driver %s\n", SDL_GetCurrentVideoDriver());
fprintf (stderr, "Could not initialize SDL:\n%s\n", SDL_GetError()); printf("\n");
return -1;
} try
atterm (SDL_Quit); {
Args = new DArgs(argc, argv);
{
char viddriver[80]; /*
killough 1/98:
if (SDL_VideoDriverName(viddriver, sizeof(viddriver)) != NULL)
{ This fixes some problems with exit handling
printf("Using video driver %s\n", viddriver); during abnormal situations.
#ifdef USE_XCURSOR
UseXCursor = (strcmp(viddriver, "x11") == 0); The old code called I_Quit() to end program,
#endif while now I_Quit() is installed as an exit
} handler and exit() is called to exit, either
printf("\n"); normally or abnormally. Seg faults are caught
} and the error handler is used, to prevent
being left in graphics mode or having very
char caption[100]; loud SFX noise because the sound card is
mysnprintf(caption, countof(caption), GAMESIG " %s (%s)", GetVersionString(), GetGitTime()); left in an unstable state.
SDL_WM_SetCaption(caption, caption); */
#ifdef __APPLE__ atexit (call_terms);
atterm (I_Quit);
const SDL_VideoInfo* videoInfo = SDL_GetVideoInfo();
if ( NULL != videoInfo ) // Should we even be doing anything with progdir on Unix systems?
{ char program[PATH_MAX];
EXTERN_CVAR( Int, vid_defwidth ) if (realpath (argv[0], program) == NULL)
EXTERN_CVAR( Int, vid_defheight ) strcpy (program, argv[0]);
EXTERN_CVAR( Int, vid_defbits ) char *slash = strrchr (program, '/');
EXTERN_CVAR( Bool, vid_vsync ) if (slash != NULL)
EXTERN_CVAR( Bool, fullscreen ) {
*(slash + 1) = '\0';
vid_defwidth = videoInfo->current_w; progdir = program;
vid_defheight = videoInfo->current_h; }
vid_defbits = videoInfo->vfmt->BitsPerPixel; else
vid_vsync = true; {
fullscreen = true; progdir = "./";
} }
#endif // __APPLE__ I_StartupJoysticks();
C_InitConsole (80*8, 25*8, false);
try D_DoomMain ();
{ }
Args = new DArgs(argc, argv); catch (class CDoomError &error)
{
/* I_ShutdownJoysticks();
killough 1/98: if (error.GetMessage ())
fprintf (stderr, "%s\n", error.GetMessage ());
This fixes some problems with exit handling
during abnormal situations. #ifdef __APPLE__
Mac_I_FatalError(error.GetMessage());
The old code called I_Quit() to end program, #endif // __APPLE__
while now I_Quit() is installed as an exit
handler and exit() is called to exit, either exit (-1);
normally or abnormally. Seg faults are caught }
and the error handler is used, to prevent catch (...)
being left in graphics mode or having very {
loud SFX noise because the sound card is call_terms ();
left in an unstable state. throw;
*/ }
return 0;
atexit (call_terms); }
atterm (I_Quit);
// Should we even be doing anything with progdir on Unix systems?
char program[PATH_MAX];
if (realpath (argv[0], program) == NULL)
strcpy (program, argv[0]);
char *slash = strrchr (program, '/');
if (slash != NULL)
{
*(slash + 1) = '\0';
progdir = program;
}
else
{
progdir = "./";
}
I_StartupJoysticks();
C_InitConsole (80*8, 25*8, false);
D_DoomMain ();
}
catch (class CDoomError &error)
{
I_ShutdownJoysticks();
if (error.GetMessage ())
fprintf (stderr, "%s\n", error.GetMessage ());
#ifdef __APPLE__
Mac_I_FatalError(error.GetMessage());
#endif // __APPLE__
exit (-1);
}
catch (...)
{
call_terms ();
throw;
}
return 0;
}

File diff suppressed because it is too large Load Diff

View File

@ -1,22 +1,21 @@
#include "hardware.h" #include "hardware.h"
#include "v_video.h" #include "v_video.h"
class SDLVideo : public IVideo class SDLVideo : public IVideo
{ {
public: public:
SDLVideo (int parm); SDLVideo (int parm);
~SDLVideo (); ~SDLVideo ();
EDisplayType GetDisplayType () { return DISPLAY_Both; } EDisplayType GetDisplayType () { return DISPLAY_Both; }
void SetWindowedScale (float scale); void SetWindowedScale (float scale);
DFrameBuffer *CreateFrameBuffer (int width, int height, bool fs, DFrameBuffer *old); DFrameBuffer *CreateFrameBuffer (int width, int height, bool fs, DFrameBuffer *old);
void StartModeIterator (int bits, bool fs); void StartModeIterator (int bits, bool fs);
bool NextMode (int *width, int *height, bool *letterbox); bool NextMode (int *width, int *height, bool *letterbox);
private: private:
int IteratorMode; int IteratorMode;
int IteratorBits; int IteratorBits;
bool IteratorFS; };
};

View File

@ -1,354 +1,354 @@
/* /*
** st_start.cpp ** st_start.cpp
** Handles the startup screen. ** Handles the startup screen.
** **
**--------------------------------------------------------------------------- **---------------------------------------------------------------------------
** Copyright 2006-2007 Randy Heit ** Copyright 2006-2007 Randy Heit
** All rights reserved. ** All rights reserved.
** **
** Redistribution and use in source and binary forms, with or without ** Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions ** modification, are permitted provided that the following conditions
** are met: ** are met:
** **
** 1. Redistributions of source code must retain the above copyright ** 1. Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer. ** notice, this list of conditions and the following disclaimer.
** 2. Redistributions in binary form must reproduce the above copyright ** 2. Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in the ** notice, this list of conditions and the following disclaimer in the
** documentation and/or other materials provided with the distribution. ** documentation and/or other materials provided with the distribution.
** 3. The name of the author may not be used to endorse or promote products ** 3. The name of the author may not be used to endorse or promote products
** derived from this software without specific prior written permission. ** derived from this software without specific prior written permission.
** **
** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR ** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES ** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. ** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, ** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT ** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
**--------------------------------------------------------------------------- **---------------------------------------------------------------------------
** **
*/ */
// HEADER FILES ------------------------------------------------------------ // HEADER FILES ------------------------------------------------------------
#include <unistd.h> #include <unistd.h>
#include <sys/time.h> #include <sys/time.h>
#include <sys/types.h> #include <sys/types.h>
#include <termios.h> #include <termios.h>
#include "st_start.h" #include "st_start.h"
#include "doomdef.h" #include "doomdef.h"
#include "i_system.h" #include "i_system.h"
#include "c_cvars.h" #include "c_cvars.h"
// MACROS ------------------------------------------------------------------ // MACROS ------------------------------------------------------------------
// TYPES ------------------------------------------------------------------- // TYPES -------------------------------------------------------------------
class FTTYStartupScreen : public FStartupScreen class FTTYStartupScreen : public FStartupScreen
{ {
public: public:
FTTYStartupScreen(int max_progress); FTTYStartupScreen(int max_progress);
~FTTYStartupScreen(); ~FTTYStartupScreen();
void Progress(); void Progress();
void NetInit(const char *message, int num_players); void NetInit(const char *message, int num_players);
void NetProgress(int count); void NetProgress(int count);
void NetMessage(const char *format, ...); // cover for printf void NetMessage(const char *format, ...); // cover for printf
void NetDone(); void NetDone();
bool NetLoop(bool (*timer_callback)(void *), void *userdata); bool NetLoop(bool (*timer_callback)(void *), void *userdata);
protected: protected:
bool DidNetInit; bool DidNetInit;
int NetMaxPos, NetCurPos; int NetMaxPos, NetCurPos;
const char *TheNetMessage; const char *TheNetMessage;
termios OldTermIOS; termios OldTermIOS;
}; };
// EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES --------------------------------------------
// PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ----------------------------------------------
void I_ShutdownJoysticks(); void I_ShutdownJoysticks();
// PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // PRIVATE FUNCTION PROTOTYPES ---------------------------------------------
static void DeleteStartupScreen(); static void DeleteStartupScreen();
// EXTERNAL DATA DECLARATIONS ---------------------------------------------- // EXTERNAL DATA DECLARATIONS ----------------------------------------------
// PUBLIC DATA DEFINITIONS ------------------------------------------------- // PUBLIC DATA DEFINITIONS -------------------------------------------------
FStartupScreen *StartScreen; FStartupScreen *StartScreen;
CUSTOM_CVAR(Int, showendoom, 0, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) CUSTOM_CVAR(Int, showendoom, 0, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
{ {
if (self < 0) self = 0; if (self < 0) self = 0;
else if (self > 2) self=2; else if (self > 2) self=2;
} }
// PRIVATE DATA DEFINITIONS ------------------------------------------------ // PRIVATE DATA DEFINITIONS ------------------------------------------------
static const char SpinnyProgressChars[4] = { '|', '/', '-', '\\' }; static const char SpinnyProgressChars[4] = { '|', '/', '-', '\\' };
// CODE -------------------------------------------------------------------- // CODE --------------------------------------------------------------------
//========================================================================== //==========================================================================
// //
// FStartupScreen :: CreateInstance // FStartupScreen :: CreateInstance
// //
// Initializes the startup screen for the detected game. // Initializes the startup screen for the detected game.
// Sets the size of the progress bar and displays the startup screen. // Sets the size of the progress bar and displays the startup screen.
// //
//========================================================================== //==========================================================================
FStartupScreen *FStartupScreen::CreateInstance(int max_progress) FStartupScreen *FStartupScreen::CreateInstance(int max_progress)
{ {
atterm(DeleteStartupScreen); atterm(DeleteStartupScreen);
return new FTTYStartupScreen(max_progress); return new FTTYStartupScreen(max_progress);
} }
//=========================================================================== //===========================================================================
// //
// DeleteStartupScreen // DeleteStartupScreen
// //
// Makes sure the startup screen has been deleted before quitting. // Makes sure the startup screen has been deleted before quitting.
// //
//=========================================================================== //===========================================================================
void DeleteStartupScreen() void DeleteStartupScreen()
{ {
if (StartScreen != NULL) if (StartScreen != NULL)
{ {
delete StartScreen; delete StartScreen;
StartScreen = NULL; StartScreen = NULL;
} }
} }
//=========================================================================== //===========================================================================
// //
// FTTYStartupScreen Constructor // FTTYStartupScreen Constructor
// //
// Sets the size of the progress bar and displays the startup screen. // Sets the size of the progress bar and displays the startup screen.
// //
//=========================================================================== //===========================================================================
FTTYStartupScreen::FTTYStartupScreen(int max_progress) FTTYStartupScreen::FTTYStartupScreen(int max_progress)
: FStartupScreen(max_progress) : FStartupScreen(max_progress)
{ {
DidNetInit = false; DidNetInit = false;
NetMaxPos = 0; NetMaxPos = 0;
NetCurPos = 0; NetCurPos = 0;
TheNetMessage = NULL; TheNetMessage = NULL;
} }
//=========================================================================== //===========================================================================
// //
// FTTYStartupScreen Destructor // FTTYStartupScreen Destructor
// //
// Called just before entering graphics mode to deconstruct the startup // Called just before entering graphics mode to deconstruct the startup
// screen. // screen.
// //
//=========================================================================== //===========================================================================
FTTYStartupScreen::~FTTYStartupScreen() FTTYStartupScreen::~FTTYStartupScreen()
{ {
NetDone(); // Just in case it wasn't called yet and needs to be. NetDone(); // Just in case it wasn't called yet and needs to be.
} }
//=========================================================================== //===========================================================================
// //
// FTTYStartupScreen :: Progress // FTTYStartupScreen :: Progress
// //
// If there was a progress bar, this would move it. But the basic TTY // If there was a progress bar, this would move it. But the basic TTY
// startup screen doesn't have one, so this function does nothing. // startup screen doesn't have one, so this function does nothing.
// //
//=========================================================================== //===========================================================================
void FTTYStartupScreen::Progress() void FTTYStartupScreen::Progress()
{ {
} }
//=========================================================================== //===========================================================================
// //
// FTTYStartupScreen :: NetInit // FTTYStartupScreen :: NetInit
// //
// Sets stdin for unbuffered I/O, displays the given message, and shows // Sets stdin for unbuffered I/O, displays the given message, and shows
// a progress meter. // a progress meter.
// //
//=========================================================================== //===========================================================================
void FTTYStartupScreen::NetInit(const char *message, int numplayers) void FTTYStartupScreen::NetInit(const char *message, int numplayers)
{ {
if (!DidNetInit) if (!DidNetInit)
{ {
termios rawtermios; termios rawtermios;
fprintf (stderr, "Press 'Q' to abort network game synchronization."); fprintf (stderr, "Press 'Q' to abort network game synchronization.");
// Set stdin to raw mode so we can get keypresses in ST_CheckNetAbort() // Set stdin to raw mode so we can get keypresses in ST_CheckNetAbort()
// immediately without waiting for an EOL. // immediately without waiting for an EOL.
tcgetattr (STDIN_FILENO, &OldTermIOS); tcgetattr (STDIN_FILENO, &OldTermIOS);
rawtermios = OldTermIOS; rawtermios = OldTermIOS;
rawtermios.c_lflag &= ~(ICANON | ECHO); rawtermios.c_lflag &= ~(ICANON | ECHO);
tcsetattr (STDIN_FILENO, TCSANOW, &rawtermios); tcsetattr (STDIN_FILENO, TCSANOW, &rawtermios);
DidNetInit = true; DidNetInit = true;
} }
if (numplayers == 1) if (numplayers == 1)
{ {
// Status message without any real progress info. // Status message without any real progress info.
fprintf (stderr, "\n%s.", message); fprintf (stderr, "\n%s.", message);
} }
else else
{ {
fprintf (stderr, "\n%s: ", message); fprintf (stderr, "\n%s: ", message);
} }
fflush (stderr); fflush (stderr);
TheNetMessage = message; TheNetMessage = message;
NetMaxPos = numplayers; NetMaxPos = numplayers;
NetCurPos = 0; NetCurPos = 0;
NetProgress(1); // You always know about yourself NetProgress(1); // You always know about yourself
} }
//=========================================================================== //===========================================================================
// //
// FTTYStartupScreen :: NetDone // FTTYStartupScreen :: NetDone
// //
// Restores the old stdin tty settings. // Restores the old stdin tty settings.
// //
//=========================================================================== //===========================================================================
void FTTYStartupScreen::NetDone() void FTTYStartupScreen::NetDone()
{ {
// Restore stdin settings // Restore stdin settings
if (DidNetInit) if (DidNetInit)
{ {
tcsetattr (STDIN_FILENO, TCSANOW, &OldTermIOS); tcsetattr (STDIN_FILENO, TCSANOW, &OldTermIOS);
printf ("\n"); printf ("\n");
DidNetInit = false; DidNetInit = false;
} }
} }
//=========================================================================== //===========================================================================
// //
// FTTYStartupScreen :: NetMessage // FTTYStartupScreen :: NetMessage
// //
// Call this between NetInit() and NetDone() instead of Printf() to // Call this between NetInit() and NetDone() instead of Printf() to
// display messages, because the progress meter is mixed in the same output // display messages, because the progress meter is mixed in the same output
// stream as normal messages. // stream as normal messages.
// //
//=========================================================================== //===========================================================================
void FTTYStartupScreen::NetMessage(const char *format, ...) void FTTYStartupScreen::NetMessage(const char *format, ...)
{ {
FString str; FString str;
va_list argptr; va_list argptr;
va_start (argptr, format); va_start (argptr, format);
str.VFormat (format, argptr); str.VFormat (format, argptr);
va_end (argptr); va_end (argptr);
fprintf (stderr, "\r%-40s\n", str.GetChars()); fprintf (stderr, "\r%-40s\n", str.GetChars());
} }
//=========================================================================== //===========================================================================
// //
// FTTYStartupScreen :: NetProgress // FTTYStartupScreen :: NetProgress
// //
// Sets the network progress meter. If count is 0, it gets bumped by 1. // Sets the network progress meter. If count is 0, it gets bumped by 1.
// Otherwise, it is set to count. // Otherwise, it is set to count.
// //
//=========================================================================== //===========================================================================
void FTTYStartupScreen::NetProgress(int count) void FTTYStartupScreen::NetProgress(int count)
{ {
int i; int i;
if (count == 0) if (count == 0)
{ {
NetCurPos++; NetCurPos++;
} }
else if (count > 0) else if (count > 0)
{ {
NetCurPos = count; NetCurPos = count;
} }
if (NetMaxPos == 0) if (NetMaxPos == 0)
{ {
// Spinny-type progress meter, because we're a guest waiting for the host. // Spinny-type progress meter, because we're a guest waiting for the host.
fprintf (stderr, "\r%s: %c", TheNetMessage, SpinnyProgressChars[NetCurPos & 3]); fprintf (stderr, "\r%s: %c", TheNetMessage, SpinnyProgressChars[NetCurPos & 3]);
fflush (stderr); fflush (stderr);
} }
else if (NetMaxPos > 1) else if (NetMaxPos > 1)
{ {
// Dotty-type progress meter. // Dotty-type progress meter.
fprintf (stderr, "\r%s: ", TheNetMessage); fprintf (stderr, "\r%s: ", TheNetMessage);
for (i = 0; i < NetCurPos; ++i) for (i = 0; i < NetCurPos; ++i)
{ {
fputc ('.', stderr); fputc ('.', stderr);
} }
fprintf (stderr, "%*c[%2d/%2d]", NetMaxPos + 1 - NetCurPos, ' ', NetCurPos, NetMaxPos); fprintf (stderr, "%*c[%2d/%2d]", NetMaxPos + 1 - NetCurPos, ' ', NetCurPos, NetMaxPos);
fflush (stderr); fflush (stderr);
} }
} }
//=========================================================================== //===========================================================================
// //
// FTTYStartupScreen :: NetLoop // FTTYStartupScreen :: NetLoop
// //
// The timer_callback function is called at least two times per second // The timer_callback function is called at least two times per second
// and passed the userdata value. It should return true to stop the loop and // and passed the userdata value. It should return true to stop the loop and
// return control to the caller or false to continue the loop. // return control to the caller or false to continue the loop.
// //
// ST_NetLoop will return true if the loop was halted by the callback and // ST_NetLoop will return true if the loop was halted by the callback and
// false if the loop was halted because the user wants to abort the // false if the loop was halted because the user wants to abort the
// network synchronization. // network synchronization.
// //
//=========================================================================== //===========================================================================
bool FTTYStartupScreen::NetLoop(bool (*timer_callback)(void *), void *userdata) bool FTTYStartupScreen::NetLoop(bool (*timer_callback)(void *), void *userdata)
{ {
fd_set rfds; fd_set rfds;
struct timeval tv; struct timeval tv;
int retval; int retval;
char k; char k;
for (;;) for (;;)
{ {
// Don't flood the network with packets on startup. // Don't flood the network with packets on startup.
tv.tv_sec = 0; tv.tv_sec = 0;
tv.tv_usec = 500000; tv.tv_usec = 500000;
FD_ZERO (&rfds); FD_ZERO (&rfds);
FD_SET (STDIN_FILENO, &rfds); FD_SET (STDIN_FILENO, &rfds);
retval = select (1, &rfds, NULL, NULL, &tv); retval = select (1, &rfds, NULL, NULL, &tv);
if (retval == -1) if (retval == -1)
{ {
// Error // Error
} }
else if (retval == 0) else if (retval == 0)
{ {
if (timer_callback (userdata)) if (timer_callback (userdata))
{ {
fputc ('\n', stderr); fputc ('\n', stderr);
return true; return true;
} }
} }
else if (read (STDIN_FILENO, &k, 1) == 1) else if (read (STDIN_FILENO, &k, 1) == 1)
{ {
// Check input on stdin // Check input on stdin
if (k == 'q' || k == 'Q') if (k == 'q' || k == 'Q')
{ {
fprintf (stderr, "\nNetwork game synchronization aborted."); fprintf (stderr, "\nNetwork game synchronization aborted.");
return false; return false;
} }
} }
} }
} }
void ST_Endoom() void ST_Endoom()
{ {
I_ShutdownJoysticks(); I_ShutdownJoysticks();
exit(0); exit(0);
} }

View File

@ -809,19 +809,18 @@ void FWallTmapVals::InitFromWallCoords(const FWallCoords *wallc)
{ {
if (MirrorFlags & RF_XFLIP) if (MirrorFlags & RF_XFLIP)
{ {
UoverZorg = (float)wallc->tx2 * WallTMapScale; UoverZorg = (float)wallc->tx2 * centerx;
UoverZstep = (float)(-wallc->ty2) * 32.f; UoverZstep = (float)(-wallc->ty2);
InvZorg = (float)(wallc->tx2 - wallc->tx1) * WallTMapScale; InvZorg = (float)(wallc->tx2 - wallc->tx1) * centerx;
InvZstep = (float)(wallc->ty1 - wallc->ty2) * 32.f; InvZstep = (float)(wallc->ty1 - wallc->ty2);
} }
else else
{ {
UoverZorg = (float)wallc->tx1 * WallTMapScale; UoverZorg = (float)wallc->tx1 * centerx;
UoverZstep = (float)(-wallc->ty1) * 32.f; UoverZstep = (float)(-wallc->ty1);
InvZorg = (float)(wallc->tx1 - wallc->tx2) * WallTMapScale; InvZorg = (float)(wallc->tx1 - wallc->tx2) * centerx;
InvZstep = (float)(wallc->ty2 - wallc->ty1) * 32.f; InvZstep = (float)(wallc->ty2 - wallc->ty1);
} }
InitDepth();
} }
void FWallTmapVals::InitFromLine(int tx1, int ty1, int tx2, int ty2) void FWallTmapVals::InitFromLine(int tx1, int ty1, int tx2, int ty2)
@ -837,17 +836,10 @@ void FWallTmapVals::InitFromLine(int tx1, int ty1, int tx2, int ty2)
fullx2 = -fullx2; fullx2 = -fullx2;
} }
UoverZorg = (float)fullx1 * WallTMapScale; UoverZorg = (float)fullx1 * centerx;
UoverZstep = (float)(-fully1) * 32.f; UoverZstep = (float)(-fully1);
InvZorg = (float)(fullx1 - fullx2) * WallTMapScale; InvZorg = (float)(fullx1 - fullx2) * centerx;
InvZstep = (float)(fully2 - fully1) * 32.f; InvZstep = (float)(fully2 - fully1);
InitDepth();
}
void FWallTmapVals::InitDepth()
{
DepthScale = InvZstep * WallTMapScale2;
DepthOrg = -UoverZstep * WallTMapScale2;
} }
// //

View File

@ -44,13 +44,11 @@ struct FWallCoords
struct FWallTmapVals struct FWallTmapVals
{ {
float DepthOrg, DepthScale;
float UoverZorg, UoverZstep; float UoverZorg, UoverZstep;
float InvZorg, InvZstep; float InvZorg, InvZstep;
void InitFromWallCoords(const FWallCoords *wallc); void InitFromWallCoords(const FWallCoords *wallc);
void InitFromLine(int x1, int y1, int x2, int y2); void InitFromLine(int x1, int y1, int x2, int y2);
void InitDepth();
}; };
extern FWallCoords WallC; extern FWallCoords WallC;

View File

@ -117,7 +117,6 @@ FDynamicColormap*basecolormap; // [RH] colormap currently drawing with
int fixedlightlev; int fixedlightlev;
lighttable_t *fixedcolormap; lighttable_t *fixedcolormap;
FSpecialColormap *realfixedcolormap; FSpecialColormap *realfixedcolormap;
float WallTMapScale;
float WallTMapScale2; float WallTMapScale2;
@ -386,8 +385,7 @@ void R_SWRSetWindow(int windowSize, int fullWidth, int fullHeight, int stHeight,
iyaspectmulfloat = (float)virtwidth * r_Yaspect / 320.f / (float)virtheight; iyaspectmulfloat = (float)virtwidth * r_Yaspect / 320.f / (float)virtheight;
InvZtoScale = yaspectmul * centerx; InvZtoScale = yaspectmul * centerx;
WallTMapScale = (float)centerx * 32.f; WallTMapScale2 = iyaspectmulfloat * 64.f / (float)centerx;
WallTMapScale2 = iyaspectmulfloat * 2.f / (float)centerx;
// psprite scales // psprite scales
pspritexscale = (centerxwide << FRACBITS) / 160; pspritexscale = (centerxwide << FRACBITS) / 160;

View File

@ -42,7 +42,6 @@ extern fixed_t FocalLengthX, FocalLengthY;
extern float FocalLengthXfloat; extern float FocalLengthXfloat;
extern fixed_t InvZtoScale; extern fixed_t InvZtoScale;
extern float WallTMapScale;
extern float WallTMapScale2; extern float WallTMapScale2;
extern int viewwindowx; extern int viewwindowx;

View File

@ -2893,6 +2893,8 @@ void PrepWall (fixed_t *swall, fixed_t *lwall, fixed_t walxrepeat, int x1, int x
{ // swall = scale, lwall = texturecolumn { // swall = scale, lwall = texturecolumn
double top, bot, i; double top, bot, i;
double xrepeat = fabs((double)walxrepeat); double xrepeat = fabs((double)walxrepeat);
double depth_scale = WallT.InvZstep * WallTMapScale2;
double depth_org = -WallT.UoverZstep * WallTMapScale2;
i = x1 - centerx; i = x1 - centerx;
top = WallT.UoverZorg + WallT.UoverZstep * i; top = WallT.UoverZorg + WallT.UoverZstep * i;
@ -2909,7 +2911,7 @@ void PrepWall (fixed_t *swall, fixed_t *lwall, fixed_t walxrepeat, int x1, int x
{ {
lwall[x] = xs_RoundToInt(frac * xrepeat); lwall[x] = xs_RoundToInt(frac * xrepeat);
} }
swall[x] = xs_RoundToInt(frac * WallT.DepthScale + WallT.DepthOrg); swall[x] = xs_RoundToInt(frac * depth_scale + depth_org);
top += WallT.UoverZstep; top += WallT.UoverZstep;
bot += WallT.InvZstep; bot += WallT.InvZstep;
} }

View File

@ -158,7 +158,7 @@ std2:
'random' { RET(TK_Random); } 'random' { RET(TK_Random); }
'random2' { RET(TK_Random2); } 'random2' { RET(TK_Random2); }
'frandom' { RET(TK_FRandom); } 'frandom' { RET(TK_FRandom); }
'pick' { RET(TK_Pick); } 'randompick' { RET(TK_RandomPick); }
L (L|D)* { RET(TK_Identifier); } L (L|D)* { RET(TK_Identifier); }

View File

@ -122,5 +122,5 @@ xx(TK_Array, "'array'")
xx(TK_In, "'in'") xx(TK_In, "'in'")
xx(TK_SizeOf, "'sizeof'") xx(TK_SizeOf, "'sizeof'")
xx(TK_AlignOf, "'alignof'") xx(TK_AlignOf, "'alignof'")
xx(TK_Pick, "'pick'") xx(TK_RandomPick, "'randompick'")
#undef xx #undef xx

View File

@ -1,387 +0,0 @@
/* SDLMain.m - main entry point for our Cocoa-ized SDL app
Initial Version: Darrell Walisser <dwaliss1@purdue.edu>
Non-NIB-Code & other changes: Max Horn <max@quendi.de>
Feel free to customize this file to suit your needs
*/
#import "SDL.h"
#import <Cocoa/Cocoa.h>
#import <sys/param.h> /* for MAXPATHLEN */
#import <unistd.h>
@interface SDLMain : NSObject
@end
/* For some reaon, Apple removed setAppleMenu from the headers in 10.4,
but the method still is there and works. To avoid warnings, we declare
it ourselves here. */
@interface NSApplication(SDL_Missing_Methods)
- (void)setAppleMenu:(NSMenu *)menu;
@end
/* Use this flag to determine whether we use SDLMain.nib or not */
#define SDL_USE_NIB_FILE 0
/* Use this flag to determine whether we use CPS (docking) or not */
#define SDL_USE_CPS 1
#ifdef SDL_USE_CPS
/* Portions of CPS.h */
typedef struct CPSProcessSerNum
{
UInt32 lo;
UInt32 hi;
} CPSProcessSerNum;
extern OSErr CPSGetCurrentProcess( CPSProcessSerNum *psn);
extern OSErr CPSEnableForegroundOperation( CPSProcessSerNum *psn, UInt32 _arg2, UInt32 _arg3, UInt32 _arg4, UInt32 _arg5);
extern OSErr CPSSetFrontProcess( CPSProcessSerNum *psn);
#endif /* SDL_USE_CPS */
static int gArgc;
static char **gArgv;
static BOOL gFinderLaunch;
static BOOL gCalledAppMainline = FALSE;
static NSString *getApplicationName(void)
{
NSDictionary *dict;
NSString *appName = 0;
/* Determine the application name */
dict = (NSDictionary *)CFBundleGetInfoDictionary(CFBundleGetMainBundle());
if (dict)
appName = [dict objectForKey: @"CFBundleName"];
if (![appName length])
appName = [[NSProcessInfo processInfo] processName];
return appName;
}
#if SDL_USE_NIB_FILE
/* A helper category for NSString */
@interface NSString (ReplaceSubString)
- (NSString *)stringByReplacingRange:(NSRange)aRange with:(NSString *)aString;
@end
#endif
@interface SDLApplication : NSApplication
@end
@implementation SDLApplication
/* Invoked from the Quit menu item */
- (void)terminate:(id)sender
{
/* Post a SDL_QUIT event */
SDL_Event event;
event.type = SDL_QUIT;
SDL_PushEvent(&event);
}
@end
/* The main class of the application, the application's delegate */
@implementation SDLMain
/* Set the working directory to the .app's parent directory */
- (void) setupWorkingDirectory:(BOOL)shouldChdir
{
if (shouldChdir)
{
char parentdir[MAXPATHLEN];
CFURLRef url = CFBundleCopyBundleURL(CFBundleGetMainBundle());
CFURLRef url2 = CFURLCreateCopyDeletingLastPathComponent(0, url);
if (CFURLGetFileSystemRepresentation(url2, true, (UInt8 *)parentdir, MAXPATHLEN)) {
assert ( chdir (parentdir) == 0 ); /* chdir to the binary app's parent */
}
CFRelease(url);
CFRelease(url2);
}
}
#if SDL_USE_NIB_FILE
/* Fix menu to contain the real app name instead of "SDL App" */
- (void)fixMenu:(NSMenu *)aMenu withAppName:(NSString *)appName
{
NSRange aRange;
NSEnumerator *enumerator;
NSMenuItem *menuItem;
aRange = [[aMenu title] rangeOfString:@"SDL App"];
if (aRange.length != 0)
[aMenu setTitle: [[aMenu title] stringByReplacingRange:aRange with:appName]];
enumerator = [[aMenu itemArray] objectEnumerator];
while ((menuItem = [enumerator nextObject]))
{
aRange = [[menuItem title] rangeOfString:@"SDL App"];
if (aRange.length != 0)
[menuItem setTitle: [[menuItem title] stringByReplacingRange:aRange with:appName]];
if ([menuItem hasSubmenu])
[self fixMenu:[menuItem submenu] withAppName:appName];
}
[ aMenu sizeToFit ];
}
#else
static void setApplicationMenu(void)
{
/* warning: this code is very odd */
NSMenu *appleMenu;
NSMenuItem *menuItem;
NSString *title;
NSString *appName;
appName = getApplicationName();
appleMenu = [[NSMenu alloc] initWithTitle:@""];
/* Add menu items */
title = [@"About " stringByAppendingString:appName];
[appleMenu addItemWithTitle:title action:@selector(orderFrontStandardAboutPanel:) keyEquivalent:@""];
[appleMenu addItem:[NSMenuItem separatorItem]];
title = [@"Hide " stringByAppendingString:appName];
[appleMenu addItemWithTitle:title action:@selector(hide:) keyEquivalent:@"h"];
menuItem = (NSMenuItem *)[appleMenu addItemWithTitle:@"Hide Others" action:@selector(hideOtherApplications:) keyEquivalent:@"h"];
[menuItem setKeyEquivalentModifierMask:(NSAlternateKeyMask|NSCommandKeyMask)];
[appleMenu addItemWithTitle:@"Show All" action:@selector(unhideAllApplications:) keyEquivalent:@""];
[appleMenu addItem:[NSMenuItem separatorItem]];
title = [@"Quit " stringByAppendingString:appName];
[appleMenu addItemWithTitle:title action:@selector(terminate:) keyEquivalent:@"q"];
/* Put menu into the menubar */
menuItem = [[NSMenuItem alloc] initWithTitle:@"" action:nil keyEquivalent:@""];
[menuItem setSubmenu:appleMenu];
[[NSApp mainMenu] addItem:menuItem];
/* Tell the application object that this is now the application menu */
[NSApp setAppleMenu:appleMenu];
/* Finally give up our references to the objects */
[appleMenu release];
[menuItem release];
}
/* Create a window menu */
static void setupWindowMenu(void)
{
NSMenu *windowMenu;
NSMenuItem *windowMenuItem;
NSMenuItem *menuItem;
windowMenu = [[NSMenu alloc] initWithTitle:@"Window"];
/* "Minimize" item */
menuItem = [[NSMenuItem alloc] initWithTitle:@"Minimize" action:@selector(performMiniaturize:) keyEquivalent:@"m"];
[windowMenu addItem:menuItem];
[menuItem release];
/* Put menu into the menubar */
windowMenuItem = [[NSMenuItem alloc] initWithTitle:@"Window" action:nil keyEquivalent:@""];
[windowMenuItem setSubmenu:windowMenu];
[[NSApp mainMenu] addItem:windowMenuItem];
/* Tell the application object that this is now the window menu */
[NSApp setWindowsMenu:windowMenu];
/* Finally give up our references to the objects */
[windowMenu release];
[windowMenuItem release];
}
/* Replacement for NSApplicationMain */
static void CustomApplicationMain (int argc, char **argv)
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
SDLMain *sdlMain;
/* Ensure the application object is initialised */
[SDLApplication sharedApplication];
#ifdef SDL_USE_CPS
{
CPSProcessSerNum PSN;
/* Tell the dock about us */
if (!CPSGetCurrentProcess(&PSN))
if (!CPSEnableForegroundOperation(&PSN,0x03,0x3C,0x2C,0x1103))
if (!CPSSetFrontProcess(&PSN))
[SDLApplication sharedApplication];
}
#endif /* SDL_USE_CPS */
/* Set up the menubar */
[NSApp setMainMenu:[[NSMenu alloc] init]];
setApplicationMenu();
setupWindowMenu();
/* Create SDLMain and make it the app delegate */
sdlMain = [[SDLMain alloc] init];
[NSApp setDelegate:sdlMain];
/* Start the main event loop */
[NSApp run];
[sdlMain release];
[pool release];
}
#endif
/*
* Catch document open requests...this lets us notice files when the app
* was launched by double-clicking a document, or when a document was
* dragged/dropped on the app's icon. You need to have a
* CFBundleDocumentsType section in your Info.plist to get this message,
* apparently.
*
* Files are added to gArgv, so to the app, they'll look like command line
* arguments. Previously, apps launched from the finder had nothing but
* an argv[0].
*
* This message may be received multiple times to open several docs on launch.
*
* This message is ignored once the app's mainline has been called.
*/
- (BOOL)application:(NSApplication *)theApplication openFile:(NSString *)filename
{
const char *temparg;
size_t arglen;
char *arg;
char **newargv;
if (!gFinderLaunch) /* MacOS is passing command line args. */
return FALSE;
if (gCalledAppMainline) /* app has started, ignore this document. */
return FALSE;
temparg = [filename UTF8String];
arglen = SDL_strlen(temparg) + 1;
arg = (char *) SDL_malloc(arglen);
if (arg == NULL)
return FALSE;
newargv = (char **) realloc(gArgv, sizeof (char *) * (gArgc + 2));
if (newargv == NULL)
{
SDL_free(arg);
return FALSE;
}
gArgv = newargv;
SDL_strlcpy(arg, temparg, arglen);
gArgv[gArgc++] = arg;
gArgv[gArgc] = NULL;
return TRUE;
}
/* Called when the internal event loop has just started running */
- (void) applicationDidFinishLaunching: (NSNotification *) note
{
int status;
/* Set the working directory to the .app's parent directory */
[self setupWorkingDirectory:gFinderLaunch];
#if SDL_USE_NIB_FILE
/* Set the main menu to contain the real app name instead of "SDL App" */
[self fixMenu:[NSApp mainMenu] withAppName:getApplicationName()];
#endif
/* Hand off to main application code */
gCalledAppMainline = TRUE;
status = SDL_main (gArgc, gArgv);
/* We're done, thank you for playing */
exit(status);
}
@end
@implementation NSString (ReplaceSubString)
- (NSString *)stringByReplacingRange:(NSRange)aRange with:(NSString *)aString
{
unsigned int bufferSize;
unsigned int selfLen = [self length];
unsigned int aStringLen = [aString length];
unichar *buffer;
NSRange localRange;
NSString *result;
bufferSize = selfLen + aStringLen - aRange.length;
buffer = NSAllocateMemoryPages(bufferSize*sizeof(unichar));
/* Get first part into buffer */
localRange.location = 0;
localRange.length = aRange.location;
[self getCharacters:buffer range:localRange];
/* Get middle part into buffer */
localRange.location = 0;
localRange.length = aStringLen;
[aString getCharacters:(buffer+aRange.location) range:localRange];
/* Get last part into buffer */
localRange.location = aRange.location + aRange.length;
localRange.length = selfLen - localRange.location;
[self getCharacters:(buffer+aRange.location+aStringLen) range:localRange];
/* Build output string */
result = [NSString stringWithCharacters:buffer length:bufferSize];
NSDeallocateMemoryPages(buffer, bufferSize);
return result;
}
@end
#ifdef main
# undef main
#endif
/* Main entry point to executable - should *not* be SDL_main! */
int main (int argc, char **argv)
{
/* Copy the arguments into a global variable */
/* This is passed if we are launched by double-clicking */
if ( argc >= 2 && strncmp (argv[1], "-psn", 4) == 0 ) {
gArgv = (char **) SDL_malloc(sizeof (char *) * 2);
gArgv[0] = argv[0];
gArgv[1] = NULL;
gArgc = 1;
gFinderLaunch = YES;
} else {
int i;
gArgc = argc;
gArgv = (char **) SDL_malloc(sizeof (char *) * (argc+1));
for (i = 0; i <= argc; i++)
gArgv[i] = argv[i];
gFinderLaunch = NO;
}
#if SDL_USE_NIB_FILE
[SDLApplication poseAsClass:[NSApplication class]];
NSApplicationMain (argc, argv);
#else
CustomApplicationMain (argc, argv);
#endif
return 0;
}

View File

@ -1,131 +0,0 @@
// Moved from sdl/i_system.cpp
#include <string.h>
#include <SDL.h>
#include "bitmap.h"
#include "v_palette.h"
#include "textures.h"
extern SDL_Surface *cursorSurface;
extern SDL_Rect cursorBlit;
#ifdef USE_XCURSOR
// Xlib has its own GC, so don't let it interfere.
#define GC XGC
#include <X11/Xcursor/Xcursor.h>
#undef GC
bool UseXCursor;
SDL_Cursor *X11Cursor;
SDL_Cursor *FirstCursor;
// Hack! Hack! SDL does not provide a clean way to get the XDisplay.
// On the other hand, there are no more planned updates for SDL 1.2,
// so we should be fine making assumptions.
struct SDL_PrivateVideoData
{
int local_X11;
Display *X11_Display;
};
struct SDL_VideoDevice
{
const char *name;
int (*functions[9])();
SDL_VideoInfo info;
SDL_PixelFormat *displayformatalphapixel;
int (*morefuncs[9])();
Uint16 *gamma;
int (*somefuncs[9])();
unsigned int texture; // Only here if SDL was compiled with OpenGL support. Ack!
int is_32bit;
int (*itsafuncs[13])();
SDL_Surface *surfaces[3];
SDL_Palette *physpal;
SDL_Color *gammacols;
char *wm_strings[2];
int offsets[2];
SDL_GrabMode input_grab;
int handles_any_size;
SDL_PrivateVideoData *hidden; // Why did they have to bury this so far in?
};
extern SDL_VideoDevice *current_video;
#define SDL_Display (current_video->hidden->X11_Display)
SDL_Cursor *CreateColorCursor(FTexture *cursorpic)
{
return NULL;
}
#endif
bool I_SetCursor(FTexture *cursorpic)
{
if (cursorpic != NULL && cursorpic->UseType != FTexture::TEX_Null)
{
// Must be no larger than 32x32.
if (cursorpic->GetWidth() > 32 || cursorpic->GetHeight() > 32)
{
return false;
}
#ifdef USE_XCURSOR
if (UseXCursor)
{
if (FirstCursor == NULL)
{
FirstCursor = SDL_GetCursor();
}
X11Cursor = CreateColorCursor(cursorpic);
if (X11Cursor != NULL)
{
SDL_SetCursor(X11Cursor);
return true;
}
}
#endif
if (cursorSurface == NULL)
cursorSurface = SDL_CreateRGBSurface (0, 32, 32, 32, MAKEARGB(0,255,0,0), MAKEARGB(0,0,255,0), MAKEARGB(0,0,0,255), MAKEARGB(255,0,0,0));
SDL_ShowCursor(0);
SDL_LockSurface(cursorSurface);
BYTE buffer[32*32*4];
memset(buffer, 0, 32*32*4);
FBitmap bmp(buffer, 32*4, 32, 32);
cursorpic->CopyTrueColorPixels(&bmp, 0, 0);
memcpy(cursorSurface->pixels, bmp.GetPixels(), 32*32*4);
SDL_UnlockSurface(cursorSurface);
}
else
{
SDL_ShowCursor(1);
if (cursorSurface != NULL)
{
SDL_FreeSurface(cursorSurface);
cursorSurface = NULL;
}
#ifdef USE_XCURSOR
if (X11Cursor != NULL)
{
SDL_SetCursor(FirstCursor);
SDL_FreeCursor(X11Cursor);
X11Cursor = NULL;
}
#endif
}
return true;
}
void I_SetMainWindowVisible(bool visible)
{
}
const char* I_GetBackEndName()
{
return "SDL";
}

View File

@ -1,505 +0,0 @@
#include <SDL.h>
#include <ctype.h>
#include "doomtype.h"
#include "c_dispatch.h"
#include "doomdef.h"
#include "doomstat.h"
#include "m_argv.h"
#include "i_input.h"
#include "v_video.h"
#include "d_main.h"
#include "d_event.h"
#include "d_gui.h"
#include "c_console.h"
#include "c_cvars.h"
#include "i_system.h"
#include "dikeys.h"
#include "templates.h"
#include "s_sound.h"
static void I_CheckGUICapture ();
static void I_CheckNativeMouse ();
bool GUICapture;
static bool NativeMouse = true;
extern int paused;
CVAR (Bool, use_mouse, true, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
CVAR (Bool, m_noprescale, false, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
CVAR (Bool, m_filter, false, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
CVAR (Bool, sdl_nokeyrepeat, false, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
EXTERN_CVAR (Bool, fullscreen)
extern int WaitingForKey, chatmodeon;
extern constate_e ConsoleState;
extern SDL_Surface *cursorSurface;
extern SDL_Rect cursorBlit;
static BYTE KeySymToDIK[SDLK_LAST], DownState[SDLK_LAST];
static WORD DIKToKeySym[256] =
{
0, SDLK_ESCAPE, '1', '2', '3', '4', '5', '6',
'7', '8', '9', '0', '-', '=', SDLK_BACKSPACE, SDLK_TAB,
'q', 'w', 'e', 'r', 't', 'y', 'u', 'i',
'o', 'p', '[', ']', SDLK_RETURN, SDLK_LCTRL, 'a', 's',
'd', 'f', 'g', 'h', 'j', 'k', 'l', SDLK_SEMICOLON,
'\'', '`', SDLK_LSHIFT, '\\', 'z', 'x', 'c', 'v',
'b', 'n', 'm', ',', '.', '/', SDLK_RSHIFT, SDLK_KP_MULTIPLY,
SDLK_LALT, ' ', SDLK_CAPSLOCK, SDLK_F1, SDLK_F2, SDLK_F3, SDLK_F4, SDLK_F5,
SDLK_F6, SDLK_F7, SDLK_F8, SDLK_F9, SDLK_F10, SDLK_NUMLOCK, SDLK_SCROLLOCK, SDLK_KP7,
SDLK_KP8, SDLK_KP9, SDLK_KP_MINUS, SDLK_KP4, SDLK_KP5, SDLK_KP6, SDLK_KP_PLUS, SDLK_KP1,
SDLK_KP2, SDLK_KP3, SDLK_KP0, SDLK_KP_PERIOD, 0, 0, 0, SDLK_F11,
SDLK_F12, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, SDLK_F13, SDLK_F14, SDLK_F15, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, SDLK_KP_EQUALS, 0, 0,
0, SDLK_AT, SDLK_COLON, 0, 0, 0, 0, 0,
0, 0, 0, 0, SDLK_KP_ENTER, SDLK_RCTRL, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, SDLK_KP_DIVIDE, 0, SDLK_SYSREQ,
SDLK_RALT, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, SDLK_PAUSE, 0, SDLK_HOME,
SDLK_UP, SDLK_PAGEUP, 0, SDLK_LEFT, 0, SDLK_RIGHT, 0, SDLK_END,
SDLK_DOWN, SDLK_PAGEDOWN, SDLK_INSERT, SDLK_DELETE, 0, 0, 0, 0,
0, 0, 0, SDLK_LSUPER, SDLK_RSUPER, SDLK_MENU, SDLK_POWER, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0
};
static void FlushDIKState (int low=0, int high=NUM_KEYS-1)
{
}
static void InitKeySymMap ()
{
for (int i = 0; i < 256; ++i)
{
KeySymToDIK[DIKToKeySym[i]] = i;
}
KeySymToDIK[0] = 0;
KeySymToDIK[SDLK_RSHIFT] = DIK_LSHIFT;
KeySymToDIK[SDLK_RCTRL] = DIK_LCONTROL;
KeySymToDIK[SDLK_RALT] = DIK_LMENU;
// Depending on your Linux flavor, you may get SDLK_PRINT or SDLK_SYSREQ
KeySymToDIK[SDLK_PRINT] = DIK_SYSRQ;
}
static void I_CheckGUICapture ()
{
bool wantCapt;
bool repeat;
int oldrepeat, interval;
SDL_GetKeyRepeat(&oldrepeat, &interval);
if (menuactive == MENU_Off)
{
wantCapt = ConsoleState == c_down || ConsoleState == c_falling || chatmodeon;
}
else
{
wantCapt = (menuactive == MENU_On || menuactive == MENU_OnNoPause);
}
if (wantCapt != GUICapture)
{
GUICapture = wantCapt;
if (wantCapt)
{
int x, y;
SDL_GetMouseState (&x, &y);
cursorBlit.x = x;
cursorBlit.y = y;
FlushDIKState ();
memset (DownState, 0, sizeof(DownState));
repeat = !sdl_nokeyrepeat;
SDL_EnableUNICODE (1);
}
else
{
repeat = false;
SDL_EnableUNICODE (0);
}
}
if (wantCapt)
{
repeat = !sdl_nokeyrepeat;
}
else
{
repeat = false;
}
if (repeat != (oldrepeat != 0))
{
if (repeat)
{
SDL_EnableKeyRepeat (SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL);
}
else
{
SDL_EnableKeyRepeat (0, 0);
}
}
}
void I_SetMouseCapture()
{
}
void I_ReleaseMouseCapture()
{
}
static void CenterMouse ()
{
SDL_WarpMouse (screen->GetWidth()/2, screen->GetHeight()/2);
SDL_PumpEvents ();
SDL_GetRelativeMouseState (NULL, NULL);
}
static void PostMouseMove (int x, int y)
{
static int lastx = 0, lasty = 0;
event_t ev = { 0,0,0,0,0,0,0 };
if (m_filter)
{
ev.x = (x + lastx) / 2;
ev.y = (y + lasty) / 2;
}
else
{
ev.x = x;
ev.y = y;
}
lastx = x;
lasty = y;
if (ev.x | ev.y)
{
ev.type = EV_Mouse;
D_PostEvent (&ev);
}
}
static void MouseRead ()
{
int x, y;
if (NativeMouse)
{
return;
}
SDL_GetRelativeMouseState (&x, &y);
if (!m_noprescale)
{
x *= 3;
y *= 2;
}
if (x | y)
{
CenterMouse ();
PostMouseMove (x, -y);
}
}
static void WheelMoved(event_t *event)
{
if (GUICapture)
{
if (event->type != EV_KeyUp)
{
SDLMod mod = SDL_GetModState();
event->type = EV_GUI_Event;
event->subtype = event->data1 == KEY_MWHEELUP ? EV_GUI_WheelUp : EV_GUI_WheelDown;
event->data1 = 0;
event->data3 = ((mod & KMOD_SHIFT) ? GKM_SHIFT : 0) |
((mod & KMOD_CTRL) ? GKM_CTRL : 0) |
((mod & KMOD_ALT) ? GKM_ALT : 0);
D_PostEvent(event);
}
}
else
{
D_PostEvent(event);
}
}
CUSTOM_CVAR(Int, mouse_capturemode, 1, CVAR_GLOBALCONFIG|CVAR_ARCHIVE)
{
if (self < 0) self = 0;
else if (self > 2) self = 2;
}
static bool inGame()
{
switch (mouse_capturemode)
{
default:
case 0:
return gamestate == GS_LEVEL;
case 1:
return gamestate == GS_LEVEL || gamestate == GS_INTERMISSION || gamestate == GS_FINALE;
case 2:
return true;
}
}
static void I_CheckNativeMouse ()
{
bool focus = (SDL_GetAppState() & (SDL_APPINPUTFOCUS|SDL_APPACTIVE))
== (SDL_APPINPUTFOCUS|SDL_APPACTIVE);
bool fs = (SDL_GetVideoSurface ()->flags & SDL_FULLSCREEN) != 0;
bool wantNative = !focus || (!use_mouse || GUICapture || paused || demoplayback || !inGame());
if (wantNative != NativeMouse)
{
NativeMouse = wantNative;
SDL_ShowCursor (wantNative ? cursorSurface == NULL : 0);
if (wantNative)
{
SDL_WM_GrabInput (SDL_GRAB_OFF);
FlushDIKState (KEY_MOUSE1, KEY_MOUSE8);
}
else
{
SDL_WM_GrabInput (SDL_GRAB_ON);
CenterMouse ();
}
}
}
void MessagePump (const SDL_Event &sev)
{
static int lastx = 0, lasty = 0;
int x, y;
event_t event = { 0,0,0,0,0,0,0 };
switch (sev.type)
{
case SDL_QUIT:
exit (0);
case SDL_ACTIVEEVENT:
if (sev.active.state == SDL_APPINPUTFOCUS)
{
if (sev.active.gain == 0)
{ // kill focus
FlushDIKState ();
}
S_SetSoundPaused(sev.active.gain);
}
break;
case SDL_MOUSEBUTTONDOWN:
case SDL_MOUSEBUTTONUP:
case SDL_MOUSEMOTION:
if (!GUICapture || sev.button.button == 4 || sev.button.button == 5)
{
if(sev.type != SDL_MOUSEMOTION)
{
event.type = sev.type == SDL_MOUSEBUTTONDOWN ? EV_KeyDown : EV_KeyUp;
/* These button mappings work with my Gentoo system using the
* evdev driver and a Logitech MX510 mouse. Whether or not they
* carry over to other Linux systems, I have no idea, but I sure
* hope so. (Though buttons 11 and 12 are kind of useless, since
* they also trigger buttons 4 and 5.)
*/
switch (sev.button.button)
{
case 1: event.data1 = KEY_MOUSE1; break;
case 2: event.data1 = KEY_MOUSE3; break;
case 3: event.data1 = KEY_MOUSE2; break;
case 4: event.data1 = KEY_MWHEELUP; break;
case 5: event.data1 = KEY_MWHEELDOWN; break;
case 6: event.data1 = KEY_MOUSE4; break; /* dunno; not generated by my mouse */
case 7: event.data1 = KEY_MOUSE5; break; /* ditto */
case 8: event.data1 = KEY_MOUSE4; break;
case 9: event.data1 = KEY_MOUSE5; break;
case 10: event.data1 = KEY_MOUSE6; break;
case 11: event.data1 = KEY_MOUSE7; break;
case 12: event.data1 = KEY_MOUSE8; break;
default: printf("SDL mouse button %s %d\n",
sev.type == SDL_MOUSEBUTTONDOWN ? "down" : "up", sev.button.button); break;
}
if (event.data1 != 0)
{
//DIKState[ActiveDIKState][event.data1] = (event.type == EV_KeyDown);
if (event.data1 == KEY_MWHEELUP || event.data1 == KEY_MWHEELDOWN)
{
WheelMoved(&event);
}
else
{
D_PostEvent(&event);
}
}
}
}
else if (sev.type == SDL_MOUSEMOTION || (sev.button.button >= 1 && sev.button.button <= 3))
{
int x, y;
SDL_GetMouseState (&x, &y);
cursorBlit.x = event.data1 = x;
cursorBlit.y = event.data2 = y;
event.type = EV_GUI_Event;
if(sev.type == SDL_MOUSEMOTION)
event.subtype = EV_GUI_MouseMove;
else
{
event.subtype = sev.type == SDL_MOUSEBUTTONDOWN ? EV_GUI_LButtonDown : EV_GUI_LButtonUp;
event.subtype += (sev.button.button - 1) * 3;
}
D_PostEvent(&event);
}
break;
case SDL_KEYDOWN:
case SDL_KEYUP:
if (sev.key.keysym.sym >= SDLK_LAST)
break;
if (!GUICapture)
{
event.type = sev.type == SDL_KEYDOWN ? EV_KeyDown : EV_KeyUp;
event.data1 = KeySymToDIK[sev.key.keysym.sym];
if (event.data1)
{
if (sev.key.keysym.sym < 256)
{
event.data2 = sev.key.keysym.sym;
}
D_PostEvent (&event);
}
}
else
{
event.type = EV_GUI_Event;
event.subtype = sev.type == SDL_KEYDOWN ? EV_GUI_KeyDown : EV_GUI_KeyUp;
event.data3 = ((sev.key.keysym.mod & KMOD_SHIFT) ? GKM_SHIFT : 0) |
((sev.key.keysym.mod & KMOD_CTRL) ? GKM_CTRL : 0) |
((sev.key.keysym.mod & KMOD_ALT) ? GKM_ALT : 0);
if (sev.key.keysym.sym < SDLK_LAST)
{
if (event.subtype == EV_GUI_KeyDown)
{
if (DownState[sev.key.keysym.sym])
{
event.subtype = EV_GUI_KeyRepeat;
}
DownState[sev.key.keysym.sym] = 1;
}
else
{
DownState[sev.key.keysym.sym] = 0;
}
}
switch (sev.key.keysym.sym)
{
case SDLK_KP_ENTER: event.data1 = GK_RETURN; break;
case SDLK_PAGEUP: event.data1 = GK_PGUP; break;
case SDLK_PAGEDOWN: event.data1 = GK_PGDN; break;
case SDLK_END: event.data1 = GK_END; break;
case SDLK_HOME: event.data1 = GK_HOME; break;
case SDLK_LEFT: event.data1 = GK_LEFT; break;
case SDLK_RIGHT: event.data1 = GK_RIGHT; break;
case SDLK_UP: event.data1 = GK_UP; break;
case SDLK_DOWN: event.data1 = GK_DOWN; break;
case SDLK_DELETE: event.data1 = GK_DEL; break;
case SDLK_ESCAPE: event.data1 = GK_ESCAPE; break;
case SDLK_F1: event.data1 = GK_F1; break;
case SDLK_F2: event.data1 = GK_F2; break;
case SDLK_F3: event.data1 = GK_F3; break;
case SDLK_F4: event.data1 = GK_F4; break;
case SDLK_F5: event.data1 = GK_F5; break;
case SDLK_F6: event.data1 = GK_F6; break;
case SDLK_F7: event.data1 = GK_F7; break;
case SDLK_F8: event.data1 = GK_F8; break;
case SDLK_F9: event.data1 = GK_F9; break;
case SDLK_F10: event.data1 = GK_F10; break;
case SDLK_F11: event.data1 = GK_F11; break;
case SDLK_F12: event.data1 = GK_F12; break;
default:
if (sev.key.keysym.sym < 256)
{
event.data1 = sev.key.keysym.sym;
}
break;
}
event.data2 = sev.key.keysym.unicode & 0xff;
if (event.data1 < 128)
{
event.data1 = toupper(event.data1);
D_PostEvent (&event);
}
if (!iscntrl(event.data2) && event.subtype != EV_GUI_KeyUp)
{
event.subtype = EV_GUI_Char;
event.data1 = event.data2;
event.data2 = sev.key.keysym.mod & KMOD_ALT;
event.data3 = 0;
D_PostEvent (&event);
}
}
break;
case SDL_JOYBUTTONDOWN:
case SDL_JOYBUTTONUP:
if (!GUICapture)
{
event.type = sev.type == SDL_JOYBUTTONDOWN ? EV_KeyDown : EV_KeyUp;
event.data1 = KEY_FIRSTJOYBUTTON + sev.jbutton.button;
if(event.data1 != 0)
D_PostEvent(&event);
}
break;
}
}
void I_GetEvent ()
{
SDL_Event sev;
while (SDL_PollEvent (&sev))
{
MessagePump (sev);
}
if (use_mouse)
{
MouseRead ();
}
}
void I_StartTic ()
{
I_CheckGUICapture ();
I_CheckNativeMouse ();
I_GetEvent ();
}
void I_ProcessJoysticks ();
void I_StartFrame ()
{
if (KeySymToDIK[SDLK_BACKSPACE] == 0)
{
InitKeySymMap ();
}
I_ProcessJoysticks();
}

View File

@ -37,7 +37,6 @@
#include <windows.h> #include <windows.h>
#include <mmsystem.h> #include <mmsystem.h>
#else #else
#include <SDL.h>
#include <sys/types.h> #include <sys/types.h>
#include <sys/wait.h> #include <sys/wait.h>
#include <sys/stat.h> #include <sys/stat.h>

View File

@ -13,7 +13,6 @@
#include <windows.h> #include <windows.h>
#include <mmsystem.h> #include <mmsystem.h>
#else #else
#include <SDL.h>
#define FALSE 0 #define FALSE 0
#define TRUE 1 #define TRUE 1
#endif #endif

View File

@ -38,6 +38,8 @@
#pragma once #pragma once
#endif #endif
#include <stdlib.h>
// Returns a file name suitable for use as a temp file. // Returns a file name suitable for use as a temp file.
// If you create a file with this name (and presumably you // If you create a file with this name (and presumably you
// will), it will be deleted automatically by this class's // will), it will be deleted automatically by this class's

View File

@ -907,20 +907,23 @@ enum CM_Flags
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CustomMissile) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CustomMissile)
{ {
ACTION_PARAM_START(6); ACTION_PARAM_START(7);
ACTION_PARAM_CLASS(ti, 0); ACTION_PARAM_CLASS(ti, 0);
ACTION_PARAM_FIXED(SpawnHeight, 1); ACTION_PARAM_FIXED(SpawnHeight, 1);
ACTION_PARAM_INT(Spawnofs_XY, 2); ACTION_PARAM_INT(Spawnofs_XY, 2);
ACTION_PARAM_ANGLE(Angle, 3); ACTION_PARAM_ANGLE(Angle, 3);
ACTION_PARAM_INT(flags, 4); ACTION_PARAM_INT(flags, 4);
ACTION_PARAM_ANGLE(pitch, 5); ACTION_PARAM_ANGLE(pitch, 5);
ACTION_PARAM_INT(ptr, 6);
AActor *ref = COPY_AAPTR(self, ptr);
int aimmode = flags & CMF_AIMMODE; int aimmode = flags & CMF_AIMMODE;
AActor * targ; AActor * targ;
AActor * missile; AActor * missile;
if (self->target != NULL || aimmode==2) if (ref != NULL || aimmode==2)
{ {
if (ti) if (ti)
{ {
@ -937,14 +940,14 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CustomMissile)
self->x += x; self->x += x;
self->y += y; self->y += y;
self->z += z; self->z += z;
missile = P_SpawnMissileXYZ(self->x, self->y, self->z + 32*FRACUNIT, self, self->target, ti, false); missile = P_SpawnMissileXYZ(self->x, self->y, self->z + 32*FRACUNIT, self, ref, ti, false);
self->x -= x; self->x -= x;
self->y -= y; self->y -= y;
self->z -= z; self->z -= z;
break; break;
case 1: case 1:
missile = P_SpawnMissileXYZ(self->x+x, self->y+y, self->z + self->GetBobOffset() + SpawnHeight, self, self->target, ti, false); missile = P_SpawnMissileXYZ(self->x+x, self->y+y, self->z + self->GetBobOffset() + SpawnHeight, self, ref, ti, false);
break; break;
case 2: case 2:
@ -1056,7 +1059,7 @@ enum CBA_Flags
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CustomBulletAttack) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CustomBulletAttack)
{ {
ACTION_PARAM_START(7); ACTION_PARAM_START(8);
ACTION_PARAM_ANGLE(Spread_XY, 0); ACTION_PARAM_ANGLE(Spread_XY, 0);
ACTION_PARAM_ANGLE(Spread_Z, 1); ACTION_PARAM_ANGLE(Spread_Z, 1);
ACTION_PARAM_INT(NumBullets, 2); ACTION_PARAM_INT(NumBullets, 2);
@ -1064,6 +1067,9 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CustomBulletAttack)
ACTION_PARAM_CLASS(pufftype, 4); ACTION_PARAM_CLASS(pufftype, 4);
ACTION_PARAM_FIXED(Range, 5); ACTION_PARAM_FIXED(Range, 5);
ACTION_PARAM_INT(Flags, 6); ACTION_PARAM_INT(Flags, 6);
ACTION_PARAM_INT(ptr, 7);
AActor *ref = COPY_AAPTR(self, ptr);
if(Range==0) Range=MISSILERANGE; if(Range==0) Range=MISSILERANGE;
@ -1072,9 +1078,12 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CustomBulletAttack)
int bslope = 0; int bslope = 0;
int laflags = (Flags & CBAF_NORANDOMPUFFZ)? LAF_NORANDOMPUFFZ : 0; int laflags = (Flags & CBAF_NORANDOMPUFFZ)? LAF_NORANDOMPUFFZ : 0;
if (self->target || (Flags & CBAF_AIMFACING)) if (ref || (Flags & CBAF_AIMFACING))
{ {
if (!(Flags & CBAF_AIMFACING)) A_FaceTarget (self); if (!(Flags & CBAF_AIMFACING))
{
A_Face(self, ref);
}
bangle = self->angle; bangle = self->angle;
if (!pufftype) pufftype = PClass::FindClass(NAME_BulletPuff); if (!pufftype) pufftype = PClass::FindClass(NAME_BulletPuff);
@ -4199,16 +4208,23 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Teleport)
fixed_t prevX = self->x; fixed_t prevX = self->x;
fixed_t prevY = self->y; fixed_t prevY = self->y;
fixed_t prevZ = self->z; fixed_t prevZ = self->z;
fixed_t aboveFloor = spot->z - spot->floorz;
fixed_t finalz = spot->floorz + aboveFloor;
if (spot->z + self->height > spot->ceilingz)
finalz = spot->ceilingz - self->height;
else if (spot->z < spot->floorz)
finalz = spot->floorz;
//Take precedence and cooperate with telefragging first. //Take precedence and cooperate with telefragging first.
bool teleResult = P_TeleportMove(self, spot->x, spot->y, spot->z, Flags & TF_TELEFRAG); bool teleResult = P_TeleportMove(self, spot->x, spot->y, finalz, Flags & TF_TELEFRAG);
if ((!(teleResult)) && (Flags & TF_FORCED))
{
//If for some reason the original move didn't work, regardless of telefrag, force it to move.
self->SetOrigin(spot->x, spot->y, spot->z);
teleResult = true;
if (Flags & TF_FORCED)
{
//If for some reason the original move didn't work, regardless of telefrag, force it to move.
self->SetOrigin(spot->x, spot->y, finalz);
teleResult = true;
} }
if (teleResult) if (teleResult)
@ -5016,48 +5032,74 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SetSpeed)
self->Speed = speed; self->Speed = speed;
} }
static bool DoCheckSpecies(AActor *mo, FName species, bool exclude)
{
return (!(species) || mo->Species == NAME_None || (species && ((exclude) ? (mo->Species != species) : (mo->Species == species))));
}
static bool DoCheckFilter(AActor *mo, const PClass *filter, bool exclude)
{
const PClass *c1 = mo->GetClass();
return (!(filter) || (filter == NULL) || (filter && ((exclude) ? (c1 != filter) : (c1 == filter))));
}
//=========================================================================== //===========================================================================
// //
// Common A_Damage handler // Common A_Damage handler
// //
// A_Damage* (int amount, str damagetype, int flags) // A_Damage* (int amount, str damagetype, int flags, str filter, str species)
// Damages the specified actor by the specified amount. Negative values heal. // Damages the specified actor by the specified amount. Negative values heal.
// Flags: See below.
// Filter: Specified actor is the only type allowed to be affected.
// Species: Specified species is the only type allowed to be affected.
//
// Examples:
// A_Damage(20,"Normal",DMSS_FOILINVUL,0,"DemonicSpecies") <--Only actors
// with a species "DemonicSpecies" will be affected. Use 0 to not filter by actor.
// //
//=========================================================================== //===========================================================================
enum DMSS enum DMSS
{ {
DMSS_FOILINVUL = 1, DMSS_FOILINVUL = 1, //Foil invulnerability
DMSS_AFFECTARMOR = 2, DMSS_AFFECTARMOR = 2, //Make it affect armor
DMSS_KILL = 4, DMSS_KILL = 4, //Damages them for their current health
DMSS_NOFACTOR = 8, DMSS_NOFACTOR = 8, //Ignore DamageFactors
DMSS_FOILBUDDHA = 16, DMSS_FOILBUDDHA = 16, //Can kill actors with Buddha flag, except the player.
DMSS_NOPROTECT = 32, DMSS_NOPROTECT = 32, //Ignores PowerProtection entirely
DMSS_EXFILTER = 64, //Changes filter into a blacklisted class instead of whitelisted.
DMSS_EXSPECIES = 128, // ^ but with species instead.
DMSS_EITHER = 256, //Allow either type or species to be affected.
}; };
static void DoDamage(AActor *dmgtarget, AActor *self, int amount, FName DamageType, int flags) static void DoDamage(AActor *dmgtarget, AActor *self, int amount, FName DamageType, int flags, const PClass *filter, FName species)
{ {
int dmgFlags = 0; bool filterpass = DoCheckFilter(dmgtarget, filter, (flags & DMSS_EXFILTER) ? true : false),
if (flags & DMSS_FOILINVUL) speciespass = DoCheckSpecies(dmgtarget, species, (flags & DMSS_EXSPECIES) ? true : false);
dmgFlags += DMG_FOILINVUL; if ((flags & DMSS_EITHER) ? (filterpass || speciespass) : (filterpass && speciespass))
if (flags & DMSS_FOILBUDDHA)
dmgFlags += DMG_FOILBUDDHA;
if ((flags & DMSS_KILL) || (flags & DMSS_NOFACTOR)) //Kill implies NoFactor
dmgFlags += DMG_NO_FACTOR;
if (!(flags & DMSS_AFFECTARMOR) || (flags & DMSS_KILL)) //Kill overrides AffectArmor
dmgFlags += DMG_NO_ARMOR;
if (flags & DMSS_KILL) //Kill adds the value of the damage done to it. Allows for more controlled extreme death types.
amount += dmgtarget->health;
if (flags & DMSS_NOPROTECT) //Ignore PowerProtection.
dmgFlags += DMG_NO_PROTECT;
if (amount > 0)
P_DamageMobj(dmgtarget, self, self, amount, DamageType, dmgFlags); //Should wind up passing them through just fine.
else if (amount < 0)
{ {
amount = -amount; int dmgFlags = 0;
P_GiveBody(dmgtarget, amount); if (flags & DMSS_FOILINVUL)
dmgFlags += DMG_FOILINVUL;
if (flags & DMSS_FOILBUDDHA)
dmgFlags += DMG_FOILBUDDHA;
if ((flags & DMSS_KILL) || (flags & DMSS_NOFACTOR)) //Kill implies NoFactor
dmgFlags += DMG_NO_FACTOR;
if (!(flags & DMSS_AFFECTARMOR) || (flags & DMSS_KILL)) //Kill overrides AffectArmor
dmgFlags += DMG_NO_ARMOR;
if (flags & DMSS_KILL) //Kill adds the value of the damage done to it. Allows for more controlled extreme death types.
amount += dmgtarget->health;
if (flags & DMSS_NOPROTECT) //Ignore PowerProtection.
dmgFlags += DMG_NO_PROTECT;
if (amount > 0)
P_DamageMobj(dmgtarget, self, self, amount, DamageType, dmgFlags); //Should wind up passing them through just fine.
else if (amount < 0)
{
amount = -amount;
P_GiveBody(dmgtarget, amount);
}
} }
} }
@ -5068,12 +5110,14 @@ static void DoDamage(AActor *dmgtarget, AActor *self, int amount, FName DamageTy
//=========================================================================== //===========================================================================
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_DamageSelf) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_DamageSelf)
{ {
ACTION_PARAM_START(3); ACTION_PARAM_START(5);
ACTION_PARAM_INT(amount, 0); ACTION_PARAM_INT(amount, 0);
ACTION_PARAM_NAME(DamageType, 1); ACTION_PARAM_NAME(DamageType, 1);
ACTION_PARAM_INT(flags, 2); ACTION_PARAM_INT(flags, 2);
ACTION_PARAM_CLASS(filter, 3);
ACTION_PARAM_NAME(species, 4);
DoDamage(self, self, amount, DamageType, flags); DoDamage(self, self, amount, DamageType, flags, filter, species);
} }
//=========================================================================== //===========================================================================
@ -5083,12 +5127,17 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_DamageSelf)
//=========================================================================== //===========================================================================
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_DamageTarget) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_DamageTarget)
{ {
ACTION_PARAM_START(3); ACTION_PARAM_START(5);
ACTION_PARAM_INT(amount, 0); ACTION_PARAM_INT(amount, 0);
ACTION_PARAM_NAME(DamageType, 1); ACTION_PARAM_NAME(DamageType, 1);
ACTION_PARAM_INT(flags, 2); ACTION_PARAM_INT(flags, 2);
ACTION_PARAM_CLASS(filter, 3);
ACTION_PARAM_NAME(species, 4);
if (self->target != NULL) DoDamage(self->target, self, amount, DamageType, flags); if (self->target != NULL)
{
DoDamage(self->target, self, amount, DamageType, flags, filter, species);
}
} }
//=========================================================================== //===========================================================================
@ -5098,12 +5147,17 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_DamageTarget)
//=========================================================================== //===========================================================================
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_DamageTracer) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_DamageTracer)
{ {
ACTION_PARAM_START(3); ACTION_PARAM_START(5);
ACTION_PARAM_INT(amount, 0); ACTION_PARAM_INT(amount, 0);
ACTION_PARAM_NAME(DamageType, 1); ACTION_PARAM_NAME(DamageType, 1);
ACTION_PARAM_INT(flags, 2); ACTION_PARAM_INT(flags, 2);
ACTION_PARAM_CLASS(filter, 3);
ACTION_PARAM_NAME(species, 4);
if (self->tracer != NULL) DoDamage(self->tracer, self, amount, DamageType, flags); if (self->tracer != NULL)
{
DoDamage(self->tracer, self, amount, DamageType, flags, filter, species);
}
} }
//=========================================================================== //===========================================================================
@ -5113,12 +5167,17 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_DamageTracer)
//=========================================================================== //===========================================================================
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_DamageMaster) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_DamageMaster)
{ {
ACTION_PARAM_START(3); ACTION_PARAM_START(5);
ACTION_PARAM_INT(amount, 0); ACTION_PARAM_INT(amount, 0);
ACTION_PARAM_NAME(DamageType, 1); ACTION_PARAM_NAME(DamageType, 1);
ACTION_PARAM_INT(flags, 2); ACTION_PARAM_INT(flags, 2);
ACTION_PARAM_CLASS(filter, 3);
ACTION_PARAM_NAME(species, 4);
if (self->master != NULL) DoDamage(self->master, self, amount, DamageType, flags); if (self->master != NULL)
{
DoDamage(self->master, self, amount, DamageType, flags, filter, species);
}
} }
//=========================================================================== //===========================================================================
@ -5128,17 +5187,22 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_DamageMaster)
//=========================================================================== //===========================================================================
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_DamageChildren) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_DamageChildren)
{ {
ACTION_PARAM_START(3); ACTION_PARAM_START(5);
ACTION_PARAM_INT(amount, 0); ACTION_PARAM_INT(amount, 0);
ACTION_PARAM_NAME(DamageType, 1); ACTION_PARAM_NAME(DamageType, 1);
ACTION_PARAM_INT(flags, 2); ACTION_PARAM_INT(flags, 2);
ACTION_PARAM_CLASS(filter, 3);
ACTION_PARAM_NAME(species, 4);
TThinkerIterator<AActor> it; TThinkerIterator<AActor> it;
AActor * mo; AActor * mo;
while ( (mo = it.Next()) ) while ( (mo = it.Next()) )
{ {
if (mo->master == self) DoDamage(mo, self, amount, DamageType, flags); if (mo->master == self)
{
DoDamage(mo, self, amount, DamageType, flags, filter, species);
}
} }
} }
@ -5149,10 +5213,12 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_DamageChildren)
//=========================================================================== //===========================================================================
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_DamageSiblings) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_DamageSiblings)
{ {
ACTION_PARAM_START(3); ACTION_PARAM_START(5);
ACTION_PARAM_INT(amount, 0); ACTION_PARAM_INT(amount, 0);
ACTION_PARAM_NAME(DamageType, 1); ACTION_PARAM_NAME(DamageType, 1);
ACTION_PARAM_INT(flags, 2); ACTION_PARAM_INT(flags, 2);
ACTION_PARAM_CLASS(filter, 3);
ACTION_PARAM_NAME(species, 4);
TThinkerIterator<AActor> it; TThinkerIterator<AActor> it;
AActor * mo; AActor * mo;
@ -5161,7 +5227,10 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_DamageSiblings)
{ {
while ((mo = it.Next())) while ((mo = it.Next()))
{ {
if (mo->master == self->master && mo != self) DoDamage(mo, self, amount, DamageType, flags); if (mo->master == self->master && mo != self)
{
DoDamage(mo, self, amount, DamageType, flags, filter, species);
}
} }
} }
} }
@ -5174,35 +5243,44 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_DamageSiblings)
//=========================================================================== //===========================================================================
enum KILS enum KILS
{ {
KILS_FOILINVUL = 1 << 0, KILS_FOILINVUL = 1 << 0,
KILS_KILLMISSILES = 1 << 1, KILS_KILLMISSILES = 1 << 1,
KILS_NOMONSTERS = 1 << 2, KILS_NOMONSTERS = 1 << 2,
KILS_FOILBUDDHA = 1 << 3, KILS_FOILBUDDHA = 1 << 3,
KILS_EXFILTER = 1 << 4,
KILS_EXSPECIES = 1 << 5,
KILS_EITHER = 1 << 6,
}; };
static void DoKill(AActor *killtarget, AActor *self, FName damagetype, int flags) static void DoKill(AActor *killtarget, AActor *self, FName damagetype, int flags, const PClass *filter, FName species)
{ {
int dmgFlags = DMG_NO_ARMOR + DMG_NO_FACTOR; bool filterpass = DoCheckFilter(killtarget, filter, (flags & KILS_EXFILTER) ? true : false),
speciespass = DoCheckSpecies(killtarget, species, (flags & KILS_EXSPECIES) ? true : false);
if (KILS_FOILINVUL) if ((flags & KILS_EITHER) ? (filterpass || speciespass) : (filterpass && speciespass)) //Check this first. I think it'll save the engine a lot more time this way.
dmgFlags += DMG_FOILINVUL;
if (KILS_FOILBUDDHA)
dmgFlags += DMG_FOILBUDDHA;
if ((killtarget->flags & MF_MISSILE) && (flags & KILS_KILLMISSILES))
{ {
//[MC] Now that missiles can set masters, lets put in a check to properly destroy projectiles. BUT FIRST! New feature~! int dmgFlags = DMG_NO_ARMOR + DMG_NO_FACTOR;
//Check to see if it's invulnerable. Disregarded if foilinvul is on, but never works on a missile with NODAMAGE
//since that's the whole point of it. if (KILS_FOILINVUL)
if ((!(killtarget->flags2 & MF2_INVULNERABLE) || (flags & KILS_FOILINVUL)) && dmgFlags += DMG_FOILINVUL;
(!(killtarget->flags2 & MF7_BUDDHA) || (flags & KILS_FOILBUDDHA)) && !(killtarget->flags5 & MF5_NODAMAGE)) if (KILS_FOILBUDDHA)
dmgFlags += DMG_FOILBUDDHA;
if ((killtarget->flags & MF_MISSILE) && (flags & KILS_KILLMISSILES))
{ {
P_ExplodeMissile(killtarget, NULL, NULL); //[MC] Now that missiles can set masters, lets put in a check to properly destroy projectiles. BUT FIRST! New feature~!
//Check to see if it's invulnerable. Disregarded if foilinvul is on, but never works on a missile with NODAMAGE
//since that's the whole point of it.
if ((!(killtarget->flags2 & MF2_INVULNERABLE) || (flags & KILS_FOILINVUL)) &&
(!(killtarget->flags2 & MF7_BUDDHA) || (flags & KILS_FOILBUDDHA)) && !(killtarget->flags5 & MF5_NODAMAGE))
{
P_ExplodeMissile(killtarget, NULL, NULL);
}
} }
} if (!(flags & KILS_NOMONSTERS))
if (!(flags & KILS_NOMONSTERS)) {
{
P_DamageMobj(killtarget, self, self, killtarget->health, damagetype, dmgFlags); P_DamageMobj(killtarget, self, self, killtarget->health, damagetype, dmgFlags);
}
} }
} }
@ -5214,11 +5292,16 @@ static void DoKill(AActor *killtarget, AActor *self, FName damagetype, int flags
//=========================================================================== //===========================================================================
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_KillTarget) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_KillTarget)
{ {
ACTION_PARAM_START(2); ACTION_PARAM_START(4);
ACTION_PARAM_NAME(damagetype, 0); ACTION_PARAM_NAME(damagetype, 0);
ACTION_PARAM_INT(flags, 1); ACTION_PARAM_INT(flags, 1);
ACTION_PARAM_CLASS(filter, 2);
ACTION_PARAM_NAME(species, 3);
if (self->target != NULL) DoKill(self->target, self, damagetype, flags); if (self->target != NULL)
{
DoKill(self->target, self, damagetype, flags, filter, species);
}
} }
//=========================================================================== //===========================================================================
@ -5228,11 +5311,16 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_KillTarget)
//=========================================================================== //===========================================================================
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_KillTracer) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_KillTracer)
{ {
ACTION_PARAM_START(2); ACTION_PARAM_START(4);
ACTION_PARAM_NAME(damagetype, 0); ACTION_PARAM_NAME(damagetype, 0);
ACTION_PARAM_INT(flags, 1); ACTION_PARAM_INT(flags, 1);
ACTION_PARAM_CLASS(filter, 2);
ACTION_PARAM_NAME(species, 3);
if (self->tracer != NULL) DoKill(self->tracer, self, damagetype, flags); if (self->tracer != NULL)
{
DoKill(self->tracer, self, damagetype, flags, filter, species);
}
} }
//=========================================================================== //===========================================================================
@ -5242,11 +5330,16 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_KillTracer)
//=========================================================================== //===========================================================================
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_KillMaster) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_KillMaster)
{ {
ACTION_PARAM_START(2); ACTION_PARAM_START(4);
ACTION_PARAM_NAME(damagetype, 0); ACTION_PARAM_NAME(damagetype, 0);
ACTION_PARAM_INT(flags, 1); ACTION_PARAM_INT(flags, 1);
ACTION_PARAM_CLASS(filter, 2);
ACTION_PARAM_NAME(species, 3);
if (self->master != NULL) DoKill(self->master, self, damagetype, flags); if (self->master != NULL)
{
DoKill(self->master, self, damagetype, flags, filter, species);
}
} }
//=========================================================================== //===========================================================================
@ -5256,16 +5349,21 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_KillMaster)
//=========================================================================== //===========================================================================
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_KillChildren) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_KillChildren)
{ {
ACTION_PARAM_START(2); ACTION_PARAM_START(4);
ACTION_PARAM_NAME(damagetype, 0); ACTION_PARAM_NAME(damagetype, 0);
ACTION_PARAM_INT(flags, 1); ACTION_PARAM_INT(flags, 1);
ACTION_PARAM_CLASS(filter, 2);
ACTION_PARAM_NAME(species, 3);
TThinkerIterator<AActor> it; TThinkerIterator<AActor> it;
AActor *mo; AActor *mo;
while ( (mo = it.Next()) ) while ( (mo = it.Next()) )
{ {
if (mo->master == self) DoKill(mo, self, damagetype, flags); if (mo->master == self)
{
DoKill(mo, self, damagetype, flags, filter, species);
}
} }
} }
@ -5276,9 +5374,11 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_KillChildren)
//=========================================================================== //===========================================================================
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_KillSiblings) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_KillSiblings)
{ {
ACTION_PARAM_START(2); ACTION_PARAM_START(4);
ACTION_PARAM_NAME(damagetype, 0); ACTION_PARAM_NAME(damagetype, 0);
ACTION_PARAM_INT(flags, 1); ACTION_PARAM_INT(flags, 1);
ACTION_PARAM_CLASS(filter, 2);
ACTION_PARAM_NAME(species, 3);
TThinkerIterator<AActor> it; TThinkerIterator<AActor> it;
AActor *mo; AActor *mo;
@ -5287,7 +5387,10 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_KillSiblings)
{ {
while ( (mo = it.Next()) ) while ( (mo = it.Next()) )
{ {
if (mo->master == self->master && mo != self) DoKill(mo, self, damagetype, flags); if (mo->master == self->master && mo != self)
{
DoKill(mo, self, damagetype, flags, filter, species);
}
} }
} }
} }
@ -5300,29 +5403,37 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_KillSiblings)
enum RMVF_flags enum RMVF_flags
{ {
RMVF_MISSILES = 1 << 0, RMVF_MISSILES = 1 << 0,
RMVF_NOMONSTERS = 1 << 1, RMVF_NOMONSTERS = 1 << 1,
RMVF_MISC = 1 << 2, RMVF_MISC = 1 << 2,
RMVF_EVERYTHING = 1 << 3, RMVF_EVERYTHING = 1 << 3,
RMVF_EXFILTER = 1 << 4,
RMVF_EXSPECIES = 1 << 5,
RMVF_EITHER = 1 << 6,
}; };
static void DoRemove(AActor *removetarget, int flags) static void DoRemove(AActor *removetarget, int flags, const PClass *filter, FName species)
{ {
if ((flags & RMVF_EVERYTHING)) bool filterpass = DoCheckFilter(removetarget, filter, (flags & RMVF_EXFILTER) ? true : false),
speciespass = DoCheckSpecies(removetarget, species, (flags & RMVF_EXSPECIES) ? true : false);
if ((flags & RMVF_EITHER) ? (filterpass || speciespass) : (filterpass && speciespass))
{ {
P_RemoveThing(removetarget); if ((flags & RMVF_EVERYTHING))
} {
if ((flags & RMVF_MISC) && !((removetarget->flags3 & MF3_ISMONSTER) && (removetarget->flags & MF_MISSILE))) P_RemoveThing(removetarget);
{ }
P_RemoveThing(removetarget); if ((flags & RMVF_MISC) && !((removetarget->flags3 & MF3_ISMONSTER) && (removetarget->flags & MF_MISSILE)))
} {
if ((removetarget->flags3 & MF3_ISMONSTER) && !(flags & RMVF_NOMONSTERS)) P_RemoveThing(removetarget);
{ }
P_RemoveThing(removetarget); if ((removetarget->flags3 & MF3_ISMONSTER) && !(flags & RMVF_NOMONSTERS))
} {
if ((removetarget->flags & MF_MISSILE) && (flags & RMVF_MISSILES)) P_RemoveThing(removetarget);
{ }
P_RemoveThing(removetarget); if ((removetarget->flags & MF_MISSILE) && (flags & RMVF_MISSILES))
{
P_RemoveThing(removetarget);
}
} }
} }
@ -5333,11 +5444,14 @@ static void DoRemove(AActor *removetarget, int flags)
//=========================================================================== //===========================================================================
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_RemoveTarget) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_RemoveTarget)
{ {
ACTION_PARAM_START(1); ACTION_PARAM_START(2);
ACTION_PARAM_INT(flags, 0); ACTION_PARAM_INT(flags, 0);
if (self->master != NULL) ACTION_PARAM_CLASS(filter, 1);
ACTION_PARAM_NAME(species, 2);
if (self->target != NULL)
{ {
DoRemove(self->target, flags); DoRemove(self->target, flags, filter, species);
} }
} }
@ -5348,11 +5462,14 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_RemoveTarget)
//=========================================================================== //===========================================================================
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_RemoveTracer) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_RemoveTracer)
{ {
ACTION_PARAM_START(1); ACTION_PARAM_START(2);
ACTION_PARAM_INT(flags, 0); ACTION_PARAM_INT(flags, 0);
if (self->master != NULL) ACTION_PARAM_CLASS(filter, 1);
ACTION_PARAM_NAME(species, 2);
if (self->tracer != NULL)
{ {
DoRemove(self->tracer, flags); DoRemove(self->tracer, flags, filter, species);
} }
} }
@ -5363,11 +5480,14 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_RemoveTracer)
//=========================================================================== //===========================================================================
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_RemoveMaster) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_RemoveMaster)
{ {
ACTION_PARAM_START(1); ACTION_PARAM_START(2);
ACTION_PARAM_INT(flags, 0); ACTION_PARAM_INT(flags, 0);
ACTION_PARAM_CLASS(filter, 1);
ACTION_PARAM_NAME(species, 2);
if (self->master != NULL) if (self->master != NULL)
{ {
DoRemove(self->master, flags); DoRemove(self->master, flags, filter, species);
} }
} }
@ -5380,15 +5500,18 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_RemoveChildren)
{ {
TThinkerIterator<AActor> it; TThinkerIterator<AActor> it;
AActor *mo; AActor *mo;
ACTION_PARAM_START(2); ACTION_PARAM_START(4);
ACTION_PARAM_BOOL(removeall, 0); ACTION_PARAM_BOOL(removeall, 0);
ACTION_PARAM_INT(flags, 1); ACTION_PARAM_INT(flags, 1);
ACTION_PARAM_CLASS(filter, 2);
ACTION_PARAM_NAME(species, 3);
while ((mo = it.Next()) != NULL) while ((mo = it.Next()) != NULL)
{ {
if (mo->master == self && (mo->health <= 0 || removeall)) if (mo->master == self && (mo->health <= 0 || removeall))
{ {
DoRemove(mo, flags); DoRemove(mo, flags, filter, species);
} }
} }
} }
@ -5402,9 +5525,11 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_RemoveSiblings)
{ {
TThinkerIterator<AActor> it; TThinkerIterator<AActor> it;
AActor *mo; AActor *mo;
ACTION_PARAM_START(2); ACTION_PARAM_START(4);
ACTION_PARAM_BOOL(removeall, 0); ACTION_PARAM_BOOL(removeall, 0);
ACTION_PARAM_INT(flags, 1); ACTION_PARAM_INT(flags, 1);
ACTION_PARAM_CLASS(filter, 2);
ACTION_PARAM_NAME(species, 3);
if (self->master != NULL) if (self->master != NULL)
{ {
@ -5412,7 +5537,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_RemoveSiblings)
{ {
if (mo->master == self->master && mo != self && (mo->health <= 0 || removeall)) if (mo->master == self->master && mo != self && (mo->health <= 0 || removeall))
{ {
DoRemove(mo, flags); DoRemove(mo, flags, filter, species);
} }
} }
} }
@ -5425,15 +5550,16 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_RemoveSiblings)
//=========================================================================== //===========================================================================
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Remove) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Remove)
{ {
ACTION_PARAM_START(2); ACTION_PARAM_START(4);
ACTION_PARAM_INT(removee, 0); ACTION_PARAM_INT(removee, 0);
ACTION_PARAM_INT(flags, 1); ACTION_PARAM_INT(flags, 1);
ACTION_PARAM_CLASS(filter, 2);
ACTION_PARAM_NAME(species, 3);
AActor *reference = COPY_AAPTR(self, removee); AActor *reference = COPY_AAPTR(self, removee);
if (reference != NULL) if (reference != NULL)
{ {
DoRemove(reference, flags); DoRemove(reference, flags, filter, species);
} }
} }

View File

@ -371,7 +371,7 @@ static FxExpression *ParseExpression0 (FScanner &sc, const PClass *cls)
return new FxRandom(rng, min, max, sc); return new FxRandom(rng, min, max, sc);
} }
else if (sc.CheckToken(TK_Pick)) else if (sc.CheckToken(TK_RandomPick))
{ {
FRandom *rng; FRandom *rng;
TArray<FxExpression*> list; TArray<FxExpression*> list;
@ -390,17 +390,15 @@ static FxExpression *ParseExpression0 (FScanner &sc, const PClass *cls)
} }
sc.MustGetToken('('); sc.MustGetToken('(');
while (!(sc.CheckToken(')'))) for (;;)
{ {
FxExpression *min = ParseExpressionM(sc, cls); FxExpression *expr = ParseExpressionM(sc, cls);
list.Push(min); list.Push(expr);
if (sc.CheckToken(')')) if (sc.CheckToken(')'))
break; break;
else sc.MustGetToken(',');
sc.MustGetToken(',');
} }
return new FxRandomPick(rng, list, sc);
return new FxPick(rng, list, sc);
} }
else if (sc.CheckToken(TK_FRandom)) else if (sc.CheckToken(TK_FRandom))
{ {

View File

@ -559,7 +559,7 @@ public:
// //
//========================================================================== //==========================================================================
class FxPick : public FxExpression class FxRandomPick : public FxExpression
{ {
protected: protected:
FRandom * rng; FRandom * rng;
@ -567,8 +567,8 @@ protected:
public: public:
FxPick(FRandom *, TArray<FxExpression*> mi, const FScriptPosition &pos); FxRandomPick(FRandom *, TArray<FxExpression*> mi, const FScriptPosition &pos);
~FxPick(); ~FxRandomPick();
FxExpression *Resolve(FCompileContext&); FxExpression *Resolve(FCompileContext&);
ExpVal EvalExpression(AActor *self); ExpVal EvalExpression(AActor *self);

View File

@ -1696,7 +1696,7 @@ ExpVal FxRandom::EvalExpression (AActor *self)
// //
// //
//========================================================================== //==========================================================================
FxPick::FxPick(FRandom * r, TArray<FxExpression*> mi, const FScriptPosition &pos) FxRandomPick::FxRandomPick(FRandom * r, TArray<FxExpression*> mi, const FScriptPosition &pos)
: FxExpression(pos) : FxExpression(pos)
{ {
for (unsigned int index = 0; index < mi.Size(); index++) for (unsigned int index = 0; index < mi.Size(); index++)
@ -1713,7 +1713,7 @@ FxPick::FxPick(FRandom * r, TArray<FxExpression*> mi, const FScriptPosition &pos
// //
//========================================================================== //==========================================================================
FxPick::~FxPick() FxRandomPick::~FxRandomPick()
{ {
} }
@ -1723,7 +1723,7 @@ FxPick::~FxPick()
// //
//========================================================================== //==========================================================================
FxExpression *FxPick::Resolve(FCompileContext &ctx) FxExpression *FxRandomPick::Resolve(FCompileContext &ctx)
{ {
CHECKRESOLVED(); CHECKRESOLVED();
for (unsigned int index = 0; index < min.Size(); index++) for (unsigned int index = 0; index < min.Size(); index++)
@ -1741,7 +1741,7 @@ FxExpression *FxPick::Resolve(FCompileContext &ctx)
// //
//========================================================================== //==========================================================================
ExpVal FxPick::EvalExpression(AActor *self) ExpVal FxRandomPick::EvalExpression(AActor *self)
{ {
ExpVal val; ExpVal val;
val.Type = VAL_Int; val.Type = VAL_Int;

View File

@ -128,7 +128,6 @@ void DCanvas::DrawTextV(FFont *font, int normalcolor, int x, int y, const char *
{ {
va_list *more_p; va_list *more_p;
DWORD data; DWORD data;
void *ptrval;
switch (tag) switch (tag)
{ {
@ -150,15 +149,9 @@ void DCanvas::DrawTextV(FFont *font, int normalcolor, int x, int y, const char *
// We don't handle these. :( // We don't handle these. :(
case DTA_DestWidth: case DTA_DestWidth:
case DTA_DestHeight: case DTA_DestHeight:
*(DWORD *)tags = TAG_IGNORE;
data = va_arg (tags, DWORD);
break;
// Translation is specified explicitly by the text.
case DTA_Translation: case DTA_Translation:
*(DWORD *)tags = TAG_IGNORE; assert("Bad parameter for DrawText" && false);
ptrval = va_arg (tags, void*); return;
break;
case DTA_CleanNoMove_1: case DTA_CleanNoMove_1:
boolval = va_arg (tags, INTBOOL); boolval = va_arg (tags, INTBOOL);

View File

@ -204,8 +204,8 @@ ACTOR Actor native //: Thinker
action native A_StopSoundEx(coerce name slot); action native A_StopSoundEx(coerce name slot);
action native A_SeekerMissile(int threshold, int turnmax, int flags = 0, int chance = 50, int distance = 10); action native A_SeekerMissile(int threshold, int turnmax, int flags = 0, int chance = 50, int distance = 10);
action native A_Jump(int chance = 256, state label, ...); action native A_Jump(int chance = 256, state label, ...);
action native A_CustomMissile(class<Actor> missiletype, float spawnheight = 32, int spawnofs_xy = 0, float angle = 0, int flags = 0, float pitch = 0); action native A_CustomMissile(class<Actor> missiletype, float spawnheight = 32, int spawnofs_xy = 0, float angle = 0, int flags = 0, float pitch = 0, int ptr = AAPTR_TARGET);
action native A_CustomBulletAttack(float spread_xy, float spread_z, int numbullets, int damageperbullet, class<Actor> pufftype = "BulletPuff", float range = 0, int flags = 0); action native A_CustomBulletAttack(float spread_xy, float spread_z, int numbullets, int damageperbullet, class<Actor> pufftype = "BulletPuff", float range = 0, int flags = 0, int ptr = AAPTR_TARGET);
action native A_CustomRailgun(int damage, int spawnofs_xy = 0, color color1 = "", color color2 = "", int flags = 0, bool aim = false, float maxdiff = 0, class<Actor> pufftype = "BulletPuff", float spread_xy = 0, float spread_z = 0, float range = 0, int duration = 0, float sparsity = 1.0, float driftspeed = 1.0, class<Actor> spawnclass = "none", float spawnofs_z = 0); action native A_CustomRailgun(int damage, int spawnofs_xy = 0, color color1 = "", color color2 = "", int flags = 0, bool aim = false, float maxdiff = 0, class<Actor> pufftype = "BulletPuff", float spread_xy = 0, float spread_z = 0, float range = 0, int duration = 0, float sparsity = 1.0, float driftspeed = 1.0, class<Actor> spawnclass = "none", float spawnofs_z = 0);
action native A_JumpIfHealthLower(int health, state label, int ptr_selector = AAPTR_DEFAULT); action native A_JumpIfHealthLower(int health, state label, int ptr_selector = AAPTR_DEFAULT);
action native A_JumpIfCloser(float distance, state label); action native A_JumpIfCloser(float distance, state label);
@ -237,12 +237,6 @@ ACTOR Actor native //: Thinker
action native A_ChangeFlag(string flagname, bool value); action native A_ChangeFlag(string flagname, bool value);
action native A_CheckFlag(string flagname, state label, int check_pointer = AAPTR_DEFAULT); action native A_CheckFlag(string flagname, state label, int check_pointer = AAPTR_DEFAULT);
action native A_JumpIf(bool expression, state label); action native A_JumpIf(bool expression, state label);
action native A_RemoveMaster(int flags = 0);
action native A_RemoveChildren(bool removeall = false, int flags = 0);
action native A_RemoveSiblings(bool removeall = false, int flags = 0);
action native A_KillMaster(name damagetype = "none", int flags = 0);
action native A_KillChildren(name damagetype = "none", int flags = 0);
action native A_KillSiblings(name damagetype = "none", int flags = 0);
action native A_RaiseMaster(bool copy = 0); action native A_RaiseMaster(bool copy = 0);
action native A_RaiseChildren(bool copy = 0); action native A_RaiseChildren(bool copy = 0);
action native A_RaiseSiblings(bool copy = 0); action native A_RaiseSiblings(bool copy = 0);
@ -250,7 +244,7 @@ ACTOR Actor native //: Thinker
action native A_CheckCeiling(state label); action native A_CheckCeiling(state label);
action native A_PlayerSkinCheck(state label); action native A_PlayerSkinCheck(state label);
action native A_BasicAttack(int meleedamage, sound meleesound, class<actor> missiletype, float missileheight); action native A_BasicAttack(int meleedamage, sound meleesound, class<actor> missiletype, float missileheight);
action native A_Teleport(state teleportstate = "", class<SpecialSpot> targettype = "BossSpot", class<Actor> fogtype = "TeleportFog", int flags = 0, float mindist = 128, float maxdist = 0); action native A_Teleport(state teleportstate = "", class<SpecialSpot> targettype = "BossSpot", class<Actor> fogtype = "TeleportFog", int flags = 0, float mindist = 0, float maxdist = 0);
action native A_Warp(int ptr_destination, float xofs = 0, float yofs = 0, float zofs = 0, float angle = 0, int flags = 0, state success_state = ""); action native A_Warp(int ptr_destination, float xofs = 0, float yofs = 0, float zofs = 0, float angle = 0, int flags = 0, state success_state = "");
action native A_ThrowGrenade(class<Actor> itemtype, float zheight = 0, float xyvel = 0, float zvel = 0, bool useammo = true); action native A_ThrowGrenade(class<Actor> itemtype, float zheight = 0, float xyvel = 0, float zvel = 0, bool useammo = true);
action native A_Weave(int xspeed, int yspeed, float xdist, float ydist); action native A_Weave(int xspeed, int yspeed, float xdist, float ydist);
@ -278,9 +272,6 @@ ACTOR Actor native //: Thinker
action native A_CheckLOF(state jump, int flags = 0, float range = 0, float minrange = 0, float angle = 0, float pitch = 0, float offsetheight = 0, float offsetwidth = 0, int ptr_target = AAPTR_DEFAULT); action native A_CheckLOF(state jump, int flags = 0, float range = 0, float minrange = 0, float angle = 0, float pitch = 0, float offsetheight = 0, float offsetwidth = 0, int ptr_target = AAPTR_DEFAULT);
action native A_JumpIfTargetInLOS (state label, float fov = 0, int flags = 0, float dist_max = 0, float dist_close = 0); action native A_JumpIfTargetInLOS (state label, float fov = 0, int flags = 0, float dist_max = 0, float dist_close = 0);
action native A_JumpIfInTargetLOS (state label, float fov = 0, int flags = 0, float dist_max = 0, float dist_close = 0); action native A_JumpIfInTargetLOS (state label, float fov = 0, int flags = 0, float dist_max = 0, float dist_close = 0);
action native A_DamageMaster(int amount, name damagetype = "none", int flags = 0);
action native A_DamageChildren(int amount, name damagetype = "none", int flags = 0);
action native A_DamageSiblings(int amount, name damagetype = "none", int flags = 0);
action native A_SelectWeapon(class<Weapon> whichweapon); action native A_SelectWeapon(class<Weapon> whichweapon);
action native A_Punch(); action native A_Punch();
action native A_Feathers(); action native A_Feathers();
@ -307,14 +298,23 @@ ACTOR Actor native //: Thinker
action native A_SetDamageType(name damagetype); action native A_SetDamageType(name damagetype);
action native A_DropItem(class<Actor> item, int dropamount = -1, int chance = 256); action native A_DropItem(class<Actor> item, int dropamount = -1, int chance = 256);
action native A_SetSpeed(float speed); action native A_SetSpeed(float speed);
action native A_DamageSelf(int amount, name damagetype = "none", int flags = 0); action native A_DamageSelf(int amount, name damagetype = "none", int flags = 0, class<Actor> filter = "None", name species = "None");
action native A_DamageTarget(int amount, name damagetype = "none", int flags = 0); action native A_DamageTarget(int amount, name damagetype = "none", int flags = 0, class<Actor> filter = "None", name species = "None");
action native A_DamageTracer(int amount, name damagetype = "none", int flags = 0); action native A_DamageMaster(int amount, name damagetype = "none", int flags = 0, class<Actor> filter = "None", name species = "None");
action native A_KillTarget(name damagetype = "none", int flags = 0); action native A_DamageTracer(int amount, name damagetype = "none", int flags = 0, class<Actor> filter = "None", name species = "None");
action native A_KillTracer(name damagetype = "none", int flags = 0); action native A_DamageChildren(int amount, name damagetype = "none", int flags = 0, class<Actor> filter = "None", name species = "None");
action native A_RemoveTarget(int flags = 0); action native A_DamageSiblings(int amount, name damagetype = "none", int flags = 0, class<Actor> filter = "None", name species = "None");
action native A_RemoveTracer(int flags = 0); action native A_KillTarget(name damagetype = "none", int flags = 0, class<Actor> filter = "None", name species = "None");
action native A_Remove(int removee, int flags = 0); action native A_KillMaster(name damagetype = "none", int flags = 0, class<Actor> filter = "None", name species = "None");
action native A_KillTracer(name damagetype = "none", int flags = 0, class<Actor> filter = "None", name species = "None");
action native A_KillChildren(name damagetype = "none", int flags = 0, class<Actor> filter = "None", name species = "None");
action native A_KillSiblings(name damagetype = "none", int flags = 0, class<Actor> filter = "None", name species = "None");
action native A_RemoveTarget(int flags = 0, class<Actor> filter = "None", name species = "None");
action native A_RemoveMaster(int flags = 0, class<Actor> filter = "None", name species = "None");
action native A_RemoveTracer(int flags = 0, class<Actor> filter = "None", name species = "None");
action native A_RemoveChildren(bool removeall = false, int flags = 0, class<Actor> filter = "None", name species = "None");
action native A_RemoveSiblings(bool removeall = false, int flags = 0, class<Actor> filter = "None", name species = "None");
action native A_Remove(int removee, int flags = 0, class<Actor> filter = "None", name species = "None");
action native A_GiveToChildren(class<Inventory> itemtype, int amount = 0); action native A_GiveToChildren(class<Inventory> itemtype, int amount = 0);
action native A_GiveToSiblings(class<Inventory> itemtype, int amount = 0); action native A_GiveToSiblings(class<Inventory> itemtype, int amount = 0);
action native A_TakeFromChildren(class<Inventory> itemtype, int amount = 0); action native A_TakeFromChildren(class<Inventory> itemtype, int amount = 0);

View File

@ -396,19 +396,30 @@ enum
}; };
// Flags for A_Kill (Master/Target/Tracer/Children/Siblings) series // Flags for A_Kill (Master/Target/Tracer/Children/Siblings) series
enum
const int KILS_FOILINVUL = 1; {
const int KILS_KILLMISSILES = 2; KILS_FOILINVUL = 0x00000001,
const int KILS_NOMONSTERS = 4; KILS_KILLMISSILES = 0x00000002,
const int KILS_FOILBUDDHA = 8; KILS_NOMONSTERS = 0x00000004,
KILS_FOILBUDDHA = 0x00000008,
KILS_EXFILTER = 0x00000010,
KILS_EXSPECIES = 0x00000020,
KILS_EITHER = 0x00000040,
};
// Flags for A_Damage (Master/Target/Tracer/Children/Siblings/Self) series // Flags for A_Damage (Master/Target/Tracer/Children/Siblings/Self) series
const int DMSS_FOILINVUL = 1; enum
const int DMSS_AFFECTARMOR = 2; {
const int DMSS_KILL = 4; DMSS_FOILINVUL = 0x00000001,
const int DMSS_NOFACTOR = 8; DMSS_AFFECTARMOR = 0x00000002,
const int DMSS_FOILBUDDHA = 16; DMSS_KILL = 0x00000004,
const int DMSS_NOPROTECT = 32; DMSS_NOFACTOR = 0x00000008,
DMSS_FOILBUDDHA = 0x00000010,
DMSS_NOPROTECT = 0x00000020,
DMSS_EXFILTER = 0x00000040,
DMSS_EXSPECIES = 0x00000080,
DMSS_EITHER = 0x00000100,
};
// Flags for A_AlertMonsters // Flags for A_AlertMonsters
const int AMF_TARGETEMITTER = 1; const int AMF_TARGETEMITTER = 1;
@ -418,10 +429,13 @@ const int AMF_EMITFROMTARGET = 4;
// Flags for A_Remove* // Flags for A_Remove*
enum enum
{ {
RMVF_MISSILES = 1 << 0, RMVF_MISSILES = 0x00000001,
RMVF_NOMONSTERS = 1 << 1, RMVF_NOMONSTERS = 0x00000002,
RMVF_MISC = 1 << 2, RMVF_MISC = 0x00000004,
RMVF_EVERYTHING = 1 << 3, RMVF_EVERYTHING = 0x00000008,
RMVF_EXFILTER = 0x00000010,
RMVF_EXSPECIES = 0x00000020,
RMVF_EITHER = 0x00000040,
}; };
// Flags for A_Fade* // Flags for A_Fade*