comparison scn2k/scn2k_grp.cc @ 0:223b71206888

Initial import
author thib
date Fri, 01 Aug 2008 16:32:45 +0000
parents
children 9fb4609a5372
comparison
equal deleted inserted replaced
-1:000000000000 0:223b71206888
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"scn2k.h"
29 #include"window/widget.h"
30 #include"system/file.h"
31 #include"system/system_config.h"
32 #include"font/text.h"
33 #include<set>
34
35 using namespace std;
36
37 extern void DSurfaceFill(Surface* dest, const Rect& rect, int r, int g, int b, int a=0xff);
38 extern void DSurfaceMove(Surface* src_o, const Rect& srcrect, Surface* dst_o, const Rect& dstpos);
39 extern Rect DSurfaceRenderText(TextGlyphStream::iterator start, TextGlyphStream::iterator end, const Rect& srcrect,
40 Surface* dst, const Rect& dstrect);
41 extern XKFont::HorizLayout* DefaultLayout(int text_size);
42
43 /*******************************************************************
44 ** GrpObj(interface)
45 */
46
47 struct SEL {
48 Rect from;
49 Rect to;
50 int time;
51 int sel_no;
52 int args[8];
53 SEL() : from(0,0), to(0,0) {}
54 };
55
56 struct GrpObj {
57 string name;
58 string gan_name;
59 PicContainer* pic_parent;
60 PicBase* picture;
61 WidAnmTime* anm;
62 int _posx, _posy;
63 int posx[9],posy[9];
64 Rect clip_area;
65 unsigned char alpha;
66 int order;
67 int surface_num;
68
69 string print_moji;
70 int print_size, print_r, print_b, print_g;
71
72 int dig_number, dig_digit;
73
74 // zoom / rotate 関係
75 int zoom; // 256 で 1 倍
76 int rotate; // 0-360度
77
78 vector<Rect> src_pos;
79 enum GrpType { FILLRECT = 1, FILE = 2, GAN = 3, MOJI = 4, DIGIT = 5} gtype;
80 enum Attribute { NONE=0, WIPEON=1, SATURATE=2, HIDDEN=4, HIDDEN_GROUP=8,
81 UPDATE_PICTURE = 8, UPDATE_POS = 16, UPDATE_ALPHA = 32, UPDATE_SNUM = 64, UPDATE_CLIP = 128, UPDATE_VISIBLE = 256,
82 UPDATE_ALL = (8|16|32|64|128|256),
83 ANM_PLAYSTART = 0x8000, ANM_PLAYING = 0x10000,
84 DIG_ZERO = 0x10000*2, DIG_SIGN = 0x10000*4, DIG_PACK=0x10000*8,DIG_SPACE=0x10000*16
85 };
86 Attribute attr;
87
88 GrpImpl* parent_pimpl;
89
90 GrpObj(void);
91 ~GrpObj(void);
92
93 void SetPos(int index, int x, int y);
94 void GetPos(int index, int& x, int& y);
95 int PosX(void);
96 int PosY(void);
97 void SetAlpha(void);
98 void SetAlpha(int alpha);
99 void SetSurfaceNum(int num = -1);
100 void SetZoomRotate(int zoom=-1, int rotate=-1);
101 void SetClipArea(int x, int y, int width, int height);
102 void GetSrcGeom(int& width, int& height);
103 void SetUpdate(void);
104 TextStream ParseMoji(const char* str, int def_r ,int def_g, int def_b, int def_size);
105 void UpdateMoji(void);
106 void UpdateDigit(void);
107 void UpdateSurface(void);
108 void ZoomRotate(void);
109 void Update(void);
110 void CreateSurface(PicContainer* parent);
111 void CreateGan(Event::Container& event, int event_number);
112 void CreateGanSpecial(Event::Container& event, int event_number, int time);
113 PicBase* DeletePic(void);
114 };
115
116 /*******************************************************************
117 ** GrpObj(interface)
118 */
119
120
121 struct GrpObjMap : std::map<int, GrpObj> {
122 typedef pair<const int, GrpObj> value_type;
123 class GrpImpl* parent;
124 GrpObj& operator[](const int& k) {
125 iterator it = lower_bound(k);
126 if (it == end() || it->first != k) {
127 GrpObj obj;
128 obj.parent_pimpl = parent;
129 it = insert(it, value_type(k, obj));
130 }
131 return it->second;
132 }
133 GrpObjMap(class GrpImpl* p) {
134 parent = p;
135 }
136 };
137
138 class GrpImpl {
139 #define MAXPDT 256
140 #define WORKPDT 255
141 Event::Container& event;
142 const Flags& flags;
143 PicBase* screen;
144 PicBase* screen_front;
145 Surface* surface, *surface_update;
146
147 Surface* dsurface[MAXPDT]; // 書き込み可能な Surface
148 Surface* ssurface[MAXPDT]; // ファイルの内容等、読み込みのみ可能な状態の Surface
149 PicContainer& parent;
150
151 // 画像効果の保存用
152 WidAnmTime* anm1, *anm2;
153 typedef enum { NORMAL, WAIT_ANM, WAIT_SHAKE, WAIT_SE, WAIT_MOVIE} Status;
154 Status status;
155 SkipMode skip_mode;
156
157 std::string bg_name;
158 std::map<int, SEL> anmtype;
159 GrpObjMap grpobj;
160 GrpObjMap bs_obj;
161 void CreateObj(int number);
162 void ZMoveObj(int number);
163 void SetObjChanged(int number);
164 void SetObjChangedGroup(int number);
165 void SwapObj(int a1, int a2);
166 void DeleteObjPic(int num);// object の surface のみ削除
167 void DeleteObj(int num);
168 void DeleteObjRange(int num_b, int num_e);
169
170 std::set<int> changed_obj;
171 string reserved_load_surface0;
172 vector<PicBase*> deleted_pic;
173 void RefreshObj(void);
174
175 Surface* Dsurface(int pdt);
176 Surface* Ssurface(int pdt);
177
178 // cgmode 用画像処理関連
179 void LoadCgm(AyuSysConfig& config);
180 std::map<std::string, int> cgm_info;
181 set<int>& cgm_data;
182
183 class MuSys& music;
184
185 public:
186 AyuSysConfig& config;
187 void LoadSurface(const char* str, int pdt);
188 private:
189 void LoadSurface(const char* str);
190 void LoadSurface(void);
191 void AddSurface(const char* str);
192
193 void StartAnm(int type);
194 void StartShake(int total, const int* pattern);
195 void AbortAnm(void);
196 static bool Pressed(int x, int y, void* pointer);
197 public:
198 GrpImpl(Event::Container& _event, PicContainer& _parent, const Flags& _flag, set<int>& _cgm_data, class MuSys& mu, AyuSysConfig& config);
199 ~GrpImpl();
200 bool Wait(unsigned int current_time, Cmd& cmd);
201 void Exec(Cmd& cmd);
202 void InitSel(AyuSysConfig& config);
203 void Save(std::string& str);
204 void Load(const char* str);
205 void SaveSys(std::string& str);
206 void LoadSys(const char* str);
207 void SetSkipMode(SkipMode _mode);
208 };
209 /*******************************************************************
210 ** GrpObj(implementation)
211 */
212
213 GrpObj::GrpObj(void) :
214 name(""), gan_name(""), pic_parent(0), picture(0), anm(0),
215 _posx(0), _posy(0), clip_area(0,0,0,0),
216 alpha(255), order(0), surface_num(0), print_moji(""), print_size(0), print_r(-1),print_g(-1),print_b(-1),
217 dig_number(0), dig_digit(0),
218 zoom(-1), rotate(-1), attr(GrpObj::HIDDEN), parent_pimpl(0) {
219 int i;
220 for (i=0; i<9; i++) {
221 posx[i] = posy[i] = 0;
222 }
223 }
224 GrpObj::~GrpObj() {
225 if (picture) delete picture;
226 if (parent_pimpl == 0) {
227 fprintf(stderr,"\n**************\nFATAL : UNINITIALIZED GrpObj IS FOUND!!! \n**************\n");
228 }
229 }
230 int GrpObj::PosX() {
231 return _posx;
232 }
233 int GrpObj::PosY() {
234 return _posy;
235 }
236 void GrpObj::SetUpdate(void) {
237 attr = Attribute (attr | UPDATE_PICTURE);
238 }
239 void GrpObj::SetPos(int index, int x,int y) {
240 if (index < 0 || index > 8) {
241 fprintf(stderr,"GrpObj::SetPos: Invalid index %d <- %d,%d\n",index,x,y);
242 return;
243 }
244 if (x == posx[index] && y == posy[index]) return;
245 attr = Attribute(attr | UPDATE_POS);
246 _posx += x-posx[index];
247 _posy += y-posy[index];
248 posx[index] = x;
249 posy[index] = y;
250 }
251 void GrpObj::GetPos(int index, int& x, int& y) {
252 if (index < 0 || index > 8) {
253 fprintf(stderr,"GrpObj::GetPos: Invalid index %d\n",index);
254 x = 0; y = 0;
255 return;
256 }
257 x = posx[index];
258 y = posy[index];
259 return;
260 }
261 void GrpObj::SetAlpha(int new_alpha) {
262 if (alpha == new_alpha) return;
263 alpha = new_alpha;
264 attr = Attribute(attr | UPDATE_ALPHA);
265 return;
266 }
267 void GrpObj::SetSurfaceNum(int num) {
268 if (num != -1) {
269 if (surface_num == num) return;
270 surface_num = num;
271 }
272 attr = Attribute(attr | UPDATE_SNUM);
273 return;
274 }
275
276 void GrpObj::SetClipArea(int x, int y, int w, int h) {
277 Rect new_clip(x,y,x+w,y+h);
278 if (clip_area == new_clip) return;
279 clip_area = new_clip;
280 attr = Attribute(attr | UPDATE_CLIP);
281 return;
282 }
283 PicBase* GrpObj::DeletePic(void) {
284 PicBase* p = picture;
285 anm = 0;
286 picture = 0;
287 src_pos.clear();
288 attr = Attribute(attr & (HIDDEN | HIDDEN_GROUP));
289 return p;
290 }
291 void GrpObj::GetSrcGeom(int& width, int& height) {
292 if (src_pos.empty()) {
293 width = 0; height = 0;
294 if (name.length() == 0) {
295 return;
296 }
297 /* ボタンの位置情報を求める */
298 /* g00 ファイルのヘッダ部分に位置情報は入っている */
299 string path(name);
300 path += ".g00";
301 ARCINFO* info = file_searcher.Find(FILESEARCH::PDT, path.c_str(), "g00");
302 if (info == 0) { // ファイルが見つからない
303 fprintf(stderr,"GrpObj::GetSrcGeom : Cannot find file %s\n", path.c_str());
304 return;
305 }
306 const char* data = info->Read();
307 int srclen = read_little_endian_int(data+5);
308 if (data && *data == 2) { // 画像ファイル内にボタン情報が存在する
309 int srclen = read_little_endian_int(data+5);
310 int i;
311 for (i=0; i<srclen; i++) {
312 int x1 = read_little_endian_int(data+9+i*24+0);
313 int y1 = read_little_endian_int(data+9+i*24+4);
314 int x2 = read_little_endian_int(data+9+i*24+8);
315 int y2 = read_little_endian_int(data+9+i*24+12);
316 src_pos.push_back(Rect(x1, y1, x2+1, y2+1));
317 if (width < src_pos.back().width()) width = src_pos.back().width();
318 if (height < src_pos.back().height()) height = src_pos.back().height();
319 }
320 } else { // 画像ファイルから大きさ取得
321 width = read_little_endian_short(data+1);
322 height = read_little_endian_short(data+3);
323 src_pos.push_back(Rect(0,0,width,height));
324 }
325 delete info;
326 }
327 int sn = surface_num;
328 if (sn < 0 || sn > src_pos.size()) sn = 0;
329 width = src_pos[sn].width();
330 height = src_pos[sn].height();
331 return;
332 }
333 void GrpObj::Update(void) {
334 if (attr & UPDATE_PICTURE) {
335 UpdateSurface();
336 attr = Attribute( (attr | UPDATE_ALL) & (~UPDATE_PICTURE));
337 }
338 if (picture == 0) return;
339 if (attr & UPDATE_POS) {
340 if (attr & SATURATE) {
341 int w=0, h=0;
342 GetSrcGeom(w,h);
343 picture->Move(_posx-w/2, _posy-h/2);
344 } else {
345 picture->Move(_posx, _posy);
346 }
347 }
348 if (attr & UPDATE_ALPHA) {
349 if (alpha <= 0) {
350 picture->SetSurfaceAlpha(0, Rect(0,0));
351 picture->hide();
352 } else if (alpha >= ALPHA_MAX) {
353 picture->SetSurfaceAlpha(0, Rect(0,0));
354 if (attr & HIDDEN) picture->hide();
355 else picture->show();
356 } else {
357 picture->SetSurfaceAlpha(&alpha, Rect(0,0,1,1));
358 if (attr & HIDDEN) picture->hide();
359 else picture->show();
360 }
361 }
362 if ( (attr & UPDATE_SNUM) && (!src_pos.empty())) {
363 if (surface_num < 0 || surface_num >= src_pos.size()) surface_num = 0;
364 picture->SetSurfacePos(src_pos[surface_num].lx, src_pos[surface_num].ty);
365 }
366 if (attr & UPDATE_CLIP) {
367 picture->SetClipArea(clip_area);
368 }
369 attr = Attribute(attr & (~UPDATE_ALL));
370 if (attr & ANM_PLAYSTART) {
371 if (anm) {
372 anm->Play();
373 attr = Attribute(attr | ANM_PLAYING);
374 }
375 attr = Attribute(attr & (~ANM_PLAYSTART));
376 }
377 }
378 void GrpObj::CreateSurface(PicContainer* parent) {
379 if (picture) {
380 PicBase* p = DeletePic();
381 delete p;
382 }
383 src_pos.clear();
384 // picture を作成
385 pic_parent = parent;
386 picture = parent->create_leaf(Rect(_posx,_posy,_posx+1,_posy+1), 0);
387 picture->hide();
388 UpdateSurface();
389 }
390
391 void GrpObj::UpdateSurface(void) {
392 if (pic_parent == 0 || picture == 0) return;
393 int width = 0, height = 0;
394 if (gtype == FILE || gtype == GAN) {
395 if (name.length() == 0) return;
396 // ファイル名が存在する場合、ファイルを読み込み
397 GetSrcGeom(width, height);
398 if (width <= 0 || height <= 0) return;
399 // surface の設定
400 if (surface_num == 0 && ( (zoom > 0 && zoom != 256) || rotate > 0)) {
401 ZoomRotate();
402 } else {
403 // 普通に surface を設定
404 string path(name);
405 path += ".g00";
406 picture->SetSurface(path.c_str(), 0, 0);
407 picture->SetSurfaceRect(Rect(0,0,width,height));
408 }
409 if (attr & SATURATE)
410 picture->SetSurfaceAttribute(PicBase::BLIT_SATURATE);
411 } else if (gtype == MOJI) { // テキスト描画
412 if (print_moji.length() == 0) return;
413 UpdateMoji();
414 } else if (gtype == DIGIT) { // 数値を画像表示
415 UpdateDigit();
416 }
417 }
418 void GrpObj::ZoomRotate(void) {
419 picture->SetSurface( (Surface*)0,0,0);
420
421 // 回転、縮小拡大は座標原点が画像の中心になる
422 string path(name);
423 path += ".g00";
424 Surface* surface_orig = pic_parent->Root().NewSurface(path.c_str());
425 if (surface_orig == 0) return;
426
427 Surface* zoom_surface = pic_parent->Root().RotZoomSurface(surface_orig, double(zoom)/256.0, rotate);
428 Rect zoom_r (*zoom_surface);
429 picture->SetSurface(zoom_surface, 0, 0);
430 picture->SetSurfaceFreeFlag();
431 //picture->Move(PosX() + - zoom_r.width()/2, PosY() + - zoom_r.height()/2);
432 // 中心座標がわからん・・・
433 picture->Move(320 - zoom_r.width()/2, 240 - zoom_r.height()/2);
434 picture->SetSurfaceRect(Rect(0, 0, zoom_r.width(), zoom_r.height()));
435
436 pic_parent->Root().DeleteSurface(surface_orig);
437 }
438
439 static char* wstrchr(const char* s, unsigned int chr) {
440 int ws, wc;
441 while(*s != 0) {
442 if (*s < 0 && s[1] != 0) {
443 wc = int((unsigned char)(s[0]))*0x100 + int((unsigned char)(s[1]));
444 ws = 2;
445 } else {
446 wc = (unsigned char)(s[0]);
447 ws = 1;
448 }
449 if (wc == chr) return (char*)s;
450 s += ws;
451 }
452 return 0;
453 }
454 TextStream GrpObj::ParseMoji(const char* str, int def_r ,int def_g, int def_b, int def_size) { // 制御シーケンス付き文字列をparse
455 TextStream ts;
456 ts.kanji_type = TextStream::sjis;
457 ts.SetColor(def_r, def_g, def_b);
458 char* copy_str = new char[strlen(str)+1];
459 char* next_str;
460 char* retptr;
461 int var;
462
463 while( (next_str = wstrchr(str, '#')) != 0) {
464 int len = next_str - str;
465 strncpy(copy_str, str, len);
466 copy_str[len] = 0;
467 ts.Add(copy_str);
468 str = next_str + 1;
469
470 switch(str[0]) {
471 case '#': // separator
472 str += 1;
473 break;
474 case 'D': case 'd': // return
475 ts.AddReturn();
476 str += 1;
477 break;
478 case 'C': case 'c': // color
479 str += 1;
480 var = strtol(str, &next_str,10);
481 if (var == 0 && str == next_str) { // no parameter
482 ts.SetColor(def_r, def_g, def_b);
483 } else {
484 int r,g,b; char key[1024];
485 sprintf(key, "#COLOR_TABLE.%03d", var);
486 if (parent_pimpl->config.GetParam(key, 3, &r, &g, &b)) { // color not found
487 r = g = b = 0;
488 }
489 ts.SetColor(r,g,b);
490 str = next_str;
491 }
492 break;
493 case 'S': case 's': // size
494 str += 1;
495 var = strtol(str, &next_str, 10);
496 if (var == 0 && str == next_str) { // no parameter
497 ts.SetSize(1);
498 } else {
499 if (def_size == 0) def_size = 20;
500 if (var <= 0) var = 1;
501 ts.SetSize(double(var)/def_size);
502 }
503 break;
504 case 'X': case 'x': // xpos : not supported
505 case 'Y': case 'y': // ypos : not supported
506 default:
507 ts.Add("#");
508 break;
509 }
510 }
511 ts.Add(str);
512 return ts;
513 }
514 void GrpObj::UpdateMoji(void) { // 文字の大きさ、色などを変更
515 if (print_moji.length() == 0) return;
516 if (pic_parent == 0) return;
517 /* テキストの大きさを得る */
518 int r, g, b;
519 if (print_r == -1 || print_g == -1 || print_b == -1) {// 色設定なし
520 r = g = b = 0; // とりあえず黒(clannad のSave/Loadメニュー用)
521 } else {
522 r = print_r;
523 g = print_g;
524 b = print_b;
525 }
526 TextStream ts = ParseMoji(print_moji.c_str(), r, g, b, print_size);
527 TextGlyphStream gs;
528 vector<int> lh;
529 // とりあえず drawable width は充分に大きく(2048)取る
530 DefaultLayout(print_size-2)->Layout(ts, gs, lh, 2048); // print_size そのままだと弱干大きすぎるので -2
531 int width = gs.width();
532 int height = gs.height();
533 Surface* surface = pic_parent->Root().NewSurface(width, height, ALPHA_MASK);
534 DSurfaceFill(surface, Rect(*surface), 0, 0, 0, 0);
535 DSurfaceRenderText(gs.begin(), gs.end(), Rect(0, 0, width, height), surface, Rect(0,0));
536 picture->SetSurface(surface, 0, 0);
537 picture->SetSurfaceRect(Rect(0,0,width,height));
538 picture->SetSurfaceFreeFlag();
539 }
540 void GrpObj::UpdateDigit(void) {
541 // 画像表示の数値文字列を表示する
542 if (name.length() == 0) return;
543 // ファイル名が存在する場合、ファイルを読み込み
544 string path(name);
545 path += ".g00";
546 Surface* surface_orig = pic_parent->Root().NewSurface(path.c_str());
547 if (surface_orig == 0) return;
548
549 int width, height;
550 int i;
551 GetSrcGeom(width, height);
552 if (width <= 0 || height <= 0) return;
553 if (src_pos.size() < 14) {
554 // 必要な数の object がない
555 // 表示できない分の空の rect を追加しておく
556 for (i=src_pos.size(); i<14; i++)
557 src_pos.push_back(Rect(0,0,0,0));
558 pic_parent->Root().DeleteSurface(surface_orig);
559 return;
560 }
561 // 桁数の計算
562 char num_str[20];
563 if (dig_number < 0) sprintf(num_str, "%d", -dig_number);
564 else sprintf(num_str, "%d", dig_number);
565 int sign_count = 0;
566 int space_count = 0;
567 int total_count;
568 int dig_count = strlen(num_str);
569 if (dig_number < 0 && (attr&DIG_SIGN) == 0) dig_count++;
570 if (dig_count < dig_digit) space_count = dig_digit - dig_count;
571 if (attr & DIG_SIGN) sign_count = 1;
572 total_count = dig_count + space_count + sign_count;
573
574 Surface* surface = pic_parent->Root().NewSurface(width*total_count, height, ALPHA_MASK);
575 DSurfaceFill(surface, Rect(*surface), 0, 0, 0, 0);
576
577 /* surface にコピーする */
578 int cur_x = 0;
579 if ( (attr & DIG_PACK) && !(attr & DIG_ZERO)) { // 始めに空白を挿入
580 cur_x += space_count * width;
581 }
582 int plus = 10, minus = 11, plusminus = 12;
583 if (dig_number < 0) {
584 DSurfaceMove(surface, src_pos[minus], surface, Rect(cur_x,0));
585 cur_x += width;
586 } else if (attr & DIG_SIGN) {
587 if (dig_number == 0)
588 DSurfaceMove(surface, src_pos[plusminus], surface, Rect(cur_x,0));
589 else
590 DSurfaceMove(surface, src_pos[plus], surface, Rect(cur_x,0));
591 cur_x += width;
592 }
593 if (attr & DIG_ZERO) { // ゼロ・パディング
594 for (i=0; i<space_count; i++) {
595 DSurfaceMove(surface, src_pos[0], surface, Rect(cur_x, 0));
596 cur_x += width;;
597 }
598 } else if (!(attr & DIG_PACK)) { // PACK オプションなし
599 cur_x += space_count * width;
600 }
601 for (i=0; num_str[i] != 0; i++) {
602 DSurfaceMove(surface_orig, src_pos[num_str[i]-'0'], surface, Rect(cur_x, 0));
603 cur_x += width;
604 }
605
606 /* picture に設定 */
607 picture->SetSurface(surface, 0, 0);
608 picture->SetSurfaceRect(Rect(0,0,width*total_count,height));
609 picture->SetSurfaceFreeFlag();
610
611 pic_parent->Root().DeleteSurface(surface_orig);
612 }
613 void GrpObj::CreateGan(Event::Container& event, int event_number) {
614 if (picture == 0) {
615 fprintf(stderr,"GrpObj::CreateGan() is called before Create()\n");
616 return;
617 }
618 if (anm) {
619 anm->Abort();
620 delete anm;
621 }
622 if (gan_name.empty()) return;
623 /* アニーメション情報 (.GAN ファイル)を求める */
624 string path(gan_name);
625 path += ".gan";
626 ARCINFO* info = file_searcher.Find(FILESEARCH::GAN, path.c_str(), "gan");
627 if (info == 0) {
628 fprintf(stderr,"GrpObj::CreateGan: Cannot Find 'GAN' file %s\n", path.c_str());
629 return;
630 }
631 const char* data = info->Read();
632 if (read_little_endian_int(data) != 10000 || read_little_endian_int(data+4) != 10000) {
633 fprintf(stderr,"GrpObj::CreateGan: Invalid'GAN' file %s\n", path.c_str());
634 delete info;
635 return;
636 }
637
638 picture->SetSurfaceAttribute(PicBase::BLIT_SATURATE);
639 attr = Attribute(attr | UPDATE_POS | SATURATE);
640
641 const char* buf = data + 16;
642 buf += strlen(buf) + 1; // 画像ファイル名が入っている
643 buf += 4; // 定数 20000
644 int pics = read_little_endian_int(buf); buf += 4; // 複数のアニメーション情報が入っている場合、情報数
645 // 以下、pics 回繰り返し
646 // アニメーションを行う実体を作成
647 AnmAlphaMove* wid = new AnmAlphaMove(event, picture);
648
649 if (event_number && event_number < pics) { // 複数のアニメーション情報がある場合、先の情報を読み飛ばす */
650 int i; for (i=0; i<event_number; i++) {
651 buf += 4; // 定数 30000
652 int ptns = read_little_endian_int(buf); buf += 4;
653 buf += ptns*52;
654 }
655 }
656 buf += 4; // 定数 30000
657 int ptns = read_little_endian_int(buf); buf += 4;
658 int total_time = 0;
659 int i;
660 for (i=0; i<ptns; i++) {
661 int p = read_little_endian_int(buf+i*52+0*8+4);
662 int x = read_little_endian_int(buf+i*52+1*8+4);
663 int y = read_little_endian_int(buf+i*52+2*8+4);
664 int t = read_little_endian_int(buf+i*52+3*8+4);
665 int a = read_little_endian_int(buf+i*52+4*8+4);
666 x += PosX();
667 y += PosY();
668 if (p == -1) { a = 0; p = 0; } // p == -1 ならなにも表示しない
669 if (p >= src_pos.size()) {
670 fprintf(stderr,"Reading GAN file %s (G00 %s) : not enough pictures in .G00 file\n", path.c_str(), name.c_str());
671 a = 0; p = 0;
672 }
673 total_time += t;
674 wid->ptns.push_back(AnmAlphaMove::Ptn(Rect(x,y), src_pos[p], a, total_time));
675 }
676 wid->SetPtn(); // パターン登録終了
677 attr = Attribute(attr | ANM_PLAYSTART);
678 anm = wid;
679 };
680 void GrpObj::CreateGanSpecial(Event::Container& event, int event_number, int time) {
681 if (picture == 0) {
682 fprintf(stderr,"GrpObj::CreateGan() is called before Create()\n");
683 return;
684 }
685 if (anm) {
686 anm->Abort();
687 delete anm;
688 }
689
690 // アニメーションを行う実体を作成
691 AnmAlphaMove* wid = new AnmAlphaMove(event, picture);
692
693 int i;
694 switch(event_number) {
695 case 0: // pattern を 0 から最後まで変化させる
696 for (i=0; i<src_pos.size(); i++) {
697 wid->ptns.push_back(AnmAlphaMove::Ptn(Rect(PosX(), PosY()), src_pos[i], 255, time*i));
698 }
699 wid->SetPtn(); // パターン登録終了
700 anm = wid;
701 attr = Attribute(attr | ANM_PLAYSTART);
702 break;
703 default:
704 break;
705 }
706 return;
707 };
708
709 void GrpObj::SetZoomRotate(int new_zoom, int new_rotate) {
710 if (zoom == new_zoom && rotate == new_rotate) return;
711 if (new_zoom != -1) zoom = new_zoom;
712 if (new_rotate != -1) rotate = new_rotate;
713 if (zoom < 0) zoom = 256;
714 if (rotate < 0) rotate = 0;
715 else if (rotate > 360) rotate %= 360;
716
717 attr = Attribute(attr | UPDATE_PICTURE);
718 return;
719 }
720 /******************************************************************
721 **
722 ** class ScnGrp*
723 */
724 /* Princess Bride: 背景画の一部のみ移動、の実装 */
725 struct ScnGrpMove : public WidAnmTime {
726 Surface* dest;
727 Surface* src;
728 PicRoot& root;
729 Rect dest_r, from, to;
730 ScnGrpMove(Event::Container& container, PicBase* _pic, PicRoot& root, Surface* dest, const Rect& _dest_r, Surface* src, const Rect& from, const Rect& to, int total_time);
731 void Exec(int count);
732 };
733 ScnGrpMove::ScnGrpMove(Event::Container& container, PicBase* _pic, PicRoot& _root, Surface* _dest, const Rect& _dest_r, Surface* _src, const Rect& _from, const Rect& _to, int total_time) :
734 WidAnmTime(container, _pic, total_time),
735 dest(_dest), src(_src), root(_root),dest_r(_dest_r), from(_from), to(_to) {
736 int dx = to.lx - from.lx;
737 int dy = to.ty - from.ty;
738 if (dx < 0) dx = -dx;
739 if (dy < 0) dy = -dy;
740 if (dx < dy) dx = dy;
741 if (dx == 0) dx = 1;
742 SetAllCount(dx);
743 }
744 void ScnGrpMove::Exec(int count) {
745 Rect r(0,0,dest_r.width(),dest_r.height());
746 int dx = to.lx - from.lx;
747 int dy = to.ty - from.ty;
748 int x = dx*count/all_count + from.lx;
749 int y = dy*count/all_count + from.ty;
750 r.rmove(x, y);
751 root.BlitSurface(src, r, dest, dest_r);
752 iterator it;
753 for (it=pic.begin(); it!=pic.end(); it++)
754 (*it)->SetSurface(dest, 0, 0);
755 }
756
757 /* Princess Bride: カードがおちるアニメーション */
758
759 struct ScnGrpAnmAtom {
760 string name;
761 int time;
762 ScnGrpAnmAtom(const char* _n, int _t) : name(_n), time(_t) {}
763 };
764 struct ScnGrpAnm : public WidAnmTime, vector<ScnGrpAnmAtom> {
765 GrpImpl& owner;
766 ScnGrpAnm(Event::Container& container, PicBase* _pic, GrpImpl& _owner) :
767 WidAnmTime(container, _pic, 0), owner(_owner) {
768 }
769 void CalcTotal(void);
770 void Exec(int count);
771 };
772 void ScnGrpAnm::CalcTotal(void) {
773 /* total time を計算 */
774 if (empty()) return;
775 int tm = 0;
776 vector<ScnGrpAnmAtom>::iterator it;
777 for (it=begin(); it != end(); it++) tm += it->time;
778 total_time = tm;
779 SetAllCount(tm);
780 }
781 void ScnGrpAnm::Exec(int count) {
782 int tm = 0; vector<ScnGrpAnmAtom>::iterator it;
783 for (it=begin(); it != end(); it++) {
784 tm += it->time;
785 if (count < tm) break;
786 }
787 if (it == end()) it--;
788 owner.LoadSurface(it->name.c_str(), 0);
789 }
790
791
792 /*****************************************************
793 *
794 * GrpImpl(implementation) : 定義
795 *
796 */
797
798 #include"music2/music.h"
799
800 GrpImpl::GrpImpl(Event::Container& _event, PicContainer& _parent, const Flags& f, set<int>& _cgm_data, class MuSys& _mu, AyuSysConfig& _config) :
801 event(_event),
802 flags(f),
803 parent(_parent),
804 status(NORMAL),
805 skip_mode(SKIP_NO),
806 music(_mu),
807 cgm_data(_cgm_data),
808 grpobj(this),
809 bs_obj(this),
810 config(_config)
811 {
812 int i;
813 for (i=0; i<MAXPDT; i++) {
814 ssurface[i] = 0;
815 dsurface[i] = 0;
816 }
817 screen = parent.create_leaf(Rect(0, 0, parent.Width(), parent.Height()), 0);
818 screen_front = parent.create_leaf(Rect(0, 0, parent.Width(), parent.Height()), 0);
819 surface = parent.Root().NewSurface(parent.Width(), parent.Height(), NO_MASK);
820 surface_update = parent.Root().NewSurface(parent.Width(), parent.Height(), NO_MASK);
821 DSurfaceFill(surface, Rect(*surface), 0, 0, 0);
822 DSurfaceFill(surface_update, Rect(*surface), 0, 0, 0);
823 screen->SetSurface(surface, 0, 0);
824 screen->show();
825 screen_front->hide();
826 screen_front->ZMove(screen);
827
828 LoadCgm(config);
829
830 anm1 = 0; anm2 = 0;
831 }
832
833 GrpImpl::~GrpImpl() {
834
835 map<int,GrpObj>::iterator it;
836 for (it=grpobj.begin(); it!=grpobj.end(); it++) {
837 PicBase* p = it->second.DeletePic();
838 delete p;
839 }
840
841 delete screen;
842 delete screen_front;
843 parent.Root().DeleteSurface(surface);
844 int i;
845 for (i=0; i<MAXPDT; i++) {
846 if (ssurface[i]) parent.Root().DeleteSurface(ssurface[i]);
847 if (dsurface[i]) parent.Root().DeleteSurface(dsurface[i]);
848 }
849 }
850
851 Surface* GrpImpl::Dsurface(int pdt) {
852 if (pdt == 0) return surface;
853 if (dsurface[pdt] == 0) { // とりあえず画面の大きさということにする
854 if (pdt == WORKPDT)
855 dsurface[pdt] = parent.Root().NewSurface(parent.Width(), parent.Height(), ALPHA_MASK);
856 else
857 dsurface[pdt] = parent.Root().NewSurface(parent.Width(), parent.Height(), NO_MASK);
858 }
859 if (ssurface[pdt]) { // ssurface が存在すれば、dsurface にコピーして返す
860 DSurfaceMove(ssurface[pdt], Rect(*ssurface[pdt]), dsurface[pdt], Rect(0,0));
861 parent.Root().DeleteSurface(ssurface[pdt]);
862 ssurface[pdt] = 0;
863 }
864 return dsurface[pdt];
865 }
866 #include<SDL.h>
867 Surface* GrpImpl::Ssurface(int pdt) {
868 if (pdt == 0) return surface;
869 if (ssurface[pdt]) {
870 return ssurface[pdt];
871 }
872 return Dsurface(pdt);
873 }
874
875 void GrpImpl::LoadSurface(const char* str, int pdt) {
876 string s = str;
877 if (cgm_info.find(s) != cgm_info.end()) {
878 cgm_data.insert(cgm_info[s]);
879 }
880 Surface* bg = parent.Root().NewSurface(s.c_str());
881 if (bg == 0) {
882 s += ".g00";
883 bg = parent.Root().NewSurface(s.c_str());
884 }
885 if (bg) {
886 if (ssurface[pdt]) parent.Root().DeleteSurface(ssurface[pdt]);
887 ssurface[pdt] = bg;
888 if (pdt == 0) {
889 /* とりあえず Princess Bride のアニメーション効果専用 */
890 Rect r(*ssurface[0]);
891 Rect dr(*surface);
892 int x = (dr.width()-r.width())/2;
893 int y = (dr.height()-r.height())/2;
894 DSurfaceMove(ssurface[0], r, surface, Rect(x,y));
895 parent.Root().DeleteSurface(ssurface[0]);
896 ssurface[0] = 0;
897 screen->SetSurface(surface, 0, 0);
898 }
899 } else {
900 if (str[0] != 0)
901 fprintf(stderr,"Cannot find surface %d <- '%s'\n",pdt,str);
902 }
903 return;
904 }
905 void GrpImpl::InitSel(AyuSysConfig& config) {
906 int i; int args[16]; char key[1024];
907 for (i=0; i<999; i++) {
908 sprintf(key, "#SEL.%03d",i);
909 if (config.GetParam(key, 15, &args[0], &args[1],
910 &args[2], &args[3], &args[4], &args[5], &args[6], &args[7],
911 &args[8], &args[9], &args[10], &args[11], &args[12], &args[13],
912 &args[14])) {
913
914 sprintf(key, "#SELR.%03d", i);
915 if (config.GetParam(key, 16, &args[0], &args[1],
916 &args[2], &args[3], &args[4], &args[5], &args[6], &args[7],
917 &args[8], &args[9], &args[10], &args[11], &args[12], &args[13],
918 &args[14], &args[15])) continue;
919 }
920 SEL& s = anmtype[i];
921 s.from = Rect(args[0], args[1], args[2]+1, args[3]+1);
922 s.to = Rect(args[4], args[5]);
923 s.time = args[6];
924 s.sel_no = args[7];
925 int j; for (j=0; j<8; j++) s.args[j] = args[8+j];
926 }
927 return;
928 }
929 void GrpImpl::SetSkipMode(SkipMode _mode) {
930 if ( (skip_mode & SKIP_IN_MENU) && (_mode & SKIP_IN_MENU) == 0) {
931 RefreshObj();
932 } else if ( (skip_mode & SKIP_IN_MENU) == 0 && (_mode & SKIP_IN_MENU) ) {
933 }
934 skip_mode = _mode;
935 }
936 void GrpImpl::SetObjChanged(int num) {
937 changed_obj.insert(num);
938 }
939 void GrpImpl::SetObjChangedGroup(int num) {
940 if (num % 1000 != 0) {
941 SetObjChanged(num);
942 return;
943 }
944 std::map<int, GrpObj>::iterator begin,end,it;
945 begin = grpobj.lower_bound(num);
946 end = grpobj.lower_bound(num+1000);
947 for (it=begin;it!=end;it++) {
948 changed_obj.insert(it->first);
949 }
950 }
951 void GrpImpl::RefreshObj(void) {
952 if (!deleted_pic.empty()) {
953 vector<PicBase*>::iterator it;
954 for (it=deleted_pic.begin(); it!=deleted_pic.end(); it++) {
955 if (*it) delete *it;
956 }
957 deleted_pic.clear();
958 }
959 if (!changed_obj.empty()) {
960 set<int>::iterator it;
961 for (it=changed_obj.begin(); it != changed_obj.end(); it++) {
962 if (grpobj.find(*it) == grpobj.end()) continue;
963 GrpObj& obj = grpobj[*it];
964 GrpObj& parent_obj = grpobj[ ((*it)/1000) * 1000];
965 if (obj.picture == 0) continue;
966 if (obj.alpha == 0 || (obj.attr & GrpObj::HIDDEN) || (parent_obj.attr & GrpObj::HIDDEN_GROUP) ) {
967 if (obj.attr & GrpObj::ANM_PLAYING) {
968 obj.attr = GrpObj::Attribute(obj.attr & ~(GrpObj::ANM_PLAYING));
969 if (obj.anm) obj.anm->Abort();
970 }
971 obj.picture->hide();
972 } else {
973 obj.Update();
974 obj.picture->show();
975 }
976 }
977 changed_obj.clear();
978 }
979 if (reserved_load_surface0.length() != 0) {
980 LoadSurface(reserved_load_surface0.c_str(), 0);
981 reserved_load_surface0 = "";
982 }
983 screen->ReBlit();
984 }
985
986
987 #include<SDL.h>
988 void GrpImpl::StartAnm(int type) {
989 SEL sel;
990
991 if (anmtype.find(type) == anmtype.end()) {
992 if (anmtype.find(0) == anmtype.end()) {
993 sel.sel_no = 1;
994 sel.from = Rect(*surface);
995 sel.to = Rect(0,0);
996 sel.time = 0;
997 } else {
998 sel = anmtype[0];
999 }
1000 } else {
1001 sel = anmtype[type];
1002 }
1003 if (anm1) {
1004 fprintf(stderr,"Warning: StartAnm() called before anm1 finished\n");
1005 anm1->Abort();
1006 delete anm1;
1007 anm1 = 0;
1008 }
1009 map<int,GrpObj>::iterator it;
1010 // 現在表示中のobjectを消去
1011 deleted_pic.push_back(screen);
1012 for (it=grpobj.begin(); it!=grpobj.end(); it++) {
1013 if (! (it->second.attr & GrpObj::WIPEON)) { // 画像切り替え時に object 削除
1014 deleted_pic.push_back(it->second.DeletePic());
1015 } else {
1016 GrpObj& new_obj = bs_obj[it->first];
1017 if (new_obj.name.empty()) { // 新しい object が存在しなければ内容を引き継ぐ
1018 new_obj = it->second;
1019 it->second.DeletePic();
1020 } else {
1021 new_obj.attr = GrpObj::Attribute(new_obj.attr | GrpObj::WIPEON);
1022 deleted_pic.push_back(it->second.DeletePic());
1023 }
1024 }
1025 }
1026 grpobj.clear(); // 全オブジェクト削除
1027
1028 // 全画像オブジェクトの前にscreen 移動
1029 // 新しい screen_front を作成しておく
1030 screen = screen_front;
1031 screen->hide();
1032 screen->SetSurface(surface_update, 0, 0);
1033 parent.Root().BlitSurface(Dsurface(1), Rect(*surface_update), surface_update, Rect(0,0));
1034
1035 screen_front = parent.create_leaf(Rect(0, 0, parent.Width(), parent.Height()), 0);
1036 screen_front->hide();
1037 screen_front->ZMove(screen);
1038
1039 // 新しい object へ更新、surface_update へ新しい object を表示
1040 // (object 作成時は picture は hide されている)
1041 for (it=bs_obj.begin(); it!=bs_obj.end(); it++) {
1042 grpobj[it->first] = it->second;
1043 it->second.DeletePic();
1044 CreateObj(it->first);
1045 GrpObj& g = grpobj[it->first];
1046 GrpObj& parent_obj = grpobj[ (it->first/1000) * 1000];
1047 if (g.picture) {
1048 g.Update();
1049 if (g.alpha == 0 || (g.attr & GrpObj::HIDDEN) || (parent_obj.attr & GrpObj::HIDDEN_GROUP) ) ;
1050 else g.picture->SimpleBlit(surface_update);
1051 g.picture->hide();
1052 }
1053 }
1054 bs_obj.clear();
1055 // 画像効果開始
1056 switch(sel.sel_no) {
1057 default:
1058 case 0: case 50: // 0 と 50 の違いが良くわからない
1059 if (skip_mode & SKIP_GRP_NOEFFEC)
1060 anm1 = new WidAnmAlpha(event, screen, ALPHA_MAX, ALPHA_MAX, 0);
1061 else if (skip_mode & SKIP_GRP_FAST)
1062 anm1 = new WidAnmAlpha(event, screen, 0, ALPHA_MAX, sel.time/4);
1063 else
1064 anm1 = new WidAnmAlpha(event, screen, 0, ALPHA_MAX, sel.time);
1065 break;
1066 }
1067 if (anm1) anm1->Play();
1068 if (skip_mode & SKIP_GRP_NOEFFEC) AbortAnm();
1069 }
1070 void GrpImpl::StartShake(int total, const int* pattern) {
1071 if (anm2) {
1072 fprintf(stderr,"Warning: StartShake() called before another animation finished\n");
1073 anm2->Abort();
1074 delete anm2;
1075 anm2 = 0;
1076 }
1077 if (skip_mode & SKIP_GRP_NOEFFEC) return;
1078 AnmAlphaMove* new_anm = new AnmAlphaMove(event, &parent); // shake screen では元画面の座標を揺らす
1079 int i; int tm = 0;
1080 for (i=0; i<total; i+=3) {
1081 int x = pattern[i];
1082 int y = pattern[i+1];
1083 new_anm->ptns.push_back(AnmAlphaMove::Ptn(Rect(x,y), Rect(0,0), 255, tm));
1084 tm += pattern[i+2];
1085 }
1086 new_anm->ptns.push_back(AnmAlphaMove::Ptn(Rect(0,0), Rect(0,0), 255, tm));
1087 new_anm->SetPtn(); // パターン登録終了
1088 new_anm->Play();
1089 anm2 = new_anm;
1090 }
1091 void GrpImpl::AbortAnm(void) {
1092 if (anm1 == 0) return;
1093 anm1->Abort();
1094 delete anm1;
1095 anm1 = 0;
1096 /* 画像効果終了 */
1097 /* 古い画面への画像効果があれば消去 */
1098 if (anm2 && anm2->pic[0] != screen) {
1099 anm2->Abort();
1100 delete anm2;
1101 anm2 = 0;
1102 }
1103 /* pdt1 -> pdt0 へコピー */
1104 DSurfaceMove(dsurface[1], Rect(*dsurface[1]), surface, Rect(0,0));
1105 screen->SetSurface(surface, 0, 0);
1106 // 画像効果開始時に存在したobjectを消去
1107 // 新しい object 表示
1108 RefreshObj();
1109 return;
1110 }
1111 void GrpImpl::LoadSurface(const char* str) {
1112 if (anm1) AbortAnm(); // 前の描画が終わってなければ強制終了
1113 LoadSurface(str, 1);
1114 bg_name = str;
1115 }
1116 void GrpImpl::LoadSurface(void) {
1117 if (anm1) AbortAnm(); // 前の描画が終わってなければ強制終了
1118 LoadSurface(bg_name.c_str(), 1);
1119 }
1120 void GrpImpl::AddSurface(const char* str) {
1121 if (anm1) AbortAnm(); // 前の描画が終わってなければ強制終了
1122 LoadSurface(bg_name.c_str());
1123
1124 string s = str;
1125 Surface* front = parent.Root().NewSurface(s.c_str());
1126 if (front == 0) {
1127 s += ".g00";
1128 front = parent.Root().NewSurface(s.c_str());
1129 }
1130 if (front) {
1131 parent.Root().BlitSurface(front, Rect(*front), Dsurface(1), Rect(0,0));
1132 parent.Root().DeleteSurface(front);
1133 } else {
1134 fprintf(stderr,"Cannot find surface %s\n",str);
1135 }
1136 }
1137
1138 void GrpImpl::CreateObj(int index) {
1139 std::map<int, GrpObj>::iterator cur = grpobj.find(index);
1140 if (cur == grpobj.end()) return;
1141 GrpObj& g = grpobj[index];
1142 g.CreateSurface(&parent);
1143 g.order = index;
1144 if (g.picture == 0) return; // エラー:surface が存在しない
1145 g.picture->hide();
1146 SetObjChanged(index);
1147 ZMoveObj(index);
1148 return;
1149 }
1150 void GrpImpl::ZMoveObj(int index) {
1151 std::map<int, GrpObj>::iterator cur = grpobj.find(index);
1152 if (cur == grpobj.end()) return;
1153 GrpObj& g = grpobj[index];
1154 if (g.picture == 0) return;
1155 // 自分より前に object があれば、その前に表示
1156 // そうでなければ screen の前に表示
1157 std::map<int, GrpObj>::iterator cur_backobj = grpobj.end();
1158 std::map<int, GrpObj>::iterator it;
1159 for (it = grpobj.begin(); it != grpobj.end(); it++) {
1160 if (it == cur) continue;
1161 if (it->second.picture == 0) continue;
1162 if (it->second.order < g.order) {
1163 if (cur_backobj == grpobj.end()) {
1164 cur_backobj = it;
1165 } else if (cur_backobj->second.order < it->second.order) {
1166 cur_backobj = it;
1167 }
1168 }
1169 }
1170 if (cur_backobj == grpobj.end()) {
1171 g.picture->ZMove(screen);
1172 } else {
1173 g.picture->ZMove(cur_backobj->second.picture);
1174 }
1175 return;
1176 }
1177 void GrpImpl::SwapObj(int index1, int index2) {
1178 // デフォルト値から order が変更されていた場合のみ、order は保存される
1179 // まずは両方のobjectをswap
1180 if (grpobj.find(index1) == grpobj.end()) {
1181 if (grpobj.find(index2) == grpobj.end()) return; // どちらの object も存在しない
1182 grpobj[index1] = grpobj[index2];
1183 if (grpobj[index1].order == index2)
1184 grpobj[index1].order = index1;
1185 grpobj[index2].DeletePic();
1186 grpobj.erase(index2);
1187 ZMoveObj(index1);
1188 return;
1189 } else if (grpobj.find(index2) == grpobj.end()) { // index2 が存在しない場合
1190 grpobj[index2] = grpobj[index1];
1191 if (grpobj[index2].order == index1)
1192 grpobj[index2].order = index2;
1193 grpobj[index1].DeletePic();
1194 grpobj.erase(index1);
1195 ZMoveObj(index2);
1196 return;
1197 } else {
1198 GrpObj obj = grpobj[index1];
1199 grpobj[index1] = grpobj[index2];
1200 grpobj[index2].DeletePic();
1201 if (grpobj[index1].order == index2)
1202 grpobj[index1].order = index1;
1203 ZMoveObj(index1);
1204 grpobj[index2] = obj;
1205 if (grpobj[index2].order == index1)
1206 grpobj[index2].order = index2;
1207 ZMoveObj(index2);
1208 obj.DeletePic();
1209 }
1210 }
1211
1212 bool GrpImpl::Pressed(int x, int y, void* pointer) { // マウスクリックでキャンセル
1213 GrpImpl* g = (GrpImpl*)pointer;
1214 if (g->status == WAIT_MOVIE)
1215 g->music.StopMovie();
1216 if (g->status == WAIT_ANM)
1217 g->AbortAnm();
1218 if (g->status == WAIT_SHAKE && g->anm2 != 0) {
1219 delete g->anm2;
1220 g->anm2 = 0;
1221 }
1222 return false; // event deleted
1223 }
1224
1225 /* mode.cgm の decode 用 */
1226 static unsigned char decode_char[256] = {
1227 0x8b, 0xe5, 0x5d, 0xc3, 0xa1, 0xe0, 0x30, 0x44,
1228 0x00, 0x85, 0xc0, 0x74, 0x09, 0x5f, 0x5e, 0x33,
1229 0xc0, 0x5b, 0x8b, 0xe5, 0x5d, 0xc3, 0x8b, 0x45,
1230 0x0c, 0x85, 0xc0, 0x75, 0x14, 0x8b, 0x55, 0xec,
1231 0x83, 0xc2, 0x20, 0x52, 0x6a, 0x00, 0xe8, 0xf5,
1232 0x28, 0x01, 0x00, 0x83, 0xc4, 0x08, 0x89, 0x45,
1233 0x0c, 0x8b, 0x45, 0xe4, 0x6a, 0x00, 0x6a, 0x00,
1234 0x50, 0x53, 0xff, 0x15, 0x34, 0xb1, 0x43, 0x00,
1235 0x8b, 0x45, 0x10, 0x85, 0xc0, 0x74, 0x05, 0x8b,
1236 0x4d, 0xec, 0x89, 0x08, 0x8a, 0x45, 0xf0, 0x84,
1237 0xc0, 0x75, 0x78, 0xa1, 0xe0, 0x30, 0x44, 0x00,
1238 0x8b, 0x7d, 0xe8, 0x8b, 0x75, 0x0c, 0x85, 0xc0,
1239 0x75, 0x44, 0x8b, 0x1d, 0xd0, 0xb0, 0x43, 0x00,
1240 0x85, 0xff, 0x76, 0x37, 0x81, 0xff, 0x00, 0x00,
1241 0x04, 0x00, 0x6a, 0x00, 0x76, 0x43, 0x8b, 0x45,
1242 0xf8, 0x8d, 0x55, 0xfc, 0x52, 0x68, 0x00, 0x00,
1243 0x04, 0x00, 0x56, 0x50, 0xff, 0x15, 0x2c, 0xb1,
1244 0x43, 0x00, 0x6a, 0x05, 0xff, 0xd3, 0xa1, 0xe0,
1245 0x30, 0x44, 0x00, 0x81, 0xef, 0x00, 0x00, 0x04,
1246 0x00, 0x81, 0xc6, 0x00, 0x00, 0x04, 0x00, 0x85,
1247 0xc0, 0x74, 0xc5, 0x8b, 0x5d, 0xf8, 0x53, 0xe8,
1248 0xf4, 0xfb, 0xff, 0xff, 0x8b, 0x45, 0x0c, 0x83,
1249 0xc4, 0x04, 0x5f, 0x5e, 0x5b, 0x8b, 0xe5, 0x5d,
1250 0xc3, 0x8b, 0x55, 0xf8, 0x8d, 0x4d, 0xfc, 0x51,
1251 0x57, 0x56, 0x52, 0xff, 0x15, 0x2c, 0xb1, 0x43,
1252 0x00, 0xeb, 0xd8, 0x8b, 0x45, 0xe8, 0x83, 0xc0,
1253 0x20, 0x50, 0x6a, 0x00, 0xe8, 0x47, 0x28, 0x01,
1254 0x00, 0x8b, 0x7d, 0xe8, 0x89, 0x45, 0xf4, 0x8b,
1255 0xf0, 0xa1, 0xe0, 0x30, 0x44, 0x00, 0x83, 0xc4,
1256 0x08, 0x85, 0xc0, 0x75, 0x56, 0x8b, 0x1d, 0xd0,
1257 0xb0, 0x43, 0x00, 0x85, 0xff, 0x76, 0x49, 0x81,
1258 0xff, 0x00, 0x00, 0x04, 0x00, 0x6a, 0x00, 0x76
1259 };
1260
1261 void GrpImpl::LoadCgm(AyuSysConfig& config) {
1262 /* cgm ファイル読み込み */
1263 const char* fname = config.GetParaStr("#CGTABLE_FILE");
1264 if (fname == 0) return;
1265 ARCINFO* info = file_searcher.Find(FILESEARCH::ALL, fname, "");
1266 if (info == 0) return;
1267 char* data = info->CopyRead();
1268 int sz = info->Size();
1269 delete info;
1270
1271
1272 if ( strncmp(data, "CGTABLE", 7) != 0) return;
1273 int cgm_size = read_little_endian_int(data+0x10);
1274
1275 int i,j;
1276 // xor 解除
1277 for (i=0;i<sz-0x20; i++) {
1278 data[i+0x20]^=decode_char[i&0xff];
1279 }
1280 // 展開
1281 int dest_size = cgm_size * 36;
1282 char* dest = new char[dest_size+1024];
1283 char* src = data + 0x28;
1284 char* dest_orig = dest;
1285 ARCINFO::Extract2k(dest,src,dest+dest_size,data+sz);
1286 dest = dest_orig;
1287 for (i=0; i<cgm_size; i++) {
1288 char* s = dest + i * 36;
1289 int n = read_little_endian_int(dest + i * 36 + 32);
1290 cgm_info[s] = n;
1291 }
1292 delete[] dest_orig;
1293 }
1294
1295 /*****************************************************
1296 *
1297 * GrpImpl :: Save, Load : セーブファイル処理
1298 *
1299 */
1300 void GrpImpl::Save(std::string& str) {
1301 }
1302 void GrpImpl::Load(const char* str) {
1303 status = NORMAL;
1304 if (anm1) {
1305 AbortAnm();
1306 }
1307 if (anm2) {
1308 anm2->Abort();
1309 delete anm2;
1310 anm2 = 0;
1311 }
1312 map<int,GrpObj>::iterator it;
1313 for (it=grpobj.begin(); it!=grpobj.end(); it++) {
1314 PicBase* p = it->second.DeletePic();
1315 delete p;
1316 }
1317 grpobj.clear();
1318
1319 bg_name = "";
1320 music.StopCDROM(100);
1321 }
1322 void GrpImpl::SaveSys(string& save) {
1323 char buf[1024];
1324 save = "\n[Graphics]\n";
1325 save += "CGM_CG=";
1326
1327 set<int>::iterator it;
1328 for (it=cgm_data.begin(); it != cgm_data.end(); it++) {
1329 sprintf(buf,"%d,",*it);
1330 save += buf;
1331 }
1332 save += "\n";
1333 }
1334 void GrpImpl::LoadSys(const char* save) {
1335 cgm_data.clear();
1336 save = strstr(save, "\n[Graphics]\n");
1337
1338 if (save) {
1339 save += strlen("\n[Graphics]\n");
1340 do {
1341 if (save[0] == '[') break; // next section
1342 if (strncmp(save, "CGM_CG=",7) == 0) {
1343 save += 7;
1344 while(isdigit(*save)) {
1345 int n = atoi(save);
1346 cgm_data.insert(n);
1347 save = strchr(save, ',');
1348 if (save) save++;
1349 }
1350 }
1351 save = strchr(save, '\n');
1352 if (save) save++;
1353 } while (save);
1354 }
1355 return;
1356 }
1357
1358
1359 /*****************************************************
1360 *
1361 * GrpImpl :: Wait , Exec : コマンド実行部
1362 *
1363 */
1364 static vector<int> drawn_images;
1365 static int draw_n = 0;
1366 extern bool grpdump_req;
1367 bool GrpImpl::Wait(unsigned int current_time, Cmd& cmd) {
1368 if (grpdump_req) {
1369 grpdump_req = 0;
1370 std::map<int,GrpObj>::iterator it;
1371 fprintf(stderr,"front %08x(%d) / %08x(%d)\n",screen,screen->IsHidden(),screen_front,screen_front->IsHidden());
1372 for (it=grpobj.begin(); it != grpobj.end(); it++) {
1373 GrpObj& obj = it->second;
1374 GrpObj& parent_obj = grpobj[ ((it->first)/1000) * 1000];
1375 if (obj.picture) {
1376 if (!obj.name.empty()) {
1377 fprintf(stderr,"obj %06d(%08x): name %10s pos %d,%d alpha %d (%d/%d/%d)\n",
1378 it->first,obj.picture,obj.name.c_str(),
1379 obj.PosX(),obj.PosY(),obj.alpha,obj.attr&GrpObj::HIDDEN ? 1 : 0,parent_obj.attr&GrpObj::HIDDEN_GROUP ? 1 : 0,obj.picture->IsHidden());
1380 } else if (!obj.print_moji.empty()) {
1381 fprintf(stderr,"obj %06d(%08x): name %10s pos %d,%d alpha %d (%d/%d/%d)\n",
1382 it->first,obj.picture,obj.print_moji.c_str(),
1383 obj.PosX(),obj.PosY(),obj.alpha,obj.attr&GrpObj::HIDDEN ? 1 : 0,parent_obj.attr&GrpObj::HIDDEN_GROUP ? 1 : 0,obj.picture->IsHidden());
1384 } else {
1385 fprintf(stderr,"obj %06d(%08x): name %10s pos %d,%d alpha %d (%d/%d/%d)\n",
1386 it->first,obj.picture,"<EMPTY>",
1387 obj.PosX(),obj.PosY(),obj.alpha,obj.attr&GrpObj::HIDDEN ? 1 : 0,parent_obj.attr&GrpObj::HIDDEN_GROUP ? 1 : 0,obj.picture->IsHidden());
1388 }
1389 }
1390 }
1391 std::list<PicBase*>::iterator it2;
1392 for (it2=parent.children.begin(); it2!=parent.children.end();it2++) {
1393 fprintf(stderr,"%08x(%d)\n",*it2,(*it2)->IsHidden());
1394 }
1395 RefreshObj();
1396
1397 }
1398 #if 0
1399 if (event.presscount(MOUSE_UP)) {
1400 std::list<PicBase*>::iterator lit;
1401 draw_n++; int i=0;
1402 for (lit=parent.children.end(); lit!=parent.children.begin(); ) {
1403 lit--;
1404 (*lit)->hide();
1405 i++;
1406 if (i >= draw_n) break;
1407 }
1408 if (drawn_images.empty()) {
1409 map<int, GrpObj>::iterator it;
1410 for (it=grpobj.begin(); it!=grpobj.end(); it++) {
1411 if (it->second.picture) {
1412 drawn_images.push_back(it->first);
1413 PicBase* p = it->second.DeletePic();
1414 delete p;
1415 }
1416 }
1417 } else {
1418 vector<int>::iterator it;
1419 for (it=drawn_images.begin(); it!=drawn_images.end(); it++) {
1420 CreateObj(*it);
1421 }
1422 drawn_images.clear();
1423 }
1424 }
1425 #endif
1426 if (status == WAIT_ANM) {
1427 if (anm1) {
1428 if (!anm1->IsEnd()) return true;
1429 AbortAnm();
1430 }
1431 } else if (status == WAIT_SHAKE) {
1432 if (anm2) {
1433 if (!anm2->IsEnd()) return true;
1434 delete anm2;
1435 anm2 = 0;
1436 }
1437 status = NORMAL;
1438 } else if (status == WAIT_SE) {
1439 if (music.IsStopSE()) status = NORMAL;
1440 return true;
1441 } else if (status == WAIT_MOVIE) {
1442 if (music.IsStopMovie()) {
1443 music.StopMovie();
1444 status = NORMAL;
1445 screen->ReBlit();
1446 }
1447 return true;
1448 }
1449 if (anm2) {
1450 if (anm2->IsEnd()) {
1451 delete anm2;
1452 anm2 = 0;
1453 }
1454 }
1455 return false;
1456 }
1457
1458 void GrpImpl::DeleteObjPic(int num) { // object の surface のみ削除
1459 if (grpobj.find(num) == grpobj.end()) return;
1460 deleted_pic.push_back(grpobj[num].DeletePic());
1461 }
1462 void GrpImpl::DeleteObj(int num) {
1463 if (grpobj.find(num) == grpobj.end()) return;
1464 deleted_pic.push_back(grpobj[num].DeletePic());
1465 grpobj.erase(num);
1466 }
1467 void GrpImpl::DeleteObjRange(int num_first, int num_end) {
1468 std::map<int, GrpObj>::iterator begin,end,it;
1469 begin = grpobj.lower_bound(num_first);
1470 end = grpobj.lower_bound(num_end);
1471 for (it=begin;it!=end;it++) {
1472 deleted_pic.push_back(it->second.DeletePic());
1473 }
1474 grpobj.erase(begin, end);
1475 }
1476 void GrpImpl::Exec(Cmd& cmd) {
1477 if (cmd.cmd_type == CMD_TEXTEND) {
1478 music.StopKoe(500); // テキスト終了で声を止める
1479 cmd.clear();
1480 return;
1481 }
1482 if (cmd.cmd_type == CMD_WAITFRAMEUPDATE) {
1483 // wait する場合は RefreshObj() しておく
1484 RefreshObj();
1485 }
1486 if (cmd.cmd_type != CMD_OTHER) return;
1487 if (cmd.cmd1 == 1 && cmd.cmd2 == 0x1e && cmd.cmd3 == 0) {
1488 cmd.cmd_type = CMD_SAVECMDGRP_START; // grp stack clear
1489 }
1490 if (cmd.cmd1 == 1 && cmd.cmd2 == 0x21) {
1491 if (cmd.cmd3 == 0x46) {
1492 const char* name = cmd.Str(cmd.args[0]);
1493 int pdt = cmd.args[1].value;
1494 eprintf("load surface %s pdt %d\n",name, pdt);
1495 if (pdt == 0)
1496 reserved_load_surface0 = name; // 画像読み込みは 01-1f:0000 まで待つ
1497 else if (pdt == 1)
1498 LoadSurface(name); // 背景絵読み込み?
1499 else
1500 LoadSurface(name, pdt);
1501 cmd.cmd_type = CMD_SAVECMDGRP;
1502 } else if (cmd.cmd3 == 0x49) {
1503 const char* name = cmd.Str(cmd.args[0]);
1504 int sel = cmd.args[1].value;
1505 eprintf("set background %s sel %d\n",name, sel);
1506 if (name[0] == '?') {
1507 LoadSurface();
1508 } else {
1509 LoadSurface(name);
1510 }
1511 StartAnm(sel);
1512 status = WAIT_ANM;
1513 event.RegisterGlobalPressFunc(&Pressed, (void*)this);
1514 if (name[0] == '?')
1515 cmd.cmd_type = CMD_SAVECMDGRP_ONCE;
1516 else
1517 cmd.cmd_type = CMD_SAVECMDGRP_START;
1518 } else if (cmd.cmd3 == 0x4b) {
1519 int pos = cmd.args[0].value;
1520 const char* name = cmd.Str(cmd.args[1]);
1521 int sel = cmd.args[2].value;
1522 eprintf("set foreground %s sel %d pos %d\n",name, sel, pos);
1523 AddSurface(name);
1524 StartAnm(sel);
1525 event.RegisterGlobalPressFunc(&Pressed, (void*)this);
1526 status = WAIT_ANM;
1527 cmd.cmd_type = CMD_SAVECMDGRP_ONCE;
1528 } else if (cmd.cmd3 == 0x4c) {
1529 /* 0x46 との違いがわからない */
1530 /* とりあえず bg として登録しないでみる */
1531 /* 735 / 19438 : unsupported command; 0x23 - cmd 01-21:004c:00[ 2]
1532 ** "?",0
1533 */
1534 /* arg1 = "?" arg2 = 0 */
1535 const char* name = cmd.Str(cmd.args[0]);
1536 int sel = cmd.args[1].value;
1537 if (name[0] == '?') {
1538 LoadSurface();
1539 } else {
1540 LoadSurface(name, 1);
1541 }
1542 StartAnm(sel);
1543 status = WAIT_ANM;
1544 event.RegisterGlobalPressFunc(&Pressed, (void*)this);
1545 if (name[0] == '?')
1546 cmd.cmd_type = CMD_SAVECMDGRP_ONCE;
1547 else
1548 cmd.cmd_type = CMD_SAVECMDGRP_START;
1549 } else if (cmd.cmd3 == 0x20) {
1550 // shake screen
1551 char key[1024];
1552 sprintf(key, "#SHAKE.%03d", cmd.args[0].value);
1553 if (config.SearchParam(key) != 2) {
1554 fprintf(stderr,"Cannot find shake pattern %d; use default pattern\n",cmd.args[0].value);
1555 strcpy(key, "#SHAKE.000"); // default key
1556 }
1557 int num; const int* pattern;
1558 pattern = config.GetParamArray(key, num);
1559 if (pattern) {
1560 StartShake(num, pattern);
1561 status = WAIT_SHAKE;
1562 }
1563 cmd.clear();
1564 } else if (cmd.cmd3 == 0x64 && cmd.cmd4 == 2) { // copy (KANOGI)
1565 int sx = cmd.args[0].value;
1566 int sy = cmd.args[1].value;
1567 int w = cmd.args[2].value - sx;
1568 int h = cmd.args[3].value - sy;
1569 Rect rect(sx, sy, sx+w, sy+h);
1570 int src = cmd.args[4].value;
1571 int dx = cmd.args[5].value;
1572 int dy = cmd.args[6].value;
1573 int dest = cmd.args[7].value;
1574 unsigned char alpha;
1575 eprintf("copy surface %d:(%d,%d) size(%d,%d) -> %d:(%d,%d)\n",src,sx,sy,w,h,dest,dx,dy);
1576 printf("copy surface %d:(%d,%d) size(%d,%d) -> %d:(%d,%d)\n",src,sx,sy,w,h,dest,dx,dy);
1577 if (src == dest) {
1578 DSurfaceMove(Ssurface(src), rect, Dsurface(WORKPDT), rect);
1579 src = WORKPDT;
1580 }
1581 parent.Root().BlitSurface(Ssurface(src), rect, Dsurface(dest), Rect(dx,dy));
1582 if (dest == 0) screen->ReBlit(Rect(dx,dy,dx+w,dy+h));
1583 cmd.clear();
1584 } else if (cmd.cmd3 == 0x4b1 && cmd.cmd4 == 2) {
1585 int x = cmd.args[0].value;
1586 int y = cmd.args[1].value;
1587 int w = cmd.args[2].value;
1588 int h = cmd.args[3].value;
1589 Rect rect(x,y,x+w,y+w);
1590 int pdt = cmd.args[4].value;
1591 int r = cmd.args[5].value;
1592 int g = cmd.args[6].value;
1593 int b = cmd.args[7].value;
1594 eprintf("clear %d:(%d,%d) size (%d,%d) r %d g %d b %d\n",pdt,x,y,w,h,r,g,b);
1595 DSurfaceFill(Dsurface(pdt), rect, r, g, b, 0xff);
1596 // if (pdt == 0) screen->ReBlit(rect);
1597 cmd.cmd_type = CMD_SAVECMDGRP;
1598 } else if (cmd.cmd3 == 0x4b1 && cmd.cmd4 == 3) { // alpha つきfill
1599 int x = cmd.args[0].value;
1600 int y = cmd.args[1].value;
1601 int w = cmd.args[2].value;
1602 int h = cmd.args[3].value;
1603 Rect rect(x,y,x+w,y+h);
1604 int pdt = cmd.args[4].value;
1605 int r = cmd.args[5].value;
1606 int g = cmd.args[6].value;
1607 int b = cmd.args[7].value;
1608 int a = cmd.args[8].value;
1609 eprintf("alpha-clear %d:(%d,%d) size (%d,%d) r %d g %d b %d a %d\n",pdt,x,y,w,h,r,g,b,a);
1610 if (a <= 0) ;
1611 else if (a >= 255) DSurfaceFill(Dsurface(pdt), rect, r, g, b);
1612 else {
1613 DSurfaceFill(Dsurface(WORKPDT), rect, r, g, b, a);
1614 parent.Root().BlitSurface(Dsurface(WORKPDT), rect, Dsurface(pdt), rect);
1615 }
1616 // if (pdt == 0) screen->ReBlit(rect);
1617 cmd.clear();
1618 } else if (cmd.cmd3 == 0x44c && cmd.cmd4 == 2) {
1619 int sx = cmd.args[0].value;
1620 int sy = cmd.args[1].value;
1621 int w = cmd.args[2].value;
1622 int h = cmd.args[3].value;
1623 int src = cmd.args[4].value;
1624 int dx = cmd.args[5].value;
1625 int dy = cmd.args[6].value;
1626 int dest = cmd.args[7].value;
1627 eprintf("copy surface %d:(%d,%d) size(%d,%d) -> %d:(%d,%d)\n",src,sx,sy,w,h,dest,dx,dy);
1628 parent.Root().BlitSurface(Ssurface(src), Rect(sx,sy,sx+w,sy+h), Dsurface(dest), Rect(dx,dy));
1629 //DSurfaceMove(Ssurface(src), Rect(sx,sy,sx+w,sy+h), Dsurface(dest), Rect(dx,dy));
1630 // if (dest == 0) screen->ReBlit(Rect(dx,dy,dx+w,dy+h));
1631 cmd.cmd_type = CMD_SAVECMDGRP;
1632 } else if (cmd.cmd3 == 0x44c && cmd.cmd4 == 3) { // alpha つきcopy
1633 int sx = cmd.args[0].value;
1634 int sy = cmd.args[1].value;
1635 int w = cmd.args[2].value;
1636 int h = cmd.args[3].value;
1637 Rect rect(sx, sy, sx+w, sy+h);
1638 int src = cmd.args[4].value;
1639 int dx = cmd.args[5].value;
1640 int dy = cmd.args[6].value;
1641 int dest = cmd.args[7].value;
1642 unsigned char alpha;
1643 if (cmd.args[8].value < 0) alpha = 0;
1644 else if (cmd.args[8].value > 255) alpha = 255;
1645 else alpha = cmd.args[8].value;
1646 eprintf("copy surface %d:(%d,%d) size(%d,%d) -> %d:(%d,%d)\n",src,sx,sy,w,h,dest,dx,dy);
1647 if (src == dest) {
1648 DSurfaceMove(Ssurface(src), rect, Dsurface(WORKPDT), rect);
1649 src = WORKPDT;
1650 }
1651 if (alpha != 0)
1652 parent.Root().BlitSurface(Ssurface(src), rect, &alpha, Rect(0,0,1,1), Dsurface(dest), Rect(dx,dy), 0);
1653 // if (dest == 0) screen->ReBlit(Rect(dx,dy,dx+w,dy+h));
1654 cmd.clear();
1655 } else if (cmd.cmd3 == 0x640 && cmd.cmd4 == 3) { // saturate mode で alpha 付き copy
1656 int sx = cmd.args[0].value;
1657 int sy = cmd.args[1].value;
1658 int w = cmd.args[2].value;
1659 int h = cmd.args[3].value;
1660 Rect rect(sx, sy, sx+w, sy+h);
1661 int src = cmd.args[4].value;
1662 int dx = cmd.args[5].value;
1663 int dy = cmd.args[6].value;
1664 int dest = cmd.args[7].value;
1665 unsigned char alpha;
1666 if (cmd.args[8].value < 0) alpha = 0;
1667 else if (cmd.args[8].value > 255) alpha = 255;
1668 else alpha = cmd.args[8].value;
1669 eprintf("copy surface w/ saturate %d:(%d,%d) size(%d,%d) -> %d:(%d,%d)\n",src,sx,sy,w,h,dest,dx,dy);
1670 if (src == dest) {
1671 DSurfaceMove(Ssurface(src), rect, Dsurface(WORKPDT), rect);
1672 src = WORKPDT;
1673 }
1674 if (alpha != 0) {
1675 // saturate mode : screen (picture) を一時的に作成
1676 PicBase* screen_tmp = parent.create_leaf(Rect(0, 0, parent.Width(), parent.Height()), 0);
1677 screen_tmp->SetSurface(Ssurface(src), 0, 0, PicBase::BLIT_SATURATE);
1678 screen_tmp->SetSurfaceRect(rect);
1679 screen_tmp->Move(dx, dy);
1680 screen_tmp->SetSurfaceAlpha(&alpha, Rect(0,0,1,1));
1681 screen_tmp->SimpleBlit(Dsurface(dest));
1682 delete screen_tmp;
1683 }
1684 cmd.clear();
1685 } else if (cmd.cmd3 == 0x196 && cmd.cmd4 == 0) {
1686 Rect r_from(cmd.args[0].value, cmd.args[1].value);
1687 Rect r_to(cmd.args[2].value, cmd.args[3].value);
1688 int src_pdt = cmd.args[4].value;
1689 Rect r(cmd.args[5].value,cmd.args[6].value,cmd.args[7].value+1,cmd.args[8].value+1);
1690 int tm = cmd.args[9].value;
1691 fprintf(stderr,"??? cmd time %d\n",tm);
1692 // anm1 = new ScnGrpMove(event, screen, parent.Root(), surface, r, Ssurface(2), r_from, r_to, tm);
1693 // status = WAIT_ANM;
1694 }
1695 }
1696 if (cmd.cmd1 == 1 && cmd.cmd2 == 0x22) {
1697 if (cmd.cmd3 == 0x0c30 && cmd.cmd4 == 0) { // スクロールする画像効果(Princess Bride)
1698 if (anm2) {
1699 anm2->Abort();
1700 delete anm2;
1701 }
1702 PicBase* pic; Surface* s;
1703 Rect r(cmd.args[1].value, cmd.args[2].value, cmd.args[3].value+1, cmd.args[4].value+1);
1704 const char* name = cmd.Str(cmd.args[5]);
1705 Rect sr_start(cmd.args[6].value,cmd.args[7].value);
1706 Rect sr_end(cmd.args[8].value,cmd.args[9].value);
1707 int tm = cmd.args[10].value;
1708 LoadSurface(name, 2); /* PDT2 に読み込み、と決め打ち */
1709
1710 anm2 = new ScnGrpMove(event, screen, parent.Root(), Dsurface(1), r, Ssurface(2), sr_start, sr_end, tm);
1711 cmd.cmd_type = CMD_SAVECMDGRP;
1712 }
1713 if ( (cmd.cmd3 == 0xc1c && cmd.cmd4 == 0) || (cmd.cmd3 == 0x835 && cmd.cmd4 == 0) ) {
1714 // カードが落ちるアニメーション
1715 int i;
1716 ScnGrpAnm* new_anm = new ScnGrpAnm(event, screen, *this);
1717 if (cmd.cmd3 == 0x835) {
1718 AbortAnm();
1719 anm1 = new_anm;
1720 status = WAIT_ANM;
1721 event.RegisterGlobalPressFunc(&Pressed, (void*)this);
1722 } else {
1723 anm2 = new_anm;
1724 }
1725 for (i=0; i<cmd.argc; i++) {
1726 const char* name = cmd.Str(cmd.args[i*3+1]);
1727 int tm = cmd.args[i*3+2].value;
1728 new_anm->push_back(ScnGrpAnmAtom(name,tm));
1729 }
1730 new_anm->CalcTotal();
1731 cmd.clear();
1732 }
1733 }
1734 if (cmd.cmd1 == 1 && cmd.cmd2 == 4) {
1735 if (cmd.cmd3 == 0xd8 || cmd.cmd3 == 0xd3 || cmd.cmd3 == 0xd2 || cmd.cmd3 == 0xd7) {
1736 cmd.clear(); // いつも 0xd8 / 0xd7 と組で出てくる
1737 }
1738 if (cmd.cmd3 == 0x5e0) { // 画像既視フラグを得る
1739 string s = cmd.Str(cmd.args[0]);
1740 if (cgm_info.find(s) == cgm_info.end()) {
1741 fprintf(stderr,"cmd 01-04:05e0 : cannot find cgm-info of '%s'\n",s.c_str());
1742 return;
1743 }
1744 int n = cgm_info[s];
1745 if (cgm_data.find(n) == cgm_data.end()) cmd.SetSysvar(0);
1746 else cmd.SetSysvar(1);
1747 }
1748 }
1749 #if 1
1750 /* object 操作 */
1751 if ( (cmd.cmd1 == 1 || cmd.cmd1 == 2) && (cmd.cmd2 == 0x3d || cmd.cmd2 == 0x3e) && (cmd.cmd3 == 0x0a || cmd.cmd3 == 0x0b || cmd.cmd3 == 0x0e)) { // clear object
1752 if (cmd.cmd3 == 0x0a || cmd.cmd3 == 0x0b) {
1753 if (cmd.cmd1 == 2 && cmd.args.size() == 2) {
1754 int num = cmd.args[0].value*1000 + cmd.args[1].value + 500;
1755 DeleteObj(num);
1756 } else if (cmd.args.size() == 1) { // group ごと消去
1757 int num_first = cmd.args[0].value * 1000;
1758 int num_end = num_first+1000;
1759 DeleteObjRange(num_first, num_end);
1760 }
1761 } else { // 0x0e
1762 if (cmd.cmd1 == 1 && cmd.args.size() == 2) {
1763 SwapObj(cmd.args[0].value * 1000, cmd.args[1].value * 1000);
1764 } else if (cmd.cmd1 == 2 && cmd.args.size() == 3) {
1765 int v1 = cmd.args[0].value*1000 + cmd.args[1].value + 500;
1766 int v2 = cmd.args[0].value*1000 + cmd.args[2].value + 500;
1767 SwapObj(v1, v2);
1768 }
1769 }
1770 cmd.clear();
1771 }
1772 if (cmd.cmd1 == 1 && cmd.cmd2 == 0x3c && cmd.cmd3 == 0x01) { // ??? : CLANNAD
1773 cmd.clear();
1774 }
1775 if (cmd.cmd1 == 1 && cmd.cmd2 == 0x3c && cmd.cmd3 == 0) { // ??? : KANOGI : 画像オブジェクトの削除?
1776 DeleteObjPic(cmd.args[0].value * 1000); // 旧ファイル名のsurfaceを削除
1777 GrpObj& g = grpobj[cmd.args[0].value * 1000];
1778 g.attr = GrpObj::Attribute(g.attr | GrpObj::HIDDEN);
1779 cmd.clear();
1780 }
1781 if ( (cmd.cmd1 == 1 || cmd.cmd1 == 2) && (cmd.cmd2 == 0x47 || cmd.cmd2 == 0x48|| cmd.cmd2 == 0x49 || cmd.cmd2 == 0x51 || cmd.cmd2 == 0x52 || cmd.cmd2 == 0x54)) {
1782 if (cmd.cmd1 == 1) {
1783 if (cmd.args.size() >= 1) cmd.args[0].value *= 1000; // とりあえず 1000倍しておく
1784 } else { // cmd.cmd2 == 2
1785 // オブジェクト番号を指定するコマンド引数が一つ増えているのを消去
1786 vector<VarInfo> args = cmd.args;
1787 cmd.args.clear();
1788 if (args.size() >= 2) {
1789 cmd.args.push_back(args[0].value*1000 + args[1].value + 500);
1790 cmd.args.insert(cmd.args.end(), args.begin()+2, args.end());
1791 }
1792 }
1793 if (cmd.cmd2 == 0x47) {
1794 /**************:
1795 0x47 : オブジェクト内容の設定
1796 0x3e8: G00 ファイル
1797 0x3eb: GAN ファイル
1798 0x44c: 矩形領域
1799 0x4b0: 文字列
1800 0x514: 天候効果
1801 0x578: 数字の画像表示
1802 */
1803 int base_argc = 0;
1804 DeleteObjPic(cmd.args[0].value); // 旧ファイル名のsurfaceを削除
1805 GrpObj& g = grpobj[cmd.args[0].value];
1806 if (cmd.cmd3 == 0x3e8) { /* ファイル名設定 */
1807 g.gtype = GrpObj::FILE;
1808 string name = cmd.Str(cmd.args[1]);
1809 if (name.find('?') != -1) {
1810 name.erase(name.find('?')); // '?' 以降の意味がわからない
1811 }
1812 g.name = name;
1813 } else if (cmd.cmd3 == 0x3eb) { /* ファイル名設定(GAN含む) */
1814 g.gtype = GrpObj::GAN;
1815 if (cmd.Str(cmd.args[1]) == string("???"))
1816 g.name = cmd.Str(cmd.args[2]);
1817 else
1818 g.name = cmd.Str(cmd.args[1]);
1819 g.gan_name = cmd.Str(cmd.args[2]);
1820 } else if (cmd.cmd3 == 0x4b0) { // 画像を文字列として指定
1821 g.gtype = GrpObj::MOJI;
1822 g.print_moji = cmd.Str(cmd.args[1]);
1823 g.attr = GrpObj::Attribute(g.attr & (~GrpObj::HIDDEN)); // 常に表示がデフォルト?
1824 cmd.clear();
1825 } else if (cmd.cmd3 == 0x578) { // 数値を画像として表示
1826 g.gtype = GrpObj::DIGIT;
1827 g.name = cmd.Str(cmd.args[1]);
1828 }
1829 CreateObj(cmd.args[0].value);
1830 if (cmd.cmd3 == 0x3e8 || cmd.cmd3 == 0x3eb || cmd.cmd3 == 0x4b0 || cmd.cmd3 == 0x578) {
1831 // FILE, GAN, MOJI, DIGIT ならば座標等の設定を行う
1832 if (cmd.cmd4 >= 1+base_argc) {
1833 if (cmd.args[2+base_argc].value == 0) {
1834 if (cmd.cmd1 == 1)
1835 g.attr = GrpObj::Attribute(g.attr | GrpObj::HIDDEN | GrpObj::HIDDEN_GROUP);
1836 else
1837 g.attr = GrpObj::Attribute(g.attr | GrpObj::HIDDEN);
1838 } else {
1839 if (cmd.cmd1 == 1)
1840 g.attr = GrpObj::Attribute(g.attr & (~(GrpObj::HIDDEN | GrpObj::HIDDEN_GROUP)));
1841 else
1842 g.attr = GrpObj::Attribute(g.attr & (~GrpObj::HIDDEN));
1843 }
1844 if (cmd.cmd1 == 1)
1845 SetObjChangedGroup(cmd.args[0].value);
1846 }
1847 if (cmd.cmd4 >= 2+base_argc) { // 座標等も設定
1848 g.SetPos(0,cmd.args[3+base_argc].value, cmd.args[4+base_argc].value);
1849 }
1850 if ( (cmd.cmd3 == 0x3e8 || cmd.cmd3 == 0x3eb) && cmd.cmd4 >= 4+base_argc) { // pattern 番号も設定
1851 g.SetSurfaceNum(cmd.args[5+base_argc].value);
1852 base_argc++; // 0x3e8 (FILE) / 0x3eb (GAN) の場合のみこのオプションは存在する
1853 }
1854 cmd.clear();
1855 } else {
1856 fprintf(stderr,"CreateObj : cmd.cmd3 = %04x ; not supported!\n",cmd.cmd3);
1857 }
1858 } else if (cmd.cmd2 == 0x48) {
1859 // 画面切り替え後の object (back screen object) 設定
1860 if (cmd.cmd3 == 0x3e8) {
1861 // cmd.cmd4 == 0 : args = 2, CLANNAD : cg mode
1862 // cmd.cmd4 == 1 : args = 3, CLANNAD : 春原回想?のところで画面が黒くなってしまうので、とりあえず。
1863 // cmd.cmd4 == 2 : args = 5, KANOGI : Fore Graphics
1864 // cmd.cmd4 == 3 : args = 6, KANOGI : CG mode
1865 GrpObj& g = bs_obj[cmd.args[0].value];
1866 string name = cmd.Str(cmd.args[1]);
1867 if (name.find('?') != -1) {
1868 name.erase(name.find('?')); // '?' 以降の意味がわからない
1869 }
1870 g.gtype = GrpObj::FILE;
1871 g.name = name;
1872 if (cmd.cmd4 >= 1 && cmd.args[2].value == 0)
1873 g.attr = GrpObj::Attribute(g.attr | GrpObj::HIDDEN);
1874 else
1875 g.attr = GrpObj::Attribute(g.attr & ~(GrpObj::HIDDEN));
1876 if (cmd.cmd4 >= 2)
1877 g.SetPos(0,cmd.args[3].value, cmd.args[4].value);
1878 if (cmd.cmd4 >= 3)
1879 g.SetSurfaceNum(cmd.args[5].value);
1880 if (cmd.cmd4 <= 3)
1881 cmd.cmd_type = CMD_SAVECMDGRP;
1882 }
1883 } else if (cmd.cmd2 == 0x49) {
1884 if (cmd.cmd3 == 0) { // アニメーションを強制終了
1885 GrpObj& g = grpobj[cmd.args[0].value];
1886 if (g.anm == 0 || g.anm->IsEnd()) ;
1887 else g.anm->Abort();
1888 } else if (cmd.cmd3 == 3) { // アニメーション中か?
1889 GrpObj& g = grpobj[cmd.args[0].value];
1890 if (g.anm == 0 || g.anm->IsEnd()) {
1891 cmd.SetSysvar(0);
1892 } else {
1893 cmd.SetSysvar(1);
1894 }
1895 } else if (cmd.cmd3 == 1000) {
1896 // アニメーションを途中で停止した状態にする
1897 GrpObj& g = grpobj[cmd.args[0].value];
1898 if (g.anm == 0 || g.anm->IsEnd()) {
1899 // fprintf(stderr,"AnimPause : no animation in %d (%d)\n",cmd.args[0].value, cmd.args[1].value);
1900 g.SetSurfaceNum(cmd.args[1].value);
1901 } else {
1902 g.anm->Abort();
1903 g.SetSurfaceNum(cmd.args[1].value);
1904 }
1905 SetObjChanged(cmd.args[0].value);
1906 cmd.clear();
1907 } else if (cmd.cmd3 == 0x7d3) { // surface を増加させる画像効果
1908 GrpObj& g = grpobj[cmd.args[0].value];
1909 g.CreateGanSpecial(event, 0, cmd.args[1].value);
1910 // g.attr = GrpObj::Attribute(g.attr & (~GrpObj::HIDDEN));
1911 SetObjChanged(cmd.args[0].value);
1912 cmd.clear();
1913 } else if (cmd.cmd3 == 0xbbd || cmd.cmd3 == 0xbbb || cmd.cmd3 == 0xbb9) { // アニメーション開始
1914 GrpObj& g = grpobj[cmd.args[0].value];
1915 g.CreateGan(event, cmd.args[1].value);
1916 // g.attr = GrpObj::Attribute(g.attr & (~GrpObj::HIDDEN));
1917 SetObjChanged(cmd.args[0].value);
1918 cmd.clear();
1919 }
1920 } else if (cmd.cmd2 == 0x51 || cmd.cmd2 == 0x52) {
1921 GrpObj& g = (cmd.cmd2 == 0x51) ?
1922 grpobj[cmd.args[0].value] :
1923 bs_obj[cmd.args[0].value];
1924 if (cmd.cmd3 == 0x3e8) { /* 座標設定 */
1925 g.SetPos(0,cmd.args[1].value, cmd.args[2].value);
1926 cmd.clear();
1927 } else if (cmd.cmd3 == 0x3e9 || cmd.cmd3 == 0x3ea) { /* x / y 座標のみ設定 */
1928 int x0, y0;
1929 g.GetPos(0, x0, y0);
1930 if (cmd.cmd3 == 0x3e9)
1931 g.SetPos(0,cmd.args[1].value, y0);
1932 else
1933 g.SetPos(0,x0, cmd.args[1].value);
1934 cmd.clear();
1935 } else if (cmd.cmd3 == 0x3eb) { /* alpha */
1936 g.SetAlpha(cmd.args[1].value);
1937 cmd.clear();
1938 } else if (cmd.cmd3 == 0x3ec) { /* visible flag */
1939 if (cmd.cmd1 == 1) {
1940 if (cmd.args[1].value) g.attr = GrpObj::Attribute(g.attr & (~(GrpObj::HIDDEN | GrpObj::HIDDEN_GROUP)));
1941 else g.attr = GrpObj::Attribute(g.attr | GrpObj::HIDDEN | GrpObj::HIDDEN_GROUP);
1942 } else {
1943 if (cmd.args[1].value) g.attr = GrpObj::Attribute(g.attr & (~GrpObj::HIDDEN));
1944 else g.attr = GrpObj::Attribute(g.attr | GrpObj::HIDDEN);
1945 }
1946 g.attr = GrpObj::Attribute(g.attr | GrpObj::UPDATE_VISIBLE);
1947 // グループ単位で次の RefreshObj で表示・消去
1948 if (cmd.cmd2 == 0x51 && cmd.cmd1 == 1)
1949 SetObjChangedGroup(cmd.args[0].value);
1950 cmd.clear();
1951 } else if (cmd.cmd3 == 0x3ee || cmd.cmd3 == 0x7d6) { /* 座標設定その2? */
1952 /* 0x7d6 : 画像側の基準座標を args[4,5] に入れているのかもしれない */
1953 int index = cmd.args[1].value;
1954 int x = cmd.args[2].value;
1955 int y = cmd.args[3].value;
1956 g.SetPos(index+1, x, y);
1957 cmd.clear();
1958 } else if (cmd.cmd3 == 0x3f8) { // 画像を文字列として設定:色の設定
1959 g.print_r = cmd.args[1].value;
1960 g.print_g = cmd.args[2].value;
1961 g.print_b = cmd.args[3].value;
1962 g.SetUpdate();
1963 // grpobj[cmd.args[0].value].print_a = cmd.args[4].value;
1964 /* args:229,18,minus-1,0,99,255,-1 */
1965 /* args:102,26,minus-1,0,99,0,255 */
1966 cmd.clear();
1967 } else if (cmd.cmd3 == 0x3fd) { // centering mode などを設定?
1968 if (cmd.args[1].value == 1) {
1969 g.attr = GrpObj::Attribute(g.attr | GrpObj::SATURATE);
1970 cmd.clear();
1971 } else if (cmd.args[1].value == 0) {
1972 g.attr = GrpObj::Attribute(g.attr & (~GrpObj::SATURATE));
1973 cmd.clear();
1974 }
1975 g.SetUpdate();
1976 /* cmd3 == 0x41c : ゲームの進行とともに
1977 args:10,105
1978 args:10,133
1979 args:10,144
1980 args:10,144
1981 と変化
1982
1983 cmd3 == 0x418 :
1984 args: 10, 400 -> 100
1985 と、alpha の増加とともに変化
1986 */
1987 /*
1988 487 / 8047 : unsupported command; 0x23 - cmd 01-51:0419:00[ 2]
1989 81,-40,
1990 第二引数の 1/10 がオブジェクトの回転角
1991 */
1992 } else if (cmd.cmd3 == 0x400) { // 画像を文字列として指定
1993 g.print_moji = cmd.Str(cmd.args[1]);
1994 g.SetUpdate();
1995 cmd.clear();
1996 } else if (cmd.cmd3 == 0x401) { // 画像を文字列として設定:文字の大きさなど
1997 /* args: size, xspace, yspace, vertical, color, shadow */
1998 /*
1999 args:17, 0,0,-1, 0,-1 DT in Tomoyo
2000 args:17, 0,0,-1,200,-1 Save/Load in Tomoyo
2001 args:20, 0,0, 0,255,-1 "──ありがとう…。" (勝平Ed付近)
2002 args:16,-1,0,99,255,-1 "やあ、久しぶり──…。" (同上,Save/Load Menu)
2003 args:26,-1,0,99, 0,255 Kuma in CLANNAD
2004 */
2005 g.print_size = cmd.args[1].value;
2006 /* 前景色を得る */
2007 int cr,cg,cb; char key[1024];
2008 sprintf(key, "#COLOR_TABLE.%03d", cmd.args[5].value);
2009 if (config.GetParam(key, 3, &cr, &cg, &cb)) { // color not found
2010 cr = cg = cb = 0;
2011 }
2012 g.print_r = cr;
2013 g.print_g = cg;
2014 g.print_b = cb;
2015 g.SetUpdate();
2016 cmd.clear();
2017 } else if (cmd.cmd3 == 0x408) { // set order
2018 int order = cmd.args[1].value;
2019 if (cmd.cmd1 == 1) order *= 1000; // order も 1000 倍する必要がある?
2020 g.order = order;
2021 ZMoveObj(cmd.args[0].value);
2022 cmd.clear();
2023 } else if (cmd.cmd3 == 0x40a && cmd.cmd4 == 1) { // set surface geometry?
2024 // オブジェクトのどの部分を画面に表示するか(クリップ領域)の設定
2025 int rx = cmd.args[1].value;
2026 int ry = cmd.args[2].value;
2027 g.SetClipArea(cmd.args[1].value, cmd.args[2].value, cmd.args[3].value,cmd.args[4].value);
2028 cmd.clear();
2029 } else if (cmd.cmd3 == 0x40d) { // set digit number
2030 g.dig_number = cmd.args[1].value;
2031 g.SetUpdate();
2032 cmd.clear();
2033 } else if (cmd.cmd3 == 0x40e) { // set digit option
2034 g.dig_digit = cmd.args[1].value;
2035 int attr = g.attr;
2036 attr &= ~(GrpObj::DIG_ZERO | GrpObj::DIG_SIGN | GrpObj::DIG_PACK);
2037 if (cmd.args[2].value) attr |= GrpObj::DIG_ZERO;
2038 if (cmd.args[3].value) attr |= GrpObj::DIG_SIGN;
2039 if (cmd.args[4].value) attr |= GrpObj::DIG_PACK;
2040 g.attr = GrpObj::Attribute(attr);
2041 g.SetUpdate();
2042 cmd.clear();
2043 } else if (cmd.cmd3 == 0x40f) { /* set surface number */
2044 g.SetSurfaceNum(cmd.args[1].value);
2045 cmd.clear();
2046 } else if (cmd.cmd3 == 0x416) { // オブジェクトの拡大率設定
2047 int zoom = (cmd.args[1].value + cmd.args[2].value)/2; // x,y 別に設定できるらしい
2048 zoom = zoom*256/100;
2049 g.SetZoomRotate(zoom, -1);
2050 cmd.clear();
2051 } else if (cmd.cmd3 == 0x419) { // オブジェクトの回転設定
2052 int angle = cmd.args[1].value;
2053 angle /= 10;
2054 if (angle < 0) {
2055 angle %= 360;
2056 angle += 360;
2057 }
2058 angle %= 360;
2059 g.SetZoomRotate(-1, angle);
2060 cmd.clear();
2061 }
2062 if (cmd.cmd2 == 0x51 && (g.attr & GrpObj::UPDATE_ALL)) {
2063 SetObjChanged(cmd.args[0].value);
2064 }
2065 } else if (cmd.cmd2 == 0x54) {
2066 /* 座標取得 */
2067 if (cmd.cmd3 == 0x3e8) {
2068 GrpObj& obj = grpobj[cmd.args[0].value];
2069 VarInfo arg1 = cmd.args[1];
2070 VarInfo arg2 = cmd.args[2];
2071 int x0, y0;
2072 obj.GetPos(0,x0, y0);
2073 cmd.SetFlagvar(arg1, x0);
2074 cmd.SetFlagvar(arg2, y0);
2075 } else if (cmd.cmd3 == 0x44c) {
2076 int w, h;
2077 GrpObj& obj = grpobj[cmd.args[0].value];
2078 obj.GetSrcGeom(w, h);
2079 VarInfo arg1 = cmd.args[1];
2080 VarInfo arg2 = cmd.args[2];
2081 cmd.SetFlagvar(arg1, w);
2082 cmd.SetFlagvar(arg2, h);
2083 }
2084 }
2085 // セーブ用にコマンドを元に戻す
2086 if (cmd.args.size() != 0 && (cmd.cmd_type == CMD_SAVECMDGRP || cmd.cmd_type == CMD_SAVECMDGRP_ONCE)) {
2087 if (cmd.cmd1 == 1) cmd.args[0].value /= 1000;
2088 else if (cmd.cmd1 == 2) {
2089 vector<VarInfo> args = cmd.args;
2090 int value = args[0].value;
2091 cmd.args.clear();
2092 args[0].value = value / 1000;
2093 cmd.args.push_back(args[0]);
2094 args[0].value = value % 1000 - 500;
2095 cmd.args.push_back(args[0]);
2096 cmd.args.insert(cmd.args.end(), args.begin()+1, args.end());
2097 }
2098 }
2099 }
2100 #endif
2101 if (cmd.cmd1 == 1 && cmd.cmd2 == 0x1f) { // 本来は grpstack clear らしい
2102 RefreshObj();
2103 // Princess Bride の中途 Staff roll
2104 // このタイミングで描画するのが都合がいいので、
2105 //シナリオループを抜けて描画を起動
2106 cmd.cmd_type = CMD_WAITFRAMEUPDATE;
2107 }
2108
2109 /* XXX : GiGiGi */
2110 /* 122 : 0x23 - cmd 01-04:0924:00[ 0] : V<sys> にBGM再生モードを返す (0/1)
2111 ** 256 : 0x23 - cmd 01-04:091a:00[ 0] : V<sys> にBGM音量を返す (0-255?)
2112 ** 278 : 0x23 - cmd 01-04:0926:00[ 0] : V<sys> にEff再生モードを返す (0/1)
2113 ** 412 : 0x23 - cmd 01-04:091c:00[ 0] : V<sys> にEff音量を返す (0-255?)
2114 ** 434 : 0x23 - cmd 01-04:0927:00[ 0] : V<sys> にSE 再生モードを返す (0/1)
2115 ** 568 : 0x23 - cmd 01-04:091d:00[ 0] : V<sys> にSE 音量を返す (0-255?)
2116
2117 ** 122 : 0x23 - cmd 01-04:08c0:00[ 0] : V<sys> にBGM再生モードを設定 (0/1)
2118 ** 256 : 0x23 - cmd 01-04:08b6:00[ 0] : V<sys> にBGM音量を設定 (0-255?)
2119 ** 278 : 0x23 - cmd 01-04:08c2:00[ 0] : V<sys> にEff再生モードを設定 (0/1)
2120 ** 412 : 0x23 - cmd 01-04:08b8:00[ 0] : V<sys> にEff音量を設定 (0-255?)
2121 ** 434 : 0x23 - cmd 01-04:08c3:00[ 0] : V<sys> にSE 再生モードを設定 (0/1)
2122 ** 568 : 0x23 - cmd 01-04:08b9:00[ 0] : V<sys> にSE 音量を設定 (0-255?)
2123 */
2124 // 本来は音楽関連のコマンド
2125 if (cmd.cmd1 == 1 && cmd.cmd2 == 0x14) {
2126 if (cmd.cmd3 == 0 && cmd.cmd4 == 0) {
2127 eprintf("play bgm %s\n",cmd.Str(cmd.args[0]));
2128 music.PlayCDROM( (char*)cmd.Str(cmd.args[0]), 10000);
2129 cmd.cmd_type = CMD_SAVECMD_ONCE;
2130 }
2131 if (cmd.cmd3 == 2 && (cmd.cmd4 == 2 || cmd.cmd4 == 0) ) { /* ??? : ことみシナリオラストの音楽再生 */
2132 eprintf("play bgm %s\n",cmd.Str(cmd.args[0]));
2133 music.PlayCDROM( (char*)cmd.Str(cmd.args[0]), 1);
2134 cmd.cmd_type = CMD_SAVECMD_ONCE;
2135 }
2136 if (cmd.cmd3 == 0 && cmd.cmd4 == 2) {
2137 eprintf("fade bgm %d? and play bgm %s; %d\n",cmd.args[1].value, cmd.Str(cmd.args[0]), cmd.args[2].value);
2138 // music.PlayCDROM( (char*)cmd.Str(cmd.args[0]), 10000, cmd.args[2].value);
2139 music.PlayCDROM( (char*)cmd.Str(cmd.args[0]), 10000);
2140 cmd.cmd_type = CMD_SAVECMD_ONCE;
2141 }
2142 if ( (cmd.cmd3 == 5 || cmd.cmd3 == 0x69) && cmd.cmd4 == 0) {
2143 if (cmd.cmd3 == 5) {
2144 music.StopCDROM(0);
2145 eprintf("stop bgm\n");
2146 } else {
2147 music.StopCDROM(cmd.args[0].value);
2148 eprintf("fade bgm %d\n",cmd.args[0].value);
2149 }
2150 cmd.cmd_type = CMD_SAVECMD_ONCE;
2151 }
2152 }
2153 if (cmd.cmd1 == 1 && cmd.cmd2 == 0x15) {
2154 if ((cmd.cmd3 == 2) || (cmd.cmd3 == 0 && cmd.cmd4 == 1) || (cmd.cmd3 == 0 && cmd.cmd4 == 0)) {
2155 eprintf("play SE %s\n",cmd.Str(cmd.args[0]));
2156 if (cmd.cmd3 == 2) {
2157 music.PlaySE(cmd.Str(cmd.args[0]),1);
2158 cmd.cmd_type = CMD_SAVECMD_ONCE;
2159 } else {
2160 music.PlaySE(cmd.Str(cmd.args[0]));
2161 cmd.clear();
2162 }
2163 } else if (cmd.cmd3 == 5) {
2164 eprintf("Stop SE\n");
2165 music.StopSE();
2166 cmd.cmd_type = CMD_SAVECMD_ONCE;
2167 } else if (cmd.cmd3 == 0x69) {
2168 eprintf("Stop SE with fade %d\n",cmd.args[0].value);
2169 music.StopSE(cmd.args[0].value);
2170 cmd.cmd_type = CMD_SAVECMD_ONCE;
2171 }
2172 }
2173 if (cmd.cmd1 == 1 && cmd.cmd2 == 4 && (cmd.cmd3 == 0x4bb || cmd.cmd3 == 0x4bc) ) {
2174 // 音楽を待ってみる(絶対に違うが)。本来、04-803 に対応してなにかの終わりをwaitするっぽい(風子/智代Ed付近)
2175 // EnableSyscom らしいが、よくわからない (rldev)
2176 // if (!music.IsStopSE()) status = WAIT_SE;
2177 cmd.clear();
2178 }
2179 if (cmd.cmd1 == 1 && cmd.cmd2 == 4 && (cmd.cmd3 == 0x8b6 || cmd.cmd3 == 0x91a) ) {
2180 // 音楽モードで音量を上げるためのコマンド (SetBgmVolume)
2181 // とりあえず未実装
2182 cmd.clear();
2183 }
2184
2185 if (cmd.cmd1 == 1 && cmd.cmd2 == 0x16) {
2186 if (cmd.cmd3 == 0 && cmd.cmd4 == 0) {
2187 eprintf("play SE %d\n",cmd.args[0].value);
2188 music.PlaySE(cmd.args[0].value);
2189 cmd.clear();
2190 }
2191 }
2192 if (cmd.cmd1 == 1 && cmd.cmd2 == 0x17) {
2193 if (cmd.cmd3 == 0) {
2194 eprintf("play koe %d",cmd.args[0].value);
2195 if (cmd.cmd4 == 1) {
2196 eprintf(", para? %d",cmd.args[1].value);
2197 }
2198 eprintf("\n");
2199 char buf[1024]; sprintf(buf, "%d",cmd.args[0].value);
2200 if ( !(skip_mode & SKIP_TEXT)) music.PlayKoe(buf);
2201 cmd.clear();
2202 }
2203 }
2204 if (cmd.cmd1 == 1 && cmd.cmd2 == 0x1a) {
2205 if ( (cmd.cmd3 == 0x14 || cmd.cmd3 == 1) && cmd.cmd4 == 0) {
2206 const char* str = cmd.Str(cmd.args[0]);
2207 int x = cmd.args[1].value;
2208 int y = cmd.args[2].value;
2209 int x2 = cmd.args[3].value;
2210 int y2 = cmd.args[4].value;
2211 eprintf("play movie ; name %s pos %d,%d - %d,%d\n",str,x,y,x2,y2);
2212 music.PlayMovie(str, x, y, x2, y2,1);
2213 status = WAIT_MOVIE;
2214 event.RegisterGlobalPressFunc(&Pressed, (void*)this);
2215 cmd.clear();
2216 }
2217 }
2218 return;
2219 }
2220
2221
2222 /********************************************************
2223 **
2224 ** class Grp
2225 */
2226
2227 Grp::Grp(Event::Container& _event, PicContainer& _parent, const Flags& f, set<int>& _cgm,class MuSys& mu, AyuSysConfig& config) {
2228 pimpl = new GrpImpl(_event, _parent, f, _cgm, mu, config);
2229 };
2230 Grp::~Grp() {
2231 delete pimpl;
2232 }
2233
2234 bool Grp::Wait(unsigned int current_time, Cmd& cmd) {
2235 return pimpl->Wait(current_time, cmd);
2236 }
2237 void Grp::Exec(Cmd& cmd) {
2238 pimpl->Exec(cmd);
2239 }
2240 void Grp::SetSkipMode(SkipMode mode) {
2241 pimpl->SetSkipMode(mode);
2242 }
2243 void Grp::InitSel(AyuSysConfig& config) {
2244 pimpl->InitSel(config);
2245 }
2246 void Grp::Save(std::string& str) {
2247 pimpl->Save(str);
2248 }
2249
2250 void Grp::Load(const char* str) {
2251 pimpl->Load(str);
2252 }
2253 void Grp::SaveSys(std::string& str) {
2254 pimpl->SaveSys(str);
2255 }
2256
2257 void Grp::LoadSys(const char* str) {
2258 pimpl->LoadSys(str);
2259 }