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