2
0
mirror of https://github.com/rehlds/rehlds.git synced 2025-01-07 20:45:34 +03:00
rehlds/rehlds/engine/tmessage.cpp
dreamstalker ed575d9b7d Fixed: all functions that could be called from outside must realign the stack
Removed NOINLINE from MSG_Write*Bits functions since stack alignment issue is resolved
2015-06-30 17:09:22 +04:00

511 lines
11 KiB
C++

/*
*
* 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
*
* In addition, as a special exception, the author gives permission to
* link the code of this program with the Half-Life Game Engine ("HL
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
* L.L.C ("Valve"). You must obey the GNU General Public License in all
* respects for all of the code used other than the HL Engine and MODs
* from Valve. If you modify this file, you may extend this exception
* to your version of the file, but you are not obligated to do so. If
* you do not wish to do so, delete this exception statement from your
* version.
*
*/
#include "precompiled.h"
char gNetworkTextMessageBuffer[MAX_NETMESSAGE][512];
client_textmessage_t gMessageParms;
/*
* Globals initialization
*/
#ifndef HOOK_ENGINE
client_textmessage_t *gMessageTable = NULL;
int gMessageTableCount = 0;
const char *gNetworkMessageNames[MAX_NETMESSAGE] =
{
NETWORK_MESSAGE1,
NETWORK_MESSAGE2,
NETWORK_MESSAGE3,
NETWORK_MESSAGE4
};
client_textmessage_t gNetworkTextMessage[MAX_NETMESSAGE] =
{
0, // effect
255, 255, 255, 255,
255, 255, 255, 255,
-1.0f, // x
-1.0f, // y
0.0f, // fadein
0.0f, // fadeout
0.0f, // holdtime
0.0f, // fxTime,
NETWORK_MESSAGE1,// pName message name.
gNetworkTextMessageBuffer[0] // pMessage
};
#else //HOOK_ENGINE
client_textmessage_t *gMessageTable;
int gMessageTableCount;
const char *gNetworkMessageNames[MAX_NETMESSAGE];
client_textmessage_t gNetworkTextMessage[MAX_NETMESSAGE];
#endif //HOOK_ENGINE
/* <c5144> ../engine/tmessage.c:47 */
char* EXT_FUNC memfgets(unsigned char *pMemFile, int fileSize, int *pFilePos, char *pBuffer, int bufferSize)
{
int filePos;
int last;
int i;
int stop;
int size;
filePos = *pFilePos;
if (!pMemFile || !pBuffer || filePos >= fileSize)
return NULL;
last = fileSize;
i = *pFilePos;
if (fileSize - filePos > bufferSize - 1)
last = filePos + bufferSize - 1;
stop = 0;
if (filePos >= last)
return NULL;
do
{
if (stop)
break;
if (pMemFile[i] == 10)
stop = 1;
++i;
} while (i < last);
if (i == filePos)
return NULL;
size = i - filePos;
Q_memcpy(pBuffer, &pMemFile[filePos], i - filePos);
if (size < bufferSize)
pBuffer[size] = 0;
*pFilePos = i;
return pBuffer;
}
/* <c5236> ../engine/tmessage.c:99 */
int IsComment(char *pText)
{
int length;
if (!pText)
{
return TRUE;
}
length = Q_strlen(pText);
if (length >= 2 && pText[0] == '/' && pText[1] == '/' || length <= 0)
{
return TRUE;
}
return FALSE;
}
/* <c5108> ../engine/tmessage.c:118 */
int IsStartOfText(char *pText)
{
return pText && pText[0] == '{';
}
/* <c5126> ../engine/tmessage.c:130 */
int IsEndOfText(char *pText)
{
return pText && pText[0] == '}';
}
/* <c50c1> ../engine/tmessage.c:141 */
int IsWhiteSpace(char space)
{
return space == ' ' || space == '\t' || space == '\r' || space == '\n';
}
/* <c52fe> ../engine/tmessage.c:149 */
NOXREF const char *SkipSpace(const char *pText)
{
if (pText)
{
int pos = 0;
while (pText[pos] && IsWhiteSpace(pText[pos]))
pos++;
return pText + pos;
}
return NULL;
}
/* <c5372> ../engine/tmessage.c:163 */
NOXREF const char *SkipText(const char *pText)
{
if (pText)
{
int pos = 0;
while (pText[pos] && !IsWhiteSpace(pText[pos]))
pos++;
return pText + pos;
}
return NULL;
}
/* <c5400> ../engine/tmessage.c:177 */
NOXREF int ParseFloats(const char *pText, float *pFloat, int count)
{
const char *pTemp = pText;
int index = 0;
while (pTemp && count > 0)
{
pTemp = SkipText(pTemp);
pTemp = SkipSpace(pTemp);
if (pTemp)
{
pFloat[index] = (float)atof(pTemp);
count--;
index++;
}
}
if (count == 0)
return 1;
return 0;
}
/* <c5506> ../engine/tmessage.c:205 */
void TrimSpace(const char *source, char *dest)
{
int start, end, length;
length = Q_strlen(source);
for (start = 0; start < length; start++)
{
if (!IsWhiteSpace(source[start]))
break;
}
for (end = length - 1; end > start; end--)
{
if (!IsWhiteSpace(source[end]))
break;
}
length = end - start + 1;
if (length <= 0)
{
dest[0] = 0;
}
else
{
Q_strncpy(dest, &source[start], length);
dest[length] = 0;
}
}
/* <c50df> ../engine/tmessage.c:232 */
NOXREF int IsToken(const char *pText, const char *pTokenName)
{
if (!pText || !pTokenName)
return 0;
if (!Q_strnicmp(pText + 1, pTokenName, Q_strlen(pTokenName)))
return 1;
return 0;
}
/* <c55e5> ../engine/tmessage.c:245 */
NOXREF int ParseDirective(const char *pText)
{
if (pText && pText[0] == '$')
{
float tempFloat[8];
if (IsToken(pText, "position"))
{
if (ParseFloats(pText, tempFloat, 2))
{
gMessageParms.x = tempFloat[0];
gMessageParms.y = tempFloat[1];
}
}
else if (IsToken(pText, "effect"))
{
if (ParseFloats(pText, tempFloat, 1))
{
gMessageParms.effect = (int)tempFloat[0];
}
}
else if (IsToken(pText, "fxtime"))
{
if (ParseFloats(pText, tempFloat, 1))
{
gMessageParms.fxtime = tempFloat[0];
}
}
else if (IsToken(pText, "color2"))
{
if (ParseFloats(pText, tempFloat, 3))
{
gMessageParms.r2 = (int)tempFloat[0];
gMessageParms.g2 = (int)tempFloat[1];
gMessageParms.b2 = (int)tempFloat[2];
}
}
else if (IsToken(pText, "color"))
{
if (ParseFloats(pText, tempFloat, 3))
{
gMessageParms.r1 = (int)tempFloat[0];
gMessageParms.g1 = (int)tempFloat[1];
gMessageParms.b1 = (int)tempFloat[2];
}
}
else if (IsToken(pText, "fadein"))
{
if (ParseFloats(pText, tempFloat, 1))
{
gMessageParms.fadein = tempFloat[0];
}
}
else if (IsToken(pText, "fadeout"))
{
if (ParseFloats(pText, tempFloat, 3))
{
gMessageParms.fadeout = tempFloat[0];
}
}
else if (IsToken(pText, "holdtime"))
{
if (ParseFloats(pText, tempFloat, 3))
{
gMessageParms.holdtime = tempFloat[0];
}
}
else
{
Con_DPrintf("Unknown token: %s\n", pText);
}
return 1;
}
return 0;
}
/* <c584f> ../engine/tmessage.c:324 */
NOXREF void TextMessageParse(unsigned char *pMemFile, int fileSize)
{
char buf[512];
char trim[512];
char *pCurrentText;
char *pNameHeap;
char currentName[512];
char nameHeap[NAME_HEAP_SIZE];
int lastNamePos;
int mode;
int lineNumber;
int filePos;
int lastLinePos;
int messageCount;
client_textmessage_t textMessages[MAX_MESSAGES];
int i;
int nameHeapSize;
int textHeapSize;
int messageSize;
int nameOffset;
lastNamePos = 0;
lineNumber = 0;
filePos = 0;
lastLinePos = 0;
messageCount = 0;
mode = MSGFILE_NAME;
while (memfgets(pMemFile, fileSize, &filePos, buf, 512) != NULL)
{
if(messageCount >= MAX_MESSAGES)
Sys_Error("tmessage::TextMessageParse : messageCount>=MAX_MESSAGES");
TrimSpace(buf, trim);
switch (mode)
{
case MSGFILE_NAME:
{
if (IsComment(trim))
break;
if (ParseDirective(trim))
break;
if (IsStartOfText(trim))
{
mode = MSGFILE_TEXT;
pCurrentText = (char *)(pMemFile + filePos);
break;
}
if (IsEndOfText(trim))
{
Con_DPrintf("Unexpected '}' found, line %d\n", lineNumber);
return;
}
Q_strncpy(currentName, trim, 511);
currentName[511] = 0;
break;
}
case MSGFILE_TEXT:
{
if (IsEndOfText(trim))
{
int length = Q_strlen(currentName);
if (lastNamePos + length > sizeof(nameHeap))
{
Con_DPrintf("Error parsing file! length > %i bytes\n", sizeof(nameHeap));
return;
}
Q_strcpy(nameHeap + lastNamePos, currentName);
pMemFile[lastLinePos - 1] = 0;
textMessages[messageCount] = gMessageParms;
textMessages[messageCount].pName = nameHeap + lastNamePos;
lastNamePos += Q_strlen(currentName) + 1;
textMessages[messageCount].pMessage = pCurrentText;
messageCount++;
mode = MSGFILE_NAME;
break;
}
if (IsStartOfText(trim))
{
Con_DPrintf("Unexpected '{' found, line %d\n", lineNumber);
return;
}
break;
}
}
lineNumber++;
lastLinePos = filePos;
}
Con_DPrintf("Parsed %d text messages\n", messageCount);
nameHeapSize = lastNamePos;
textHeapSize = 0;
for (i = 0; i < messageCount; i++)
textHeapSize += Q_strlen(textMessages[i].pMessage) + 1;
messageSize = (messageCount * sizeof(client_textmessage_t));
gMessageTable = (client_textmessage_t *)Mem_Malloc(textHeapSize + nameHeapSize + messageSize);
Q_memcpy(gMessageTable, textMessages, messageSize);
pNameHeap = ((char *)gMessageTable) + messageSize;
Q_memcpy(pNameHeap, nameHeap, nameHeapSize);
nameOffset = pNameHeap - gMessageTable[0].pName;
pCurrentText = pNameHeap + nameHeapSize;
for (i = 0; i < messageCount; i++)
{
gMessageTable[i].pName += nameOffset;
Q_strcpy(pCurrentText, gMessageTable[i].pMessage);
gMessageTable[i].pMessage = pCurrentText;
pCurrentText += Q_strlen(pCurrentText) + 1;
}
gMessageTableCount = messageCount;
}
/* <c5b18> ../engine/tmessage.c:454 */
NOXREF void TextMessageShutdown(void)
{
if (gMessageTable)
{
Mem_Free(gMessageTable);
gMessageTable = NULL;
}
}
/* <c5b2e> ../engine/tmessage.c:464 */
NOXREF void TextMessageInit(void)
{
int fileSize;
unsigned char *pMemFile;
if (gMessageTable)
{
Mem_Free(gMessageTable);
gMessageTable = NULL;
}
pMemFile = COM_LoadTempFile("titles.txt", &fileSize);
if (pMemFile)
TextMessageParse(pMemFile, fileSize);
}
/* <c5b68> ../engine/tmessage.c:497 */
NOXREF client_textmessage_t *TextMessageGet(const char *pName)
{
int i;
#ifndef SWDS
g_engdstAddrs->pfnTextMessageGet(&pName);
if (!Q_stricmp(pName, DEMO_MESSAGE))
return &tm_demomessage;
#endif // SWDS
if (!Q_stricmp(pName, NETWORK_MESSAGE1))
return gNetworkTextMessage;
else if (!Q_stricmp(pName, NETWORK_MESSAGE2))
return gNetworkTextMessage + 1;
else if (!Q_stricmp(pName, NETWORK_MESSAGE3))
return gNetworkTextMessage + 2;
else if (!Q_stricmp(pName, NETWORK_MESSAGE4))
return gNetworkTextMessage + 3;
for (i = 0; i < gMessageTableCount; i++)
{
if (!Q_strcmp(pName, gMessageTable[i].pName))
return &gMessageTable[i];
}
return NULL;
}