Put all non-Windows source code into posix directory and its subdirectories

This commit is contained in:
alexey.lysiuk 2014-12-18 11:52:29 +02:00
parent 84b12d23b5
commit 1433bf3f78
37 changed files with 2574 additions and 2953 deletions

View file

@ -554,35 +554,35 @@ set( PLAT_POSIX_SOURCES
posix/i_system.cpp posix/i_system.cpp
posix/st_start.cpp ) posix/st_start.cpp )
set( PLAT_SDL_SOURCES set( PLAT_SDL_SOURCES
sdl/crashcatcher.c posix/sdl/crashcatcher.c
sdl/hardware.cpp posix/sdl/hardware.cpp
sdl/i_gui.cpp posix/sdl/i_gui.cpp
sdl/i_input.cpp posix/sdl/i_input.cpp
sdl/i_joystick.cpp posix/sdl/i_joystick.cpp
sdl/i_main.cpp posix/sdl/i_main.cpp
sdl/i_timer.cpp posix/sdl/i_timer.cpp
sdl/sdlvideo.cpp ) posix/sdl/sdlvideo.cpp )
set( PLAT_MAC_SOURCES set( PLAT_OSX_SOURCES
cocoa/iwadpicker_cocoa.mm ) posix/osx/iwadpicker_cocoa.mm
posix/osx/zdoom.icns )
set( PLAT_COCOA_SOURCES set( PLAT_COCOA_SOURCES
cocoa/hid/HID_Config_Utilities.c posix/cocoa/hid/HID_Config_Utilities.c
cocoa/hid/HID_Error_Handler.c posix/cocoa/hid/HID_Error_Handler.c
cocoa/hid/HID_Name_Lookup.c posix/cocoa/hid/HID_Name_Lookup.c
cocoa/hid/HID_Queue_Utilities.c posix/cocoa/hid/HID_Queue_Utilities.c
cocoa/hid/HID_Utilities.c posix/cocoa/hid/HID_Utilities.c
cocoa/hid/IOHIDDevice_.c posix/cocoa/hid/IOHIDDevice_.c
cocoa/hid/IOHIDElement_.c posix/cocoa/hid/IOHIDElement_.c
cocoa/hid/ImmrHIDUtilAddOn.c posix/cocoa/hid/ImmrHIDUtilAddOn.c
cocoa/critsec.cpp posix/cocoa/critsec.cpp
cocoa/i_backend_cocoa.mm posix/cocoa/i_backend_cocoa.mm
cocoa/i_joystick.cpp posix/cocoa/i_joystick.cpp
cocoa/i_timer.cpp posix/cocoa/i_timer.cpp )
cocoa/zdoom.icns )
if( WIN32 ) if( WIN32 )
set( SYSTEM_SOURCES_DIR win32 ) set( SYSTEM_SOURCES_DIR win32 )
set( SYSTEM_SOURCES ${PLAT_WIN32_SOURCES} ) set( SYSTEM_SOURCES ${PLAT_WIN32_SOURCES} )
set( OTHER_SYSTEM_SOURCES ${PLAT_POSIX_SOURCES} ${PLAT_SDL_SOURCES} ${PLAT_MAC_SOURCES} ${PLAT_COCOA_SOURCES} ) set( OTHER_SYSTEM_SOURCES ${PLAT_POSIX_SOURCES} ${PLAT_SDL_SOURCES} ${PLAT_OSX_SOURCES} ${PLAT_COCOA_SOURCES} )
if( ZD_CMAKE_COMPILER_IS_GNUCXX_COMPATIBLE ) if( ZD_CMAKE_COMPILER_IS_GNUCXX_COMPATIBLE )
# CMake is not set up to compile and link rc files with GCC. :( # CMake is not set up to compile and link rc files with GCC. :(
@ -595,24 +595,24 @@ if( WIN32 )
endif( ZD_CMAKE_COMPILER_IS_GNUCXX_COMPATIBLE ) endif( ZD_CMAKE_COMPILER_IS_GNUCXX_COMPATIBLE )
elseif( APPLE ) elseif( APPLE )
if( OSX_COCOA_BACKEND ) if( OSX_COCOA_BACKEND )
set( SYSTEM_SOURCES_DIR posix cocoa ) set( SYSTEM_SOURCES_DIR posix posix/cocoa )
set( SYSTEM_SOURCES ${PLAT_COCOA_SOURCES} ) set( SYSTEM_SOURCES ${PLAT_COCOA_SOURCES} )
set( OTHER_SYSTEM_SOURCES ${PLAT_WIN32_SOURCES} ${PLAT_SDL_SOURCES} ) set( OTHER_SYSTEM_SOURCES ${PLAT_WIN32_SOURCES} ${PLAT_SDL_SOURCES} )
else( OSX_COCOA_BACKEND ) else( OSX_COCOA_BACKEND )
set( SYSTEM_SOURCES_DIR posix sdl ) set( SYSTEM_SOURCES_DIR posix posix/sdl )
set( SYSTEM_SOURCES ${PLAT_SDL_SOURCES} ) set( SYSTEM_SOURCES ${PLAT_SDL_SOURCES} )
set( PLAT_MAC_SOURCES ${PLAT_MAC_SOURCES} sdl/i_system_cocoa.mm ) set( PLAT_OSX_SOURCES ${PLAT_OSX_SOURCES} posix/sdl/i_system.mm )
set( OTHER_SYSTEM_SOURCES ${PLAT_WIN32_SOURCES} ${PLAT_COCOA_SOURCES} ) set( OTHER_SYSTEM_SOURCES ${PLAT_WIN32_SOURCES} ${PLAT_COCOA_SOURCES} )
endif( OSX_COCOA_BACKEND ) endif( OSX_COCOA_BACKEND )
set( SYSTEM_SOURCES ${SYSTEM_SOURCES} ${PLAT_POSIX_SOURCES} ${PLAT_MAC_SOURCES} "${FMOD_LIBRARY}" ) set( SYSTEM_SOURCES ${SYSTEM_SOURCES} ${PLAT_POSIX_SOURCES} ${PLAT_OSX_SOURCES} "${FMOD_LIBRARY}" )
set_source_files_properties( cocoa/zdoom.icns PROPERTIES MACOSX_PACKAGE_LOCATION Resources ) set_source_files_properties( posix/osx/zdoom.icns PROPERTIES MACOSX_PACKAGE_LOCATION Resources )
set_source_files_properties( "${FMOD_LIBRARY}" PROPERTIES MACOSX_PACKAGE_LOCATION Frameworks ) set_source_files_properties( "${FMOD_LIBRARY}" PROPERTIES MACOSX_PACKAGE_LOCATION Frameworks )
else( WIN32 ) else( WIN32 )
set( SYSTEM_SOURCES_DIR posix sdl ) set( SYSTEM_SOURCES_DIR posix posix/sdl )
set( SYSTEM_SOURCES ${PLAT_POSIX_SOURCES} ${PLAT_SDL_SOURCES} ) set( SYSTEM_SOURCES ${PLAT_POSIX_SOURCES} ${PLAT_SDL_SOURCES} )
set( OTHER_SYSTEM_SOURCES ${PLAT_WIN32_SOURCES} ${PLAT_MAC_SOURCES} ${PLAT_COCOA_SOURCES} ) set( OTHER_SYSTEM_SOURCES ${PLAT_WIN32_SOURCES} ${PLAT_OSX_SOURCES} ${PLAT_COCOA_SOURCES} )
endif( WIN32 ) endif( WIN32 )
if( NOT ASM_SOURCES ) if( NOT ASM_SOURCES )
@ -672,16 +672,15 @@ if( WIN32 )
set( EXTRA_HEADER_DIRS win32/*.h ) set( EXTRA_HEADER_DIRS win32/*.h )
elseif( APPLE ) elseif( APPLE )
if( OSX_COCOA_BACKEND ) if( OSX_COCOA_BACKEND )
set( EXTRA_HEADER_DIRS posix/*.h cocoa/*.h ) set( EXTRA_HEADER_DIRS posix/*.h posix/cocoa/*.h )
else( OSX_COCOA_BACKEND ) else( OSX_COCOA_BACKEND )
set( EXTRA_HEADER_DIRS posix/*.h sdl/*.h ) set( EXTRA_HEADER_DIRS posix/*.h posix/sdl/*.h )
endif( OSX_COCOA_BACKEND ) endif( OSX_COCOA_BACKEND )
else( WIN32 ) else( WIN32 )
set( EXTRA_HEADER_DIRS posix/*.h sdl/*.h ) set( EXTRA_HEADER_DIRS posix/*.h posix/sdl/*.h )
endif( WIN32 ) endif( WIN32 )
file( GLOB HEADER_FILES file( GLOB HEADER_FILES
${EXTRA_HEADER_DIRS} ${EXTRA_HEADER_DIRS}
cocoa/*.h
fragglescript/*.h fragglescript/*.h
g_doom/*.h g_doom/*.h
g_heretic/*.h g_heretic/*.h
@ -694,9 +693,10 @@ file( GLOB HEADER_FILES
oplsynth/*.h oplsynth/*.h
oplsynth/dosbox/*.h oplsynth/dosbox/*.h
posix/*.h posix/*.h
posix/cocoa/*.h
posix/sdl/*.h
r_data/*.h r_data/*.h
resourcefiles/*.h resourcefiles/*.h
sdl/*.h
sfmt/*.h sfmt/*.h
sound/*.h sound/*.h
textures/*.h textures/*.h
@ -1195,7 +1195,7 @@ endif( ZD_CMAKE_COMPILER_IS_GNUCXX_COMPATIBLE )
if( APPLE ) if( APPLE )
set_target_properties(zdoom PROPERTIES set_target_properties(zdoom PROPERTIES
LINK_FLAGS "-framework Carbon -framework Cocoa -framework IOKit -framework OpenGL" LINK_FLAGS "-framework Carbon -framework Cocoa -framework IOKit -framework OpenGL"
MACOSX_BUNDLE_INFO_PLIST "${CMAKE_CURRENT_SOURCE_DIR}/cocoa/zdoom-info.plist" ) MACOSX_BUNDLE_INFO_PLIST "${CMAKE_CURRENT_SOURCE_DIR}/posix/osx/zdoom-info.plist" )
# Fix fmod link so that it can be found in the app bundle. # Fix fmod link so that it can be found in the app bundle.
find_program( OTOOL otool HINTS "/usr/bin" "${OSX_DEVELOPER_ROOT}/usr/bin" ) find_program( OTOOL otool HINTS "/usr/bin" "${OSX_DEVELOPER_ROOT}/usr/bin" )
@ -1218,7 +1218,6 @@ source_group("Audio Files\\OPL Synth" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURC
source_group("Audio Files\\OPL Synth\\DOSBox" FILES oplsynth/dosbox/opl.cpp oplsynth/dosbox/opl.h) source_group("Audio Files\\OPL Synth\\DOSBox" FILES oplsynth/dosbox/opl.cpp oplsynth/dosbox/opl.h)
source_group("Audio Files\\Timidity\\Headers" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/timidity/.+\\.h$") source_group("Audio Files\\Timidity\\Headers" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/timidity/.+\\.h$")
source_group("Audio Files\\Timidity\\Source" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/timidity/.+\\.cpp$") source_group("Audio Files\\Timidity\\Source" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/timidity/.+\\.cpp$")
source_group("Cocoa Files" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/cocoa/.+")
source_group("Decorate++" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/thingdef/.+") source_group("Decorate++" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/thingdef/.+")
source_group("FraggleScript" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/fragglescript/.+") source_group("FraggleScript" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/fragglescript/.+")
source_group("Games\\Doom Game" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/g_doom/.+") source_group("Games\\Doom Game" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/g_doom/.+")
@ -1235,7 +1234,10 @@ source_group("Render Data\\Resource Sources" REGULAR_EXPRESSION "^${CMAKE_CURREN
source_group("Render Data\\Textures" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/textures/.+") source_group("Render Data\\Textures" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/textures/.+")
source_group("Render Interface" FILES r_defs.h r_renderer.h r_sky.cpp r_sky.h r_state.h r_utility.cpp r_utility.h) source_group("Render Interface" FILES r_defs.h r_renderer.h r_sky.cpp r_sky.h r_state.h r_utility.cpp r_utility.h)
source_group("Resource Files" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/resourcefiles/.+") source_group("Resource Files" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/resourcefiles/.+")
source_group("SDL Files" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/sdl/.+") source_group("POSIX Files" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/posix/.+")
source_group("Cocoa Files" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/posix/cocoa/.+")
source_group("OS X Files" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/posix/osx/.+")
source_group("SDL Files" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/posix/sdl/.+")
source_group("SFMT" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/sfmt/.+") source_group("SFMT" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/sfmt/.+")
source_group("Shared Game" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/g_shared/.+") source_group("Shared Game" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/g_shared/.+")
source_group("Versioning" FILES version.h win32/zdoom.rc) source_group("Versioning" FILES version.h win32/zdoom.rc)

View file

@ -1,62 +1,62 @@
/* /*
** critsec.cpp ** critsec.cpp
** **
**--------------------------------------------------------------------------- **---------------------------------------------------------------------------
** Copyright 2014 Alexey Lysiuk ** Copyright 2014 Alexey Lysiuk
** All rights reserved. ** All rights reserved.
** **
** Redistribution and use in source and binary forms, with or without ** Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions ** modification, are permitted provided that the following conditions
** are met: ** are met:
** **
** 1. Redistributions of source code must retain the above copyright ** 1. Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer. ** notice, this list of conditions and the following disclaimer.
** 2. Redistributions in binary form must reproduce the above copyright ** 2. Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in the ** notice, this list of conditions and the following disclaimer in the
** documentation and/or other materials provided with the distribution. ** documentation and/or other materials provided with the distribution.
** 3. The name of the author may not be used to endorse or promote products ** 3. The name of the author may not be used to endorse or promote products
** derived from this software without specific prior written permission. ** derived from this software without specific prior written permission.
** **
** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR ** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES ** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. ** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, ** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT ** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
**--------------------------------------------------------------------------- **---------------------------------------------------------------------------
** **
*/ */
#include "critsec.h" #include "critsec.h"
// TODO: add error handling // TODO: add error handling
FCriticalSection::FCriticalSection() FCriticalSection::FCriticalSection()
{ {
pthread_mutexattr_t attributes; pthread_mutexattr_t attributes;
pthread_mutexattr_init(&attributes); pthread_mutexattr_init(&attributes);
pthread_mutexattr_settype(&attributes, PTHREAD_MUTEX_RECURSIVE); pthread_mutexattr_settype(&attributes, PTHREAD_MUTEX_RECURSIVE);
pthread_mutex_init(&m_mutex, &attributes); pthread_mutex_init(&m_mutex, &attributes);
pthread_mutexattr_destroy(&attributes); pthread_mutexattr_destroy(&attributes);
} }
FCriticalSection::~FCriticalSection() FCriticalSection::~FCriticalSection()
{ {
pthread_mutex_destroy(&m_mutex); pthread_mutex_destroy(&m_mutex);
} }
void FCriticalSection::Enter() void FCriticalSection::Enter()
{ {
pthread_mutex_lock(&m_mutex); pthread_mutex_lock(&m_mutex);
} }
void FCriticalSection::Leave() void FCriticalSection::Leave()
{ {
pthread_mutex_unlock(&m_mutex); pthread_mutex_unlock(&m_mutex);
} }

View file

@ -1,53 +1,53 @@
/* /*
** critsec.h ** critsec.h
** **
**--------------------------------------------------------------------------- **---------------------------------------------------------------------------
** Copyright 2014 Alexey Lysiuk ** Copyright 2014 Alexey Lysiuk
** All rights reserved. ** All rights reserved.
** **
** Redistribution and use in source and binary forms, with or without ** Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions ** modification, are permitted provided that the following conditions
** are met: ** are met:
** **
** 1. Redistributions of source code must retain the above copyright ** 1. Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer. ** notice, this list of conditions and the following disclaimer.
** 2. Redistributions in binary form must reproduce the above copyright ** 2. Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in the ** notice, this list of conditions and the following disclaimer in the
** documentation and/or other materials provided with the distribution. ** documentation and/or other materials provided with the distribution.
** 3. The name of the author may not be used to endorse or promote products ** 3. The name of the author may not be used to endorse or promote products
** derived from this software without specific prior written permission. ** derived from this software without specific prior written permission.
** **
** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR ** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES ** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. ** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, ** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT ** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
**--------------------------------------------------------------------------- **---------------------------------------------------------------------------
** **
*/ */
#ifndef CRITSEC_H #ifndef CRITSEC_H
#define CRITSEC_H #define CRITSEC_H
#include <pthread.h> #include <pthread.h>
class FCriticalSection class FCriticalSection
{ {
public: public:
FCriticalSection(); FCriticalSection();
~FCriticalSection(); ~FCriticalSection();
void Enter(); void Enter();
void Leave(); void Leave();
private: private:
pthread_mutex_t m_mutex; pthread_mutex_t m_mutex;
}; };
#endif #endif

View file

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

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

View file

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

View file

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

View file

@ -1,330 +1,330 @@
/* /*
** hardware.cpp ** hardware.cpp
** Somewhat OS-independant interface to the screen, mouse, keyboard, and stick ** Somewhat OS-independant interface to the screen, mouse, keyboard, and stick
** **
**--------------------------------------------------------------------------- **---------------------------------------------------------------------------
** Copyright 1998-2006 Randy Heit ** Copyright 1998-2006 Randy Heit
** All rights reserved. ** All rights reserved.
** **
** Redistribution and use in source and binary forms, with or without ** Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions ** modification, are permitted provided that the following conditions
** are met: ** are met:
** **
** 1. Redistributions of source code must retain the above copyright ** 1. Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer. ** notice, this list of conditions and the following disclaimer.
** 2. Redistributions in binary form must reproduce the above copyright ** 2. Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in the ** notice, this list of conditions and the following disclaimer in the
** documentation and/or other materials provided with the distribution. ** documentation and/or other materials provided with the distribution.
** 3. The name of the author may not be used to endorse or promote products ** 3. The name of the author may not be used to endorse or promote products
** derived from this software without specific prior written permission. ** derived from this software without specific prior written permission.
** **
** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR ** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES ** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. ** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, ** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT ** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
**--------------------------------------------------------------------------- **---------------------------------------------------------------------------
** **
*/ */
#include <SDL.h> #include <SDL.h>
#include <signal.h> #include <signal.h>
#include <time.h> #include <time.h>
#include "hardware.h" #include "hardware.h"
#include "i_video.h" #include "i_video.h"
#include "i_system.h" #include "i_system.h"
#include "c_console.h" #include "c_console.h"
#include "c_cvars.h" #include "c_cvars.h"
#include "c_dispatch.h" #include "c_dispatch.h"
#include "sdlvideo.h" #include "sdlvideo.h"
#include "v_text.h" #include "v_text.h"
#include "doomstat.h" #include "doomstat.h"
#include "m_argv.h" #include "m_argv.h"
#include "r_renderer.h" #include "r_renderer.h"
#include "r_swrenderer.h" #include "r_swrenderer.h"
EXTERN_CVAR (Bool, ticker) EXTERN_CVAR (Bool, ticker)
EXTERN_CVAR (Bool, fullscreen) EXTERN_CVAR (Bool, fullscreen)
EXTERN_CVAR (Float, vid_winscale) EXTERN_CVAR (Float, vid_winscale)
IVideo *Video; IVideo *Video;
void I_ShutdownGraphics () void I_ShutdownGraphics ()
{ {
if (screen) if (screen)
{ {
DFrameBuffer *s = screen; DFrameBuffer *s = screen;
screen = NULL; screen = NULL;
s->ObjectFlags |= OF_YesReallyDelete; s->ObjectFlags |= OF_YesReallyDelete;
delete s; delete s;
} }
if (Video) if (Video)
delete Video, Video = NULL; delete Video, Video = NULL;
} }
void I_InitGraphics () void I_InitGraphics ()
{ {
UCVarValue val; UCVarValue val;
val.Bool = !!Args->CheckParm ("-devparm"); val.Bool = !!Args->CheckParm ("-devparm");
ticker.SetGenericRepDefault (val, CVAR_Bool); ticker.SetGenericRepDefault (val, CVAR_Bool);
Video = new SDLVideo (0); Video = new SDLVideo (0);
if (Video == NULL) if (Video == NULL)
I_FatalError ("Failed to initialize display"); I_FatalError ("Failed to initialize display");
atterm (I_ShutdownGraphics); atterm (I_ShutdownGraphics);
Video->SetWindowedScale (vid_winscale); Video->SetWindowedScale (vid_winscale);
} }
static void I_DeleteRenderer() static void I_DeleteRenderer()
{ {
if (Renderer != NULL) delete Renderer; if (Renderer != NULL) delete Renderer;
} }
void I_CreateRenderer() void I_CreateRenderer()
{ {
if (Renderer == NULL) if (Renderer == NULL)
{ {
Renderer = new FSoftwareRenderer; Renderer = new FSoftwareRenderer;
atterm(I_DeleteRenderer); atterm(I_DeleteRenderer);
} }
} }
/** Remaining code is common to Win32 and Linux **/ /** Remaining code is common to Win32 and Linux **/
// VIDEO WRAPPERS --------------------------------------------------------- // VIDEO WRAPPERS ---------------------------------------------------------
DFrameBuffer *I_SetMode (int &width, int &height, DFrameBuffer *old) DFrameBuffer *I_SetMode (int &width, int &height, DFrameBuffer *old)
{ {
bool fs = false; bool fs = false;
switch (Video->GetDisplayType ()) switch (Video->GetDisplayType ())
{ {
case DISPLAY_WindowOnly: case DISPLAY_WindowOnly:
fs = false; fs = false;
break; break;
case DISPLAY_FullscreenOnly: case DISPLAY_FullscreenOnly:
fs = true; fs = true;
break; break;
case DISPLAY_Both: case DISPLAY_Both:
fs = fullscreen; fs = fullscreen;
break; break;
} }
DFrameBuffer *res = Video->CreateFrameBuffer (width, height, fs, old); DFrameBuffer *res = Video->CreateFrameBuffer (width, height, fs, old);
/* Right now, CreateFrameBuffer cannot return NULL /* Right now, CreateFrameBuffer cannot return NULL
if (res == NULL) if (res == NULL)
{ {
I_FatalError ("Mode %dx%d is unavailable\n", width, height); I_FatalError ("Mode %dx%d is unavailable\n", width, height);
} }
*/ */
return res; return res;
} }
bool I_CheckResolution (int width, int height, int bits) bool I_CheckResolution (int width, int height, int bits)
{ {
int twidth, theight; int twidth, theight;
Video->StartModeIterator (bits, screen ? screen->IsFullscreen() : fullscreen); Video->StartModeIterator (bits, screen ? screen->IsFullscreen() : fullscreen);
while (Video->NextMode (&twidth, &theight, NULL)) while (Video->NextMode (&twidth, &theight, NULL))
{ {
if (width == twidth && height == theight) if (width == twidth && height == theight)
return true; return true;
} }
return false; return false;
} }
void I_ClosestResolution (int *width, int *height, int bits) void I_ClosestResolution (int *width, int *height, int bits)
{ {
int twidth, theight; int twidth, theight;
int cwidth = 0, cheight = 0; int cwidth = 0, cheight = 0;
int iteration; int iteration;
DWORD closest = 4294967295u; DWORD closest = 4294967295u;
for (iteration = 0; iteration < 2; iteration++) for (iteration = 0; iteration < 2; iteration++)
{ {
Video->StartModeIterator (bits, screen ? screen->IsFullscreen() : fullscreen); Video->StartModeIterator (bits, screen ? screen->IsFullscreen() : fullscreen);
while (Video->NextMode (&twidth, &theight, NULL)) while (Video->NextMode (&twidth, &theight, NULL))
{ {
if (twidth == *width && theight == *height) if (twidth == *width && theight == *height)
return; return;
if (iteration == 0 && (twidth < *width || theight < *height)) if (iteration == 0 && (twidth < *width || theight < *height))
continue; continue;
DWORD dist = (twidth - *width) * (twidth - *width) DWORD dist = (twidth - *width) * (twidth - *width)
+ (theight - *height) * (theight - *height); + (theight - *height) * (theight - *height);
if (dist < closest) if (dist < closest)
{ {
closest = dist; closest = dist;
cwidth = twidth; cwidth = twidth;
cheight = theight; cheight = theight;
} }
} }
if (closest != 4294967295u) if (closest != 4294967295u)
{ {
*width = cwidth; *width = cwidth;
*height = cheight; *height = cheight;
return; return;
} }
} }
} }
//========================================================================== //==========================================================================
// //
// SetFPSLimit // SetFPSLimit
// //
// Initializes an event timer to fire at a rate of <limit>/sec. The video // Initializes an event timer to fire at a rate of <limit>/sec. The video
// update will wait for this timer to trigger before updating. // update will wait for this timer to trigger before updating.
// //
// Pass 0 as the limit for unlimited. // Pass 0 as the limit for unlimited.
// Pass a negative value for the limit to use the value of vid_maxfps. // Pass a negative value for the limit to use the value of vid_maxfps.
// //
//========================================================================== //==========================================================================
EXTERN_CVAR(Int, vid_maxfps); EXTERN_CVAR(Int, vid_maxfps);
EXTERN_CVAR(Bool, cl_capfps); EXTERN_CVAR(Bool, cl_capfps);
#ifndef __APPLE__ #ifndef __APPLE__
Semaphore FPSLimitSemaphore; Semaphore FPSLimitSemaphore;
static void FPSLimitNotify(sigval val) static void FPSLimitNotify(sigval val)
{ {
SEMAPHORE_SIGNAL(FPSLimitSemaphore) SEMAPHORE_SIGNAL(FPSLimitSemaphore)
} }
void I_SetFPSLimit(int limit) void I_SetFPSLimit(int limit)
{ {
static sigevent FPSLimitEvent; static sigevent FPSLimitEvent;
static timer_t FPSLimitTimer; static timer_t FPSLimitTimer;
static bool FPSLimitTimerEnabled = false; static bool FPSLimitTimerEnabled = false;
static bool EventSetup = false; static bool EventSetup = false;
if(!EventSetup) if(!EventSetup)
{ {
EventSetup = true; EventSetup = true;
FPSLimitEvent.sigev_notify = SIGEV_THREAD; FPSLimitEvent.sigev_notify = SIGEV_THREAD;
FPSLimitEvent.sigev_signo = 0; FPSLimitEvent.sigev_signo = 0;
FPSLimitEvent.sigev_value.sival_int = 0; FPSLimitEvent.sigev_value.sival_int = 0;
FPSLimitEvent.sigev_notify_function = FPSLimitNotify; FPSLimitEvent.sigev_notify_function = FPSLimitNotify;
FPSLimitEvent.sigev_notify_attributes = NULL; FPSLimitEvent.sigev_notify_attributes = NULL;
SEMAPHORE_INIT(FPSLimitSemaphore, 0, 0) SEMAPHORE_INIT(FPSLimitSemaphore, 0, 0)
} }
if (limit < 0) if (limit < 0)
{ {
limit = vid_maxfps; limit = vid_maxfps;
} }
// Kill any leftover timer. // Kill any leftover timer.
if (FPSLimitTimerEnabled) if (FPSLimitTimerEnabled)
{ {
timer_delete(FPSLimitTimer); timer_delete(FPSLimitTimer);
FPSLimitTimerEnabled = false; FPSLimitTimerEnabled = false;
} }
if (limit == 0) if (limit == 0)
{ // no limit { // no limit
DPrintf("FPS timer disabled\n"); DPrintf("FPS timer disabled\n");
} }
else else
{ {
FPSLimitTimerEnabled = true; FPSLimitTimerEnabled = true;
if(timer_create(CLOCK_REALTIME, &FPSLimitEvent, &FPSLimitTimer) == -1) if(timer_create(CLOCK_REALTIME, &FPSLimitEvent, &FPSLimitTimer) == -1)
Printf("Failed to create FPS limitter event\n"); Printf("Failed to create FPS limitter event\n");
itimerspec period = { {0, 0}, {0, 0} }; itimerspec period = { {0, 0}, {0, 0} };
period.it_value.tv_nsec = period.it_interval.tv_nsec = 1000000000 / limit; period.it_value.tv_nsec = period.it_interval.tv_nsec = 1000000000 / limit;
if(timer_settime(FPSLimitTimer, 0, &period, NULL) == -1) if(timer_settime(FPSLimitTimer, 0, &period, NULL) == -1)
Printf("Failed to set FPS limitter timer\n"); Printf("Failed to set FPS limitter timer\n");
DPrintf("FPS timer set to %u ms\n", (unsigned int) period.it_interval.tv_nsec / 1000000); DPrintf("FPS timer set to %u ms\n", (unsigned int) period.it_interval.tv_nsec / 1000000);
} }
} }
#else #else
// So Apple doesn't support POSIX timers and I can't find a good substitute short of // So Apple doesn't support POSIX timers and I can't find a good substitute short of
// having Objective-C Cocoa events or something like that. // having Objective-C Cocoa events or something like that.
void I_SetFPSLimit(int limit) void I_SetFPSLimit(int limit)
{ {
} }
#endif #endif
CUSTOM_CVAR (Int, vid_maxfps, 200, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) CUSTOM_CVAR (Int, vid_maxfps, 200, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
{ {
if (vid_maxfps < TICRATE && vid_maxfps != 0) if (vid_maxfps < TICRATE && vid_maxfps != 0)
{ {
vid_maxfps = TICRATE; vid_maxfps = TICRATE;
} }
else if (vid_maxfps > 1000) else if (vid_maxfps > 1000)
{ {
vid_maxfps = 1000; vid_maxfps = 1000;
} }
else if (cl_capfps == 0) else if (cl_capfps == 0)
{ {
I_SetFPSLimit(vid_maxfps); I_SetFPSLimit(vid_maxfps);
} }
} }
extern int NewWidth, NewHeight, NewBits, DisplayBits; extern int NewWidth, NewHeight, NewBits, DisplayBits;
CUSTOM_CVAR (Bool, fullscreen, false, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) CUSTOM_CVAR (Bool, fullscreen, false, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
{ {
NewWidth = screen->GetWidth(); NewWidth = screen->GetWidth();
NewHeight = screen->GetHeight(); NewHeight = screen->GetHeight();
NewBits = DisplayBits; NewBits = DisplayBits;
setmodeneeded = true; setmodeneeded = true;
} }
CUSTOM_CVAR (Float, vid_winscale, 1.f, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) CUSTOM_CVAR (Float, vid_winscale, 1.f, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
{ {
if (self < 1.f) if (self < 1.f)
{ {
self = 1.f; self = 1.f;
} }
else if (Video) else if (Video)
{ {
Video->SetWindowedScale (self); Video->SetWindowedScale (self);
NewWidth = screen->GetWidth(); NewWidth = screen->GetWidth();
NewHeight = screen->GetHeight(); NewHeight = screen->GetHeight();
NewBits = DisplayBits; NewBits = DisplayBits;
setmodeneeded = true; setmodeneeded = true;
} }
} }
CCMD (vid_listmodes) CCMD (vid_listmodes)
{ {
static const char *ratios[5] = { "", " - 16:9", " - 16:10", "", " - 5:4" }; static const char *ratios[5] = { "", " - 16:9", " - 16:10", "", " - 5:4" };
int width, height, bits; int width, height, bits;
bool letterbox; bool letterbox;
if (Video == NULL) if (Video == NULL)
{ {
return; return;
} }
for (bits = 1; bits <= 32; bits++) for (bits = 1; bits <= 32; bits++)
{ {
Video->StartModeIterator (bits, screen->IsFullscreen()); Video->StartModeIterator (bits, screen->IsFullscreen());
while (Video->NextMode (&width, &height, &letterbox)) while (Video->NextMode (&width, &height, &letterbox))
{ {
bool thisMode = (width == DisplayWidth && height == DisplayHeight && bits == DisplayBits); bool thisMode = (width == DisplayWidth && height == DisplayHeight && bits == DisplayBits);
int ratio = CheckRatio (width, height); int ratio = CheckRatio (width, height);
Printf (thisMode ? PRINT_BOLD : PRINT_HIGH, Printf (thisMode ? PRINT_BOLD : PRINT_HIGH,
"%s%4d x%5d x%3d%s%s\n", "%s%4d x%5d x%3d%s%s\n",
thisMode || !(ratio & 3) ? "" : TEXTCOLOR_GOLD, thisMode || !(ratio & 3) ? "" : TEXTCOLOR_GOLD,
width, height, bits, width, height, bits,
ratios[ratio], ratios[ratio],
thisMode || !letterbox ? "" : TEXTCOLOR_BROWN " LB" thisMode || !letterbox ? "" : TEXTCOLOR_BROWN " LB"
); );
} }
} }
} }
CCMD (vid_currentmode) CCMD (vid_currentmode)
{ {
Printf ("%dx%dx%d\n", DisplayWidth, DisplayHeight, DisplayBits); Printf ("%dx%dx%d\n", DisplayWidth, DisplayHeight, DisplayBits);
} }

File diff suppressed because it is too large Load diff

View file

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

File diff suppressed because it is too large Load diff

View file

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

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