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/textconsole.h"
24
25 #include "parallaction/parallaction.h"
26 #include "parallaction/objects.h"
27 #include "parallaction/parser.h"
28
29 namespace Parallaction {
30
31
Command()32 Command::Command() {
33 _id = 0;
34 _flagsOn = 0;
35 _flagsOff = 0;
36 _valid = false;
37
38 _flags = 0;
39 _callable = 0;
40 _object = 0;
41 _counterValue = 0;
42 _zeta0 = 0;
43 _zeta1 = 0;
44 _zeta2 = 0;
45 _characterId = 0;
46 _musicCommand = 0;
47 _musicParm = 0;
48 }
49
Animation()50 Animation::Animation() {
51 gfxobj = NULL;
52 _frame = 0;
53 _z = 0;
54 }
55
~Animation()56 Animation::~Animation() {
57 if (gfxobj) {
58 gfxobj->release();
59 }
60 }
61
getFrameRect(Common::Rect & r) const62 void Animation::getFrameRect(Common::Rect &r) const {
63 r.setWidth(0); r.setHeight(0);
64 if (!gfxobj) {
65 return;
66 }
67 gfxobj->getRect(_frame, r);
68 r.translate(_left, _top);
69 }
70
hitFrameRect(int x,int y) const71 bool Animation::hitFrameRect(int x, int y) const {
72 if (!gfxobj) {
73 return false;
74 }
75 Common::Rect r;
76 getFrameRect(r);
77 return r.contains(x, y);
78 }
79
getBottom() const80 int16 Animation::getBottom() const {
81 int bottom = _top;
82 if (gfxobj) {
83 Common::Rect r;
84 getFrameRect(r);
85 bottom = r.bottom;
86 }
87 return bottom;
88 }
89
resetZ()90 void Animation::resetZ() {
91 setZ(getBottom());
92 }
93
getFrameNum() const94 uint16 Animation::getFrameNum() const {
95 if (!gfxobj) return 0;
96 return gfxobj->getNum();
97 }
98
getFrameData() const99 byte* Animation::getFrameData() const {
100 if (!gfxobj) return NULL;
101 return gfxobj->getData(_frame);
102 }
103
setF(int16 value)104 void Animation::setF(int16 value) {
105 int16 min = MIN(0, getFrameNum() - 1);
106 int16 max = MAX(0, getFrameNum() - 1);
107 _frame = CLIP(value, min, max);
108 }
109
forceXYZF(int16 x,int16 y,int16 z,int16 f)110 void Animation::forceXYZF(int16 x, int16 y, int16 z, int16 f) {
111 _left = x;
112 _top = y;
113 _z = z;
114 _frame = f;
115 }
116
getFoot(Common::Point & foot)117 void Animation::getFoot(Common::Point &foot) {
118 Common::Rect rect;
119 gfxobj->getRect(_frame, rect);
120 foot.x = getX() + (rect.left + rect.width() / 2);
121 foot.y = getY() + (rect.top + rect.height());
122 }
123
setFoot(const Common::Point & foot)124 void Animation::setFoot(const Common::Point &foot) {
125 Common::Rect rect;
126 gfxobj->getRect(_frame, rect);
127
128 setX(foot.x - (rect.left + rect.width() / 2));
129 setY(foot.y - (rect.top + rect.height()));
130 }
131
132 #define NUM_LOCALS 10
133 char _localNames[NUM_LOCALS][10];
134
Program()135 Program::Program() {
136 _loopCounter = 0;
137 _locals = new LocalVariable[NUM_LOCALS];
138 _numLocals = 0;
139 _status = kProgramIdle;
140 _ip = 0;
141 _loopStart = 0;
142 }
143
~Program()144 Program::~Program() {
145 delete[] _locals;
146 }
147
findLocal(const char * name)148 int16 Program::findLocal(const char* name) {
149 for (uint16 _si = 0; _si < NUM_LOCALS; _si++) {
150 if (!scumm_stricmp(name, _localNames[_si]))
151 return _si;
152 }
153
154 return -1;
155 }
156
addLocal(const char * name,int16 value,int16 min,int16 max)157 int16 Program::addLocal(const char *name, int16 value, int16 min, int16 max) {
158 assert(_numLocals < NUM_LOCALS);
159
160 Common::strlcpy(_localNames[_numLocals], name, 10);
161 _locals[_numLocals].setRange(min, max);
162 _locals[_numLocals].setValue(value);
163
164 return _numLocals++;
165 }
166
setValue(int16 value)167 void LocalVariable::setValue(int16 value) {
168 if (value >= _max)
169 value = _min;
170 if (value < _min)
171 value = _max - 1;
172
173 _value = value;
174 }
175
setRange(int16 min,int16 max)176 void LocalVariable::setRange(int16 min, int16 max) {
177 _max = max;
178 _min = min;
179 }
180
getValue() const181 int16 LocalVariable::getValue() const {
182 return _value;
183 }
184
185
Zone()186 Zone::Zone() {
187 _left = _top = _right = _bottom = 0;
188
189 _type = 0;
190
191 _flags = kFlagsNoName;
192 _label = 0;
193
194 // BRA specific
195 _index = INVALID_ZONE_INDEX;
196 _locationIndex = INVALID_LOCATION_INDEX;
197 }
198
~Zone()199 Zone::~Zone() {
200 g_vm->_gfx->unregisterLabel(_label);
201 delete _label;
202 }
203
translate(int16 x,int16 y)204 void Zone::translate(int16 x, int16 y) {
205 _left += x;
206 _right += x;
207 _top += y;
208 _bottom += y;
209 }
210
hitRect(int x,int y) const211 bool Zone::hitRect(int x, int y) const {
212 // The scripts of Nippon Safes are full of invalid rectangles, used to
213 // provide 'special' features.
214 if (_right < _left || _bottom < _top) {
215 return false;
216 }
217
218 Common::Rect r(_left, _top, _right + 1, _bottom + 1);
219 r.grow(-1);
220
221 return r.contains(x, y);
222 }
223
Dialogue()224 Dialogue::Dialogue() {
225 memset(_questions, 0, sizeof(_questions));
226 _numQuestions = 0;
227 }
228
~Dialogue()229 Dialogue::~Dialogue() {
230 for (int i = 0; i < NUM_QUESTIONS; i++) {
231 delete _questions[i];
232 }
233 }
234
findQuestion(const Common::String & name) const235 Question *Dialogue::findQuestion(const Common::String &name) const {
236 for (uint i = 0; _questions[i]; ++i) {
237 if (_questions[i]->_name == name) {
238 return _questions[i];
239 }
240 }
241 return 0;
242 }
243
addQuestion(Question * q)244 void Dialogue::addQuestion(Question *q) {
245 assert(_numQuestions < NUM_QUESTIONS);
246 assert(q);
247 _questions[_numQuestions] = q;
248 _numQuestions++;
249 }
250
Answer()251 Answer::Answer() {
252 _mood = 0;
253 _noFlags = 0;
254 _yesFlags = 0;
255 _hasCounterCondition = false;
256 _counterValue = 0;
257 _counterOp = 0;
258 }
259
textIsNull()260 bool Answer::textIsNull() {
261 return (_text.equalsIgnoreCase("NULL"));
262 }
263
speakerMood()264 int Answer::speakerMood() {
265 return _mood & 0xF;
266 }
267
Question(const Common::String & name)268 Question::Question(const Common::String &name) : _name(name), _mood(0) {
269 memset(_answers, 0, sizeof(_answers));
270 }
271
~Question()272 Question::~Question() {
273 for (uint32 i = 0; i < NUM_ANSWERS; i++) {
274 delete _answers[i];
275 }
276 }
277
textIsNull()278 bool Question::textIsNull() {
279 return (_text.equalsIgnoreCase("NULL"));
280 }
281
speakerMood()282 int Question::speakerMood() {
283 return _mood & 0xF;
284 }
285
balloonWinding()286 int Question::balloonWinding() {
287 return _mood & 0x10;
288 }
289
290
Instruction()291 Instruction::Instruction() {
292 _index = 0;
293 _flags = 0;
294
295 // common
296 _immediate = 0;
297 _endif = 0;
298
299 // BRA specific
300 _y = 0;
301 }
302
getValue()303 int16 ScriptVar::getValue() {
304
305 if (_flags & kParaImmediate) {
306 return _value;
307 }
308
309 if (_flags & kParaLocal) {
310 return _local->getValue();
311 }
312
313 if (_flags & kParaField) {
314 return _field->getValue();
315 }
316
317 if (_flags & kParaRandom) {
318 return (g_vm->_rnd.getRandomNumber(65536) * _value) >> 16;
319 }
320
321 error("Parameter is not an r-value");
322 return 0; // for compilers that don't support NORETURN
323 }
324
setValue(int16 value)325 void ScriptVar::setValue(int16 value) {
326 if ((_flags & kParaLValue) == 0) {
327 error("Only l-value can be set");
328 }
329
330 if (_flags & kParaLocal) {
331 _local->setValue(value);
332 }
333
334 if (_flags & kParaField) {
335 _field->setValue(value);
336 }
337
338 }
339
setLocal(LocalVariable * local)340 void ScriptVar::setLocal(LocalVariable *local) {
341 _local = local;
342 _flags |= (kParaLocal | kParaLValue);
343 }
344
setField(Animation * anim,AnimationField::AccessorFunc accessor,AnimationField::MutatorFunc mutator)345 void ScriptVar::setField(Animation *anim, AnimationField::AccessorFunc accessor, AnimationField::MutatorFunc mutator) {
346 _field = new AnimationField(anim, accessor, mutator);
347 _flags |= (kParaField | kParaLValue);
348 }
349
setField(Animation * anim,AnimationField::AccessorFunc accessor)350 void ScriptVar::setField(Animation *anim, AnimationField::AccessorFunc accessor) {
351 _field = new AnimationField(anim, accessor);
352 _flags |= kParaField;
353 }
354
setImmediate(int16 value)355 void ScriptVar::setImmediate(int16 value) {
356 _value = value;
357 _flags |= kParaImmediate;
358 }
359
setRandom(int16 seed)360 void ScriptVar::setRandom(int16 seed) {
361 _value = seed;
362 _flags |= kParaRandom;
363 }
364
365
ScriptVar()366 ScriptVar::ScriptVar() {
367 _flags = 0;
368 _local = 0;
369 _value = 0;
370 _field = 0;
371 }
372
~ScriptVar()373 ScriptVar::~ScriptVar() {
374 delete _field;
375 }
376
377
Table(uint32 size)378 Table::Table(uint32 size) : _size(size), _used(0), _disposeMemory(true) {
379 _data = (char**)calloc(size, sizeof(char *));
380 }
381
Table(uint32 size,const char ** data)382 Table::Table(uint32 size, const char **data) : _size(size), _used(size), _disposeMemory(false) {
383 _data = const_cast<char **>(data);
384 }
385
~Table()386 Table::~Table() {
387
388 if (!_disposeMemory) return;
389
390 clear();
391
392 free(_data);
393
394 }
395
addData(const char * s)396 void Table::addData(const char* s) {
397
398 if (!(_used < _size))
399 error("Table overflow");
400
401 char *data = (char *)malloc(strlen(s) + 1);
402 strcpy(data, s);
403 _data[_used++] = data;
404 }
405
lookup(const char * s)406 uint16 Table::lookup(const char* s) {
407
408 for (uint16 i = 0; i < _used; i++) {
409 if (!scumm_stricmp(_data[i], s)) return i + 1;
410 }
411
412 return notFound;
413 }
414
clear()415 void Table::clear() {
416 for (uint32 i = 0; i < _used; i++)
417 free(_data[i]);
418
419 _used = 0;
420 }
421
item(uint index) const422 const char *Table::item(uint index) const {
423 assert(index < _used);
424 return _data[index];
425 }
426
427
FixedTable(uint32 size,uint32 fixed)428 FixedTable::FixedTable(uint32 size, uint32 fixed) : Table(size), _numFixed(fixed) {
429 }
430
clear()431 void FixedTable::clear() {
432 uint32 deleted = 0;
433 for (uint32 i = _numFixed; i < _used; i++) {
434 free(_data[i]);
435 _data[i] = 0;
436 deleted++;
437 }
438
439 _used -= deleted;
440 }
441
createTableFromStream(uint32 size,Common::SeekableReadStream * stream)442 Table* createTableFromStream(uint32 size, Common::SeekableReadStream *stream) {
443 assert(stream);
444
445 Table *t = new Table(size);
446 assert(t);
447
448 Script s(stream, false);
449 s.readLineToken();
450 while (scumm_stricmp(_tokens[0], "ENDTABLE")) {
451 t->addData(_tokens[0]);
452 s.readLineToken();
453 }
454 delete stream;
455 return t;
456 }
457
458
459 } // namespace Parallaction
460