mirror of
https://github.com/scummvm/scummvm.git
synced 2026-06-20 05:45:29 +00:00
This not only simplifies all the use of _t types to the ScummVM equivalents, it gets rid of the int32 usage in favor of just int, solving common type clashes with the Amiga, for which int doesn't match int32
377 lines
8.9 KiB
C++
377 lines
8.9 KiB
C++
/* 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 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
*
|
|
*/
|
|
|
|
//include <stdlib.h>
|
|
//include <string.h>
|
|
#include "ags/shared/script/cc_error.h"
|
|
#include "ags/shared/script/cc_script.h"
|
|
#include "ags/shared/script/script_common.h"
|
|
#include "ags/shared/util/stream.h"
|
|
#include "ags/shared/util/string_compat.h"
|
|
|
|
namespace AGS3 {
|
|
|
|
using AGS::Shared::Stream;
|
|
|
|
// currently executed line
|
|
int currentline;
|
|
// script file format signature
|
|
const char scfilesig[5] = "SCOM";
|
|
|
|
// [IKM] I reckon this function is almost identical to fgetstring in string_utils
|
|
void freadstring(char **strptr, Stream *in) {
|
|
static char ibuffer[300];
|
|
int idxx = 0;
|
|
|
|
while ((ibuffer[idxx] = in->ReadInt8()) != 0)
|
|
idxx++;
|
|
|
|
if (ibuffer[0] == 0) {
|
|
strptr[0] = nullptr;
|
|
return;
|
|
}
|
|
|
|
strptr[0] = (char *)malloc(strlen(ibuffer) + 1);
|
|
strcpy(strptr[0], ibuffer);
|
|
}
|
|
|
|
void fwritestring(const char *strptr, Stream *out) {
|
|
if (strptr == nullptr) {
|
|
out->WriteByte(0);
|
|
} else {
|
|
out->Write(strptr, strlen(strptr) + 1);
|
|
}
|
|
}
|
|
|
|
ccScript *ccScript::CreateFromStream(Shared::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 = (int *)malloc(codesize * sizeof(int));
|
|
memcpy(code, src.code, sizeof(int) * 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 = (int *)malloc(numfixups * sizeof(int));
|
|
memcpy(fixuptypes, src.fixuptypes, numfixups);
|
|
memcpy(fixups, src.fixups, numfixups * sizeof(int));
|
|
} 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 = (int *)malloc(sizeof(int) * 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 = (int *)malloc(numSections * sizeof(int));
|
|
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(Shared::Stream *out) {
|
|
int n;
|
|
out->Write(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++)
|
|
fwritestring(imports[n], out);
|
|
out->WriteInt32(numexports);
|
|
for (n = 0; n < numexports; n++) {
|
|
fwritestring(exports[n], out);
|
|
out->WriteInt32(export_addr[n]);
|
|
}
|
|
out->WriteInt32(numSections);
|
|
for (n = 0; n < numSections; n++) {
|
|
fwritestring(sectionNames[n], out);
|
|
out->WriteInt32(sectionOffsets[n]);
|
|
}
|
|
out->WriteInt32(ENDFILESIG);
|
|
}
|
|
|
|
bool ccScript::Read(Shared::Stream *in) {
|
|
instances = 0;
|
|
int n;
|
|
char gotsig[5];
|
|
currentline = -1;
|
|
// MACPORT FIX: swap 'size' and 'nmemb'
|
|
in->Read(gotsig, 4);
|
|
gotsig[4] = 0;
|
|
|
|
int fileVer = in->ReadInt32();
|
|
|
|
if ((strcmp(gotsig, 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);
|
|
// MACPORT FIX: swap
|
|
in->Read(globaldata, globaldatasize);
|
|
} else
|
|
globaldata = nullptr;
|
|
|
|
if (codesize > 0) {
|
|
code = (int *)malloc(codesize * sizeof(int));
|
|
// MACPORT FIX: swap
|
|
|
|
// 64 bit: Read code into 8 byte array, necessary for being able to perform
|
|
// relocations on the references.
|
|
in->ReadArrayOfInt32(code, codesize);
|
|
} else
|
|
code = nullptr;
|
|
|
|
if (stringssize > 0) {
|
|
strings = (char *)malloc(stringssize);
|
|
// MACPORT FIX: swap
|
|
in->Read(strings, stringssize);
|
|
} else
|
|
strings = nullptr;
|
|
|
|
numfixups = in->ReadInt32();
|
|
if (numfixups > 0) {
|
|
fixuptypes = (char *)malloc(numfixups);
|
|
fixups = (int *)malloc(numfixups * sizeof(int));
|
|
// MACPORT FIX: swap 'size' and 'nmemb'
|
|
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++)
|
|
freadstring(&imports[n], in);
|
|
|
|
numexports = in->ReadInt32();
|
|
exports = (char **)malloc(sizeof(char *) * numexports);
|
|
export_addr = (int *)malloc(sizeof(int) * numexports);
|
|
for (n = 0; n < numexports; n++) {
|
|
freadstring(&exports[n], in);
|
|
export_addr[n] = in->ReadInt32();
|
|
}
|
|
|
|
if (fileVer >= 83) {
|
|
// read in the Sections
|
|
numSections = in->ReadInt32();
|
|
sectionNames = (char **)malloc(numSections * sizeof(char *));
|
|
sectionOffsets = (int *)malloc(numSections * sizeof(int));
|
|
for (n = 0; n < numSections; n++) {
|
|
freadstring(§ionNames[n], in);
|
|
sectionOffsets[n] = in->ReadInt32();
|
|
}
|
|
} else {
|
|
numSections = 0;
|
|
sectionNames = nullptr;
|
|
sectionOffsets = nullptr;
|
|
}
|
|
|
|
if (in->ReadInt32() != (int)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(int offs) {
|
|
|
|
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
|