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 "cruise/cruise_main.h"
24 #include "common/file.h"
25 #include "cruise/cell.h"
26 
27 namespace Cruise {
28 
29 cellStruct cellHead;
30 
resetPtr(cellStruct * ptr)31 void resetPtr(cellStruct *ptr) {
32 	ptr->next = NULL;
33 	ptr->prev = NULL;
34 }
35 
freeMessageList(cellStruct * objPtr)36 void freeMessageList(cellStruct *objPtr) {
37 	/*	if (objPtr) {
38 			 if (objPtr->next)
39 			 MemFree(objPtr->next);
40 
41 			MemFree(objPtr);
42 		} */
43 }
44 
addCell(cellStruct * pHead,int16 overlayIdx,int16 objIdx,int16 type,int16 backgroundPlane,int16 scriptOverlay,int16 scriptNumber,int16 scriptType)45 cellStruct *addCell(cellStruct *pHead, int16 overlayIdx, int16 objIdx, int16 type, int16 backgroundPlane, int16 scriptOverlay, int16 scriptNumber, int16 scriptType) {
46 	int16 var;
47 
48 	cellStruct *newElement;
49 	cellStruct *currentHead = pHead;
50 	cellStruct *currentHead2;
51 	cellStruct *currentHead3;
52 
53 	if (getSingleObjectParam(overlayIdx, objIdx, 2, &var) < 0) {
54 		return 0;
55 	}
56 
57 	currentHead3 = currentHead;
58 	currentHead2 = currentHead->next;
59 
60 	while (currentHead2 && (currentHead2->type != 3)) {
61 
62 		if (currentHead2->type != 5) {
63 			int16 lvar2;
64 
65 			if (getSingleObjectParam(currentHead2->overlay, currentHead2->idx, 2, &lvar2) >= 0 && lvar2 >= var)
66 				break;
67 		}
68 
69 		currentHead3 = currentHead2;
70 		currentHead2 = currentHead2->next;
71 	}
72 
73 	if (currentHead2) {
74 		if ((currentHead2->overlay == overlayIdx) &&
75 		        (currentHead2->backgroundPlane == backgroundPlane) &&
76 		        (currentHead2->idx == objIdx) &&
77 		        (currentHead2->type == type))
78 
79 			return NULL;
80 	}
81 
82 	currentHead = currentHead2;
83 
84 	newElement = (cellStruct *) mallocAndZero(sizeof(cellStruct));
85 
86 	if (!newElement)
87 		return 0;
88 
89 	newElement->next = currentHead3->next;
90 	currentHead3->next = newElement;
91 
92 	newElement->idx = objIdx;
93 	newElement->type = type;
94 	newElement->backgroundPlane = backgroundPlane;
95 	newElement->overlay = overlayIdx;
96 	newElement->freeze = 0;
97 	newElement->parent = scriptNumber;
98 	newElement->parentOverlay = scriptOverlay;
99 	newElement->gfxPtr = NULL;
100 	newElement->followObjectIdx = objIdx;
101 	newElement->followObjectOverlayIdx = overlayIdx;
102 	newElement->parentType = scriptType;
103 
104 	newElement->animStart = 0;
105 	newElement->animEnd = 0;
106 	newElement->animWait = 0;
107 	newElement->animSignal = 0;
108 	newElement->animCounter = 0;
109 	newElement->animType = 0;
110 	newElement->animStep = 0;
111 	newElement->animLoop = 0;
112 
113 	if (currentHead) {
114 		newElement->prev = currentHead->prev;
115 		currentHead->prev = newElement;
116 	} else {
117 		newElement->prev = pHead->prev;
118 		pHead->prev = newElement;
119 	}
120 
121 	return newElement;
122 }
123 
createTextObject(cellStruct * pObject,int overlayIdx,int messageIdx,int x,int y,int width,int16 color,int backgroundPlane,int parentOvl,int parentIdx)124 void createTextObject(cellStruct *pObject, int overlayIdx, int messageIdx, int x, int y, int width, int16 color, int backgroundPlane, int parentOvl, int parentIdx) {
125 
126 	const char *ax;
127 	cellStruct *savePObject = pObject;
128 	cellStruct *cx;
129 
130 	cellStruct *pNewElement;
131 	cellStruct *si = pObject->next;
132 
133 	while (si) {
134 		pObject = si;
135 		si = si->next;
136 	}
137 
138 	pNewElement = (cellStruct *) MemAlloc(sizeof(cellStruct));
139 	memset(pNewElement, 0, sizeof(cellStruct));
140 
141 	pNewElement->next = pObject->next;
142 	pObject->next = pNewElement;
143 
144 	pNewElement->idx = messageIdx;
145 	pNewElement->type = OBJ_TYPE_MESSAGE;
146 	pNewElement->backgroundPlane = backgroundPlane;
147 	pNewElement->overlay = overlayIdx;
148 	pNewElement->x = x;
149 	pNewElement->field_C = y;
150 	pNewElement->spriteIdx = width;
151 	pNewElement->color = color;
152 	pNewElement->freeze = 0;
153 	pNewElement->parent = parentIdx;
154 	pNewElement->parentOverlay = parentOvl;
155 	pNewElement->gfxPtr = NULL;
156 
157 	cx = savePObject;
158 
159 	pNewElement->prev = cx->prev;
160 	cx->prev = pNewElement;
161 
162 	ax = getText(messageIdx, overlayIdx);
163 
164 	if (ax) {
165 		pNewElement->gfxPtr = renderText(width, ax);
166 	}
167 
168 	// WORKAROUND: This is needed for the new dirty rect handling so as to properly refresh the screen
169 	// when the copy protection screen is being shown
170 	if ((messageIdx == 0) && !strcmp(overlayTable[overlayIdx].overlayName, "XX2"))
171 		backgroundChanged[0] = true;
172 }
173 
removeCell(cellStruct * objPtr,int ovlNumber,int objectIdx,int objType,int backgroundPlane)174 void removeCell(cellStruct *objPtr, int ovlNumber, int objectIdx, int objType, int backgroundPlane) {
175 	cellStruct *currentObj = objPtr->next;
176 	cellStruct *previous;
177 
178 	while (currentObj) {
179 		if (((currentObj->overlay == ovlNumber) || (ovlNumber == -1)) &&
180 		        ((currentObj->idx == objectIdx) || (objectIdx == -1)) &&
181 		        ((currentObj->type == objType) || (objType == -1)) &&
182 		        ((currentObj->backgroundPlane == backgroundPlane) || (backgroundPlane == -1))) {
183 			currentObj->type = -1;
184 		}
185 
186 		currentObj = currentObj->next;
187 	}
188 
189 	previous = objPtr;
190 	currentObj = objPtr->next;
191 
192 	while (currentObj) {
193 		cellStruct *si;
194 
195 		si = currentObj;
196 
197 		if (si->type == -1) {
198 			cellStruct *dx;
199 			previous->next = si->next;
200 
201 			dx = si->next;
202 
203 			if (!si->next) {
204 				dx = objPtr;
205 			}
206 
207 			dx->prev = si->prev;
208 
209 			// Free the entry
210 			if (si->gfxPtr)
211 				freeGfx(si->gfxPtr);
212 			MemFree(si);
213 
214 			currentObj = dx;
215 		} else {
216 			currentObj = si->next;
217 			previous = si;
218 		}
219 	}
220 }
221 
linkCell(cellStruct * pHead,int ovl,int obj,int type,int ovl2,int obj2)222 void linkCell(cellStruct *pHead, int ovl, int obj, int type, int ovl2, int obj2) {
223 	while (pHead) {
224 		if ((pHead->overlay == ovl) || (ovl == -1)) {
225 			if ((pHead->idx == obj) || (obj == -1)) {
226 				if ((pHead->type == type) || (type == -1)) {
227 					pHead->followObjectIdx = obj2;
228 					pHead->followObjectOverlayIdx = ovl2;
229 				}
230 			}
231 		}
232 
233 		pHead = pHead->next;
234 	}
235 }
236 
freezeCell(cellStruct * pObject,int overlayIdx,int objIdx,int objType,int backgroundPlane,int oldFreeze,int newFreeze)237 void freezeCell(cellStruct * pObject, int overlayIdx, int objIdx, int objType, int backgroundPlane, int oldFreeze, int newFreeze) {
238 	while (pObject) {
239 		if ((pObject->overlay == overlayIdx) || (overlayIdx == -1)) {
240 			if ((pObject->idx == objIdx) || (objIdx == -1)) {
241 				if ((pObject->type == objType) || (objType == -1)) {
242 					if ((pObject->backgroundPlane == backgroundPlane) || (backgroundPlane == -1)) {
243 						if ((pObject->freeze == oldFreeze) || (oldFreeze == -1)) {
244 							pObject->freeze = newFreeze;
245 						}
246 					}
247 				}
248 			}
249 		}
250 
251 		pObject = pObject->next;
252 	}
253 }
254 
sortCells(int16 ovlIdx,int16 ovjIdx,cellStruct * objPtr)255 void sortCells(int16 ovlIdx, int16 ovjIdx, cellStruct *objPtr) {
256 	cellStruct *pl, *pl2, *pl3, *pl4, *plz, *pllast;
257 	cellStruct prov;
258 	int16 newz, objz, sobjz;
259 
260 	pl4 = NULL;
261 
262 	getSingleObjectParam(ovlIdx, ovjIdx, 2, &sobjz);
263 	pl = objPtr;
264 	prov.next = NULL;
265 	prov.prev = NULL;
266 
267 	pl2 = pl->next;
268 	pllast = NULL;
269 	plz = objPtr;
270 
271 	while (pl2) {
272 		pl3 = pl2->next;
273 		if ((pl2->overlay == ovlIdx) && (pl2->idx == ovjIdx)) {// found
274 			pl->next = pl3;
275 
276 			if (pl3) {
277 				pl3->prev = pl2->prev;
278 			} else {
279 				objPtr->prev = pl2->prev;
280 			}
281 
282 			pl4 = prov.next;
283 
284 			if (pl4) {
285 				pl4->prev = pl2;
286 			} else {
287 				prov.prev = pl2;
288 			}
289 
290 			pl2->prev = NULL;
291 			pl2->next = prov.next;
292 			prov.next = pl2;
293 
294 			if (pllast == NULL) {
295 				pllast = pl2;
296 			}
297 		} else {
298 			if (pl2->type == 5) {
299 				newz = 32000;
300 			} else {
301 				getSingleObjectParam(pl2->overlay, pl2->idx, 2, &objz);
302 				newz = objz;
303 			}
304 
305 			if (newz < sobjz) {
306 				plz = pl2;
307 			}
308 
309 			pl = pl->next;
310 		}
311 
312 		pl2 = pl3;
313 	}
314 
315 	if (pllast) {
316 		pl2 = prov.next;
317 		pl4 = plz->next;
318 		plz->next = pl2;
319 		pllast->next = pl4;
320 
321 		if (plz != objPtr)
322 			pl2->prev = plz;
323 		if (!pl4)
324 			objPtr->prev = pllast;
325 		else
326 			pl4->prev = pllast;
327 	}
328 }
329 
330 } // End of namespace Cruise
331