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 #include <stdexcept>
|
|
29 #include"scn2k_impl.h"
|
|
30 #include"system/file.h"
|
|
31 #include"system/system_config.h"
|
|
32 #include"window/picture.h"
|
|
33 #include"window/system.h"
|
|
34
|
|
35 // #define DEBUG 1
|
|
36
|
|
37 using namespace std;
|
|
38
|
|
39 /**********************************************
|
|
40 ** Scn2k
|
|
41 */
|
|
42
|
|
43 void kconv(const unsigned char* src, unsigned char* dest);
|
|
44 void kconv_rev(const unsigned char* src, unsigned char* dest);
|
|
45 string kconv(const string& s);
|
|
46 string kconv_rev(const string& s);
|
|
47
|
|
48 Scn2k::Scn2k(Event::Container& _event, PicContainer& _parent, class MuSys& mu, AyuSysConfig& _config) :
|
|
49 Event::Time(_event),
|
|
50 event(_event),
|
|
51 parent(_parent),
|
|
52 config(_config),
|
|
53 text_exec(_event, _parent, config),
|
|
54 grp_exec(_event, _parent, flag, flag.cgm_data, mu, config)
|
|
55 {
|
|
56 system_version = 0;
|
|
57 skip_mode = SKIP_NO;
|
|
58
|
|
59 script_start = 0;
|
|
60 script = 0;
|
|
61 script_end = 0;
|
|
62
|
|
63 backlog_script_scn = -1;
|
|
64 backlog_script_start = 0;
|
|
65 backlog_script_end = 0;
|
|
66
|
|
67 save_scn = 0;
|
|
68 save_point = 0;
|
|
69 scn_number = 0;
|
|
70 scn_point = 0;
|
|
71 cmd_stack_str = cmd_stack_str_orig;
|
|
72
|
|
73 dialog = 0;
|
|
74 dialog_type = CMD_NOP;
|
|
75 menu = 0;
|
|
76 menu_mouseshown = false;
|
|
77
|
|
78 /* マウスカーソルを作成 */
|
|
79 mouse_type = 0;
|
|
80 mouse_surface = 0;
|
|
81 mouse_pressed = 0;
|
|
82 ShowCursor();
|
|
83
|
|
84 LoadSys();
|
|
85 text_exec.InitWindow();
|
|
86 grp_exec.InitSel(config);
|
|
87 }
|
|
88
|
|
89 Scn2k::~Scn2k() {
|
|
90 HideCursor();
|
|
91 SaveSys();
|
|
92 }
|
|
93
|
|
94 char* Scn2k::OpenScript(int new_scn_number, char*& end, int* call_vec, int& system_version) {
|
|
95 char fname[1024];
|
|
96 const char* data;
|
|
97 char* ret_data;
|
|
98 int offset = 0;
|
|
99 int scenario_magic;
|
|
100
|
|
101 sprintf(fname, "SEEN%04d.TXT", new_scn_number);
|
|
102 ARCINFO* info = file_searcher.Find(FILESEARCH::SCN, fname, "");
|
|
103 if (info == 0) goto err;
|
|
104 data = info->Read();
|
|
105
|
|
106 /* version 確認 */
|
|
107 scenario_magic = read_little_endian_int(data + 4);
|
|
108 if (scenario_magic != 0x2712 && scenario_magic != 0x1adb2) {
|
|
109 fprintf(stderr,"Invalid scenario header : scenario number %d\n",new_scn_number);
|
|
110 goto err;
|
|
111 }
|
|
112 if (read_little_endian_int(data) == 0x1cc) {
|
|
113 system_version = 0;
|
|
114 offset = 0x1cc + read_little_endian_int(data+0x20) + 4;
|
|
115 } else if (read_little_endian_int(data) == 0x1d0) {
|
|
116 system_version = 1;
|
|
117 offset = read_little_endian_int(data + 0x20);
|
|
118 } else {
|
|
119 fprintf(stderr,"Invalid scenario header : scenario number %d\n",new_scn_number);
|
|
120 goto err;
|
|
121 }
|
|
122 /* header から subroutine number とりだし */
|
|
123 if (call_vec) {
|
|
124 int i;
|
|
125 for (i=0; i<100; i++) {
|
|
126 call_vec[i] = read_little_endian_int(data + 0x34 + i * 4);
|
|
127 }
|
|
128 }
|
|
129 ret_data = new char[info->Size() - offset + 1024];
|
|
130 memcpy(ret_data, data+offset, info->Size()-offset);
|
|
131 memset(ret_data+info->Size()-offset, 0, 1024);
|
|
132 end = ret_data + info->Size() - offset;
|
|
133 delete info;
|
|
134 return ret_data;
|
|
135
|
|
136 err:
|
|
137 delete info;
|
|
138 fprintf(stderr,"Cannot open scenario number %d\n",new_scn_number);
|
|
139 throw std::invalid_argument("Scn2k::OpenScript");
|
|
140
|
|
141 return false;
|
|
142 }
|
|
143 bool Scn2k::ChangeScript(int new_scn_number, int call_no) {
|
|
144 int old_scn_number = scn_number;
|
|
145 int old_scn_pt = script - script_start;
|
|
146 int scn_pt = 0;
|
|
147
|
|
148 if (script_start) delete[] script_start;
|
|
149 script_start = 0;
|
|
150 script = 0;
|
|
151 script_end = 0;
|
|
152
|
|
153 int call_vec[100];
|
|
154
|
|
155 try {
|
|
156 script_start = OpenScript(new_scn_number, script_end, call_vec, system_version);
|
|
157 } catch(...) {
|
|
158 fprintf(stderr,"\tFrom script %d pt %d\n",old_scn_number, old_scn_pt);
|
|
159 throw;
|
|
160 }
|
|
161 if (call_no > 0 && call_no < 100) {
|
|
162 scn_pt = call_vec[call_no];
|
|
163 if (scn_pt == 0) {
|
|
164 fprintf(stderr,"Invalid subroutine number: scn %d sub %d\n",new_scn_number, call_no);
|
|
165 scn_pt = 0;
|
|
166 }
|
|
167 } else if (call_no < 0) {
|
|
168 scn_pt = -call_no; // デバッグ用
|
|
169 }
|
|
170
|
|
171 scn_number = new_scn_number;
|
|
172 scn_point = scn_pt;
|
|
173 script = script_start + scn_pt;
|
|
174 if (script < script_start || script >= script_end)
|
|
175 fprintf(stderr,"scn %d pt %d: Cannot jump to %d:%d; fall back to the top\n",old_scn_number, old_scn_pt, scn_number, scn_pt);
|
|
176 return true;
|
|
177 }
|
|
178 bool Scn2k::ReadCmdAt(Cmd& cmd, int scn, int pt) {
|
|
179 const char* d;
|
|
180 if (scn ==scn_number) {
|
|
181 d = script_start + pt;
|
|
182 if (d < script_start || d >= script_end) {
|
|
183 fprintf(stderr,"Cannot read script at current scn %d pt %d\n", scn, pt);
|
|
184 return false;
|
|
185 }
|
|
186 } else {
|
|
187 if (backlog_script_scn != scn) {
|
|
188 if (backlog_script_start) delete[] backlog_script_start;
|
|
189 backlog_script_start = OpenScript(scn, backlog_script_end, 0, system_version);
|
|
190 }
|
|
191 d = backlog_script_start + pt;
|
|
192 if (d < backlog_script_start || d >= backlog_script_end) {
|
|
193 fprintf(stderr,"Cannot read script at scn %d pt %d\n", scn, pt);
|
|
194 return false;
|
|
195 }
|
|
196 }
|
|
197
|
|
198 cmd.GetCmd(flag, d);
|
|
199 return true;
|
|
200 }
|
|
201
|
|
202 extern bool save_req, load_req; // キーボードからセーブ・ロードできるように
|
|
203 extern bool pressAreq;
|
|
204
|
|
205 void Scn2k::Elapsed(unsigned int current_time) {
|
|
206 SetWakeup(current_time + 10); // 10msに一回シナリオスクリプト解釈
|
|
207 if (script == 0) return;
|
|
208 //VarInfo info; info.type = 6; info.number = 0; // PB の「一回ゲームを開始したことがある」フラグ
|
|
209 //flag.Set(info,1);
|
|
210 //info.type = 0; info.number = 604; // Princess Bride: クリア対象設定フラグ (聖)
|
|
211 //flag.Set(info, 1);
|
|
212
|
|
213
|
|
214 Cmd cmd(flag, system_version);
|
|
215 int cnt1;
|
|
216 int cnt2 = 1000; // flag / jump / flag 系コマンドの最大実行回数
|
|
217
|
|
218 /* XXX */
|
|
219 if (save_req) {
|
|
220 save_req = false;
|
|
221 load_req = false;
|
|
222 cmd.cmd_type = CMD_SAVEREQ;
|
|
223 } else if (load_req) {
|
|
224 load_req = false;
|
|
225 save_req = false;
|
|
226 cmd.cmd_type = CMD_LOADREQ;
|
|
227 }
|
|
228 if (pressAreq) {
|
|
229 pressAreq = false;
|
|
230 LoadRollback(cmd);
|
|
231 return;
|
|
232 }
|
|
233
|
|
234 /* キー入力などに対応 */
|
|
235 // メニュー内以外で shift キーが押されたらスキップ開始
|
|
236 if ( (skip_mode&SKIP_IN_MENU) == 0) {
|
|
237 if (event.pressed(KEY_SHIFT)) {
|
|
238 if (skip_mode & SKIP_TEXT) {
|
|
239 ; // スキップ中ならなにもしない
|
|
240 } else {
|
|
241 SetSkipMode(SkipMode(SKIP_TEXT | SKIP_GRP_NOEFFEC | SKIPEND_KEY));
|
|
242 }
|
|
243 } else {
|
|
244 if ( skip_mode & SKIPEND_KEY) {
|
|
245 if ( (skip_mode & SKIPEND_TEXT) && (skip_mode & SKIP_TEXT)) {
|
|
246 SkipMode new_skip_mode = SkipMode(skip_mode & (~SKIPEND_KEY));
|
|
247 if ( (new_skip_mode & SKIP_GRP_FAST) || (new_skip_mode & SKIP_GRP_NODRAW)) {
|
|
248 new_skip_mode = SkipMode(skip_mode & (~SKIP_GRP_NOEFFEC));
|
|
249 }
|
|
250 SetSkipMode(new_skip_mode);
|
|
251 } else {
|
|
252 SetSkipMode(SKIP_NO);
|
|
253 }
|
|
254 }
|
|
255 }
|
|
256 }
|
|
257
|
|
258 for (cnt1=0; cnt1<20; cnt1++) { // 一回につき 20 個のコマンド実行
|
|
259 // 他のコマンド実行中なら終了
|
|
260 if ( (cmd.cmd_type == CMD_NOP && SysWait(cmd)) ||
|
|
261 // (cmd.cmd_type == CMD_NOP && text_exec.Wait(current_time, cmd)) ||
|
|
262 // (cmd.cmd_type == CMD_NOP && grp_exec.Wait(current_time, cmd))) {
|
|
263 (cmd.cmd_type == CMD_NOP && grp_exec.Wait(current_time, cmd)) ||
|
|
264 (cmd.cmd_type == CMD_NOP && text_exec.Wait(current_time, cmd))) {
|
|
265 break;
|
|
266 }
|
|
267 // コマンド読み込み
|
|
268 for (; cnt2 > 0; cnt2--) {
|
|
269 scn_point = script - script_start;
|
|
270 eprintf("%d / %d :", script - script_start, script_end-script_start);
|
|
271 // fprintf(stderr,"%d: %d / %d :",scn_number, script - script_start, script_end-script_start);
|
|
272 cmd.GetCmd(flag, script);
|
|
273 // if (cmd.cmd_type != CMD_NOP) {
|
|
274 if (0) {
|
|
275 fprintf(stderr,"%d / %d : 0x23 - cmd %02x-%02x:%04x:%02x[%2d] \n",
|
|
276 scn_point, script_end-script_start,
|
|
277 cmd.cmd1,cmd.cmd2,cmd.cmd3,cmd.cmd4,cmd.argc);
|
|
278 int i; for (i=0; i<cmd.args.size(); i++) {
|
|
279 if (i == 0) fprintf(stderr,"\t");
|
|
280 VarInfo info = cmd.args[i];
|
|
281 if (info.type == TYPE_STR || info.type == TYPE_VARSTR)
|
|
282 fprintf(stderr,"\"%s\",", cmd.Str(info));
|
|
283 else
|
|
284 fprintf(stderr,"%d,",info.value);
|
|
285 }
|
|
286 fprintf(stderr,"\n");
|
|
287 }
|
|
288 cmd.scn = scn_number;
|
|
289 cmd.pos = scn_point;
|
|
290 if (cmd.IsError()) break;
|
|
291 if (cmd.cmd_type == CMD_NOP) continue;
|
|
292 if (cmd.cmd_type == CMD_JMP) {
|
|
293 // local jump
|
|
294 if (cmd.cmd1 == 0 && cmd.cmd2 == 1 && cmd.cmd3 == 16) {
|
|
295 int i;
|
|
296 for (i=0; i<cmd.args.size()-1; i++) {
|
|
297 VarInfo var;
|
|
298 var.type = 11;
|
|
299 var.number = i;
|
|
300 flag.Set(var, cmd.args[i].value);
|
|
301 }
|
|
302 cmd.args[0].value = cmd.args[i].value;
|
|
303 }
|
|
304 if ( cmd.cmd1 == 0 && cmd.cmd2 == 1 && (cmd.cmd3 == 5 || cmd.cmd3 == 8 || cmd.cmd3 == 16) ) { // local call / simple switch
|
|
305 int scn_pt = script - script_start;
|
|
306 // fprintf(stderr,"\nlocal call %d:%d from %d\n",scn_number,cmd.args[0].value,scn_pt);
|
|
307 stack.push_back(StackItem(-1, scn_pt));
|
|
308 }
|
|
309 if (cmd.cmd1 == 0 && cmd.cmd2 == 1 && cmd.cmd3 == 1) {
|
|
310 fprintf(stderr,"*** unsupported: cond 1\n");
|
|
311 }
|
|
312 script = script_start + cmd.args[0].value;
|
|
313 if (script < script_start || script >= script_end) {
|
|
314 fprintf(stderr,"scn %d pt %d: Cannot jump to %d; fall back to the top\n",scn_number, cmd.args[0].value);
|
|
315 script = script_start;
|
|
316 }
|
|
317 cmd.clear();
|
|
318 continue;
|
|
319 }
|
|
320 if (flag.Exec(cmd)) continue;
|
|
321 break;
|
|
322 }
|
|
323 if (cmd.IsError()) {
|
|
324 fprintf(stderr,"cmd error occured: scn %d pt %d / cur %d",scn_number,scn_point,script-script_start);
|
|
325 while(script < script_end) {
|
|
326 if (*script == 0x29 && script[1] == 0x0a) {script++;break;}
|
|
327 if (*script == 0 && script[1] == 0x0a) {script++;break;}
|
|
328 if (*script == 0 && script[1] == 0x23) {script++;break;}
|
|
329 script++;
|
|
330 fprintf(stderr," -> fall back to %d\n",script-script_start);
|
|
331 }
|
|
332 const char* dprev = script - 0x60;
|
|
333 if (dprev < script_start) dprev = script_start;
|
|
334 int ilen = (script-dprev+65)/16;
|
|
335 int i; for (i=0; i<ilen; i++) {
|
|
336 fprintf(stderr, "%6d: ",dprev-script_start);
|
|
337 int j; for (j=0; j<16; j++) {
|
|
338 if (dprev >= script_end) break;
|
|
339 fprintf(stderr, "%02x ",*(unsigned char*)(dprev));
|
|
340 dprev++;
|
|
341 }
|
|
342 fprintf(stderr, "\n");
|
|
343 }
|
|
344 break;
|
|
345 }
|
|
346 if (cmd.cmd_type == CMD_NOP) continue;
|
|
347
|
|
348 if (cmd.cmd_type == CMD_TEXT && cmd.pos != -1) {
|
|
349 set<int>& readflag = text_readflag[scn_number];
|
|
350 if (readflag.find(cmd.pos) == readflag.end()) { // 未読テキスト発見
|
|
351 readflag.insert(cmd.pos);
|
|
352 if (skip_mode & SKIPEND_TEXT) {
|
|
353 if (!(skip_mode & SKIPEND_KEY)) SetSkipMode(SKIP_NO);
|
|
354 }
|
|
355 }
|
|
356 }
|
|
357 text_exec.Exec(cmd);
|
|
358 grp_exec.Exec(cmd);
|
|
359 SysExec(cmd);
|
|
360 if (cmd.cmd_type == CMD_WAITFRAMEUPDATE) {
|
|
361 SetWakeup(Event::Time::FRAME_UPDATE);
|
|
362 break;
|
|
363 } else if (cmd.cmd_type != CMD_NOP) {
|
|
364 #if DEBUG
|
|
365 fprintf(stderr,"%d-%d / %d : unsupported command; 0x23 - cmd %02x-%02x:%04x:%02x[%2d] \n",
|
|
366 cmd.scn, script - script_start, script_end-script_start,
|
|
367 cmd.cmd1,cmd.cmd2,cmd.cmd3,cmd.cmd4,cmd.argc);
|
|
368 int i; for (i=0; i<cmd.args.size(); i++) {
|
|
369 if (i == 0) fprintf(stderr,"\t");
|
|
370 VarInfo info = cmd.args[i];
|
|
371 if (info.type == TYPE_STR || info.type == TYPE_VARSTR)
|
|
372 fprintf(stderr,"\"%s\",", cmd.Str(info));
|
|
373 else
|
|
374 fprintf(stderr,"%d,",info.value);
|
|
375 }
|
|
376 fprintf(stderr,"\n");
|
|
377 #endif
|
|
378 cmd.clear();
|
|
379 }
|
|
380 }
|
|
381 return;
|
|
382 }
|
|
383
|
|
384 void Scn2k::ShowCursor(void) {
|
|
385 HideCursor();
|
|
386 char key[1024];
|
|
387 sprintf(key, "#MOUSE_CURSOR.%03d.NAME",mouse_type);
|
|
388 const char* name = config.GetParaStr(key);
|
|
389 if (name == 0 || name[0] == 0) mouse_surface = DEFAULT_MOUSECURSOR;
|
|
390 else {
|
|
391 mouse_surface = parent.Root().NewSurface(name, COLOR_MASK);
|
|
392 }
|
|
393 if (mouse_surface == 0) mouse_surface = DEFAULT_MOUSECURSOR;
|
|
394 System::Main::SetCursor(mouse_surface, Rect(8, 8, 8+32, 8+32));
|
|
395 }
|
|
396
|
|
397 void Scn2k::HideCursor(void) {
|
|
398 if (mouse_surface) {
|
|
399 System::Main::SetCursor(0, Rect(0,0));
|
|
400 if (mouse_surface != DEFAULT_MOUSECURSOR)
|
|
401 parent.Root().DeleteSurface(mouse_surface);
|
|
402 mouse_surface = 0;
|
|
403 }
|
|
404 return;
|
|
405 }
|
|
406
|
|
407 bool Scn2k::SysWait(Cmd& cmd) {
|
|
408
|
|
409 if (menu) {
|
|
410 menu->Exec(cmd);
|
|
411 if (menu->status & Scn2kMenu::MENU_DELETE || menu->pimpl == 0) {
|
|
412 delete menu;
|
|
413 menu = 0;
|
|
414 if (! menu_mouseshown) HideCursor();
|
|
415 else ShowCursor();
|
|
416 SetSkipMode(SkipMode(skip_mode & (~SKIP_IN_MENU) ));
|
|
417 }
|
|
418 if (cmd.cmd_type == CMD_NOP) return true;
|
|
419 else return false; /* exec command */
|
|
420 }
|
|
421 return false;
|
|
422 }
|
|
423
|
|
424 void DllCall_LB(Cmd& cmd, Flags& flags);
|
|
425 void Scn2k::SysExec(Cmd& cmd) {
|
|
426 if (cmd.cmd_type == CMD_SYSVAR) {
|
|
427 int i;
|
|
428 for (i=0; i<cmd.args.size(); i++) {
|
|
429 if (cmd.args[i].type == TYPE_SYS) {
|
|
430 if (cmd.args[i].number == TYPE_SYS_SYS) {
|
|
431 flag.SetSys(cmd.args[i].value);
|
|
432 } else if (cmd.args[i].number == TYPE_SYS_SKIPMODE) {
|
|
433 SetSkipMode(SkipMode(cmd.args[i].value));
|
|
434 }
|
|
435 } else if (cmd.args[i].type == TYPE_VARSTR) {
|
|
436 flag.SetStr(cmd.args[i].number, cmd.Str(cmd.args[i]));
|
|
437 } else {
|
|
438 flag.Set(cmd.args[i], cmd.args[i].value);
|
|
439 }
|
|
440 }
|
|
441 cmd.clear();
|
|
442 }
|
|
443 if (cmd.cmd_type == CMD_SAVEPOINT || cmd.cmd_type == CMD_ROLLBACKPOINT) {
|
|
444 if (text_exec.backlog_item.scn != -1) {
|
|
445 text_exec.backlog.push_back(text_exec.backlog_item);
|
|
446 text_exec.backlog_item.Clear();
|
|
447 }
|
|
448 save_scn = scn_number;
|
|
449 save_point = scn_point;
|
|
450 if (!new_rollback_save.empty()) {
|
|
451 rollback_save.push_back(new_rollback_save);
|
|
452 new_rollback_save = "";
|
|
453 }
|
|
454 if (cmd.cmd_type == CMD_ROLLBACKPOINT) SaveRollback();
|
|
455 cmd.clear();
|
|
456 }
|
|
457 if (cmd.cmd_type == CMD_SAVEREQ || cmd.cmd_type == CMD_SAVE) {
|
|
458 Save(cmd);
|
|
459 return;
|
|
460 }
|
|
461 if (cmd.cmd_type == CMD_LOADREQ || cmd.cmd_type == CMD_LOAD) {
|
|
462 Load(cmd);
|
|
463 return;
|
|
464 }
|
|
465 if (cmd.cmd_type == CMD_BACKLOGREQ || cmd.cmd_type == CMD_BACKLOGREQ_FWD) {
|
|
466 if (menu) {
|
|
467 fprintf(stderr,"BACKLOG_REQ requested!!!\n");
|
|
468 return;
|
|
469 }
|
|
470 if (cmd.cmd_type == CMD_BACKLOGREQ_FWD) {
|
|
471 cmd.clear(); // backlog mode 以外で fwd を押されてもなにもしない
|
|
472 return;
|
|
473 }
|
|
474 SetSkipMode(SKIP_IN_MENU); // テキストスキップ等はここで中断
|
|
475 menu = new Scn2kMenu(Scn2kMenu::MENU_BACKLOG, *this, flag, text_exec, system_version);
|
|
476 menu->InitPanel(event, parent);
|
|
477 menu->InitTitle(Scn2kSaveTitle(*this));
|
|
478 if (mouse_surface) menu_mouseshown = true;
|
|
479 else menu_mouseshown = false;
|
|
480 ShowCursor();
|
|
481 return;
|
|
482 }
|
|
483 if (cmd.cmd_type == CMD_MENUREQ) {
|
|
484 int scn=0, pt=0;
|
|
485 config.GetParam("#CANCELCALL", 2, &scn, &pt);
|
|
486 if (scn) {
|
|
487 // 右クリックされたら global call を行う
|
|
488 cmd.cmd_type = CMD_OTHER;
|
|
489 cmd.cmd1 = 0;
|
|
490 cmd.cmd2 = 1;
|
|
491 cmd.cmd3 = 0x0c;
|
|
492 cmd.cmd4 = 1;
|
|
493 cmd.args.clear();
|
|
494 cmd.args.push_back(VarInfo(SCN_INFO_MENU));
|
|
495 cmd.args.push_back(0);
|
|
496 SetSkipMode(SKIP_IN_MENU); // テキストスキップ等はここで中断
|
|
497 }
|
|
498 }
|
|
499 if (cmd.cmd_type == CMD_SAVECMDGRP || cmd.cmd_type == CMD_SAVECMDGRP_START || cmd.cmd_type == CMD_SAVECMDGRP_ONCE || cmd.cmd_type == CMD_SAVECMD_ONCE) {
|
|
500 // 画像コマンド等はスタックに保存し、セーブ時に保存できるようにする
|
|
501 if (cmd.cmd_type == CMD_SAVECMDGRP_START) {
|
|
502 vector<CmdSimplified>::iterator it, cur;
|
|
503 cur = cmd_stack.begin();
|
|
504 cmd_stack_str = cmd_stack_str_orig;
|
|
505 /* 画像関連コマンド以外を別にする */
|
|
506 for (it=cmd_stack.begin(); it != cmd_stack.end(); it++) {
|
|
507 if (it->type != CMD_SAVECMDGRP && it->type != CMD_SAVECMDGRP_START && it->type != CMD_SAVECMDGRP_ONCE) {
|
|
508 cur->copy(*it, cmd_stack_str);
|
|
509 cur++;
|
|
510 }
|
|
511 }
|
|
512 cmd_stack.erase(cur, cmd_stack.end());
|
|
513 }
|
|
514 if (cmd.cmd_type == CMD_SAVECMD_ONCE || cmd.cmd_type == CMD_SAVECMDGRP_ONCE) { // 同じコマンドがあれば削除する
|
|
515 vector<CmdSimplified>::iterator it;
|
|
516 for (it = cmd_stack.end(); it != cmd_stack.begin(); ) {
|
|
517 --it;
|
|
518 if (it->cmd1 == cmd.cmd1 && it->cmd2 == cmd.cmd2 && it->cmd3 == cmd.cmd3 && it->cmd4 == cmd.cmd4) {
|
|
519 cmd_stack.erase(it);
|
|
520 break;
|
|
521 }
|
|
522 }
|
|
523 }
|
|
524 CmdSimplified cmd_item;
|
|
525 cmd.write(cmd_item, cmd_stack_str);
|
|
526 cmd_stack.push_back(cmd_item);
|
|
527 cmd.clear();
|
|
528 if (cmd_stack_str > cmd_stack_str_orig + 30000) { // char cmd_stack_str_orig[32768]
|
|
529 fprintf(stderr,"Error in Scn2k::SysExec: too long cmdstack (%d): stack string overflow\n",cmd_stack.size());
|
|
530 cmd_stack_str = cmd_stack_str_orig;
|
|
531 cmd_stack.clear();
|
|
532 }
|
|
533 }
|
|
534 if (cmd.cmd_type != CMD_OTHER) return;
|
|
535 if (cmd.cmd1 == 0 && cmd.cmd2 == 1) {
|
|
536 if (cmd.cmd3 == 0x0b) { // global jump
|
6
|
537 int call_no = 0;
|
|
538 if (cmd.args.size() >= 2) call_no = cmd.args[1].value;
|
0
|
539 eprintf("global jump to %d\n",cmd.args[0].value);
|
6
|
540 if (! ChangeScript(cmd.args[0].value, call_no)) return; // 読み込めない; abort.
|
0
|
541 cmd.clear();
|
|
542 } else if (cmd.cmd3 == 0x0c || cmd.cmd3 == 0x12) { // call (0x12 の方は微妙)
|
|
543 int new_scn = cmd.args[0].value;
|
|
544 int new_pt = 0;
|
|
545 if (cmd.args.size() >= 1) { // subroutine number が付く
|
|
546 // 引数が付くのもあるらしい
|
|
547 new_pt = cmd.args[1].value;
|
|
548 }
|
|
549 if (new_scn == SCN_INFO_MENU) { // menu call
|
|
550 config.GetParam("#CANCELCALL", 2, &new_scn, &new_pt);
|
|
551 stack.push_back(StackItem(SCN_INFO, SCN_INFO_MENU)); // menu call を示す特殊な記号
|
|
552 } else {
|
|
553 int i;
|
|
554 VarInfo var;
|
|
555 // ローカル変数を伴う subroutine call
|
|
556 var.type = 11;
|
|
557 var.number = 0;
|
|
558 int saved_vars = 0;
|
|
559 for (i=0; i<40; i++) {
|
|
560 int val = flag.Get(var.type, i);
|
|
561 if (val != 0) {
|
|
562 stack.push_back(StackItem(SCN_INFO_LOCALS + i, val));
|
|
563 saved_vars++;
|
|
564 }
|
|
565 }
|
|
566 var.type = TYPE_VARLOCSTR;
|
|
567 for (i=0; i<3; i++) {
|
|
568 string s = flag.Str(var.type, i);
|
|
569 if (s.size()) {
|
|
570 int sp = stack_strbuffer.size();
|
|
571 stack.push_back(StackItem(SCN_INFO_LOCALSTR+i, sp));
|
|
572 stack_strbuffer.push_back(s);
|
|
573 saved_vars++;
|
|
574 }
|
|
575 }
|
|
576 stack.push_back(StackItem(SCN_INFO, SCN_INFO_LOCALS + saved_vars));
|
|
577
|
|
578 var.type = 11;
|
|
579 var.number = 0;
|
|
580 // 特殊な subroutine call なので、余計な情報を引数に渡す
|
|
581 for (i=2; i<cmd.args.size(); i++) {
|
|
582 flag.Set(var, cmd.args[i].value);
|
|
583 // fprintf(stderr,"<%d:%d>=%d;",var.type,var.number,cmd.args[i].value);
|
|
584 var.number++;
|
|
585 }
|
|
586 // fprintf(stderr,"%d; ",stack.size());
|
|
587 }
|
|
588 int scn_pt = script - script_start;
|
|
589 stack.push_back(StackItem(scn_number, scn_pt));
|
|
590 // fprintf(stderr,"\nglobal call %d:%d from %d:%d\n",new_scn,new_pt,scn_number,scn_pt);
|
|
591 eprintf("global call to %d, %d\n",new_scn, new_pt);
|
|
592 if (! ChangeScript(new_scn, new_pt)) return; // 読み込めない; abort.
|
|
593 cmd.clear();
|
|
594 } else if (cmd.cmd3 == 0x65) { // 文字列の返り値をセットする
|
|
595 int arg1 = cmd.args[0].value;
|
|
596 string s = cmd.Str(cmd.args[1]);
|
|
597 int sp = stack_strbuffer.size();
|
|
598 stack.push_back(StackItem(SCN_INFO_RETSTR+arg1, sp));
|
|
599 stack_strbuffer.push_back(s);
|
|
600 cmd.clear();
|
|
601 } else if (cmd.cmd3 == 0x0d || cmd.cmd3 == 0x0a || cmd.cmd3 == 0x11 || cmd.cmd3 == 0x13) { // return (0a: local return) (0x13はよくわからない)
|
|
602 // fprintf(stderr,"global return : stack size %d\n",stack.size());
|
|
603 if (stack.empty()) {
|
|
604 cmd.clear();
|
|
605 return; // スタックがおかしい:abort
|
|
606 }
|
|
607 map<int, string> retstr;
|
|
608 while( (!stack.empty()) && stack.back().scn_number >= SCN_INFO_RETSTR) {
|
|
609 int ret_num = stack.back().scn_number - SCN_INFO_RETSTR;
|
|
610 // fprintf(stderr,"\nRetStr;");
|
|
611 string str = stack_strbuffer.back();
|
|
612 stack_strbuffer.pop_back();
|
|
613 retstr[ret_num] = str;
|
|
614 stack.pop_back();
|
|
615 }
|
|
616 if (stack.empty()) {
|
|
617 cmd.clear();
|
|
618 return; // スタックがおかしい:abort
|
|
619 }
|
|
620 StackItem s = stack.back();
|
|
621 stack.pop_back();
|
|
622 bool localvar_init = false;
|
|
623 while( (!stack.empty()) && stack.back().scn_number == SCN_INFO) {
|
|
624 int mode = stack.back().scn_pt;
|
|
625 stack.pop_back();
|
|
626 if (mode == SCN_INFO_MENU) {
|
|
627 // fprintf(stderr,"\nInfo Menu;");
|
|
628 // menu モード終了
|
|
629 SetSkipMode(SkipMode(skip_mode & (~SKIP_IN_MENU) ));
|
|
630 } else if (mode >= SCN_INFO_LOCALS && mode <= SCN_INFO_LOCALS+50) {
|
|
631 // fprintf(stderr,"\nInfo Local;");
|
|
632 int i;
|
|
633 // ローカル変数を元に戻す
|
|
634 VarInfo var;
|
|
635 var.type = 11;
|
|
636 var.number = 0;
|
|
637 for (i=0; i<40; i++) {
|
|
638 var.number = i;
|
|
639 flag.Set(var, 0);
|
|
640 }
|
|
641 var.type = TYPE_VARLOCSTR;
|
|
642 for (i=0; i<3; i++) {
|
|
643 var.number = i;
|
|
644 flag.SetStr(var, "");
|
|
645 }
|
|
646 int args = mode - SCN_INFO_LOCALS;
|
|
647 // fprintf(stderr," args = %d; ",args);
|
|
648 for (i=0; i<args; i++) {
|
|
649 if (stack.empty() || stack.back().scn_number < SCN_INFO) {
|
|
650 fprintf(stderr,"Fatal : Invalid stack found in preserved local variables!\n");
|
|
651 break;
|
|
652 }
|
|
653 var.number = stack.back().scn_number;
|
|
654 // fprintf(stderr,"%d:%d; ",stack.back().scn_number,stack.back().scn_pt);
|
|
655 if (var.number >= SCN_INFO_LOCALS && var.number < SCN_INFO_LOCALSTR) {
|
|
656 var.type = 11;
|
|
657 var.number -= SCN_INFO_LOCALS;
|
|
658 flag.Set(var, stack.back().scn_pt);
|
|
659 } else if (var.number >= SCN_INFO_LOCALSTR && var.number < SCN_INFO_RETSTR) {
|
|
660 var.type = TYPE_VARLOCSTR;
|
|
661 var.number -= SCN_INFO_LOCALSTR;
|
|
662 flag.SetStr(var, stack_strbuffer.back());
|
|
663 stack_strbuffer.pop_back();
|
|
664 }
|
|
665 stack.pop_back();
|
|
666 }
|
|
667 }
|
|
668 // fprintf(stderr,"stack size %d string size %d\n",stack.size(),stack_strbuffer.size());
|
|
669 }
|
|
670 if (cmd.cmd3 == 0x11 || cmd.cmd3 == 0x13) {
|
|
671 // fprintf(stderr,"\nSet RetLocal;");
|
|
672 // 返り値をセットする
|
|
673 map<int,string>::iterator it;
|
|
674 VarInfo var;
|
|
675 var.type = TYPE_VARLOCSTR;
|
|
676 for (it=retstr.begin(); it!=retstr.end(); it++) {
|
|
677 var.number = it->first;
|
|
678 flag.SetStr(var, it->second);
|
|
679 }
|
|
680 var.type = 11;
|
|
681 // fprintf(stderr,"return : cmd.cmd3 == 0x11; size %d\n",cmd.args.size());
|
|
682 if (cmd.args.size() == 1) {
|
|
683 // fprintf(stderr,"return value %d\n",cmd.args[0].value);
|
|
684 flag.SetSys(cmd.args[0].value);
|
|
685 } else {
|
|
686 int i;for (i=0; i<cmd.args.size(); i++) {
|
|
687 var.number = i;
|
|
688 flag.Set(var, cmd.args[i].value);
|
|
689 }
|
|
690 }
|
|
691 }
|
|
692 // fprintf(stderr,"global return : return to %d:%d\n",s.scn_number,s.scn_pt);
|
|
693 // fprintf(stderr,"\nglobal return %d:%d from %d:%d\n",s.scn_number,s.scn_pt,scn_number, script - script_start);
|
|
694 if (s.scn_number != -1) {
|
|
695 if (! ChangeScript(s.scn_number, 0)) return; // 読み込めない; abort.
|
|
696 }
|
|
697 script = script_start + s.scn_pt;
|
|
698 cmd.clear();
|
|
699 }
|
|
700 } else if (cmd.cmd1 == 2 && cmd.cmd2 == 1 && cmd.cmd3 == 12) { // DLL Call
|
|
701 const char* regname = config.GetParaStr("#REGNAME");
|
|
702 const char key_lb[] = "KEY\\LittleBusters";
|
|
703 if (strcmp(regname, key_lb) == 0) {
|
|
704 DllCall_LB(cmd, flag);
|
|
705 cmd.clear();
|
|
706 }
|
|
707 } else if (cmd.cmd1 == 0 && cmd.cmd2 == 0x04) { // メニューモード
|
|
708 if (cmd.cmd3 == 300 || cmd.cmd3 == 301 || cmd.cmd3 == 302) {
|
|
709 // メニューからのreturn
|
|
710 cmd.cmd2 = 1;
|
|
711 cmd.cmd3 = 0x0d;
|
|
712 SysExec(cmd);
|
|
713 }
|
|
714 } else if (cmd.cmd1 == 1 && cmd.cmd2 == 0x04) {
|
|
715 if (cmd.cmd3 == 0 && cmd.cmd4 == 0) { // タイトル名設定
|
|
716 const char* name = cmd.Str(cmd.args[0]);
|
|
717 if (name == 0) name = "";
|
|
718 window_title = name;
|
|
719 const char* config_name = config.GetParaStr("#CAPTION");
|
|
720 if (config_name == 0) config_name = "";
|
|
721 string setname = kconv(string(config_name) + " " + window_title);
|
|
722 parent.Root().SetWindowCaption(setname.c_str());
|
|
723 cmd.clear();
|
|
724 } else if (cmd.cmd3 == 0x82 && cmd.cmd4 == 0) {
|
|
725 /* cmd.cmd3 == 0x82 : マウスの press 状態クリアかも */
|
|
726 event.presscount(MOUSE_LEFT);
|
|
727 event.presscount(MOUSE_RIGHT);
|
|
728 cmd.clear();
|
|
729 } else if (cmd.cmd3 == 0x85 && cmd.cmd4 == 0) {
|
|
730 int x,y,left,right;
|
|
731 event.MousePos(x,y);
|
|
732 if (event.presscount(MOUSE_LEFT)) left = 2;
|
|
733 else if (event.pressed(MOUSE_LEFT)) left = 1;
|
|
734 else left = 0;
|
|
735
|
|
736 if (event.presscount(MOUSE_RIGHT)) right = 2;
|
|
737 else if (event.pressed(MOUSE_RIGHT)) right = 1;
|
|
738 else right = 0;
|
|
739
|
|
740 // eprintf("mouse pos\n");
|
|
741 flag.Set(cmd.args[0], x);
|
|
742 flag.Set(cmd.args[1], y);
|
|
743 flag.Set(cmd.args[2], left);
|
|
744 flag.Set(cmd.args[3], right);
|
|
745 cmd.clear();
|
|
746 } else if (cmd.cmd3 == 0x15e || cmd.cmd3 == 0x161 || cmd.cmd3 == 0x162 || cmd.cmd3 == 0x14c || cmd.cmd3 == 0x7d1) {
|
|
747 /* 15e, 161, 162, 14c, 7d1 : なんらかのシステム情報を返す(skip modeなど?) */
|
|
748 /* 7d1: == 1 || 14c: == 1 || (15e==1&&161==1&&162==0) || (press_val == 2) : スキップ中? タイトル画面のアニメーション終了 */
|
|
749 flag.SetSys(0);
|
|
750 cmd.clear();
|
|
751 } else if (cmd.cmd3 == 0x4b0) { // 終了
|
|
752 System::Main::Quit();
|
|
753 script = 0; script_start = 0; script_end = 0;
|
|
754 cmd.clear();
|
|
755 cmd.cmd_type = CMD_WAITFRAMEUPDATE;
|
|
756 } else if (cmd.cmd3 == 0x4b4 || cmd.cmd3 == 0x4b5) { // 選択肢巻き戻し
|
|
757 LoadRollback(cmd);
|
|
758 } else if (cmd.cmd3 == 0x58d) {
|
|
759 // 前にロード|セーブされた番号を返す。
|
|
760 flag.SetSys(-1);
|
|
761 } else if (cmd.cmd3 == 0x585) {
|
|
762 // 第一引数の記録された日付、タイトルなどが返される
|
|
763 // データがないなら sys に 0が、あるなら 1 が返る
|
|
764 int y,m,d,wd,h,min,s,ms;
|
|
765 string title;
|
|
766 fprintf(stderr,"StatSave %d:",cmd.args[0].value+1);
|
|
767 if (StatSaveFile(cmd.args[0].value+1,y,m,d,wd,h,min,s,ms,title) == true) {
|
|
768 flag.Set(cmd.args[1], y);
|
|
769 flag.Set(cmd.args[2], m);
|
|
770 flag.Set(cmd.args[3], d);
|
|
771 flag.Set(cmd.args[4], wd);
|
|
772 flag.Set(cmd.args[5], h);
|
|
773 flag.Set(cmd.args[6], min);
|
|
774 flag.Set(cmd.args[7], s);
|
|
775 flag.Set(cmd.args[8], ms);
|
|
776 if (cmd.args[9].type == TYPE_VARSTR) {
|
|
777 flag.SetStr(cmd.args[9].number, kconv_rev(title));
|
|
778 }
|
|
779 flag.SetSys(1);
|
|
780 } else {
|
|
781 flag.SetSys(0);
|
|
782 }
|
|
783 cmd.clear();
|
|
784 } else if (cmd.cmd3 == 0xc23) { // save
|
|
785 Save(cmd);
|
|
786 } else if (cmd.cmd3 == 0xc25) { // load
|
|
787 Load(cmd);
|
|
788 } else if (cmd.cmd3 == 0x4b1 || cmd.cmd3 == 0x4b3) { // menu へ戻る (4b3: バッドエンド)
|
|
789 int scn_start;
|
|
790 if (config.GetParam("#SEEN_MENU", 1, &scn_start) == 0) {
|
|
791 ChangeScript(scn_start, 0);
|
|
792 save_scn = 0;
|
|
793 save_point = 0;
|
|
794 window_title = "";
|
|
795 const char* window_title_config = config.GetParaStr("#CAPTION");
|
|
796 if (window_title_config) window_title = window_title_config;
|
|
797 parent.Root().SetWindowCaption(kconv(window_title).c_str());
|
|
798 stack.clear();
|
|
799 cmd_stack.clear();
|
|
800 cmd_stack_str = cmd_stack_str_orig;
|
|
801 flag.Load("");
|
|
802 text_exec.Load("");
|
|
803 grp_exec.Load("");
|
|
804 SetSkipMode(SKIP_NO);
|
|
805 }
|
|
806 } else if (cmd.cmd3 == 0xcc) {
|
|
807 eprintf("show mouse cursor\n");
|
|
808 ShowCursor();
|
|
809 cmd.clear();
|
|
810 } else if (cmd.cmd3 == 0xcd) {
|
|
811 eprintf("hide mouse cursor\n");
|
|
812 HideCursor();
|
|
813 cmd.clear();
|
|
814 } else if (cmd.cmd3 == 0xcf) {
|
|
815 mouse_type = cmd.args[0].value;
|
|
816 eprintf("change mouse cursor : %d\n", mouse_type);
|
|
817 if (mouse_surface) ShowCursor();
|
|
818 cmd.clear();
|
|
819 }
|
|
820 }
|
|
821
|
|
822 }
|
|
823
|
|
824 #include<sys/types.h>
|
|
825 #include<sys/stat.h>
|
|
826 #include<errno.h>
|
|
827 #include<unistd.h>
|
|
828
|
|
829 // セーブファイルの名前をつくる
|
|
830 string Scn2k::MakeSaveFile(void) const {
|
|
831 struct stat sstatus;
|
|
832 string dir = "~/.xkanon";
|
|
833
|
|
834 if (dir.c_str()[0] == '~' && dir.c_str()[1] == '/') {
|
|
835 char* home = getenv("HOME");
|
|
836 if (home != 0) {
|
|
837 string new_dir = string(home) + (dir.c_str()+1);
|
|
838 dir = new_dir;
|
|
839 }
|
|
840 }
|
|
841 // savepathにファイル名が入っていれば、それをセーブファイルとして使う
|
|
842 if (stat(dir.c_str(), &sstatus) == -1) {
|
|
843 if (errno != ENOENT) {
|
|
844 fprintf(stderr,"Cannot open save file; dir %s is not directory\n",dir.c_str());
|
|
845 return "";
|
|
846 }
|
|
847 if (mkdir(dir.c_str(), S_IRWXU) != 0 && errno != EEXIST) {
|
|
848 fprintf(stderr, "Cannot create directory %s ; Please create manually!!\n",dir.c_str());
|
|
849 }
|
|
850 } else {
|
|
851 if ( (sstatus.st_mode & S_IFMT) == S_IFREG) {
|
|
852 return dir;
|
|
853 }
|
|
854 }
|
|
855 // ファイル名を作る
|
|
856 const char* regname = config.GetParaStr("#REGNAME");
|
|
857
|
|
858 char* fname = new char[strlen(regname)+1];
|
|
859 /* レジストリ名をファイル名として有効なものにする */
|
|
860 int i; for (i=0; regname[i]!=0; i++) {
|
|
861 char c = regname[i];
|
|
862 if (c == '\\' || c == '/' || c == ':' || c <= 0x20) c = '_';
|
|
863 fname[i] = tolower(c);
|
|
864 }
|
|
865 fname[i] = 0;
|
|
866 dir += "/save.";
|
|
867 dir += fname;
|
8
|
868 delete[] fname;
|
0
|
869 return dir;
|
|
870 }
|
|
871 // セーブファイルの名前をつくる
|
|
872 string Scn2kSaveTitle::operator() (int number) const {
|
|
873 int y,m,d,wd,h,min,sec,msec;
|
|
874 string title;
|
|
875 if (! impl.StatSaveFile(number, y,m,d,wd,h,min,sec,msec,title)) {
|
|
876 return "";
|
|
877 } else {
|
|
878 char buf[1024];
|
|
879 sprintf(buf, "%2d/%2d %2d:%2d ",m,d,h,min);
|
|
880 return string(buf) + title;
|
|
881 }
|
|
882 };
|
|
883
|
|
884 void Scn2k::SaveSys(void) {
|
|
885 char buf[1024];
|
|
886 string save;
|
|
887 string path = MakeSaveFile();
|
|
888
|
|
889 sprintf(buf, "KEY=%s\n", config.GetParaStr("#REGNAME")); save += buf;
|
|
890 string save_config;
|
|
891 config.DiffOriginal(save_config);
|
|
892 save += "CONFIG=";
|
|
893 save += save_config;
|
|
894 save += "\n";
|
|
895 string save_flag; flag.SaveSys(save_flag);
|
|
896 save += save_flag;
|
|
897 string save_grp; grp_exec.SaveSys(save_grp);
|
|
898 save += save_grp;
|
|
899 map<int,set<int> >::iterator it;
|
|
900 save += "[TextRead]\n";
|
|
901 for (it=text_readflag.begin(); it != text_readflag.end(); it++) {
|
|
902 set<int>& read_flag = it->second;
|
|
903 set<int>::iterator jt;
|
|
904 char buf[1024];
|
|
905 sprintf(buf,"T<%05d>=",it->first);
|
|
906 string save_readflag = buf;
|
|
907 for (jt=read_flag.begin(); jt != read_flag.end(); jt++) {
|
|
908 sprintf(buf, "%d,", *jt);
|
|
909 save_readflag += buf;
|
|
910 }
|
|
911 save_readflag += "\n";
|
|
912 save += save_readflag;
|
|
913 }
|
|
914
|
|
915 path += ".0";
|
|
916 FILE* f = fopen(path.c_str(), "w");
|
|
917 if (f == 0) {
|
|
918 fprintf(stderr,"Cannot open save file %s\n",path.c_str());
|
|
919 return;
|
|
920 }
|
|
921 fwrite(save.c_str(), save.length(), 1, f);
|
|
922 fclose(f);
|
|
923 return;
|
|
924 }
|
|
925
|
|
926 void Scn2k::LoadSys(void) {
|
|
927 char buf[1024];
|
|
928 string path = MakeSaveFile();
|
|
929 path += ".0";
|
|
930 FILE* f = fopen(path.c_str(), "r");
|
|
931 if (f == 0) {
|
|
932 fprintf(stderr, "Cannot open save file %s\n",path.c_str());
|
|
933 } else {
|
|
934 fseek(f,0,2);
|
|
935 int sz = ftell(f);
|
|
936 fseek(f,0,0);
|
|
937 char* savedata = new char[sz+1];
|
|
938 fread(savedata, sz, 1, f);
|
|
939 savedata[sz] = 0;
|
|
940 fclose(f);
|
|
941
|
|
942 sprintf(buf, "KEY=%s\n", config.GetParaStr("#REGNAME"));
|
|
943 if (strncmp(savedata, buf, strlen(buf)) != 0) {
|
|
944 fprintf(stderr,"Invalid header in save file %s: it must be started with \"%s\"\n",buf);
|
|
945 } else {
|
|
946 char* config_str = strstr(savedata, "\nCONFIG=");
|
|
947 if (config_str) {
|
|
948 config_str += strlen("\nCONFIG=");
|
|
949 char* strend = strchr(config_str, '\n');
|
|
950 if (strend) {
|
|
951 int l = strend - config_str;
|
|
952 char* config_copy = new char[l+1];
|
|
953 strncpy(config_copy, config_str, l);
|
|
954 config_copy[l] = 0;
|
|
955 config.PatchOriginal(config_copy);
|
|
956 delete[] config_copy;
|
|
957 }
|
|
958 }
|
|
959 flag.LoadSys(savedata);
|
|
960 grp_exec.LoadSys(savedata);
|
|
961 char* save = strstr(savedata, "\n[TextRead]\n");
|
|
962 if (save) {
|
|
963 save += strlen("\n[TextRead]\n");
|
|
964 do {
|
|
965 if (save[0] == '[') break; // next section
|
|
966 char* next_save = strchr(save, '\n');
|
|
967 if (next_save) {
|
|
968 *next_save++ = 0;
|
|
969 }
|
|
970 // T<XXXXX>=YYY,YYY,YYY,...
|
|
971 if (strncmp(save,"T<",2) == 0) {
|
|
972 int scn_num = atoi(save+2);
|
|
973 set<int>& read_flag = text_readflag[scn_num];
|
|
974 save += strlen("T<XXXXX>=");
|
|
975 while(save && *save) {
|
|
976 if (save[0] >= '0' && save[0] <= '9') {
|
|
977 int num = atoi(save);
|
|
978 read_flag.insert(num);
|
|
979 }
|
|
980 save = strchr(save, ',');
|
|
981 if (save) save++;
|
|
982 }
|
|
983 }
|
|
984 save = next_save;
|
|
985 } while(save);
|
|
986 }
|
|
987
|
|
988 }
|
|
989 delete[] savedata;
|
|
990 }
|
|
991
|
|
992 /* 初期化 */
|
|
993 int scn_start; config.GetParam("#SEEN_START", 1, &scn_start);
|
|
994 ChangeScript(scn_start, 0);
|
|
995 save_scn = 0;
|
|
996 save_point = 0;
|
|
997 window_title = "";
|
|
998 const char* window_title_config = config.GetParaStr("#CAPTION");
|
|
999 if (window_title_config) window_title = window_title_config;
|
|
1000 parent.Root().SetWindowCaption(kconv(window_title).c_str());
|
|
1001 stack.clear();
|
|
1002 cmd_stack.clear();
|
|
1003 cmd_stack_str = cmd_stack_str_orig;
|
|
1004
|
|
1005 return;
|
|
1006 }
|
|
1007
|
|
1008 bool Scn2k::StatSaveFile(int num, int& year, int& month, int& day, int& wday, int& hour,int& min, int& sec, int& msec, string& title) const {
|
|
1009 char buf[1024];
|
|
1010 string path = MakeSaveFile();
|
|
1011 if (num <= 0 || num > 99) return false;
|
|
1012 sprintf(buf,".%d",num);
|
|
1013 path += buf;
|
|
1014
|
|
1015 struct stat sb;
|
|
1016 if (stat(path.c_str(), &sb) == -1) return false;
|
|
1017 struct tm* t = localtime(&sb.st_mtime);
|
|
1018 month = t->tm_mon + 1;
|
|
1019 day = t->tm_mday;
|
|
1020 hour = t->tm_hour;
|
|
1021 min = t->tm_min;
|
|
1022 /* タイトルの取得 */
|
|
1023 FILE* savefile = fopen(path.c_str(), "rb");
|
|
1024 if (savefile == 0) return false;
|
|
1025 char regname[1024];
|
|
1026 sprintf(regname, "KEY=%s\n", config.GetParaStr("#REGNAME"));
|
|
1027 fgets(buf,1000,savefile);
|
|
1028 if (strncmp(regname, buf, strlen(regname)) != 0) {
|
|
1029 fprintf(stderr,"invalid save file %s (registory name is not %s)\n",path.c_str(),regname);
|
|
1030 fclose(savefile);
|
|
1031 return false;
|
|
1032 }
|
|
1033 title="none";
|
|
1034 while(!feof(savefile)) {
|
|
1035 fgets(buf,1000,savefile);
|
|
1036 if (strncmp(buf,"Title=",6) == 0) {
|
|
1037 if (buf[strlen(buf)-2] == 0x0a) buf[strlen(buf)-2] = 0;
|
|
1038 if (strlen(buf) > 20) buf[20] = 0, buf[21] = 0;
|
|
1039 title = kconv(buf+6);
|
|
1040 break;
|
|
1041 }
|
|
1042 }
|
|
1043 fclose(savefile);
|
|
1044 return true;
|
|
1045 }
|
|
1046
|
|
1047 void Scn2k::SaveRollback(void) {
|
|
1048 fprintf(stderr,"Save rollback\n");
|
|
1049 new_rollback_save = "";
|
|
1050 string save_sys; SaveImpl(save_sys);
|
|
1051 string save_flag; flag.Save(save_flag);
|
|
1052 string save_text; text_exec.Save(save_text, true);
|
|
1053 string save_grp; grp_exec.Save(save_grp);
|
|
1054 new_rollback_save += save_sys;
|
|
1055 new_rollback_save += save_flag;
|
|
1056 new_rollback_save += save_text;
|
|
1057 new_rollback_save += save_grp;
|
|
1058 }
|
|
1059
|
|
1060 void Scn2k::LoadRollback(Cmd& cmd) {
|
|
1061 if (rollback_save.empty()) return;
|
|
1062 new_rollback_save = "";
|
|
1063 string savedata = rollback_save.back();
|
|
1064 rollback_save.pop_back();
|
|
1065 LoadImpl(savedata.c_str());
|
|
1066 flag.Load(savedata.c_str());
|
|
1067 text_exec.Load(savedata.c_str());
|
|
1068 grp_exec.Load(savedata.c_str());
|
|
1069
|
|
1070 /* 画面の回復など */
|
|
1071 SetSkipMode(SKIP_NO);
|
|
1072 vector<CmdSimplified>::iterator it;
|
|
1073 cmd.clear();
|
|
1074 for (it = cmd_stack.begin(); it != cmd_stack.end(); it++) {
|
|
1075 cmd.read(*it);
|
|
1076 cmd.cmd_type = CMD_OTHER;
|
|
1077 flag.Exec(cmd);
|
|
1078 text_exec.Exec(cmd);
|
|
1079 grp_exec.Exec(cmd);
|
|
1080 }
|
|
1081 cmd.clear();
|
|
1082 return;
|
|
1083 }
|
|
1084
|
|
1085 void Scn2k::Save(Cmd& cmd) {
|
|
1086 if (cmd.cmd_type == CMD_SAVEREQ) {
|
|
1087 if (menu == 0) {
|
|
1088 SetSkipMode(SKIP_IN_MENU); // テキストスキップ等はここで中断
|
|
1089 menu = new Scn2kMenu(Scn2kMenu::MENU_SAVE, *this, flag, text_exec, system_version);
|
|
1090 menu->InitPanel(event, parent);
|
|
1091 menu->InitTitle(Scn2kSaveTitle(*this));
|
|
1092 if (mouse_surface) menu_mouseshown = true;
|
|
1093 else menu_mouseshown = false;
|
|
1094 ShowCursor();
|
|
1095 return;
|
|
1096 }
|
|
1097 }
|
|
1098 char buf[1024];
|
|
1099 string save;
|
|
1100 FILE* f = 0;
|
|
1101 if (save_scn == 0) {
|
|
1102 fprintf(stderr,"Cannot decide save point\n");
|
|
1103 return; // セーブ位置が保存されてない
|
|
1104 }
|
|
1105 string path = MakeSaveFile();
|
|
1106 int file_number = 1;
|
|
1107 if (cmd.args.size() == 1)
|
|
1108 file_number = cmd.args[0].value + 1;
|
|
1109 if (file_number <= 0) {
|
|
1110 fprintf(stderr, "Cannot open save file %s\n",path.c_str());
|
|
1111 return;
|
|
1112 }
|
|
1113 sprintf(buf, ".%d",file_number);
|
|
1114 path += buf;
|
|
1115
|
|
1116 /* セーブファイル確認 */
|
|
1117
|
|
1118 sprintf(buf, "KEY=%s\n", config.GetParaStr("#REGNAME")); save += buf;
|
|
1119 string save_sys; SaveImpl(save_sys);
|
|
1120 string save_flag; flag.Save(save_flag);
|
|
1121 string save_text; text_exec.Save(save_text, false);
|
|
1122 string save_grp; grp_exec.Save(save_grp);
|
|
1123 save += save_sys;
|
|
1124 save += save_flag;
|
|
1125 save += save_text;
|
|
1126 save += save_grp;
|
|
1127 vector<string>::iterator it;
|
|
1128 for (it=rollback_save.begin(); it != rollback_save.end(); it++) {
|
|
1129 save += "[Rollback Data]\n";
|
|
1130 save += *it;
|
|
1131 save += "[Rollback End]\n";
|
|
1132 }
|
|
1133
|
|
1134 f = fopen(path.c_str(), "w");
|
|
1135 if (f == 0) {
|
|
1136 fprintf(stderr,"Cannot open save file %s\n",path.c_str());
|
|
1137 return;
|
|
1138 }
|
|
1139 fwrite(save.c_str(), save.length(), 1, f);
|
|
1140 fclose(f);
|
|
1141 cmd.clear();
|
|
1142 return;
|
|
1143 }
|
|
1144
|
|
1145 void Scn2k::Load(Cmd& cmd) {
|
|
1146 if (cmd.cmd_type == CMD_LOADREQ) {
|
|
1147 if (menu == 0) {
|
|
1148 menu = new Scn2kMenu(Scn2kMenu::MENU_LOAD, *this, flag, text_exec, system_version);
|
|
1149 menu->InitPanel(event, parent);
|
|
1150 menu->InitTitle(Scn2kSaveTitle(*this));
|
|
1151 SetSkipMode(SKIP_IN_MENU); // テキストスキップ等はここで中断
|
|
1152 if (mouse_surface) menu_mouseshown = true;
|
|
1153 else menu_mouseshown = false;
|
|
1154 ShowCursor();
|
|
1155 return;
|
|
1156 }
|
|
1157 }
|
|
1158 char buf[1024];
|
|
1159 string path = MakeSaveFile();
|
|
1160 int file_number = 1;
|
|
1161 if (cmd.args.size() == 1)
|
|
1162 file_number = cmd.args[0].value + 1;
|
|
1163 sprintf(buf, ".%d",file_number);
|
|
1164 path += buf;
|
|
1165 FILE* f = 0;
|
|
1166 if (file_number > 0) f = fopen(path.c_str(), "r");
|
|
1167 if (f == 0) {
|
|
1168 fprintf(stderr, "Cannot open save file %s\n",path.c_str());
|
|
1169 return;
|
|
1170 }
|
|
1171
|
|
1172 fseek(f,0,2);
|
|
1173 int sz = ftell(f);
|
|
1174 fseek(f,0,0);
|
|
1175 char* savedata = new char[sz+1];
|
|
1176 fread(savedata, sz, 1, f);
|
|
1177 savedata[sz] = 0;
|
|
1178 fclose(f);
|
|
1179
|
|
1180 sprintf(buf, "KEY=%s\n", config.GetParaStr("#REGNAME"));
|
|
1181 if (strncmp(savedata, buf, strlen(buf)) != 0) {
|
|
1182 fprintf(stderr,"Invalid header in save file %s: it must be started with \"%s\"\n",buf);
|
|
1183 delete[] savedata;
|
|
1184 return;
|
|
1185 }
|
|
1186 LoadImpl(savedata);
|
|
1187 flag.Load(savedata);
|
|
1188 text_exec.Load(savedata);
|
|
1189 grp_exec.Load(savedata);
|
|
1190 rollback_save.clear();
|
|
1191 new_rollback_save = "";
|
|
1192 char* rollback_data = savedata;
|
|
1193 while( (rollback_data = strstr(rollback_data,"[Rollback Data]\n")) != 0) {
|
|
1194 rollback_data += strlen("[Rollback Data]\n");
|
|
1195 char* rollback_end = strstr(rollback_data, "[Rollback End]\n");
|
|
1196 if (rollback_end == 0) rollback_end = rollback_data + strlen(rollback_data);
|
|
1197 string s(rollback_data, rollback_end);
|
|
1198 rollback_save.push_back(s);
|
|
1199 rollback_data = rollback_end;
|
|
1200 }
|
|
1201
|
|
1202 /* 画面の回復など */
|
|
1203 SetSkipMode(SKIP_NO);
|
|
1204 vector<CmdSimplified>::iterator it;
|
|
1205 for (it = cmd_stack.begin(); it != cmd_stack.end(); it++) {
|
|
1206 cmd.read(*it);
|
|
1207 cmd.cmd_type = CMD_OTHER;
|
|
1208 flag.Exec(cmd);
|
|
1209 text_exec.Exec(cmd);
|
|
1210 grp_exec.Exec(cmd);
|
|
1211 }
|
|
1212 cmd.clear();
|
|
1213 return;
|
|
1214 }
|
|
1215
|
|
1216 void Scn2k::SaveImpl(string& save) {
|
|
1217 char buf[1024];
|
|
1218
|
|
1219 /* save point */
|
|
1220 sprintf(buf, "\n[SCENARIO]\nScn=%d\nPoint=%d\n",save_scn, save_point); save += buf;
|
|
1221 sprintf(buf, "Title=%s\nMouseType=%d\nMouseShown=1\n",window_title.c_str(), mouse_type); save += buf;
|
|
1222 vector<StackItem>::iterator sit;
|
|
1223 for (sit=stack.begin(); sit!=stack.end(); sit++) {
|
|
1224 if (sit->scn_number == SCN_INFO && sit->scn_pt == SCN_INFO_MENU) break; // メニューに入る直前までのスタックを保存
|
|
1225 sprintf(buf, "Stack=%d,%d\n",sit->scn_number,sit->scn_pt);
|
|
1226 save += buf;
|
|
1227 }
|
|
1228 vector<string>::reverse_iterator ssit;
|
|
1229 for (ssit=stack_strbuffer.rbegin(); ssit != stack_strbuffer.rend(); ssit++) {
|
|
1230 sprintf(buf, "StackStr=%s\n",ssit->c_str());
|
|
1231 save += buf;
|
|
1232 }
|
|
1233 vector<CmdSimplified>::iterator cit;
|
|
1234 for (cit=cmd_stack.begin(); cit != cmd_stack.end(); cit++) {
|
|
1235 if (cit->type == CMD_SAVECMDGRP || cit->type == CMD_SAVECMDGRP_ONCE || cit->type == CMD_SAVECMDGRP_START) {
|
|
1236 save += "CmdG=";
|
|
1237 } else {
|
|
1238 save += "Cmd=";
|
|
1239 }
|
|
1240 string s; cit->Save(s);
|
|
1241 save += s;
|
|
1242 save += "\n";
|
|
1243 }
|
|
1244 }
|
|
1245
|
|
1246 void Scn2k::LoadImpl(const char* save) {
|
|
1247 char buf[1024];
|
|
1248 save_scn = 0;
|
|
1249 save_point = 0;
|
|
1250 window_title = "";
|
|
1251 stack.clear();
|
|
1252 cmd_stack.clear();
|
|
1253 cmd_stack_str = cmd_stack_str_orig;
|
|
1254
|
|
1255 save = strstr(save, "\n[SCENARIO]\n");
|
|
1256 if (save == 0) return;
|
|
1257 save += strlen("\n[SCENARIO]\n");
|
|
1258 while(save[0] != 0 && save[0] != '[') { // while next section start
|
|
1259 if (strncmp(save, "Scn=", 4) == 0) {
|
|
1260 sscanf(save, "Scn=%d", &save_scn);
|
|
1261 } else if (strncmp(save, "Point=", 6) == 0) {
|
|
1262 sscanf(save, "Point=%d", &save_point);
|
|
1263 } else if (strncmp(save, "Title=", 6) == 0) {
|
|
1264 save += 6;
|
|
1265 char* s = strchr(save, '\n');
|
|
1266 if (s == 0) window_title = save;
|
|
1267 else window_title.assign(save, s-save);
|
|
1268 const char* config_name = config.GetParaStr("#CAPTION");
|
|
1269 if (config_name == 0) config_name = "";
|
|
1270 string setname = kconv(string(config_name)+" "+window_title);
|
|
1271 parent.Root().SetWindowCaption(setname.c_str());
|
|
1272 } else if (strncmp(save, "MouseType=", 10) == 0) {
|
|
1273 sscanf(save, "MouseType=%d", &mouse_type);
|
|
1274 } else if (strncmp(save, "MouseShown=", 11) == 0) {
|
|
1275 int v;
|
|
1276 sscanf(save, "MouseShown=%d", &v);
|
|
1277 if (v) ShowCursor();
|
|
1278 else HideCursor();
|
|
1279 } else if (strncmp(save, "Stack=", 6) == 0) {
|
|
1280 int scn, pt;
|
|
1281 sscanf(save, "Stack=%d,%d", &scn, &pt);
|
|
1282 stack.push_back( StackItem(scn, pt));
|
|
1283 } else if (strncmp(save, "StackStr=", 9) == 0) {
|
|
1284 save += 9;
|
|
1285 char* s = strchr(save, '\n');
|
|
1286 if (s == 0) stack_strbuffer.push_back("");
|
|
1287 else stack_strbuffer.push_back(string(save, s-save));
|
|
1288 } else if (strncmp(save, "Cmd=", 4) == 0) {
|
|
1289 CmdSimplified cmd;
|
|
1290 cmd.Load(save+4, cmd_stack_str);
|
|
1291 cmd_stack.push_back(cmd);
|
|
1292 } else if (strncmp(save, "CmdG=", 5) == 0) {
|
|
1293 CmdSimplified cmd;
|
|
1294 cmd.Load(save+5, cmd_stack_str);
|
|
1295 cmd.type = CMD_SAVECMDGRP;
|
|
1296 cmd_stack.push_back(cmd);
|
|
1297 }
|
|
1298 save = strchr(save, '\n');
|
|
1299 if (save != 0) save++;
|
|
1300 }
|
|
1301 ChangeScript(save_scn, 0);
|
|
1302 script = script_start + save_point;
|
|
1303 return;
|
|
1304 }
|
|
1305 void Scn2k::SetSkipMode(SkipMode mode) {
|
|
1306 if (skip_mode != mode) {
|
|
1307 skip_mode = mode;
|
|
1308 text_exec.SetSkipMode(mode);
|
|
1309 grp_exec.SetSkipMode(mode);
|
|
1310 }
|
|
1311 }
|
|
1312
|
|
1313 /***********************************************************
|
|
1314 **
|
|
1315 ** DLL Call Implementation
|
|
1316 **
|
|
1317 **/
|
|
1318 static double* lb_ef_param = 0;
|
|
1319 void DLLCall_LB_EF00_0(Cmd& cmd, Flags& flags) { // エフェクトの設定
|
|
1320 if (lb_ef_param == 0) {
|
|
1321 lb_ef_param = new double[sizeof(double) * 0x60 * 8];
|
|
1322 }
|
|
1323 int i,j;
|
|
1324 int param_top, param_size;
|
|
1325 if (cmd.args[2].value == 1) {
|
|
1326 param_top = 0;
|
|
1327 param_size = 0x20;
|
|
1328 } else {
|
|
1329 param_top = cmd.args[3].value;
|
|
1330 param_size = cmd.args[4].value;
|
|
1331 if (param_top < 0) param_top = 0;
|
|
1332 if (param_top > 0x20) param_top = 0x20;
|
|
1333 if (param_size+param_top > 0x20) param_size = 0x20 - param_top;
|
|
1334 }
|
|
1335 for (i=0; i<8; i++) {
|
|
1336 double* param = lb_ef_param + i*0x60 + param_top*3;
|
|
1337 for (j=0; j<param_size; j++) {
|
|
1338 *param++ = random() % 800 - 400;
|
|
1339 *param++ = random() % 600 - 300;
|
|
1340 *param++ = random() % 700 - 350;
|
|
1341 }
|
|
1342 }
|
|
1343 if (cmd.args[5].value != 1) return;
|
|
1344 static int random_dirtable[] = {
|
|
1345 0, 2, 1, 3, 0, 2, 1, 3,
|
|
1346 1, 3, 2, 0, 1, 3, 2, 0,
|
|
1347 0, 0, 0, 0, 3, 1, 2, 0,
|
|
1348 3, 1, 3, 1, 0, 2, 3, 1
|
|
1349 };
|
|
1350 int* dir = &random_dirtable[(random()&3) * 8];
|
|
1351 for (i=0; i<8; i++) {
|
|
1352 double* param = lb_ef_param + i*0x60;
|
|
1353 double x = random()%600 - 300;
|
|
1354 double y = random()%480-240;
|
|
1355 if (x < 0) x -= 80;
|
|
1356 else x += 80;
|
|
1357 if (y < 0) y -= 80;
|
|
1358 else y += 80;
|
|
1359 switch(*dir++) {
|
|
1360 case 0:
|
|
1361 if (x < 0) x = -x;
|
|
1362 if (y < 0) y = -y;
|
|
1363 break;
|
|
1364 case 1:
|
|
1365 if (x > 0) x = -x;
|
|
1366 if (y < 0) y = -y;
|
|
1367 break;
|
|
1368 case 2:
|
|
1369 if (x < 0) x = -x;
|
|
1370 if (y > 0) y = -y;
|
|
1371 break;
|
|
1372 case 4:
|
|
1373 if (x > 0) x = -x;
|
|
1374 if (y > 0) y = -y;
|
|
1375 break;
|
|
1376 }
|
|
1377 param[9] = x*1.2;
|
|
1378 param[10] = y*1.2;
|
|
1379 param[11] *= 1.2;
|
|
1380 param[12] *= -0.08;
|
|
1381 param[13] *= -0.08;
|
|
1382 param[14] *= -0.08;
|
|
1383 param[15] = -param[9];
|
|
1384 param[16] = -param[10];
|
|
1385 param[17] = -param[11];
|
|
1386 }
|
|
1387 return;
|
|
1388 }
|
|
1389 void DLLCall_LB_EF00_1(Cmd& cmd, Flags& flags) { // 計算を行う
|
|
1390 if (lb_ef_param == 0) {
|
|
1391 fprintf(stderr,"Warning : DLLCall_LB_EF00_1 : Script error : effect calculation was called before setting\n");
|
|
1392 return;
|
|
1393 }
|
|
1394 int index = cmd.args[2].value;
|
|
1395 int v5_1154 = flags.Get(5, 1154+index);
|
|
1396 int j = ((v5_1154) & 0x1f) + index * 0x20;
|
|
1397 int k = ((v5_1154+1) & 0x1f) + index * 0x20;
|
|
1398 int l = ((v5_1154+2) & 0x1f) + index * 0x20;
|
|
1399 int m = ((v5_1154+3) & 0x1f) + index * 0x20;
|
|
1400 j *= 3;
|
|
1401 k *= 3;
|
|
1402 l *= 3;
|
|
1403 m *= 3;
|
|
1404
|
|
1405 // 0 < x < 1
|
|
1406 // va - vd は 0-1 の範囲で対称性を持つ3次関数
|
|
1407 double x = double(flags.Get(5, 1162 + index)) * 0.001;
|
|
1408 double va = (x * x * x)/6;
|
|
1409 double vb = (-x*x*x + 3*x*x - 3*x + 1) / 6;
|
|
1410 double vc = (3*x*x*x - 6*x*x + 4) / 6;
|
|
1411 double vd = (-3*x*x*x+3*x*x+3*x+1) / 6;
|
|
1412
|
|
1413 double r1 = va * lb_ef_param[m+3] + vd * lb_ef_param[l+3] + vc * lb_ef_param[k+3] + vb * lb_ef_param[j+3];
|
|
1414 double r2 = va * lb_ef_param[m+2] + vd * lb_ef_param[l+2] + vc * lb_ef_param[k+2] + vb * lb_ef_param[j+2];
|
|
1415 double r3 = va * lb_ef_param[m+1] + vd * lb_ef_param[l+1] + vc * lb_ef_param[k+1] + vb * lb_ef_param[j+1];
|
|
1416 if (r1 != 400) {
|
|
1417 r2 = r2 * 800 / (400-r1);
|
|
1418 r3 = r3 * 700 / (400-r1);
|
|
1419 }
|
|
1420 VarInfo var;
|
|
1421 var.type = 5;
|
|
1422 var.number = 1151;
|
|
1423 flags.Set(var, int(r2));
|
|
1424 var.number = 1152;
|
|
1425 flags.Set(var, int(r3));
|
|
1426 var.number = 1153;
|
|
1427 flags.Set(var, int(r1));
|
|
1428 return;
|
|
1429 }
|
|
1430
|
|
1431
|
|
1432 void DllCall_LB(Cmd& cmd, Flags& flags) { // リトルバスターズ!の EF00.dll をエミュレート
|
|
1433 if (cmd.args[0].value == 1) {
|
|
1434 // "EF00.dll"
|
|
1435 if (cmd.args[1].value == 0) { // エフェクトの設定
|
|
1436 DLLCall_LB_EF00_0(cmd, flags);
|
|
1437 } else if (cmd.args[1].value == 1) { // 計算を行う
|
|
1438 DLLCall_LB_EF00_1(cmd, flags);
|
|
1439 }
|
|
1440 } else {
|
|
1441 fprintf(stderr,"Unsupported DLL call for DLL<%d>\n",cmd.args[0].value);
|
|
1442 }
|
|
1443 return;
|
|
1444 }
|
|
1445
|
|
1446 /**********************************************************
|
|
1447 **
|
|
1448 ** MenuImpl
|
|
1449 **
|
|
1450 */
|
|
1451
|
|
1452 #include"window/widget.h"
|
|
1453 #include"window/menuitem.h"
|
|
1454
|
|
1455 void DSurfaceFill(Surface* src, const Rect& rect, int r, int g, int b, int a = 0xff);
|
|
1456
|
|
1457 struct Scn2kMenuImpl {
|
|
1458 Scn2kMenu& interface;
|
|
1459 MenuItem* menu;
|
|
1460 Event::Container* pevent;
|
|
1461 PicContainer* pparent;
|
|
1462
|
|
1463 virtual void InitPanel(Event::Container& event, PicContainer& parent) = 0;
|
|
1464 virtual void InitTitle(const SaveTitle&) = 0;
|
|
1465 virtual void Cancel(void) = 0;
|
|
1466 virtual void Exec(Cmd& cmd) = 0;
|
|
1467 Scn2kMenuImpl(Scn2kMenu& _interface) : interface(_interface) {
|
|
1468 menu = 0;
|
|
1469 pevent = 0;
|
|
1470 pparent = 0;
|
|
1471 }
|
|
1472 virtual ~Scn2kMenuImpl() {
|
|
1473 if (menu) delete menu;
|
|
1474 menu = 0;
|
|
1475 }
|
|
1476 };
|
|
1477
|
|
1478 struct LoadMenu : Scn2kMenuImpl {
|
|
1479 vector<string> title;
|
|
1480 vector<int> title_valid;
|
|
1481 RadioButton* btn_local;
|
|
1482 RadioButton* btn_page;
|
|
1483 RadioButton* btn_set;
|
|
1484 Scale* btn_scale;
|
|
1485 Dialog* awk_dialog;
|
|
1486 int btn_page_val, btn_set_val, btn_local_val, select_page, select_value;
|
|
1487 LoadMenu(Scn2kMenu& _interface);
|
|
1488 ~LoadMenu();
|
|
1489 void InitPanel(Event::Container& event, PicContainer& parent);
|
|
1490 void InitTitle(const SaveTitle&);
|
|
1491 void Cancel(void);
|
|
1492 void Exec(Cmd& cmd);
|
|
1493 static void ChangeBtnPage(void* pointer, MenuItem* widget);
|
|
1494 static void ChangeBtnLocal(void* pointer, MenuItem* widget);
|
|
1495 static void ChangeBtnScale(void* pointer, Scale* widget);
|
|
1496 static void ChangeBtnSet(void* pointer, MenuItem* widget);
|
|
1497 static void ChangeDialog(void* pointer, Dialog* widget);
|
|
1498 bool in_setpage;
|
|
1499 void SetPage(int new_page);
|
|
1500 void SetValue(int new_value);
|
|
1501 void PressOk(void);
|
|
1502 };
|
|
1503 LoadMenu::LoadMenu(Scn2kMenu& _interface) : Scn2kMenuImpl(_interface) {
|
|
1504 btn_local = 0;
|
|
1505 btn_scale = 0;
|
|
1506 btn_set = 0;
|
|
1507 btn_page_val = 0;
|
|
1508 btn_set_val = -1;
|
|
1509 btn_local_val = -1;
|
|
1510 awk_dialog = 0;
|
|
1511 in_setpage = false;
|
|
1512 select_page = 0;
|
|
1513 select_value = -1;
|
|
1514 }
|
|
1515 LoadMenu::~LoadMenu() {
|
|
1516 if (awk_dialog) delete awk_dialog;
|
|
1517 }
|
|
1518 void LoadMenu::InitPanel(Event::Container& event, PicContainer& parent) {
|
|
1519 pevent = &event;
|
|
1520 pparent = &parent;
|
|
1521
|
|
1522 if (menu) delete menu;
|
|
1523 menu = 0;
|
|
1524 menu = new MenuItem(&parent, Rect(80,30,560, 450), 1, 3, 0);
|
|
1525 Surface* surface = parent.Root().NewSurface(menu->Pic()->Width(), menu->Pic()->Height(), ALPHA_MASK);
|
|
1526 if (interface.type == Scn2kMenu::MENU_LOAD) {
|
|
1527 menu->SetLabelTop(new Label(menu->PicNode(), Rect(0,0), true, "Load", 26), Rect(0,0,10,0), Rect(0,0,0,20));
|
|
1528 DSurfaceFill(surface, Rect(*surface), 0, 0, 0x80, 0x80);
|
|
1529 } else {
|
|
1530 menu->SetLabelTop(new Label(menu->PicNode(), Rect(0,0), true, "Save", 26), Rect(0,0,10,0), Rect(0,0,0,20));
|
|
1531 DSurfaceFill(surface, Rect(*surface), 0, 0x80, 0, 0x80);
|
|
1532 }
|
|
1533 menu->Pic()->SetSurface(surface, 0, 0);
|
|
1534 menu->Pic()->SetSurfaceFreeFlag();
|
|
1535
|
|
1536 btn_page = new RadioButton(event, menu->PicNode(), Rect(0, 0, 480, 40), 10, 1, &btn_page_val,
|
|
1537 Rect(0,0,0,0), 18, Color(0,0,0),Color(0xff,0,0),Color(0xff,0x80,0));
|
|
1538 btn_page->set_func = &ChangeBtnPage;
|
|
1539 btn_page->set_pointer = this;
|
|
1540 btn_page->SetLabelLeft(new Label(btn_page->PicNode(), Rect(0,0), true, "Page", 18), Rect(0, 0, 180, 0), Rect(0,0));
|
|
1541 btn_page->Add(" 1 ");
|
|
1542 btn_page->Add(" 2 ");
|
|
1543 btn_page->Add(" 3 ");
|
|
1544 btn_page->Add(" 4 ");
|
|
1545 btn_page->Add(" 5 ");
|
|
1546 btn_page->Add(" 6 ");
|
|
1547 btn_page->Add(" 7 ");
|
|
1548 btn_page->Add(" 8 ");
|
|
1549 btn_page->Add(" 9 ");
|
|
1550 btn_page->Add(" 10 ");
|
|
1551 btn_page->pack();
|
|
1552 /*
|
|
1553 surface = parent.Root().NewSurface(btn_page->Pic()->Width(), btn_page->Pic()->Height(), ALPHA_MASK);
|
|
1554 DSurfaceFill(surface, Rect(*surface), 0xff, 0, 0, 0x80);
|
|
1555 btn_page->Pic()->SetSurface(surface, 0, 0);
|
|
1556 btn_page->Pic()->SetSurfaceFreeFlag();
|
|
1557 */
|
|
1558 menu->item[0] = btn_page;
|
|
1559 btn_set = new RadioButton(event, menu->PicNode(), Rect(0, 0, 480, 40), 2, 1, &btn_set_val,
|
|
1560 Rect(0,0,0,0), 18, Color(0,0,0),Color(0xff,0,0),Color(0xff,0x80,0));
|
|
1561 btn_set->set_func = &ChangeBtnSet;
|
|
1562 btn_set->set_pointer = this;
|
|
1563 btn_set->SetLabelLeft(new Label(btn_set->PicNode(), Rect(0,0)), Rect(0,0,200,0), Rect(0,0));
|
|
1564 if (interface.type == Scn2kMenu::MENU_LOAD) {
|
|
1565 btn_set->Add(" Load ");
|
|
1566 } else {
|
|
1567 btn_set->Add(" Save ");
|
|
1568 }
|
|
1569 btn_set->Add(" Cancel ");
|
|
1570 btn_set->pack();
|
|
1571 /*
|
|
1572 surface = parent.Root().NewSurface(btn_set->Pic()->Width(), btn_set->Pic()->Height(), ALPHA_MASK);
|
|
1573 DSurfaceFill(surface, Rect(*surface), 0, 0, 0xff, 0x80);
|
|
1574 btn_set->Pic()->SetSurface(surface, 0, 0);
|
|
1575 btn_set->Pic()->SetSurfaceFreeFlag();
|
|
1576 */
|
|
1577 menu->item[2] = btn_set;
|
|
1578 // void btn_set_press(void* pointer, MenuItem* widget);
|
|
1579 // btn_set->set_func = btn_set_press;
|
|
1580 // btn_set->set_pointer = this;
|
|
1581 btn_local = new RadioButton(*pevent, menu->PicNode(), Rect(0, 0, 480, 300), 1, 100, &btn_local_val,
|
|
1582 Rect(0,0,300,30), 18, Color(0,0,0),Color(0xff,0,0),Color(0xff,0x80,0));
|
|
1583 btn_local->set_func = &ChangeBtnLocal;
|
|
1584 btn_local->set_pointer = this;
|
|
1585 /*
|
|
1586 surface = pparent->Root().NewSurface(btn_local->Pic()->Width(), btn_local->Pic()->Height(), ALPHA_MASK);
|
|
1587 DSurfaceFill(surface, Rect(*surface), 0, 0xff, 0, 0x80);
|
|
1588 btn_local->Pic()->SetSurface(surface, 0, 0);
|
|
1589 btn_local->Pic()->SetSurfaceFreeFlag();
|
|
1590 */
|
|
1591 menu->item[1] = btn_local;
|
|
1592 int i;
|
|
1593 for (i=0; i<12; i++)
|
|
1594 btn_local->Add("",false);
|
|
1595 btn_local->pack();
|
|
1596 btn_local->show_all();
|
|
1597 menu->pack();
|
|
1598
|
|
1599 PicBase* local_pic = btn_local->Pic();
|
|
1600 int local_x2 = local_pic->PosX() + local_pic->Width();
|
|
1601 int local_y2 = local_pic->PosY() + local_pic->Height();
|
|
1602 btn_scale = new Scale(*pevent, menu->PicNode(), Rect(local_x2-16, local_pic->PosY(), local_x2, local_y2), Color(0xff, 0x80, 0), true);
|
|
1603 btn_scale->SetRange(0, 900);
|
|
1604 btn_scale->InitCursor(1024/10);
|
|
1605 btn_scale->SetValue(0);
|
|
1606 btn_scale->change_func = &ChangeBtnScale;
|
|
1607 btn_scale->change_pointer = this;
|
|
1608
|
|
1609 menu->PicNode()->show_all();
|
|
1610 }
|
|
1611
|
|
1612 void LoadMenu::InitTitle(const SaveTitle& title_op) {
|
|
1613 title.clear();
|
|
1614 int i;
|
|
1615 for (i=1; i<=100; i++) {
|
|
1616 char buf[100];
|
|
1617 sprintf(buf,"%2d:",i);
|
|
1618 string t = title_op(i);
|
|
1619 string s = string(buf) + t;
|
|
1620 if (t.length() == 0) {
|
|
1621 string s = string(buf) + "--------";
|
|
1622 title_valid.push_back(0);
|
|
1623 } else {
|
|
1624 title_valid.push_back(1);
|
|
1625 }
|
|
1626 title.push_back(s);
|
|
1627 }
|
|
1628 if (btn_local==0) return;
|
|
1629 for (i=0; i<10; i++) {
|
|
1630 TextButton* button = dynamic_cast<TextButton*>(btn_local->item[i]);
|
|
1631 if (button) button->SetText(title[i].c_str());
|
|
1632 }
|
|
1633 }
|
|
1634
|
|
1635 void LoadMenu::SetPage(int new_page) {
|
|
1636 if (new_page < 0) new_page = 0;
|
|
1637 if (new_page > 900) new_page = 900;
|
|
1638 if (select_page == new_page) return;
|
|
1639 if (in_setpage) return;
|
|
1640 in_setpage = true;
|
|
1641
|
|
1642 int prev_page = select_page / 10;
|
|
1643 int cur_page = new_page / 10;
|
|
1644 int prev_point = select_page%10;
|
|
1645 int new_point = new_page%10;
|
|
1646 select_page = new_page;
|
|
1647 if (prev_page != cur_page) {
|
|
1648 int i;
|
|
1649 for (i=0; i<12; i++) {
|
|
1650 TextButton* button = dynamic_cast<TextButton*>(btn_local->item[i]);
|
|
1651 if (button) {
|
|
1652 if (cur_page+i < title.size()) button->SetText(title[cur_page+i].c_str());
|
|
1653 else button->SetText("----");
|
|
1654 }
|
|
1655 }
|
|
1656 // ボタンの内容を変更する
|
|
1657 if (select_value < cur_page || select_value > cur_page+12)
|
|
1658 btn_local->SetValue(-1);
|
|
1659 else
|
|
1660 btn_local->SetValue(select_value - cur_page);
|
|
1661 }
|
|
1662 if (prev_point != new_point) {
|
|
1663 int i;
|
|
1664 for (i=0; i<12; i++) {
|
|
1665 int old_x = btn_local->item[i]->Pic()->PosX();
|
|
1666 btn_local->item[i]->Pic()->Move(old_x, i*30-new_point*3);
|
|
1667 }
|
|
1668 }
|
|
1669 if (btn_page) {
|
|
1670 if (select_page%100 == 0) btn_page->SetValue(select_page/100);
|
|
1671 else btn_page->SetValue(-1);
|
|
1672 }
|
|
1673 if (btn_scale) {
|
|
1674 btn_scale->SetValue(select_page);
|
|
1675 }
|
|
1676 in_setpage = false;
|
|
1677 return;
|
|
1678 }
|
|
1679 void LoadMenu::SetValue(int new_value) {
|
|
1680 if (in_setpage) return;
|
|
1681 in_setpage = true;
|
|
1682
|
|
1683 if (new_value < 0 || new_value > title.size() ||
|
|
1684 (interface.type == Scn2kMenu::MENU_LOAD && title_valid[new_value] == 0) ) { // 無効な選択肢
|
|
1685 if (select_value < select_page/10 || select_value > select_page/10+12)
|
|
1686 btn_local->SetValue(-1);
|
|
1687 else
|
|
1688 btn_local->SetValue(select_value-select_page/10);
|
|
1689 } else { // 選択肢を変更する
|
|
1690 if (select_value == new_value) {
|
|
1691 PressOk(); // ダブルクリック
|
|
1692 } else {
|
|
1693 select_value = new_value;
|
|
1694 if (interface.type == Scn2kMenu::MENU_SAVE && title_valid[select_value] == 0) {
|
|
1695 PressOk(); // 新しいセーブデータなら無条件に選択
|
|
1696 }
|
|
1697 }
|
|
1698 }
|
|
1699
|
|
1700 in_setpage = false;
|
|
1701 return;
|
|
1702 }
|
|
1703 void LoadMenu::PressOk(void) {
|
|
1704 if (select_value == -1) {
|
|
1705 btn_set->SetValue(-1); // なにもしない
|
|
1706 return;
|
|
1707 }
|
|
1708 menu->deactivate();
|
|
1709 if (interface.type == Scn2kMenu::MENU_LOAD) {
|
|
1710 interface.cmd.cmd_type = CMD_LOAD;
|
|
1711 interface.cmd.args.push_back(VarInfo(select_value));
|
|
1712 awk_dialog = new Dialog(*pevent, pparent, "ファイルをロードしますか?", true);
|
|
1713 awk_dialog->set_pointer = this;
|
|
1714 awk_dialog->set_func = ChangeDialog;
|
|
1715 } else {// MENU_SAVE
|
|
1716 interface.cmd.cmd_type = CMD_SAVE;
|
|
1717 interface.cmd.args.push_back(VarInfo(select_value));
|
|
1718 if (title_valid[select_value] == 0) { // 新しいセーブデータ
|
|
1719 interface.status = Scn2kMenu::MenuStatus(Scn2kMenu::MENU_CMD | Scn2kMenu::MENU_DELETE);
|
|
1720 } else { // セーブデータを上書き:確認
|
|
1721 awk_dialog = new Dialog(*pevent, pparent, "データを上書きしますか?", true);
|
|
1722 awk_dialog->set_pointer = this;
|
|
1723 awk_dialog->set_func = ChangeDialog;
|
|
1724 }
|
|
1725 }
|
|
1726 }
|
|
1727 void LoadMenu::Cancel(void) {
|
|
1728 if (awk_dialog) { // ダイアログのキャンセル
|
|
1729 awk_dialog->status = Dialog::CANCEL;
|
|
1730 ChangeDialog(this, awk_dialog);
|
|
1731 } else { // 一般キャンセル
|
|
1732 btn_set->SetValue(1);
|
|
1733 }
|
|
1734 }
|
|
1735 void LoadMenu::Exec(Cmd& cmd) {
|
|
1736 }
|
|
1737 void LoadMenu::ChangeBtnPage(void* pointer, MenuItem* widget) {
|
|
1738 LoadMenu* instance = (LoadMenu*)pointer;
|
|
1739 if (instance->btn_page_val == -1) return;
|
|
1740 instance->SetPage(instance->btn_page_val*100);
|
|
1741 }
|
|
1742 void LoadMenu::ChangeBtnScale(void* pointer, Scale* from) {
|
|
1743 LoadMenu* instance = (LoadMenu*)pointer;
|
|
1744 int value = from->GetValue();
|
|
1745 instance->SetPage(value);
|
|
1746 }
|
|
1747 void LoadMenu::ChangeBtnSet(void* pointer, MenuItem* widget) {
|
|
1748 LoadMenu* instance = (LoadMenu*)pointer;
|
|
1749 if (instance->btn_set_val == 1) { // cancel
|
|
1750 instance->interface.status = Scn2kMenu::MENU_DELETE;
|
|
1751 return;
|
|
1752 } else if (instance->btn_set_val == 0) { // OK
|
|
1753 instance->PressOk();
|
|
1754 }
|
|
1755 }
|
|
1756 void LoadMenu::ChangeDialog(void* pointer, Dialog* widget) {
|
|
1757 LoadMenu* instance = (LoadMenu*)pointer;
|
|
1758 if (widget->status == Dialog::CANCEL) {
|
|
1759 // ダイアログ消去、OK ボタン復帰
|
|
1760 delete instance->awk_dialog;
|
|
1761 instance->awk_dialog = 0;
|
|
1762 instance->menu->activate();
|
|
1763 instance->btn_set->SetValue(-1);
|
|
1764 return;
|
|
1765 } else if (widget->status == Dialog::OK) {
|
|
1766 instance->interface.status = Scn2kMenu::MenuStatus(Scn2kMenu::MENU_CMD | Scn2kMenu::MENU_DELETE);
|
|
1767 return;
|
|
1768 }
|
|
1769 }
|
|
1770 void LoadMenu::ChangeBtnLocal(void* pointer, MenuItem* widget) {
|
|
1771 LoadMenu* instance = (LoadMenu*)pointer;
|
|
1772 if (instance->btn_local_val == -1) return;
|
|
1773 instance->SetValue( (instance->select_page/10) + instance->btn_local_val);
|
|
1774 }
|
|
1775
|
|
1776 struct BacklogMenu : Scn2kMenuImpl {
|
|
1777 Scn2k& scn_impl;
|
|
1778 Text& text_exec;
|
|
1779 bool backlog_update;
|
|
1780 int backlog_cnt;
|
|
1781 BacklogMenu(Scn2kMenu& _interface, Scn2k& scn_impl, Text& text_exec);
|
|
1782 ~BacklogMenu();
|
|
1783 void InitPanel(Event::Container& event, PicContainer& parent);
|
|
1784 void InitTitle(const SaveTitle&);
|
|
1785 void Cancel(void);
|
|
1786 void Exec(Cmd& cmd);
|
|
1787 };
|
|
1788 BacklogMenu::BacklogMenu(Scn2kMenu& _interface, Scn2k& _scn, Text& parent_text_exec) : Scn2kMenuImpl(_interface), scn_impl(_scn), text_exec(parent_text_exec) {
|
|
1789 backlog_cnt = -1;
|
|
1790 backlog_update = false;
|
|
1791 }
|
|
1792 BacklogMenu::~BacklogMenu() {
|
|
1793 }
|
|
1794 void BacklogMenu::InitPanel(Event::Container& event, PicContainer& parent) {
|
|
1795 pevent = &event;
|
|
1796 }
|
|
1797
|
|
1798 void BacklogMenu::InitTitle(const SaveTitle& title_op) {
|
|
1799 }
|
|
1800 void BacklogMenu::Cancel(void) {
|
|
1801 interface.status = Scn2kMenu::MenuStatus(Scn2kMenu::MENU_DELETE);
|
|
1802 }
|
|
1803 void BacklogMenu::Exec(Cmd& cmd) {
|
|
1804 int command_direction = 0; // forward
|
|
1805 if (cmd.cmd_type == CMD_NOP) text_exec.Wait(0xffffffffUL, cmd);
|
|
1806 if (cmd.cmd_type == CMD_BACKLOGREQ || pevent->presscount(MOUSE_UP)) {
|
|
1807 if (cmd.cmd_type == CMD_BACKLOGREQ) cmd.clear();
|
|
1808 backlog_cnt++;
|
|
1809 backlog_update = false;
|
|
1810 command_direction = 1;
|
|
1811 }
|
|
1812 if (cmd.cmd_type == CMD_BACKLOGREQ_FWD || pevent->presscount(MOUSE_DOWN)) {
|
|
1813 if (cmd.cmd_type == CMD_BACKLOGREQ_FWD) cmd.clear();
|
|
1814 backlog_cnt--;
|
|
1815 backlog_update = false;
|
|
1816 if (backlog_cnt == -2 || (
|
|
1817 (backlog_cnt == -1 && text_exec.backlog_item.scn == -1 && text_exec.backlog_item.pos == -1)) ){
|
|
1818 Cancel();
|
|
1819 return;
|
|
1820 }
|
|
1821 command_direction = -1;
|
|
1822 }
|
|
1823 if (cmd.cmd_type != CMD_NOP) return;
|
|
1824 if (backlog_update) return;
|
|
1825 // backlog を最新の状態に更新
|
|
1826 cmd.clear();
|
|
1827 BacklogItem item;
|
|
1828
|
|
1829 retry:
|
|
1830 if (backlog_cnt < -1) backlog_cnt = -1;
|
|
1831 if (backlog_cnt >= int(text_exec.backlog.size())) backlog_cnt = text_exec.backlog.size() - 1;
|
|
1832
|
|
1833 if (backlog_cnt == -1) {
|
|
1834 if (text_exec.backlog_item.scn == -1 && text_exec.backlog_item.pos == -1) {
|
|
1835 if (text_exec.backlog.size() == 0 || command_direction < 0) {
|
|
1836 Cancel();
|
|
1837 return;
|
|
1838 }
|
|
1839 item = text_exec.backlog.back();
|
|
1840 backlog_cnt = 0;
|
|
1841 } else {
|
|
1842 // item = text_exec.backlog.back();
|
|
1843 item = text_exec.backlog_item;
|
|
1844 }
|
|
1845 } else {
|
|
1846 item = text_exec.backlog[text_exec.backlog.size()-1-backlog_cnt];
|
|
1847 }
|
|
1848 if (item.scn == BacklogItem::SaveSelect) { // select marker ; skip this item
|
|
1849 if (command_direction == 0) command_direction = 1;
|
|
1850 backlog_cnt += command_direction;
|
|
1851 goto retry;
|
|
1852 }
|
|
1853 if (item.scn == 0 && item.pos == -1) ; // not read cmd
|
|
1854 else {
|
|
1855 scn_impl.ReadCmdAt(cmd, item.scn, item.pos);
|
|
1856 }
|
|
1857 text_exec.DrawBacklog(item, cmd);
|
|
1858 cmd.clear();
|
|
1859 backlog_update = true;
|
|
1860 }
|
|
1861
|
|
1862 /*******************************************************************************
|
|
1863 **
|
|
1864 **
|
|
1865 */
|
|
1866
|
|
1867 Scn2kMenu::Scn2kMenu(MenuType _type, Scn2k& scn_impl, const Flags& flags, Text& text_exec, int system_version) :
|
|
1868 cmd(flags, system_version), type(_type) {
|
|
1869 pimpl = 0;
|
|
1870 status = MENU_CONTINUE;
|
|
1871 switch(type) {
|
|
1872 case MENU_LOAD: pimpl = new LoadMenu(*this); break;
|
|
1873 case MENU_SAVE: pimpl = new LoadMenu(*this); break;
|
|
1874 case MENU_BACKLOG: pimpl = new BacklogMenu(*this, scn_impl, text_exec); break;
|
|
1875 }
|
|
1876 return;
|
|
1877 }
|
|
1878 Scn2kMenu::~Scn2kMenu() {
|
|
1879 if (pimpl) delete pimpl;
|
|
1880 pimpl = 0;
|
|
1881 }
|
|
1882 void Scn2kMenu::InitPanel(Event::Container& event, PicContainer& parent) {
|
|
1883 if (pimpl) pimpl->InitPanel(event, parent);
|
|
1884 }
|
|
1885 void Scn2kMenu::InitTitle(const SaveTitle& t) {
|
|
1886 if (pimpl) pimpl->InitTitle(t);
|
|
1887 }
|
|
1888 void Scn2kMenu::Cancel(void) {
|
|
1889 if (pimpl) pimpl->Cancel();
|
|
1890 }
|
|
1891 void Scn2kMenu::Exec(Cmd& ret_cmd) {
|
|
1892 if (pimpl == 0) return;
|
|
1893 pimpl->Exec(ret_cmd);
|
|
1894 if (pimpl->pevent->presscount(MOUSE_RIGHT)) {
|
|
1895 Cancel();
|
|
1896 }
|
|
1897 if (status & MENU_CMD && cmd.cmd_type != CMD_NOP) {
|
|
1898 status = Scn2kMenu::MenuStatus(status & (~Scn2kMenu::MENU_CMD) );
|
|
1899 CmdSimplified tmp_cmd;
|
|
1900 char cmd_str[32768];
|
|
1901 char* tmp_cmd_str = cmd_str;
|
|
1902 cmd.write(tmp_cmd, tmp_cmd_str);
|
|
1903 ret_cmd.read(tmp_cmd);
|
|
1904 }
|
|
1905 }
|
|
1906 void Scn2kMenu::activate(void) {
|
|
1907 if (pimpl && pimpl->menu) pimpl->menu->activate();
|
|
1908 }
|
|
1909 void Scn2kMenu::deactivate(void) {
|
|
1910 if (pimpl && pimpl->menu) pimpl->menu->deactivate();
|
|
1911 }
|
|
1912
|