86
83
uint32 scriptResourceId = 0;
87
84
scriptResourceId = _vm->getResourceDescription()->moduleLUTResourceId;
88
85
debug(3, "Loading module LUT from resource %i", scriptResourceId);
89
_vm->_resource->loadResource(resourceContext, scriptResourceId, resourcePointer, resourceLength);
86
_vm->_resource->loadResource(resourceContext, scriptResourceId, resourceData);
91
88
// Create logical script LUT from resource
92
if (resourceLength % 22 == 0) { // ITE CD
89
if (resourceData.size() % 22 == 0) { // ITE CD
93
90
_modulesLUTEntryLen = 22;
94
} else if (resourceLength % 16 == 0) { // ITE disk, IHNM
91
} else if (resourceData.size() % 16 == 0) { // ITE disk, IHNM
95
92
_modulesLUTEntryLen = 16;
97
error("Script::Script() Invalid script lookup table length (%i)", (int)resourceLength);
94
error("Script::Script() Invalid script lookup table length (%i)", (int)resourceData.size());
100
97
// Calculate number of entries
101
_modulesCount = resourceLength / _modulesLUTEntryLen;
98
int modulesCount = resourceData.size() / _modulesLUTEntryLen;
103
debug(3, "LUT has %i entries", _modulesCount);
100
debug(3, "LUT has %i entries", modulesCount);
105
102
// Allocate space for logical LUT
106
_modules = (ModuleData *)malloc(_modulesCount * sizeof(*_modules));
107
if (_modules == NULL) {
108
memoryError("Script::Script()");
103
_modules.resize(modulesCount);
111
105
// Convert LUT resource to logical LUT
112
MemoryReadStreamEndian scriptS(resourcePointer, resourceLength, resourceContext->isBigEndian());
113
for (i = 0; i < _modulesCount; i++) {
114
memset(&_modules[i], 0, sizeof(ModuleData));
106
ByteArrayReadStreamEndian scriptS(resourceData, resourceContext->isBigEndian());
107
for (ui = 0; ui < _modules.size(); ui++) {
116
109
prevTell = scriptS.pos();
117
_modules[i].scriptResourceId = scriptS.readUint16();
118
_modules[i].stringsResourceId = scriptS.readUint16();
119
_modules[i].voicesResourceId = scriptS.readUint16();
110
_modules[ui].scriptResourceId = scriptS.readUint16();
111
_modules[ui].stringsResourceId = scriptS.readUint16();
112
_modules[ui].voicesResourceId = scriptS.readUint16();
121
114
// Skip the unused portion of the structure
122
115
for (j = scriptS.pos(); j < prevTell + _modulesLUTEntryLen; j++) {
123
116
if (scriptS.readByte() != 0)
124
warning("Unused scriptLUT part isn't really unused for LUT %d (pos: %d)", i, j);
117
warning("Unused scriptLUT part isn't really unused for LUT %d (pos: %d)", ui, j);
128
free(resourcePointer);
132
123
// In ITE, the "main strings" resource contains both the verb strings
181
162
// Script export segment (lookup table)
182
uint32 saga2ExportSegId = MKID_BE('_EXP');
163
uint32 saga2ExportSegId = MKTAG('_','E','X','P');
183
164
int32 entryNum = _scriptContext->getEntryNum(saga2ExportSegId);
184
165
if (entryNum < 0)
185
166
error("Unable to locate the script's export segment");
186
167
debug(3, "Loading module LUT from resource %i", entryNum);
187
_vm->_resource->loadResource(_scriptContext, (uint32)entryNum, resourcePointer, resourceLength);
168
_vm->_resource->loadResource(_scriptContext, (uint32)entryNum, resourceData);
189
170
_modulesLUTEntryLen = sizeof(uint32);
191
172
// Calculate number of entries
192
_modulesCount = resourceLength / _modulesLUTEntryLen + 1;
173
int modulesCount = resourceData.size() / _modulesLUTEntryLen + 1;
194
debug(3, "LUT has %i entries", _modulesCount);
175
debug(3, "LUT has %i entries", modulesCount);
196
177
// Script data segment
198
uint32 saga2DataSegId = MKID_BE('__DA');
179
uint32 saga2DataSegId = MKTAG('_','_','D','A');
199
180
entryNum = _scriptContext->getEntryNum(saga2DataSegId);
200
181
if (entryNum < 0)
201
182
error("Unable to locate the script's data segment");
1083
1063
// Initialize script data structure
1084
1064
debug(3, "Loading script module #%d", scriptModuleNumber);
1086
_vm->_resource->loadResource(_scriptContext, _modules[scriptModuleNumber].scriptResourceId, resourcePointer, resourceLength);
1088
loadModuleBase(_modules[scriptModuleNumber], resourcePointer, resourceLength);
1089
free(resourcePointer);
1091
_vm->_resource->loadResource(_scriptContext, _modules[scriptModuleNumber].stringsResourceId, resourcePointer, resourceLength);
1093
_vm->loadStrings(_modules[scriptModuleNumber].strings, resourcePointer, resourceLength);
1094
free(resourcePointer);
1066
_vm->_resource->loadResource(_scriptContext, _modules[scriptModuleNumber].scriptResourceId, resourceData);
1068
loadModuleBase(_modules[scriptModuleNumber], resourceData);
1070
_vm->_resource->loadResource(_scriptContext, _modules[scriptModuleNumber].stringsResourceId, resourceData);
1072
_vm->loadStrings(_modules[scriptModuleNumber].strings, resourceData);
1096
1074
if (_modules[scriptModuleNumber].voicesResourceId > 0) {
1097
_vm->_resource->loadResource(_scriptContext, _modules[scriptModuleNumber].voicesResourceId, resourcePointer, resourceLength);
1075
_vm->_resource->loadResource(_scriptContext, _modules[scriptModuleNumber].voicesResourceId, resourceData);
1099
loadVoiceLUT(_modules[scriptModuleNumber].voiceLUT, resourcePointer, resourceLength);
1100
free(resourcePointer);
1077
loadVoiceLUT(_modules[scriptModuleNumber].voiceLUT, resourceData);
1103
1080
_modules[scriptModuleNumber].staticOffset = _staticSize;
1104
1081
_staticSize += _modules[scriptModuleNumber].staticSize;
1105
if (_staticSize > _commonBufferSize) {
1106
error("Script::loadModule() _staticSize > _commonBufferSize");
1082
if (_staticSize > _commonBuffer.size()) {
1083
error("Script::loadModule() _staticSize > _commonBuffer.size()");
1108
1085
_modules[scriptModuleNumber].loaded = true;
1111
void Script::freeModules() {
1113
for (i = 0; i < _modulesCount; i++) {
1088
void Script::clearModules() {
1090
for (i = 0; i < _modules.size(); i++) {
1114
1091
if (_modules[i].loaded) {
1115
_modules[i].freeMem();
1116
_modules[i].loaded = false;
1092
_modules[i].clear();
1119
1095
_staticSize = 0;
1122
void Script::loadModuleBase(ModuleData &module, const byte *resourcePointer, size_t resourceLength) {
1098
void Script::loadModuleBase(ModuleData &module, const ByteArray &resourceData) {
1125
1101
debug(3, "Loading module base...");
1127
module.moduleBase = (byte*)malloc(resourceLength);
1128
module.moduleBaseSize = resourceLength;
1130
memcpy(module.moduleBase, resourcePointer, resourceLength);
1132
MemoryReadStreamEndian scriptS(module.moduleBase, module.moduleBaseSize, _scriptContext->isBigEndian());
1134
module.entryPointsCount = scriptS.readUint16();
1135
scriptS.readUint16(); //skip
1136
module.entryPointsTableOffset = scriptS.readUint16();
1137
scriptS.readUint16(); //skip
1139
if ((module.moduleBaseSize - module.entryPointsTableOffset) < (module.entryPointsCount * SCRIPT_TBLENTRY_LEN)) {
1103
module.moduleBase.assign(resourceData);
1105
ByteArrayReadStreamEndian scriptS(module.moduleBase, _scriptContext->isBigEndian());
1107
uint entryPointsCount = scriptS.readUint16();
1108
scriptS.readUint16(); //skip
1109
uint16 entryPointsTableOffset; // offset of entrypoint table in moduleBase
1110
entryPointsTableOffset = scriptS.readUint16();
1111
scriptS.readUint16(); //skip
1113
if ((module.moduleBase.size() - entryPointsTableOffset) < (entryPointsCount * SCRIPT_TBLENTRY_LEN)) {
1140
1114
error("Script::loadModuleBase() Invalid table offset");
1143
if (module.entryPointsCount > SCRIPT_MAX) {
1117
if (entryPointsCount > SCRIPT_MAX) {
1144
1118
error("Script::loadModuleBase()Script limit exceeded");
1147
module.entryPoints = (EntryPoint *)malloc(module.entryPointsCount * sizeof(*module.entryPoints));
1148
if (module.entryPoints == NULL) {
1149
memoryError("Script::loadModuleBase");
1121
module.entryPoints.resize(entryPointsCount);
1152
1123
// Read in the entrypoint table
1154
1125
module.staticSize = scriptS.readUint16();
1155
while (scriptS.pos() < module.entryPointsTableOffset)
1126
while (scriptS.pos() < entryPointsTableOffset)
1156
1127
scriptS.readByte();
1158
for (i = 0; i < module.entryPointsCount; i++) {
1129
for (i = 0; i < module.entryPoints.size(); i++) {
1159
1130
// First uint16 is the offset of the entrypoint name from the start
1160
1131
// of the bytecode resource, second uint16 is the offset of the
1161
1132
// bytecode itself for said entrypoint
1163
1134
module.entryPoints[i].offset = scriptS.readUint16();
1165
1136
// Perform a simple range check on offset values
1166
if ((module.entryPoints[i].nameOffset >= module.moduleBaseSize) || (module.entryPoints[i].offset >= module.moduleBaseSize)) {
1137
if ((module.entryPoints[i].nameOffset >= module.moduleBase.size()) || (module.entryPoints[i].offset >= module.moduleBase.size())) {
1167
1138
error("Script::loadModuleBase() Invalid offset encountered in script entrypoint table");
1172
void Script::loadVoiceLUT(VoiceLUT &voiceLUT, const byte *resourcePointer, size_t resourceLength) {
1143
void Script::loadVoiceLUT(VoiceLUT &voiceLUT, const ByteArray &resourceData) {
1175
voiceLUT.voicesCount = resourceLength / 2;
1177
voiceLUT.voices = (uint16 *)malloc(voiceLUT.voicesCount * sizeof(*voiceLUT.voices));
1178
if (voiceLUT.voices == NULL) {
1179
error("Script::loadVoiceLUT() not enough memory");
1182
MemoryReadStreamEndian scriptS(resourcePointer, resourceLength, _scriptContext->isBigEndian());
1184
for (i = 0; i < voiceLUT.voicesCount; i++) {
1185
voiceLUT.voices[i] = scriptS.readUint16();
1146
voiceLUT.resize(resourceData.size() / 2);
1148
ByteArrayReadStreamEndian scriptS(resourceData, _scriptContext->isBigEndian());
1150
for (i = 0; i < voiceLUT.size(); i++) {
1151
voiceLUT[i] = scriptS.readUint16();