From 6a0928281cfa49353dca28c94cd70e9fad81c29e Mon Sep 17 00:00:00 2001 From: g-cont Date: Thu, 22 Nov 2007 00:00:00 +0300 Subject: [PATCH] 22 Nov 2007 --- changelog.log | 3 + engine/client/cl_cin.c | 16 +- engine/client/cl_main.c | 18 +- engine/client/client.h | 4 +- engine/common/progsvm.h | 2 +- engine/common/vm_cmds.c | 214 ++++++++++++++++--- engine/common/vm_cmds.h | 7 +- engine/common/vm_edict.c | 42 ++-- engine/engine.dsp | 4 + engine/engine.h | 11 +- engine/host.c | 25 ++- engine/menu.c | 12 +- engine/qmenu.h | 7 +- engine/server/sv_cmds.c | 3 +- engine/server/sv_init.c | 5 +- engine/server/sv_main.c | 10 +- engine/server/sv_utils.c | 1 - engine/snd_dma.c | 2 +- engine/system.c | 28 ++- engine/ui_cmds.c | 427 +++++++++++++++++++++++++++++++++++++ engine/ui_main.c | 177 +++------------ engine/uimenu.h | 9 +- launch/common/console.c | 4 +- launch/common/filesystem.c | 40 ++++ launch/common/system.c | 36 ++-- launch/launch.h | 2 + public/ref_stdlib.h | 1 + public/ref_system.h | 1 + 28 files changed, 850 insertions(+), 261 deletions(-) create mode 100644 engine/ui_cmds.c diff --git a/changelog.log b/changelog.log index 432591c1..a401d200 100644 --- a/changelog.log +++ b/changelog.log @@ -26,10 +26,13 @@ scroll = visible_offset Имплементация нового меню 1. перенести все ресурсы из версии 0.4 +2. разобраться с short->word конверсией VM //================================================== // то, что уже готово //================================================== ++добавлен Sys_Crash ++исправлен баг с рекурсивным вызовом Sys_Error и Host_Error +имплементированы простейшие сохранялки +qcclib создает progs.src +исправлен баг в stdlib.c diff --git a/engine/client/cl_cin.c b/engine/client/cl_cin.c index a566bdfa..8ed0422c 100644 --- a/engine/client/cl_cin.c +++ b/engine/client/cl_cin.c @@ -1343,7 +1343,7 @@ void CIN_DrawCinematic( void ) Cinematic user interface ============================================================================== */ -void SCR_PlayCinematic( char *name, int bits ) +bool SCR_PlayCinematic( char *name, int bits ) { if (cls.state == ca_cinematic) SCR_StopCinematic(); @@ -1351,7 +1351,11 @@ void SCR_PlayCinematic( char *name, int bits ) S_StopAllSounds(); if (CIN_PlayCinematic( name, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, bits )) + { SCR_RunCinematic(); // load first frame + return true; + } + return false; } void SCR_DrawCinematic( void ) @@ -1370,6 +1374,16 @@ void SCR_StopCinematic( void ) S_StopAllSounds(); } +void SCR_ResetCinematic( void ) +{ + RoQReset(); +} + +int SCR_GetCinematicState( void ) +{ + return cinTable.status; +} + /* ==================== SCR_FinishCinematic diff --git a/engine/client/cl_main.c b/engine/client/cl_main.c index 3bfec0d7..8dc45af1 100644 --- a/engine/client/cl_main.c +++ b/engine/client/cl_main.c @@ -450,20 +450,18 @@ void CL_Connect_f (void) return; } - if (Host_ServerState ()) - { // if running a local server, kill it and reissue - SV_Shutdown (va("Server quit\n", msg), false); - } - else - { - CL_Disconnect (); + if(Host_ServerState()) + { + // if running a local server, kill it and reissue + std.strncpy( host.finalmsg, "Server quit\n", MAX_STRING ); + SV_Shutdown( false ); } + else CL_Disconnect(); server = Cmd_Argv (1); - NET_Config (true); // allow remote - - CL_Disconnect (); + NET_Config( true ); // allow remote + CL_Disconnect(); cls.state = ca_connecting; strncpy (cls.servername, server, sizeof(cls.servername)-1); diff --git a/engine/client/client.h b/engine/client/client.h index 4051aa4f..54118c6b 100644 --- a/engine/client/client.h +++ b/engine/client/client.h @@ -649,10 +649,12 @@ int Key_GetKey( char *binding ); // // cl_cin.c // -void SCR_PlayCinematic( char *name, int bits ); +bool SCR_PlayCinematic( char *name, int bits ); void SCR_DrawCinematic( void ); void SCR_RunCinematic( void ); void SCR_StopCinematic( void ); +void SCR_ResetCinematic( void ); +int SCR_GetCinematicState( void ); void SCR_FinishCinematic( void ); #endif//CLIENT_H \ No newline at end of file diff --git a/engine/common/progsvm.h b/engine/common/progsvm.h index 86ae00ab..68157286 100644 --- a/engine/common/progsvm.h +++ b/engine/common/progsvm.h @@ -155,7 +155,7 @@ typedef struct prvm_prog_s //============================================================================ // until this point everything also exists (with the pr_ prefix) in the old vm - file_t *openfiles[PRVM_MAX_OPENFILES]; + vfile_t *openfiles[PRVM_MAX_OPENFILES]; search_t *opensearches[PRVM_MAX_OPENSEARCHES]; // copies of some vars that were former read from sv diff --git a/engine/common/vm_cmds.c b/engine/common/vm_cmds.c index 6f515e80..e97b6ba8 100644 --- a/engine/common/vm_cmds.c +++ b/engine/common/vm_cmds.c @@ -213,6 +213,23 @@ void VM_sprint( void ) SV_ClientPrintf (svs.clients+(num - 1), PRINT_HIGH, "%s", string ); } +/* +================= +VM_centerprint + +single print to the screen + +centerprint(clientent, value) +================= +*/ +void VM_centerprint( void ) +{ + char string[VM_STRINGTEMP_LENGTH]; + + VM_VarString(0, string, sizeof(string)); + CG_CenterPrint( string, SCREEN_HEIGHT/2, BIGCHAR_WIDTH ); +} + void VM_servercmd (void) { char string[VM_STRINGTEMP_LENGTH]; @@ -1376,18 +1393,23 @@ void VM_Files_Init(void) prog->openfiles[i] = NULL; } -void VM_Files_CloseAll(void) +void VM_Files_CloseAll( void ) { - int i; - for (i = 0;i < PRVM_MAX_OPENFILES;i++) + int i; + file_t *f; + + for(i = 0; i < PRVM_MAX_OPENFILES; i++) { if (prog->openfiles[i]) - FS_Close(prog->openfiles[i]); + { + f = VFS_Close(prog->openfiles[i]); + FS_Close( f ); // close real file too + } prog->openfiles[i] = NULL; } } -file_t *VM_GetFileHandle( int index ) +vfile_t *VM_GetFileHandle( int index ) { if (index < 0 || index >= PRVM_MAX_OPENFILES) { @@ -1412,20 +1434,21 @@ float fopen(string filename, float mode) // float(string filename, float mode) fopen = #110; // opens a file inside quake/gamedir/data/ (mode is FILE_READ, FILE_APPEND, or FILE_WRITE), // returns fhandle >= 0 if successful, or fhandle < 0 if unable to open file for any reason -void VM_fopen(void) +void VM_fopen( void ) { - int filenum, mode; - const char *modestring, *filename; + int filenum, mode; + const char *modestring, *filename; - VM_SAFEPARMCOUNT(2,VM_fopen); + VM_SAFEPARMCOUNT(2, VM_fopen); - for (filenum = 0;filenum < PRVM_MAX_OPENFILES;filenum++) + for (filenum = 0; filenum < PRVM_MAX_OPENFILES; filenum++) if (prog->openfiles[filenum] == NULL) break; + if (filenum >= PRVM_MAX_OPENFILES) { PRVM_G_FLOAT(OFS_RETURN) = -2; - VM_Warning("VM_fopen: %s ran out of file handles (%i)\n", PRVM_NAME, PRVM_MAX_OPENFILES); + VM_Warning("VM_fopen: %s ran out of file handles(%i)\n", PRVM_NAME, PRVM_MAX_OPENFILES); return; } mode = (int)PRVM_G_FLOAT(OFS_PARM1); @@ -1440,27 +1463,30 @@ void VM_fopen(void) case 2: // FILE_WRITE modestring = "wb"; break; + case 3: // FILE_WRITE_DEFLATED + modestring = "wz"; + break; default: PRVM_G_FLOAT(OFS_RETURN) = -3; - VM_Warning("VM_fopen: %s: no such mode %i (valid: 0 = read, 1 = append, 2 = write)\n", PRVM_NAME, mode); + VM_Warning("VM_fopen: %s: no such mode %i (valid: 0 = read, 1 = append, 2 = write, 3 = deflate)\n", PRVM_NAME, mode); return; } filename = PRVM_G_STRING(OFS_PARM0); - prog->openfiles[filenum] = FS_Open(va("data/%s", filename), modestring ); + prog->openfiles[filenum] = VFS_Open(FS_Open(va("temp/%s", filename), modestring), modestring ); if (prog->openfiles[filenum] == NULL && mode == 0) - prog->openfiles[filenum] = FS_Open(va("%s", filename), modestring ); + prog->openfiles[filenum] = VFS_Open(FS_Open(va("%s", filename), modestring), modestring ); if (prog->openfiles[filenum] == NULL) { PRVM_G_FLOAT(OFS_RETURN) = -1; - if (host.developer >= D_WARN) + if(host.developer >= D_WARN) VM_Warning("VM_fopen: %s: %s mode %s failed\n", PRVM_NAME, filename, modestring); } else { PRVM_G_FLOAT(OFS_RETURN) = filenum; - if (host.developer >= D_WARN) + if(host.developer >= D_WARN) Msg("VM_fopen: %s: %s mode %s opened as #%i\n", PRVM_NAME, filename, modestring, filenum); } } @@ -1473,7 +1499,7 @@ fclose(float fhandle) ========= */ //void(float fhandle) fclose = #111; // closes a file -void VM_fclose(void) +void VM_fclose( void ) { int filenum; @@ -1490,10 +1516,12 @@ void VM_fclose(void) VM_Warning("VM_fclose: no such file handle %i (or file has been closed) in %s\n", filenum, PRVM_NAME); return; } - FS_Close(prog->openfiles[filenum]); + FS_Close(VFS_Close(prog->openfiles[filenum])); prog->openfiles[filenum] = NULL; if (host.developer >= D_WARN) + { Msg("VM_fclose: %s: #%i closed\n", PRVM_NAME, filenum); + } } /* @@ -1524,7 +1552,7 @@ void VM_fgets(void) return; } - c = FS_Gets (prog->openfiles[filenum], string, VM_STRINGTEMP_LENGTH ); + c = VFS_Gets(prog->openfiles[filenum], string, VM_STRINGTEMP_LENGTH ); if (host.developer >= D_WARN) Msg("fgets: %s: %s\n", PRVM_NAME, string); @@ -1546,7 +1574,7 @@ void VM_fputs(void) char string[VM_STRINGTEMP_LENGTH]; int filenum; - VM_SAFEPARMCOUNT(2,VM_fputs); + VM_SAFEPARMCOUNT(2, VM_fputs); filenum = (int)PRVM_G_FLOAT(OFS_PARM0); if (filenum < 0 || filenum >= PRVM_MAX_OPENFILES) @@ -1560,10 +1588,8 @@ void VM_fputs(void) return; } VM_VarString(1, string, sizeof(string)); - if ((stringlength = (int)strlen(string))) - FS_Write(prog->openfiles[filenum], string, stringlength); - if (host.developer >= D_WARN) - Msg("fputs: %s: %s\n", PRVM_NAME, string); + if ((stringlength = (int)strlen(string))) VFS_Write(prog->openfiles[filenum], string, stringlength); + if (host.developer >= D_WARN) Msg("fputs: %s: %s\n", PRVM_NAME, string); } /* @@ -1689,7 +1715,7 @@ void VM_allocstring(void) char string[VM_STRINGTEMP_LENGTH]; size_t alloclen; - VM_SAFEPARMCOUNT(1,VM_strzone); + VM_SAFEPARMCOUNT(1, VM_allocstring); VM_VarString(0, string, sizeof(string)); alloclen = strlen(string) + 1; @@ -1709,7 +1735,7 @@ void FreeString(string s) */ void VM_freestring(void) { - VM_SAFEPARMCOUNT(1,VM_strunzone); + VM_SAFEPARMCOUNT(1, VM_freestring); PRVM_FreeString(PRVM_G_INT(OFS_PARM0)); } @@ -1840,6 +1866,20 @@ void VM_clientcount(void) PRVM_G_FLOAT(OFS_RETURN) = host.maxclients; } +/* +========= +VM_clientstate + +float clientstate() +========= +*/ +void VM_clientstate(void) +{ + VM_SAFEPARMCOUNT(0,VM_clientstate); + + PRVM_G_FLOAT(OFS_RETURN) = cls.state; +} + /* ========= VM_getmousepos @@ -1850,7 +1890,7 @@ vector getmousepos() void VM_getmousepos(void) { - VM_SAFEPARMCOUNT(0,VM_getmousepos); + VM_SAFEPARMCOUNT(0, VM_getmousepos); PRVM_G_VECTOR(OFS_RETURN)[0] = mouse_x; PRVM_G_VECTOR(OFS_RETURN)[1] = mouse_y; @@ -2177,6 +2217,38 @@ void VM_precache_pic(void) re->RegisterPic((char *)s); //may return empty frame } +/* +========= +VM_drawcharacter + +float drawcharacter(vector position, float character, vector scale, vector rgb, float alpha, float flag) +========= +*/ +void VM_drawcharacter(void) +{ + float *pos, *rgb; + char character; + VM_SAFEPARMCOUNT(3, VM_drawcharacter); + + character = (char)PRVM_G_FLOAT(OFS_PARM1); + if(character == 0) + { + PRVM_G_FLOAT(OFS_RETURN) = -1; + VM_Warning("VM_drawcharacter: %s passed null character !\n", PRVM_NAME); + return; + } + + pos = PRVM_G_VECTOR(OFS_PARM0); + rgb = PRVM_G_VECTOR(OFS_PARM3); + + if(pos[2]) Msg("VM_drawcharacter: z value from \"pos\" discarded\n" ); + + re->SetColor( GetRGBA(rgb[0], rgb[1], rgb[2], 1.0f)); + SCR_DrawSmallChar( pos[0], pos[1], character ); + re->SetColor( NULL ); + PRVM_G_FLOAT(OFS_RETURN) = 1; +} + /* ========= VM_drawstring @@ -2208,6 +2280,32 @@ void VM_drawstring(void) SCR_DrawBigString( pos[0], pos[1], string, alpha ); PRVM_G_FLOAT(OFS_RETURN) = 1; } + +/* +========= +VM_getimagesize + +vector getimagesize(string pic) +========= +*/ +void VM_getimagesize(void) +{ + const char *p; + int w, h; + + VM_SAFEPARMCOUNT(1, VM_getimagesize); + p = PRVM_G_STRING(OFS_PARM0); + + if(!p) PRVM_ERROR("VM_getimagepos: %s passed null picture name !", PRVM_NAME); + + VM_CheckEmptyString(p); + re->DrawGetPicSize( &w, &h, (char *)p ); + + PRVM_G_VECTOR(OFS_RETURN)[0] = w; + PRVM_G_VECTOR(OFS_RETURN)[1] = h; + PRVM_G_VECTOR(OFS_RETURN)[2] = 0; +} + /* ========= VM_drawpic @@ -2269,6 +2367,68 @@ void VM_drawfill(void) PRVM_G_FLOAT(OFS_RETURN) = 1; } +/* +======================== +VM_cin_open + +float cin_open(string name, float bits) +======================== +*/ +void VM_cin_open( void ) +{ + const char *name; + int flags; + + VM_SAFEPARMCOUNT( 2, VM_cin_open ); + + name = PRVM_G_STRING( OFS_PARM0 ); + flags = (int)PRVM_G_FLOAT( OFS_PARM1 ); + + VM_CheckEmptyString( name ); + + if(SCR_PlayCinematic( (char *)name, flags )) + PRVM_G_FLOAT( OFS_RETURN ) = 1; + else PRVM_G_FLOAT( OFS_RETURN ) = 0; +} + +/* +======================== +VM_cin_close + +void cin_close( void ) +======================== +*/ +void VM_cin_close( void ) +{ + VM_SAFEPARMCOUNT( 0, VM_cin_close ); + SCR_StopCinematic(); +} + +/* +======================== +VM_cin_getstate + +float cin_getstate(void) +======================== +*/ +void VM_cin_getstate( void ) +{ + VM_SAFEPARMCOUNT( 0, VM_cin_getstate ); + PRVM_G_FLOAT( OFS_RETURN ) = SCR_GetCinematicState(); +} + +/* +======================== +VM_cin_restart + +void cin_restart(void) +======================== +*/ +void VM_cin_restart( void ) +{ + SCR_ResetCinematic(); +} + /* ========= VM_keynumtostring diff --git a/engine/common/vm_cmds.h b/engine/common/vm_cmds.h index c2d98213..c1623610 100644 --- a/engine/common/vm_cmds.h +++ b/engine/common/vm_cmds.h @@ -201,6 +201,7 @@ void VM_objerror (void); void VM_print (void); void VM_bprint (void); void VM_sprint (void); +void VM_centerprint(void); void VM_normalize (void); void VM_veclength (void); void VM_vectoyaw (void); @@ -266,7 +267,7 @@ void VM_fgets(void); void VM_fputs(void); // used by M_WriteToFile // should be only called from a builtin -file_t *VM_GetFileHandle( int index ); +vfile_t *VM_GetFileHandle( int index ); void VM_strlen(void); void VM_strcat(void); @@ -283,6 +284,7 @@ void VM_argv (void); void VM_isserver(void); void VM_clientcount(void); +void VM_clientstate(void); void VM_getmousepos(void); void VM_gettime(void); void VM_loadfromdata(void); @@ -297,6 +299,7 @@ void VM_search_getfilename(void); void VM_chr(void); void VM_iscachedpic(void); void VM_precache_pic(void); +void VM_drawcharacter(void); void VM_drawstring(void); void VM_drawpic(void); void VM_drawfill(void); @@ -313,11 +316,9 @@ void VM_stringtokeynum (void); void VM_cin_open( void ); void VM_cin_close( void ); -void VM_cin_setstate( void ); void VM_cin_getstate( void ); void VM_cin_restart( void ); -void VM_drawline (void); void VM_R_PolygonBegin (void); void VM_R_PolygonVertex (void); void VM_R_PolygonEnd (void); diff --git a/engine/common/vm_edict.c b/engine/common/vm_edict.c index dd0cb946..cbf03ce1 100644 --- a/engine/common/vm_edict.c +++ b/engine/common/vm_edict.c @@ -1295,15 +1295,16 @@ void PRVM_LoadProgs (const char *filename, int numedfunc, char **ed_func, int nu } prog->progs = (dprograms_t *)FS_LoadFile(va("vprogs/%s", filename ), &filesize); + if (prog->progs == NULL || filesize < (fs_offset_t)sizeof(dprograms_t)) - PRVM_ERROR ("PRVM_LoadProgs: couldn't load %s for %s", filename, PRVM_NAME); + PRVM_ERROR("PRVM_LoadProgs: couldn't load %s for %s\n", filename, PRVM_NAME); MsgDev(D_INFO, "%s programs occupy %iK.\n", PRVM_NAME, filesize/1024); prog->filecrc = CRC_Block((unsigned char *)prog->progs, filesize); // byte swap the header for (i = 0; i < (int)sizeof(*prog->progs)/4; i++) ((int *)prog->progs)[i] = LittleLong(((int *)prog->progs)[i]); - + switch( prog->progs->version ) { case QPROGS_VERSION: @@ -1320,14 +1321,16 @@ void PRVM_LoadProgs (const char *filename, int numedfunc, char **ed_func, int nu PRVM_ERROR ("%s: %s has wrong version number (%i should be %i)", PRVM_NAME, filename, prog->progs->version, VPROGS_VERSION); break; } - + // try to recognize progs.dat by crc switch(prog->progs->crc) { case PROG_CRC_SERVER: break; + case 10020: + break; default: - PRVM_ERROR ("%s: %s system vars have been modified, progdefs.h is out of date", PRVM_NAME, filename); + PRVM_ERROR("%s: %s system vars have been modified, progdefs.h is out of date", PRVM_NAME, filename); break; } MsgDev(D_INFO, "Loading %s [CRC %d]\n", filename, prog->progs->crc ); @@ -1341,8 +1344,8 @@ void PRVM_LoadProgs (const char *filename, int numedfunc, char **ed_func, int nu prog->globals.gp = (float *)((byte *)prog->progs + prog->progs->ofs_globals); // debug info - if (prog->progs->ofslinenums) prog->linenums = (int *)((byte *)prog->progs + prog->progs->ofslinenums); - if (prog->progs->ofs_types) prog->types = (type_t *)((byte *)prog->progs + prog->progs->ofs_types); + if(prog->progs->ofslinenums) prog->linenums = (int *)((byte *)prog->progs + prog->progs->ofslinenums); + if(prog->progs->ofs_types) prog->types = (type_t *)((byte *)prog->progs + prog->progs->ofs_types); // decompress progs if needed if (prog->progs->blockscompressed & COMP_STATEMENTS) @@ -1554,11 +1557,11 @@ void PRVM_LoadProgs (const char *filename, int numedfunc, char **ed_func, int nu { case OP_IF: case OP_IFNOT: - if ((word) st->a >= prog->progs->numglobals || (word)st->b + i < 0 || (word)st->b + i >= prog->progs->numstatements) + if((word)st->a >= prog->progs->numglobals || (word)st->b + i < 0 || (word)st->b + i >= prog->progs->numstatements) PRVM_ERROR("PRVM_LoadProgs: out of bounds IF/IFNOT (statement %d) in %s", i, PRVM_NAME); break; case OP_GOTO: - if (st->a + i < 0 || st->a + i >= prog->progs->numstatements) + if(st->a + i < 0 || st->a + i >= prog->progs->numstatements) PRVM_ERROR("PRVM_LoadProgs: out of bounds GOTO (statement %d) in %s", i, PRVM_NAME); break; // global global global @@ -1596,7 +1599,7 @@ void PRVM_LoadProgs (const char *filename, int numedfunc, char **ed_func, int nu case OP_LOAD_S: case OP_LOAD_FNC: case OP_LOAD_V: - if ((word) st->a >= prog->progs->numglobals || (word) st->b >= prog->progs->numglobals || (word)st->c >= prog->progs->numglobals) + if((word) st->a >= prog->progs->numglobals || (word) st->b >= prog->progs->numglobals || (word)st->c >= prog->progs->numglobals) PRVM_ERROR("PRVM_LoadProgs: out of bounds global index (statement %d)", i); break; // global none global @@ -1605,7 +1608,7 @@ void PRVM_LoadProgs (const char *filename, int numedfunc, char **ed_func, int nu case OP_NOT_S: case OP_NOT_FNC: case OP_NOT_ENT: - if ((word) st->a >= prog->progs->numglobals || (word) st->c >= prog->progs->numglobals) + if((word) st->a >= prog->progs->numglobals || (word) st->c >= prog->progs->numglobals) PRVM_ERROR("PRVM_LoadProgs: out of bounds global index (statement %d) in %s", i, PRVM_NAME); break; // 2 globals @@ -1623,7 +1626,7 @@ void PRVM_LoadProgs (const char *filename, int numedfunc, char **ed_func, int nu case OP_STOREP_V: case OP_STORE_V: if ((word) st->a >= prog->progs->numglobals || (word) st->b >= prog->progs->numglobals) - PRVM_ERROR("PRVM_LoadProgs: out of bounds global index (statement %d) in %s", i, PRVM_NAME); + Host_Error("PRVM_LoadProgs: out of bounds global index (statement %d) in %s", i, PRVM_NAME); break; // 1 global case OP_CALL0: @@ -1638,7 +1641,7 @@ void PRVM_LoadProgs (const char *filename, int numedfunc, char **ed_func, int nu case OP_DONE: case OP_RETURN: if ((word) st->a >= prog->progs->numglobals) - PRVM_ERROR("PRVM_LoadProgs: out of bounds global index (statement %d) in %s", i, PRVM_NAME); + Host_Error("PRVM_LoadProgs: out of bounds global index (statement %d) in %s", i, PRVM_NAME); break; default: MsgDev(D_NOTE, "PRVM_LoadProgs: unknown opcode %d at statement %d in %s\n", st->op, i, PRVM_NAME); @@ -1655,18 +1658,13 @@ void PRVM_LoadProgs (const char *filename, int numedfunc, char **ed_func, int nu // set flags & ddef_ts in prog prog->flag = 0; - prog->pev = PRVM_ED_FindGlobal("pev"); if( PRVM_ED_FindGlobal("time") && PRVM_ED_FindGlobal("time")->type & ev_float ) prog->time = &PRVM_G_FLOAT(PRVM_ED_FindGlobal("time")->ofs); - if(PRVM_ED_FindField ("chain")) - prog->flag |= PRVM_FE_CHAIN; - - if(PRVM_ED_FindField ("classname")) - prog->flag |= PRVM_FE_CLASSNAME; - + if(PRVM_ED_FindField ("chain")) prog->flag |= PRVM_FE_CHAIN; + if(PRVM_ED_FindField ("classname")) prog->flag |= PRVM_FE_CLASSNAME; if(PRVM_ED_FindField ("nextthink") && PRVM_ED_FindField ("frame") && PRVM_ED_FindField ("think") && prog->flag && prog->pev) prog->flag |= PRVM_OP_STATE; @@ -1925,16 +1923,16 @@ VM_error Abort the server with a game error =============== */ -void VM_Error (const char *fmt, ...) +void VM_Error(const char *fmt, ...) { char msg[1024]; va_list argptr; - va_start (argptr,fmt); + va_start (argptr, fmt); vsprintf (msg, fmt, argptr); va_end (argptr); - Msg ("Prvm error: %s", msg); + Host_Error("Prvm error: %s", msg); } /* diff --git a/engine/engine.dsp b/engine/engine.dsp index b64fca28..443a286a 100644 --- a/engine/engine.dsp +++ b/engine/engine.dsp @@ -298,6 +298,10 @@ SOURCE=.\system.c # End Source File # Begin Source File +SOURCE=.\ui_cmds.c +# End Source File +# Begin Source File + SOURCE=.\ui_main.c # End Source File # Begin Source File diff --git a/engine/engine.h b/engine/engine.h index ee878a71..a7e3bccd 100644 --- a/engine/engine.h +++ b/engine/engine.h @@ -61,6 +61,8 @@ typedef struct host_parm_s host_redirect_t rd; // remote console jmp_buf abortframe; // abort current frame + char finalmsg[MAX_STRING];// server shutdown final message + dword framecount; // global framecount double realtime; // host realtime float frametime; // frametime (default 0.1) @@ -121,6 +123,9 @@ void Host_DPrintf(int level, const char *fmt, ...); void Host_DWarnf( const char *fmt, ...); void Host_Error( const char *error, ... ); +// host dlls managment +void Host_FreeRender( void ); + // host cmds void Host_Error_f( void ); @@ -159,9 +164,9 @@ void CL_Drop (void); void CL_Shutdown (void); void CL_Frame (float time); -void SV_Init (void); -void SV_Shutdown (char *finalmsg, bool reconnect); -void SV_Frame (float time); +void SV_Init( void ); +void SV_Shutdown( bool reconnect ); +void SV_Frame( float time ); void SV_Transform( sv_edict_t *ed, vec3_t origin, vec3_t angles ); /* diff --git a/engine/host.c b/engine/host.c index 0fcd42d3..6ee4336c 100644 --- a/engine/host.c +++ b/engine/host.c @@ -512,19 +512,22 @@ void Host_Error( const char *error, ... ) vsprintf( hosterror1, error, argptr ); va_end( argptr ); - if (host.framecount < 3 || host.state == HOST_SHUTDOWN) + if( host.framecount < 3 || host.state == HOST_SHUTDOWN ) Sys_Error ("%s", hosterror1 ); else Host_Printf("Host_Error: %s", hosterror1); if(recursive) { - Msg("Host_Error: recursive %s", hosterror2); - Sys_Error ("%s", hosterror1); + Msg("Host_RecursiveError: %s", hosterror2 ); + Sys_Error ("%s", hosterror1 ); + return; // don't multiple executes } - recursive = true; - strncpy(hosterror2, hosterror1, sizeof(hosterror2)); - SV_Shutdown (va("Server crashed: %s", hosterror1), false); + recursive = true; + sprintf( host.finalmsg, "Server crashed: %s\n", hosterror1 ); + std.strncpy( host.finalmsg, "Server shutdown\n", MAX_STRING ); + + SV_Shutdown( false ); CL_Drop(); // drop clients recursive = false; @@ -624,15 +627,19 @@ void Host_Main( void ) oldtime = host.realtime; // main window message loop - while (host.type != HOST_OFFLINE) + while( host.type != HOST_OFFLINE ) { oldtime = newtime; newtime = Sys_DoubleTime(); time = newtime - oldtime; - Host_Frame( time ); // engine frame + // engine frame + Host_Frame( time ); } + + // prepare host to normal shutdown host.state = HOST_SHUTDOWN; + std.strncpy( host.finalmsg, "Server shutdown\n", MAX_STRING ); } @@ -643,7 +650,7 @@ Host_Shutdown */ void Host_Free( void ) { - SV_Shutdown("Server shutdown\n", false ); + SV_Shutdown( false ); CL_Shutdown(); Host_FreeRender(); NET_Shutdown(); diff --git a/engine/menu.c b/engine/menu.c index 2e56552e..cfca972a 100644 --- a/engine/menu.c +++ b/engine/menu.c @@ -18,11 +18,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include -#ifdef _WIN32 -#include -#endif -#include "client.h" -#include "qmenu.h" +#include "uimenu.h" static int m_main_cursor; @@ -613,7 +609,7 @@ static void M_UnbindCommand (char *command) } } -static void M_FindKeysForCommand(char *command, int *twokeys) +void M_FindKeysForCommand(char *command, int *twokeys) { int count; int j; @@ -3421,6 +3417,9 @@ void M_Init (void) Cmd_AddCommand ("menu_options", M_Menu_Options_f, "opens main options menu"); Cmd_AddCommand ("menu_keys", M_Menu_Keys_f, "opens redefinition keys menu" ); Cmd_AddCommand ("menu_quit", M_Menu_Quit_f, "show quit dialog" ); + Cmd_AddCommand ("menu_toggle", UI_ToggleMenu_f, "enable progs menu(test)" ); + + UI_Init(); } @@ -3434,6 +3433,7 @@ void M_Draw (void) if (cls.key_dest != key_menu) return; m_drawfunc(); + UI_Draw(); // delay playing the enter sound until after the // menu has been drawn, to avoid delay while diff --git a/engine/qmenu.h b/engine/qmenu.h index a81aeb67..79289c18 100644 --- a/engine/qmenu.h +++ b/engine/qmenu.h @@ -38,12 +38,12 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. typedef struct _tag_menuframework { - int x, y; + int x, y; int cursor; int nitems; - int nslots; - void *items[64]; + int nslots; + void *items[64]; const char *statusbar; @@ -116,6 +116,7 @@ bool Menu_SelectItem( menuframework_s *s ); void Menu_SetStatusBar( menuframework_s *s, const char *string ); void Menu_SlideItem( menuframework_s *s, int dir ); int Menu_TallySlots( menuframework_s *menu ); +void M_FindKeysForCommand(char *command, int *keys); void Menu_DrawString( int, int, const char * ); void Menu_DrawStringDark( int, int, const char * ); diff --git a/engine/server/sv_cmds.c b/engine/server/sv_cmds.c index 85d9503a..c69e8a6a 100644 --- a/engine/server/sv_cmds.c +++ b/engine/server/sv_cmds.c @@ -492,7 +492,8 @@ Kick everyone off, possibly in preparation for a new game void SV_KillServer_f (void) { if(!svs.initialized) return; - SV_Shutdown("Server was killed.\n", false); + std.strncpy( host.finalmsg, "Server was killed\n", MAX_STRING ); + SV_Shutdown( false ); NET_Config( false );// close network sockets } diff --git a/engine/server/sv_init.c b/engine/server/sv_init.c index d31d82cc..982371dd 100644 --- a/engine/server/sv_init.c +++ b/engine/server/sv_init.c @@ -257,10 +257,11 @@ void SV_InitGame (void) char i, idmaster[32]; edict_t *ent; - if (svs.initialized) + if( svs.initialized ) { // cause any connected clients to reconnect - SV_Shutdown("Server restarted\n", true); + std.strncpy( host.finalmsg, "Server restarted\n", MAX_STRING ); + SV_Shutdown( true ); } else { diff --git a/engine/server/sv_main.c b/engine/server/sv_main.c index 841e6078..2b202bca 100644 --- a/engine/server/sv_main.c +++ b/engine/server/sv_main.c @@ -1035,16 +1035,16 @@ Called when each game quits, before Sys_Quit or Sys_Error ================ */ -void SV_Shutdown (char *finalmsg, bool reconnect) +void SV_Shutdown( bool reconnect ) { // already freed if(host.state == HOST_ERROR) return; - MsgDev(D_NOTE, "SV_Shutdown: %s\n", finalmsg ); - if (svs.clients) SV_FinalMessage (finalmsg, reconnect); + MsgDev(D_NOTE, "SV_Shutdown: %s\n", host.finalmsg ); + if (svs.clients) SV_FinalMessage( host.finalmsg, reconnect); - Master_Shutdown (); - SV_ShutdownGameProgs (); + Master_Shutdown(); + SV_ShutdownGameProgs(); // free current level if (sv.demofile) FS_Close (sv.demofile); diff --git a/engine/server/sv_utils.c b/engine/server/sv_utils.c index 3e3750af..044cf1c7 100644 --- a/engine/server/sv_utils.c +++ b/engine/server/sv_utils.c @@ -1467,7 +1467,6 @@ void SV_ShutdownGameProgs (void) SV_VM_End(); if(!svs.gclients) return; - Mem_Free( svs.gclients ); svs.gclients = NULL; diff --git a/engine/snd_dma.c b/engine/snd_dma.c index e77f72af..b27f73c6 100644 --- a/engine/snd_dma.c +++ b/engine/snd_dma.c @@ -110,7 +110,7 @@ void S_Init( void ) s_show = Cvar_Get ("s_show", "0", CVAR_CHEAT); s_testsound = Cvar_Get ("s_testsound", "0", CVAR_CHEAT); - cv = Cvar_Get ("s_initsound", "1", 0); + cv = Cvar_Get("s_initsound", "1", 0); if ( !cv->value ) return; Cmd_AddCommand("play", S_Play_f, "playing a specified sound file" ); diff --git a/engine/system.c b/engine/system.c index 20cffc94..55c803ec 100644 --- a/engine/system.c +++ b/engine/system.c @@ -28,20 +28,34 @@ SYSTEM IO =============================================================================== */ + + void Sys_Error( const char *error, ... ) { - char syserror1[MAX_INPUTLINE]; + char errorstring[MAX_INPUTLINE]; + static bool recursive = false; va_list argptr; - + va_start( argptr, error ); - vsprintf( syserror1, error, argptr ); + std.vsprintf( errorstring, error, argptr ); va_end( argptr ); - SV_Shutdown(va("Server fatal crashed: %s\n", syserror1), false); - CL_Shutdown(); - host.state = HOST_ERROR; // lock shutdown state + // don't multiple executes + if( recursive ) + { + // echo to system console and log + Sys_Print( va("Sys_RecursiveError: %s\n", errorstring )); + return; + } - std.error("%s", syserror1); + recursive = true; + + // prepare host to close + sprintf( host.finalmsg, "Server fatal crashed: %s\n", errorstring ); + host.state = HOST_ERROR; // lock shutdown state + Host_FreeRender(); + + std.error("%s", errorstring ); } /* diff --git a/engine/ui_cmds.c b/engine/ui_cmds.c new file mode 100644 index 00000000..82e612ba --- /dev/null +++ b/engine/ui_cmds.c @@ -0,0 +1,427 @@ +//======================================================================= +// Copyright XashXT Group 2007 © +// ui_cmds.c - ui menu builtins +//======================================================================= + +#include "uimenu.h" + +/* +========= +VM_M_precache_file + +string precache_file(string) +========= +*/ +void VM_M_precache_file (void) +{ + // precache_file is only used to copy files with qcc, it does nothing + VM_SAFEPARMCOUNT(1, VM_precache_file); + PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0); +} + +/* +========= +VM_M_preache_error + +used instead of the other VM_precache_* functions in the builtin list +========= +*/ +void VM_M_precache_error (void) +{ + PRVM_ERROR("PF_Precache: Precache can only be done in spawn functions"); +} + +/* +========= +VM_M_precache_sound + +string precache_sound (string sample) +========= +*/ +void VM_M_precache_sound( void ) +{ + const char *s; + + VM_SAFEPARMCOUNT(1, VM_precache_sound); + + s = PRVM_G_STRING(OFS_PARM0); + PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0); + VM_CheckEmptyString( s ); + + if(!SV_SoundIndex( s )) + { + VM_Warning("VM_precache_sound: Failed to load %s for %s\n", s, PRVM_NAME); + return; + } +} + +/* +========= +VM_M_setmousetarget + +setmousetarget(float target) +========= +*/ +void VM_M_setmousetarget(void) +{ + VM_SAFEPARMCOUNT(1, VM_M_setmousetarget); + + Msg("VM_M_setmousetarget: called\n" ); +} + +/* +========= +VM_M_getmousetarget + +float getmousetarget +========= +*/ +void VM_M_getmousetarget(void) +{ + VM_SAFEPARMCOUNT(0, VM_M_getmousetarget); + + PRVM_G_FLOAT(OFS_RETURN) = 1; +} + + + +/* +========= +VM_M_setkeydest + +setkeydest(float dest) +========= +*/ +void VM_M_setkeydest(void) +{ + VM_SAFEPARMCOUNT(1, VM_M_setkeydest); + + switch((int)PRVM_G_FLOAT(OFS_PARM0)) + { + case 0: + // key_game + cls.key_dest = key_game; + break; + case 2: + // key_menu + cls.key_dest = key_menu; + break; + case 1: + // key_message + // cls.key_dest = key_message + // break; + default: + PRVM_ERROR("VM_M_setkeydest: wrong destination %f !", PRVM_G_FLOAT(OFS_PARM0)); + } +} + +/* +========= +VM_M_getkeydest + +float getkeydest +========= +*/ +void VM_M_getkeydest(void) +{ + VM_SAFEPARMCOUNT(0,VM_M_getkeydest); + + // key_game = 0, key_message = 1, key_menu = 2, unknown = 3 + switch(cls.key_dest) + { + case key_game: + PRVM_G_FLOAT(OFS_RETURN) = 0; + break; + case key_menu: + PRVM_G_FLOAT(OFS_RETURN) = 2; + break; + case key_message: + // not supported + // PRVM_G_FLOAT(OFS_RETURN) = 1; + // break; + default: + PRVM_G_FLOAT(OFS_RETURN) = 3; + } +} + +/* +========= +VM_M_callfunction + + callfunction(...,string function_name) +Extension: pass +========= +*/ +mfunction_t *PRVM_ED_FindFunction (const char *name); +void VM_M_callfunction(void) +{ + mfunction_t *func; + const char *s; + + if(prog->argc == 0) + PRVM_ERROR("VM_M_callfunction: 1 parameter is required !"); + + s = PRVM_G_STRING(OFS_PARM0 + (prog->argc - 1)); + + if(!s) + PRVM_ERROR("VM_M_callfunction: null string !"); + + VM_CheckEmptyString(s); + + func = PRVM_ED_FindFunction(s); + + if(!func) + PRVM_ERROR("VM_M_callfunciton: function %s not found !", s); + else if (func->first_statement < 0) + { + // negative statements are built in functions + int builtinnumber = -func->first_statement; + prog->xfunction->builtinsprofile++; + if (builtinnumber < prog->numbuiltins && prog->builtins[builtinnumber]) + prog->builtins[builtinnumber](); + else + PRVM_ERROR("No such builtin #%i in %s", builtinnumber, PRVM_NAME); + } + else if(func > 0) + { + prog->argc--; + PRVM_ExecuteProgram(func - prog->functions,""); + prog->argc++; + } +} + +/* +========= +VM_M_isfunction + +float isfunction(string function_name) +========= +*/ +mfunction_t *PRVM_ED_FindFunction (const char *name); +void VM_M_isfunction(void) +{ + mfunction_t *func; + const char *s; + + VM_SAFEPARMCOUNT(1, VM_M_isfunction); + + s = PRVM_G_STRING(OFS_PARM0); + + if(!s) + PRVM_ERROR("VM_M_isfunction: null string !"); + + VM_CheckEmptyString(s); + + func = PRVM_ED_FindFunction(s); + + if(!func) + PRVM_G_FLOAT(OFS_RETURN) = false; + else + PRVM_G_FLOAT(OFS_RETURN) = true; +} + +/* +========= +VM_M_writetofile + + writetofile(float fhandle, entity ent) +========= +*/ +void VM_M_writetofile(void) +{ + edict_t *ent; + vfile_t *file; + + VM_SAFEPARMCOUNT(2, VM_M_writetofile); + + file = VM_GetFileHandle( (int)PRVM_G_FLOAT(OFS_PARM0) ); + if( !file ) + { + VM_Warning("VM_M_writetofile: invalid or closed file handle\n"); + return; + } + + ent = PRVM_G_EDICT(OFS_PARM1); + if(ent->priv.ed->free) + { + VM_Warning("VM_M_writetofile: %s: entity %i is free !\n", PRVM_NAME, PRVM_EDICT_NUM(OFS_PARM1)); + return; + } + PRVM_ED_Write(file, ent); +} + +/* +========= +VM_M_findkeysforcommand + +string findkeysforcommand(string command) + +the returned string is an altstring +========= +*/ +void VM_M_findkeysforcommand(void) +{ + const char *cmd; + char *ret; + int keys[2]; + int i; + + VM_SAFEPARMCOUNT(1, VM_M_findkeysforcommand); + + cmd = PRVM_G_STRING(OFS_PARM0); + + VM_CheckEmptyString(cmd); + + (ret = VM_GetTempString())[0] = 0; + + M_FindKeysForCommand((char *)cmd, keys); + for(i = 0; i < 2; i++) std.strncat(ret, va(" \'%i\'", keys[i]), VM_STRINGTEMP_LENGTH); + PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(ret); +} + +prvm_builtin_t vm_m_builtins[] = +{ + 0, // to be consistent with the old vm + // common builtings (mostly) + VM_checkextension, + VM_error, + VM_objerror, + VM_print, + VM_bprint, + VM_sprint, + VM_centerprint, + VM_normalize, + VM_veclength, + VM_vectoyaw, // #10 + VM_vectoangles, + VM_random_float, + VM_localcmd, + VM_cvar, + VM_cvar_set, + VM_print, + VM_ftoa, + VM_fabs, + VM_vtoa, + VM_etos, // 20 + VM_atof, + VM_create, + VM_remove, + VM_find, + VM_findfloat, + VM_findchain, + VM_findchainfloat, + VM_M_precache_file, + VM_M_precache_sound, + VM_coredump, // 30 + VM_traceon, + VM_traceoff, + VM_eprint, + VM_rint, + VM_floor, + VM_ceil, + VM_nextent, + VM_sin, + VM_cos, + VM_sqrt, // 40 + VM_randomvec, + VM_registercvar, + VM_min, + VM_max, + VM_bound, + VM_pow, + VM_copyentity, + VM_fopen, + VM_fclose, + VM_fgets, // 50 + VM_fputs, + VM_strlen, + VM_strcat, + VM_substring, + VM_atov, + VM_allocstring, + VM_freestring, + VM_tokenize, + VM_argv, + VM_isserver, // 60 + VM_clientcount, + VM_clientstate, + VM_clientcmd, + VM_changelevel, + VM_localsound, + VM_getmousepos, + VM_gettime, + VM_loadfromdata, + VM_loadfromfile, + VM_modulo, // 70 + VM_cvar_string, + VM_crash, + VM_stackdump, // 73 + VM_search_begin, + VM_search_end, + VM_search_getsize, + VM_search_getfilename, // 77 + VM_chr, + VM_itof, + VM_ftoe, // 80 + VM_itof, // isString + VM_altstr_count, + VM_altstr_prepare, + VM_altstr_get, + VM_altstr_set, + VM_altstr_ins, + VM_findflags, + VM_findchainflags, + NULL, // 89 + NULL, // 90 + e10, // 100 + e100, // 200 + e100, // 300 + e100, // 400 + e10, // 410 + e10, // 420 + e10, // 430 + e10, // 440 + e10, // 450 + // draw functions + VM_iscachedpic, + VM_precache_pic, + NULL, + VM_drawcharacter, + VM_drawstring, + VM_drawpic, + VM_drawfill, + NULL, + NULL, + VM_getimagesize, // 460 + VM_cin_open, + VM_cin_close, + NULL, + VM_cin_getstate, + VM_cin_restart, // 465 + NULL, // 466 + NULL, + NULL, + NULL, + NULL, // 470 + e10, // 480 + e10, // 490 + e10, // 500 + e100, // 600 + // menu functions + VM_M_setkeydest, + VM_M_getkeydest, + VM_M_setmousetarget, + VM_M_getmousetarget, + VM_M_callfunction, + VM_M_writetofile, + VM_M_isfunction, + NULL, + VM_keynumtostring, + VM_M_findkeysforcommand, // 610 + NULL, + NULL, + VM_parseentitydata, + VM_stringtokeynum, // 614 +}; + +const int vm_m_numbuiltins = sizeof(vm_m_builtins) / sizeof(prvm_builtin_t); \ No newline at end of file diff --git a/engine/ui_main.c b/engine/ui_main.c index 6f2e5ebd..a655cec1 100644 --- a/engine/ui_main.c +++ b/engine/ui_main.c @@ -9,11 +9,11 @@ #define M_F_KEYDOWN "m_keydown" #define M_F_KEYUP "m_keyup" #define M_F_DRAW "m_draw" -// normal menu names (rest) #define M_F_TOGGLE "m_toggle" #define M_F_SHUTDOWN "m_shutdown" -static char *m_required_func[] = { +static char *m_required_func[] = +{ M_F_INIT, M_F_KEYDOWN, M_F_DRAW, @@ -21,69 +21,55 @@ M_F_TOGGLE, M_F_SHUTDOWN, }; -#ifdef NG_MENU -static bool m_displayed; -#endif - static int m_numrequiredfunc = sizeof(m_required_func) / sizeof(char*); static func_t m_draw, m_keydown; static mfunction_t *m_keyup; -void MR_SetRouting (bool forceold); - -void MP_Error(const char *format, ...) +void UI_Error(const char *format, ...) { - static bool processingError = false; - char errorstring[MAX_INPUTLINE]; - va_list argptr; + static bool processingError = false; + char errorstring[MAX_INPUTLINE]; + va_list argptr; - va_start (argptr, format); - std.vsnprintf (errorstring, sizeof(errorstring), format, argptr); - va_end (argptr); - Msg( "Menu_Error: %s\n", errorstring ); + va_start( argptr, format ); + std.vsnprintf(errorstring, sizeof(errorstring), format, argptr); + va_end( argptr ); + Host_Error( "Menu_Error: %s\n", errorstring ); - if( !processingError ) { + if( !processingError ) + { processingError = true; PRVM_Crash(); processingError = false; - } else { - Msg( "Menu_Error: Recursive call to MP_Error (from PRVM_Crash)!\n" ); } + else Host_Error( "Menu_RecursiveError: call to UI_Error (from PRVM_Crash)!\n" ); // fall back to the normal menu - - // say it - Con_Print("Falling back to normal menu\n"); - + Msg("Falling back to normal menu\n"); cls.key_dest = key_game; // init the normal menu now -> this will also correct the menu router pointers - MR_SetRouting (TRUE); - Host_AbortCurrentFrame(); } -void MP_KeyEvent (int key, char ascii, bool downevent) +void UI_KeyEvent(menuframework_s *m, int key) { PRVM_Begin; - PRVM_SetProg(PRVM_MENUPROG); + PRVM_SetProg( PRVM_MENUPROG ); // set time *prog->time = cls.realtime; // pass key - prog->globals.gp[OFS_PARM0] = (float) key; - prog->globals.gp[OFS_PARM1] = (float) ascii; - if (downevent) - PRVM_ExecuteProgram(m_keydown, M_F_KEYDOWN"(float key, float ascii) required\n"); - else if (m_keyup) - PRVM_ExecuteProgram((func_t)(m_keyup - prog->functions), M_F_KEYUP"(float key, float ascii) required\n"); + prog->globals.gp[OFS_PARM0] = (float)key; + prog->globals.gp[OFS_PARM1] = (string_t)PRVM_SetEngineString(Key_KeynumToString(key)); + PRVM_ExecuteProgram(m_keydown, M_F_KEYDOWN"(menuframework_s *m, int key) required\n"); PRVM_End; } -void MP_Draw (void) +void UI_Draw( void ) { PRVM_Begin; PRVM_SetProg(PRVM_MENUPROG); @@ -91,12 +77,11 @@ void MP_Draw (void) // set time *prog->time = cls.realtime; - PRVM_ExecuteProgram(m_draw,""); - + PRVM_ExecuteProgram( m_draw, "" ); PRVM_End; } -void MP_ToggleMenu_f (void) +void UI_ToggleMenu_f( void ) { PRVM_Begin; PRVM_SetProg(PRVM_MENUPROG); @@ -104,26 +89,17 @@ void MP_ToggleMenu_f (void) // set time *prog->time = cls.realtime; -#ifdef NG_MENU - m_displayed = !m_displayed; - if( m_displayed ) - PRVM_ExecuteProgram((func_t) (PRVM_ED_FindFunction(M_F_DISPLAY) - prog->functions),""); - else - PRVM_ExecuteProgram((func_t) (PRVM_ED_FindFunction(M_F_HIDE) - prog->functions),""); -#else - PRVM_ExecuteProgram((func_t) (PRVM_ED_FindFunction(M_F_TOGGLE) - prog->functions),""); -#endif - + PRVM_ExecuteProgram((func_t) (PRVM_ED_FindFunction(M_F_TOGGLE) - prog->functions), "" ); PRVM_End; } -void MP_Shutdown (void) +void UI_Shutdown( void ) { PRVM_Begin; PRVM_SetProg(PRVM_MENUPROG); // set time - *prog->time = cls.realtime; + //*prog->time = cls.realtime; PRVM_ExecuteProgram((func_t) (PRVM_ED_FindFunction(M_F_SHUTDOWN) - prog->functions),""); @@ -136,39 +112,29 @@ void MP_Shutdown (void) PRVM_End; } -void MP_Fallback (void) -{ - MP_Shutdown(); - - cls.key_dest = key_game; - - // init the normal menu now -> this will also correct the menu router pointers - MR_SetRouting (TRUE); -} - -void MP_Init (void) +void UI_Init( void ) { PRVM_Begin; - PRVM_InitProg(PRVM_MENUPROG); + PRVM_InitProg( PRVM_MENUPROG ); prog->edictprivate_size = 0; // no private struct used prog->name = M_NAME; prog->num_edicts = 1; prog->limit_edicts = M_MAX_EDICTS; - prog->extensionstring = vm_m_extensions; + prog->extensionstring = ""; prog->builtins = vm_m_builtins; prog->numbuiltins = vm_m_numbuiltins; - prog->init_cmd = VM_M_Cmd_Init; - prog->reset_cmd = VM_M_Cmd_Reset; - prog->error_cmd = MP_Error; + prog->init_cmd = VM_Cmd_Init; + prog->reset_cmd = VM_Cmd_Reset; + prog->error_cmd = UI_Error; // allocate the mempools prog->progs_mempool = Mem_AllocPool( M_PROG_FILENAME ); - PRVM_LoadProgs(M_PROG_FILENAME, m_numrequiredfunc, m_required_func, 0, NULL); + PRVM_LoadProgs( M_PROG_FILENAME, m_numrequiredfunc, m_required_func, 0, NULL); // set m_draw and m_keydown - m_draw = (func_t) (PRVM_ED_FindFunction(M_F_DRAW) - prog->functions); - m_keydown = (func_t) (PRVM_ED_FindFunction(M_F_KEYDOWN) - prog->functions); + m_draw = (func_t)(PRVM_ED_FindFunction(M_F_DRAW) - prog->functions); + m_keydown = (func_t)(PRVM_ED_FindFunction(M_F_KEYDOWN) - prog->functions); m_keyup = PRVM_ED_FindFunction(M_F_KEYUP); // set time @@ -176,80 +142,5 @@ void MP_Init (void) // call the prog init PRVM_ExecuteProgram((func_t) (PRVM_ED_FindFunction(M_F_INIT) - prog->functions),""); - PRVM_End; -} - -void MP_Restart(void) -{ - MP_Init(); -} - -//============================================================================ -// Menu router - -void (*MR_KeyEvent) (int key, char ascii, bool downevent); -void (*MR_Draw) (void); -void (*MR_ToggleMenu_f) (void); -void (*MR_Shutdown) (void); - -void MR_SetRouting(bool forceold) -{ - static bool m_init = FALSE, mp_init = FALSE; - - // if the menu prog isnt available or forceqmenu ist set, use the old menu - if(!FS_FileExists(M_PROG_FILENAME)) - { - // set menu router function pointers - /*MR_KeyEvent = M_KeyEvent; - MR_Draw = M_Draw; - MR_ToggleMenu_f = M_ToggleMenu_f; - MR_Shutdown = M_Shutdown; - */ - - // init - if(!m_init) - { - M_Init(); - m_init = TRUE; - } - else M_Restart(); - } - else - { - // set menu router function pointers - MR_KeyEvent = MP_KeyEvent; - MR_Draw = MP_Draw; - MR_ToggleMenu_f = MP_ToggleMenu_f; - MR_Shutdown = MP_Shutdown; - - if(!mp_init) - { - MP_Init(); - mp_init = TRUE; - } - else - MP_Restart(); - } -} - -void MR_Restart(void) -{ - MR_Shutdown(); - MR_SetRouting(FALSE); -} - -void Call_MR_ToggleMenu_f(void) -{ - if(MR_ToggleMenu_f) - MR_ToggleMenu_f(); -} - -void MR_Init_Commands(void) -{ - Cmd_AddCommand("menu_restart",MR_Restart, "restart menu system (reloads menu.dat"); -} - -void MR_Init(void) -{ } \ No newline at end of file diff --git a/engine/uimenu.h b/engine/uimenu.h index f1f5f3f0..11dcbd25 100644 --- a/engine/uimenu.h +++ b/engine/uimenu.h @@ -23,10 +23,11 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "engine.h" #include "client.h" +#include "qmenu.h" #include "progsvm.h" #include "vm_cmds.h" -#define M_PROG_FILENAME "menu.dat" +#define M_PROG_FILENAME "uimenu.dat" #define M_NAME "menu" #define M_MAX_EDICTS (1 << 12) // should be enough for a menu @@ -57,4 +58,10 @@ enum m_state_e { }; extern enum m_state_e m_state; +void UI_Init( void ); +void UI_KeyEvent(menuframework_s *m, int key); +void UI_ToggleMenu_f( void ); +void UI_Shutdown( void ); +void UI_Draw( void ); + #endif//UIMENU_H \ No newline at end of file diff --git a/launch/common/console.c b/launch/common/console.c index 3f8127e3..6643409c 100644 --- a/launch/common/console.c +++ b/launch/common/console.c @@ -368,7 +368,9 @@ destroy win32 console void Con_DestroyConsole( void ) { // last text message into console or log - MsgDev(D_ERROR, "Sys_FreeLibrary: Unloading launch.dll\n"); + + if(Sys.crash) MsgDev(D_ERROR, "Sys_FreeLibrary: Hold launch.dll for debugging\n" ); + else MsgDev(D_ERROR, "Sys_FreeLibrary: Unloading launch.dll\n"); if(Sys.hooked_out) { diff --git a/launch/common/filesystem.c b/launch/common/filesystem.c index 43752a15..b2526246 100644 --- a/launch/common/filesystem.c +++ b/launch/common/filesystem.c @@ -2584,6 +2584,46 @@ fs_offset_t VFS_Tell (vfile_t* file) return file->offset; } +/* +==================== +FS_Getc + +Get the next character of a file +==================== +*/ +int VFS_Getc(vfile_t *file) +{ + char c; + + if(!VFS_Read (file, &c, 1)) + return EOF; + return c; +} + +int VFS_Gets(vfile_t* file, byte *string, size_t bufsize ) +{ + int c, end = 0; + + while( 1 ) + { + c = VFS_Getc( file ); + if (c == '\r' || c == '\n' || c < 0) + break; + if (end < bufsize - 1) string[end++] = c; + } + string[end] = 0; + + // remove \n following \r + if (c == '\r') + { + c = VFS_Getc( file ); + if (c != '\n') VFS_Seek( file, -1, SEEK_CUR ); // rewind + } + MsgDev(D_INFO, "VFS_Gets: %s\n", string); + + return c; +} + int VFS_Seek( vfile_t *file, fs_offset_t offset, int whence ) { if (!file) return -1; diff --git a/launch/common/system.c b/launch/common/system.c index bd998a9d..eaa2a58d 100644 --- a/launch/common/system.c +++ b/launch/common/system.c @@ -149,6 +149,7 @@ void Sys_GetStdAPI( void ) std.vfclose = VFS_Close; // free buffer or write dump std.vfwrite = VFS_Write; // write into buffer std.vfread = VFS_Read; // read from buffer + std.vfgets = VFS_Gets; // read text line std.vfprint = VFS_Print; // write message std.vfprintf = VFS_Printf; // write formatted message std.vfseek = VFS_Seek; // fseek, can seek in packfiles too @@ -764,33 +765,35 @@ void Sys_Error(const char *error, ...) } -long _stdcall Sys_ExecptionFilter( PEXCEPTION_POINTERS pExceptionInfo ) +long _stdcall Sys_Crash( PEXCEPTION_POINTERS pInfo ) { // save config - Sys_Print("Engine crashed\n"); + Sys.crash = true; Sys.Free(); // prepare host to close Sys_FreeLibrary( Sys.linked_dll ); + + if(Sys.developer >= D_MEMORY) + { + // show execption in native console too + Con_ShowConsole( true ); + Msg("Sys_Crash: call %p at address %p\n", pInfo->ExceptionRecord->ExceptionCode, pInfo->ExceptionRecord->ExceptionAddress ); + Sys_WaitForQuit(); + } Con_DestroyConsole(); - if( Sys.oldFilter ) return Sys.oldFilter( pExceptionInfo ); - -#if 1 + if( Sys.oldFilter ) + return Sys.oldFilter( pInfo ); return EXCEPTION_CONTINUE_SEARCH; -#else - return EXCEPTION_CONTINUE_EXECUTION; -#endif } void Sys_Init( void ) { HANDLE hStdout; - OSVERSIONINFO vinfo; MEMORYSTATUS lpBuffer; char dev_level[4]; lpBuffer.dwLength = sizeof(MEMORYSTATUS); - vinfo.dwOSVersionInfoSize = sizeof(vinfo); -//oldFilter = SetUnhandledExceptionFilter( Sys_ExecptionFilter ); + Sys.oldFilter = SetUnhandledExceptionFilter( Sys_Crash ); GlobalMemoryStatus (&lpBuffer); Sys.hInstance = (HINSTANCE)GetModuleHandle( NULL ); // get current hInstance first @@ -845,7 +848,8 @@ void Sys_Exit ( void ) Memory_Shutdown(); Con_DestroyConsole(); - if( Sys.oldFilter ) // restore filter + // restore filter + if( Sys.oldFilter ) SetUnhandledExceptionFilter( Sys.oldFilter ); exit( Sys.error ); } @@ -948,8 +952,14 @@ bool Sys_FreeLibrary ( dll_info_t *dll ) { if(!dll || !dll->link) // invalid desc or alredy freed return false; + if(Sys.crash) + { + // we need to hold down all modules, while MSVC can find erorr + MsgDev(D_ERROR, "Sys_FreeLibrary: Hold %s for debugging\n", dll->name ); + return false; + } + else MsgDev(D_ERROR, "Sys_FreeLibrary: Unloading %s\n", dll->name ); - MsgDev(D_ERROR, "Sys_FreeLibrary: Unloading %s\n", dll->name ); FreeLibrary (dll->link); dll->link = NULL; diff --git a/launch/launch.h b/launch/launch.h index 1a636b82..12a990c3 100644 --- a/launch/launch.h +++ b/launch/launch.h @@ -44,6 +44,7 @@ typedef struct system_s bool con_showcredits; bool con_silentmode; bool error; + bool crash; byte *basepool; byte *zonepool; byte *imagepool; @@ -241,6 +242,7 @@ fs_offset_t VFS_Read(vfile_t* file, void* buffer, size_t buffersize); int VFS_Print(vfile_t* file, const char *msg); int VFS_Printf(vfile_t* file, const char* format, ...); int VFS_Seek( vfile_t *file, fs_offset_t offset, int whence ); +int VFS_Gets(vfile_t* file, byte *string, size_t bufsize ); bool VFS_Unpack( void* compbuf, size_t compsize, void **buf, size_t size ); fs_offset_t VFS_Tell (vfile_t* file); file_t *VFS_Close( vfile_t *file ); diff --git a/public/ref_stdlib.h b/public/ref_stdlib.h index a40d72e1..85907982 100644 --- a/public/ref_stdlib.h +++ b/public/ref_stdlib.h @@ -90,6 +90,7 @@ virtual filesystem manager #define VFS_Read std.vfread #define VFS_Print std.vfprint #define VFS_Printf std.vfprintf +#define VFS_Gets std.vfgets #define VFS_Seek std.vfseek #define VFS_Tell std.vftell #define VFS_Close std.vfclose diff --git a/public/ref_system.h b/public/ref_system.h index b0ae9fff..651601f5 100644 --- a/public/ref_system.h +++ b/public/ref_system.h @@ -596,6 +596,7 @@ typedef struct stdilib_api_s file_t *(*vfclose)(vfile_t* file); // free buffer or write dump long (*vfwrite)(vfile_t* file, const void* buf, size_t datasize); // write into buffer long (*vfread)(vfile_t* file, void* buffer, size_t buffersize); // read from buffer + int (*vfgets)(vfile_t* file, byte *string, size_t bufsize ); // read text line int (*vfprint)(vfile_t* file, const char *msg); // write message int (*vfprintf)(vfile_t* file, const char* format, ...); // write formatted message int (*vfseek)(vfile_t* file, fs_offset_t offset, int whence); // fseek, can seek in packfiles too