diff --git a/neo/CMakeLists.txt b/neo/CMakeLists.txt index 809251ad..4310301d 100644 --- a/neo/CMakeLists.txt +++ b/neo/CMakeLists.txt @@ -30,6 +30,8 @@ endif() set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/sys/cmake") set(CMAKE_SKIP_RPATH ON CACHE BOOL "Skip RPATH" FORCE) +set(DHEWM3BINARY "dhewm3") + include(CheckCXXCompilerFlag) include(GNUInstallDirs OPTIONAL RESULT_VARIABLE GNUINSTALLDIRS) @@ -108,8 +110,10 @@ include_directories(${VORBISFILE_INCLUDE_DIR}) find_package(OpenAL REQUIRED) include_directories(${OPENAL_INCLUDE_DIR}) -find_package(X11 REQUIRED) -include_directories(${X11_INCLUDE_DIR}) +if(NOT AROS) + find_package(X11 REQUIRED) + include_directories(${X11_INCLUDE_DIR}) +endif() if (SDL2) # skip SDL2main @@ -162,11 +166,13 @@ if(CMAKE_COMPILER_IS_GNUCC OR CMAKE_C_COMPILER_ID STREQUAL "Clang") add_compile_options(-fno-strict-aliasing) - CHECK_CXX_COMPILER_FLAG("-fvisibility=hidden" cxx_has_fvisibility) - if(NOT cxx_has_fvisibility) - message(FATAL_ERROR "Compiler does not support -fvisibility") + if(NOT AROS) + CHECK_CXX_COMPILER_FLAG("-fvisibility=hidden" cxx_has_fvisibility) + if(NOT cxx_has_fvisibility) + message(FATAL_ERROR "Compiler does not support -fvisibility") + endif() + add_compile_options(-fvisibility=hidden) endif() - add_compile_options(-fvisibility=hidden) # TODO fix these warnings add_compile_options(-Wno-sign-compare) @@ -178,7 +184,10 @@ if(CMAKE_COMPILER_IS_GNUCC OR CMAKE_C_COMPILER_ID STREQUAL "Clang") add_compile_options(-Woverloaded-virtual) endif() - if(APPLE) + if(AROS) + set(CMAKE_SHARED_LIBRARY_SUFFIX ".aros-${cpu}") + add_definitions(-DIOAPI_NO_64) + elseif(APPLE) add_definitions(-DMACOS_X=1) if(cpu STREQUAL "x86_64") @@ -679,7 +688,31 @@ set(src_core set(src_stub_openal sys/stub/openal_stub.cpp) set(src_stub_gl sys/stub/stub_gl.cpp) -if(APPLE) +if(AROS) + set(DHEWM3BINARY "ADoom3") + set(sys_libs ${sys_libs} dll) + + set(src_arosdll + sys/aros/dll/dllstartup.c + sys/aros/dll/dll.c + sys/aros/dll/dllimport.c + ) + + set(src_sys_base + sys/cpu.cpp + sys/threads.cpp + sys/events.cpp + sys/sys_local.cpp + sys/aros/aros_net.cpp + sys/aros/aros_signal.cpp + sys/aros/aros_main.cpp + sys/aros/aros_dos.cpp + ) + + set(src_sys_core + sys/glimp.cpp + ) +elseif(APPLE) set(OSX_RESOURCE_FILES "${CMAKE_SOURCE_DIR}/sys/osx/Doom3.icns" "${CMAKE_SOURCE_DIR}/sys/osx/Doom 3.rsrc" @@ -745,27 +778,36 @@ include_directories(${CMAKE_BINARY_DIR}) include_directories(${CMAKE_SOURCE_DIR}) add_library(idlib STATIC ${src_idlib}) -if(CMAKE_COMPILER_IS_GNUCC OR CMAKE_C_COMPILER_ID STREQUAL "Clang" AND NOT MINGW) - set_target_properties(idlib PROPERTIES COMPILE_FLAGS "-fPIC") +if (AROS) + add_library(dll STATIC ${src_arosdll}) + if(CMAKE_SYSTEM_PROCESSOR STREQUAL "i386") + set(AROS_ARCH "x86") + else() + set(AROS_ARCH ${CMAKE_SYSTEM_PROCESSOR}) + endif() +else() + if(CMAKE_COMPILER_IS_GNUCC OR CMAKE_C_COMPILER_ID STREQUAL "Clang" AND NOT MINGW) + set_target_properties(idlib PROPERTIES COMPILE_FLAGS "-fPIC") + endif() endif() if(CORE) - add_executable(dhewm3 WIN32 MACOSX_BUNDLE + add_executable(${DHEWM3BINARY} WIN32 MACOSX_BUNDLE ${src_core} ${src_sys_base} ${src_sys_core} ) - set_target_properties(dhewm3 PROPERTIES COMPILE_DEFINITIONS "__DOOM_DLL__") - set_target_properties(dhewm3 PROPERTIES LINK_FLAGS "${ldflags}") - set_target_properties(dhewm3 PROPERTIES MACOSX_BUNDLE_INFO_PLIST ${PROJECT_SOURCE_DIR}/sys/osx/Info.plist) + set_target_properties(${DHEWM3BINARY} PROPERTIES COMPILE_DEFINITIONS "__DOOM_DLL__") + set_target_properties(${DHEWM3BINARY} PROPERTIES LINK_FLAGS "${ldflags}") + set_target_properties(${DHEWM3BINARY} PROPERTIES MACOSX_BUNDLE_INFO_PLIST ${PROJECT_SOURCE_DIR}/sys/osx/Info.plist) - target_link_libraries(dhewm3 + target_link_libraries(${DHEWM3BINARY} idlib ${OPENAL_LIBRARY} - ${OGG_LIBRARIES} ${VORBISFILE_LIBRARIES} ${VORBIS_LIBRARIES} + ${OGG_LIBRARIES} ${CURL_LIBRARY} ${JPEG_LIBRARY} ${ZLIB_LIBRARY} @@ -774,7 +816,7 @@ if(CORE) ) if(NOT APPLE AND NOT WIN32) - install(TARGETS dhewm3 + install(TARGETS ${DHEWM3BINARY} RUNTIME DESTINATION "${bindir}" LIBRARY DESTINATION "${libdir}" ARCHIVE DESTINATION "${libdir}" @@ -783,19 +825,20 @@ if(CORE) endif() if(DEDICATED) - add_executable(dhewm3ded WIN32 MACOSX_BUNDLE + add_executable(${DHEWM3BINARY}ded WIN32 MACOSX_BUNDLE ${src_core} ${src_stub_openal} ${src_stub_gl} ${src_sys_base} ) - set_target_properties(dhewm3ded PROPERTIES COMPILE_DEFINITIONS "ID_DEDICATED;__DOOM_DLL__") - set_target_properties(dhewm3ded PROPERTIES LINK_FLAGS "${ldflags}") - target_link_libraries(dhewm3ded + set_target_properties(${DHEWM3BINARY}ded PROPERTIES COMPILE_DEFINITIONS "ID_DEDICATED;__DOOM_DLL__") + set_target_properties(${DHEWM3BINARY}ded PROPERTIES LINK_FLAGS "${ldflags}") + target_link_libraries(${DHEWM3BINARY}ded idlib ${VORBISFILE_LIBRARIES} ${VORBIS_LIBRARIES} + ${OGG_LIBRARIES} ${CURL_LIBRARY} ${JPEG_LIBRARY} ${ZLIB_LIBRARY} @@ -804,7 +847,7 @@ if(DEDICATED) ) if(NOT APPLE AND NOT WIN32) - install(TARGETS dhewm3ded + install(TARGETS ${DHEWM3BINARY}ded RUNTIME DESTINATION "${bindir}" LIBRARY DESTINATION "${libdir}" ARCHIVE DESTINATION "${libdir}" @@ -813,13 +856,22 @@ if(DEDICATED) endif() if(BASE) - add_library(base SHARED ${src_game}) + if (AROS) + add_executable(base sys/aros/dll/dllglue.c ${src_game}) + set_target_properties(base PROPERTIES OUTPUT_NAME "base.aros-${AROS_ARCH}") + else() + add_library(base SHARED ${src_game}) + endif() set_target_properties(base PROPERTIES PREFIX "") set_target_properties(base PROPERTIES COMPILE_DEFINITIONS "GAME_DLL") set_target_properties(base PROPERTIES COMPILE_FLAGS "-I${CMAKE_SOURCE_DIR}/game") set_target_properties(base PROPERTIES LINK_FLAGS "${ldflags}") set_target_properties(base PROPERTIES INSTALL_NAME_DIR "@executable_path") - target_link_libraries(base idlib) + if (AROS) + target_link_libraries(base idlib dll) + else() + target_link_libraries(base idlib) + endif() if(NOT APPLE AND NOT WIN32) install(TARGETS base @@ -831,13 +883,22 @@ if(BASE) endif() if(D3XP) - add_library(d3xp SHARED ${src_d3xp}) + if (AROS) + add_executable(d3xp sys/aros/dll/dllglue.c ${src_d3xp}) + set_target_properties(d3xp PROPERTIES OUTPUT_NAME "d3xp.aros-${AROS_ARCH}") + else() + add_library(d3xp SHARED ${src_d3xp}) + endif() set_target_properties(d3xp PROPERTIES PREFIX "") set_target_properties(d3xp PROPERTIES COMPILE_DEFINITIONS "GAME_DLL;_D3XP;CTF") set_target_properties(d3xp PROPERTIES COMPILE_FLAGS "-I${CMAKE_SOURCE_DIR}/d3xp") set_target_properties(d3xp PROPERTIES LINK_FLAGS "${ldflags}") set_target_properties(d3xp PROPERTIES INSTALL_NAME_DIR "@executable_path") - target_link_libraries(d3xp idlib) + if (AROS) + target_link_libraries(d3xp idlib dll) + else() + target_link_libraries(d3xp idlib) + endif() if(NOT APPLE AND NOT WIN32) install(TARGETS d3xp diff --git a/neo/framework/FileSystem.cpp b/neo/framework/FileSystem.cpp index 48002781..d47015c8 100644 --- a/neo/framework/FileSystem.cpp +++ b/neo/framework/FileSystem.cpp @@ -476,7 +476,7 @@ idCVar idFileSystemLocal::fs_cdpath( "fs_cdpath", "", CVAR_SYSTEM | CVAR_INIT, " idCVar idFileSystemLocal::fs_devpath( "fs_devpath", "", CVAR_SYSTEM | CVAR_INIT, "" ); idCVar idFileSystemLocal::fs_game( "fs_game", "", CVAR_SYSTEM | CVAR_INIT | CVAR_SERVERINFO, "mod path" ); idCVar idFileSystemLocal::fs_game_base( "fs_game_base", "", CVAR_SYSTEM | CVAR_INIT | CVAR_SERVERINFO, "alternate mod path, searched after the main fs_game path, before the basedir" ); -#ifdef WIN32 +#if defined(__AROS__) || defined(WIN32) idCVar idFileSystemLocal::fs_caseSensitiveOS( "fs_caseSensitiveOS", "0", CVAR_SYSTEM | CVAR_BOOL, "" ); #else idCVar idFileSystemLocal::fs_caseSensitiveOS( "fs_caseSensitiveOS", "1", CVAR_SYSTEM | CVAR_BOOL, "" ); diff --git a/neo/framework/Licensee.h b/neo/framework/Licensee.h index 12251274..45b19b5a 100644 --- a/neo/framework/Licensee.h +++ b/neo/framework/Licensee.h @@ -34,15 +34,23 @@ If you have questions concerning this license or the applicable additional terms =============================================================================== */ +#if defined(__AROS__) +#define GAME_NAME "ADoom3" // appears on window titles and errors +#define ENGINE_VERSION "dhewm3 1.4.1" // printed in console +#define CONFIG_FILE "adoom3.cfg" +#else #define GAME_NAME "dhewm 3" // appears on window titles and errors #define ENGINE_VERSION "dhewm 3 1.4.1" // printed in console +#endif // paths #define BASE_GAMEDIR "base" // filenames +#ifndef CONFIG_FILE #define CONFIG_FILE "dhewm.cfg" +#endif // base folder where the source code lives #define SOURCE_CODE_BASE_FOLDER "neo" diff --git a/neo/framework/Session.cpp b/neo/framework/Session.cpp index 579a6623..cca5cf91 100644 --- a/neo/framework/Session.cpp +++ b/neo/framework/Session.cpp @@ -37,6 +37,14 @@ If you have questions concerning this license or the applicable additional terms #include "framework/Session_local.h" +#if defined(__AROS__) +#define CDKEY_FILEPATH CDKEY_FILE +#define XPKEY_FILEPATH XPKEY_FILE +#else +#define CDKEY_FILEPATH "../" BASE_GAMEDIR "/" CDKEY_FILE +#define XPKEY_FILEPATH "../" BASE_GAMEDIR "/" XPKEY_FILE +#endif + idCVar idSessionLocal::com_showAngles( "com_showAngles", "0", CVAR_SYSTEM | CVAR_BOOL, "" ); idCVar idSessionLocal::com_minTics( "com_minTics", "1", CVAR_SYSTEM, "" ); idCVar idSessionLocal::com_showTics( "com_showTics", "0", CVAR_SYSTEM | CVAR_BOOL, "" ); @@ -2961,7 +2969,7 @@ void idSessionLocal::ReadCDKey( void ) { cdkey_state = CDKEY_UNKNOWN; - filename = "../" BASE_GAMEDIR "/" CDKEY_FILE; + filename = CDKEY_FILEPATH; f = fileSystem->OpenExplicitFileRead( fileSystem->RelativePathToOSPath( filename, "fs_configpath" ) ); // try the install path, which is where the cd installer and steam put it @@ -2980,7 +2988,7 @@ void idSessionLocal::ReadCDKey( void ) { xpkey_state = CDKEY_UNKNOWN; - filename = "../" BASE_GAMEDIR "/" XPKEY_FILE; + filename = XPKEY_FILEPATH; f = fileSystem->OpenExplicitFileRead( fileSystem->RelativePathToOSPath( filename, "fs_configpath" ) ); // try the install path, which is where the cd installer and steam put it @@ -3008,7 +3016,7 @@ void idSessionLocal::WriteCDKey( void ) { idFile *f; const char *OSPath; - filename = "../" BASE_GAMEDIR "/" CDKEY_FILE; + filename = CDKEY_FILEPATH; // OpenFileWrite advertises creating directories to the path if needed, but that won't work with a '..' in the path // occasionally on windows, but mostly on Linux and OSX, the fs_configpath/base may not exist in full OSPath = fileSystem->BuildOSPath( cvarSystem->GetCVarString( "fs_configpath" ), BASE_GAMEDIR, CDKEY_FILE ); @@ -3021,7 +3029,7 @@ void idSessionLocal::WriteCDKey( void ) { f->Printf( "%s%s", cdkey, CDKEY_TEXT ); fileSystem->CloseFile( f ); - filename = "../" BASE_GAMEDIR "/" XPKEY_FILE; + filename = XPKEY_FILEPATH; f = fileSystem->OpenFileWrite( filename, "fs_configpath" ); if ( !f ) { common->Printf( "Couldn't write %s.\n", filename.c_str() ); diff --git a/neo/game/ai/AI_pathing.cpp b/neo/game/ai/AI_pathing.cpp index 314928ea..9c961a9c 100644 --- a/neo/game/ai/AI_pathing.cpp +++ b/neo/game/ai/AI_pathing.cpp @@ -36,6 +36,8 @@ If you have questions concerning this license or the applicable additional terms #include "ai/AI.h" +#include <stddef.h> + /* =============================================================================== @@ -604,12 +606,14 @@ pathNode_t *BuildPathTree( const obstacle_t *obstacles, int numObstacles, const pathNode_t *root, *node, *child; // gcc 4.0 idQueueTemplate<pathNode_t, offsetof( pathNode_t, next ) > pathNodeQueue, treeQueue; + root = pathNodeAllocator.Alloc(); root->Init(); root->pos = startPos; root->delta = seekPos - root->pos; root->numNodes = 0; + pathNodeQueue.Add( root ); for ( node = pathNodeQueue.Get(); node && pathNodeAllocator.GetAllocCount() < MAX_PATH_NODES; node = pathNodeQueue.Get() ) { diff --git a/neo/idlib/Str.cpp b/neo/idlib/Str.cpp index 2271c733..b37e1a9e 100644 --- a/neo/idlib/Str.cpp +++ b/neo/idlib/Str.cpp @@ -817,7 +817,11 @@ idStr::DefaultPath ================== */ idStr &idStr::DefaultPath( const char *basepath ) { +#if defined(__AROS__) + if ( ( ( *this )[ 0 ] == '/' ) || ( ( *this )[ 0 ] == '\\' ) || ( ( *this )[ 0 ] == ':' ) ) { +#else if ( ( ( *this )[ 0 ] == '/' ) || ( ( *this )[ 0 ] == '\\' ) ) { +#endif // absolute path location return *this; } @@ -840,11 +844,19 @@ void idStr::AppendPath( const char *text ) { EnsureAlloced( len + strlen( text ) + 2 ); if ( pos ) { +#if defined(__AROS__) + if (( data[ pos-1 ] != '/' ) || ( data[ pos-1 ] != ':' )) { +#else if ( data[ pos-1 ] != '/' ) { +#endif data[ pos++ ] = '/'; } } +#if defined(__AROS__) + if (( text[i] == '/' ) || ( text[i] == ':' )) { +#else if ( text[i] == '/' ) { +#endif i++; } @@ -869,7 +881,11 @@ idStr &idStr::StripFilename( void ) { int pos; pos = Length() - 1; +#if defined(__AROS__) + while( ( pos > 0 ) && ( ( *this )[ pos ] != '/' ) && ( ( *this )[ pos ] != '\\' ) && ( ( *this )[ pos ] != ':' ) ) { +#else while( ( pos > 0 ) && ( ( *this )[ pos ] != '/' ) && ( ( *this )[ pos ] != '\\' ) ) { +#endif pos--; } @@ -890,7 +906,11 @@ idStr &idStr::StripPath( void ) { int pos; pos = Length(); +#if defined(__AROS__) + while( ( pos > 0 ) && ( ( *this )[ pos - 1 ] != '/' ) && ( ( *this )[ pos - 1 ] != '\\' ) && ( ( *this )[ pos - 1 ] != ':' ) ) { +#else while( ( pos > 0 ) && ( ( *this )[ pos - 1 ] != '/' ) && ( ( *this )[ pos - 1 ] != '\\' ) ) { +#endif pos--; } @@ -910,7 +930,11 @@ void idStr::ExtractFilePath( idStr &dest ) const { // back up until a \ or the start // pos = Length(); +#if defined(__AROS__) + while( ( pos > 0 ) && ( ( *this )[ pos - 1 ] != '/' ) && ( ( *this )[ pos - 1 ] != '\\' ) && ( ( *this )[ pos - 1 ] != ':' ) ) { +#else while( ( pos > 0 ) && ( ( *this )[ pos - 1 ] != '/' ) && ( ( *this )[ pos - 1 ] != '\\' ) ) { +#endif pos--; } @@ -929,7 +953,11 @@ void idStr::ExtractFileName( idStr &dest ) const { // back up until a \ or the start // pos = Length() - 1; +#if defined(__AROS__) + while( ( pos > 0 ) && ( ( *this )[ pos - 1 ] != '/' ) && ( ( *this )[ pos - 1 ] != '\\' ) && ( ( *this )[ pos - 1 ] != ':' ) ) { +#else while( ( pos > 0 ) && ( ( *this )[ pos - 1 ] != '/' ) && ( ( *this )[ pos - 1 ] != '\\' ) ) { +#endif pos--; } @@ -949,7 +977,11 @@ void idStr::ExtractFileBase( idStr &dest ) const { // back up until a \ or the start // pos = Length() - 1; +#if defined(__AROS__) + while( ( pos > 0 ) && ( ( *this )[ pos - 1 ] != '/' ) && ( ( *this )[ pos - 1 ] != '\\' ) && ( ( *this )[ pos - 1 ] != ':' ) ) { +#else while( ( pos > 0 ) && ( ( *this )[ pos - 1 ] != '/' ) && ( ( *this )[ pos - 1 ] != '\\' ) ) { +#endif pos--; } diff --git a/neo/idlib/Str.h b/neo/idlib/Str.h index 70e6c9dd..5dfabe9b 100644 --- a/neo/idlib/Str.h +++ b/neo/idlib/Str.h @@ -64,12 +64,18 @@ If you have questions concerning this license or the applicable additional terms #endif #define StrCmpNI use_idStr_Icmpn +#if defined( stricmp ) +#undef stricmp +#endif #define stricmp idStr::Icmp // use_idStr_Icmp #define _stricmp use_idStr_Icmp #if defined( strcasecmp ) #undef strcasecmp #endif #define strcasecmp use_idStr_Icmp +#if defined( strnicmp ) +#undef strnicmp +#endif #define strnicmp use_idStr_Icmpn #define _strnicmp use_idStr_Icmpn #define _memicmp use_idStr_Icmpn diff --git a/neo/mmakefile.src b/neo/mmakefile.src new file mode 100644 index 00000000..d05dffd0 --- /dev/null +++ b/neo/mmakefile.src @@ -0,0 +1,54 @@ +# Copyright � 2012-2017, Nick "Kalamatee" Andrews. +# $Id$ + +# +# This is the AROS specific top level mmakefile to build +# dhewm3. It correctly configures/invokes cmake to +# build the AROS ARM, i386 and x86_64 ports. +# + +include $(SRCDIR)/config/aros.cfg + +DOOM3_EXEDIR := $(AROS_CONTRIB)/Games/Fps/ADoom3 +DOOM3_GAMEDIR := base + +GRAPHITE_CFLAGS := \ + -ftree-loop-linear $(CFLAGS_LOOP_STRIP_MINE) $(CFLAGS_LOOP_BLOCK) + +NOWARN_FLAGS := $(NOWARN_ERROR) $(NOWARN_MISLEADING_INDENTATION) $(NOWARN_MAYBE_UNINITIALIZED) $(NOWARN_NONNULL_COMPARE) $(NOWARN_ENUM_COMPARE) + +USER_CFLAGS := $(NOWARN_FLAGS) +USER_CXXFLAGS := \ + $(CFLAGS_FAST_MATH) -fomit-frame-pointer -fexceptions $(NOWARN_FLAGS) +USER_LDFLAGS := -static-libstdc++ + +#MM- aros-doom3-libs : workbench-libs-jpeg-linklib contrib-openal-linklib development-libogg development-libvorbis +#MM- aros-doom3-libs : contrib-curl contrib-sdl development-SDL_gfx-quick + +#MM aros-doom3 : aros-doom3-libs iconset-Gorilla-contrib-icons-extras-games-adoom3 iconset-Gorilla-contrib-games-doom3game + +DOOM3_OPTIONS := -DCORE=ON -DDEDICATED=ON -DBASE=ON -DSDL2=OFF \ + -DCMAKE_INSTALL_BINDIR= \ + -DCMAKE_INSTALL_LIBDIR= \ + -DZLIB_LIBRARY=$(AROS_DEVELOPER)/lib/libz.a \ + -DZLIB_INCLUDE_DIR=$(AROS_DEVELOPER)/include \ + -DJPEG_LIBRARY=$(AROS_DEVELOPER)/lib/libjpeg.a \ + -DJPEG_INCLUDE_DIR=$(AROS_DEVELOPER)/include \ + -DOPENAL_INCLUDE_DIR=$(AROS_DEVELOPER)/include \ + -DOPENAL_LIBRARY="$(AROS_DEVELOPER)/lib/libopenal.a;$(AROS_DEVELOPER)/lib/libpthread.a;" \ + -DOGG_LIBRARY=$(AROS_DEVELOPER)/lib/libogg.a \ + -DOGG_INCLUDE_DIR=$(AROS_DEVELOPER)/include \ + -DVORBIS_LIBRARY=$(AROS_DEVELOPER)/lib/libvorbis.a \ + -DVORBIS_INCLUDE_DIR=$(AROS_DEVELOPER)/include \ + -DVORBISFILE_LIBRARY=$(AROS_DEVELOPER)/lib/libvorbisfile.a \ + -DVORBISFILE_INCLUDE_DIR=$(AROS_DEVELOPER)/include \ + -DCURL_LIBRARY="$(AROS_DEVELOPER)/lib/libcurl.a;$(AROS_DEVELOPER)/lib/libiconv.a;$(AROS_DEVELOPER)/lib/libz.a;$(AROS_DEVELOPER)/lib/libssl.a;$(AROS_DEVELOPER)/lib/libcrypto.a;" \ + -DCURL_INCLUDE_DIR=$(AROS_DEVELOPER)/include \ + -DSDL_LIBRARY=$(AROS_DEVELOPER)/lib/libSDL.a \ + -DSDL_INCLUDE_DIR=$(AROS_DEVELOPER)/include/SDL + +%build_with_cmake mmake=aros-doom3 \ + prefix="$(DOOM3_EXEDIR)" \ + extraoptions="$(DOOM3_OPTIONS)" + +%common diff --git a/neo/renderer/RenderSystem_init.cpp b/neo/renderer/RenderSystem_init.cpp index 7a7fd62d..669e1358 100644 --- a/neo/renderer/RenderSystem_init.cpp +++ b/neo/renderer/RenderSystem_init.cpp @@ -1309,7 +1309,7 @@ thousands of shots void R_ScreenshotFilename( int &lastNumber, const char *base, idStr &fileName ) { int a,b,c,d, e; - bool restrict = cvarSystem->GetCVarBool( "fs_restrict" ); + bool fsrestrict = cvarSystem->GetCVarBool( "fs_restrict" ); cvarSystem->SetCVarBool( "fs_restrict", false ); lastNumber++; @@ -1339,7 +1339,7 @@ void R_ScreenshotFilename( int &lastNumber, const char *base, idStr &fileName ) } // check again... } - cvarSystem->SetCVarBool( "fs_restrict", restrict ); + cvarSystem->SetCVarBool( "fs_restrict", fsrestrict ); } /* diff --git a/neo/sys/aros/ADoom3.info.src b/neo/sys/aros/ADoom3.info.src new file mode 100644 index 00000000..f5714415 --- /dev/null +++ b/neo/sys/aros/ADoom3.info.src @@ -0,0 +1,2 @@ +TYPE = TOOL +STACK = 10000000 diff --git a/neo/sys/aros/ADoom3.png b/neo/sys/aros/ADoom3.png new file mode 100644 index 00000000..69ac661a Binary files /dev/null and b/neo/sys/aros/ADoom3.png differ diff --git a/neo/sys/aros/ROE.info.src b/neo/sys/aros/ROE.info.src new file mode 100644 index 00000000..1e102045 --- /dev/null +++ b/neo/sys/aros/ROE.info.src @@ -0,0 +1,2 @@ +TYPE = PROJECT +DEFAULTTOOL = C:IconX diff --git a/neo/sys/aros/ROE.png b/neo/sys/aros/ROE.png new file mode 100644 index 00000000..362049fb Binary files /dev/null and b/neo/sys/aros/ROE.png differ diff --git a/neo/sys/aros/aros_dedicated.cpp b/neo/sys/aros/aros_dedicated.cpp new file mode 100644 index 00000000..b7b9c6e5 --- /dev/null +++ b/neo/sys/aros/aros_dedicated.cpp @@ -0,0 +1,46 @@ +/* +=========================================================================== + +Doom 3 GPL Source Code +Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company. + +This file is part of the Doom 3 GPL Source Code ("Doom 3 Source Code"). + +Doom 3 Source Code is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +Doom 3 Source Code is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>. + +In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below. + +If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA. + +=========================================================================== +*/ + +#include "sys/platform.h" +#include "renderer/tr_local.h" +#include "sys/aros/aros_public.h" + +#include "sys/aros/aros_local.h" + +/* +================ +Sys_GetVideoRam +returns in megabytes +================ +*/ + +struct Library *MesaBase; + +int Sys_GetVideoRam( void ) { + return 64; +} diff --git a/neo/sys/aros/aros_dos.cpp b/neo/sys/aros/aros_dos.cpp new file mode 100644 index 00000000..ed135cbd --- /dev/null +++ b/neo/sys/aros/aros_dos.cpp @@ -0,0 +1,516 @@ +/* +=========================================================================== + +Doom 3 GPL Source Code +Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company. + +This file is part of the Doom 3 GPL Source Code ("Doom 3 Source Code"). + +Doom 3 Source Code is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +Doom 3 Source Code is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>. + +In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below. + +If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA. + +=========================================================================== +*/ + +#define DEBUG 1 + +#include <aros/debug.h> +#undef ASSERT + +#include <proto/alib.h> +#include <proto/intuition.h> +#include <proto/exec.h> +#include <proto/dos.h> +#include <proto/iffparse.h> +#include <proto/socket.h> +#include <proto/openurl.h> + +#include <dos/dos.h> +#include <dos/dosextens.h> + +#include <proto/icon.h> +#include <intuition/intuition.h> +#include <workbench/startup.h> + +// undefine - conflict with ID functions +#undef Remove +#undef Insert +#undef Read +#undef Write +#undef Seek +#undef Flush +#undef Close +#undef Allocate +#undef Printf +#undef VPrintf + +#include "sys/platform.h" +#include "idlib/containers/StrList.h" +#include "framework/Licensee.h" +#include "sys/sys_local.h" + +#define ID_FTXT MAKE_ID('F','T','X','T') +#define ID_CHRS MAKE_ID('C','H','R','S') + +extern idCVar com_pid; + +struct Library *MiamiBase; +struct Library *OpenURLBase; + +char chunk_buffer[1024]; + +idStr adoom3_basepath; +idStr adoom3_savepath; + +/* +================ +Sys_GetSystemRam +returns in megabytes rounded to the nearest 16Mb +================ +*/ +int Sys_GetSystemRam( void ) { + int mb; + + bug("[ADoom3] %s()\n", __PRETTY_FUNCTION__); + + mb = ( ( AvailMem( MEMF_ANY ) / ( 1024 * 1024 ) ) + 8 ) & ~15; + + return mb; +} + +/* +================ +Sys_LockMemory +================ +*/ +bool Sys_LockMemory( void *ptr, int bytes ) { + D(bug("[ADoom3] Sys_LockMemory( 0x%p, %u )\n", ptr, bytes)); + return true; +} + +/* +================ +Sys_UnlockMemory +================ +*/ +bool Sys_UnlockMemory( void *ptr, int bytes ) { + D(bug("[ADoom3] Sys_UnlockMemory( 0x%p, %u )\n", ptr, bytes)); + return true; +} + +/* +================ +Sys_ListFiles +================ +*/ +int Sys_ListFiles( const char *directory, const char *extension, idStrList &list ) { + BPTR dirlock; + struct FileInfoBlock *fib; + char search[1024]; + + bool dironly = false; + + bug("[ADoom3] %s()\n", __PRETTY_FUNCTION__); + + list.Clear(); + + if (!extension) + extension = ""; + + // passing a slash as extension will find directories + if (extension[0] == '/' && extension[1] == 0) { + extension = ""; + dironly = true; + } + + // search + // NOTE: case sensitivity of directory path can screw us up here + if ((dirlock = Lock(directory, SHARED_LOCK)) == BNULL) { + D(bug("[ADoom3] Sys_ListFiles: opendir '%s' failed\n", directory)); + return -1; + } + + if ((fib = (struct FileInfoBlock *)AllocDosObject(DOS_FIB, NULL)) != (struct FileInfoBlock *)NULL) + { + if (Examine(dirlock, fib)) + { + while(ExNext(dirlock, fib)) + { + idStr filename((const char *)fib->fib_FileName); + + idStr::snPrintf(search, sizeof(search), "%s/%s", directory, fib->fib_FileName); + if (!dironly) { + idStr look(search); + idStr ext; + look.ExtractFileExtension(ext); + if (extension[0] != '\0' && ext.Icmp(&extension[1]) != 0) { + continue; + } + } + if ((dironly && (fib->fib_DirEntryType != ST_USERDIR)) || + (!dironly && (fib->fib_DirEntryType == ST_USERDIR))) + continue; + D(bug("[ADoom3] Sys_ListFiles:\tadding %s to list\n", filename.c_str())); + list.Append(filename); + } + } + FreeDosObject(DOS_FIB, fib); + } + + UnLock(dirlock); + + D(bug( "[ADoom3] Sys_ListFiles: %d entries in %s\n", list.Num(), directory )); + + return list.Num(); +} + +/* +================ +Sys_Mkdir +================ +*/ +void Sys_Mkdir( const char *path ) { + BPTR dirlock; + + D(bug("[ADoom3] Sys_Mkdir('%s')\n", path)); + + if ((dirlock = CreateDir(path)) != BNULL) + { + D(bug("[ADoom3] Sys_Mkdir: created\n")); + UnLock(dirlock); + } +} + +char *Sys_GetClipboardData(void) { + struct IFFHandle *IFFHandle; + struct ContextNode *cn; + ULONG error, read = 0; + + D(bug("[ADoom3] Sys_GetClipboardData()\n")); + + if ((IFFHandle = AllocIFF())) + { + if ((IFFHandle->iff_Stream = (IPTR)OpenClipboard(0))) + { + InitIFFasClip(IFFHandle); + + if (!OpenIFF(IFFHandle, IFFF_READ)) + { + if (!StopChunk(IFFHandle, ID_FTXT, ID_CHRS)) + { + if (!(error = ParseIFF(IFFHandle, IFFPARSE_SCAN))) + { + cn = CurrentChunk(IFFHandle); + + if (cn && (cn->cn_Type == ID_FTXT) && (cn->cn_ID == ID_CHRS)) + { + read = ReadChunkBytes(IFFHandle, chunk_buffer, 1024); + } + } + } + CloseIFF(IFFHandle); + } + CloseClipboard((struct ClipboardHandle *)IFFHandle->iff_Stream); + } + FreeIFF(IFFHandle); + } + + + if (read > 0) + { + return chunk_buffer; + } + + return NULL; +} + +void Sys_SetClipboardData( const char *string ) { + struct IFFHandle *IFFHandle; + BOOL written = FALSE; + + D(bug("[ADoom3] Sys_SetClipboardData('%s')\n", string)); + + if ((string) && (strlen(string) > 0)) + { + if((IFFHandle = AllocIFF())) + { + if((IFFHandle->iff_Stream = (IPTR)OpenClipboard(0))) + { + InitIFFasClip(IFFHandle); + + if(!OpenIFF(IFFHandle, IFFF_WRITE)) + { + if(!PushChunk(IFFHandle, ID_FTXT, ID_FORM, IFFSIZE_UNKNOWN)) + { + if(!PushChunk(IFFHandle, 0, ID_CHRS, IFFSIZE_UNKNOWN)) + { + if(WriteChunkBytes(IFFHandle, (char *)string, strlen(string)) == strlen(string)) + { + if(!PopChunk(IFFHandle)) + written = TRUE; + } + } + if(written) + PopChunk(IFFHandle); + } + CloseIFF(IFFHandle); + } + CloseClipboard((struct ClipboardHandle *)IFFHandle->iff_Stream); + } + FreeIFF(IFFHandle); + } + } +} + +/* +=========== +Sys_GetDriveFreeSpace +return in MegaBytes +=========== +*/ +int Sys_GetDriveFreeSpace( const char *path ) { + D(bug("[ADoom3] Sys_GetDriveFreeSpace('%s')\n", path)); + + D(bug("[ADoom3] ** TODO: Sys_GetDriveFreeSpace\n")); + + return 1000 * 1024; +} + +/* +=============== +AROS_InitLibs +=============== +*/ +void AROS_InitLibs( void ) { + bug("[ADoom3] %s()\n", __PRETTY_FUNCTION__); + + MiamiBase = OpenLibrary("miami.library", 0); + OpenURLBase = OpenLibrary("openurl.library", 0); +} + +#if (0) +/* +============== +Sys_EXEPath +============== +*/ +const char *Sys_EXEPath( void ) { + static char buf[ 1024 ]; + BPTR pathlock; + + D(bug("[ADoom3] Sys_EXEPath()\n")); + + if ((pathlock = Lock("PROGDIR:", SHARED_LOCK)) != BNULL) + { + if ( NameFromLock( pathlock, buf, sizeof( buf ) ) ) + { + UnLock(pathlock); + struct Node *thisTask = (struct Node *)FindTask(NULL); + + AddPart(buf, thisTask->ln_Name, 1024); + + D(bug("[ADoom3] Sys_EXEPath: using '%s'\n", buf)); + return buf; + } + UnLock(pathlock); + } + D(bug("[ADoom3] Sys_EXEPath: faling back to PROGDIR\n")); + + return "PROGDIR:ADoom3"; +} + + +/* +================ +AROS_Cwd +================ +*/ +const char *AROS_Cwd( void ) { + static char buf[ 1024 ]; + struct Process *thisTask = (struct Process *)FindTask(NULL); + D(bug("[ADoom3] AROS_Cwd()\n")); + + if (thisTask->pr_CurrentDir != BNULL) + { + if ( NameFromLock( thisTask->pr_CurrentDir, buf, sizeof( buf ) ) ) + { + D(bug("[ADoom3] AROS_Cwd: '%s'\n", buf)); + return buf; + } + } + return "PROGDIR:"; +} + +/* +================ +Sys_DefaultBasePath + +Get the default base path +- binary image path +- current directory +- hardcoded +Try to be intelligent: if there is no BASE_GAMEDIR, try the next path +================ +*/ +const char *Sys_DefaultBasePath(void) { + struct FileInfoBlock *fib; + BPTR pathLock = BNULL; + idStr testbase; + + D(bug("[ADoom3] Sys_DefaultBasePath()\n")); + + adoom3_basepath = Sys_EXEPath(); + if ( adoom3_basepath.Length() ) { + adoom3_basepath.StripFilename(); + testbase = adoom3_basepath; testbase += "/"; testbase += BASE_GAMEDIR; + if ((fib = (struct FileInfoBlock *)AllocDosObject(DOS_FIB, NULL)) != (struct FileInfoBlock *)NULL) + { + if ((pathLock = Lock(testbase.c_str(), SHARED_LOCK)) != BNULL) + { + if (Examine(pathLock, fib)) + { + if (fib->fib_DirEntryType == ST_USERDIR) + { + UnLock(pathLock); + FreeDosObject(DOS_FIB, fib); + return adoom3_basepath.c_str(); + } + } + UnLock(pathLock); + } + FreeDosObject(DOS_FIB, fib); + } + D(bug( "[ADoom3] Sys_DefaultBasePath: no '%s' directory in exe path %s, skipping\n", BASE_GAMEDIR, adoom3_basepath.c_str() )); + } + if ( adoom3_basepath != AROS_Cwd() ) { + adoom3_basepath = AROS_Cwd(); + testbase = adoom3_basepath; testbase += "/"; testbase += BASE_GAMEDIR; + if ((fib = (struct FileInfoBlock *)AllocDosObject(DOS_FIB, NULL)) != (struct FileInfoBlock *)NULL) + { + if ((pathLock = Lock(testbase.c_str(), SHARED_LOCK)) != BNULL) + { + if (Examine(pathLock, fib)) + { + if (fib->fib_DirEntryType == ST_USERDIR) + { + UnLock(pathLock); + FreeDosObject(DOS_FIB, fib); + return adoom3_basepath.c_str(); + } + } + UnLock(pathLock); + } + FreeDosObject(DOS_FIB, fib); + } + D(bug( "[ADoom3] Sys_DefaultBasePath: no '%s' directory in cwd path %s, skipping\n", BASE_GAMEDIR, adoom3_basepath.c_str())); + } + return "PROGDIR:"; +} + +/* + ============== + Sys_DefaultSavePath + ============== + */ +const char *Sys_DefaultSavePath(void) { + static char buf[ 1024 ]; + BPTR pathlock; + + D(bug("[ADoom3] Sys_DefaultSavePath()\n")); + + if ((pathlock = Lock("ENVARC:", SHARED_LOCK)) != BNULL) + { + if ( NameFromLock( pathlock, buf, sizeof( buf ) ) ) + { + UnLock(pathlock); + +#if defined( ID_DEMO_BUILD ) + AddPart(buf, ".doom3-demo", sizeof( buf )); +#else + AddPart(buf, ".doom3", sizeof( buf )); +#endif + D(bug("[ADoom3] Sys_DefaultSavePath: using '%s'\n", buf)); + return buf; + } + UnLock(pathlock); + } + + D(bug("[ADoom3] Sys_DefaultSavePath: faling back to DefaultBasePath\n")); + + sprintf(buf, "%s/.doom3", Sys_DefaultBasePath()); + return buf; +} +#endif + +/* +================= +Sys_OpenURL +================= +*/ +void AROS_OpenURL( const char *url ) { + struct TagItem tags[2]; + + tags[0].ti_Tag = TAG_DONE; tags[0].ti_Data = 0; + + D(bug("[ADoom3] OpenURL( '%s' )\n", url)); + + URL_OpenA( (char *)url, tags ); +} + + +bool Sys_GetPath(sysPath_t type, idStr &path) { + char buf[1024]; + BPTR pathlock; + + D(bug("[ADoom3] Sys_GetPath(%d)\n", type)); + + path.Clear(); + + switch(type) { + case PATH_BASE: + case PATH_CONFIG: + case PATH_SAVE: + if ((pathlock = Lock("PROGDIR:", SHARED_LOCK)) != BNULL) + { + if ( NameFromLock( pathlock, buf, sizeof( buf ) ) ) + { + D(bug("[ADoom3] Sys_GetPath: using '%s'\n", buf)); + path = buf; + } + UnLock(pathlock); + } + return true; + + case PATH_EXE: + if ((pathlock = Lock("PROGDIR:", SHARED_LOCK)) != BNULL) + { + if ( NameFromLock( pathlock, buf, sizeof( buf ) ) ) + { + struct Node *thisTask = (struct Node *)FindTask(NULL); + + AddPart(buf, thisTask->ln_Name, 1024); + + D(bug("[ADoom3] Sys_GetPath: using '%s'\n", buf)); + path = buf; + } + UnLock(pathlock); + } + return true; + } + + return false; +} diff --git a/neo/sys/aros/aros_local.h b/neo/sys/aros/aros_local.h new file mode 100644 index 00000000..753ccb2c --- /dev/null +++ b/neo/sys/aros/aros_local.h @@ -0,0 +1,43 @@ +/* +=========================================================================== + +Doom 3 GPL Source Code +Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company. + +This file is part of the Doom 3 GPL Source Code ("Doom 3 Source Code"). + +Doom 3 Source Code is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +Doom 3 Source Code is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>. + +In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below. + +If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA. + +=========================================================================== +*/ +#ifndef __AROS_LOCAL_H__ +#define __AROS_LOCAL_H__ + +#include "renderer/RenderSystem.h" +#include "renderer/tr_local.h" + +// input.cpp +void Sys_XEvents(); +void Sys_XUninstallGrabs(); + + +#define KEY_MASK (1 << 0) +#define MOUSE_MASK (1 << 1) +#define X_MASK (KEY_MASK | MOUSE_MASK | 1 << 2) + +#endif diff --git a/neo/sys/aros/aros_main.cpp b/neo/sys/aros/aros_main.cpp new file mode 100644 index 00000000..cdaa872a --- /dev/null +++ b/neo/sys/aros/aros_main.cpp @@ -0,0 +1,897 @@ +/* +=========================================================================== + +Doom 3 GPL Source Code +Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company. + +This file is part of the Doom 3 GPL Source Code ("Doom 3 Source Code"). + +Doom 3 Source Code is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +Doom 3 Source Code is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>. + +In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below. + +If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA. + +=========================================================================== +*/ + +#define DEBUG 1 + +#include <aros/debug.h> +#undef ASSERT + +#include <proto/exec.h> +#include <proto/dos.h> + +// undefine - conflict with ID functions +#undef Remove +#undef Insert +#undef Read +#undef Write +#undef Seek +#undef Flush +#undef Close +#undef Allocate +#undef Printf +#undef VPrintf + +#include <sys/types.h> +#include <sys/stat.h> +#include <errno.h> +#include <dirent.h> +#include <unistd.h> +#include <sys/time.h> +#include <pwd.h> +#include <termios.h> +#include <signal.h> +#include <fcntl.h> + +#include <SDL_main.h> + +#include "dll/dll.h" + +#include "sys/platform.h" +#include "idlib/containers/StrList.h" +#include "framework/FileSystem.h" +#include "framework/KeyInput.h" +#include "framework/EditField.h" +#include "sys/sys_local.h" + +#include "sys/aros/aros_public.h" + +#define COMMAND_HISTORY 64 + +extern idStr adoom3_basepath; +extern idStr adoom3_savepath; + +static int input_hide = 0; + +idEditField input_field; +static char input_ret[256]; + +static idStr history[ COMMAND_HISTORY ]; // cycle buffer +static int history_count = 0; // buffer fill up +static int history_start = 0; // current history start +static int history_current = 0; // goes back in history +idEditField history_backup; // the base edit line + +// terminal support +idCVar in_tty( "in_tty", "1", CVAR_BOOL | CVAR_INIT | CVAR_SYSTEM, "terminal tab-completion and history" ); + +static bool tty_enabled = false; +static struct termios tty_tc; + +// pid - useful when you attach to gdb.. +idCVar com_pid( "com_pid", "0", CVAR_INTEGER | CVAR_INIT | CVAR_SYSTEM, "process id" ); + +// exit - quit - error -------------------------------------------------------- + +static int set_exit = 0; +static char exit_spawn[ 1024 ]; + +/* +================ +AROS_Exit +================ +*/ +void AROS_Exit(int ret) { + bug("[ADoom3] %s()\n", __PRETTY_FUNCTION__); + + if ( tty_enabled ) { + Sys_Printf( "shutdown terminal support\n" ); +#if (0) + if ( tcsetattr( 0, TCSADRAIN, &tty_tc ) == -1 ) { + Sys_Printf( "tcsetattr failed: %s\n", strerror( errno ) ); + } +#endif + } + // at this point, too late to catch signals + AROS_ClearSigs(); + + // process spawning. it's best when it happens after everything has shut down + if ( exit_spawn[0] ) { + Sys_DoStartProcess( exit_spawn, false ); + } + // in case of signal, handler tries a common->Quit + // we use set_exit to maintain a correct exit code + if ( set_exit ) { + exit( set_exit ); + } + exit( ret ); +} + +/* +================ +AROS_SetExit +================ +*/ +void AROS_SetExit(int ret) { + bug("[ADoom3] %s()\n", __PRETTY_FUNCTION__); + + set_exit = 0; +} + +/* +=============== +AROS_SetExitSpawn +set the process to be spawned when we quit +=============== +*/ +void AROS_SetExitSpawn( const char *exeName ) { + bug("[ADoom3] %s()\n", __PRETTY_FUNCTION__); + + idStr::Copynz( exit_spawn, exeName, 1024 ); +} + +/* +================== +idSysLocal::StartProcess +if !quit, start the process asap +otherwise, push it for execution at exit +(i.e. let complete shutdown of the game and freeing of resources happen) +NOTE: might even want to add a small delay? +================== +*/ +void idSysLocal::StartProcess( const char *exeName, bool quit ) { + bug("[ADoom3] %s()\n", __PRETTY_FUNCTION__); + + if ( quit ) { + common->DPrintf( "Sys_StartProcess %s (delaying until final exit)\n", exeName ); + AROS_SetExitSpawn( exeName ); + cmdSystem->BufferCommandText( CMD_EXEC_APPEND, "quit\n" ); + return; + } + + common->DPrintf( "Sys_StartProcess %s\n", exeName ); + Sys_DoStartProcess( exeName ); +} + +/* +================ +Sys_Quit +================ +*/ +void Sys_Quit(void) { + bug("[ADoom3] %s()\n", __PRETTY_FUNCTION__); + + AROS_Exit( EXIT_SUCCESS ); +} + +/* +================= +Sys_Init +================= +*/ +void Sys_Init( void ) { + bug("[ADoom3] %s()\n", __PRETTY_FUNCTION__); + + AROS_InitConsoleInput(); + com_pid.SetString( (char *)FindTask(NULL) ); + common->Printf( "pid: %p\n", com_pid.GetString() ); + common->Printf( "%d MB System Memory\n", Sys_GetSystemRam() ); +#if (0) +#ifndef ID_DEDICATED + common->Printf( "%d MB Video Memory\n", Sys_GetVideoRam() ); +#endif +#endif +} + +/* +================= +AROS_Shutdown +================= +*/ +void AROS_Shutdown( void ) { + bug("[ADoom3] %s()\n", __PRETTY_FUNCTION__); + + for ( int i = 0; i < COMMAND_HISTORY; i++ ) { + history[ i ].Clear(); + } +} + +/* +================= +Sys_DLL_Load +================= +*/ +uintptr_t Sys_DLL_Load( const char *path ) { + bug("[ADoom3] %s()\n", __PRETTY_FUNCTION__); + + void *handle = dllLoadLibrary( (char *)path, FilePart(path) ); + if ( !handle ) { + Sys_Printf( "dllLoadLibrary '%s' failed\n", path ); + } + return (uintptr_t)handle; +} + +/* +================= +Sys_DLL_GetProcAddress +================= +*/ +void* Sys_DLL_GetProcAddress( uintptr_t handle, const char *sym ) { + bug("[ADoom3] %s()\n", __PRETTY_FUNCTION__); + + //const char *error; + void *ret = dllGetProcAddress( (void *)handle, (char *)sym); + if (ret == NULL) { + Sys_Printf( "dllGetProcAddress '%s' failed\n", sym ); + } + return ret; +} + +/* +================= +Sys_DLL_Unload +================= +*/ +void Sys_DLL_Unload( uintptr_t handle ) { + bug("[ADoom3] %s()\n", __PRETTY_FUNCTION__); + + dllFreeLibrary( (void *)handle); +} + +/* +================ +Sys_ShowConsole +================ +*/ +void Sys_ShowConsole( int visLevel, bool quitOnClose ) { + bug("[ADoom3] %s()\n", __PRETTY_FUNCTION__); +} + +// --------------------------------------------------------------------------- + +ID_TIME_T Sys_FileTimeStamp(FILE * fp) { + bug("[ADoom3] %s()\n", __PRETTY_FUNCTION__); + + struct stat st; + fstat(fileno(fp), &st); + return st.st_mtime; +} + +bool Sys_FPU_StackIsEmpty( void ) { + bug("[ADoom3] %s()\n", __PRETTY_FUNCTION__); + + return true; +} + +const char *Sys_FPU_GetState( void ) { + bug("[ADoom3] %s()\n", __PRETTY_FUNCTION__); + + return ""; +} + +void Sys_FPU_SetPrecision( int precision ) { + bug("[ADoom3] %s()\n", __PRETTY_FUNCTION__); + +} + +/* +================ +Sys_SetPhysicalWorkMemory +================ +*/ +void Sys_SetPhysicalWorkMemory( int minBytes, int maxBytes ) { + bug("[ADoom3] %s()\n", __PRETTY_FUNCTION__); + + common->DPrintf( "TODO: Sys_SetPhysicalWorkMemory\n" ); +} + +/* +=============== +AROS_EarlyInit +=============== +*/ +void AROS_EarlyInit( void ) { + bug("[ADoom3] %s()\n", __PRETTY_FUNCTION__); + + exit_spawn[0] = '\0'; + AROS_InitLibs(); + AROS_InitSigs(); +} + +/* +=============== +AROS_InitConsoleInput +=============== +*/ +void AROS_InitConsoleInput( void ) { + struct termios tc; + + bug("[ADoom3] %s()\n", __PRETTY_FUNCTION__); + + + if ( in_tty.GetBool() ) { + if ( isatty( STDIN_FILENO ) != 1 ) { + Sys_Printf( "terminal support disabled: stdin is not a tty\n" ); + in_tty.SetBool( false ); + return; + } +#if !defined(__AROS__) + if ( tcgetattr( 0, &tty_tc ) == -1 ) { + Sys_Printf( "tcgetattr failed. disabling terminal support: %s\n", strerror( errno ) ); + in_tty.SetBool( false ); + return; + } + // make the input non blocking + if ( fcntl( STDIN_FILENO, F_SETFL, fcntl( STDIN_FILENO, F_GETFL, 0 ) | O_NONBLOCK ) == -1 ) { + Sys_Printf( "fcntl STDIN non blocking failed. disabling terminal support: %s\n", strerror( errno ) ); + in_tty.SetBool( false ); + return; + } +#endif + tc = tty_tc; + /* + ECHO: don't echo input characters + ICANON: enable canonical mode. This enables the special + characters EOF, EOL, EOL2, ERASE, KILL, REPRINT, + STATUS, and WERASE, and buffers by lines. + ISIG: when any of the characters INTR, QUIT, SUSP, or + DSUSP are received, generate the corresponding signal + */ + tc.c_lflag &= ~(ECHO | ICANON); + /* + ISTRIP strip off bit 8 + INPCK enable input parity checking + */ + tc.c_iflag &= ~(ISTRIP | INPCK); + tc.c_cc[VMIN] = 1; + tc.c_cc[VTIME] = 0; + +#if !defined(__AROS__) + if ( tcsetattr( 0, TCSADRAIN, &tc ) == -1 ) { + Sys_Printf( "tcsetattr failed: %s\n", strerror( errno ) ); + Sys_Printf( "terminal support may not work correctly. Use +set in_tty 0 to disable it\n" ); + } + // make the output non blocking + if ( fcntl( STDOUT_FILENO, F_SETFL, fcntl( STDOUT_FILENO, F_GETFL, 0 ) | O_NONBLOCK ) == -1 ) { + Sys_Printf( "fcntl STDOUT non blocking failed: %s\n", strerror( errno ) ); + } +#endif + tty_enabled = true; + // check the terminal type for the supported ones + char *term = getenv( "TERM" ); + if ( term ) { + if ( strcmp( term, "linux" ) && strcmp( term, "xterm" ) && strcmp( term, "xterm-color" ) && strcmp( term, "screen" ) ) { + Sys_Printf( "WARNING: terminal type '%s' is unknown. terminal support may not work correctly\n", term ); + } + } + Sys_Printf( "terminal support enabled ( use +set in_tty 0 to disabled )\n" ); + } else { + Sys_Printf( "terminal support disabled\n" ); + } +} + +/* +================ +terminal support utilities +================ +*/ + +void tty_Del() { + putchar('\b'); + putchar(' '); + putchar('\b'); +} + +void tty_Left() { + putchar('\b'); +} + +void tty_Right() { + putchar(27); + putchar('['); + putchar('C'); +} + +// clear the display of the line currently edited +// bring cursor back to beginning of line +void tty_Hide() { + int len, buf_len; + + if ( !tty_enabled ) { + return; + } + if ( input_hide ) { + input_hide++; + return; + } + // clear after cursor + len = strlen( input_field.GetBuffer() ) - input_field.GetCursor(); + while ( len > 0 ) { + tty_Right(); + len--; + } + buf_len = strlen( input_field.GetBuffer() ); + while ( buf_len > 0 ) { + tty_Del(); + buf_len--; + } + input_hide++; +} + +// show the current line +void tty_Show() { + // int i; + if ( !tty_enabled ) { + return; + } + assert( input_hide > 0 ); + input_hide--; + if ( input_hide == 0 ) { + char *buf = input_field.GetBuffer(); + size_t len = strlen(buf); + if ( len < 1 ) + return; + + len = write( STDOUT_FILENO, buf, len ); + if ( len < 1 ) + return; + + len -= input_field.GetCursor(); + while ( len > 0 ) { + tty_Left(); + len--; + } + } +} + +void tty_FlushIn() { + char key; + while ( ( key = getchar() ) != EOF ) { + Sys_Printf( "'%d' ", key ); + } + Sys_Printf( "\n" ); +} + +/* +================ +Sys_ConsoleInput +Checks for a complete line of text typed in at the console. +Return NULL if a complete line is not ready. +================ +*/ +char *Sys_ConsoleInput( void ) { + /* + if ( tty_enabled ) { + char key; + bool hidden = false; + while ( ( key = getchar() ) != EOF ) { + if ( !hidden ) { + tty_Hide(); + hidden = true; + } + switch ( key ) { + case 1: + input_field.SetCursor( 0 ); + break; + case 5: + input_field.SetCursor( strlen( input_field.GetBuffer() ) ); + break; + case 127: + case 8: + input_field.CharEvent( K_BACKSPACE ); + break; + case '\n': + idStr::Copynz( input_ret, input_field.GetBuffer(), sizeof( input_ret ) ); + assert( hidden ); + tty_Show(); + putchar(key); + input_field.Clear(); + if ( history_count < CMD_HIST ) { + history[ history_count ] = input_ret; + history_count++; + } else { + history[ history_start ] = input_ret; + history_start++; + history_start %= CMD_HIST; + } + history_current = 0; + return input_ret; + case '\t': + input_field.AutoComplete(); + break; + case 27: { + // enter escape sequence mode + if ( ( key = getchar() ) == EOF ) { + Sys_Printf( "dropping sequence: '27' " ); + tty_FlushIn(); + assert( hidden ); + tty_Show(); + return NULL; + } + switch ( key ) { + case 79: + if ( ( key = getchar() ) == EOF ) { + Sys_Printf( "dropping sequence: '27' '79' " ); + tty_FlushIn(); + assert( hidden ); + tty_Show(); + return NULL; + } + switch ( key ) { + case 72: + // xterm only + input_field.SetCursor( 0 ); + break; + case 70: + // xterm only + input_field.SetCursor( strlen( input_field.GetBuffer() ) ); + break; + default: + Sys_Printf( "dropping sequence: '27' '79' '%d' ", key ); + tty_FlushIn(); + assert( hidden ); + tty_Show(); + return NULL; + } + break; + case 91: { + if ( ( key = getchar() ) == EOF ) { + Sys_Printf( "dropping sequence: '27' '91' " ); + tty_FlushIn(); + assert( hidden ); + tty_Show(); + return NULL; + } + switch ( key ) { + case 49: { + if ( ( key = getchar() ) == EOF || key != 126 ) { + Sys_Printf( "dropping sequence: '27' '91' '49' '%d' ", key ); + tty_FlushIn(); + assert( hidden ); + tty_Show(); + return NULL; + } + // only screen and linux terms + input_field.SetCursor( 0 ); + break; + } + case 50: { + if ( ( key = getchar() ) == EOF || key != 126 ) { + Sys_Printf( "dropping sequence: '27' '91' '50' '%d' ", key ); + tty_FlushIn(); + assert( hidden ); + tty_Show(); + return NULL; + } + // all terms + input_field.KeyDownEvent( K_INS ); + break; + } + case 52: { + if ( ( key = getchar() ) == EOF || key != 126 ) { + Sys_Printf( "dropping sequence: '27' '91' '52' '%d' ", key ); + tty_FlushIn(); + assert( hidden ); + tty_Show(); + return NULL; + } + // only screen and linux terms + input_field.SetCursor( strlen( input_field.GetBuffer() ) ); + break; + } + case 51: { + if ( ( key = getchar() ) == EOF ) { + Sys_Printf( "dropping sequence: '27' '91' '51' " ); + tty_FlushIn(); + assert( hidden ); + tty_Show(); + return NULL; + } + if ( key == 126 ) { + input_field.KeyDownEvent( K_DEL ); + break; + } + Sys_Printf( "dropping sequence: '27' '91' '51' '%d'", key ); + tty_FlushIn(); + assert( hidden ); + tty_Show(); + return NULL; + } + case 65: + case 66: { + // history + if ( history_current == 0 ) { + history_backup = input_field; + } + if ( key == 65 ) { + // up + history_current++; + } else { + // down + history_current--; + } + // history_current cycle: + // 0: current edit + // 1 .. Min( CMD_HIST, history_count ): back in history + if ( history_current < 0 ) { + history_current = Min( CMD_HIST, history_count ); + } else { + history_current %= Min( CMD_HIST, history_count ) + 1; + } + int index = -1; + if ( history_current == 0 ) { + input_field = history_backup; + } else { + index = history_start + Min( CMD_HIST, history_count ) - history_current; + index %= CMD_HIST; + assert( index >= 0 && index < CMD_HIST ); + input_field.SetBuffer( history[ index ] ); + } + assert( hidden ); + tty_Show(); + return NULL; + } + case 67: + input_field.KeyDownEvent( K_RIGHTARROW ); + break; + case 68: + input_field.KeyDownEvent( K_LEFTARROW ); + break; + default: + Sys_Printf( "dropping sequence: '27' '91' '%d' ", key ); + tty_FlushIn(); + assert( hidden ); + tty_Show(); + return NULL; + } + break; + } + default: + Sys_Printf( "dropping sequence: '27' '%d' ", key ); + tty_FlushIn(); + assert( hidden ); + tty_Show(); + return NULL; + } + break; + } + default: + if ( key >= ' ' ) { + input_field.CharEvent( key ); + break; + } + Sys_Printf( "dropping sequence: '%d' ", key ); + tty_FlushIn(); + assert( hidden ); + tty_Show(); + return NULL; + } + } + if ( hidden ) { + tty_Show(); + } + return NULL; + } else { + // no terminal support - read only complete lines + int len; + fd_set fdset; + struct timeval timeout; + + FD_ZERO( &fdset ); + FD_SET( STDIN_FILENO, &fdset ); + timeout.tv_sec = 0; + timeout.tv_usec = 0; + if ( select( 1, &fdset, NULL, NULL, &timeout ) == -1 || !FD_ISSET( 0, &fdset ) ) { + return NULL; + } + + len = read( 0, input_ret, sizeof( input_ret ) ); + if ( len == 0 ) { + // EOF + return NULL; + } + + if ( len < 1 ) { + Sys_Printf( "read failed: %s\n", strerror( errno ) ); // something bad happened, cancel this line and print an error + return NULL; + } + + if ( len == sizeof( input_ret ) ) { + Sys_Printf( "read overflow\n" ); // things are likely to break, as input will be cut into pieces + } + + input_ret[ len-1 ] = '\0'; // rip off the \n and terminate + return input_ret; + }*/ + return NULL; +} + +/* +=============== +low level output +=============== +*/ + +void Sys_DebugPrintf( const char *fmt, ... ) { + va_list argptr; + + tty_Hide(); + va_start( argptr, fmt ); + vprintf( fmt, argptr ); + va_end( argptr ); + tty_Show(); +} + +void Sys_DebugVPrintf( const char *fmt, va_list arg ) { + tty_Hide(); + vprintf( fmt, arg ); + tty_Show(); +} + +void Sys_Printf(const char *msg, ...) { + va_list argptr; + + tty_Hide(); + va_start( argptr, msg ); + vprintf( msg, argptr ); + va_end( argptr ); + tty_Show(); +} + +void Sys_VPrintf(const char *msg, va_list arg) { + tty_Hide(); + vprintf(msg, arg); + tty_Show(); +} + +/* +================ +Sys_Error +================ +*/ +void Sys_Error(const char *error, ...) { + va_list argptr; + + Sys_Printf( "Sys_Error: " ); + va_start( argptr, error ); + Sys_DebugVPrintf( error, argptr ); + va_end( argptr ); + Sys_Printf( "\n" ); + + AROS_Exit( EXIT_FAILURE ); +} + +/* +=============== +Sys_Shutdown +=============== +*/ +void Sys_Shutdown( void ) { + bug("[ADoom3] %s()\n", __PRETTY_FUNCTION__); + + adoom3_basepath.Clear(); + adoom3_savepath.Clear(); + AROS_Shutdown(); +} + +/* +=============== +Sys_FPU_EnableExceptions +=============== +*/ +void Sys_FPU_EnableExceptions( int exceptions ) { + bug("[ADoom3] %s()\n", __PRETTY_FUNCTION__); +} + +/* +=============== +Sys_FPE_handler +=============== +*/ +void Sys_FPE_handler( int signum, siginfo_t *info, void *context ) { + bug("[ADoom3] %s()\n", __PRETTY_FUNCTION__); + + assert( signum == SIGFPE ); + Sys_Printf( "FPE\n" ); +} + +/* +================== +Sys_DoStartProcess +if we don't fork, this function never returns +the no-fork lets you keep the terminal when you're about to spawn an installer + +if the command contains spaces, system() is used. Otherwise the more straightforward execl ( system() blows though ) +================== +*/ +void Sys_DoStartProcess( const char *exeName, bool dofork ) { + bool use_system = false; + + bug("[ADoom3] %s()\n", __PRETTY_FUNCTION__); + + if ( strchr( exeName, ' ' ) ) { + use_system = true; + } else { + // set exec rights when it's about a single file to execute + struct stat buf; + if ( stat( exeName, &buf ) == -1 ) { + printf( "stat %s failed: %s\n", exeName, strerror( errno ) ); + } else { + if ( chmod( exeName, buf.st_mode | S_IXUSR ) == -1 ) { + printf( "cmod +x %s failed: %s\n", exeName, strerror( errno ) ); + } + } + } + if ( use_system ) { + printf( "system %s\n", exeName ); + if (system( exeName ) == -1) + printf( "system failed: %s\n", strerror( errno ) ); + else + sleep( 1 ); // on some systems I've seen that starting the new process and exiting this one should not be too close + } else { + printf( "execl %s\n", exeName ); + execl( exeName, exeName, 0 ); + printf( "execl failed: %s\n", strerror( errno ) ); + } + // terminate + _exit( 0 ); +} + +/* +================= +Sys_OpenURL +================= +*/ +void idSysLocal::OpenURL( const char *url, bool quit ) { + bug("[ADoom3] %s()\n", __PRETTY_FUNCTION__); + + AROS_OpenURL( url ); +} + +/* +=============== +main +=============== +*/ +int main(int argc, char **argv) { + bug("[ADoom3] %s()\n", __PRETTY_FUNCTION__); + + AROS_EarlyInit( ); + + if ( argc > 1 ) { + common->Init( argc-1, &argv[1] ); + } else { + common->Init( 0, NULL ); + } + + Sys_Init( ); + + while (1) { + common->Frame(); + } + return 0; +} diff --git a/neo/sys/aros/aros_net.cpp b/neo/sys/aros/aros_net.cpp new file mode 100644 index 00000000..e61bc0a0 --- /dev/null +++ b/neo/sys/aros/aros_net.cpp @@ -0,0 +1,759 @@ +/* +=========================================================================== + +Doom 3 GPL Source Code +Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company. + +This file is part of the Doom 3 GPL Source Code ("Doom 3 Source Code"). + +Doom 3 Source Code is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +Doom 3 Source Code is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>. + +In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below. + +If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA. + +=========================================================================== +*/ + + +#include <proto/socket.h> +#include <proto/miami.h> +#include <bsdsocket/socketbasetags.h> +#ifndef INADDR_LOOPBACK +# define INADDR_LOOPBACK ((unsigned long int) 0x7f000001) +#endif /* INADDR_LOOPBACK */ + +#include <signal.h> +#include <unistd.h> +#include <fcntl.h> +#include <sys/socket.h> +#include <sys/time.h> +#include <netinet/in.h> +#include <netinet/tcp.h> +#include <arpa/inet.h> +#include <netdb.h> +#include <sys/param.h> +#include <sys/ioctl.h> +#include <sys/uio.h> +#include <errno.h> +#include <net/if.h> + + +#include "sys/platform.h" +#include "framework/Common.h" +#include "framework/CVarSystem.h" +#include "sys/sys_public.h" + +#include "sys/aros/aros_public.h" + +idPort clientPort, serverPort; + +idCVar net_ip( "net_ip", "localhost", CVAR_SYSTEM, "local IP address" ); +idCVar net_port( "net_port", "", CVAR_SYSTEM | CVAR_INTEGER, "local IP port number" ); + +typedef struct { + unsigned int ip; + unsigned int mask; +} net_interface; + +#define MAX_INTERFACES 32 +int num_interfaces = 0; +net_interface netint[MAX_INTERFACES]; + +/* +============= +NetadrToSockadr +============= +*/ +static void NetadrToSockadr( const netadr_t * a, struct sockaddr_in *s ) { + memset(s, 0, sizeof(*s)); + + if ( a->type == NA_BROADCAST ) { + s->sin_family = AF_INET; + + s->sin_port = htons( (short)a->port ); + *(int *) &s->sin_addr = -1; + } else if ( a->type == NA_IP || a->type == NA_LOOPBACK ) { + s->sin_family = AF_INET; + + *(int *) &s->sin_addr = *(int *) &a->ip; + s->sin_port = htons( (short)a->port ); + } +} + +/* +============= +SockadrToNetadr +============= +*/ +static void SockadrToNetadr(struct sockaddr_in *s, netadr_t * a) { + unsigned int ip = *(int *)&s->sin_addr; + *(int *)&a->ip = ip; + a->port = ntohs( s->sin_port ); + // we store in network order, that loopback test is host order.. + ip = ntohl( ip ); + if ( ip == INADDR_LOOPBACK ) { + a->type = NA_LOOPBACK; + } else { + a->type = NA_IP; + } +} + +/* +============= +ExtractPort +============= +*/ +static bool ExtractPort( const char *src, char *buf, int bufsize, int *port ) { + char *p; + strncpy( buf, src, bufsize ); + p = buf; p += Min( bufsize - 1, (int)strlen( src ) ); *p = '\0'; + p = strchr( buf, ':' ); + if ( !p ) { + return false; + } + *p = '\0'; + *port = strtol( p+1, NULL, 10 ); + if ( ( *port == 0 && errno == EINVAL ) || + ( ( *port == INT_MIN || *port == INT_MAX ) && errno == ERANGE ) ) { + return false; + } + return true; +} + +/* +============= +StringToSockaddr +============= +*/ +static bool StringToSockaddr( const char *s, struct sockaddr_in *sadr, bool doDNSResolve ) { + struct hostent *h; + char buf[256]; + int port; + + memset( sadr, 0, sizeof( *sadr ) ); + sadr->sin_family = AF_INET; + + sadr->sin_port = 0; + + if (s[0] >= '0' && s[0] <= '9') { + if ( !inet_aton( (char *)s, &sadr->sin_addr ) ) { + // check for port + if ( !ExtractPort( s, buf, sizeof( buf ), &port ) ) { + return false; + } + if ( !inet_aton( buf, &sadr->sin_addr ) ) { + return false; + } + sadr->sin_port = htons( port ); + } + } else if ( doDNSResolve ) { + // try to remove the port first, otherwise the DNS gets confused into multiple timeouts + // failed or not failed, buf is expected to contain the appropriate host to resolve + if ( ExtractPort( s, buf, sizeof( buf ), &port ) ) { + sadr->sin_port = htons( port ); + } + if ( !( h = gethostbyname( buf ) ) ) { + return false; + } + *(int *) &sadr->sin_addr = + *(int *) h->h_addr_list[0]; + } + + return true; +} + +/* +============= +Sys_StringToAdr +============= +*/ +bool Sys_StringToNetAdr( const char *s, netadr_t * a, bool doDNSResolve ) { + struct sockaddr_in sadr; + + if ( !StringToSockaddr( s, &sadr, doDNSResolve ) ) { + return false; + } + + SockadrToNetadr( &sadr, a ); + return true; +} + +/* +============= +Sys_NetAdrToString +============= +*/ +const char *Sys_NetAdrToString( const netadr_t a ) { + static char s[64]; + + if ( a.type == NA_LOOPBACK ) { + if ( a.port ) { + idStr::snPrintf( s, sizeof(s), "localhost:%i", a.port ); + } else { + idStr::snPrintf( s, sizeof(s), "localhost" ); + } + } else if ( a.type == NA_IP ) { + idStr::snPrintf( s, sizeof(s), "%i.%i.%i.%i:%i", + a.ip[0], a.ip[1], a.ip[2], a.ip[3], a.port ); + } + return s; +} + +/* +================== +Sys_IsLANAddress +================== +*/ +bool Sys_IsLANAddress( const netadr_t adr ) { + int i; + unsigned int ip; + +#if ID_NOLANADDRESS + common->Printf( "Sys_IsLANAddress: ID_NOLANADDRESS\n" ); + return false; +#endif + + if ( adr.type == NA_LOOPBACK ) { + return true; + } + + if ( adr.type != NA_IP ) { + return false; + } + + if ( !num_interfaces ) { + return false; // well, if there's no networking, there are no LAN addresses, right + } + + for ( i = 0; i < num_interfaces; i++ ) { + ip = ntohl( adr.ip[0] ); + if( ( netint[i].ip & netint[i].mask ) == ( ip & netint[i].mask ) ) { + return true; + } + } + + return false; +} + +/* +=================== +Sys_CompareNetAdrBase + +Compares without the port +=================== +*/ +bool Sys_CompareNetAdrBase( const netadr_t a, const netadr_t b ) { + if ( a.type != b.type ) { + return false; + } + + if ( a.type == NA_LOOPBACK ) { + return true; + } + + if ( a.type == NA_IP ) { + if ( a.ip[0] == b.ip[0] && a.ip[1] == b.ip[1] && a.ip[2] == b.ip[2] && a.ip[3] == b.ip[3] ) { + return true; + } + return false; + } + + common->Printf( "Sys_CompareNetAdrBase: bad address type\n" ); + return false; +} + +/* +==================== +NET_InitNetworking +==================== +*/ +void Sys_InitNetworking(void) +{ + // haven't been able to clearly pinpoint which standards or RFCs define SIOCGIFCONF, SIOCGIFADDR, SIOCGIFNETMASK ioctls + // it seems fairly widespread, in Linux kernel ioctl, and in BSD .. so let's assume it's always available on our targets + + int s; + char buf[ MAX_INTERFACES*sizeof( ifreq ) ]; + struct ifconf ifc; + struct ifreq *ifr; + int ifindex; + unsigned int ip, mask; + + num_interfaces = 0; + + s = socket( AF_INET, SOCK_DGRAM, 0 ); + + memset (buf, 0, MAX_INTERFACES*sizeof( struct ifreq )); + memset (&ifc, 0, sizeof(struct ifconf)); + + ifc.ifc_len = MAX_INTERFACES*sizeof( struct ifreq ); + ifc.ifc_buf = buf; + + if ( IoctlSocket( s, SIOCGIFCONF, (char *)&ifc ) < 0 ) { + common->FatalError( "InitNetworking: SIOCGIFCONF error - %s\n", strerror( errno ) ); + return; + } + ifindex = 0; + + common->Printf( "Dumping SIOCGIFCONF data -:\n"); + + int var1, var2; + for (var1 = 0; var1 < ifc.ifc_len; var1 += 10) + { + common->Printf( "%p: ", ((caddr_t)&ifc + var1) ); + for (var2 = 0; var2 < 10; var2 ++) + { + common->Printf( " %02X", *((char *)((caddr_t)&ifc + var1 + var2))); + } + common->Printf( "\n"); + } + + while ( ifindex < ifc.ifc_len ) { + // find the type - ignore interfaces for which we can find we can't get IP and mask ( not configured ) + ifr = (struct ifreq *)((caddr_t)ifc.ifc_buf + ifindex ); + + common->Printf( "interface @ %p '%s' - ", ifr, ifr->ifr_name ); + if ( IoctlSocket( s, SIOCGIFADDR, (char *)ifr ) < 0 ) { + common->Printf( "SIOCGIFADDR failed: %s\n", strerror( errno ) ); + } else { + if ( ifr->ifr_addr.sa_family != AF_INET ) { + common->Printf( "not AF_INET\n" ); + } else { + ip = ntohl( *( unsigned int *)&ifr->ifr_addr.sa_data[2] ); + if ( ip == INADDR_LOOPBACK ) { + common->Printf( "loopback\n" ); + } else { + common->Printf( "%d.%d.%d.%d", + (unsigned char)ifr->ifr_addr.sa_data[2], + (unsigned char)ifr->ifr_addr.sa_data[3], + (unsigned char)ifr->ifr_addr.sa_data[4], + (unsigned char)ifr->ifr_addr.sa_data[5] ); + } + if ( IoctlSocket( s, SIOCGIFNETMASK, (char *)ifr ) < 0 ) { + common->Printf( " SIOCGIFNETMASK failed: %s\n", strerror( errno ) ); + } else { + mask = ntohl( *( unsigned int *)&ifr->ifr_addr.sa_data[2] ); + if ( ip != INADDR_LOOPBACK ) { + common->Printf( "/%d.%d.%d.%d\n", + (unsigned char)ifr->ifr_addr.sa_data[2], + (unsigned char)ifr->ifr_addr.sa_data[3], + (unsigned char)ifr->ifr_addr.sa_data[4], + (unsigned char)ifr->ifr_addr.sa_data[5] ); + } + netint[ num_interfaces ].ip = ip; + netint[ num_interfaces ].mask = mask; + num_interfaces++; + } + } + } + ifindex += sizeof(ifr->ifr_name) + + (ifr->ifr_addr.sa_len > sizeof(struct sockaddr) + ? ifr->ifr_addr.sa_len + : sizeof(struct sockaddr)); + } +} + +/* +==================== +IPSocket +==================== +*/ +static int IPSocket( const char *net_interface, int port, netadr_t *bound_to = NULL ) { + int newsocket; + struct sockaddr_in address; + int i = 1; + + if ( net_interface ) { + common->Printf( "Opening IP socket: %s:%i\n", net_interface, port ); + } else { + common->Printf( "Opening IP socket: localhost:%i\n", port ); + } + + if ( ( newsocket = socket( PF_INET, SOCK_DGRAM, IPPROTO_UDP ) ) == -1 ) { + common->Printf( "ERROR: IPSocket: socket: %s", strerror( errno ) ); + return 0; + } + // make it non-blocking + int on = 1; + if ( IoctlSocket( newsocket, FIONBIO, (char *)&on ) < 0 ) { + common->Printf( "ERROR: IPSocket: ioctl FIONBIO:%s\n", + strerror( errno ) ); + return 0; + } + // make it broadcast capable + if ( setsockopt( newsocket, SOL_SOCKET, SO_BROADCAST, (char *) &i, sizeof(i) ) == -1 ) { + common->Printf( "ERROR: IPSocket: setsockopt SO_BROADCAST:%s\n", strerror( errno ) ); + return 0; + } + + if ( !net_interface || !net_interface[ 0 ] + || !idStr::Icmp( net_interface, "localhost" ) ) { + address.sin_addr.s_addr = INADDR_ANY; + } else { + StringToSockaddr( net_interface, &address, true ); + } + + if ( port == PORT_ANY ) { + address.sin_port = 0; + } else { + address.sin_port = htons((short) port); + } + + address.sin_family = AF_INET; + + if ( bind( newsocket, (struct sockaddr *)&address, sizeof( address ) ) == -1 ) { + common->Printf( "ERROR: IPSocket: bind: %s\n", strerror( errno ) ); + CloseSocket( newsocket ); + return 0; + } + + if ( bound_to ) { + socklen_t len = sizeof( address ); + if ( (unsigned int)(getsockname( newsocket, (struct sockaddr *)&address, &len )) == -1 ) { + common->Printf( "ERROR: IPSocket: getsockname: %s\n", strerror( errno ) ); + CloseSocket( newsocket ); + return 0; + } + SockadrToNetadr( &address, bound_to ); + } + + return newsocket; +} + +/* +================== +idPort::idPort +================== +*/ +idPort::idPort() { + netSocket = 0; + memset( &bound_to, 0, sizeof( bound_to ) ); +} + +/* +================== +idPort::~idPort +================== +*/ +idPort::~idPort() { + Close(); +} + +/* +================== +idPort::Close +================== +*/ +void idPort::Close() { + if ( netSocket ) { + CloseSocket(netSocket); + netSocket = 0; + memset( &bound_to, 0, sizeof( bound_to ) ); + } +} + +/* +================== +idPort::GetPacket +================== +*/ +bool idPort::GetPacket( netadr_t &net_from, void *data, int &size, int maxSize ) { + int ret; + struct sockaddr_in from; + socklen_t fromlen; + + if ( !netSocket ) { + return false; + } + + fromlen = sizeof( from ); + ret = recvfrom( netSocket, data, maxSize, 0, (struct sockaddr *) &from, &fromlen ); + + if ( ret == -1 ) { + if (errno == EWOULDBLOCK || errno == ECONNREFUSED) { + // those commonly happen, don't verbose + return false; + } + common->DPrintf( "idPort::GetPacket recvfrom(): %s\n", strerror( errno ) ); + return false; + } + + assert( ret < maxSize ); + + SockadrToNetadr( &from, &net_from ); + size = ret; + return true; +} + +/* +================== +idPort::GetPacketBlocking +================== +*/ +bool idPort::GetPacketBlocking( netadr_t &net_from, void *data, int &size, int maxSize, int timeout ) { + fd_set set; + struct timeval tv; + int ret; + + if ( !netSocket ) { + return false; + } + + if ( timeout < 0 ) { + return GetPacket( net_from, data, size, maxSize ); + } + + FD_ZERO( &set ); + FD_SET( netSocket, &set ); + + tv.tv_sec = timeout / 1000; + tv.tv_usec = ( timeout % 1000 ) * 1000; + ret = WaitSelect( netSocket+1, &set, NULL, NULL, &tv, NULL ); + if ( ret == -1 ) { + if ( errno == EINTR ) { + common->DPrintf( "idPort::GetPacketBlocking: select EINTR\n" ); + return false; + } else { + common->Error( "idPort::GetPacketBlocking: select failed: %s\n", strerror( errno ) ); + } + } + + if ( ret == 0 ) { + // timed out + return false; + } + struct sockaddr_in from; + socklen_t fromlen; + fromlen = sizeof( from ); + ret = recvfrom( netSocket, data, maxSize, 0, (struct sockaddr *)&from, &fromlen ); + if ( ret == -1 ) { + // there should be no blocking errors once select declares things are good + common->DPrintf( "idPort::GetPacketBlocking: %s\n", strerror( errno ) ); + return false; + } + assert( ret < maxSize ); + SockadrToNetadr( &from, &net_from ); + size = ret; + return true; +} + +/* +================== +idPort::SendPacket +================== +*/ +void idPort::SendPacket( const netadr_t to, const void *data, int size ) { + int ret; + struct sockaddr_in addr; + + if ( to.type == NA_BAD ) { + common->Warning( "idPort::SendPacket: bad address type NA_BAD - ignored" ); + return; + } + + if ( !netSocket ) { + return; + } + + NetadrToSockadr( &to, &addr ); + + ret = sendto( netSocket, data, size, 0, (struct sockaddr *) &addr, sizeof(addr) ); + if ( ret == -1 ) { + common->Printf( "idPort::SendPacket ERROR: to %s: %s\n", Sys_NetAdrToString( to ), strerror( errno ) ); + } +} + +/* +================== +idPort::InitForPort +================== +*/ +bool idPort::InitForPort( int portNumber ) { + netSocket = IPSocket( net_ip.GetString(), portNumber, &bound_to ); + if ( netSocket <= 0 ) { + netSocket = 0; + memset( &bound_to, 0, sizeof( bound_to ) ); + return false; + } + return true; +} + +//============================================================================= + +/* +================== +idTCP::idTCP +================== +*/ +idTCP::idTCP() { + fd = 0; + memset(&address, 0, sizeof(address)); +} + +/* +================== +idTCP::~idTCP +================== +*/ +idTCP::~idTCP() { + Close(); +} + +/* +================== +idTCP::Init +================== +*/ +bool idTCP::Init( const char *host, short port ) { + struct sockaddr_in sadr; + if ( !Sys_StringToNetAdr( host, &address, true ) ) { + common->Printf( "Couldn't resolve server name \"%s\"\n", host ); + return false; + } + address.type = NA_IP; + if (!address.port) { + address.port = port; + } + common->Printf( "\"%s\" resolved to %i.%i.%i.%i:%i\n", host, + address.ip[0], address.ip[1], address.ip[2], address.ip[3], address.port ); + NetadrToSockadr(&address, &sadr); + + if (fd) { + common->Warning("idTCP::Init: already initialized?\n"); + } + + if ((fd = socket(PF_INET, SOCK_STREAM, 0)) == -1) { + fd = 0; + common->Printf("ERROR: idTCP::Init: socket: %s\n", strerror(errno)); + return false; + } + + if ( connect( fd, (sockaddr *)&sadr, sizeof( sadr ) ) == -1 ) { + common->Printf( "ERROR: idTCP::Init: connect: %s\n", strerror( errno ) ); + CloseSocket( fd ); + fd = 0; + return false; + } + + int status; + if ((status = fcntl(fd, F_GETFL, 0)) != -1) { + status |= O_NONBLOCK; /* POSIX */ + status = fcntl(fd, F_SETFL, status); + } + if (status == -1) { + common->Printf("ERROR: idTCP::Init: fcntl / O_NONBLOCK: %s\n", strerror(errno)); + CloseSocket(fd); + fd = 0; + return false; + } + + common->DPrintf("Opened TCP connection\n"); + return true; +} + +/* +================== +idTCP::Close +================== +*/ +void idTCP::Close() { + if (fd) { + CloseSocket(fd); + } + fd = 0; +} + +/* +================== +idTCP::Read +================== +*/ +int idTCP::Read(void *data, int size) { + int nbytes; + + if (!fd) { + common->Printf("idTCP::Read: not initialized\n"); + return -1; + } + + do { + nbytes = recv( fd, data, size, 0 ); + } while ( nbytes == -1 && errno == EINTR ); + if ( nbytes == -1 ) { + if (errno == EAGAIN) { + return 0; + } + common->Printf("ERROR: idTCP::Read: %s\n", strerror(errno)); + Close(); + return -1; + } + + // a successful read of 0 bytes indicates remote has closed the connection + if ( nbytes == 0 ) { + common->DPrintf( "idTCP::Read: read 0 bytes - assume connection closed\n" ); + return -1; + } + + return nbytes; +} + +/* +================== +idTCP::Write +================== +*/ + +static void got_SIGPIPE( int signum ) { + common->Printf( "idTCP: SIGPIPE\n" ); +} + +int idTCP::Write(void *data, int size) { + int nbytes; + + if ( !fd ) { + common->Printf( "idTCP::Write: not initialized\n"); + return -1; + } + + struct sigaction bak_action; + struct sigaction action; + + action.sa_handler = got_SIGPIPE; + sigemptyset( &action.sa_mask ); + action.sa_flags = 0; + + if ( sigaction( SIGPIPE, &action, &bak_action ) != 0 ) { + common->Printf( "ERROR: idTCP::Write: failed to set temporary SIGPIPE handler\n" ); + Close(); + return -1; + } + + do { + nbytes = send( fd, data, size, 0 ); + } while ( nbytes == -1 && errno == EINTR ); + if ( nbytes == -1 ) { + common->Printf( "ERROR: idTCP::Write: %s\n", strerror( errno ) ); + Close(); + return -1; + } + + if ( sigaction( SIGPIPE, &bak_action, NULL ) != 0 ) { + common->Printf( "ERROR: idTCP::Write: failed to reset SIGPIPE handler\n" ); + Close(); + return -1; + } + + return nbytes; +} diff --git a/neo/sys/aros/aros_public.h b/neo/sys/aros/aros_public.h new file mode 100644 index 00000000..9880f9ef --- /dev/null +++ b/neo/sys/aros/aros_public.h @@ -0,0 +1,59 @@ +/* +=========================================================================== + +Doom 3 GPL Source Code +Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company. + +This file is part of the Doom 3 GPL Source Code ("Doom 3 Source Code"). + +Doom 3 Source Code is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +Doom 3 Source Code is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>. + +In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below. + +If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA. + +=========================================================================== +*/ + +#ifndef __SYS_AROS__ +#define __SYS_AROS__ + +#include <signal.h> + +#include "sys/sys_public.h" + +const char* AROS_Cwd( void ); + +// called first thing. does InitSigs and various things +void AROS_EarlyInit( ); +// called after common has been initialized +void AROS_LateInit( ); + +void AROS_InitLibs( ); +void AROS_InitSigs( ); +void AROS_ClearSigs( ); + +void AROS_Exit( int ret ); +void AROS_SetExit(int ret); // override the exit code +void AROS_SetExitSpawn( const char *exeName ); // set the process to be spawned when we quit + +void AROS_InitConsoleInput( void ); +void AROS_Shutdown( void ); + +void AROS_OpenURL( const char *url ); + +void Sys_FPE_handler( int signum, siginfo_t *info, void *context ); +void Sys_DoStartProcess( const char *exeName, bool dofork = true ); // if not forking, current process gets replaced + +#endif diff --git a/neo/sys/aros/aros_signal.cpp b/neo/sys/aros/aros_signal.cpp new file mode 100644 index 00000000..f8626f49 --- /dev/null +++ b/neo/sys/aros/aros_signal.cpp @@ -0,0 +1,174 @@ +/* +=========================================================================== + +Doom 3 GPL Source Code +Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company. + +This file is part of the Doom 3 GPL Source Code ("Doom 3 Source Code"). + +Doom 3 Source Code is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +Doom 3 Source Code is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>. + +In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below. + +If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA. + +=========================================================================== +*/ + +#include <string.h> +#include <unistd.h> +#include <errno.h> + +#include "sys/platform.h" +#include "framework/Common.h" + +#include "sys/aros/aros_public.h" + +const int siglist[] = { + SIGHUP, + SIGQUIT, + SIGILL, + SIGTRAP, +#if !defined(__AROS__) + SIGIOT, +#endif + SIGBUS, + SIGFPE, + SIGSEGV, + SIGPIPE, + SIGABRT, + // SIGTTIN, + // SIGTTOU, + -1 + }; + +const char *signames[] = { + "SIGHUP", + "SIGQUIT", + "SIGILL", + "SIGTRAP", +#if !defined(__AROS__) + "SIGIOT", +#endif + "SIGBUS", + "SIGFPE", + "SIGSEGV", + "SIGPIPE", + "SIGABRT", + // "SIGTTIN", + // "SIGTTOUT" +}; + +static char fatalError[ 1024 ]; + +#if defined(__AROS__) +#define strsignal(x) signames[x] +#endif + +/* +================ +AROS_ClearSigs +================ +*/ +void AROS_ClearSigs( ) { + struct sigaction action; + int i; + + /* Set up the structure */ + action.sa_handler = SIG_DFL; + sigemptyset( &action.sa_mask ); + action.sa_flags = 0; + + i = 0; + while ( siglist[ i ] != -1 ) { + if ( sigaction( siglist[ i ], &action, NULL ) != 0 ) { + Sys_Printf( "Failed to reset %s handler: %s\n", signames[ i ], strerror( errno ) ); + } + i++; + } +} + +/* +================ +sig_handler +================ +*/ +static void sig_handler( int signum, siginfo_t *info, void *context ) { + static bool double_fault = false; + + if ( double_fault ) { + Sys_Printf( "double fault %s, bailing out\n", strsignal( signum ) ); + _exit( signum ); + } + + double_fault = true; + + // NOTE: see sigaction man page, could verbose the whole siginfo_t and print human readable si_code + Sys_Printf( "signal caught: %s\nsi_code %d\n", strsignal( signum ), info->si_code ); + + if ( fatalError[ 0 ] ) { + Sys_Printf( "Was in fatal error shutdown: %s\n", fatalError ); + } + + Sys_Printf( "Trying to exit gracefully..\n" ); + + AROS_SetExit( signum ); + + common->Quit(); +} + +/* +================ +AROS_InitSigs +================ +*/ +void AROS_InitSigs( ) { + struct sigaction action; + int i; + + fatalError[0] = '\0'; + + /* Set up the structure */ + action.sa_sigaction = sig_handler; + sigemptyset( &action.sa_mask ); + action.sa_flags = SA_SIGINFO | SA_NODEFER; + + i = 0; + while ( siglist[ i ] != -1 ) { + if ( siglist[ i ] == SIGFPE ) { + action.sa_sigaction = Sys_FPE_handler; + if ( sigaction( siglist[ i ], &action, NULL ) != 0 ) { + Sys_Printf( "Failed to set SIGFPE handler: %s\n", strerror( errno ) ); + } + action.sa_sigaction = sig_handler; + } else if ( sigaction( siglist[ i ], &action, NULL ) != 0 ) { + Sys_Printf( "Failed to set %s handler: %s\n", signames[ i ], strerror( errno ) ); + } + i++; + } + + // if the process is backgrounded (running non interactively) + // then SIGTTIN or SIGTOU could be emitted, if not caught, turns into a SIGSTP + signal( SIGTTIN, SIG_IGN ); + signal( SIGTTOU, SIG_IGN ); +} + +/* +================== +Sys_SetFatalError +================== +*/ +void Sys_SetFatalError( const char *error ) { + strncpy( fatalError, error, sizeof( fatalError ) ); +} diff --git a/neo/sys/aros/dll/dll.c b/neo/sys/aros/dll/dll.c new file mode 100644 index 00000000..cf463357 --- /dev/null +++ b/neo/sys/aros/dll/dll.c @@ -0,0 +1,368 @@ +/* +** This file contains the runtime usable DLL functions, like LoadLibrary, GetProcAddress etc. +*/ + +#define DEBUG 1 + +#include <aros/debug.h> + +#define __DLL_LIB_BUILD + +#include "dll.h" +#include <dos/dos.h> +#include <dos/dostags.h> +#include <stdlib.h> +#include <string.h> +#include <stdio.h> +#include <proto/exec.h> +#include <proto/dos.h> + +void dllInternalFreeLibrary(int); + +#define DLLOPENDLLS_MAX 20 +static int dllsopened = 0; + +struct dllOpenedDLL +{ + struct dll_sInstance *inst; + int usecount; + char name[100]; +}; + +struct dllOpenedDLL dllOpenedDLLs[DLLOPENDLLS_MAX]; //Maybe better use a linked list, but should work for now + +void dllCleanup() +{ + int i; + + bug("[DynLink] %s()\n", __PRETTY_FUNCTION__); + + for(i=0;i<DLLOPENDLLS_MAX;i++) + if(dllOpenedDLLs[i].inst) + dllInternalFreeLibrary(i); +} + +void *dllLoadLibrary(char *filename,char *portname) +{ + int (*Entry)(void *, long, void *); + void *hinst; + + bug("[DynLink] %s('%s','%s')\n", __PRETTY_FUNCTION__, filename, portname); + + hinst = dllInternalLoadLibrary(filename, portname, 1L); + + if (!hinst) return NULL; + + // Check for an entry point + Entry = dllGetProcAddress(hinst, "DllEntryPoint"); + if (Entry) + { + int ret = Entry(hinst, 0, NULL); + if (ret) + { + // if we get non-null here, assume the initialisation worked + return hinst; + } + else + { + // the entry point reported an error + dllFreeLibrary(hinst); + return NULL; + } + } + return hinst; +} + +void *dllInternalLoadLibrary(char *filename,char *portname,int raiseusecount) +{ + struct dll_sInstance *inst; + struct MsgPort *dllport; + struct MsgPort *myport; + dll_tMessage msg,*reply; + static int cleanupflag=0; + BPTR handle; + int i; + + bug("[DynLink] %s('%s','%s')\n", __PRETTY_FUNCTION__, filename, portname); + + if(!cleanupflag) + { + bzero(&dllOpenedDLLs, sizeof(dllOpenedDLLs)); + + if(atexit((void *)dllCleanup)) + return 0L; + else + cleanupflag=1L; + } + + if(!filename) + return 0L; //Paranoia + + if(!(handle=Open(filename, MODE_OLDFILE))) + return 0L; + + Close(handle); + + if(!portname) + portname=filename; + + // Search for already opened DLLs + for(i=0;i<DLLOPENDLLS_MAX;i++) + { + if(dllOpenedDLLs[i].inst) + { + if(strcmp(dllOpenedDLLs[i].name,portname)==0) + { + if(raiseusecount) + dllOpenedDLLs[i].usecount++; + return dllOpenedDLLs[i].inst; + } + } + } + + bug("[DynLink] %s: not opened yet\n", __PRETTY_FUNCTION__); + // Not opened yet, search for a free slot + + for(i=0;i<DLLOPENDLLS_MAX;i++) + if(!dllOpenedDLLs[i].inst) + break; + + if(i==DLLOPENDLLS_MAX) + return 0L; // No free slot available + + bug("[DynLink] %s: using slot %u\n", __PRETTY_FUNCTION__, i); + + if(!(inst=malloc(sizeof(struct dll_sInstance)))) + return 0L; + + bug("[DynLink] %s: instance @ 0x%p\n", __PRETTY_FUNCTION__, inst); + + if(!(myport=CreateMsgPort())) + { + free(inst); + return 0L; + } + + bug("[DynLink] %s: port @ 0x%p\n", __PRETTY_FUNCTION__, myport); + + if(!(dllport=FindPort(portname))) + { + BPTR output = Open("CON:0/0/800/600/DLL_OUTPUT/AUTO/CLOSE/WAIT", MODE_NEWFILE); + char commandline[1024]; + int i; + + sprintf(commandline,"\"%s\" \"%s\"", filename, portname); + + bug("[DynLink] %s: calling '%s', output @ 0x%p\n", __PRETTY_FUNCTION__, commandline, output); + + SystemTags(commandline, + SYS_Asynch, TRUE, + SYS_Output, output, + SYS_Input, NULL, //FIXME: some dll's might need stdin + NP_StackSize, 10000, //Messagehandler doesn't need a big stack (FIXME: but DLL_(De)Init might) + TAG_DONE); + + bug("[DynLink] %s: waiting for load ...\n", __PRETTY_FUNCTION__); + + for (i=0; i<20; i++) + { + dllport = FindPort(portname); + if (dllport) break; + //printf("Delaying...\n"); + Delay(25L); + } + } + + if(!dllport) + { + DeleteMsgPort(myport); + free(inst); + return 0L; + } + + bug("[DynLink] %s: found port for '%s' @ 0x%p\n", __PRETTY_FUNCTION__, portname, dllport); + + inst->dllPort=dllport; + inst->StackType=DLLSTACK_DEFAULT; + + bzero(&msg, sizeof(msg)); + + msg.dllMessageType=DLLMTYPE_Open; + msg.dllMessageData.dllOpen.StackType = inst->StackType; + + msg.Message.mn_ReplyPort = myport; + PutMsg(dllport, (struct Message *)&msg); + WaitPort(myport); + reply=(dll_tMessage *)GetMsg(myport); + + if (reply) + { + if(reply->dllMessageData.dllOpen.ErrorCode!=DLLERR_NoError) + { + DeleteMsgPort(myport); + free(inst); + return 0L; + } + + //Obligatory symbol exports + inst->FindResource = dllGetProcAddress(inst,"dllFindResource"); + inst->LoadResource = dllGetProcAddress(inst,"dllLoadResource"); + inst->FreeResource = dllGetProcAddress(inst,"dllFreeResource"); + + if((inst->FindResource==0L)|| + (inst->LoadResource==0L)|| + (inst->FreeResource==0L)) + { + DeleteMsgPort(myport); + dllOpenedDLLs[i].inst=inst; + dllInternalFreeLibrary(i); + return 0L; + } + } + else + { + //FIXME: Must/Can I send a Close message here ?? + DeleteMsgPort(myport); + free(inst); + return 0L; + } + + DeleteMsgPort(myport); + + dllOpenedDLLs[i].inst=inst; + dllOpenedDLLs[i].usecount=1; + strcpy(dllOpenedDLLs[i].name,portname); + + return inst; +} + +void dllFreeLibrary(void *hinst) +{ + int i; + + bug("[DynLink] %s(0x%p)\n", __PRETTY_FUNCTION__, hinst); + + for(i=0;i<DLLOPENDLLS_MAX;i++) + if(dllOpenedDLLs[i].inst==hinst) + break; + + if(i==DLLOPENDLLS_MAX) + return; // ????? + + dllOpenedDLLs[i].usecount--; + + if(dllOpenedDLLs[i].usecount<=0) + dllInternalFreeLibrary(i); +} + +void dllInternalFreeLibrary(int i) +{ + dll_tMessage msg,*reply; + struct MsgPort *myport; + struct dll_sInstance *inst=(struct dll_sInstance *) dllOpenedDLLs[i].inst; + + bug("[DynLink] %s(%u)\n", __PRETTY_FUNCTION__, i); + + if(!inst) + return; + + if(!(myport=CreateMsgPort())) + { + exit(0L); //Arghh + } + + bzero(&msg, sizeof(msg)); + + msg.dllMessageType=DLLMTYPE_Close; + + msg.Message.mn_ReplyPort = myport; + + if(FindPort(dllOpenedDLLs[i].name)==inst->dllPort) + { + PutMsg(inst->dllPort, (struct Message *)&msg); + /*WaitPort(myport);*/ + while(!(reply=(dll_tMessage *)GetMsg(myport))) + { + Delay(2); + if(FindPort(dllOpenedDLLs[i].name)!=inst->dllPort) + break; + } + } + + DeleteMsgPort(myport); + free(inst); + + bzero(&dllOpenedDLLs[i],sizeof(dllOpenedDLLs[i])); + return; +} + +void *dllGetProcAddress(void *hinst,char *name) +{ + dll_tMessage msg,*reply; + struct MsgPort *myport; + struct dll_sInstance *inst=(struct dll_sInstance *) hinst; + void *sym; + + bug("[DynLink] %s(0x%p, '%s')\n", __PRETTY_FUNCTION__, hinst, name); + + if(!hinst) + return 0L; + + if(!(myport=CreateMsgPort())) + { + return 0L; + } + + bzero(&msg, sizeof(msg)); + + msg.dllMessageType=DLLMTYPE_SymbolQuery; + msg.dllMessageData.dllSymbolQuery.StackType=inst->StackType; + msg.dllMessageData.dllSymbolQuery.SymbolName=name; + msg.dllMessageData.dllSymbolQuery.SymbolPointer=&sym; + + msg.Message.mn_ReplyPort = myport; + PutMsg(inst->dllPort, (struct Message *)&msg); + WaitPort(myport); + reply=(dll_tMessage *)GetMsg(myport); + + DeleteMsgPort(myport); + + if(reply) + return(sym); + + return 0L; +} + +int dllKillLibrary(char *portname) +{ + dll_tMessage msg,*reply; + struct MsgPort *myport; + struct MsgPort *dllport; + + bug("[DynLink] %s('%s')\n", __PRETTY_FUNCTION__, portname); + + if(!(myport=CreateMsgPort())) + exit(0L); //Arghh + + bzero(&msg, sizeof(msg)); + + msg.dllMessageType=DLLMTYPE_Kill; + + msg.Message.mn_ReplyPort = myport; + + if((dllport=FindPort(portname))) + { + PutMsg(dllport, (struct Message *)&msg); + /*WaitPort(myport);*/ + while(!(reply=(dll_tMessage *)GetMsg(myport))) + { + Delay(2); + if(FindPort(portname)!=dllport) + break; + } + } + + DeleteMsgPort(myport); + + return (dllport?1:0); +} diff --git a/neo/sys/aros/dll/dll.h b/neo/sys/aros/dll/dll.h new file mode 100644 index 00000000..a7438f10 --- /dev/null +++ b/neo/sys/aros/dll/dll.h @@ -0,0 +1,212 @@ +#ifndef __DLL_H +#define __DLL_H + +#ifdef __DLL_LIB_BUILD +#include <exec/exec.h> +#endif + +/************************************************************ + * External structures + ************************************************************/ + +typedef struct dll_sExportSymbol +{ + void * SymbolAddress; + char * SymbolName; +} dll_tExportSymbol; + +typedef struct dll_sImportSymbol +{ + void ** SymbolPointer; + char * SymbolName; + char * DLLFileName; + char * DLLPortName; +} dll_tImportSymbol; + +#ifdef __cplusplus +extern "C" { +#endif + +int dllImportSymbols(void); +void * dllLoadLibrary(char *name,char *portname); +void dllFreeLibrary(void *hinst); +void * dllGetProcAddress(void *hinst,char *name); +int dllKillLibrary(char *portname); + +int DLL_Init(void); +void DLL_DeInit(void); + +#ifdef __cplusplus +} +#endif + + +/* + * Prototypes for DLL implementations + */ + +extern dll_tExportSymbol DLL_ExportSymbols[]; +extern dll_tImportSymbol DLL_ImportSymbols[]; + +/************************************************************ + * Internal structures + ************************************************************/ + +void *dllInternalLoadLibrary(char *filename,char *portname,int raiseusecount); + +/* +** Typedefs for function vectors. +** Any DLL implementor must deliver these functions. +*/ +typedef void* (*dll_tFindResourceFn)(int, char*); +typedef void* (*dll_tLoadResourceFn)(void*); +typedef void (*dll_tFreeResourceFn)(void*); + +/* +** The stack type the application using the DLL prefers. +** If there is no support for this type in your DLL, return +** DLLERR_StackNotSupported. +** +** Implementation note: In the startup code, return different +** function pointers depending on the stack frame. This is +** the preferred method. Some of the stack frames might be +** identical, for example, since there is not UBYTE passing +** on the stack for the different DLL interface functions, +** using the same stack from for all 68k stack types is safe. +*/ + +typedef enum +{ + DLLSTACK_STORM = 0x01, // 68k, StormC + DLLSTACK_EGCS = 0x02, // 68k, GCC or egcs + DLLSTACK_SAS = 0x04, // 68k, SAS/C + DLLSTACK_VBCC = 0x08, // 68k, vbcc + DLLSTACK_POWEROPEN = 0x10, // PPC, StormC or vbcc + DLLSTACK_SYSV = 0x20 // PPC, egcs + //.. +} dll_tStackType; + +#ifdef __STORM__ +#ifdef __PPC__ +#define DLLSTACK_DEFAULT DLLSTACK_POWEROPEN +#else +#define DLLSTACK_DEFAULT DLLSTACK_STORM +#endif +#else //not Storm +#ifdef __VBCC__ +#ifdef __PPC__ +#define DLLSTACK_DEFAULT DLLSTACK_POWEROPEN +#else +#define DLLSTACK_DEFAULT DLLSTACK_VBCC +#endif +#else //not VBCC +#ifdef __GNUC__ +#ifdef __PPC +#define DLLSTACK_DEFAULT DLLSTACK_SYSV +#else +#define DLLSTACK_DEFAULT DLLSTACK_EGCS +#endif +#else //not GCC +#ifdef __SASC__ +#define DLLSTACK_DEFAULT DLLSTACK_SAS +#endif +#endif //GCC +#endif //VBCC +#endif //STORMC + +#ifdef __DLL_LIB_BUILD + +typedef enum +{ + DLLERR_NoError = 0, // No error occured + DLLERR_StackNotSupported = 1, // Illegal stack frame + DLLERR_OutOfMemory = 2 // Init failed due to memory shortage +} dll_tErrorCode; + + +typedef enum +{ + DLLMTYPE_Open = 0, + DLLMTYPE_Close = 1, + DLLMTYPE_SymbolQuery = 2, + DLLMTYPE_Kill = 3 +} dll_tMessageType; + +typedef struct dll_sSymbolQuery +{ + // Preferred stack type of the main program + dll_tStackType StackType; + + // Name of the Symbol + char * SymbolName; + + // Where to put the Symbol Address + void ** SymbolPointer; +} dll_tSymbolQuery; + +/* +*/ +typedef struct dll_sMessage +{ + // Message for sending + struct Message Message; + + dll_tMessageType dllMessageType; + + union + { + struct + { + // Preferred stack type of the main program + dll_tStackType StackType; + + // Initialization error code + dll_tErrorCode ErrorCode; + } dllOpen; + + struct + { + //Empty for now + } dllClose; + + dll_tSymbolQuery dllSymbolQuery; + + } dllMessageData; + + // ... Might grow +} dll_tMessage; + +/* +** This structure is returned by the LoadLibrary() call. It is strictly +** Off-Limits for both the caller and the DLL but rather used internally +** to for tracking resources and other stuff for the DLL. This structure +** may change at any time. +*/ +struct dll_sInstance +{ + struct MsgPort *dllPort; + dll_tStackType StackType; + dll_tFindResourceFn FindResource; + dll_tLoadResourceFn LoadResource; + dll_tFreeResourceFn FreeResource; + // ... Might grow +}; + +/************************************************************ + * Misc + ************************************************************/ + + +#endif // DLL_LIB_BUILD + +#ifndef HINSTANCE +typedef void * HINSTANCE; +#endif + +#ifdef __GNUC__ +#ifdef __PPC +#define __saveds +#endif +#endif + +#endif diff --git a/neo/sys/aros/dll/dllglue.c b/neo/sys/aros/dll/dllglue.c new file mode 100644 index 00000000..4e63ba96 --- /dev/null +++ b/neo/sys/aros/dll/dllglue.c @@ -0,0 +1,50 @@ +/* +** This file contains glue linked into the "shared" object +*/ + +#define DEBUG 1 + +#include <aros/debug.h> +#include <exec/types.h> + +#include "sys/aros/dll/dll.h" + +extern void *GetGameAPI(void *); + +void* dllFindResource(int id, char *pType) +{ + return NULL; +} + +void* dllLoadResource(void *pHandle) +{ + return NULL; +} + +void dllFreeResource(void *pHandle) +{ + return; +} + +dll_tExportSymbol DLL_ExportSymbols[] = +{ + {dllFindResource, "dllFindResource"}, + {dllLoadResource, "dllLoadResource"}, + {dllFreeResource, "dllFreeResource"}, + {(void *)GetGameAPI, "GetGameAPI"}, + {0,0} +}; + +dll_tImportSymbol DLL_ImportSymbols[] = +{ + {0,0,0,0} +}; + +int DLL_Init(void) +{ + return 1; +} + +void DLL_DeInit(void) +{ +} diff --git a/neo/sys/aros/dll/dllimport.c b/neo/sys/aros/dll/dllimport.c new file mode 100644 index 00000000..e6b67190 --- /dev/null +++ b/neo/sys/aros/dll/dllimport.c @@ -0,0 +1,37 @@ +/* +** This file handles the implicit (loadtime) imports. +** For a DLL its called automatically but a normal executable must call it manually +** if it wants to import symbols from a DLL +*/ + +#define __DLL_LIB_BUILD + +#include "dll.h" +#include <stdlib.h> +#include <string.h> + +int dllImportSymbols() +{ + dll_tImportSymbol *symtable=DLL_ImportSymbols; //reference caller's import symbol table + + while(symtable->SymbolPointer) //End of table ?? + { + void *sym; + void *h=dllInternalLoadLibrary(symtable->DLLFileName,symtable->DLLPortName,0L); + + if(!h) + return 0L; + + sym=dllGetProcAddress(h,symtable->SymbolName); + + if(!sym) + return 0L; + + *symtable->SymbolPointer=sym; + + symtable++; + } + + + return 1L; //Success +} diff --git a/neo/sys/aros/dll/dllstartup.c b/neo/sys/aros/dll/dllstartup.c new file mode 100644 index 00000000..a84a86fe --- /dev/null +++ b/neo/sys/aros/dll/dllstartup.c @@ -0,0 +1,177 @@ +/* DLL Startup function + * This file gets linked in when the user does not define a main function + * that is, if he wants to compile a dll + */ + +#define DEBUG 1 + +#include <aros/debug.h> + +#define __DLL_LIB_BUILD + +#include <exec/exec.h> +#include <proto/exec.h> +#include <proto/dos.h> +#include <clib/alib_protos.h> +#include <string.h> +#include <stdio.h> +#include <stdlib.h> +#include "dll.h" + +/* +* Only DLL's can export symbols so this function is defined here. +* Note that on the other hand normal executables *can* have a symbolimport table, +* so dllImportSymbols is defined elsewhere. +*/ + +void dllExportSymbol(dll_tSymbolQuery *sym) +{ + dll_tExportSymbol *symtable=DLL_ExportSymbols; //reference DLL's export symbol table + + if(!sym->SymbolPointer) + return; //Paranoia + + while(symtable->SymbolAddress) //End of table ?? + { + if(strcmp(symtable->SymbolName,sym->SymbolName)==0) + { + //FIXME: Stackframe handling + *sym->SymbolPointer=symtable->SymbolAddress; + return; + } + symtable++; + } + + *sym->SymbolPointer=0L; //Symbol not found +} + +/* +** The actual main function of a DLL +*/ + +int main(int argc, char **argv) +{ + struct MsgPort *myport; + char PortName[255]; + dll_tMessage *msg; + int expunge=0L; + int opencount=0L; + + bug("[DynFile] %s('%s')\n", __PRETTY_FUNCTION__, argv[0]); + + /* + * If an argument was passed, use it as the port name, + * otherwise use the program name + */ + if (argc>1) + { + char *argPort = argv[1]; + + if (argPort[0] == '"') + strncpy(PortName, &argPort[1], strlen(argPort) - 2); + else + strcpy(PortName, argPort); + } + else + { + strcpy(PortName, argv[0]); + } + + bug("[DynFile] %s: Portname '%s'\n", __PRETTY_FUNCTION__, PortName); + /* + * Process symbol import table + */ + if(!dllImportSymbols()) + exit(0L); + + bug("[DynFile] %s: symbols imported\n", __PRETTY_FUNCTION__); + + /* + * Call DLL specific constructor + */ + if(!DLL_Init()) + exit(0L); + + bug("[DynFile] %s: initialised\n", __PRETTY_FUNCTION__); + + /* + * Create a (public) message port + */ + myport = CreatePort(PortName,0); + if (!myport) + exit(0l); + + bug("[DynFile] %s: port @ 0x%p\n", __PRETTY_FUNCTION__, myport); + + /* + ** Loop until DLL expunges (that is if a CloseMessage leads to opencount==0) + ** and no pending Messages are left + */ + while((msg=(dll_tMessage *)GetMsg(myport))||(!expunge)) + { + if (msg) + { + switch(msg->dllMessageType) + { + case DLLMTYPE_Open: + bug("[DynFile] %s: DLLMTYPE_Open\n", __PRETTY_FUNCTION__); + /* + * Stack type checking should go here. Might be ommited for strictly + * private DLLs, or when stack frame compatibility can be 100% assured. + * FIXME: Not handled for now + */ + opencount++; + if(opencount>0) + expunge=0L; + msg->dllMessageData.dllOpen.ErrorCode=DLLERR_NoError; + break; + + case DLLMTYPE_Close: + bug("[DynFile] %s: DLLMTYPE_Close\n", __PRETTY_FUNCTION__); + opencount--; + if(opencount<=0L) // <0 ???? + expunge=1L; + break; + + case DLLMTYPE_SymbolQuery: + bug("[DynFile] %s: DLLMTYPE_SymbolQuery\n", __PRETTY_FUNCTION__); + dllExportSymbol(&msg->dllMessageData.dllSymbolQuery); + //printf("Symbol Query for %s : %p\n",msg->dllMessageData.dllSymbolQuery.SymbolName, + // *msg->dllMessageData.dllSymbolQuery.SymbolPointer); + break; + + case DLLMTYPE_Kill: + bug("[DynFile] %s: DLLMTYPE_Kill\n", __PRETTY_FUNCTION__); + expunge=1L; + break; + } + + /* + * Send the message back + */ + ReplyMsg((struct Message *)msg); + } + + /* + * Wait for messages to pop up + * Note that if the DLL is expunged it doesn't wait anymore, + * but it still processes all pending messages (including open messages + * which can disable the expunge flag). + * FIXME: Is this multithread safe ?? + */ + if(!expunge) + WaitPort(myport); + } + + /* + * Delete public port + */ + DeletePort(myport); + + /* + * Call DLL specific destructor + */ + DLL_DeInit(); + + return 0L; +} diff --git a/neo/sys/aros/mmakefile.src b/neo/sys/aros/mmakefile.src new file mode 100644 index 00000000..db7222fc --- /dev/null +++ b/neo/sys/aros/mmakefile.src @@ -0,0 +1,10 @@ +# Copyright � 2004, The AROS Development Team. All rights reserved. +# $Id: mmakefile.src 33489 2010-06-07 23:03:12Z mazze $ + +include $(TOP)/config/make.cfg + +#MM- iconset-Gorilla-contrib-games-doom3game : doom3-gorillaicons-game + +DOOM3_EXEDIR := $(AROS_CONTRIB)/Games/Fps/ADoom3 +DOOM3_ICONS := ADoom3 ROE +%build_icons mmake=doom3-gorillaicons-game icons="$(DOOM3_ICONS)" dir=$(DOOM3_EXEDIR) diff --git a/neo/sys/aros/setup/ADoom3.info.src b/neo/sys/aros/setup/ADoom3.info.src new file mode 100644 index 00000000..045d67c5 --- /dev/null +++ b/neo/sys/aros/setup/ADoom3.info.src @@ -0,0 +1 @@ +TYPE = DRAWER diff --git a/neo/sys/aros/setup/ADoom3.png b/neo/sys/aros/setup/ADoom3.png new file mode 100644 index 00000000..760901af Binary files /dev/null and b/neo/sys/aros/setup/ADoom3.png differ diff --git a/neo/sys/aros/setup/mmakefile.src b/neo/sys/aros/setup/mmakefile.src new file mode 100644 index 00000000..b6e651b5 --- /dev/null +++ b/neo/sys/aros/setup/mmakefile.src @@ -0,0 +1,20 @@ +# $Id$ + +include $(TOP)/config/make.cfg + +#MM- aros-doom3 : aros-doom3-defconfig + +#MM aros-doom3-defconfig : aros-doom3-dirs + +aros-doom3-defconfig: $(AROS_CONTRIB)/Games/Fps/ADoom3/base/default.cfg + +$(AROS_CONTRIB)/Games/ADoom3/base/default.cfg: $(SRCDIR)/$(CURDIR)/default.cfg + @$(CP) $< $@ + +%build_icons mmake=iconset-Gorilla-contrib-icons-extras-games-adoom3 icons=ADoom3 dir=$(AROS_CONTRIB)/Games/Fps + +#MM +aros-doom3-dirs : + %mkdirs_q $(AROS_CONTRIB)/Fps/Games/ADoom3/base + +%common diff --git a/neo/sys/platform.h b/neo/sys/platform.h index 64aa5d2e..2c4ce984 100644 --- a/neo/sys/platform.h +++ b/neo/sys/platform.h @@ -40,6 +40,34 @@ If you have questions concerning this license or the applicable additional terms =============================================================================== */ +// Win32 +#if defined(__AROS__) + +#define _alloca alloca +#define _alloca16( x ) ((void *)((((uintptr_t)alloca( (x)+15 )) + 15) & ~15)) + +#ifdef GAME_DLL +#define ID_GAME_API __attribute__((visibility ("default"))) +#else +#define ID_GAME_API +#endif + +#define ALIGN16( x ) x __attribute__ ((aligned (16))) +#define PACKED __attribute__((packed)) + +#define PATHSEPERATOR_STR "/" +#define PATHSEPERATOR_CHAR '/' + +#define __cdecl +#define ASSERT assert + +#define ID_INLINE inline +#define ID_STATIC_TEMPLATE + +#define assertmem( x, y ) + +#endif + // Win32 #if defined(WIN32) || defined(_WIN32)