/* * ShGraph.c アニメーション関連 module * * 大悪司 * * Copyright (C) 1997-1998 Masaki Chikama (Wren) * 1998- * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ /* $Id: ShGraph.c,v 1.7 2002/09/01 11:54:51 chikama Exp $ */ #include "config.h" #include #include #include #include "portab.h" #include "system.h" #include "xsystem35.h" #include "modules.h" #include "nact.h" #include "ags.h" #include "music.h" #include "hacks.h" #define SLOT 40 static SDL_Rect maprect; /* アニメーション表示領域 */ static SDL_Rect mapback; /* 背景セーブ領域 */ static int mapback_p5; /* 背景転送先 X */ static int mapback_p6; /* 背景転送先 Y */ struct animsrc { int x; int y; int w; int h; int uw; int uh; int r; int g; int b; }; static struct animsrc src[SLOT]; /* アニメーション各コマ転送元 */ struct _s0 { vmvar_t *dst_p1; vmvar_t *dst_p2; int dw_1000A188; }; static struct _s0 s0[SLOT]; struct _s1 { int add_p2; int add_p3; int w_1000A378; int add_p4; int add_p6; // wavfile; }; static struct _s1 s1[SLOT]; struct _s2 { int dst_p3; int dst_p4; int dst_p5; int dst_p6; int w_1000A8A0; int w_1000A8A2; }; static struct _s2 s2[SLOT]; static vmvar_t *add_p5[SLOT]; /* どこまでアニメーションのコマが進んだか */ static void copy_sprite(int sx, int sy, int width, int height, int dx, int dy, int r, int g, int b) { SDL_Surface *sf = nact->ags.dib->sdl_surface; SDL_SetColorKey(sf, SDL_TRUE, SDL_MapRGB(sf->format, r, g, b)); SDL_Rect src_rect = { sx, sy, width, height }; SDL_Rect dst_rect = { dx, dy, width, height }; SDL_BlitSurface(sf, &src_rect, sf, &dst_rect); SDL_SetColorKey(sf, SDL_FALSE, 0); } static void Init() { /* モジュール初期化 */ int p1 = getCaliValue(); /* ISurface */ TRACE("ShGraph.Init %d:", p1); } static void GetSurfaceData() { int p1 = getCaliValue(); /* ISurface */ TRACE_UNIMPLEMENTED("ShGraph.GetSurfaceData %d:", p1); } static void ChangeEquColor() { int p1 = getCaliValue(); int p2 = getCaliValue(); int p3 = getCaliValue(); int p4 = getCaliValue(); vmvar_t *p5 = getCaliVariable(); vmvar_t *p6 = getCaliVariable(); int p7 = getCaliValue(); /* ISurface */ TRACE_UNIMPLEMENTED("ShGraph.ChangeEquColor %d,%d,%d,%d,%p,%p,%d:", p1, p2, p3, p4, p5, p6, p7); } static void ChangeNotColor() { /* 指定の領域が src と等しくなければ dst に塗りつぶす x0: source x0 y0: source y0 width: source width height: source height *src: 塗りつぶし候補の色が入っている変数 src, src+1, src+2 *dst: 塗りつぶしの色が入っている変数 dst, dst+1, dst+2 */ int x0 = getCaliValue(); int y0 = getCaliValue(); int width = getCaliValue(); int height = getCaliValue(); vmvar_t *src = getCaliVariable(); /* r, g, b */ vmvar_t *dst = getCaliVariable(); /* r, g, b */ int p7 = getCaliValue(); /* ISurface */ surface_t *dib; int x, y; uint8_t *dp; TRACE("ShGraph.ChangeNotColor %d,%d,%d,%d,%p,%p,%d:", x0, y0, width, height, src, dst, p7); ags_check_param(&x0, &y0, &width, &height); dib = nact->ags.dib; dp = GETOFFSET_PIXEL(dib, x0, y0); uint32_t pic24s = PIX24(*src, *(src+1), *(src+2)); uint32_t pic24d = PIX24(*dst, *(dst+1), *(dst+2)); uint32_t *yl; for (y = 0; y < height; y++) { yl = (uint32_t *)(dp + y * dib->sdl_surface->pitch); for (x = 0; x < width; x++) { if (*yl != pic24s) { *yl = pic24d; } yl++; } } // The CX command after ChangeNotColor (in FIGHT.ADV) must use a precise // calculation. daiakuji_cx_hack = true; } /* アニメーション使用手順 1: まず、リセット (ResetAnimData 0:) 2: アニメーションを表示する領域の設定 (SetAnimeRect x,y,w,h:) 3: アニメーションの背景が書かれている領域の設定 (SetAnimeBack sx,sy,w,h,dx,dy:) dx, dy は転送先 4: 各アニメーションのパターンの領域の設定 (SetAnimeSrc slot,sx,sy,w,h,uw,uh,pal) 5: 各アニメーションの表示座標の設定 (SetAnimeDst slot,varx,vary,offx,offy,offw,offh:) 6: アニメーションパターンの設定 何番のスロットをどの順番で再生するかを指定 (SetAnimeData pat,src,dst,num,varpat,waveno:) 例 ShGraph.AddAnimeData 1,11,11,5,var1,81: ShGraph.AddAnimeData 1,13,12,8,var2,84: ShGraph.AddAnimeData 1,14,12,2,var3,20736: アニメその1は パターン 11->13->14 のスロットを再生。それぞれ、5コマ, 8コマ,2コマづつ使用する。表示位置は 11->12->12 のスロットを使用。 7: 実際に再生するアニメを決定。(AddAnimeRemain slot:) 8: 指定するスロットまでアニメ再生 (PlayAnimeData lastslot,wait:) lastslotが0の場合は 7 で指定したところまで。 */ static void ResetAnimeData() { /* アニメーション用の各種データをクリア no: クリア対象スロット(0なら全スロットクリア) */ int no = getCaliValue(); TRACE("ShGraph.ResetAnimeData %d:", no); if (no > 0 && no <= SLOT) { memset(&src[no-1], 0, sizeof(struct animsrc)); memset(&s0[no-1], 0, sizeof(struct _s2)); memset(&s2[no-1], 0, sizeof(struct _s0)); } else { memset(src, 0, sizeof(struct animsrc) * SLOT); memset(s0, 0, sizeof(struct _s0) * SLOT); memset(s2, 0, sizeof(struct _s2) * SLOT); } memset(s1, 0, sizeof(struct _s1) * SLOT); memset(add_p5, 0, sizeof(vmvar_t *) * SLOT); } static void SetAnimeSrc() { /* アニメーションの各パターンのソース領域の設定 no: スロット番号 x0: src x0 y0: src y0 w : src width h : src height uw: パターンの横の並びの数 uh: パターンの縦の並びの数 *pal: 抜き色を格納してある変数の先頭 (pal, pal+1, pal+2) */ int no = getCaliValue(); int x0 = getCaliValue(); int y0 = getCaliValue(); int w = getCaliValue(); int h = getCaliValue(); int uw = getCaliValue(); int uh = getCaliValue(); vmvar_t *pal = getCaliVariable(); int r, g, b; TRACE("ShGraph.SetAnimeSrc %d,%d,%d,%d,%d,%d,%d,%p:", no, x0, y0, w, h, uw, uh, pal); if (no <= 0 || no > SLOT) return; r = *pal; g = *(pal + 1); b = *(pal + 2); no--; src[no].x = x0; src[no].y = y0; src[no].w = w; src[no].h = h; src[no].uw = uw; src[no].uh = uh; src[no].r = r; src[no].g = g; src[no].b = b; } static void SetAnimeDst() { /* アニメーションの描画先設定 no: スロット番号 p1: 現在の描画先(x)を格納する変数 p2: 現在の描画先(y)を格納する変数 p3: 描画先オフセット (x) 10000が中央(0) p4: 描画先オフセット (y) 10000が中央 p5: 描画先オフセット追加分 (w) 10000が中央 p6: 描画先オフセット追加分 (h) 10000が中央 */ int no = getCaliValue(); vmvar_t *p1 = getCaliVariable(); vmvar_t *p2 = getCaliVariable(); int p3 = getCaliValue(); int p4 = getCaliValue(); int p5 = getCaliValue(); int p6 = getCaliValue(); TRACE("ShGraph.SetAnimeDst %d,%p,%p,%d,%d,%d,%d:", no, p1, p2, p3, p4, p5, p6); if (no <= 0 || no > SLOT) return; no--; s0[no].dst_p1 = p1; s0[no].dst_p2 = p2; s2[no].dst_p3 = p3; s2[no].dst_p4 = p4; s2[no].dst_p5 = p5; s2[no].dst_p6 = p6; s2[no].w_1000A8A0 = 0; s2[no].w_1000A8A2 = 0; } static void AddAnimeData() { /* アニメーション各種設定 no: スロット番号 p2: アニメーションパターン格納先頭スロット p3: アニメーションパターン表示先頭スロット p4: アニメーションパターン個数 p5: 現在どの何番目のパターンを書いているかを保存しておく変数 p6: 効果音 WAV ファイル番号 */ int no = getCaliValue(); int p2 = getCaliValue(); int p3 = getCaliValue(); int p4 = getCaliValue(); vmvar_t *p5 = getCaliVariable(); int p6 = getCaliValue(); int i; TRACE("ShGraph.AddAnimeData %d,%d,%d,%d,%p,%d:", no, p2, p3, p4, p5, p6); if (no <= 0 || no > SLOT) return; no--; for (i = 0; i < SLOT; i++) { if (s1[i].add_p4 == 0 && s1[i].add_p6 == 0) break; } if (i == SLOT) return; s1[i].w_1000A378 = s2[no].w_1000A8A0; s2[no].w_1000A8A0 += p4; if (p4 != 0) { s2[no].w_1000A8A2 = i; } s1[i].add_p2 = p2 -1; s1[i].add_p3 = p3 -1; s1[i].add_p4 = p4; s1[i].add_p6 = p6; add_p5[i] = p5; } static void AddAnimeRemain() { /* アニメーション各種設定 no: スロット番号 */ int no = getCaliValue(); int i, _max = 0; TRACE("ShGraph.AddAnimeRemain %d:", no); if (no <= 0 || no > SLOT) return; for (i = 0; i < SLOT; i++) { _max = max(s2[i].w_1000A8A0, _max); } no--; if (s2[no].w_1000A8A0 < _max) { i = s2[no].w_1000A8A2; s1[i].add_p4 += (_max - s2[no].w_1000A8A0); s2[no].w_1000A8A0 = _max; } } static void SetAnimeRect() { /* アニメーション描画領域設定 x: region x y: region y w: region width h: region height */ int x = getCaliValue(); int y = getCaliValue(); int w = getCaliValue(); int h = getCaliValue(); TRACE("ShGraph.SetAnimeRect %d,%d,%d,%d:", x, y, w, h); maprect.x = x; maprect.y = y; maprect.w = w; maprect.h = h; } static void SetAnimeBack() { /* アニメーション背景領域設定 sx: 背景領域 x sy: 背景領域 y w: 背景領域 width h: 背景領域 height p5: 背景領域 転送先 x オフセット p6: 背景領域 転送先 y オフセット */ int sx = getCaliValue(); int sy = getCaliValue(); int w = getCaliValue(); int h = getCaliValue(); int p5 = getCaliValue(); int p6 = getCaliValue(); TRACE("ShGraph.SetAnimeBack %d,%d,%d,%d,%d,%d:", sx, sy, w, h, p5, p6); mapback.x = sx; mapback.y = sy; mapback.w = w; mapback.h = h; mapback_p5 = p5; mapback_p6 = p6; } static void PlayAnimeData() { /* 実際にアニメーションを実行 p1: 最大再生スロット(0の場合は全部) p2: アニメーションインターバル(10msec単位) */ int p1 = getCaliValue(); int p2 = getCaliValue(); int p3 = getCaliValue(); /* ISurface */ int p4 = getCaliValue(); /* ISys3xDIB */ int p5 = getCaliValue(); /* ITimer */ int p6 = getCaliValue(); /* IWinMsg */ int interval, loop; int i; bool is_backcopied; surface_t *dib; TRACE("ShGraph.PlayAnimeData %d,%d,%d,%d,%d,%d:", p1, p2, p3, p4, p5, p6); interval = p2 * 10; if (p1 == 0) { for (i = 0; i < SLOT; i++) { p1 = max(s2[i].w_1000A8A0, p1); } } if (p1 == 0) return; dib = ags_getDIB(); for (loop = 0; loop < p1; loop++) { int cnt = sys_get_ticks(); is_backcopied = false; for (i = 0; i < SLOT; i++) { int srcno = s1[i].add_p2; int dstno = s1[i].add_p3; int wavno = s1[i].add_p6; #if 0 printf("loop=%d,i=%d,w_1000A378=%d,add_p4=%d,srcno=%d, dstno=%d,dst_p1=%d,dst_p2=%d\n", loop, i, s1[i].w_1000A378, s1[i].add_p4, srcno, dstno, *s0[dstno].dst_p1, *s0[dstno].dst_p2); #endif if (loop < s1[i].w_1000A378) continue; if (s1[i].add_p4 != 0) { int sx, sy, dx, dy; if (!is_backcopied) { is_backcopied = true; ags_copyArea(mapback.x, mapback.y, mapback.w, mapback.h, mapback_p5, mapback_p6); } if (wavno != 0) { if (wavno > 255) { mus_pcm_stop(wavno % 255); } // printf("wavPlay %d\n", wavno % 256); mus_wav_play(wavno % 256, 1); s1[i].add_p6 = 0; } sx = src[srcno].x + (*add_p5[i] % src[srcno].uw) * src[srcno].w; sy = src[srcno].y + (*add_p5[i] / src[srcno].uw) * src[srcno].h; dx = *(s0[dstno].dst_p1) + s2[dstno].dst_p3 -10000; dy = *(s0[dstno].dst_p2) + s2[dstno].dst_p4 -10000; if (dx > 10000) dx = 0; if (dy > 10000) dy = 0; copy_sprite(sx, sy, src[srcno].w, src[srcno].h, maprect.x + dx, maprect.y + dy, src[srcno].r, src[srcno].g, src[srcno].b); *(s0[dstno].dst_p1) += (s2[dstno].dst_p5 - 10000); *(s0[dstno].dst_p2) += (s2[dstno].dst_p6 - 10000); if (*(s0[dstno].dst_p1) >= 10000) { *(s0[dstno].dst_p1) = 0; } if (*(s0[dstno].dst_p2) >= 10000) { *(s0[dstno].dst_p2) = 0; } (*(add_p5[i]))++; s1[i].add_p4--; if (*add_p5[i] >= (src[srcno].uw * src[srcno].uh)) { *add_p5[i] = 0; } } else { if (wavno == 0) continue; s1[i].add_p6 = 0; if (wavno > 255) { mus_wav_stop(wavno % 256); } mus_wav_play(wavno % 256, 1); // printf("wavPlay %d\n", wavno % 256); } } if (is_backcopied && !SDL_RectEmpty(&maprect)) ags_updateArea(maprect.x, maprect.y, maprect.w, maprect.h); int now = sys_get_ticks(); if (now - cnt < interval) { sys_sleep(interval - (now-cnt)); } } } static const ModuleFunc functions[] = { {"AddAnimeData", AddAnimeData}, {"AddAnimeRemain", AddAnimeRemain}, {"ChangeEquColor", ChangeEquColor}, {"ChangeNotColor", ChangeNotColor}, {"GetSurfaceData", GetSurfaceData}, {"Init", Init}, {"PlayAnimeData", PlayAnimeData}, {"ResetAnimeData", ResetAnimeData}, {"SetAnimeBack", SetAnimeBack}, {"SetAnimeDst", SetAnimeDst}, {"SetAnimeRect", SetAnimeRect}, {"SetAnimeSrc", SetAnimeSrc}, }; const Module module_ShGraph = {"ShGraph", functions, sizeof(functions) / sizeof(ModuleFunc)};