mirror of
https://github.com/ZDoom/raze-gles.git
synced 2025-01-11 18:50:46 +00:00
RFS parser wip
# Conflicts: # .gitignore # platform/Windows/nblood.vcxproj.filters
This commit is contained in:
parent
9be59caef8
commit
b13bdf50be
9 changed files with 1106 additions and 16 deletions
|
@ -778,6 +778,7 @@ blood_game_objs := \
|
|||
aizomba.cpp \
|
||||
aizombf.cpp \
|
||||
asound.cpp \
|
||||
barf.cpp \
|
||||
callback.cpp \
|
||||
choke.cpp \
|
||||
common.cpp \
|
||||
|
|
|
@ -195,6 +195,7 @@
|
|||
<ClCompile Include="..\..\source\blood\src\aizomba.cpp" />
|
||||
<ClCompile Include="..\..\source\blood\src\aizombf.cpp" />
|
||||
<ClCompile Include="..\..\source\blood\src\asound.cpp" />
|
||||
<ClCompile Include="..\..\source\blood\src\barf.cpp" />
|
||||
<ClCompile Include="..\..\source\blood\src\blood.cpp" />
|
||||
<ClCompile Include="..\..\source\blood\src\callback.cpp" />
|
||||
<ClCompile Include="..\..\source\blood\src\choke.cpp" />
|
||||
|
@ -299,6 +300,7 @@
|
|||
<ClInclude Include="..\..\source\blood\src\aizomba.h" />
|
||||
<ClInclude Include="..\..\source\blood\src\aizombf.h" />
|
||||
<ClInclude Include="..\..\source\blood\src\asound.h" />
|
||||
<ClInclude Include="..\..\source\blood\src\barf.h" />
|
||||
<ClInclude Include="..\..\source\blood\src\blood.h" />
|
||||
<ClInclude Include="..\..\source\blood\src\callback.h" />
|
||||
<ClInclude Include="..\..\source\blood\src\choke.h" />
|
||||
|
|
|
@ -228,6 +228,9 @@
|
|||
<ClCompile Include="..\..\source\blood\src\aiunicult.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\source\blood\src\barf.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="..\..\source\blood\rsrc\gameres.rc">
|
||||
|
@ -457,5 +460,8 @@
|
|||
<ClInclude Include="..\..\source\blood\src\aiunicult.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\source\blood\src\barf.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
</Project>
|
952
source/blood/src/barf.cpp
Normal file
952
source/blood/src/barf.cpp
Normal file
|
@ -0,0 +1,952 @@
|
|||
//-------------------------------------------------------------------------
|
||||
/*
|
||||
Copyright (C) 2010-2019 EDuke32 developers and contributors
|
||||
Copyright (C) 2019 sirlemonhead, Nuke.YKT
|
||||
|
||||
This file is part of NBlood.
|
||||
|
||||
NBlood is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License version 2
|
||||
as published by the Free Software Foundation.
|
||||
|
||||
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
#include "compat.h"
|
||||
#ifdef WITHKPLIB
|
||||
#include "kplib.h"
|
||||
#endif
|
||||
#include "common_game.h"
|
||||
#include "resource.h"
|
||||
#include "misc.h"
|
||||
#include "globals.h"
|
||||
#include "sound.h"
|
||||
|
||||
static Resource gBarfRes;
|
||||
|
||||
#define kMaxCmdLineDefines 5
|
||||
#define kMaxDefines 1000
|
||||
#define kMaxParseLevels 5
|
||||
static int nCmdDefines = 0;
|
||||
static int nDefines = 0;
|
||||
|
||||
static int gParseLevel = 0;
|
||||
int dword_44CE0[kMaxParseLevels] = { 0, 0, 0, 0, 0 };
|
||||
|
||||
// FIXME
|
||||
unsigned int nBytes = 0;
|
||||
char buffer[1024];
|
||||
int scriptValue = 0;
|
||||
|
||||
char scriptBuffer[256];
|
||||
|
||||
struct define_t
|
||||
{
|
||||
char *_text;
|
||||
int _value;
|
||||
};
|
||||
|
||||
define_t gCmdDefines[kMaxCmdLineDefines];
|
||||
|
||||
void sub_11DF0(char *pzScriptDir, char *fileName, char flags, int ID);
|
||||
void sub_11C10(char *pzScriptDir, char *fileName, char flags, int ID);
|
||||
|
||||
struct tag_t {
|
||||
const char *_value;
|
||||
uint8_t _index;
|
||||
};
|
||||
|
||||
enum eTags
|
||||
{
|
||||
kTag0,
|
||||
kTagEnd,
|
||||
kTagString,
|
||||
kTagConstant,
|
||||
kTag4, // string constant?
|
||||
kTagComma,
|
||||
kTagSemiColon,
|
||||
kTagColon,
|
||||
kTagEquals,
|
||||
kTagHash,
|
||||
kTagComment,
|
||||
kTagInclude,
|
||||
kTagResource,
|
||||
kTagAs,
|
||||
kTagPreload,
|
||||
kTagPrelock,
|
||||
kTagData,
|
||||
kTagLoad,
|
||||
kTagEmit,
|
||||
kTagIfDef,
|
||||
kTagEndif,
|
||||
kTagElse
|
||||
};
|
||||
|
||||
tag_t tags[] =
|
||||
{
|
||||
{ ",", kTagComma },
|
||||
{ ";", kTagSemiColon },
|
||||
{ ":", kTagColon },
|
||||
{ "=", kTagEquals },
|
||||
{ "#", kTagHash },
|
||||
{ "//", kTagComment },
|
||||
{ "INCLUDE", kTagInclude },
|
||||
{ "RESOURCE", kTagResource },
|
||||
{ "AS", kTagAs },
|
||||
{ "PRELOAD", kTagPreload },
|
||||
{ "PRELOCK", kTagPrelock },
|
||||
{ "DATA", kTagData },
|
||||
{ "LOAD", kTagLoad },
|
||||
{ "EMIT", kTagEmit },
|
||||
{ "%ifdef", kTagIfDef },
|
||||
{ "%endif", kTagEndif },
|
||||
{ "%else", kTagElse }
|
||||
};
|
||||
|
||||
const int kTagCount = sizeof(tags) / sizeof(tag_t);
|
||||
|
||||
int qsort_compar(const void *a, const void *b)
|
||||
{
|
||||
return stricmp((const char*)a, (const char*)b);
|
||||
}
|
||||
|
||||
void SortTags()
|
||||
{
|
||||
qsort(tags, kTagCount, sizeof(tag_t), qsort_compar);
|
||||
}
|
||||
|
||||
void AddCmdDefine(char *text, int value)
|
||||
{
|
||||
dassert(nCmdDefines < kMaxCmdLineDefines);
|
||||
|
||||
gCmdDefines[nCmdDefines]._text = (char*)Resource::Alloc(strlen(text) + 1);
|
||||
|
||||
strcpy(gCmdDefines[nCmdDefines]._text, text);
|
||||
gCmdDefines[nCmdDefines]._value = value;
|
||||
|
||||
nCmdDefines++;
|
||||
}
|
||||
|
||||
// 174 bytes
|
||||
struct RFS
|
||||
{
|
||||
private:
|
||||
char *_ptr; // [0]
|
||||
char _curChar; // [4]
|
||||
char *_pUnknown2; // [5] - some sort of pointer into _ptr?
|
||||
char *_pStartLine; // [9]
|
||||
char *_pEnd; // [13]
|
||||
char *_pMark; // [17]
|
||||
char _unknown6; // [21]
|
||||
int _unknown7; // [22]
|
||||
int _curLine; // [26]
|
||||
char _fileName[BMAX_PATH]; // [30]
|
||||
|
||||
public:
|
||||
void Open(const char *fileName);
|
||||
void Close();
|
||||
void Increment();
|
||||
void SkipBeyondValue(char value);
|
||||
uint8_t GetNextTag();
|
||||
void ScriptError(const char *message);
|
||||
void SetMark();
|
||||
void UnsetMark();
|
||||
};
|
||||
|
||||
void RFS::Open(const char *fileName)
|
||||
{
|
||||
strcpy(_fileName, fileName);
|
||||
|
||||
int hFile = open(_fileName, O_BINARY);
|
||||
if (hFile == -1) {
|
||||
ThrowError("Error opening file %s", _fileName);
|
||||
}
|
||||
|
||||
int fileSize = filelength(hFile);
|
||||
_ptr = (char*)Resource::Alloc(fileSize);
|
||||
if (_ptr == NULL) {
|
||||
ThrowError("Not enough memory to read %s", _fileName);
|
||||
}
|
||||
|
||||
read(hFile, _ptr, fileSize);
|
||||
close(hFile);
|
||||
|
||||
_curLine = 0;
|
||||
_pUnknown2 = _ptr;
|
||||
_curChar = '\n';
|
||||
_pEnd = &_ptr[fileSize - 1];
|
||||
}
|
||||
|
||||
void RFS::Close()
|
||||
{
|
||||
if (_ptr) {
|
||||
/* BUG - the original code called nfree but this should be a Resource::Free()
|
||||
_nfree(_ptr);
|
||||
*/
|
||||
Resource::Free(_ptr);
|
||||
}
|
||||
}
|
||||
|
||||
void RFS::Increment()
|
||||
{
|
||||
if (_curChar == '\n') {
|
||||
_curLine++;
|
||||
_pStartLine = _pUnknown2;
|
||||
}
|
||||
|
||||
if (_pUnknown2 >= _pEnd) {
|
||||
_curChar = 0;
|
||||
}
|
||||
else {
|
||||
_curChar = *_pUnknown2; // grabs the next char
|
||||
_pUnknown2++; // increment pointer into char data
|
||||
}
|
||||
}
|
||||
|
||||
void RFS::SkipBeyondValue(char nVal)
|
||||
{
|
||||
while (_curChar && _curChar != nVal) {
|
||||
Increment();
|
||||
}
|
||||
}
|
||||
|
||||
void RFS::SetMark()
|
||||
{
|
||||
_pMark = _pUnknown2;
|
||||
_unknown6 = _curChar;
|
||||
_unknown7 = _curLine;
|
||||
}
|
||||
|
||||
// inverse of the above function
|
||||
void RFS::UnsetMark()
|
||||
{
|
||||
_pUnknown2 = _pMark;
|
||||
_curChar = _unknown6;
|
||||
_curLine = _unknown7;
|
||||
}
|
||||
|
||||
void RFS::ScriptError(const char *message)
|
||||
{
|
||||
// TODO
|
||||
|
||||
char *p = _pStartLine;
|
||||
while (*p != '\n')
|
||||
{
|
||||
if (isprint(*p))
|
||||
putchar(*p);
|
||||
else
|
||||
putchar(' ');
|
||||
p++;
|
||||
}
|
||||
|
||||
putchar('\n');
|
||||
|
||||
p = _pStartLine;
|
||||
|
||||
while (p < _pMark)
|
||||
{
|
||||
putchar(' ');
|
||||
p++;
|
||||
}
|
||||
|
||||
puts("^");
|
||||
|
||||
initprintf("Error in %s line %d: %s\n\n", _fileName, _curLine, message);
|
||||
}
|
||||
|
||||
uint8_t RFS::GetNextTag()
|
||||
{
|
||||
// skip any space characters
|
||||
do {
|
||||
Increment();
|
||||
} while (isspace(_curChar));
|
||||
|
||||
if (_curChar == '\0') {
|
||||
return kTagEnd;
|
||||
}
|
||||
|
||||
SetMark();
|
||||
|
||||
// Path A
|
||||
if (_curChar == '"')
|
||||
{
|
||||
Increment();
|
||||
|
||||
int i = 0;
|
||||
|
||||
// section 1
|
||||
while (1) {
|
||||
|
||||
if (_curChar == '\0' || _curChar == '"') {
|
||||
scriptBuffer[i] = '\0';
|
||||
return kTagString;
|
||||
}
|
||||
|
||||
if (i == 256) {
|
||||
ScriptError("String exceeds maximum string length");
|
||||
break;
|
||||
}
|
||||
|
||||
scriptBuffer[i] = _curChar;
|
||||
i++;
|
||||
Increment();
|
||||
}
|
||||
|
||||
// section 2
|
||||
while (1)
|
||||
{
|
||||
if (_curChar == '\0' || _curChar == '"') {
|
||||
return kTag0;
|
||||
}
|
||||
|
||||
Increment();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
scriptValue = 0;
|
||||
BOOL isNegative = FALSE; // or 'isSigned' ?
|
||||
|
||||
// is it a negative number?
|
||||
if (_curChar == '-')
|
||||
{
|
||||
Increment();
|
||||
|
||||
isNegative = TRUE;
|
||||
|
||||
if (!isdigit(_curChar)) {
|
||||
UnsetMark();
|
||||
}
|
||||
}
|
||||
|
||||
if (isdigit(_curChar))
|
||||
{
|
||||
// left path
|
||||
if (_curChar == '0')
|
||||
{
|
||||
Increment();
|
||||
|
||||
// handle a hex value
|
||||
if (toupper(_curChar) == 'X')
|
||||
{
|
||||
// orange loop
|
||||
while (1)
|
||||
{
|
||||
Increment();
|
||||
if (!isxdigit(_curChar)) { // isxdigit() checks for a hex value
|
||||
break;
|
||||
}
|
||||
|
||||
// hex version of atoi?
|
||||
scriptValue *= 16;
|
||||
if (!isdigit(_curChar)) {
|
||||
scriptValue += toupper(_curChar) - 55;
|
||||
}
|
||||
else {
|
||||
scriptValue += _curChar - '0';
|
||||
}
|
||||
|
||||
SetMark();
|
||||
}
|
||||
|
||||
UnsetMark();
|
||||
if (isNegative) {
|
||||
scriptValue = -scriptValue;
|
||||
}
|
||||
|
||||
return kTagConstant;
|
||||
}
|
||||
|
||||
UnsetMark();
|
||||
}
|
||||
|
||||
// the loop
|
||||
while (isdigit(_curChar))
|
||||
{
|
||||
// atoi implementation
|
||||
scriptValue = scriptValue * 10 + _curChar - '0';
|
||||
SetMark();
|
||||
Increment();
|
||||
}
|
||||
|
||||
UnsetMark();
|
||||
if (isNegative) {
|
||||
scriptValue = -scriptValue;
|
||||
}
|
||||
|
||||
return kTagConstant;
|
||||
}
|
||||
else
|
||||
{
|
||||
// BLUEISH PATH
|
||||
int ebp = 0; // v11
|
||||
int i = 0;
|
||||
|
||||
// blue loop #1
|
||||
while (1)
|
||||
{
|
||||
scriptBuffer[ebp] = _curChar;
|
||||
ebp++;
|
||||
int eax = -1;
|
||||
|
||||
// blue loop #2
|
||||
for (i = 0; i < kTagCount; i++)
|
||||
{
|
||||
//if (eax >= 0) {
|
||||
if (eax == 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
// eax = strnicmp(tags[i]._value, scriptBuffer, ebp);
|
||||
eax = strnicmp(scriptBuffer, tags[i]._value, ebp);
|
||||
|
||||
//if (eax >= 0) {
|
||||
if (eax == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (eax > 0 || i == kTagCount) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (eax == 0 && strlen(tags[i]._value) == ebp)
|
||||
{
|
||||
scriptBuffer[ebp] = 0;
|
||||
return tags[i]._index;
|
||||
}
|
||||
|
||||
Increment();
|
||||
}
|
||||
|
||||
UnsetMark();
|
||||
|
||||
i = 0;
|
||||
|
||||
while (isalnum(_curChar))
|
||||
{
|
||||
scriptBuffer[i] = _curChar;
|
||||
SetMark();
|
||||
i++;
|
||||
Increment();
|
||||
}
|
||||
|
||||
UnsetMark();
|
||||
scriptBuffer[i] = 0;
|
||||
return kTag4;
|
||||
}
|
||||
}
|
||||
|
||||
// qAssert(1==0); // TODO - what to return here
|
||||
}
|
||||
|
||||
void ParseScript(char *scriptFileName)
|
||||
{
|
||||
char text[256];
|
||||
char char256_1[256];
|
||||
char char256_2[256];
|
||||
char fileName[BMAX_PATH];
|
||||
char inp[BMAX_PATH];
|
||||
char zScriptDirectory[BMAX_PATH], zTemp1[BMAX_PATH], zTemp2[BMAX_PATH];
|
||||
|
||||
SplitPath(scriptFileName, zScriptDirectory, zTemp1, zTemp2);
|
||||
|
||||
RFS rfs;
|
||||
|
||||
// AddExtension(name, ".RFS");
|
||||
rfs.Open(scriptFileName);
|
||||
|
||||
gParseLevel = 0;
|
||||
dword_44CE0[0] = 0;
|
||||
|
||||
BOOL parsing = TRUE;
|
||||
|
||||
while (parsing)
|
||||
{
|
||||
// START LOOP. to be fixed later
|
||||
START:
|
||||
|
||||
uint8_t tag = rfs.GetNextTag();
|
||||
|
||||
switch (tag)
|
||||
{
|
||||
default:
|
||||
{
|
||||
break;
|
||||
}
|
||||
case kTagEnd:
|
||||
{
|
||||
parsing = FALSE;
|
||||
break;
|
||||
}
|
||||
case kTagComment:
|
||||
{
|
||||
// skip to next line
|
||||
rfs.SkipBeyondValue('\n');
|
||||
break;
|
||||
}
|
||||
case kTagEmit: // minty/light green colour
|
||||
{
|
||||
tag = rfs.GetNextTag();
|
||||
if (tag != kTag4)
|
||||
{
|
||||
rfs.ScriptError("Symbol name expected");
|
||||
rfs.SkipBeyondValue(';');
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
strcpy(char256_2, scriptBuffer);
|
||||
tag = rfs.GetNextTag();
|
||||
if (tag != kTagEquals)
|
||||
{
|
||||
rfs.ScriptError("Missing '='");
|
||||
rfs.SkipBeyondValue(';');
|
||||
break;
|
||||
}
|
||||
|
||||
tag = rfs.GetNextTag();
|
||||
if (tag != kTagConstant)
|
||||
{
|
||||
rfs.ScriptError("Constant expected");
|
||||
rfs.SkipBeyondValue(';');
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
//AddDefine(char256_2, scriptValue);
|
||||
rfs.SkipBeyondValue('\n');
|
||||
}
|
||||
}
|
||||
}
|
||||
case kTagResource: // really light blue..
|
||||
{
|
||||
if (kTagString != rfs.GetNextTag()) {
|
||||
rfs.ScriptError("String constant exected");
|
||||
rfs.SkipBeyondValue('\n');
|
||||
break;
|
||||
}
|
||||
|
||||
strcpy(inp, scriptBuffer);
|
||||
char nFlags = 0;
|
||||
int ID = 0;
|
||||
BOOL isDefine = FALSE;
|
||||
|
||||
tag = rfs.GetNextTag();
|
||||
if (tag == kTagAs)
|
||||
{
|
||||
tag = rfs.GetNextTag();
|
||||
if (tag == kTag4)
|
||||
{
|
||||
strcpy(text, scriptBuffer);
|
||||
|
||||
if (rfs.GetNextTag() != kTagEquals)
|
||||
{
|
||||
rfs.ScriptError("Missing '='");
|
||||
rfs.SkipBeyondValue(';');
|
||||
break;
|
||||
}
|
||||
|
||||
isDefine = TRUE;
|
||||
tag = rfs.GetNextTag();
|
||||
}
|
||||
|
||||
if (tag != kTagConstant)
|
||||
{
|
||||
rfs.ScriptError("Constant expected");
|
||||
rfs.SkipBeyondValue(';');
|
||||
break;
|
||||
}
|
||||
|
||||
if (isDefine) {
|
||||
//AddDefine(text, scriptValue);
|
||||
}
|
||||
|
||||
ID = scriptValue;
|
||||
nFlags |= DICT_ID;
|
||||
tag = rfs.GetNextTag();
|
||||
}
|
||||
|
||||
//if (!bNoEncrypt) {
|
||||
// nFlags |= kResFlagIsEncrypted;
|
||||
//}
|
||||
|
||||
while (tag == kTagComma)
|
||||
{
|
||||
tag = rfs.GetNextTag();
|
||||
|
||||
if (tag == kTagPreload) {
|
||||
nFlags |= DICT_LOAD;
|
||||
}
|
||||
else if (tag == kTagPrelock) {
|
||||
nFlags |= DICT_LOCK;
|
||||
}
|
||||
else {
|
||||
rfs.ScriptError("Unrecognized flag");
|
||||
rfs.SkipBeyondValue(';');
|
||||
goto START; // FIXME
|
||||
}
|
||||
|
||||
tag = rfs.GetNextTag();
|
||||
}
|
||||
|
||||
if (tag != kTagSemiColon)
|
||||
{
|
||||
rfs.ScriptError("';' expected");
|
||||
rfs.SkipBeyondValue(';');
|
||||
break;
|
||||
}
|
||||
|
||||
if (dword_44CE0[gParseLevel] == 0) {
|
||||
sub_11C10(zScriptDirectory, inp, nFlags, ID);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case kTagIfDef: // purplish colour
|
||||
{
|
||||
tag = rfs.GetNextTag();
|
||||
if (tag != kTag4)
|
||||
{
|
||||
rfs.ScriptError("Parameter error in ifdef");
|
||||
rfs.SkipBeyondValue('\n');
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
rfs.SetMark();
|
||||
strcpy(char256_1, scriptBuffer);
|
||||
|
||||
BOOL bGotDefine = FALSE;
|
||||
|
||||
// check if this was defined via command prompt arguments
|
||||
for (int i = 0; i < nCmdDefines; i++)
|
||||
{
|
||||
if (stricmp(gCmdDefines[i]._text, char256_1) == 0) { // string is equivalent
|
||||
bGotDefine = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// loc_11FC3:
|
||||
gParseLevel++;
|
||||
dassert(gParseLevel < kMaxParseLevels);
|
||||
|
||||
if (bGotDefine) {
|
||||
dword_44CE0[gParseLevel] = dword_44CE0[gParseLevel - 1];
|
||||
}
|
||||
else {
|
||||
dword_44CE0[gParseLevel] = 1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case kTagElse: // pinky colour
|
||||
{
|
||||
if (gParseLevel)
|
||||
{
|
||||
// loc_12066:
|
||||
if (dword_44CE0[gParseLevel - 1] == 0) {
|
||||
if (dword_44CE0[gParseLevel] == 0) {
|
||||
dword_44CE0[gParseLevel] = 1;
|
||||
}
|
||||
|
||||
rfs.SkipBeyondValue('\n');
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
rfs.ScriptError("Unexpected else");
|
||||
rfs.SkipBeyondValue('\n');
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case kTagEndif: // poo coloured
|
||||
{
|
||||
if (gParseLevel) {
|
||||
gParseLevel--;
|
||||
rfs.SkipBeyondValue('\n');
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
rfs.ScriptError("Unexpected Endif");
|
||||
rfs.SkipBeyondValue('\n');
|
||||
break;
|
||||
}
|
||||
}
|
||||
case kTagHash: // gold colour
|
||||
{
|
||||
tag = rfs.GetNextTag();
|
||||
if (tag == kTagInclude)
|
||||
{
|
||||
tag = rfs.GetNextTag();
|
||||
if (tag != kTagString)
|
||||
{
|
||||
rfs.ScriptError("String constant exected");
|
||||
// why no SkipBeyondValue?
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
ParseScript(scriptBuffer);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case kTagData: // eg: data "AMB1.SFX" as 1: 80, 0x10000, 0x0, 1, -1, "amb1";
|
||||
{
|
||||
// green coloured section
|
||||
if (rfs.GetNextTag() != kTagString) {
|
||||
rfs.ScriptError("String constant expected");
|
||||
rfs.SkipBeyondValue(';');
|
||||
break;
|
||||
}
|
||||
|
||||
// eg strcpy(fileName, "AMB1.SFX");
|
||||
strcpy(fileName, scriptBuffer);
|
||||
|
||||
char nFlags = 0;
|
||||
int ID = 0;
|
||||
|
||||
BOOL isDefine = FALSE;
|
||||
|
||||
tag = rfs.GetNextTag();
|
||||
|
||||
// process an ID section
|
||||
if (tag == kTagAs)
|
||||
{
|
||||
tag = rfs.GetNextTag();
|
||||
if (tag == kTag4)
|
||||
{
|
||||
strcpy(fileName, scriptBuffer);
|
||||
|
||||
tag = rfs.GetNextTag();
|
||||
if (tag != kTagEquals) {
|
||||
rfs.ScriptError("Missing '='");
|
||||
rfs.SkipBeyondValue(';');
|
||||
break;
|
||||
}
|
||||
|
||||
isDefine = TRUE;
|
||||
tag = rfs.GetNextTag();
|
||||
}
|
||||
|
||||
if (tag != kTagConstant)
|
||||
{
|
||||
rfs.ScriptError("Constant Expected");
|
||||
rfs.SkipBeyondValue(';');
|
||||
break;
|
||||
}
|
||||
else {
|
||||
//if (isDefine) {
|
||||
// AddDefine(fileName, scriptValue);
|
||||
//}
|
||||
|
||||
nFlags |= DICT_ID;
|
||||
ID = scriptValue;
|
||||
tag = rfs.GetNextTag();
|
||||
}
|
||||
}
|
||||
|
||||
if (tag == kTagComma)
|
||||
{
|
||||
// process all sections on this line that are comma separated
|
||||
while (1)
|
||||
{
|
||||
tag = rfs.GetNextTag();
|
||||
if (tag == kTagPreload)
|
||||
{
|
||||
nFlags |= DICT_LOAD;
|
||||
tag = rfs.GetNextTag();
|
||||
|
||||
if (tag == kTagComma) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else if (tag == kTagPrelock)
|
||||
{
|
||||
nFlags |= DICT_LOCK;
|
||||
tag = rfs.GetNextTag();
|
||||
|
||||
if (tag == kTagComma) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
rfs.ScriptError("Unrecognized flag");
|
||||
rfs.SkipBeyondValue(';');
|
||||
goto START; // FIXME
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// loc_12471:
|
||||
if (tag != kTagColon) // marked orange in IDA
|
||||
{
|
||||
while (1)
|
||||
{
|
||||
if (tag == kTagPreload)
|
||||
{
|
||||
nFlags |= DICT_LOAD;
|
||||
tag = rfs.GetNextTag();
|
||||
|
||||
if (tag == kTagColon) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (tag == kTagPrelock)
|
||||
{
|
||||
nFlags |= DICT_LOCK;
|
||||
tag = rfs.GetNextTag();
|
||||
|
||||
if (tag == kTagColon) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
rfs.ScriptError("':' expected");
|
||||
rfs.SkipBeyondValue(';');
|
||||
goto START; // FIXME
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
nBytes = 0;
|
||||
|
||||
// yellow loop
|
||||
while (1)
|
||||
{
|
||||
tag = rfs.GetNextTag();
|
||||
|
||||
switch (tag)
|
||||
{
|
||||
case kTagString:
|
||||
{
|
||||
memcpy(&buffer[nBytes], scriptBuffer, strlen(scriptBuffer) + 1);
|
||||
nBytes += strlen(scriptBuffer) + 1;
|
||||
break;
|
||||
}
|
||||
case kTagConstant:
|
||||
{
|
||||
memcpy(&buffer[nBytes], &scriptValue, sizeof(scriptValue));
|
||||
nBytes += sizeof(scriptValue);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
rfs.ScriptError("Constant expected");
|
||||
rfs.SkipBeyondValue(';');
|
||||
goto START; // FIXME
|
||||
}
|
||||
}
|
||||
|
||||
tag = rfs.GetNextTag();
|
||||
if (tag != kTagComma) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (tag != kTagSemiColon) {
|
||||
rfs.ScriptError("Semicolon expected");
|
||||
rfs.SkipBeyondValue(';');
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (dword_44CE0[gParseLevel] == 0) {
|
||||
sub_11DF0(zScriptDirectory, fileName, nFlags, ID);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//CreateHeader();
|
||||
rfs.Close();
|
||||
}
|
||||
|
||||
void sub_11C10(char *pzScriptDir, char *fileName, char flags, int ID)
|
||||
{
|
||||
char zDirectory[BMAX_PATH];
|
||||
char zFilename[BMAX_PATH];
|
||||
char zType[BMAX_PATH];
|
||||
BDIR* dirr;
|
||||
struct Bdirent* dirent;
|
||||
dirr = Bopendir("./");
|
||||
if (dirr)
|
||||
{
|
||||
while (dirent = Breaddir(dirr))
|
||||
{
|
||||
if (!Bwildmatch(dirent->name, fileName))
|
||||
continue;
|
||||
|
||||
SplitPath(dirent->name, zDirectory, zFilename, zType);
|
||||
|
||||
if (!Bstrcasecmp(zType, "RAW") || !Bstrcasecmp(zType, "SFX") || !Bstrcasecmp(zType, "MID") || !Bstrcasecmp(zType, "TMB"))
|
||||
gSoundRes.AddExternalResource(zFilename, zType, ID, flags, dirent->name);
|
||||
else
|
||||
gSysRes.AddExternalResource(zFilename, zType, ID, flags, dirent->name);
|
||||
}
|
||||
Bclosedir(dirr);
|
||||
}
|
||||
dirr = Bopendir(pzScriptDir);
|
||||
if (dirr)
|
||||
{
|
||||
while (dirent = Breaddir(dirr))
|
||||
{
|
||||
if (!Bwildmatch(dirent->name, fileName))
|
||||
continue;
|
||||
|
||||
SplitPath(dirent->name, zDirectory, zFilename, zType);
|
||||
|
||||
if (!Bstrcasecmp(zType, "RAW") || !Bstrcasecmp(zType, "SFX") || !Bstrcasecmp(zType, "MID") || !Bstrcasecmp(zType, "TMB"))
|
||||
gSoundRes.AddExternalResource(zFilename, zType, ID, flags, dirent->name);
|
||||
else
|
||||
gSysRes.AddExternalResource(zFilename, zType, ID, flags, dirent->name);
|
||||
}
|
||||
Bclosedir(dirr);
|
||||
}
|
||||
}
|
||||
|
||||
void sub_11DF0(char* pzScriptDir, char *filePath, char flags, int ID)
|
||||
{
|
||||
char zDirectory[BMAX_PATH];
|
||||
char zFilename[BMAX_PATH];
|
||||
char zType[BMAX_PATH];
|
||||
char zFilePath[BMAX_PATH];
|
||||
buildvfs_fd handle;
|
||||
|
||||
ConcatPath(pzScriptDir, filePath, zFilePath);
|
||||
|
||||
handle = kopen4loadfrommod(zFilePath, 0);
|
||||
if (handle == buildvfs_fd_invalid)
|
||||
{
|
||||
Bstrcpy(zFilePath, filePath);
|
||||
handle = kopen4loadfrommod(zFilePath, 0);
|
||||
if (handle == buildvfs_fd_invalid)
|
||||
return;
|
||||
}
|
||||
|
||||
kclose(handle);
|
||||
|
||||
SplitPath(zFilePath, zDirectory, zFilename, zType);
|
||||
|
||||
if (!Bstrcasecmp(zType, "RAW") || !Bstrcasecmp(zType, "SFX") || !Bstrcasecmp(zType, "MID") || !Bstrcasecmp(zType, "TMB"))
|
||||
gSoundRes.AddExternalResource(zFilename, zType, ID, flags, zFilePath);
|
||||
else
|
||||
gSysRes.AddExternalResource(zFilename, zType, ID, flags, zFilePath);
|
||||
}
|
||||
|
24
source/blood/src/barf.h
Normal file
24
source/blood/src/barf.h
Normal file
|
@ -0,0 +1,24 @@
|
|||
//-------------------------------------------------------------------------
|
||||
/*
|
||||
Copyright (C) 2010-2019 EDuke32 developers and contributors
|
||||
Copyright (C) 2019 sirlemonhead, Nuke.YKT
|
||||
|
||||
This file is part of NBlood.
|
||||
|
||||
NBlood is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License version 2
|
||||
as published by the Free Software Foundation.
|
||||
|
||||
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
//-------------------------------------------------------------------------
|
||||
#pragma once
|
||||
|
|
@ -131,11 +131,80 @@ void ChangeExtension(char *pzFile, const char *pzExt)
|
|||
_splitpath(pzFile, drive, dir, filename, NULL);
|
||||
_makepath(pzFile, drive, dir, filename, pzExt);
|
||||
#else
|
||||
char *pDot = strrchr(pzFile, '.');
|
||||
if (!pDot)
|
||||
pDot = pzFile + strlen(pzFile);
|
||||
else
|
||||
*pDot = 0;
|
||||
strcat(pDot, pzExt);
|
||||
int const nLength = Bstrlen(pzFile);
|
||||
char * pDot = pzFile+nLength;
|
||||
for (int i = nLength-1; i >= 0; i--)
|
||||
{
|
||||
if (pzFile[i] == '/' || pzFile[i] == '\\')
|
||||
break;
|
||||
if (pzFile[i] == '.')
|
||||
{
|
||||
pDot = pzFile+i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
*pDot = '\0';
|
||||
Bstrcat(pDot, pzExt);
|
||||
#endif
|
||||
}
|
||||
|
||||
void SplitPath(const char *pzPath, char *pzDirectory, char *pzFile, char *pzType)
|
||||
{
|
||||
int const nLength = Bstrlen(pzFile);
|
||||
const char *pDirectory = pzFile+nLength;
|
||||
const char *pDot = NULL;
|
||||
for (int i = nLength-1; i >= 0; i--)
|
||||
{
|
||||
if (pzFile[i] == '/' || pzFile[i] == '\\')
|
||||
{
|
||||
Bstrncpy(pzDirectory, pzPath, i);
|
||||
pzDirectory[i] = 0;
|
||||
if (!pDot)
|
||||
{
|
||||
Bstrcpy(pzFile, pzPath+i+1);
|
||||
Bstrcpy(pzType, "");
|
||||
}
|
||||
else
|
||||
{
|
||||
Bstrncpy(pzFile, pzPath+i+1, pDot-(pzPath+i+1));
|
||||
Bstrcpy(pzType, pDot+1);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
else if (pzFile[i] == '.')
|
||||
{
|
||||
pDot = pzFile+i;
|
||||
}
|
||||
}
|
||||
Bstrcpy(pzDirectory, "/");
|
||||
if (!pDot)
|
||||
{
|
||||
Bstrcpy(pzFile, pzPath);
|
||||
Bstrcpy(pzType, "");
|
||||
}
|
||||
else
|
||||
{
|
||||
Bstrncpy(pzFile, pzPath, pDot-pzPath);
|
||||
Bstrcpy(pzType, pDot+1);
|
||||
}
|
||||
}
|
||||
|
||||
void ConcatPath(const char *pzPath1, const char *pzPath2, char *pzConcatPath)
|
||||
{
|
||||
int n1 = Bstrlen(pzPath1), n2 = Bstrlen(pzPath2);
|
||||
int i = n1, j = 0;
|
||||
while (i > 0 && (pzPath1[i-1] == '/' || pzPath1[i-1] == '\\'))
|
||||
{
|
||||
i--;
|
||||
}
|
||||
while (j < n2 && (pzPath2[j] == '/' || pzPath1[j] == '\\'))
|
||||
{
|
||||
j++;
|
||||
}
|
||||
Bstrncpy(pzConcatPath, pzPath1, i);
|
||||
pzConcatPath[i] = 0;
|
||||
Bstrcpy(pzConcatPath, pzPath2+j);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -30,3 +30,5 @@ unsigned int qrand(void);
|
|||
int wrand(void);
|
||||
void wsrand(int);
|
||||
void ChangeExtension(char *pzFile, const char *pzExt);
|
||||
void SplitPath(const char *pzPath, char *pzDirectory, char *pzFile, char *pzType);
|
||||
void ConcatPath(const char* pzPath1, const char* pzPath2, char* pzConcatPath);
|
||||
|
|
|
@ -68,6 +68,8 @@ Resource::~Resource(void)
|
|||
Free(dict[i].type);
|
||||
if (dict[i].name)
|
||||
Free(dict[i].name);
|
||||
if (dict[i].path)
|
||||
Free(dict[i].path);
|
||||
}
|
||||
Free(dict);
|
||||
dict = NULL;
|
||||
|
@ -149,6 +151,7 @@ void Resource::Init(const char *filename)
|
|||
dict[i].name = (char*)Alloc(nNameLength+1);
|
||||
strncpy(dict[i].type, tdict[i].type, min(3, nTypeLength));
|
||||
strncpy(dict[i].name, tdict[i].name, min(8, nNameLength));
|
||||
dict[i].path = NULL;
|
||||
dict[i].type[nTypeLength] = 0;
|
||||
dict[i].name[nNameLength] = 0;
|
||||
dict[i].id = B_LITTLE32(tdict[i].id);
|
||||
|
@ -362,14 +365,20 @@ void Resource::Grow(void)
|
|||
Reindex();
|
||||
}
|
||||
|
||||
void Resource::AddExternalResource(const char *name, const char *type, int id)
|
||||
void Resource::AddExternalResource(const char *name, const char *type, int id, int flags, const char *pzDirectory)
|
||||
{
|
||||
char name2[BMAX_PATH], type2[BMAX_PATH], filename[BMAX_PATH*2];
|
||||
//if (strlen(name) > 8 || strlen(type) > 3) return;
|
||||
char name2[BMAX_PATH], type2[BMAX_PATH], filename[BMAX_PATH], path[BMAX_PATH];
|
||||
|
||||
if (Bstrlen(type) > 0)
|
||||
Bsprintf(filename, "%s.%s", name, type);
|
||||
Bsnprintf(filename, BMAX_PATH-1, "%s.%s", name, type);
|
||||
else
|
||||
Bsprintf(filename, "%s", name);
|
||||
Bsnprintf(filename, BMAX_PATH-1, "%s", name);
|
||||
|
||||
if (pzDirectory)
|
||||
Bsnprintf(path, BMAX_PATH-1, "%s/%s", pzDirectory, filename);
|
||||
else
|
||||
Bstrncpy(path, filename, BMAX_PATH-1);
|
||||
|
||||
int fhandle = kopen4loadfrommod(filename, 0);
|
||||
if (fhandle == -1)
|
||||
return;
|
||||
|
@ -404,17 +413,25 @@ void Resource::AddExternalResource(const char *name, const char *type, int id)
|
|||
Free(node->name);
|
||||
node->name = NULL;
|
||||
}
|
||||
if (node->path)
|
||||
{
|
||||
Free(node->path);
|
||||
node->path = NULL;
|
||||
}
|
||||
int nTypeLength = strlen(type2);
|
||||
int nNameLength = strlen(name2);
|
||||
int nPathLength = strlen(path);
|
||||
node->type = (char*)Alloc(nTypeLength+1);
|
||||
node->name = (char*)Alloc(nNameLength+1);
|
||||
node->path = (char*)Alloc(nPathLength+1);
|
||||
strcpy(node->type, type2);
|
||||
strcpy(node->name, name2);
|
||||
strcpy(node->path, path);
|
||||
}
|
||||
node->size = size;
|
||||
node->flags |= DICT_EXTERNAL;
|
||||
node->flags |= DICT_EXTERNAL | flags;
|
||||
Flush(node);
|
||||
if (id != -1)
|
||||
if (id >= 0)
|
||||
{
|
||||
index = Probe(id, type2);
|
||||
dassert(index != NULL);
|
||||
|
@ -439,15 +456,23 @@ void Resource::AddExternalResource(const char *name, const char *type, int id)
|
|||
Free(node->name);
|
||||
node->name = NULL;
|
||||
}
|
||||
if (node->path)
|
||||
{
|
||||
Free(node->path);
|
||||
node->path = NULL;
|
||||
}
|
||||
int nTypeLength = strlen(type2);
|
||||
int nNameLength = strlen(name2);
|
||||
int nPathLength = strlen(path);
|
||||
node->type = (char*)Alloc(nTypeLength+1);
|
||||
node->name = (char*)Alloc(nNameLength+1);
|
||||
node->path = (char*)Alloc(nPathLength+1);
|
||||
strcpy(node->type, type2);
|
||||
strcpy(node->name, name2);
|
||||
strcpy(node->path, path);
|
||||
node->id = id;
|
||||
node->size = size;
|
||||
node->flags |= DICT_EXTERNAL;
|
||||
node->flags |= DICT_EXTERNAL | flags;
|
||||
Flush(node);
|
||||
}
|
||||
}
|
||||
|
@ -550,7 +575,10 @@ void Resource::Read(DICTNODE *n, void *p)
|
|||
dassert(n != NULL);
|
||||
if (n->flags & DICT_EXTERNAL)
|
||||
{
|
||||
sprintf(filename, "%s.%s", n->name, n->type);
|
||||
if (n->path)
|
||||
Bstrncpy(filename, n->path, BMAX_PATH-1);
|
||||
else
|
||||
Bsnprintf(filename, MAX_PATH-1, "%s.%s", n->name, n->type);
|
||||
int fhandle = kopen4loadfrommod(filename, 0);
|
||||
if (fhandle == -1 || (uint32_t)kread(fhandle, p, n->size) != n->size)
|
||||
{
|
||||
|
@ -814,6 +842,11 @@ void Resource::RemoveNode(DICTNODE* pNode)
|
|||
Free(pNode->type);
|
||||
pNode->type = NULL;
|
||||
}
|
||||
if (pNode->path)
|
||||
{
|
||||
Free(pNode->path);
|
||||
pNode->path = NULL;
|
||||
}
|
||||
*pNode = dict[--count];
|
||||
Bmemset(&dict[count], 0, sizeof(DICTNODE));
|
||||
if (pNode->ptr && !pNode->lockCount)
|
||||
|
|
|
@ -76,6 +76,7 @@ struct DICTNODE : CACHENODE
|
|||
//char name[8];
|
||||
char *type;
|
||||
char *name;
|
||||
char *path;
|
||||
unsigned int id;
|
||||
};
|
||||
|
||||
|
@ -92,7 +93,7 @@ public:
|
|||
DICTNODE **Probe(unsigned int id, const char *type);
|
||||
void Reindex(void);
|
||||
void Grow(void);
|
||||
void AddExternalResource(const char *name, const char *type, int id = -1);
|
||||
void AddExternalResource(const char *name, const char *type, int id = 0, int flags = 0, const char* pzDirectory = NULL);
|
||||
static void *Alloc(int nSize);
|
||||
static void Free(void *p);
|
||||
DICTNODE *Lookup(const char *name, const char *type);
|
||||
|
|
Loading…
Reference in a new issue