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