1 /* ScummVM - Graphic Adventure Engine
2 *
3 * ScummVM is the legal property of its developers, whose names
4 * are too numerous to list here. Please refer to the COPYRIGHT
5 * file distributed with this source distribution.
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 *
21 */
22
23 #include "common/endian.h"
24 #include "cruise/cruise_main.h"
25
26 namespace Cruise {
27
parseExport(int * out1,int * pExportedFuncionIdx,char * buffer)28 exportEntryStruct *parseExport(int *out1, int *pExportedFuncionIdx, char *buffer) {
29 char localBuffer[256];
30 char functionName[256];
31 char overlayName[256];
32 char *dotPtr;
33 char *ptr2;
34 int idx;
35 int numSymbGlob;
36 exportEntryStruct *currentExportEntry;
37 char *entity1Name;
38
39 *out1 = 0;
40 *pExportedFuncionIdx = 0;
41
42 Common::strlcpy(localBuffer, buffer, sizeof(localBuffer));
43 dotPtr = strchr(localBuffer, '.');
44
45 if (dotPtr) {
46 Common::strlcpy(functionName, dotPtr + 1, sizeof(functionName));
47 *dotPtr = 0;
48
49 strcpy(overlayName, localBuffer);
50 } else {
51 overlayName[0] = 0;
52
53 Common::strlcpy(functionName, buffer, sizeof(functionName));
54 }
55
56 ptr2 = strchr((char *)functionName, ':');
57
58 if (ptr2) {
59 *ptr2 = 0;
60
61 *out1 = 1;
62 }
63
64 strToUpper(overlayName);
65 strToUpper(functionName);
66 if (strlen((char *)overlayName) == 0)
67 return NULL;
68
69 idx = findOverlayByName2(overlayName);
70
71 if (idx == -4)
72 return (NULL);
73
74 if (overlayTable[idx].alreadyLoaded == 0)
75 return (NULL);
76
77 if (!overlayTable[idx].ovlData)
78 return (NULL);
79
80 numSymbGlob = overlayTable[idx].ovlData->numSymbGlob;
81 currentExportEntry = overlayTable[idx].ovlData->arraySymbGlob;
82 entity1Name = overlayTable[idx].ovlData->arrayNameSymbGlob;
83
84 if (!entity1Name)
85 return (0);
86
87 for (int i = 0; i < numSymbGlob; i++) {
88 char exportedName[256];
89 char *name = entity1Name + currentExportEntry->offsetToName;
90
91 Common::strlcpy(exportedName, name, sizeof(exportedName));
92 strToUpper(exportedName);
93
94 if (!strcmp(functionName, exportedName)) {
95 *pExportedFuncionIdx = idx;
96
97 return (currentExportEntry);
98 }
99
100 currentExportEntry++;
101 }
102
103 return (NULL);
104 }
105
updateScriptImport(int ovlIdx)106 int updateScriptImport(int ovlIdx) {
107 char buffer[256];
108 ovlDataStruct *ovlData;
109 int numData3;
110 int size5;
111 int numRelocGlob;
112 int param;
113 int var_32;
114 ovlData3Struct *pScript;
115 // char* arrayRelocGlob;
116 // char* namePtr;
117 // char* arrayMsgRelHeader;
118
119 if (!overlayTable[ovlIdx].ovlData)
120 return (-4);
121
122 ovlData = overlayTable[ovlIdx].ovlData;
123
124 numData3 = ovlData->numProc;
125 size5 = ovlData->numRel;
126 numRelocGlob = ovlData->numRelocGlob;
127 param = 0;
128
129 // do it for the 2 first string types
130 do {
131
132 if (param == 0) {
133 var_32 = numData3;
134 } else {
135 var_32 = size5;
136 }
137
138 if (var_32) {
139 int i = 0;
140 do {
141 importScriptStruct *ptrImportData;
142 const char *ptrImportName;
143 uint8 *ptrData;
144
145 if (param == 0)
146 pScript = getOvlData3Entry(ovlIdx, i);
147 else
148 pScript = scriptFunc1Sub2(ovlIdx, i);
149
150 ptrImportData = (importScriptStruct *)(pScript->dataPtr + pScript->offsetToImportData); // import data
151 ptrImportName = (const char*)(pScript->dataPtr + pScript->offsetToImportName); // import name
152 ptrData = pScript->dataPtr;
153
154 if (pScript->numRelocGlob > 0) {
155 int counter = pScript->numRelocGlob;
156
157 do {
158 int param2 = ptrImportData->type;
159
160 if (param2 != 70) {
161 exportEntryStruct * ptrDest2;
162 int out1;
163 int out2;
164
165 Common::strlcpy(buffer, ptrImportName + ptrImportData->offsetToName, sizeof(buffer));
166 ptrDest2 = parseExport(&out1, &out2, buffer);
167
168 if (ptrDest2 && out2) {
169 int temp =
170 ptrImportData->
171 offset;
172 if (out1) { //is sub function... (ie 'invent.livre:s')
173 uint8 *ptr = ptrData + temp;
174
175 *(ptr + 1) = out2;
176 WRITE_BE_UINT16(ptr + 2, ptrDest2->idx);
177 } else {
178 if (param2 == 20 || param2 == 30 || param2 == 40 || param2 == 50) { // this patch a double push
179 uint8 *ptr = ptrData + temp;
180
181 *(ptr + 1) = 0;
182 *(ptr + 2) = out2; // update the overlay number
183
184 WRITE_BE_UINT16(ptr + 4, ptrDest2->idx);
185 } else {
186 int var_4 = ptrDest2->var4;
187
188 if (var_4 & 1) {
189 param2 = 8;
190 } else {
191 param2 = 16;
192 }
193
194 if (var_4 >= 0 && var_4 <= 3) {
195 param2 |= 5;
196 } else {
197 param2 |= 6;
198 }
199
200 *(ptrData + temp) = param2;
201 *(ptrData + temp + 1) = out2;
202
203 WRITE_BE_UINT16(ptrData + temp + 2, ptrDest2->idx);
204 }
205 }
206 }
207 }
208
209 ptrImportData++;
210 } while (--counter);
211 }
212
213 } while (++i < var_32);
214
215 }
216
217 } while (++param < 2);
218
219 if (ovlData->arrayRelocGlob && ovlData->arrayNameRelocGlob && numRelocGlob) {
220 int numImport2 = numRelocGlob;
221 for (int i = 0; i < numImport2; i++) {
222 int out1;
223 int foundExportIdx;
224 exportEntryStruct *pFoundExport;
225 int linkType;
226 int linkEntryIdx;
227
228 Common::strlcpy(buffer, ovlData->arrayNameRelocGlob + ovlData->arrayRelocGlob[i].nameOffset, sizeof(buffer));
229
230 pFoundExport = parseExport(&out1, &foundExportIdx, buffer);
231
232 linkType = ovlData->arrayRelocGlob[i].linkType;
233 linkEntryIdx = ovlData->arrayRelocGlob[i].linkIdx;
234
235 if (pFoundExport && foundExportIdx) {
236 switch (linkType) {
237 case 0: { // verb
238 ovlData->arrayMsgRelHeader[linkEntryIdx].verbOverlay = foundExportIdx;
239 ovlData->arrayMsgRelHeader[linkEntryIdx].verbNumber = pFoundExport->idx;
240 break;
241 }
242 case 1: { // obj1
243 ovlData->arrayMsgRelHeader[linkEntryIdx].obj1Overlay = foundExportIdx;
244 ovlData->arrayMsgRelHeader[linkEntryIdx].obj1Number = pFoundExport->idx;
245 break;
246 }
247 case 2: { // obj2
248 ovlData->arrayMsgRelHeader[linkEntryIdx].obj2Overlay = foundExportIdx;
249 ovlData->arrayMsgRelHeader[linkEntryIdx].obj2Number = pFoundExport->idx;
250 break;
251 }
252 default:
253 break;
254 }
255 }
256 }
257 }
258
259 return (0);
260 }
261
262 // check that the newly loaded isn't used by the already loaded overlays
updateAllScriptsImports()263 void updateAllScriptsImports() {
264 for (int i = 0; i < 90; i++) {
265 if (overlayTable[i].ovlData && overlayTable[i].alreadyLoaded)
266 updateScriptImport(i);
267 }
268 }
269
270 } // End of namespace Cruise
271