Mercurial > otakunoraifu
annotate scn2k/scn2k_cmd.cc @ 74:f8751d74918b default tip
Remove “duplicate” functions as they can be remplaced by a nearly-identical existing function.
author | Emmanuel Gil Peyrot <linkmauve@linkmauve.fr> |
---|---|
date | Sat, 02 Apr 2011 19:13:54 +0200 |
parents | e4a12dd9a51b |
children |
rev | line source |
---|---|
0 | 1 /* |
2 * Copyright (c) 2004-2006 Kazunori "jagarl" Ueno | |
3 * All rights reserved. | |
4 * | |
5 * Redistribution and use in source and binary forms, with or without | |
6 * modification, are permitted provided that the following conditions | |
7 * are met: | |
8 * 1. Redistributions of source code must retain the above copyright | |
9 * notice, this list of conditions and the following disclaimer. | |
10 * 2. Redistributions in binary form must reproduce the above copyright | |
11 * notice, this list of conditions and the following disclaimer in the | |
12 * documentation and/or other materials provided with the distribution. | |
13 * 3. The name of the author may not be used to endorse or promote products | |
14 * derived from this software without specific prior written permission. | |
15 * | |
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR | |
17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | |
18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | |
19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | |
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | |
21 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |
22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |
23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | |
25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
26 */ | |
27 | |
28 | |
52 | 29 #include "scn2k.h" |
0 | 30 |
52 | 31 #include <stdlib.h> |
32 #include <stdarg.h> | |
33 #include <stdio.h> | |
34 #include <string.h> | |
35 #include <string> | |
36 #include "system/file.h" | |
0 | 37 |
38 using namespace std; | |
39 | |
40 | |
65
4416cfac86ae
Convert EUC-JP files to UTF8
Thibaut Girka <thib@sitedethib.com>
parents:
63
diff
changeset
|
41 /* 注意点: @@@ で表記 */ |
0 | 42 |
43 //bool debug_flag = true; | |
44 bool debug_flag = false; | |
45 void dprintf(const char* fmt, ...) { | |
46 if (debug_flag) { | |
52 | 47 va_list ap; |
48 va_start(ap, fmt); | |
0 | 49 vprintf(fmt, ap); |
50 va_end(ap); | |
51 } | |
52 } | |
53 | |
54 | |
55 void eprintf(const char* fmt, ...) { | |
56 va_list ap; va_start(ap, fmt); | |
57 // vprintf(fmt, ap); | |
58 va_end(ap); | |
59 } | |
60 | |
61 /************************************************************** | |
62 ** Flag | |
63 */ | |
64 | |
65 Flags::Flags(void) { | |
66 int i,j; | |
67 for (i=0; i<=TYPE_VARMAX; i++) { | |
68 for (j=0; j<2000; j++) { | |
69 var[i][j] = 0; | |
70 } | |
71 } | |
72 sys = 0; | |
73 } | |
74 | |
75 bool Flags::IsInt(int type) const { | |
76 int v = type % 26; | |
43
01aa5ddf7dc8
A lot of very minor improvements (deleted some unused variables, and other things like that...)
thib
parents:
29
diff
changeset
|
77 return (v >= 0 && v < 7) || v == 25; |
0 | 78 } |
79 | |
80 int Flags::MaxIndex(int type) const { | |
81 switch (type / 26) { | |
82 case 1: | |
83 return 63999; | |
84 case 2: | |
85 return 31999; | |
86 case 3: | |
87 return 15999; | |
88 case 4: | |
89 return 7999; | |
90 default: | |
91 return 1999; | |
92 } | |
93 } | |
94 | |
95 int Flags::operator()() const { | |
96 return sys; // rand() % 10000; | |
97 } | |
98 | |
99 int Flags::operator() (VarInfo info) const { | |
100 return Get(info.type, info.number); | |
101 } | |
102 | |
103 int Flags::Get(int type, int number) const { | |
104 int index = type % 26; | |
105 type /= 26; | |
106 if (index == 25) { | |
107 if (var[7][number] != 0) return var[7][number]; | |
108 if (cgm_data.find(number) == cgm_data.end()) return 0; | |
109 else return 1; | |
110 } | |
111 if (index == 10) index = 8; | |
112 if (index == 11) index = 9; | |
113 if (index > TYPE_VARMAX || uint(type) > 4) return 0; | |
114 if (type == 0) { | |
65
4416cfac86ae
Convert EUC-JP files to UTF8
Thibaut Girka <thib@sitedethib.com>
parents:
63
diff
changeset
|
115 // A[]..G[], Z[] を直に読む |
0 | 116 if (uint(number) >= 2000) return 0; |
117 return var[index][number]; | |
118 } else { | |
65
4416cfac86ae
Convert EUC-JP files to UTF8
Thibaut Girka <thib@sitedethib.com>
parents:
63
diff
changeset
|
119 // Ab[]..G4b[], Z8b[] などを読む |
0 | 120 int factor = 1 << (type - 1); |
121 int eltsize = 32 / factor; | |
122 if (uint(number) >= (64000 / factor)) return 0; | |
123 return (var[index][number / eltsize] >> ((number % eltsize) * factor)) & ((1 << factor) - 1); | |
124 } | |
125 } | |
126 | |
127 void Flags::Set(VarInfo info, int value) { | |
128 int type = info.type / 26; | |
129 int index = info.type % 26; | |
130 if (index == 25) { | |
131 if (uint(info.number) >= 2000) return; | |
132 if (value == 0) | |
133 cgm_data.erase(info.number); | |
134 else | |
135 cgm_data.insert(info.number); | |
136 index = 7; | |
137 } | |
138 if (index == 10) index = 8; | |
139 if (index == 11) index = 9; | |
140 if (index < 0 || index > TYPE_VARMAX) { | |
141 fprintf(stderr,"Error: invalid access to Var<%d>[%d]\n",info.type,info.number); | |
142 } | |
143 if (type == 0) { | |
65
4416cfac86ae
Convert EUC-JP files to UTF8
Thibaut Girka <thib@sitedethib.com>
parents:
63
diff
changeset
|
144 // A[]..G[], Z[] を直に書く |
0 | 145 if (uint(info.number) >= 2000) return; |
146 var[index][info.number] = value; | |
147 } else { | |
65
4416cfac86ae
Convert EUC-JP files to UTF8
Thibaut Girka <thib@sitedethib.com>
parents:
63
diff
changeset
|
148 // Ab[]..G4b[], Z8b[] などを書く |
0 | 149 int factor = 1 << (type - 1); |
150 int eltsize = 32 / factor; | |
151 int eltmask = (1 << factor) - 1; | |
152 int shift = (info.number % eltsize) * factor; | |
153 if (uint(info.number) >= (64000 / factor)) return; | |
154 var[index][info.number / eltsize] = | |
155 (var[index][info.number / eltsize] & ~(eltmask << shift)) | |
156 | (value & eltmask) << shift; | |
157 } | |
158 } | |
159 | |
160 void Flags::SetSys(int value) { | |
161 sys = value; | |
162 } | |
52 | 163 |
0 | 164 void Flags::SetStr(VarInfo info, string val) { |
165 switch(info.type) { | |
52 | 166 case TYPE_VARLOCSTR: |
167 if (info.number >= 3) return; | |
168 loc_str[info.number] = val; | |
169 break; | |
170 case TYPE_VARSYSSTR: | |
171 if (info.number >= 2000) return; | |
172 sys_str[info.number] = val; | |
173 break; | |
174 case TYPE_VARSTR: | |
175 if (info.number >= 2000) return; | |
176 str[info.number] = val; | |
177 break; | |
0 | 178 } |
179 return; | |
180 } | |
52 | 181 |
0 | 182 void Flags::Str(int type, unsigned int number, char* buf, int sz) const { |
183 if (sz <= 0) return; | |
184 buf[0] = 0; | |
185 const string* sptr; | |
186 switch(type) { | |
52 | 187 case TYPE_VARLOCSTR: |
188 if (number >= 3) return; | |
189 sptr = &loc_str[number]; | |
190 break; | |
191 case TYPE_VARSYSSTR: | |
192 if (number >= 2000) return; | |
193 sptr = &sys_str[number]; | |
194 break; | |
195 case TYPE_VARSTR: | |
196 if (number >= 2000) return; | |
197 sptr = &str[number]; | |
198 break; | |
0 | 199 } |
200 | |
201 int len = sptr->length(); | |
202 if (sz-1 > len) sz = len; | |
203 sptr->copy(buf, sz, 0); | |
204 buf[sz] = 0; | |
205 return; | |
206 } | |
52 | 207 |
0 | 208 string Flags::Str(int type, unsigned int number) const { |
209 switch(type) { | |
210 case TYPE_VARLOCSTR: | |
211 if (number >= 3) return ""; | |
212 return loc_str[number]; | |
213 case TYPE_VARSYSSTR: | |
214 if (number >= 2000) return ""; | |
215 return sys_str[number]; | |
216 case TYPE_VARSTR: | |
217 if (number >= 2000) return ""; | |
218 return str[number]; | |
219 } | |
220 return ""; | |
221 } | |
222 | |
63 | 223 void Flags::Load(const char* save) { |
224 Load(save, false); | |
225 } | |
226 | |
227 void Flags::LoadSys(const char* save) { | |
228 Load(save, true); | |
229 } | |
230 | |
231 void Flags::Load(const char* save, bool sys) { | |
232 int i, j; | |
233 int start, end; | |
234 std::string *var_str; | |
235 char string_field[] = "V<?>[%04d]="; | |
236 | |
237 start = (sys) ? (TYPE_NONSYSVARMAX + 1) : 0; | |
238 end = (sys) ? (TYPE_NONSYSVARMAX + 2) : TYPE_NONSYSVARMAX; | |
239 | |
240 var_str = (sys) ? sys_str : str; | |
241 string_field[2] = (sys) ? 'M' : 'C'; | |
242 | |
243 for (i=start; i <= end; i++) { | |
244 for (j=0; j < 2000; j++) { | |
245 var[i][j] = 0; | |
246 } | |
247 } | |
248 for (j=0; j<2000; j++) { | |
249 var_str[j] = ""; | |
250 } | |
251 sys = 0; | |
252 | |
253 save = strstr(save, "\n[Flags]\n"); | |
254 | |
255 if (save) { | |
256 save += strlen("\n[Flags]\n"); | |
257 do { | |
258 if (save[0] == '[') break; // next section | |
259 if (strncmp(save, string_field, 2) == 0) { | |
260 if (strncmp(save, string_field, 5) == 0) { // string | |
261 char buf[1024]; | |
262 int n; | |
263 if (sscanf(save, string_field, &n) == 1) { | |
264 const char* s = strchr(save, '='); | |
265 s++; | |
266 const char* send = strchr(s, '\n'); | |
267 int slen = send - s; | |
268 strncpy(buf, s, slen); | |
269 buf[slen] = 0; | |
270 if (n >= 0 && n < 2000) | |
271 var_str[n] = buf; | |
272 } | |
273 } else if (save[2] >= '0' && save[2] <= '9') { | |
274 int c, n, v; | |
275 if (sscanf(save, "V<%d>[%04d]=%d\n",&c,&n,&v) == 3) { | |
276 if (n >= 0 && n < 2000) | |
277 { | |
278 if (!sys && c >= 0 && c <= TYPE_NONSYSVARMAX) | |
279 var[c][n] = v; | |
280 else if (sys && c == TYPE_NONSYSVARMAX + 1) | |
281 var[TYPE_NONSYSVARMAX + 1][n] = v; | |
282 else if (sys && c == 25) | |
283 var[7][n] = v; | |
284 } | |
285 } | |
286 } | |
287 } | |
288 save = strchr(save, '\n'); | |
289 if (save) | |
290 save++; | |
291 } while (save); | |
292 } | |
293 } | |
294 | |
0 | 295 void Flags::Save(string& save) { |
296 char buf[1024]; | |
297 save = "\n[Flags]\n"; | |
63 | 298 int i, j; |
0 | 299 for (i=0; i<=TYPE_NONSYSVARMAX; i++) { |
300 for (j=0; j<2000; j++) { | |
301 if (var[i][j] != 0) { | |
302 sprintf(buf, "V<%d>[%04d]=%d\n",i,j,var[i][j]); | |
303 save += buf; | |
304 } | |
305 } | |
306 } | |
307 for (j=0; j<2000; j++) { | |
308 if (str[j].length() != 0) { | |
309 sprintf(buf, "V<C>[%04d]=%s\n", j, str[j].c_str()); | |
310 save += buf; | |
311 } | |
312 } | |
313 } | |
52 | 314 |
315 void Flags::SaveSys(string& save) { //FIXME: see how to factorize with Save | |
0 | 316 char buf[1024]; |
317 int j; | |
318 save = "\n[Flags]\n"; | |
63 | 319 for (j=0; j<2000; j++) { |
0 | 320 if (var[6][j] != 0) { |
63 | 321 sprintf(buf, "V<6>[%04d]=%d\n", j, var[6][j]); |
322 save += buf; | |
0 | 323 } |
63 | 324 } |
0 | 325 for (j=0; j<2000; j++) { |
326 if (var[7][j] != 0) { | |
327 sprintf(buf, "V<25>[%04d]=%d\n",j,var[7][j]); | |
328 save += buf; | |
329 } | |
330 } | |
331 for (j=0; j<2000; j++) { | |
332 if (sys_str[j].length() != 0) { | |
333 sprintf(buf, "V<M>[%04d]=%s\n", j, sys_str[j].c_str()); | |
334 save += buf; | |
335 } | |
336 } | |
337 } | |
52 | 338 |
0 | 339 bool Flags::Exec(Cmd& cmd) { |
65
4416cfac86ae
Convert EUC-JP files to UTF8
Thibaut Girka <thib@sitedethib.com>
parents:
63
diff
changeset
|
340 if (cmd.cmd_type == CMD_FLAGS) { // 代入演算 |
0 | 341 if (cmd.args.size() != 2) return false; |
342 Set(cmd.args[0], cmd.args[1].value); | |
343 cmd.clear(); | |
344 return true; | |
345 } | |
65
4416cfac86ae
Convert EUC-JP files to UTF8
Thibaut Girka <thib@sitedethib.com>
parents:
63
diff
changeset
|
346 if (cmd.cmd1 == 1 && cmd.cmd2 == 0x0a) { // 文字列演算 |
0 | 347 VarInfo arg1 = cmd.args[0]; |
348 switch(cmd.cmd3) { | |
52 | 349 case 0: |
350 if (cmd.cmd4 == 0) { | |
351 SetStr(arg1, cmd.Str(cmd.args[1])); | |
352 } else if (cmd.cmd4 == 1) { | |
353 string s = cmd.Str(cmd.args[1]); | |
354 const char* sc = s.c_str(); | |
355 int len = cmd.args[2].value; | |
356 int i; | |
357 for (i=0; i < sc[i] && len != 0; i++, len--) { | |
358 if (sc[i]<0 && sc[i+1]!=0) i++; | |
359 } | |
65
4416cfac86ae
Convert EUC-JP files to UTF8
Thibaut Girka <thib@sitedethib.com>
parents:
63
diff
changeset
|
360 s.erase(i); // 全角で len 文字まで切り詰める |
52 | 361 SetStr(arg1, s); |
362 // fprintf(stderr,"Set[%d,%d]<-%s\n",arg1.type,arg1.number,s.c_str()); | |
363 } else break; | |
364 cmd.clear(); | |
365 break; | |
366 case 1: | |
367 if (cmd.cmd4 == 0) { | |
368 SetStr(arg1, ""); | |
369 cmd.clear(); | |
370 } else if (cmd.cmd4 == 1) { | |
65
4416cfac86ae
Convert EUC-JP files to UTF8
Thibaut Girka <thib@sitedethib.com>
parents:
63
diff
changeset
|
371 // 領域指定で文字列クリア |
52 | 372 VarInfo v1 = cmd.args[0]; |
373 VarInfo v2 = cmd.args[1]; | |
374 eprintf("memclear(str). Var[%d]<%d> - Var[%d]<%d>\n",v1.type, v1.number, v2.type, v2.number); | |
375 if (v1.type != v2.type || (v1.type != TYPE_VARSTR && v1.type != TYPE_VARSYSSTR && v1.type != TYPE_VARLOCSTR)) { | |
376 eprintf(" error: bad args\n"); | |
377 } else { | |
378 if (v1.number < 0) v1.number = 0; | |
379 if (v2.number > 2000) v2.number = 2000; | |
380 for (; v1.number <= v2.number; v1.number++) { | |
381 SetStr(v1, ""); | |
382 } | |
383 } | |
384 cmd.clear(); | |
0 | 385 } |
52 | 386 case 2: |
387 SetStr(arg1, Str(arg1.type,arg1.number) + cmd.Str(cmd.args[1])); | |
388 // fprintf(stderr,"Append[%d,%d]<-%s(%d:%d)\n",arg1.type,arg1.number,Str(arg1.type,arg1.number).c_str(),cmd.args[1].type,cmd.args[1].number); | |
389 cmd.clear(); | |
390 break; | |
391 case 3: | |
392 SetSys(strlen(cmd.Str(cmd.args[0]))); | |
393 cmd.clear(); | |
394 break; | |
395 case 4: | |
396 { int v = strcmp(cmd.Str(cmd.args[0]), cmd.Str(cmd.args[1])); | |
397 // string s1=cmd.Str(cmd.args[0]); | |
398 // string s2=cmd.Str(cmd.args[1]); | |
399 // fprintf(stderr,"Cmp %s(%d:%d):%s(%d:%d):%d\n",s1.c_str(),cmd.args[0].type,cmd.args[0].number,s2.c_str(),cmd.args[1].type,cmd.args[1].number,v); | |
400 if (v < 0) SetSys(-1); | |
401 else if (v > 0) SetSys(1); | |
402 else SetSys(0); | |
0 | 403 cmd.clear(); |
52 | 404 break; } |
405 case 5: // substring, index from left | |
406 case 6: // substring, index from right | |
65
4416cfac86ae
Convert EUC-JP files to UTF8
Thibaut Girka <thib@sitedethib.com>
parents:
63
diff
changeset
|
407 // 全角対応らしい |
52 | 408 //FIXME: Make sure it works properly |
409 { int offset = cmd.args[2].value; | |
410 int len = strlen(cmd.Str(cmd.args[1])); | |
411 string str = cmd.Str(cmd.args[1]); | |
412 const char* s = str.c_str(); | |
413 if (cmd.cmd3 == 6) offset = len - offset; | |
414 if (offset < 0) offset = 0; | |
65
4416cfac86ae
Convert EUC-JP files to UTF8
Thibaut Girka <thib@sitedethib.com>
parents:
63
diff
changeset
|
415 // 先頭 N 文字を読み飛ばす |
52 | 416 int i; |
417 int offset_top = 0; | |
418 for (i=0; i<offset && s[offset_top] != 0; i++) { | |
419 if (s[offset_top] < 0 && s[offset_top+1] != 0) offset_top += 2; | |
420 else offset_top += 1; | |
421 } | |
422 if (s[offset_top] == 0) { | |
423 SetStr(arg1, ""); | |
65
4416cfac86ae
Convert EUC-JP files to UTF8
Thibaut Girka <thib@sitedethib.com>
parents:
63
diff
changeset
|
424 } else if (cmd.cmd4 == 0) { // 長さ制限なし |
52 | 425 SetStr(arg1, string(s, offset_top, len-offset_top)); |
426 } else { // cmd.cmd4 == 1 | |
427 int slen = cmd.args[3].value; | |
428 int offset_end = offset_top; | |
429 for (i=0; i<slen && s[offset_end] != 0; i++) { | |
430 if (s[offset_end] < 0 && s[offset_end]+1 != 0) offset_end += 2; | |
431 else offset_end += 1; | |
0 | 432 } |
52 | 433 string result(s, offset_top, offset_end-offset_top); |
434 SetStr(arg1, result); | |
0 | 435 } |
436 cmd.clear(); | |
52 | 437 break; } |
438 case 7: {// strlen w/ kanji | |
439 const char* s = cmd.Str(cmd.args[0]); int i; | |
440 for (i=0; *s != 0; i++) { | |
441 if (*s < 0 && s[1] != 0) s += 2; | |
442 else s++; | |
443 } | |
444 SetSys(i); | |
445 cmd.clear(); | |
446 break; } | |
65
4416cfac86ae
Convert EUC-JP files to UTF8
Thibaut Girka <thib@sitedethib.com>
parents:
63
diff
changeset
|
447 case 8: // 文字列を切って短くする |
52 | 448 if (cmd.args[1].value <= 0) { |
449 SetStr(arg1, ""); | |
450 } else if (cmd.args[1].value < strlen(cmd.Str(cmd.args[1]))) { | |
451 Str(arg1.type,arg1.number).erase(cmd.args[1].value); | |
452 } | |
453 cmd.clear(); | |
454 break; | |
65
4416cfac86ae
Convert EUC-JP files to UTF8
Thibaut Girka <thib@sitedethib.com>
parents:
63
diff
changeset
|
455 case 0x0e: // 漢字モードでitoa |
52 | 456 { |
457 int arg1 = cmd.args[0].value; | |
458 string result; | |
459 char wc[3]; wc[2]=0; | |
460 char buf[20]; | |
461 if (cmd.cmd4 == 0) { | |
462 sprintf(buf, "%d", arg1); | |
463 } else { // cmd.cmd4 == 1 | |
464 char fmt[20]; | |
465 sprintf(fmt, "%%%dd", cmd.args[2].value); | |
466 sprintf(buf, fmt, arg1); | |
0 | 467 } |
52 | 468 int i; |
469 for (i=0; buf[i] != 0; i++) { | |
470 if (buf[i] == ' ') { | |
471 wc[0] = 0x81; // ' ' in SHIFT_JIS | |
472 wc[1] = 0x40; | |
473 } else if (buf[i] == '-') { | |
474 wc[0] = 0x81; // '-' in SHIFT_JIS | |
475 wc[1] = 0x7c; | |
476 } else if (isdigit(buf[i])) { | |
477 wc[0] = 0x82; // number in SHIFT_JIS | |
478 wc[1] = buf[i] - '0' + 0x4f; | |
479 } else { | |
480 continue; | |
481 } | |
482 result += wc; | |
0 | 483 } |
52 | 484 SetStr(cmd.args[1], result); |
0 | 485 cmd.clear(); |
486 } | |
52 | 487 break; |
65
4416cfac86ae
Convert EUC-JP files to UTF8
Thibaut Girka <thib@sitedethib.com>
parents:
63
diff
changeset
|
488 case 0x0f: case 0x11: // itoa (0x11 の方は zero padding するっぽい) |
52 | 489 if (cmd.cmd4 == 0) { |
490 int arg1 = cmd.args[0].value; | |
491 char buf[1024]; sprintf(buf, "%d", arg1); | |
492 SetStr(cmd.args[1], buf); | |
493 cmd.clear(); | |
494 } else if (cmd.cmd4 == 1) { | |
65
4416cfac86ae
Convert EUC-JP files to UTF8
Thibaut Girka <thib@sitedethib.com>
parents:
63
diff
changeset
|
495 // 漢字(SJIS) : 82 [4f+N] |
4416cfac86ae
Convert EUC-JP files to UTF8
Thibaut Girka <thib@sitedethib.com>
parents:
63
diff
changeset
|
496 // やはり漢字じゃない? |
52 | 497 int arg1 = cmd.args[0].value; |
498 char buf[1024]; char fmt[1024]; | |
499 if (cmd.cmd3 == 0x0f) { | |
65
4416cfac86ae
Convert EUC-JP files to UTF8
Thibaut Girka <thib@sitedethib.com>
parents:
63
diff
changeset
|
500 sprintf(fmt, "%%%dd",cmd.args[2].value); /* 空白でパディング */ |
52 | 501 } else { |
502 sprintf(fmt, "%%0%dd",cmd.args[2].value); | |
503 } | |
504 sprintf(buf, fmt, arg1); | |
505 SetStr(cmd.args[1], buf); | |
506 cmd.clear(); | |
507 } | |
508 break; | |
65
4416cfac86ae
Convert EUC-JP files to UTF8
Thibaut Girka <thib@sitedethib.com>
parents:
63
diff
changeset
|
509 case 0x64: // 文字列の表示 : 引数をテキストウィンドウに表示 |
52 | 510 if (cmd.cmd4 == 1) { |
511 char buf[256]; | |
512 snprintf(buf, 255, "%d", Get(cmd.args[0].type, cmd.args[0].number)); | |
513 cmd.args[0].type = TYPE_STR; | |
514 cmd.args[0].value = cmd.AddStr(buf); | |
515 cmd.cmd4 = 0; | |
516 } | |
517 cmd.cmd_type = CMD_TEXT; | |
518 break; | |
0 | 519 } |
520 } | |
65
4416cfac86ae
Convert EUC-JP files to UTF8
Thibaut Girka <thib@sitedethib.com>
parents:
63
diff
changeset
|
521 if (cmd.cmd1 == 1 && cmd.cmd2 == 0x0b) { // 数値変数演算 |
0 | 522 if (cmd.cmd3 == 0 && cmd.cmd4 == 0) { |
65
4416cfac86ae
Convert EUC-JP files to UTF8
Thibaut Girka <thib@sitedethib.com>
parents:
63
diff
changeset
|
523 /* 複数の変数をセット */ |
0 | 524 VarInfo v1 = cmd.args[0]; |
525 eprintf("set multiple-var Var[%d]<%d> <- ",v1.type, v1.number); | |
526 int i; | |
527 if (cmd.args.size() < cmd.argc) { | |
528 eprintf(" error: argsize changed %d -> %d\n",cmd.argc, cmd.args.size()); | |
529 cmd.argc = cmd.args.size(); | |
530 } | |
531 for (i=0; i<cmd.argc; i++) { | |
532 eprintf("%d, ",cmd.args[i+1].value); | |
533 Set(v1, cmd.args[i+1].value); | |
534 v1.number++; | |
535 } | |
536 eprintf("\n"); | |
537 cmd.clear(); | |
538 } else if (cmd.cmd3 == 1 && cmd.cmd4 == 0) { | |
65
4416cfac86ae
Convert EUC-JP files to UTF8
Thibaut Girka <thib@sitedethib.com>
parents:
63
diff
changeset
|
539 /* 領域指定で変数をクリア */ |
0 | 540 VarInfo v1 = cmd.args[0]; |
541 VarInfo v2 = cmd.args[1]; | |
542 eprintf("memclear. Var[%d]<%d> - Var[%d]<%d>\n",v1.type, v1.number, v2.type, v2.number); | |
543 if (v1.type != v2.type || !IsInt(v1.type)) eprintf(" error: bad args\n"); | |
544 else { | |
545 if (v1.number < 0) v1.number = 0; | |
546 if (v2.number > MaxIndex(v2.type)) v2.number = MaxIndex(v2.type); | |
547 for (; v1.number <= v2.number; v1.number++) | |
548 Set(v1, 0); | |
549 } | |
550 cmd.clear(); | |
551 } else if (cmd.cmd3 == 1 && cmd.cmd4 == 1) { | |
65
4416cfac86ae
Convert EUC-JP files to UTF8
Thibaut Girka <thib@sitedethib.com>
parents:
63
diff
changeset
|
552 /* 領域指定で変数をセット */ |
0 | 553 VarInfo v1 = cmd.args[0]; |
554 VarInfo v2 = cmd.args[1]; | |
555 int value = cmd.args[2].value; | |
556 eprintf("memset. Var[%d]<%d> - Var[%d]<%d> <- %d\n",v1.type, v1.number, v2.type, v2.number, value); | |
557 if (v1.type != v2.type || !IsInt(v1.type)) eprintf(" error: bad args\n"); | |
558 else { | |
559 if (v1.number < 0) v1.number = 0; | |
560 if (v2.number > MaxIndex(v2.type)) v2.number = MaxIndex(v2.type); | |
561 for (; v1.number <= v2.number; v1.number++) | |
562 Set(v1, value); | |
563 } | |
564 cmd.clear(); | |
65
4416cfac86ae
Convert EUC-JP files to UTF8
Thibaut Girka <thib@sitedethib.com>
parents:
63
diff
changeset
|
565 } else if (cmd.cmd3 == 4 && cmd.cmd4 == 1) { // 領域クリア(sysfunc.txt) |
0 | 566 VarInfo v1 = cmd.args[0]; |
567 int step = cmd.args[1].value; | |
568 int deal = cmd.args[2].value; | |
569 int val = cmd.args[3].value; | |
570 eprintf("memclear. Var[%d]<%d> step %d deal %d <- val %d\n",v1.type, v1.number, step, deal, val); | |
571 int i; for (i=0; i<deal; i++) { | |
572 Set(v1, val); | |
573 v1.number += step; | |
574 } | |
575 cmd.clear(); | |
65
4416cfac86ae
Convert EUC-JP files to UTF8
Thibaut Girka <thib@sitedethib.com>
parents:
63
diff
changeset
|
576 } else if (cmd.cmd3 == 0x64 && cmd.cmd4 == 0) { //領域で数値を合計する |
0 | 577 VarInfo v1 = cmd.args[0]; |
578 VarInfo v2 = cmd.args[1]; | |
579 eprintf("sum var. Var[%d]<%d> - Var[%d]<%d>\n",v1.type, v1.number, v2.type, v2.number); | |
580 int sum = 0; | |
581 if (v1.type != v2.type || !IsInt(v1.type)) eprintf(" error: bad args\n"); | |
582 else { | |
583 if (v1.number < 0) v1.number = 0; | |
584 if (v2.number > MaxIndex(v2.type)) v2.number = MaxIndex(v2.type); | |
585 for (; v1.number <= v2.number; v1.number++) | |
586 sum += (*this)(v1); | |
587 } | |
588 eprintf(" ret %d\n",sum); | |
589 cmd.SetSysvar(sum); | |
590 } | |
591 } | |
592 return false; | |
593 } | |
594 | |
595 /********************************************************************* | |
54
d7cde171a1de
* scn2k_grp.cc now handles commands in a cleanier way \o/
thib
parents:
52
diff
changeset
|
596 ** SimpleCmd |
d7cde171a1de
* scn2k_grp.cc now handles commands in a cleanier way \o/
thib
parents:
52
diff
changeset
|
597 */ |
d7cde171a1de
* scn2k_grp.cc now handles commands in a cleanier way \o/
thib
parents:
52
diff
changeset
|
598 |
d7cde171a1de
* scn2k_grp.cc now handles commands in a cleanier way \o/
thib
parents:
52
diff
changeset
|
599 SimpleCmd::SimpleCmd(int a, int b, int c) |
d7cde171a1de
* scn2k_grp.cc now handles commands in a cleanier way \o/
thib
parents:
52
diff
changeset
|
600 { |
d7cde171a1de
* scn2k_grp.cc now handles commands in a cleanier way \o/
thib
parents:
52
diff
changeset
|
601 cmd1 = a; |
d7cde171a1de
* scn2k_grp.cc now handles commands in a cleanier way \o/
thib
parents:
52
diff
changeset
|
602 cmd2 = b; |
d7cde171a1de
* scn2k_grp.cc now handles commands in a cleanier way \o/
thib
parents:
52
diff
changeset
|
603 cmd3 = c; |
d7cde171a1de
* scn2k_grp.cc now handles commands in a cleanier way \o/
thib
parents:
52
diff
changeset
|
604 } |
d7cde171a1de
* scn2k_grp.cc now handles commands in a cleanier way \o/
thib
parents:
52
diff
changeset
|
605 |
d7cde171a1de
* scn2k_grp.cc now handles commands in a cleanier way \o/
thib
parents:
52
diff
changeset
|
606 SimpleCmd::SimpleCmd(void) |
d7cde171a1de
* scn2k_grp.cc now handles commands in a cleanier way \o/
thib
parents:
52
diff
changeset
|
607 { |
d7cde171a1de
* scn2k_grp.cc now handles commands in a cleanier way \o/
thib
parents:
52
diff
changeset
|
608 cmd1 = cmd2 = cmd3 = 0; |
d7cde171a1de
* scn2k_grp.cc now handles commands in a cleanier way \o/
thib
parents:
52
diff
changeset
|
609 } |
d7cde171a1de
* scn2k_grp.cc now handles commands in a cleanier way \o/
thib
parents:
52
diff
changeset
|
610 |
d7cde171a1de
* scn2k_grp.cc now handles commands in a cleanier way \o/
thib
parents:
52
diff
changeset
|
611 bool SimpleCmd::operator<(const SimpleCmd& cmd) const |
d7cde171a1de
* scn2k_grp.cc now handles commands in a cleanier way \o/
thib
parents:
52
diff
changeset
|
612 { |
d7cde171a1de
* scn2k_grp.cc now handles commands in a cleanier way \o/
thib
parents:
52
diff
changeset
|
613 if (cmd1 < cmd.cmd1) return true; |
d7cde171a1de
* scn2k_grp.cc now handles commands in a cleanier way \o/
thib
parents:
52
diff
changeset
|
614 else if (cmd1 > cmd.cmd1) return false; |
d7cde171a1de
* scn2k_grp.cc now handles commands in a cleanier way \o/
thib
parents:
52
diff
changeset
|
615 |
d7cde171a1de
* scn2k_grp.cc now handles commands in a cleanier way \o/
thib
parents:
52
diff
changeset
|
616 if (cmd2 < cmd.cmd2) return true; |
d7cde171a1de
* scn2k_grp.cc now handles commands in a cleanier way \o/
thib
parents:
52
diff
changeset
|
617 else if (cmd2 > cmd.cmd2) return false; |
d7cde171a1de
* scn2k_grp.cc now handles commands in a cleanier way \o/
thib
parents:
52
diff
changeset
|
618 |
d7cde171a1de
* scn2k_grp.cc now handles commands in a cleanier way \o/
thib
parents:
52
diff
changeset
|
619 if (cmd3 < cmd.cmd3) return true; |
d7cde171a1de
* scn2k_grp.cc now handles commands in a cleanier way \o/
thib
parents:
52
diff
changeset
|
620 else return false; |
d7cde171a1de
* scn2k_grp.cc now handles commands in a cleanier way \o/
thib
parents:
52
diff
changeset
|
621 } |
d7cde171a1de
* scn2k_grp.cc now handles commands in a cleanier way \o/
thib
parents:
52
diff
changeset
|
622 |
d7cde171a1de
* scn2k_grp.cc now handles commands in a cleanier way \o/
thib
parents:
52
diff
changeset
|
623 bool SimpleCmd::operator==(const SimpleCmd& cmd) const |
d7cde171a1de
* scn2k_grp.cc now handles commands in a cleanier way \o/
thib
parents:
52
diff
changeset
|
624 { |
d7cde171a1de
* scn2k_grp.cc now handles commands in a cleanier way \o/
thib
parents:
52
diff
changeset
|
625 return (cmd1 == cmd.cmd1 && cmd2 == cmd.cmd2 && cmd3 == cmd.cmd3); |
d7cde171a1de
* scn2k_grp.cc now handles commands in a cleanier way \o/
thib
parents:
52
diff
changeset
|
626 } |
d7cde171a1de
* scn2k_grp.cc now handles commands in a cleanier way \o/
thib
parents:
52
diff
changeset
|
627 |
d7cde171a1de
* scn2k_grp.cc now handles commands in a cleanier way \o/
thib
parents:
52
diff
changeset
|
628 |
d7cde171a1de
* scn2k_grp.cc now handles commands in a cleanier way \o/
thib
parents:
52
diff
changeset
|
629 /********************************************************************* |
0 | 630 ** Cmd |
631 */ | |
632 | |
65
4416cfac86ae
Convert EUC-JP files to UTF8
Thibaut Girka <thib@sitedethib.com>
parents:
63
diff
changeset
|
633 /* 数値 num := 0x24 0xff <int num> */ |
4416cfac86ae
Convert EUC-JP files to UTF8
Thibaut Girka <thib@sitedethib.com>
parents:
63
diff
changeset
|
634 /* 変数 var := 0x24 <uchar type> 0x5b <exp> 0x5d */ |
4416cfac86ae
Convert EUC-JP files to UTF8
Thibaut Girka <thib@sitedethib.com>
parents:
63
diff
changeset
|
635 /* 項 token := num | var | 0x28 <exp> 0x29 | <plus|minus> token */ |
0 | 636 |
637 int Cmd::GetLeftToken(const char*& d, VarInfo& info) { | |
638 bool var_flag = true; | |
639 int minus_flag = 0; | |
640 int value = 0; | |
641 if (d[0] == 0x5c && (d[1] == 1 || d[1] == 0) ) { | |
642 if (d[1] == 1) {dprintf("minus-"); minus_flag ^= 1;} | |
643 else dprintf("plus-"); | |
644 d += 2; | |
645 var_flag = false; | |
646 } | |
647 if (d[0] == 0x24 && ((unsigned const char*)d)[1] == 0xff) { | |
65
4416cfac86ae
Convert EUC-JP files to UTF8
Thibaut Girka <thib@sitedethib.com>
parents:
63
diff
changeset
|
648 // if ( (d[0] == 0x30 || d[0] == 0x31) && d[1] == 0x24 && ((unsigned const char*)d)[2] == 0xff) /* @@@ not supported; selection 内で、0x30|0x31 が付随することがある */ |
0 | 649 // numerical atom |
650 d += 6; | |
651 value = read_little_endian_int(d-4); | |
652 dprintf("%d",value); | |
653 var_flag = false; | |
654 } else if (d[0] == 0x24 && *(unsigned char*)(d+1) == 0xc8) { | |
655 dprintf("V<sys>"); | |
656 d += 2; | |
657 info.type = TYPE_SYS; info.number = 0; | |
658 value = info.value = flags(); | |
659 } else if (d[0] == 0x24 && d[2] == 0x5b) { | |
660 // 0x24,<type>,0x5b,<expr>,0x5d-terminated term | |
661 info.type = *(unsigned char*)(d+1); | |
662 d += 3; | |
663 dprintf("V<%d>[",info.type); | |
664 info.number = GetExpression(d); | |
665 dprintf("]"); | |
666 if (*d == 0x5d) d++; | |
667 else SetError(); | |
668 if (info.type == TYPE_VARSTR || info.type == TYPE_VARSYSSTR || info.type == TYPE_VARLOCSTR) { | |
669 value = 0; | |
670 info.value = StrVar(info.type, info.number); | |
671 } else { | |
672 value = info.value = flags(info); | |
673 } | |
674 dprintf("(=%d)",value); | |
675 } else SetError(); | |
676 | |
677 if (minus_flag) value = -value; | |
678 if (!var_flag) { | |
679 info.type = TYPE_VAL; | |
680 info.value = value; | |
681 } | |
682 return value; | |
683 } | |
684 | |
47
5f548e5957a8
* get rid of the "deprecated conversion from string constant to ‘char*’" warnings
thib
parents:
44
diff
changeset
|
685 static const char* op_str[70] = { |
0 | 686 // 0 1 2 3 4 5 6 7 8 9 |
687 "+", "-", "*", "/", "%", "&", "|", "^", "<<", ">>", // +00 | |
688 "err.","err.","err.","err.","err.","err.","err.","err.","err.","err.", // +10 | |
689 "+=", "-=", "*=", "/=", "%=", "&=", "|=", "^=", "<<=", ">>=", // +20 | |
690 "=", "err.","err.","err.","err.","err.","err.","err.","err.","err.", // +30 | |
691 "==", "!=", "<=", "<", ">=", ">", "err.","err.","err.","err.", // +40 | |
692 "err.","err.","err.","err.","err.","err.","err.","err.","err.","err.", // +50 | |
693 "&&", "||", "err.","err.","err.","err.","err.","err.","err.","err.", // +60 | |
694 }; | |
695 | |
696 static int op_pri_tbl[12] = { | |
697 // + - * / % & | ^ << >> | |
698 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 10, 10}; | |
699 | |
700 inline int op_pri(int op) { | |
701 if (op > 11) return 10; | |
702 return op_pri_tbl[op]; | |
703 } | |
704 inline int op_pri_cond(int op) { | |
705 if (op <= 11) return op_pri_tbl[op]; | |
706 else if (op < 50) return 7; | |
707 else if (op == 60) return 8; | |
708 else if (op == 61) return 8; | |
709 else return 10; | |
710 } | |
711 | |
712 | |
713 inline int eval(int v1, int op, int v2) { | |
714 switch(op) { | |
715 case 0: return v1+v2; | |
716 case 1: return v1-v2; | |
717 case 2: return v1*v2; | |
718 case 3: return v2!=0 ? v1/v2 : v1; | |
719 case 4: return v2!=0 ? v1%v2 : v1; | |
720 case 5: return v1&v2; | |
721 case 6: return v1|v2; | |
722 case 7: return v1^v2; | |
723 case 8: return v1<<v2; | |
724 case 9: return v1>>v2; | |
725 case 40: return v1 == v2; | |
726 case 41: return v1 != v2; | |
727 case 42: return v1 <= v2; | |
728 case 43: return v1 < v2; | |
729 case 44: return v1 >= v2; | |
730 case 45: return v1 > v2; | |
731 case 60: return v1 && v2; | |
732 case 61: return v1 || v2; | |
733 } | |
734 return v2; | |
735 } | |
736 | |
52 | 737 Cmd::Cmd(const Flags& f, int _sys_ver) : flags(f), system_version(_sys_ver) { |
738 cmd_type = CMD_NOP; | |
739 argc = 0; | |
740 errorflag = false; | |
741 cmdstr[0] = 0; | |
742 strend = 0; | |
743 pos = -1; | |
744 } | |
745 | |
65
4416cfac86ae
Convert EUC-JP files to UTF8
Thibaut Girka <thib@sitedethib.com>
parents:
63
diff
changeset
|
746 /* 演算子 op := 0x5c <uchar op> */ |
4416cfac86ae
Convert EUC-JP files to UTF8
Thibaut Girka <thib@sitedethib.com>
parents:
63
diff
changeset
|
747 /* 数式 exp: [op] <token> [op <token> [...]] */ |
0 | 748 int Cmd::GetExpression(const char*& d, VarInfo* info_ptr) { |
749 #define STACK_DEPTH 1024 | |
750 #define OP_LB 11 | |
751 char op_stack[STACK_DEPTH]; | |
752 int val_stack[STACK_DEPTH]; | |
753 int stack_count = 0; | |
754 | |
65
4416cfac86ae
Convert EUC-JP files to UTF8
Thibaut Girka <thib@sitedethib.com>
parents:
63
diff
changeset
|
755 // 第一項の読み込み |
0 | 756 while(*d == 0x28) { |
757 d++; | |
758 dprintf("("); | |
759 op_stack[stack_count++] = OP_LB; | |
760 } | |
761 VarInfo info; | |
762 int value = GetLeftToken(d, info); | |
763 | |
764 while(*d == 0x29 && stack_count > 0 && op_stack[stack_count-1] == OP_LB) { | |
765 d++; | |
766 dprintf(")"); | |
767 stack_count--; | |
768 } | |
769 | |
770 if (*d != 0x5c && stack_count == 0) { | |
771 if (info_ptr) *info_ptr = info; | |
65
4416cfac86ae
Convert EUC-JP files to UTF8
Thibaut Girka <thib@sitedethib.com>
parents:
63
diff
changeset
|
772 return value; // 単純なleft-termはここで終了。有効なinfo_ptrを帰す(可能性がある) |
0 | 773 } |
774 | |
775 while(*d == 0x5c) { | |
776 int op_type = *(unsigned char*)(d+1); | |
777 d += 2; | |
778 if (op_type < 70) dprintf("%s",op_str[op_type]); | |
779 else dprintf("err."); | |
780 if (op_type >= 10) SetError(); | |
781 int cur_pri = op_pri(op_type); | |
782 while(stack_count != 0 && op_pri(op_stack[stack_count-1]) <= cur_pri) { | |
65
4416cfac86ae
Convert EUC-JP files to UTF8
Thibaut Girka <thib@sitedethib.com>
parents:
63
diff
changeset
|
783 // 優先順位の高い、先行する演算を行う |
0 | 784 value = eval(val_stack[stack_count-1], op_stack[stack_count-1], value); |
785 stack_count--; | |
786 } | |
787 val_stack[stack_count] = value; | |
788 op_stack[stack_count++] = op_type; | |
789 while(*d == 0x28) { | |
790 d++; | |
791 dprintf("("); | |
792 op_stack[stack_count++] = OP_LB; | |
793 } | |
794 if (stack_count >= STACK_DEPTH) SetError(); | |
795 value = GetLeftToken(d, info); | |
796 | |
797 while (*d != 0x5c && stack_count > 0) { | |
65
4416cfac86ae
Convert EUC-JP files to UTF8
Thibaut Girka <thib@sitedethib.com>
parents:
63
diff
changeset
|
798 // 未実行の演算を終わらせる |
0 | 799 if (op_stack[stack_count-1] != OP_LB) { |
800 value = eval(val_stack[stack_count-1], op_stack[stack_count-1], value); | |
801 stack_count--; | |
802 } else if (*d == 0x29) { /* op_stack == OP_LB */ | |
65
4416cfac86ae
Convert EUC-JP files to UTF8
Thibaut Girka <thib@sitedethib.com>
parents:
63
diff
changeset
|
803 // bracket 終端があれば、閉じておく |
0 | 804 d++; |
805 dprintf(")"); | |
806 stack_count--; | |
807 } else break; // error | |
808 } | |
809 } | |
810 if (stack_count) SetError(); // unbalanced bracket | |
811 dprintf("(=%d)",value); | |
812 if (info_ptr) { | |
813 info_ptr->type = TYPE_VAL; | |
814 info_ptr->value = value; | |
815 } | |
816 return value; | |
817 } | |
818 | |
65
4416cfac86ae
Convert EUC-JP files to UTF8
Thibaut Girka <thib@sitedethib.com>
parents:
63
diff
changeset
|
819 // 条件分岐専用に、条件演算と算術演算の混合を検知できる専用ルーチン(本来はGetExpressionで差し支えない) |
0 | 820 int Cmd::GetExpressionCond(const char*& d) { |
821 char op_stack[STACK_DEPTH]; | |
822 int val_stack[STACK_DEPTH]; | |
823 int valattr_stack[STACK_DEPTH]; | |
824 #define ATTR_VAL 0 | |
825 #define ATTR_FLAG 1 | |
826 int stack_count = 0; | |
827 | |
65
4416cfac86ae
Convert EUC-JP files to UTF8
Thibaut Girka <thib@sitedethib.com>
parents:
63
diff
changeset
|
828 // 第一項の読み込み |
0 | 829 while(*d == 0x28) { |
830 d++; | |
831 dprintf("("); | |
832 op_stack[stack_count++] = OP_LB; | |
833 } | |
834 VarInfo info; | |
835 int value = GetLeftToken(d, info); | |
836 while(*d == 0x29 && stack_count > 0 && op_stack[stack_count-1] == OP_LB) { | |
837 d++; | |
838 dprintf(")"); | |
839 stack_count--; | |
840 } | |
841 bool valattr = ATTR_VAL; | |
842 | |
843 while(*d == 0x5c) { | |
844 int op_type = *(unsigned char*)(d+1); | |
845 d += 2; | |
846 if (op_type < 70) dprintf("%s",op_str[op_type]); | |
847 else dprintf("err."); | |
848 int cur_pri = op_pri_cond(op_type); | |
849 while(stack_count != 0 && op_pri_cond(op_stack[stack_count-1]) <= cur_pri) { | |
65
4416cfac86ae
Convert EUC-JP files to UTF8
Thibaut Girka <thib@sitedethib.com>
parents:
63
diff
changeset
|
850 // 優先順位の高い、先行する演算を行う |
0 | 851 if (op_stack[stack_count-1] >= 60) { |
852 if (valattr_stack[stack_count-1] != ATTR_FLAG || valattr != ATTR_FLAG) SetError(); | |
853 } else { | |
854 if (valattr_stack[stack_count-1] != ATTR_VAL || valattr != ATTR_VAL) SetError(); | |
855 } | |
856 value = eval(val_stack[stack_count-1], op_stack[stack_count-1], value); | |
857 if (op_stack[stack_count-1] >= 40) valattr = ATTR_FLAG; | |
858 stack_count--; | |
859 } | |
860 val_stack[stack_count] = value; | |
861 valattr_stack[stack_count] = valattr; | |
862 op_stack[stack_count++] = op_type; | |
863 while(*d == 0x28) { | |
864 d++; | |
865 dprintf("("); | |
866 op_stack[stack_count++] = OP_LB; | |
867 } | |
868 if (stack_count >= STACK_DEPTH) SetError(); | |
869 value = GetLeftToken(d, info); | |
870 valattr = ATTR_VAL; | |
871 | |
872 while (*d != 0x5c && stack_count > 0) { | |
65
4416cfac86ae
Convert EUC-JP files to UTF8
Thibaut Girka <thib@sitedethib.com>
parents:
63
diff
changeset
|
873 // 未実行の演算を終わらせる |
0 | 874 if (op_stack[stack_count-1] != OP_LB) { |
875 if (op_stack[stack_count-1] >= 60) { | |
876 if (valattr_stack[stack_count-1] != ATTR_FLAG || valattr != ATTR_FLAG) SetError(); | |
877 } else { | |
878 if (valattr_stack[stack_count-1] != ATTR_VAL || valattr != ATTR_VAL) SetError(); | |
879 } | |
880 value = eval(val_stack[stack_count-1], op_stack[stack_count-1], value); | |
881 if (op_stack[stack_count-1] >= 40) valattr = ATTR_FLAG; | |
882 stack_count--; | |
65
4416cfac86ae
Convert EUC-JP files to UTF8
Thibaut Girka <thib@sitedethib.com>
parents:
63
diff
changeset
|
883 // bracket 終端があれば、閉じておく |
0 | 884 } else if (*d == 0x29) { /* op_stack == OP_LB */ |
885 d++; | |
886 dprintf(")"); | |
887 stack_count--; | |
888 } else break; // error | |
889 } | |
890 } | |
891 if (stack_count) SetError(); // unbalanced bracket | |
892 if (value) dprintf("(=true)"); | |
893 else dprintf("(=false)"); | |
894 return value; | |
895 } | |
896 | |
897 | |
898 /* | |
899 str = | |
900 arg = | |
901 args = 0x28 <exp> [[0x2c] <exp> [[0x2c] <exp> [...] ]] | |
902 */ | |
903 | |
904 int Cmd::GetArgs(const char*& d) { | |
65
4416cfac86ae
Convert EUC-JP files to UTF8
Thibaut Girka <thib@sitedethib.com>
parents:
63
diff
changeset
|
905 if (*d != 0x28) return 0; /* 引数なし */ |
0 | 906 d++; |
907 dprintf("args:"); | |
908 VarInfo var; | |
909 int i; for (i=0; i<100 ; i++) { | |
65
4416cfac86ae
Convert EUC-JP files to UTF8
Thibaut Girka <thib@sitedethib.com>
parents:
63
diff
changeset
|
910 /* number, variable, string の種別なく値を得る */ |
4416cfac86ae
Convert EUC-JP files to UTF8
Thibaut Girka <thib@sitedethib.com>
parents:
63
diff
changeset
|
911 if (*d == 0x61) { // よくわからない(智代アフター) |
29
d229cce98f50
* no more (or, at least, less) duplicate code between scn2kdump and the rest
thib
parents:
21
diff
changeset
|
912 dprintf("@%d",d[1]); |
0 | 913 d += 2; |
914 if (*d == 0x28) { | |
915 dprintf("{"); | |
65
4416cfac86ae
Convert EUC-JP files to UTF8
Thibaut Girka <thib@sitedethib.com>
parents:
63
diff
changeset
|
916 GetArgs(d); // (A,B,C)節が含まれることがある |
0 | 917 dprintf("}"); |
918 } else { | |
919 dprintf("{}"); | |
920 } | |
65
4416cfac86ae
Convert EUC-JP files to UTF8
Thibaut Girka <thib@sitedethib.com>
parents:
63
diff
changeset
|
921 } else if (d[0] == 0x0a || d[0] == 0x40) { // よくわからない (Little Busters!) |
0 | 922 int var; |
923 if (system_version == 0) { var = read_little_endian_int(d+1); d += 5;} | |
924 else { var = read_little_endian_short(d+1); d += 3;} | |
925 dprintf("line %d; ",var); | |
926 } else if (*d == 0x24 || (*d == 0x5c && (d[1] == 1 || d[1] == 0)) || *d == 0x28) { | |
927 GetExpression(d, &var); | |
928 args.push_back(var); | |
929 } else if (StrType(d)) { | |
930 var.type = TYPE_STR; | |
931 var.value = GetString(d); | |
932 args.push_back(var); | |
933 } else SetError(); | |
934 if (*d == 0x29) break; | |
65
4416cfac86ae
Convert EUC-JP files to UTF8
Thibaut Girka <thib@sitedethib.com>
parents:
63
diff
changeset
|
935 if (*d == 0x2c) {d++;} // 次の arg が演算子で始まる、などがなければ存在しない |
0 | 936 dprintf(","); |
937 } | |
938 if (*d == 0x29) d++; | |
939 else SetError(); | |
940 return i; | |
941 } | |
942 | |
943 int Cmd::GetArgsSpecial(int normal_args,const char*& d) { | |
65
4416cfac86ae
Convert EUC-JP files to UTF8
Thibaut Girka <thib@sitedethib.com>
parents:
63
diff
changeset
|
944 if (*d != 0x28) return 0; /* 引数なし */ |
0 | 945 d++; |
946 dprintf("args:"); | |
947 int i; for (i=0; i<normal_args; i++) { | |
65
4416cfac86ae
Convert EUC-JP files to UTF8
Thibaut Girka <thib@sitedethib.com>
parents:
63
diff
changeset
|
948 /* number, variable, string の種別なく値を得る */ |
0 | 949 if (*d == 0x24 || (*d == 0x5c && (d[1] == 1 || d[1] == 0)) || *d == 0x28) { |
950 GetExpression(d); | |
951 } else if (StrType(d)) { | |
952 GetString(d); | |
953 } else SetError(); | |
954 if (*d == 0x29) break; | |
65
4416cfac86ae
Convert EUC-JP files to UTF8
Thibaut Girka <thib@sitedethib.com>
parents:
63
diff
changeset
|
955 if (*d == 0x2c) {d++;} // 次の arg が演算子で始まる、などがなければ存在しない |
0 | 956 dprintf(","); |
957 } | |
958 for (i=0; i<argc ; i++) { | |
959 if (*d == 0x28) { | |
960 /* | |
961 ** cmd 01-22:0c1c, 01-22:0835 | |
65
4416cfac86ae
Convert EUC-JP files to UTF8
Thibaut Girka <thib@sitedethib.com>
parents:
63
diff
changeset
|
962 ** Princess Bride のカードが落ちるアニメの場面 |
4416cfac86ae
Convert EUC-JP files to UTF8
Thibaut Girka <thib@sitedethib.com>
parents:
63
diff
changeset
|
963 ** なお、_PBCARDANM* の画像はこのコマンドでのみ使われているので、特殊処理として無視することも可能 |
0 | 964 ** |
965 ** cmd 01-04:0276, 026c, 0270 | |
65
4416cfac86ae
Convert EUC-JP files to UTF8
Thibaut Girka <thib@sitedethib.com>
parents:
63
diff
changeset
|
966 ** 複数の enum が args の数だけ続く処理。特殊処理として分離する |
0 | 967 */ |
968 dprintf("enum.<"); | |
65
4416cfac86ae
Convert EUC-JP files to UTF8
Thibaut Girka <thib@sitedethib.com>
parents:
63
diff
changeset
|
969 /* (...) は列挙型 or 構造体の可能性がある */ |
0 | 970 const char* d_orig = d; |
971 int pt = args.size(); args.push_back(VarInfo(0)); | |
972 int count = GetArgs(d); | |
973 args[pt] = VarInfo(count); | |
974 dprintf(">"); | |
975 } else if (*d == 0x61 && (d[1] >= 0x00 && d[1] <= 0x04) && d[2] == 0x28 ) { | |
65
4416cfac86ae
Convert EUC-JP files to UTF8
Thibaut Girka <thib@sitedethib.com>
parents:
63
diff
changeset
|
976 /* 使われるコマンドは 01-21:004b, 01-28:0064 のいずれか(R,C,PB,LO) |
4416cfac86ae
Convert EUC-JP files to UTF8
Thibaut Girka <thib@sitedethib.com>
parents:
63
diff
changeset
|
977 ** それらのコマンドは |
4416cfac86ae
Convert EUC-JP files to UTF8
Thibaut Girka <thib@sitedethib.com>
parents:
63
diff
changeset
|
978 ** arg1: 画像ファイル名 |
4416cfac86ae
Convert EUC-JP files to UTF8
Thibaut Girka <thib@sitedethib.com>
parents:
63
diff
changeset
|
979 ** arg2 : Sel 番号 |
4416cfac86ae
Convert EUC-JP files to UTF8
Thibaut Girka <thib@sitedethib.com>
parents:
63
diff
changeset
|
980 ** らしく、arg3 以降が 0x61 <00-04> (a,b,c,...) となる(ダンプ上は enum と表記される) |
4416cfac86ae
Convert EUC-JP files to UTF8
Thibaut Girka <thib@sitedethib.com>
parents:
63
diff
changeset
|
981 ** () 内の引数はさまざまで、a のみ(画像ファイル名)、 |
0 | 982 ** a,b b=SEL? |
65
4416cfac86ae
Convert EUC-JP files to UTF8
Thibaut Girka <thib@sitedethib.com>
parents:
63
diff
changeset
|
983 ** a,b,c (b,c)=座標? |
0 | 984 ** a,(b,c,d,e,f,g) b-g = src / dest? |
65
4416cfac86ae
Convert EUC-JP files to UTF8
Thibaut Girka <thib@sitedethib.com>
parents:
63
diff
changeset
|
985 ** らしい |
0 | 986 */ |
987 dprintf("kasane. #%d <",d[1]); | |
988 d += 2; | |
989 int pt = args.size(); args.push_back(VarInfo(0)); | |
990 int count = GetArgs(d); | |
991 args[pt] = VarInfo(count); | |
992 dprintf(">"); | |
993 } else if (*d == 0x24 || (*d == 0x5c && (d[1] == 1 || d[1] == 0))) { | |
65
4416cfac86ae
Convert EUC-JP files to UTF8
Thibaut Girka <thib@sitedethib.com>
parents:
63
diff
changeset
|
994 /* cmd 01-15:0028 ; 始めに 0x24 節があり、続いて 0x28 節になる */ |
0 | 995 VarInfo var; |
996 GetExpression(d, &var); | |
997 args.push_back(var); | |
65
4416cfac86ae
Convert EUC-JP files to UTF8
Thibaut Girka <thib@sitedethib.com>
parents:
63
diff
changeset
|
998 i--; // この引数はargc の数には入らない |
0 | 999 } else SetError(); |
1000 if (d[0] == 0x0a || d[0] == 0x40) { | |
65
4416cfac86ae
Convert EUC-JP files to UTF8
Thibaut Girka <thib@sitedethib.com>
parents:
63
diff
changeset
|
1001 /* cmd 01-15:0028 ; 0x28 節の後に毎回 0x0a 節が来る */ |
0 | 1002 int var; |
1003 if (system_version == 0) { var = read_little_endian_int(d+1); d += 5;} | |
1004 else { var = read_little_endian_short(d+1); d += 3;} | |
1005 dprintf("line %d; ",var); | |
1006 } | |
1007 if (*d == 0x29) break; | |
65
4416cfac86ae
Convert EUC-JP files to UTF8
Thibaut Girka <thib@sitedethib.com>
parents:
63
diff
changeset
|
1008 if (*d == 0x2c) {d++;} // 次の arg が演算子で始まる、などがなければ存在しない |
0 | 1009 dprintf(","); |
1010 } | |
1011 if (*d == 0x29) d++; | |
1012 else SetError(); | |
1013 return 0; | |
1014 } | |
1015 | |
1016 /* switch | |
1017 <exp> | |
1018 0x7b | |
1019 <exp> <int> | |
1020 ... | |
1021 0x7d | |
1022 */ | |
1023 | |
1024 int Cmd::GetSwitch(const char*& d) { | |
1025 if (*d != 0x28) {SetError(); return -1;} | |
1026 d++; | |
1027 dprintf("switch. "); | |
1028 int var = GetExpression(d); | |
1029 if (*d != 0x29) {SetError(); return -1;} | |
1030 d++; | |
1031 dprintf("->\n"); | |
1032 if (*d == 0x7b) { | |
1033 d++; | |
1034 } else SetError(); | |
1035 | |
1036 int default_jmp = -1; int jmpto = -1; | |
1037 int i; for (i=0; i<argc; i++) { | |
1038 dprintf("\t"); | |
1039 if (*d++ != 0x28) {SetError(); return -1;} | |
1040 if (*d != 0x29) { | |
1041 int item = GetExpression(d); | |
1042 if (*d++ != 0x29) {SetError(); return -1;} | |
1043 int jmp = read_little_endian_int(d); | |
1044 if (var == item) { | |
1045 dprintf("(selected)"); | |
1046 jmpto = jmp; | |
1047 } | |
1048 dprintf(" -> %d\n", jmp); | |
1049 } else { | |
1050 d++; | |
1051 default_jmp = read_little_endian_int(d); | |
1052 } | |
1053 d += 4; | |
1054 } | |
1055 if (default_jmp != -1) { | |
1056 dprintf("default -> %d\n",default_jmp); | |
1057 if (jmpto == -1) jmpto = default_jmp; | |
1058 } | |
1059 if (*d == 0x7d) { | |
1060 d++; | |
1061 } else SetError(); | |
1062 return jmpto; | |
1063 } | |
1064 /* simple switch | |
1065 <exp> | |
1066 0x7b | |
1067 <int> | |
1068 ... | |
1069 0x7d | |
1070 */ | |
1071 int Cmd::GetSimpleSwitch(const char*& d) { | |
1072 if (*d != 0x28) {SetError(); return -1;} | |
1073 d++; | |
1074 dprintf("simple switch. "); | |
1075 int var = GetExpression(d); | |
1076 if (*d != 0x29) {SetError(); return -1;} | |
1077 d++; | |
1078 dprintf(" ->\n"); | |
1079 int jumpto = -1; | |
1080 if (*d == 0x7b) { | |
1081 d++; | |
1082 } else SetError(); | |
1083 int i; for (i=0; i<argc; i++) { | |
1084 int j = read_little_endian_int(d); | |
1085 d += 4; | |
1086 dprintf("\t%d -> %d\n", i+1, j); | |
1087 if (var == i) jumpto = j; | |
1088 } | |
1089 if (*d == 0x7d) { | |
1090 d++; | |
1091 } else SetError(); | |
1092 return jumpto; | |
1093 } | |
1094 | |
1095 /* | |
1096 selection | |
1097 ? <exp> | |
1098 0x7b | |
1099 <0x0a|0x40> <ushort | uint> | |
1100 */ | |
1101 void Cmd::GetSelection(const char*& d) { | |
1102 dprintf("selection. "); | |
1103 if (*d == 0x28) { | |
1104 d++; | |
1105 GetExpression(d); | |
1106 if (*d != 0x29) { SetError(); return;} | |
1107 d++; | |
1108 } | |
1109 if (*d == 0x7b) { | |
1110 d++; | |
1111 dprintf("{\n\t"); | |
1112 } else SetError(); | |
1113 int arg_count = 0; | |
1114 string text = ""; | |
1115 int cond_result = false; | |
1116 int sel_no = 0; | |
1117 while(*d != 0x7d) { | |
1118 if (d[0] == 0x0a || d[0] == 0x40) { | |
1119 int var; | |
1120 if (system_version == 0) { var = read_little_endian_int(d+1); d += 5;} | |
1121 else { var = read_little_endian_short(d+1); d += 3;} | |
1122 dprintf("Line %d; ",var); | |
1123 if (text.length() != 0) { | |
65
4416cfac86ae
Convert EUC-JP files to UTF8
Thibaut Girka <thib@sitedethib.com>
parents:
63
diff
changeset
|
1124 if (cond_result) ; // 条件節が true なら表示しない |
0 | 1125 else { |
1126 const char* str = text.c_str(); | |
1127 VarInfo var; | |
1128 var.type = TYPE_STR; | |
1129 var.value = CopyString(str); | |
1130 args.push_back(var); | |
1131 var.type = TYPE_VAL; | |
1132 var.value = sel_no; | |
1133 args.push_back(var); | |
1134 } | |
1135 sel_no++; | |
1136 } | |
1137 text = ""; | |
1138 cond_result = false; | |
1139 } else if (d[0] == 0x2c) { | |
1140 dprintf(":comma:"); | |
1141 } else if (d[0] == 0x28) { | |
1142 dprintf(":cond:"); | |
1143 d++; | |
1144 while(d[0] != 0x29) { | |
65
4416cfac86ae
Convert EUC-JP files to UTF8
Thibaut Girka <thib@sitedethib.com>
parents:
63
diff
changeset
|
1145 int result = GetExpressionCond(d); // PRINT- 節でないばあい、条件表示。次は文字節、またはPRINT節のはず |
4416cfac86ae
Convert EUC-JP files to UTF8
Thibaut Girka <thib@sitedethib.com>
parents:
63
diff
changeset
|
1146 if (*d == 0x32) { // 0x32 なら、現在の条件節を表示しない |
0 | 1147 d++; dprintf("##"); |
1148 cond_result = result; | |
65
4416cfac86ae
Convert EUC-JP files to UTF8
Thibaut Girka <thib@sitedethib.com>
parents:
63
diff
changeset
|
1149 } else if (*d == 0x31) { // 0x31 なら、現在の条件節を表示する |
4416cfac86ae
Convert EUC-JP files to UTF8
Thibaut Girka <thib@sitedethib.com>
parents:
63
diff
changeset
|
1150 // Little Busters! : この条件で正しいかは未検証 |
0 | 1151 d++; dprintf("***"); |
1152 cond_result = !result; | |
1153 } | |
1154 dprintf(":"); | |
1155 } | |
1156 d++; | |
1157 } else if (StrType(d)) { | |
1158 int strpt = GetString(d); | |
1159 text += strheap + strpt; | |
1160 arg_count++; | |
1161 dprintf("\n\t"); | |
1162 } else if (*d == 0x23 && strncmp(d,"###PRINT",8) == 0) { | |
1163 d += 8; | |
1164 if (d[0] != 0x28) SetError(); | |
65
4416cfac86ae
Convert EUC-JP files to UTF8
Thibaut Girka <thib@sitedethib.com>
parents:
63
diff
changeset
|
1165 else { // 文字変数の内容の表示 |
0 | 1166 d++; |
1167 dprintf("Print."); | |
1168 VarInfo info; | |
1169 GetLeftToken(d, info); | |
1170 if (d[0] != 0x29 || info.type == -1) SetError(); | |
1171 d++; | |
21
d1bb7b365816
Fixed dynamic strings in selections (Fuko Pranks for instance)
thib
parents:
13
diff
changeset
|
1172 dprintf(";");/* |
65
4416cfac86ae
Convert EUC-JP files to UTF8
Thibaut Girka <thib@sitedethib.com>
parents:
63
diff
changeset
|
1173 // 数値を全角文字に変換して登録 |
0 | 1174 char str[10], str2[20]; // itoa |
1175 sprintf(str, "%d", info.value); | |
1176 int i; for (i=0; str[i] != 0; i++) { | |
1177 str2[i*2] = 0xa3; | |
1178 str2[i*2+1] = 0xb0 + str[i]-'0'; | |
1179 } | |
21
d1bb7b365816
Fixed dynamic strings in selections (Fuko Pranks for instance)
thib
parents:
13
diff
changeset
|
1180 str2[i*2] = 0;*/ |
d1bb7b365816
Fixed dynamic strings in selections (Fuko Pranks for instance)
thib
parents:
13
diff
changeset
|
1181 text += strheap + info.value; |
0 | 1182 } |
1183 } else { SetError(); break;} | |
1184 } | |
1185 d++; | |
1186 /* @@@ */ | |
65
4416cfac86ae
Convert EUC-JP files to UTF8
Thibaut Girka <thib@sitedethib.com>
parents:
63
diff
changeset
|
1187 /* 一致しない場合があるのでコメントアウト */ |
0 | 1188 // if (arg_count != argc) SetError(); |
1189 dprintf("\n}\n"); | |
1190 } | |
1191 | |
1192 void Cmd::GetCmd(Flags& flags_orig, const char*& d ) { | |
52 | 1193 if (d == NULL) { SetError(); return;} |
0 | 1194 if (cmd_type != CMD_NOP) return; |
1195 | |
1196 cmdstr[0] = 0; | |
1197 rawdata = d; | |
65
4416cfac86ae
Convert EUC-JP files to UTF8
Thibaut Girka <thib@sitedethib.com>
parents:
63
diff
changeset
|
1198 if (*d == 0x23) { /* コマンド */ |
0 | 1199 cmd_type = CMD_OTHER; |
1200 cmd1 = *(unsigned const char*)(d+1); | |
1201 cmd2 = *(unsigned const char*)(d+2); | |
1202 cmd3 = read_little_endian_short(d+3); | |
1203 argc = read_little_endian_short(d+5); | |
1204 cmd4 = *(unsigned const char*)(d+7); | |
1205 d += 8; | |
1206 /* verbose */ | |
1207 // dprintf(" 0x23 - cmd %02x-%02x:%04x:%02x[%2d] \n",cmd1,cmd2,cmd3,cmd4,argc); | |
29
d229cce98f50
* no more (or, at least, less) duplicate code between scn2kdump and the rest
thib
parents:
21
diff
changeset
|
1208 sprintf(cmdstr, "%02x-%02x:%04x:%02x : %s",cmd1,cmd2,cmd3,cmd4, CmdDescr(cmd1,cmd2,cmd3,cmd4)); |
65
4416cfac86ae
Convert EUC-JP files to UTF8
Thibaut Girka <thib@sitedethib.com>
parents:
63
diff
changeset
|
1209 /* 引数を得る */ |
4416cfac86ae
Convert EUC-JP files to UTF8
Thibaut Girka <thib@sitedethib.com>
parents:
63
diff
changeset
|
1210 /* 特殊引数のもの */ |
0 | 1211 int is_special = 0; |
1212 if (cmd1 == 0) { | |
1213 if (cmd2 == 1) { | |
1214 int jump_arg = -1; | |
1215 if (cmd3 == 0 || cmd3 == 5) { | |
1216 /* gosub / goto */ | |
1217 jump_arg =read_little_endian_int(d); | |
1218 d += 4; | |
1219 if (cmd3 == 0) | |
1220 dprintf("\tjmp -> %d\n", jump_arg); | |
1221 else /* cmd3 == 5 */ | |
1222 dprintf("\tcall -> %d\n", jump_arg); | |
1223 is_special = 1; | |
1224 } else if (cmd3 == 1 || cmd3 == 2) { | |
1225 /* conditional jump (if / unless) */ | |
1226 if (*d++ != 0x28) { SetError(); return;} | |
1227 dprintf("\t"); | |
1228 int cond = GetExpressionCond(d); | |
65
4416cfac86ae
Convert EUC-JP files to UTF8
Thibaut Girka <thib@sitedethib.com>
parents:
63
diff
changeset
|
1229 if (cmd3 == 1) cond = !cond; // 逆になる |
0 | 1230 if (*d++ != 0x29) { SetError(); return; } |
1231 int jumpto = read_little_endian_int(d); | |
1232 d += 4; | |
1233 dprintf("-> %d\n", jumpto); | |
65
4416cfac86ae
Convert EUC-JP files to UTF8
Thibaut Girka <thib@sitedethib.com>
parents:
63
diff
changeset
|
1234 if (! cond) jump_arg = jumpto; /* condition が満たされない場合、ジャンプ */ |
0 | 1235 is_special = 1; |
1236 } else if (cmd3 == 4) { | |
1237 /* switch to */ | |
1238 jump_arg = GetSwitch(d); | |
1239 is_special = 1; | |
1240 } else if (cmd3 == 8 || cmd3 == 3) { | |
1241 /* switch to */ | |
1242 jump_arg = GetSimpleSwitch(d); | |
1243 is_special = 1; | |
1244 } else if (cmd3 == 16) { // call with parameters | |
1245 GetArgs(d); | |
1246 jump_arg = read_little_endian_int(d); | |
1247 d += 4; | |
1248 is_special = 1; | |
1249 } else goto retry; | |
1250 if (jump_arg == -1) { | |
1251 cmd_type = CMD_NOP; | |
1252 } | |
1253 else { | |
1254 cmd_type = CMD_JMP; | |
1255 args.push_back(VarInfo(jump_arg)); | |
1256 } | |
1257 } else if (cmd2 == 2 && (cmd3 == 0 || cmd3 == 1 || cmd3 == 2 || cmd3 == 3 || cmd3 == 0x0d) ) { | |
1258 /* selection */ | |
1259 GetSelection(d); | |
1260 is_special = 1; | |
1261 } | |
1262 } | |
1263 retry: | |
65
4416cfac86ae
Convert EUC-JP files to UTF8
Thibaut Girka <thib@sitedethib.com>
parents:
63
diff
changeset
|
1264 /* 一般引数のもの */ |
0 | 1265 if (!is_special) { |
29
d229cce98f50
* no more (or, at least, less) duplicate code between scn2kdump and the rest
thib
parents:
21
diff
changeset
|
1266 dprintf(" 0x23 - cmd %02x-%02x:%04x:%02x[%2d] : %s\n",cmd1,cmd2,cmd3,cmd4,argc,CmdDescr(cmd1,cmd2,cmd3,cmd4)); |
0 | 1267 dprintf("\t"); |
1268 if (cmd1 == 1 && cmd2 == 0x22 && (cmd3 == 0xc1c || cmd3 == 0x835)) GetArgsSpecial(3, d); | |
1269 else if (cmd1 == 1 && cmd2 == 0x0b && cmd3 == 0x65) GetArgsSpecial(0, d); | |
1270 else if (cmd1 == 1 && cmd2 == 0x15 && cmd3 == 0x28) GetArgsSpecial(0, d); | |
1271 else if (cmd1 == 1 && cmd2 == 4 && (cmd3 == 0x26c || cmd3 == 0x26d || cmd3 == 0x270 || cmd3 == 0x276)) GetArgsSpecial(0, d); | |
1272 else if (cmd1 == 1 && cmd2 == 4 && cmd3 == 0x586) GetArgsSpecial(1, d); | |
43
01aa5ddf7dc8
A lot of very minor improvements (deleted some unused variables, and other things like that...)
thib
parents:
29
diff
changeset
|
1273 else if (cmd1 == 1 && ((cmd2 == 0x21 && cmd3 == 0x4b) || (cmd2 == 0x28 && cmd3 == 0x64))) GetArgsSpecial(2,d); |
0 | 1274 else GetArgs(d); |
1275 dprintf("\n"); | |
1276 | |
1277 } | |
65
4416cfac86ae
Convert EUC-JP files to UTF8
Thibaut Girka <thib@sitedethib.com>
parents:
63
diff
changeset
|
1278 } else if (*d == 0x24) { /* 代入演算 */ |
0 | 1279 if (d[1] == 0x12 || d[2] != 0x5b) SetError(); |
1280 dprintf("expr: "); | |
1281 sprintf(cmdstr, "expr"); | |
1282 | |
1283 VarInfo info; | |
1284 int value = GetLeftToken(d, info); | |
1285 if (d[0] != 0x5c) SetError(); | |
1286 int type = d[1]; | |
1287 if (type < 20 || type > 30) SetError(); | |
1288 else dprintf("%s",op_str[type]); | |
1289 d += 2; | |
1290 int value2 = GetExpression(d); | |
65
4416cfac86ae
Convert EUC-JP files to UTF8
Thibaut Girka <thib@sitedethib.com>
parents:
63
diff
changeset
|
1291 // 代入情報を埋め込む |
0 | 1292 if (type != 30) value2 = eval(value, type-20, value2); |
1293 cmd_type = CMD_FLAGS; | |
1294 args.push_back(info); | |
1295 args.push_back(value2); | |
1296 dprintf("\n"); | |
65
4416cfac86ae
Convert EUC-JP files to UTF8
Thibaut Girka <thib@sitedethib.com>
parents:
63
diff
changeset
|
1297 } else if (StrType(d)) { /* 文字出力 */ |
0 | 1298 VarInfo info; |
1299 info.type = TYPE_STR; | |
1300 info.value = GetString(d); | |
1301 args.push_back(info); | |
1302 cmd_type = CMD_TEXT; | |
1303 dprintf("\n"); | |
65
4416cfac86ae
Convert EUC-JP files to UTF8
Thibaut Girka <thib@sitedethib.com>
parents:
63
diff
changeset
|
1304 } else if (*d == 0x0a || *d == 0x40 || *d == 0x21) { /* デバッグ用データと既読フラグ */ |
0 | 1305 cmd_type = CMD_NOP; |
1306 if (*d == 0x0a) { | |
1307 dprintf("line "); | |
1308 d++; | |
1309 int l; | |
1310 if (system_version == 0) { | |
1311 l = read_little_endian_int(d); | |
1312 d += 4; | |
1313 } else { | |
1314 l = read_little_endian_short(d); | |
1315 d += 2; | |
1316 } | |
1317 dprintf("%d\n", l); | |
1318 } else { /* 0x40, 0x21 */ | |
65
4416cfac86ae
Convert EUC-JP files to UTF8
Thibaut Girka <thib@sitedethib.com>
parents:
63
diff
changeset
|
1319 // 既読マーカーらしい。エントリーポイントとセーブポイントも使われる。 |
4416cfac86ae
Convert EUC-JP files to UTF8
Thibaut Girka <thib@sitedethib.com>
parents:
63
diff
changeset
|
1320 // RealLive 1.2.5から、0x40はセーブポイント、0x21はエントリーポイント。 |
4416cfac86ae
Convert EUC-JP files to UTF8
Thibaut Girka <thib@sitedethib.com>
parents:
63
diff
changeset
|
1321 // 1.2.5以前、どちらも0x40が使われる。 |
0 | 1322 int kidoku_index; |
1323 d++; | |
1324 if (system_version == 0) { | |
1325 kidoku_index = read_little_endian_int(d); | |
1326 d += 4; | |
1327 } else { | |
1328 kidoku_index = read_little_endian_short(d); | |
1329 d += 2; | |
1330 } | |
1331 dprintf("kidoku marker %d\n", kidoku_index); | |
65
4416cfac86ae
Convert EUC-JP files to UTF8
Thibaut Girka <thib@sitedethib.com>
parents:
63
diff
changeset
|
1332 // text_readflagは、このkidoku_indexを使ったら良いかな。 |
0 | 1333 } |
1334 } else if (*d == 0x2c) { /* ??? */ | |
65
4416cfac86ae
Convert EUC-JP files to UTF8
Thibaut Girka <thib@sitedethib.com>
parents:
63
diff
changeset
|
1335 dprintf("commd;0x2c\n"); // conditional jump の行き先によくあるらしい(常に、かはわからない) |
0 | 1336 d++; |
1337 } else { | |
1338 SetError(); | |
1339 } | |
1340 } | |
52 | 1341 |
0 | 1342 void Cmd::clear(void) { |
1343 cmd_type = CMD_NOP; | |
1344 ResetString(); | |
1345 args.clear(); | |
1346 errorflag = false; | |
1347 pos = -1; | |
1348 } | |
1349 | |
1350 char Cmd::strtype[256] = { | |
1351 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, /* +00 */ | |
1352 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, /* +10 */ // 0123456789ABCDEF | |
1353 1,0,3,0, 0,0,0,1, 0,0,0,0, 0,1,1,0, /* +20 */ // !"#$%&'()*+,-./ | |
1354 1,1,1,1, 1,1,1,1, 1,1,1,0, 0,0,0,1, /* +30 */ // 0123456789:;<=>? | |
1355 0,1,1,1, 1,1,1,1, 1,1,1,1, 1,1,1,1, /* +40 */ // @ABCDEFGHIJKLMNO | |
1356 1,1,1,1, 1,1,1,1, 1,1,1,0, 0,0,0,1, /* +50 */ // PQRSTUVWXYZ[\]^_ | |
1357 0,0,1,1, 1,1,1,1, 1,1,1,1, 1,1,1,1, /* +60 */ // `abcdefghijklmno | |
1358 1,1,1,1, 1,1,1,1, 1,1,1,1, 0,0,0,0, /* +70 */ // pqrstuvwxyz{|}~ | |
1359 2,2,2,2, 2,2,2,2, 2,2,2,2, 2,2,2,2, /* +80 */ | |
1360 2,2,2,2, 2,2,2,2, 2,2,2,2, 2,2,2,2, /* +90 */ | |
1361 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, /* +A0 */ | |
1362 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, /* +B0 */ | |
1363 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, /* +C0 */ | |
1364 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, /* +D0 */ | |
1365 2,2,2,2, 2,2,2,2, 2,2,2,2, 2,2,2,2, /* +E0 */ | |
1366 2,2,2,2, 2,2,2,2, 2,2,2,2, 2,2,0,0 /* +F0 */ | |
1367 }; | |
1368 | |
1369 int Cmd::GetString(const char*& d) { | |
1370 int retnum = -1; | |
1371 bool quote_flag = false; | |
1372 int stype; | |
1373 retnum = strend; | |
1374 while(1) { | |
1375 if (*d == '\\') { | |
1376 d++; | |
1377 strheap[strend++] = *d++; | |
1378 } else if (*d == '"') { | |
1379 if (quote_flag) quote_flag = false; | |
1380 else quote_flag = true; | |
1381 d++; | |
1382 } else if (quote_flag) { | |
1383 strheap[strend++] = *d++; | |
43
01aa5ddf7dc8
A lot of very minor improvements (deleted some unused variables, and other things like that...)
thib
parents:
29
diff
changeset
|
1384 } else if ((stype = StrType(d))) { |
0 | 1385 strheap[strend++] = *d++; |
1386 if (stype == 2) strheap[strend++] = *d++; | |
1387 } else break; | |
1388 } | |
1389 strheap[strend++] = 0; | |
1390 dprintf("\"%s\"", strheap + retnum); | |
1391 if (strend >= STRHEAP_SIZE) { | |
1392 dprintf("Error: string heap overflow\n"); | |
1393 } | |
1394 return retnum; | |
1395 } | |
1396 | |
1397 int Cmd::CopyString(const char* d) { | |
1398 int retnum = strend; | |
1399 int len = strlen(d); | |
1400 memcpy(strheap+strend, d, len+1); | |
1401 strend += len+1; | |
1402 d += len+1; | |
1403 return retnum; | |
1404 } | |
1405 | |
1406 int Cmd::StrVar(int type, int var_num) { | |
1407 int retnum = strend; | |
1408 flags.Str(type, var_num, strheap+strend, STRHEAP_SIZE-strend); | |
1409 strend += strlen(strheap+strend)+1; | |
1410 return retnum; | |
1411 } | |
1412 | |
1413 void Cmd::SetSysvar(int n, int val) { | |
1414 VarInfo info; | |
1415 if (cmd_type != CMD_SYSVAR) { | |
1416 args.clear(); | |
1417 } | |
1418 cmd_type = CMD_SYSVAR; | |
1419 | |
1420 info.type = TYPE_SYS; | |
1421 info.number = n; | |
1422 info.value = val; | |
1423 args.push_back(info); | |
1424 } | |
1425 void Cmd::SetFlagvar(VarInfo info, int val) { | |
1426 if (cmd_type != CMD_SYSVAR) { | |
1427 args.clear(); | |
1428 } | |
1429 cmd_type = CMD_SYSVAR; | |
1430 | |
1431 info.value = val; | |
1432 args.push_back(info); | |
1433 } | |
1434 | |
1435 void Cmd::SetStrvar(VarInfo info, const string& s) { | |
1436 if (cmd_type != CMD_SYSVAR) { | |
1437 args.clear(); | |
1438 } | |
1439 | |
1440 cmd_type = CMD_SYSVAR; | |
1441 const char* ss = s.c_str(); | |
1442 info.value = CopyString(ss); | |
1443 args.push_back(info); | |
1444 } | |
1445 | |
52 | 1446 |
1447 const char* Cmd::Str(const VarInfo& info) const { | |
1448 if (info.type != TYPE_STR && info.type != TYPE_VARSTR && info.type != TYPE_VARLOCSTR && info.type != TYPE_VARSYSSTR) | |
1449 return ""; | |
1450 int pt = info.value; | |
1451 if (pt < 0 || pt >= STRHEAP_SIZE) return ""; | |
1452 return strheap + pt; | |
1453 } | |
1454 | |
1455 int Cmd::AddStr(char* s) { | |
65
4416cfac86ae
Convert EUC-JP files to UTF8
Thibaut Girka <thib@sitedethib.com>
parents:
63
diff
changeset
|
1456 // 1-0a-0064 はこういうものが必要らしい |
52 | 1457 int start = strend; |
1458 while (*s) strheap[strend++] = *s++; | |
1459 strheap[strend++] = 0; | |
1460 return start; | |
1461 } | |
1462 | |
1463 | |
0 | 1464 void Cmd::read(const CmdSimplified& from) { |
1465 errorflag = false; | |
1466 ResetString(); | |
1467 | |
1468 cmd_type = Cmdtype(from.type); | |
1469 cmd1 = from.cmd1; | |
1470 cmd2 = from.cmd2; | |
1471 cmd3 = from.cmd3; | |
1472 cmd4 = from.cmd4; | |
1473 argc = from.argc; | |
65
4416cfac86ae
Convert EUC-JP files to UTF8
Thibaut Girka <thib@sitedethib.com>
parents:
63
diff
changeset
|
1474 /* args の読み込み */ |
0 | 1475 args.clear(); |
1476 char* d = from.args; | |
52 | 1477 if (d == NULL) return; |
0 | 1478 while(*d != TYPE_END) { |
1479 VarInfo info; | |
1480 switch(*d) { | |
1481 case TYPE_VAL: | |
1482 info.type = TYPE_VAL; | |
1483 info.number = 0; | |
1484 info.value = read_little_endian_int(d+1); | |
1485 d += 5; | |
1486 args.push_back(info); | |
1487 break; | |
1488 case TYPE_STR: | |
1489 info.type = TYPE_STR; | |
1490 info.number = 0; | |
1491 d++; | |
1492 info.value = CopyString( d); | |
1493 d += strlen(d)+1; | |
1494 args.push_back(info); | |
1495 break; | |
1496 default: | |
1497 fprintf(stderr,"Cmd::read: Invalid Load Data\n"); | |
1498 *d = TYPE_END; | |
1499 } | |
1500 } | |
1501 } | |
52 | 1502 |
0 | 1503 void Cmd::write(CmdSimplified& to, char*& buffer) const { |
1504 /* | |
1505 if (cmd_type != CMD_OTHER) { | |
1506 fprintf(stderr,"Cmd::write: Invalid Cmd during Saving Data\n"); | |
1507 to.cmd1 = 0; to.cmd2 = 0; to.cmd3 = 0; to.cmd4 = 0; to.argc = 0; to.args = 0; | |
1508 return; | |
1509 } | |
1510 */ | |
1511 to.type = cmd_type; | |
1512 to.cmd1 = cmd1; | |
1513 to.cmd2 = cmd2; | |
1514 to.cmd3 = cmd3; | |
1515 to.cmd4 = cmd4; | |
1516 to.argc = argc; | |
65
4416cfac86ae
Convert EUC-JP files to UTF8
Thibaut Girka <thib@sitedethib.com>
parents:
63
diff
changeset
|
1517 /* args の書き込み */ |
0 | 1518 if (args.empty()) { |
52 | 1519 to.args = NULL; |
0 | 1520 } else { |
1521 to.args = buffer; | |
1522 char* d = to.args; | |
1523 vector<VarInfo>::const_iterator it; | |
1524 for (it = args.begin(); it != args.end(); it++) { | |
1525 int type = it->type; | |
1526 if ( (type >= 0 && type < 7) || type == TYPE_VAL || type == char(TYPE_SYS)) { // digits | |
1527 *d++ = TYPE_VAL; | |
1528 write_little_endian_int(d, it->value); | |
1529 d += 4; | |
1530 } else if (type == TYPE_VARSTR || type == TYPE_VARSYSSTR || type == TYPE_VARLOCSTR || type == TYPE_STR) { // string | |
1531 *d++ = TYPE_STR; | |
1532 const char* s = Str(*it); | |
1533 int len = strlen(s); | |
1534 memcpy(d, s, len+1); | |
1535 d += len+1; | |
1536 } else { | |
1537 fprintf(stderr,"Cmd::write: Invalid Cmd args during Saving Data\n"); | |
1538 } | |
1539 } | |
1540 *d++ = TYPE_END; | |
1541 buffer = d; | |
1542 } | |
1543 } | |
52 | 1544 |
0 | 1545 void CmdSimplified::copy(const CmdSimplified& from, char*& args_buffer) { |
1546 *this = from; | |
52 | 1547 if (args == NULL) return; |
0 | 1548 char* args_old = from.args; |
65
4416cfac86ae
Convert EUC-JP files to UTF8
Thibaut Girka <thib@sitedethib.com>
parents:
63
diff
changeset
|
1549 /* args のコピー */ |
0 | 1550 while(*args_old != TYPE_END) { |
1551 if (*args_old == TYPE_VAL) { | |
1552 args_old += 5; | |
1553 } else { /* TYPE_STR */ | |
1554 args_old += strlen(args_old)+1; | |
1555 } | |
1556 } | |
1557 args_old++; | |
1558 int args_len = args_old - from.args; | |
1559 memmove(args_buffer, from.args, args_len); | |
1560 args = args_buffer; | |
1561 args_buffer += args_len; | |
1562 } | |
52 | 1563 |
0 | 1564 void CmdSimplified::Save(string& saveret) { |
1565 char buf[1024]; | |
1566 sprintf(buf, "%02x-%02x:%04x:%02x(%02d),", cmd1, cmd2, cmd3, cmd4, argc); | |
1567 saveret += buf; | |
1568 | |
65
4416cfac86ae
Convert EUC-JP files to UTF8
Thibaut Girka <thib@sitedethib.com>
parents:
63
diff
changeset
|
1569 /* args のコピー */ |
0 | 1570 char* d = args; |
1571 while(d && *d != TYPE_END) { | |
1572 if (*d == TYPE_VAL) { | |
1573 d++; | |
1574 sprintf(buf, "%d,", read_little_endian_int(d)); | |
1575 d += 4; | |
65
4416cfac86ae
Convert EUC-JP files to UTF8
Thibaut Girka <thib@sitedethib.com>
parents:
63
diff
changeset
|
1576 } else { /* TYPE_STR と仮定 */ |
0 | 1577 d++; |
65
4416cfac86ae
Convert EUC-JP files to UTF8
Thibaut Girka <thib@sitedethib.com>
parents:
63
diff
changeset
|
1578 if (strlen(d) > 1000) d[1000] = 0; // ありえない・・・ |
0 | 1579 int i; int cnt = 0; |
1580 buf[cnt++] = '"'; | |
1581 for (i=0; d[i] != 0; i++) { | |
1582 if (d[i] == '"') buf[cnt++] = '"'; | |
1583 buf[cnt++] = d[i]; | |
1584 } | |
1585 buf[cnt++]='"'; | |
1586 buf[cnt++] = ','; | |
1587 buf[cnt++] = 0; | |
1588 d += strlen(d)+1; | |
1589 } | |
1590 saveret += buf; | |
1591 } | |
1592 saveret += 'E'; | |
1593 } | |
1594 | |
1595 void CmdSimplified::Load(const char* save, char*& args_buffer) { | |
1596 args = args_buffer; | |
1597 | |
1598 type = CMD_OTHER; | |
1599 sscanf(save, "%02x-%02x:%04x:%02x(%02d),", &cmd1, &cmd2, &cmd3, &cmd4, &argc); | |
1600 save = strchr(save, ','); | |
52 | 1601 if (save == NULL) { |
0 | 1602 *args_buffer++ = TYPE_END; |
1603 return; | |
1604 } | |
1605 save++; | |
1606 while(*save != 'E' && *save != '\n' && *save != '\0') { | |
1607 if (isdigit(*save)) { | |
1608 int v; | |
1609 sscanf(save,"%d,",&v); | |
1610 *args_buffer++ = TYPE_VAL; | |
1611 write_little_endian_int(args_buffer, v); | |
1612 args_buffer+= 4; | |
1613 save = strchr(save, ','); | |
1614 if (save) save++; | |
1615 } else { // *save == '"' | |
1616 save++; | |
1617 *args_buffer++ = TYPE_STR; | |
1618 while(1) { | |
1619 if (*save == 0) break; | |
1620 if (*save == '"') { | |
1621 if (save[1] != '"') break; | |
1622 save++; | |
1623 } | |
1624 *args_buffer++ = *save++; | |
1625 } | |
1626 save += 2; | |
1627 *args_buffer++ = 0; | |
1628 } | |
1629 } | |
1630 *args_buffer++ = TYPE_END; | |
1631 } | |
1632 |