root/scn2k/scn2k_cmd.cc

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