From b998e03723b5eb69925ef9cdb5d9f5f8a99eec3e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Josef=20S=C3=B6ntgen?= Date: Mon, 10 Feb 2014 20:07:52 +0100 Subject: [PATCH] Port of uhexen2 (v1.5.6) This is a working(*) port of 'Hammer of Thyrion' v1.5.6, a Hexen2 cross-platform source port, using SDL on Genode. (*) SDL_VIDEO works, SDL_AUDIO at least makes some noise and network-play is currently untested. Fixes #6. --- ports/uhexen2.hash | 1 + ports/uhexen2.port | 8 + run/uhexen2.run | 204 +++++++++ src/app/uhexen2/net_udp_genode.c | 418 +++++++++++++++++ src/app/uhexen2/sys_genode.cc | 747 +++++++++++++++++++++++++++++++ src/app/uhexen2/target.mk | 126 ++++++ 6 files changed, 1504 insertions(+) create mode 100644 ports/uhexen2.hash create mode 100644 ports/uhexen2.port create mode 100644 run/uhexen2.run create mode 100644 src/app/uhexen2/net_udp_genode.c create mode 100644 src/app/uhexen2/sys_genode.cc create mode 100644 src/app/uhexen2/target.mk diff --git a/ports/uhexen2.hash b/ports/uhexen2.hash new file mode 100644 index 0000000..b2cf01d --- /dev/null +++ b/ports/uhexen2.hash @@ -0,0 +1 @@ +c1af3379613390c015ce0779c5a45e43d3f1f52d diff --git a/ports/uhexen2.port b/ports/uhexen2.port new file mode 100644 index 0000000..8219fe9 --- /dev/null +++ b/ports/uhexen2.port @@ -0,0 +1,8 @@ +LICENSE := GPLv2 +VERSION := 1.5.6 +DOWNLOADS := uhexen2.archive + +BASE_URL := http://downloads.sourceforge.net/project/uhexen2/Hammer%20of%20Thyrion/$(VERSION)/Source +URL(uhexen2) := $(BASE_URL)/hexen2source-$(VERSION).tgz +SHA(uhexen2) := f3735a650468583eb433628b24bf9a15755d092a +DIR(uhexen2) := src/app/uhexen2 diff --git a/run/uhexen2.run b/run/uhexen2.run new file mode 100644 index 0000000..2e7af10 --- /dev/null +++ b/run/uhexen2.run @@ -0,0 +1,204 @@ + +# Build +# + + +set build_components { + core init + drivers/timer + drivers/audio + drivers/usb + drivers/framebuffer drivers/input + app/uhexen2 +} + +source ${genode_dir}/repos/base/run/platform_drv.inc +append_platform_drv_build_components + +set usb_only 0 + +lappend_if [expr !$usb_only] build_components server/input_merger + +build $build_components + +create_boot_directory + +# +# Generate config +# + +append config { + + + + + + + + + + + + + + + + + + + + + } + +append_if [have_spec sdl] config { + + + + + + + } + +append_platform_drv_config + +append_if [have_spec vesa] config { + + + + + + + + + + } + +append_if [have_spec pl11x] config { + + + + } + +append_if [expr [have_spec ps2] && !$usb_only] config { + + + + } + +append config { + + + + + + + + + + + } + +append_if [expr !$usb_only] config { + + + + + + + + + + + + + + + + + + + } + +append config { + + + + + + + + + + + + + + + + } + +append_if [expr !$usb_only] config { + } +append config { + + + +} + +install_config $config + +if {![file exists bin/hexen2demo_data.tar]} { + set hexen2demo_dir "hexen2demo_nov1997" + set hexen2demo_tgz "hexen2demo_nov1997-linux-i586.tgz" + set hexen2demo_url "http://downloads.sourceforge.net/project/uhexen2/Hexen2Demo-Nov.1997/$hexen2demo_tgz" + + if {![file exists bin/hexen2demo_nov1997-linux-i586.tgz]} { + puts "" + puts "Please download Hexen 2 demo data from '$hexen2demo_url'." + puts "Place the archive in './bin' and run this script again." + puts "" + exit 1 + } + + exec tar xzf bin/$hexen2demo_tgz -C bin $hexen2demo_dir/data1 + exec echo showfps 1 >> bin/$hexen2demo_dir/data1/autoexec.cfg + + exec tar cf bin/hexen2demo_data.tar -C bin/$hexen2demo_dir data1 + exec rm -rf bin/$hexen2demo_dir +} + +# +# Boot modules +# + +# generic modules +set boot_modules { + core init + timer + audio_drv + usb_drv + uhexen2 + ld.lib.so + libc.lib.so + libm.lib.so lwip.lib.so sdl.lib.so sdl_mixer.lib.so pthread.lib.so + hexen2demo_data.tar +} + +# platform-specific modules +append_platform_drv_boot_modules + +lappend_if [expr !$usb_only] boot_modules input_merger + +lappend_if [have_spec linux] boot_modules fb_sdl +lappend_if [have_spec vesa] boot_modules fb_drv +lappend_if [have_spec ps2] boot_modules ps2_drv +lappend_if [have_spec pl11x] boot_modules fb_drv + +build_boot_image $boot_modules + +append qemu_args " -m 512 -soundhw es1370 " + +run_genode_until forever diff --git a/src/app/uhexen2/net_udp_genode.c b/src/app/uhexen2/net_udp_genode.c new file mode 100644 index 0000000..38101d4 --- /dev/null +++ b/src/app/uhexen2/net_udp_genode.c @@ -0,0 +1,418 @@ +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program 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 2 +of the License, or (at your option) any later version. + +This program 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 this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ +// net_udp.c + +#include "quakedef.h" + +#include +#include +#include +#include +#include +#include +#include + +typedef int sys_socket_t; + +extern int gethostname (char *, int); +extern int close (int); + +extern cvar_t hostname; + +static int net_acceptsocket = -1; // socket for fielding new connections +static int net_controlsocket; +static int net_broadcastsocket = 0; +static struct qsockaddr broadcastaddr; + +static unsigned long myAddr; + +struct qsockaddr +{ + short sa_family; + unsigned char sa_data[14]; +}; + + +#include "net_udp.h" + +//============================================================================= + +int UDP_Init (void) +{ +/* + struct hostent *local; +*/ + char buff[MAXHOSTNAMELEN]; + struct qsockaddr addr; + char *colon; + + if (COM_CheckParm ("-noudp")) + return -1; +/* + // determine my name & address + gethostname(buff, MAXHOSTNAMELEN); + local = gethostbyname(buff); + myAddr = *(int *)local->h_addr_list[0]; + + // if the quake hostname isn't set, set it to the machine name + if (Q_strcmp(hostname.string, "UNNAMED") == 0) + { + buff[15] = 0; + Cvar_Set ("hostname", buff); + } + +*/ + if ((net_controlsocket = UDP_OpenSocket (0)) == -1) + Sys_Error("UDP_Init: Unable to open control socket\n"); + + ((struct sockaddr_in *)&broadcastaddr)->sin_family = AF_INET; + ((struct sockaddr_in *)&broadcastaddr)->sin_addr.s_addr = INADDR_BROADCAST; + ((struct sockaddr_in *)&broadcastaddr)->sin_port = htons(net_hostport); + + UDP_GetSocketAddr (net_controlsocket, &addr); + strcpy(my_tcpip_address, UDP_AddrToString (&addr)); + colon = strrchr (my_tcpip_address, ':'); + if (colon) + *colon = 0; + + Con_Printf("UDP Initialized\n"); + tcpipAvailable = true; + + return net_controlsocket; +} + +//============================================================================= + +void UDP_Shutdown (void) +{ + UDP_Listen (false); + UDP_CloseSocket (net_controlsocket); +} + +//============================================================================= + +void UDP_Listen (qboolean state) +{ + // enable listening + if (state) + { + if (net_acceptsocket != -1) + return; + if ((net_acceptsocket = UDP_OpenSocket (net_hostport)) == -1) + Sys_Error ("UDP_Listen: Unable to open accept socket\n"); + return; + } + + // disable listening + if (net_acceptsocket == -1) + return; + UDP_CloseSocket (net_acceptsocket); + net_acceptsocket = -1; +} + +//============================================================================= + +int UDP_OpenSocket (int port) +{ + int newsocket; + struct sockaddr_in address; + qboolean _true = true; + + if ((newsocket = socket (PF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1) + return -1; + + if (ioctl (newsocket, FIONBIO, (char *)&_true) == -1) + goto ErrorReturn; + + address.sin_family = AF_INET; + address.sin_addr.s_addr = INADDR_ANY; + address.sin_port = htons(port); + if( bind (newsocket, (void *)&address, sizeof(address)) == -1) + goto ErrorReturn; + + return newsocket; + +ErrorReturn: + close (newsocket); + return -1; +} + +//============================================================================= + +int UDP_CloseSocket (int socket) +{ + if (socket == net_broadcastsocket) + net_broadcastsocket = 0; + return close (socket); +} + + +//============================================================================= +/* +============ +PartialIPAddress + +this lets you type only as much of the net address as required, using +the local network components to fill in the rest +============ +*/ +static int PartialIPAddress (char *in, struct qsockaddr *hostaddr) +{ + char buff[256]; + char *b; + int addr; + int num; + int mask; + int run; + int port; + + buff[0] = '.'; + b = buff; + strcpy(buff+1, in); + if (buff[1] == '.') + b++; + + addr = 0; + mask=-1; + while (*b == '.') + { + b++; + num = 0; + run = 0; + while (!( *b < '0' || *b > '9')) + { + num = num*10 + *b++ - '0'; + if (++run > 3) + return -1; + } + if ((*b < '0' || *b > '9') && *b != '.' && *b != ':' && *b != 0) + return -1; + if (num < 0 || num > 255) + return -1; + mask<<=8; + addr = (addr<<8) + num; + } + + if (*b++ == ':') + port = atoi(b); + else + port = net_hostport; + + hostaddr->sa_family = AF_INET; + ((struct sockaddr_in *)hostaddr)->sin_port = htons((short)port); + ((struct sockaddr_in *)hostaddr)->sin_addr.s_addr = (myAddr & htonl(mask)) | htonl(addr); + + return 0; +} +//============================================================================= + +int UDP_Connect (int socket, struct qsockaddr *addr) +{ + return 0; +} + +//============================================================================= + +int UDP_CheckNewConnections (void) +{ + unsigned long available; + + if (net_acceptsocket == -1) + return -1; + + if (ioctl (net_acceptsocket, FIONREAD, &available) == -1) + Sys_Error ("UDP: ioctlsocket (FIONREAD) failed\n"); + if (available) + return net_acceptsocket; + return -1; +} + +//============================================================================= + +int UDP_Read (int socket, byte *buf, int len, struct qsockaddr *addr) +{ + int addrlen = sizeof (struct qsockaddr); + int ret; + + ret = recvfrom (socket, buf, len, 0, (struct sockaddr *)addr, &addrlen); + if (ret == -1 && (errno == EWOULDBLOCK || errno == ECONNREFUSED)) + return 0; + return ret; +} + +//============================================================================= + +int UDP_MakeSocketBroadcastCapable (int socket) +{ + int i = 1; + + // make this socket broadcast capable + if (setsockopt(socket, SOL_SOCKET, SO_BROADCAST, (char *)&i, sizeof(i)) < 0) + return -1; + net_broadcastsocket = socket; + + return 0; +} + +//============================================================================= + +int UDP_Broadcast (int socket, byte *buf, int len) +{ + int ret; + + if (socket != net_broadcastsocket) + { + if (net_broadcastsocket != 0) + Sys_Error("Attempted to use multiple broadcasts sockets\n"); + ret = UDP_MakeSocketBroadcastCapable (socket); + if (ret == -1) + { + Con_Printf("Unable to make socket broadcast capable\n"); + return ret; + } + } + + return UDP_Write (socket, buf, len, &broadcastaddr); +} + +//============================================================================= + +int UDP_Write (int socket, byte *buf, int len, struct qsockaddr *addr) +{ + int ret; + + ret = sendto (socket, buf, len, 0, (struct sockaddr *)addr, sizeof(struct qsockaddr)); + if (ret == -1 && errno == EWOULDBLOCK) + return 0; + return ret; +} + +//============================================================================= + +const char *UDP_AddrToString (struct qsockaddr *addr) +{ + static char buffer[22]; + int haddr; + + haddr = ntohl(((struct sockaddr_in *)addr)->sin_addr.s_addr); + sprintf(buffer, "%d.%d.%d.%d:%d", (haddr >> 24) & 0xff, (haddr >> 16) & 0xff, (haddr >> 8) & 0xff, haddr & 0xff, ntohs(((struct sockaddr_in *)addr)->sin_port)); + return buffer; +} + +//============================================================================= + +int UDP_StringToAddr (const char *string, struct qsockaddr *addr) +{ + int ha1, ha2, ha3, ha4, hp; + int ipaddr; + + sscanf(string, "%d.%d.%d.%d:%d", &ha1, &ha2, &ha3, &ha4, &hp); + ipaddr = (ha1 << 24) | (ha2 << 16) | (ha3 << 8) | ha4; + + addr->sa_family = AF_INET; + ((struct sockaddr_in *)addr)->sin_addr.s_addr = htonl(ipaddr); + ((struct sockaddr_in *)addr)->sin_port = htons(hp); + return 0; +} + +//============================================================================= + +int UDP_GetSocketAddr (int socket, struct qsockaddr *addr) +{ + int addrlen = sizeof(struct qsockaddr); + unsigned int a; + + memset(addr, 0, sizeof(struct qsockaddr)); + getsockname(socket, (struct sockaddr *)addr, &addrlen); + a = ((struct sockaddr_in *)addr)->sin_addr.s_addr; + if (a == 0 || a == inet_addr("127.0.0.1")) + ((struct sockaddr_in *)addr)->sin_addr.s_addr = myAddr; + + return 0; +} + +//============================================================================= + +int UDP_GetNameFromAddr (struct qsockaddr *addr, char *name) +{ + struct hostent *hostentry; +/* + hostentry = gethostbyaddr ((char *)&((struct sockaddr_in *)addr)->sin_addr, sizeof(struct in_addr), AF_INET); + if (hostentry) + { + strncpy (name, (char *)hostentry->h_name, NET_NAMELEN - 1); + return 0; + } +*/ + strcpy (name, UDP_AddrToString (addr)); + return 0; +} + +//============================================================================= + +int UDP_GetAddrFromName(const char *name, struct qsockaddr *addr) +{ + struct hostent *hostentry = NULL; + + if (name[0] >= '0' && name[0] <= '9') + return PartialIPAddress (name, addr); + +// hostentry = gethostbyname (name); + if (!hostentry) + return -1; + + addr->sa_family = AF_INET; + ((struct sockaddr_in *)addr)->sin_port = htons(net_hostport); + ((struct sockaddr_in *)addr)->sin_addr.s_addr = *(int *)hostentry->h_addr_list[0]; + + return 0; +} + +//============================================================================= + +int UDP_AddrCompare (struct qsockaddr *addr1, struct qsockaddr *addr2) +{ + if (addr1->sa_family != addr2->sa_family) + return -1; + + if (((struct sockaddr_in *)addr1)->sin_addr.s_addr != ((struct sockaddr_in *)addr2)->sin_addr.s_addr) + return -1; + + if (((struct sockaddr_in *)addr1)->sin_port != ((struct sockaddr_in *)addr2)->sin_port) + return 1; + + return 0; +} + +//============================================================================= + +int UDP_GetSocketPort (struct qsockaddr *addr) +{ + return ntohs(((struct sockaddr_in *)addr)->sin_port); +} + + +int UDP_SetSocketPort (struct qsockaddr *addr, int port) +{ + ((struct sockaddr_in *)addr)->sin_port = htons(port); + return 0; +} + +//============================================================================= diff --git a/src/app/uhexen2/sys_genode.cc b/src/app/uhexen2/sys_genode.cc new file mode 100644 index 0000000..039cbdd --- /dev/null +++ b/src/app/uhexen2/sys_genode.cc @@ -0,0 +1,747 @@ +/* + sys_unix.c + Unix system interface code + + $Id: sys_unix.c 4285 2011-10-24 14:20:58Z sezero $ + */ + +extern "C" { + +#include "quakedef.h" +#include "userdir.h" +#include "debuglog.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "sdl_inc.h" + +// heapsize: minimum 16mb, standart 32 mb, max is 96 mb. +// -heapsize argument will abide by these min/max settings +// unless the -forcemem argument is used +#define MIN_MEM_ALLOC 0x1000000 +#define STD_MEM_ALLOC 0x2000000 +#define MAX_MEM_ALLOC 0x6000000 + +cvar_t sys_nostdout = {"sys_nostdout", "0", CVAR_NONE}; +cvar_t sys_throttle = {"sys_throttle", "0.02", CVAR_ARCHIVE}; + +qboolean isDedicated; +static double starttime; +static qboolean first = true; + + +/* =============================================================================== + FILE IO + =============================================================================== */ + +int Sys_mkdir (const char *path, qboolean crash) +{ + int rc = mkdir (path, 0777); + if (rc != 0 && errno == EEXIST) + rc = 0; + if (rc != 0 && crash) + { + rc = errno; + // Sys_Error("Unable to create directory %s: %s", path, strerror(rc)); + } + return rc; +} + +int Sys_rmdir (const char *path) +{ + return rmdir(path); +} + +int Sys_unlink (const char *path) +{ + return unlink(path); +} + +int Sys_rename (const char *oldp, const char *newp) +{ + return rename(oldp, newp); +} + +long Sys_filesize (const char *path) +{ + struct stat st; + + if (stat(path, &st) != 0) + return -1; + if (! S_ISREG(st.st_mode)) + return -1; + + return (long) st.st_size; +} + +int Sys_FileType (const char *path) +{ + /* + if (access(path, R_OK) == -1) + return 0; + */ + struct stat st; + + if (stat(path, &st) != 0) + return FS_ENT_NONE; + if (S_ISDIR(st.st_mode)) + return FS_ENT_DIRECTORY; + if (S_ISREG(st.st_mode)) + return FS_ENT_FILE; + + return FS_ENT_NONE; +} + +#define COPY_READ_BUFSIZE 8192 /* BUFSIZ */ +int Sys_CopyFile (const char *frompath, const char *topath) +{ + char buf[COPY_READ_BUFSIZE]; + FILE *in, *out; + struct stat st; + int err = 0; + // off_t remaining, count; + size_t remaining, count; + + if (stat(frompath, &st) != 0) + { + Con_Printf ("%s: unable to stat %s\n", frompath, __thisfunc__); + return 1; + } + in = fopen (frompath, "rb"); + if (!in) + { + Con_Printf ("%s: unable to open %s\n", frompath, __thisfunc__); + return 1; + } + out = fopen (topath, "wb"); + if (!out) + { + Con_Printf ("%s: unable to create %s\n", topath, __thisfunc__); + fclose (in); + return 1; + } + + remaining = st.st_size; + memset (buf, 0, sizeof(buf)); + while (remaining) + { + if (remaining < sizeof(buf)) + count = remaining; + else + count = sizeof(buf); + + fread (buf, 1, count, in); + err = ferror (in); + if (err) + break; + + fwrite (buf, 1, count, out); + err = ferror (out); + if (err) + break; + + remaining -= count; + } + + fclose (in); + fclose (out); + + if (!err) + { + // restore the file's timestamp + struct utimbuf tm; + tm.actime = time (NULL); + tm.modtime = st.st_mtime; + utime (topath, &tm); + } + + return err; +} + +/* + ================================================= + simplified findfirst/findnext implementation: + Sys_FindFirstFile and Sys_FindNextFile return + filenames only, not a dirent struct. this is + what we presently need in this engine. + ================================================= + */ +static DIR *finddir; +static struct dirent *finddata; +static char *findpath, *findpattern; + +const char *Sys_FindFirstFile (const char *path, const char *pattern) +{ + if (finddir) + Sys_Error ("Sys_FindFirst without FindClose"); + + finddir = opendir (path); + if (!finddir) + return NULL; + + findpattern = Z_Strdup (pattern); + findpath = Z_Strdup (path); + + return Sys_FindNextFile(); +} + +const char *Sys_FindNextFile (void) +{ + struct stat test; + + if (!finddir) + return NULL; + + while ((finddata = readdir(finddir)) != NULL) + { + if (!fnmatch (findpattern, finddata->d_name, FNM_PATHNAME)) + { + if ( (stat(va("%s/%s", findpath, finddata->d_name), &test) == 0) + && S_ISREG(test.st_mode)) + return finddata->d_name; + } + } + + return NULL; +} + +void Sys_FindClose (void) +{ + if (finddir != NULL) + { + closedir(finddir); + finddir = NULL; + } + if (findpath != NULL) + { + Z_Free (findpath); + findpath = NULL; + } + if (findpattern != NULL) + { + Z_Free (findpattern); + findpattern = NULL; + } +} + +/* =============================================================================== + SYSTEM IO + =============================================================================== */ + +/* ================ + Sys_MakeCodeWriteable + ================ */ + +#if id386 && !defined(GLQUAKE) +void Sys_MakeCodeWriteable (unsigned long startaddr, unsigned long length) +{ + int r; + unsigned long endaddr = startaddr + length; +#if !defined(__QNX__) +# if 1 + long psize = sysconf (_SC_PAGESIZE); +# else + int psize = getpagesize(); +# endif + startaddr &= ~(psize - 1); + endaddr = (endaddr + psize - 1) & ~(psize - 1); +#endif + // systems with mprotect but not getpagesize (or similar) probably don't + // need to page align the arguments to mprotect (eg, QNX) + r = mprotect ((char *) startaddr, endaddr - startaddr, PROT_WRITE | PROT_READ | PROT_EXEC); + + if (r == -1) + Sys_Error("Protection change failed\n"); +} +#endif /* id386, !GLQUAKE */ + + +/* ================ + Sys_Init + ================ */ + +static void Sys_Init (void) +{ + /* do we really need these with opengl ?? */ + Sys_SetFPCW(); +} + +#define ERROR_PREFIX "\nFATAL ERROR: " +void Sys_Error (const char *error, ...) +{ + va_list argptr; + char text[MAX_PRINTMSG]; + const char text2[] = ERROR_PREFIX; + const unsigned char *p; + + va_start (argptr, error); + q_vsnprintf (text, sizeof(text), error, argptr); + va_end (argptr); + + if (con_debuglog) + { + LOG_Print (ERROR_PREFIX); + LOG_Print (text); + LOG_Print ("\n\n"); + } + + Host_Shutdown (); + + printf("%s%s\n\n", text2, text); + + exit (1); +} + +void Sys_PrintTerm (const char *msgtxt) +{ + const unsigned char *p; + + if (sys_nostdout.integer) + return; + + for (p = (const unsigned char *) msgtxt; *p; p++) + putc (*p, stdout); +} + +void Sys_Quit (void) +{ + Host_Shutdown(); + + exit (0); +} + + +/* ================ + Sys_DoubleTime + ================ */ + +double Sys_DoubleTime (void) +{ + struct timeval tp; + double now; + + gettimeofday (&tp, NULL); + + now = tp.tv_sec + tp.tv_usec / 1e6; + + if (first) + { + first = false; + starttime = now; + return 0.0; + } + + return now - starttime; +} + +char *Sys_DateTimeString (char *buf) +{ + static char strbuf[24]; + time_t t; + struct tm *l; + int val; + + if (!buf) buf = strbuf; + + t = time(NULL); + l = localtime(&t); + + val = l->tm_mon + 1; /* tm_mon: months since January [0,11] */ + buf[0] = val / 10 + '0'; + buf[1] = val % 10 + '0'; + buf[2] = '/'; + val = l->tm_mday; + buf[3] = val / 10 + '0'; + buf[4] = val % 10 + '0'; + buf[5] = '/'; + val = l->tm_year / 100 + 19; /* tm_year: #years since 1900. */ + buf[6] = val / 10 + '0'; + buf[7] = val % 10 + '0'; + val = l->tm_year % 100; + buf[8] = val / 10 + '0'; + buf[9] = val % 10 + '0'; + + buf[10] = ' '; + + val = l->tm_hour; + buf[11] = val / 10 + '0'; + buf[12] = val % 10 + '0'; + buf[13] = ':'; + val = l->tm_min; + buf[14] = val / 10 + '0'; + buf[15] = val % 10 + '0'; + buf[16] = ':'; + val = l->tm_sec; + buf[17] = val / 10 + '0'; + buf[18] = val % 10 + '0'; + + buf[19] = '\0'; + + return buf; +} + + +/* ================ + Sys_ConsoleInput + ================ */ + +const char *Sys_ConsoleInput (void) +{ + static char con_text[256]; + static int textlen; + char c; + fd_set set; + struct timeval timeout; + + FD_ZERO (&set); + FD_SET (0, &set); // stdin + timeout.tv_sec = 0; + timeout.tv_usec = 0; + + while (select (1, &set, NULL, NULL, &timeout)) + { + read (0, &c, 1); + if (c == '\n' || c == '\r') + { + con_text[textlen] = '\0'; + textlen = 0; + return con_text; + } + else if (c == 8) + { + if (textlen) + { + textlen--; + con_text[textlen] = '\0'; + } + continue; + } + con_text[textlen] = c; + textlen++; + if (textlen < (int) sizeof(con_text)) + con_text[textlen] = '\0'; + else + { + // buffer is full + textlen = 0; + con_text[0] = '\0'; + Sys_PrintTerm("\nConsole input too long!\n"); + break; + } + } + + return NULL; +} + +void Sys_Sleep (unsigned long msecs) +{ + if (!msecs) + return; + else if (msecs > 1000) + msecs = 1000; + + usleep (msecs * 1000); +} + +void Sys_SendKeyEvents (void) +{ + IN_SendKeyEvents(); +} + +char *Sys_GetClipboardData (void) +{ + return NULL; +} + +static int Sys_GetBasedir (char *argv0, char *dst, size_t dstsize) +{ + char *tmp; + + if (getcwd(dst, dstsize - 1) == NULL) + return -1; + + tmp = dst; + while (*tmp != 0) + tmp++; + while (*tmp == 0 && tmp != dst) + { + --tmp; + if (tmp != dst && *tmp == '/') + *tmp = 0; + } + + return 0; +} + +#if DO_USERDIRS +static int Sys_GetUserdir (char *dst, size_t dstsize) +{ + return 1; +} +#endif /* DO_USERDIRS */ + +static void Sys_CheckSDL (void) +{ +#if defined(SDLQUAKE) + const SDL_version *sdl_version; + + sdl_version = SDL_Linked_Version(); + Sys_Printf("Found SDL version %i.%i.%i\n",sdl_version->major,sdl_version->minor,sdl_version->patch); + if (SDL_VERSIONNUM(sdl_version->major,sdl_version->minor,sdl_version->patch) < SDL_REQUIREDVERSION) + { /*reject running under SDL versions older than what is stated in sdl_inc.h */ + Sys_Error("You need at least v%d.%d.%d of SDL to run this game.", SDL_MIN_X,SDL_MIN_Y,SDL_MIN_Z); + } +# if defined(SDL_NEW_VERSION_REJECT) + if (SDL_VERSIONNUM(sdl_version->major,sdl_version->minor,sdl_version->patch) >= SDL_NEW_VERSION_REJECT) + { /*reject running under SDL versions newer than what is stated in sdl_inc.h */ + Sys_Error("Your version of SDL library is incompatible with me.\n" + "You need a library version in the line of %d.%d.%d\n", SDL_MIN_X,SDL_MIN_Y,SDL_MIN_Z); + } +# endif /* SDL_NEW_VERSION_REJECT */ +#endif /* SDLQUAKE */ +} + +static void PrintVersion (void) +{ +#if HOT_VERSION_BETA + Sys_Printf ("Hammer of Thyrion, %s-%s (%s) pre-release\n", HOT_VERSION_STR, HOT_VERSION_BETA_STR, HOT_VERSION_REL_DATE); +#else + Sys_Printf ("Hammer of Thyrion, release %s (%s)\n", HOT_VERSION_STR, HOT_VERSION_REL_DATE); +#endif + Sys_Printf ("running on %s engine %4.2f (%s)\n", ENGINE_NAME, ENGINE_VERSION, PLATFORM_STRING); + Sys_Printf ("More info / sending bug reports: http://uhexen2.sourceforge.net\n"); +} + +#include "snd_sys.h" +static const char *help_strings[] = { + " [-v | --version] Display version information", +#ifndef DEMOBUILD +# if defined(H2MP) + " [-noportals] Disable the mission pack support", +# else + " [-portals | -h2mp ] Run the Portal of Praevus mission pack", +# endif +#endif +#ifdef GLQUAKE + " [-bpp] Depth for GL fullscreen mode", + " [-vsync] Enable sync with monitor refresh", + " [-g | -gllibrary] Select 3D rendering library", + " [-fsaa N] Enable N sample antialiasing", + " [-paltex] Enable 8-bit textures", + " [-nomtex] Disable multitexture detection/usage", +#endif +#if !defined(_NO_SOUND) +#if SOUND_NUMDRIVERS + " [-s | -nosound] Run the game without sound", +#endif +#if (SOUND_NUMDRIVERS > 1) +#if HAVE_OSS_SOUND + " [-sndoss] Use OSS sound", +#endif +#if HAVE_ALSA_SOUND + " [-sndalsa] Use ALSA sound (alsa > 1.0.1)", +#endif +#if HAVE_SUN_SOUND + " [-sndsun | -sndbsd] Use SUN / BSD sound", +#endif +#if HAVE_SDL_SOUND + " [-sndsdl] Use SDL sound", +#endif +#endif /* SOUND_NUMDRIVERS */ +#endif /* _NO_SOUND */ + " [-nomouse] Disable mouse usage", + " [-listen N] Enable multiplayer with max N players", + " [-heapsize Bytes] Heapsize (memory to allocate)", + NULL +}; + +static void PrintHelp(const char *name) +{ + int i = 0; + + Sys_Printf ("Usage: %s [options]\n", name); + while (help_strings[i]) + { + Sys_PrintTerm (help_strings[i]); + Sys_PrintTerm ("\n"); + i++; + } + Sys_PrintTerm ("\n"); +} + +/* =============================================================================== + MAIN + =============================================================================== */ + +static quakeparms_t parms; +static char cwd[MAX_OSPATH]; +#if DO_USERDIRS +static char userdir[MAX_OSPATH]; +#endif +#if defined(SDLQUAKE) +static Uint8 appState; +#endif + +} /* extern "C" */ + +int hexen_main (int argc, char **argv) +{ + int i; + double time, oldtime, newtime; + + PrintVersion(); + + if (argc > 1) + { + for (i = 1; i < argc; i++) + { + if ( !(strcmp(argv[i], "-v")) || !(strcmp(argv[i], "-version" )) || + !(strcmp(argv[i], "--version")) ) + { + exit(0); + } + else if ( !(strcmp(argv[i], "-h")) || !(strcmp(argv[i], "-help" )) || + !(strcmp(argv[i], "-?")) || !(strcmp(argv[i], "--help")) ) + { + PrintHelp(argv[0]); + exit (0); + } + } + } + + memset (cwd, 0, sizeof(cwd)); + if (Sys_GetBasedir(argv[0], cwd, sizeof(cwd)) != 0) + Sys_Error ("Couldn't determine current directory"); + + /* initialize the host params */ + memset (&parms, 0, sizeof(parms)); + parms.basedir = cwd; + parms.userdir = cwd; + parms.argc = argc; + parms.argv = argv; + host_parms = &parms; + + LOG_Init (&parms); + + Sys_Printf("basedir is: %s\n", parms.basedir); + Sys_Printf("userdir is: %s\n", parms.userdir); + + COM_ValidateByteorder (); + + isDedicated = (COM_CheckParm ("-dedicated") != 0); + + Sys_CheckSDL (); + + if (isDedicated) + parms.memsize = MIN_MEM_ALLOC; + else + parms.memsize = STD_MEM_ALLOC; + + i = COM_CheckParm ("-heapsize"); + if (i && i < com_argc-1) + { + parms.memsize = atoi (com_argv[i+1]) * 1024; + + if ((parms.memsize > MAX_MEM_ALLOC) && !(COM_CheckParm ("-forcemem"))) + { + Sys_Printf ("Requested memory (%d Mb) too large, using the default maximum.\n", parms.memsize/(1024*1024)); + Sys_Printf ("If you are sure, use the -forcemem switch.\n"); + parms.memsize = MAX_MEM_ALLOC; + } + else if ((parms.memsize < MIN_MEM_ALLOC) && !(COM_CheckParm ("-forcemem"))) + { + Sys_Printf ("Requested memory (%d Mb) too little, using the default minimum.\n", parms.memsize/(1024*1024)); + Sys_Printf ("If you are sure, use the -forcemem switch.\n"); + parms.memsize = MIN_MEM_ALLOC; + } + } + + parms.membase = malloc (parms.memsize); + + if (!parms.membase) + Sys_Error ("Insufficient memory.\n"); + + Sys_Init (); + + Host_Init(); + + oldtime = Sys_DoubleTime (); + + /* main window message loop */ + while (1) + { +#if 0 + if (isDedicated) + { + newtime = Sys_DoubleTime (); + time = newtime - oldtime; + + while (time < sys_ticrate.value ) + { + usleep (1000); + newtime = Sys_DoubleTime (); + time = newtime - oldtime; + } + + Host_Frame (time); + oldtime = newtime; + } + else +#endif + { + appState = SDL_GetAppState(); + /* If we have no input focus at all, sleep a bit */ + if ( !(appState & (SDL_APPMOUSEFOCUS | SDL_APPINPUTFOCUS)) || cl.paused) + { + usleep (16000); + } + /* If we're minimised, sleep a bit more */ + if ( !(appState & SDL_APPACTIVE) ) + { + scr_skipupdate = 1; + usleep (32000); + } + else + { + scr_skipupdate = 0; + } + + newtime = Sys_DoubleTime (); + time = newtime - oldtime; + + Host_Frame (time); + + if (time < sys_throttle.value) + usleep (1000); + + oldtime = newtime; + } + } + + return 0; +} + +/* keep the noise down */ +/* x86 */ +extern "C" int _sigprocmask(int, const sigset_t*, sigset_t*) { return -1; } +/* arm */ +extern "C" int sigprocmask(int, const sigset_t*, sigset_t*) { return -1; } + +#include + +int main(int argc, char *argv[]) +{ + /* Hexen 2 needs lots of stack */ + Genode::Thread_base::myself()->stack_size(256 * 1024); + + return ::hexen_main(argc, argv); +} diff --git a/src/app/uhexen2/target.mk b/src/app/uhexen2/target.mk new file mode 100644 index 0000000..29a82e4 --- /dev/null +++ b/src/app/uhexen2/target.mk @@ -0,0 +1,126 @@ +# +# uhexen2 +# + +UHEXEN2_DIR = $(call select_from_ports,uhexen2)/src/app/uhexen2 + +TARGET = uhexen2 + +# softobjs +SRC_C = d_edge.c \ + d_fill.c \ + d_init.c \ + d_modech.c \ + d_part.c \ + d_polyse.c \ + d_scan.c \ + d_sky.c \ + d_sprite.c \ + d_surf.c \ + d_vars.c \ + d_zpoint.c \ + r_aclip.c \ + r_alias.c \ + r_bsp.c \ + r_draw.c \ + r_edge.c \ + r_efrag.c \ + r_light.c \ + r_main.c \ + r_misc.c \ + r_part.c \ + r_sky.c \ + r_sprite.c \ + r_surf.c \ + r_vars.c \ + screen.c \ + vid_sdl.c \ + draw.c \ + model.c + +SRC_C += bgmnull.c \ + midi_nul.c \ + cd_null.c + +SRC_C += snd_sdl.c \ + snd_sys.c \ + snd_mix.c \ + snd_dma.c \ + snd_mem.c \ + snd_codec.c \ + snd_wave.c + +# commonobjs +SRC_C += in_sdl.c \ + chase.c \ + cl_demo.c \ + cl_effect.c \ + cl_input.c \ + cl_inlude.c \ + cl_main.c \ + cl_parse.c \ + cl_string.c \ + cl_tent.c \ + cl_cmd.c \ + console.c \ + keys.c \ + menu.c \ + sbar.c \ + view.c \ + wad.c \ + cmd.c \ + q_endian.c \ + link_ops.c \ + sizebuf.c \ + strlcat.c \ + strlcpy.c \ + qsnprint.c \ + msg_io.c \ + common.c \ + debuglog.c \ + quakefs.c \ + crc.c \ + cvar.c \ + cfgfile.c \ + host.c \ + host_cmd.c \ + host_string.c \ + mathlib.c \ + pr_cmds.c \ + pr_edict.c \ + pr_exec.c \ + sv_effect.c \ + sv_main.c \ + sv_move.c \ + sv_phys.c \ + sv_user.c \ + world.c \ + zone.c \ + net_bsd.c \ + net_dgrm.c \ + net_loop.c \ + net_main.c \ + net_udp_genode.c + +SRC_CC = sys_genode.cc + + +INC_DIR += $(UHEXEN2_DIR)/engine/hexen2 +INC_DIR += $(UHEXEN2_DIR)/engine/h2shared +INC_DIR += $(UHEXEN2_DIR)/libs/common +INC_DIR += $(UHEXEN2_DIR)/common +INC_DIR += $(REP_DIR)/include/SDL + +CC_OPT += -ffast-math +CC_OPT += -DSDLQUAKE -D_NO_MIDIDRV -D_NO_CDAUDIO -DPARANOID + +CC_OPT += -DNO_ALSA_AUDIO -DNO_OSS_AUDIO -DNO_SUN_AUDIO + +CC_OPT += -DDEMOBUILD + +LIBS = libc libc_lwip lwip libm sdl sdl_mixer config_args + +vpath % $(UHEXEN2_DIR)/common +vpath % $(UHEXEN2_DIR)/engine/hexen2 +vpath % $(UHEXEN2_DIR)/engine/h2shared +vpath % $(UHEXEN2_DIR)/libs/common