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 )
add_library( output_sdl MODULE output_sdl.c )
include_directories( ${FMOD_INCLUDE_DIR} ${SDL_INCLUDE_DIR} )
target_link_libraries( output_sdl SDL )
include_directories( ${FMOD_INCLUDE_DIR} ${SDL2_INCLUDE_DIR} )
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" )
add_custom_command( TARGET output_sdl POST_BUILD

View file

@ -192,19 +192,6 @@ else( WIN32 )
set( NO_GTK ON )
endif( GTK2_FOUND )
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 )
set( NASM_NAMES nasm )
@ -212,15 +199,12 @@ else( WIN32 )
add_definitions( -DNO_GTK=1 )
endif( NO_GTK )
# Non-Windows version also needs SDL
find_package( SDL )
if( NOT SDL_FOUND )
message( SEND_ERROR "SDL is required for building." )
endif( NOT SDL_FOUND )
# Non-Windows version also needs SDL except native OS X 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 )
include_directories( "${SDL_INCLUDE_DIR}" )
find_path( FPU_CONTROL_DIR fpu_control.h )
if( FPU_CONTROL_DIR )
@ -586,58 +570,45 @@ set( PLAT_WIN32_SOURCES
win32/st_start.cpp
win32/win32gliface.cpp
win32/win32video.cpp )
set( PLAT_SDL_SYSTEM_SOURCES
sdl/crashcatcher.c
sdl/hardware.cpp
sdl/i_cd.cpp
sdl/i_main.cpp
sdl/i_movie.cpp
sdl/i_steam.cpp
sdl/i_system.cpp
sdl/sdlvideo.cpp
sdl/sdlglvideo.cpp
sdl/st_start.cpp )
set( PLAT_SDL_SPECIAL_SOURCES
sdl/i_gui.cpp
sdl/i_input.cpp
sdl/i_joystick.cpp
sdl/i_timer.cpp )
set( PLAT_MAC_SOURCES
sdl/iwadpicker_cocoa.mm
sdl/i_system_cocoa.mm )
set( PLAT_POSIX_SOURCES
posix/i_cd.cpp
posix/i_movie.cpp
posix/i_steam.cpp
posix/i_system.cpp
posix/st_start.cpp )
set( PLAT_SDL_SOURCES
posix/sdl/crashcatcher.c
posix/sdl/hardware.cpp
posix/sdl/i_gui.cpp
posix/sdl/i_input.cpp
posix/sdl/i_joystick.cpp
posix/sdl/i_main.cpp
posix/sdl/i_timer.cpp
posix/sdl/sdlvideo.cpp )
set( PLAT_OSX_SOURCES
posix/osx/iwadpicker_cocoa.mm
posix/osx/zdoom.icns )
# Fixme: This must be adjusted to the new way of doing things:
# sdl/sdlglvideo.cpp
set( PLAT_COCOA_SOURCES
cocoa/HID_Config_Utilities.c
cocoa/HID_Error_Handler.c
cocoa/HID_Name_Lookup.c
cocoa/HID_Queue_Utilities.c
cocoa/HID_Utilities.c
cocoa/IOHIDDevice_.c
cocoa/IOHIDElement_.c
cocoa/ImmrHIDUtilAddOn.c
cocoa/i_backend_cocoa.mm
cocoa/i_joystick.cpp
cocoa/i_timer.cpp
cocoa/zdoom.icns )
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 )
posix/cocoa/hid/HID_Config_Utilities.c
posix/cocoa/hid/HID_Error_Handler.c
posix/cocoa/hid/HID_Name_Lookup.c
posix/cocoa/hid/HID_Queue_Utilities.c
posix/cocoa/hid/HID_Utilities.c
posix/cocoa/hid/IOHIDDevice_.c
posix/cocoa/hid/IOHIDElement_.c
posix/cocoa/hid/ImmrHIDUtilAddOn.c
posix/cocoa/critsec.cpp
posix/cocoa/i_backend_cocoa.mm
posix/cocoa/i_joystick.cpp
posix/cocoa/i_timer.cpp )
if( WIN32 )
set( SYSTEM_SOURCES_DIR win32 )
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 )
# 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 )
set( SYSTEM_SOURCES ${SYSTEM_SOURCES} win32/zdoom.rc )
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 )
set( SYSTEM_SOURCES_DIR sdl )
set( SYSTEM_SOURCES ${PLAT_SDL_SOURCES} )
if( APPLE )
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 )
set( SYSTEM_SOURCES_DIR posix posix/sdl )
set( SYSTEM_SOURCES ${PLAT_POSIX_SOURCES} ${PLAT_SDL_SOURCES} )
set( OTHER_SYSTEM_SOURCES ${PLAT_WIN32_SOURCES} ${PLAT_OSX_SOURCES} ${PLAT_COCOA_SOURCES} )
endif( WIN32 )
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
if( WIN32 )
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 )
set( EXTRA_HEADER_DIRS sdl/*.h )
set( EXTRA_HEADER_DIRS posix/*.h posix/sdl/*.h )
endif( WIN32 )
file( GLOB HEADER_FILES
${EXTRA_HEADER_DIRS}
@ -731,9 +718,11 @@ file( GLOB HEADER_FILES
menu/*.h
oplsynth/*.h
oplsynth/dosbox/*.h
posix/*.h
posix/cocoa/*.h
posix/sdl/*.h
r_data/*.h
resourcefiles/*.h
sdl/*.h
sfmt/*.h
sound/*.h
textures/*.h
@ -1302,7 +1291,7 @@ endif( ZD_CMAKE_COMPILER_IS_GNUCXX_COMPATIBLE )
if( APPLE )
set_target_properties(zdoom PROPERTIES
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.
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\\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("Cocoa Files" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/cocoa/.+")
source_group("Decorate++" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/thingdef/.+")
source_group("FraggleScript" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/fragglescript/.+")
source_group("Games\\Doom Game" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/g_doom/.+")
@ -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 Interface" FILES r_defs.h r_renderer.h r_sky.cpp r_sky.h r_state.h r_utility.cpp r_utility.h)
source_group("Resource Files" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/resourcefiles/.+")
source_group("SDL Files" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/sdl/.+")
source_group("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("Shared Game" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/g_shared/.+")
source_group("Versioning" FILES version.h win32/zdoom.rc)

View file

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

View file

@ -178,7 +178,10 @@ void FCajunMaster::End ()
{
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;
@ -216,19 +219,16 @@ bool FCajunMaster::SpawnBot (const char *name, int color)
"\\color\\cf df 90" //10 = Bleached Bone
};
botinfo_t *thebot;
int botshift;
botinfo_t *thebot = botinfo;
int botshift = 0;
if (name)
{
thebot = botinfo;
// Check if exist or already in the game.
botshift = 0;
while (thebot && stricmp (name, thebot->name))
{
thebot = thebot->next;
botshift++;
thebot = thebot->next;
}
if (thebot == NULL)
@ -246,27 +246,36 @@ bool FCajunMaster::SpawnBot (const char *name, int color)
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
{
Printf ("Couldn't spawn bot; no bot left in %s\n", BOTFILENAME);
return false;
//Spawn a random bot from bots.cfg if no name given.
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;
@ -478,7 +487,6 @@ void FCajunMaster::ForgetBots ()
}
botinfo = NULL;
loaded_bots = 0;
}
bool FCajunMaster::LoadBots ()
@ -486,6 +494,7 @@ bool FCajunMaster::LoadBots ()
FScanner sc;
FString tmp;
bool gotteam = false;
int loaded_bots = 0;
bglobal.ForgetBots ();
tmp = M_GetCajunPath(BOTFILENAME);
@ -602,9 +611,9 @@ bool FCajunMaster::LoadBots ()
newinfo->next = bglobal.botinfo;
newinfo->lastteam = TEAM_NONE;
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;
}

View file

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

View file

@ -669,25 +669,38 @@ void PlayerIsGone (int netnode, int netconsole)
{
int i;
if (!nodeingame[netnode])
return;
if (nodeingame[netnode])
{
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 (nodeingame[i])
break;
if (playeringame[netconsole])
{
players[netconsole].playerstate = PST_GONE;
}
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;
}
if (playeringame[netconsole])
{
players[netconsole].playerstate = PST_GONE;
}
nodeingame[netnode] = false;
nodejustleft[netnode] = false;
else return;
if (netconsole == Net_Arbitrator)
{
@ -790,7 +803,6 @@ void GetPackets (void)
else
{
nodeingame[netnode] = false;
playeringame[netconsole] = false;
nodejustleft[netnode] = true;
}
continue;
@ -1064,16 +1076,16 @@ void NetUpdate (void)
if (consoleplayer == Net_Arbitrator)
{
for (j = 0; j < doomcom.numnodes; j++)
{
if (nodeingame[j] && NetMode == NET_PacketServer)
{
count++;
}
}
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,
// and it also added the player being sent the packet to the count.
count -= 2;
@ -1203,12 +1215,15 @@ void NetUpdate (void)
netbuffer[0] |= NCMD_MULTI;
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];
netbuffer[k++] = playerfornode[j];
if (playeringame[j] && players[j].Bot == NULL && j != playerfornode[i] && j != consoleplayer)
{
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)
{
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)
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_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 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
double velz;
double thrust;

View file

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

View file

@ -49,11 +49,13 @@ public:
WORD operator [](FTextureID tex) const
{
if ((unsigned)tex.GetIndex() >= Types.Size()) return DefaultTerrainType;
WORD type = Types[tex.GetIndex()];
return type == 0xffff? DefaultTerrainType : type;
}
WORD operator [](int texnum) const
{
if ((unsigned)texnum >= Types.Size()) return DefaultTerrainType;
WORD type = Types[texnum];
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;
bool blocked;
@ -1073,23 +1073,27 @@ bool FPolyObj::RotatePolyobj (angle_t angle)
validcount++;
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)
{
for(unsigned i=0;i < Vertices.Size(); i++)
if (blocked)
{
Vertices[i]->x = PrevPts[i].x;
Vertices[i]->y = PrevPts[i].y;
for(unsigned i=0;i < Vertices.Size(); i++)
{
Vertices[i]->x = PrevPts[i].x;
Vertices[i]->y = PrevPts[i].y;
}
UpdateBBox();
LinkPolyobj();
return false;
}
UpdateBBox();
LinkPolyobj();
return false;
}
this->angle += angle;
LinkPolyobj();

View file

@ -74,7 +74,7 @@ struct FPolyObj
int GetMirror();
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 LinkPolyobj ();
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
#include "HID_Utilities_External.h"
#include "hid/HID_Utilities_External.h"
#include "d_event.h"
#include "doomdef.h"

View file

View file

@ -4,8 +4,6 @@
#include <pthread.h>
#include <libkern/OSAtomic.h>
#include <SDL.h>
#include "basictypes.h"
#include "basicinlines.h"
#include "doomdef.h"
@ -13,23 +11,36 @@
#include "templates.h"
static timeval s_startTicks;
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()
{
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
{
bool s_isTicFrozen;
timespec GetNextTickTime()
{
static const long MILLISECONDS_IN_SECOND = 1000;
@ -91,7 +102,7 @@ void* TimerThreadFunc(void*)
pthread_mutex_lock(&s_timerMutex);
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:
// __sync_add_and_fetch(&s_tics, 1);
@ -101,7 +112,7 @@ void* TimerThreadFunc(void*)
OSAtomicIncrement32(&s_tics);
}
s_timerStart = SDL_GetTicks();
s_timerStart = I_MSTime();
pthread_cond_broadcast(&s_timerEvent);
pthread_mutex_unlock(&s_timerMutex);
@ -122,7 +133,7 @@ int GetTimeThreaded(bool saveMS)
int WaitForTicThreaded(int prevTic)
{
assert(!g_isTicFrozen);
assert(!s_isTicFrozen);
while (s_tics <= prevTic)
{
@ -136,7 +147,7 @@ int WaitForTicThreaded(int prevTic)
void FreezeTimeThreaded(bool frozen)
{
g_isTicFrozen = frozen;
s_isTicFrozen = frozen;
}
} // unnamed namespace
@ -144,7 +155,7 @@ void FreezeTimeThreaded(bool frozen)
fixed_t I_GetTimeFrac(uint32* ms)
{
const uint32_t now = SDL_GetTicks();
const uint32_t now = I_MSTime();
if (NULL != ms)
{
@ -157,11 +168,13 @@ fixed_t I_GetTimeFrac(uint32* ms)
}
void I_InitTimer ()
void I_InitTimer()
{
assert(!s_timerInitialized);
s_timerInitialized = true;
gettimeofday(&s_startTicks, NULL);
pthread_cond_init (&s_timerEvent, NULL);
pthread_mutex_init(&s_timerMutex, NULL);
@ -172,7 +185,7 @@ void I_InitTimer ()
I_FreezeTime = FreezeTimeThreaded;
}
void I_ShutdownTimer ()
void I_ShutdownTimer()
{
if (!s_timerInitialized)
{

View file

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

View file

@ -1,96 +1,96 @@
/*
** hardware.h
**
**---------------------------------------------------------------------------
** Copyright 1998-2006 Randy Heit
** 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 __HARDWARE_H__
#define __HARDWARE_H__
#include "i_video.h"
#include "v_video.h"
// Semaphores
#ifdef __APPLE__
#include <mach/mach_init.h>
#include <mach/semaphore.h>
#include <mach/task.h>
typedef semaphore_t Semaphore;
#define SEMAPHORE_WAIT(sem) \
while(semaphore_wait(sem) != KERN_SUCCESS){}
#define SEMAPHORE_SIGNAL(sem) \
semaphore_signal(sem);
#define SEMAPHORE_INIT(sem, shared, value) \
semaphore_create(mach_task_self(), &sem, shared, value);
#else
#include <semaphore.h>
typedef sem_t Semaphore;
#define SEMAPHORE_WAIT(sem) \
do { \
while(sem_wait(&sem) != 0); \
int semValue; \
sem_getvalue(&sem, &semValue); \
if(semValue < 1) \
break; \
} while(true);
#define SEMAPHORE_SIGNAL(sem) \
sem_post(&sem);
#define SEMAPHORE_INIT(sem, shared, value) \
sem_init(&sem, shared, value);
#endif
class IVideo
{
public:
virtual ~IVideo () {}
virtual EDisplayType GetDisplayType () = 0;
virtual void SetWindowedScale (float scale) = 0;
virtual DFrameBuffer *CreateFrameBuffer (int width, int height, bool fs, DFrameBuffer *old) = 0;
virtual void StartModeIterator (int bits, bool fs) = 0;
virtual bool NextMode (int *width, int *height, bool *letterbox) = 0;
virtual bool SetResolution (int width, int height, int bits);
virtual void DumpAdapters();
};
void I_InitGraphics ();
void I_ShutdownGraphics ();
void I_CreateRenderer();
extern Semaphore FPSLimitSemaphore;
void I_SetFPSLimit(int limit);
extern IVideo *Video;
#endif // __HARDWARE_H__
/*
** hardware.h
**
**---------------------------------------------------------------------------
** Copyright 1998-2006 Randy Heit
** 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 __HARDWARE_H__
#define __HARDWARE_H__
#include "i_video.h"
#include "v_video.h"
// Semaphores
#ifdef __APPLE__
#include <mach/mach_init.h>
#include <mach/semaphore.h>
#include <mach/task.h>
typedef semaphore_t Semaphore;
#define SEMAPHORE_WAIT(sem) \
while(semaphore_wait(sem) != KERN_SUCCESS){}
#define SEMAPHORE_SIGNAL(sem) \
semaphore_signal(sem);
#define SEMAPHORE_INIT(sem, shared, value) \
semaphore_create(mach_task_self(), &sem, shared, value);
#else
#include <semaphore.h>
typedef sem_t Semaphore;
#define SEMAPHORE_WAIT(sem) \
do { \
while(sem_wait(&sem) != 0); \
int semValue; \
sem_getvalue(&sem, &semValue); \
if(semValue < 1) \
break; \
} while(true);
#define SEMAPHORE_SIGNAL(sem) \
sem_post(&sem);
#define SEMAPHORE_INIT(sem, shared, value) \
sem_init(&sem, shared, value);
#endif
class IVideo
{
public:
virtual ~IVideo () {}
virtual EDisplayType GetDisplayType () = 0;
virtual void SetWindowedScale (float scale) = 0;
virtual DFrameBuffer *CreateFrameBuffer (int width, int height, bool fs, DFrameBuffer *old) = 0;
virtual void StartModeIterator (int bits, bool fs) = 0;
virtual bool NextMode (int *width, int *height, bool *letterbox) = 0;
virtual bool SetResolution (int width, int height, int bits);
virtual void DumpAdapters();
};
void I_InitGraphics ();
void I_ShutdownGraphics ();
void I_CreateRenderer();
extern Semaphore FPSLimitSemaphore;
void I_SetFPSLimit(int limit);
extern IVideo *Video;
#endif // __HARDWARE_H__

View file

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

View file

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

View file

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

View file

@ -34,6 +34,10 @@
#include <sys/stat.h>
#ifdef __APPLE__
#include <CoreServices/CoreServices.h>
#endif // __APPLE__
#include "doomerrors.h"
#include "d_main.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.
// To do so, we read the virtual registry.
#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
{
SteamInstallFolders = ParseSteamRegistry(regPath);
@ -180,7 +195,7 @@ TArray<FString> I_GetSteamPath()
return result;
}
SteamInstallFolders.Push(OSX_FindApplicationSupport() + "/Steam/SteamApps/common");
SteamInstallFolders.Push(appSupportPath + "/Steam/SteamApps/common");
#else
char* home = getenv("HOME");
if(home != NULL && *home != '\0')

View file

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

View file

@ -1,170 +1,170 @@
// Emacs style mode select -*- C++ -*-
//-----------------------------------------------------------------------------
//
// $Id:$
//
// Copyright (C) 1993-1996 by id Software, Inc.
//
// This source is available for distribution and/or modification
// only under the terms of the DOOM Source Code License as
// published by id Software. All rights reserved.
//
// The source is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License
// for more details.
//
// DESCRIPTION:
// System specific interface stuff.
//
//-----------------------------------------------------------------------------
#ifndef __I_SYSTEM__
#define __I_SYSTEM__
#include <dirent.h>
#include <ctype.h>
#include "doomtype.h"
struct ticcmd_t;
struct WadStuff;
#ifndef SHARE_DIR
#define SHARE_DIR "/usr/local/share/"
#endif
// Index values into the LanguageIDs array
enum
{
LANGIDX_UserPreferred,
LANGIDX_UserDefault,
LANGIDX_SysPreferred,
LANGIDX_SysDefault
};
extern DWORD LanguageIDs[4];
extern void SetLanguageIDs ();
// Called by DoomMain.
void I_Init (void);
// Called by D_DoomLoop,
// returns current time in tics.
extern int (*I_GetTime) (bool saveMS);
// like I_GetTime, except it waits for a new tic before returning
extern int (*I_WaitForTic) (int);
// Freezes tic counting temporarily. While frozen, calls to I_GetTime()
// will always return the same value. This does not affect I_MSTime().
// You must also not call I_WaitForTic() while freezing time, since the
// tic will never arrive (unless it's the current one).
extern void (*I_FreezeTime) (bool frozen);
fixed_t I_GetTimeFrac (uint32 *ms);
// Return a seed value for the RNG.
unsigned int I_MakeRNGSeed();
//
// Called by D_DoomLoop,
// called before processing any tics in a frame
// (just after displaying a frame).
// Time consuming syncronous operations
// are performed here (joystick reading).
// Can call D_PostEvent.
//
void I_StartFrame (void);
//
// Called by D_DoomLoop,
// called before processing each tic in a frame.
// Quick syncronous operations are performed here.
// Can call D_PostEvent.
void I_StartTic (void);
// Asynchronous interrupt functions should maintain private queues
// that are read by the synchronous functions
// to be converted into events.
// Either returns a null ticcmd,
// or calls a loadable driver to build it.
// This ticcmd will then be modified by the gameloop
// for normal input.
ticcmd_t *I_BaseTiccmd (void);
// Called by M_Responder when quit is selected.
// Clean exit, displays sell blurb.
void I_Quit (void);
void I_Tactile (int on, int off, int total);
void STACK_ARGS I_Error (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);
#define atterm(t) addterm (t, #t)
void popterm ();
// Print a console string
void I_PrintStr (const char *str);
// Set the title string of the startup window
void I_SetIWADInfo ();
// Pick from multiple IWADs to use
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
// directories for IWADs if the user purchased any through Steam.
TArray<FString> I_GetSteamPath();
// The ini could not be saved at exit
bool I_WriteIniFailed ();
// [RH] Returns millisecond-accurate time
unsigned int I_MSTime (void);
unsigned int I_FPSTime();
class FTexture;
bool I_SetCursor(FTexture *);
// Directory searching routines
struct findstate_t
{
int count;
struct dirent **namelist;
int current;
};
void *I_FindFirst (const char *filespec, findstate_t *fileinfo);
int I_FindNext (void *handle, findstate_t *fileinfo);
int I_FindClose (void *handle);
int I_FindAttr (findstate_t *fileinfo);
#define I_FindName(a) ((a)->namelist[(a)->current]->d_name)
#define FA_RDONLY 1
#define FA_HIDDEN 2
#define FA_SYSTEM 4
#define FA_DIREC 8
#define FA_ARCH 16
static inline char *strlwr(char *str)
{
char *ptr = str;
while(*ptr)
{
*ptr = tolower(*ptr);
++ptr;
}
return str;
}
#endif
// Emacs style mode select -*- C++ -*-
//-----------------------------------------------------------------------------
//
// $Id:$
//
// Copyright (C) 1993-1996 by id Software, Inc.
//
// This source is available for distribution and/or modification
// only under the terms of the DOOM Source Code License as
// published by id Software. All rights reserved.
//
// The source is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License
// for more details.
//
// DESCRIPTION:
// System specific interface stuff.
//
//-----------------------------------------------------------------------------
#ifndef __I_SYSTEM__
#define __I_SYSTEM__
#include <dirent.h>
#include <ctype.h>
#include "doomtype.h"
struct ticcmd_t;
struct WadStuff;
#ifndef SHARE_DIR
#define SHARE_DIR "/usr/local/share/"
#endif
// Index values into the LanguageIDs array
enum
{
LANGIDX_UserPreferred,
LANGIDX_UserDefault,
LANGIDX_SysPreferred,
LANGIDX_SysDefault
};
extern DWORD LanguageIDs[4];
extern void SetLanguageIDs ();
// Called by DoomMain.
void I_Init (void);
// Called by D_DoomLoop,
// returns current time in tics.
extern int (*I_GetTime) (bool saveMS);
// like I_GetTime, except it waits for a new tic before returning
extern int (*I_WaitForTic) (int);
// Freezes tic counting temporarily. While frozen, calls to I_GetTime()
// will always return the same value. This does not affect I_MSTime().
// You must also not call I_WaitForTic() while freezing time, since the
// tic will never arrive (unless it's the current one).
extern void (*I_FreezeTime) (bool frozen);
fixed_t I_GetTimeFrac (uint32 *ms);
// Return a seed value for the RNG.
unsigned int I_MakeRNGSeed();
//
// Called by D_DoomLoop,
// called before processing any tics in a frame
// (just after displaying a frame).
// Time consuming syncronous operations
// are performed here (joystick reading).
// Can call D_PostEvent.
//
void I_StartFrame (void);
//
// Called by D_DoomLoop,
// called before processing each tic in a frame.
// Quick syncronous operations are performed here.
// Can call D_PostEvent.
void I_StartTic (void);
// Asynchronous interrupt functions should maintain private queues
// that are read by the synchronous functions
// to be converted into events.
// Either returns a null ticcmd,
// or calls a loadable driver to build it.
// This ticcmd will then be modified by the gameloop
// for normal input.
ticcmd_t *I_BaseTiccmd (void);
// Called by M_Responder when quit is selected.
// Clean exit, displays sell blurb.
void I_Quit (void);
void I_Tactile (int on, int off, int total);
void STACK_ARGS I_Error (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);
#define atterm(t) addterm (t, #t)
void popterm ();
// Print a console string
void I_PrintStr (const char *str);
// Set the title string of the startup window
void I_SetIWADInfo ();
// Pick from multiple IWADs to use
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
// directories for IWADs if the user purchased any through Steam.
TArray<FString> I_GetSteamPath();
// The ini could not be saved at exit
bool I_WriteIniFailed ();
// [RH] Returns millisecond-accurate time
unsigned int I_MSTime (void);
unsigned int I_FPSTime();
class FTexture;
bool I_SetCursor(FTexture *);
// Directory searching routines
struct findstate_t
{
int count;
struct dirent **namelist;
int current;
};
void *I_FindFirst (const char *filespec, findstate_t *fileinfo);
int I_FindNext (void *handle, findstate_t *fileinfo);
int I_FindClose (void *handle);
int I_FindAttr (findstate_t *fileinfo);
#define I_FindName(a) ((a)->namelist[(a)->current]->d_name)
#define FA_RDONLY 1
#define FA_HIDDEN 2
#define FA_SYSTEM 4
#define FA_DIREC 8
#define FA_ARCH 16
static inline char *strlwr(char *str)
{
char *ptr = str;
while(*ptr)
{
*ptr = tolower(*ptr);
++ptr;
}
return str;
}
#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 <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <sys/param.h>
#include <sys/ucontext.h>
#include <string.h>
#include <errno.h>
#include <limits.h>
#ifdef __linux__
#include <sys/prctl.h>
#ifndef PR_SET_PTRACER
#define PR_SET_PTRACER 0x59616d61
#endif
#elif defined (__APPLE__)
#include <signal.h>
#endif
static const char crash_switch[] = "--cc-handle-crash";
static const char fatal_err[] = "\n\n*** Fatal Error ***\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 exec_err[] = "!!! Failed to exec debug process\n";
static char argv0[PATH_MAX];
static char altstack[SIGSTKSZ];
static struct {
int signum;
pid_t pid;
int has_siginfo;
siginfo_t siginfo;
char buf[1024];
} crash_info;
static const struct {
const char *name;
int signum;
} signals[] = {
{ "Segmentation fault", SIGSEGV },
{ "Illegal instruction", SIGILL },
{ "FPU exception", SIGFPE },
{ "System BUS error", SIGBUS },
{ NULL, 0 }
};
static const struct {
int code;
const char *name;
} sigill_codes[] = {
#ifndef __FreeBSD__
{ ILL_ILLOPC, "Illegal opcode" },
{ ILL_ILLOPN, "Illegal operand" },
{ ILL_ILLADR, "Illegal addressing mode" },
{ ILL_ILLTRP, "Illegal trap" },
{ ILL_PRVOPC, "Privileged opcode" },
{ ILL_PRVREG, "Privileged register" },
{ ILL_COPROC, "Coprocessor error" },
{ ILL_BADSTK, "Internal stack error" },
#endif
{ 0, NULL }
};
static const struct {
int code;
const char *name;
} sigfpe_codes[] = {
{ FPE_INTDIV, "Integer divide by zero" },
{ FPE_INTOVF, "Integer overflow" },
{ FPE_FLTDIV, "Floating point divide by zero" },
{ FPE_FLTOVF, "Floating point overflow" },
{ FPE_FLTUND, "Floating point underflow" },
{ FPE_FLTRES, "Floating point inexact result" },
{ FPE_FLTINV, "Floating point invalid operation" },
{ FPE_FLTSUB, "Subscript out of range" },
{ 0, NULL }
};
static const struct {
int code;
const char *name;
} sigsegv_codes[] = {
#ifndef __FreeBSD__
{ SEGV_MAPERR, "Address not mapped to object" },
{ SEGV_ACCERR, "Invalid permissions for mapped object" },
#endif
{ 0, NULL }
};
static const struct {
int code;
const char *name;
} sigbus_codes[] = {
#ifndef __FreeBSD__
{ BUS_ADRALN, "Invalid address alignment" },
{ BUS_ADRERR, "Non-existent physical address" },
{ BUS_OBJERR, "Object specific hardware error" },
#endif
{ 0, NULL }
};
static int (*cc_user_info)(char*, char*);
static void gdb_info(pid_t pid)
{
char respfile[64];
char cmd_buf[128];
FILE *f;
int fd;
/* Create a temp file to put gdb commands into */
strcpy(respfile, "gdb-respfile-XXXXXX");
if((fd=mkstemp(respfile)) >= 0 && (f=fdopen(fd, "w")) != NULL)
{
fprintf(f, "attach %d\n"
"shell echo \"\"\n"
"shell echo \"* Loaded Libraries\"\n"
"info sharedlibrary\n"
"shell echo \"\"\n"
"shell echo \"* Threads\"\n"
"info threads\n"
"shell echo \"\"\n"
"shell echo \"* FPU Status\"\n"
"info float\n"
"shell echo \"\"\n"
"shell echo \"* Registers\"\n"
"info registers\n"
"shell echo \"\"\n"
"shell echo \"* Backtrace\"\n"
"thread apply all backtrace full\n"
"detach\n"
"quit\n", pid);
fclose(f);
/* Run gdb and print process info. */
snprintf(cmd_buf, sizeof(cmd_buf), "gdb --quiet --batch --command=%s", respfile);
printf("Executing: %s\n", cmd_buf);
fflush(stdout);
system(cmd_buf);
/* Clean up */
remove(respfile);
}
else
{
/* Error creating temp file */
if(fd >= 0)
{
close(fd);
remove(respfile);
}
printf("!!! Could not create gdb command file\n");
}
fflush(stdout);
}
static void sys_info(void)
{
#ifdef __unix__
system("echo \"System: `uname -a`\"");
putchar('\n');
fflush(stdout);
#endif
}
static size_t safe_write(int fd, const void *buf, size_t len)
{
size_t ret = 0;
while(ret < len)
{
ssize_t rem;
if((rem=write(fd, (const char*)buf+ret, len-ret)) == -1)
{
if(errno == EINTR)
continue;
break;
}
ret += rem;
}
return ret;
}
static void crash_catcher(int signum, siginfo_t *siginfo, void *context)
{
//ucontext_t *ucontext = (ucontext_t*)context;
pid_t dbg_pid;
int fd[2];
/* Make sure the effective uid is the real uid */
if(getuid() != geteuid())
{
raise(signum);
return;
}
safe_write(STDERR_FILENO, fatal_err, sizeof(fatal_err)-1);
if(pipe(fd) == -1)
{
safe_write(STDERR_FILENO, pipe_err, sizeof(pipe_err)-1);
raise(signum);
return;
}
crash_info.signum = signum;
crash_info.pid = getpid();
crash_info.has_siginfo = !!siginfo;
if(siginfo)
crash_info.siginfo = *siginfo;
if(cc_user_info)
cc_user_info(crash_info.buf, crash_info.buf+sizeof(crash_info.buf));
/* Fork off to start a crash handler */
switch((dbg_pid=fork()))
{
/* Error */
case -1:
safe_write(STDERR_FILENO, fork_err, sizeof(fork_err)-1);
raise(signum);
return;
case 0:
dup2(fd[0], STDIN_FILENO);
close(fd[0]);
close(fd[1]);
execl(argv0, argv0, crash_switch, NULL);
safe_write(STDERR_FILENO, exec_err, sizeof(exec_err)-1);
_exit(1);
default:
#ifdef __linux__
prctl(PR_SET_PTRACER, dbg_pid, 0, 0, 0);
#endif
safe_write(fd[1], &crash_info, sizeof(crash_info));
close(fd[0]);
close(fd[1]);
/* Wait; we'll be killed when gdb is done */
do {
int status;
if(waitpid(dbg_pid, &status, 0) == dbg_pid &&
(WIFEXITED(status) || WIFSIGNALED(status)))
{
/* The debug process died before it could kill us */
raise(signum);
break;
}
} while(1);
}
}
static void crash_handler(const char *logfile)
{
const char *sigdesc = "";
int i;
if(fread(&crash_info, sizeof(crash_info), 1, stdin) != 1)
{
fprintf(stderr, "!!! Failed to retrieve info from crashed process\n");
exit(1);
}
/* Get the signal description */
for(i = 0;signals[i].name;++i)
{
if(signals[i].signum == crash_info.signum)
{
sigdesc = signals[i].name;
break;
}
}
if(crash_info.has_siginfo)
{
switch(crash_info.signum)
{
case SIGSEGV:
for(i = 0;sigsegv_codes[i].name;++i)
{
if(sigsegv_codes[i].code == crash_info.siginfo.si_code)
{
sigdesc = sigsegv_codes[i].name;
break;
}
}
break;
case SIGFPE:
for(i = 0;sigfpe_codes[i].name;++i)
{
if(sigfpe_codes[i].code == crash_info.siginfo.si_code)
{
sigdesc = sigfpe_codes[i].name;
break;
}
}
break;
case SIGILL:
for(i = 0;sigill_codes[i].name;++i)
{
if(sigill_codes[i].code == crash_info.siginfo.si_code)
{
sigdesc = sigill_codes[i].name;
break;
}
}
break;
case SIGBUS:
for(i = 0;sigbus_codes[i].name;++i)
{
if(sigbus_codes[i].code == crash_info.siginfo.si_code)
{
sigdesc = sigbus_codes[i].name;
break;
}
}
break;
}
}
fprintf(stderr, "%s (signal %i)\n", sigdesc, crash_info.signum);
if(crash_info.has_siginfo)
fprintf(stderr, "Address: %p\n", crash_info.siginfo.si_addr);
fputc('\n', stderr);
if(logfile)
{
/* Create crash log file and redirect shell output to it */
if(freopen(logfile, "wa", stdout) != stdout)
{
fprintf(stderr, "!!! Could not create %s following signal\n", logfile);
exit(1);
}
fprintf(stderr, "Generating %s and killing process %d, please wait... ", logfile, crash_info.pid);
printf("*** Fatal Error ***\n"
"%s (signal %i)\n", sigdesc, crash_info.signum);
if(crash_info.has_siginfo)
printf("Address: %p\n", crash_info.siginfo.si_addr);
fputc('\n', stdout);
fflush(stdout);
}
sys_info();
crash_info.buf[sizeof(crash_info.buf)-1] = '\0';
printf("%s\n", crash_info.buf);
fflush(stdout);
if(crash_info.pid > 0)
{
gdb_info(crash_info.pid);
kill(crash_info.pid, SIGKILL);
}
if(logfile)
{
const char *str;
char buf[512];
if((str=getenv("KDE_FULL_SESSION")) && strcmp(str, "true") == 0)
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')
snprintf(buf, sizeof(buf), "gxmessage -buttons \"Okay:0\" -geometry 800x600 -title \"Very Fatal Error\" -center -file \"%s\"", logfile);
else
snprintf(buf, sizeof(buf), "xmessage -buttons \"Okay:0\" -center -file \"%s\"", logfile);
system(buf);
}
exit(0);
}
int cc_install_handlers(int argc, char **argv, int num_signals, int *signals, const char *logfile, int (*user_info)(char*, char*))
{
struct sigaction sa;
stack_t altss;
int retval;
if(argc == 2 && strcmp(argv[1], crash_switch) == 0)
crash_handler(logfile);
cc_user_info = user_info;
if(argv[0][0] == '/')
snprintf(argv0, sizeof(argv0), "%s", argv[0]);
else
{
getcwd(argv0, sizeof(argv0));
retval = strlen(argv0);
snprintf(argv0+retval, sizeof(argv0)-retval, "/%s", argv[0]);
}
/* Set an alternate signal stack so SIGSEGVs caused by stack overflows
* still run */
altss.ss_sp = altstack;
altss.ss_flags = 0;
altss.ss_size = sizeof(altstack);
sigaltstack(&altss, NULL);
memset(&sa, 0, sizeof(sa));
sa.sa_sigaction = crash_catcher;
sa.sa_flags = SA_RESETHAND | SA_NODEFER | SA_SIGINFO | SA_ONSTACK;
sigemptyset(&sa.sa_mask);
retval = 0;
while(num_signals--)
{
if((*signals != SIGSEGV && *signals != SIGILL && *signals != SIGFPE &&
*signals != SIGBUS) || sigaction(*signals, &sa, NULL) == -1)
{
*signals = 0;
retval = -1;
}
++signals;
}
return retval;
}
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <sys/param.h>
#include <sys/ucontext.h>
#include <string.h>
#include <errno.h>
#include <limits.h>
#ifdef __linux__
#include <sys/prctl.h>
#ifndef PR_SET_PTRACER
#define PR_SET_PTRACER 0x59616d61
#endif
#elif defined (__APPLE__)
#include <signal.h>
#endif
static const char crash_switch[] = "--cc-handle-crash";
static const char fatal_err[] = "\n\n*** Fatal Error ***\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 exec_err[] = "!!! Failed to exec debug process\n";
static char argv0[PATH_MAX];
static char altstack[SIGSTKSZ];
static struct {
int signum;
pid_t pid;
int has_siginfo;
siginfo_t siginfo;
char buf[1024];
} crash_info;
static const struct {
const char *name;
int signum;
} signals[] = {
{ "Segmentation fault", SIGSEGV },
{ "Illegal instruction", SIGILL },
{ "FPU exception", SIGFPE },
{ "System BUS error", SIGBUS },
{ NULL, 0 }
};
static const struct {
int code;
const char *name;
} sigill_codes[] = {
#ifndef __FreeBSD__
{ ILL_ILLOPC, "Illegal opcode" },
{ ILL_ILLOPN, "Illegal operand" },
{ ILL_ILLADR, "Illegal addressing mode" },
{ ILL_ILLTRP, "Illegal trap" },
{ ILL_PRVOPC, "Privileged opcode" },
{ ILL_PRVREG, "Privileged register" },
{ ILL_COPROC, "Coprocessor error" },
{ ILL_BADSTK, "Internal stack error" },
#endif
{ 0, NULL }
};
static const struct {
int code;
const char *name;
} sigfpe_codes[] = {
{ FPE_INTDIV, "Integer divide by zero" },
{ FPE_INTOVF, "Integer overflow" },
{ FPE_FLTDIV, "Floating point divide by zero" },
{ FPE_FLTOVF, "Floating point overflow" },
{ FPE_FLTUND, "Floating point underflow" },
{ FPE_FLTRES, "Floating point inexact result" },
{ FPE_FLTINV, "Floating point invalid operation" },
{ FPE_FLTSUB, "Subscript out of range" },
{ 0, NULL }
};
static const struct {
int code;
const char *name;
} sigsegv_codes[] = {
#ifndef __FreeBSD__
{ SEGV_MAPERR, "Address not mapped to object" },
{ SEGV_ACCERR, "Invalid permissions for mapped object" },
#endif
{ 0, NULL }
};
static const struct {
int code;
const char *name;
} sigbus_codes[] = {
#ifndef __FreeBSD__
{ BUS_ADRALN, "Invalid address alignment" },
{ BUS_ADRERR, "Non-existent physical address" },
{ BUS_OBJERR, "Object specific hardware error" },
#endif
{ 0, NULL }
};
static int (*cc_user_info)(char*, char*);
static void gdb_info(pid_t pid)
{
char respfile[64];
char cmd_buf[128];
FILE *f;
int fd;
/* Create a temp file to put gdb commands into */
strcpy(respfile, "gdb-respfile-XXXXXX");
if((fd=mkstemp(respfile)) >= 0 && (f=fdopen(fd, "w")) != NULL)
{
fprintf(f, "attach %d\n"
"shell echo \"\"\n"
"shell echo \"* Loaded Libraries\"\n"
"info sharedlibrary\n"
"shell echo \"\"\n"
"shell echo \"* Threads\"\n"
"info threads\n"
"shell echo \"\"\n"
"shell echo \"* FPU Status\"\n"
"info float\n"
"shell echo \"\"\n"
"shell echo \"* Registers\"\n"
"info registers\n"
"shell echo \"\"\n"
"shell echo \"* Backtrace\"\n"
"thread apply all backtrace full\n"
"detach\n"
"quit\n", pid);
fclose(f);
/* Run gdb and print process info. */
snprintf(cmd_buf, sizeof(cmd_buf), "gdb --quiet --batch --command=%s", respfile);
printf("Executing: %s\n", cmd_buf);
fflush(stdout);
system(cmd_buf);
/* Clean up */
remove(respfile);
}
else
{
/* Error creating temp file */
if(fd >= 0)
{
close(fd);
remove(respfile);
}
printf("!!! Could not create gdb command file\n");
}
fflush(stdout);
}
static void sys_info(void)
{
#ifdef __unix__
system("echo \"System: `uname -a`\"");
putchar('\n');
fflush(stdout);
#endif
}
static size_t safe_write(int fd, const void *buf, size_t len)
{
size_t ret = 0;
while(ret < len)
{
ssize_t rem;
if((rem=write(fd, (const char*)buf+ret, len-ret)) == -1)
{
if(errno == EINTR)
continue;
break;
}
ret += rem;
}
return ret;
}
static void crash_catcher(int signum, siginfo_t *siginfo, void *context)
{
//ucontext_t *ucontext = (ucontext_t*)context;
pid_t dbg_pid;
int fd[2];
/* Make sure the effective uid is the real uid */
if(getuid() != geteuid())
{
raise(signum);
return;
}
safe_write(STDERR_FILENO, fatal_err, sizeof(fatal_err)-1);
if(pipe(fd) == -1)
{
safe_write(STDERR_FILENO, pipe_err, sizeof(pipe_err)-1);
raise(signum);
return;
}
crash_info.signum = signum;
crash_info.pid = getpid();
crash_info.has_siginfo = !!siginfo;
if(siginfo)
crash_info.siginfo = *siginfo;
if(cc_user_info)
cc_user_info(crash_info.buf, crash_info.buf+sizeof(crash_info.buf));
/* Fork off to start a crash handler */
switch((dbg_pid=fork()))
{
/* Error */
case -1:
safe_write(STDERR_FILENO, fork_err, sizeof(fork_err)-1);
raise(signum);
return;
case 0:
dup2(fd[0], STDIN_FILENO);
close(fd[0]);
close(fd[1]);
execl(argv0, argv0, crash_switch, NULL);
safe_write(STDERR_FILENO, exec_err, sizeof(exec_err)-1);
_exit(1);
default:
#ifdef __linux__
prctl(PR_SET_PTRACER, dbg_pid, 0, 0, 0);
#endif
safe_write(fd[1], &crash_info, sizeof(crash_info));
close(fd[0]);
close(fd[1]);
/* Wait; we'll be killed when gdb is done */
do {
int status;
if(waitpid(dbg_pid, &status, 0) == dbg_pid &&
(WIFEXITED(status) || WIFSIGNALED(status)))
{
/* The debug process died before it could kill us */
raise(signum);
break;
}
} while(1);
}
}
static void crash_handler(const char *logfile)
{
const char *sigdesc = "";
int i;
if(fread(&crash_info, sizeof(crash_info), 1, stdin) != 1)
{
fprintf(stderr, "!!! Failed to retrieve info from crashed process\n");
exit(1);
}
/* Get the signal description */
for(i = 0;signals[i].name;++i)
{
if(signals[i].signum == crash_info.signum)
{
sigdesc = signals[i].name;
break;
}
}
if(crash_info.has_siginfo)
{
switch(crash_info.signum)
{
case SIGSEGV:
for(i = 0;sigsegv_codes[i].name;++i)
{
if(sigsegv_codes[i].code == crash_info.siginfo.si_code)
{
sigdesc = sigsegv_codes[i].name;
break;
}
}
break;
case SIGFPE:
for(i = 0;sigfpe_codes[i].name;++i)
{
if(sigfpe_codes[i].code == crash_info.siginfo.si_code)
{
sigdesc = sigfpe_codes[i].name;
break;
}
}
break;
case SIGILL:
for(i = 0;sigill_codes[i].name;++i)
{
if(sigill_codes[i].code == crash_info.siginfo.si_code)
{
sigdesc = sigill_codes[i].name;
break;
}
}
break;
case SIGBUS:
for(i = 0;sigbus_codes[i].name;++i)
{
if(sigbus_codes[i].code == crash_info.siginfo.si_code)
{
sigdesc = sigbus_codes[i].name;
break;
}
}
break;
}
}
fprintf(stderr, "%s (signal %i)\n", sigdesc, crash_info.signum);
if(crash_info.has_siginfo)
fprintf(stderr, "Address: %p\n", crash_info.siginfo.si_addr);
fputc('\n', stderr);
if(logfile)
{
/* Create crash log file and redirect shell output to it */
if(freopen(logfile, "wa", stdout) != stdout)
{
fprintf(stderr, "!!! Could not create %s following signal\n", logfile);
exit(1);
}
fprintf(stderr, "Generating %s and killing process %d, please wait... ", logfile, crash_info.pid);
printf("*** Fatal Error ***\n"
"%s (signal %i)\n", sigdesc, crash_info.signum);
if(crash_info.has_siginfo)
printf("Address: %p\n", crash_info.siginfo.si_addr);
fputc('\n', stdout);
fflush(stdout);
}
sys_info();
crash_info.buf[sizeof(crash_info.buf)-1] = '\0';
printf("%s\n", crash_info.buf);
fflush(stdout);
if(crash_info.pid > 0)
{
gdb_info(crash_info.pid);
kill(crash_info.pid, SIGKILL);
}
if(logfile)
{
const char *str;
char buf[512];
if((str=getenv("KDE_FULL_SESSION")) && strcmp(str, "true") == 0)
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')
snprintf(buf, sizeof(buf), "gxmessage -buttons \"Okay:0\" -geometry 800x600 -title \"Very Fatal Error\" -center -file \"%s\"", logfile);
else
snprintf(buf, sizeof(buf), "xmessage -buttons \"Okay:0\" -center -file \"%s\"", logfile);
system(buf);
}
exit(0);
}
int cc_install_handlers(int argc, char **argv, int num_signals, int *signals, const char *logfile, int (*user_info)(char*, char*))
{
struct sigaction sa;
stack_t altss;
int retval;
if(argc == 2 && strcmp(argv[1], crash_switch) == 0)
crash_handler(logfile);
cc_user_info = user_info;
if(argv[0][0] == '/')
snprintf(argv0, sizeof(argv0), "%s", argv[0]);
else
{
getcwd(argv0, sizeof(argv0));
retval = strlen(argv0);
snprintf(argv0+retval, sizeof(argv0)-retval, "/%s", argv[0]);
}
/* Set an alternate signal stack so SIGSEGVs caused by stack overflows
* still run */
altss.ss_sp = altstack;
altss.ss_flags = 0;
altss.ss_size = sizeof(altstack);
sigaltstack(&altss, NULL);
memset(&sa, 0, sizeof(sa));
sa.sa_sigaction = crash_catcher;
sa.sa_flags = SA_RESETHAND | SA_NODEFER | SA_SIGINFO | SA_ONSTACK;
sigemptyset(&sa.sa_mask);
retval = 0;
while(num_signals--)
{
if((*signals != SIGSEGV && *signals != SIGILL && *signals != SIGFPE &&
*signals != SIGBUS) || sigaction(*signals, &sa, NULL) == -1)
{
*signals = 0;
retval = -1;
}
++signals;
}
return retval;
}

View file

@ -1,48 +1,48 @@
// 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
// only one process, hence the class name.)
#ifndef CRITSEC_H
#define CRITSEC_H
#include "SDL.h"
#include "SDL_thread.h"
#include "i_system.h"
class FCriticalSection
{
public:
FCriticalSection()
{
CritSec = SDL_CreateMutex();
if (CritSec == NULL)
{
I_FatalError("Failed to create a critical section mutex.");
}
}
~FCriticalSection()
{
if (CritSec != NULL)
{
SDL_DestroyMutex(CritSec);
}
}
void Enter()
{
if (SDL_mutexP(CritSec) != 0)
{
I_FatalError("Failed entering a critical section.");
}
}
void Leave()
{
if (SDL_mutexV(CritSec) != 0)
{
I_FatalError("Failed to leave a critical section.");
}
}
private:
SDL_mutex *CritSec;
};
#endif
// 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
// only one process, hence the class name.)
#ifndef CRITSEC_H
#define CRITSEC_H
#include "SDL.h"
#include "SDL_thread.h"
#include "i_system.h"
class FCriticalSection
{
public:
FCriticalSection()
{
CritSec = SDL_CreateMutex();
if (CritSec == NULL)
{
I_FatalError("Failed to create a critical section mutex.");
}
}
~FCriticalSection()
{
if (CritSec != NULL)
{
SDL_DestroyMutex(CritSec);
}
}
void Enter()
{
if (SDL_mutexP(CritSec) != 0)
{
I_FatalError("Failed entering a critical section.");
}
}
void Leave()
{
if (SDL_mutexV(CritSec) != 0)
{
I_FatalError("Failed to leave a critical section.");
}
}
private:
SDL_mutex *CritSec;
};
#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()
{
return SDL_JoystickName(DeviceIndex);
return SDL_JoystickName(Device);
}
float GetSensitivity()
{

View file

@ -1,378 +1,338 @@
/*
** i_main.cpp
** System-specific startup code. Eventually calls D_DoomMain.
**
**---------------------------------------------------------------------------
** Copyright 1998-2007 Randy Heit
** 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.
**---------------------------------------------------------------------------
**
*/
// HEADER FILES ------------------------------------------------------------
#include <SDL.h>
#include <unistd.h>
#include <stdlib.h>
#include <signal.h>
#include <new>
#include <sys/param.h>
#ifndef NO_GTK
#include <gtk/gtk.h>
#endif
#include <locale.h>
#if defined(__MACH__) && !defined(NOASM)
#include <sys/types.h>
#include <sys/mman.h>
#endif
#include "doomerrors.h"
#include "m_argv.h"
#include "d_main.h"
#include "i_system.h"
#include "i_video.h"
#include "c_console.h"
#include "errors.h"
#include "version.h"
#include "w_wad.h"
#include "g_level.h"
#include "r_state.h"
#include "cmdlib.h"
#include "r_utility.h"
#include "doomstat.h"
// MACROS ------------------------------------------------------------------
// The maximum number of functions that can be registered with atterm.
#define MAX_TERMS 64
// TYPES -------------------------------------------------------------------
// EXTERNAL FUNCTION PROTOTYPES --------------------------------------------
extern "C" int cc_install_handlers(int, char**, int, int*, const char*, int(*)(char*, char*));
#ifdef __APPLE__
void Mac_I_FatalError(const char* errortext);
#endif
// PUBLIC FUNCTION PROTOTYPES ----------------------------------------------
// PRIVATE FUNCTION PROTOTYPES ---------------------------------------------
// EXTERNAL DATA DECLARATIONS ----------------------------------------------
#ifdef USE_XCURSOR
extern bool UseXCursor;
#endif
// PUBLIC DATA DEFINITIONS -------------------------------------------------
#ifndef NO_GTK
bool GtkAvailable;
#endif
// The command line arguments.
DArgs *Args;
// PRIVATE DATA DEFINITIONS ------------------------------------------------
static void (*TermFuncs[MAX_TERMS]) ();
static const char *TermNames[MAX_TERMS];
static int NumTerms;
// CODE --------------------------------------------------------------------
void addterm (void (*func) (), const char *name)
{
// Make sure this function wasn't already registered.
for (int i = 0; i < NumTerms; ++i)
{
if (TermFuncs[i] == func)
{
return;
}
}
if (NumTerms == MAX_TERMS)
{
func ();
I_FatalError (
"Too many exit functions registered.\n"
"Increase MAX_TERMS in i_main.cpp");
}
TermNames[NumTerms] = name;
TermFuncs[NumTerms++] = func;
}
void popterm ()
{
if (NumTerms)
NumTerms--;
}
void STACK_ARGS call_terms ()
{
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 int DoomSpecificInfo (char *buffer, char *end)
{
const char *arg;
int size = end-buffer-2;
int i, p;
p = 0;
p += snprintf (buffer+p, size-p, GAMENAME" version %s (%s)\n", GetVersionString(), GetGitHash());
#ifdef __VERSION__
p += snprintf (buffer+p, size-p, "Compiler version: %s\n", __VERSION__);
#endif
p += snprintf (buffer+p, size-p, "\nCommand line:");
for (i = 0; i < Args->NumArgs(); ++i)
{
p += snprintf (buffer+p, size-p, " %s", Args->GetArg(i));
}
p += snprintf (buffer+p, size-p, "\n");
for (i = 0; (arg = Wads.GetWadName (i)) != NULL; ++i)
{
p += snprintf (buffer+p, size-p, "\nWad %d: %s", i, arg);
}
if (gamestate != GS_LEVEL && gamestate != GS_TITLELEVEL)
{
p += snprintf (buffer+p, size-p, "\n\nNot in a level.");
}
else
{
p += snprintf (buffer+p, size-p, "\n\nCurrent map: %s", level.MapName.GetChars());
if (!viewactive)
{
p += snprintf (buffer+p, size-p, "\n\nView not active.");
}
else
{
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);
p += snprintf (buffer+p, size-p, "\nviewangle = %x", (unsigned int)viewangle);
}
}
buffer[p++] = '\n';
buffer[p++] = '\0';
return p;
}
#if defined(__MACH__) && !defined(NOASM)
// 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.
extern "C"
{
extern void *rtext_a_start, *rtext_a_end;
extern void *rtext_tmap_start, *rtext_tmap_end;
extern void *rtext_tmap2_start, *rtext_tmap2_end;
extern void *rtext_tmap3_start, *rtext_tmap3_end;
};
static void unprotect_pages(long pagesize, void *start, void *end)
{
char *page = (char *)((intptr_t)start & ~(pagesize - 1));
size_t len = (char *)end - (char *)start;
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[] =
{
rtext_a_start, rtext_a_end,
rtext_tmap_start, rtext_tmap_end,
rtext_tmap2_start, rtext_tmap2_end,
rtext_tmap3_start, rtext_tmap3_end
};
long pagesize = sysconf(_SC_PAGESIZE);
for (void *const *p = pages; p < &pages[countof(pages)]; p += 2)
{
unprotect_pages(pagesize, p[0], p[1]);
}
}
#endif
void I_StartupJoysticks();
void I_ShutdownJoysticks();
const char* I_GetBackEndName();
int main (int argc, char **argv)
{
#if !defined (__APPLE__)
{
int s[4] = { SIGSEGV, SIGILL, SIGFPE, SIGBUS };
cc_install_handlers(argc, argv, 4, s, "zdoom-crash.log", DoomSpecificInfo);
}
#endif // !__APPLE__
printf(GAMENAME" %s - %s - %s version\nCompiled on %s\n",
GetVersionString(), GetGitTime(), I_GetBackEndName(), __DATE__);
seteuid (getuid ());
std::set_new_handler (NewFailure);
#if defined(__MACH__) && !defined(NOASM)
unprotect_rtext();
#endif
// Set LC_NUMERIC environment variable in case some library decides to
// clear the setlocale call at least this will be correct.
// Note that the LANG environment variable is overridden by LC_*
setenv ("LC_NUMERIC", "C", 1);
#ifndef NO_GTK
GtkAvailable = gtk_init_check (&argc, &argv);
#endif
setlocale (LC_ALL, "C");
if (SDL_Init (SDL_INIT_VIDEO|SDL_INIT_TIMER|SDL_INIT_NOPARACHUTE|SDL_INIT_JOYSTICK) == -1)
{
fprintf (stderr, "Could not initialize SDL:\n%s\n", SDL_GetError());
return -1;
}
atterm (SDL_Quit);
{
char viddriver[80];
if (SDL_VideoDriverName(viddriver, sizeof(viddriver)) != NULL)
{
printf("Using video driver %s\n", viddriver);
#ifdef USE_XCURSOR
UseXCursor = (strcmp(viddriver, "x11") == 0);
#endif
}
printf("\n");
}
char caption[100];
mysnprintf(caption, countof(caption), GAMESIG " %s (%s)", GetVersionString(), GetGitTime());
SDL_WM_SetCaption(caption, caption);
#ifdef __APPLE__
const SDL_VideoInfo* videoInfo = SDL_GetVideoInfo();
if ( NULL != videoInfo )
{
EXTERN_CVAR( Int, vid_defwidth )
EXTERN_CVAR( Int, vid_defheight )
EXTERN_CVAR( Int, vid_defbits )
EXTERN_CVAR( Bool, vid_vsync )
EXTERN_CVAR( Bool, fullscreen )
vid_defwidth = videoInfo->current_w;
vid_defheight = videoInfo->current_h;
vid_defbits = videoInfo->vfmt->BitsPerPixel;
vid_vsync = true;
fullscreen = true;
}
#endif // __APPLE__
try
{
Args = new DArgs(argc, argv);
/*
killough 1/98:
This fixes some problems with exit handling
during abnormal situations.
The old code called I_Quit() to end program,
while now I_Quit() is installed as an exit
handler and exit() is called to exit, either
normally or abnormally. Seg faults are caught
and the error handler is used, to prevent
being left in graphics mode or having very
loud SFX noise because the sound card is
left in an unstable state.
*/
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;
}
/*
** i_main.cpp
** System-specific startup code. Eventually calls D_DoomMain.
**
**---------------------------------------------------------------------------
** Copyright 1998-2007 Randy Heit
** 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.
**---------------------------------------------------------------------------
**
*/
// HEADER FILES ------------------------------------------------------------
#include <SDL.h>
#include <unistd.h>
#include <stdlib.h>
#include <signal.h>
#include <new>
#include <sys/param.h>
#ifndef NO_GTK
#include <gtk/gtk.h>
#endif
#include <locale.h>
#if defined(__MACH__) && !defined(NOASM)
#include <sys/types.h>
#include <sys/mman.h>
#endif
#include "doomerrors.h"
#include "m_argv.h"
#include "d_main.h"
#include "i_system.h"
#include "i_video.h"
#include "c_console.h"
#include "errors.h"
#include "version.h"
#include "w_wad.h"
#include "g_level.h"
#include "r_state.h"
#include "cmdlib.h"
#include "r_utility.h"
#include "doomstat.h"
// MACROS ------------------------------------------------------------------
// The maximum number of functions that can be registered with atterm.
#define MAX_TERMS 64
// TYPES -------------------------------------------------------------------
// EXTERNAL FUNCTION PROTOTYPES --------------------------------------------
extern "C" int cc_install_handlers(int, char**, int, int*, const char*, int(*)(char*, char*));
#ifdef __APPLE__
void Mac_I_FatalError(const char* errortext);
#endif
// PUBLIC FUNCTION PROTOTYPES ----------------------------------------------
// PRIVATE FUNCTION PROTOTYPES ---------------------------------------------
// EXTERNAL DATA DECLARATIONS ----------------------------------------------
// PUBLIC DATA DEFINITIONS -------------------------------------------------
#ifndef NO_GTK
bool GtkAvailable;
#endif
// The command line arguments.
DArgs *Args;
// PRIVATE DATA DEFINITIONS ------------------------------------------------
static void (*TermFuncs[MAX_TERMS]) ();
static const char *TermNames[MAX_TERMS];
static int NumTerms;
// CODE --------------------------------------------------------------------
void addterm (void (*func) (), const char *name)
{
// Make sure this function wasn't already registered.
for (int i = 0; i < NumTerms; ++i)
{
if (TermFuncs[i] == func)
{
return;
}
}
if (NumTerms == MAX_TERMS)
{
func ();
I_FatalError (
"Too many exit functions registered.\n"
"Increase MAX_TERMS in i_main.cpp");
}
TermNames[NumTerms] = name;
TermFuncs[NumTerms++] = func;
}
void popterm ()
{
if (NumTerms)
NumTerms--;
}
void STACK_ARGS call_terms ()
{
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 int DoomSpecificInfo (char *buffer, char *end)
{
const char *arg;
int size = end-buffer-2;
int i, p;
p = 0;
p += snprintf (buffer+p, size-p, GAMENAME" version %s (%s)\n", GetVersionString(), GetGitHash());
#ifdef __VERSION__
p += snprintf (buffer+p, size-p, "Compiler version: %s\n", __VERSION__);
#endif
p += snprintf (buffer+p, size-p, "\nCommand line:");
for (i = 0; i < Args->NumArgs(); ++i)
{
p += snprintf (buffer+p, size-p, " %s", Args->GetArg(i));
}
p += snprintf (buffer+p, size-p, "\n");
for (i = 0; (arg = Wads.GetWadName (i)) != NULL; ++i)
{
p += snprintf (buffer+p, size-p, "\nWad %d: %s", i, arg);
}
if (gamestate != GS_LEVEL && gamestate != GS_TITLELEVEL)
{
p += snprintf (buffer+p, size-p, "\n\nNot in a level.");
}
else
{
p += snprintf (buffer+p, size-p, "\n\nCurrent map: %s", level.MapName.GetChars());
if (!viewactive)
{
p += snprintf (buffer+p, size-p, "\n\nView not active.");
}
else
{
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);
p += snprintf (buffer+p, size-p, "\nviewangle = %x", (unsigned int)viewangle);
}
}
buffer[p++] = '\n';
buffer[p++] = '\0';
return p;
}
#if defined(__MACH__) && !defined(NOASM)
// 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.
extern "C"
{
extern void *rtext_a_start, *rtext_a_end;
extern void *rtext_tmap_start, *rtext_tmap_end;
extern void *rtext_tmap2_start, *rtext_tmap2_end;
extern void *rtext_tmap3_start, *rtext_tmap3_end;
};
static void unprotect_pages(long pagesize, void *start, void *end)
{
char *page = (char *)((intptr_t)start & ~(pagesize - 1));
size_t len = (char *)end - (char *)start;
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[] =
{
rtext_a_start, rtext_a_end,
rtext_tmap_start, rtext_tmap_end,
rtext_tmap2_start, rtext_tmap2_end,
rtext_tmap3_start, rtext_tmap3_end
};
long pagesize = sysconf(_SC_PAGESIZE);
for (void *const *p = pages; p < &pages[countof(pages)]; p += 2)
{
unprotect_pages(pagesize, p[0], p[1]);
}
}
#endif
void I_StartupJoysticks();
void I_ShutdownJoysticks();
int main (int argc, char **argv)
{
#if !defined (__APPLE__)
{
int s[4] = { SIGSEGV, SIGILL, SIGFPE, SIGBUS };
cc_install_handlers(argc, argv, 4, s, "zdoom-crash.log", DoomSpecificInfo);
}
#endif // !__APPLE__
printf(GAMENAME" %s - %s - SDL version\nCompiled on %s\n",
GetVersionString(), GetGitTime(), __DATE__);
seteuid (getuid ());
std::set_new_handler (NewFailure);
#if defined(__MACH__) && !defined(NOASM)
unprotect_rtext();
#endif
// Set LC_NUMERIC environment variable in case some library decides to
// clear the setlocale call at least this will be correct.
// Note that the LANG environment variable is overridden by LC_*
setenv ("LC_NUMERIC", "C", 1);
#ifndef NO_GTK
GtkAvailable = gtk_init_check (&argc, &argv);
#endif
setlocale (LC_ALL, "C");
if (SDL_Init (SDL_INIT_VIDEO|SDL_INIT_TIMER|SDL_INIT_NOPARACHUTE|SDL_INIT_JOYSTICK) == -1)
{
fprintf (stderr, "Could not initialize SDL:\n%s\n", SDL_GetError());
return -1;
}
atterm (SDL_Quit);
printf("Using video driver %s\n", SDL_GetCurrentVideoDriver());
printf("\n");
try
{
Args = new DArgs(argc, argv);
/*
killough 1/98:
This fixes some problems with exit handling
during abnormal situations.
The old code called I_Quit() to end program,
while now I_Quit() is installed as an exit
handler and exit() is called to exit, either
normally or abnormally. Seg faults are caught
and the error handler is used, to prevent
being left in graphics mode or having very
loud SFX noise because the sound card is
left in an unstable state.
*/
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 "v_video.h"
class SDLVideo : public IVideo
{
public:
SDLVideo (int parm);
~SDLVideo ();
EDisplayType GetDisplayType () { return DISPLAY_Both; }
void SetWindowedScale (float scale);
DFrameBuffer *CreateFrameBuffer (int width, int height, bool fs, DFrameBuffer *old);
void StartModeIterator (int bits, bool fs);
bool NextMode (int *width, int *height, bool *letterbox);
private:
int IteratorMode;
int IteratorBits;
bool IteratorFS;
};
#include "hardware.h"
#include "v_video.h"
class SDLVideo : public IVideo
{
public:
SDLVideo (int parm);
~SDLVideo ();
EDisplayType GetDisplayType () { return DISPLAY_Both; }
void SetWindowedScale (float scale);
DFrameBuffer *CreateFrameBuffer (int width, int height, bool fs, DFrameBuffer *old);
void StartModeIterator (int bits, bool fs);
bool NextMode (int *width, int *height, bool *letterbox);
private:
int IteratorMode;
int IteratorBits;
};

View file

@ -1,354 +1,354 @@
/*
** st_start.cpp
** Handles the startup screen.
**
**---------------------------------------------------------------------------
** Copyright 2006-2007 Randy Heit
** 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.
**---------------------------------------------------------------------------
**
*/
// HEADER FILES ------------------------------------------------------------
#include <unistd.h>
#include <sys/time.h>
#include <sys/types.h>
#include <termios.h>
#include "st_start.h"
#include "doomdef.h"
#include "i_system.h"
#include "c_cvars.h"
// MACROS ------------------------------------------------------------------
// TYPES -------------------------------------------------------------------
class FTTYStartupScreen : public FStartupScreen
{
public:
FTTYStartupScreen(int max_progress);
~FTTYStartupScreen();
void Progress();
void NetInit(const char *message, int num_players);
void NetProgress(int count);
void NetMessage(const char *format, ...); // cover for printf
void NetDone();
bool NetLoop(bool (*timer_callback)(void *), void *userdata);
protected:
bool DidNetInit;
int NetMaxPos, NetCurPos;
const char *TheNetMessage;
termios OldTermIOS;
};
// EXTERNAL FUNCTION PROTOTYPES --------------------------------------------
// PUBLIC FUNCTION PROTOTYPES ----------------------------------------------
void I_ShutdownJoysticks();
// PRIVATE FUNCTION PROTOTYPES ---------------------------------------------
static void DeleteStartupScreen();
// EXTERNAL DATA DECLARATIONS ----------------------------------------------
// PUBLIC DATA DEFINITIONS -------------------------------------------------
FStartupScreen *StartScreen;
CUSTOM_CVAR(Int, showendoom, 0, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
{
if (self < 0) self = 0;
else if (self > 2) self=2;
}
// PRIVATE DATA DEFINITIONS ------------------------------------------------
static const char SpinnyProgressChars[4] = { '|', '/', '-', '\\' };
// CODE --------------------------------------------------------------------
//==========================================================================
//
// FStartupScreen :: CreateInstance
//
// Initializes the startup screen for the detected game.
// Sets the size of the progress bar and displays the startup screen.
//
//==========================================================================
FStartupScreen *FStartupScreen::CreateInstance(int max_progress)
{
atterm(DeleteStartupScreen);
return new FTTYStartupScreen(max_progress);
}
//===========================================================================
//
// DeleteStartupScreen
//
// Makes sure the startup screen has been deleted before quitting.
//
//===========================================================================
void DeleteStartupScreen()
{
if (StartScreen != NULL)
{
delete StartScreen;
StartScreen = NULL;
}
}
//===========================================================================
//
// FTTYStartupScreen Constructor
//
// Sets the size of the progress bar and displays the startup screen.
//
//===========================================================================
FTTYStartupScreen::FTTYStartupScreen(int max_progress)
: FStartupScreen(max_progress)
{
DidNetInit = false;
NetMaxPos = 0;
NetCurPos = 0;
TheNetMessage = NULL;
}
//===========================================================================
//
// FTTYStartupScreen Destructor
//
// Called just before entering graphics mode to deconstruct the startup
// screen.
//
//===========================================================================
FTTYStartupScreen::~FTTYStartupScreen()
{
NetDone(); // Just in case it wasn't called yet and needs to be.
}
//===========================================================================
//
// FTTYStartupScreen :: Progress
//
// 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.
//
//===========================================================================
void FTTYStartupScreen::Progress()
{
}
//===========================================================================
//
// FTTYStartupScreen :: NetInit
//
// Sets stdin for unbuffered I/O, displays the given message, and shows
// a progress meter.
//
//===========================================================================
void FTTYStartupScreen::NetInit(const char *message, int numplayers)
{
if (!DidNetInit)
{
termios rawtermios;
fprintf (stderr, "Press 'Q' to abort network game synchronization.");
// Set stdin to raw mode so we can get keypresses in ST_CheckNetAbort()
// immediately without waiting for an EOL.
tcgetattr (STDIN_FILENO, &OldTermIOS);
rawtermios = OldTermIOS;
rawtermios.c_lflag &= ~(ICANON | ECHO);
tcsetattr (STDIN_FILENO, TCSANOW, &rawtermios);
DidNetInit = true;
}
if (numplayers == 1)
{
// Status message without any real progress info.
fprintf (stderr, "\n%s.", message);
}
else
{
fprintf (stderr, "\n%s: ", message);
}
fflush (stderr);
TheNetMessage = message;
NetMaxPos = numplayers;
NetCurPos = 0;
NetProgress(1); // You always know about yourself
}
//===========================================================================
//
// FTTYStartupScreen :: NetDone
//
// Restores the old stdin tty settings.
//
//===========================================================================
void FTTYStartupScreen::NetDone()
{
// Restore stdin settings
if (DidNetInit)
{
tcsetattr (STDIN_FILENO, TCSANOW, &OldTermIOS);
printf ("\n");
DidNetInit = false;
}
}
//===========================================================================
//
// FTTYStartupScreen :: NetMessage
//
// Call this between NetInit() and NetDone() instead of Printf() to
// display messages, because the progress meter is mixed in the same output
// stream as normal messages.
//
//===========================================================================
void FTTYStartupScreen::NetMessage(const char *format, ...)
{
FString str;
va_list argptr;
va_start (argptr, format);
str.VFormat (format, argptr);
va_end (argptr);
fprintf (stderr, "\r%-40s\n", str.GetChars());
}
//===========================================================================
//
// FTTYStartupScreen :: NetProgress
//
// Sets the network progress meter. If count is 0, it gets bumped by 1.
// Otherwise, it is set to count.
//
//===========================================================================
void FTTYStartupScreen::NetProgress(int count)
{
int i;
if (count == 0)
{
NetCurPos++;
}
else if (count > 0)
{
NetCurPos = count;
}
if (NetMaxPos == 0)
{
// Spinny-type progress meter, because we're a guest waiting for the host.
fprintf (stderr, "\r%s: %c", TheNetMessage, SpinnyProgressChars[NetCurPos & 3]);
fflush (stderr);
}
else if (NetMaxPos > 1)
{
// Dotty-type progress meter.
fprintf (stderr, "\r%s: ", TheNetMessage);
for (i = 0; i < NetCurPos; ++i)
{
fputc ('.', stderr);
}
fprintf (stderr, "%*c[%2d/%2d]", NetMaxPos + 1 - NetCurPos, ' ', NetCurPos, NetMaxPos);
fflush (stderr);
}
}
//===========================================================================
//
// FTTYStartupScreen :: NetLoop
//
// 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
// 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
// false if the loop was halted because the user wants to abort the
// network synchronization.
//
//===========================================================================
bool FTTYStartupScreen::NetLoop(bool (*timer_callback)(void *), void *userdata)
{
fd_set rfds;
struct timeval tv;
int retval;
char k;
for (;;)
{
// Don't flood the network with packets on startup.
tv.tv_sec = 0;
tv.tv_usec = 500000;
FD_ZERO (&rfds);
FD_SET (STDIN_FILENO, &rfds);
retval = select (1, &rfds, NULL, NULL, &tv);
if (retval == -1)
{
// Error
}
else if (retval == 0)
{
if (timer_callback (userdata))
{
fputc ('\n', stderr);
return true;
}
}
else if (read (STDIN_FILENO, &k, 1) == 1)
{
// Check input on stdin
if (k == 'q' || k == 'Q')
{
fprintf (stderr, "\nNetwork game synchronization aborted.");
return false;
}
}
}
}
void ST_Endoom()
{
I_ShutdownJoysticks();
exit(0);
}
/*
** st_start.cpp
** Handles the startup screen.
**
**---------------------------------------------------------------------------
** Copyright 2006-2007 Randy Heit
** 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.
**---------------------------------------------------------------------------
**
*/
// HEADER FILES ------------------------------------------------------------
#include <unistd.h>
#include <sys/time.h>
#include <sys/types.h>
#include <termios.h>
#include "st_start.h"
#include "doomdef.h"
#include "i_system.h"
#include "c_cvars.h"
// MACROS ------------------------------------------------------------------
// TYPES -------------------------------------------------------------------
class FTTYStartupScreen : public FStartupScreen
{
public:
FTTYStartupScreen(int max_progress);
~FTTYStartupScreen();
void Progress();
void NetInit(const char *message, int num_players);
void NetProgress(int count);
void NetMessage(const char *format, ...); // cover for printf
void NetDone();
bool NetLoop(bool (*timer_callback)(void *), void *userdata);
protected:
bool DidNetInit;
int NetMaxPos, NetCurPos;
const char *TheNetMessage;
termios OldTermIOS;
};
// EXTERNAL FUNCTION PROTOTYPES --------------------------------------------
// PUBLIC FUNCTION PROTOTYPES ----------------------------------------------
void I_ShutdownJoysticks();
// PRIVATE FUNCTION PROTOTYPES ---------------------------------------------
static void DeleteStartupScreen();
// EXTERNAL DATA DECLARATIONS ----------------------------------------------
// PUBLIC DATA DEFINITIONS -------------------------------------------------
FStartupScreen *StartScreen;
CUSTOM_CVAR(Int, showendoom, 0, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
{
if (self < 0) self = 0;
else if (self > 2) self=2;
}
// PRIVATE DATA DEFINITIONS ------------------------------------------------
static const char SpinnyProgressChars[4] = { '|', '/', '-', '\\' };
// CODE --------------------------------------------------------------------
//==========================================================================
//
// FStartupScreen :: CreateInstance
//
// Initializes the startup screen for the detected game.
// Sets the size of the progress bar and displays the startup screen.
//
//==========================================================================
FStartupScreen *FStartupScreen::CreateInstance(int max_progress)
{
atterm(DeleteStartupScreen);
return new FTTYStartupScreen(max_progress);
}
//===========================================================================
//
// DeleteStartupScreen
//
// Makes sure the startup screen has been deleted before quitting.
//
//===========================================================================
void DeleteStartupScreen()
{
if (StartScreen != NULL)
{
delete StartScreen;
StartScreen = NULL;
}
}
//===========================================================================
//
// FTTYStartupScreen Constructor
//
// Sets the size of the progress bar and displays the startup screen.
//
//===========================================================================
FTTYStartupScreen::FTTYStartupScreen(int max_progress)
: FStartupScreen(max_progress)
{
DidNetInit = false;
NetMaxPos = 0;
NetCurPos = 0;
TheNetMessage = NULL;
}
//===========================================================================
//
// FTTYStartupScreen Destructor
//
// Called just before entering graphics mode to deconstruct the startup
// screen.
//
//===========================================================================
FTTYStartupScreen::~FTTYStartupScreen()
{
NetDone(); // Just in case it wasn't called yet and needs to be.
}
//===========================================================================
//
// FTTYStartupScreen :: Progress
//
// 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.
//
//===========================================================================
void FTTYStartupScreen::Progress()
{
}
//===========================================================================
//
// FTTYStartupScreen :: NetInit
//
// Sets stdin for unbuffered I/O, displays the given message, and shows
// a progress meter.
//
//===========================================================================
void FTTYStartupScreen::NetInit(const char *message, int numplayers)
{
if (!DidNetInit)
{
termios rawtermios;
fprintf (stderr, "Press 'Q' to abort network game synchronization.");
// Set stdin to raw mode so we can get keypresses in ST_CheckNetAbort()
// immediately without waiting for an EOL.
tcgetattr (STDIN_FILENO, &OldTermIOS);
rawtermios = OldTermIOS;
rawtermios.c_lflag &= ~(ICANON | ECHO);
tcsetattr (STDIN_FILENO, TCSANOW, &rawtermios);
DidNetInit = true;
}
if (numplayers == 1)
{
// Status message without any real progress info.
fprintf (stderr, "\n%s.", message);
}
else
{
fprintf (stderr, "\n%s: ", message);
}
fflush (stderr);
TheNetMessage = message;
NetMaxPos = numplayers;
NetCurPos = 0;
NetProgress(1); // You always know about yourself
}
//===========================================================================
//
// FTTYStartupScreen :: NetDone
//
// Restores the old stdin tty settings.
//
//===========================================================================
void FTTYStartupScreen::NetDone()
{
// Restore stdin settings
if (DidNetInit)
{
tcsetattr (STDIN_FILENO, TCSANOW, &OldTermIOS);
printf ("\n");
DidNetInit = false;
}
}
//===========================================================================
//
// FTTYStartupScreen :: NetMessage
//
// Call this between NetInit() and NetDone() instead of Printf() to
// display messages, because the progress meter is mixed in the same output
// stream as normal messages.
//
//===========================================================================
void FTTYStartupScreen::NetMessage(const char *format, ...)
{
FString str;
va_list argptr;
va_start (argptr, format);
str.VFormat (format, argptr);
va_end (argptr);
fprintf (stderr, "\r%-40s\n", str.GetChars());
}
//===========================================================================
//
// FTTYStartupScreen :: NetProgress
//
// Sets the network progress meter. If count is 0, it gets bumped by 1.
// Otherwise, it is set to count.
//
//===========================================================================
void FTTYStartupScreen::NetProgress(int count)
{
int i;
if (count == 0)
{
NetCurPos++;
}
else if (count > 0)
{
NetCurPos = count;
}
if (NetMaxPos == 0)
{
// Spinny-type progress meter, because we're a guest waiting for the host.
fprintf (stderr, "\r%s: %c", TheNetMessage, SpinnyProgressChars[NetCurPos & 3]);
fflush (stderr);
}
else if (NetMaxPos > 1)
{
// Dotty-type progress meter.
fprintf (stderr, "\r%s: ", TheNetMessage);
for (i = 0; i < NetCurPos; ++i)
{
fputc ('.', stderr);
}
fprintf (stderr, "%*c[%2d/%2d]", NetMaxPos + 1 - NetCurPos, ' ', NetCurPos, NetMaxPos);
fflush (stderr);
}
}
//===========================================================================
//
// FTTYStartupScreen :: NetLoop
//
// 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
// 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
// false if the loop was halted because the user wants to abort the
// network synchronization.
//
//===========================================================================
bool FTTYStartupScreen::NetLoop(bool (*timer_callback)(void *), void *userdata)
{
fd_set rfds;
struct timeval tv;
int retval;
char k;
for (;;)
{
// Don't flood the network with packets on startup.
tv.tv_sec = 0;
tv.tv_usec = 500000;
FD_ZERO (&rfds);
FD_SET (STDIN_FILENO, &rfds);
retval = select (1, &rfds, NULL, NULL, &tv);
if (retval == -1)
{
// Error
}
else if (retval == 0)
{
if (timer_callback (userdata))
{
fputc ('\n', stderr);
return true;
}
}
else if (read (STDIN_FILENO, &k, 1) == 1)
{
// Check input on stdin
if (k == 'q' || k == 'Q')
{
fprintf (stderr, "\nNetwork game synchronization aborted.");
return false;
}
}
}
}
void ST_Endoom()
{
I_ShutdownJoysticks();
exit(0);
}

View file

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

View file

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

View file

@ -117,7 +117,6 @@ FDynamicColormap*basecolormap; // [RH] colormap currently drawing with
int fixedlightlev;
lighttable_t *fixedcolormap;
FSpecialColormap *realfixedcolormap;
float WallTMapScale;
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;
InvZtoScale = yaspectmul * centerx;
WallTMapScale = (float)centerx * 32.f;
WallTMapScale2 = iyaspectmulfloat * 2.f / (float)centerx;
WallTMapScale2 = iyaspectmulfloat * 64.f / (float)centerx;
// psprite scales
pspritexscale = (centerxwide << FRACBITS) / 160;

View file

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

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
double top, bot, i;
double xrepeat = fabs((double)walxrepeat);
double depth_scale = WallT.InvZstep * WallTMapScale2;
double depth_org = -WallT.UoverZstep * WallTMapScale2;
i = x1 - centerx;
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);
}
swall[x] = xs_RoundToInt(frac * WallT.DepthScale + WallT.DepthOrg);
swall[x] = xs_RoundToInt(frac * depth_scale + depth_org);
top += WallT.UoverZstep;
bot += WallT.InvZstep;
}

View file

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

View file

@ -122,5 +122,5 @@ xx(TK_Array, "'array'")
xx(TK_In, "'in'")
xx(TK_SizeOf, "'sizeof'")
xx(TK_AlignOf, "'alignof'")
xx(TK_Pick, "'pick'")
xx(TK_RandomPick, "'randompick'")
#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 <mmsystem.h>
#else
#include <SDL.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/stat.h>

View file

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

View file

@ -38,6 +38,8 @@
#pragma once
#endif
#include <stdlib.h>
// Returns a file name suitable for use as a temp file.
// If you create a file with this name (and presumably you
// 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)
{
ACTION_PARAM_START(6);
ACTION_PARAM_START(7);
ACTION_PARAM_CLASS(ti, 0);
ACTION_PARAM_FIXED(SpawnHeight, 1);
ACTION_PARAM_INT(Spawnofs_XY, 2);
ACTION_PARAM_ANGLE(Angle, 3);
ACTION_PARAM_INT(flags, 4);
ACTION_PARAM_ANGLE(pitch, 5);
ACTION_PARAM_INT(ptr, 6);
AActor *ref = COPY_AAPTR(self, ptr);
int aimmode = flags & CMF_AIMMODE;
AActor * targ;
AActor * missile;
if (self->target != NULL || aimmode==2)
if (ref != NULL || aimmode==2)
{
if (ti)
{
@ -937,14 +940,14 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CustomMissile)
self->x += x;
self->y += y;
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->y -= y;
self->z -= z;
break;
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;
case 2:
@ -1056,7 +1059,7 @@ enum CBA_Flags
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_Z, 1);
ACTION_PARAM_INT(NumBullets, 2);
@ -1064,6 +1067,9 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CustomBulletAttack)
ACTION_PARAM_CLASS(pufftype, 4);
ACTION_PARAM_FIXED(Range, 5);
ACTION_PARAM_INT(Flags, 6);
ACTION_PARAM_INT(ptr, 7);
AActor *ref = COPY_AAPTR(self, ptr);
if(Range==0) Range=MISSILERANGE;
@ -1072,9 +1078,12 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CustomBulletAttack)
int bslope = 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;
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 prevY = self->y;
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.
bool teleResult = P_TeleportMove(self, spot->x, spot->y, spot->z, 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;
bool teleResult = P_TeleportMove(self, spot->x, spot->y, finalz, Flags & TF_TELEFRAG);
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)
@ -5016,48 +5032,74 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SetSpeed)
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
//
// 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.
// 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
{
DMSS_FOILINVUL = 1,
DMSS_AFFECTARMOR = 2,
DMSS_KILL = 4,
DMSS_NOFACTOR = 8,
DMSS_FOILBUDDHA = 16,
DMSS_NOPROTECT = 32,
DMSS_FOILINVUL = 1, //Foil invulnerability
DMSS_AFFECTARMOR = 2, //Make it affect armor
DMSS_KILL = 4, //Damages them for their current health
DMSS_NOFACTOR = 8, //Ignore DamageFactors
DMSS_FOILBUDDHA = 16, //Can kill actors with Buddha flag, except the player.
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;
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)
bool filterpass = DoCheckFilter(dmgtarget, filter, (flags & DMSS_EXFILTER) ? true : false),
speciespass = DoCheckSpecies(dmgtarget, species, (flags & DMSS_EXSPECIES) ? true : false);
if ((flags & DMSS_EITHER) ? (filterpass || speciespass) : (filterpass && speciespass))
{
amount = -amount;
P_GiveBody(dmgtarget, amount);
int dmgFlags = 0;
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)
{
ACTION_PARAM_START(3);
ACTION_PARAM_START(5);
ACTION_PARAM_INT(amount, 0);
ACTION_PARAM_NAME(DamageType, 1);
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)
{
ACTION_PARAM_START(3);
ACTION_PARAM_START(5);
ACTION_PARAM_INT(amount, 0);
ACTION_PARAM_NAME(DamageType, 1);
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)
{
ACTION_PARAM_START(3);
ACTION_PARAM_START(5);
ACTION_PARAM_INT(amount, 0);
ACTION_PARAM_NAME(DamageType, 1);
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)
{
ACTION_PARAM_START(3);
ACTION_PARAM_START(5);
ACTION_PARAM_INT(amount, 0);
ACTION_PARAM_NAME(DamageType, 1);
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)
{
ACTION_PARAM_START(3);
ACTION_PARAM_START(5);
ACTION_PARAM_INT(amount, 0);
ACTION_PARAM_NAME(DamageType, 1);
ACTION_PARAM_INT(flags, 2);
ACTION_PARAM_CLASS(filter, 3);
ACTION_PARAM_NAME(species, 4);
TThinkerIterator<AActor> it;
AActor * mo;
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)
{
ACTION_PARAM_START(3);
ACTION_PARAM_START(5);
ACTION_PARAM_INT(amount, 0);
ACTION_PARAM_NAME(DamageType, 1);
ACTION_PARAM_INT(flags, 2);
ACTION_PARAM_CLASS(filter, 3);
ACTION_PARAM_NAME(species, 4);
TThinkerIterator<AActor> it;
AActor * mo;
@ -5161,7 +5227,10 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_DamageSiblings)
{
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
{
KILS_FOILINVUL = 1 << 0,
KILS_KILLMISSILES = 1 << 1,
KILS_NOMONSTERS = 1 << 2,
KILS_FOILBUDDHA = 1 << 3,
KILS_FOILINVUL = 1 << 0,
KILS_KILLMISSILES = 1 << 1,
KILS_NOMONSTERS = 1 << 2,
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;
if (KILS_FOILINVUL)
dmgFlags += DMG_FOILINVUL;
if (KILS_FOILBUDDHA)
dmgFlags += DMG_FOILBUDDHA;
if ((killtarget->flags & MF_MISSILE) && (flags & KILS_KILLMISSILES))
bool filterpass = DoCheckFilter(killtarget, filter, (flags & KILS_EXFILTER) ? true : false),
speciespass = DoCheckSpecies(killtarget, species, (flags & KILS_EXSPECIES) ? true : false);
if ((flags & KILS_EITHER) ? (filterpass || speciespass) : (filterpass && speciespass)) //Check this first. I think it'll save the engine a lot more time this way.
{
//[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))
int dmgFlags = DMG_NO_ARMOR + DMG_NO_FACTOR;
if (KILS_FOILINVUL)
dmgFlags += DMG_FOILINVUL;
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);
}
}
}
@ -5214,11 +5292,16 @@ static void DoKill(AActor *killtarget, AActor *self, FName damagetype, int flags
//===========================================================================
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_KillTarget)
{
ACTION_PARAM_START(2);
ACTION_PARAM_START(4);
ACTION_PARAM_NAME(damagetype, 0);
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)
{
ACTION_PARAM_START(2);
ACTION_PARAM_START(4);
ACTION_PARAM_NAME(damagetype, 0);
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)
{
ACTION_PARAM_START(2);
ACTION_PARAM_START(4);
ACTION_PARAM_NAME(damagetype, 0);
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)
{
ACTION_PARAM_START(2);
ACTION_PARAM_START(4);
ACTION_PARAM_NAME(damagetype, 0);
ACTION_PARAM_INT(flags, 1);
ACTION_PARAM_CLASS(filter, 2);
ACTION_PARAM_NAME(species, 3);
TThinkerIterator<AActor> it;
AActor *mo;
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)
{
ACTION_PARAM_START(2);
ACTION_PARAM_START(4);
ACTION_PARAM_NAME(damagetype, 0);
ACTION_PARAM_INT(flags, 1);
ACTION_PARAM_CLASS(filter, 2);
ACTION_PARAM_NAME(species, 3);
TThinkerIterator<AActor> it;
AActor *mo;
@ -5287,7 +5387,10 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_KillSiblings)
{
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
{
RMVF_MISSILES = 1 << 0,
RMVF_NOMONSTERS = 1 << 1,
RMVF_MISC = 1 << 2,
RMVF_EVERYTHING = 1 << 3,
RMVF_MISSILES = 1 << 0,
RMVF_NOMONSTERS = 1 << 1,
RMVF_MISC = 1 << 2,
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_MISC) && !((removetarget->flags3 & MF3_ISMONSTER) && (removetarget->flags & MF_MISSILE)))
{
P_RemoveThing(removetarget);
}
if ((removetarget->flags3 & MF3_ISMONSTER) && !(flags & RMVF_NOMONSTERS))
{
P_RemoveThing(removetarget);
}
if ((removetarget->flags & MF_MISSILE) && (flags & RMVF_MISSILES))
{
P_RemoveThing(removetarget);
if ((flags & RMVF_EVERYTHING))
{
P_RemoveThing(removetarget);
}
if ((flags & RMVF_MISC) && !((removetarget->flags3 & MF3_ISMONSTER) && (removetarget->flags & MF_MISSILE)))
{
P_RemoveThing(removetarget);
}
if ((removetarget->flags3 & MF3_ISMONSTER) && !(flags & RMVF_NOMONSTERS))
{
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)
{
ACTION_PARAM_START(1);
ACTION_PARAM_START(2);
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)
{
ACTION_PARAM_START(1);
ACTION_PARAM_START(2);
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)
{
ACTION_PARAM_START(1);
ACTION_PARAM_START(2);
ACTION_PARAM_INT(flags, 0);
ACTION_PARAM_CLASS(filter, 1);
ACTION_PARAM_NAME(species, 2);
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;
AActor *mo;
ACTION_PARAM_START(2);
ACTION_PARAM_START(4);
ACTION_PARAM_BOOL(removeall, 0);
ACTION_PARAM_INT(flags, 1);
ACTION_PARAM_CLASS(filter, 2);
ACTION_PARAM_NAME(species, 3);
while ((mo = it.Next()) != NULL)
{
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;
AActor *mo;
ACTION_PARAM_START(2);
ACTION_PARAM_START(4);
ACTION_PARAM_BOOL(removeall, 0);
ACTION_PARAM_INT(flags, 1);
ACTION_PARAM_CLASS(filter, 2);
ACTION_PARAM_NAME(species, 3);
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))
{
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)
{
ACTION_PARAM_START(2);
ACTION_PARAM_START(4);
ACTION_PARAM_INT(removee, 0);
ACTION_PARAM_INT(flags, 1);
ACTION_PARAM_CLASS(filter, 2);
ACTION_PARAM_NAME(species, 3);
AActor *reference = COPY_AAPTR(self, removee);
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);
}
else if (sc.CheckToken(TK_Pick))
else if (sc.CheckToken(TK_RandomPick))
{
FRandom *rng;
TArray<FxExpression*> list;
@ -390,17 +390,15 @@ static FxExpression *ParseExpression0 (FScanner &sc, const PClass *cls)
}
sc.MustGetToken('(');
while (!(sc.CheckToken(')')))
for (;;)
{
FxExpression *min = ParseExpressionM(sc, cls);
list.Push(min);
FxExpression *expr = ParseExpressionM(sc, cls);
list.Push(expr);
if (sc.CheckToken(')'))
break;
else
sc.MustGetToken(',');
sc.MustGetToken(',');
}
return new FxPick(rng, list, sc);
return new FxRandomPick(rng, list, sc);
}
else if (sc.CheckToken(TK_FRandom))
{

View file

@ -559,7 +559,7 @@ public:
//
//==========================================================================
class FxPick : public FxExpression
class FxRandomPick : public FxExpression
{
protected:
FRandom * rng;
@ -567,8 +567,8 @@ protected:
public:
FxPick(FRandom *, TArray<FxExpression*> mi, const FScriptPosition &pos);
~FxPick();
FxRandomPick(FRandom *, TArray<FxExpression*> mi, const FScriptPosition &pos);
~FxRandomPick();
FxExpression *Resolve(FCompileContext&);
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)
{
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();
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;
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;
DWORD data;
void *ptrval;
switch (tag)
{
@ -150,15 +149,9 @@ void DCanvas::DrawTextV(FFont *font, int normalcolor, int x, int y, const char *
// We don't handle these. :(
case DTA_DestWidth:
case DTA_DestHeight:
*(DWORD *)tags = TAG_IGNORE;
data = va_arg (tags, DWORD);
break;
// Translation is specified explicitly by the text.
case DTA_Translation:
*(DWORD *)tags = TAG_IGNORE;
ptrval = va_arg (tags, void*);
break;
assert("Bad parameter for DrawText" && false);
return;
case DTA_CleanNoMove_1:
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_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_CustomMissile(class<Actor> missiletype, float spawnheight = 32, int spawnofs_xy = 0, float angle = 0, int flags = 0, float pitch = 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);
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, 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_JumpIfHealthLower(int health, state label, int ptr_selector = AAPTR_DEFAULT);
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_CheckFlag(string flagname, state label, int check_pointer = AAPTR_DEFAULT);
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_RaiseChildren(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_PlayerSkinCheck(state label);
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_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);
@ -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_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_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_Punch();
action native A_Feathers();
@ -307,14 +298,23 @@ ACTOR Actor native //: Thinker
action native A_SetDamageType(name damagetype);
action native A_DropItem(class<Actor> item, int dropamount = -1, int chance = 256);
action native A_SetSpeed(float speed);
action native A_DamageSelf(int amount, name damagetype = "none", int flags = 0);
action native A_DamageTarget(int amount, name damagetype = "none", int flags = 0);
action native A_DamageTracer(int amount, name damagetype = "none", int flags = 0);
action native A_KillTarget(name damagetype = "none", int flags = 0);
action native A_KillTracer(name damagetype = "none", int flags = 0);
action native A_RemoveTarget(int flags = 0);
action native A_RemoveTracer(int flags = 0);
action native A_Remove(int removee, 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, class<Actor> filter = "None", name species = "None");
action native A_DamageMaster(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, class<Actor> filter = "None", name species = "None");
action native A_DamageChildren(int amount, name damagetype = "none", int flags = 0, class<Actor> filter = "None", name species = "None");
action native A_DamageSiblings(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, class<Actor> filter = "None", name species = "None");
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_GiveToSiblings(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
const int KILS_FOILINVUL = 1;
const int KILS_KILLMISSILES = 2;
const int KILS_NOMONSTERS = 4;
const int KILS_FOILBUDDHA = 8;
enum
{
KILS_FOILINVUL = 0x00000001,
KILS_KILLMISSILES = 0x00000002,
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
const int DMSS_FOILINVUL = 1;
const int DMSS_AFFECTARMOR = 2;
const int DMSS_KILL = 4;
const int DMSS_NOFACTOR = 8;
const int DMSS_FOILBUDDHA = 16;
const int DMSS_NOPROTECT = 32;
enum
{
DMSS_FOILINVUL = 0x00000001,
DMSS_AFFECTARMOR = 0x00000002,
DMSS_KILL = 0x00000004,
DMSS_NOFACTOR = 0x00000008,
DMSS_FOILBUDDHA = 0x00000010,
DMSS_NOPROTECT = 0x00000020,
DMSS_EXFILTER = 0x00000040,
DMSS_EXSPECIES = 0x00000080,
DMSS_EITHER = 0x00000100,
};
// Flags for A_AlertMonsters
const int AMF_TARGETEMITTER = 1;
@ -418,10 +429,13 @@ const int AMF_EMITFROMTARGET = 4;
// Flags for A_Remove*
enum
{
RMVF_MISSILES = 1 << 0,
RMVF_NOMONSTERS = 1 << 1,
RMVF_MISC = 1 << 2,
RMVF_EVERYTHING = 1 << 3,
RMVF_MISSILES = 0x00000001,
RMVF_NOMONSTERS = 0x00000002,
RMVF_MISC = 0x00000004,
RMVF_EVERYTHING = 0x00000008,
RMVF_EXFILTER = 0x00000010,
RMVF_EXSPECIES = 0x00000020,
RMVF_EITHER = 0x00000040,
};
// Flags for A_Fade*