The Quake III Arena sources as originally released under the GPL license on August 20, 2005.
This commit is contained in:
commit
dbe4ddb103
1409 changed files with 806066 additions and 0 deletions
751
q3radiant/QE3.CPP
Normal file
751
q3radiant/QE3.CPP
Normal file
|
@ -0,0 +1,751 @@
|
|||
/*
|
||||
===========================================================================
|
||||
Copyright (C) 1999-2005 Id Software, Inc.
|
||||
|
||||
This file is part of Quake III Arena source code.
|
||||
|
||||
Quake III Arena 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 2 of the License,
|
||||
or (at your option) any later version.
|
||||
|
||||
Quake III Arena 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 Foobar; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
===========================================================================
|
||||
*/
|
||||
#include "stdafx.h"
|
||||
#include "qe3.h"
|
||||
#include "PrefsDlg.h"
|
||||
#include <direct.h>
|
||||
#include <sys\stat.h>
|
||||
|
||||
QEGlobals_t g_qeglobals;
|
||||
|
||||
void WINAPI QE_CheckOpenGLForErrors(void)
|
||||
{
|
||||
CString strMsg;
|
||||
int i = qglGetError();
|
||||
if (i != GL_NO_ERROR)
|
||||
{
|
||||
if (i == GL_OUT_OF_MEMORY)
|
||||
{
|
||||
//strMsg.Format("OpenGL out of memory error %s\nDo you wish to save before exiting?", qgluErrorString((GLenum)i));
|
||||
if (MessageBox(g_qeglobals.d_hwndMain, strMsg, "Q3Radiant Error", MB_YESNO) == IDYES)
|
||||
{
|
||||
Map_SaveFile(NULL, false);
|
||||
}
|
||||
exit(1);
|
||||
}
|
||||
else
|
||||
{
|
||||
//strMsg.Format("Warning: OpenGL Error %s\n ", qgluErrorString((GLenum)i));
|
||||
Sys_Printf (strMsg.GetBuffer(0));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
char *ExpandReletivePath (char *p)
|
||||
{
|
||||
static char temp[1024];
|
||||
char *base;
|
||||
|
||||
if (!p || !p[0])
|
||||
return NULL;
|
||||
if (p[0] == '/' || p[0] == '\\')
|
||||
return p;
|
||||
|
||||
base = ValueForKey(g_qeglobals.d_project_entity, "basepath");
|
||||
sprintf (temp, "%s/%s", base, p);
|
||||
return temp;
|
||||
}
|
||||
|
||||
char *copystring (char *s)
|
||||
{
|
||||
char *b;
|
||||
b = (char*)malloc(strlen(s)+1);
|
||||
strcpy (b,s);
|
||||
return b;
|
||||
}
|
||||
|
||||
|
||||
bool DoesFileExist(const char* pBuff, long& lSize)
|
||||
{
|
||||
CFile file;
|
||||
if (file.Open(pBuff, CFile::modeRead | CFile::shareDenyNone))
|
||||
{
|
||||
lSize += file.GetLength();
|
||||
file.Close();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void Map_Snapshot()
|
||||
{
|
||||
CString strMsg;
|
||||
// we need to do the following
|
||||
// 1. make sure the snapshot directory exists (create it if it doesn't)
|
||||
// 2. find out what the lastest save is based on number
|
||||
// 3. inc that and save the map
|
||||
CString strOrgPath, strOrgFile;
|
||||
ExtractPath_and_Filename(currentmap, strOrgPath, strOrgFile);
|
||||
AddSlash(strOrgPath);
|
||||
strOrgPath += "snapshots";
|
||||
bool bGo = true;
|
||||
struct _stat Stat;
|
||||
if (_stat(strOrgPath, &Stat) == -1)
|
||||
{
|
||||
bGo = (_mkdir(strOrgPath) != -1);
|
||||
}
|
||||
AddSlash(strOrgPath);
|
||||
if (bGo)
|
||||
{
|
||||
int nCount = 0;
|
||||
long lSize = 0;
|
||||
CString strNewPath = strOrgPath;
|
||||
strNewPath += strOrgFile;
|
||||
CString strFile;
|
||||
while (bGo)
|
||||
{
|
||||
strFile.Format("%s.%i", strNewPath, nCount);
|
||||
bGo = DoesFileExist(strFile, lSize);
|
||||
nCount++;
|
||||
}
|
||||
// strFile has the next available slot
|
||||
Map_SaveFile(strFile.GetBuffer(0), false);
|
||||
Sys_SetTitle (currentmap);
|
||||
if (lSize > 12 * 1024 * 1024) // total size of saves > 4 mb
|
||||
{
|
||||
Sys_Printf("The snapshot files in the [%s] directory total more than 4 megabytes. You might consider cleaning the directory up.", strOrgPath);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
strMsg.Format("Snapshot save failed.. unabled to create directory\n%s", strOrgPath);
|
||||
g_pParentWnd->MessageBox(strMsg);
|
||||
}
|
||||
}
|
||||
/*
|
||||
===============
|
||||
QE_CheckAutoSave
|
||||
|
||||
If five minutes have passed since making a change
|
||||
and the map hasn't been saved, save it out.
|
||||
===============
|
||||
*/
|
||||
|
||||
|
||||
void QE_CheckAutoSave( void )
|
||||
{
|
||||
static clock_t s_start;
|
||||
clock_t now;
|
||||
|
||||
now = clock();
|
||||
|
||||
if ( modified != 1 || !s_start)
|
||||
{
|
||||
s_start = now;
|
||||
return;
|
||||
}
|
||||
|
||||
if ( now - s_start > ( CLOCKS_PER_SEC * 60 * g_PrefsDlg.m_nAutoSave))
|
||||
{
|
||||
|
||||
if (g_PrefsDlg.m_bAutoSave)
|
||||
{
|
||||
CString strMsg = g_PrefsDlg.m_bSnapShots ? "Autosaving snapshot..." : "Autosaving...";
|
||||
Sys_Printf(strMsg.GetBuffer(0));
|
||||
Sys_Printf("\n");
|
||||
Sys_Status (strMsg.GetBuffer(0),0);
|
||||
|
||||
// only snapshot if not working on a default map
|
||||
if (g_PrefsDlg.m_bSnapShots && stricmp(currentmap, "unnamed.map") != 0)
|
||||
{
|
||||
Map_Snapshot();
|
||||
}
|
||||
else
|
||||
{
|
||||
Map_SaveFile (ValueForKey(g_qeglobals.d_project_entity, "autosave"), false);
|
||||
}
|
||||
|
||||
Sys_Status ("Autosaving...Saved.", 0 );
|
||||
modified = 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
Sys_Printf ("Autosave skipped...\n");
|
||||
Sys_Status ("Autosave skipped...", 0 );
|
||||
}
|
||||
s_start = now;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int BuildShortPathName(const char* pPath, char* pBuffer, int nBufferLen)
|
||||
{
|
||||
char *pFile = NULL;
|
||||
int nResult = GetFullPathName(pPath, nBufferLen, pBuffer, &pFile);
|
||||
nResult = GetShortPathName(pPath, pBuffer, nBufferLen);
|
||||
if (nResult == 0)
|
||||
strcpy(pBuffer, pPath); // Use long filename
|
||||
return nResult;
|
||||
}
|
||||
|
||||
|
||||
|
||||
const char *g_pPathFixups[]=
|
||||
{
|
||||
"basepath",
|
||||
"remotebasepath",
|
||||
"entitypath",
|
||||
"texturepath",
|
||||
"autosave",
|
||||
"mapspath"
|
||||
};
|
||||
|
||||
const int g_nPathFixupCount = sizeof(g_pPathFixups) / sizeof(const char*);
|
||||
|
||||
/*
|
||||
===========
|
||||
QE_LoadProject
|
||||
===========
|
||||
*/
|
||||
qboolean QE_LoadProject (char *projectfile)
|
||||
{
|
||||
char *data;
|
||||
|
||||
Sys_Printf ("QE_LoadProject (%s)\n", projectfile);
|
||||
|
||||
if ( LoadFileNoCrash (projectfile, (void **)&data) == -1)
|
||||
return false;
|
||||
|
||||
g_strProject = projectfile;
|
||||
|
||||
CString strData = data;
|
||||
free(data);
|
||||
|
||||
CString strQ2Path = g_PrefsDlg.m_strQuake2;
|
||||
CString strQ2File;
|
||||
ExtractPath_and_Filename(g_PrefsDlg.m_strQuake2, strQ2Path, strQ2File);
|
||||
AddSlash(strQ2Path);
|
||||
|
||||
|
||||
char* pBuff = new char[1024];
|
||||
|
||||
BuildShortPathName(strQ2Path, pBuff, 1024);
|
||||
FindReplace(strData, "__Q2PATH", pBuff);
|
||||
BuildShortPathName(g_strAppPath, pBuff, 1024);
|
||||
FindReplace(strData, "__QERPATH", pBuff);
|
||||
|
||||
char* pFile;
|
||||
if (GetFullPathName(projectfile, 1024, pBuff, &pFile))
|
||||
{
|
||||
g_PrefsDlg.m_strLastProject = pBuff;
|
||||
BuildShortPathName(g_PrefsDlg.m_strLastProject, pBuff, 1024);
|
||||
g_PrefsDlg.m_strLastProject = pBuff;
|
||||
g_PrefsDlg.SavePrefs();
|
||||
|
||||
ExtractPath_and_Filename(pBuff, strQ2Path, strQ2File);
|
||||
int nLen = strQ2Path.GetLength();
|
||||
if (nLen > 0)
|
||||
{
|
||||
if (strQ2Path[nLen - 1] == '\\')
|
||||
strQ2Path.SetAt(nLen-1,'\0');
|
||||
char* pBuffer = strQ2Path.GetBufferSetLength(_MAX_PATH + 1);
|
||||
int n = strQ2Path.ReverseFind('\\');
|
||||
if (n >=0 )
|
||||
pBuffer[n + 1] = '\0';
|
||||
strQ2Path.ReleaseBuffer();
|
||||
FindReplace(strData, "__QEPROJPATH", strQ2Path);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
StartTokenParsing (strData.GetBuffer(0));
|
||||
g_qeglobals.d_project_entity = Entity_Parse (true);
|
||||
if (!g_qeglobals.d_project_entity)
|
||||
Error ("Couldn't parse %s", projectfile);
|
||||
|
||||
for (int i = 0; i < g_nPathFixupCount; i++)
|
||||
{
|
||||
char *pPath = ValueForKey (g_qeglobals.d_project_entity, g_pPathFixups[i]);
|
||||
if (pPath[0] != '\\' && pPath[0] != '/')
|
||||
{
|
||||
if (GetFullPathName(pPath, 1024, pBuff, &pFile))
|
||||
{
|
||||
SetKeyValue(g_qeglobals.d_project_entity, g_pPathFixups[i], pBuff);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
delete []pBuff;
|
||||
|
||||
// set here some default project settings you need
|
||||
if ( strlen( ValueForKey( g_qeglobals.d_project_entity, "brush_primit" ) ) == 0 )
|
||||
{
|
||||
SetKeyValue( g_qeglobals.d_project_entity, "brush_primit", "0" );
|
||||
}
|
||||
|
||||
g_qeglobals.m_bBrushPrimitMode = IntForKey( g_qeglobals.d_project_entity, "brush_primit" );
|
||||
|
||||
|
||||
Eclass_InitForSourceDirectory (ValueForKey (g_qeglobals.d_project_entity, "entitypath"));
|
||||
FillClassList(); // list in entity window
|
||||
|
||||
Map_New();
|
||||
|
||||
|
||||
FillTextureMenu();
|
||||
FillBSPMenu();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
===========
|
||||
QE_SaveProject
|
||||
===========
|
||||
*/
|
||||
//extern char *bsp_commands[256];
|
||||
|
||||
qboolean QE_SaveProject (const char* pProjectFile)
|
||||
{
|
||||
//char filename[1024];
|
||||
FILE *fp;
|
||||
epair_t *ep;
|
||||
|
||||
//sprintf (filename, "%s\\%s.prj", g_projectdir, g_username);
|
||||
|
||||
if (!(fp = fopen (pProjectFile, "w+")))
|
||||
Error ("Could not open project file!");
|
||||
|
||||
fprintf (fp, "{\n");
|
||||
for (ep = g_qeglobals.d_project_entity->epairs; ep; ep=ep->next)
|
||||
fprintf (fp, "\"%s\" \"%s\"\n", ep->key, ep->value);
|
||||
fprintf (fp, "}\n");
|
||||
|
||||
fclose (fp);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
===========
|
||||
QE_KeyDown
|
||||
===========
|
||||
*/
|
||||
#define SPEED_MOVE 32
|
||||
#define SPEED_TURN 22.5
|
||||
|
||||
|
||||
/*
|
||||
===============
|
||||
ConnectEntities
|
||||
|
||||
Sets target / targetname on the two entities selected
|
||||
from the first selected to the secon
|
||||
===============
|
||||
*/
|
||||
void ConnectEntities (void)
|
||||
{
|
||||
entity_t *e1, *e2, *e;
|
||||
char *target, *tn;
|
||||
int maxtarg, targetnum;
|
||||
char newtarg[32];
|
||||
|
||||
if (g_qeglobals.d_select_count != 2)
|
||||
{
|
||||
Sys_Status ("Must have two brushes selected.", 0);
|
||||
Sys_Beep ();
|
||||
return;
|
||||
}
|
||||
|
||||
e1 = g_qeglobals.d_select_order[0]->owner;
|
||||
e2 = g_qeglobals.d_select_order[1]->owner;
|
||||
|
||||
if (e1 == world_entity || e2 == world_entity)
|
||||
{
|
||||
Sys_Status ("Can't connect to the world.", 0);
|
||||
Sys_Beep ();
|
||||
return;
|
||||
}
|
||||
|
||||
if (e1 == e2)
|
||||
{
|
||||
Sys_Status ("Brushes are from same entity.", 0);
|
||||
Sys_Beep ();
|
||||
return;
|
||||
}
|
||||
|
||||
target = ValueForKey (e1, "target");
|
||||
if (target && target[0])
|
||||
strcpy (newtarg, target);
|
||||
else
|
||||
{
|
||||
target = ValueForKey (e2, "targetname");
|
||||
if (target && target[0])
|
||||
strcpy (newtarg, target);
|
||||
else
|
||||
{
|
||||
// make a unique target value
|
||||
maxtarg = 0;
|
||||
for (e=entities.next ; e != &entities ; e=e->next)
|
||||
{
|
||||
tn = ValueForKey (e, "targetname");
|
||||
if (tn && tn[0])
|
||||
{
|
||||
targetnum = atoi(tn+1);
|
||||
if (targetnum > maxtarg)
|
||||
maxtarg = targetnum;
|
||||
}
|
||||
}
|
||||
sprintf (newtarg, "t%i", maxtarg+1);
|
||||
}
|
||||
}
|
||||
|
||||
SetKeyValue (e1, "target", newtarg);
|
||||
SetKeyValue (e2, "targetname", newtarg);
|
||||
Sys_UpdateWindows (W_XY | W_CAMERA);
|
||||
|
||||
Select_Deselect();
|
||||
Select_Brush (g_qeglobals.d_select_order[1]);
|
||||
}
|
||||
|
||||
qboolean QE_SingleBrush (bool bQuiet)
|
||||
{
|
||||
if ( (selected_brushes.next == &selected_brushes)
|
||||
|| (selected_brushes.next->next != &selected_brushes) )
|
||||
{
|
||||
if (!bQuiet)
|
||||
{
|
||||
Sys_Printf ("Error: you must have a single brush selected\n");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
if (selected_brushes.next->owner->eclass->fixedsize)
|
||||
{
|
||||
if (!bQuiet)
|
||||
{
|
||||
Sys_Printf ("Error: you cannot manipulate fixed size entities\n");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void QE_Init (void)
|
||||
{
|
||||
/*
|
||||
** initialize variables
|
||||
*/
|
||||
g_qeglobals.d_gridsize = 8;
|
||||
g_qeglobals.d_showgrid = true;
|
||||
|
||||
/*
|
||||
** other stuff
|
||||
*/
|
||||
Texture_Init (true);
|
||||
//Cam_Init ();
|
||||
//XY_Init ();
|
||||
Z_Init ();
|
||||
Terrain_Init();
|
||||
}
|
||||
|
||||
void WINAPI QE_ConvertDOSToUnixName( char *dst, const char *src )
|
||||
{
|
||||
while ( *src )
|
||||
{
|
||||
if ( *src == '\\' )
|
||||
*dst = '/';
|
||||
else
|
||||
*dst = *src;
|
||||
dst++; src++;
|
||||
}
|
||||
*dst = 0;
|
||||
}
|
||||
|
||||
int g_numbrushes, g_numentities;
|
||||
|
||||
void QE_CountBrushesAndUpdateStatusBar( void )
|
||||
{
|
||||
static int s_lastbrushcount, s_lastentitycount;
|
||||
static qboolean s_didonce;
|
||||
|
||||
//entity_t *e;
|
||||
brush_t *b, *next;
|
||||
|
||||
g_numbrushes = 0;
|
||||
g_numentities = 0;
|
||||
|
||||
if ( active_brushes.next != NULL )
|
||||
{
|
||||
for ( b = active_brushes.next ; b != NULL && b != &active_brushes ; b=next)
|
||||
{
|
||||
next = b->next;
|
||||
if (b->brush_faces )
|
||||
{
|
||||
if ( !b->owner->eclass->fixedsize)
|
||||
g_numbrushes++;
|
||||
else
|
||||
g_numentities++;
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
if ( entities.next != NULL )
|
||||
{
|
||||
for ( e = entities.next ; e != &entities && g_numentities != MAX_MAP_ENTITIES ; e = e->next)
|
||||
{
|
||||
g_numentities++;
|
||||
}
|
||||
}
|
||||
*/
|
||||
if ( ( ( g_numbrushes != s_lastbrushcount ) || ( g_numentities != s_lastentitycount ) ) || ( !s_didonce ) )
|
||||
{
|
||||
Sys_UpdateStatusBar();
|
||||
|
||||
s_lastbrushcount = g_numbrushes;
|
||||
s_lastentitycount = g_numentities;
|
||||
s_didonce = true;
|
||||
}
|
||||
}
|
||||
|
||||
char com_token[1024];
|
||||
qboolean com_eof;
|
||||
|
||||
/*
|
||||
================
|
||||
I_FloatTime
|
||||
================
|
||||
*/
|
||||
double I_FloatTime (void)
|
||||
{
|
||||
time_t t;
|
||||
|
||||
time (&t);
|
||||
|
||||
return t;
|
||||
#if 0
|
||||
// more precise, less portable
|
||||
struct timeval tp;
|
||||
struct timezone tzp;
|
||||
static int secbase;
|
||||
|
||||
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;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
==============
|
||||
COM_Parse
|
||||
|
||||
Parse a token out of a string
|
||||
==============
|
||||
*/
|
||||
char *COM_Parse (char *data)
|
||||
{
|
||||
int c;
|
||||
int len;
|
||||
|
||||
len = 0;
|
||||
com_token[0] = 0;
|
||||
|
||||
if (!data)
|
||||
return NULL;
|
||||
|
||||
// skip whitespace
|
||||
skipwhite:
|
||||
while ( (c = *data) <= ' ')
|
||||
{
|
||||
if (c == 0)
|
||||
{
|
||||
com_eof = true;
|
||||
return NULL; // end of file;
|
||||
}
|
||||
data++;
|
||||
}
|
||||
|
||||
// skip // comments
|
||||
if (c=='/' && data[1] == '/')
|
||||
{
|
||||
while (*data && *data != '\n')
|
||||
data++;
|
||||
goto skipwhite;
|
||||
}
|
||||
|
||||
|
||||
// handle quoted strings specially
|
||||
if (c == '\"')
|
||||
{
|
||||
data++;
|
||||
do
|
||||
{
|
||||
c = *data++;
|
||||
if (c=='\"')
|
||||
{
|
||||
com_token[len] = 0;
|
||||
return data;
|
||||
}
|
||||
com_token[len] = c;
|
||||
len++;
|
||||
} while (1);
|
||||
}
|
||||
|
||||
// parse single characters
|
||||
if (c=='{' || c=='}'|| c==')'|| c=='(' || c=='\'' || c==':')
|
||||
{
|
||||
com_token[len] = c;
|
||||
len++;
|
||||
com_token[len] = 0;
|
||||
return data+1;
|
||||
}
|
||||
|
||||
// parse a regular word
|
||||
do
|
||||
{
|
||||
com_token[len] = c;
|
||||
data++;
|
||||
len++;
|
||||
c = *data;
|
||||
if (c=='{' || c=='}'|| c==')'|| c=='(' || c=='\'' || c==':')
|
||||
break;
|
||||
} while (c>32);
|
||||
|
||||
com_token[len] = 0;
|
||||
return data;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
=============================================================================
|
||||
|
||||
MISC FUNCTIONS
|
||||
|
||||
=============================================================================
|
||||
*/
|
||||
|
||||
|
||||
int argc;
|
||||
char *argv[MAX_NUM_ARGVS];
|
||||
|
||||
/*
|
||||
============
|
||||
ParseCommandLine
|
||||
============
|
||||
*/
|
||||
void ParseCommandLine (char *lpCmdLine)
|
||||
{
|
||||
argc = 1;
|
||||
argv[0] = "programname";
|
||||
|
||||
while (*lpCmdLine && (argc < MAX_NUM_ARGVS))
|
||||
{
|
||||
while (*lpCmdLine && ((*lpCmdLine <= 32) || (*lpCmdLine > 126)))
|
||||
lpCmdLine++;
|
||||
|
||||
if (*lpCmdLine)
|
||||
{
|
||||
argv[argc] = lpCmdLine;
|
||||
argc++;
|
||||
|
||||
while (*lpCmdLine && ((*lpCmdLine > 32) && (*lpCmdLine <= 126)))
|
||||
lpCmdLine++;
|
||||
|
||||
if (*lpCmdLine)
|
||||
{
|
||||
*lpCmdLine = 0;
|
||||
lpCmdLine++;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
=================
|
||||
CheckParm
|
||||
|
||||
Checks for the given parameter in the program's command line arguments
|
||||
Returns the argument number (1 to argc-1) or 0 if not present
|
||||
=================
|
||||
*/
|
||||
int CheckParm (char *check)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 1;i<argc;i++)
|
||||
{
|
||||
if ( stricmp(check, argv[i]) )
|
||||
return i;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
==============
|
||||
ParseNum / ParseHex
|
||||
==============
|
||||
*/
|
||||
int ParseHex (char *hex)
|
||||
{
|
||||
char *str;
|
||||
int num;
|
||||
|
||||
num = 0;
|
||||
str = hex;
|
||||
|
||||
while (*str)
|
||||
{
|
||||
num <<= 4;
|
||||
if (*str >= '0' && *str <= '9')
|
||||
num += *str-'0';
|
||||
else if (*str >= 'a' && *str <= 'f')
|
||||
num += 10 + *str-'a';
|
||||
else if (*str >= 'A' && *str <= 'F')
|
||||
num += 10 + *str-'A';
|
||||
else
|
||||
Error ("Bad hex number: %s",hex);
|
||||
str++;
|
||||
}
|
||||
|
||||
return num;
|
||||
}
|
||||
|
||||
|
||||
int ParseNum (char *str)
|
||||
{
|
||||
if (str[0] == '$')
|
||||
return ParseHex (str+1);
|
||||
if (str[0] == '0' && str[1] == 'x')
|
||||
return ParseHex (str+2);
|
||||
return atol (str);
|
||||
}
|
||||
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue