Initial commit
This commit is contained in:
85
engines/ags/shared/script/cc_common.cpp
Normal file
85
engines/ags/shared/script/cc_common.cpp
Normal file
@@ -0,0 +1,85 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "common/std/utility.h"
|
||||
#include "ags/shared/script/cc_common.h"
|
||||
#include "ags/shared/util/string.h"
|
||||
#include "ags/globals.h"
|
||||
|
||||
namespace AGS3 {
|
||||
|
||||
using namespace AGS::Shared;
|
||||
|
||||
void ccSetOption(int optbit, int onoroff) {
|
||||
if (onoroff)
|
||||
_G(ccCompOptions) |= optbit;
|
||||
else
|
||||
_G(ccCompOptions) &= ~optbit;
|
||||
}
|
||||
|
||||
int ccGetOption(int optbit) {
|
||||
if (_G(ccCompOptions) & optbit)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void cc_clear_error() {
|
||||
_GP(ccError) = ScriptError();
|
||||
}
|
||||
|
||||
bool cc_has_error() {
|
||||
return _GP(ccError).HasError;
|
||||
}
|
||||
|
||||
const ScriptError &cc_get_error() {
|
||||
return _GP(ccError);
|
||||
}
|
||||
|
||||
String cc_get_err_callstack(int max_lines) {
|
||||
return cc_has_error() ? _GP(ccError).CallStack : cc_get_callstack(max_lines);
|
||||
}
|
||||
|
||||
void cc_error(const char *descr, ...) {
|
||||
_GP(ccError).IsUserError = false;
|
||||
if (descr[0] == '!') {
|
||||
_GP(ccError).IsUserError = true;
|
||||
descr++;
|
||||
}
|
||||
|
||||
va_list ap;
|
||||
va_start(ap, descr);
|
||||
String displbuf = String::FromFormatV(descr, ap);
|
||||
va_end(ap);
|
||||
|
||||
// TODO: because this global ccError is a global shared variable,
|
||||
// we have to use project-dependent function to format the final message
|
||||
_GP(ccError).ErrorString = cc_format_error(displbuf);
|
||||
_GP(ccError).CallStack = cc_get_callstack();
|
||||
_GP(ccError).HasError = 1;
|
||||
_GP(ccError).Line = _G(currentline);
|
||||
}
|
||||
|
||||
void cc_error(const ScriptError &err) {
|
||||
_GP(ccError) = err;
|
||||
}
|
||||
|
||||
} // namespace AGS3
|
||||
67
engines/ags/shared/script/cc_common.h
Normal file
67
engines/ags/shared/script/cc_common.h
Normal file
@@ -0,0 +1,67 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
// Script options and error reporting.
|
||||
|
||||
#ifndef AGS_SHARED_SCRIPT_CC_COMMON_H
|
||||
#define AGS_SHARED_SCRIPT_CC_COMMON_H
|
||||
|
||||
#include "ags/shared/util/string.h"
|
||||
|
||||
namespace AGS3 {
|
||||
|
||||
#define SCOPT_EXPORTALL 1 // export all functions automatically
|
||||
#define SCOPT_SHOWWARNINGS 2 // printf warnings to console
|
||||
#define SCOPT_LINENUMBERS 4 // include line numbers in compiled code
|
||||
#define SCOPT_AUTOIMPORT 8 // when creating instance, export funcs to other scripts
|
||||
#define SCOPT_DEBUGRUN 0x10 // write instructions as they are procssed to log file
|
||||
#define SCOPT_NOIMPORTOVERRIDE 0x20 // do not allow an import to be re-declared
|
||||
#define SCOPT_LEFTTORIGHT 0x40 // left-to-right operator precedance
|
||||
#define SCOPT_OLDSTRINGS 0x80 // allow old-style strings
|
||||
#define SCOPT_UTF8 0x100 // UTF-8 text mode
|
||||
|
||||
extern void ccSetOption(int, int);
|
||||
extern int ccGetOption(int);
|
||||
|
||||
// error reporting
|
||||
|
||||
struct ScriptError {
|
||||
bool HasError = false; // set if error occurs
|
||||
bool IsUserError = false; // marks script use errors
|
||||
AGS::Shared::String ErrorString; // description of the error
|
||||
int Line = 0; // line number of the error
|
||||
AGS::Shared::String CallStack; // callstack where error happened
|
||||
};
|
||||
|
||||
void cc_clear_error();
|
||||
bool cc_has_error();
|
||||
const ScriptError &cc_get_error();
|
||||
// Returns callstack of the last recorded script error, or a callstack
|
||||
// of a current execution point, if no script error is currently saved in memory.
|
||||
AGS::Shared::String cc_get_err_callstack(int max_lines = INT_MAX);
|
||||
void cc_error(const char *, ...);
|
||||
void cc_error(const ScriptError &err);
|
||||
// Project-dependent script error formatting
|
||||
AGS::Shared::String cc_format_error(const AGS::Shared::String &message);
|
||||
|
||||
} // namespace AGS3
|
||||
|
||||
#endif
|
||||
134
engines/ags/shared/script/cc_internal.h
Normal file
134
engines/ags/shared/script/cc_internal.h
Normal file
@@ -0,0 +1,134 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef AGS_SHARED_SCRIPT_CC_INTERNAL_H
|
||||
#define AGS_SHARED_SCRIPT_CC_INTERNAL_H
|
||||
|
||||
namespace AGS3 {
|
||||
|
||||
#define SCOM_VERSION 90
|
||||
#define SCOM_VERSIONSTR "0.90"
|
||||
|
||||
// virtual CPU registers
|
||||
#define SREG_SP 1 // stack pointer
|
||||
#define SREG_MAR 2 // memory address register
|
||||
#define SREG_AX 3 // general purpose
|
||||
#define SREG_BX 4
|
||||
#define SREG_CX 5
|
||||
#define SREG_OP 6 // object pointer for member func calls
|
||||
#define SREG_DX 7
|
||||
#define CC_NUM_REGISTERS 8
|
||||
|
||||
// virtual CPU commands
|
||||
#define SCMD_ADD 1 // reg1 += arg2
|
||||
#define SCMD_SUB 2 // reg1 -= arg2
|
||||
#define SCMD_REGTOREG 3 // reg2 = reg1
|
||||
#define SCMD_WRITELIT 4 // m[MAR] = arg2 (copy arg1 bytes)
|
||||
#define SCMD_RET 5 // return from subroutine
|
||||
#define SCMD_LITTOREG 6 // set reg1 to literal value arg2
|
||||
#define SCMD_MEMREAD 7 // reg1 = m[MAR]
|
||||
#define SCMD_MEMWRITE 8 // m[MAR] = reg1
|
||||
#define SCMD_MULREG 9 // reg1 *= reg2
|
||||
#define SCMD_DIVREG 10 // reg1 /= reg2
|
||||
#define SCMD_ADDREG 11 // reg1 += reg2
|
||||
#define SCMD_SUBREG 12 // reg1 -= reg2
|
||||
#define SCMD_BITAND 13 // bitwise reg1 & reg2
|
||||
#define SCMD_BITOR 14 // bitwise reg1 | reg2
|
||||
#define SCMD_ISEQUAL 15 // reg1 == reg2 reg1=1 if true, =0 if not
|
||||
#define SCMD_NOTEQUAL 16 // reg1 != reg2
|
||||
#define SCMD_GREATER 17 // reg1 > reg2
|
||||
#define SCMD_LESSTHAN 18 // reg1 < reg2
|
||||
#define SCMD_GTE 19 // reg1 >= reg2
|
||||
#define SCMD_LTE 20 // reg1 <= reg2
|
||||
#define SCMD_AND 21 // (reg1!=0) && (reg2!=0) -> reg1
|
||||
#define SCMD_OR 22 // (reg1!=0) || (reg2!=0) -> reg1
|
||||
#define SCMD_CALL 23 // jump to subroutine at reg1
|
||||
#define SCMD_MEMREADB 24 // reg1 = m[MAR] (1 byte)
|
||||
#define SCMD_MEMREADW 25 // reg1 = m[MAR] (2 bytes)
|
||||
#define SCMD_MEMWRITEB 26 // m[MAR] = reg1 (1 byte)
|
||||
#define SCMD_MEMWRITEW 27 // m[MAR] = reg1 (2 bytes)
|
||||
#define SCMD_JZ 28 // jump if ax==0 to arg1
|
||||
#define SCMD_PUSHREG 29 // m[sp]=reg1; sp++
|
||||
#define SCMD_POPREG 30 // sp--; reg1=m[sp]
|
||||
#define SCMD_JMP 31 // jump to arg1
|
||||
#define SCMD_MUL 32 // reg1 *= arg2
|
||||
#define SCMD_CALLEXT 33 // call external (imported) function reg1
|
||||
#define SCMD_PUSHREAL 34 // push reg1 onto real stack
|
||||
#define SCMD_SUBREALSTACK 35 // decrement stack ptr by literal
|
||||
#define SCMD_LINENUM 36 // debug info - source code line number
|
||||
#define SCMD_CALLAS 37 // call external script function
|
||||
#define SCMD_THISBASE 38 // current relative address
|
||||
#define SCMD_NUMFUNCARGS 39 // number of arguments for ext func call
|
||||
#define SCMD_MODREG 40 // reg1 %= reg2
|
||||
#define SCMD_XORREG 41 // reg1 ^= reg2
|
||||
#define SCMD_NOTREG 42 // reg1 = !reg1
|
||||
#define SCMD_SHIFTLEFT 43 // reg1 = reg1 << reg2
|
||||
#define SCMD_SHIFTRIGHT 44 // reg1 = reg1 >> reg2
|
||||
#define SCMD_CALLOBJ 45 // next call is member function of reg1
|
||||
#define SCMD_CHECKBOUNDS 46 // check reg1 is between 0 and arg2
|
||||
#define SCMD_MEMWRITEPTR 47 // m[MAR] = reg1 (adjust ptr addr)
|
||||
#define SCMD_MEMREADPTR 48 // reg1 = m[MAR] (adjust ptr addr)
|
||||
#define SCMD_MEMZEROPTR 49 // m[MAR] = 0 (blank ptr)
|
||||
#define SCMD_MEMINITPTR 50 // m[MAR] = reg1 (but don't free old one)
|
||||
#define SCMD_LOADSPOFFS 51 // MAR = SP - arg1 (optimization for local var access)
|
||||
#define SCMD_CHECKNULL 52 // error if MAR==0
|
||||
#define SCMD_FADD 53 // reg1 += arg2 (float,int)
|
||||
#define SCMD_FSUB 54 // reg1 -= arg2 (float,int)
|
||||
#define SCMD_FMULREG 55 // reg1 *= reg2 (float)
|
||||
#define SCMD_FDIVREG 56 // reg1 /= reg2 (float)
|
||||
#define SCMD_FADDREG 57 // reg1 += reg2 (float)
|
||||
#define SCMD_FSUBREG 58 // reg1 -= reg2 (float)
|
||||
#define SCMD_FGREATER 59 // reg1 > reg2 (float)
|
||||
#define SCMD_FLESSTHAN 60 // reg1 < reg2 (float)
|
||||
#define SCMD_FGTE 61 // reg1 >= reg2 (float)
|
||||
#define SCMD_FLTE 62 // reg1 <= reg2 (float)
|
||||
#define SCMD_ZEROMEMORY 63 // m[MAR]..m[MAR+(arg1-1)] = 0
|
||||
#define SCMD_CREATESTRING 64 // reg1 = new String(reg1)
|
||||
#define SCMD_STRINGSEQUAL 65 // (char*)reg1 == (char*)reg2 reg1=1 if true, =0 if not
|
||||
#define SCMD_STRINGSNOTEQ 66 // (char*)reg1 != (char*)reg2
|
||||
#define SCMD_CHECKNULLREG 67 // error if reg1 == NULL
|
||||
#define SCMD_LOOPCHECKOFF 68 // no loop checking for this function
|
||||
#define SCMD_MEMZEROPTRND 69 // m[MAR] = 0 (blank ptr, no dispose if = ax)
|
||||
#define SCMD_JNZ 70 // jump to arg1 if ax!=0
|
||||
#define SCMD_DYNAMICBOUNDS 71 // check reg1 is between 0 and m[MAR-4]
|
||||
#define SCMD_NEWARRAY 72 // reg1 = new array of reg1 elements, each of size arg2 (arg3=managed type?)
|
||||
#define SCMD_NEWUSEROBJECT 73 // reg1 = new user object of arg1 size
|
||||
|
||||
#define CC_NUM_SCCMDS 74
|
||||
#define MAX_SCMD_ARGS 3 // maximal possible number of arguments
|
||||
|
||||
#define EXPORT_FUNCTION 1
|
||||
#define EXPORT_DATA 2
|
||||
|
||||
#define FIXUP_NOFIXUP 0 // no-op
|
||||
#define FIXUP_GLOBALDATA 1 // code[fixup] += &globaldata[0]
|
||||
#define FIXUP_FUNCTION 2 // code[fixup] += &code[0]
|
||||
#define FIXUP_STRING 3 // code[fixup] += &strings[0]
|
||||
#define FIXUP_IMPORT 4 // code[fixup] = &imported_thing[code[fixup]]
|
||||
#define FIXUP_DATADATA 5 // globaldata[fixup] += &globaldata[0]
|
||||
#define FIXUP_STACK 6 // code[fixup] += &stack[0]
|
||||
|
||||
// Script file signature
|
||||
#define ENDFILESIG 0xbeefcafe
|
||||
|
||||
} // namespace AGS3
|
||||
|
||||
#endif
|
||||
336
engines/ags/shared/script/cc_script.cpp
Normal file
336
engines/ags/shared/script/cc_script.cpp
Normal file
@@ -0,0 +1,336 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "ags/shared/script/cc_common.h"
|
||||
#include "ags/shared/script/cc_script.h"
|
||||
#include "ags/shared/script/cc_internal.h"
|
||||
#include "ags/shared/util/stream.h"
|
||||
#include "ags/shared/util/string_compat.h"
|
||||
#include "ags/shared/util/string_utils.h"
|
||||
#include "ags/globals.h"
|
||||
|
||||
namespace AGS3 {
|
||||
|
||||
using namespace AGS::Shared;
|
||||
|
||||
ccScript *ccScript::CreateFromStream(Stream *in) {
|
||||
ccScript *scri = new ccScript();
|
||||
if (!scri->Read(in)) {
|
||||
delete scri;
|
||||
return nullptr;
|
||||
}
|
||||
return scri;
|
||||
}
|
||||
|
||||
ccScript::ccScript() {
|
||||
globaldata = nullptr;
|
||||
globaldatasize = 0;
|
||||
code = nullptr;
|
||||
codesize = 0;
|
||||
strings = nullptr;
|
||||
stringssize = 0;
|
||||
fixuptypes = nullptr;
|
||||
fixups = nullptr;
|
||||
numfixups = 0;
|
||||
importsCapacity = 0;
|
||||
imports = nullptr;
|
||||
numimports = 0;
|
||||
exportsCapacity = 0;
|
||||
exports = nullptr;
|
||||
export_addr = nullptr;
|
||||
numexports = 0;
|
||||
instances = 0;
|
||||
sectionNames = nullptr;
|
||||
sectionOffsets = nullptr;
|
||||
numSections = 0;
|
||||
capacitySections = 0;
|
||||
}
|
||||
|
||||
ccScript::ccScript(const ccScript &src) {
|
||||
globaldatasize = src.globaldatasize;
|
||||
if (globaldatasize > 0) {
|
||||
globaldata = (char *)malloc(globaldatasize);
|
||||
memcpy(globaldata, src.globaldata, globaldatasize);
|
||||
} else {
|
||||
globaldata = nullptr;
|
||||
}
|
||||
|
||||
codesize = src.codesize;
|
||||
if (codesize > 0) {
|
||||
code = (int32_t *)malloc(codesize * sizeof(int32_t));
|
||||
memcpy(code, src.code, sizeof(int32_t) * codesize);
|
||||
} else {
|
||||
code = nullptr;
|
||||
}
|
||||
|
||||
stringssize = src.stringssize;
|
||||
if (stringssize > 0) {
|
||||
strings = (char *)malloc(stringssize);
|
||||
memcpy(strings, src.strings, stringssize);
|
||||
} else {
|
||||
strings = nullptr;
|
||||
}
|
||||
|
||||
numfixups = src.numfixups;
|
||||
if (numfixups > 0) {
|
||||
fixuptypes = (char *)malloc(numfixups);
|
||||
fixups = (int32_t *)malloc(numfixups * sizeof(int32_t));
|
||||
memcpy(fixuptypes, src.fixuptypes, numfixups);
|
||||
memcpy(fixups, src.fixups, numfixups * sizeof(int32_t));
|
||||
} else {
|
||||
fixups = nullptr;
|
||||
fixuptypes = nullptr;
|
||||
}
|
||||
|
||||
importsCapacity = src.numimports;
|
||||
numimports = src.numimports;
|
||||
if (numimports > 0) {
|
||||
imports = (char **)malloc(sizeof(char *) * numimports);
|
||||
for (int i = 0; i < numimports; ++i)
|
||||
imports[i] = ags_strdup(src.imports[i]);
|
||||
} else {
|
||||
imports = nullptr;
|
||||
}
|
||||
|
||||
exportsCapacity = src.numexports;
|
||||
numexports = src.numexports;
|
||||
if (numexports > 0) {
|
||||
exports = (char **)malloc(sizeof(char *) * numexports);
|
||||
export_addr = (int32_t *)malloc(sizeof(int32_t) * numexports);
|
||||
for (int i = 0; i < numexports; ++i) {
|
||||
exports[i] = ags_strdup(src.exports[i]);
|
||||
export_addr[i] = src.export_addr[i];
|
||||
}
|
||||
} else {
|
||||
exports = nullptr;
|
||||
export_addr = nullptr;
|
||||
}
|
||||
|
||||
capacitySections = src.numSections;
|
||||
numSections = src.numSections;
|
||||
if (numSections > 0) {
|
||||
sectionNames = (char **)malloc(numSections * sizeof(char *));
|
||||
sectionOffsets = (int32_t *)malloc(numSections * sizeof(int32_t));
|
||||
for (int i = 0; i < numSections; ++i) {
|
||||
sectionNames[i] = ags_strdup(src.sectionNames[i]);
|
||||
sectionOffsets[i] = src.sectionOffsets[i];
|
||||
}
|
||||
} else {
|
||||
numSections = 0;
|
||||
sectionNames = nullptr;
|
||||
sectionOffsets = nullptr;
|
||||
}
|
||||
|
||||
instances = 0;
|
||||
}
|
||||
|
||||
ccScript::~ccScript() {
|
||||
Free();
|
||||
}
|
||||
|
||||
void ccScript::Write(Stream *out) {
|
||||
int n;
|
||||
out->Write(_G(scfilesig), 4);
|
||||
out->WriteInt32(SCOM_VERSION);
|
||||
out->WriteInt32(globaldatasize);
|
||||
out->WriteInt32(codesize);
|
||||
out->WriteInt32(stringssize);
|
||||
if (globaldatasize > 0)
|
||||
out->WriteArray(globaldata, globaldatasize, 1);
|
||||
if (codesize > 0)
|
||||
out->WriteArrayOfInt32(code, codesize);
|
||||
if (stringssize > 0)
|
||||
out->WriteArray(strings, stringssize, 1);
|
||||
out->WriteInt32(numfixups);
|
||||
if (numfixups > 0) {
|
||||
out->WriteArray(fixuptypes, numfixups, 1);
|
||||
out->WriteArrayOfInt32(fixups, numfixups);
|
||||
}
|
||||
out->WriteInt32(numimports);
|
||||
for (n = 0; n < numimports; n++)
|
||||
StrUtil::WriteCStr(imports[n], out);
|
||||
out->WriteInt32(numexports);
|
||||
for (n = 0; n < numexports; n++) {
|
||||
StrUtil::WriteCStr(exports[n], out);
|
||||
out->WriteInt32(export_addr[n]);
|
||||
}
|
||||
out->WriteInt32(numSections);
|
||||
for (n = 0; n < numSections; n++) {
|
||||
StrUtil::WriteCStr(sectionNames[n], out);
|
||||
out->WriteInt32(sectionOffsets[n]);
|
||||
}
|
||||
out->WriteInt32(ENDFILESIG);
|
||||
}
|
||||
|
||||
bool ccScript::Read(Stream *in) {
|
||||
instances = 0;
|
||||
int n;
|
||||
char gotsig[5];
|
||||
_G(currentline) = -1;
|
||||
in->Read(gotsig, 4);
|
||||
gotsig[4] = 0;
|
||||
|
||||
int fileVer = in->ReadInt32();
|
||||
|
||||
if ((strcmp(gotsig, _G(scfilesig)) != 0) || (fileVer > SCOM_VERSION)) {
|
||||
cc_error("file was not written by ccScript::Write or seek position is incorrect");
|
||||
return false;
|
||||
}
|
||||
|
||||
globaldatasize = in->ReadInt32();
|
||||
codesize = in->ReadInt32();
|
||||
stringssize = in->ReadInt32();
|
||||
|
||||
if (globaldatasize > 0) {
|
||||
globaldata = (char *)malloc(globaldatasize);
|
||||
in->Read(globaldata, globaldatasize);
|
||||
} else
|
||||
globaldata = nullptr;
|
||||
|
||||
if (codesize > 0) {
|
||||
code = (int32_t *)malloc(codesize * sizeof(int32_t));
|
||||
in->ReadArrayOfInt32(code, codesize);
|
||||
} else
|
||||
code = nullptr;
|
||||
|
||||
if (stringssize > 0) {
|
||||
strings = (char *)malloc(stringssize);
|
||||
in->Read(strings, stringssize);
|
||||
} else
|
||||
strings = nullptr;
|
||||
|
||||
numfixups = in->ReadInt32();
|
||||
if (numfixups > 0) {
|
||||
fixuptypes = (char *)malloc(numfixups);
|
||||
fixups = (int32_t *)malloc(numfixups * sizeof(int32_t));
|
||||
in->Read(fixuptypes, numfixups);
|
||||
in->ReadArrayOfInt32(fixups, numfixups);
|
||||
} else {
|
||||
fixups = nullptr;
|
||||
fixuptypes = nullptr;
|
||||
}
|
||||
|
||||
numimports = in->ReadInt32();
|
||||
|
||||
imports = (char **)malloc(sizeof(char *) * numimports);
|
||||
for (n = 0; n < numimports; n++)
|
||||
imports[n] = StrUtil::ReadMallocCStrOrNull(in);
|
||||
|
||||
numexports = in->ReadInt32();
|
||||
exports = (char **)malloc(sizeof(char *) * numexports);
|
||||
export_addr = (int32_t *)malloc(sizeof(int32_t) * numexports);
|
||||
for (n = 0; n < numexports; n++) {
|
||||
exports[n] = StrUtil::ReadMallocCStrOrNull(in);
|
||||
export_addr[n] = in->ReadInt32();
|
||||
}
|
||||
|
||||
if (fileVer >= 83) {
|
||||
// read in the Sections
|
||||
numSections = in->ReadInt32();
|
||||
sectionNames = (char **)malloc(numSections * sizeof(char *));
|
||||
sectionOffsets = (int32_t *)malloc(numSections * sizeof(int32_t));
|
||||
for (n = 0; n < numSections; n++) {
|
||||
sectionNames[n] = StrUtil::ReadMallocCStrOrNull(in);
|
||||
sectionOffsets[n] = in->ReadInt32();
|
||||
}
|
||||
} else {
|
||||
numSections = 0;
|
||||
sectionNames = nullptr;
|
||||
sectionOffsets = nullptr;
|
||||
}
|
||||
|
||||
if (static_cast<uint32_t>(in->ReadInt32()) != ENDFILESIG) {
|
||||
cc_error("internal error rebuilding script");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void ccScript::Free() {
|
||||
if (globaldata != nullptr)
|
||||
free(globaldata);
|
||||
|
||||
if (code != nullptr)
|
||||
free(code);
|
||||
|
||||
if (strings != nullptr)
|
||||
free(strings);
|
||||
|
||||
if (fixups != nullptr && numfixups > 0)
|
||||
free(fixups);
|
||||
|
||||
if (fixuptypes != nullptr && numfixups > 0)
|
||||
free(fixuptypes);
|
||||
|
||||
globaldata = nullptr;
|
||||
code = nullptr;
|
||||
strings = nullptr;
|
||||
fixups = nullptr;
|
||||
fixuptypes = nullptr;
|
||||
|
||||
int aa;
|
||||
for (aa = 0; aa < numimports; aa++) {
|
||||
if (imports[aa] != nullptr)
|
||||
free(imports[aa]);
|
||||
}
|
||||
|
||||
for (aa = 0; aa < numexports; aa++)
|
||||
free(exports[aa]);
|
||||
|
||||
for (aa = 0; aa < numSections; aa++)
|
||||
free(sectionNames[aa]);
|
||||
|
||||
if (sectionNames != nullptr) {
|
||||
free(sectionNames);
|
||||
free(sectionOffsets);
|
||||
sectionNames = nullptr;
|
||||
sectionOffsets = nullptr;
|
||||
}
|
||||
|
||||
if (imports != nullptr) {
|
||||
free(imports);
|
||||
free(exports);
|
||||
free(export_addr);
|
||||
imports = nullptr;
|
||||
exports = nullptr;
|
||||
export_addr = nullptr;
|
||||
}
|
||||
numimports = 0;
|
||||
numexports = 0;
|
||||
numSections = 0;
|
||||
}
|
||||
|
||||
const char *ccScript::GetSectionName(int32_t offs) const {
|
||||
int i;
|
||||
for (i = 0; i < numSections; i++) {
|
||||
if (sectionOffsets[i] < offs)
|
||||
continue;
|
||||
break;
|
||||
}
|
||||
|
||||
// if no sections in script, return unknown
|
||||
if (i == 0)
|
||||
return "(unknown section)";
|
||||
|
||||
return sectionNames[i - 1];
|
||||
}
|
||||
|
||||
} // namespace AGS3
|
||||
85
engines/ags/shared/script/cc_script.h
Normal file
85
engines/ags/shared/script/cc_script.h
Normal file
@@ -0,0 +1,85 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef AGS_SHARED_SCRIPT_CC_SCRIPT_H
|
||||
#define AGS_SHARED_SCRIPT_CC_SCRIPT_H
|
||||
|
||||
#include "common/std/memory.h"
|
||||
#include "ags/shared/core/types.h"
|
||||
|
||||
namespace AGS3 {
|
||||
|
||||
namespace AGS {
|
||||
namespace Shared {
|
||||
class Stream;
|
||||
}
|
||||
}
|
||||
using namespace AGS; // FIXME later
|
||||
|
||||
struct ccScript {
|
||||
public:
|
||||
char *globaldata;
|
||||
int32_t globaldatasize;
|
||||
int32_t *code; // executable byte-code, 32-bit per op or arg
|
||||
int32_t codesize; // TODO: find out if we can make it size_t
|
||||
char *strings;
|
||||
int32_t stringssize;
|
||||
char *fixuptypes; // global data/string area/ etc
|
||||
int32_t *fixups; // code array index to fixup (in ints)
|
||||
int numfixups;
|
||||
int importsCapacity;
|
||||
char **imports;
|
||||
int numimports;
|
||||
int exportsCapacity;
|
||||
char **exports; // names of exports
|
||||
int32_t *export_addr; // high byte is type; low 24-bits are offset
|
||||
int numexports;
|
||||
int instances;
|
||||
// 'sections' allow the interpreter to find out which bit
|
||||
// of the code came from header files, and which from the main file
|
||||
char **sectionNames;
|
||||
int32_t *sectionOffsets;
|
||||
int numSections;
|
||||
int capacitySections;
|
||||
|
||||
static ccScript *CreateFromStream(Shared::Stream *in);
|
||||
|
||||
ccScript();
|
||||
ccScript(const ccScript &src);
|
||||
virtual ~ccScript(); // there are few derived classes, so dtor should be virtual
|
||||
|
||||
// write the script to disk (after compiling)
|
||||
void Write(Shared::Stream *out);
|
||||
// read back a script written with Write
|
||||
bool Read(Shared::Stream *in);
|
||||
const char *GetSectionName(int32_t offset) const;
|
||||
|
||||
protected:
|
||||
// free the memory occupied by the script - do NOT attempt to run the
|
||||
// script after calling this function
|
||||
void Free();
|
||||
};
|
||||
|
||||
typedef std::shared_ptr<ccScript> PScript;
|
||||
|
||||
} // namespace AGS3
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user