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 "scumm/he/intern_he.h"
24 #include "scumm/he/moonbase/moonbase.h"
25 #include "scumm/he/moonbase/ai_main.h"
26 #ifdef USE_SDL_NET
27 #include "scumm/he/moonbase/net_main.h"
28 #endif
29 
30 namespace Scumm {
31 
Moonbase(ScummEngine_v100he * vm)32 Moonbase::Moonbase(ScummEngine_v100he *vm) : _vm(vm) {
33 	initFOW();
34 
35 	_ai = new AI(_vm);
36 #ifdef USE_SDL_NET
37 	_net = new Net(_vm);
38 #endif
39 }
40 
~Moonbase()41 Moonbase::~Moonbase() {
42 	delete _ai;
43 #ifdef USE_SDL_NET
44 	delete _net;
45 #endif
46 }
47 
readFromArray(int array,int y,int x)48 int Moonbase::readFromArray(int array, int y, int x) {
49 	_vm->VAR(_vm->VAR_U32_ARRAY_UNK) = array;
50 
51 	return _vm->readArray(_vm->VAR_U32_ARRAY_UNK, y, x);
52 }
53 
deallocateArray(int array)54 void Moonbase::deallocateArray(int array) {
55 	_vm->VAR(_vm->VAR_U32_ARRAY_UNK) = array;
56 
57 	return _vm->nukeArray(_vm->VAR_U32_ARRAY_UNK);
58 }
59 
callScummFunction(int scriptNumber,int paramCount,...)60 int Moonbase::callScummFunction(int scriptNumber, int paramCount,...) {
61 	va_list va_params;
62 	va_start(va_params, paramCount);
63 	int args[25];
64 
65 	memset(args, 0, sizeof(args));
66 
67 	Common::String str;
68 	str = Common::String::format("callScummFunction(%d, [", scriptNumber);
69 
70 	for (int i = 0; i < paramCount; i++) {
71 		args[i] = va_arg(va_params, int);
72 
73 		str += Common::String::format("%d ", args[i]);
74 	}
75 	str += "])";
76 
77 	debug(0, "%s", str.c_str());
78 
79 
80 	va_end(va_params);
81 
82 	_vm->runScript(scriptNumber, 0, 1, args);
83 
84 	return _vm->pop();
85 }
86 
87 
blitT14WizImage(uint8 * dst,int dstw,int dsth,int dstPitch,const Common::Rect * clipBox,uint8 * wizd,int x,int y,int rawROP,int paramROP)88 void Moonbase::blitT14WizImage(uint8 *dst, int dstw, int dsth, int dstPitch, const Common::Rect *clipBox,
89 		 uint8 *wizd, int x, int y, int rawROP, int paramROP) {
90 	bool premulAlpa = false;
91 
92 	if (rawROP == 1)
93 		premulAlpa = true;
94 
95 	Common::Rect clippedDstRect(dstw, dsth);
96 	if (clipBox) {
97 		Common::Rect clip(clipBox->left, clipBox->top, clipBox->right, clipBox->bottom);
98 		if (clippedDstRect.intersects(clip)) {
99 			clippedDstRect.clip(clip);
100 		} else {
101 			return;
102 		}
103 	}
104 
105 	int width = READ_LE_UINT16(wizd + 0x8 + 0);
106 	int height = READ_LE_UINT16(wizd + 0x8 + 2);
107 
108 	Common::Rect srcLimitsRect(width, height);
109 	Common::Rect dstOperation(x, y, x + width, y + height);
110 	if (!clippedDstRect.intersects(dstOperation))
111 		return;
112 	Common::Rect clippedRect = clippedDstRect.findIntersectingRect(dstOperation);
113 
114 	int cx = clippedRect.right - clippedRect.left;
115 	int cy = clippedRect.bottom - clippedRect.top;
116 
117 	int sx = ((clippedRect.left - x) + srcLimitsRect.left);
118 	int sy = ((clippedRect.top - y) + srcLimitsRect.top);
119 
120 	dst += clippedRect.top * dstPitch + clippedRect.left * 2;
121 
122 	int headerSize = READ_LE_UINT32(wizd + 0x4);
123 	uint8 *dataPointer = wizd + 0x8 + headerSize;
124 
125 	for (int i = 0; i < sy; i++) {
126 		uint16 lineSize = READ_LE_UINT16(dataPointer + 0);
127 
128 		dataPointer += lineSize;
129 	}
130 
131 	for (int i = 0; i < cy; i++) {
132 		uint16 lineSize      = READ_LE_UINT16(dataPointer + 0);
133 		uint8 *singlesOffset = READ_LE_UINT16(dataPointer + 2) + dataPointer;
134 		uint8 *quadsOffset   = READ_LE_UINT16(dataPointer + 4) + dataPointer;
135 
136 		int pixels = 0;
137 		byte *dst1 = dst;
138 		byte *codes = dataPointer + 6;
139 
140 		while (1) {
141 			int code = *codes - 2;
142 			codes++;
143 
144 			if (code <= 0) { // quad or single
145 				uint8 *src;
146 				int cnt;
147 				if (code == 0) { // quad
148 					src = quadsOffset;
149 					quadsOffset += 8;
150 					cnt = 4; // 4 pixels
151 				} else { // single
152 					src = singlesOffset;
153 					singlesOffset += 2;
154 					cnt = 1;
155 				}
156 
157 				for (int c = 0; c < cnt; c++) {
158 					if (pixels >= sx) {
159 						if (rawROP == 1) { // MMX_PREMUL_ALPHA_COPY
160 							WRITE_LE_UINT16(dst1, READ_LE_UINT16(src));
161 						} else if (rawROP == 2) { // MMX_ADDITIVE
162 							uint16 color = READ_LE_UINT16(src);
163 							uint16 orig = READ_LE_UINT16(dst1);
164 
165 							uint32 r = MIN<uint32>(0x7c00, (orig & 0x7c00) + (color & 0x7c00));
166 							uint32 g = MIN<uint32>(0x03e0, (orig & 0x03e0) + (color & 0x03e0));
167 							uint32 b = MIN<uint32>(0x001f, (orig & 0x001f) + (color & 0x001f));
168 							WRITE_LE_UINT16(dst1, (r | g | b));
169 						} else if (rawROP == 5) { // MMX_CHEAP_50_50
170 							uint16 color = (READ_LE_UINT16(src) >> 1) & 0x3DEF;
171 							uint16 orig = (READ_LE_UINT16(dst1) >> 1) & 0x3DEF;
172 							WRITE_LE_UINT16(dst1, (color + orig));
173 						}
174 						dst1 += 2;
175 					}
176 					src += 2;
177 					pixels++;
178 					if (pixels >= cx + sx)
179 						break;
180 				}
181 			} else { // skip
182 				if ((code & 1) == 0) {
183 					code >>= 1;
184 
185 					for (int j = 0; j < code; j++) {
186 						if (pixels >= sx)
187 							dst1 += 2;
188 						pixels++;
189 						if (pixels >= cx + sx)
190 							break;
191 					}
192 				} else { // special case
193 					if (pixels >= sx) {
194 						int alpha = code >> 1;
195 						uint16 color = READ_LE_UINT16(singlesOffset);
196 						uint32 orig = READ_LE_UINT16(dst1);
197 
198 						if (!premulAlpa) {
199 							WRITE_LE_UINT16(dst1, color); // ENABLE_PREMUL_ALPHA = 0
200 						} else {
201 							if (alpha > 32) {
202 								alpha -= 32;
203 
204 								uint32 oR = orig & 0x7c00;
205 								uint32 oG = orig & 0x03e0;
206 								uint32 oB = orig & 0x1f;
207 								uint32 dR = ((((color & 0x7c00) - oR) * alpha) >> 5) + oR;
208 								uint32 dG = ((((color &  0x3e0) - oG) * alpha) >> 5) + oG;
209 								uint32 dB = ((((color &   0x1f) - oB) * alpha) >> 5) + oB;
210 
211 								WRITE_LE_UINT16(dst1, (dR & 0x7c00) | (dG & 0x3e0) | (dB & 0x1f));
212 							} else {
213 								uint32 pix = ((orig << 16) | orig) & 0x3e07c1f;
214 								pix = (((pix * alpha) & 0xffffffff) >> 5) & 0x3e07c1f;
215 								pix = ((pix >> 16) + pix + color) & 0xffff;
216 								WRITE_LE_UINT16(dst1, pix);
217 							}
218 						}
219 
220 						dst1 += 2;
221 					}
222 					singlesOffset += 2;
223 					pixels++;
224 				}
225 			}
226 
227 			if (pixels >= cx + sx)
228 				break;
229 		}
230 
231 		dataPointer += lineSize;
232 		dst += dstPitch;
233 	}
234 }
235 
236 } // End of namespace Scumm
237