- ZDoom implementation of strcpy, submitted by FDARI.

SVN r3227 (trunk)
This commit is contained in:
Christoph Oelckers 2011-06-13 09:14:02 +00:00
parent e6de6fed3c
commit 74ad869e62
2 changed files with 174 additions and 11 deletions

View file

@ -1721,6 +1721,25 @@ void FBehavior::SetArrayVal (int arraynum, int index, int value)
array->Elements[index] = value;
}
inline bool FBehavior::CopyStringToArray(int arraynum, int index, int maxLength, const char *string)
{
// false if the operation was incomplete or unsuccessful
if ((unsigned)arraynum >= (unsigned)NumTotalArrays || index < 0)
return false;
const ArrayInfo *array = Arrays[arraynum];
if ((signed)array->ArraySize - index < maxLength) maxLength = (signed)array->ArraySize - index;
while (maxLength-- > 0)
{
array->Elements[index++] = *string;
if (!(*string)) return true; // written terminating 0
string++;
}
return !(*string); // return true if only terminating 0 was not written
}
BYTE *FBehavior::FindChunk (DWORD id) const
{
BYTE *chunk = Chunks;
@ -5112,43 +5131,101 @@ int DLevelScript::RunScript ()
// [JB] Print map character array
case PCD_PRINTMAPCHARARRAY:
case PCD_PRINTMAPCHRANGE:
{
int capacity, offset;
if (pcd == PCD_PRINTMAPCHRANGE)
{
capacity = STACK(1);
offset = STACK(2);
if (capacity < 1 || offset < 0)
{
sp -= 4;
break;
}
sp -= 2;
}
else
{
capacity = 0x7FFFFFFF;
offset = 0;
}
int a = *(activeBehavior->MapVars[STACK(1)]);
int offset = STACK(2);
offset += STACK(2);
int c;
while((c = activeBehavior->GetArrayVal (a, offset)) != '\0') {
while(capacity-- && (c = activeBehavior->GetArrayVal (a, offset)) != '\0') {
work += (char)c;
offset++;
}
sp-=2;
sp-= 2;
}
break;
// [JB] Print world character array
case PCD_PRINTWORLDCHARARRAY:
case PCD_PRINTWORLDCHRANGE:
{
int capacity, offset;
if (pcd == PCD_PRINTWORLDCHRANGE)
{
capacity = STACK(1);
offset = STACK(2);
if (capacity < 1 || offset < 0)
{
sp -= 4;
break;
}
sp -= 2;
}
else
{
capacity = 0x7FFFFFFF;
offset = 0;
}
int a = STACK(1);
int offset = STACK(2);
offset += STACK(2);
int c;
while((c = ACS_WorldArrays[a][offset]) != '\0') {
while(capacity-- && (c = ACS_WorldArrays[a][offset]) != '\0') {
work += (char)c;
offset++;
}
sp-=2;
sp-= 2;
}
break;
// [JB] Print global character array
case PCD_PRINTGLOBALCHARARRAY:
case PCD_PRINTGLOBALCHRANGE:
{
int capacity, offset;
if (pcd == PCD_PRINTGLOBALCHRANGE)
{
capacity = STACK(1);
offset = STACK(2);
if (capacity < 1 || offset < 0)
{
sp -= 4;
break;
}
sp -= 2;
}
else
{
capacity = 0x7FFFFFFF;
offset = 0;
}
int a = STACK(1);
int offset = STACK(2);
offset += STACK(2);
int c;
while((c = ACS_GlobalArrays[a][offset]) != '\0') {
while(capacity-- && (c = ACS_GlobalArrays[a][offset]) != '\0') {
work += (char)c;
offset++;
}
sp-=2;
sp-= 2;
}
break;
@ -6731,6 +6808,84 @@ int DLevelScript::RunScript ()
}
break;
case PCD_STRCPYTOMAPCHRANGE:
case PCD_STRCPYTOWORLDCHRANGE:
case PCD_STRCPYTOGLOBALCHRANGE:
// source: stringid(2); stringoffset(1)
// destination: capacity (3); stringoffset(4); arrayid (5); offset(6)
{
int index = STACK(4);
int capacity = STACK(3);
if (index < 0 || STACK(1) < 0)
{
// no writable destination, or negative offset to source string
sp -= 5;
Stack[sp-1] = 0; // false
break;
}
index += STACK(6);
lookup = FBehavior::StaticLookupString (STACK(2));
if (!lookup) {
// no data, operation complete
STRCPYTORANGECOMPLETE:
sp -= 5;
Stack[sp-1] = 1; // true
break;
}
for (int i = 0;i < STACK(1); i++)
{
if (! (*(lookup++)))
{
// no data, operation complete
goto STRCPYTORANGECOMPLETE;
}
}
switch (pcd)
{
case PCD_STRCPYTOMAPCHRANGE:
{
Stack[sp-6] = activeBehavior->CopyStringToArray(STACK(5), index, capacity, lookup);
}
break;
case PCD_STRCPYTOWORLDCHRANGE:
{
int a = STACK(5);
while (capacity-- > 0)
{
ACS_WorldArrays[a][index++] = *lookup;
if (! (*(lookup++))) goto STRCPYTORANGECOMPLETE; // complete with terminating 0
}
Stack[sp-6] = !(*lookup); // true/success if only terminating 0 was not copied
}
break;
case PCD_STRCPYTOGLOBALCHRANGE:
{
int a = STACK(5);
while (capacity-- > 0)
{
ACS_GlobalArrays[a][index++] = *lookup;
if (! (*(lookup++))) goto STRCPYTORANGECOMPLETE; // complete with terminating 0
}
Stack[sp-6] = !(*lookup); // true/success if only terminating 0 was not copied
}
break;
}
sp -= 5;
}
break;
}
}

View file

@ -168,6 +168,8 @@ public:
ScriptFunction *GetFunction (int funcnum, FBehavior *&module) const;
int GetArrayVal (int arraynum, int index) const;
void SetArrayVal (int arraynum, int index, int value);
inline bool CopyStringToArray(int arraynum, int index, int maxLength, const char * string);
int FindFunctionName (const char *funcname) const;
int FindMapVarName (const char *varname) const;
int FindMapArray (const char *arrayname) const;
@ -587,9 +589,15 @@ public:
PCD_PRINTBINARY,
/*350*/ PCD_PRINTHEX,
PCD_CALLFUNC,
PCD_SAVESTRING, // [FDARI]
PCD_SAVESTRING, // [FDARI] create string (temporary)
PCD_PRINTMAPCHRANGE, // [FDARI] output range (print part of array)
PCD_PRINTWORLDCHRANGE,
PCD_PRINTGLOBALCHRANGE,
PCD_STRCPYTOMAPCHRANGE, // [FDARI] input range (copy string to all/part of array)
PCD_STRCPYTOWORLDCHRANGE,
PCD_STRCPYTOGLOBALCHRANGE,
/*353*/ PCODE_COMMAND_COUNT
/*359*/ PCODE_COMMAND_COUNT
};
// Some constants used by ACS scripts