Mercurial > otakunoraifu
view scn2k/scn2k_grp.cc @ 66:d112357a0ec1
Fix a bug with savegames introduced with changeset c7bcc0ec2267.
Warning: savegames created since c7bcc0ec2267 are probably corrupted,
you may have to start the game over.
If you chose not to do so, you should replace all occurrences of 'TextWindow' by 'TextImplWindow',
and 'Text Window' by 'TextImpl Window' in your save files.
author | Thibaut Girka <thib@sitedethib.com> |
---|---|
date | Sat, 11 Dec 2010 18:36:20 +0100 |
parents | 4416cfac86ae |
children | 1fd20d231376 |
line wrap: on
line source
/* * Copyright (c) 2004-2006 Kazunori "jagarl" Ueno * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "scn2k.h" #include "system/file.h" #include "system/system_config.h" #include "font/text.h" #include "window/render.h" extern XKFont::HorizLayout* DefaultLayout(int text_size); /******************************************************************* ** GrpObj(implementation) */ GrpObj::GrpObj(void) : name(""), gan_name(""), pic_parent(0), picture(0), anm(0), _posx(0), _posy(0), clip_area(0,0,0,0), alpha(255), order(0), surface_num(0), print_moji(""), print_size(0), print_r(-1),print_g(-1),print_b(-1), dig_number(0), dig_digit(0), zoom(-1), rotate(-1), attr(GrpObj::HIDDEN) { int i; for (i=0; i<9; i++) { posx[i] = posy[i] = 0; } } GrpObj::~GrpObj() { if (picture != NULL) delete picture; } int GrpObj::PosX() { return _posx; } int GrpObj::PosY() { return _posy; } void GrpObj::SetUpdate(void) { attr = Attribute (attr | UPDATE_PICTURE); //Update(); //FIXME } void GrpObj::SetPos(int index, int x, int y) { if (index < 0 || index > 8) { fprintf(stderr,"GrpObj::SetPos: Invalid index %d <- %d,%d\n",index,x,y); return; } if (x == posx[index] && y == posy[index]) return; attr = Attribute(attr | UPDATE_POS); _posx += x-posx[index]; _posy += y-posy[index]; posx[index] = x; posy[index] = y; } void GrpObj::GetPos(int index, int& x, int& y) { if (index < 0 || index > 8) { fprintf(stderr,"GrpObj::GetPos: Invalid index %d\n",index); x = 0; y = 0; return; } x = posx[index]; y = posy[index]; } void GrpObj::SetAlpha(int new_alpha) { if (alpha == new_alpha) return; alpha = new_alpha; attr = Attribute(attr | UPDATE_ALPHA); return; } void GrpObj::SetSurfaceNum(int num) { if (num != -1) { if (surface_num == num) return; surface_num = num; } attr = Attribute(attr | UPDATE_SNUM); } void GrpObj::SetClipArea(int x, int y, int w, int h) { Rect new_clip(x,y,x+w,y+h); if (clip_area == new_clip) return; clip_area = new_clip; attr = Attribute(attr | UPDATE_CLIP); } PicBase* GrpObj::DeletePic(void) { PicBase* p = picture; anm = NULL; picture = NULL; src_pos.clear(); attr = Attribute(attr & HIDDEN); return p; } void GrpObj::GetSrcGeom(int& width, int& height) { if (src_pos.empty()) { width = 0; height = 0; if (name.length() == 0) { return; } /* ボタンの位置情報を求める */ /* g00 ファイルのヘッダ部分に位置情報は入っている */ string path(name); path += ".g00"; ARCINFO* info = FileSearcher::GetInstance()->Find(FileSearcher::PDT, path.c_str(), "g00"); if (info == NULL) { // ファイルが見つからない fprintf(stderr, "GrpObj::GetSrcGeom : Cannot find file %s\n", path.c_str()); return; } const char* data = info->Read(); if (data != NULL && *data == 2) { // 画像ファイル内にボタン情報が存在する int srclen = read_little_endian_int(data+5); int i; for (i=0; i<srclen; i++) { int x1 = read_little_endian_int(data+9+i*24+0); int y1 = read_little_endian_int(data+9+i*24+4); int x2 = read_little_endian_int(data+9+i*24+8); int y2 = read_little_endian_int(data+9+i*24+12); src_pos.push_back(Rect(x1, y1, x2+1, y2+1)); if (width < src_pos.back().width()) width = src_pos.back().width(); if (height < src_pos.back().height()) height = src_pos.back().height(); } } else { // 画像ファイルから大きさ取得 width = read_little_endian_short(data+1); height = read_little_endian_short(data+3); src_pos.push_back(Rect(0,0,width,height)); } delete info; } int sn = surface_num; if (sn < 0 || sn > src_pos.size()) sn = 0; width = src_pos[sn].width(); height = src_pos[sn].height(); } void GrpObj::Update(void) { if (attr & UPDATE_PICTURE) { UpdateSurface(); attr = Attribute( (attr | UPDATE_ALL) & (~UPDATE_PICTURE)); } if (picture == NULL) return; if (attr & UPDATE_POS) { if (zoom != -1) { int w=0, h=0; GetSrcGeom(w,h); picture->Move(_posx-w/2, _posy-h/2); } else { picture->Move(_posx, _posy); } } if (attr & UPDATE_ALPHA) { if (alpha <= 0) { picture->SetSurfaceAlpha(0, Rect(0,0)); picture->hide(); } else if (alpha >= ALPHA_MAX) { picture->SetSurfaceAlpha(0, Rect(0,0)); if (attr & HIDDEN) picture->hide(); else picture->show(); } else { picture->SetSurfaceAlpha(&alpha, Rect(0,0,1,1)); if (attr & HIDDEN) picture->hide(); else picture->show(); } } if ( (attr & UPDATE_SNUM) && (!src_pos.empty())) { if (surface_num < 0 || surface_num >= src_pos.size()) surface_num = 0; picture->SetSurfacePos(src_pos[surface_num].lx, src_pos[surface_num].ty); } if (attr & UPDATE_CLIP) { picture->SetClipArea(clip_area); } attr = Attribute(attr & (~UPDATE_ALL)); if (attr & ANM_PLAYSTART) { if (anm != NULL) { anm->Play(); attr = Attribute(attr | ANM_PLAYING); } attr = Attribute(attr & (~ANM_PLAYSTART)); } } void GrpObj::CreateSurface(PicContainer* parent) { if (picture != NULL) { PicBase* p = DeletePic(); delete p; } src_pos.clear(); // picture を作成 pic_parent = parent; picture = parent->create_leaf(Rect(_posx,_posy,_posx+1,_posy+1), 0); picture->hide(); UpdateSurface(); } void GrpObj::UpdateSurface(void) { if (pic_parent == NULL || picture == NULL) return; int width = 0, height = 0; if (gtype == FILE || gtype == GAN) { if (name.length() == 0) return; // ファイル名が存在する場合、ファイルを読み込み GetSrcGeom(width, height); if (width <= 0 || height <= 0) return; // surface の設定 if (surface_num == 0 && ( (zoom > 0 && zoom != 256) || rotate > 0)) { ZoomRotate(); } else { // 普通に surface を設定 string path(name); path += ".g00"; picture->SetSurface(path.c_str(), 0, 0); picture->SetSurfaceRect(Rect(0,0,width,height)); } if (attr & BLIT_ADD) picture->SetSurfaceAttribute(PicBase::BLIT_ADD); } else if (gtype == MOJI) { // テキスト描画 if (print_moji.length() == 0) return; UpdateMoji(); } else if (gtype == DIGIT) { // 数値を画像表示 UpdateDigit(); } } void GrpObj::ZoomRotate(void) { picture->SetSurface( (Surface*)0, 0, 0); // 回転、縮小拡大は座標原点が画像の中心になる string path(name); path += ".g00"; Surface* surface_orig = pic_parent->Root().NewSurface(path.c_str()); if (surface_orig == NULL) return; Surface* zoom_surface = pic_parent->Root().RotZoomSurface(surface_orig, double(zoom)/256.0, rotate); Rect zoom_r (*zoom_surface); picture->SetSurface(zoom_surface, 0, 0); picture->SetSurfaceFreeFlag(); //picture->Move(PosX() + - zoom_r.width()/2, PosY() + - zoom_r.height()/2); // 中心座標がわからん・・・ picture->Move(320 - zoom_r.width()/2, 240 - zoom_r.height()/2); picture->SetSurfaceRect(Rect(0, 0, zoom_r.width(), zoom_r.height())); pic_parent->Root().DeleteSurface(surface_orig); } void GrpObj::UpdateMoji(void) { // 文字の大きさ、色などを変更 if (print_moji.length() == 0 || print_size <= 2) return; if (pic_parent == 0) return; /* テキストの大きさを得る */ int r, g, b; if (print_r == -1 || print_g == -1 || print_b == -1) {// 色設定なし r = g = b = 0; // とりあえず黒(clannad のSave/Loadメニュー用) } else { r = print_r; g = print_g; b = print_b; } TextStream ts = TextStream::ParseMoji(print_moji.c_str(), r, g, b, print_size); TextGlyphStream gs; vector<int> lh; // とりあえず drawable width は充分に大きく(2048)取る DefaultLayout(print_size-2)->Layout(ts, gs, lh, 2048); // print_size そのままだと弱干大きすぎるので -2 int width = gs.width(); int height = gs.height(); Surface* surface = pic_parent->Root().NewSurface(width, height, ALPHA_MASK); DSurfaceFill(surface, Rect(*surface), 0, 0, 0, 0); DSurfaceRenderText(gs.begin(), gs.end(), Rect(0, 0, width, height), surface, Rect(0,0)); picture->SetSurface(surface, 0, 0); picture->SetSurfaceRect(Rect(0,0,width,height)); picture->SetSurfaceFreeFlag(); } void GrpObj::UpdateDigit(void) { // 画像表示の数値文字列を表示する if (name.length() == 0) return; // ファイル名が存在する場合、ファイルを読み込み string path(name); path += ".g00"; Surface* surface_orig = pic_parent->Root().NewSurface(path.c_str()); if (surface_orig == NULL) return; int width, height; int i; GetSrcGeom(width, height); if (width <= 0 || height <= 0) return; if (src_pos.size() < 14) { // 必要な数の object がない // 表示できない分の空の rect を追加しておく for (i=src_pos.size(); i<14; i++) src_pos.push_back(Rect(0,0,0,0)); pic_parent->Root().DeleteSurface(surface_orig); return; } // 桁数の計算 char num_str[20]; if (dig_number < 0) sprintf(num_str, "%d", -dig_number); else sprintf(num_str, "%d", dig_number); int sign_count = 0; int space_count = 0; int total_count; int dig_count = strlen(num_str); if (dig_number < 0 && (attr&DIG_SIGN) == 0) dig_count++; if (dig_count < dig_digit) space_count = dig_digit - dig_count; if (attr & DIG_SIGN) sign_count = 1; total_count = dig_count + space_count + sign_count; Surface* surface = pic_parent->Root().NewSurface(width*total_count, height, ALPHA_MASK); DSurfaceFill(surface, Rect(*surface), 0, 0, 0, 0); /* surface にコピーする */ int cur_x = 0; if ( (attr & DIG_PACK) && !(attr & DIG_ZERO)) { // 始めに空白を挿入 cur_x += space_count * width; } int plus = 10, minus = 11, plusminus = 12; if (dig_number < 0) { DSurfaceMove(surface, src_pos[minus], surface, Rect(cur_x,0)); cur_x += width; } else if (attr & DIG_SIGN) { if (dig_number == 0) DSurfaceMove(surface, src_pos[plusminus], surface, Rect(cur_x,0)); else DSurfaceMove(surface, src_pos[plus], surface, Rect(cur_x,0)); cur_x += width; } if (attr & DIG_ZERO) { // ゼロ・パディング for (i=0; i<space_count; i++) { DSurfaceMove(surface, src_pos[0], surface, Rect(cur_x, 0)); cur_x += width;; } } else if (!(attr & DIG_PACK)) { // PACK オプションなし cur_x += space_count * width; } for (i=0; num_str[i] != 0; i++) { DSurfaceMove(surface_orig, src_pos[num_str[i]-'0'], surface, Rect(cur_x, 0)); cur_x += width; } /* picture に設定 */ picture->SetSurface(surface, 0, 0); picture->SetSurfaceRect(Rect(0,0,width*total_count,height)); picture->SetSurfaceFreeFlag(); pic_parent->Root().DeleteSurface(surface_orig); } void GrpObj::CreateGan(Event::Container& event, int event_number) { if (picture == NULL) { fprintf(stderr,"GrpObj::CreateGan() is called before Create()\n"); return; } if (anm != NULL) { anm->Abort(); delete anm; anm = NULL; } if (gan_name.empty()) return; /* アニーメション情報 (.GAN ファイル)を求める */ string path(gan_name); path += ".gan"; ARCINFO* info = FileSearcher::GetInstance()->Find(FileSearcher::GAN, path.c_str(), "gan"); if (info == NULL) { fprintf(stderr,"GrpObj::CreateGan: Cannot Find 'GAN' file %s\n", path.c_str()); return; } const char* data = info->Read(); if (read_little_endian_int(data) != 10000 || read_little_endian_int(data+4) != 10000) { fprintf(stderr,"GrpObj::CreateGan: Invalid'GAN' file %s\n", path.c_str()); delete info; return; } attr = Attribute(attr | UPDATE_POS); const char* buf = data + 16; buf += strlen(buf) + 1; // 画像ファイル名が入っている buf += 4; // 定数 20000 int pics = read_little_endian_int(buf); buf += 4; // 複数のアニメーション情報が入っている場合、情報数 // 以下、pics 回繰り返し // アニメーションを行う実体を作成 AnmAlphaMove* wid = new AnmAlphaMove(event, picture); if (event_number && event_number < pics) { // 複数のアニメーション情報がある場合、先の情報を読み飛ばす */ int i; for (i=0; i<event_number; i++) { buf += 4; // 定数 30000 int ptns = read_little_endian_int(buf); buf += 4; buf += ptns*52; } } buf += 4; // 定数 30000 int ptns = read_little_endian_int(buf); buf += 4; int total_time = 0; int i; for (i=0; i<ptns; i++) { int p = read_little_endian_int(buf+i*52+0*8+4); int x = read_little_endian_int(buf+i*52+1*8+4); int y = read_little_endian_int(buf+i*52+2*8+4); int t = read_little_endian_int(buf+i*52+3*8+4); int a = read_little_endian_int(buf+i*52+4*8+4); x += PosX(); y += PosY(); if (p == -1) { a = 0; p = 0; } // p == -1 ならなにも表示しない if (p >= src_pos.size()) { fprintf(stderr,"Reading GAN file %s (G00 %s) : not enough pictures in .G00 file\n", path.c_str(), name.c_str()); a = 0; p = 0; } total_time += t; wid->ptns.push_back(AnmAlphaMove::Ptn(Rect(x,y), src_pos[p], a, total_time)); } wid->SetPtn(); // パターン登録終了 attr = Attribute(attr | ANM_PLAYSTART); anm = wid; } void GrpObj::CreateGanSpecial(Event::Container& event, int event_number, int time) { if (picture == NULL) { fprintf(stderr,"GrpObj::CreateGan() is called before Create()\n"); return; } if (anm != NULL) { anm->Abort(); delete anm; anm = NULL; } // アニメーションを行う実体を作成 AnmAlphaMove* wid = new AnmAlphaMove(event, picture); int i; switch(event_number) { case 0: // pattern を 0 から最後まで変化させる for (i=0; i<src_pos.size(); i++) { wid->ptns.push_back(AnmAlphaMove::Ptn(Rect(PosX(), PosY()), src_pos[i], 255, time*i)); } wid->SetPtn(); // パターン登録終了 anm = wid; attr = Attribute(attr | ANM_PLAYSTART); break; default: break; } } void GrpObj::SetZoomRotate(int new_zoom, int new_rotate) { if (zoom == new_zoom && rotate == new_rotate) return; if ( zoom == -1 || new_zoom == -1) { attr = Attribute(attr | UPDATE_POS); // centering する } zoom = new_zoom; if (new_rotate != -1) rotate = new_rotate; if (zoom < 0) zoom = 256; if (rotate < 0) rotate = 0; else if (rotate > 360) rotate %= 360; attr = Attribute(attr | UPDATE_PICTURE); } void GrpObj::Refresh(GrpObj& parent_obj) { //if (&parent_obj != this) printf("Toto\n"); //FIXME GrpObjMap::iterator it; for (it = children_obj.begin(); it != children_obj.end(); it++) it->second.Refresh(parent_obj); if (picture == NULL) return; if (alpha == 0 || (attr & GrpObj::HIDDEN) || (parent_obj.attr & GrpObj::HIDDEN)) { if (attr & GrpObj::ANM_PLAYING) { attr = GrpObj::Attribute(attr & ~(GrpObj::ANM_PLAYING)); if (anm != NULL) anm->Abort(); } picture->hide(); } else { Update(); picture->show(); } } void GrpObj::_debug_Dump(int id, int indent) { const char* repr; if (indent == 0) repr = "obj %04d(%p): name %10s pos %d,%d alpha %d (%d/%d/%d)\n"; else repr = " * obj %04d(%p): name %10s pos %d,%d alpha %d (%d/%d/%d)\n"; if (picture != NULL) { if (!name.empty()) fprintf(stderr, repr, id, this, name.c_str(), PosX(), PosY(), alpha, attr&GrpObj::HIDDEN ? 1 : 0, 0, picture->IsHidden()); else if (!print_moji.empty()) fprintf(stderr, repr, id, this, print_moji.c_str(), PosX(), PosY(), alpha, attr&GrpObj::HIDDEN ? 1 : 0, 0, picture->IsHidden()); else fprintf(stderr, repr, id, this, "<EMPTY>", PosX(), PosY(), alpha, attr&GrpObj::HIDDEN ? 1 : 0, 0, picture->IsHidden()); } GrpObjMap::iterator it; for (it = children_obj.begin(); it != children_obj.end(); it++) it->second._debug_Dump(it->first, indent+1); } /****************************************************************** ** ** class ScnGrp* */ /* Princess Bride: 背景画の一部のみ移動、の実装 */ 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) : WidAnmTime(container, _pic, total_time), dest(_dest), src(_src), root(_root),dest_r(_dest_r), from(_from), to(_to) { int dx = to.lx - from.lx; int dy = to.ty - from.ty; if (dx < 0) dx = -dx; if (dy < 0) dy = -dy; if (dx < dy) dx = dy; if (dx == 0) dx = 1; SetAllCount(dx); } void ScnGrpMove::Exec(int count) { Rect r(0,0,dest_r.width(),dest_r.height()); int dx = to.lx - from.lx; int dy = to.ty - from.ty; int x = dx*count/all_count + from.lx; int y = dy*count/all_count + from.ty; r.rmove(x, y); root.BlitSurface(src, r, dest, dest_r); iterator it; for (it=pic.begin(); it!=pic.end(); it++) (*it)->SetSurface(dest, 0, 0); } void ScnGrpAnm::CalcTotal(void) { /* total time を計算 */ if (empty()) return; int tm = 0; vector<ScnGrpAnmAtom>::iterator it; for (it=begin(); it != end(); it++) tm += it->time; total_time = tm; SetAllCount(tm); } void ScnGrpAnm::Exec(int count) { int tm = 0; vector<ScnGrpAnmAtom>::iterator it; for (it=begin(); it != end(); it++) { tm += it->time; if (count < tm) break; } if (it == end()) it--; owner.LoadSurface(it->name.c_str(), 0); } /***************************************************** * * Grp * */ #include "music2/music.h" Grp::Grp(Event::Container& _event, PicContainer& _parent, const Flags& f, set<int>& _cgm_data): event(_event), flags(f), parent(_parent), status(NORMAL), skip_mode(SKIP_NO), cgm_data(_cgm_data) { int i; for (i=0; i<MAXPDT; i++) { ssurface[i] = 0; dsurface[i] = 0; } music = MuSys::GetInstance(); config = AyuSysConfig::GetInstance(); screen = parent.create_leaf(Rect(0, 0, parent.Width(), parent.Height()), 0); screen_front = parent.create_leaf(Rect(0, 0, parent.Width(), parent.Height()), 0); surface = parent.Root().NewSurface(parent.Width(), parent.Height(), NO_MASK); surface_update = parent.Root().NewSurface(parent.Width(), parent.Height(), NO_MASK); DSurfaceFill(surface, Rect(*surface), 0, 0, 0); DSurfaceFill(surface_update, Rect(*surface), 0, 0, 0); screen->SetSurface(surface, 0, 0); screen->show(); screen_front->hide(); screen_front->ZMove(screen); LoadCgm(); RegisterCommand(1, 30, 0, "stackClear", (CmdImpl) &Grp::impl_stackClear); RegisterCommand(1, 33, 70, "grpBuffer", (CmdImpl) &Grp::impl_grpBuffer); RegisterCommand(1, 33, 73, "grpOpenBG", (CmdImpl) &Grp::impl_grpOpen); RegisterCommand(1, 33, 75, "grpMulti", (CmdImpl) &Grp::impl_grpMulti); //FIXME: or not... RegisterCommand(1, 33, 76, "grpOpen", (CmdImpl) &Grp::impl_grpOpen); RegisterCommand(1, 33, 32, "shake", (CmdImpl) &Grp::impl_shake); RegisterCommand(1, 33, 100, "grpCopy", (CmdImpl) &Grp::impl_grpCopy); RegisterCommand(1, 33, 1201, "recFill", (CmdImpl) &Grp::impl_recFill); RegisterCommand(1, 33, 1100, "recCopy", (CmdImpl) &Grp::impl_recCopy); RegisterCommand(1, 33, 1101, "recMaskCopy", NULL); //TODO: Same thing as recCopy, but using source's alpha RegisterCommand(1, 33, 1600, "recAdd", (CmdImpl) &Grp::impl_recAdd); RegisterCommand(1, 33, 406, "grpPan", (CmdImpl) &Grp::impl_grpPan); RegisterCommand(1, 34, 3120, "snmBgScroll", (CmdImpl) &Grp::impl_snmBgScroll); RegisterCommand(1, 34, 3100, "snmBgPlay", (CmdImpl) &Grp::impl_snmPlay); RegisterCommand(1, 34, 2100, "snmPlay", (CmdImpl) &Grp::impl_snmPlay); RegisterCommand(1, 34, 2101, "snmPlayEx", (CmdImpl) &Grp::impl_snmPlay); RegisterCommand(1, 4, 1500, "cgGetTotal", (CmdImpl) &Grp::impl_cgGet); RegisterCommand(1, 4, 1501, "cgGetViewed", (CmdImpl) &Grp::impl_cgGet); RegisterCommand(1, 4, 1502, "cgGetViewedPcnt", (CmdImpl) &Grp::impl_cgGet); RegisterCommand(1, 4, 1503, "cgGetFlag", (CmdImpl) &Grp::impl_cgStatus); RegisterCommand(1, 4, 1504, "cgStatus", (CmdImpl) &Grp::impl_cgStatus); RegisterCommand(1, 4, 0x6a4, "CreateInput", NULL); RegisterCommand(1, 4, 0x6ae, "SetInput", NULL); RegisterCommand(1, 61, 10, "objClear", (CmdImpl) &Grp::impl_objClear); RegisterCommand(1, 61, 11, "objDelete", (CmdImpl) &Grp::impl_objClear); RegisterCommand(1, 71, 1000, "objOfFile", (CmdImpl) &Grp::impl_createObj); RegisterCommand(1, 71, 1003, "objOfFileGan", (CmdImpl) &Grp::impl_createObj); RegisterCommand(1, 71, 1100, "objOfArea", (CmdImpl) &Grp::impl_createObj); RegisterCommand(1, 71, 1200, "objOfText", (CmdImpl) &Grp::impl_createObj); RegisterCommand(1, 71, 1300, "objDriftOfFile", (CmdImpl) &Grp::impl_createObj); RegisterCommand(1, 71, 1400, "objOfDigits", (CmdImpl) &Grp::impl_createObj); RegisterCommand(2, 71, 1000, "subObjOfFile", (CmdImpl) &Grp::impl_createObj); RegisterCommand(2, 71, 1003, "subObjOfGan", (CmdImpl) &Grp::impl_createObj); RegisterCommand(2, 71, 1100, "subObjOfArea", (CmdImpl) &Grp::impl_createObj); RegisterCommand(2, 71, 1200, "subObjOfText", (CmdImpl) &Grp::impl_createObj); RegisterCommand(2, 71, 1300, "subObjDriftOfFile", (CmdImpl) &Grp::impl_createObj); RegisterCommand(2, 71, 1400, "subObjOfDigits", (CmdImpl) &Grp::impl_createObj); //I suppose it's the same thing as createObj*, but I didn't see it in action. For now, mark it unhandled. RegisterCommand(1, 72, 1000, "objBgOfFile", (CmdImpl) &Grp::impl_createObj); RegisterCommand(1, 72, 1003, "objBgOfFileGan", (CmdImpl) &Grp::impl_createObj); RegisterCommand(1, 72, 1100, "objBgOfArea", (CmdImpl) &Grp::impl_createObj); RegisterCommand(1, 72, 1200, "objBgOfText", (CmdImpl) &Grp::impl_createObj); RegisterCommand(1, 72, 1300, "objBgDriftOfFile", (CmdImpl) &Grp::impl_createObj); RegisterCommand(1, 72, 1400, "objBgOfDigits", (CmdImpl) &Grp::impl_createObj); RegisterCommand(2, 72, 1000, "subObjBgOfFile", NULL);//FIXME RegisterCommand(2, 72, 1003, "subObjBgOfGan", NULL);//FIXME RegisterCommand(2, 72, 1100, "subObjBgOfArea", NULL);//FIXME RegisterCommand(2, 72, 1200, "subObjBgOfText", NULL);//FIXME RegisterCommand(2, 72, 1300, "subObjBgDriftOfFile", NULL);//FIXME RegisterCommand(2, 72, 1400, "subObjBgOfDigits", NULL);//FIXME; RegisterCommand(1, 73, 0, "ganStop?", NULL); //That's what xclannad says, but I'm not sure... RegisterCommand(1, 73, 1000, "ganStop", (CmdImpl) &Grp::impl_gan); //That's what rldev says RegisterCommand(1, 73, 3, "ganIsPlaying", (CmdImpl) &Grp::impl_gan); RegisterCommand(1, 73, 2003, "objPlay", (CmdImpl) &Grp::impl_gan); RegisterCommand(1, 73, 1001, "ganLoop", (CmdImpl) &Grp::impl_gan); RegisterCommand(1, 73, 1003, "ganPlay", (CmdImpl) &Grp::impl_gan); RegisterCommand(1, 73, 1005, "ganPlayOnce", (CmdImpl) &Grp::impl_gan); RegisterCommand(1, 73, 3001, "ganLoop2", (CmdImpl) &Grp::impl_gan); RegisterCommand(1, 73, 3003, "ganPlay2", (CmdImpl) &Grp::impl_gan); RegisterCommand(1, 73, 3005, "ganPlayOnce2", (CmdImpl) &Grp::impl_gan); RegisterCommand(2, 73, 0, "ganSubStop?", NULL); //FIXME RegisterCommand(2, 73, 1000, "ganSubStop", NULL); //FIXME RegisterCommand(2, 73, 3, "ganSubIsPlaying", NULL); //FIXME RegisterCommand(2, 73, 2003, "objSubPlay", NULL); //FIXME RegisterCommand(2, 73, 1001, "ganSubLoop", NULL); //FIXME RegisterCommand(2, 73, 1003, "ganSubPlay", NULL); //FIXME RegisterCommand(2, 73, 1005, "ganSubPlayOnce", NULL); //FIXME RegisterCommand(2, 73, 3001, "ganSubLoop2", (CmdImpl) &Grp::impl_gan); //FIXME RegisterCommand(2, 73, 3003, "ganSubPlay2", NULL); //FIXME RegisterCommand(2, 73, 3005, "ganSubPlayOnce2", NULL); //FIXME RegisterCommand(1, 81, 1000, "objMove", (CmdImpl) &Grp::impl_objSetPos); RegisterCommand(1, 82, 1000, "objBgMove", (CmdImpl) &Grp::impl_objSetPos); RegisterCommand(1, 81, 1001, "objLeft", (CmdImpl) &Grp::impl_objSetPos); RegisterCommand(1, 82, 1001, "objBgLeft", (CmdImpl) &Grp::impl_objSetPos); RegisterCommand(1, 81, 1002, "objTop", (CmdImpl) &Grp::impl_objSetPos); RegisterCommand(1, 82, 1002, "objBgTop", (CmdImpl) &Grp::impl_objSetPos); RegisterCommand(1, 81, 1003, "objAlpha", (CmdImpl) &Grp::impl_objAlpha); RegisterCommand(1, 82, 1003, "objBgAlpha", (CmdImpl) &Grp::impl_objAlpha); RegisterCommand(1, 81, 1004, "objShow", (CmdImpl) &Grp::impl_objShow); RegisterCommand(1, 82, 1004, "objBgShow", (CmdImpl) &Grp::impl_objShow); RegisterCommand(1, 81, 1005, "objDispArea", NULL); RegisterCommand(1, 82, 1005, "objBgDispArea", NULL); RegisterCommand(1, 81, 1006, "objAdjust", (CmdImpl) &Grp::impl_objSetPos); RegisterCommand(1, 82, 1006, "objBgAdjust", NULL); //FIXME: (CmdImpl) &Grp::impl_objSetPos); RegisterCommand(1, 81, 1007, "objAdjustX", NULL); RegisterCommand(1, 82, 1007, "objBgAdjustX", NULL); RegisterCommand(1, 81, 1008, "objAdjustY", NULL); RegisterCommand(1, 82, 1008, "objBgAdjustY", NULL); RegisterCommand(1, 81, 2006, "objAdjust2?", NULL); //FIXME: (CmdImpl) &Grp::impl_objSetPos); I don't know if it is usefull or properly implemented RegisterCommand(1, 82, 2006, "objBgAdjust2?", NULL); //FIXME: (CmdImpl) &Grp::impl_objSetPos); See above RegisterCommand(1, 81, 1016, "objColour", NULL); //FIXME: (CmdImpl) &Grp::impl_objColour); RegisterCommand(1, 82, 1016, "objBgColour", NULL); //FIXME: (CmdImpl) &Grp::impl_objColour); RegisterCommand(1, 81, 1017, "objColR", NULL); RegisterCommand(1, 82, 1017, "objBgColR", NULL); RegisterCommand(1, 81, 1018, "objColG", NULL); RegisterCommand(1, 82, 1018, "objBgColG", NULL); RegisterCommand(1, 81, 1019, "objColB", NULL); RegisterCommand(1, 82, 1019, "objBgColB", NULL); RegisterCommand(1, 81, 1020, "objColLevel", NULL); RegisterCommand(1, 82, 1020, "objBgColLevel", NULL); RegisterCommand(1, 81, 1021, "objComposite", (CmdImpl) &Grp::impl_objComposite); //FIXME: May be broken RegisterCommand(1, 82, 1021, "objBgComposite", (CmdImpl) &Grp::impl_objComposite); RegisterCommand(1, 81, 1024, "objSetText", (CmdImpl) &Grp::impl_objSetText); RegisterCommand(1, 82, 1024, "objBgSetText", (CmdImpl) &Grp::impl_objSetText); RegisterCommand(1, 81, 1025, "objTextOpts", (CmdImpl) &Grp::impl_objTextOpts); //FIXME: Incomplete RegisterCommand(1, 82, 1025, "objBgTextOpts", (CmdImpl) &Grp::impl_objTextOpts); RegisterCommand(1, 81, 1032, "objOrder", (CmdImpl) &Grp::impl_objOrder); RegisterCommand(1, 82, 1032, "objBgOrder", (CmdImpl) &Grp::impl_objOrder); RegisterCommand(1, 81, 1034, "objDispRect", (CmdImpl) &Grp::impl_objDispArea); RegisterCommand(1, 82, 1034, "objBgDispRect", (CmdImpl) &Grp::impl_objDispArea); RegisterCommand(1, 81, 1037, "objSetDigits", (CmdImpl) &Grp::impl_objSetDigits); RegisterCommand(1, 82, 1037, "objBgSetDigits", (CmdImpl) &Grp::impl_objSetDigits); RegisterCommand(1, 81, 1038, "objNumOpts", (CmdImpl) &Grp::impl_objNumOpts); RegisterCommand(1, 82, 1038, "objBgNumOpts", (CmdImpl) &Grp::impl_objNumOpts); RegisterCommand(1, 81, 1039, "objPattNo", (CmdImpl) &Grp::impl_objPattNo); RegisterCommand(1, 82, 1039, "objBgPattNo", (CmdImpl) &Grp::impl_objPattNo); RegisterCommand(1, 81, 1046, "objScale", (CmdImpl) &Grp::impl_objScale); //FIXME: Broken behaviour RegisterCommand(1, 82, 1046, "objBgScale", (CmdImpl) &Grp::impl_objScale); RegisterCommand(1, 81, 1047, "objWidth", NULL); RegisterCommand(1, 82, 1047, "objBgWidth", NULL); RegisterCommand(1, 81, 1049, "objRotate", (CmdImpl) &Grp::impl_objRotate); RegisterCommand(1, 82, 1049, "objBgRotate", (CmdImpl) &Grp::impl_objRotate); RegisterCommand(2, 81, 1000, "childObjMove", (CmdImpl) &Grp::impl_objSetPos); RegisterCommand(2, 82, 1000, "childObjBgMove", (CmdImpl) &Grp::impl_objSetPos); RegisterCommand(2, 81, 1001, "childObjLeft", NULL); RegisterCommand(2, 82, 1001, "childObjBgLeft", NULL); RegisterCommand(2, 81, 1002, "childObjTop", NULL); RegisterCommand(2, 82, 1002, "childObjBgTop", NULL); RegisterCommand(2, 81, 1003, "childObjAlpha", (CmdImpl) &Grp::impl_objAlpha); RegisterCommand(2, 82, 1003, "childObjBgAlpha", (CmdImpl) &Grp::impl_objAlpha); RegisterCommand(2, 81, 1004, "childObjShow", (CmdImpl) &Grp::impl_objShow); RegisterCommand(2, 82, 1004, "childObjBgShow", (CmdImpl) &Grp::impl_objShow); RegisterCommand(2, 81, 1005, "childObjDispArea", NULL); RegisterCommand(2, 82, 1005, "childObjBgDispArea", NULL); RegisterCommand(2, 81, 1006, "childObjAdjust", (CmdImpl) &Grp::impl_objSetPos); RegisterCommand(2, 82, 1006, "childObjBgAdjust", (CmdImpl) &Grp::impl_objSetPos); RegisterCommand(2, 81, 1007, "childObjAdjustX", NULL); RegisterCommand(2, 82, 1007, "childObjBgAdjustX", NULL); RegisterCommand(2, 81, 1008, "childObjAdjustY", NULL); RegisterCommand(2, 82, 1008, "childObjBgAdjustY", NULL); RegisterCommand(2, 81, 2006, "childObjAdjust2?", NULL); RegisterCommand(2, 82, 2006, "childObjBgAdjust2?", NULL); RegisterCommand(2, 81, 1016, "childObjColour", NULL); RegisterCommand(2, 82, 1016, "childObjBgColour", NULL); RegisterCommand(2, 81, 1017, "childObjColR", NULL); RegisterCommand(2, 82, 1017, "childObjBgColR", NULL); RegisterCommand(2, 81, 1018, "childObjColG", NULL); RegisterCommand(2, 82, 1018, "childObjBgColG", NULL); RegisterCommand(2, 81, 1019, "childObjColB", NULL); RegisterCommand(2, 82, 1019, "childObjBgColB", NULL); RegisterCommand(2, 81, 1020, "childObjColLevel", NULL); RegisterCommand(2, 82, 1020, "childObjBgColLevel", NULL); RegisterCommand(2, 81, 1021, "childObjComposite", NULL); RegisterCommand(2, 82, 1021, "childObjBgComposite", NULL); RegisterCommand(2, 81, 1024, "childObjSetText", (CmdImpl) &Grp::impl_objSetText); RegisterCommand(2, 82, 1024, "childObjBgSetText", (CmdImpl) &Grp::impl_objSetText); RegisterCommand(2, 81, 1025, "childObjTextOpts", (CmdImpl) &Grp::impl_objTextOpts); RegisterCommand(2, 82, 1025, "childObjBgTextOpts", (CmdImpl) &Grp::impl_objTextOpts); RegisterCommand(2, 81, 1032, "childObjOrder", NULL); RegisterCommand(2, 82, 1032, "childObjBgOrder", NULL); RegisterCommand(2, 81, 1034, "childObjDispRect", NULL); RegisterCommand(2, 82, 1034, "childObjBgDispRect", NULL); RegisterCommand(2, 81, 1037, "childObjSetDigits", (CmdImpl) &Grp::impl_objSetDigits); RegisterCommand(2, 82, 1037, "childObjBgSetDigits", (CmdImpl) &Grp::impl_objSetDigits); RegisterCommand(2, 81, 1038, "childObjNumOpts", (CmdImpl) &Grp::impl_objNumOpts); RegisterCommand(2, 82, 1038, "childObjBgNumOpts", (CmdImpl) &Grp::impl_objNumOpts); RegisterCommand(2, 81, 1039, "childObjPattNo", (CmdImpl) &Grp::impl_objPattNo); RegisterCommand(2, 82, 1039, "childObjBgPattNo", (CmdImpl) &Grp::impl_objPattNo); RegisterCommand(2, 81, 1046, "childObjScale", (CmdImpl) &Grp::impl_objScale); RegisterCommand(2, 82, 1046, "childObjBgScale", (CmdImpl) &Grp::impl_objScale); RegisterCommand(2, 81, 1047, "childObjWidth", NULL); RegisterCommand(2, 82, 1047, "childObjBgWidth", NULL); RegisterCommand(2, 81, 1049, "childObjRotate", NULL); RegisterCommand(2, 82, 1049, "childObjBgRotate", NULL); RegisterCommand(1, 84, 1000, "objGetPos", (CmdImpl) &Grp::impl_objPosDims); RegisterCommand(1, 84, 1100, "objGetDims", (CmdImpl) &Grp::impl_objPosDims); RegisterCommand(2, 84, 1000, "childObjGetPos", (CmdImpl) &Grp::impl_objPosDims); RegisterCommand(2, 84, 1100, "childObjGetDims", (CmdImpl) &Grp::impl_objPosDims); RegisterCommand(1, 31, 0, "refresh", (CmdImpl) &Grp::impl_refresh); RegisterCommand(1, 20, 0, "bgmLoop", (CmdImpl) &Grp::impl_bgmLoop); RegisterCommand(1, 20, 1, "bgmPlayEx", (CmdImpl) &Grp::impl_bgmLoop); //FIXME: wait RegisterCommand(1, 20, 2, "bgmPlay", (CmdImpl) &Grp::impl_bgmLoop); RegisterCommand(1, 20, 5, "bgmStop", (CmdImpl) &Grp::impl_bgmStop); RegisterCommand(1, 20, 105, "bgmFadeOut", (CmdImpl) &Grp::impl_bgmStop); RegisterCommand(1, 21, 0, "wavPlay", (CmdImpl) &Grp::impl_playWav); RegisterCommand(1, 21, 1, "wavPlayEx", (CmdImpl) &Grp::impl_playWav); RegisterCommand(1, 21, 2, "wavLoop", (CmdImpl) &Grp::impl_playWav); RegisterCommand(1, 21, 3, "wavWait", NULL); RegisterCommand(1, 21, 4, "wavPlaying", NULL); RegisterCommand(1, 21, 5, "wavStop", (CmdImpl) &Grp::impl_stopWav); RegisterCommand(1, 21, 105, "wavFadeout", (CmdImpl) &Grp::impl_stopWav); RegisterCommand(1, 22, 0, "sePlay", (CmdImpl) &Grp::impl_playSE); RegisterCommand(1, 4, 2230, "SetBgmVolMod", (CmdImpl) &Grp::impl_SetVolMod); RegisterCommand(1, 4, 2231, "SetKoeVolMod", (CmdImpl) &Grp::impl_SetVolMod); RegisterCommand(1, 4, 2232, "SetPCMVolMod", (CmdImpl) &Grp::impl_SetVolMod); RegisterCommand(1, 4, 2233, "SetSeVolMod", (CmdImpl) &Grp::impl_SetVolMod); RegisterCommand(1, 4, 2330, "BgmVolMod", (CmdImpl) &Grp::impl_GetVolMod); RegisterCommand(1, 4, 2331, "KoeVolMod", (CmdImpl) &Grp::impl_GetVolMod); RegisterCommand(1, 4, 2332, "PCMVolMod", (CmdImpl) &Grp::impl_GetVolMod); RegisterCommand(1, 4, 2333, "SeVolMod", (CmdImpl) &Grp::impl_GetVolMod); RegisterCommand(1, 23, 0, "koePlay", (CmdImpl) &Grp::impl_koePlay); RegisterCommand(1, 23, 1, "koePlayEx", (CmdImpl) &Grp::impl_koePlay); //FIXME RegisterCommand(1, 23, 7, "koePlayExC", (CmdImpl) &Grp::impl_koePlay); //FIXME RegisterCommand(1, 23, 8, "koeDoPlay", (CmdImpl) &Grp::impl_koePlay); //FIXME RegisterCommand(1, 23, 9, "koeDoPlayEx", (CmdImpl) &Grp::impl_koePlay); //FIXME RegisterCommand(1, 23, 10, "koeDoPlayExC", (CmdImpl) &Grp::impl_koePlay); //FIXME RegisterCommand(1, 26, 1, "movPlayEx", (CmdImpl) &Grp::impl_movPlay); RegisterCommand(1, 26, 20, "movPlayExC", (CmdImpl) &Grp::impl_movPlay); RegisterCommand(1, 61, 14, "objSwap?", NULL); RegisterCommand(1, 62, 14, "objSwap?", NULL); RegisterCommand(1, 4, 1211, "EnableSyscom", NULL); RegisterCommand(1, 4, 1212, "HideSyscom", NULL); RegisterCommand(1, 4, 1213, "DisableSyscom", NULL); anm1 = NULL; anm2 = NULL; } Grp::~Grp() { map<int,GrpObj>::iterator it; for (it=grpobj.begin(); it!=grpobj.end(); it++) { PicBase* p = it->second.DeletePic(); delete p; } delete screen; delete screen_front; parent.Root().DeleteSurface(surface); parent.Root().DeleteSurface(surface_update); int i; for (i=0; i<MAXPDT; i++) { if (ssurface[i]) parent.Root().DeleteSurface(ssurface[i]); if (dsurface[i]) parent.Root().DeleteSurface(dsurface[i]); } } Surface* Grp::Dsurface(int pdt) { if (pdt == 0) return surface; if (dsurface[pdt] == 0) { // とりあえず画面の大きさということにする if (pdt == WORKPDT) dsurface[pdt] = parent.Root().NewSurface(parent.Width(), parent.Height(), ALPHA_MASK); else dsurface[pdt] = parent.Root().NewSurface(parent.Width(), parent.Height(), NO_MASK); } if (ssurface[pdt]) { // ssurface が存在すれば、dsurface にコピーして返す DSurfaceMove(ssurface[pdt], Rect(*ssurface[pdt]), dsurface[pdt], Rect(0,0)); parent.Root().DeleteSurface(ssurface[pdt]); ssurface[pdt] = 0; } return dsurface[pdt]; } GrpObj* Grp::GetGraphicObj(int grp, bool fg) { if (fg) return &grpobj[grp]; else return &bs_obj[grp]; } GrpObj* Grp::GetGraphicObj(int grp, int index, bool fg) { GrpObj* g = GetGraphicObj(grp, fg); return &g->children_obj[index]; } GrpObj* Grp::GetGraphicObjVarMode(Cmd& cmd, int &base_arg, bool fg) { GrpObj* g; if (cmd.cmd1 == 2) { g = GetGraphicObj(cmd.args[base_arg].value, cmd.args[base_arg+1].value, fg); base_arg += 1; } else g = GetGraphicObj(cmd.args[base_arg].value, fg); return g; } #include <SDL.h> Surface* Grp::Ssurface(int pdt) { if (pdt == 0) return surface; if (ssurface[pdt]) { return ssurface[pdt]; } return Dsurface(pdt); } void Grp::LoadSurface(const char* str, int pdt) { string s = str; if (cgm_info.find(s) != cgm_info.end()) { cgm_data.insert(cgm_info[s]); } Surface* bg = parent.Root().NewSurface(s.c_str()); if (bg == NULL) { s += ".g00"; bg = parent.Root().NewSurface(s.c_str()); } if (bg != NULL) { if (ssurface[pdt]) parent.Root().DeleteSurface(ssurface[pdt]); ssurface[pdt] = bg; if (pdt == 0) { /* とりあえず Princess Bride のアニメーション効果専用 */ Rect r(*ssurface[0]); Rect dr(*surface); int x = (dr.width()-r.width())/2; int y = (dr.height()-r.height())/2; DSurfaceMove(ssurface[0], r, surface, Rect(x,y)); parent.Root().DeleteSurface(ssurface[0]); ssurface[0] = NULL; screen->SetSurface(surface, 0, 0); } } else { if (str[0] != 0) fprintf(stderr,"Cannot find surface %d <- '%s'\n",pdt,str); } } void Grp::InitSel(void) { int i; int args[16]; char key[10]; for (i=0; i<999; i++) { sprintf(key, "#SEL.%03d",i); if (config->GetParam(key, 15, &args[0], &args[1], &args[2], &args[3], &args[4], &args[5], &args[6], &args[7], &args[8], &args[9], &args[10], &args[11], &args[12], &args[13], &args[14])) { sprintf(key, "#SELR.%03d", i); if (config->GetParam(key, 16, &args[0], &args[1], &args[2], &args[3], &args[4], &args[5], &args[6], &args[7], &args[8], &args[9], &args[10], &args[11], &args[12], &args[13], &args[14], &args[15])) continue; } SEL& s = anmtype[i]; s.from = Rect(args[0], args[1], args[2]+1, args[3]+1); s.to = Rect(args[4], args[5]); s.time = args[6]; s.sel_no = args[7]; int j; for (j=0; j<8; j++) s.args[j] = args[8+j]; } } void Grp::SetSkipMode(SkipMode _mode) { if ( (skip_mode & SKIP_IN_MENU) && (_mode & SKIP_IN_MENU) == 0) { RefreshObj(); } else if ( (skip_mode & SKIP_IN_MENU) == 0 && (_mode & SKIP_IN_MENU) ) { } skip_mode = _mode; } void Grp::SetObjChanged(int num) { changed_obj.insert(num); } void Grp::RefreshObj(void) { if (!deleted_pic.empty()) { vector<PicBase*>::iterator it; for (it=deleted_pic.begin(); it!=deleted_pic.end(); it++) { if (*it) delete *it; } deleted_pic.clear(); } if (!changed_obj.empty()) { set<int>::iterator it; for (it=changed_obj.begin(); it != changed_obj.end(); it++) { if (grpobj.find(*it) == grpobj.end()) continue; GrpObj& obj = grpobj[*it]; obj.Refresh(obj); } changed_obj.clear(); } if (reserved_load_surface0.length() != 0) { LoadSurface(reserved_load_surface0.c_str(), 0); reserved_load_surface0 = ""; } screen->ReBlit(); } #include <SDL.h> void Grp::StartAnm(int type) { SEL sel; if (anmtype.find(type) == anmtype.end()) { if (anmtype.find(0) == anmtype.end()) { sel.sel_no = 1; sel.from = Rect(*surface); sel.to = Rect(0,0); sel.time = 0; } else { sel = anmtype[0]; } } else { sel = anmtype[type]; } if (anm1 != NULL) { fprintf(stderr,"Warning: StartAnm() called before anm1 finished\n"); anm1->Abort(); delete anm1; anm1 = NULL; } map<int,GrpObj>::iterator it; // 現在表示中のobjectを消去 deleted_pic.push_back(screen); for (it=grpobj.begin(); it!=grpobj.end(); it++) { if (! (it->second.attr & GrpObj::WIPEON)) { // 画像切り替え時に object 削除 deleted_pic.push_back(it->second.DeletePic()); } else { GrpObj& new_obj = bs_obj[it->first]; if (new_obj.name.empty()) { // 新しい object が存在しなければ内容を引き継ぐ new_obj = it->second; it->second.DeletePic(); } else { new_obj.attr = GrpObj::Attribute(new_obj.attr | GrpObj::WIPEON); deleted_pic.push_back(it->second.DeletePic()); } } } grpobj.clear(); // 全オブジェクト削除 // 全画像オブジェクトの前にscreen 移動 // 新しい screen_front を作成しておく screen = screen_front; screen->hide(); screen->SetSurface(surface_update, 0, 0); parent.Root().BlitSurface(Dsurface(1), Rect(*surface_update), surface_update, Rect(0,0)); screen_front = parent.create_leaf(Rect(0, 0, parent.Width(), parent.Height()), 0); screen_front->hide(); screen_front->ZMove(screen); // 新しい object へ更新、surface_update へ新しい object を表示 // (object 作成時は picture は hide されている) for (it=bs_obj.begin(); it!=bs_obj.end(); it++) { grpobj[it->first] = it->second; it->second.DeletePic(); CreateObj(it->first);//FIXME: Adapt to groups GrpObj& g = grpobj[it->first]; if (g.picture) { g.Update(); if (g.alpha == 0 || (g.attr & GrpObj::HIDDEN)) ; else g.picture->SimpleBlit(surface_update); g.picture->hide(); } } bs_obj.clear(); // 画像効果開始 switch(sel.sel_no) { default: case 0: case 50: // 0 と 50 の違いが良くわからない if (skip_mode & SKIP_GRP_NOEFFEC) anm1 = new WidAnmAlpha(event, screen, ALPHA_MAX, ALPHA_MAX, 0); else if (skip_mode & SKIP_GRP_FAST) anm1 = new WidAnmAlpha(event, screen, 0, ALPHA_MAX, sel.time/4); else anm1 = new WidAnmAlpha(event, screen, 0, ALPHA_MAX, sel.time); break; } if (anm1) anm1->Play(); if (skip_mode & SKIP_GRP_NOEFFEC) AbortAnm(); } void Grp::StartShake(int total, const int* pattern) { if (anm2) { fprintf(stderr,"Warning: StartShake() called before another animation finished\n"); anm2->Abort(); delete anm2; anm2 = NULL; } if (skip_mode & SKIP_GRP_NOEFFEC) return; AnmAlphaMove* new_anm = new AnmAlphaMove(event, &parent); // shake screen では元画面の座標を揺らす int i; int tm = 0; for (i=0; i<total; i+=3) { int x = pattern[i]; int y = pattern[i+1]; new_anm->ptns.push_back(AnmAlphaMove::Ptn(Rect(x,y), Rect(0,0), 255, tm)); tm += pattern[i+2]; } new_anm->ptns.push_back(AnmAlphaMove::Ptn(Rect(0,0), Rect(0,0), 255, tm)); new_anm->SetPtn(); // パターン登録終了 new_anm->Play(); anm2 = new_anm; } void Grp::AbortAnm(void) { if (anm1 == NULL) return; anm1->Abort(); delete anm1; anm1 = NULL; /* 画像効果終了 */ /* 古い画面への画像効果があれば消去 */ if (anm2 && anm2->pic[0] != screen) { anm2->Abort(); delete anm2; anm2 = NULL; } /* pdt1 -> pdt0 へコピー */ DSurfaceMove(dsurface[1], Rect(*dsurface[1]), surface, Rect(0,0)); screen->SetSurface(surface, 0, 0); // 画像効果開始時に存在したobjectを消去 // 新しい object 表示 RefreshObj(); return; } void Grp::LoadSurface(const char* str) { if (anm1 != NULL) AbortAnm(); // 前の描画が終わってなければ強制終了 LoadSurface(str, 1); bg_name = str; } void Grp::LoadSurface(void) { if (anm1 != NULL) AbortAnm(); // 前の描画が終わってなければ強制終了 LoadSurface(bg_name.c_str(), 1); } void Grp::AddSurface(const char* str) { if (anm1 != NULL) AbortAnm(); // 前の描画が終わってなければ強制終了 LoadSurface(bg_name.c_str()); string s = str; Surface* front = parent.Root().NewSurface(s.c_str()); if (front == NULL) { s += ".g00"; front = parent.Root().NewSurface(s.c_str()); } if (front != NULL) { parent.Root().BlitSurface(front, Rect(*front), Dsurface(1), Rect(0,0)); parent.Root().DeleteSurface(front); } else { fprintf(stderr,"Cannot find surface %s\n",str); } } void Grp::CreateObj(int index) { GrpObjMap::iterator cur = grpobj.find(index); if (cur == grpobj.end()) return; GrpObj& g = grpobj[index]; g.CreateSurface(&parent); g.order = index; if (g.picture == NULL) return; // エラー:surface が存在しない g.picture->hide(); SetObjChanged(index); ZMoveObj(index); } void Grp::CreateSubObj(int grp_index, int index) { GrpObjMap::iterator cur = grpobj.find(grp_index); if (cur == grpobj.end()) return; GrpObj* g = &grpobj[grp_index]; cur = g->children_obj.find(index); if (cur == g->children_obj.end()) return; g = &g->children_obj[index]; g->CreateSurface(&parent); g->order = index; if (g->picture == NULL) return; // エラー:surface が存在しない g->picture->hide(); //TODO SetObjChanged(grp_index); /*ZMoveObj(index);*/ } void Grp::ZMoveObj(int index) { GrpObjMap::iterator cur = grpobj.find(index); if (cur == grpobj.end()) return; GrpObj& g = grpobj[index]; if (g.picture == NULL) return; // 自分より前に object があれば、その前に表示 // そうでなければ screen の前に表示 GrpObjMap::iterator cur_backobj = grpobj.end(); GrpObjMap::iterator it; for (it = grpobj.begin(); it != grpobj.end(); it++) { if (it == cur) continue; if (it->second.picture == NULL) continue; if (it->second.order < g.order) { if (cur_backobj == grpobj.end()) { cur_backobj = it; } else if (cur_backobj->second.order < it->second.order) { cur_backobj = it; } } } if (cur_backobj == grpobj.end()) { g.picture->ZMove(screen); } else { g.picture->ZMove(cur_backobj->second.picture); } } void Grp::SwapObj(int index1, int index2) { // デフォルト値から order が変更されていた場合のみ、order は保存される // まずは両方のobjectをswap if (grpobj.find(index1) == grpobj.end()) { if (grpobj.find(index2) == grpobj.end()) return; // どちらの object も存在しない grpobj[index1] = grpobj[index2]; if (grpobj[index1].order == index2) grpobj[index1].order = index1; grpobj[index2].DeletePic(); grpobj.erase(index2); ZMoveObj(index1); return; } else if (grpobj.find(index2) == grpobj.end()) { // index2 が存在しない場合 grpobj[index2] = grpobj[index1]; if (grpobj[index2].order == index1) grpobj[index2].order = index2; grpobj[index1].DeletePic(); grpobj.erase(index1); ZMoveObj(index2); return; } else { GrpObj obj = grpobj[index1]; grpobj[index1] = grpobj[index2]; grpobj[index2].DeletePic(); if (grpobj[index1].order == index2) grpobj[index1].order = index1; ZMoveObj(index1); grpobj[index2] = obj; if (grpobj[index2].order == index1) grpobj[index2].order = index2; ZMoveObj(index2); obj.DeletePic(); } } bool Grp::Pressed(int x, int y, void* pointer) { // マウスクリックでキャンセル Grp* g = (Grp*)pointer; if (g->status == WAIT_MOVIE) g->music->StopMovie(); if (g->status == WAIT_ANM) g->AbortAnm(); if (g->status == WAIT_SHAKE && g->anm2 != NULL) { g->anm2->Abort(); delete g->anm2; g->anm2 = NULL; } return false; // event deleted } /* mode.cgm の decode 用 */ static unsigned char decode_char[256] = { 0x8b, 0xe5, 0x5d, 0xc3, 0xa1, 0xe0, 0x30, 0x44, 0x00, 0x85, 0xc0, 0x74, 0x09, 0x5f, 0x5e, 0x33, 0xc0, 0x5b, 0x8b, 0xe5, 0x5d, 0xc3, 0x8b, 0x45, 0x0c, 0x85, 0xc0, 0x75, 0x14, 0x8b, 0x55, 0xec, 0x83, 0xc2, 0x20, 0x52, 0x6a, 0x00, 0xe8, 0xf5, 0x28, 0x01, 0x00, 0x83, 0xc4, 0x08, 0x89, 0x45, 0x0c, 0x8b, 0x45, 0xe4, 0x6a, 0x00, 0x6a, 0x00, 0x50, 0x53, 0xff, 0x15, 0x34, 0xb1, 0x43, 0x00, 0x8b, 0x45, 0x10, 0x85, 0xc0, 0x74, 0x05, 0x8b, 0x4d, 0xec, 0x89, 0x08, 0x8a, 0x45, 0xf0, 0x84, 0xc0, 0x75, 0x78, 0xa1, 0xe0, 0x30, 0x44, 0x00, 0x8b, 0x7d, 0xe8, 0x8b, 0x75, 0x0c, 0x85, 0xc0, 0x75, 0x44, 0x8b, 0x1d, 0xd0, 0xb0, 0x43, 0x00, 0x85, 0xff, 0x76, 0x37, 0x81, 0xff, 0x00, 0x00, 0x04, 0x00, 0x6a, 0x00, 0x76, 0x43, 0x8b, 0x45, 0xf8, 0x8d, 0x55, 0xfc, 0x52, 0x68, 0x00, 0x00, 0x04, 0x00, 0x56, 0x50, 0xff, 0x15, 0x2c, 0xb1, 0x43, 0x00, 0x6a, 0x05, 0xff, 0xd3, 0xa1, 0xe0, 0x30, 0x44, 0x00, 0x81, 0xef, 0x00, 0x00, 0x04, 0x00, 0x81, 0xc6, 0x00, 0x00, 0x04, 0x00, 0x85, 0xc0, 0x74, 0xc5, 0x8b, 0x5d, 0xf8, 0x53, 0xe8, 0xf4, 0xfb, 0xff, 0xff, 0x8b, 0x45, 0x0c, 0x83, 0xc4, 0x04, 0x5f, 0x5e, 0x5b, 0x8b, 0xe5, 0x5d, 0xc3, 0x8b, 0x55, 0xf8, 0x8d, 0x4d, 0xfc, 0x51, 0x57, 0x56, 0x52, 0xff, 0x15, 0x2c, 0xb1, 0x43, 0x00, 0xeb, 0xd8, 0x8b, 0x45, 0xe8, 0x83, 0xc0, 0x20, 0x50, 0x6a, 0x00, 0xe8, 0x47, 0x28, 0x01, 0x00, 0x8b, 0x7d, 0xe8, 0x89, 0x45, 0xf4, 0x8b, 0xf0, 0xa1, 0xe0, 0x30, 0x44, 0x00, 0x83, 0xc4, 0x08, 0x85, 0xc0, 0x75, 0x56, 0x8b, 0x1d, 0xd0, 0xb0, 0x43, 0x00, 0x85, 0xff, 0x76, 0x49, 0x81, 0xff, 0x00, 0x00, 0x04, 0x00, 0x6a, 0x00, 0x76 }; void Grp::LoadCgm() { /* cgm ファイル読み込み */ const char* fname = config->GetParaStr("#CGTABLE_FILE"); if (fname == NULL) return; ARCINFO* info = FileSearcher::GetInstance()->Find(FileSearcher::ALL, fname, ""); if (info == NULL) return; char* data = info->CopyRead(); int sz = info->Size(); delete info; if ( strncmp(data, "CGTABLE", 7) != 0) { delete[] data; return; } cgm_size = read_little_endian_int(data+0x10); int i, j; // xor 解除 for (i=0; i < sz-0x20; i++) { data[i+0x20]^=decode_char[i&0xff]; } // 展開 int dest_size = cgm_size * 36; char* dest = new char[dest_size+1024]; char* src = data + 0x28; char* dest_orig = dest; ARCINFO::Extract2k(dest,src,dest+dest_size,data+sz); dest = dest_orig; for (i=0; i<cgm_size; i++) { char* s = dest + i * 36; int n = read_little_endian_int(dest + i * 36 + 32); cgm_info[s] = n; } delete[] data; delete[] dest_orig; } /***************************************************** * * Grp :: Save, Load : セーブファイル処理 * */ void Grp::Save(std::string& str) { } void Grp::Load(const char* str) { status = NORMAL; if (anm1 != NULL) { AbortAnm(); } if (anm2 != NULL) { anm2->Abort(); delete anm2; anm2 = NULL; } map<int,GrpObj>::iterator it; for (it=grpobj.begin(); it!=grpobj.end(); it++) { PicBase* p = it->second.DeletePic(); delete p; } grpobj.clear(); bg_name = ""; music->StopCDROM(100); } void Grp::SaveSys(string& save) { char buf[1024]; save = "\n[Graphics]\n"; save += "CGM_CG="; set<int>::iterator it; for (it=cgm_data.begin(); it != cgm_data.end(); it++) { sprintf(buf,"%d,",*it); save += buf; } save += "\n"; } void Grp::LoadSys(const char* save) { cgm_data.clear(); save = strstr(save, "\n[Graphics]\n"); if (save) { save += strlen("\n[Graphics]\n"); do { if (save[0] == '[') break; // next section if (strncmp(save, "CGM_CG=",7) == 0) { save += 7; while(isdigit(*save)) { int n = atoi(save); cgm_data.insert(n); save = strchr(save, ','); if (save) save++; } } save = strchr(save, '\n'); if (save) save++; } while (save); } return; } /***************************************************** * * Grp :: Wait , Exec : コマンド実行部 * */ static vector<int> drawn_images; static int draw_n = 0; extern bool grpdump_req; bool Grp::Wait(unsigned int current_time, Cmd& cmd) { if (grpdump_req) { grpdump_req = 0; GrpObjMap::iterator it; fprintf(stderr,"front %p(%d) / %p(%d)\n",screen,screen->IsHidden(),screen_front,screen_front->IsHidden()); for (it=grpobj.begin(); it != grpobj.end(); it++) { GrpObj& obj = it->second; obj._debug_Dump(it->first, 0); } std::list<PicBase*>::iterator it2; for (it2=parent.children.begin(); it2!=parent.children.end();it2++) { fprintf(stderr,"%p(%d)\n",*it2,(*it2)->IsHidden()); } RefreshObj(); } #if 0 if (event.presscount(MOUSE_UP)) { std::list<PicBase*>::iterator lit; draw_n++; int i=0; for (lit=parent.children.end(); lit!=parent.children.begin(); ) { lit--; (*lit)->hide(); i++; if (i >= draw_n) break; } if (drawn_images.empty()) { map<int, GrpObj>::iterator it; for (it=grpobj.begin(); it!=grpobj.end(); it++) { if (it->second.picture) { drawn_images.push_back(it->first); PicBase* p = it->second.DeletePic(); delete p; } } } else { vector<int>::iterator it; for (it=drawn_images.begin(); it!=drawn_images.end(); it++) { CreateObj(*it); } drawn_images.clear(); } } #endif if (status == WAIT_ANM) { if (anm1 != NULL) { if (!anm1->IsEnd()) return true; //FIXME: Handle animation loops AbortAnm(); } } else if (status == WAIT_SHAKE) { if (anm2 != NULL) { if (!anm2->IsEnd()) return true; delete anm2; anm2 = NULL; } status = NORMAL; } else if (status == WAIT_SE) { if (music->IsStopSE()) status = NORMAL; return true; } else if (status == WAIT_MOVIE) { if (music->IsStopMovie()) { music->StopMovie(); status = NORMAL; screen->ReBlit(); } return true; } if (anm2 != NULL) { if (anm2->IsEnd()) { delete anm2; anm2 = NULL; } } return false; } void Grp::DeleteObjPic(int num) { // object の surface のみ削除 if (grpobj.find(num) == grpobj.end()) return; deleted_pic.push_back(grpobj[num].DeletePic()); } void Grp::DeleteSubObjPic(int num_grp, int num) { if (grpobj.find(num_grp) == grpobj.end()) return; if (grpobj[num_grp].children_obj.find(num) == grpobj[num_grp].children_obj.end()) return; deleted_pic.push_back(grpobj[num_grp].children_obj[num].DeletePic()); } void Grp::DeleteObj(int num) { if (grpobj.find(num) == grpobj.end()) return; deleted_pic.push_back(grpobj[num].DeletePic()); GrpObjMap::iterator it; for (it = grpobj[num].children_obj.begin(); it != grpobj[num].children_obj.end(); it++) { deleted_pic.push_back(it->second.DeletePic()); } grpobj.erase(num); } void Grp::DeleteSubObj(int num_grp, int num) { if (grpobj.find(num_grp) == grpobj.end()) return; if (grpobj[num_grp].children_obj.find(num) == grpobj[num_grp].children_obj.end()) return; deleted_pic.push_back(grpobj[num_grp].children_obj[num].DeletePic()); grpobj[num_grp].children_obj.erase(num); } void Grp::Exec(Cmd& cmd) { if (cmd.cmd_type == CMD_TEXTEND) { music->StopKoe(500); // テキスト終了で声を止める cmd.clear(); return; } if (cmd.cmd_type == CMD_WAITFRAMEUPDATE) { // wait する場合は RefreshObj() しておく RefreshObj(); } if (cmd.cmd_type != CMD_OTHER) return; CommandHandler::Exec(cmd); //TODO: ??? if (cmd.cmd1 == 1 && cmd.cmd2 == 60 && cmd.cmd3 == 0) { // ??? : KANOGI : 画像オブジェクトの削除? DeleteObjPic(cmd.args[0].value); // 旧ファイル名のsurfaceを削除 GrpObj& g = grpobj[cmd.args[0].value]; g.attr = GrpObj::Attribute(g.attr | GrpObj::HIDDEN); cmd.clear(); } // Refresh changed objects... //FIXME: should may be go away? //Seems it'll work only for objects in the foreground if ( (cmd.cmd1 == 1 || cmd.cmd1 == 2) && cmd.cmd2 == 81) { GrpObj* g; if (cmd.cmd1 == 2) g = GetGraphicObj(cmd.args[0].value, cmd.args[1].value); else g = GetGraphicObj(cmd.args[0].value); if (g->attr & GrpObj::UPDATE_ALL) SetObjChanged(cmd.args[0].value); } }