1 | Index: tools/descumm-common.cpp
|
---|
2 | ===================================================================
|
---|
3 | RCS file: /cvsroot/scummvm/tools/descumm-common.cpp,v
|
---|
4 | retrieving revision 1.10
|
---|
5 | diff -U8 -d -r1.10 descumm-common.cpp
|
---|
6 | --- tools/descumm-common.cpp 21 Sep 2004 15:17:34 -0000 1.10
|
---|
7 | +++ tools/descumm-common.cpp 30 Sep 2004 01:06:54 -0000
|
---|
8 | @@ -34,16 +34,17 @@
|
---|
9 |
|
---|
10 | int g_jump_opcode;
|
---|
11 |
|
---|
12 | bool alwaysShowOffs = false;
|
---|
13 | bool dontOutputIfs = false;
|
---|
14 | bool dontOutputElse = false;
|
---|
15 | bool dontOutputElseif = false;
|
---|
16 | bool dontOutputWhile = false;
|
---|
17 | +bool dontOutputBreaks = false;
|
---|
18 | bool dontShowOpcode = false;
|
---|
19 | bool dontShowOffsets = false;
|
---|
20 | bool haltOnError;
|
---|
21 |
|
---|
22 | byte scriptVersion;
|
---|
23 | byte heVersion;
|
---|
24 |
|
---|
25 | byte *cur_pos, *org_pos;
|
---|
26 | @@ -198,28 +199,36 @@
|
---|
27 | p->from = cur;
|
---|
28 | p->to = to;
|
---|
29 | return true;
|
---|
30 | }
|
---|
31 |
|
---|
32 | // Returns 0 or 1 depending if it's ok to add an else
|
---|
33 | bool maybeAddElse(uint cur, uint to)
|
---|
34 | {
|
---|
35 | + int i;
|
---|
36 | BlockStack *p;
|
---|
37 |
|
---|
38 | if (((to | cur) >> 16) || (to <= cur))
|
---|
39 | return false; /* Invalid jump */
|
---|
40 |
|
---|
41 | if (!num_block_stack)
|
---|
42 | return false; /* There are no previous blocks, so an else is not ok */
|
---|
43 |
|
---|
44 | p = &block_stack[num_block_stack - 1];
|
---|
45 | if (cur != p->to)
|
---|
46 | return false; /* We have no prevoius if that is exiting right at the end of this goto */
|
---|
47 |
|
---|
48 | + /* Don't jump out of previous blocks. This test is stronger than the one in
|
---|
49 | + maybeAddIf. ( >= vs > ) */
|
---|
50 | + for (i = 0, p = block_stack; i < num_block_stack - 1; i++, p++) {
|
---|
51 | + if (to >= p->to)
|
---|
52 | + return false;
|
---|
53 | + }
|
---|
54 | +
|
---|
55 | num_block_stack--;
|
---|
56 | if (maybeAddIf(cur, to))
|
---|
57 | return true; /* We can add an else */
|
---|
58 | num_block_stack++;
|
---|
59 | return false; /* An else is not OK here :( */
|
---|
60 | }
|
---|
61 |
|
---|
62 | bool maybeAddElseIf(uint cur, uint elseto, uint to)
|
---|
63 | @@ -241,33 +250,58 @@
|
---|
64 | if (scriptVersion == 8)
|
---|
65 | k = to - 5;
|
---|
66 | else
|
---|
67 | k = to - 3;
|
---|
68 |
|
---|
69 | if (k >= size_of_code)
|
---|
70 | return false; /* Invalid jump */
|
---|
71 |
|
---|
72 | - if (org_pos[k] != g_jump_opcode)
|
---|
73 | - return false; /* Invalid jump */
|
---|
74 | -
|
---|
75 | - if (scriptVersion == 8)
|
---|
76 | - k = to + TO_LE_32(*(int32*)(org_pos + k + 1));
|
---|
77 | - else
|
---|
78 | - k = to + TO_LE_16(*(int16*)(org_pos + k + 1));
|
---|
79 | -
|
---|
80 | - if (k != elseto)
|
---|
81 | - return false; /* Not an ifelse */
|
---|
82 | -
|
---|
83 | + if (elseto != to) {
|
---|
84 | + if (org_pos[k] != g_jump_opcode)
|
---|
85 | + return false; /* Invalid jump */
|
---|
86 | +
|
---|
87 | + if (scriptVersion == 8)
|
---|
88 | + k = to + TO_LE_32(*(int32*)(org_pos + k + 1));
|
---|
89 | + else
|
---|
90 | + k = to + TO_LE_16(*(int16*)(org_pos + k + 1));
|
---|
91 | +
|
---|
92 | + if (k != elseto)
|
---|
93 | + return false; /* Not an ifelse */
|
---|
94 | + }
|
---|
95 | p->from = cur;
|
---|
96 | p->to = to;
|
---|
97 |
|
---|
98 | return true;
|
---|
99 | }
|
---|
100 |
|
---|
101 | +bool maybeAddBreak(uint cur, uint to)
|
---|
102 | +{
|
---|
103 | + BlockStack *p;
|
---|
104 | +
|
---|
105 | + if (((to | cur) >> 16) || (to <= cur))
|
---|
106 | + return false; /* Invalid jump */
|
---|
107 | +
|
---|
108 | + if (!num_block_stack)
|
---|
109 | + return false; /* There are no previous blocks, so a break is not ok */
|
---|
110 | +
|
---|
111 | + /* Find the first parent block that is a while and if we're jumping to the end of that, we use a break */
|
---|
112 | + for (int i = num_block_stack - 1; i >= 0; i--) {
|
---|
113 | + p = &block_stack[i];
|
---|
114 | + if (p->isWhile) {
|
---|
115 | + if (to == p->to)
|
---|
116 | + return true;
|
---|
117 | + else
|
---|
118 | + return false;
|
---|
119 | + }
|
---|
120 | + }
|
---|
121 | +
|
---|
122 | + return false;
|
---|
123 | +}
|
---|
124 | +
|
---|
125 | void writePendingElse()
|
---|
126 | {
|
---|
127 | if (pendingElse) {
|
---|
128 | char buf[32];
|
---|
129 | sprintf(buf, alwaysShowOffs ? "} else /*%.4X*/ {" : "} else {", pendingElseTo);
|
---|
130 | outputLine(buf, offs_of_line, pendingElseOpcode, pendingElseIndent - 1);
|
---|
131 | offs_of_line = pendingElseOffs;
|
---|
132 | pendingElse = false;
|
---|
133 | Index: tools/descumm-tool.cpp
|
---|
134 | ===================================================================
|
---|
135 | RCS file: /cvsroot/scummvm/tools/descumm-tool.cpp,v
|
---|
136 | retrieving revision 1.8
|
---|
137 | diff -U8 -d -r1.8 descumm-tool.cpp
|
---|
138 | --- tools/descumm-tool.cpp 28 Sep 2004 19:09:16 -0000 1.8
|
---|
139 | +++ tools/descumm-tool.cpp 30 Sep 2004 01:06:54 -0000
|
---|
140 | @@ -41,16 +41,17 @@
|
---|
141 | "\t-n\tUse Indy3-256 specific hacks\n"
|
---|
142 | "\t-z\tUse Zak256 specific hacks\n"
|
---|
143 | "\t-u\tScript is Unblocked/has no header\n"
|
---|
144 | "\t-o\tAlways Show offsets\n"
|
---|
145 | "\t-i\tDon't output ifs\n"
|
---|
146 | "\t-e\tDon't output else\n"
|
---|
147 | "\t-f\tDon't output else-if\n"
|
---|
148 | "\t-w\tDon't output while\n"
|
---|
149 | + "\t-b\tDon't output breaks\n"
|
---|
150 | "\t-c\tDon't show opcode\n"
|
---|
151 | "\t-x\tDon't show offsets\n"
|
---|
152 | "\t-h\tHalt on error\n");
|
---|
153 | exit(0);
|
---|
154 | }
|
---|
155 |
|
---|
156 | int skipVerbHeader_V12(byte *p)
|
---|
157 | {
|
---|
158 | @@ -215,16 +216,19 @@
|
---|
159 | dontOutputElse = true;
|
---|
160 | break;
|
---|
161 | case 'f':
|
---|
162 | dontOutputElseif = true;
|
---|
163 | break;
|
---|
164 | case 'w':
|
---|
165 | dontOutputWhile = true;
|
---|
166 | break;
|
---|
167 | + case 'b':
|
---|
168 | + dontOutputBreaks = true;
|
---|
169 | + break;
|
---|
170 | case 'c':
|
---|
171 | dontShowOpcode = true;
|
---|
172 | break;
|
---|
173 | case 'x':
|
---|
174 | dontShowOffsets = true;
|
---|
175 | break;
|
---|
176 | case 'h':
|
---|
177 | haltOnError = true;
|
---|
178 | @@ -380,17 +384,18 @@
|
---|
179 | if (haveElse) {
|
---|
180 | haveElse = false;
|
---|
181 | j--;
|
---|
182 | }
|
---|
183 | outputLine(buf, offs_of_line, opcode, j);
|
---|
184 | offs_of_line = get_curoffs();
|
---|
185 | }
|
---|
186 | while (indentBlock(get_curoffs())) {
|
---|
187 | - outputLine("}", -1, -1, -1);
|
---|
188 | + outputLine("}", offs_of_line, -1, -1);
|
---|
189 | + offs_of_line = get_curoffs();
|
---|
190 | }
|
---|
191 | fflush(stdout);
|
---|
192 | }
|
---|
193 |
|
---|
194 | printf("END\n");
|
---|
195 |
|
---|
196 | /*
|
---|
197 | if (scriptVersion >= 6 && num_stack != 0) {
|
---|
198 | Index: tools/descumm.h
|
---|
199 | ===================================================================
|
---|
200 | RCS file: /cvsroot/scummvm/tools/descumm.h,v
|
---|
201 | retrieving revision 1.13
|
---|
202 | diff -U8 -d -r1.13 descumm.h
|
---|
203 | --- tools/descumm.h 28 Sep 2004 19:09:16 -0000 1.13
|
---|
204 | +++ tools/descumm.h 30 Sep 2004 01:06:54 -0000
|
---|
205 | @@ -57,16 +57,17 @@
|
---|
206 | //
|
---|
207 | // Command line options
|
---|
208 | //
|
---|
209 | extern bool alwaysShowOffs;
|
---|
210 | extern bool dontOutputIfs;
|
---|
211 | extern bool dontOutputElse;
|
---|
212 | extern bool dontOutputElseif;
|
---|
213 | extern bool dontOutputWhile;
|
---|
214 | +extern bool dontOutputBreaks;
|
---|
215 | extern bool dontShowOpcode;
|
---|
216 | extern bool dontShowOffsets;
|
---|
217 | extern bool haltOnError;
|
---|
218 |
|
---|
219 | //
|
---|
220 | // The SCUMM version used for the script we are descumming.
|
---|
221 | //
|
---|
222 | extern byte scriptVersion;
|
---|
223 | @@ -93,16 +94,17 @@
|
---|
224 | extern char *strecpy(char *buf, const char *src);
|
---|
225 | extern int get_curoffs();
|
---|
226 | extern int get_byte();
|
---|
227 | extern int get_word();
|
---|
228 |
|
---|
229 | extern bool maybeAddIf(uint cur, uint to);
|
---|
230 | extern bool maybeAddElse(uint cur, uint to);
|
---|
231 | extern bool maybeAddElseIf(uint cur, uint elseto, uint to);
|
---|
232 | +extern bool maybeAddBreak(uint cur, uint to);
|
---|
233 | extern void writePendingElse();
|
---|
234 |
|
---|
235 | //
|
---|
236 | // Entry points for the descumming
|
---|
237 | //
|
---|
238 | extern void next_line_V12(char *buf); // For V1 and V2
|
---|
239 | extern void next_line_V345(char *buf); // For V3, V4, V5
|
---|
240 | extern void next_line_V67(char *buf);
|
---|
241 | Index: tools/descumm6.cpp
|
---|
242 | ===================================================================
|
---|
243 | RCS file: /cvsroot/scummvm/tools/descumm6.cpp,v
|
---|
244 | retrieving revision 1.180
|
---|
245 | diff -U8 -d -r1.180 descumm6.cpp
|
---|
246 | --- tools/descumm6.cpp 28 Sep 2004 19:09:16 -0000 1.180
|
---|
247 | +++ tools/descumm6.cpp 30 Sep 2004 01:06:55 -0000
|
---|
248 | @@ -52,61 +52,16 @@
|
---|
249 | Anyway, the fixed key pattern here seems to be for each case:
|
---|
250 | dup - push - eq - jumpFalse - kill
|
---|
251 | And of course a push before the first of these. Note that there doesn't have
|
---|
252 | to be a jump before each case: after all, "fall through" is possible with C(++)
|
---|
253 | switch/case statements, too, so it's possible they used that in Scumm, too.
|
---|
254 |
|
---|
255 | */
|
---|
256 |
|
---|
257 | -/*
|
---|
258 | - FIXME: The current "while" and "else" detection code interfer. There simply are case
|
---|
259 | - which they can't decode correctly, leading to completely wrong output. An example
|
---|
260 | - can be seen by looking at script 52 of Sam&Max. It gets descummed to this:
|
---|
261 | -
|
---|
262 | - [002E] (43) localvar1 = 6
|
---|
263 | - [0037] (5D) while (localvar1 <= 80) {
|
---|
264 | - [0041] (5D) if (array-178[localvar1] == 0) {
|
---|
265 | - [004E] (47) array-178[localvar0] = localvar1
|
---|
266 | - [0057] (4F) var179 += 1
|
---|
267 | - [005A] (73) } else {
|
---|
268 | - [005D] (4F) localvar1 += 1
|
---|
269 | - [0060] (73) jump 37
|
---|
270 | - [0063] (**) }
|
---|
271 | - [0063] (**) }
|
---|
272 | - [0063] (**) }
|
---|
273 | - [0063] (66) stopObjectCodeB()
|
---|
274 | -
|
---|
275 | - Using "-e" we get the correct result:
|
---|
276 | - [002E] (43) localvar1 = 6
|
---|
277 | - [0037] (5D) while (localvar1 <= 80) {
|
---|
278 | - [0041] (5D) if (array-178[localvar1] == 0) {
|
---|
279 | - [004E] (47) array-178[localvar0] = localvar1
|
---|
280 | - [0057] (4F) var179 += 1
|
---|
281 | - [005A] (73) jump 63
|
---|
282 | - [005D] (**) }
|
---|
283 | - [005D] (4F) localvar1 += 1
|
---|
284 | - [0063] (**) }
|
---|
285 | - [0063] (**) }
|
---|
286 | - [0060] (66) stopObjectCodeB()
|
---|
287 | -(but note the wrong offset in the last line!)
|
---|
288 | -
|
---|
289 | -When doing raw output, we get this:
|
---|
290 | - [0031] (43) localvar1 = 6
|
---|
291 | - [0037] (5D) unless ((localvar1 <= 80)) jump 63
|
---|
292 | - [0041] (5D) unless ((array-178[localvar1] == 0)) jump 5d
|
---|
293 | - [004E] (47) array-178[localvar0] = localvar1
|
---|
294 | - [0057] (4F) var179 += 1
|
---|
295 | - [005A] (73) jump 63
|
---|
296 | - [005D] (4F) localvar1 += 1
|
---|
297 | - [0060] (73) jump 37
|
---|
298 | - [0063] (66) stopObjectCodeB()
|
---|
299 | -
|
---|
300 | -*/
|
---|
301 | -
|
---|
302 |
|
---|
303 | struct StackEnt {
|
---|
304 | byte type;
|
---|
305 | long data;
|
---|
306 | StackEnt *left, *right;
|
---|
307 | char *str;
|
---|
308 | StackEnt **list;
|
---|
309 | };
|
---|
310 | @@ -949,23 +904,23 @@
|
---|
311 | where += sprintf(where, "localvar%ld", se->data & 0xFFF);
|
---|
312 | } else {
|
---|
313 | where += sprintf(where, "?var?%ld", se->data);
|
---|
314 | }
|
---|
315 | }
|
---|
316 | break;
|
---|
317 | case seArray:
|
---|
318 | if (se->left) {
|
---|
319 | - where += sprintf(where, "array-%ld[", se->data);
|
---|
320 | + where += sprintf(where, "array%ld[", se->data);
|
---|
321 | where = se_astext(se->left, where);
|
---|
322 | where = strecpy(where, "][");
|
---|
323 | where = se_astext(se->right, where);
|
---|
324 | where = strecpy(where, "]");
|
---|
325 | } else {
|
---|
326 | - where += sprintf(where, "array-%ld[", se->data);
|
---|
327 | + where += sprintf(where, "array%ld[", se->data);
|
---|
328 | where = se_astext(se->right, where);
|
---|
329 | where = strecpy(where, "]");
|
---|
330 | }
|
---|
331 | break;
|
---|
332 | case seUnary:
|
---|
333 | where += sprintf(where, "%s", oper_list[se->data]);
|
---|
334 | where = se_astext(se->left, where);
|
---|
335 | break;
|
---|
336 | @@ -1037,17 +992,24 @@
|
---|
337 | char *e = se_astext(dst, output);
|
---|
338 | e = strecpy(e, " = ");
|
---|
339 | se_astext(src, e);
|
---|
340 | }
|
---|
341 |
|
---|
342 | void doAdd(char *output, StackEnt * se, int val)
|
---|
343 | {
|
---|
344 | char *e = se_astext(se, output);
|
---|
345 | - sprintf(e, " += %d", val);
|
---|
346 | + if (val == 1) {
|
---|
347 | + sprintf(e, "++");
|
---|
348 | + } else if (val == -1) {
|
---|
349 | + sprintf(e, "--");
|
---|
350 | + } else {
|
---|
351 | + /* SCUMM doesn't support this */
|
---|
352 | + sprintf(e, " += %d", val);
|
---|
353 | + }
|
---|
354 | }
|
---|
355 |
|
---|
356 | StackEnt *dup(char *output, StackEnt * se)
|
---|
357 | {
|
---|
358 | static int dupindex = 0;
|
---|
359 |
|
---|
360 | if (se->type == seInt)
|
---|
361 | return se;
|
---|
362 | @@ -1314,16 +1276,20 @@
|
---|
363 | pendingElseOffs = cur;
|
---|
364 | pendingElseOpcode = g_jump_opcode;
|
---|
365 | pendingElseIndent = num_block_stack;
|
---|
366 | } else {
|
---|
367 | if (num_block_stack && !dontOutputWhile) {
|
---|
368 | BlockStack *p = &block_stack[num_block_stack - 1];
|
---|
369 | if (p->isWhile && cur == p->to)
|
---|
370 | return; // A 'while' ends here.
|
---|
371 | + if (!dontOutputBreaks && maybeAddBreak(cur, to)) {
|
---|
372 | + sprintf(output, "break");
|
---|
373 | + return;
|
---|
374 | + }
|
---|
375 | }
|
---|
376 | sprintf(output, "jump %x", to);
|
---|
377 | }
|
---|
378 | }
|
---|
379 |
|
---|
380 | void jumpif(char *output, StackEnt * se, bool negate)
|
---|
381 | {
|
---|
382 | int offset = get_word();
|
---|
383 | @@ -1331,31 +1297,27 @@
|
---|
384 | int to = cur + offset;
|
---|
385 | char *e = output;
|
---|
386 |
|
---|
387 | if (!dontOutputElseif && pendingElse) {
|
---|
388 | if (maybeAddElseIf(cur, pendingElseTo, to)) {
|
---|
389 | pendingElse = false;
|
---|
390 | haveElse = true;
|
---|
391 | e = strecpy(e, "} else if (");
|
---|
392 | - if (negate)
|
---|
393 | - se = se_neg(se);
|
---|
394 | e = se_astext(se, e, false);
|
---|
395 | sprintf(e, alwaysShowOffs ? ") /*%.4X*/ {" : ") {", to);
|
---|
396 | return;
|
---|
397 | }
|
---|
398 | }
|
---|
399 |
|
---|
400 | if (!dontOutputIfs && maybeAddIf(cur, to)) {
|
---|
401 | - if (!dontOutputWhile && block_stack[num_block_stack - 1].isWhile) {
|
---|
402 | - e = strecpy(e, "while (");
|
---|
403 | - } else
|
---|
404 | - e = strecpy(e, "if (");
|
---|
405 | - if (negate)
|
---|
406 | - se = se_neg(se);
|
---|
407 | + if (!dontOutputWhile && block_stack[num_block_stack - 1].isWhile)
|
---|
408 | + e = strecpy(e, negate ? "until (" : "while (");
|
---|
409 | + else
|
---|
410 | + e = strecpy(e, negate ? "unless (" : "if (");
|
---|
411 | e = se_astext(se, e, false);
|
---|
412 | sprintf(e, alwaysShowOffs ? ") /*%.4X*/ {" : ") {", to);
|
---|
413 | return;
|
---|
414 | }
|
---|
415 |
|
---|
416 | e = strecpy(e, negate ? "if (" : "unless (");
|
---|
417 | e = se_astext(se, e);
|
---|
418 | sprintf(e, ") jump %x", to);
|
---|
419 | @@ -1518,17 +1480,17 @@
|
---|
420 | "\x97|softUserputOff,"
|
---|
421 | "\x99z|setCursorImg,"
|
---|
422 | "\x9App|setCursorHotspot,"
|
---|
423 | "\x9Cp|initCharset,"
|
---|
424 | "\x9Dl|charsetColors,"
|
---|
425 | "\xD6p|makeCursorColorTransparent");
|
---|
426 | break;
|
---|
427 | case 0x6C:
|
---|
428 | - ext(output, "|break");
|
---|
429 | + ext(output, "|breakHere");
|
---|
430 | break;
|
---|
431 | case 0x6D:
|
---|
432 | ext(output, "rlp|ifClassOfIs");
|
---|
433 | break;
|
---|
434 | case 0x6E:
|
---|
435 | ext(output, "lp|setClass");
|
---|
436 | break;
|
---|
437 | case 0x6F:
|
---|
438 | @@ -2910,17 +2872,17 @@
|
---|
439 | "\x97|softUserputOff,"
|
---|
440 | "\x99z|setCursorImg,"
|
---|
441 | "\x9App|setCursorHotspot,"
|
---|
442 | "\x9Cp|initCharset,"
|
---|
443 | "\x9Dl|charsetColors,"
|
---|
444 | "\xD6p|makeCursorColorTransparent");
|
---|
445 | break;
|
---|
446 | case 0x6C:
|
---|
447 | - ext(output, "|break");
|
---|
448 | + ext(output, "|breakHere");
|
---|
449 | break;
|
---|
450 | case 0x6D:
|
---|
451 | ext(output, "rlp|ifClassOfIs");
|
---|
452 | break;
|
---|
453 | case 0x6E:
|
---|
454 | ext(output, "lp|setClass");
|
---|
455 | break;
|
---|
456 | case 0x6F:
|
---|