/* Copyright (C) 2006-2007 Mark Olsen 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. */ #include #include #include #include #include #include #include #include #include "quakedef.h" #warning Find a better stack size int __stack = 4*1024*1024; struct Library *DynLoadBase; extern struct Library *VorbisFileBase; #ifndef CLIENTONLY qboolean isDedicated; #endif void Sys_RecentServer(char *command, char *target, char *title, char *desc) { } void Sys_Shutdown() { if(DynLoadBase) { CloseLibrary(DynLoadBase); DynLoadBase = 0; } if (VorbisFileBase) { CloseLibrary(VorbisFileBase); VorbisFileBase = 0; } } void Sys_Quit (void) { Host_Shutdown(); Sys_Shutdown(); exit(0); } static void ftevprintf(const char *fmt, va_list arg) { char buf[4096]; unsigned char *p; vsnprintf(buf, sizeof(buf), fmt, arg); for (p = (unsigned char *)buf; *p; p++) if ((*p > 128 || *p < 32) && *p != 10 && *p != 13 && *p != 9) printf("[%02x]", *p); else putc(*p, stdout); } void Sys_Printf(char *fmt, ...) { va_list arg; va_start(arg, fmt); ftevprintf(fmt, arg); va_end(arg); } void Sys_Error(const char *error, ...) { va_list arg; printf("Error: "); va_start(arg, error); ftevprintf(error, arg); va_end(arg); Host_Shutdown (); exit (1); } void Sys_Warn(char *warning, ...) { va_list arg; printf("Warning: "); va_start(arg, warning); ftevprintf(warning, arg); va_end(arg); } int Sys_DebugLog(char *file, char *fmt, ...) { va_list arg; char buf[4096]; BPTR fh; fh = Open(file, MODE_READWRITE); if (fh) { Seek(fh, OFFSET_END, 0); va_start(arg, fmt); vsnprintf(buf, sizeof(buf), fmt, arg); va_end(arg); Write(fh, buf, strlen(buf)); Close(fh); return 0; } return 1; } int secbase; unsigned int Sys_Milliseconds(void) { struct timeval tp; struct timezone tzp; gettimeofday(&tp, &tzp); if (!secbase) { secbase = tp.tv_sec; return tp.tv_usec/1000; } return (tp.tv_sec - secbase)*1000 + tp.tv_usec/1000; } double Sys_DoubleTime(void) { struct timeval tp; struct timezone tzp; gettimeofday(&tp, &tzp); if (!secbase) { secbase = tp.tv_sec; return tp.tv_usec/1000000.0; } return (tp.tv_sec - secbase) + tp.tv_usec/1000000.0; } /* FS stuff */ int Sys_FileTime(char *path) { BPTR lock; struct FileInfoBlock fib; int ret = -1; if (path[0] == '.' && path[1] == '/') path+= 2; lock = Lock(path, ACCESS_READ); if (lock) { if (Examine(lock, &fib)) { ret = ((fib.fib_Date.ds_Days+2922)*1440+fib.fib_Date.ds_Minute)*60+fib.fib_Date.ds_Tick/TICKS_PER_SECOND; } UnLock(lock); } return ret; } int Sys_EnumerateFiles(const char *gpath, const char *match, int (*func)(const char *, int, void *), void *parm) { char *pattern; char pattrans[256]; char finddir[256]; char findpattern[514]; char filename[256]; int i, j; BPTR lock; struct FileInfoBlock fib; int ret = false; snprintf(finddir, sizeof(finddir), "%s/%s", gpath, match); pattern = strrchr(finddir, '/'); if (pattern) { finddir[((unsigned int)(pattern-finddir))] = 0; pattern++; } for(i=0,j=0;i= 0) { ret = true; while(ExNext(lock, &fib)) { if (MatchPatternNoCase(findpattern, fib.fib_FileName)) { snprintf(filename, sizeof(filename), "%s%s", fib.fib_FileName, fib.fib_DirEntryType>=0?"/":""); if (func(filename, fib.fib_Size, parm) == 0) { ret = false; break; } } } } } UnLock(lock); } return ret; } void Sys_mkdir(char *path) { BPTR lock; if (path[0] == '.' && path[1] == '/') path+= 2; lock = CreateDir(path); if (lock) { UnLock(lock); } } qboolean Sys_remove(char *path) { if (path[0] == '.' && path[1] == '/') path+= 2; return DeleteFile(path); } qboolean Sys_Rename (char *oldfname, char *newfname) { return !rename(oldfname, newfname); } /* Quake 2 stuff */ static void *gamefile; void *Sys_GetGameAPI(void *parms) { int (*q2_so_init)(void); void (*q2_so_deinit)(void); void *(*GetGameAPI)(void *); void *ret; char *searchpath; char path[256]; searchpath = 0; while((searchpath = COM_NextPath(searchpath))) { snprintf(path, sizeof(path), "%s%sgameppc.so", searchpath[0]!='.'?searchpath:"", searchpath[0]&&searchpath[0]!='.'?"/":""); gamefile = dlopen(path, RTLD_NOW); if (gamefile) { q2_so_init = dlsym(gamefile, "q2_so_init"); q2_so_deinit = dlsym(gamefile, "q2_so_deinit"); if (q2_so_init && q2_so_init()) { GetGameAPI = dlsym(gamefile, "GetGameAPI"); if (GetGameAPI && (ret = GetGameAPI(parms))) { return ret; } if (q2_so_deinit) q2_so_deinit(); } dlclose(gamefile); gamefile = 0; } } return 0; } void Sys_UnloadGame(void) { void (*q2_so_deinit)(void); if (gamefile) { q2_so_deinit = dlsym(gamefile, "q2_so_deinit"); if (q2_so_deinit) q2_so_deinit(); dlclose(gamefile); gamefile = 0; } } void Sys_CloseLibrary(dllhandle_t *lib) { dlclose((void*)lib); } dllhandle_t *Sys_LoadLibrary(const char *name, dllfunction_t *funcs) { int i; dllhandle_t lib; lib = dlopen (name, RTLD_LAZY); if (!lib) return NULL; if (funcs) { for (i = 0; funcs[i].name; i++) { *funcs[i].funcptr = dlsym(lib, funcs[i].name); if (!*funcs[i].funcptr) break; } if (funcs[i].name) { Sys_CloseLibrary((dllhandle_t*)lib); lib = NULL; } } return (dllhandle_t*)lib; } void *Sys_GetAddressForName(dllhandle_t *module, const char *exportname) { if (!module) return NULL; return dlsym(module, exportname); } int main(int argc, char **argv) { double oldtime, newtime; quakeparms_t parms; int i; COM_InitArgv(argc, argv); TL_InitLanguages(); i = COM_CheckParm("-mem"); if (i && i < com_argc) parms.memsize = atoi(com_argv[i+1])*1024*1024; else parms.memsize = 16*1024*1024; parms.basedir = ""; parms.argc = argc; parms.argv = argv; parms.membase = malloc(parms.memsize); if (parms.membase == 0) Sys_Error("Can't allocated %d bytes\n", parms.memsize); DynLoadBase = OpenLibrary("dynload.library", 0); Host_Init(&parms); oldtime = Sys_DoubleTime (); while(!(SetSignal(0, 0)&SIGBREAKF_CTRL_C)) { double sleeptime; newtime = Sys_DoubleTime (); sleeptime = Host_Frame(newtime - oldtime); oldtime = newtime; Sys_Sleep(sleeptime); } } void Sys_Init() { } char *Sys_GetClipboard(void) { return 0; } void Sys_CloseClipboard(char *buf) { } void Sys_SaveClipboard(char *text) { } qboolean Sys_InitTerminal() { return false; } void Sys_CloseTerminal() { } char *Sys_ConsoleInput() { return 0; } void Sys_ServerActivity(void) { } qboolean Sys_GetDesktopParameters(int *width, int *height, int *bpp, int *refreshrate) { return false; } qboolean Sys_RandomBytes(qbyte *string, int len) { while(len--) *string++ = RandomByte(); return true; } #ifdef MULTITHREAD /* Everything here is stubbed because I don't know MorphOS */ /* Thread creation calls */ void *Sys_CreateThread(int (*func)(void *), void *args, int priority, int stacksize) { return NULL; } void Sys_WaitOnThread(void *thread) {} /* Mutex calls */ void *Sys_CreateMutex(void) { return NULL; } qboolean Sys_TryLockMutex(void *mutex) { return false; } qboolean Sys_LockMutex(void *mutex) { return false; } qboolean Sys_UnlockMutex(void *mutex) { return false; } void Sys_DestroyMutex(void *mutex) {} /* Conditional wait calls */ void *Sys_CreateConditional(void) { return NULL; } qboolean Sys_LockConditional(void *condv) { return false; } qboolean Sys_UnlockConditional(void *condv) { return false; } qboolean Sys_ConditionWait(void *condv) { return false; } qboolean Sys_ConditionSignal(void *condv) { return false; } qboolean Sys_ConditionBroadcast(void *condv) { return false; } void Sys_DestroyConditional(void *condv) {} #endif void Sys_Sleep(double seconds) {}