diff --git a/history.txt b/history.txt index cec874a..3fee1c8 100644 --- a/history.txt +++ b/history.txt @@ -1,154 +1,154 @@ -2004.07.03 - - Win9x系のOS上で、16bppのDIBSection生成時に落ちる問題を修正した。 - HPC2000版で、簡易にFM音源を再生できるようにした。 - -2004.07.04 - - HPC2000版において、GAPIを使用するバージョンを作成しました。 - こちらは完全にsigmarion3専用です。 - -2004.07.05 - - セーブデータの、オリジナルとの非互換部分を修正しました。 - (テキストウィンドウの枠の有無の記録部分がずれていた) - - セーブ速度の向上を図りました。(HPC2000版で効果絶大) - - HPC2000版で、Only Youのオープニング速度調整部の結果に補正を掛ける - ようにしました。(sigmarion3, 533MHz, GAPI使用を基準に、D09=140) - - HPC2000版で、FM音源の再生品質を向上させました。 - 1-3chは正弦波、4-6chは矩形波、7-9chは三角波として合成しています。 - -2004.07.09 - - HPC2000版を廃止して、sigmarion3+GAPI専用としました。 - PPC2002版を追加しました。 - WINCE版の簡易FM音源を8KHzに変更しました。 - -2005.02.08 - - メッセージスキップ、メッセージウェイトを実装しました。 - -2005.02.09 - - 動詞-目的語メニューの実装を変更しました。 - -2005.02.19 - - sig3版のバイナリを更新しました。 - コンパイラの最適化の不具合です。 - -2006.09.03 - - いつの間にか、ゲーム毎の仕様違いを吸収するロジックが機能しなく - なっていたのを修正しました。(プリプロセッサの定義ミス) - 例えば夢幻泡影のCGの色化けなどが解決しています。 - - Eコマンドの初期領域を(0,0)-(639,399)に変更しました。 - あゆみちゃんのオープニングで画面右端にゴミが残る問題が解決しています。 - - K1-K3で、マウスカーソルの移動をカーソル入力とする処理を実装しました。 - 例えば館3のタイトル画面でマウス操作を受け付けるようになっています。 - -2006.09.04 - - Y27に対応しました。 - -2006.09.05 - - パレット展開の処理を修正しました。 - 特にアンビヴァレンツ、ファニーBeeは例外的な処理を加えています。 - -2006.09.06 - - ファニーBeeの256色PMSが色化けする問題を修正しました。 - パレット展開の指定を無視して常に取得するようにしています。 - -2006.09.07 - - 画面領域を退避してウィンドウを開いた後にパレットが更新されて、 - 退避した領域を復帰したときに色化けする問題の対策を行いました。 - フェード中にパレットの内容の異なるCGを同時に表示した場合に - 色化けする問題の対策を行いました。 - - 夢幻泡影の色化け問題がこれで解決した筈です。 - -2006.09.09 - - ファニーBeeにおいてテキストの窓枠が消える問題、Pコマンドで - パレットを変更しても画面に反映されない問題の対策を行いました。 - -2006.09.15 - - 9/7の修正で、B4の画面退避、窓退避の処理にエンバグしてしまって - いたのを修正しました。 - ぷろすちゅーでんとGのオープニングで文字が重なってしまう問題、 - DPS全部でウィンドウが消えない問題が修正されています。 - -2007.02.22 - - フルスクリーンからウィンドウに移行したときに、ウィンドウが一番下に - いってしまう問題を修正しました。 - - フェードイン状態で更にフェードインしたときに、画面が消えてしまう - 問題の対策を行いました。 - 乙女戦記で迷宮の画面が消える問題が修正されています。 - - 副作用がなければ、多分これで最終版です。 - -2007.02.23 - - おまけで再起動機能を追加しました。 - -2016.01.11 - - フルスクリーン時にメニューを隠すようにしました。 - 16bppから24bppに変更しました。 - Vista以降で文字が化ける問題が解決しているかもしれません。 - - WindowsCE版はもうサポートできないので、ソースから削除しました。 - -2016.01.13 - - 文字の描画も24bppで処理するようにしました。 - Y4の乱数生成をxorshift32にしました。 - 512命令毎にSleep(10)を入れるようにしました。 - -2016.01.15 - - あゆみちゃん物語 フルカラー実写版をサポートしました。 - キーまたはボタンが離されるまで、メニューを表示しないようにしました。 - -2020.03.21 - - SYSTEM1, SYSTEM2用の実行ファイルを統合しました。 - SYSTEM1, SYSTEM2用のAMUS.MDAをリソースに追加しました。 - - マウス操作でメニューが未選択になっているときに、Enterキーを押して - 誤選択されないようにしました。(thanks system3-sdl2) - 連打によってメニューが誤選択されないように待機時間を追加しました。 - - DRIでファイルサイズをチェックするようにしました。 - DRIでリソースからBMUS.MDA, CMUS.MDAを読み込めるようにしました。 - - Super D.P.Sの画面がフェードしたままになる問題を修正しました。 - (Y40-Y43はそもそもフェード命令ではないかもしれない) - - SYSTEM2のUコマンドで、透明色の指定が101の場合はパレットを取得しない - ようにしました。(婦警さんDA) - SYSTEM2のY2コマンドの引数を、最大文字数でなく、文字列変数番号と - 解釈するようにしました。(Super D.P.S) - - ALICEの館をサポートしました。 - あぶない文化祭前夜をサポートしました。 - 闘神都市 ヒントディスクをサポートしました。(闘神ランスは動作しません) - - ALICEの館IIをサポートしました。(ぱっとん、おかゆは動作しません) - DALK ヒントディスクをサポートしました。(零式は動作しません) - Dr.STOP!をサポートしました。(DRD.COMのオープニングは未移植) - prostudent G (FD版)をサポートしました。 - Rance 3 ヒントディスクをサポートしました。(走り女は動作しません) - あゆみちゃん物語 (FD版)をサポートしました。 - あゆみちゃん物語 ヒントディスクをサポートしました。 +2004.07.03 + + Win9x系のOS上で、16bppのDIBSection生成時に落ちる問題を修正した。 + HPC2000版で、簡易にFM音源を再生できるようにした。 + +2004.07.04 + + HPC2000版において、GAPIを使用するバージョンを作成しました。 + こちらは完全にsigmarion3専用です。 + +2004.07.05 + + セーブデータの、オリジナルとの非互換部分を修正しました。 + (テキストウィンドウの枠の有無の記録部分がずれていた) + + セーブ速度の向上を図りました。(HPC2000版で効果絶大) + + HPC2000版で、Only Youのオープニング速度調整部の結果に補正を掛ける + ようにしました。(sigmarion3, 533MHz, GAPI使用を基準に、D09=140) + + HPC2000版で、FM音源の再生品質を向上させました。 + 1-3chは正弦波、4-6chは矩形波、7-9chは三角波として合成しています。 + +2004.07.09 + + HPC2000版を廃止して、sigmarion3+GAPI専用としました。 + PPC2002版を追加しました。 + WINCE版の簡易FM音源を8KHzに変更しました。 + +2005.02.08 + + メッセージスキップ、メッセージウェイトを実装しました。 + +2005.02.09 + + 動詞-目的語メニューの実装を変更しました。 + +2005.02.19 + + sig3版のバイナリを更新しました。 + コンパイラの最適化の不具合です。 + +2006.09.03 + + いつの間にか、ゲーム毎の仕様違いを吸収するロジックが機能しなく + なっていたのを修正しました。(プリプロセッサの定義ミス) + 例えば夢幻泡影のCGの色化けなどが解決しています。 + + Eコマンドの初期領域を(0,0)-(639,399)に変更しました。 + あゆみちゃんのオープニングで画面右端にゴミが残る問題が解決しています。 + + K1-K3で、マウスカーソルの移動をカーソル入力とする処理を実装しました。 + 例えば館3のタイトル画面でマウス操作を受け付けるようになっています。 + +2006.09.04 + + Y27に対応しました。 + +2006.09.05 + + パレット展開の処理を修正しました。 + 特にアンビヴァレンツ、ファニーBeeは例外的な処理を加えています。 + +2006.09.06 + + ファニーBeeの256色PMSが色化けする問題を修正しました。 + パレット展開の指定を無視して常に取得するようにしています。 + +2006.09.07 + + 画面領域を退避してウィンドウを開いた後にパレットが更新されて、 + 退避した領域を復帰したときに色化けする問題の対策を行いました。 + フェード中にパレットの内容の異なるCGを同時に表示した場合に + 色化けする問題の対策を行いました。 + + 夢幻泡影の色化け問題がこれで解決した筈です。 + +2006.09.09 + + ファニーBeeにおいてテキストの窓枠が消える問題、Pコマンドで + パレットを変更しても画面に反映されない問題の対策を行いました。 + +2006.09.15 + + 9/7の修正で、B4の画面退避、窓退避の処理にエンバグしてしまって + いたのを修正しました。 + ぷろすちゅーでんとGのオープニングで文字が重なってしまう問題、 + DPS全部でウィンドウが消えない問題が修正されています。 + +2007.02.22 + + フルスクリーンからウィンドウに移行したときに、ウィンドウが一番下に + いってしまう問題を修正しました。 + + フェードイン状態で更にフェードインしたときに、画面が消えてしまう + 問題の対策を行いました。 + 乙女戦記で迷宮の画面が消える問題が修正されています。 + + 副作用がなければ、多分これで最終版です。 + +2007.02.23 + + おまけで再起動機能を追加しました。 + +2016.01.11 + + フルスクリーン時にメニューを隠すようにしました。 + 16bppから24bppに変更しました。 + Vista以降で文字が化ける問題が解決しているかもしれません。 + + WindowsCE版はもうサポートできないので、ソースから削除しました。 + +2016.01.13 + + 文字の描画も24bppで処理するようにしました。 + Y4の乱数生成をxorshift32にしました。 + 512命令毎にSleep(10)を入れるようにしました。 + +2016.01.15 + + あゆみちゃん物語 フルカラー実写版をサポートしました。 + キーまたはボタンが離されるまで、メニューを表示しないようにしました。 + +2020.03.21 + + SYSTEM1, SYSTEM2用の実行ファイルを統合しました。 + SYSTEM1, SYSTEM2用のAMUS.MDAをリソースに追加しました。 + + マウス操作でメニューが未選択になっているときに、Enterキーを押して + 誤選択されないようにしました。(thanks system3-sdl2) + 連打によってメニューが誤選択されないように待機時間を追加しました。 + + DRIでファイルサイズをチェックするようにしました。 + DRIでリソースからBMUS.MDA, CMUS.MDAを読み込めるようにしました。 + + Super D.P.Sの画面がフェードしたままになる問題を修正しました。 + (Y40-Y43はそもそもフェード命令ではないかもしれない) + + SYSTEM2のUコマンドで、透明色の指定が101の場合はパレットを取得しない + ようにしました。(婦警さんDA) + SYSTEM2のY2コマンドの引数を、最大文字数でなく、文字列変数番号と + 解釈するようにしました。(Super D.P.S) + + ALICEの館をサポートしました。 + あぶない文化祭前夜をサポートしました。 + 闘神都市 ヒントディスクをサポートしました。(闘神ランスは動作しません) + + ALICEの館IIをサポートしました。(ぱっとん、おかゆは動作しません) + DALK ヒントディスクをサポートしました。(零式は動作しません) + Dr.STOP!をサポートしました。(DRD.COMのオープニングは未移植) + prostudent G (FD版)をサポートしました。 + Rance 3 ヒントディスクをサポートしました。(走り女は動作しません) + あゆみちゃん物語 (FD版)をサポートしました。 + あゆみちゃん物語 ヒントディスクをサポートしました。 diff --git a/readme.txt b/readme.txt index ccd1d00..c29aa35 100644 --- a/readme.txt +++ b/readme.txt @@ -1,20 +1,20 @@ -GPL扱いで、適当に。 -このアーカイブについては一切サポート外です。 - -コンパイル環境は以下の通りです。 - - Visual C++ 2008 SP1 - -プロジェクトファイルは以下の通りです。 - - system1.vcproj SYSTEM1汎用 - system2.vcproj SYSTEM2汎用 - system3.vcproj SYSTEM3汎用 - prog_omake.vcproj prostudent G おまけ - -実装上では、近間さんのxsystem35を参考にしています。 -旧作の実装については、Ryu1さんが移植されたDOS版や、 -unitbase内部でsystem35に移植されたものを参考にしています。 - -alsmidiは、Nastyさん、teruさんの作品です。 -REITHUSさんの作成されたMDAデータを内蔵しています。 +GPL扱いで、適当に。 +このアーカイブについては一切サポート外です。 + +コンパイル環境は以下の通りです。 + + Visual C++ 2008 SP1 + +プロジェクトファイルは以下の通りです。 + + system1.vcproj SYSTEM1汎用 + system2.vcproj SYSTEM2汎用 + system3.vcproj SYSTEM3汎用 + prog_omake.vcproj prostudent G おまけ + +実装上では、近間さんのxsystem35を参考にしています。 +旧作の実装については、Ryu1さんが移植されたDOS版や、 +unitbase内部でsystem35に移植されたものを参考にしています。 + +alsmidiは、Nastyさん、teruさんの作品です。 +REITHUSさんの作成されたMDAデータを内蔵しています。 diff --git a/src/common.h b/src/common.h index 3b662c1..1b19973 100644 --- a/src/common.h +++ b/src/common.h @@ -1,59 +1,59 @@ -/* - ALICE SOFT SYSTEM 3 for Win32 - - [ Common Header ] -*/ - -#ifndef _COMMON_H_ -#define _COMMON_H_ - -#include -#include -#include -#include - -#ifdef __EMSCRIPTEN__ -#include -#else -#define EMSCRIPTEN_KEEPALIVE -#endif - -#define FONT_RESOURCE_NAME "MTLc3m.ttf" - -// type definition -typedef uint8_t uint8; -typedef uint16_t uint16; -typedef uint32_t uint32; -typedef int8_t int8; -typedef int16_t int16; -typedef int32_t int32; - -#define ERROR(fmt, ...) \ - SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "%s:%d: " fmt, __func__, __LINE__, ##__VA_ARGS__) -#define WARNING(fmt, ...) \ - SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, "%s:%d: " fmt, __func__, __LINE__, ##__VA_ARGS__) -#define NOTICE SDL_Log - -#ifndef WIN32 - -#define _MAX_PATH PATH_MAX -#define sscanf_s sscanf -#define sprintf_s snprintf - -inline void strcpy_s(char* dst, size_t n, const char* src) -{ - strncpy(dst, src, n); - dst[n - 1] = '\0'; -} - -#endif // !WIN32 - -#ifdef _MSC_VER -#define strcasecmp _stricmp -#endif - -// resource.cpp -SDL_RWops* open_resource(const char* name, const char* type); -SDL_RWops* open_file(const char* name); - -#endif +/* + ALICE SOFT SYSTEM 3 for Win32 + + [ Common Header ] +*/ + +#ifndef _COMMON_H_ +#define _COMMON_H_ + +#include +#include +#include +#include + +#ifdef __EMSCRIPTEN__ +#include +#else +#define EMSCRIPTEN_KEEPALIVE +#endif + +#define FONT_RESOURCE_NAME "MTLc3m.ttf" + +// type definition +typedef uint8_t uint8; +typedef uint16_t uint16; +typedef uint32_t uint32; +typedef int8_t int8; +typedef int16_t int16; +typedef int32_t int32; + +#define ERROR(fmt, ...) \ + SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "%s:%d: " fmt, __func__, __LINE__, ##__VA_ARGS__) +#define WARNING(fmt, ...) \ + SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, "%s:%d: " fmt, __func__, __LINE__, ##__VA_ARGS__) +#define NOTICE SDL_Log + +#ifndef WIN32 + +#define _MAX_PATH PATH_MAX +#define sscanf_s sscanf +#define sprintf_s snprintf + +inline void strcpy_s(char* dst, size_t n, const char* src) +{ + strncpy(dst, src, n); + dst[n - 1] = '\0'; +} + +#endif // !WIN32 + +#ifdef _MSC_VER +#define strcasecmp _stricmp +#endif + +// resource.cpp +SDL_RWops* open_resource(const char* name, const char* type); +SDL_RWops* open_file(const char* name); + +#endif diff --git a/src/fileio.cpp b/src/fileio.cpp index 3ee8ca9..bfe7819 100644 --- a/src/fileio.cpp +++ b/src/fileio.cpp @@ -1,162 +1,162 @@ -/* - ALICE SOFT SYSTEM 3 for Win32 - - [ File I/O ] -*/ - -#include "fileio.h" -#include -#include -#include -#ifndef _WIN32 -#include -#endif -#ifdef __EMSCRIPTEN__ -#include -#endif - -std::string FILEIO::savedir = "."; - -namespace { - -std::string FindFile(const std::string& dir, const char* filename) { - std::string path = dir + "/" + filename; - -#ifndef _WIN32 - // Case-insensitive search for files in `dir`. - DIR* d = opendir(dir.c_str()); - if (!d) - return path; - - while (struct dirent* entry = readdir(d)) { - if (strcasecmp(filename, entry->d_name) == 0) - path = dir + "/" + entry->d_name; - } - closedir(d); -#endif - return path; -} - -} // namespace - -void FILEIO::SetSaveDir(const std::string& dir) -{ - savedir = dir; - while (!savedir.empty() && savedir.back() == '/') - savedir.pop_back(); -} - -int FILEIO::StatSavedata(const char* filename, struct stat* buf) -{ - return stat(FindFile(savedir, filename).c_str(), buf); -} - -FILEIO::~FILEIO(void) -{ - if(fp != NULL) { - Fclose(); - } -} - -bool FILEIO::Fopen(const char *file_name, int mode) -{ - mode_ = mode; - std::string path = - FindFile((mode & FILEIO_SAVEDATA) ? savedir : ".", file_name); - - mode &= ~FILEIO_SAVEDATA; - - if(fp != NULL) { - Fclose(); - } - fp = NULL; - - if(mode == FILEIO_READ_BINARY) { - fp = fopen(path.c_str(), "rb"); - } else if(mode == FILEIO_WRITE_BINARY) { - fp = fopen(path.c_str(), "wb"); - } - return (fp != NULL); -} - -void FILEIO::Fclose() -{ - if(fp) { - fclose(fp); - } - fp = NULL; - -#ifdef __EMSCRIPTEN__ - if (mode_ & FILEIO_WRITE_BINARY) - EM_ASM( xsystem35.shell.syncfs(); ); -#endif -} - -uint32 FILEIO::Fseek(long offset, int origin) -{ - uint32 val = 0xFFFFFFFF; - if(origin == FILEIO_SEEK_CUR) { - val = fseek(fp, offset, SEEK_CUR); - } else if(origin == FILEIO_SEEK_END) { - val = fseek(fp, offset, SEEK_END); - } else if(origin == FILEIO_SEEK_SET) { - val = fseek(fp, offset, SEEK_SET); - } - return val; -} - -uint32 FILEIO::Ftell() -{ - return ftell(fp); -} - -size_t FILEIO::Fread(void* buffer, uint32 size, uint32 count) -{ - return fread(buffer, size, count, fp); -} - -size_t FILEIO::Fwrite(void* buffer, uint32 size, uint32 count) -{ - return fwrite(buffer, size, count, fp); -} - -int FILEIO::Fgetc() -{ - return fgetc(fp); -} - -int FILEIO::Fgetw() -{ - int val = Fgetc(); - return val | (Fgetc() << 8); -} - -void FILEIO::Fgets(char *dest, int length) -{ - int p = 0; - - for(;;) { - int c = Fgetc(); - if(c == 0x0d || c == EOF) { - break; - } - if(c != 0x0a) { - if(p < length + 1) { - dest[p++] = c; - } - } - } - dest[p] = '\0'; -} - -void FILEIO::Fputc(int c) -{ - fputc(c, fp); -} - -void FILEIO::Fputw(int w) -{ - Fputc(w & 0xff); - Fputc((w >> 8) & 0xff); -} - +/* + ALICE SOFT SYSTEM 3 for Win32 + + [ File I/O ] +*/ + +#include "fileio.h" +#include +#include +#include +#ifndef _WIN32 +#include +#endif +#ifdef __EMSCRIPTEN__ +#include +#endif + +std::string FILEIO::savedir = "."; + +namespace { + +std::string FindFile(const std::string& dir, const char* filename) { + std::string path = dir + "/" + filename; + +#ifndef _WIN32 + // Case-insensitive search for files in `dir`. + DIR* d = opendir(dir.c_str()); + if (!d) + return path; + + while (struct dirent* entry = readdir(d)) { + if (strcasecmp(filename, entry->d_name) == 0) + path = dir + "/" + entry->d_name; + } + closedir(d); +#endif + return path; +} + +} // namespace + +void FILEIO::SetSaveDir(const std::string& dir) +{ + savedir = dir; + while (!savedir.empty() && savedir.back() == '/') + savedir.pop_back(); +} + +int FILEIO::StatSavedata(const char* filename, struct stat* buf) +{ + return stat(FindFile(savedir, filename).c_str(), buf); +} + +FILEIO::~FILEIO(void) +{ + if(fp != NULL) { + Fclose(); + } +} + +bool FILEIO::Fopen(const char *file_name, int mode) +{ + mode_ = mode; + std::string path = + FindFile((mode & FILEIO_SAVEDATA) ? savedir : ".", file_name); + + mode &= ~FILEIO_SAVEDATA; + + if(fp != NULL) { + Fclose(); + } + fp = NULL; + + if(mode == FILEIO_READ_BINARY) { + fp = fopen(path.c_str(), "rb"); + } else if(mode == FILEIO_WRITE_BINARY) { + fp = fopen(path.c_str(), "wb"); + } + return (fp != NULL); +} + +void FILEIO::Fclose() +{ + if(fp) { + fclose(fp); + } + fp = NULL; + +#ifdef __EMSCRIPTEN__ + if (mode_ & FILEIO_WRITE_BINARY) + EM_ASM( xsystem35.shell.syncfs(); ); +#endif +} + +uint32 FILEIO::Fseek(long offset, int origin) +{ + uint32 val = 0xFFFFFFFF; + if(origin == FILEIO_SEEK_CUR) { + val = fseek(fp, offset, SEEK_CUR); + } else if(origin == FILEIO_SEEK_END) { + val = fseek(fp, offset, SEEK_END); + } else if(origin == FILEIO_SEEK_SET) { + val = fseek(fp, offset, SEEK_SET); + } + return val; +} + +uint32 FILEIO::Ftell() +{ + return ftell(fp); +} + +size_t FILEIO::Fread(void* buffer, uint32 size, uint32 count) +{ + return fread(buffer, size, count, fp); +} + +size_t FILEIO::Fwrite(void* buffer, uint32 size, uint32 count) +{ + return fwrite(buffer, size, count, fp); +} + +int FILEIO::Fgetc() +{ + return fgetc(fp); +} + +int FILEIO::Fgetw() +{ + int val = Fgetc(); + return val | (Fgetc() << 8); +} + +void FILEIO::Fgets(char *dest, int length) +{ + int p = 0; + + for(;;) { + int c = Fgetc(); + if(c == 0x0d || c == EOF) { + break; + } + if(c != 0x0a) { + if(p < length + 1) { + dest[p++] = c; + } + } + } + dest[p] = '\0'; +} + +void FILEIO::Fputc(int c) +{ + fputc(c, fp); +} + +void FILEIO::Fputw(int w) +{ + Fputc(w & 0xff); + Fputc((w >> 8) & 0xff); +} + diff --git a/src/fileio.h b/src/fileio.h index 797e8fa..bf1321f 100644 --- a/src/fileio.h +++ b/src/fileio.h @@ -1,48 +1,48 @@ -/* - ALICE SOFT SYSTEM 3 for Win32 - - [ File I/O ] -*/ - -#ifndef _FILEIO_H_ -#define _FILEIO_H_ - -#include -#include -#include -#include "common.h" - -#define FILEIO_READ_BINARY 1 -#define FILEIO_WRITE_BINARY 2 -#define FILEIO_SAVEDATA 4 - -#define FILEIO_SEEK_SET 0 -#define FILEIO_SEEK_CUR 1 -#define FILEIO_SEEK_END 2 - -class FILEIO -{ -private: - static std::string savedir; - FILE* fp; - int mode_; -public: - FILEIO() : fp(NULL), mode_(0) {} - ~FILEIO(); - - static void SetSaveDir(const std::string& dir); - static int StatSavedata(const char* filename, struct stat* buf); - bool Fopen(const char *file_name, int mode); - void Fclose(); - uint32 Fseek(long offset, int origin); - uint32 Ftell(); - size_t Fread(void* buffer, uint32 size, uint32 count); - size_t Fwrite(void* buffer, uint32 size, uint32 count); - int Fgetc(); - int Fgetw(); - void Fgets(char* dest, int length); - void Fputc(int c); - void Fputw(int w); -}; - -#endif +/* + ALICE SOFT SYSTEM 3 for Win32 + + [ File I/O ] +*/ + +#ifndef _FILEIO_H_ +#define _FILEIO_H_ + +#include +#include +#include +#include "common.h" + +#define FILEIO_READ_BINARY 1 +#define FILEIO_WRITE_BINARY 2 +#define FILEIO_SAVEDATA 4 + +#define FILEIO_SEEK_SET 0 +#define FILEIO_SEEK_CUR 1 +#define FILEIO_SEEK_END 2 + +class FILEIO +{ +private: + static std::string savedir; + FILE* fp; + int mode_; +public: + FILEIO() : fp(NULL), mode_(0) {} + ~FILEIO(); + + static void SetSaveDir(const std::string& dir); + static int StatSavedata(const char* filename, struct stat* buf); + bool Fopen(const char *file_name, int mode); + void Fclose(); + uint32 Fseek(long offset, int origin); + uint32 Ftell(); + size_t Fread(void* buffer, uint32 size, uint32 count); + size_t Fwrite(void* buffer, uint32 size, uint32 count); + int Fgetc(); + int Fgetw(); + void Fgets(char* dest, int length); + void Fputc(int c); + void Fputw(int w); +}; + +#endif diff --git a/src/linux/mako.cpp b/src/linux/mako.cpp index 3a8d4c8..5d33673 100644 --- a/src/linux/mako.cpp +++ b/src/linux/mako.cpp @@ -1,234 +1,234 @@ -/* - ALICE SOFT SYSTEM 3 for Win32 - - [ MAKO ] -*/ - -#include -#include -#include - -#include "mako.h" -#include "mako_midi.h" -#include "fm/mako_fmgen.h" -#include "../config.h" -#include "dri.h" - -// MIX_INIT_FLUIDSYNTH was renamed to MIX_INIT_MID in SDL_mixer 2.0.2 -#if (SDL_MIXER_MAJOR_VERSION == 2) && (SDL_MIXER_MINOR_VERSION == 0) && (SDL_MIXER_PATCHLEVEL < 2) -#define MIX_INIT_MID MIX_INIT_FLUIDSYNTH -#endif - -namespace { - -const int SAMPLE_RATE = 44100; - -std::vector smf; -Mix_Music *mix_music; -Mix_Chunk *mix_chunk; -SDL_mutex* fm_mutex; -std::unique_ptr fm; - -void FMHook(void *udata, Uint8 *stream, int len) { - SDL_LockMutex(fm_mutex); - fm->Process(reinterpret_cast(stream), len / 4); - SDL_UnlockMutex(fm_mutex); -} - -} // namespace - -MAKO::MAKO(NACT* parent, const Config& config) : - use_fm(config.use_fm), - current_music(0), - next_loop(0), - nact(parent) -{ - int mix_init_flags = MIX_INIT_MID; - - if (!config.playlist.empty() && load_playlist(config.playlist.c_str())) - mix_init_flags |= MIX_INIT_MP3 | MIX_INIT_OGG; - - strcpy_s(amus, 16, "AMUS.DAT"); - strcpy_s(amse, 16, "AMSE.DAT"); // 実際には使わない - - for(int i = 1; i <= 99; i++) { - cd_track[i] = 0; - } - if (Mix_Init(mix_init_flags) != mix_init_flags) - WARNING("Mix_Init(0x%x) failed", mix_init_flags); - if (Mix_OpenAudio(SAMPLE_RATE, AUDIO_S16LSB, 2, 4096) < 0) - WARNING("Mix_OpenAudio failed: %s", Mix_GetError()); -} - -MAKO::~MAKO() -{ - stop_pcm(); - Mix_CloseAudio(); - Mix_Quit(); -} - -bool MAKO::load_playlist(const char* path) -{ - FILE* fp = fopen(path, "r"); - if (!fp) { - WARNING("Cannot open %s", path); - return false; - } - char buf[256]; - while (fgets(buf, sizeof(buf) - 1, fp)) { - for (char *p = buf; *p; p++) { - if (*p == '\\') - *p = '/'; - else if (*p == '\r' || *p == '\n') - *p = '\0'; - } - playlist.push_back(buf[0] ? strdup(buf) : NULL); - } - fclose(fp); - return true; -} - -void MAKO::play_music(int page) -{ - if(current_music == page) - return; - - stop_music(); - - int track = page < 100 ? cd_track[page] : 0; - if(track) { - if (track < playlist.size() && playlist[track]) { - mix_music = Mix_LoadMUS(playlist[track]); - if (!mix_music) { - WARNING("Mix_LoadMUS failed: %s: %s", playlist[track], Mix_GetError()); - return; - } - if (Mix_PlayMusic(mix_music, next_loop ? next_loop : -1) != 0) { - WARNING("Mix_PlayMusic failed: %s", Mix_GetError()); - Mix_FreeMusic(mix_music); - return; - } - } - } else if (use_fm) { - DRI dri; - int size; - uint8* data = dri.load(amus, page, &size); - if (!data) - return; - if (!fm_mutex) - fm_mutex = SDL_CreateMutex(); - - SDL_LockMutex(fm_mutex); - fm = std::make_unique(SAMPLE_RATE, data, true); - Mix_HookMusic(&FMHook, this); - SDL_UnlockMutex(fm_mutex); - } else { - auto midi = std::make_unique(nact, amus); - if (midi->load_mml(page)) { - midi->load_mda(page); - smf = midi->generate_smf(next_loop); - SDL_RWops *rwops = SDL_RWFromConstMem(smf.data(), smf.size()); - mix_music = Mix_LoadMUSType_RW(rwops, MUS_MID, SDL_TRUE /* freesrc */); - if (!mix_music) { - WARNING("Mix_LoadMUS failed: %s", Mix_GetError()); - return; - } - if (Mix_PlayMusic(mix_music, -1) != 0) { - WARNING("Mix_PlayMusic failed: %s", Mix_GetError()); - Mix_FreeMusic(mix_music); - return; - } - } - } - current_music = page; -} - -void MAKO::stop_music() -{ - if (mix_music) { - Mix_FreeMusic(mix_music); - mix_music = NULL; - smf.clear(); - } - Mix_HookMusic(NULL, NULL); - current_music = 0; -} - -bool MAKO::check_music() -{ - return Mix_PlayingMusic(); -} - -void MAKO::get_mark(int* mark, int* loop) -{ - SDL_LockMutex(fm_mutex); - if (fm) { - fm->get_mark(mark, loop); - } else { - *mark = 0; - *loop = 0; - } - SDL_UnlockMutex(fm_mutex); -} - -void MAKO::play_pcm(int page, bool loop) -{ - static char header[44] = { - 'R' , 'I' , 'F' , 'F' , 0x00, 0x00, 0x00, 0x00, 'W' , 'A' , 'V' , 'E' , 'f' , 'm' , 't' , ' ' , - 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x40, 0x1f, 0x00, 0x00, 0x40, 0x1f, 0x00, 0x00, - 0x01, 0x00, 0x08, 0x00, 'd' , 'a' , 't' , 'a' , 0x00, 0x00, 0x00, 0x00 - }; - - stop_pcm(); - - uint8* buffer = NULL; - int size; - DRI* dri = new DRI(); - - if((buffer = dri->load("AWAV.DAT", page, &size)) != NULL) { - // WAV形式 (Only You) - mix_chunk = Mix_LoadWAV_RW(SDL_RWFromConstMem(buffer, size), 1 /* freesrc */); - free(buffer); - Mix_PlayChannel(-1, mix_chunk, loop ? -1 : 0); - } else if((buffer = dri->load("AMSE.DAT", page, &size)) != NULL) { - // AMSE形式 (乙女戦記) - int total = (size - 12) * 2 + 0x24; - int samples = (size - 12) * 2; - - uint8* wav = (uint8*)malloc(total + 8); - memcpy(wav, header, 44); - wav[ 4] = (total >> 0) & 0xff; - wav[ 5] = (total >> 8) & 0xff; - wav[ 6] = (total >> 16) & 0xff; - wav[ 7] = (total >> 24) & 0xff; - wav[40] = (samples >> 0) & 0xff; - wav[41] = (samples >> 8) & 0xff; - wav[42] = (samples >> 16) & 0xff; - wav[43] = (samples >> 24) & 0xff; - for(int i = 12, p = 44; i < size; i++) { - wav[p++] = buffer[i] & 0xf0; - wav[p++] = (buffer[i] & 0x0f) << 4; - } - free(buffer); - - mix_chunk = Mix_LoadWAV_RW(SDL_RWFromConstMem(wav, total + 8), 1 /* freesrc */); - free(wav); - Mix_PlayChannel(-1, mix_chunk, loop ? -1 : 0); - } -} - -void MAKO::stop_pcm() -{ - Mix_HaltChannel(-1); - if (mix_chunk) { - Mix_FreeChunk(mix_chunk); - mix_chunk = NULL; - } -} - -bool MAKO::check_pcm() -{ - // 再生中でtrue - return Mix_Playing(-1) != 0; -} - +/* + ALICE SOFT SYSTEM 3 for Win32 + + [ MAKO ] +*/ + +#include +#include +#include + +#include "mako.h" +#include "mako_midi.h" +#include "fm/mako_fmgen.h" +#include "../config.h" +#include "dri.h" + +// MIX_INIT_FLUIDSYNTH was renamed to MIX_INIT_MID in SDL_mixer 2.0.2 +#if (SDL_MIXER_MAJOR_VERSION == 2) && (SDL_MIXER_MINOR_VERSION == 0) && (SDL_MIXER_PATCHLEVEL < 2) +#define MIX_INIT_MID MIX_INIT_FLUIDSYNTH +#endif + +namespace { + +const int SAMPLE_RATE = 44100; + +std::vector smf; +Mix_Music *mix_music; +Mix_Chunk *mix_chunk; +SDL_mutex* fm_mutex; +std::unique_ptr fm; + +void FMHook(void *udata, Uint8 *stream, int len) { + SDL_LockMutex(fm_mutex); + fm->Process(reinterpret_cast(stream), len / 4); + SDL_UnlockMutex(fm_mutex); +} + +} // namespace + +MAKO::MAKO(NACT* parent, const Config& config) : + use_fm(config.use_fm), + current_music(0), + next_loop(0), + nact(parent) +{ + int mix_init_flags = MIX_INIT_MID; + + if (!config.playlist.empty() && load_playlist(config.playlist.c_str())) + mix_init_flags |= MIX_INIT_MP3 | MIX_INIT_OGG; + + strcpy_s(amus, 16, "AMUS.DAT"); + strcpy_s(amse, 16, "AMSE.DAT"); // 実際には使わない + + for(int i = 1; i <= 99; i++) { + cd_track[i] = 0; + } + if (Mix_Init(mix_init_flags) != mix_init_flags) + WARNING("Mix_Init(0x%x) failed", mix_init_flags); + if (Mix_OpenAudio(SAMPLE_RATE, AUDIO_S16LSB, 2, 4096) < 0) + WARNING("Mix_OpenAudio failed: %s", Mix_GetError()); +} + +MAKO::~MAKO() +{ + stop_pcm(); + Mix_CloseAudio(); + Mix_Quit(); +} + +bool MAKO::load_playlist(const char* path) +{ + FILE* fp = fopen(path, "r"); + if (!fp) { + WARNING("Cannot open %s", path); + return false; + } + char buf[256]; + while (fgets(buf, sizeof(buf) - 1, fp)) { + for (char *p = buf; *p; p++) { + if (*p == '\\') + *p = '/'; + else if (*p == '\r' || *p == '\n') + *p = '\0'; + } + playlist.push_back(buf[0] ? strdup(buf) : NULL); + } + fclose(fp); + return true; +} + +void MAKO::play_music(int page) +{ + if(current_music == page) + return; + + stop_music(); + + int track = page < 100 ? cd_track[page] : 0; + if(track) { + if (track < playlist.size() && playlist[track]) { + mix_music = Mix_LoadMUS(playlist[track]); + if (!mix_music) { + WARNING("Mix_LoadMUS failed: %s: %s", playlist[track], Mix_GetError()); + return; + } + if (Mix_PlayMusic(mix_music, next_loop ? next_loop : -1) != 0) { + WARNING("Mix_PlayMusic failed: %s", Mix_GetError()); + Mix_FreeMusic(mix_music); + return; + } + } + } else if (use_fm) { + DRI dri; + int size; + uint8* data = dri.load(amus, page, &size); + if (!data) + return; + if (!fm_mutex) + fm_mutex = SDL_CreateMutex(); + + SDL_LockMutex(fm_mutex); + fm = std::make_unique(SAMPLE_RATE, data, true); + Mix_HookMusic(&FMHook, this); + SDL_UnlockMutex(fm_mutex); + } else { + auto midi = std::make_unique(nact, amus); + if (midi->load_mml(page)) { + midi->load_mda(page); + smf = midi->generate_smf(next_loop); + SDL_RWops *rwops = SDL_RWFromConstMem(smf.data(), smf.size()); + mix_music = Mix_LoadMUSType_RW(rwops, MUS_MID, SDL_TRUE /* freesrc */); + if (!mix_music) { + WARNING("Mix_LoadMUS failed: %s", Mix_GetError()); + return; + } + if (Mix_PlayMusic(mix_music, -1) != 0) { + WARNING("Mix_PlayMusic failed: %s", Mix_GetError()); + Mix_FreeMusic(mix_music); + return; + } + } + } + current_music = page; +} + +void MAKO::stop_music() +{ + if (mix_music) { + Mix_FreeMusic(mix_music); + mix_music = NULL; + smf.clear(); + } + Mix_HookMusic(NULL, NULL); + current_music = 0; +} + +bool MAKO::check_music() +{ + return Mix_PlayingMusic(); +} + +void MAKO::get_mark(int* mark, int* loop) +{ + SDL_LockMutex(fm_mutex); + if (fm) { + fm->get_mark(mark, loop); + } else { + *mark = 0; + *loop = 0; + } + SDL_UnlockMutex(fm_mutex); +} + +void MAKO::play_pcm(int page, bool loop) +{ + static char header[44] = { + 'R' , 'I' , 'F' , 'F' , 0x00, 0x00, 0x00, 0x00, 'W' , 'A' , 'V' , 'E' , 'f' , 'm' , 't' , ' ' , + 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x40, 0x1f, 0x00, 0x00, 0x40, 0x1f, 0x00, 0x00, + 0x01, 0x00, 0x08, 0x00, 'd' , 'a' , 't' , 'a' , 0x00, 0x00, 0x00, 0x00 + }; + + stop_pcm(); + + uint8* buffer = NULL; + int size; + DRI* dri = new DRI(); + + if((buffer = dri->load("AWAV.DAT", page, &size)) != NULL) { + // WAV形式 (Only You) + mix_chunk = Mix_LoadWAV_RW(SDL_RWFromConstMem(buffer, size), 1 /* freesrc */); + free(buffer); + Mix_PlayChannel(-1, mix_chunk, loop ? -1 : 0); + } else if((buffer = dri->load("AMSE.DAT", page, &size)) != NULL) { + // AMSE形式 (乙女戦記) + int total = (size - 12) * 2 + 0x24; + int samples = (size - 12) * 2; + + uint8* wav = (uint8*)malloc(total + 8); + memcpy(wav, header, 44); + wav[ 4] = (total >> 0) & 0xff; + wav[ 5] = (total >> 8) & 0xff; + wav[ 6] = (total >> 16) & 0xff; + wav[ 7] = (total >> 24) & 0xff; + wav[40] = (samples >> 0) & 0xff; + wav[41] = (samples >> 8) & 0xff; + wav[42] = (samples >> 16) & 0xff; + wav[43] = (samples >> 24) & 0xff; + for(int i = 12, p = 44; i < size; i++) { + wav[p++] = buffer[i] & 0xf0; + wav[p++] = (buffer[i] & 0x0f) << 4; + } + free(buffer); + + mix_chunk = Mix_LoadWAV_RW(SDL_RWFromConstMem(wav, total + 8), 1 /* freesrc */); + free(wav); + Mix_PlayChannel(-1, mix_chunk, loop ? -1 : 0); + } +} + +void MAKO::stop_pcm() +{ + Mix_HaltChannel(-1); + if (mix_chunk) { + Mix_FreeChunk(mix_chunk); + mix_chunk = NULL; + } +} + +bool MAKO::check_pcm() +{ + // 再生中でtrue + return Mix_Playing(-1) != 0; +} + diff --git a/src/resource.cpp b/src/resource.cpp index 2f763e1..076b6cc 100644 --- a/src/resource.cpp +++ b/src/resource.cpp @@ -1,38 +1,38 @@ -#ifdef _WIN32 -#include -#undef ERROR -#endif -#include "common.h" - -SDL_RWops* open_resource(const char* name, const char* type) { -#ifdef _WIN32 - // On Windows, read from resource. - HINSTANCE hInst = GetModuleHandle(NULL); - HRSRC hRes = FindResource(hInst, name, type); - HGLOBAL hGlobal = LoadResource(hInst, hRes); - if (!hGlobal) { - WARNING("Cannot load resource %s (type: %s)", name, type); - return NULL; - } - return SDL_RWFromConstMem(LockResource(hGlobal), SizeofResource(hInst, hRes)); -#else - // On Android, read from APK assets. - // On other platforms, read from a file under RESOURCE_PATH. - char path[_MAX_PATH]; - sprintf_s(path, _MAX_PATH, "%s%s/%s", RESOURCE_PATH, type, name); - return SDL_RWFromFile(path, "rb"); -#endif -} - -SDL_RWops* open_file(const char* name) { -#ifdef __ANDROID__ - // We cannot use SDL_RWFromFile() because it does not resolve relative - // paths using the current directory on Android. - FILE *fp = fopen(name, "rb"); - if (!fp) - return NULL; - return SDL_RWFromFP(fp, SDL_TRUE); -#else - return SDL_RWFromFile(name, "rb"); -#endif -} +#ifdef _WIN32 +#include +#undef ERROR +#endif +#include "common.h" + +SDL_RWops* open_resource(const char* name, const char* type) { +#ifdef _WIN32 + // On Windows, read from resource. + HINSTANCE hInst = GetModuleHandle(NULL); + HRSRC hRes = FindResource(hInst, name, type); + HGLOBAL hGlobal = LoadResource(hInst, hRes); + if (!hGlobal) { + WARNING("Cannot load resource %s (type: %s)", name, type); + return NULL; + } + return SDL_RWFromConstMem(LockResource(hGlobal), SizeofResource(hInst, hRes)); +#else + // On Android, read from APK assets. + // On other platforms, read from a file under RESOURCE_PATH. + char path[_MAX_PATH]; + sprintf_s(path, _MAX_PATH, "%s%s/%s", RESOURCE_PATH, type, name); + return SDL_RWFromFile(path, "rb"); +#endif +} + +SDL_RWops* open_file(const char* name) { +#ifdef __ANDROID__ + // We cannot use SDL_RWFromFile() because it does not resolve relative + // paths using the current directory on Android. + FILE *fp = fopen(name, "rb"); + if (!fp) + return NULL; + return SDL_RWFromFP(fp, SDL_TRUE); +#else + return SDL_RWFromFile(name, "rb"); +#endif +} diff --git a/src/sys/ags.cpp b/src/sys/ags.cpp index 0661097..77cfdbc 100644 --- a/src/sys/ags.cpp +++ b/src/sys/ags.cpp @@ -1,533 +1,533 @@ -/* - ALICE SOFT SYSTEM 3 for Win32 - - [ AGS ] -*/ - -#include "ags.h" -#include -#include "crc32.h" -#include "../config.h" -#include "../fileio.h" - -extern SDL_Window* g_window; -static SDL_Surface* display_surface; - -#define SET_TEXT(n, x1, y1, x2, y2, f) { \ - text_w[n].sx = x1; \ - text_w[n].sy = y1; \ - text_w[n].ex = x2; \ - text_w[n].ey = y2; \ - text_w[n].frame = f; \ -} -#define SET_MENU(n, x1, y1, x2, y2, f) { \ - menu_w[n].sx = x1; \ - menu_w[n].sy = y1; \ - menu_w[n].ex = x2; \ - menu_w[n].ey = y2; \ - menu_w[n].frame = f; \ -} -#define SET_BOX(n, c, x1, y1, x2, y2) { \ - box[n].color = c; \ - box[n].sx = x1; \ - box[n].sy = y1; \ - box[n].ex = x2; \ - box[n].ey = y2; \ -} - -AGS::AGS(NACT* parent, const Config& config) : nact(parent), dirty(false) -{ - sdlRenderer = SDL_CreateRenderer(g_window, -1, 0); - SDL_RenderSetLogicalSize(sdlRenderer, 640, 400); - sdlTexture = SDL_CreateTexture(sdlRenderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STATIC, 640, 400); // TOOD: pixelformat? - - // DIBSection 8bpp * 3 (表, 裏, メニュー) - for(int i = 0; i < 3; i++) { - hBmpScreen[i] = SDL_CreateRGBSurface(0, 640, 480, 32, 0, 0, 0, 0); - SDL_LockSurface(hBmpScreen[i]); - - // TODO: clear surface - // memset(lpBmpScreen[i], 0, 640 * 480 * sizeof(DWORD)); - - // 仮想VRAMへのポインタ取得 - for(int j = 0; j < 480; j++) { - vram[i][j] = surface_line(hBmpScreen[i], j); - } - } - - // DIBSection 24bpp * 1 (最終出力先) - display_surface = hBmpDest = SDL_CreateRGBSurface(0, 640, 480, 32, 0, 0, 0, 0); - SDL_LockSurface(hBmpDest); - // TODO: clear surface - - // フォント - TTF_Init(); - if (!config.font_file.empty()) { - rw_font = open_file(config.font_file.c_str()); - if (!rw_font) - parent->fatal("Cannot open font file %s", config.font_file.c_str()); - } else { - rw_font = open_resource(FONT_RESOURCE_NAME, "fonts"); - if (!rw_font) - parent->fatal("Cannot open default font"); - } - if (rw_font) { - hFont16 = TTF_OpenFontRW(rw_font, 0, 16); - SDL_RWseek(rw_font, 0, SEEK_SET); - hFont24 = TTF_OpenFontRW(rw_font, 0, 24); - SDL_RWseek(rw_font, 0, SEEK_SET); - hFont32 = TTF_OpenFontRW(rw_font, 0, 32); - SDL_RWseek(rw_font, 0, SEEK_SET); - hFont48 = TTF_OpenFontRW(rw_font, 0, 48); - SDL_RWseek(rw_font, 0, SEEK_SET); - hFont64 = TTF_OpenFontRW(rw_font, 0, 64); - if (!hFont16 || !hFont24 || !hFont32 || !hFont48 || !hFont64) { - parent->fatal("TTF_OpenFontRW failed: %s", TTF_GetError()); - } - } - if (config.no_antialias) - ags_setAntialiasedStringMode(0); - - // カーソル初期化 - for(int i = 0; i < 10; i++) { - hCursor[i] = NULL; - } - - // GAIJI.DAT読み込み - memset(gaiji, 0, sizeof(gaiji)); - - FILEIO* fio = new FILEIO(); - if(fio->Fopen("GAIJI.DAT", FILEIO_READ_BINARY)) { - int d1, d2; - while((d1 = fio->Fgetc()) != EOF) { - d2 = fio->Fgetc(); - // jis to sjis - d1 += (d2 & 1) ? 0x1f : 0x7d; - d1 += (d1 > 0x7f) ? 1 : 0; - d2 = ((d2 - 0x21) >> 1) + 0x81; - d2 += (d2 > 0x9f) ? 0x40 : 0; - uint16 code = (d1 & 0xff) | ((d2 & 0xff) << 8); - - if(0xeb9f <= code && code <= 0xebfc) { - for(int i = 0; i < 32; i++) { - gaiji[code - 0xeb9f][i] = fio->Fgetc(); - } - } else if(0xec40 <= code && code <= 0xec9e) { - for(int i = 0; i < 32; i++) { - gaiji[code - 0xec40 + 94][i] = fio->Fgetc(); - } - } else { - fio->Fseek(32, FILEIO_SEEK_CUR); - } - } - fio->Fclose(); - } - delete fio; - - // SYSTEM3 初期化 - - // ACG.DAT - strcpy_s(acg, 16, "ACG.DAT"); - - // パレット - memset(program_palette, 0, sizeof(program_palette)); - program_palette[0x00] = SETPALETTE16(0x0, 0x0, 0x0); - program_palette[0x01] = SETPALETTE16(0x0, 0x0, 0xa); - program_palette[0x02] = SETPALETTE16(0xa, 0x0, 0x0); - program_palette[0x03] = SETPALETTE16(0xa, 0x0, 0xa); - program_palette[0x04] = SETPALETTE16(0x0, 0x0, 0x0); - program_palette[0x05] = SETPALETTE16(0x0, 0xa, 0xa); - program_palette[0x06] = SETPALETTE16(0xa, 0xa, 0x0); - program_palette[0x07] = SETPALETTE16(0xd, 0xd, 0xd); - program_palette[0x08] = SETPALETTE16(0x7, 0x7, 0x7); - program_palette[0x09] = SETPALETTE16(0x0, 0x0, 0xf); - program_palette[0x0a] = SETPALETTE16(0xf, 0x0, 0x0); - program_palette[0x0b] = SETPALETTE16(0xf, 0x0, 0xf); - program_palette[0x0c] = SETPALETTE16(0x0, 0xf, 0x0); - program_palette[0x0d] = SETPALETTE16(0x0, 0xf, 0xf); - program_palette[0x0e] = SETPALETTE16(0xf, 0xf, 0x0); - program_palette[0x0f] = SETPALETTE16(0xf, 0xf, 0xf); - if (nact->sys_ver == 1) { - program_palette[0x10] = SETPALETTE16(0x0, 0x0, 0x0); - program_palette[0x11] = SETPALETTE16(0x0, 0x0, 0xf); - program_palette[0x12] = SETPALETTE16(0xf, 0x0, 0x0); - program_palette[0x13] = SETPALETTE16(0xf, 0x0, 0xf); - program_palette[0x14] = SETPALETTE16(0x0, 0xf, 0x0); - program_palette[0x15] = SETPALETTE16(0x0, 0xf, 0xf); - program_palette[0x16] = SETPALETTE16(0xf, 0xf, 0x0); - program_palette[0x17] = SETPALETTE16(0xf, 0xf, 0xf); - program_palette[0x18] = SETPALETTE16(0x0, 0x0, 0x0); - program_palette[0x19] = SETPALETTE16(0x0, 0x0, 0xf); - program_palette[0x1a] = SETPALETTE16(0xf, 0x0, 0x0); - program_palette[0x1b] = SETPALETTE16(0xf, 0x0, 0xf); - program_palette[0x1c] = SETPALETTE16(0x0, 0xf, 0x0); - program_palette[0x1d] = SETPALETTE16(0x0, 0xf, 0xf); - program_palette[0x1e] = SETPALETTE16(0xf, 0xf, 0x0); - } - program_palette[0x1f] = SETPALETTE16(0xf, 0xf, 0xf); - program_palette[0x2f] = SETPALETTE16(0xf, 0xf, 0xf); - program_palette[0x3f] = SETPALETTE16(0xf, 0xf, 0xf); - program_palette[0x4f] = SETPALETTE16(0xf, 0xf, 0xf); - program_palette[0x5f] = SETPALETTE16(0xf, 0xf, 0xf); - program_palette[0x6f] = SETPALETTE16(0xf, 0xf, 0xf); - program_palette[0x7f] = SETPALETTE16(0xf, 0xf, 0xf); - program_palette[0x8f] = SETPALETTE16(0xf, 0xf, 0xf); - program_palette[0x9f] = SETPALETTE16(0xf, 0xf, 0xf); - program_palette[0xaf] = SETPALETTE16(0xf, 0xf, 0xf); - program_palette[0xbf] = SETPALETTE16(0xf, 0xf, 0xf); - program_palette[0xcf] = SETPALETTE16(0xf, 0xf, 0xf); - program_palette[0xdf] = SETPALETTE16(0xf, 0xf, 0xf); - program_palette[0xef] = SETPALETTE16(0xf, 0xf, 0xf); - - // This improves text antialias - for (int i = 1; i <= 0xf; i++) - program_palette[0xf0 + i] = SETPALETTE16(i, i, i); - - memcpy(screen_palette, program_palette, sizeof(program_palette)); - - // Bコマンド - for(int i = 0; i < 10; i++) { - // ウィンドウの初期位置はシステムによって異なる - switch (nact->crc32_a) { - case CRC32_BUNKASAI: - SET_TEXT(i, 24, 304, 616, 384, false); - SET_MENU(i, 440, 18, 620, 178, true); - break; - case CRC32_CRESCENT: - SET_TEXT(i, 24, 288, 616, 378, false); - // 本来は横メニュー - SET_MENU(i, 464, 50, 623, 240, true); - break; - case CRC32_DPS: - case CRC32_DPS_SG: - //case CRC32_DPS_SG2: - case CRC32_DPS_SG3: - SET_TEXT(i, 48, 288, 594, 393, false); - //SET_MENU(i, 48, 288, 584, 393, false); - SET_MENU(i, 48, 288, 594, 393, false); - break; - case CRC32_FUKEI: - SET_TEXT(i, 44, 282, 593, 396, false); - SET_MENU(i, 460, 14, 635, 214, false); - break; - case CRC32_INTRUDER: - SET_TEXT(i, 8, 280, 629, 393, false); - SET_MENU(i, 448, 136, 623, 340, true); - break; - case CRC32_TENGU: - SET_TEXT(i, 44, 282, 593, 396, false); - SET_MENU(i, 452, 14, 627, 214, false); - break; - case CRC32_TOUSHIN_HINT: - SET_TEXT(i, 8, 311, 623, 391, false); - SET_MENU(i, 452, 14, 627, 214, true); - break; - case CRC32_VAMPIRE: - case CRC32_VAMPIRE_ENG: - SET_TEXT(i, 8, 255, 615, 383, false); - SET_MENU(i, 448, 11, 615, 224, false); - break; - case CRC32_YAKATA: - SET_TEXT(i, 48, 288, 594, 393, false); - SET_MENU(i, 452, 14, 627, 214, false); - break; - case CRC32_DALK_HINT: - SET_TEXT(i, 24, 308, 376, 386, false); - SET_MENU(i, 404, 28, 604, 244, true); - break; - case CRC32_RANCE3_HINT: - SET_TEXT(i, 104, 304, 615, 383, false); - SET_MENU(i, 464, 24, 623, 200, true); - break; - case CRC32_YAKATA2: - SET_TEXT(i, 104, 304, 620, 382, false); - SET_MENU(i, 420, 28, 620, 244, true); - break; - default: - SET_TEXT(i, 8, 311, 623, 391, true); - SET_MENU(i, 464, 80, 623, 240, true); - break; - } - text_w[i].push = false; - text_w[i].screen = NULL; - text_w[i].window = NULL; - menu_w[i].push = true; - menu_w[i].screen = NULL; - menu_w[i].window = NULL; - } - - // Eコマンド - for(int i = 0; i < 20; i++) { -// SET_BOX(i, 0, 0, 0, 631, 399); - SET_BOX(i, 0, 0, 0, 639, 399); - } - if (nact->sys_ver == 2) { - if(nact->crc32_a == CRC32_SDPS && (nact->crc32_b == CRC32_SDPS_TONO || nact->crc32_b == CRC32_SDPS_KAIZOKU)) { - SET_BOX(0, 0, 40, 8, 598, 271); - } else if(nact->crc32_a == CRC32_PROSTUDENTG_FD) { - SET_BOX(0, 0, 64, 13, 407, 289); - SET_BOX(1, 0, 24, 298, 111, 390); - SET_BOX(2, 0, 0, 0, 639, 307); - SET_BOX(3, 0, 0, 0, 319, 399); - SET_BOX(4, 0, (16*8), 310, ((77*8)-1), 390); - SET_BOX(5, 0, (4*8), 310, ((76*8)-1), 390); - SET_BOX(6, 0, (2*8), 317, ((56*8)-1), 389); - SET_BOX(7, 15, 64, 13, 407, 289); - SET_BOX(8, 0, 0, 0, 319, 399); - SET_BOX(9, 0, 320, 0, 639, 40); - } - } - - // 画面選択 - src_screen = dest_screen = 0; - - // 画面サイズ - screen_height = 400; - scroll = 400; - - // メッセージ表示 - text_dest_x = text_w[0].sx; - text_dest_y = text_w[0].sy + 2; - text_space = 2; - text_font_size = 16; - if (nact->sys_ver == 1) { - text_font_color = 15 + 16; - text_frame_color = 15 + 16; - text_back_color = 0 + 16; - } else { - text_font_color = 15; - text_frame_color = 15; - text_back_color = 0; - } - - // メニュー表示 - menu_dest_x = 2; - menu_dest_y = 0; - menu_font_size = 16; - if (nact->sys_ver == 1) { - menu_font_color = 15 + 16; - menu_frame_color = 15 + 16; - menu_back_color = 0 + 16; - } else { - menu_font_color = 15; - menu_frame_color = 15; - menu_back_color = 0; - } - menu_fix = false; - - draw_hankaku = false; - draw_menu = false; - - // CG表示 - set_cg_dest = false; - cg_dest_x = cg_dest_y = 0; - for(int i = 0; i < MAX_CG; i++) { - extract_palette_cg[i] = true; - } - get_palette = extract_palette = extract_cg = true; - palette_bank = -1; - - // マウスカーソル - cursor_color = 15; - cursor_index = 0; -} - -AGS::~AGS() -{ - // 退避領域の開放 - for(int i = 0; i < 10; i++) { - if(menu_w[i].screen) { - free(menu_w[i].screen); - } - if(menu_w[i].window) { - free(menu_w[i].window); - } - if(text_w[i].screen) { - free(text_w[i].screen); - } - if(text_w[i].window) { - free(text_w[i].window); - } - } - - // カーソル開放 - for(int i = 0; i < 10; i++) { - if(hCursor[i]) { - SDL_FreeCursor(hCursor[i]); - } - } - - // フォント開放 - if (rw_font) { - TTF_CloseFont(hFont16); - TTF_CloseFont(hFont24); - TTF_CloseFont(hFont32); - TTF_CloseFont(hFont48); - TTF_CloseFont(hFont64); - SDL_RWclose(rw_font); - } - - // surface開放 - for(int i = 0; i < 3; i++) { - SDL_FreeSurface(hBmpScreen[i]); - } - - SDL_FreeSurface(hBmpDest); - - SDL_DestroyTexture(sdlTexture); - SDL_DestroyRenderer(sdlRenderer); -} - -void AGS::set_palette(int index, int r, int g, int b) -{ - if(index < 16) { - screen_palette[index] = program_palette[index] = SETPALETTE16(r, g, b); - } else { - screen_palette[index] = program_palette[index] = SETPALETTE256(r, g, b); - } -} - -uint8 AGS::get_pixel(int dest, int x, int y) -{ - if(vram[dest][y][x] & 0x80000000) { - return 0; - } else { - return (uint8)vram[dest][y][x]; - } -} - -void AGS::set_pixel(int dest, int x, int y, uint8 color) -{ - vram[dest][y][x] = color; -} - -void AGS::fade_out(int duration_ms, bool white) -{ - if (fade_level) - return; - - fade_color = white ? 255 : 0; - - Uint32 dwStart = SDL_GetTicks(); - while (fade_level < 255) { - nact->sys_sleep(16); - int t = SDL_GetTicks() - dwStart; - fade_level = t >= duration_ms ? 255 : t * 255 / duration_ms; - dirty = true; - } - update_screen(); -} - -void AGS::fade_in(int duration_ms) -{ - if (fade_level == 0) - return; - - Uint32 dwStart = SDL_GetTicks(); - while (fade_level > 0) { - nact->sys_sleep(16); - int t = SDL_GetTicks() - dwStart; - fade_level = t >= duration_ms ? 0 : (duration_ms - t) * 255 / duration_ms; - dirty = true; - } - update_screen(); -} - -void AGS::flush_screen(bool update) -{ - if(update) { - for(int y = 0; y < screen_height; y++) { - uint32* src = vram[0][y]; - uint32* dest = surface_line(hBmpDest, y); - for(int x = 0; x < 640; x++) { - if (nact->sys_ver == 3 && src[x] & 0x80000000) { - // あゆみちゃん物語 フルカラー実写版 - dest[x] = src[x] & 0xffffff; - } else { - dest[x] = screen_palette[src[x] & 0xff]; - } - } - } - } - invalidate_screen(0, 0, 640, screen_height); -} - -void AGS::draw_screen(int sx, int sy, int width, int height) -{ - for(int y = sy; y < (sy + height) && y < 480; y++) { - uint32* src = vram[0][y]; - uint32* dest = surface_line(hBmpDest, y); - for(int x = sx; x < (sx + width) && x < 640; x++) { - uint32 a=src[x]; - if (nact->sys_ver == 3 && src[x] & 0x80000000) { - // あゆみちゃん物語 フルカラー実写版 - dest[x] = src[x] & 0xffffff; - } else { - dest[x] = screen_palette[src[x] & 0xff]; - } - } - } - invalidate_screen(sx, sy, width, height); -} - -void AGS::invalidate_screen(int sx, int sy, int width, int height) -{ - int top = screen_height == 400 ? sy + (scroll - 400) : sy; - if (top < 0) { - height += top; - top = 0; - } - uint32* pixels = surface_line(hBmpDest, top) + sx; - if (sy + height > screen_height) - height = screen_height - sy; - if (sx + width > hBmpDest->w) - width = hBmpDest->w - sx; - SDL_Rect rect = {sx, sy, width, height}; - SDL_UpdateTexture(sdlTexture, &rect, pixels, hBmpDest->pitch); - dirty = true; -} - -void AGS::update_screen() -{ - if (!dirty) - return; - SDL_RenderClear(sdlRenderer); - SDL_RenderCopy(sdlRenderer, sdlTexture, NULL, NULL); - if (fade_level) { - SDL_SetRenderDrawBlendMode(sdlRenderer, SDL_BLENDMODE_BLEND); - SDL_SetRenderDrawColor(sdlRenderer, fade_color, fade_color, fade_color, fade_level); - SDL_RenderFillRect(sdlRenderer, NULL); - SDL_SetRenderDrawBlendMode(sdlRenderer, SDL_BLENDMODE_NONE); - } - SDL_RenderPresent(sdlRenderer); - dirty = false; -} - -void AGS::save_screenshot(const char* path) -{ - SDL_Surface* sf = SDL_CreateRGBSurface(0, 640, screen_height, 32, 0, 0, 0, 0); - SDL_Rect r = {0, 0, 640, screen_height}; - SDL_UnlockSurface(hBmpDest); - SDL_BlitSurface(hBmpDest, &r, sf, NULL); - SDL_LockSurface(hBmpDest); - - if (SDL_SaveBMP(sf, path) != 0) { - SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "system3", - SDL_GetError(), g_window); - SDL_ClearError(); - } - - SDL_FreeSurface(sf); -} - -#ifdef __EMSCRIPTEN__ -extern "C" { - -void* EMSCRIPTEN_KEEPALIVE sdl_getDisplaySurface() { - if (SDL_MUSTLOCK(display_surface)) - return NULL; - return display_surface->pixels; -} - -} -#endif +/* + ALICE SOFT SYSTEM 3 for Win32 + + [ AGS ] +*/ + +#include "ags.h" +#include +#include "crc32.h" +#include "../config.h" +#include "../fileio.h" + +extern SDL_Window* g_window; +static SDL_Surface* display_surface; + +#define SET_TEXT(n, x1, y1, x2, y2, f) { \ + text_w[n].sx = x1; \ + text_w[n].sy = y1; \ + text_w[n].ex = x2; \ + text_w[n].ey = y2; \ + text_w[n].frame = f; \ +} +#define SET_MENU(n, x1, y1, x2, y2, f) { \ + menu_w[n].sx = x1; \ + menu_w[n].sy = y1; \ + menu_w[n].ex = x2; \ + menu_w[n].ey = y2; \ + menu_w[n].frame = f; \ +} +#define SET_BOX(n, c, x1, y1, x2, y2) { \ + box[n].color = c; \ + box[n].sx = x1; \ + box[n].sy = y1; \ + box[n].ex = x2; \ + box[n].ey = y2; \ +} + +AGS::AGS(NACT* parent, const Config& config) : nact(parent), dirty(false) +{ + sdlRenderer = SDL_CreateRenderer(g_window, -1, 0); + SDL_RenderSetLogicalSize(sdlRenderer, 640, 400); + sdlTexture = SDL_CreateTexture(sdlRenderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STATIC, 640, 400); // TOOD: pixelformat? + + // DIBSection 8bpp * 3 (表, 裏, メニュー) + for(int i = 0; i < 3; i++) { + hBmpScreen[i] = SDL_CreateRGBSurface(0, 640, 480, 32, 0, 0, 0, 0); + SDL_LockSurface(hBmpScreen[i]); + + // TODO: clear surface + // memset(lpBmpScreen[i], 0, 640 * 480 * sizeof(DWORD)); + + // 仮想VRAMへのポインタ取得 + for(int j = 0; j < 480; j++) { + vram[i][j] = surface_line(hBmpScreen[i], j); + } + } + + // DIBSection 24bpp * 1 (最終出力先) + display_surface = hBmpDest = SDL_CreateRGBSurface(0, 640, 480, 32, 0, 0, 0, 0); + SDL_LockSurface(hBmpDest); + // TODO: clear surface + + // フォント + TTF_Init(); + if (!config.font_file.empty()) { + rw_font = open_file(config.font_file.c_str()); + if (!rw_font) + parent->fatal("Cannot open font file %s", config.font_file.c_str()); + } else { + rw_font = open_resource(FONT_RESOURCE_NAME, "fonts"); + if (!rw_font) + parent->fatal("Cannot open default font"); + } + if (rw_font) { + hFont16 = TTF_OpenFontRW(rw_font, 0, 16); + SDL_RWseek(rw_font, 0, SEEK_SET); + hFont24 = TTF_OpenFontRW(rw_font, 0, 24); + SDL_RWseek(rw_font, 0, SEEK_SET); + hFont32 = TTF_OpenFontRW(rw_font, 0, 32); + SDL_RWseek(rw_font, 0, SEEK_SET); + hFont48 = TTF_OpenFontRW(rw_font, 0, 48); + SDL_RWseek(rw_font, 0, SEEK_SET); + hFont64 = TTF_OpenFontRW(rw_font, 0, 64); + if (!hFont16 || !hFont24 || !hFont32 || !hFont48 || !hFont64) { + parent->fatal("TTF_OpenFontRW failed: %s", TTF_GetError()); + } + } + if (config.no_antialias) + ags_setAntialiasedStringMode(0); + + // カーソル初期化 + for(int i = 0; i < 10; i++) { + hCursor[i] = NULL; + } + + // GAIJI.DAT読み込み + memset(gaiji, 0, sizeof(gaiji)); + + FILEIO* fio = new FILEIO(); + if(fio->Fopen("GAIJI.DAT", FILEIO_READ_BINARY)) { + int d1, d2; + while((d1 = fio->Fgetc()) != EOF) { + d2 = fio->Fgetc(); + // jis to sjis + d1 += (d2 & 1) ? 0x1f : 0x7d; + d1 += (d1 > 0x7f) ? 1 : 0; + d2 = ((d2 - 0x21) >> 1) + 0x81; + d2 += (d2 > 0x9f) ? 0x40 : 0; + uint16 code = (d1 & 0xff) | ((d2 & 0xff) << 8); + + if(0xeb9f <= code && code <= 0xebfc) { + for(int i = 0; i < 32; i++) { + gaiji[code - 0xeb9f][i] = fio->Fgetc(); + } + } else if(0xec40 <= code && code <= 0xec9e) { + for(int i = 0; i < 32; i++) { + gaiji[code - 0xec40 + 94][i] = fio->Fgetc(); + } + } else { + fio->Fseek(32, FILEIO_SEEK_CUR); + } + } + fio->Fclose(); + } + delete fio; + + // SYSTEM3 初期化 + + // ACG.DAT + strcpy_s(acg, 16, "ACG.DAT"); + + // パレット + memset(program_palette, 0, sizeof(program_palette)); + program_palette[0x00] = SETPALETTE16(0x0, 0x0, 0x0); + program_palette[0x01] = SETPALETTE16(0x0, 0x0, 0xa); + program_palette[0x02] = SETPALETTE16(0xa, 0x0, 0x0); + program_palette[0x03] = SETPALETTE16(0xa, 0x0, 0xa); + program_palette[0x04] = SETPALETTE16(0x0, 0x0, 0x0); + program_palette[0x05] = SETPALETTE16(0x0, 0xa, 0xa); + program_palette[0x06] = SETPALETTE16(0xa, 0xa, 0x0); + program_palette[0x07] = SETPALETTE16(0xd, 0xd, 0xd); + program_palette[0x08] = SETPALETTE16(0x7, 0x7, 0x7); + program_palette[0x09] = SETPALETTE16(0x0, 0x0, 0xf); + program_palette[0x0a] = SETPALETTE16(0xf, 0x0, 0x0); + program_palette[0x0b] = SETPALETTE16(0xf, 0x0, 0xf); + program_palette[0x0c] = SETPALETTE16(0x0, 0xf, 0x0); + program_palette[0x0d] = SETPALETTE16(0x0, 0xf, 0xf); + program_palette[0x0e] = SETPALETTE16(0xf, 0xf, 0x0); + program_palette[0x0f] = SETPALETTE16(0xf, 0xf, 0xf); + if (nact->sys_ver == 1) { + program_palette[0x10] = SETPALETTE16(0x0, 0x0, 0x0); + program_palette[0x11] = SETPALETTE16(0x0, 0x0, 0xf); + program_palette[0x12] = SETPALETTE16(0xf, 0x0, 0x0); + program_palette[0x13] = SETPALETTE16(0xf, 0x0, 0xf); + program_palette[0x14] = SETPALETTE16(0x0, 0xf, 0x0); + program_palette[0x15] = SETPALETTE16(0x0, 0xf, 0xf); + program_palette[0x16] = SETPALETTE16(0xf, 0xf, 0x0); + program_palette[0x17] = SETPALETTE16(0xf, 0xf, 0xf); + program_palette[0x18] = SETPALETTE16(0x0, 0x0, 0x0); + program_palette[0x19] = SETPALETTE16(0x0, 0x0, 0xf); + program_palette[0x1a] = SETPALETTE16(0xf, 0x0, 0x0); + program_palette[0x1b] = SETPALETTE16(0xf, 0x0, 0xf); + program_palette[0x1c] = SETPALETTE16(0x0, 0xf, 0x0); + program_palette[0x1d] = SETPALETTE16(0x0, 0xf, 0xf); + program_palette[0x1e] = SETPALETTE16(0xf, 0xf, 0x0); + } + program_palette[0x1f] = SETPALETTE16(0xf, 0xf, 0xf); + program_palette[0x2f] = SETPALETTE16(0xf, 0xf, 0xf); + program_palette[0x3f] = SETPALETTE16(0xf, 0xf, 0xf); + program_palette[0x4f] = SETPALETTE16(0xf, 0xf, 0xf); + program_palette[0x5f] = SETPALETTE16(0xf, 0xf, 0xf); + program_palette[0x6f] = SETPALETTE16(0xf, 0xf, 0xf); + program_palette[0x7f] = SETPALETTE16(0xf, 0xf, 0xf); + program_palette[0x8f] = SETPALETTE16(0xf, 0xf, 0xf); + program_palette[0x9f] = SETPALETTE16(0xf, 0xf, 0xf); + program_palette[0xaf] = SETPALETTE16(0xf, 0xf, 0xf); + program_palette[0xbf] = SETPALETTE16(0xf, 0xf, 0xf); + program_palette[0xcf] = SETPALETTE16(0xf, 0xf, 0xf); + program_palette[0xdf] = SETPALETTE16(0xf, 0xf, 0xf); + program_palette[0xef] = SETPALETTE16(0xf, 0xf, 0xf); + + // This improves text antialias + for (int i = 1; i <= 0xf; i++) + program_palette[0xf0 + i] = SETPALETTE16(i, i, i); + + memcpy(screen_palette, program_palette, sizeof(program_palette)); + + // Bコマンド + for(int i = 0; i < 10; i++) { + // ウィンドウの初期位置はシステムによって異なる + switch (nact->crc32_a) { + case CRC32_BUNKASAI: + SET_TEXT(i, 24, 304, 616, 384, false); + SET_MENU(i, 440, 18, 620, 178, true); + break; + case CRC32_CRESCENT: + SET_TEXT(i, 24, 288, 616, 378, false); + // 本来は横メニュー + SET_MENU(i, 464, 50, 623, 240, true); + break; + case CRC32_DPS: + case CRC32_DPS_SG: + //case CRC32_DPS_SG2: + case CRC32_DPS_SG3: + SET_TEXT(i, 48, 288, 594, 393, false); + //SET_MENU(i, 48, 288, 584, 393, false); + SET_MENU(i, 48, 288, 594, 393, false); + break; + case CRC32_FUKEI: + SET_TEXT(i, 44, 282, 593, 396, false); + SET_MENU(i, 460, 14, 635, 214, false); + break; + case CRC32_INTRUDER: + SET_TEXT(i, 8, 280, 629, 393, false); + SET_MENU(i, 448, 136, 623, 340, true); + break; + case CRC32_TENGU: + SET_TEXT(i, 44, 282, 593, 396, false); + SET_MENU(i, 452, 14, 627, 214, false); + break; + case CRC32_TOUSHIN_HINT: + SET_TEXT(i, 8, 311, 623, 391, false); + SET_MENU(i, 452, 14, 627, 214, true); + break; + case CRC32_VAMPIRE: + case CRC32_VAMPIRE_ENG: + SET_TEXT(i, 8, 255, 615, 383, false); + SET_MENU(i, 448, 11, 615, 224, false); + break; + case CRC32_YAKATA: + SET_TEXT(i, 48, 288, 594, 393, false); + SET_MENU(i, 452, 14, 627, 214, false); + break; + case CRC32_DALK_HINT: + SET_TEXT(i, 24, 308, 376, 386, false); + SET_MENU(i, 404, 28, 604, 244, true); + break; + case CRC32_RANCE3_HINT: + SET_TEXT(i, 104, 304, 615, 383, false); + SET_MENU(i, 464, 24, 623, 200, true); + break; + case CRC32_YAKATA2: + SET_TEXT(i, 104, 304, 620, 382, false); + SET_MENU(i, 420, 28, 620, 244, true); + break; + default: + SET_TEXT(i, 8, 311, 623, 391, true); + SET_MENU(i, 464, 80, 623, 240, true); + break; + } + text_w[i].push = false; + text_w[i].screen = NULL; + text_w[i].window = NULL; + menu_w[i].push = true; + menu_w[i].screen = NULL; + menu_w[i].window = NULL; + } + + // Eコマンド + for(int i = 0; i < 20; i++) { +// SET_BOX(i, 0, 0, 0, 631, 399); + SET_BOX(i, 0, 0, 0, 639, 399); + } + if (nact->sys_ver == 2) { + if(nact->crc32_a == CRC32_SDPS && (nact->crc32_b == CRC32_SDPS_TONO || nact->crc32_b == CRC32_SDPS_KAIZOKU)) { + SET_BOX(0, 0, 40, 8, 598, 271); + } else if(nact->crc32_a == CRC32_PROSTUDENTG_FD) { + SET_BOX(0, 0, 64, 13, 407, 289); + SET_BOX(1, 0, 24, 298, 111, 390); + SET_BOX(2, 0, 0, 0, 639, 307); + SET_BOX(3, 0, 0, 0, 319, 399); + SET_BOX(4, 0, (16*8), 310, ((77*8)-1), 390); + SET_BOX(5, 0, (4*8), 310, ((76*8)-1), 390); + SET_BOX(6, 0, (2*8), 317, ((56*8)-1), 389); + SET_BOX(7, 15, 64, 13, 407, 289); + SET_BOX(8, 0, 0, 0, 319, 399); + SET_BOX(9, 0, 320, 0, 639, 40); + } + } + + // 画面選択 + src_screen = dest_screen = 0; + + // 画面サイズ + screen_height = 400; + scroll = 400; + + // メッセージ表示 + text_dest_x = text_w[0].sx; + text_dest_y = text_w[0].sy + 2; + text_space = 2; + text_font_size = 16; + if (nact->sys_ver == 1) { + text_font_color = 15 + 16; + text_frame_color = 15 + 16; + text_back_color = 0 + 16; + } else { + text_font_color = 15; + text_frame_color = 15; + text_back_color = 0; + } + + // メニュー表示 + menu_dest_x = 2; + menu_dest_y = 0; + menu_font_size = 16; + if (nact->sys_ver == 1) { + menu_font_color = 15 + 16; + menu_frame_color = 15 + 16; + menu_back_color = 0 + 16; + } else { + menu_font_color = 15; + menu_frame_color = 15; + menu_back_color = 0; + } + menu_fix = false; + + draw_hankaku = false; + draw_menu = false; + + // CG表示 + set_cg_dest = false; + cg_dest_x = cg_dest_y = 0; + for(int i = 0; i < MAX_CG; i++) { + extract_palette_cg[i] = true; + } + get_palette = extract_palette = extract_cg = true; + palette_bank = -1; + + // マウスカーソル + cursor_color = 15; + cursor_index = 0; +} + +AGS::~AGS() +{ + // 退避領域の開放 + for(int i = 0; i < 10; i++) { + if(menu_w[i].screen) { + free(menu_w[i].screen); + } + if(menu_w[i].window) { + free(menu_w[i].window); + } + if(text_w[i].screen) { + free(text_w[i].screen); + } + if(text_w[i].window) { + free(text_w[i].window); + } + } + + // カーソル開放 + for(int i = 0; i < 10; i++) { + if(hCursor[i]) { + SDL_FreeCursor(hCursor[i]); + } + } + + // フォント開放 + if (rw_font) { + TTF_CloseFont(hFont16); + TTF_CloseFont(hFont24); + TTF_CloseFont(hFont32); + TTF_CloseFont(hFont48); + TTF_CloseFont(hFont64); + SDL_RWclose(rw_font); + } + + // surface開放 + for(int i = 0; i < 3; i++) { + SDL_FreeSurface(hBmpScreen[i]); + } + + SDL_FreeSurface(hBmpDest); + + SDL_DestroyTexture(sdlTexture); + SDL_DestroyRenderer(sdlRenderer); +} + +void AGS::set_palette(int index, int r, int g, int b) +{ + if(index < 16) { + screen_palette[index] = program_palette[index] = SETPALETTE16(r, g, b); + } else { + screen_palette[index] = program_palette[index] = SETPALETTE256(r, g, b); + } +} + +uint8 AGS::get_pixel(int dest, int x, int y) +{ + if(vram[dest][y][x] & 0x80000000) { + return 0; + } else { + return (uint8)vram[dest][y][x]; + } +} + +void AGS::set_pixel(int dest, int x, int y, uint8 color) +{ + vram[dest][y][x] = color; +} + +void AGS::fade_out(int duration_ms, bool white) +{ + if (fade_level) + return; + + fade_color = white ? 255 : 0; + + Uint32 dwStart = SDL_GetTicks(); + while (fade_level < 255) { + nact->sys_sleep(16); + int t = SDL_GetTicks() - dwStart; + fade_level = t >= duration_ms ? 255 : t * 255 / duration_ms; + dirty = true; + } + update_screen(); +} + +void AGS::fade_in(int duration_ms) +{ + if (fade_level == 0) + return; + + Uint32 dwStart = SDL_GetTicks(); + while (fade_level > 0) { + nact->sys_sleep(16); + int t = SDL_GetTicks() - dwStart; + fade_level = t >= duration_ms ? 0 : (duration_ms - t) * 255 / duration_ms; + dirty = true; + } + update_screen(); +} + +void AGS::flush_screen(bool update) +{ + if(update) { + for(int y = 0; y < screen_height; y++) { + uint32* src = vram[0][y]; + uint32* dest = surface_line(hBmpDest, y); + for(int x = 0; x < 640; x++) { + if (nact->sys_ver == 3 && src[x] & 0x80000000) { + // あゆみちゃん物語 フルカラー実写版 + dest[x] = src[x] & 0xffffff; + } else { + dest[x] = screen_palette[src[x] & 0xff]; + } + } + } + } + invalidate_screen(0, 0, 640, screen_height); +} + +void AGS::draw_screen(int sx, int sy, int width, int height) +{ + for(int y = sy; y < (sy + height) && y < 480; y++) { + uint32* src = vram[0][y]; + uint32* dest = surface_line(hBmpDest, y); + for(int x = sx; x < (sx + width) && x < 640; x++) { + uint32 a=src[x]; + if (nact->sys_ver == 3 && src[x] & 0x80000000) { + // あゆみちゃん物語 フルカラー実写版 + dest[x] = src[x] & 0xffffff; + } else { + dest[x] = screen_palette[src[x] & 0xff]; + } + } + } + invalidate_screen(sx, sy, width, height); +} + +void AGS::invalidate_screen(int sx, int sy, int width, int height) +{ + int top = screen_height == 400 ? sy + (scroll - 400) : sy; + if (top < 0) { + height += top; + top = 0; + } + uint32* pixels = surface_line(hBmpDest, top) + sx; + if (sy + height > screen_height) + height = screen_height - sy; + if (sx + width > hBmpDest->w) + width = hBmpDest->w - sx; + SDL_Rect rect = {sx, sy, width, height}; + SDL_UpdateTexture(sdlTexture, &rect, pixels, hBmpDest->pitch); + dirty = true; +} + +void AGS::update_screen() +{ + if (!dirty) + return; + SDL_RenderClear(sdlRenderer); + SDL_RenderCopy(sdlRenderer, sdlTexture, NULL, NULL); + if (fade_level) { + SDL_SetRenderDrawBlendMode(sdlRenderer, SDL_BLENDMODE_BLEND); + SDL_SetRenderDrawColor(sdlRenderer, fade_color, fade_color, fade_color, fade_level); + SDL_RenderFillRect(sdlRenderer, NULL); + SDL_SetRenderDrawBlendMode(sdlRenderer, SDL_BLENDMODE_NONE); + } + SDL_RenderPresent(sdlRenderer); + dirty = false; +} + +void AGS::save_screenshot(const char* path) +{ + SDL_Surface* sf = SDL_CreateRGBSurface(0, 640, screen_height, 32, 0, 0, 0, 0); + SDL_Rect r = {0, 0, 640, screen_height}; + SDL_UnlockSurface(hBmpDest); + SDL_BlitSurface(hBmpDest, &r, sf, NULL); + SDL_LockSurface(hBmpDest); + + if (SDL_SaveBMP(sf, path) != 0) { + SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "system3", + SDL_GetError(), g_window); + SDL_ClearError(); + } + + SDL_FreeSurface(sf); +} + +#ifdef __EMSCRIPTEN__ +extern "C" { + +void* EMSCRIPTEN_KEEPALIVE sdl_getDisplaySurface() { + if (SDL_MUSTLOCK(display_surface)) + return NULL; + return display_surface->pixels; +} + +} +#endif diff --git a/src/sys/ags.h b/src/sys/ags.h index 982e5f1..bd23577 100644 --- a/src/sys/ags.h +++ b/src/sys/ags.h @@ -1,220 +1,220 @@ -/* - ALICE SOFT SYSTEM 3 for Win32 - - [ AGS ] -*/ - -#ifndef _AGS_H_ -#define _AGS_H_ - -#include -#include "../common.h" -#include "nact.h" -#include - -#define MAX_CG 10000 - -static inline uint32 SETPALETTE256(uint32 R, uint32 G, uint32 B) -{ - return ((R & 0xff) << 16) | ((G & 0xff) << 8) | (B & 0xff); -} - -static inline uint32 SETPALETTE16(uint32 R, uint32 G, uint32 B) -{ - R = (255 * (R & 0x0f)) / 15; - G = (255 * (G & 0x0f)) / 15; - B = (255 * (B & 0x0f)) / 15; - return SETPALETTE256(R, G, B); -} - -inline uint32* surface_line(SDL_Surface* surface, int y) -{ - return (uint32*)((uint8*)surface->pixels + surface->pitch * y); -} - -struct Config; - -class AGS -{ -protected: - NACT* nact; -private: - SDL_Renderer* sdlRenderer; - SDL_Texture* sdlTexture; - - // Surface - SDL_Surface* hBmpScreen[3]; // 8bpp * 3 (表, 裏, メニュー) - SDL_Surface* hBmpDest; // DIBSection 24bpp (最終出力先) - - // フォント - SDL_RWops* rw_font; - TTF_Font* hFont16; - TTF_Font* hFont24; - TTF_Font* hFont32; - TTF_Font* hFont48; - TTF_Font* hFont64; - - // カーソル - SDL_Cursor* hCursor[10]; - - // AGS - void load_gm3(uint8* data, int page, int transparent); // Intruder -桜屋敷の探索- - void load_vsp2l(uint8* data, int page, int transparent); // Little Vampire - void load_gl3(uint8* data, int page, int transparent); - void load_pms(uint8* data, int page, int transparent); - void load_bmp(const char* file_name); // あゆみちゃん物語 フルカラー実写版 - void load_vsp(uint8* data, int page, int transparent); - - void draw_char(int dest, int dest_x, int dest_y, uint16 code, TTF_Font* font, uint8 color); - void draw_char_antialias(int dest, int dest_x, int dest_y, uint16 code, TTF_Font* font, uint8 color, uint8 cache[]); - void draw_gaiji(int dest, int dest_x, int dest_y, uint16 code, int size, uint8 color); - - void draw_window(int sx, int sy, int ex, int ey, bool frame, uint8 frame_color, uint8 back_color); - - void draw_screen(int sx, int sy, int width, int heignt); - void invalidate_screen(int sx, int sy, int width, int height); - - uint8 palR(uint8 col) { return screen_palette[col] >> 16 & 0xff; } - uint8 palG(uint8 col) { return screen_palette[col] >> 8 & 0xff; } - uint8 palB(uint8 col) { return screen_palette[col] & 0xff; } - int nearest_color(int r, int g, int b); - - uint32* vram[3][480]; // 仮想VRAMへのポインタ - - uint32 program_palette[256]; - uint32 screen_palette[256]; - uint8 gaiji[188][32]; - - int fade_level = 0; // 0-255 - int fade_color = 0; // 0: black, 255: white - -public: - AGS(NACT* parent, const Config& config); - ~AGS(); - - void update_screen(); - - void flush_screen(bool update); - - void load_cg(int page, int transparent); - - void set_palette(int index, int r, int g, int b); - uint8 get_pixel(int dest, int x, int y); - void set_pixel(int dest, int x, int y, uint8 color); - - void fade_out(int duration_ms, bool white); - void fade_in(int duration_ms); - - void copy(int sx, int sy, int ex, int ey, int dx, int dy); - void gcopy(int gsc, int gde, int glx, int gly, int gsw); - void paint(int x, int y, uint8 color); - void draw_box(int index); - void draw_mesh(int sx, int sy, int width, int height); - void box_fill(int dest, int sx, int sy, int ex, int ey, uint8 color); - void box_line(int dest, int sx, int sy, int ex, int ey, uint8 color); - - void draw_text(const char* string, bool text_wait = false); - - void clear_text_window(int index, bool erase); - bool return_text_line(int index); - void draw_push(int index); - void open_text_window(int index, bool erase); - void close_text_window(int index, bool update); - - void clear_menu_window(); - void open_menu_window(int index); - void redraw_menu_window(int index, int selected); - void close_menu_window(int index); - - void load_cursor(int page); - void select_cursor(); - void translate_mouse_coords(int* x, int* y); - - void save_screenshot(const char* path); - - bool dirty; - - // ACG.DAT - char acg[16]; - - // 画面選択 - int src_screen; - int dest_screen; - - int scroll; - int screen_height; - - // メッセージ表示 - int text_dest_x; - int text_dest_y; - int text_space; - int text_font_size; - uint8 text_font_color; - uint8 text_frame_color; - uint8 text_back_color; - int text_font_maxsize; // その行での最大フォントサイズ - - // メニュー表示 - int menu_dest_x; - int menu_dest_y; - int menu_font_size; - uint8 menu_font_color; - uint8 menu_frame_color; - uint8 menu_back_color; - bool menu_fix; - - bool draw_hankaku; - bool draw_menu; - - // ウィンドウ (Bコマンド) - typedef struct { - int sx; - int sy; - int ex; - int ey; - bool frame; - bool push; - uint32* screen; - int screen_x; - int screen_y; - int screen_width; - int screen_height; - uint32 screen_palette[256]; - uint32* window; - int window_x; - int window_y; - int window_width; - int window_height; - uint32 window_palette[256]; - } WINDOW; - WINDOW menu_w[10]; - WINDOW text_w[10]; - - // ボックス (E, Y7コマンド) - typedef struct { - uint8 color; - int sx; - int sy; - int ex; - int ey; - } BOX; - BOX box[20]; - - // CG表示 - bool set_cg_dest; - int cg_dest_x; - int cg_dest_y; - bool get_palette; - bool extract_palette; - bool extract_cg; - bool extract_palette_cg[MAX_CG]; - int palette_bank; - - // マウスカーソル - uint8 cursor_color; - int cursor_index; -}; - -extern "C" void ags_setAntialiasedStringMode(int on); - -#endif +/* + ALICE SOFT SYSTEM 3 for Win32 + + [ AGS ] +*/ + +#ifndef _AGS_H_ +#define _AGS_H_ + +#include +#include "../common.h" +#include "nact.h" +#include + +#define MAX_CG 10000 + +static inline uint32 SETPALETTE256(uint32 R, uint32 G, uint32 B) +{ + return ((R & 0xff) << 16) | ((G & 0xff) << 8) | (B & 0xff); +} + +static inline uint32 SETPALETTE16(uint32 R, uint32 G, uint32 B) +{ + R = (255 * (R & 0x0f)) / 15; + G = (255 * (G & 0x0f)) / 15; + B = (255 * (B & 0x0f)) / 15; + return SETPALETTE256(R, G, B); +} + +inline uint32* surface_line(SDL_Surface* surface, int y) +{ + return (uint32*)((uint8*)surface->pixels + surface->pitch * y); +} + +struct Config; + +class AGS +{ +protected: + NACT* nact; +private: + SDL_Renderer* sdlRenderer; + SDL_Texture* sdlTexture; + + // Surface + SDL_Surface* hBmpScreen[3]; // 8bpp * 3 (表, 裏, メニュー) + SDL_Surface* hBmpDest; // DIBSection 24bpp (最終出力先) + + // フォント + SDL_RWops* rw_font; + TTF_Font* hFont16; + TTF_Font* hFont24; + TTF_Font* hFont32; + TTF_Font* hFont48; + TTF_Font* hFont64; + + // カーソル + SDL_Cursor* hCursor[10]; + + // AGS + void load_gm3(uint8* data, int page, int transparent); // Intruder -桜屋敷の探索- + void load_vsp2l(uint8* data, int page, int transparent); // Little Vampire + void load_gl3(uint8* data, int page, int transparent); + void load_pms(uint8* data, int page, int transparent); + void load_bmp(const char* file_name); // あゆみちゃん物語 フルカラー実写版 + void load_vsp(uint8* data, int page, int transparent); + + void draw_char(int dest, int dest_x, int dest_y, uint16 code, TTF_Font* font, uint8 color); + void draw_char_antialias(int dest, int dest_x, int dest_y, uint16 code, TTF_Font* font, uint8 color, uint8 cache[]); + void draw_gaiji(int dest, int dest_x, int dest_y, uint16 code, int size, uint8 color); + + void draw_window(int sx, int sy, int ex, int ey, bool frame, uint8 frame_color, uint8 back_color); + + void draw_screen(int sx, int sy, int width, int heignt); + void invalidate_screen(int sx, int sy, int width, int height); + + uint8 palR(uint8 col) { return screen_palette[col] >> 16 & 0xff; } + uint8 palG(uint8 col) { return screen_palette[col] >> 8 & 0xff; } + uint8 palB(uint8 col) { return screen_palette[col] & 0xff; } + int nearest_color(int r, int g, int b); + + uint32* vram[3][480]; // 仮想VRAMへのポインタ + + uint32 program_palette[256]; + uint32 screen_palette[256]; + uint8 gaiji[188][32]; + + int fade_level = 0; // 0-255 + int fade_color = 0; // 0: black, 255: white + +public: + AGS(NACT* parent, const Config& config); + ~AGS(); + + void update_screen(); + + void flush_screen(bool update); + + void load_cg(int page, int transparent); + + void set_palette(int index, int r, int g, int b); + uint8 get_pixel(int dest, int x, int y); + void set_pixel(int dest, int x, int y, uint8 color); + + void fade_out(int duration_ms, bool white); + void fade_in(int duration_ms); + + void copy(int sx, int sy, int ex, int ey, int dx, int dy); + void gcopy(int gsc, int gde, int glx, int gly, int gsw); + void paint(int x, int y, uint8 color); + void draw_box(int index); + void draw_mesh(int sx, int sy, int width, int height); + void box_fill(int dest, int sx, int sy, int ex, int ey, uint8 color); + void box_line(int dest, int sx, int sy, int ex, int ey, uint8 color); + + void draw_text(const char* string, bool text_wait = false); + + void clear_text_window(int index, bool erase); + bool return_text_line(int index); + void draw_push(int index); + void open_text_window(int index, bool erase); + void close_text_window(int index, bool update); + + void clear_menu_window(); + void open_menu_window(int index); + void redraw_menu_window(int index, int selected); + void close_menu_window(int index); + + void load_cursor(int page); + void select_cursor(); + void translate_mouse_coords(int* x, int* y); + + void save_screenshot(const char* path); + + bool dirty; + + // ACG.DAT + char acg[16]; + + // 画面選択 + int src_screen; + int dest_screen; + + int scroll; + int screen_height; + + // メッセージ表示 + int text_dest_x; + int text_dest_y; + int text_space; + int text_font_size; + uint8 text_font_color; + uint8 text_frame_color; + uint8 text_back_color; + int text_font_maxsize; // その行での最大フォントサイズ + + // メニュー表示 + int menu_dest_x; + int menu_dest_y; + int menu_font_size; + uint8 menu_font_color; + uint8 menu_frame_color; + uint8 menu_back_color; + bool menu_fix; + + bool draw_hankaku; + bool draw_menu; + + // ウィンドウ (Bコマンド) + typedef struct { + int sx; + int sy; + int ex; + int ey; + bool frame; + bool push; + uint32* screen; + int screen_x; + int screen_y; + int screen_width; + int screen_height; + uint32 screen_palette[256]; + uint32* window; + int window_x; + int window_y; + int window_width; + int window_height; + uint32 window_palette[256]; + } WINDOW; + WINDOW menu_w[10]; + WINDOW text_w[10]; + + // ボックス (E, Y7コマンド) + typedef struct { + uint8 color; + int sx; + int sy; + int ex; + int ey; + } BOX; + BOX box[20]; + + // CG表示 + bool set_cg_dest; + int cg_dest_x; + int cg_dest_y; + bool get_palette; + bool extract_palette; + bool extract_cg; + bool extract_palette_cg[MAX_CG]; + int palette_bank; + + // マウスカーソル + uint8 cursor_color; + int cursor_index; +}; + +extern "C" void ags_setAntialiasedStringMode(int on); + +#endif diff --git a/src/sys/ags_bmp.cpp b/src/sys/ags_bmp.cpp index ab1bbc9..1cf1587 100644 --- a/src/sys/ags_bmp.cpp +++ b/src/sys/ags_bmp.cpp @@ -1,46 +1,46 @@ -/* - ALICE SOFT SYSTEM 3 for Win32 - - [ AGS - bmp loader ] -*/ - -#include "ags.h" -#include "../fileio.h" - -void AGS::load_bmp(const char* file_name) -{ - // ヘッダ取得 - int sx = 0, sy = 0; - - // Jコマンドの処理 - if(set_cg_dest) { - sx = cg_dest_x; - sy = cg_dest_y; - set_cg_dest = false; - } - - if(extract_cg) { - assert(false); -#if 0 - // BMP読み込み - WCHAR wszFilePath[_MAX_PATH]; - MultiByteToWideChar(CP_ACP, 0, FILEIO::GetFilePath(file_name), -1, wszFilePath, _MAX_PATH); - Gdiplus::Bitmap *pBitmap = Gdiplus::Bitmap::FromFile(wszFilePath); - for(unsigned int y = 0; y < pBitmap->GetHeight(); y++) { - for(unsigned int x = 0; x < pBitmap->GetWidth(); x++) { - Gdiplus::Color srcColor; - pBitmap->GetPixel(x, y, &srcColor); - vram[dest_screen][y + sy][sx + x] = SETPALETTE256(srcColor.GetR(), srcColor.GetG(), srcColor.GetB()) | 0x80000000; - } - } - - // 画面更新 - if(dest_screen == 0) { - draw_screen(sx, sy, pBitmap->GetWidth(), pBitmap->GetHeight()); - } - - // BMP開放 - delete pBitmap; -#endif - } -} +/* + ALICE SOFT SYSTEM 3 for Win32 + + [ AGS - bmp loader ] +*/ + +#include "ags.h" +#include "../fileio.h" + +void AGS::load_bmp(const char* file_name) +{ + // ヘッダ取得 + int sx = 0, sy = 0; + + // Jコマンドの処理 + if(set_cg_dest) { + sx = cg_dest_x; + sy = cg_dest_y; + set_cg_dest = false; + } + + if(extract_cg) { + assert(false); +#if 0 + // BMP読み込み + WCHAR wszFilePath[_MAX_PATH]; + MultiByteToWideChar(CP_ACP, 0, FILEIO::GetFilePath(file_name), -1, wszFilePath, _MAX_PATH); + Gdiplus::Bitmap *pBitmap = Gdiplus::Bitmap::FromFile(wszFilePath); + for(unsigned int y = 0; y < pBitmap->GetHeight(); y++) { + for(unsigned int x = 0; x < pBitmap->GetWidth(); x++) { + Gdiplus::Color srcColor; + pBitmap->GetPixel(x, y, &srcColor); + vram[dest_screen][y + sy][sx + x] = SETPALETTE256(srcColor.GetR(), srcColor.GetG(), srcColor.GetB()) | 0x80000000; + } + } + + // 画面更新 + if(dest_screen == 0) { + draw_screen(sx, sy, pBitmap->GetWidth(), pBitmap->GetHeight()); + } + + // BMP開放 + delete pBitmap; +#endif + } +} diff --git a/src/sys/ags_cursor.cpp b/src/sys/ags_cursor.cpp index 9f3625a..dd2e705 100644 --- a/src/sys/ags_cursor.cpp +++ b/src/sys/ags_cursor.cpp @@ -1,121 +1,121 @@ -/* - ALICE SOFT SYSTEM 3 for Win32 - - [ AGS - draw ] -*/ - -#include "ags.h" -#include - -extern SDL_Window* g_window; - -void AGS::load_cursor(int page) -{ - // カーソルCGをロードする - bool j_set = set_cg_dest; - int j_x = cg_dest_x; - int j_y = cg_dest_y; - int dest = dest_screen; - - set_cg_dest = true; - cg_dest_x = 0; - cg_dest_y = 0; - dest_screen = 1; - - load_cg(page, -1); - - set_cg_dest = j_set; - cg_dest_x = j_x; - cg_dest_y = j_y; - dest_screen = dest; - - // フォントの生成 - for(int i = 0; i < 10; i++) { - // パターン読み込み - uint8 pat[34][34]; - memset(pat, 0, sizeof(pat)); - - for(int y = 0; y < 32; y++) { - for(int x = 0; x < 32; x++) { - pat[y + 1][x + 1] = (vram[1][y >> 1][(x >> 1) + 16 * i] & 0xf) ? 1 : 0; - } - } - - // パターン縁取り - for(int y = 1; y <= 32; y++) { - for(int x = 1; x <= 32; x++) { - if(pat[y][x] == 0 && (pat[y - 1][x] == 1 || pat[y + 1][x] == 1 || pat[y][x - 1] == 1 || pat[y][x + 1] == 1)) { - pat[y][x] = 2; - } - } - } - - // フォント生成 - uint8 amask[128], xmask[128]; - memset(amask, 0, sizeof(amask)); - memset(xmask, 0, sizeof(xmask)); - - for(int y = 0; y < 32; y++) { - for(int x = 0; x < 32; x += 8) { - amask[y * 4 + (x >> 3)] = (pat[y + 1][x + 1] == 0) ? 0x80 : 0; - amask[y * 4 + (x >> 3)] |= (pat[y + 1][x + 2] == 0) ? 0x40 : 0; - amask[y * 4 + (x >> 3)] |= (pat[y + 1][x + 3] == 0) ? 0x20 : 0; - amask[y * 4 + (x >> 3)] |= (pat[y + 1][x + 4] == 0) ? 0x10 : 0; - amask[y * 4 + (x >> 3)] |= (pat[y + 1][x + 5] == 0) ? 0x08 : 0; - amask[y * 4 + (x >> 3)] |= (pat[y + 1][x + 6] == 0) ? 0x04 : 0; - amask[y * 4 + (x >> 3)] |= (pat[y + 1][x + 7] == 0) ? 0x02 : 0; - amask[y * 4 + (x >> 3)] |= (pat[y + 1][x + 8] == 0) ? 0x01 : 0; - - xmask[y * 4 + (x >> 3)] = (pat[y + 1][x + 1] == 1) ? 0x80 : 0; - xmask[y * 4 + (x >> 3)] |= (pat[y + 1][x + 2] == 1) ? 0x40 : 0; - xmask[y * 4 + (x >> 3)] |= (pat[y + 1][x + 3] == 1) ? 0x20 : 0; - xmask[y * 4 + (x >> 3)] |= (pat[y + 1][x + 4] == 1) ? 0x10 : 0; - xmask[y * 4 + (x >> 3)] |= (pat[y + 1][x + 5] == 1) ? 0x08 : 0; - xmask[y * 4 + (x >> 3)] |= (pat[y + 1][x + 6] == 1) ? 0x04 : 0; - xmask[y * 4 + (x >> 3)] |= (pat[y + 1][x + 7] == 1) ? 0x02 : 0; - xmask[y * 4 + (x >> 3)] |= (pat[y + 1][x + 8] == 1) ? 0x01 : 0; - } - } - if(hCursor[i]) { - SDL_FreeCursor(hCursor[i]); - } - // TODO: fix amask/xmask values - hCursor[i] = SDL_CreateCursor(amask, xmask, 32, 32, 2, 2); - } -} - -void AGS::select_cursor() -{ - if(cursor_index == 0) { - SDL_SetCursor(SDL_GetDefaultCursor()); - } else if(1 <= cursor_index && cursor_index <= 10 && hCursor[cursor_index - 1]) { - SDL_SetCursor(hCursor[cursor_index - 1]); - } -} - -void AGS::translate_mouse_coords(int* x, int* y) -{ - // scale mouse x and y - float scalex, scaley; - SDL_RenderGetScale(sdlRenderer, &scalex, &scaley); - *x *= scalex; - *y *= scaley; - - // calculate window borders - int logw, logh; - SDL_RenderGetLogicalSize(sdlRenderer, &logw, &logh); - - float scalew, scaleh; - scalew = logw * scalex; - scaleh = logh * scaley; - - int winw, winh; - SDL_GetWindowSize(g_window, &winw, &winh); - - float border_left = (winw - scalew) / 2; - float border_top = (winh - scaleh) / 2; - - // offset x and y by window borders - *x += border_left; - *y += border_top; -} +/* + ALICE SOFT SYSTEM 3 for Win32 + + [ AGS - draw ] +*/ + +#include "ags.h" +#include + +extern SDL_Window* g_window; + +void AGS::load_cursor(int page) +{ + // カーソルCGをロードする + bool j_set = set_cg_dest; + int j_x = cg_dest_x; + int j_y = cg_dest_y; + int dest = dest_screen; + + set_cg_dest = true; + cg_dest_x = 0; + cg_dest_y = 0; + dest_screen = 1; + + load_cg(page, -1); + + set_cg_dest = j_set; + cg_dest_x = j_x; + cg_dest_y = j_y; + dest_screen = dest; + + // フォントの生成 + for(int i = 0; i < 10; i++) { + // パターン読み込み + uint8 pat[34][34]; + memset(pat, 0, sizeof(pat)); + + for(int y = 0; y < 32; y++) { + for(int x = 0; x < 32; x++) { + pat[y + 1][x + 1] = (vram[1][y >> 1][(x >> 1) + 16 * i] & 0xf) ? 1 : 0; + } + } + + // パターン縁取り + for(int y = 1; y <= 32; y++) { + for(int x = 1; x <= 32; x++) { + if(pat[y][x] == 0 && (pat[y - 1][x] == 1 || pat[y + 1][x] == 1 || pat[y][x - 1] == 1 || pat[y][x + 1] == 1)) { + pat[y][x] = 2; + } + } + } + + // フォント生成 + uint8 amask[128], xmask[128]; + memset(amask, 0, sizeof(amask)); + memset(xmask, 0, sizeof(xmask)); + + for(int y = 0; y < 32; y++) { + for(int x = 0; x < 32; x += 8) { + amask[y * 4 + (x >> 3)] = (pat[y + 1][x + 1] == 0) ? 0x80 : 0; + amask[y * 4 + (x >> 3)] |= (pat[y + 1][x + 2] == 0) ? 0x40 : 0; + amask[y * 4 + (x >> 3)] |= (pat[y + 1][x + 3] == 0) ? 0x20 : 0; + amask[y * 4 + (x >> 3)] |= (pat[y + 1][x + 4] == 0) ? 0x10 : 0; + amask[y * 4 + (x >> 3)] |= (pat[y + 1][x + 5] == 0) ? 0x08 : 0; + amask[y * 4 + (x >> 3)] |= (pat[y + 1][x + 6] == 0) ? 0x04 : 0; + amask[y * 4 + (x >> 3)] |= (pat[y + 1][x + 7] == 0) ? 0x02 : 0; + amask[y * 4 + (x >> 3)] |= (pat[y + 1][x + 8] == 0) ? 0x01 : 0; + + xmask[y * 4 + (x >> 3)] = (pat[y + 1][x + 1] == 1) ? 0x80 : 0; + xmask[y * 4 + (x >> 3)] |= (pat[y + 1][x + 2] == 1) ? 0x40 : 0; + xmask[y * 4 + (x >> 3)] |= (pat[y + 1][x + 3] == 1) ? 0x20 : 0; + xmask[y * 4 + (x >> 3)] |= (pat[y + 1][x + 4] == 1) ? 0x10 : 0; + xmask[y * 4 + (x >> 3)] |= (pat[y + 1][x + 5] == 1) ? 0x08 : 0; + xmask[y * 4 + (x >> 3)] |= (pat[y + 1][x + 6] == 1) ? 0x04 : 0; + xmask[y * 4 + (x >> 3)] |= (pat[y + 1][x + 7] == 1) ? 0x02 : 0; + xmask[y * 4 + (x >> 3)] |= (pat[y + 1][x + 8] == 1) ? 0x01 : 0; + } + } + if(hCursor[i]) { + SDL_FreeCursor(hCursor[i]); + } + // TODO: fix amask/xmask values + hCursor[i] = SDL_CreateCursor(amask, xmask, 32, 32, 2, 2); + } +} + +void AGS::select_cursor() +{ + if(cursor_index == 0) { + SDL_SetCursor(SDL_GetDefaultCursor()); + } else if(1 <= cursor_index && cursor_index <= 10 && hCursor[cursor_index - 1]) { + SDL_SetCursor(hCursor[cursor_index - 1]); + } +} + +void AGS::translate_mouse_coords(int* x, int* y) +{ + // scale mouse x and y + float scalex, scaley; + SDL_RenderGetScale(sdlRenderer, &scalex, &scaley); + *x *= scalex; + *y *= scaley; + + // calculate window borders + int logw, logh; + SDL_RenderGetLogicalSize(sdlRenderer, &logw, &logh); + + float scalew, scaleh; + scalew = logw * scalex; + scaleh = logh * scaley; + + int winw, winh; + SDL_GetWindowSize(g_window, &winw, &winh); + + float border_left = (winw - scalew) / 2; + float border_top = (winh - scaleh) / 2; + + // offset x and y by window borders + *x += border_left; + *y += border_top; +} diff --git a/src/sys/ags_draw.cpp b/src/sys/ags_draw.cpp index 4c536e7..8f111d7 100644 --- a/src/sys/ags_draw.cpp +++ b/src/sys/ags_draw.cpp @@ -1,254 +1,254 @@ -/* - ALICE SOFT SYSTEM 3 for Win32 - - [ AGS - draw ] -*/ - -#include "ags.h" -#include -#include -#include -#include -#include "dri.h" -#include "crc32.h" - -void AGS::load_cg(int page, int transparent) -{ - if (nact->sys_ver == 3) { - // あゆみちゃん物語 フルカラー実写版 - if(strncmp(acg, "CGA000.BMP", 10) == 0) { - char file_name[16]; - sprintf(file_name, "CGA%03d.BMP", page); - load_bmp(file_name); - return; - } else if(strncmp(acg, "CGB000.BMP", 10) == 0) { - char file_name[16]; - sprintf(file_name, "CGB%03d.BMP", page); - load_bmp(file_name); - return; - } - } - DRI* dri = new DRI(); - int size; - uint8* data = dri->load(acg, page, &size); - if(data && size > 0) { - switch (nact->sys_ver) { - case 1: - switch (nact->crc32_a) { - case CRC32_BUNKASAI: - load_vsp(data, page, transparent); - break; - case CRC32_INTRUDER: - // load_gm3(data, page, transparent); - load_vsp(data, page, transparent); // 暫定 - break; - case CRC32_VAMPIRE: - case CRC32_VAMPIRE_ENG: - load_vsp2l(data, page, transparent); - break; - default: - load_gl3(data, page, transparent); - break; - } - break; - case 2: - if(nact->crc32_a == CRC32_AYUMI_PROTO) { - // あゆみちゃん物語 PROTO - load_gl3(data, page, transparent); - } else if(nact->crc32_a == CRC32_AYUMI_FD || nact->crc32_a == CRC32_AYUMI_HINT) { - // あゆみちゃん物語 - load_vsp(data, page, transparent); - } else if(nact->crc32_a == CRC32_SDPS) { - // Super D.P.S - load_pms(data, page, transparent); - } else { - if(data[0x8] == 0) { - load_vsp(data, page, transparent); - } else { - load_pms(data, page, transparent); - } - } - break; - case 3: - if(data[0x8] == 0) { - load_vsp(data, page, transparent); - } else { - load_pms(data, page, transparent); - } - break; - } - } - if (data) - free(data); - delete dri; -} - -void AGS::copy(int sx, int sy, int ex, int ey, int dx, int dy) -{ -#if 0 - int width = ex - sx + 1; - int height = ey - sy + 1; - - uint32 tmp[640 * 480]; - memcpy(tmp, lpBmpScreen[src_screen], sizeof(tmp)); - - for(int y = 0; y < height && y + sy < 480 && y + dy < 480; y++) { - uint32* src = &tmp[640 * (479 - (y + sy))]; - uint32* dest = vram[dest_screen][y + dy]; - for(int x = 0; x < width && x + sx < 640 && x + dx < 640; x++) { - dest[x + dx] = src[x + sx]; - } - } - if(dest_screen == 0) { - draw_screen(dx, dy, width, height); - } -#else - int width = ex - sx + 1; - int height = ey - sy + 1; - SDL_Rect srcrect = {sx, sy, width, height}; - SDL_Rect destrect = {dx, dy, width, height}; - - SDL_UnlockSurface(hBmpScreen[src_screen]); - if (src_screen != dest_screen) - SDL_UnlockSurface(hBmpScreen[dest_screen]); - SDL_BlitSurface(hBmpScreen[src_screen], &srcrect, hBmpScreen[dest_screen], &destrect); - if (src_screen != dest_screen) - SDL_LockSurface(hBmpScreen[dest_screen]); - SDL_LockSurface(hBmpScreen[src_screen]); - - if(dest_screen == 0) { - draw_screen(dx, dy, ex - sx + 1, ey - sy + 1); - } -#endif -} - -void AGS::gcopy(int gsc, int gde, int glx, int gly, int gsw) -{ - // N88-BASIC時代のコピーコマンド - int src = (gsw == 0 || gsw == 2) ? 0 : 1; - int dest = (gsw == 0 || gsw == 3) ? 0 : 1; - int sx = (gsc % 80) * 8; - int sy = gsc / 80; - int dx = (gde % 80) * 8; - int dy = gde / 80; - SDL_Rect srcrect = {sx, sy, glx * 8, gly}; - SDL_Rect destrect = {dx, dy, glx * 8, gly}; - - SDL_UnlockSurface(hBmpScreen[src]); - if (src_screen != dest_screen) - SDL_UnlockSurface(hBmpScreen[dest]); - SDL_BlitSurface(hBmpScreen[src], &srcrect, hBmpScreen[dest], &destrect); - if (src_screen != dest_screen) - SDL_LockSurface(hBmpScreen[dest]); - SDL_LockSurface(hBmpScreen[src]); - - if(dest == 0) { - draw_screen(dx, dy, glx * 8, gly); - } -} - -void AGS::paint(int x, int y, uint8 color) -{ - int old_color = vram[0][y][x]; - if (old_color == color) - return; - - int minx = x, maxx = x, miny = y, maxy = y; - std::vector> stack; - stack.push_back({x, y}); - - while (!stack.empty()) { - std::tie(x, y) = stack.back(); - stack.pop_back(); - while (x >= 0 && vram[0][y][x] == old_color) x--; - x++; - minx = std::min(x, minx); - bool span_above = false, span_below = false; - for (; x < 640 && vram[0][y][x] == old_color; x++) { - vram[0][y][x] = color; - if (y > 0) { - if (!span_above && vram[0][y - 1][x] == old_color) { - stack.push_back({x, y - 1}); - span_above = true; - } else if (span_above && vram[0][y - 1][x] != old_color) { - span_above = false; - } - } - if (y < screen_height - 1) { - if (!span_below && vram[0][y + 1][x] == old_color) { - stack.push_back({x, y + 1}); - span_below = true; - } else if (span_below && vram[0][y + 1][x] != old_color) { - span_below = false; - } - } - } - maxx = std::max(x - 1, maxx); - miny = std::min(y, miny); - maxy = std::max(y, maxy); - } - draw_screen(minx, miny, maxx - minx + 1, maxy - miny + 1); -} - -void AGS::draw_box(int index) -{ - if(index == 0) { - // 全画面消去 - box_fill(dest_screen, 0, 0, 639, 479, 0); - return; - } - - int sx = box[index - 1].sx; - int sy = box[index - 1].sy; - int ex = box[index - 1].ex; - int ey = box[index - 1].ey; - uint8 color = box[index - 1].color; - - if(1 <= index && index <= 10) { - box_fill(dest_screen, sx, sy, ex, ey, color); - } else if(11 <= index && index <= 20) { - box_line(dest_screen, sx, sy, ex, ey, color); - } -} - -void AGS::draw_mesh(int sx, int sy, int width, int height) -{ - // super d.p.s - for(int y = sy, h = 0; h < height && y < 480; y += 2, h += 2) { - for(int x = sx, w = 0; w < width && x < 640; x += 2, w += 2) { - vram[0][y][x] = 255; - } - for(int x = sx + 1, w = 1; w < width && x < 640; x += 2, w += 2) { - vram[0][y + 1][x] = 255; - } - } - draw_screen(sx, sy, width, height); -} - -void AGS::box_fill(int dest, int sx, int sy, int ex, int ey, uint8 color) -{ - for(int y = sy; y <= ey && y < 480; y++) { - for(int x = sx; x <= ex && x < 640; x++) { - vram[dest][y][x] = color; - } - } - if(dest == 0) { - draw_screen(sx, sy, ex - sx + 1, ey - sy + 1); - } -} - -void AGS::box_line(int dest, int sx, int sy, int ex, int ey, uint8 color) -{ - for(int x = sx; x <= ex && x < 640; x++) { - vram[dest][sy][x] = color; - vram[dest][ey][x] = color; - } - for(int y = sy; y <= ey && y < 480; y++) { - vram[dest][y][sx] = color; - vram[dest][y][ex] = color; - } - if(dest == 0) { - draw_screen(sx, sy, ex - sx + 1, ey - sy + 1); - } -} - +/* + ALICE SOFT SYSTEM 3 for Win32 + + [ AGS - draw ] +*/ + +#include "ags.h" +#include +#include +#include +#include +#include "dri.h" +#include "crc32.h" + +void AGS::load_cg(int page, int transparent) +{ + if (nact->sys_ver == 3) { + // あゆみちゃん物語 フルカラー実写版 + if(strncmp(acg, "CGA000.BMP", 10) == 0) { + char file_name[16]; + sprintf(file_name, "CGA%03d.BMP", page); + load_bmp(file_name); + return; + } else if(strncmp(acg, "CGB000.BMP", 10) == 0) { + char file_name[16]; + sprintf(file_name, "CGB%03d.BMP", page); + load_bmp(file_name); + return; + } + } + DRI* dri = new DRI(); + int size; + uint8* data = dri->load(acg, page, &size); + if(data && size > 0) { + switch (nact->sys_ver) { + case 1: + switch (nact->crc32_a) { + case CRC32_BUNKASAI: + load_vsp(data, page, transparent); + break; + case CRC32_INTRUDER: + // load_gm3(data, page, transparent); + load_vsp(data, page, transparent); // 暫定 + break; + case CRC32_VAMPIRE: + case CRC32_VAMPIRE_ENG: + load_vsp2l(data, page, transparent); + break; + default: + load_gl3(data, page, transparent); + break; + } + break; + case 2: + if(nact->crc32_a == CRC32_AYUMI_PROTO) { + // あゆみちゃん物語 PROTO + load_gl3(data, page, transparent); + } else if(nact->crc32_a == CRC32_AYUMI_FD || nact->crc32_a == CRC32_AYUMI_HINT) { + // あゆみちゃん物語 + load_vsp(data, page, transparent); + } else if(nact->crc32_a == CRC32_SDPS) { + // Super D.P.S + load_pms(data, page, transparent); + } else { + if(data[0x8] == 0) { + load_vsp(data, page, transparent); + } else { + load_pms(data, page, transparent); + } + } + break; + case 3: + if(data[0x8] == 0) { + load_vsp(data, page, transparent); + } else { + load_pms(data, page, transparent); + } + break; + } + } + if (data) + free(data); + delete dri; +} + +void AGS::copy(int sx, int sy, int ex, int ey, int dx, int dy) +{ +#if 0 + int width = ex - sx + 1; + int height = ey - sy + 1; + + uint32 tmp[640 * 480]; + memcpy(tmp, lpBmpScreen[src_screen], sizeof(tmp)); + + for(int y = 0; y < height && y + sy < 480 && y + dy < 480; y++) { + uint32* src = &tmp[640 * (479 - (y + sy))]; + uint32* dest = vram[dest_screen][y + dy]; + for(int x = 0; x < width && x + sx < 640 && x + dx < 640; x++) { + dest[x + dx] = src[x + sx]; + } + } + if(dest_screen == 0) { + draw_screen(dx, dy, width, height); + } +#else + int width = ex - sx + 1; + int height = ey - sy + 1; + SDL_Rect srcrect = {sx, sy, width, height}; + SDL_Rect destrect = {dx, dy, width, height}; + + SDL_UnlockSurface(hBmpScreen[src_screen]); + if (src_screen != dest_screen) + SDL_UnlockSurface(hBmpScreen[dest_screen]); + SDL_BlitSurface(hBmpScreen[src_screen], &srcrect, hBmpScreen[dest_screen], &destrect); + if (src_screen != dest_screen) + SDL_LockSurface(hBmpScreen[dest_screen]); + SDL_LockSurface(hBmpScreen[src_screen]); + + if(dest_screen == 0) { + draw_screen(dx, dy, ex - sx + 1, ey - sy + 1); + } +#endif +} + +void AGS::gcopy(int gsc, int gde, int glx, int gly, int gsw) +{ + // N88-BASIC時代のコピーコマンド + int src = (gsw == 0 || gsw == 2) ? 0 : 1; + int dest = (gsw == 0 || gsw == 3) ? 0 : 1; + int sx = (gsc % 80) * 8; + int sy = gsc / 80; + int dx = (gde % 80) * 8; + int dy = gde / 80; + SDL_Rect srcrect = {sx, sy, glx * 8, gly}; + SDL_Rect destrect = {dx, dy, glx * 8, gly}; + + SDL_UnlockSurface(hBmpScreen[src]); + if (src_screen != dest_screen) + SDL_UnlockSurface(hBmpScreen[dest]); + SDL_BlitSurface(hBmpScreen[src], &srcrect, hBmpScreen[dest], &destrect); + if (src_screen != dest_screen) + SDL_LockSurface(hBmpScreen[dest]); + SDL_LockSurface(hBmpScreen[src]); + + if(dest == 0) { + draw_screen(dx, dy, glx * 8, gly); + } +} + +void AGS::paint(int x, int y, uint8 color) +{ + int old_color = vram[0][y][x]; + if (old_color == color) + return; + + int minx = x, maxx = x, miny = y, maxy = y; + std::vector> stack; + stack.push_back({x, y}); + + while (!stack.empty()) { + std::tie(x, y) = stack.back(); + stack.pop_back(); + while (x >= 0 && vram[0][y][x] == old_color) x--; + x++; + minx = std::min(x, minx); + bool span_above = false, span_below = false; + for (; x < 640 && vram[0][y][x] == old_color; x++) { + vram[0][y][x] = color; + if (y > 0) { + if (!span_above && vram[0][y - 1][x] == old_color) { + stack.push_back({x, y - 1}); + span_above = true; + } else if (span_above && vram[0][y - 1][x] != old_color) { + span_above = false; + } + } + if (y < screen_height - 1) { + if (!span_below && vram[0][y + 1][x] == old_color) { + stack.push_back({x, y + 1}); + span_below = true; + } else if (span_below && vram[0][y + 1][x] != old_color) { + span_below = false; + } + } + } + maxx = std::max(x - 1, maxx); + miny = std::min(y, miny); + maxy = std::max(y, maxy); + } + draw_screen(minx, miny, maxx - minx + 1, maxy - miny + 1); +} + +void AGS::draw_box(int index) +{ + if(index == 0) { + // 全画面消去 + box_fill(dest_screen, 0, 0, 639, 479, 0); + return; + } + + int sx = box[index - 1].sx; + int sy = box[index - 1].sy; + int ex = box[index - 1].ex; + int ey = box[index - 1].ey; + uint8 color = box[index - 1].color; + + if(1 <= index && index <= 10) { + box_fill(dest_screen, sx, sy, ex, ey, color); + } else if(11 <= index && index <= 20) { + box_line(dest_screen, sx, sy, ex, ey, color); + } +} + +void AGS::draw_mesh(int sx, int sy, int width, int height) +{ + // super d.p.s + for(int y = sy, h = 0; h < height && y < 480; y += 2, h += 2) { + for(int x = sx, w = 0; w < width && x < 640; x += 2, w += 2) { + vram[0][y][x] = 255; + } + for(int x = sx + 1, w = 1; w < width && x < 640; x += 2, w += 2) { + vram[0][y + 1][x] = 255; + } + } + draw_screen(sx, sy, width, height); +} + +void AGS::box_fill(int dest, int sx, int sy, int ex, int ey, uint8 color) +{ + for(int y = sy; y <= ey && y < 480; y++) { + for(int x = sx; x <= ex && x < 640; x++) { + vram[dest][y][x] = color; + } + } + if(dest == 0) { + draw_screen(sx, sy, ex - sx + 1, ey - sy + 1); + } +} + +void AGS::box_line(int dest, int sx, int sy, int ex, int ey, uint8 color) +{ + for(int x = sx; x <= ex && x < 640; x++) { + vram[dest][sy][x] = color; + vram[dest][ey][x] = color; + } + for(int y = sy; y <= ey && y < 480; y++) { + vram[dest][y][sx] = color; + vram[dest][y][ex] = color; + } + if(dest == 0) { + draw_screen(sx, sy, ex - sx + 1, ey - sy + 1); + } +} + diff --git a/src/sys/ags_gl3.cpp b/src/sys/ags_gl3.cpp index f041618..0684e9f 100644 --- a/src/sys/ags_gl3.cpp +++ b/src/sys/ags_gl3.cpp @@ -1,151 +1,151 @@ -/* - ALICE SOFT SYSTEM 1 for Win32 - - [ AGS - gl3 loader ] -*/ - -#include "ags.h" -#include - -void AGS::load_gl3(uint8* data, int page, int transparent) -{ - // ヘッダ取得 - uint16 tmp = (data[0x30] | (data[0x31] << 8)) - 0x8000; - int sx = tmp % 80; - int sy = tmp / 80; - int width = data[0x32] | (data[0x33] << 8); - int height = data[0x34] | (data[0x35] << 8); - uint8 base = 0; - - // Jコマンドの処理 - if(set_cg_dest) { - sx = cg_dest_x >> 3; - sy = cg_dest_y; - set_cg_dest = false; - } - - // Zコマンドの処理 - if(palette_bank != -1) { - base = (palette_bank & 0x0f) << 4; - } - - // パレット取得 - if(get_palette) { - for(int i = 0; i < 16; i++) { - uint32 b = data[i * 3 + 0]; - uint32 r = data[i * 3 + 1]; - uint32 g = data[i * 3 + 2]; - program_palette[base + i] = SETPALETTE16(r, g, b); - } - } - - // パレット展開 - if(extract_palette && extract_palette_cg[page]) { - for(int i = 0; i < 16; i++) { - screen_palette[base + i] = program_palette[base + i]; - } - } - - // GL3展開 - uint8 cgdata[4][80][3]; - int p = 0x36; - memset(cgdata, 0, sizeof(cgdata)); - - for(int y = 0; y < height; y++) { - for(int pl = 0; pl < 4; pl++) { - int x = 0; - while(x < width) { - uint8 d1 = data[p++]; - if(d1 == 0x0) { - uint8 d2 = data[p++]; - if(d2 < 0x80) { - uint8 d3 = data[p++]; - for(int i = 0; i < d2; i++) { - cgdata[pl][x++][0] = d3; - } - } else { - uint8 d3 = cgdata[pl][x + 1][2]; - for(int i = 0; i < d2 - 0x80; i++) { - cgdata[pl][x++][0] = d3; - } - } - } else if(d1 == 0x1) { - cgdata[pl][x++][0] = data[p++]; - } else if(0x2 <= d1 && d1 <= 0x7) { - uint8 d2 = data[p++]; - for(int i = 0; i < d1; i++) { - cgdata[pl][x++][0] = d2; - } - } else if(0x8 <= d1 && d1 <= 0xd) { - uint8 d2 = cgdata[pl][x + 1][2]; - for(int i = 0; i < d1 - 6; i++) { - cgdata[pl][x++][0] = d2; - } - } else if(d1 == 0xe) { - uint8 d2 = data[p++]; - for(int i = 0; i < d2; i++) { - cgdata[pl][x][0] = cgdata[2][x][0]; - x++; - } - } else if(d1 == 0xf) { - uint8 d2 = data[p++]; - if(d2 < 0x80) { - for(int i = 0; i < d2; i++) { - cgdata[pl][x][0] = cgdata[0][x][0]; - x++; - } - } else { - for(int i = 0; i < d2 - 0x80; i++) { - cgdata[pl][x][0] = cgdata[1][x][0]; - x++; - } - } - } else { - cgdata[pl][x++][0] = d1; - } - } - } - - // VRAMに転送 - if(extract_cg) { - for(int x = 0; x < width; x++) { - for(int pl = 0; pl < 4; pl++) { - cgdata[pl][x][2] = cgdata[pl][x][1]; - cgdata[pl][x][1] = cgdata[pl][x][0]; - } - uint8 b0, b1, b2, b3, c[8]; - b0 = cgdata[0][x][0]; - b1 = cgdata[1][x][0]; - b2 = cgdata[2][x][0]; - b3 = cgdata[3][x][0]; - c[0] = ((b0 >> 7) & 1) | ((b1 >> 6) & 2) | ((b2 >> 5) & 4) | ((b3 >> 4) & 8); - c[1] = ((b0 >> 6) & 1) | ((b1 >> 5) & 2) | ((b2 >> 4) & 4) | ((b3 >> 3) & 8); - c[2] = ((b0 >> 5) & 1) | ((b1 >> 4) & 2) | ((b2 >> 3) & 4) | ((b3 >> 2) & 8); - c[3] = ((b0 >> 4) & 1) | ((b1 >> 3) & 2) | ((b2 >> 2) & 4) | ((b3 >> 1) & 8); - c[4] = ((b0 >> 3) & 1) | ((b1 >> 2) & 2) | ((b2 >> 1) & 4) | ((b3 ) & 8); - c[5] = ((b0 >> 2) & 1) | ((b1 >> 1) & 2) | ((b2 ) & 4) | ((b3 << 1) & 8); - c[6] = ((b0 >> 1) & 1) | ((b1 ) & 2) | ((b2 << 1) & 4) | ((b3 << 2) & 8); - c[7] = ((b0 ) & 1) | ((b1 << 1) & 2) | ((b2 << 2) & 4) | ((b3 << 3) & 8); - - uint32* dest = &vram[dest_screen][y + sy][(x + sx) * 8]; - if(transparent == -1) { - for(int i = 0; i < 8; i++) { - dest[i] = c[i] | base; - } - } else { - for(int i = 0; i < 8; i++) { - if(c[i] != transparent) { - dest[i] = c[i] | base; - } - } - } - } - } - } - - // 画面更新 - if(dest_screen == 0 && extract_cg) { - draw_screen(sx * 8, sy, width * 8, height); - } -} - +/* + ALICE SOFT SYSTEM 1 for Win32 + + [ AGS - gl3 loader ] +*/ + +#include "ags.h" +#include + +void AGS::load_gl3(uint8* data, int page, int transparent) +{ + // ヘッダ取得 + uint16 tmp = (data[0x30] | (data[0x31] << 8)) - 0x8000; + int sx = tmp % 80; + int sy = tmp / 80; + int width = data[0x32] | (data[0x33] << 8); + int height = data[0x34] | (data[0x35] << 8); + uint8 base = 0; + + // Jコマンドの処理 + if(set_cg_dest) { + sx = cg_dest_x >> 3; + sy = cg_dest_y; + set_cg_dest = false; + } + + // Zコマンドの処理 + if(palette_bank != -1) { + base = (palette_bank & 0x0f) << 4; + } + + // パレット取得 + if(get_palette) { + for(int i = 0; i < 16; i++) { + uint32 b = data[i * 3 + 0]; + uint32 r = data[i * 3 + 1]; + uint32 g = data[i * 3 + 2]; + program_palette[base + i] = SETPALETTE16(r, g, b); + } + } + + // パレット展開 + if(extract_palette && extract_palette_cg[page]) { + for(int i = 0; i < 16; i++) { + screen_palette[base + i] = program_palette[base + i]; + } + } + + // GL3展開 + uint8 cgdata[4][80][3]; + int p = 0x36; + memset(cgdata, 0, sizeof(cgdata)); + + for(int y = 0; y < height; y++) { + for(int pl = 0; pl < 4; pl++) { + int x = 0; + while(x < width) { + uint8 d1 = data[p++]; + if(d1 == 0x0) { + uint8 d2 = data[p++]; + if(d2 < 0x80) { + uint8 d3 = data[p++]; + for(int i = 0; i < d2; i++) { + cgdata[pl][x++][0] = d3; + } + } else { + uint8 d3 = cgdata[pl][x + 1][2]; + for(int i = 0; i < d2 - 0x80; i++) { + cgdata[pl][x++][0] = d3; + } + } + } else if(d1 == 0x1) { + cgdata[pl][x++][0] = data[p++]; + } else if(0x2 <= d1 && d1 <= 0x7) { + uint8 d2 = data[p++]; + for(int i = 0; i < d1; i++) { + cgdata[pl][x++][0] = d2; + } + } else if(0x8 <= d1 && d1 <= 0xd) { + uint8 d2 = cgdata[pl][x + 1][2]; + for(int i = 0; i < d1 - 6; i++) { + cgdata[pl][x++][0] = d2; + } + } else if(d1 == 0xe) { + uint8 d2 = data[p++]; + for(int i = 0; i < d2; i++) { + cgdata[pl][x][0] = cgdata[2][x][0]; + x++; + } + } else if(d1 == 0xf) { + uint8 d2 = data[p++]; + if(d2 < 0x80) { + for(int i = 0; i < d2; i++) { + cgdata[pl][x][0] = cgdata[0][x][0]; + x++; + } + } else { + for(int i = 0; i < d2 - 0x80; i++) { + cgdata[pl][x][0] = cgdata[1][x][0]; + x++; + } + } + } else { + cgdata[pl][x++][0] = d1; + } + } + } + + // VRAMに転送 + if(extract_cg) { + for(int x = 0; x < width; x++) { + for(int pl = 0; pl < 4; pl++) { + cgdata[pl][x][2] = cgdata[pl][x][1]; + cgdata[pl][x][1] = cgdata[pl][x][0]; + } + uint8 b0, b1, b2, b3, c[8]; + b0 = cgdata[0][x][0]; + b1 = cgdata[1][x][0]; + b2 = cgdata[2][x][0]; + b3 = cgdata[3][x][0]; + c[0] = ((b0 >> 7) & 1) | ((b1 >> 6) & 2) | ((b2 >> 5) & 4) | ((b3 >> 4) & 8); + c[1] = ((b0 >> 6) & 1) | ((b1 >> 5) & 2) | ((b2 >> 4) & 4) | ((b3 >> 3) & 8); + c[2] = ((b0 >> 5) & 1) | ((b1 >> 4) & 2) | ((b2 >> 3) & 4) | ((b3 >> 2) & 8); + c[3] = ((b0 >> 4) & 1) | ((b1 >> 3) & 2) | ((b2 >> 2) & 4) | ((b3 >> 1) & 8); + c[4] = ((b0 >> 3) & 1) | ((b1 >> 2) & 2) | ((b2 >> 1) & 4) | ((b3 ) & 8); + c[5] = ((b0 >> 2) & 1) | ((b1 >> 1) & 2) | ((b2 ) & 4) | ((b3 << 1) & 8); + c[6] = ((b0 >> 1) & 1) | ((b1 ) & 2) | ((b2 << 1) & 4) | ((b3 << 2) & 8); + c[7] = ((b0 ) & 1) | ((b1 << 1) & 2) | ((b2 << 2) & 4) | ((b3 << 3) & 8); + + uint32* dest = &vram[dest_screen][y + sy][(x + sx) * 8]; + if(transparent == -1) { + for(int i = 0; i < 8; i++) { + dest[i] = c[i] | base; + } + } else { + for(int i = 0; i < 8; i++) { + if(c[i] != transparent) { + dest[i] = c[i] | base; + } + } + } + } + } + } + + // 画面更新 + if(dest_screen == 0 && extract_cg) { + draw_screen(sx * 8, sy, width * 8, height); + } +} + diff --git a/src/sys/ags_gm3.cpp b/src/sys/ags_gm3.cpp index 73d3219..fa675c2 100644 --- a/src/sys/ags_gm3.cpp +++ b/src/sys/ags_gm3.cpp @@ -1,153 +1,153 @@ -/* - ALICE SOFT SYSTEM 1 for Win32 - - [ AGS - gm3 loader ] -*/ - -#include "ags.h" -#include - -void AGS::load_gm3(uint8* data, int page, int transparent) -{ - // ヘッダ取得 - uint16 tmp = (data[0x30] | (data[0x31] << 8)) - 0x8000; - int sx = tmp % 80; - int sy = tmp / 80; - int width = data[0x32] | (data[0x33] << 8); - int height = data[0x34] | (data[0x35] << 8); - uint8 base = 0; - - // Jコマンドの処理 - if(set_cg_dest) { - sx = cg_dest_x >> 3; - sy = cg_dest_y; - set_cg_dest = false; - } - - // Zコマンドの処理 - if(palette_bank != -1) { - base = (palette_bank & 0x0f) << 4; - } - -/* - // パレット取得 - if(get_palette) { - for(int i = 0; i < 16; i++) { - uint32 b = data[i * 3 + 0] & 0xf; - uint32 r = data[i * 3 + 1] & 0xf; - uint32 g = data[i * 3 + 2] & 0xf; - program_palette[base + i] = SETPALETTE16(r, g, b); - } - } - - // パレット展開 - if(extract_palette && extract_palette_cg[page]) { - for(int i = 0; i < 16; i++) { - screen_palette[base + i] = program_palette[base + i]; - } - } -*/ - - // GM3展開 - uint8 cgdata[3][80][3]; - int p = 0x36; - memset(cgdata, 0, sizeof(cgdata)); - - for(int y = 0; y < height; y++) { - for(int pl = 0; pl < 3; pl++) { - int x = 0; - while(x < width) { - uint8 d1 = data[p++]; - if(d1 == 0x0) { - uint8 d2 = data[p++]; - if(d2 < 0x80) { - uint8 d3 = data[p++]; - for(int i = 0; i < d2; i++) { - cgdata[pl][x++][0] = d3; - } - } else { - uint8 d3 = cgdata[pl][x + 1][2]; - for(int i = 0; i < d2 - 0x80; i++) { - cgdata[pl][x++][0] = d3; - } - } - } else if(d1 == 0x1) { - cgdata[pl][x++][0] = data[p++]; - } else if(0x2 <= d1 && d1 <= 0x7) { - uint8 d2 = data[p++]; - for(int i = 0; i < d1; i++) { - cgdata[pl][x++][0] = d2; - } - } else if(0x8 <= d1 && d1 <= 0xd) { - uint8 d2 = cgdata[pl][x + 1][2]; - for(int i = 0; i < d1 - 6; i++) { - cgdata[pl][x++][0] = d2; - } - } else if(d1 == 0xe) { - uint8 d2 = data[p++]; - for(int i = 0; i < d2; i++) { - cgdata[pl][x][0] = cgdata[2][x][0]; - x++; - } - } else if(d1 == 0xf) { - uint8 d2 = data[p++]; - if(d2 < 0x80) { - for(int i = 0; i < d2; i++) { - cgdata[pl][x][0] = cgdata[0][x][0]; - x++; - } - } else { - for(int i = 0; i < d2 - 0x80; i++) { - cgdata[pl][x][0] = cgdata[1][x][0]; - x++; - } - } - } else { - cgdata[pl][x++][0] = d1; - } - } - } - - // VRAMに転送 - if(extract_cg) { - for(int x = 0; x < width; x++) { - for(int pl = 0; pl < 3; pl++) { - cgdata[pl][x][2] = cgdata[pl][x][1]; - cgdata[pl][x][1] = cgdata[pl][x][0]; - } - uint8 b0, b1, b2, c[8]; - b0 = cgdata[0][x][0]; - b1 = cgdata[1][x][0]; - b2 = cgdata[2][x][0]; - c[0] = ((b0 >> 7) & 1) | ((b1 >> 6) & 2) | ((b2 >> 5) & 4); - c[1] = ((b0 >> 6) & 1) | ((b1 >> 5) & 2) | ((b2 >> 4) & 4); - c[2] = ((b0 >> 5) & 1) | ((b1 >> 4) & 2) | ((b2 >> 3) & 4); - c[3] = ((b0 >> 4) & 1) | ((b1 >> 3) & 2) | ((b2 >> 2) & 4); - c[4] = ((b0 >> 3) & 1) | ((b1 >> 2) & 2) | ((b2 >> 1) & 4); - c[5] = ((b0 >> 2) & 1) | ((b1 >> 1) & 2) | ((b2 ) & 4); - c[6] = ((b0 >> 1) & 1) | ((b1 ) & 2) | ((b2 << 1) & 4); - c[7] = ((b0 ) & 1) | ((b1 << 1) & 2) | ((b2 << 2) & 4); - - uint32* dest0 = &vram[dest_screen][(y + sy) * 2 + 0][(x + sx) * 8]; - uint32* dest1 = &vram[dest_screen][(y + sy) * 2 + 1][(x + sx) * 8]; - if(transparent == -1) { - for(int i = 0; i < 8; i++) { - dest0[i] = dest1[i] = c[i] | base; - } - } else { - for(int i = 0; i < 8; i++) { - if(c[i] != transparent) { - dest0[i] = dest1[i] = c[i] | base; - } - } - } - } - } - } - - // 画面更新 - if(dest_screen == 0 && extract_cg) { - draw_screen(sx * 8, sy * 2, width * 8, height * 2); - } -} - +/* + ALICE SOFT SYSTEM 1 for Win32 + + [ AGS - gm3 loader ] +*/ + +#include "ags.h" +#include + +void AGS::load_gm3(uint8* data, int page, int transparent) +{ + // ヘッダ取得 + uint16 tmp = (data[0x30] | (data[0x31] << 8)) - 0x8000; + int sx = tmp % 80; + int sy = tmp / 80; + int width = data[0x32] | (data[0x33] << 8); + int height = data[0x34] | (data[0x35] << 8); + uint8 base = 0; + + // Jコマンドの処理 + if(set_cg_dest) { + sx = cg_dest_x >> 3; + sy = cg_dest_y; + set_cg_dest = false; + } + + // Zコマンドの処理 + if(palette_bank != -1) { + base = (palette_bank & 0x0f) << 4; + } + +/* + // パレット取得 + if(get_palette) { + for(int i = 0; i < 16; i++) { + uint32 b = data[i * 3 + 0] & 0xf; + uint32 r = data[i * 3 + 1] & 0xf; + uint32 g = data[i * 3 + 2] & 0xf; + program_palette[base + i] = SETPALETTE16(r, g, b); + } + } + + // パレット展開 + if(extract_palette && extract_palette_cg[page]) { + for(int i = 0; i < 16; i++) { + screen_palette[base + i] = program_palette[base + i]; + } + } +*/ + + // GM3展開 + uint8 cgdata[3][80][3]; + int p = 0x36; + memset(cgdata, 0, sizeof(cgdata)); + + for(int y = 0; y < height; y++) { + for(int pl = 0; pl < 3; pl++) { + int x = 0; + while(x < width) { + uint8 d1 = data[p++]; + if(d1 == 0x0) { + uint8 d2 = data[p++]; + if(d2 < 0x80) { + uint8 d3 = data[p++]; + for(int i = 0; i < d2; i++) { + cgdata[pl][x++][0] = d3; + } + } else { + uint8 d3 = cgdata[pl][x + 1][2]; + for(int i = 0; i < d2 - 0x80; i++) { + cgdata[pl][x++][0] = d3; + } + } + } else if(d1 == 0x1) { + cgdata[pl][x++][0] = data[p++]; + } else if(0x2 <= d1 && d1 <= 0x7) { + uint8 d2 = data[p++]; + for(int i = 0; i < d1; i++) { + cgdata[pl][x++][0] = d2; + } + } else if(0x8 <= d1 && d1 <= 0xd) { + uint8 d2 = cgdata[pl][x + 1][2]; + for(int i = 0; i < d1 - 6; i++) { + cgdata[pl][x++][0] = d2; + } + } else if(d1 == 0xe) { + uint8 d2 = data[p++]; + for(int i = 0; i < d2; i++) { + cgdata[pl][x][0] = cgdata[2][x][0]; + x++; + } + } else if(d1 == 0xf) { + uint8 d2 = data[p++]; + if(d2 < 0x80) { + for(int i = 0; i < d2; i++) { + cgdata[pl][x][0] = cgdata[0][x][0]; + x++; + } + } else { + for(int i = 0; i < d2 - 0x80; i++) { + cgdata[pl][x][0] = cgdata[1][x][0]; + x++; + } + } + } else { + cgdata[pl][x++][0] = d1; + } + } + } + + // VRAMに転送 + if(extract_cg) { + for(int x = 0; x < width; x++) { + for(int pl = 0; pl < 3; pl++) { + cgdata[pl][x][2] = cgdata[pl][x][1]; + cgdata[pl][x][1] = cgdata[pl][x][0]; + } + uint8 b0, b1, b2, c[8]; + b0 = cgdata[0][x][0]; + b1 = cgdata[1][x][0]; + b2 = cgdata[2][x][0]; + c[0] = ((b0 >> 7) & 1) | ((b1 >> 6) & 2) | ((b2 >> 5) & 4); + c[1] = ((b0 >> 6) & 1) | ((b1 >> 5) & 2) | ((b2 >> 4) & 4); + c[2] = ((b0 >> 5) & 1) | ((b1 >> 4) & 2) | ((b2 >> 3) & 4); + c[3] = ((b0 >> 4) & 1) | ((b1 >> 3) & 2) | ((b2 >> 2) & 4); + c[4] = ((b0 >> 3) & 1) | ((b1 >> 2) & 2) | ((b2 >> 1) & 4); + c[5] = ((b0 >> 2) & 1) | ((b1 >> 1) & 2) | ((b2 ) & 4); + c[6] = ((b0 >> 1) & 1) | ((b1 ) & 2) | ((b2 << 1) & 4); + c[7] = ((b0 ) & 1) | ((b1 << 1) & 2) | ((b2 << 2) & 4); + + uint32* dest0 = &vram[dest_screen][(y + sy) * 2 + 0][(x + sx) * 8]; + uint32* dest1 = &vram[dest_screen][(y + sy) * 2 + 1][(x + sx) * 8]; + if(transparent == -1) { + for(int i = 0; i < 8; i++) { + dest0[i] = dest1[i] = c[i] | base; + } + } else { + for(int i = 0; i < 8; i++) { + if(c[i] != transparent) { + dest0[i] = dest1[i] = c[i] | base; + } + } + } + } + } + } + + // 画面更新 + if(dest_screen == 0 && extract_cg) { + draw_screen(sx * 8, sy * 2, width * 8, height * 2); + } +} + diff --git a/src/sys/ags_pms.cpp b/src/sys/ags_pms.cpp index 30498cb..923d9b8 100644 --- a/src/sys/ags_pms.cpp +++ b/src/sys/ags_pms.cpp @@ -1,184 +1,184 @@ -/* - ALICE SOFT SYSTEM 3 for Win32 - - [ AGS - pms loader ] -*/ - -#include "ags.h" -#include "crc32.h" -#include - -void AGS::load_pms(uint8* data, int page, int transparent) -{ - // ヘッダ取得 - int sx = data[0x0] | (data[0x1] << 8); - int sy = data[0x2] | (data[0x3] << 8); - int ex = data[0x4] | (data[0x5] << 8); - int ey = data[0x6] | (data[0x7] << 8); - int width = ex - sx + 1; - int height = ey - sy + 1; - uint8 mask = data[0xa]; - - // Jコマンドの処理 - if(set_cg_dest) { - sx = cg_dest_x; - sy = cg_dest_y; - ex = sx + width - 1; - ey = sy + height - 1; - set_cg_dest = false; - } - - // パレット取得 - uint32 tmp_palette[256]; - - if(get_palette) { - int p = 0x20; - for(int i = 0; i < 16; i++) { - for(int j = 0; j < 16; j++) { - uint32 r = data[p++]; - uint32 g = data[p++]; - uint32 b = data[p++]; - tmp_palette[i * 16 + j] = SETPALETTE256(r, g, b); - } - } - if(nact->crc32_a == CRC32_RANCE41 || - nact->crc32_a == CRC32_RANCE41_ENG || - nact->crc32_a == CRC32_RANCE42 || - nact->crc32_a == CRC32_RANCE42_ENG || - nact->crc32_a == CRC32_HASHIRIONNA2) { - // 上下16色は取得しない - for(int i = 1; i < 15; i++) { - for(int j = 0; j < 16; j++) { - if(!(mask & (0x01 << i))) { - program_palette[i * 16 + j] = tmp_palette[i * 16 + j]; - } - } - } - } else if(nact->crc32_a == CRC32_MUGENHOUYOU && transparent != -1) { - // Uコマンドでは上下32色は取得しない - for(int i = 2; i < 14; i++) { - for(int j = 0; j < 16; j++) { - if(!(mask & (0x01 << i))) { - program_palette[i * 16 + j] = tmp_palette[i * 16 + j]; - } - } - } - } else { - for(int i = 0; i < 16; i++) { - for(int j = 0; j < 16; j++) { - if(!(mask & (0x01 << i))) { - program_palette[i * 16 + j] = tmp_palette[i * 16 + j]; - } - } - } - } - } - - // パレット展開 - if (nact->sys_ver == 3) { - if((extract_palette && extract_palette_cg[page]) || nact->crc32_a == CRC32_FUNNYBEE_CD) { - if(nact->crc32_a == CRC32_RANCE41 || - nact->crc32_a == CRC32_RANCE41_ENG || - nact->crc32_a == CRC32_RANCE42 || - nact->crc32_a == CRC32_RANCE42_ENG || - nact->crc32_a == CRC32_HASHIRIONNA2) { - // 上下16色は展開しない - for(int i = 1; i < 15; i++) { - for(int j = 0; j < 16; j++) { - if(!(mask & (0x01 << i))) { - screen_palette[i * 16 + j] = program_palette[i * 16 + j]; - } - } - } - } else if(nact->crc32_a == CRC32_MUGENHOUYOU && transparent != -1) { - // Uコマンドでは上下32色は展開しない - for(int i = 2; i < 14; i++) { - for(int j = 0; j < 16; j++) { - if(!(mask & (0x01 << i))) { - screen_palette[i * 16 + j] = program_palette[i * 16 + j]; - } - } - } - } else { - for(int i = 0; i < 16; i++) { - for(int j = 0; j < 16; j++) { - if(!(mask & (0x01 << i))) { - screen_palette[i * 16 + j] = program_palette[i * 16 + j]; - } - } - } - } - } - } else if(extract_palette && extract_palette_cg[page]) { - for(int i = 0; i < 16; i++) { - for(int j = 0; j < 16; j++) { - if(!(mask & (0x01 << i))) { - screen_palette[i * 16 + j] = program_palette[i * 16 + j]; - } - } - } - } - - // PMS展開 - uint8 cgdata[3][640]; - int p = 0x320; - memset(cgdata, 0, sizeof(cgdata)); - - for(int y = 0; y < height; y++) { - int x = 0; - while(x < width) { - uint8 d1 = data[p++]; - if(d1 == 0xff) { - int length = data[p++] + 3; - memcpy(cgdata[0] + x, cgdata[1] + x, length); - x += length; - } else if(d1 == 0xfe) { - int length = data[p++] + 3; - memcpy(cgdata[0] + x, cgdata[2] + x, length); - x += length; - } else if(d1 == 0xfd) { - int length = data[p++] + 4; - uint8 d2 = data[p++]; - memset(cgdata[0] + x, d2, length); - x += length; - } else if(d1 == 0xfc) { - int length = data[p++] + 3; - uint8 d2 = data[p++]; - uint8 d3 = data[p++]; - for(int i = 0; i < length; i++) { - cgdata[0][x++] = d2; - cgdata[0][x++] = d3; - } - } else if(d1 == 0xfb || d1 == 0xfa || d1 == 0xf9 || d1 == 0xf8) { - cgdata[0][x++] = data[p++]; - } else { - cgdata[0][x++] = d1; - } - } - - // VRAMに転送 - if(extract_cg) { - uint32* dest = &vram[dest_screen][y + sy][sx]; - if(transparent == -1) { - for(int x = 0; x < width; x++) { - cgdata[2][x] = cgdata[1][x]; - cgdata[1][x] = cgdata[0][x]; - dest[x] = cgdata[0][x]; - } - } else { - for(int x = 0; x < width; x++) { - cgdata[2][x] = cgdata[1][x]; - cgdata[1][x] = cgdata[0][x]; - if(cgdata[0][x] != transparent) { - dest[x] = cgdata[0][x]; - } - } - } - } - } - - // 画面更新 - if(dest_screen == 0 && extract_cg) { - draw_screen(sx, sy, width, height); - } -} +/* + ALICE SOFT SYSTEM 3 for Win32 + + [ AGS - pms loader ] +*/ + +#include "ags.h" +#include "crc32.h" +#include + +void AGS::load_pms(uint8* data, int page, int transparent) +{ + // ヘッダ取得 + int sx = data[0x0] | (data[0x1] << 8); + int sy = data[0x2] | (data[0x3] << 8); + int ex = data[0x4] | (data[0x5] << 8); + int ey = data[0x6] | (data[0x7] << 8); + int width = ex - sx + 1; + int height = ey - sy + 1; + uint8 mask = data[0xa]; + + // Jコマンドの処理 + if(set_cg_dest) { + sx = cg_dest_x; + sy = cg_dest_y; + ex = sx + width - 1; + ey = sy + height - 1; + set_cg_dest = false; + } + + // パレット取得 + uint32 tmp_palette[256]; + + if(get_palette) { + int p = 0x20; + for(int i = 0; i < 16; i++) { + for(int j = 0; j < 16; j++) { + uint32 r = data[p++]; + uint32 g = data[p++]; + uint32 b = data[p++]; + tmp_palette[i * 16 + j] = SETPALETTE256(r, g, b); + } + } + if(nact->crc32_a == CRC32_RANCE41 || + nact->crc32_a == CRC32_RANCE41_ENG || + nact->crc32_a == CRC32_RANCE42 || + nact->crc32_a == CRC32_RANCE42_ENG || + nact->crc32_a == CRC32_HASHIRIONNA2) { + // 上下16色は取得しない + for(int i = 1; i < 15; i++) { + for(int j = 0; j < 16; j++) { + if(!(mask & (0x01 << i))) { + program_palette[i * 16 + j] = tmp_palette[i * 16 + j]; + } + } + } + } else if(nact->crc32_a == CRC32_MUGENHOUYOU && transparent != -1) { + // Uコマンドでは上下32色は取得しない + for(int i = 2; i < 14; i++) { + for(int j = 0; j < 16; j++) { + if(!(mask & (0x01 << i))) { + program_palette[i * 16 + j] = tmp_palette[i * 16 + j]; + } + } + } + } else { + for(int i = 0; i < 16; i++) { + for(int j = 0; j < 16; j++) { + if(!(mask & (0x01 << i))) { + program_palette[i * 16 + j] = tmp_palette[i * 16 + j]; + } + } + } + } + } + + // パレット展開 + if (nact->sys_ver == 3) { + if((extract_palette && extract_palette_cg[page]) || nact->crc32_a == CRC32_FUNNYBEE_CD) { + if(nact->crc32_a == CRC32_RANCE41 || + nact->crc32_a == CRC32_RANCE41_ENG || + nact->crc32_a == CRC32_RANCE42 || + nact->crc32_a == CRC32_RANCE42_ENG || + nact->crc32_a == CRC32_HASHIRIONNA2) { + // 上下16色は展開しない + for(int i = 1; i < 15; i++) { + for(int j = 0; j < 16; j++) { + if(!(mask & (0x01 << i))) { + screen_palette[i * 16 + j] = program_palette[i * 16 + j]; + } + } + } + } else if(nact->crc32_a == CRC32_MUGENHOUYOU && transparent != -1) { + // Uコマンドでは上下32色は展開しない + for(int i = 2; i < 14; i++) { + for(int j = 0; j < 16; j++) { + if(!(mask & (0x01 << i))) { + screen_palette[i * 16 + j] = program_palette[i * 16 + j]; + } + } + } + } else { + for(int i = 0; i < 16; i++) { + for(int j = 0; j < 16; j++) { + if(!(mask & (0x01 << i))) { + screen_palette[i * 16 + j] = program_palette[i * 16 + j]; + } + } + } + } + } + } else if(extract_palette && extract_palette_cg[page]) { + for(int i = 0; i < 16; i++) { + for(int j = 0; j < 16; j++) { + if(!(mask & (0x01 << i))) { + screen_palette[i * 16 + j] = program_palette[i * 16 + j]; + } + } + } + } + + // PMS展開 + uint8 cgdata[3][640]; + int p = 0x320; + memset(cgdata, 0, sizeof(cgdata)); + + for(int y = 0; y < height; y++) { + int x = 0; + while(x < width) { + uint8 d1 = data[p++]; + if(d1 == 0xff) { + int length = data[p++] + 3; + memcpy(cgdata[0] + x, cgdata[1] + x, length); + x += length; + } else if(d1 == 0xfe) { + int length = data[p++] + 3; + memcpy(cgdata[0] + x, cgdata[2] + x, length); + x += length; + } else if(d1 == 0xfd) { + int length = data[p++] + 4; + uint8 d2 = data[p++]; + memset(cgdata[0] + x, d2, length); + x += length; + } else if(d1 == 0xfc) { + int length = data[p++] + 3; + uint8 d2 = data[p++]; + uint8 d3 = data[p++]; + for(int i = 0; i < length; i++) { + cgdata[0][x++] = d2; + cgdata[0][x++] = d3; + } + } else if(d1 == 0xfb || d1 == 0xfa || d1 == 0xf9 || d1 == 0xf8) { + cgdata[0][x++] = data[p++]; + } else { + cgdata[0][x++] = d1; + } + } + + // VRAMに転送 + if(extract_cg) { + uint32* dest = &vram[dest_screen][y + sy][sx]; + if(transparent == -1) { + for(int x = 0; x < width; x++) { + cgdata[2][x] = cgdata[1][x]; + cgdata[1][x] = cgdata[0][x]; + dest[x] = cgdata[0][x]; + } + } else { + for(int x = 0; x < width; x++) { + cgdata[2][x] = cgdata[1][x]; + cgdata[1][x] = cgdata[0][x]; + if(cgdata[0][x] != transparent) { + dest[x] = cgdata[0][x]; + } + } + } + } + } + + // 画面更新 + if(dest_screen == 0 && extract_cg) { + draw_screen(sx, sy, width, height); + } +} diff --git a/src/sys/ags_text.cpp b/src/sys/ags_text.cpp index 74f0dae..7ee317d 100644 --- a/src/sys/ags_text.cpp +++ b/src/sys/ags_text.cpp @@ -1,547 +1,547 @@ -/* - ALICE SOFT SYSTEM 3 for Win32 - - [ AGS - text ] -*/ - -#include -#include "ags.h" -#include "encoding.h" -#include "texthook.h" - -namespace { - -bool antialias = true; - -int convert_to_zenkaku(int code) -{ - switch(code) { - case u' ': return u' '; - case u'!': return u'!'; - case u'"': return u'”'; - case u'#': return u'#'; - case u'$': return u'$'; - case u'%': return u'%'; - case u'&': return u'&'; - case u'\'': return u'’'; - case u'(': return u'('; - case u')': return u')'; - case u'*': return u'*'; - case u'+': return u'+'; - case u',': return u','; - case u'-': return u'-'; - case u'.': return u'.'; - case u'/': return u'/'; - case u'0': return u'0'; - case u'1': return u'1'; - case u'2': return u'2'; - case u'3': return u'3'; - case u'4': return u'4'; - case u'5': return u'5'; - case u'6': return u'6'; - case u'7': return u'7'; - case u'8': return u'8'; - case u'9': return u'9'; - case u':': return u':'; - case u';': return u';'; - case u'<': return u'<'; - case u'=': return u'='; - case u'>': return u'>'; - case u'?': return u'?'; - case u'@': return u'@'; - case u'A': return u'A'; - case u'B': return u'B'; - case u'C': return u'C'; - case u'D': return u'D'; - case u'E': return u'E'; - case u'F': return u'F'; - case u'G': return u'G'; - case u'H': return u'H'; - case u'I': return u'I'; - case u'J': return u'J'; - case u'K': return u'K'; - case u'L': return u'L'; - case u'M': return u'M'; - case u'N': return u'N'; - case u'O': return u'O'; - case u'P': return u'P'; - case u'Q': return u'Q'; - case u'R': return u'R'; - case u'S': return u'S'; - case u'T': return u'T'; - case u'U': return u'U'; - case u'V': return u'V'; - case u'W': return u'W'; - case u'X': return u'X'; - case u'Y': return u'Y'; - case u'Z': return u'Z'; - case u'[': return u'['; - case u'\\': return u'¥'; - case u']': return u']'; - case u'^': return u'^'; - case u'_': return u'_'; - case u'`': return u'‘'; - case u'a': return u'a'; - case u'b': return u'b'; - case u'c': return u'c'; - case u'd': return u'd'; - case u'e': return u'e'; - case u'f': return u'f'; - case u'g': return u'g'; - case u'h': return u'h'; - case u'i': return u'i'; - case u'j': return u'j'; - case u'k': return u'k'; - case u'l': return u'l'; - case u'm': return u'm'; - case u'n': return u'n'; - case u'o': return u'o'; - case u'p': return u'p'; - case u'q': return u'q'; - case u'r': return u'r'; - case u's': return u's'; - case u't': return u't'; - case u'u': return u'u'; - case u'v': return u'v'; - case u'w': return u'w'; - case u'x': return u'x'; - case u'y': return u'y'; - case u'z': return u'z'; - case u'{': return u'{'; - case u'|': return u'|'; - case u'}': return u'}'; - case u'~': return u'~'; - case u'。': return u'。'; - case u'「': return u'「'; - case u'」': return u'」'; - case u'、': return u'、'; - case u'・': return u'・'; - case u'ヲ': return u'を'; - case u'ァ': return u'ぁ'; - case u'ィ': return u'ぃ'; - case u'ゥ': return u'ぅ'; - case u'ェ': return u'ぇ'; - case u'ォ': return u'ぉ'; - case u'ャ': return u'ゃ'; - case u'ュ': return u'ゅ'; - case u'ョ': return u'ょ'; - case u'ッ': return u'っ'; - case u'ー': return u'ー'; - case u'ア': return u'あ'; - case u'イ': return u'い'; - case u'ウ': return u'う'; - case u'エ': return u'え'; - case u'オ': return u'お'; - case u'カ': return u'か'; - case u'キ': return u'き'; - case u'ク': return u'く'; - case u'ケ': return u'け'; - case u'コ': return u'こ'; - case u'サ': return u'さ'; - case u'シ': return u'し'; - case u'ス': return u'す'; - case u'セ': return u'せ'; - case u'ソ': return u'そ'; - case u'タ': return u'た'; - case u'チ': return u'ち'; - case u'ツ': return u'つ'; - case u'テ': return u'て'; - case u'ト': return u'と'; - case u'ナ': return u'な'; - case u'ニ': return u'に'; - case u'ヌ': return u'ぬ'; - case u'ネ': return u'ね'; - case u'ノ': return u'の'; - case u'ハ': return u'は'; - case u'ヒ': return u'ひ'; - case u'フ': return u'ふ'; - case u'ヘ': return u'へ'; - case u'ホ': return u'ほ'; - case u'マ': return u'ま'; - case u'ミ': return u'み'; - case u'ム': return u'む'; - case u'メ': return u'め'; - case u'モ': return u'も'; - case u'ヤ': return u'や'; - case u'ユ': return u'ゆ'; - case u'ヨ': return u'よ'; - case u'ラ': return u'ら'; - case u'リ': return u'り'; - case u'ル': return u'る'; - case u'レ': return u'れ'; - case u'ロ': return u'ろ'; - case u'ワ': return u'わ'; - case u'ン': return u'ん'; - case u'゙': return u'゛'; - case u'゚': return u'゜'; - } - return code; -} - -int convert_to_hankaku(int code) -{ - switch(code) { - case u' ': return u' '; - case u'!': return u'!'; - case u'”': return u'"'; - case u'#': return u'#'; - case u'$': return u'$'; - case u'%': return u'%'; - case u'&': return u'&'; - case u'’': return u'\''; - case u'(': return u'('; - case u')': return u')'; - case u'*': return u'*'; - case u'+': return u'+'; - case u',': return u','; - case u'-': return u'-'; - case u'.': return u'.'; - case u'/': return u'/'; - case u'0': return u'0'; - case u'1': return u'1'; - case u'2': return u'2'; - case u'3': return u'3'; - case u'4': return u'4'; - case u'5': return u'5'; - case u'6': return u'6'; - case u'7': return u'7'; - case u'8': return u'8'; - case u'9': return u'9'; - case u':': return u':'; - case u';': return u';'; - case u'<': return u'<'; - case u'=': return u'='; - case u'>': return u'>'; - case u'?': return u'?'; - case u'@': return u'@'; - case u'A': return u'A'; - case u'B': return u'B'; - case u'C': return u'C'; - case u'D': return u'D'; - case u'E': return u'E'; - case u'F': return u'F'; - case u'G': return u'G'; - case u'H': return u'H'; - case u'I': return u'I'; - case u'J': return u'J'; - case u'K': return u'K'; - case u'L': return u'L'; - case u'M': return u'M'; - case u'N': return u'N'; - case u'O': return u'O'; - case u'P': return u'P'; - case u'Q': return u'Q'; - case u'R': return u'R'; - case u'S': return u'S'; - case u'T': return u'T'; - case u'U': return u'U'; - case u'V': return u'V'; - case u'W': return u'W'; - case u'X': return u'X'; - case u'Y': return u'Y'; - case u'Z': return u'Z'; - case u'[': return u'['; - case u'¥': return u'\\'; - case u']': return u']'; - case u'^': return u'^'; - case u'_': return u'_'; - case u'‘': return u'`'; - case u'a': return u'a'; - case u'b': return u'b'; - case u'c': return u'c'; - case u'd': return u'd'; - case u'e': return u'e'; - case u'f': return u'f'; - case u'g': return u'g'; - case u'h': return u'h'; - case u'i': return u'i'; - case u'j': return u'j'; - case u'k': return u'k'; - case u'l': return u'l'; - case u'm': return u'm'; - case u'n': return u'n'; - case u'o': return u'o'; - case u'p': return u'p'; - case u'q': return u'q'; - case u'r': return u'r'; - case u's': return u's'; - case u't': return u't'; - case u'u': return u'u'; - case u'v': return u'v'; - case u'w': return u'w'; - case u'x': return u'x'; - case u'y': return u'y'; - case u'z': return u'z'; - case u'{': return u'{'; - case u'|': return u'|'; - case u'}': return u'}'; - case u'~': return u'~'; - case u'。': return u'。'; - case u'「': return u'「'; - case u'」': return u'」'; - case u'、': return u'、'; - case u'・': return u'・'; - case u'を': return u'ヲ'; - case u'ぁ': return u'ァ'; - case u'ぃ': return u'ィ'; - case u'ぅ': return u'ゥ'; - case u'ぇ': return u'ェ'; - case u'ぉ': return u'ォ'; - case u'ゃ': return u'ャ'; - case u'ゅ': return u'ュ'; - case u'ょ': return u'ョ'; - case u'っ': return u'ッ'; - case u'ー': return u'ー'; - case u'あ': return u'ア'; - case u'い': return u'イ'; - case u'う': return u'ウ'; - case u'え': return u'エ'; - case u'お': return u'オ'; - case u'か': return u'カ'; - case u'き': return u'キ'; - case u'く': return u'ク'; - case u'け': return u'ケ'; - case u'こ': return u'コ'; - case u'さ': return u'サ'; - case u'し': return u'シ'; - case u'す': return u'ス'; - case u'せ': return u'セ'; - case u'そ': return u'ソ'; - case u'た': return u'タ'; - case u'ち': return u'チ'; - case u'つ': return u'ツ'; - case u'て': return u'テ'; - case u'と': return u'ト'; - case u'な': return u'ナ'; - case u'に': return u'ニ'; - case u'ぬ': return u'ヌ'; - case u'ね': return u'ネ'; - case u'の': return u'ノ'; - case u'は': return u'ハ'; - case u'ひ': return u'ヒ'; - case u'ふ': return u'フ'; - case u'へ': return u'ヘ'; - case u'ほ': return u'ホ'; - case u'ま': return u'マ'; - case u'み': return u'ミ'; - case u'む': return u'ム'; - case u'め': return u'メ'; - case u'も': return u'モ'; - case u'や': return u'ヤ'; - case u'ゆ': return u'ユ'; - case u'よ': return u'ヨ'; - case u'ら': return u'ラ'; - case u'り': return u'リ'; - case u'る': return u'ル'; - case u'れ': return u'レ'; - case u'ろ': return u'ロ'; - case u'わ': return u'ワ'; - case u'ん': return u'ン'; - case u'゛': return u'゙'; - case u'゜': return u'゚'; - } - return code; -} - -} // namespace - -void AGS::draw_text(const char* string, bool text_wait) -{ - int screen, dest_x, dest_y, font_size; - uint8 font_color; - - uint8 antialias_cache[256*7]; - if (antialias) - memset(antialias_cache, 0, 256); - - if (draw_menu) { - screen = 2; - dest_x = menu_dest_x; - dest_y = menu_dest_y; - font_size = menu_font_size; - font_color = menu_font_color; - } else { - screen = dest_screen; - dest_x = text_dest_x; - dest_y = text_dest_y; - font_size = text_font_size; - font_color = text_font_color; - if (*string && text_font_maxsize < text_font_size) - text_font_maxsize = text_font_size; - } - - TTF_Font* font = NULL; - switch (font_size) { - case 16: font = hFont16; break; - case 24: font = hFont24; break; - case 32: font = hFont32; break; - case 48: font = hFont48; break; - case 64: font = hFont64; break; - } - int ascent = TTF_FontAscent(font); - int descent = TTF_FontDescent(font); - // Adjust dest_y if the font height is larger than the specified size. - dest_y -= (ascent - descent - font_size) / 2; - - while (*string) { - int code = nact->encoding->next_codepoint(&string); - if(draw_hankaku) { - code = convert_to_hankaku(code); - } else { - code = convert_to_zenkaku(code); - } - - // 文字出力 - if (GAIJI_FIRST <= code && code <= GAIJI_LAST) { - // Use unadjusted dest_y here. - draw_gaiji(screen, dest_x, draw_menu ? menu_dest_y : text_dest_y, code, font_size, font_color); - dest_x += font_size; - } else { - if (!draw_menu) - texthook_character(nact->get_scenario_page(), code); - - if (antialias) - draw_char_antialias(screen, dest_x, dest_y, code, font, font_color, antialias_cache); - else - draw_char(screen, dest_x, dest_y, code, font, font_color); - - int miny, maxy, advance; - TTF_GlyphMetrics(font, code, NULL, NULL, &miny, &maxy, &advance); - // Some fonts report incorrect Ascent/Descent value so we need to fix them. - if (miny < descent) descent = miny; - if (maxy > ascent) ascent = maxy; - dest_x += advance; - } - - if (!draw_menu && text_wait && code != ' ') { - // 画面更新 - if(screen == 0) - draw_screen(text_dest_x, dest_y, dest_x - text_dest_x, ascent - descent); - text_dest_x = dest_x; - // Wait - nact->text_wait(); - } - } - if (draw_menu) - menu_dest_x = dest_x; - else if (!text_wait) { - // 画面更新 - if(screen == 0) - draw_screen(text_dest_x, dest_y, dest_x - text_dest_x, ascent - descent); - text_dest_x = dest_x; - } -} - -void AGS::draw_char(int dest, int dest_x, int dest_y, uint16 code, TTF_Font* font, uint8 color) -{ - // パターン取得 - SDL_Color white = {0xff, 0xff, 0xff}; - SDL_Surface* fs = TTF_RenderGlyph_Solid(font, code, white); - - // パターン出力 - for(int y = 0; y < fs->h && dest_y + y < 480; y++) { - uint8 *pattern = (uint8*)surface_line(fs, y); // FIXME: do not assume 8bpp - for(int x = 0; x < fs->w && dest_x + x < 640; x++) { - if(pattern[x] != 0) { - vram[dest][dest_y + y][dest_x + x] = color; - } - } - } - - SDL_FreeSurface(fs); -} - -int AGS::nearest_color(int r, int g, int b) { - int i, col, mind = INT_MAX; - for (i = 0; i < 256; i++) { - int dr = r - palR(i); - int dg = g - palG(i); - int db = b - palB(i); - int d = dr*dr*30 + dg*dg*59 + db*db*11; - if (d < mind) { - mind = d; - col = i; - } - } - return col; -} - -void AGS::draw_char_antialias(int dest, int dest_x, int dest_y, uint16 code, TTF_Font* font, uint8 color, uint8 cache[]) -{ - // パターン取得 - SDL_Color black = {0, 0, 0}; - SDL_Color white = {0xff, 0xff, 0xff}; - SDL_Surface* fs = TTF_RenderGlyph_Shaded(font, code, white, black); - - // パターン出力 - for(int y = 0; y < fs->h && dest_y + y < 480; y++) { - uint8 *pattern = (uint8*)surface_line(fs, y); - uint32 *dp = &vram[dest][dest_y + y][dest_x]; - for(int x = 0; x < fs->w && dest_x + x < 640; x++, dp++) { - uint8 bg = *dp; - int alpha = pattern[x] >> 5; - if (alpha == 0) { - // Transparent, do nothing - } else if (alpha == 7) { - *dp = color; - } else if (cache[bg] & 1 << alpha) { - *dp = cache[alpha << 8 | bg]; - } else { - cache[bg] |= 1 << alpha; - int c = nearest_color((palR(color) * alpha + palR(bg) * (7 - alpha)) / 7, - (palG(color) * alpha + palG(bg) * (7 - alpha)) / 7, - (palB(color) * alpha + palB(bg) * (7 - alpha)) / 7); - cache[alpha << 8 | bg] = c; - *dp = c; - } - } - } - - SDL_FreeSurface(fs); -} - -void AGS::draw_gaiji(int dest, int dest_x, int dest_y, uint16 code, int size, uint8 color) -{ - int index = code - GAIJI_FIRST; - bool pattern[16][16]; - - // パターン取得 - for(int y = 0; y < 16; y++) { - uint8 l = gaiji[index][y * 2 + 0]; - uint8 r = gaiji[index][y * 2 + 1]; - - pattern[y][ 0] = ((l & 0x80) != 0); - pattern[y][ 1] = ((l & 0x40) != 0); - pattern[y][ 2] = ((l & 0x20) != 0); - pattern[y][ 3] = ((l & 0x10) != 0); - pattern[y][ 4] = ((l & 0x08) != 0); - pattern[y][ 5] = ((l & 0x04) != 0); - pattern[y][ 6] = ((l & 0x02) != 0); - pattern[y][ 7] = ((l & 0x01) != 0); - pattern[y][ 8] = ((r & 0x80) != 0); - pattern[y][ 9] = ((r & 0x40) != 0); - pattern[y][10] = ((r & 0x20) != 0); - pattern[y][11] = ((r & 0x10) != 0); - pattern[y][12] = ((r & 0x08) != 0); - pattern[y][13] = ((r & 0x04) != 0); - pattern[y][14] = ((r & 0x02) != 0); - pattern[y][15] = ((r & 0x01) != 0); - } - - // パターン出力 - for(int y = 0; y < size && dest_y + y < 480; y++) { - for(int x = 0; x < size && dest_x + x < 640; x++) { - if(pattern[(y * 16) / size][(x * 16) / size]) { - vram[dest][dest_y + y][dest_x + x] = color; - } - } - } -} - -extern "C" { - -void EMSCRIPTEN_KEEPALIVE ags_setAntialiasedStringMode(int on) { - antialias = on != 0; -} - -} +/* + ALICE SOFT SYSTEM 3 for Win32 + + [ AGS - text ] +*/ + +#include +#include "ags.h" +#include "encoding.h" +#include "texthook.h" + +namespace { + +bool antialias = true; + +int convert_to_zenkaku(int code) +{ + switch(code) { + case u' ': return u' '; + case u'!': return u'!'; + case u'"': return u'”'; + case u'#': return u'#'; + case u'$': return u'$'; + case u'%': return u'%'; + case u'&': return u'&'; + case u'\'': return u'’'; + case u'(': return u'('; + case u')': return u')'; + case u'*': return u'*'; + case u'+': return u'+'; + case u',': return u','; + case u'-': return u'-'; + case u'.': return u'.'; + case u'/': return u'/'; + case u'0': return u'0'; + case u'1': return u'1'; + case u'2': return u'2'; + case u'3': return u'3'; + case u'4': return u'4'; + case u'5': return u'5'; + case u'6': return u'6'; + case u'7': return u'7'; + case u'8': return u'8'; + case u'9': return u'9'; + case u':': return u':'; + case u';': return u';'; + case u'<': return u'<'; + case u'=': return u'='; + case u'>': return u'>'; + case u'?': return u'?'; + case u'@': return u'@'; + case u'A': return u'A'; + case u'B': return u'B'; + case u'C': return u'C'; + case u'D': return u'D'; + case u'E': return u'E'; + case u'F': return u'F'; + case u'G': return u'G'; + case u'H': return u'H'; + case u'I': return u'I'; + case u'J': return u'J'; + case u'K': return u'K'; + case u'L': return u'L'; + case u'M': return u'M'; + case u'N': return u'N'; + case u'O': return u'O'; + case u'P': return u'P'; + case u'Q': return u'Q'; + case u'R': return u'R'; + case u'S': return u'S'; + case u'T': return u'T'; + case u'U': return u'U'; + case u'V': return u'V'; + case u'W': return u'W'; + case u'X': return u'X'; + case u'Y': return u'Y'; + case u'Z': return u'Z'; + case u'[': return u'['; + case u'\\': return u'¥'; + case u']': return u']'; + case u'^': return u'^'; + case u'_': return u'_'; + case u'`': return u'‘'; + case u'a': return u'a'; + case u'b': return u'b'; + case u'c': return u'c'; + case u'd': return u'd'; + case u'e': return u'e'; + case u'f': return u'f'; + case u'g': return u'g'; + case u'h': return u'h'; + case u'i': return u'i'; + case u'j': return u'j'; + case u'k': return u'k'; + case u'l': return u'l'; + case u'm': return u'm'; + case u'n': return u'n'; + case u'o': return u'o'; + case u'p': return u'p'; + case u'q': return u'q'; + case u'r': return u'r'; + case u's': return u's'; + case u't': return u't'; + case u'u': return u'u'; + case u'v': return u'v'; + case u'w': return u'w'; + case u'x': return u'x'; + case u'y': return u'y'; + case u'z': return u'z'; + case u'{': return u'{'; + case u'|': return u'|'; + case u'}': return u'}'; + case u'~': return u'~'; + case u'。': return u'。'; + case u'「': return u'「'; + case u'」': return u'」'; + case u'、': return u'、'; + case u'・': return u'・'; + case u'ヲ': return u'を'; + case u'ァ': return u'ぁ'; + case u'ィ': return u'ぃ'; + case u'ゥ': return u'ぅ'; + case u'ェ': return u'ぇ'; + case u'ォ': return u'ぉ'; + case u'ャ': return u'ゃ'; + case u'ュ': return u'ゅ'; + case u'ョ': return u'ょ'; + case u'ッ': return u'っ'; + case u'ー': return u'ー'; + case u'ア': return u'あ'; + case u'イ': return u'い'; + case u'ウ': return u'う'; + case u'エ': return u'え'; + case u'オ': return u'お'; + case u'カ': return u'か'; + case u'キ': return u'き'; + case u'ク': return u'く'; + case u'ケ': return u'け'; + case u'コ': return u'こ'; + case u'サ': return u'さ'; + case u'シ': return u'し'; + case u'ス': return u'す'; + case u'セ': return u'せ'; + case u'ソ': return u'そ'; + case u'タ': return u'た'; + case u'チ': return u'ち'; + case u'ツ': return u'つ'; + case u'テ': return u'て'; + case u'ト': return u'と'; + case u'ナ': return u'な'; + case u'ニ': return u'に'; + case u'ヌ': return u'ぬ'; + case u'ネ': return u'ね'; + case u'ノ': return u'の'; + case u'ハ': return u'は'; + case u'ヒ': return u'ひ'; + case u'フ': return u'ふ'; + case u'ヘ': return u'へ'; + case u'ホ': return u'ほ'; + case u'マ': return u'ま'; + case u'ミ': return u'み'; + case u'ム': return u'む'; + case u'メ': return u'め'; + case u'モ': return u'も'; + case u'ヤ': return u'や'; + case u'ユ': return u'ゆ'; + case u'ヨ': return u'よ'; + case u'ラ': return u'ら'; + case u'リ': return u'り'; + case u'ル': return u'る'; + case u'レ': return u'れ'; + case u'ロ': return u'ろ'; + case u'ワ': return u'わ'; + case u'ン': return u'ん'; + case u'゙': return u'゛'; + case u'゚': return u'゜'; + } + return code; +} + +int convert_to_hankaku(int code) +{ + switch(code) { + case u' ': return u' '; + case u'!': return u'!'; + case u'”': return u'"'; + case u'#': return u'#'; + case u'$': return u'$'; + case u'%': return u'%'; + case u'&': return u'&'; + case u'’': return u'\''; + case u'(': return u'('; + case u')': return u')'; + case u'*': return u'*'; + case u'+': return u'+'; + case u',': return u','; + case u'-': return u'-'; + case u'.': return u'.'; + case u'/': return u'/'; + case u'0': return u'0'; + case u'1': return u'1'; + case u'2': return u'2'; + case u'3': return u'3'; + case u'4': return u'4'; + case u'5': return u'5'; + case u'6': return u'6'; + case u'7': return u'7'; + case u'8': return u'8'; + case u'9': return u'9'; + case u':': return u':'; + case u';': return u';'; + case u'<': return u'<'; + case u'=': return u'='; + case u'>': return u'>'; + case u'?': return u'?'; + case u'@': return u'@'; + case u'A': return u'A'; + case u'B': return u'B'; + case u'C': return u'C'; + case u'D': return u'D'; + case u'E': return u'E'; + case u'F': return u'F'; + case u'G': return u'G'; + case u'H': return u'H'; + case u'I': return u'I'; + case u'J': return u'J'; + case u'K': return u'K'; + case u'L': return u'L'; + case u'M': return u'M'; + case u'N': return u'N'; + case u'O': return u'O'; + case u'P': return u'P'; + case u'Q': return u'Q'; + case u'R': return u'R'; + case u'S': return u'S'; + case u'T': return u'T'; + case u'U': return u'U'; + case u'V': return u'V'; + case u'W': return u'W'; + case u'X': return u'X'; + case u'Y': return u'Y'; + case u'Z': return u'Z'; + case u'[': return u'['; + case u'¥': return u'\\'; + case u']': return u']'; + case u'^': return u'^'; + case u'_': return u'_'; + case u'‘': return u'`'; + case u'a': return u'a'; + case u'b': return u'b'; + case u'c': return u'c'; + case u'd': return u'd'; + case u'e': return u'e'; + case u'f': return u'f'; + case u'g': return u'g'; + case u'h': return u'h'; + case u'i': return u'i'; + case u'j': return u'j'; + case u'k': return u'k'; + case u'l': return u'l'; + case u'm': return u'm'; + case u'n': return u'n'; + case u'o': return u'o'; + case u'p': return u'p'; + case u'q': return u'q'; + case u'r': return u'r'; + case u's': return u's'; + case u't': return u't'; + case u'u': return u'u'; + case u'v': return u'v'; + case u'w': return u'w'; + case u'x': return u'x'; + case u'y': return u'y'; + case u'z': return u'z'; + case u'{': return u'{'; + case u'|': return u'|'; + case u'}': return u'}'; + case u'~': return u'~'; + case u'。': return u'。'; + case u'「': return u'「'; + case u'」': return u'」'; + case u'、': return u'、'; + case u'・': return u'・'; + case u'を': return u'ヲ'; + case u'ぁ': return u'ァ'; + case u'ぃ': return u'ィ'; + case u'ぅ': return u'ゥ'; + case u'ぇ': return u'ェ'; + case u'ぉ': return u'ォ'; + case u'ゃ': return u'ャ'; + case u'ゅ': return u'ュ'; + case u'ょ': return u'ョ'; + case u'っ': return u'ッ'; + case u'ー': return u'ー'; + case u'あ': return u'ア'; + case u'い': return u'イ'; + case u'う': return u'ウ'; + case u'え': return u'エ'; + case u'お': return u'オ'; + case u'か': return u'カ'; + case u'き': return u'キ'; + case u'く': return u'ク'; + case u'け': return u'ケ'; + case u'こ': return u'コ'; + case u'さ': return u'サ'; + case u'し': return u'シ'; + case u'す': return u'ス'; + case u'せ': return u'セ'; + case u'そ': return u'ソ'; + case u'た': return u'タ'; + case u'ち': return u'チ'; + case u'つ': return u'ツ'; + case u'て': return u'テ'; + case u'と': return u'ト'; + case u'な': return u'ナ'; + case u'に': return u'ニ'; + case u'ぬ': return u'ヌ'; + case u'ね': return u'ネ'; + case u'の': return u'ノ'; + case u'は': return u'ハ'; + case u'ひ': return u'ヒ'; + case u'ふ': return u'フ'; + case u'へ': return u'ヘ'; + case u'ほ': return u'ホ'; + case u'ま': return u'マ'; + case u'み': return u'ミ'; + case u'む': return u'ム'; + case u'め': return u'メ'; + case u'も': return u'モ'; + case u'や': return u'ヤ'; + case u'ゆ': return u'ユ'; + case u'よ': return u'ヨ'; + case u'ら': return u'ラ'; + case u'り': return u'リ'; + case u'る': return u'ル'; + case u'れ': return u'レ'; + case u'ろ': return u'ロ'; + case u'わ': return u'ワ'; + case u'ん': return u'ン'; + case u'゛': return u'゙'; + case u'゜': return u'゚'; + } + return code; +} + +} // namespace + +void AGS::draw_text(const char* string, bool text_wait) +{ + int screen, dest_x, dest_y, font_size; + uint8 font_color; + + uint8 antialias_cache[256*7]; + if (antialias) + memset(antialias_cache, 0, 256); + + if (draw_menu) { + screen = 2; + dest_x = menu_dest_x; + dest_y = menu_dest_y; + font_size = menu_font_size; + font_color = menu_font_color; + } else { + screen = dest_screen; + dest_x = text_dest_x; + dest_y = text_dest_y; + font_size = text_font_size; + font_color = text_font_color; + if (*string && text_font_maxsize < text_font_size) + text_font_maxsize = text_font_size; + } + + TTF_Font* font = NULL; + switch (font_size) { + case 16: font = hFont16; break; + case 24: font = hFont24; break; + case 32: font = hFont32; break; + case 48: font = hFont48; break; + case 64: font = hFont64; break; + } + int ascent = TTF_FontAscent(font); + int descent = TTF_FontDescent(font); + // Adjust dest_y if the font height is larger than the specified size. + dest_y -= (ascent - descent - font_size) / 2; + + while (*string) { + int code = nact->encoding->next_codepoint(&string); + if(draw_hankaku) { + code = convert_to_hankaku(code); + } else { + code = convert_to_zenkaku(code); + } + + // 文字出力 + if (GAIJI_FIRST <= code && code <= GAIJI_LAST) { + // Use unadjusted dest_y here. + draw_gaiji(screen, dest_x, draw_menu ? menu_dest_y : text_dest_y, code, font_size, font_color); + dest_x += font_size; + } else { + if (!draw_menu) + texthook_character(nact->get_scenario_page(), code); + + if (antialias) + draw_char_antialias(screen, dest_x, dest_y, code, font, font_color, antialias_cache); + else + draw_char(screen, dest_x, dest_y, code, font, font_color); + + int miny, maxy, advance; + TTF_GlyphMetrics(font, code, NULL, NULL, &miny, &maxy, &advance); + // Some fonts report incorrect Ascent/Descent value so we need to fix them. + if (miny < descent) descent = miny; + if (maxy > ascent) ascent = maxy; + dest_x += advance; + } + + if (!draw_menu && text_wait && code != ' ') { + // 画面更新 + if(screen == 0) + draw_screen(text_dest_x, dest_y, dest_x - text_dest_x, ascent - descent); + text_dest_x = dest_x; + // Wait + nact->text_wait(); + } + } + if (draw_menu) + menu_dest_x = dest_x; + else if (!text_wait) { + // 画面更新 + if(screen == 0) + draw_screen(text_dest_x, dest_y, dest_x - text_dest_x, ascent - descent); + text_dest_x = dest_x; + } +} + +void AGS::draw_char(int dest, int dest_x, int dest_y, uint16 code, TTF_Font* font, uint8 color) +{ + // パターン取得 + SDL_Color white = {0xff, 0xff, 0xff}; + SDL_Surface* fs = TTF_RenderGlyph_Solid(font, code, white); + + // パターン出力 + for(int y = 0; y < fs->h && dest_y + y < 480; y++) { + uint8 *pattern = (uint8*)surface_line(fs, y); // FIXME: do not assume 8bpp + for(int x = 0; x < fs->w && dest_x + x < 640; x++) { + if(pattern[x] != 0) { + vram[dest][dest_y + y][dest_x + x] = color; + } + } + } + + SDL_FreeSurface(fs); +} + +int AGS::nearest_color(int r, int g, int b) { + int i, col, mind = INT_MAX; + for (i = 0; i < 256; i++) { + int dr = r - palR(i); + int dg = g - palG(i); + int db = b - palB(i); + int d = dr*dr*30 + dg*dg*59 + db*db*11; + if (d < mind) { + mind = d; + col = i; + } + } + return col; +} + +void AGS::draw_char_antialias(int dest, int dest_x, int dest_y, uint16 code, TTF_Font* font, uint8 color, uint8 cache[]) +{ + // パターン取得 + SDL_Color black = {0, 0, 0}; + SDL_Color white = {0xff, 0xff, 0xff}; + SDL_Surface* fs = TTF_RenderGlyph_Shaded(font, code, white, black); + + // パターン出力 + for(int y = 0; y < fs->h && dest_y + y < 480; y++) { + uint8 *pattern = (uint8*)surface_line(fs, y); + uint32 *dp = &vram[dest][dest_y + y][dest_x]; + for(int x = 0; x < fs->w && dest_x + x < 640; x++, dp++) { + uint8 bg = *dp; + int alpha = pattern[x] >> 5; + if (alpha == 0) { + // Transparent, do nothing + } else if (alpha == 7) { + *dp = color; + } else if (cache[bg] & 1 << alpha) { + *dp = cache[alpha << 8 | bg]; + } else { + cache[bg] |= 1 << alpha; + int c = nearest_color((palR(color) * alpha + palR(bg) * (7 - alpha)) / 7, + (palG(color) * alpha + palG(bg) * (7 - alpha)) / 7, + (palB(color) * alpha + palB(bg) * (7 - alpha)) / 7); + cache[alpha << 8 | bg] = c; + *dp = c; + } + } + } + + SDL_FreeSurface(fs); +} + +void AGS::draw_gaiji(int dest, int dest_x, int dest_y, uint16 code, int size, uint8 color) +{ + int index = code - GAIJI_FIRST; + bool pattern[16][16]; + + // パターン取得 + for(int y = 0; y < 16; y++) { + uint8 l = gaiji[index][y * 2 + 0]; + uint8 r = gaiji[index][y * 2 + 1]; + + pattern[y][ 0] = ((l & 0x80) != 0); + pattern[y][ 1] = ((l & 0x40) != 0); + pattern[y][ 2] = ((l & 0x20) != 0); + pattern[y][ 3] = ((l & 0x10) != 0); + pattern[y][ 4] = ((l & 0x08) != 0); + pattern[y][ 5] = ((l & 0x04) != 0); + pattern[y][ 6] = ((l & 0x02) != 0); + pattern[y][ 7] = ((l & 0x01) != 0); + pattern[y][ 8] = ((r & 0x80) != 0); + pattern[y][ 9] = ((r & 0x40) != 0); + pattern[y][10] = ((r & 0x20) != 0); + pattern[y][11] = ((r & 0x10) != 0); + pattern[y][12] = ((r & 0x08) != 0); + pattern[y][13] = ((r & 0x04) != 0); + pattern[y][14] = ((r & 0x02) != 0); + pattern[y][15] = ((r & 0x01) != 0); + } + + // パターン出力 + for(int y = 0; y < size && dest_y + y < 480; y++) { + for(int x = 0; x < size && dest_x + x < 640; x++) { + if(pattern[(y * 16) / size][(x * 16) / size]) { + vram[dest][dest_y + y][dest_x + x] = color; + } + } + } +} + +extern "C" { + +void EMSCRIPTEN_KEEPALIVE ags_setAntialiasedStringMode(int on) { + antialias = on != 0; +} + +} diff --git a/src/sys/ags_vsp.cpp b/src/sys/ags_vsp.cpp index d0fec13..ba2951f 100644 --- a/src/sys/ags_vsp.cpp +++ b/src/sys/ags_vsp.cpp @@ -1,165 +1,165 @@ -/* - ALICE SOFT SYSTEM 3 for Win32 - - [ AGS - vsp loader ] -*/ - -#include "ags.h" -#include "crc32.h" -#include - -void AGS::load_vsp(uint8* data, int page, int transparent) -{ - // ヘッダ取得 - int sx = data[0] | (data[1] << 8); - int sy = data[2] | (data[3] << 8); - int ex = data[4] | (data[5] << 8); - int ey = data[6] | (data[7] << 8); - int width = ex - sx; - int height = ey - sy; - uint8 base = (data[9] & 0x0f) << 4; - - // Jコマンドの処理 - if(set_cg_dest) { - sx = cg_dest_x >> 3; - sy = cg_dest_y; - ex = sx + width; - ey = sy + height; - set_cg_dest = false; - } - - // Zコマンドの処理 - if(nact->crc32_a == CRC32_AMBIVALENZ_FD || nact->crc32_a == CRC32_AMBIVALENZ_CD) { - // Z 0,numを無視する - } else { - if(palette_bank != -1) { - base = (palette_bank & 0x0f) << 4; - } - } - - // パレット取得 - if(get_palette && transparent != 101) { - int p = 0x0a; - for(int i = 0; i < 16; i++) { - uint32 b = data[p++] & 0xf; - uint32 r = data[p++] & 0xf; - uint32 g = data[p++] & 0xf; - program_palette[base + i] = SETPALETTE16(r, g, b); - } - } - - // パレット展開 - if(nact->crc32_a == CRC32_FUNNYBEE_FD || nact->crc32_a == CRC32_FUNNYBEE_CD || nact->crc32_a == CRC32_FUNNYBEE_PATCH) { - if(extract_palette_cg[page]) { - for(int i = 0; i < 16; i++) { - screen_palette[base + i] = program_palette[base + i]; - } - } - } else { - if(extract_palette && extract_palette_cg[page]) { - for(int i = 0; i < 16; i++) { - screen_palette[base + i] = program_palette[base + i]; - } - } - } - - // VSP展開 - uint8 cgdata[4][2][480], mask = 0; - int p = 0x3a; - memset(cgdata, 0, sizeof(cgdata)); - - for(int x = 0; x < width; x++) { - for(int pl = 0; pl < 4; pl++) { - int y = 0; - while(y < height) { - uint8 d1 = data[p++]; - if(d1 == 0) { - int length = data[p++] + 1; - for(int i = 0; i < length; i++) { - cgdata[pl][0][y] = cgdata[pl][1][y]; - y++; - } - } else if(d1 == 1) { - int length = data[p++] + 1; - uint8 d2 = data[p++]; - for(int i = 0; i < length; i++) { - cgdata[pl][0][y++] = d2; - } - } else if(d1 == 2) { - int length = data[p++] + 1; - uint8 d2 = data[p++]; - uint8 d3 = data[p++]; - for(int i = 0; i < length; i++) { - cgdata[pl][0][y++] = d2; - cgdata[pl][0][y++] = d3; - } - } else if(d1 == 3) { - int length = data[p++] + 1; - for(int i = 0; i < length; i++) { - cgdata[pl][0][y] = cgdata[0][0][y] ^ mask; - y++; - } - mask = 0; - } else if(d1 == 4) { - int length = data[p++] + 1; - for(int i = 0; i < length; i++) { - cgdata[pl][0][y] = cgdata[1][0][y] ^ mask; - y++; - } - mask = 0; - } else if(d1 == 5) { - int length = data[p++] + 1; - for(int i = 0; i < length; i++) { - cgdata[pl][0][y] = cgdata[2][0][y] ^ mask; - y++; - } - mask = 0; - } else if(d1 == 6) { - mask = 0xff; - } else if(d1 == 7) { - cgdata[pl][0][y++] = data[p++]; - } else { - cgdata[pl][0][y++] = d1; - } - } - } - - // VRAMに転送 - if(extract_cg) { - for(int y = 0; y < height; y++) { - uint8 b0, b1, b2, b3, c[8]; - b0 = cgdata[0][1][y] = cgdata[0][0][y]; - b1 = cgdata[1][1][y] = cgdata[1][0][y]; - b2 = cgdata[2][1][y] = cgdata[2][0][y]; - b3 = cgdata[3][1][y] = cgdata[3][0][y]; - c[0] = ((b0 >> 7) & 1) | ((b1 >> 6) & 2) | ((b2 >> 5) & 4) | ((b3 >> 4) & 8); - c[1] = ((b0 >> 6) & 1) | ((b1 >> 5) & 2) | ((b2 >> 4) & 4) | ((b3 >> 3) & 8); - c[2] = ((b0 >> 5) & 1) | ((b1 >> 4) & 2) | ((b2 >> 3) & 4) | ((b3 >> 2) & 8); - c[3] = ((b0 >> 4) & 1) | ((b1 >> 3) & 2) | ((b2 >> 2) & 4) | ((b3 >> 1) & 8); - c[4] = ((b0 >> 3) & 1) | ((b1 >> 2) & 2) | ((b2 >> 1) & 4) | ((b3 ) & 8); - c[5] = ((b0 >> 2) & 1) | ((b1 >> 1) & 2) | ((b2 ) & 4) | ((b3 << 1) & 8); - c[6] = ((b0 >> 1) & 1) | ((b1 ) & 2) | ((b2 << 1) & 4) | ((b3 << 2) & 8); - c[7] = ((b0 ) & 1) | ((b1 << 1) & 2) | ((b2 << 2) & 4) | ((b3 << 3) & 8); - - uint32* dest = &vram[dest_screen][y + sy][(x + sx) * 8]; - if(transparent == -1) { - for(int i = 0; i < 8; i++) { - dest[i] = c[i] | base; - } - } else { - for(int i = 0; i < 8; i++) { - if(c[i] != transparent) { - dest[i] = c[i] | base; - } - } - } - } - } - } - - // 画面更新 - if(dest_screen == 0 && extract_cg) { - draw_screen(sx * 8, sy, width * 8, height); - } -} - +/* + ALICE SOFT SYSTEM 3 for Win32 + + [ AGS - vsp loader ] +*/ + +#include "ags.h" +#include "crc32.h" +#include + +void AGS::load_vsp(uint8* data, int page, int transparent) +{ + // ヘッダ取得 + int sx = data[0] | (data[1] << 8); + int sy = data[2] | (data[3] << 8); + int ex = data[4] | (data[5] << 8); + int ey = data[6] | (data[7] << 8); + int width = ex - sx; + int height = ey - sy; + uint8 base = (data[9] & 0x0f) << 4; + + // Jコマンドの処理 + if(set_cg_dest) { + sx = cg_dest_x >> 3; + sy = cg_dest_y; + ex = sx + width; + ey = sy + height; + set_cg_dest = false; + } + + // Zコマンドの処理 + if(nact->crc32_a == CRC32_AMBIVALENZ_FD || nact->crc32_a == CRC32_AMBIVALENZ_CD) { + // Z 0,numを無視する + } else { + if(palette_bank != -1) { + base = (palette_bank & 0x0f) << 4; + } + } + + // パレット取得 + if(get_palette && transparent != 101) { + int p = 0x0a; + for(int i = 0; i < 16; i++) { + uint32 b = data[p++] & 0xf; + uint32 r = data[p++] & 0xf; + uint32 g = data[p++] & 0xf; + program_palette[base + i] = SETPALETTE16(r, g, b); + } + } + + // パレット展開 + if(nact->crc32_a == CRC32_FUNNYBEE_FD || nact->crc32_a == CRC32_FUNNYBEE_CD || nact->crc32_a == CRC32_FUNNYBEE_PATCH) { + if(extract_palette_cg[page]) { + for(int i = 0; i < 16; i++) { + screen_palette[base + i] = program_palette[base + i]; + } + } + } else { + if(extract_palette && extract_palette_cg[page]) { + for(int i = 0; i < 16; i++) { + screen_palette[base + i] = program_palette[base + i]; + } + } + } + + // VSP展開 + uint8 cgdata[4][2][480], mask = 0; + int p = 0x3a; + memset(cgdata, 0, sizeof(cgdata)); + + for(int x = 0; x < width; x++) { + for(int pl = 0; pl < 4; pl++) { + int y = 0; + while(y < height) { + uint8 d1 = data[p++]; + if(d1 == 0) { + int length = data[p++] + 1; + for(int i = 0; i < length; i++) { + cgdata[pl][0][y] = cgdata[pl][1][y]; + y++; + } + } else if(d1 == 1) { + int length = data[p++] + 1; + uint8 d2 = data[p++]; + for(int i = 0; i < length; i++) { + cgdata[pl][0][y++] = d2; + } + } else if(d1 == 2) { + int length = data[p++] + 1; + uint8 d2 = data[p++]; + uint8 d3 = data[p++]; + for(int i = 0; i < length; i++) { + cgdata[pl][0][y++] = d2; + cgdata[pl][0][y++] = d3; + } + } else if(d1 == 3) { + int length = data[p++] + 1; + for(int i = 0; i < length; i++) { + cgdata[pl][0][y] = cgdata[0][0][y] ^ mask; + y++; + } + mask = 0; + } else if(d1 == 4) { + int length = data[p++] + 1; + for(int i = 0; i < length; i++) { + cgdata[pl][0][y] = cgdata[1][0][y] ^ mask; + y++; + } + mask = 0; + } else if(d1 == 5) { + int length = data[p++] + 1; + for(int i = 0; i < length; i++) { + cgdata[pl][0][y] = cgdata[2][0][y] ^ mask; + y++; + } + mask = 0; + } else if(d1 == 6) { + mask = 0xff; + } else if(d1 == 7) { + cgdata[pl][0][y++] = data[p++]; + } else { + cgdata[pl][0][y++] = d1; + } + } + } + + // VRAMに転送 + if(extract_cg) { + for(int y = 0; y < height; y++) { + uint8 b0, b1, b2, b3, c[8]; + b0 = cgdata[0][1][y] = cgdata[0][0][y]; + b1 = cgdata[1][1][y] = cgdata[1][0][y]; + b2 = cgdata[2][1][y] = cgdata[2][0][y]; + b3 = cgdata[3][1][y] = cgdata[3][0][y]; + c[0] = ((b0 >> 7) & 1) | ((b1 >> 6) & 2) | ((b2 >> 5) & 4) | ((b3 >> 4) & 8); + c[1] = ((b0 >> 6) & 1) | ((b1 >> 5) & 2) | ((b2 >> 4) & 4) | ((b3 >> 3) & 8); + c[2] = ((b0 >> 5) & 1) | ((b1 >> 4) & 2) | ((b2 >> 3) & 4) | ((b3 >> 2) & 8); + c[3] = ((b0 >> 4) & 1) | ((b1 >> 3) & 2) | ((b2 >> 2) & 4) | ((b3 >> 1) & 8); + c[4] = ((b0 >> 3) & 1) | ((b1 >> 2) & 2) | ((b2 >> 1) & 4) | ((b3 ) & 8); + c[5] = ((b0 >> 2) & 1) | ((b1 >> 1) & 2) | ((b2 ) & 4) | ((b3 << 1) & 8); + c[6] = ((b0 >> 1) & 1) | ((b1 ) & 2) | ((b2 << 1) & 4) | ((b3 << 2) & 8); + c[7] = ((b0 ) & 1) | ((b1 << 1) & 2) | ((b2 << 2) & 4) | ((b3 << 3) & 8); + + uint32* dest = &vram[dest_screen][y + sy][(x + sx) * 8]; + if(transparent == -1) { + for(int i = 0; i < 8; i++) { + dest[i] = c[i] | base; + } + } else { + for(int i = 0; i < 8; i++) { + if(c[i] != transparent) { + dest[i] = c[i] | base; + } + } + } + } + } + } + + // 画面更新 + if(dest_screen == 0 && extract_cg) { + draw_screen(sx * 8, sy, width * 8, height); + } +} + diff --git a/src/sys/ags_vsp2l.cpp b/src/sys/ags_vsp2l.cpp index 4bfe74a..03f7a7c 100644 --- a/src/sys/ags_vsp2l.cpp +++ b/src/sys/ags_vsp2l.cpp @@ -1,144 +1,144 @@ -/* - ALICE SOFT SYSTEM 1 for Win32 - - [ AGS - vsp2l loader ] -*/ - -#include "ags.h" -#include - -void AGS::load_vsp2l(uint8* data, int page, int transparent) -{ - // ヘッダ取得 - int sx = data[0] | (data[1] << 8); - int sy = data[2] | (data[3] << 8); - int ex = data[4] | (data[5] << 8); - int ey = data[6] | (data[7] << 8); - int width = ex - sx; - int height = ey - sy; - uint8 base = 0;//(data[9] & 0x0f) << 4; - - // Jコマンドの処理 - if(set_cg_dest) { - sx = cg_dest_x >> 3; - sy = cg_dest_y; - ex = sx + width; - ey = sy + height; - set_cg_dest = false; - } - - // Zコマンドの処理 - if(palette_bank != -1) { - base = (palette_bank & 0x0f) << 4; - } - - // パレット取得 - screen_palette[base + 0] = SETPALETTE16(0x0, 0x0, 0x0); - screen_palette[base + 1] = SETPALETTE16(0x0, 0x0, 0xf); - screen_palette[base + 2] = SETPALETTE16(0xf, 0x0, 0x0); - screen_palette[base + 3] = SETPALETTE16(0xf, 0x0, 0xf); - screen_palette[base + 4] = SETPALETTE16(0x0, 0xf, 0x0); - screen_palette[base + 5] = SETPALETTE16(0x0, 0xf, 0xf); - screen_palette[base + 6] = SETPALETTE16(0xf, 0xf, 0x0); - screen_palette[base + 7] = SETPALETTE16(0xf, 0xf, 0xf); - - // VSP2L展開 - uint8 cgdata[3][2][200], mask = 0; - int p = 0x1a; - memset(cgdata, 0, sizeof(cgdata)); - - for(int x = 0; x < width; x++) { - for(int pl = 0; pl < 3; pl++) { - int y = 0; - while(y < height) { - uint8 d1 = data[p++]; - if(d1 == 0) { - int length = data[p++] + 1; - for(int i = 0; i < length; i++) { - cgdata[pl][0][y] = cgdata[pl][1][y]; - y++; - } - } else if(d1 == 1) { - int length = data[p++] + 1; - uint8 d2 = data[p++]; - for(int i = 0; i < length; i++) { - cgdata[pl][0][y++] = d2; - } - } else if(d1 == 2) { - int length = data[p++] + 1; - uint8 d2 = data[p++]; - uint8 d3 = data[p++]; - for(int i = 0; i < length; i++) { - cgdata[pl][0][y++] = d2; - cgdata[pl][0][y++] = d3; - } - } else if(d1 == 3) { - int length = data[p++] + 1; - for(int i = 0; i < length; i++) { - cgdata[pl][0][y] = cgdata[0][0][y] ^ mask; - y++; - } - mask = 0; - } else if(d1 == 4) { - int length = data[p++] + 1; - for(int i = 0; i < length; i++) { - cgdata[pl][0][y] = cgdata[1][0][y] ^ mask; - y++; - } - mask = 0; - } else if(d1 == 5) { - int length = data[p++] + 1; - for(int i = 0; i < length; i++) { - cgdata[pl][0][y] = cgdata[2][0][y] ^ mask; - y++; - } - mask = 0; - } else if(d1 == 6) { - mask = 0xff; - } else if(d1 == 7) { - cgdata[pl][0][y++] = data[p++]; - } else { - cgdata[pl][0][y++] = d1; - } - } - } - - // VRAMに転送 - if(extract_cg) { - for(int y = 0; y < height; y++) { - uint8 b0, b1, b2, c[8]; - b0 = cgdata[0][1][y] = cgdata[0][0][y]; - b1 = cgdata[1][1][y] = cgdata[1][0][y]; - b2 = cgdata[2][1][y] = cgdata[2][0][y]; - c[0] = ((b0 >> 7) & 1) | ((b1 >> 6) & 2) | ((b2 >> 5) & 4); - c[1] = ((b0 >> 6) & 1) | ((b1 >> 5) & 2) | ((b2 >> 4) & 4); - c[2] = ((b0 >> 5) & 1) | ((b1 >> 4) & 2) | ((b2 >> 3) & 4); - c[3] = ((b0 >> 4) & 1) | ((b1 >> 3) & 2) | ((b2 >> 2) & 4); - c[4] = ((b0 >> 3) & 1) | ((b1 >> 2) & 2) | ((b2 >> 1) & 4); - c[5] = ((b0 >> 2) & 1) | ((b1 >> 1) & 2) | ((b2 ) & 4); - c[6] = ((b0 >> 1) & 1) | ((b1 ) & 2) | ((b2 << 1) & 4); - c[7] = ((b0 ) & 1) | ((b1 << 1) & 2) | ((b2 << 2) & 4); - - uint32* dest0 = &vram[dest_screen][(y + sy) * 2 + 0][(x + sx) * 8]; - uint32* dest1 = &vram[dest_screen][(y + sy) * 2 + 1][(x + sx) * 8]; - if(transparent == -1) { - for(int i = 0; i < 8; i++) { - dest0[i] = dest1[i] = c[i] | base; - } - } else { - for(int i = 0; i < 8; i++) { - if(c[i] != transparent) { - dest0[i] = dest1[i] = c[i] | base; - } - } - } - } - } - } - - // 画面更新 - if(dest_screen == 0 && extract_cg) { - draw_screen(sx * 8, sy * 2, width * 8, height * 2); - } -} - +/* + ALICE SOFT SYSTEM 1 for Win32 + + [ AGS - vsp2l loader ] +*/ + +#include "ags.h" +#include + +void AGS::load_vsp2l(uint8* data, int page, int transparent) +{ + // ヘッダ取得 + int sx = data[0] | (data[1] << 8); + int sy = data[2] | (data[3] << 8); + int ex = data[4] | (data[5] << 8); + int ey = data[6] | (data[7] << 8); + int width = ex - sx; + int height = ey - sy; + uint8 base = 0;//(data[9] & 0x0f) << 4; + + // Jコマンドの処理 + if(set_cg_dest) { + sx = cg_dest_x >> 3; + sy = cg_dest_y; + ex = sx + width; + ey = sy + height; + set_cg_dest = false; + } + + // Zコマンドの処理 + if(palette_bank != -1) { + base = (palette_bank & 0x0f) << 4; + } + + // パレット取得 + screen_palette[base + 0] = SETPALETTE16(0x0, 0x0, 0x0); + screen_palette[base + 1] = SETPALETTE16(0x0, 0x0, 0xf); + screen_palette[base + 2] = SETPALETTE16(0xf, 0x0, 0x0); + screen_palette[base + 3] = SETPALETTE16(0xf, 0x0, 0xf); + screen_palette[base + 4] = SETPALETTE16(0x0, 0xf, 0x0); + screen_palette[base + 5] = SETPALETTE16(0x0, 0xf, 0xf); + screen_palette[base + 6] = SETPALETTE16(0xf, 0xf, 0x0); + screen_palette[base + 7] = SETPALETTE16(0xf, 0xf, 0xf); + + // VSP2L展開 + uint8 cgdata[3][2][200], mask = 0; + int p = 0x1a; + memset(cgdata, 0, sizeof(cgdata)); + + for(int x = 0; x < width; x++) { + for(int pl = 0; pl < 3; pl++) { + int y = 0; + while(y < height) { + uint8 d1 = data[p++]; + if(d1 == 0) { + int length = data[p++] + 1; + for(int i = 0; i < length; i++) { + cgdata[pl][0][y] = cgdata[pl][1][y]; + y++; + } + } else if(d1 == 1) { + int length = data[p++] + 1; + uint8 d2 = data[p++]; + for(int i = 0; i < length; i++) { + cgdata[pl][0][y++] = d2; + } + } else if(d1 == 2) { + int length = data[p++] + 1; + uint8 d2 = data[p++]; + uint8 d3 = data[p++]; + for(int i = 0; i < length; i++) { + cgdata[pl][0][y++] = d2; + cgdata[pl][0][y++] = d3; + } + } else if(d1 == 3) { + int length = data[p++] + 1; + for(int i = 0; i < length; i++) { + cgdata[pl][0][y] = cgdata[0][0][y] ^ mask; + y++; + } + mask = 0; + } else if(d1 == 4) { + int length = data[p++] + 1; + for(int i = 0; i < length; i++) { + cgdata[pl][0][y] = cgdata[1][0][y] ^ mask; + y++; + } + mask = 0; + } else if(d1 == 5) { + int length = data[p++] + 1; + for(int i = 0; i < length; i++) { + cgdata[pl][0][y] = cgdata[2][0][y] ^ mask; + y++; + } + mask = 0; + } else if(d1 == 6) { + mask = 0xff; + } else if(d1 == 7) { + cgdata[pl][0][y++] = data[p++]; + } else { + cgdata[pl][0][y++] = d1; + } + } + } + + // VRAMに転送 + if(extract_cg) { + for(int y = 0; y < height; y++) { + uint8 b0, b1, b2, c[8]; + b0 = cgdata[0][1][y] = cgdata[0][0][y]; + b1 = cgdata[1][1][y] = cgdata[1][0][y]; + b2 = cgdata[2][1][y] = cgdata[2][0][y]; + c[0] = ((b0 >> 7) & 1) | ((b1 >> 6) & 2) | ((b2 >> 5) & 4); + c[1] = ((b0 >> 6) & 1) | ((b1 >> 5) & 2) | ((b2 >> 4) & 4); + c[2] = ((b0 >> 5) & 1) | ((b1 >> 4) & 2) | ((b2 >> 3) & 4); + c[3] = ((b0 >> 4) & 1) | ((b1 >> 3) & 2) | ((b2 >> 2) & 4); + c[4] = ((b0 >> 3) & 1) | ((b1 >> 2) & 2) | ((b2 >> 1) & 4); + c[5] = ((b0 >> 2) & 1) | ((b1 >> 1) & 2) | ((b2 ) & 4); + c[6] = ((b0 >> 1) & 1) | ((b1 ) & 2) | ((b2 << 1) & 4); + c[7] = ((b0 ) & 1) | ((b1 << 1) & 2) | ((b2 << 2) & 4); + + uint32* dest0 = &vram[dest_screen][(y + sy) * 2 + 0][(x + sx) * 8]; + uint32* dest1 = &vram[dest_screen][(y + sy) * 2 + 1][(x + sx) * 8]; + if(transparent == -1) { + for(int i = 0; i < 8; i++) { + dest0[i] = dest1[i] = c[i] | base; + } + } else { + for(int i = 0; i < 8; i++) { + if(c[i] != transparent) { + dest0[i] = dest1[i] = c[i] | base; + } + } + } + } + } + } + + // 画面更新 + if(dest_screen == 0 && extract_cg) { + draw_screen(sx * 8, sy * 2, width * 8, height * 2); + } +} + diff --git a/src/sys/ags_window.cpp b/src/sys/ags_window.cpp index 66158a4..9262ab3 100644 --- a/src/sys/ags_window.cpp +++ b/src/sys/ags_window.cpp @@ -1,331 +1,331 @@ -/* - ALICE SOFT SYSTEM 3 for Win32 - - [ AGS - window ] -*/ - -#include "ags.h" -#include - -void AGS::clear_text_window(int index, bool erase) -{ - int sx = text_w[index - 1].sx; - int sy = text_w[index - 1].sy; - int ex = text_w[index - 1].ex; - int ey = text_w[index - 1].ey; - - if(erase) { - if(text_w[index - 1].frame && fade_level) { - draw_window(sx - 8, sy - 8, ex + 8, ey + 8, true, text_frame_color, text_back_color); - } else { - box_fill(0, sx, sy, ex, ey, text_back_color); - } - } - - text_dest_x = sx; - text_dest_y = sy + 2;//text_space; - text_font_maxsize = 0; -} - -bool AGS::return_text_line(int index) -{ - int sx = text_w[index - 1].sx; - int ey = text_w[index - 1].ey; - - text_dest_x = sx; - text_dest_y += (text_font_maxsize > text_font_size) ? text_font_maxsize : text_font_size; - text_dest_y += text_space; - text_font_maxsize = 0; - - // 次の行が表示しきれるか? - return (text_dest_y + text_font_size) > ey ? true : false; -} - -void AGS::draw_push(int index) -{ - // Pushのパターンデータ - static uint16 pattern[16] = { - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xe000, - 0x9000, 0x9974, 0xe944, 0x8977, 0x8915, 0x8775, 0x0000, 0xffff - }; - - int x = text_w[index - 1].ex - 16; - int y = text_w[index - 1].ey - 16; - - for(int i = 0; i < 16; i++) { - if(pattern[i] & 0x8000) vram[0][y + i][x + 0] = text_font_color; - if(pattern[i] & 0x4000) vram[0][y + i][x + 1] = text_font_color; - if(pattern[i] & 0x2000) vram[0][y + i][x + 2] = text_font_color; - if(pattern[i] & 0x1000) vram[0][y + i][x + 3] = text_font_color; - if(pattern[i] & 0x0800) vram[0][y + i][x + 4] = text_font_color; - if(pattern[i] & 0x0400) vram[0][y + i][x + 5] = text_font_color; - if(pattern[i] & 0x0200) vram[0][y + i][x + 6] = text_font_color; - if(pattern[i] & 0x0100) vram[0][y + i][x + 7] = text_font_color; - if(pattern[i] & 0x0080) vram[0][y + i][x + 8] = text_font_color; - if(pattern[i] & 0x0040) vram[0][y + i][x + 9] = text_font_color; - if(pattern[i] & 0x0020) vram[0][y + i][x + 10] = text_font_color; - if(pattern[i] & 0x0010) vram[0][y + i][x + 11] = text_font_color; - if(pattern[i] & 0x0008) vram[0][y + i][x + 12] = text_font_color; - if(pattern[i] & 0x0004) vram[0][y + i][x + 13] = text_font_color; - if(pattern[i] & 0x0002) vram[0][y + i][x + 14] = text_font_color; - if(pattern[i] & 0x0001) vram[0][y + i][x + 15] = text_font_color; - } - draw_screen(x, y, 16, 16); -} - -void AGS::open_text_window(int index, bool erase) -{ - int sx = text_w[index - 1].sx - (text_w[index - 1].frame ? 8 : 0); - int sy = text_w[index - 1].sy - (text_w[index - 1].frame ? 8 : 0); - int ex = text_w[index - 1].ex + (text_w[index - 1].frame ? 8 : 0); - int ey = text_w[index - 1].ey + (text_w[index - 1].frame ? 8 : 0); - int width = ex - sx + 1; - int height = ey - sy + 1; - - // 画面退避 - if(text_w[index - 1].push) { - if(text_w[index - 1].screen) { - free(text_w[index - 1].screen); - } - - text_w[index - 1].screen = (uint32*)malloc(width * height * sizeof(uint32)); - text_w[index - 1].screen_x = sx; - text_w[index - 1].screen_y = sy; - text_w[index - 1].screen_width = width; - text_w[index - 1].screen_height = height; - - for(int y = 0; y < height && y + sy < 480; y++) { - uint32* scr = surface_line(hBmpDest, y + sy) + sx; - for(int x = 0; x < width && x + sx < 640; x++) { - uint32 col = vram[0][y + sy][x + sx]; - if(!(col & 0x80000000)) { - text_w[index - 1].screen_palette[col & 0xff] = scr[x]; - } - text_w[index - 1].screen[x + width * y] = col; - } - } - } - - if(erase) { - // 窓初期化 - draw_window(sx, sy, ex, ey, text_w[index - 1].frame, text_frame_color, text_back_color); - } else if(text_w[index - 1].push && text_w[index - 1].window) { - // 窓復帰 - sx = text_w[index - 1].window_x; - sy = text_w[index - 1].window_y; - width = text_w[index - 1].window_width; - height = text_w[index - 1].window_height; - - for(int y = 0; y < height && y + sy < 480; y++) { - for(int x = 0; x < width && x + sx < 640; x++) { - vram[0][y + sy][x + sx] = text_w[index - 1].window[x + width * y]; - } - } - - uint32 palette[256]; - memcpy(palette, screen_palette, sizeof(screen_palette)); - memcpy(screen_palette, text_w[index - 1].window_palette, sizeof(screen_palette)); - draw_screen(sx, sy, width, height); - memcpy(screen_palette, palette, sizeof(screen_palette)); - } - - // テキスト描画位置更新 - text_dest_x = text_w[index - 1].sx; - text_dest_y = text_w[index - 1].sy + text_space;; - text_font_maxsize = 0; -} - -void AGS::close_text_window(int index, bool update) -{ - int sx = text_w[index - 1].sx - (text_w[index - 1].frame ? 8 : 0); - int sy = text_w[index - 1].sy - (text_w[index - 1].frame ? 8 : 0); - int ex = text_w[index - 1].ex + (text_w[index - 1].frame ? 8 : 0); - int ey = text_w[index - 1].ey + (text_w[index - 1].frame ? 8 : 0); - int width = ex - sx + 1; - int height = ey - sy + 1; - - // 窓退避 - if(text_w[index - 1].push) { - if(text_w[index - 1].window) { - free(text_w[index - 1].window); - } - - text_w[index - 1].window = (uint32*)malloc(width * height * sizeof(uint32)); - text_w[index - 1].window_x = sx; - text_w[index - 1].window_y = sy; - text_w[index - 1].window_width = width; - text_w[index - 1].window_height = height; - - for(int y = 0; y < height && y + sy < 480; y++) { - uint32* scr = surface_line(hBmpDest, y + sy) + sx; - for(int x = 0; x < width && x + sx < 640; x++) { - uint32 col = vram[0][y + sy][x + sx]; - if(!(col & 0x80000000)) { - text_w[index - 1].window_palette[col & 0xff] = scr[x]; - } - text_w[index - 1].window[x + width * y] = col; - } - } - } - - // 画面復帰 - if(text_w[index - 1].push && text_w[index - 1].screen) { - sx = text_w[index - 1].screen_x; - sy = text_w[index - 1].screen_y; - width = text_w[index - 1].screen_width; - height = text_w[index - 1].screen_height; - - for(int y = 0; y < height && y + sy < 480; y++) { - for(int x = 0; x < width && x + sx < 640; x++) { - vram[0][y + sy][x + sx] = text_w[index - 1].screen[x + width * y]; - } - } - - uint32 palette[256]; - memcpy(palette, screen_palette, sizeof(screen_palette)); - memcpy(screen_palette, text_w[index - 1].screen_palette, sizeof(screen_palette)); - draw_screen(sx, sy, width, height); - memcpy(screen_palette, palette, sizeof(screen_palette)); - } - - // テキスト描画位置更新 - if(update) { - text_dest_x = text_w[index - 1].sx; - text_dest_y = text_w[index - 1].sy + text_space;; - text_font_maxsize = 0; - } -} - -void AGS::clear_menu_window() -{ - // TODO: use draw function - memset(hBmpScreen[2]->pixels, menu_back_color, 640 * 480 * sizeof(Uint32)); -} - -void AGS::open_menu_window(int index) -{ - int sx = menu_w[index - 1].sx; - int sy = menu_w[index - 1].sy; - int ex = menu_w[index - 1].ex; - int ey = menu_fix ? menu_w[index - 1].ey : sy + menu_dest_y - 1; - int width = ex - sx + 1; - int height = ey - sy + 1; - int wsx = sx - (menu_w[index - 1].frame ? 8 : 0); - int wsy = sy - (menu_w[index - 1].frame ? 8 : 0); - int wex = ex + (menu_w[index - 1].frame ? 8 : 0); - int wey = ey + (menu_w[index - 1].frame ? 8 : 0); - int wwidth = wex - wsx + 1; - int wheight = wey - wsy + 1; - - // 画面退避 - if(menu_w[index - 1].push) { - if(menu_w[index - 1].screen) { - free(menu_w[index - 1].screen); - } - - menu_w[index - 1].screen = (uint32*)malloc(wwidth * wheight * sizeof(uint32)); - menu_w[index - 1].screen_x = wsx; - menu_w[index - 1].screen_y = wsy; - menu_w[index - 1].screen_width = wwidth; - menu_w[index - 1].screen_height = wheight; - - for(int y = 0; y < wheight && y + wsy < 480; y++) { - uint32* scr = surface_line(hBmpDest, y + wsy) + wsx; - for(int x = 0; x < wwidth && x + wsx < 640; x++) { - uint32 col = vram[0][y + wsy][x + wsx]; - if(!(col & 0x80000000)) { - menu_w[index - 1].screen_palette[col & 0xff] = scr[x]; - } - menu_w[index - 1].screen[x + wwidth * y] = col; - } - } - } - - // メニュー表示 - draw_window(wsx, wsy, wex, wey, menu_w[index - 1].frame, menu_frame_color, menu_back_color); - for(int y = 0; y < height && y + sy < 480; y++) { - for(int x = 0; x < width && x + sx < 640; x++) { - vram[0][y + sy][x + sx] = vram[2][y][x]; - } - } - box_line(0, sx, sy, ex, sy + menu_font_size + 3, menu_frame_color); - draw_screen(wsx, wsy, wwidth, wheight); -} - -void AGS::redraw_menu_window(int index, int selected) -{ - int sx = menu_w[index - 1].sx; - int sy = menu_w[index - 1].sy; - int ex = menu_w[index - 1].ex; - int ey = menu_fix ? menu_w[index - 1].ey : sy + menu_dest_y - 1; - int width = ex - sx + 1; - int height = ey - sy + 1; - - for(int y = 0; y < height && y + sy < 480; y++) { - for(int x = 0; x < width && x + sx < 640; x++) { - vram[0][y + sy][x + sx] = vram[2][y][x]; - } - } - box_line(0, sx, sy + (menu_font_size + 4) * selected, ex, sy + (menu_font_size + 4) * (selected + 1) - 1, menu_frame_color); - draw_screen(sx, sy, width, height); -} - -void AGS::close_menu_window(int index) -{ - // 画面復帰 - if(menu_w[index - 1].push && menu_w[index - 1].screen) { - int sx = menu_w[index - 1].screen_x; - int sy = menu_w[index - 1].screen_y; - int width = menu_w[index - 1].screen_width; - int height = menu_w[index - 1].screen_height; - - for(int y = 0; y < height && y + sy < 480; y++) { - for(int x = 0; x < width && x + sx < 640; x++) { - vram[0][y + sy][x + sx] = menu_w[index - 1].screen[x + width * y]; - } - } - - uint32 palette[256]; - memcpy(palette, screen_palette, sizeof(screen_palette)); - memcpy(screen_palette, menu_w[index - 1].screen_palette, sizeof(screen_palette)); - draw_screen(sx, sy, width, height); - memcpy(screen_palette, palette, sizeof(screen_palette)); - } -} - -void AGS::draw_window(int sx, int sy, int ex, int ey, bool frame, uint8 frame_color, uint8 back_color) -{ - // 領域の塗り潰し - for(int y = sy; y <= ey && y < 480; y++) { - uint32* dest = vram[0][y]; - for(int x = sx; x <= ex && x < 640; x++) { - dest[x] = back_color; - } - } - - // 枠表示 - if(frame) { - for(int x = sx + 1; x <= ex - 1; x++) { - vram[0][sy + 1][x] = frame_color; - vram[0][sy + 2][x] = frame_color; - vram[0][ey - 2][x] = frame_color; - vram[0][ey - 1][x] = frame_color; - } - for(int y = sy + 1; y <= ey - 1; y++) { - vram[0][y][sx + 1] = frame_color; - vram[0][y][sx + 2] = frame_color; - vram[0][y][ex - 2] = frame_color; - vram[0][y][ex - 1] = frame_color; - } - for(int x = sx + 4; x <= ex - 4; x++) { - vram[0][sy + 4][x] = frame_color; - vram[0][ey - 4][x] = frame_color; - } - for(int y = sy + 4; y <= ey - 4; y++) { - vram[0][y][sx + 4] = frame_color; - vram[0][y][ex - 4] = frame_color; - } - } - draw_screen(sx, sy, ex - sx + 1, ey - sy + 1); -} - +/* + ALICE SOFT SYSTEM 3 for Win32 + + [ AGS - window ] +*/ + +#include "ags.h" +#include + +void AGS::clear_text_window(int index, bool erase) +{ + int sx = text_w[index - 1].sx; + int sy = text_w[index - 1].sy; + int ex = text_w[index - 1].ex; + int ey = text_w[index - 1].ey; + + if(erase) { + if(text_w[index - 1].frame && fade_level) { + draw_window(sx - 8, sy - 8, ex + 8, ey + 8, true, text_frame_color, text_back_color); + } else { + box_fill(0, sx, sy, ex, ey, text_back_color); + } + } + + text_dest_x = sx; + text_dest_y = sy + 2;//text_space; + text_font_maxsize = 0; +} + +bool AGS::return_text_line(int index) +{ + int sx = text_w[index - 1].sx; + int ey = text_w[index - 1].ey; + + text_dest_x = sx; + text_dest_y += (text_font_maxsize > text_font_size) ? text_font_maxsize : text_font_size; + text_dest_y += text_space; + text_font_maxsize = 0; + + // 次の行が表示しきれるか? + return (text_dest_y + text_font_size) > ey ? true : false; +} + +void AGS::draw_push(int index) +{ + // Pushのパターンデータ + static uint16 pattern[16] = { + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xe000, + 0x9000, 0x9974, 0xe944, 0x8977, 0x8915, 0x8775, 0x0000, 0xffff + }; + + int x = text_w[index - 1].ex - 16; + int y = text_w[index - 1].ey - 16; + + for(int i = 0; i < 16; i++) { + if(pattern[i] & 0x8000) vram[0][y + i][x + 0] = text_font_color; + if(pattern[i] & 0x4000) vram[0][y + i][x + 1] = text_font_color; + if(pattern[i] & 0x2000) vram[0][y + i][x + 2] = text_font_color; + if(pattern[i] & 0x1000) vram[0][y + i][x + 3] = text_font_color; + if(pattern[i] & 0x0800) vram[0][y + i][x + 4] = text_font_color; + if(pattern[i] & 0x0400) vram[0][y + i][x + 5] = text_font_color; + if(pattern[i] & 0x0200) vram[0][y + i][x + 6] = text_font_color; + if(pattern[i] & 0x0100) vram[0][y + i][x + 7] = text_font_color; + if(pattern[i] & 0x0080) vram[0][y + i][x + 8] = text_font_color; + if(pattern[i] & 0x0040) vram[0][y + i][x + 9] = text_font_color; + if(pattern[i] & 0x0020) vram[0][y + i][x + 10] = text_font_color; + if(pattern[i] & 0x0010) vram[0][y + i][x + 11] = text_font_color; + if(pattern[i] & 0x0008) vram[0][y + i][x + 12] = text_font_color; + if(pattern[i] & 0x0004) vram[0][y + i][x + 13] = text_font_color; + if(pattern[i] & 0x0002) vram[0][y + i][x + 14] = text_font_color; + if(pattern[i] & 0x0001) vram[0][y + i][x + 15] = text_font_color; + } + draw_screen(x, y, 16, 16); +} + +void AGS::open_text_window(int index, bool erase) +{ + int sx = text_w[index - 1].sx - (text_w[index - 1].frame ? 8 : 0); + int sy = text_w[index - 1].sy - (text_w[index - 1].frame ? 8 : 0); + int ex = text_w[index - 1].ex + (text_w[index - 1].frame ? 8 : 0); + int ey = text_w[index - 1].ey + (text_w[index - 1].frame ? 8 : 0); + int width = ex - sx + 1; + int height = ey - sy + 1; + + // 画面退避 + if(text_w[index - 1].push) { + if(text_w[index - 1].screen) { + free(text_w[index - 1].screen); + } + + text_w[index - 1].screen = (uint32*)malloc(width * height * sizeof(uint32)); + text_w[index - 1].screen_x = sx; + text_w[index - 1].screen_y = sy; + text_w[index - 1].screen_width = width; + text_w[index - 1].screen_height = height; + + for(int y = 0; y < height && y + sy < 480; y++) { + uint32* scr = surface_line(hBmpDest, y + sy) + sx; + for(int x = 0; x < width && x + sx < 640; x++) { + uint32 col = vram[0][y + sy][x + sx]; + if(!(col & 0x80000000)) { + text_w[index - 1].screen_palette[col & 0xff] = scr[x]; + } + text_w[index - 1].screen[x + width * y] = col; + } + } + } + + if(erase) { + // 窓初期化 + draw_window(sx, sy, ex, ey, text_w[index - 1].frame, text_frame_color, text_back_color); + } else if(text_w[index - 1].push && text_w[index - 1].window) { + // 窓復帰 + sx = text_w[index - 1].window_x; + sy = text_w[index - 1].window_y; + width = text_w[index - 1].window_width; + height = text_w[index - 1].window_height; + + for(int y = 0; y < height && y + sy < 480; y++) { + for(int x = 0; x < width && x + sx < 640; x++) { + vram[0][y + sy][x + sx] = text_w[index - 1].window[x + width * y]; + } + } + + uint32 palette[256]; + memcpy(palette, screen_palette, sizeof(screen_palette)); + memcpy(screen_palette, text_w[index - 1].window_palette, sizeof(screen_palette)); + draw_screen(sx, sy, width, height); + memcpy(screen_palette, palette, sizeof(screen_palette)); + } + + // テキスト描画位置更新 + text_dest_x = text_w[index - 1].sx; + text_dest_y = text_w[index - 1].sy + text_space;; + text_font_maxsize = 0; +} + +void AGS::close_text_window(int index, bool update) +{ + int sx = text_w[index - 1].sx - (text_w[index - 1].frame ? 8 : 0); + int sy = text_w[index - 1].sy - (text_w[index - 1].frame ? 8 : 0); + int ex = text_w[index - 1].ex + (text_w[index - 1].frame ? 8 : 0); + int ey = text_w[index - 1].ey + (text_w[index - 1].frame ? 8 : 0); + int width = ex - sx + 1; + int height = ey - sy + 1; + + // 窓退避 + if(text_w[index - 1].push) { + if(text_w[index - 1].window) { + free(text_w[index - 1].window); + } + + text_w[index - 1].window = (uint32*)malloc(width * height * sizeof(uint32)); + text_w[index - 1].window_x = sx; + text_w[index - 1].window_y = sy; + text_w[index - 1].window_width = width; + text_w[index - 1].window_height = height; + + for(int y = 0; y < height && y + sy < 480; y++) { + uint32* scr = surface_line(hBmpDest, y + sy) + sx; + for(int x = 0; x < width && x + sx < 640; x++) { + uint32 col = vram[0][y + sy][x + sx]; + if(!(col & 0x80000000)) { + text_w[index - 1].window_palette[col & 0xff] = scr[x]; + } + text_w[index - 1].window[x + width * y] = col; + } + } + } + + // 画面復帰 + if(text_w[index - 1].push && text_w[index - 1].screen) { + sx = text_w[index - 1].screen_x; + sy = text_w[index - 1].screen_y; + width = text_w[index - 1].screen_width; + height = text_w[index - 1].screen_height; + + for(int y = 0; y < height && y + sy < 480; y++) { + for(int x = 0; x < width && x + sx < 640; x++) { + vram[0][y + sy][x + sx] = text_w[index - 1].screen[x + width * y]; + } + } + + uint32 palette[256]; + memcpy(palette, screen_palette, sizeof(screen_palette)); + memcpy(screen_palette, text_w[index - 1].screen_palette, sizeof(screen_palette)); + draw_screen(sx, sy, width, height); + memcpy(screen_palette, palette, sizeof(screen_palette)); + } + + // テキスト描画位置更新 + if(update) { + text_dest_x = text_w[index - 1].sx; + text_dest_y = text_w[index - 1].sy + text_space;; + text_font_maxsize = 0; + } +} + +void AGS::clear_menu_window() +{ + // TODO: use draw function + memset(hBmpScreen[2]->pixels, menu_back_color, 640 * 480 * sizeof(Uint32)); +} + +void AGS::open_menu_window(int index) +{ + int sx = menu_w[index - 1].sx; + int sy = menu_w[index - 1].sy; + int ex = menu_w[index - 1].ex; + int ey = menu_fix ? menu_w[index - 1].ey : sy + menu_dest_y - 1; + int width = ex - sx + 1; + int height = ey - sy + 1; + int wsx = sx - (menu_w[index - 1].frame ? 8 : 0); + int wsy = sy - (menu_w[index - 1].frame ? 8 : 0); + int wex = ex + (menu_w[index - 1].frame ? 8 : 0); + int wey = ey + (menu_w[index - 1].frame ? 8 : 0); + int wwidth = wex - wsx + 1; + int wheight = wey - wsy + 1; + + // 画面退避 + if(menu_w[index - 1].push) { + if(menu_w[index - 1].screen) { + free(menu_w[index - 1].screen); + } + + menu_w[index - 1].screen = (uint32*)malloc(wwidth * wheight * sizeof(uint32)); + menu_w[index - 1].screen_x = wsx; + menu_w[index - 1].screen_y = wsy; + menu_w[index - 1].screen_width = wwidth; + menu_w[index - 1].screen_height = wheight; + + for(int y = 0; y < wheight && y + wsy < 480; y++) { + uint32* scr = surface_line(hBmpDest, y + wsy) + wsx; + for(int x = 0; x < wwidth && x + wsx < 640; x++) { + uint32 col = vram[0][y + wsy][x + wsx]; + if(!(col & 0x80000000)) { + menu_w[index - 1].screen_palette[col & 0xff] = scr[x]; + } + menu_w[index - 1].screen[x + wwidth * y] = col; + } + } + } + + // メニュー表示 + draw_window(wsx, wsy, wex, wey, menu_w[index - 1].frame, menu_frame_color, menu_back_color); + for(int y = 0; y < height && y + sy < 480; y++) { + for(int x = 0; x < width && x + sx < 640; x++) { + vram[0][y + sy][x + sx] = vram[2][y][x]; + } + } + box_line(0, sx, sy, ex, sy + menu_font_size + 3, menu_frame_color); + draw_screen(wsx, wsy, wwidth, wheight); +} + +void AGS::redraw_menu_window(int index, int selected) +{ + int sx = menu_w[index - 1].sx; + int sy = menu_w[index - 1].sy; + int ex = menu_w[index - 1].ex; + int ey = menu_fix ? menu_w[index - 1].ey : sy + menu_dest_y - 1; + int width = ex - sx + 1; + int height = ey - sy + 1; + + for(int y = 0; y < height && y + sy < 480; y++) { + for(int x = 0; x < width && x + sx < 640; x++) { + vram[0][y + sy][x + sx] = vram[2][y][x]; + } + } + box_line(0, sx, sy + (menu_font_size + 4) * selected, ex, sy + (menu_font_size + 4) * (selected + 1) - 1, menu_frame_color); + draw_screen(sx, sy, width, height); +} + +void AGS::close_menu_window(int index) +{ + // 画面復帰 + if(menu_w[index - 1].push && menu_w[index - 1].screen) { + int sx = menu_w[index - 1].screen_x; + int sy = menu_w[index - 1].screen_y; + int width = menu_w[index - 1].screen_width; + int height = menu_w[index - 1].screen_height; + + for(int y = 0; y < height && y + sy < 480; y++) { + for(int x = 0; x < width && x + sx < 640; x++) { + vram[0][y + sy][x + sx] = menu_w[index - 1].screen[x + width * y]; + } + } + + uint32 palette[256]; + memcpy(palette, screen_palette, sizeof(screen_palette)); + memcpy(screen_palette, menu_w[index - 1].screen_palette, sizeof(screen_palette)); + draw_screen(sx, sy, width, height); + memcpy(screen_palette, palette, sizeof(screen_palette)); + } +} + +void AGS::draw_window(int sx, int sy, int ex, int ey, bool frame, uint8 frame_color, uint8 back_color) +{ + // 領域の塗り潰し + for(int y = sy; y <= ey && y < 480; y++) { + uint32* dest = vram[0][y]; + for(int x = sx; x <= ex && x < 640; x++) { + dest[x] = back_color; + } + } + + // 枠表示 + if(frame) { + for(int x = sx + 1; x <= ex - 1; x++) { + vram[0][sy + 1][x] = frame_color; + vram[0][sy + 2][x] = frame_color; + vram[0][ey - 2][x] = frame_color; + vram[0][ey - 1][x] = frame_color; + } + for(int y = sy + 1; y <= ey - 1; y++) { + vram[0][y][sx + 1] = frame_color; + vram[0][y][sx + 2] = frame_color; + vram[0][y][ex - 2] = frame_color; + vram[0][y][ex - 1] = frame_color; + } + for(int x = sx + 4; x <= ex - 4; x++) { + vram[0][sy + 4][x] = frame_color; + vram[0][ey - 4][x] = frame_color; + } + for(int y = sy + 4; y <= ey - 4; y++) { + vram[0][y][sx + 4] = frame_color; + vram[0][y][ex - 4] = frame_color; + } + } + draw_screen(sx, sy, ex - sx + 1, ey - sy + 1); +} + diff --git a/src/sys/crc32.h b/src/sys/crc32.h index 08f0a08..569582c 100644 --- a/src/sys/crc32.h +++ b/src/sys/crc32.h @@ -1,79 +1,79 @@ -/* - ALICE SOFT SYSTEM 3 for Win32 - - [ crc32 database ] -*/ - -#ifndef _CRC32_H_ -#define _CRC32_H_ - -// ADISK.DATの先頭256bytes -// SYSTEM1 - -#define CRC32_BUNKASAI 0xc80f99b8 // あぶない文化祭前夜 -#define CRC32_CRESCENT 0x42351f2c // クレセントムーンがぁる -#define CRC32_DPS 0x69ea4865 // D.P.S. - Dream Program System -#define CRC32_DPS_SG 0xab4cda48 // D.P.S. SG -#define CRC32_DPS_SG_FAHREN 0xe405d57c // D.P.S. SG - Fahren Fliegen -#define CRC32_DPS_SG_KATEI 0x23e67d18 // D.P.S. SG - 家庭教師はステキなお仕事 -#define CRC32_DPS_SG_NOBUNAGA 0x2ec116f2 // D.P.S. SG - 信長の淫謀 -#define CRC32_DPS_SG2 0xab4cda48 // D.P.S. SG set2 -#define CRC32_DPS_SG2_ANTIQUE 0x41fe8b3d // D.P.S. SG set2 - ANTIQUE HOUSE -#define CRC32_DPS_SG2_IKENAI 0x6b562c09 // D.P.S. SG set2 - いけない内科検診再び -#define CRC32_DPS_SG2_AKAI 0x1098e78c // D.P.S. SG set2 - 朱い夜 -#define CRC32_DPS_SG3 0xb77ae133 // D.P.S. SG SG set3 -#define CRC32_DPS_SG3_RABBIT 0xa3228b6c // D.P.S. SG set3 - Rabbit P4P -#define CRC32_DPS_SG3_SHINKON 0x09b4448a // D.P.S. SG set3 - しんこんさんものがたり -#define CRC32_DPS_SG3_SOTSUGYOU 0xbc4525d8 // D.P.S. SG set3 - 卒業 -#define CRC32_FUKEI 0x026de326 // 婦警さんVX -#define CRC32_INTRUDER 0xa7520fb2 // Intruder -桜屋敷の探索- -#define CRC32_TENGU 0xc942ff58 // あぶないてんぐ伝説 -#define CRC32_TOUSHIN_HINT 0xac337537 // 闘神都市 ヒントディスク -#define CRC32_VAMPIRE 0x957bcfbf // Little Vampire -#define CRC32_VAMPIRE_ENG 0x61985a7f // Little Vampire (English) Patch 1.5 -#define CRC32_YAKATA 0x8cef6fa6 // ALICEの館 - -// SYSTEM2 - -#define CRC32_AYUMI_FD 0x4e2fed2a // あゆみちゃん物語 (FD) -#define CRC32_AYUMI_HINT 0xf6bd963a // あゆみちゃん物語 ヒントディスク -#define CRC32_AYUMI_PROTO 0x4e2f5678 // あゆみちゃん物語 PROTO -#define CRC32_DALK_HINT 0x4793b843 // DALK ヒントディスク -#define CRC32_DRSTOP 0x73fa86c4 // Dr. STOP! -#define CRC32_PROSTUDENTG_FD 0x5ffbfee7 // Prostudent -G- (FD) -#define CRC32_RANCE3_HINT 0x8d5ec610 // Rance3 ヒントディスク -#define CRC32_SDPS 0xc7a20cdf // Super D.P.S -#define CRC32_SDPS_MARIA 0x80d4eaca // Super D.P.S - マリアとカンパン -#define CRC32_SDPS_TONO 0xbb1edff1 // Super D.P.S - 遠野の森 -#define CRC32_SDPS_KAIZOKU 0xf81829e3 // Super D.P.S - うれしたのし海賊稼業 -#define CRC32_YAKATA2 0x2df591ff // ALICEの館II - -// SYSTEM3 - -#define CRC32_AMBIVALENZ_FD 0xa6b48dfe // AmbivalenZ (FD) -#define CRC32_AMBIVALENZ_CD 0x4b10db69 // AmbivalenZ (CD) -#define CRC32_DPSALL 0xd48b4ec6 // DPS全部 -#define CRC32_FUNNYBEE_CD 0xe14e3971 // Funny Bee (CD) -#define CRC32_FUNNYBEE_PATCH 0xe14e3971 // Funny Bee (CD + Patch) -#define CRC32_FUNNYBEE_FD 0x731267fa // Funny Bee (FD) -#define CRC32_ONLYYOU 0x832aeb97 // Only You -#define CRC32_ONLYYOU_DEMO 0xc1d13e44 // Only You (DEMO) -#define CRC32_PROSTUDENTG_CD 0xfb0e4a63 // Prostudent -G- (CD) -#define CRC32_PROG_OMAKE 0x8ba18bff // Prostudent G おまけ (CRC32 of AGAME.DAT) -#define CRC32_RANCE41 0xa43fb4b6 // Rance 4.1 -#define CRC32_RANCE41_ENG 0x811f4ff3 // Rance 4.1 (English) 1.5 Beta -#define CRC32_RANCE42 0x04d24d1e // Rance 4.2 -#define CRC32_RANCE42_ENG 0xa97cc370 // Rance 4.2 (English) 1.5 Beta -#define CRC32_AYUMI_CD 0xd2bed9ee // あゆみちゃん物語 (CD) -#define CRC32_AYUMI_JISSHA_256 0x00d15a2b // あゆみちゃん物語 実写版 -#define CRC32_AYUMI_JISSHA_FULL 0x5f66ff1d // あゆみちゃん物語 フルカラー実写版 -#define CRC32_YAKATA3_CD 0x7f8f5e2a // アリスの館3 (CD) -#define CRC32_YAKATA3_FD 0x58ebcc99 // アリスの館3 (FD) -#define CRC32_HASHIRIONNA2 0x09f47cbd // 走り女2 (Rance 4.x ヒントディスク) -#define CRC32_TOUSHIN2_GD 0xb5eba798 // 闘神都市2 グラフィックディスク -#define CRC32_TOUSHIN2_SP 0x2172c7b2 // 闘神都市2 そして、それから… -#define CRC32_OTOMESENKI 0x49a4db15 // 乙女戦記 -#define CRC32_NINGYO 0xd491e7ab // 人魚 -蘿子- -#define CRC32_MUGENHOUYOU 0xbb27d1ba // 夢幻泡影 - -#endif +/* + ALICE SOFT SYSTEM 3 for Win32 + + [ crc32 database ] +*/ + +#ifndef _CRC32_H_ +#define _CRC32_H_ + +// ADISK.DATの先頭256bytes +// SYSTEM1 + +#define CRC32_BUNKASAI 0xc80f99b8 // あぶない文化祭前夜 +#define CRC32_CRESCENT 0x42351f2c // クレセントムーンがぁる +#define CRC32_DPS 0x69ea4865 // D.P.S. - Dream Program System +#define CRC32_DPS_SG 0xab4cda48 // D.P.S. SG +#define CRC32_DPS_SG_FAHREN 0xe405d57c // D.P.S. SG - Fahren Fliegen +#define CRC32_DPS_SG_KATEI 0x23e67d18 // D.P.S. SG - 家庭教師はステキなお仕事 +#define CRC32_DPS_SG_NOBUNAGA 0x2ec116f2 // D.P.S. SG - 信長の淫謀 +#define CRC32_DPS_SG2 0xab4cda48 // D.P.S. SG set2 +#define CRC32_DPS_SG2_ANTIQUE 0x41fe8b3d // D.P.S. SG set2 - ANTIQUE HOUSE +#define CRC32_DPS_SG2_IKENAI 0x6b562c09 // D.P.S. SG set2 - いけない内科検診再び +#define CRC32_DPS_SG2_AKAI 0x1098e78c // D.P.S. SG set2 - 朱い夜 +#define CRC32_DPS_SG3 0xb77ae133 // D.P.S. SG SG set3 +#define CRC32_DPS_SG3_RABBIT 0xa3228b6c // D.P.S. SG set3 - Rabbit P4P +#define CRC32_DPS_SG3_SHINKON 0x09b4448a // D.P.S. SG set3 - しんこんさんものがたり +#define CRC32_DPS_SG3_SOTSUGYOU 0xbc4525d8 // D.P.S. SG set3 - 卒業 +#define CRC32_FUKEI 0x026de326 // 婦警さんVX +#define CRC32_INTRUDER 0xa7520fb2 // Intruder -桜屋敷の探索- +#define CRC32_TENGU 0xc942ff58 // あぶないてんぐ伝説 +#define CRC32_TOUSHIN_HINT 0xac337537 // 闘神都市 ヒントディスク +#define CRC32_VAMPIRE 0x957bcfbf // Little Vampire +#define CRC32_VAMPIRE_ENG 0x61985a7f // Little Vampire (English) Patch 1.5 +#define CRC32_YAKATA 0x8cef6fa6 // ALICEの館 + +// SYSTEM2 + +#define CRC32_AYUMI_FD 0x4e2fed2a // あゆみちゃん物語 (FD) +#define CRC32_AYUMI_HINT 0xf6bd963a // あゆみちゃん物語 ヒントディスク +#define CRC32_AYUMI_PROTO 0x4e2f5678 // あゆみちゃん物語 PROTO +#define CRC32_DALK_HINT 0x4793b843 // DALK ヒントディスク +#define CRC32_DRSTOP 0x73fa86c4 // Dr. STOP! +#define CRC32_PROSTUDENTG_FD 0x5ffbfee7 // Prostudent -G- (FD) +#define CRC32_RANCE3_HINT 0x8d5ec610 // Rance3 ヒントディスク +#define CRC32_SDPS 0xc7a20cdf // Super D.P.S +#define CRC32_SDPS_MARIA 0x80d4eaca // Super D.P.S - マリアとカンパン +#define CRC32_SDPS_TONO 0xbb1edff1 // Super D.P.S - 遠野の森 +#define CRC32_SDPS_KAIZOKU 0xf81829e3 // Super D.P.S - うれしたのし海賊稼業 +#define CRC32_YAKATA2 0x2df591ff // ALICEの館II + +// SYSTEM3 + +#define CRC32_AMBIVALENZ_FD 0xa6b48dfe // AmbivalenZ (FD) +#define CRC32_AMBIVALENZ_CD 0x4b10db69 // AmbivalenZ (CD) +#define CRC32_DPSALL 0xd48b4ec6 // DPS全部 +#define CRC32_FUNNYBEE_CD 0xe14e3971 // Funny Bee (CD) +#define CRC32_FUNNYBEE_PATCH 0xe14e3971 // Funny Bee (CD + Patch) +#define CRC32_FUNNYBEE_FD 0x731267fa // Funny Bee (FD) +#define CRC32_ONLYYOU 0x832aeb97 // Only You +#define CRC32_ONLYYOU_DEMO 0xc1d13e44 // Only You (DEMO) +#define CRC32_PROSTUDENTG_CD 0xfb0e4a63 // Prostudent -G- (CD) +#define CRC32_PROG_OMAKE 0x8ba18bff // Prostudent G おまけ (CRC32 of AGAME.DAT) +#define CRC32_RANCE41 0xa43fb4b6 // Rance 4.1 +#define CRC32_RANCE41_ENG 0x811f4ff3 // Rance 4.1 (English) 1.5 Beta +#define CRC32_RANCE42 0x04d24d1e // Rance 4.2 +#define CRC32_RANCE42_ENG 0xa97cc370 // Rance 4.2 (English) 1.5 Beta +#define CRC32_AYUMI_CD 0xd2bed9ee // あゆみちゃん物語 (CD) +#define CRC32_AYUMI_JISSHA_256 0x00d15a2b // あゆみちゃん物語 実写版 +#define CRC32_AYUMI_JISSHA_FULL 0x5f66ff1d // あゆみちゃん物語 フルカラー実写版 +#define CRC32_YAKATA3_CD 0x7f8f5e2a // アリスの館3 (CD) +#define CRC32_YAKATA3_FD 0x58ebcc99 // アリスの館3 (FD) +#define CRC32_HASHIRIONNA2 0x09f47cbd // 走り女2 (Rance 4.x ヒントディスク) +#define CRC32_TOUSHIN2_GD 0xb5eba798 // 闘神都市2 グラフィックディスク +#define CRC32_TOUSHIN2_SP 0x2172c7b2 // 闘神都市2 そして、それから… +#define CRC32_OTOMESENKI 0x49a4db15 // 乙女戦記 +#define CRC32_NINGYO 0xd491e7ab // 人魚 -蘿子- +#define CRC32_MUGENHOUYOU 0xbb27d1ba // 夢幻泡影 + +#endif diff --git a/src/sys/dri.cpp b/src/sys/dri.cpp index b1b9bc4..02ecf5d 100644 --- a/src/sys/dri.cpp +++ b/src/sys/dri.cpp @@ -1,319 +1,319 @@ -/* - ALICE SOFT SYSTEM 3 for Win32 - - [ DRI ] -*/ - -#include "dri.h" -#include -#include "crc32.h" -#include "../fileio.h" - -uint8* DRI::load(const char* file_name, int page, int* size) -{ - char tmp_name[20]; - strcpy_s(tmp_name, sizeof(tmp_name), file_name); - - FILEIO* fio = new FILEIO(); - - // ページの位置を取得 - tmp_name[0] = 'A'; - if(!fio->Fopen(tmp_name, FILEIO_READ_BINARY)) { - delete fio; - return NULL; - } - - int link_sector = fio->Fgetc(); - link_sector |= fio->Fgetc() << 8; - int data_sector = fio->Fgetc(); - data_sector |= fio->Fgetc() << 8; - - if(page > (data_sector - link_sector) * 128 - 1) { - // ページ番号不正 - fio->Fclose(); - delete fio; - return NULL; - } - - fio->Fseek((link_sector - 1) * 256 + (page - 1) * 2, FILEIO_SEEK_SET); - int disk_index = fio->Fgetc(); - int link_index = fio->Fgetc(); - - if(disk_index == 0 || disk_index == 0x1a) { - // 欠番 - fio->Fclose(); - delete fio; - return NULL; - } - - // A??.DAT以外にリンクされている場合はファイルを開き直す - if(disk_index != 1) { - tmp_name[0] = 'A' + disk_index - 1; - fio->Fclose(); - if(!fio->Fopen(tmp_name, FILEIO_READ_BINARY)) { - delete fio; - return NULL; - } - } - - // データ取得 - fio->Fseek(link_index * 2, FILEIO_SEEK_SET); - int start_sector = fio->Fgetc(); - start_sector |= fio->Fgetc() << 8; - int end_sector = fio->Fgetc(); - end_sector |= fio->Fgetc() << 8; - - if((*size = (end_sector - start_sector) * 256) == 0) { - // サイズ不正 - fio->Fclose(); - delete fio; - return NULL; - } - - uint8 *buffer = (uint8 *)malloc(*size); - fio->Fseek((start_sector - 1) * 256, FILEIO_SEEK_SET); - fio->Fread(buffer, 256, end_sector - start_sector); - - fio->Fclose(); - delete fio; - - return buffer; -} - -uint8* DRI::load_mda(uint32 crc32_a, uint32 crc32_b, int page, int* size) -{ - // データ取得 - const char* name = NULL; - - switch(crc32_a) { - case CRC32_BUNKASAI: // あぶない文化祭前夜 - name = "AMUS_AB.MDA"; - break; - case CRC32_CRESCENT: // クレセントムーンがぁる - name = "AMUS_CRS.MDA"; - break; - case CRC32_DPS: // D.P.S. - Dream Program System - name = "AMUS_DPS.MDA"; - break; - case CRC32_DPS_SG: // D.P.S. SG -// case CRC32_DPS_SG2: // D.P.S. SG set2 - case CRC32_DPS_SG3: // D.P.S. SG set2 - name = "AMUS_SG.MDA"; - break; - case CRC32_FUKEI: // 婦警さんVX - name = "AMUS_VX.MDA"; - break; - case CRC32_INTRUDER: // Intruder -桜屋敷の探索- - name = "AMUS_INT"; - break; - case CRC32_TENGU: // あぶないてんぐ伝説 - name = "AMUS_AT"; - break; - case CRC32_TOUSHIN_HINT: // 闘神都市 ヒントディスク - name = "AMUS_T1"; - break; - case CRC32_VAMPIRE: // Little Vampire - case CRC32_VAMPIRE_ENG: - name = "AMUS_LP2"; - break; - case CRC32_YAKATA: // ALICEの館 - name = "AMUS_AL1"; - break; - - case CRC32_AYUMI_FD: // あゆみちゃん物語 (FD) - case CRC32_AYUMI_HINT: // あゆみちゃん物語 ヒントディスク - case CRC32_AYUMI_PROTO: // あゆみちゃん物語 PROTO - name = "AMUS_AYM"; - break; - case CRC32_DALK_HINT: // DALK ヒントディスク - name = "AMUS_DLK"; - break; - case CRC32_DRSTOP: // Dr. STOP! - name = "AMUS_DRS"; - break; - case CRC32_PROSTUDENTG_FD: // Prostudent -G- (FD) - name = "AMUS_PSG"; - break; - case CRC32_RANCE3_HINT: // Rance3 ヒントディスク - name = "AMUS_R3H"; - break; - case CRC32_SDPS: // Super D.P.S - name = "AMUS_SDP"; - break; - case CRC32_YAKATA2: // ALICEの館II - name = "AMUS_AL2"; - break; - - case CRC32_AMBIVALENZ_FD: // AmbivalenZ (FD) - case CRC32_AMBIVALENZ_CD: // AmbivalenZ (CD) - name = "AMUS_AMB.MDA"; - break; - case CRC32_DPSALL: // DPS全部 - name = "AMUS_ALL.MDA"; - break; - case CRC32_FUNNYBEE_CD: // Funny Bee (CD) -// case CRC32_FUNNYBEE_PATCH: // Funny Bee (CD + Patch) - case CRC32_FUNNYBEE_FD: // Funny Bee (FD) - name = "AMUS_BEE.MDA"; - break; - case CRC32_ONLYYOU: // Only You - case CRC32_ONLYYOU_DEMO: // Only You (DEMO) - name = "AMUS_OY.MDA"; - break; - case CRC32_PROSTUDENTG_CD: // Prostudent -G- (CD) - name = "AMUS_PSG.MDA"; - break; - case CRC32_RANCE41: // Rance 4.1 - case CRC32_RANCE41_ENG: - name = "AMUS_R41.MDA"; - break; - case CRC32_RANCE42: // Rance 4.2 - case CRC32_RANCE42_ENG: - name = "AMUS_R42.MDA"; - break; - case CRC32_AYUMI_CD: // あゆみちゃん物語 (CD) - case CRC32_AYUMI_JISSHA_256: // あゆみちゃん物語 実写版 - case CRC32_AYUMI_JISSHA_FULL: // あゆみちゃん物語 フルカラー実写版 - name = "AMUS_AYM.MDA"; - break; - case CRC32_YAKATA3_CD: // アリスの館3 (CD) - case CRC32_YAKATA3_FD: // アリスの館3 (FD) - name = "AMUS_AL3.MDA"; - break; - case CRC32_HASHIRIONNA2: // 走り女2 (Rance 4.x ヒントディスク) - name = "AMUS_RG2.MDA"; - break; - case CRC32_TOUSHIN2_GD: // 闘神都市2 グラフィックディスク - name = "AMUS_T2"; - break; - case CRC32_OTOMESENKI: // 乙女戦記 - name = "AMUS_OTM.MDA"; - break; - case CRC32_MUGENHOUYOU: // 夢幻泡影 - name = "AMUS_MGN.MDA"; - break; - } - - if(name == NULL) { - return NULL; - } - - SDL_RWops* rw = open_resource(name, "mda"); - if (!rw) - return NULL; - uint8 buf[4]; - - // ページの位置を取得 - SDL_RWread(rw, buf, 4, 1); - int link_sector = buf[0] | (buf[1] << 8); - int data_sector = buf[2] | (buf[3] << 8); - - if(page > (data_sector - link_sector) * 128 - 1) { - // ページ番号不正 - SDL_RWclose(rw); - return NULL; - } - - SDL_RWseek(rw, (link_sector - 1) * 256 + (page - 1) * 2, RW_SEEK_SET); - SDL_RWread(rw, buf, 2, 1); - - int disk_index = buf[0]; - int link_index = buf[1]; - - if(disk_index == 0 || disk_index == 0x1a) { - // 欠番 - SDL_RWclose(rw); - return NULL; - } - - // AMUS.MDA以外にリンクされている場合はリソースを開き直す - if(disk_index == 2) { - SDL_RWclose(rw); - switch(crc32_b) { - case CRC32_DPS_SG_FAHREN: // D.P.S. SG - Fahren Fliegen - name = "BMUS_FAH"; - break; - case CRC32_DPS_SG_KATEI: // D.P.S. SG - 家庭教師はステキなお仕事 - name = "BMUS_KAT"; - break; - case CRC32_DPS_SG_NOBUNAGA: // D.P.S. SG - 信長の淫謀 - name = "BMUS_NOB"; - break; - case CRC32_DPS_SG2_ANTIQUE: // D.P.S. SG set2 - ANTIQUE HOUSE - name = "BMUS_ANT"; - break; - case CRC32_DPS_SG2_IKENAI: // D.P.S. SG set2 - いけない内科検診再び - name = "BMUS_NAI"; - break; - case CRC32_DPS_SG2_AKAI: // D.P.S. SG set2 - 朱い夜 - name = "BMUS_AKA"; - break; - case CRC32_DPS_SG3_RABBIT: // D.P.S. SG set3 - Rabbit P4P - name = "BMUS_RAB"; - break; - case CRC32_DPS_SG3_SHINKON: // D.P.S. SG set3 - しんこんさんものがたり - name = "BMUS_SIN"; - break; - case CRC32_DPS_SG3_SOTSUGYOU: // D.P.S. SG set3 - 卒業 - name = "BMUS_SOT"; - break; - case CRC32_SDPS_MARIA: // Super D.P.S - マリアとカンパン - name = "BMUS_MTK"; - break; - case CRC32_SDPS_TONO: // Super D.P.S - 遠野の森 - name = "BMUS_TNM"; - break; - case CRC32_SDPS_KAIZOKU: // Super D.P.S - うれしたのし海賊稼業 - name = "BMUS_KAM"; - break; - default: - name = NULL; - break; - } - if(name == NULL) { - return NULL; - } - if((rw = open_resource(name, "mda")) == NULL) { - return NULL; - } - } else if(disk_index == 3) { - SDL_RWclose(rw); - switch(crc32_a) { - case CRC32_TOUSHIN_HINT: // 闘神都市 ヒントディスク - name = "CMUS_T1"; - break; - default: - name = NULL; - break; - } - if(name == NULL) { - return NULL; - } - if((rw = open_resource(name, "mda")) == NULL) { - return NULL; - } - } else if(disk_index != 1) { - // AMUS.MDA以外にリンクされている場合は失敗 - SDL_RWclose(rw); - return NULL; - } - - // データ取得 - SDL_RWseek(rw, link_index * 2, RW_SEEK_SET); - SDL_RWread(rw, buf, 4, 1); - int start_sector = buf[0] | (buf[1] << 8); - int end_sector = buf[2] | (buf[3] << 8); - - if((*size = (end_sector - start_sector) * 256) == 0) { - // サイズ不正 - SDL_RWclose(rw); - return NULL; - } - uint8* buffer = (uint8*)malloc(*size); - SDL_RWseek(rw, (start_sector - 1) * 256, RW_SEEK_SET); - SDL_RWread(rw, buffer, *size, 1); - - SDL_RWclose(rw); - - return buffer; -} +/* + ALICE SOFT SYSTEM 3 for Win32 + + [ DRI ] +*/ + +#include "dri.h" +#include +#include "crc32.h" +#include "../fileio.h" + +uint8* DRI::load(const char* file_name, int page, int* size) +{ + char tmp_name[20]; + strcpy_s(tmp_name, sizeof(tmp_name), file_name); + + FILEIO* fio = new FILEIO(); + + // ページの位置を取得 + tmp_name[0] = 'A'; + if(!fio->Fopen(tmp_name, FILEIO_READ_BINARY)) { + delete fio; + return NULL; + } + + int link_sector = fio->Fgetc(); + link_sector |= fio->Fgetc() << 8; + int data_sector = fio->Fgetc(); + data_sector |= fio->Fgetc() << 8; + + if(page > (data_sector - link_sector) * 128 - 1) { + // ページ番号不正 + fio->Fclose(); + delete fio; + return NULL; + } + + fio->Fseek((link_sector - 1) * 256 + (page - 1) * 2, FILEIO_SEEK_SET); + int disk_index = fio->Fgetc(); + int link_index = fio->Fgetc(); + + if(disk_index == 0 || disk_index == 0x1a) { + // 欠番 + fio->Fclose(); + delete fio; + return NULL; + } + + // A??.DAT以外にリンクされている場合はファイルを開き直す + if(disk_index != 1) { + tmp_name[0] = 'A' + disk_index - 1; + fio->Fclose(); + if(!fio->Fopen(tmp_name, FILEIO_READ_BINARY)) { + delete fio; + return NULL; + } + } + + // データ取得 + fio->Fseek(link_index * 2, FILEIO_SEEK_SET); + int start_sector = fio->Fgetc(); + start_sector |= fio->Fgetc() << 8; + int end_sector = fio->Fgetc(); + end_sector |= fio->Fgetc() << 8; + + if((*size = (end_sector - start_sector) * 256) == 0) { + // サイズ不正 + fio->Fclose(); + delete fio; + return NULL; + } + + uint8 *buffer = (uint8 *)malloc(*size); + fio->Fseek((start_sector - 1) * 256, FILEIO_SEEK_SET); + fio->Fread(buffer, 256, end_sector - start_sector); + + fio->Fclose(); + delete fio; + + return buffer; +} + +uint8* DRI::load_mda(uint32 crc32_a, uint32 crc32_b, int page, int* size) +{ + // データ取得 + const char* name = NULL; + + switch(crc32_a) { + case CRC32_BUNKASAI: // あぶない文化祭前夜 + name = "AMUS_AB.MDA"; + break; + case CRC32_CRESCENT: // クレセントムーンがぁる + name = "AMUS_CRS.MDA"; + break; + case CRC32_DPS: // D.P.S. - Dream Program System + name = "AMUS_DPS.MDA"; + break; + case CRC32_DPS_SG: // D.P.S. SG +// case CRC32_DPS_SG2: // D.P.S. SG set2 + case CRC32_DPS_SG3: // D.P.S. SG set2 + name = "AMUS_SG.MDA"; + break; + case CRC32_FUKEI: // 婦警さんVX + name = "AMUS_VX.MDA"; + break; + case CRC32_INTRUDER: // Intruder -桜屋敷の探索- + name = "AMUS_INT"; + break; + case CRC32_TENGU: // あぶないてんぐ伝説 + name = "AMUS_AT"; + break; + case CRC32_TOUSHIN_HINT: // 闘神都市 ヒントディスク + name = "AMUS_T1"; + break; + case CRC32_VAMPIRE: // Little Vampire + case CRC32_VAMPIRE_ENG: + name = "AMUS_LP2"; + break; + case CRC32_YAKATA: // ALICEの館 + name = "AMUS_AL1"; + break; + + case CRC32_AYUMI_FD: // あゆみちゃん物語 (FD) + case CRC32_AYUMI_HINT: // あゆみちゃん物語 ヒントディスク + case CRC32_AYUMI_PROTO: // あゆみちゃん物語 PROTO + name = "AMUS_AYM"; + break; + case CRC32_DALK_HINT: // DALK ヒントディスク + name = "AMUS_DLK"; + break; + case CRC32_DRSTOP: // Dr. STOP! + name = "AMUS_DRS"; + break; + case CRC32_PROSTUDENTG_FD: // Prostudent -G- (FD) + name = "AMUS_PSG"; + break; + case CRC32_RANCE3_HINT: // Rance3 ヒントディスク + name = "AMUS_R3H"; + break; + case CRC32_SDPS: // Super D.P.S + name = "AMUS_SDP"; + break; + case CRC32_YAKATA2: // ALICEの館II + name = "AMUS_AL2"; + break; + + case CRC32_AMBIVALENZ_FD: // AmbivalenZ (FD) + case CRC32_AMBIVALENZ_CD: // AmbivalenZ (CD) + name = "AMUS_AMB.MDA"; + break; + case CRC32_DPSALL: // DPS全部 + name = "AMUS_ALL.MDA"; + break; + case CRC32_FUNNYBEE_CD: // Funny Bee (CD) +// case CRC32_FUNNYBEE_PATCH: // Funny Bee (CD + Patch) + case CRC32_FUNNYBEE_FD: // Funny Bee (FD) + name = "AMUS_BEE.MDA"; + break; + case CRC32_ONLYYOU: // Only You + case CRC32_ONLYYOU_DEMO: // Only You (DEMO) + name = "AMUS_OY.MDA"; + break; + case CRC32_PROSTUDENTG_CD: // Prostudent -G- (CD) + name = "AMUS_PSG.MDA"; + break; + case CRC32_RANCE41: // Rance 4.1 + case CRC32_RANCE41_ENG: + name = "AMUS_R41.MDA"; + break; + case CRC32_RANCE42: // Rance 4.2 + case CRC32_RANCE42_ENG: + name = "AMUS_R42.MDA"; + break; + case CRC32_AYUMI_CD: // あゆみちゃん物語 (CD) + case CRC32_AYUMI_JISSHA_256: // あゆみちゃん物語 実写版 + case CRC32_AYUMI_JISSHA_FULL: // あゆみちゃん物語 フルカラー実写版 + name = "AMUS_AYM.MDA"; + break; + case CRC32_YAKATA3_CD: // アリスの館3 (CD) + case CRC32_YAKATA3_FD: // アリスの館3 (FD) + name = "AMUS_AL3.MDA"; + break; + case CRC32_HASHIRIONNA2: // 走り女2 (Rance 4.x ヒントディスク) + name = "AMUS_RG2.MDA"; + break; + case CRC32_TOUSHIN2_GD: // 闘神都市2 グラフィックディスク + name = "AMUS_T2"; + break; + case CRC32_OTOMESENKI: // 乙女戦記 + name = "AMUS_OTM.MDA"; + break; + case CRC32_MUGENHOUYOU: // 夢幻泡影 + name = "AMUS_MGN.MDA"; + break; + } + + if(name == NULL) { + return NULL; + } + + SDL_RWops* rw = open_resource(name, "mda"); + if (!rw) + return NULL; + uint8 buf[4]; + + // ページの位置を取得 + SDL_RWread(rw, buf, 4, 1); + int link_sector = buf[0] | (buf[1] << 8); + int data_sector = buf[2] | (buf[3] << 8); + + if(page > (data_sector - link_sector) * 128 - 1) { + // ページ番号不正 + SDL_RWclose(rw); + return NULL; + } + + SDL_RWseek(rw, (link_sector - 1) * 256 + (page - 1) * 2, RW_SEEK_SET); + SDL_RWread(rw, buf, 2, 1); + + int disk_index = buf[0]; + int link_index = buf[1]; + + if(disk_index == 0 || disk_index == 0x1a) { + // 欠番 + SDL_RWclose(rw); + return NULL; + } + + // AMUS.MDA以外にリンクされている場合はリソースを開き直す + if(disk_index == 2) { + SDL_RWclose(rw); + switch(crc32_b) { + case CRC32_DPS_SG_FAHREN: // D.P.S. SG - Fahren Fliegen + name = "BMUS_FAH"; + break; + case CRC32_DPS_SG_KATEI: // D.P.S. SG - 家庭教師はステキなお仕事 + name = "BMUS_KAT"; + break; + case CRC32_DPS_SG_NOBUNAGA: // D.P.S. SG - 信長の淫謀 + name = "BMUS_NOB"; + break; + case CRC32_DPS_SG2_ANTIQUE: // D.P.S. SG set2 - ANTIQUE HOUSE + name = "BMUS_ANT"; + break; + case CRC32_DPS_SG2_IKENAI: // D.P.S. SG set2 - いけない内科検診再び + name = "BMUS_NAI"; + break; + case CRC32_DPS_SG2_AKAI: // D.P.S. SG set2 - 朱い夜 + name = "BMUS_AKA"; + break; + case CRC32_DPS_SG3_RABBIT: // D.P.S. SG set3 - Rabbit P4P + name = "BMUS_RAB"; + break; + case CRC32_DPS_SG3_SHINKON: // D.P.S. SG set3 - しんこんさんものがたり + name = "BMUS_SIN"; + break; + case CRC32_DPS_SG3_SOTSUGYOU: // D.P.S. SG set3 - 卒業 + name = "BMUS_SOT"; + break; + case CRC32_SDPS_MARIA: // Super D.P.S - マリアとカンパン + name = "BMUS_MTK"; + break; + case CRC32_SDPS_TONO: // Super D.P.S - 遠野の森 + name = "BMUS_TNM"; + break; + case CRC32_SDPS_KAIZOKU: // Super D.P.S - うれしたのし海賊稼業 + name = "BMUS_KAM"; + break; + default: + name = NULL; + break; + } + if(name == NULL) { + return NULL; + } + if((rw = open_resource(name, "mda")) == NULL) { + return NULL; + } + } else if(disk_index == 3) { + SDL_RWclose(rw); + switch(crc32_a) { + case CRC32_TOUSHIN_HINT: // 闘神都市 ヒントディスク + name = "CMUS_T1"; + break; + default: + name = NULL; + break; + } + if(name == NULL) { + return NULL; + } + if((rw = open_resource(name, "mda")) == NULL) { + return NULL; + } + } else if(disk_index != 1) { + // AMUS.MDA以外にリンクされている場合は失敗 + SDL_RWclose(rw); + return NULL; + } + + // データ取得 + SDL_RWseek(rw, link_index * 2, RW_SEEK_SET); + SDL_RWread(rw, buf, 4, 1); + int start_sector = buf[0] | (buf[1] << 8); + int end_sector = buf[2] | (buf[3] << 8); + + if((*size = (end_sector - start_sector) * 256) == 0) { + // サイズ不正 + SDL_RWclose(rw); + return NULL; + } + uint8* buffer = (uint8*)malloc(*size); + SDL_RWseek(rw, (start_sector - 1) * 256, RW_SEEK_SET); + SDL_RWread(rw, buffer, *size, 1); + + SDL_RWclose(rw); + + return buffer; +} diff --git a/src/sys/dri.h b/src/sys/dri.h index 473b910..efe8725 100644 --- a/src/sys/dri.h +++ b/src/sys/dri.h @@ -1,22 +1,22 @@ -/* - ALICE SOFT SYSTEM 3 for Win32 - - [ DRI ] -*/ - -#ifndef _DRI_H_ -#define _DRI_H_ - -#include "../common.h" - -class DRI -{ -public: - DRI() {} - ~DRI() {} - - uint8* load(const char* file_name, int page, int* size); - uint8* load_mda(uint32 crc32_a, uint32 crc32_b, int page, int* size); -}; - -#endif +/* + ALICE SOFT SYSTEM 3 for Win32 + + [ DRI ] +*/ + +#ifndef _DRI_H_ +#define _DRI_H_ + +#include "../common.h" + +class DRI +{ +public: + DRI() {} + ~DRI() {} + + uint8* load(const char* file_name, int page, int* size); + uint8* load_mda(uint32 crc32_a, uint32 crc32_b, int page, int* size); +}; + +#endif diff --git a/src/sys/mako.h b/src/sys/mako.h index 708a99d..9da8ef3 100644 --- a/src/sys/mako.h +++ b/src/sys/mako.h @@ -1,70 +1,70 @@ -/* - ALICE SOFT SYSTEM 3 for Win32 - - [ MAKO ] -*/ - -#ifndef _MAKO_H_ -#define _MAKO_H_ - -#include -#include -#include -#include -#include "../common.h" -#include "nact.h" - -enum BGMDevice { - BGM_FM, - BGM_MIDI, - BGM_CD -}; - -struct Config; - -class MAKO -{ -public: - MAKO(NACT* parent, const Config& config); - ~MAKO(); - - void play_music(int page); - void stop_music(); - bool check_music(); - void get_mark(int* mark, int* loop); - - void play_pcm(int page, bool loop); - void stop_pcm(); - bool check_pcm(); - - void set_cd_track(int num, int track) { cd_track[num] = track; } - -#ifdef _WIN32 - void select_sound(BGMDevice dev); - void on_mci_notify(const SDL_SysWMmsg* msg); -#endif -#if defined(__ANDROID__) - void select_synthesizer(bool use_fm); -#endif - - bool use_fm; - - // AMUS.DAT, AMSE.DAT - char amus[16]; - char amse[16]; - - int current_music; - int next_loop; // Y19 - -private: - NACT* nact; - int cd_track[100]; // Z - -#if !defined(__EMSCRIPTEN__) && !defined(__ANDROID__) - bool load_playlist(const char* path); - - std::vector playlist; -#endif -}; - -#endif +/* + ALICE SOFT SYSTEM 3 for Win32 + + [ MAKO ] +*/ + +#ifndef _MAKO_H_ +#define _MAKO_H_ + +#include +#include +#include +#include +#include "../common.h" +#include "nact.h" + +enum BGMDevice { + BGM_FM, + BGM_MIDI, + BGM_CD +}; + +struct Config; + +class MAKO +{ +public: + MAKO(NACT* parent, const Config& config); + ~MAKO(); + + void play_music(int page); + void stop_music(); + bool check_music(); + void get_mark(int* mark, int* loop); + + void play_pcm(int page, bool loop); + void stop_pcm(); + bool check_pcm(); + + void set_cd_track(int num, int track) { cd_track[num] = track; } + +#ifdef _WIN32 + void select_sound(BGMDevice dev); + void on_mci_notify(const SDL_SysWMmsg* msg); +#endif +#if defined(__ANDROID__) + void select_synthesizer(bool use_fm); +#endif + + bool use_fm; + + // AMUS.DAT, AMSE.DAT + char amus[16]; + char amse[16]; + + int current_music; + int next_loop; // Y19 + +private: + NACT* nact; + int cd_track[100]; // Z + +#if !defined(__EMSCRIPTEN__) && !defined(__ANDROID__) + bool load_playlist(const char* path); + + std::vector playlist; +#endif +}; + +#endif diff --git a/src/sys/mako_midi.cpp b/src/sys/mako_midi.cpp index 1503891..06de9b8 100644 --- a/src/sys/mako_midi.cpp +++ b/src/sys/mako_midi.cpp @@ -1,622 +1,622 @@ -/* - ALICE SOFT SYSTEM 3 for Win32 - - [ MAKO - midi ] -*/ - -#include "mako_midi.h" -#include "nact.h" -#include "dri.h" -#include "crc32.h" - -#define next_mml(p) mml[p].data[mml[p].addr++] - -namespace { - -// MIDI playing status -struct Play { - int timbre; - int timbre_type; - int level; - int reverb; - int chorus; - int pan; - int key_shift; - int velocity; - int channel; - int note; - int loop_cnt; - int wait_time; - bool loop_flag; - bool note_flag; -}; - -// Standard MIDI File header, where 1 time unit is 10 milliseconds. -const uint8 smf_header[] = { - 0x4d, 0x54, 0x68, 0x64, // "MThd" - 0x00, 0x00, 0x00, 0x06, // Header length - 0x00, 0x00, // Format - 0x00, 0x01, // Number of tracks - 0x00, 0x32, // Division (50 ticks per beat) - 0x4d, 0x54, 0x72, 0x6b, // "MTrk" - 0x00, 0x00, 0x00, 0x00, // Track length (to be filled later) - 0x00, 0xff, 0x51, 0x03, 0x07, 0xa1, 0x20 // Tempo (120 BPM) -}; -const size_t TRACK_LENGTH_OFFSET = 18; - -const int FADEOUT_DURATION = 100; // 1 second -const int MINIMUM_MUSIC_DURATION = 6000; // 60 seconds - -class SmfWriter { -public: - SmfWriter() : - dt(0), total_ticks(0), fadeout_start(-1), - buf(smf_header, smf_header + sizeof(smf_header)) { - for (int i = 0; i < 16; i++) - volume[i] = -1; - } - - std::vector get_smf() { - // "End of track" event - buf.push_back(0x00); - buf.push_back(0xFF); - buf.push_back(0x2F); - buf.push_back(0x00); - - size_t length = buf.size() - (TRACK_LENGTH_OFFSET + 4); - buf[TRACK_LENGTH_OFFSET] = length >> 24 & 0xff; - buf[TRACK_LENGTH_OFFSET + 1] = length >> 16 & 0xff; - buf[TRACK_LENGTH_OFFSET + 2] = length >> 8 & 0xff; - buf[TRACK_LENGTH_OFFSET + 3] = length & 0xff; - - NOTICE("Generated %d seconds of MIDI data", total_ticks / 100); - - return std::move(buf); - } - - bool tick() { - dt++; - total_ticks++; - return fadeout_start < 0 || total_ticks < fadeout_start + FADEOUT_DURATION; - } - - void start_fadeout() { - if (fadeout_start < 0 && total_ticks >= MINIMUM_MUSIC_DURATION) - fadeout_start = total_ticks; - } - - void send_2bytes(uint8 d1, uint8 d2) { - write_delta_time(); - buf.push_back(d1); - buf.push_back(d2); - } - - void send_3bytes(uint8 d1, uint8 d2, uint8 d3) { - write_delta_time(); - buf.push_back(d1); - buf.push_back(d2); - buf.push_back(d3); - } - - void set_volume(uint8 ch, uint8 level) { - volume[ch] = level; - send_3bytes(0xb0 + ch, 0x07, fade(level)); - } - - void update_fader() { - if (fadeout_start < 0) - return; - for (int ch = 0; ch < 16; ch++) { - if (volume[ch] < 0) - continue; - send_3bytes(0xb0 + ch, 0x07, fade(volume[ch])); - } - } - -private: - void write_delta_time() { - if (dt < 0x80) { - buf.push_back(dt); - } else if (dt < 0x4000) { - buf.push_back((dt >> 7) | 0x80); - buf.push_back(dt & 0x7f); - } else if (dt < 0x200000) { - buf.push_back((dt >> 14) | 0x80); - buf.push_back((dt >> 7 & 0x7f) | 0x80); - buf.push_back(dt & 0x7f); - } else { - buf.push_back((dt >> 21) | 0x80); - buf.push_back((dt >> 14 & 0x7f) | 0x80); - buf.push_back((dt >> 7 & 0x7f) | 0x80); - buf.push_back(dt & 0x7f); - } - dt = 0; - } - - int fade(int level) { - if (fadeout_start < 0) - return level; - return level * (fadeout_start + FADEOUT_DURATION - total_ticks) / FADEOUT_DURATION; - } - - std::vector buf; - int dt; - int total_ticks; - int fadeout_start; - int16 volume[16]; -}; - -} // namespace - -std::vector MAKOMidi::generate_smf(int num_loops) -{ - SmfWriter w; - Play play[9]; - - for(int i = 0; i < 9; i++) { - play[i].loop_flag = true; - } - bool mute_flag = false; - - // 再生情報の初期化 - for(int i = 0; i < 9; i++) { - play[i].timbre = 255; - play[i].timbre_type = 128; - play[i].level = 255; - play[i].reverb = 255; - play[i].chorus = 255; - play[i].key_shift = 64; - play[i].pan = 255; - - play[i].channel = i; - play[i].velocity = 120; - play[i].note = 128; - - play[i].note_flag = false; - play[i].loop_cnt = 0; - play[i].wait_time = 16; - mml[i].addr = 0; - } - - for(int i = 0; i < 3; i++) { - play[i + 3].timbre = i + 256; - if(mda[i + 256].bank_select < 128) { - play[i + 3].timbre_type = 128; - play[i + 3].channel = i + 3; - } else { - play[i + 3].timbre_type = 255 - mda[i + 256].bank_select; - play[i + 3].channel = 9; - } - play[i + 3].level = mda[i + 256].level; - play[i + 3].reverb = mda[i + 256].reverb; - play[i + 3].chorus = mda[i + 256].chorus; - play[i + 3].key_shift = mda[i + 256].key_shift; - play[i + 3].pan = mda[i + 256].pan; - } - - // システムリセット、ボリュームリセット - for(int i = 0; i < 10; i++) { - w.send_3bytes(0xb0 + i, 0x79, 0x00); - } - for(int i = 0; i < 10; i++) { - w.set_volume(i, 0x64); - } - - // SSG 1-3 の音色 - for(int i = 0; i < 3; i++) { - if(mda[i + 256].bank_select < 128) { - w.send_3bytes(0xb3 + i, 0x00, mda[i + 256].bank_select); - w.send_3bytes(0xb3 + i, 0x20, 0x00); - w.send_2bytes(0xc3 + i, mda[i + 256].program_change); - w.set_volume(3 + i, mda[i + 256].level); - w.send_3bytes(0xb3 + i, 0x5b, mda[i + 256].reverb); - w.send_3bytes(0xb3 + i, 0x5d, mda[i + 256].chorus); - w.send_3bytes(0xb3 + i, 0x0a, mda[i + 256].pan); - } else { - w.set_volume(9, mda[i + 256].level); - w.send_3bytes(0xb9, 0x5b, mda[i + 256].reverb); - w.send_3bytes(0xb9, 0x5d, mda[i + 256].chorus); - w.send_3bytes(0xb9, 0x0a, mda[i + 256].pan); - } - } - - float play_time = 0; - int current_loop = 0; - int current_mark = 0; - while (w.tick()) { - play_time += 10; // elapse 10ms - // 各パートの更新 - while((play[0].loop_flag || play[1].loop_flag || play[2].loop_flag || - play[3].loop_flag || play[4].loop_flag || play[5].loop_flag || - play[6].loop_flag || play[7].loop_flag || play[8].loop_flag) && play_time > 0.0) { - // 1単位時間だけ経過時間を更新する - for(int i = 0; i < 9; i++) { - if(play[i].loop_flag && play[i].wait_time) { - play[i].wait_time--; - } - } - play_time -= (float)(545455.0 / 480.0 / (float)(tempo + 0x40 - tempo_dif)); - - // 1単位時間だけ各パートを更新 - for(int i = 0; i < 9; i++) { - if(!play[i].loop_flag) { - play[i].wait_time = 1; - } - while(play[i].wait_time == 0) { - int d0 = next_mml(i), d1, d2, d3; - if(d0 == 0xff) { - d1 = next_mml(i); - d2 = next_mml(i); - d3 = next_mml(i); - mml[i].addr = d1 | (d2 << 8) | (d3 << 16); - if(!play[i].note_flag || mute_flag) { - // 再生停止または未使用 - play[i].loop_flag = false; - if(!play[0].loop_flag && !play[1].loop_flag && !play[2].loop_flag && - !play[3].loop_flag && !play[4].loop_flag && !play[5].loop_flag && - !play[6].loop_flag && !play[7].loop_flag && !play[8].loop_flag) { - // 全チャンネルが再生停止 (ループしない曲) - goto finish; - } - play[i].wait_time = 1; - } else { - // 全体としてのループ数を取得 - int loop = ++play[i].loop_cnt; - for(int j = 0; j < 9; j++) { - if(loop > play[j].loop_cnt && play[j].loop_flag) { - loop = play[j].loop_cnt; - } - } - current_loop = loop; - if (num_loops) { - if (current_loop >= num_loops) - goto finish; - } else { - // Infinite loop mode: fade out after one playback. - if (current_loop > 0) - w.start_fadeout(); - } - } - } else if(d0 < 0x80) { - int note = d0; - play[i].wait_time = next_mml(i); - play[i].wait_time |= next_mml(i) << 8; - if(play[i].timbre_type != 128) { - note = drum_map[play[i].timbre_type][note]; - } else { - note = (note + play[i].key_shift) - 64; - } - play[i].note_flag = true; - play[i].note = note; - w.send_3bytes(0x90 + play[i].channel, note, play[i].velocity); - } else if(d0 == 0x80) { - play[i].wait_time = next_mml(i); - play[i].wait_time |= next_mml(i) << 8; - if(play[i].note != 128) { - w.send_3bytes(0x90 + play[i].channel, play[i].note, 0x00); - } - play[i].note = 128; - } else if(d0 == 0xe0) { - current_mark = next_mml(i); - } else if(d0 == 0xe1) { - d1 = next_mml(i); - play[i].velocity += (d1 > 127) ? (d1 - 256) : d1; - } else if(d0 == 0xeb) { - play[i].pan = next_mml(i); - w.send_3bytes(0xb0 + play[i].channel, 0x0a, play[i].pan); - } - else if(d0 == 0xec) { - if(!(nact->crc32_a == CRC32_DPS || nact->crc32_a == CRC32_DPS_SG || nact->crc32_a == CRC32_DPS_SG2 || nact->crc32_a == CRC32_DPS_SG3)) - mute_flag = true; - } - else if(d0 == 0xf5) { - int n = next_mml(i); - if(n != play[i].timbre) { - if(mda[n].bank_select < 128) { - // 通常のパート - play[i].timbre_type = 128; - play[i].channel = i; - w.send_3bytes(0xb0 + play[i].channel, 0x00, mda[n].bank_select); - w.send_3bytes(0xb0 + play[i].channel, 0x20, 0x00); - w.send_2bytes(0xc0 + play[i].channel, mda[n].program_change); - } else { - // ドラムパート (ch.10) - play[i].timbre_type = 255 - mda[n].bank_select; - play[i].channel = 9; - } - if(play[i].level != mda[n].level) { - w.set_volume(play[i].channel, mda[n].level); - } - if(play[i].reverb != mda[n].reverb) { - w.send_3bytes(0xb0 + play[i].channel, 0x5b, mda[n].reverb); - } - if(play[i].chorus != mda[n].chorus) { - w.send_3bytes(0xb0 + play[i].channel, 0x5d, mda[n].chorus); - } - if(play[i].pan != mda[n].pan) { - w.send_3bytes(0xb0 + play[i].channel, 0x0a, mda[n].pan); - } - } - play[i].timbre = n; - play[i].level = mda[n].level; - play[i].reverb = mda[n].reverb; - play[i].chorus = mda[n].chorus; - play[i].key_shift = mda[n].key_shift; - play[i].pan = mda[n].pan; - play[i].velocity = 120; - } else if(d0 == 0xf9) { - play[i].velocity = next_mml(i); - } else if(d0 == 0xfc) { - d1 = next_mml(i); - if(d1 > 127) { - d1 = 256 - d1; - d1 = 0x40 - (d1 > 63 ? 63 : d1); - } else { - d1 = 0x40 + (d1 > 63 ? 63 : d1); - } - w.send_3bytes(0xb0 + play[i].channel, 0x65, 0x00); - w.send_3bytes(0xb0 + play[i].channel, 0x64, 0x01); - w.send_3bytes(0xb0 + play[i].channel, 0x06, d1); - } - } - } - } - w.update_fader(); - } - finish: - for(int j = 0; j < 10; j++) { - w.send_3bytes(0xb0 + j, 0x78, 0x00); - } - for(int j = 0; j < 10; j++) { - w.send_3bytes(0xb0 + j, 0x79, 0x00); - } - return w.get_smf(); -} - -bool MAKOMidi::load_mml(int page) -{ - // データ読み込み - DRI* dri = new DRI(); - int size; - uint8* data = dri->load(amus, page, &size); - if(data == NULL) { - delete dri; - return false; - } - - // FM音源データの判定 - int p, d0, d1, d2; - - p = data[0] + 1; - if(data[p] != 0x0f || (data[p + 1] + data[p + 2] + data[p + 3] + data[p + 4] + data[p + 5]) != 0) { - free(data); - delete dri; - return false; - } - - // MML部 読み込み&変換 - for(int i = 0; i < 9; i++) { - p = 4 * (i + 1); - int block_offset_top = data[p++]; - block_offset_top |= data[p++] << 8; - int body_addr = 0; - mml[i].addr = 0; - - if(block_offset_top) { - // ブロックの探索 - int last_block = 0; - p = block_offset_top; - d0 = data[p++]; - d1 = data[p++]; - while(d1 != 0xff) { - last_block++; - d0 = data[p++]; - d1 = data[p++]; - } - int return_block = d0; - - uint16 base_octave = 4, current_octave = 4; - uint16 default_time = 48; - uint16 gate_step = 7, gate_time = 256; - uint16 time, on_time, off_time; - uint16 note; - - for(int j = 0; j < last_block; j++) { - if(j == return_block) { - body_addr = mml[i].addr; - } - p = block_offset_top + 2 * j; - int block_offset = data[p++]; - block_offset |= data[p++] << 8; - p = block_offset; - - while((d0 = data[p++]) != 0xff) { - if((0x00 <= d0 && d0 <= 0x0c) || (0x0d <= d0 && d0 <= 0x19) || (0x80 <= d0 && d0 <=0x8c)) { - if(0x00 <= d0 && d0 <= 0x0c) { - time = data[p++]; - note = d0; - } else if(0x0d <= d0 && d0 <= 0x19) { - time = data[p++]; - time |= data[p++] << 8; - note = d0 - 0x0d; - } else { - time = default_time; - note = d0 - 0x80; - } - if((d0 = data[p]) == 0xe9) { - on_time = time; - off_time = 0; - p++; - } else { - if(gate_time != 256) { - if(time > gate_time) { - on_time = time - gate_time; - off_time = gate_time; - } else { - on_time = 1; - off_time = time - 1; - } - } else { - if(time == 1) { - on_time = 1; - off_time = 0; - } else if(gate_step == 8) { - on_time = time -1 ; - off_time = 1; - } else if(time < 8) { - on_time = 1; - off_time = time - 1; - } else { - on_time = (time >> 3) * gate_step; - off_time = time - on_time; - } - } - } - if(note == 0) { - off_time = on_time + off_time; - on_time = 0; - } - if(on_time != 0) { - next_mml(i) = (note - 1) + 12 * (current_octave + 1); - next_mml(i) = on_time & 0xff; - next_mml(i) = on_time >> 8; - } - next_mml(i) = 0x80; - next_mml(i) = off_time & 0xff; - next_mml(i) = off_time >> 8; - if(current_octave != base_octave) { - current_octave = base_octave; - } - } else if(d0 == 0xe0 || d0 == 0xe1 || d0 == 0xeb || d0 == 0xf5 || d0 == 0xf9 || d0 == 0xfc) { - next_mml(i) = d0; - next_mml(i) = data[p++]; - } else if(d0 == 0xea) { - gate_time = data[p++]; - } else if(d0 == 0xec) { - next_mml(i) = d0; - } else if(d0 == 0xee) { - current_octave = ++base_octave; - } else if(d0 == 0xef) { - current_octave = --base_octave; - } else if(d0 == 0xf0) { - current_octave = base_octave = data[p++]; - } else if(d0 == 0xf2) { - gate_step = data[p++] + 1; - gate_time = 256; - } else if(d0 == 0xf3) { - d1 = data[p++]; - if(d1 >= 0x80) { - d2 = data[p++]; - default_time = ((d1 - 0x80) << 8) | d2; - } else { - default_time = d1; - } - } else if(d0 == 0xf4) { - tempo = data[p++]; - } else if(d0 == 0xf7) { - current_octave--; - } else if(d0 == 0xf8) { - current_octave++; - } else if(d0 == 0xe9) { - ; // Tie Command - } else if(d0 == 0xe5 || d0 == 0xf1 || d0 == 0xfa || d0 == 0xfd) { - p++; - } else if(d0 == 0xf6 || d0 == 0xfb) { - p += 2; - } else if(d0 == 0xe4 || d0 == 0xfe) { - p += 3; - } else if(d0 == 0xe6 || d0 == 0xe7) { - p += 8; - } else if(d0 == 0xe8) { - p += 10; - } - } - } - } - next_mml(i) = 0xff; - next_mml(i) = (body_addr >> 0) & 0xff; - next_mml(i) = (body_addr >> 8) & 0xff; - next_mml(i) = (body_addr >> 16) & 0xff; - } - free(data); - delete dri; - return true; -} - -void MAKOMidi::load_mda(int page) -{ - // 未設定時の音色設定 (Piano, Acoustic Bass Drum) - for(int i = 0; i < 256 + 3; i++) { - mda[i].bank_select = 0; - mda[i].program_change = 0; - mda[i].level = 100; - mda[i].reverb = 40; - mda[i].chorus = 40; - mda[i].key_shift = 64; - mda[i].pan = 64; - } - for(int i = 0; i < 8; i++) { - for(int j = 0; j < 128; j++) { - drum_map[i][j] = 35; - } - } - tempo_dif = 0x40; - - // MDAデータの読み込み - char path[16]; - strcpy_s(path, 16, amus); - strcpy(path + strlen(path) - 3, "MDA"); - - DRI* dri = new DRI(); - int size; - uint8* data = NULL; - if((data = dri->load(path, page, &size)) == NULL) { - data = dri->load_mda(nact->crc32_a, nact->crc32_b, page, &size); - } - - if(data) { - tempo_dif = data[7]; - int map_wide = data[24]; - int inst_num = data[25]; - int drum_format = data[26]; - - // SSGパートの音色設定 - for(int i = 0; i < 3; i++) { - uint8* buf = &data[map_wide * i + 27]; - mda[i + 256].bank_select = buf[0]; - mda[i + 256].program_change = buf[1]; - mda[i + 256].level = buf[2]; - mda[i + 256].reverb = buf[3]; - mda[i + 256].chorus = buf[4]; - mda[i + 256].key_shift = buf[5]; - mda[i + 256].pan = buf[6]; - } - - // 通常の音色設定 - for(int i = 0; i < inst_num; i++) { - uint8* buf = &data[27 + map_wide * 3 + (map_wide + 1) * i]; - int n = buf[0]; - mda[n].bank_select = buf[1]; - mda[n].program_change = buf[2]; - mda[n].level = buf[3]; - mda[n].reverb = buf[4]; - mda[n].chorus = buf[5]; - mda[n].key_shift = buf[6]; - mda[n].pan = buf[7]; - } - - // ドラムパートの音色設定 - if(drum_format) { - uint8* buf = &data[27 + map_wide * 3 + (map_wide + 1) * inst_num]; - int drum_num = buf[0]; - for(int i = 0; i < drum_num; i++) { - int d = buf[i * 3 + 1]; - int t = buf[i * 3 + 2]; - drum_map[d][t + 12] = buf[i * 3 + 3]; - } - } - free(data); - } - delete dri; -} - +/* + ALICE SOFT SYSTEM 3 for Win32 + + [ MAKO - midi ] +*/ + +#include "mako_midi.h" +#include "nact.h" +#include "dri.h" +#include "crc32.h" + +#define next_mml(p) mml[p].data[mml[p].addr++] + +namespace { + +// MIDI playing status +struct Play { + int timbre; + int timbre_type; + int level; + int reverb; + int chorus; + int pan; + int key_shift; + int velocity; + int channel; + int note; + int loop_cnt; + int wait_time; + bool loop_flag; + bool note_flag; +}; + +// Standard MIDI File header, where 1 time unit is 10 milliseconds. +const uint8 smf_header[] = { + 0x4d, 0x54, 0x68, 0x64, // "MThd" + 0x00, 0x00, 0x00, 0x06, // Header length + 0x00, 0x00, // Format + 0x00, 0x01, // Number of tracks + 0x00, 0x32, // Division (50 ticks per beat) + 0x4d, 0x54, 0x72, 0x6b, // "MTrk" + 0x00, 0x00, 0x00, 0x00, // Track length (to be filled later) + 0x00, 0xff, 0x51, 0x03, 0x07, 0xa1, 0x20 // Tempo (120 BPM) +}; +const size_t TRACK_LENGTH_OFFSET = 18; + +const int FADEOUT_DURATION = 100; // 1 second +const int MINIMUM_MUSIC_DURATION = 6000; // 60 seconds + +class SmfWriter { +public: + SmfWriter() : + dt(0), total_ticks(0), fadeout_start(-1), + buf(smf_header, smf_header + sizeof(smf_header)) { + for (int i = 0; i < 16; i++) + volume[i] = -1; + } + + std::vector get_smf() { + // "End of track" event + buf.push_back(0x00); + buf.push_back(0xFF); + buf.push_back(0x2F); + buf.push_back(0x00); + + size_t length = buf.size() - (TRACK_LENGTH_OFFSET + 4); + buf[TRACK_LENGTH_OFFSET] = length >> 24 & 0xff; + buf[TRACK_LENGTH_OFFSET + 1] = length >> 16 & 0xff; + buf[TRACK_LENGTH_OFFSET + 2] = length >> 8 & 0xff; + buf[TRACK_LENGTH_OFFSET + 3] = length & 0xff; + + NOTICE("Generated %d seconds of MIDI data", total_ticks / 100); + + return std::move(buf); + } + + bool tick() { + dt++; + total_ticks++; + return fadeout_start < 0 || total_ticks < fadeout_start + FADEOUT_DURATION; + } + + void start_fadeout() { + if (fadeout_start < 0 && total_ticks >= MINIMUM_MUSIC_DURATION) + fadeout_start = total_ticks; + } + + void send_2bytes(uint8 d1, uint8 d2) { + write_delta_time(); + buf.push_back(d1); + buf.push_back(d2); + } + + void send_3bytes(uint8 d1, uint8 d2, uint8 d3) { + write_delta_time(); + buf.push_back(d1); + buf.push_back(d2); + buf.push_back(d3); + } + + void set_volume(uint8 ch, uint8 level) { + volume[ch] = level; + send_3bytes(0xb0 + ch, 0x07, fade(level)); + } + + void update_fader() { + if (fadeout_start < 0) + return; + for (int ch = 0; ch < 16; ch++) { + if (volume[ch] < 0) + continue; + send_3bytes(0xb0 + ch, 0x07, fade(volume[ch])); + } + } + +private: + void write_delta_time() { + if (dt < 0x80) { + buf.push_back(dt); + } else if (dt < 0x4000) { + buf.push_back((dt >> 7) | 0x80); + buf.push_back(dt & 0x7f); + } else if (dt < 0x200000) { + buf.push_back((dt >> 14) | 0x80); + buf.push_back((dt >> 7 & 0x7f) | 0x80); + buf.push_back(dt & 0x7f); + } else { + buf.push_back((dt >> 21) | 0x80); + buf.push_back((dt >> 14 & 0x7f) | 0x80); + buf.push_back((dt >> 7 & 0x7f) | 0x80); + buf.push_back(dt & 0x7f); + } + dt = 0; + } + + int fade(int level) { + if (fadeout_start < 0) + return level; + return level * (fadeout_start + FADEOUT_DURATION - total_ticks) / FADEOUT_DURATION; + } + + std::vector buf; + int dt; + int total_ticks; + int fadeout_start; + int16 volume[16]; +}; + +} // namespace + +std::vector MAKOMidi::generate_smf(int num_loops) +{ + SmfWriter w; + Play play[9]; + + for(int i = 0; i < 9; i++) { + play[i].loop_flag = true; + } + bool mute_flag = false; + + // 再生情報の初期化 + for(int i = 0; i < 9; i++) { + play[i].timbre = 255; + play[i].timbre_type = 128; + play[i].level = 255; + play[i].reverb = 255; + play[i].chorus = 255; + play[i].key_shift = 64; + play[i].pan = 255; + + play[i].channel = i; + play[i].velocity = 120; + play[i].note = 128; + + play[i].note_flag = false; + play[i].loop_cnt = 0; + play[i].wait_time = 16; + mml[i].addr = 0; + } + + for(int i = 0; i < 3; i++) { + play[i + 3].timbre = i + 256; + if(mda[i + 256].bank_select < 128) { + play[i + 3].timbre_type = 128; + play[i + 3].channel = i + 3; + } else { + play[i + 3].timbre_type = 255 - mda[i + 256].bank_select; + play[i + 3].channel = 9; + } + play[i + 3].level = mda[i + 256].level; + play[i + 3].reverb = mda[i + 256].reverb; + play[i + 3].chorus = mda[i + 256].chorus; + play[i + 3].key_shift = mda[i + 256].key_shift; + play[i + 3].pan = mda[i + 256].pan; + } + + // システムリセット、ボリュームリセット + for(int i = 0; i < 10; i++) { + w.send_3bytes(0xb0 + i, 0x79, 0x00); + } + for(int i = 0; i < 10; i++) { + w.set_volume(i, 0x64); + } + + // SSG 1-3 の音色 + for(int i = 0; i < 3; i++) { + if(mda[i + 256].bank_select < 128) { + w.send_3bytes(0xb3 + i, 0x00, mda[i + 256].bank_select); + w.send_3bytes(0xb3 + i, 0x20, 0x00); + w.send_2bytes(0xc3 + i, mda[i + 256].program_change); + w.set_volume(3 + i, mda[i + 256].level); + w.send_3bytes(0xb3 + i, 0x5b, mda[i + 256].reverb); + w.send_3bytes(0xb3 + i, 0x5d, mda[i + 256].chorus); + w.send_3bytes(0xb3 + i, 0x0a, mda[i + 256].pan); + } else { + w.set_volume(9, mda[i + 256].level); + w.send_3bytes(0xb9, 0x5b, mda[i + 256].reverb); + w.send_3bytes(0xb9, 0x5d, mda[i + 256].chorus); + w.send_3bytes(0xb9, 0x0a, mda[i + 256].pan); + } + } + + float play_time = 0; + int current_loop = 0; + int current_mark = 0; + while (w.tick()) { + play_time += 10; // elapse 10ms + // 各パートの更新 + while((play[0].loop_flag || play[1].loop_flag || play[2].loop_flag || + play[3].loop_flag || play[4].loop_flag || play[5].loop_flag || + play[6].loop_flag || play[7].loop_flag || play[8].loop_flag) && play_time > 0.0) { + // 1単位時間だけ経過時間を更新する + for(int i = 0; i < 9; i++) { + if(play[i].loop_flag && play[i].wait_time) { + play[i].wait_time--; + } + } + play_time -= (float)(545455.0 / 480.0 / (float)(tempo + 0x40 - tempo_dif)); + + // 1単位時間だけ各パートを更新 + for(int i = 0; i < 9; i++) { + if(!play[i].loop_flag) { + play[i].wait_time = 1; + } + while(play[i].wait_time == 0) { + int d0 = next_mml(i), d1, d2, d3; + if(d0 == 0xff) { + d1 = next_mml(i); + d2 = next_mml(i); + d3 = next_mml(i); + mml[i].addr = d1 | (d2 << 8) | (d3 << 16); + if(!play[i].note_flag || mute_flag) { + // 再生停止または未使用 + play[i].loop_flag = false; + if(!play[0].loop_flag && !play[1].loop_flag && !play[2].loop_flag && + !play[3].loop_flag && !play[4].loop_flag && !play[5].loop_flag && + !play[6].loop_flag && !play[7].loop_flag && !play[8].loop_flag) { + // 全チャンネルが再生停止 (ループしない曲) + goto finish; + } + play[i].wait_time = 1; + } else { + // 全体としてのループ数を取得 + int loop = ++play[i].loop_cnt; + for(int j = 0; j < 9; j++) { + if(loop > play[j].loop_cnt && play[j].loop_flag) { + loop = play[j].loop_cnt; + } + } + current_loop = loop; + if (num_loops) { + if (current_loop >= num_loops) + goto finish; + } else { + // Infinite loop mode: fade out after one playback. + if (current_loop > 0) + w.start_fadeout(); + } + } + } else if(d0 < 0x80) { + int note = d0; + play[i].wait_time = next_mml(i); + play[i].wait_time |= next_mml(i) << 8; + if(play[i].timbre_type != 128) { + note = drum_map[play[i].timbre_type][note]; + } else { + note = (note + play[i].key_shift) - 64; + } + play[i].note_flag = true; + play[i].note = note; + w.send_3bytes(0x90 + play[i].channel, note, play[i].velocity); + } else if(d0 == 0x80) { + play[i].wait_time = next_mml(i); + play[i].wait_time |= next_mml(i) << 8; + if(play[i].note != 128) { + w.send_3bytes(0x90 + play[i].channel, play[i].note, 0x00); + } + play[i].note = 128; + } else if(d0 == 0xe0) { + current_mark = next_mml(i); + } else if(d0 == 0xe1) { + d1 = next_mml(i); + play[i].velocity += (d1 > 127) ? (d1 - 256) : d1; + } else if(d0 == 0xeb) { + play[i].pan = next_mml(i); + w.send_3bytes(0xb0 + play[i].channel, 0x0a, play[i].pan); + } + else if(d0 == 0xec) { + if(!(nact->crc32_a == CRC32_DPS || nact->crc32_a == CRC32_DPS_SG || nact->crc32_a == CRC32_DPS_SG2 || nact->crc32_a == CRC32_DPS_SG3)) + mute_flag = true; + } + else if(d0 == 0xf5) { + int n = next_mml(i); + if(n != play[i].timbre) { + if(mda[n].bank_select < 128) { + // 通常のパート + play[i].timbre_type = 128; + play[i].channel = i; + w.send_3bytes(0xb0 + play[i].channel, 0x00, mda[n].bank_select); + w.send_3bytes(0xb0 + play[i].channel, 0x20, 0x00); + w.send_2bytes(0xc0 + play[i].channel, mda[n].program_change); + } else { + // ドラムパート (ch.10) + play[i].timbre_type = 255 - mda[n].bank_select; + play[i].channel = 9; + } + if(play[i].level != mda[n].level) { + w.set_volume(play[i].channel, mda[n].level); + } + if(play[i].reverb != mda[n].reverb) { + w.send_3bytes(0xb0 + play[i].channel, 0x5b, mda[n].reverb); + } + if(play[i].chorus != mda[n].chorus) { + w.send_3bytes(0xb0 + play[i].channel, 0x5d, mda[n].chorus); + } + if(play[i].pan != mda[n].pan) { + w.send_3bytes(0xb0 + play[i].channel, 0x0a, mda[n].pan); + } + } + play[i].timbre = n; + play[i].level = mda[n].level; + play[i].reverb = mda[n].reverb; + play[i].chorus = mda[n].chorus; + play[i].key_shift = mda[n].key_shift; + play[i].pan = mda[n].pan; + play[i].velocity = 120; + } else if(d0 == 0xf9) { + play[i].velocity = next_mml(i); + } else if(d0 == 0xfc) { + d1 = next_mml(i); + if(d1 > 127) { + d1 = 256 - d1; + d1 = 0x40 - (d1 > 63 ? 63 : d1); + } else { + d1 = 0x40 + (d1 > 63 ? 63 : d1); + } + w.send_3bytes(0xb0 + play[i].channel, 0x65, 0x00); + w.send_3bytes(0xb0 + play[i].channel, 0x64, 0x01); + w.send_3bytes(0xb0 + play[i].channel, 0x06, d1); + } + } + } + } + w.update_fader(); + } + finish: + for(int j = 0; j < 10; j++) { + w.send_3bytes(0xb0 + j, 0x78, 0x00); + } + for(int j = 0; j < 10; j++) { + w.send_3bytes(0xb0 + j, 0x79, 0x00); + } + return w.get_smf(); +} + +bool MAKOMidi::load_mml(int page) +{ + // データ読み込み + DRI* dri = new DRI(); + int size; + uint8* data = dri->load(amus, page, &size); + if(data == NULL) { + delete dri; + return false; + } + + // FM音源データの判定 + int p, d0, d1, d2; + + p = data[0] + 1; + if(data[p] != 0x0f || (data[p + 1] + data[p + 2] + data[p + 3] + data[p + 4] + data[p + 5]) != 0) { + free(data); + delete dri; + return false; + } + + // MML部 読み込み&変換 + for(int i = 0; i < 9; i++) { + p = 4 * (i + 1); + int block_offset_top = data[p++]; + block_offset_top |= data[p++] << 8; + int body_addr = 0; + mml[i].addr = 0; + + if(block_offset_top) { + // ブロックの探索 + int last_block = 0; + p = block_offset_top; + d0 = data[p++]; + d1 = data[p++]; + while(d1 != 0xff) { + last_block++; + d0 = data[p++]; + d1 = data[p++]; + } + int return_block = d0; + + uint16 base_octave = 4, current_octave = 4; + uint16 default_time = 48; + uint16 gate_step = 7, gate_time = 256; + uint16 time, on_time, off_time; + uint16 note; + + for(int j = 0; j < last_block; j++) { + if(j == return_block) { + body_addr = mml[i].addr; + } + p = block_offset_top + 2 * j; + int block_offset = data[p++]; + block_offset |= data[p++] << 8; + p = block_offset; + + while((d0 = data[p++]) != 0xff) { + if((0x00 <= d0 && d0 <= 0x0c) || (0x0d <= d0 && d0 <= 0x19) || (0x80 <= d0 && d0 <=0x8c)) { + if(0x00 <= d0 && d0 <= 0x0c) { + time = data[p++]; + note = d0; + } else if(0x0d <= d0 && d0 <= 0x19) { + time = data[p++]; + time |= data[p++] << 8; + note = d0 - 0x0d; + } else { + time = default_time; + note = d0 - 0x80; + } + if((d0 = data[p]) == 0xe9) { + on_time = time; + off_time = 0; + p++; + } else { + if(gate_time != 256) { + if(time > gate_time) { + on_time = time - gate_time; + off_time = gate_time; + } else { + on_time = 1; + off_time = time - 1; + } + } else { + if(time == 1) { + on_time = 1; + off_time = 0; + } else if(gate_step == 8) { + on_time = time -1 ; + off_time = 1; + } else if(time < 8) { + on_time = 1; + off_time = time - 1; + } else { + on_time = (time >> 3) * gate_step; + off_time = time - on_time; + } + } + } + if(note == 0) { + off_time = on_time + off_time; + on_time = 0; + } + if(on_time != 0) { + next_mml(i) = (note - 1) + 12 * (current_octave + 1); + next_mml(i) = on_time & 0xff; + next_mml(i) = on_time >> 8; + } + next_mml(i) = 0x80; + next_mml(i) = off_time & 0xff; + next_mml(i) = off_time >> 8; + if(current_octave != base_octave) { + current_octave = base_octave; + } + } else if(d0 == 0xe0 || d0 == 0xe1 || d0 == 0xeb || d0 == 0xf5 || d0 == 0xf9 || d0 == 0xfc) { + next_mml(i) = d0; + next_mml(i) = data[p++]; + } else if(d0 == 0xea) { + gate_time = data[p++]; + } else if(d0 == 0xec) { + next_mml(i) = d0; + } else if(d0 == 0xee) { + current_octave = ++base_octave; + } else if(d0 == 0xef) { + current_octave = --base_octave; + } else if(d0 == 0xf0) { + current_octave = base_octave = data[p++]; + } else if(d0 == 0xf2) { + gate_step = data[p++] + 1; + gate_time = 256; + } else if(d0 == 0xf3) { + d1 = data[p++]; + if(d1 >= 0x80) { + d2 = data[p++]; + default_time = ((d1 - 0x80) << 8) | d2; + } else { + default_time = d1; + } + } else if(d0 == 0xf4) { + tempo = data[p++]; + } else if(d0 == 0xf7) { + current_octave--; + } else if(d0 == 0xf8) { + current_octave++; + } else if(d0 == 0xe9) { + ; // Tie Command + } else if(d0 == 0xe5 || d0 == 0xf1 || d0 == 0xfa || d0 == 0xfd) { + p++; + } else if(d0 == 0xf6 || d0 == 0xfb) { + p += 2; + } else if(d0 == 0xe4 || d0 == 0xfe) { + p += 3; + } else if(d0 == 0xe6 || d0 == 0xe7) { + p += 8; + } else if(d0 == 0xe8) { + p += 10; + } + } + } + } + next_mml(i) = 0xff; + next_mml(i) = (body_addr >> 0) & 0xff; + next_mml(i) = (body_addr >> 8) & 0xff; + next_mml(i) = (body_addr >> 16) & 0xff; + } + free(data); + delete dri; + return true; +} + +void MAKOMidi::load_mda(int page) +{ + // 未設定時の音色設定 (Piano, Acoustic Bass Drum) + for(int i = 0; i < 256 + 3; i++) { + mda[i].bank_select = 0; + mda[i].program_change = 0; + mda[i].level = 100; + mda[i].reverb = 40; + mda[i].chorus = 40; + mda[i].key_shift = 64; + mda[i].pan = 64; + } + for(int i = 0; i < 8; i++) { + for(int j = 0; j < 128; j++) { + drum_map[i][j] = 35; + } + } + tempo_dif = 0x40; + + // MDAデータの読み込み + char path[16]; + strcpy_s(path, 16, amus); + strcpy(path + strlen(path) - 3, "MDA"); + + DRI* dri = new DRI(); + int size; + uint8* data = NULL; + if((data = dri->load(path, page, &size)) == NULL) { + data = dri->load_mda(nact->crc32_a, nact->crc32_b, page, &size); + } + + if(data) { + tempo_dif = data[7]; + int map_wide = data[24]; + int inst_num = data[25]; + int drum_format = data[26]; + + // SSGパートの音色設定 + for(int i = 0; i < 3; i++) { + uint8* buf = &data[map_wide * i + 27]; + mda[i + 256].bank_select = buf[0]; + mda[i + 256].program_change = buf[1]; + mda[i + 256].level = buf[2]; + mda[i + 256].reverb = buf[3]; + mda[i + 256].chorus = buf[4]; + mda[i + 256].key_shift = buf[5]; + mda[i + 256].pan = buf[6]; + } + + // 通常の音色設定 + for(int i = 0; i < inst_num; i++) { + uint8* buf = &data[27 + map_wide * 3 + (map_wide + 1) * i]; + int n = buf[0]; + mda[n].bank_select = buf[1]; + mda[n].program_change = buf[2]; + mda[n].level = buf[3]; + mda[n].reverb = buf[4]; + mda[n].chorus = buf[5]; + mda[n].key_shift = buf[6]; + mda[n].pan = buf[7]; + } + + // ドラムパートの音色設定 + if(drum_format) { + uint8* buf = &data[27 + map_wide * 3 + (map_wide + 1) * inst_num]; + int drum_num = buf[0]; + for(int i = 0; i < drum_num; i++) { + int d = buf[i * 3 + 1]; + int t = buf[i * 3 + 2]; + drum_map[d][t + 12] = buf[i * 3 + 3]; + } + } + free(data); + } + delete dri; +} + diff --git a/src/sys/nact.cpp b/src/sys/nact.cpp index 9142f49..4e7d532 100644 --- a/src/sys/nact.cpp +++ b/src/sys/nact.cpp @@ -1,573 +1,573 @@ -/* - ALICE SOFT SYSTEM 3 for Win32 - - [ NACT ] -*/ - -#include -#include "nact.h" -#include "encoding.h" -#include "ags.h" -#include "mako.h" -#include "msgskip.h" -#include "dri.h" -#include "../config.h" -#include "../fileio.h" -#include "crc32.h" - -extern SDL_Window* g_window; - -// 初期化 - -NACT::NACT(int sys_ver, uint32 crc32_a, uint32 crc32_b, const Config& config) - : sys_ver(sys_ver), - crc32_a(crc32_a), - crc32_b(crc32_b), - config(config), - encoding(Encoding::create(get_encoding_name())), - strings(config.get_strings(encoding.get(), get_language() == ENGLISH)) -{ - platform_initialize(); - - // AG00.DAT読み込み - FILEIO* fio = new FILEIO(); - if(fio->Fopen("AG00.DAT", FILEIO_READ_BINARY)) { - int d0, d1, d2, d3; - char string[MAX_CAPTION]; - fio->Fgets(string, MAX_CAPTION); - if (sscanf_s(string, "%d,%d,%d,%d", &d0, &d1, &d2, &d3) != 4) - fatal("AG00.DAT: parse error"); - for(int i = 0; i < d1; i++) { - // 動詞の読み込み - fio->Fgets(string, MAX_CAPTION); - memcpy(caption_verb[i], string, sizeof(string)); - } - for(int i = 0; i < d2; i++) { - // 目的語の読み込み - fio->Fgets(string, MAX_CAPTION); - memcpy(caption_obj[i], string, sizeof(string)); - } - fio->Fclose(); - } - delete fio; - - // ADISK.DAT - if (crc32_a == CRC32_PROG_OMAKE) - strcpy_s(adisk, 16, "AGAME.DAT"); - else - strcpy_s(adisk, 16, "ADISK.DAT"); - - // シナリオ管理 - scenario_data = NULL; - load_scenario(0); - scenario_page = 0; - scenario_addr = 2; - label_depth = page_depth = 0; - - // 変数初期化 - memset(var, 0, sizeof(var)); - memset(var_stack, 0, sizeof(var_stack)); - memset(tvar, 0, sizeof(tvar)); - memset(tvar_stack, 0, sizeof(tvar_stack)); - - // コマンド初期化 - column = true; // 座標モード - wait_keydown = true; // ウェイト時のキー受付 - seed = SDL_GetTicks(); // 乱数の種 - text_wait_time = 100; // メッセージ表示のウェイト - text_wait_enb = false; - mouse_sence = 16; // マウス移動感知 - - menu_window = text_window = 1; - menu_index = 0; - show_push = true; - clear_text = true; - - verb_obj = false; - set_palette = false; - - tvar_index = 0; - - pcm_index = 0; - memset(pcm, 0, sizeof(pcm)); - - // 各種クラス生成 - ags = new AGS(this, config); - mako = new MAKO(this, config); - msgskip = new MsgSkip(this); - -#ifdef USE_JOY - // 入力初期化 - joy_num = joyGetNumDevs(); - if(joy_num) { - joyGetDevCaps(JOYSTICKID1, &joycaps, sizeof(JOYCAPS)); - } -#endif - - terminate = false; - restart_after_terminate = false; -} - -NACT::~NACT() -{ - delete ags; - delete mako; - delete msgskip; - - // シナリオ開放 - if(scenario_data) { - free(scenario_data); - } - - platform_finalize(); -} - -bool NACT::mainloop() -{ - msgskip->load_from_file(); - - int sleep_cnt = 0; - while(!terminate) { - execute(); - // 512コマンド実行毎にSleep(10) - if(!(sleep_cnt = (sleep_cnt + 1) & 0x1ff)) { - sys_sleep(10); - } - } - return restart_after_terminate; -} - -// コマンドパーサ - -EMSCRIPTEN_KEEPALIVE // Prevent inlining, because this function is listed in ASYNCIFY_ADD -void NACT::execute() -{ - // アドレスの確認 - if(scenario_addr < 2 || scenario_addr >= scenario_size) { - fatal("Scenario error"); - } - - // 致命的なエラー発生 or 正常終了 - if(fatal_error) { - if(!post_quit) { - terminate = true; - } - post_quit = true; - return; - } - - if(sys_ver == 1 && scenario_page == 0 && scenario_addr == 2) { - opening(); - } - - // Skip SysEng's "new style" marker - if (scenario_page == 0 && scenario_addr == 2 && - memcmp(&scenario_data[2], "REV", 3) == 0) { - scenario_addr = 5; - } - - // 1コマンド実行 - prev_addr = scenario_addr; - uint8 cmd = getd(); - - if(set_palette && cmd != 'P') { - // パレット設定が終わった - ags->flush_screen(true); - set_palette = false; - } - if(verb_obj && cmd != '[' && cmd != ':') { - // 動詞-目的語メニューの表示 - scenario_addr--; - cmd_open_verb(); - return; - } - - switch(cmd) { - case '!': - cmd_calc(); - break; - case '{': - cmd_branch(); - break; - case '}': - break; - case '@': - cmd_label_jump(); - break; - case '\\': - cmd_label_call(); - break; - case '&': - cmd_page_jump(); - break; - case '%': - cmd_page_call(); - break; - case '$': - cmd_set_menu(); - break; - case '[': - cmd_set_verbobj(); - break; - case ':': - cmd_set_verbobj2(); - break; - case ']': - cmd_open_menu(); - break; - case 'A': - cmd_a(); - break; - case 'B': - cmd_b(); - break; - case 'D': - cmd_d(); - break; - case 'E': - cmd_e(); - break; - case 'F': - cmd_f(); - break; - case 'G': - cmd_g(); - break; - case 'H': - cmd_h(); - break; - case 'I': - cmd_i(); - break; - case 'J': - cmd_j(); - break; - case 'K': - cmd_k(); - break; - case 'L': - cmd_l(); - break; - case 'M': - cmd_m(); - break; - case 'N': - cmd_n(); - break; - case 'O': - cmd_o(); - break; - case 'P': - cmd_p(); - break; - case 'Q': - cmd_q(); - break; - case 'R': - cmd_r(); - break; - case 'S': - cmd_s(); - break; - case 'T': - cmd_t(); - break; - case 'U': - cmd_u(); - break; - case 'V': - cmd_v(); - break; - case 'W': - cmd_w(); - break; - case 'X': - cmd_x(); - break; - case 'Y': - cmd_y(); - break; - case 'Z': - cmd_z(); - break; - case '\'': case '"': - message(cmd); - break; - default: - if (is_message(cmd)) { - ungetd(); - message(0); - } else if (cmd >= 0x20 && cmd < 0x7f) { - fatal("Unknown Command: '%c' at page = %d, addr = %d", cmd, scenario_page, prev_addr); - } else { - fatal("Unknown Command: %02x at page = %d, addr = %d", cmd, scenario_page, prev_addr); - } - break; - } -} - -void NACT::skip_string(uint8 terminator) -{ - for (uint8 c = getd(); c != terminator; c = getd()) { - if (c != '\\') - ungetd(); - scenario_addr += encoding->mblen(scenario_data + scenario_addr); - } -} - -void NACT::get_string(char* buf, int size, uint8 terminator) -{ - int start_addr = scenario_addr; - - int i = 0; - for (uint8 c = getd(); c != terminator; c = getd()) { - if (c != '\\') - ungetd(); - int len = encoding->mblen(scenario_data + scenario_addr); - if (i + len >= size) - fatal("String buffer overrun. page = %d, addr = %d", scenario_page, start_addr); - memcpy(&buf[i], &scenario_data[scenario_addr], len); - i += len; - scenario_addr += len; - } - buf[i] = '\0'; -} - -void NACT::message(uint8 terminator) -{ - char buf[200]; - if (terminator) { // SysEng - get_string(buf, sizeof(buf), terminator); - } else { - uint8* begin = &scenario_data[scenario_addr]; - uint8* p = begin; - while (is_message(*p)) - p += encoding->mblen(p); - int len = p - begin; - scenario_addr += len; - - strncpy(buf, reinterpret_cast(begin), len); - buf[len] = '\0'; - } - - ags->draw_text(buf, text_wait_enb); - - if(crc32_a == CRC32_DPS || crc32_a == CRC32_DPS_SG || crc32_a == CRC32_DPS_SG2 || crc32_a == CRC32_DPS_SG3) { - if(!ags->draw_menu) { - text_refresh = false; - } - } - if (!ags->draw_menu) - msgskip->on_message(scenario_page, scenario_addr); - - // TODO: Convert hankaku to zenkaku - output_console(buf); -} - -void NACT::text_wait() -{ - Uint32 dwTime = SDL_GetTicks() + text_wait_time; - for(;;) { - if(terminate) { - return; - } - RND = get_key(); - if(RND && wait_keydown) { - break; - } - if(dwTime <= SDL_GetTicks()) { - break; - } - sys_sleep(16); - } -} - -void NACT::load_scenario(int page) -{ - if(scenario_data) { - free(scenario_data); - } - DRI* dri = new DRI(); - if((scenario_data = dri->load(adisk, page + 1, &scenario_size)) == NULL) { - fatal("Cannot load scenario %d", page); - } - delete dri; -} - -// 下位関数 - -int NACT::menu_select(int num_items) -{ - if (msgskip->get_flags() & MSGSKIP_STOP_ON_MENU) - msgskip->activate(false); - - // メニュー表示 - ags->open_menu_window(menu_window); - - // マウス移動 - int sx = ags->menu_w[menu_window - 1].sx; - int sy = ags->menu_w[menu_window - 1].sy; - int ex = ags->menu_w[menu_window - 1].ex; - int mx = ex - 16; - int my = sy + 10; - int height = ags->menu_font_size + 4; - int current_index = 0; - - set_cursor(mx, my); - wait_after_open_menu(); - - // メニュー選択 - for(bool selectable = true;;) { - // 入力待機 - int val = 0, current_mx = mx, current_my = my; - for(;;) { - if(terminate) { - return -1; - } - get_cursor(¤t_mx, ¤t_my); - int dx = mx - current_mx; - int dy = my - current_my; - if (dx*dx + dy*dy > 10) - break; - if((val = get_key()) != 0) { - sys_sleep(100); - break; - } - sys_sleep(16); - } - if(val) { - for(;;) { - if(terminate) { - return -1; - } - if(!get_key()) { - break; - } - sys_sleep(16); - } - } - - if(val == 0) { - // マウス操作 - mx = current_mx; my = current_my; - int index = (my - sy) / height; - if(sx <= mx && mx <= ex && 0 <= index && index < num_items) { - current_index = index; - ags->redraw_menu_window(menu_window, current_index); - selectable = true; - } else { - selectable = false; - } - } else if(val == 1 || val == 2 || val == 4 || val == 8) { - if(val == 1) { - current_index = current_index ? current_index - 1 : num_items - 1; - } else if(val == 2) { - current_index = (current_index < num_items - 1) ? current_index + 1 : 0; - } else if(val == 4) { - current_index = 0; - } else if(val == 8) { - current_index = num_items - 1; - } - ags->redraw_menu_window(menu_window, current_index); - selectable = true; - } else if(val == 16 && selectable) { - break; - } else if(val == 32) { - current_index = -1; - break; - } - } - - // 画面更新 - ags->close_menu_window(menu_window); - if(clear_text) { - ags->clear_text_window(text_window, true); - } - - return current_index; -} - -uint16 NACT::random(uint16 range) -{ - // xorshift32 - seed = seed ^ (seed << 13); - seed = seed ^ (seed >> 17); - seed = seed ^ (seed << 15); - return (uint16)(((uint32)range * (seed & 0xffff)) >> 16) + 1; -} - -void NACT::wait_after_open_menu() -{ - // 連打による誤クリック防止 - Uint32 dwTime = SDL_GetTicks(); - Uint32 dwWait = dwTime + 400; - - while(dwTime < dwWait) { - if(terminate) { - return; - } -/* - if(get_key() == 16) { - break; - } -*/ - sys_sleep(10); - dwTime = SDL_GetTicks(); - } - - // クリック中の間は待機 - for(;;) { - if(terminate) { - return; - } - if(!get_key()) { - break; - } - sys_sleep(10); - } -} - -void NACT::sys_sleep(int ms) { - pump_events(); - ags->update_screen(); -#ifdef __EMSCRIPTEN__ - emscripten_sleep(ms); -#else - SDL_Delay(ms); -#endif -} - -// WinMainとのインターフェース - -int NACT::get_screen_height() -{ - return ags->screen_height; -} - -void NACT::select_cursor() -{ - ags->select_cursor(); -} - -void NACT::fatal(const char* format, ...) { - char buf[512]; - va_list args; - va_start(args, format); - vsnprintf(buf, sizeof buf, format, args); - SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "system3", buf, g_window); - fatal_error = true; -} - -NACT* NACT::create(const Config& config) { - uint32 crc32_a = NACT::calc_crc32("ADISK.DAT", config.game_id); - uint32 crc32_b = NACT::calc_crc32("BDISK.DAT", config.game_id); - int sys_ver = NACT::get_sys_ver(crc32_a, crc32_b); - switch (sys_ver) { - case 1: - return new NACT_Sys1(crc32_a, crc32_b, config); - case 2: - return new NACT_Sys2(crc32_a, crc32_b, config); - default: - return new NACT_Sys3(crc32_a, crc32_b, config); - } -} +/* + ALICE SOFT SYSTEM 3 for Win32 + + [ NACT ] +*/ + +#include +#include "nact.h" +#include "encoding.h" +#include "ags.h" +#include "mako.h" +#include "msgskip.h" +#include "dri.h" +#include "../config.h" +#include "../fileio.h" +#include "crc32.h" + +extern SDL_Window* g_window; + +// 初期化 + +NACT::NACT(int sys_ver, uint32 crc32_a, uint32 crc32_b, const Config& config) + : sys_ver(sys_ver), + crc32_a(crc32_a), + crc32_b(crc32_b), + config(config), + encoding(Encoding::create(get_encoding_name())), + strings(config.get_strings(encoding.get(), get_language() == ENGLISH)) +{ + platform_initialize(); + + // AG00.DAT読み込み + FILEIO* fio = new FILEIO(); + if(fio->Fopen("AG00.DAT", FILEIO_READ_BINARY)) { + int d0, d1, d2, d3; + char string[MAX_CAPTION]; + fio->Fgets(string, MAX_CAPTION); + if (sscanf_s(string, "%d,%d,%d,%d", &d0, &d1, &d2, &d3) != 4) + fatal("AG00.DAT: parse error"); + for(int i = 0; i < d1; i++) { + // 動詞の読み込み + fio->Fgets(string, MAX_CAPTION); + memcpy(caption_verb[i], string, sizeof(string)); + } + for(int i = 0; i < d2; i++) { + // 目的語の読み込み + fio->Fgets(string, MAX_CAPTION); + memcpy(caption_obj[i], string, sizeof(string)); + } + fio->Fclose(); + } + delete fio; + + // ADISK.DAT + if (crc32_a == CRC32_PROG_OMAKE) + strcpy_s(adisk, 16, "AGAME.DAT"); + else + strcpy_s(adisk, 16, "ADISK.DAT"); + + // シナリオ管理 + scenario_data = NULL; + load_scenario(0); + scenario_page = 0; + scenario_addr = 2; + label_depth = page_depth = 0; + + // 変数初期化 + memset(var, 0, sizeof(var)); + memset(var_stack, 0, sizeof(var_stack)); + memset(tvar, 0, sizeof(tvar)); + memset(tvar_stack, 0, sizeof(tvar_stack)); + + // コマンド初期化 + column = true; // 座標モード + wait_keydown = true; // ウェイト時のキー受付 + seed = SDL_GetTicks(); // 乱数の種 + text_wait_time = 100; // メッセージ表示のウェイト + text_wait_enb = false; + mouse_sence = 16; // マウス移動感知 + + menu_window = text_window = 1; + menu_index = 0; + show_push = true; + clear_text = true; + + verb_obj = false; + set_palette = false; + + tvar_index = 0; + + pcm_index = 0; + memset(pcm, 0, sizeof(pcm)); + + // 各種クラス生成 + ags = new AGS(this, config); + mako = new MAKO(this, config); + msgskip = new MsgSkip(this); + +#ifdef USE_JOY + // 入力初期化 + joy_num = joyGetNumDevs(); + if(joy_num) { + joyGetDevCaps(JOYSTICKID1, &joycaps, sizeof(JOYCAPS)); + } +#endif + + terminate = false; + restart_after_terminate = false; +} + +NACT::~NACT() +{ + delete ags; + delete mako; + delete msgskip; + + // シナリオ開放 + if(scenario_data) { + free(scenario_data); + } + + platform_finalize(); +} + +bool NACT::mainloop() +{ + msgskip->load_from_file(); + + int sleep_cnt = 0; + while(!terminate) { + execute(); + // 512コマンド実行毎にSleep(10) + if(!(sleep_cnt = (sleep_cnt + 1) & 0x1ff)) { + sys_sleep(10); + } + } + return restart_after_terminate; +} + +// コマンドパーサ + +EMSCRIPTEN_KEEPALIVE // Prevent inlining, because this function is listed in ASYNCIFY_ADD +void NACT::execute() +{ + // アドレスの確認 + if(scenario_addr < 2 || scenario_addr >= scenario_size) { + fatal("Scenario error"); + } + + // 致命的なエラー発生 or 正常終了 + if(fatal_error) { + if(!post_quit) { + terminate = true; + } + post_quit = true; + return; + } + + if(sys_ver == 1 && scenario_page == 0 && scenario_addr == 2) { + opening(); + } + + // Skip SysEng's "new style" marker + if (scenario_page == 0 && scenario_addr == 2 && + memcmp(&scenario_data[2], "REV", 3) == 0) { + scenario_addr = 5; + } + + // 1コマンド実行 + prev_addr = scenario_addr; + uint8 cmd = getd(); + + if(set_palette && cmd != 'P') { + // パレット設定が終わった + ags->flush_screen(true); + set_palette = false; + } + if(verb_obj && cmd != '[' && cmd != ':') { + // 動詞-目的語メニューの表示 + scenario_addr--; + cmd_open_verb(); + return; + } + + switch(cmd) { + case '!': + cmd_calc(); + break; + case '{': + cmd_branch(); + break; + case '}': + break; + case '@': + cmd_label_jump(); + break; + case '\\': + cmd_label_call(); + break; + case '&': + cmd_page_jump(); + break; + case '%': + cmd_page_call(); + break; + case '$': + cmd_set_menu(); + break; + case '[': + cmd_set_verbobj(); + break; + case ':': + cmd_set_verbobj2(); + break; + case ']': + cmd_open_menu(); + break; + case 'A': + cmd_a(); + break; + case 'B': + cmd_b(); + break; + case 'D': + cmd_d(); + break; + case 'E': + cmd_e(); + break; + case 'F': + cmd_f(); + break; + case 'G': + cmd_g(); + break; + case 'H': + cmd_h(); + break; + case 'I': + cmd_i(); + break; + case 'J': + cmd_j(); + break; + case 'K': + cmd_k(); + break; + case 'L': + cmd_l(); + break; + case 'M': + cmd_m(); + break; + case 'N': + cmd_n(); + break; + case 'O': + cmd_o(); + break; + case 'P': + cmd_p(); + break; + case 'Q': + cmd_q(); + break; + case 'R': + cmd_r(); + break; + case 'S': + cmd_s(); + break; + case 'T': + cmd_t(); + break; + case 'U': + cmd_u(); + break; + case 'V': + cmd_v(); + break; + case 'W': + cmd_w(); + break; + case 'X': + cmd_x(); + break; + case 'Y': + cmd_y(); + break; + case 'Z': + cmd_z(); + break; + case '\'': case '"': + message(cmd); + break; + default: + if (is_message(cmd)) { + ungetd(); + message(0); + } else if (cmd >= 0x20 && cmd < 0x7f) { + fatal("Unknown Command: '%c' at page = %d, addr = %d", cmd, scenario_page, prev_addr); + } else { + fatal("Unknown Command: %02x at page = %d, addr = %d", cmd, scenario_page, prev_addr); + } + break; + } +} + +void NACT::skip_string(uint8 terminator) +{ + for (uint8 c = getd(); c != terminator; c = getd()) { + if (c != '\\') + ungetd(); + scenario_addr += encoding->mblen(scenario_data + scenario_addr); + } +} + +void NACT::get_string(char* buf, int size, uint8 terminator) +{ + int start_addr = scenario_addr; + + int i = 0; + for (uint8 c = getd(); c != terminator; c = getd()) { + if (c != '\\') + ungetd(); + int len = encoding->mblen(scenario_data + scenario_addr); + if (i + len >= size) + fatal("String buffer overrun. page = %d, addr = %d", scenario_page, start_addr); + memcpy(&buf[i], &scenario_data[scenario_addr], len); + i += len; + scenario_addr += len; + } + buf[i] = '\0'; +} + +void NACT::message(uint8 terminator) +{ + char buf[200]; + if (terminator) { // SysEng + get_string(buf, sizeof(buf), terminator); + } else { + uint8* begin = &scenario_data[scenario_addr]; + uint8* p = begin; + while (is_message(*p)) + p += encoding->mblen(p); + int len = p - begin; + scenario_addr += len; + + strncpy(buf, reinterpret_cast(begin), len); + buf[len] = '\0'; + } + + ags->draw_text(buf, text_wait_enb); + + if(crc32_a == CRC32_DPS || crc32_a == CRC32_DPS_SG || crc32_a == CRC32_DPS_SG2 || crc32_a == CRC32_DPS_SG3) { + if(!ags->draw_menu) { + text_refresh = false; + } + } + if (!ags->draw_menu) + msgskip->on_message(scenario_page, scenario_addr); + + // TODO: Convert hankaku to zenkaku + output_console(buf); +} + +void NACT::text_wait() +{ + Uint32 dwTime = SDL_GetTicks() + text_wait_time; + for(;;) { + if(terminate) { + return; + } + RND = get_key(); + if(RND && wait_keydown) { + break; + } + if(dwTime <= SDL_GetTicks()) { + break; + } + sys_sleep(16); + } +} + +void NACT::load_scenario(int page) +{ + if(scenario_data) { + free(scenario_data); + } + DRI* dri = new DRI(); + if((scenario_data = dri->load(adisk, page + 1, &scenario_size)) == NULL) { + fatal("Cannot load scenario %d", page); + } + delete dri; +} + +// 下位関数 + +int NACT::menu_select(int num_items) +{ + if (msgskip->get_flags() & MSGSKIP_STOP_ON_MENU) + msgskip->activate(false); + + // メニュー表示 + ags->open_menu_window(menu_window); + + // マウス移動 + int sx = ags->menu_w[menu_window - 1].sx; + int sy = ags->menu_w[menu_window - 1].sy; + int ex = ags->menu_w[menu_window - 1].ex; + int mx = ex - 16; + int my = sy + 10; + int height = ags->menu_font_size + 4; + int current_index = 0; + + set_cursor(mx, my); + wait_after_open_menu(); + + // メニュー選択 + for(bool selectable = true;;) { + // 入力待機 + int val = 0, current_mx = mx, current_my = my; + for(;;) { + if(terminate) { + return -1; + } + get_cursor(¤t_mx, ¤t_my); + int dx = mx - current_mx; + int dy = my - current_my; + if (dx*dx + dy*dy > 10) + break; + if((val = get_key()) != 0) { + sys_sleep(100); + break; + } + sys_sleep(16); + } + if(val) { + for(;;) { + if(terminate) { + return -1; + } + if(!get_key()) { + break; + } + sys_sleep(16); + } + } + + if(val == 0) { + // マウス操作 + mx = current_mx; my = current_my; + int index = (my - sy) / height; + if(sx <= mx && mx <= ex && 0 <= index && index < num_items) { + current_index = index; + ags->redraw_menu_window(menu_window, current_index); + selectable = true; + } else { + selectable = false; + } + } else if(val == 1 || val == 2 || val == 4 || val == 8) { + if(val == 1) { + current_index = current_index ? current_index - 1 : num_items - 1; + } else if(val == 2) { + current_index = (current_index < num_items - 1) ? current_index + 1 : 0; + } else if(val == 4) { + current_index = 0; + } else if(val == 8) { + current_index = num_items - 1; + } + ags->redraw_menu_window(menu_window, current_index); + selectable = true; + } else if(val == 16 && selectable) { + break; + } else if(val == 32) { + current_index = -1; + break; + } + } + + // 画面更新 + ags->close_menu_window(menu_window); + if(clear_text) { + ags->clear_text_window(text_window, true); + } + + return current_index; +} + +uint16 NACT::random(uint16 range) +{ + // xorshift32 + seed = seed ^ (seed << 13); + seed = seed ^ (seed >> 17); + seed = seed ^ (seed << 15); + return (uint16)(((uint32)range * (seed & 0xffff)) >> 16) + 1; +} + +void NACT::wait_after_open_menu() +{ + // 連打による誤クリック防止 + Uint32 dwTime = SDL_GetTicks(); + Uint32 dwWait = dwTime + 400; + + while(dwTime < dwWait) { + if(terminate) { + return; + } +/* + if(get_key() == 16) { + break; + } +*/ + sys_sleep(10); + dwTime = SDL_GetTicks(); + } + + // クリック中の間は待機 + for(;;) { + if(terminate) { + return; + } + if(!get_key()) { + break; + } + sys_sleep(10); + } +} + +void NACT::sys_sleep(int ms) { + pump_events(); + ags->update_screen(); +#ifdef __EMSCRIPTEN__ + emscripten_sleep(ms); +#else + SDL_Delay(ms); +#endif +} + +// WinMainとのインターフェース + +int NACT::get_screen_height() +{ + return ags->screen_height; +} + +void NACT::select_cursor() +{ + ags->select_cursor(); +} + +void NACT::fatal(const char* format, ...) { + char buf[512]; + va_list args; + va_start(args, format); + vsnprintf(buf, sizeof buf, format, args); + SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "system3", buf, g_window); + fatal_error = true; +} + +NACT* NACT::create(const Config& config) { + uint32 crc32_a = NACT::calc_crc32("ADISK.DAT", config.game_id); + uint32 crc32_b = NACT::calc_crc32("BDISK.DAT", config.game_id); + int sys_ver = NACT::get_sys_ver(crc32_a, crc32_b); + switch (sys_ver) { + case 1: + return new NACT_Sys1(crc32_a, crc32_b, config); + case 2: + return new NACT_Sys2(crc32_a, crc32_b, config); + default: + return new NACT_Sys3(crc32_a, crc32_b, config); + } +} diff --git a/src/sys/nact.h b/src/sys/nact.h index 16c84af..684fe54 100644 --- a/src/sys/nact.h +++ b/src/sys/nact.h @@ -1,434 +1,434 @@ -/* - ALICE SOFT SYSTEM 3 for Win32 - - [ NACT ] -*/ - -#ifndef _NACT_H_ -#define _NACT_H_ - -#include -#include -#include -#include "../common.h" -#include "config.h" - -#define RND var[ 0] -#define D01 var[ 1] -#define D02 var[ 2] -#define D03 var[ 3] -#define D04 var[ 4] -#define D05 var[ 5] -#define D06 var[ 6] -#define D07 var[ 7] -#define D08 var[ 8] -#define D09 var[ 9] -#define D10 var[10] -#define D11 var[11] -#define D12 var[12] -#define D13 var[13] -#define D14 var[14] -#define D15 var[15] -#define D16 var[16] -#define D17 var[17] -#define D18 var[18] -#define D19 var[19] -#define D20 var[20] -#define U01 var[21] -#define U02 var[22] -#define U03 var[23] -#define U04 var[24] -#define U05 var[25] -#define U06 var[26] -#define U07 var[27] -#define U08 var[28] -#define U09 var[29] -#define U10 var[30] -#define U11 var[31] -#define U12 var[32] -#define U13 var[33] -#define U14 var[34] -#define U15 var[35] -#define U16 var[36] -#define U17 var[37] -#define U18 var[38] -#define U19 var[39] -#define U20 var[40] -#define B01 var[41] -#define B02 var[42] -#define B03 var[43] -#define B04 var[44] -#define B05 var[45] -#define B06 var[46] -#define B07 var[47] -#define B08 var[48] -#define B09 var[49] -#define B10 var[50] -#define B11 var[51] -#define B12 var[52] -#define B13 var[53] -#define B14 var[54] -#define B15 var[55] -#define B16 var[56] -#define M_X var[57] -#define M_Y var[58] - -#define MAX_STACK 100 -#define MAX_MENU 64 -#define MAX_VERB 128 -#define MAX_OBJ 256 -#define MAX_CAPTION 32 -#define MAX_PCM 256 - -class AGS; -class MAKO; -class MsgSkip; -class Encoding; - -enum Language { - JAPANESE = 0, - ENGLISH = 1, -}; - -class NACT -{ -public: - static NACT* create(const Config& config); - NACT(int sys_ver, uint32 crc32_a, uint32 crc32_b, const Config& config); - virtual ~NACT(); - -protected: - AGS* ags; - MAKO* mako; - MsgSkip* msgskip; - - // コマンドパーサ - void execute(); - void load_scenario(int page); - - bool fatal_error = false; - bool post_quit = false; - - // ADISK.DAT, ASLEEP.DAT - char adisk[16]; - - // シナリオデータ - uint8* scenario_data; - int scenario_size; - - // アドレス、ページ管理 - int scenario_addr, prev_addr; - int scenario_page; - int label_depth; - int label_stack[MAX_STACK]; - int page_depth; - int page_stack[MAX_STACK]; - int addr_stack[MAX_STACK]; - - // 変数 - uint16 var[512]; - uint16 var_stack[30][20]; -// char tvar[10][22]; - char tvar_stack[30][10][22]; -// int tvar_index; - - void message(uint8 terminator); - - // Commands - virtual void cmd_calc() = 0; - - virtual void cmd_branch() = 0; - virtual void cmd_label_jump() = 0; - virtual void cmd_label_call() = 0; - virtual void cmd_page_jump() = 0; - virtual void cmd_page_call() = 0; - - virtual void cmd_set_menu() = 0; - virtual void cmd_open_menu() = 0; - - virtual void cmd_set_verbobj() = 0; - virtual void cmd_set_verbobj2() = 0; - virtual void cmd_open_verb() = 0; - virtual void cmd_open_obj(int verb) = 0; - - virtual void cmd_a() = 0; - virtual void cmd_b() = 0; - virtual void cmd_d() = 0; - virtual void cmd_e() = 0; - virtual void cmd_f() = 0; - virtual void cmd_g() = 0; - virtual void cmd_h() = 0; - virtual void cmd_i() = 0; - virtual void cmd_j() = 0; - virtual void cmd_k() = 0; - virtual void cmd_l() = 0; - virtual void cmd_m() = 0; - virtual void cmd_n() = 0; - virtual void cmd_o() = 0; - virtual void cmd_p() = 0; - virtual void cmd_q() = 0; - virtual void cmd_r() = 0; - virtual void cmd_s() = 0; - virtual void cmd_t() = 0; - virtual void cmd_u() = 0; - virtual void cmd_v() = 0; - virtual void cmd_w() = 0; - virtual void cmd_x() = 0; - virtual void cmd_y() = 0; - virtual void cmd_z() = 0; - - // SYSTEM1 - virtual void opening() {} - - // DPS - bool text_refresh; - - bool column; // 座標モード - bool wait_keydown; // ウェイト時のキー受付 - int text_wait_time; // テキスト表示のウェイト - int mouse_sence; // マウス感度 - - int menu_window; // メニューウィンドウ番号 - int text_window; // メッセージウィンドウ番号 - bool show_push; // Push表示 - bool clear_text; // メニュー後のメッセージウィンドウ消去 - - int menu_index; // メニュー登録のインデックス - int menu_addr[64]; // ジャンプ先のアドレス - int menu_verb[64]; // 登録された動詞 - int menu_obj[64]; // 登録された目的語 - - char caption_verb[MAX_VERB][MAX_CAPTION]; - char caption_obj[MAX_OBJ][MAX_CAPTION]; - - bool verb_obj; // 動詞-形容詞型メニューの定義中 - bool set_palette; - - int pcm_index; - int pcm[MAX_PCM]; - - // 下位関数 - virtual uint16 cali() = 0; - virtual uint16 cali2() = 0; - uint8 getd() { return scenario_data[scenario_addr++]; } - uint16 getw() { - uint16 val = scenario_data[scenario_addr] | (scenario_data[scenario_addr + 1] << 8); - scenario_addr += 2; - return val; - } - void ungetd() { scenario_addr--; } - bool is_message(uint8_t c) { return c == ' ' || c & 0x80; } - void skip_string(uint8 terminator); - void get_string(char* buf, int size, uint8 terminator); - - uint16 random(uint16 range); - uint32 seed; - - int menu_select(int num_items); - void wait_after_open_menu(); - - uint8 get_key(); - void get_cursor(int* x, int* y); - void set_cursor(int x, int y); - -#ifdef USE_JOY - int joy_num; - JOYCAPS joycaps; -#endif - int mouse_x = 0, mouse_y = 0; - - static uint32 calc_crc32(const char* file_name, const std::string& game_id); - - // Y27 ダイアログ - void text_dialog(); - - // 終了フラグ - bool terminate; - bool restart_after_terminate; - - // Platform-specific setup / cleanup code - void platform_initialize(); - void platform_finalize(); - -public: - bool mainloop(); - void sys_sleep(int ms); - - int get_screen_height(); - - void select_cursor(); - - const char* get_game_id(); - static const int get_sys_ver(uint32 crc32_a, uint32 crc32_b); - const char* get_title(); - Language get_language(); - const char* get_encoding_name(); - void text_wait(); - void set_skip_menu_state(bool enabled, bool checked); - - bool text_wait_enb; // テキスト表示のウェイト有効/無効 - int sys_ver; - uint32 crc32_a; // ADISK - uint32 crc32_b; // BDISK for D.P.S -SG- and Super D.P.S - const Config& config; - std::unique_ptr encoding; - Strings strings; - - // for Y27 - char tvar[10][33]; - int tvar_index, tvar_maxlen; - - // デバッグログ - void output_console(const char *format, ...); - - int get_scenario_page() const { return scenario_page; } - - void fatal(const char* msg, ...); - -private: - void pump_events(); - bool handle_platform_event(const SDL_Event& e); -}; - -class NACT_Sys1 final : public NACT { -public: - NACT_Sys1(uint32 crc32_a, uint32 crc32_b, const Config& config); -protected: - void cmd_calc() override; - void cmd_branch() override; - void cmd_label_jump() override; - void cmd_label_call() override; - void cmd_page_jump() override; - void cmd_page_call() override; - void cmd_set_menu() override; - void cmd_open_menu() override; - void cmd_set_verbobj() override; - void cmd_set_verbobj2() override; - void cmd_open_verb() override; - void cmd_open_obj(int verb) override; - void cmd_a() override; - void cmd_b() override; - void cmd_d() override; - void cmd_e() override; - void cmd_f() override; - void cmd_g() override; - void cmd_h() override; - void cmd_i() override; - void cmd_j() override; - void cmd_k() override; - void cmd_l() override; - void cmd_m() override; - void cmd_n() override; - void cmd_o() override; - void cmd_p() override; - void cmd_q() override; - void cmd_r() override; - void cmd_s() override; - void cmd_t() override; - void cmd_u() override; - void cmd_v() override; - void cmd_w() override; - void cmd_x() override; - void cmd_y() override; - void cmd_z() override; - void opening() override; - uint16 cali() override; - uint16 cali2() override; -private: - // Intruder Zコマンド - int paint_x; - int paint_y; - int map_page; -}; - -class NACT_Sys2 final : public NACT { -public: - NACT_Sys2(uint32 crc32_a, uint32 crc32_b, const Config& config); -protected: - void cmd_calc() override; - void cmd_branch() override; - void cmd_label_jump() override; - void cmd_label_call() override; - void cmd_page_jump() override; - void cmd_page_call() override; - void cmd_set_menu() override; - void cmd_open_menu() override; - void cmd_set_verbobj() override; - void cmd_set_verbobj2() override; - void cmd_open_verb() override; - void cmd_open_obj(int verb) override; - void cmd_a() override; - void cmd_b() override; - void cmd_d() override; - void cmd_e() override; - void cmd_f() override; - void cmd_g() override; - void cmd_h() override; - void cmd_i() override; - void cmd_j() override; - void cmd_k() override; - void cmd_l() override; - void cmd_m() override; - void cmd_n() override; - void cmd_o() override; - void cmd_p() override; - void cmd_q() override; - void cmd_r() override; - void cmd_s() override; - void cmd_t() override; - void cmd_u() override; - void cmd_v() override; - void cmd_w() override; - void cmd_x() override; - void cmd_y() override; - void cmd_z() override; - uint16 cali() override; - uint16 cali2() override; -}; - -class NACT_Sys3 final : public NACT { -public: - NACT_Sys3(uint32 crc32_a, uint32 crc32_b, const Config& config); -protected: - void cmd_calc() override; - void cmd_branch() override; - void cmd_label_jump() override; - void cmd_label_call() override; - void cmd_page_jump() override; - void cmd_page_call() override; - void cmd_set_menu() override; - void cmd_open_menu() override; - void cmd_set_verbobj() override; - void cmd_set_verbobj2() override; - void cmd_open_verb() override; - void cmd_open_obj(int verb) override; - void cmd_a() override; - void cmd_b() override; - void cmd_d() override; - void cmd_e() override; - void cmd_f() override; - void cmd_g() override; - void cmd_h() override; - void cmd_i() override; - void cmd_j() override; - void cmd_k() override; - void cmd_l() override; - void cmd_m() override; - void cmd_n() override; - void cmd_o() override; - void cmd_p() override; - void cmd_q() override; - void cmd_r() override; - void cmd_s() override; - void cmd_t() override; - void cmd_u() override; - void cmd_v() override; - void cmd_w() override; - void cmd_x() override; - void cmd_y() override; - void cmd_z() override; - uint16 cali() override; - uint16 cali2() override; -}; - -#endif // _NACT_H_ +/* + ALICE SOFT SYSTEM 3 for Win32 + + [ NACT ] +*/ + +#ifndef _NACT_H_ +#define _NACT_H_ + +#include +#include +#include +#include "../common.h" +#include "config.h" + +#define RND var[ 0] +#define D01 var[ 1] +#define D02 var[ 2] +#define D03 var[ 3] +#define D04 var[ 4] +#define D05 var[ 5] +#define D06 var[ 6] +#define D07 var[ 7] +#define D08 var[ 8] +#define D09 var[ 9] +#define D10 var[10] +#define D11 var[11] +#define D12 var[12] +#define D13 var[13] +#define D14 var[14] +#define D15 var[15] +#define D16 var[16] +#define D17 var[17] +#define D18 var[18] +#define D19 var[19] +#define D20 var[20] +#define U01 var[21] +#define U02 var[22] +#define U03 var[23] +#define U04 var[24] +#define U05 var[25] +#define U06 var[26] +#define U07 var[27] +#define U08 var[28] +#define U09 var[29] +#define U10 var[30] +#define U11 var[31] +#define U12 var[32] +#define U13 var[33] +#define U14 var[34] +#define U15 var[35] +#define U16 var[36] +#define U17 var[37] +#define U18 var[38] +#define U19 var[39] +#define U20 var[40] +#define B01 var[41] +#define B02 var[42] +#define B03 var[43] +#define B04 var[44] +#define B05 var[45] +#define B06 var[46] +#define B07 var[47] +#define B08 var[48] +#define B09 var[49] +#define B10 var[50] +#define B11 var[51] +#define B12 var[52] +#define B13 var[53] +#define B14 var[54] +#define B15 var[55] +#define B16 var[56] +#define M_X var[57] +#define M_Y var[58] + +#define MAX_STACK 100 +#define MAX_MENU 64 +#define MAX_VERB 128 +#define MAX_OBJ 256 +#define MAX_CAPTION 32 +#define MAX_PCM 256 + +class AGS; +class MAKO; +class MsgSkip; +class Encoding; + +enum Language { + JAPANESE = 0, + ENGLISH = 1, +}; + +class NACT +{ +public: + static NACT* create(const Config& config); + NACT(int sys_ver, uint32 crc32_a, uint32 crc32_b, const Config& config); + virtual ~NACT(); + +protected: + AGS* ags; + MAKO* mako; + MsgSkip* msgskip; + + // コマンドパーサ + void execute(); + void load_scenario(int page); + + bool fatal_error = false; + bool post_quit = false; + + // ADISK.DAT, ASLEEP.DAT + char adisk[16]; + + // シナリオデータ + uint8* scenario_data; + int scenario_size; + + // アドレス、ページ管理 + int scenario_addr, prev_addr; + int scenario_page; + int label_depth; + int label_stack[MAX_STACK]; + int page_depth; + int page_stack[MAX_STACK]; + int addr_stack[MAX_STACK]; + + // 変数 + uint16 var[512]; + uint16 var_stack[30][20]; +// char tvar[10][22]; + char tvar_stack[30][10][22]; +// int tvar_index; + + void message(uint8 terminator); + + // Commands + virtual void cmd_calc() = 0; + + virtual void cmd_branch() = 0; + virtual void cmd_label_jump() = 0; + virtual void cmd_label_call() = 0; + virtual void cmd_page_jump() = 0; + virtual void cmd_page_call() = 0; + + virtual void cmd_set_menu() = 0; + virtual void cmd_open_menu() = 0; + + virtual void cmd_set_verbobj() = 0; + virtual void cmd_set_verbobj2() = 0; + virtual void cmd_open_verb() = 0; + virtual void cmd_open_obj(int verb) = 0; + + virtual void cmd_a() = 0; + virtual void cmd_b() = 0; + virtual void cmd_d() = 0; + virtual void cmd_e() = 0; + virtual void cmd_f() = 0; + virtual void cmd_g() = 0; + virtual void cmd_h() = 0; + virtual void cmd_i() = 0; + virtual void cmd_j() = 0; + virtual void cmd_k() = 0; + virtual void cmd_l() = 0; + virtual void cmd_m() = 0; + virtual void cmd_n() = 0; + virtual void cmd_o() = 0; + virtual void cmd_p() = 0; + virtual void cmd_q() = 0; + virtual void cmd_r() = 0; + virtual void cmd_s() = 0; + virtual void cmd_t() = 0; + virtual void cmd_u() = 0; + virtual void cmd_v() = 0; + virtual void cmd_w() = 0; + virtual void cmd_x() = 0; + virtual void cmd_y() = 0; + virtual void cmd_z() = 0; + + // SYSTEM1 + virtual void opening() {} + + // DPS + bool text_refresh; + + bool column; // 座標モード + bool wait_keydown; // ウェイト時のキー受付 + int text_wait_time; // テキスト表示のウェイト + int mouse_sence; // マウス感度 + + int menu_window; // メニューウィンドウ番号 + int text_window; // メッセージウィンドウ番号 + bool show_push; // Push表示 + bool clear_text; // メニュー後のメッセージウィンドウ消去 + + int menu_index; // メニュー登録のインデックス + int menu_addr[64]; // ジャンプ先のアドレス + int menu_verb[64]; // 登録された動詞 + int menu_obj[64]; // 登録された目的語 + + char caption_verb[MAX_VERB][MAX_CAPTION]; + char caption_obj[MAX_OBJ][MAX_CAPTION]; + + bool verb_obj; // 動詞-形容詞型メニューの定義中 + bool set_palette; + + int pcm_index; + int pcm[MAX_PCM]; + + // 下位関数 + virtual uint16 cali() = 0; + virtual uint16 cali2() = 0; + uint8 getd() { return scenario_data[scenario_addr++]; } + uint16 getw() { + uint16 val = scenario_data[scenario_addr] | (scenario_data[scenario_addr + 1] << 8); + scenario_addr += 2; + return val; + } + void ungetd() { scenario_addr--; } + bool is_message(uint8_t c) { return c == ' ' || c & 0x80; } + void skip_string(uint8 terminator); + void get_string(char* buf, int size, uint8 terminator); + + uint16 random(uint16 range); + uint32 seed; + + int menu_select(int num_items); + void wait_after_open_menu(); + + uint8 get_key(); + void get_cursor(int* x, int* y); + void set_cursor(int x, int y); + +#ifdef USE_JOY + int joy_num; + JOYCAPS joycaps; +#endif + int mouse_x = 0, mouse_y = 0; + + static uint32 calc_crc32(const char* file_name, const std::string& game_id); + + // Y27 ダイアログ + void text_dialog(); + + // 終了フラグ + bool terminate; + bool restart_after_terminate; + + // Platform-specific setup / cleanup code + void platform_initialize(); + void platform_finalize(); + +public: + bool mainloop(); + void sys_sleep(int ms); + + int get_screen_height(); + + void select_cursor(); + + const char* get_game_id(); + static const int get_sys_ver(uint32 crc32_a, uint32 crc32_b); + const char* get_title(); + Language get_language(); + const char* get_encoding_name(); + void text_wait(); + void set_skip_menu_state(bool enabled, bool checked); + + bool text_wait_enb; // テキスト表示のウェイト有効/無効 + int sys_ver; + uint32 crc32_a; // ADISK + uint32 crc32_b; // BDISK for D.P.S -SG- and Super D.P.S + const Config& config; + std::unique_ptr encoding; + Strings strings; + + // for Y27 + char tvar[10][33]; + int tvar_index, tvar_maxlen; + + // デバッグログ + void output_console(const char *format, ...); + + int get_scenario_page() const { return scenario_page; } + + void fatal(const char* msg, ...); + +private: + void pump_events(); + bool handle_platform_event(const SDL_Event& e); +}; + +class NACT_Sys1 final : public NACT { +public: + NACT_Sys1(uint32 crc32_a, uint32 crc32_b, const Config& config); +protected: + void cmd_calc() override; + void cmd_branch() override; + void cmd_label_jump() override; + void cmd_label_call() override; + void cmd_page_jump() override; + void cmd_page_call() override; + void cmd_set_menu() override; + void cmd_open_menu() override; + void cmd_set_verbobj() override; + void cmd_set_verbobj2() override; + void cmd_open_verb() override; + void cmd_open_obj(int verb) override; + void cmd_a() override; + void cmd_b() override; + void cmd_d() override; + void cmd_e() override; + void cmd_f() override; + void cmd_g() override; + void cmd_h() override; + void cmd_i() override; + void cmd_j() override; + void cmd_k() override; + void cmd_l() override; + void cmd_m() override; + void cmd_n() override; + void cmd_o() override; + void cmd_p() override; + void cmd_q() override; + void cmd_r() override; + void cmd_s() override; + void cmd_t() override; + void cmd_u() override; + void cmd_v() override; + void cmd_w() override; + void cmd_x() override; + void cmd_y() override; + void cmd_z() override; + void opening() override; + uint16 cali() override; + uint16 cali2() override; +private: + // Intruder Zコマンド + int paint_x; + int paint_y; + int map_page; +}; + +class NACT_Sys2 final : public NACT { +public: + NACT_Sys2(uint32 crc32_a, uint32 crc32_b, const Config& config); +protected: + void cmd_calc() override; + void cmd_branch() override; + void cmd_label_jump() override; + void cmd_label_call() override; + void cmd_page_jump() override; + void cmd_page_call() override; + void cmd_set_menu() override; + void cmd_open_menu() override; + void cmd_set_verbobj() override; + void cmd_set_verbobj2() override; + void cmd_open_verb() override; + void cmd_open_obj(int verb) override; + void cmd_a() override; + void cmd_b() override; + void cmd_d() override; + void cmd_e() override; + void cmd_f() override; + void cmd_g() override; + void cmd_h() override; + void cmd_i() override; + void cmd_j() override; + void cmd_k() override; + void cmd_l() override; + void cmd_m() override; + void cmd_n() override; + void cmd_o() override; + void cmd_p() override; + void cmd_q() override; + void cmd_r() override; + void cmd_s() override; + void cmd_t() override; + void cmd_u() override; + void cmd_v() override; + void cmd_w() override; + void cmd_x() override; + void cmd_y() override; + void cmd_z() override; + uint16 cali() override; + uint16 cali2() override; +}; + +class NACT_Sys3 final : public NACT { +public: + NACT_Sys3(uint32 crc32_a, uint32 crc32_b, const Config& config); +protected: + void cmd_calc() override; + void cmd_branch() override; + void cmd_label_jump() override; + void cmd_label_call() override; + void cmd_page_jump() override; + void cmd_page_call() override; + void cmd_set_menu() override; + void cmd_open_menu() override; + void cmd_set_verbobj() override; + void cmd_set_verbobj2() override; + void cmd_open_verb() override; + void cmd_open_obj(int verb) override; + void cmd_a() override; + void cmd_b() override; + void cmd_d() override; + void cmd_e() override; + void cmd_f() override; + void cmd_g() override; + void cmd_h() override; + void cmd_i() override; + void cmd_j() override; + void cmd_k() override; + void cmd_l() override; + void cmd_m() override; + void cmd_n() override; + void cmd_o() override; + void cmd_p() override; + void cmd_q() override; + void cmd_r() override; + void cmd_s() override; + void cmd_t() override; + void cmd_u() override; + void cmd_v() override; + void cmd_w() override; + void cmd_x() override; + void cmd_y() override; + void cmd_z() override; + uint16 cali() override; + uint16 cali2() override; +}; + +#endif // _NACT_H_ diff --git a/src/sys/nact_crc32.cpp b/src/sys/nact_crc32.cpp index bc8c1aa..72b5f23 100644 --- a/src/sys/nact_crc32.cpp +++ b/src/sys/nact_crc32.cpp @@ -1,170 +1,170 @@ -/* - ALICE SOFT SYSTEM 3 for Win32 - - [ NACT - crc32 ] -*/ - -#include "nact.h" -#include -#include "crc32.h" -#include "../fileio.h" -#include "config.h" - -namespace { - -const struct CRCTable { - const char* id; - int sys_ver; - const char* title; - Language language; - uint32 crc32_a; - uint32 crc32_b; -} crc_table[] = { - {"bunkasai", 1, "あぶない文化祭前夜", JAPANESE, CRC32_BUNKASAI}, - {"crescent", 1, "クレセントムーンがぁる", JAPANESE, CRC32_CRESCENT}, - {"dps", 1, "D.P.S - Dream Program System", JAPANESE, CRC32_DPS}, - {"dps_sg_fahren", 1, "D.P.S SG - Fahren Fliegen", JAPANESE, CRC32_DPS_SG, CRC32_DPS_SG_FAHREN}, - {"dps_sg_katei", 1, "D.P.S SG - 家庭教師はステキなお仕事", JAPANESE, CRC32_DPS_SG, CRC32_DPS_SG_KATEI}, - {"dps_sg_nobunaga", 1, "D.P.S SG - 信長の淫謀", JAPANESE, CRC32_DPS_SG, CRC32_DPS_SG_NOBUNAGA}, - {"dps_sg2_antique", 1, "D.P.S SG set2 - ANTIQUE HOUSE", JAPANESE, CRC32_DPS_SG2, CRC32_DPS_SG2_ANTIQUE}, - {"dps_sg2_ikenai", 1, "D.P.S SG set2 - いけない内科検診再び", JAPANESE, CRC32_DPS_SG2, CRC32_DPS_SG2_IKENAI}, - {"dps_sg2_akai", 1, "D.P.S SG set2 - 朱い夜", JAPANESE, CRC32_DPS_SG2, CRC32_DPS_SG2_AKAI}, - {"dps_sg3_rabbit", 1, "D.P.S SG set3 - Rabbit P4P", JAPANESE, CRC32_DPS_SG3, CRC32_DPS_SG3_RABBIT}, - {"dps_sg3_shinkon", 1, "D.P.S SG set3 - しんこんさんものがたり", JAPANESE, CRC32_DPS_SG3, CRC32_DPS_SG3_SHINKON}, - {"dps_sg3_sotsugyou", 1, "D.P.S SG set3 - 卒業", JAPANESE, CRC32_DPS_SG3, CRC32_DPS_SG3_SOTSUGYOU}, - {"fukei", 1, "婦警さんVX", JAPANESE, CRC32_FUKEI}, - {"intruder", 1, "Intruder -桜屋敷の探索-", JAPANESE, CRC32_INTRUDER}, - {"tengu", 1, "あぶないてんぐ伝説", JAPANESE, CRC32_TENGU}, - {"toushin_hint", 1, "闘神都市 ヒントディスク", JAPANESE, CRC32_TOUSHIN_HINT}, - {"little_vampire", 1, "Little Vampire", JAPANESE, CRC32_VAMPIRE}, - {"little_vampire_eng", 1, "Little Vampire", ENGLISH, CRC32_VAMPIRE_ENG}, - {"yakata", 1, "ALICEの館", JAPANESE, CRC32_YAKATA}, - - {"ayumi_fd", 2, "あゆみちゃん物語", JAPANESE, CRC32_AYUMI_FD}, - {"ayumi_hint", 2, "あゆみちゃん物語 ヒントディスク", JAPANESE, CRC32_AYUMI_HINT}, - {"ayumi_proto", 2, "あゆみちゃん物語 PROTO", JAPANESE, CRC32_AYUMI_PROTO}, - {"dalk_hint", 2, "DALK ヒントディスク", JAPANESE, CRC32_DALK_HINT}, - {"drstop", 2, "Dr. STOP!", JAPANESE, CRC32_DRSTOP}, - {"prog_fd", 2, "Prostudent G", JAPANESE, CRC32_PROSTUDENTG_FD}, - {"rance3_hint", 2, "Rance3 ヒントディスク", JAPANESE, CRC32_RANCE3_HINT}, - {"sdps_maria", 2, "Super D.P.S - マリアとカンパン", JAPANESE, CRC32_SDPS, CRC32_SDPS_MARIA}, - {"sdps_tono", 2, "Super D.P.S - 遠野の森", JAPANESE, CRC32_SDPS, CRC32_SDPS_TONO}, - {"sdps_kaizoku", 2, "Super D.P.S - うれしたのし海賊稼業", JAPANESE, CRC32_SDPS, CRC32_SDPS_KAIZOKU}, - {"yakata2", 2, "ALICEの館II", JAPANESE, CRC32_YAKATA2}, - - {"ambivalenz_fd", 3, "AmbivalenZ −二律背反−", JAPANESE, CRC32_AMBIVALENZ_FD}, - {"ambivalenz_cd", 3, "AmbivalenZ −二律背反−", JAPANESE, CRC32_AMBIVALENZ_CD}, - {"dps_all", 3, "D.P.S. 全部", JAPANESE, CRC32_DPSALL}, - {"funnybee_cd", 3, "宇宙快盗ファニーBee", JAPANESE, CRC32_FUNNYBEE_CD}, -// {"funnybee_patch", 3, "宇宙快盗ファニーBee", JAPANESE, CRC32_FUNNYBEE_PATCH}, - {"funnybee_fd", 3, "宇宙快盗ファニーBee", JAPANESE, CRC32_FUNNYBEE_FD}, - {"onlyyou", 3, "Only You −世紀末のジュリエット達−", JAPANESE, CRC32_ONLYYOU}, - {"onlyyou_demo", 3, "Only You −世紀末のジュリエット達− デモ版", JAPANESE, CRC32_ONLYYOU_DEMO}, - {"prog_cd", 3, "Prostudent G", JAPANESE, CRC32_PROSTUDENTG_CD}, - {"prog_omake", 3, "Prostudent G おまけ", JAPANESE, CRC32_PROG_OMAKE}, - {"rance41", 3, "ランス 4.1 〜お薬工場を救え!〜", JAPANESE, CRC32_RANCE41}, - {"rance41_eng", 3, "Rance 4.1 ~Save the Medicine Plant!~", ENGLISH, CRC32_RANCE41_ENG}, - {"rance42", 3, "ランス 4.2 〜エンジェル組〜", JAPANESE, CRC32_RANCE42}, - {"rance42_eng", 3, "Rance 4.2 ~Angel Army~", ENGLISH, CRC32_RANCE42_ENG}, - {"ayumi_cd", 3, "あゆみちゃん物語", JAPANESE, CRC32_AYUMI_CD}, - {"ayumi_live_256", 3, "あゆみちゃん物語 実写版", JAPANESE, CRC32_AYUMI_JISSHA_256}, - {"ayumi_live_full", 3, "あゆみちゃん物語 フルカラー実写版", JAPANESE, CRC32_AYUMI_JISSHA_FULL}, - {"yakata3_cd", 3, "アリスの館3", JAPANESE, CRC32_YAKATA3_CD}, - {"yakata3_fd", 3, "アリスの館3", JAPANESE, CRC32_YAKATA3_FD}, - {"hashirionna2", 3, "走り女2", JAPANESE, CRC32_HASHIRIONNA2}, - {"toushin2_gd", 3,"闘神都市2 グラフィックディスク", JAPANESE, CRC32_TOUSHIN2_GD}, - {"toushin2_sp", 3, "闘神都市2 そして、それから…", JAPANESE, CRC32_TOUSHIN2_SP}, - {"otome", 3, "乙女戦記", JAPANESE, CRC32_OTOMESENKI}, - {"ningyo", 3, "人魚 -蘿子-", JAPANESE, CRC32_NINGYO}, - {"mugen", 3, "夢幻泡影", JAPANESE, CRC32_MUGENHOUYOU}, - - {NULL}, -}; - -const CRCTable* lookup(uint32 crc32_a, uint32 crc32_b) -{ - for (const CRCTable* t = crc_table; t->id; t++) { - if (crc32_a == t->crc32_a && (!t->crc32_b || crc32_b == t->crc32_b)) - return t; - } - return NULL; -} - -} // namespace - -uint32 NACT::calc_crc32(const char* file_name, const std::string& game_id) -{ - if (!game_id.empty()) { - for (const CRCTable* t = crc_table; t->id; t++) { - if (t->id == game_id) - return file_name[0] == 'A' ? t->crc32_a : t->crc32_b; - } - } - - uint32 crc = 0; - FILEIO* fio = new FILEIO(); - - if(fio->Fopen(file_name, FILEIO_READ_BINARY)) { - uint32 table[256]; - for(int i = 0; i < 256; i++) { - uint32 c = i; - for(int j = 0; j < 8; j++) { - if(c & 1) { - c = (c >> 1) ^ 0xedb88320; - } else { - c >>= 1; - } - } - table[i] = c; - } - // ADISK.DATの先頭256bytes - for(int i = 0; i < 256; i++) { - int d = fio->Fgetc(); - uint32 c = ~crc; - c = table[(c ^ d) & 0xff] ^ (c >> 8); - crc = ~c; - } - fio->Fclose(); - } - delete fio; - return crc; -} - -const char* NACT::get_game_id() -{ - if (const CRCTable* entry = lookup(crc32_a, crc32_b)) - return entry->id; - return NULL; -} - -const int NACT::get_sys_ver(uint32 crc32_a, uint32 crc32_b) -{ - if (const CRCTable* entry = lookup(crc32_a, crc32_b)) - return entry->sys_ver; - return 3; -} - -const char* NACT::get_title() -{ - if (!config.title.empty()) - return config.title.c_str(); - if (const CRCTable* entry = lookup(crc32_a, crc32_b)) - return entry->title; - return NULL; -} - -Language NACT::get_language() -{ - if (const CRCTable* entry = lookup(crc32_a, crc32_b)) - return entry->language; - return JAPANESE; -} - -const char* NACT::get_encoding_name() -{ - if (!config.encoding.empty()) - return config.encoding.c_str(); - - // TODO: Determine encoding from crc32 - return "Shift_JIS"; -} +/* + ALICE SOFT SYSTEM 3 for Win32 + + [ NACT - crc32 ] +*/ + +#include "nact.h" +#include +#include "crc32.h" +#include "../fileio.h" +#include "config.h" + +namespace { + +const struct CRCTable { + const char* id; + int sys_ver; + const char* title; + Language language; + uint32 crc32_a; + uint32 crc32_b; +} crc_table[] = { + {"bunkasai", 1, "あぶない文化祭前夜", JAPANESE, CRC32_BUNKASAI}, + {"crescent", 1, "クレセントムーンがぁる", JAPANESE, CRC32_CRESCENT}, + {"dps", 1, "D.P.S - Dream Program System", JAPANESE, CRC32_DPS}, + {"dps_sg_fahren", 1, "D.P.S SG - Fahren Fliegen", JAPANESE, CRC32_DPS_SG, CRC32_DPS_SG_FAHREN}, + {"dps_sg_katei", 1, "D.P.S SG - 家庭教師はステキなお仕事", JAPANESE, CRC32_DPS_SG, CRC32_DPS_SG_KATEI}, + {"dps_sg_nobunaga", 1, "D.P.S SG - 信長の淫謀", JAPANESE, CRC32_DPS_SG, CRC32_DPS_SG_NOBUNAGA}, + {"dps_sg2_antique", 1, "D.P.S SG set2 - ANTIQUE HOUSE", JAPANESE, CRC32_DPS_SG2, CRC32_DPS_SG2_ANTIQUE}, + {"dps_sg2_ikenai", 1, "D.P.S SG set2 - いけない内科検診再び", JAPANESE, CRC32_DPS_SG2, CRC32_DPS_SG2_IKENAI}, + {"dps_sg2_akai", 1, "D.P.S SG set2 - 朱い夜", JAPANESE, CRC32_DPS_SG2, CRC32_DPS_SG2_AKAI}, + {"dps_sg3_rabbit", 1, "D.P.S SG set3 - Rabbit P4P", JAPANESE, CRC32_DPS_SG3, CRC32_DPS_SG3_RABBIT}, + {"dps_sg3_shinkon", 1, "D.P.S SG set3 - しんこんさんものがたり", JAPANESE, CRC32_DPS_SG3, CRC32_DPS_SG3_SHINKON}, + {"dps_sg3_sotsugyou", 1, "D.P.S SG set3 - 卒業", JAPANESE, CRC32_DPS_SG3, CRC32_DPS_SG3_SOTSUGYOU}, + {"fukei", 1, "婦警さんVX", JAPANESE, CRC32_FUKEI}, + {"intruder", 1, "Intruder -桜屋敷の探索-", JAPANESE, CRC32_INTRUDER}, + {"tengu", 1, "あぶないてんぐ伝説", JAPANESE, CRC32_TENGU}, + {"toushin_hint", 1, "闘神都市 ヒントディスク", JAPANESE, CRC32_TOUSHIN_HINT}, + {"little_vampire", 1, "Little Vampire", JAPANESE, CRC32_VAMPIRE}, + {"little_vampire_eng", 1, "Little Vampire", ENGLISH, CRC32_VAMPIRE_ENG}, + {"yakata", 1, "ALICEの館", JAPANESE, CRC32_YAKATA}, + + {"ayumi_fd", 2, "あゆみちゃん物語", JAPANESE, CRC32_AYUMI_FD}, + {"ayumi_hint", 2, "あゆみちゃん物語 ヒントディスク", JAPANESE, CRC32_AYUMI_HINT}, + {"ayumi_proto", 2, "あゆみちゃん物語 PROTO", JAPANESE, CRC32_AYUMI_PROTO}, + {"dalk_hint", 2, "DALK ヒントディスク", JAPANESE, CRC32_DALK_HINT}, + {"drstop", 2, "Dr. STOP!", JAPANESE, CRC32_DRSTOP}, + {"prog_fd", 2, "Prostudent G", JAPANESE, CRC32_PROSTUDENTG_FD}, + {"rance3_hint", 2, "Rance3 ヒントディスク", JAPANESE, CRC32_RANCE3_HINT}, + {"sdps_maria", 2, "Super D.P.S - マリアとカンパン", JAPANESE, CRC32_SDPS, CRC32_SDPS_MARIA}, + {"sdps_tono", 2, "Super D.P.S - 遠野の森", JAPANESE, CRC32_SDPS, CRC32_SDPS_TONO}, + {"sdps_kaizoku", 2, "Super D.P.S - うれしたのし海賊稼業", JAPANESE, CRC32_SDPS, CRC32_SDPS_KAIZOKU}, + {"yakata2", 2, "ALICEの館II", JAPANESE, CRC32_YAKATA2}, + + {"ambivalenz_fd", 3, "AmbivalenZ −二律背反−", JAPANESE, CRC32_AMBIVALENZ_FD}, + {"ambivalenz_cd", 3, "AmbivalenZ −二律背反−", JAPANESE, CRC32_AMBIVALENZ_CD}, + {"dps_all", 3, "D.P.S. 全部", JAPANESE, CRC32_DPSALL}, + {"funnybee_cd", 3, "宇宙快盗ファニーBee", JAPANESE, CRC32_FUNNYBEE_CD}, +// {"funnybee_patch", 3, "宇宙快盗ファニーBee", JAPANESE, CRC32_FUNNYBEE_PATCH}, + {"funnybee_fd", 3, "宇宙快盗ファニーBee", JAPANESE, CRC32_FUNNYBEE_FD}, + {"onlyyou", 3, "Only You −世紀末のジュリエット達−", JAPANESE, CRC32_ONLYYOU}, + {"onlyyou_demo", 3, "Only You −世紀末のジュリエット達− デモ版", JAPANESE, CRC32_ONLYYOU_DEMO}, + {"prog_cd", 3, "Prostudent G", JAPANESE, CRC32_PROSTUDENTG_CD}, + {"prog_omake", 3, "Prostudent G おまけ", JAPANESE, CRC32_PROG_OMAKE}, + {"rance41", 3, "ランス 4.1 〜お薬工場を救え!〜", JAPANESE, CRC32_RANCE41}, + {"rance41_eng", 3, "Rance 4.1 ~Save the Medicine Plant!~", ENGLISH, CRC32_RANCE41_ENG}, + {"rance42", 3, "ランス 4.2 〜エンジェル組〜", JAPANESE, CRC32_RANCE42}, + {"rance42_eng", 3, "Rance 4.2 ~Angel Army~", ENGLISH, CRC32_RANCE42_ENG}, + {"ayumi_cd", 3, "あゆみちゃん物語", JAPANESE, CRC32_AYUMI_CD}, + {"ayumi_live_256", 3, "あゆみちゃん物語 実写版", JAPANESE, CRC32_AYUMI_JISSHA_256}, + {"ayumi_live_full", 3, "あゆみちゃん物語 フルカラー実写版", JAPANESE, CRC32_AYUMI_JISSHA_FULL}, + {"yakata3_cd", 3, "アリスの館3", JAPANESE, CRC32_YAKATA3_CD}, + {"yakata3_fd", 3, "アリスの館3", JAPANESE, CRC32_YAKATA3_FD}, + {"hashirionna2", 3, "走り女2", JAPANESE, CRC32_HASHIRIONNA2}, + {"toushin2_gd", 3,"闘神都市2 グラフィックディスク", JAPANESE, CRC32_TOUSHIN2_GD}, + {"toushin2_sp", 3, "闘神都市2 そして、それから…", JAPANESE, CRC32_TOUSHIN2_SP}, + {"otome", 3, "乙女戦記", JAPANESE, CRC32_OTOMESENKI}, + {"ningyo", 3, "人魚 -蘿子-", JAPANESE, CRC32_NINGYO}, + {"mugen", 3, "夢幻泡影", JAPANESE, CRC32_MUGENHOUYOU}, + + {NULL}, +}; + +const CRCTable* lookup(uint32 crc32_a, uint32 crc32_b) +{ + for (const CRCTable* t = crc_table; t->id; t++) { + if (crc32_a == t->crc32_a && (!t->crc32_b || crc32_b == t->crc32_b)) + return t; + } + return NULL; +} + +} // namespace + +uint32 NACT::calc_crc32(const char* file_name, const std::string& game_id) +{ + if (!game_id.empty()) { + for (const CRCTable* t = crc_table; t->id; t++) { + if (t->id == game_id) + return file_name[0] == 'A' ? t->crc32_a : t->crc32_b; + } + } + + uint32 crc = 0; + FILEIO* fio = new FILEIO(); + + if(fio->Fopen(file_name, FILEIO_READ_BINARY)) { + uint32 table[256]; + for(int i = 0; i < 256; i++) { + uint32 c = i; + for(int j = 0; j < 8; j++) { + if(c & 1) { + c = (c >> 1) ^ 0xedb88320; + } else { + c >>= 1; + } + } + table[i] = c; + } + // ADISK.DATの先頭256bytes + for(int i = 0; i < 256; i++) { + int d = fio->Fgetc(); + uint32 c = ~crc; + c = table[(c ^ d) & 0xff] ^ (c >> 8); + crc = ~c; + } + fio->Fclose(); + } + delete fio; + return crc; +} + +const char* NACT::get_game_id() +{ + if (const CRCTable* entry = lookup(crc32_a, crc32_b)) + return entry->id; + return NULL; +} + +const int NACT::get_sys_ver(uint32 crc32_a, uint32 crc32_b) +{ + if (const CRCTable* entry = lookup(crc32_a, crc32_b)) + return entry->sys_ver; + return 3; +} + +const char* NACT::get_title() +{ + if (!config.title.empty()) + return config.title.c_str(); + if (const CRCTable* entry = lookup(crc32_a, crc32_b)) + return entry->title; + return NULL; +} + +Language NACT::get_language() +{ + if (const CRCTable* entry = lookup(crc32_a, crc32_b)) + return entry->language; + return JAPANESE; +} + +const char* NACT::get_encoding_name() +{ + if (!config.encoding.empty()) + return config.encoding.c_str(); + + // TODO: Determine encoding from crc32 + return "Shift_JIS"; +} diff --git a/src/sys/nact_input.cpp b/src/sys/nact_input.cpp index 2c78f9a..70e30a9 100644 --- a/src/sys/nact_input.cpp +++ b/src/sys/nact_input.cpp @@ -1,119 +1,119 @@ -/* - ALICE SOFT SYSTEM 3 for Win32 - - [ NACT - input ] -*/ - -#ifdef _WIN32 -#include -#undef ERROR -#endif -#include -#include "nact.h" -#include "ags.h" -#include "texthook.h" - -extern SDL_Window* g_window; -static int mousex, mousey, fingers; - -void NACT::pump_events() -{ - SDL_Event e; - while (SDL_PollEvent(&e)) { - if (handle_platform_event(e)) - continue; - - switch (e.type) { - case SDL_QUIT: - terminate = true; - break; - - case SDL_WINDOWEVENT: - switch (e.window.event) { - case SDL_WINDOWEVENT_EXPOSED: - case SDL_WINDOWEVENT_SIZE_CHANGED: - ags->flush_screen(false); - break; - } - break; - - case SDL_MOUSEMOTION: - mousex = e.motion.x; - mousey = e.motion.y; - break; - - case SDL_FINGERDOWN: - case SDL_FINGERUP: - case SDL_FINGERMOTION: - mousex = e.tfinger.x * 640; - mousey = e.tfinger.y * ags->screen_height; - fingers = SDL_GetNumTouchFingers(e.tfinger.touchId); - break; - - case SDL_APP_DIDENTERFOREGROUND: - ags->flush_screen(false); - break; - } - } -} - -uint8 NACT::get_key() -{ - uint8 val = 0; - - texthook_keywait(); - - pump_events(); - - // キーボード&マウス - const Uint8* key = SDL_GetKeyboardState(NULL); - Uint32 mouse; - if (fingers) { - mouse = fingers == 1 ? SDL_BUTTON_LMASK : SDL_BUTTON_RMASK; - } else { - mouse = SDL_GetMouseState(NULL, NULL); - } - - if(key[SDL_SCANCODE_UP ] || key[SDL_SCANCODE_KP_8 ] ) val |= 0x01; - if(key[SDL_SCANCODE_DOWN ] || key[SDL_SCANCODE_KP_2 ] ) val |= 0x02; - if(key[SDL_SCANCODE_LEFT ] || key[SDL_SCANCODE_KP_4 ] ) val |= 0x04; - if(key[SDL_SCANCODE_RIGHT ] || key[SDL_SCANCODE_KP_6 ] ) val |= 0x08; - if(key[SDL_SCANCODE_RETURN] || mouse & SDL_BUTTON_LMASK) val |= 0x10; - if(key[SDL_SCANCODE_SPACE ] || mouse & SDL_BUTTON_RMASK) val |= 0x20; - if(key[SDL_SCANCODE_ESCAPE] ) val |= 0x40; - if(key[SDL_SCANCODE_TAB ] ) val |= 0x80; - - // マウス移動で方向入力はサポートしない - -#ifdef USE_JOY - // ジョイスティック - if(joy_num > 0) { - JOYINFO joyinfo; - if(joyGetPos(JOYSTICKID1, &joyinfo) == JOYERR_NOERROR) { - if(joyinfo.wYpos == joycaps.wYmin) val |= 0x01; - if(joyinfo.wYpos == joycaps.wYmax) val |= 0x02; - if(joyinfo.wXpos == joycaps.wXmin) val |= 0x04; - if(joyinfo.wXpos == joycaps.wXmax) val |= 0x08; - if(joyinfo.wButtons & JOY_BUTTON1) val |= 0x10; - if(joyinfo.wButtons & JOY_BUTTON2) val |= 0x20; - if(joyinfo.wButtons & JOY_BUTTON3) val |= 0x40; - if(joyinfo.wButtons & JOY_BUTTON4) val |= 0x80; - } - } -#endif - - return val; -} - -void NACT::get_cursor(int* x, int* y) -{ - pump_events(); - *x = mousex; - *y = mousey; -} - -void NACT::set_cursor(int x, int y) -{ - ags->translate_mouse_coords(&x, &y); - SDL_WarpMouseInWindow(g_window, x, y); -} +/* + ALICE SOFT SYSTEM 3 for Win32 + + [ NACT - input ] +*/ + +#ifdef _WIN32 +#include +#undef ERROR +#endif +#include +#include "nact.h" +#include "ags.h" +#include "texthook.h" + +extern SDL_Window* g_window; +static int mousex, mousey, fingers; + +void NACT::pump_events() +{ + SDL_Event e; + while (SDL_PollEvent(&e)) { + if (handle_platform_event(e)) + continue; + + switch (e.type) { + case SDL_QUIT: + terminate = true; + break; + + case SDL_WINDOWEVENT: + switch (e.window.event) { + case SDL_WINDOWEVENT_EXPOSED: + case SDL_WINDOWEVENT_SIZE_CHANGED: + ags->flush_screen(false); + break; + } + break; + + case SDL_MOUSEMOTION: + mousex = e.motion.x; + mousey = e.motion.y; + break; + + case SDL_FINGERDOWN: + case SDL_FINGERUP: + case SDL_FINGERMOTION: + mousex = e.tfinger.x * 640; + mousey = e.tfinger.y * ags->screen_height; + fingers = SDL_GetNumTouchFingers(e.tfinger.touchId); + break; + + case SDL_APP_DIDENTERFOREGROUND: + ags->flush_screen(false); + break; + } + } +} + +uint8 NACT::get_key() +{ + uint8 val = 0; + + texthook_keywait(); + + pump_events(); + + // キーボード&マウス + const Uint8* key = SDL_GetKeyboardState(NULL); + Uint32 mouse; + if (fingers) { + mouse = fingers == 1 ? SDL_BUTTON_LMASK : SDL_BUTTON_RMASK; + } else { + mouse = SDL_GetMouseState(NULL, NULL); + } + + if(key[SDL_SCANCODE_UP ] || key[SDL_SCANCODE_KP_8 ] ) val |= 0x01; + if(key[SDL_SCANCODE_DOWN ] || key[SDL_SCANCODE_KP_2 ] ) val |= 0x02; + if(key[SDL_SCANCODE_LEFT ] || key[SDL_SCANCODE_KP_4 ] ) val |= 0x04; + if(key[SDL_SCANCODE_RIGHT ] || key[SDL_SCANCODE_KP_6 ] ) val |= 0x08; + if(key[SDL_SCANCODE_RETURN] || mouse & SDL_BUTTON_LMASK) val |= 0x10; + if(key[SDL_SCANCODE_SPACE ] || mouse & SDL_BUTTON_RMASK) val |= 0x20; + if(key[SDL_SCANCODE_ESCAPE] ) val |= 0x40; + if(key[SDL_SCANCODE_TAB ] ) val |= 0x80; + + // マウス移動で方向入力はサポートしない + +#ifdef USE_JOY + // ジョイスティック + if(joy_num > 0) { + JOYINFO joyinfo; + if(joyGetPos(JOYSTICKID1, &joyinfo) == JOYERR_NOERROR) { + if(joyinfo.wYpos == joycaps.wYmin) val |= 0x01; + if(joyinfo.wYpos == joycaps.wYmax) val |= 0x02; + if(joyinfo.wXpos == joycaps.wXmin) val |= 0x04; + if(joyinfo.wXpos == joycaps.wXmax) val |= 0x08; + if(joyinfo.wButtons & JOY_BUTTON1) val |= 0x10; + if(joyinfo.wButtons & JOY_BUTTON2) val |= 0x20; + if(joyinfo.wButtons & JOY_BUTTON3) val |= 0x40; + if(joyinfo.wButtons & JOY_BUTTON4) val |= 0x80; + } + } +#endif + + return val; +} + +void NACT::get_cursor(int* x, int* y) +{ + pump_events(); + *x = mousex; + *y = mousey; +} + +void NACT::set_cursor(int x, int y) +{ + ags->translate_mouse_coords(&x, &y); + SDL_WarpMouseInWindow(g_window, x, y); +} diff --git a/src/sys/nact_sys1.cpp b/src/sys/nact_sys1.cpp index 7f04d8d..d55aade 100644 --- a/src/sys/nact_sys1.cpp +++ b/src/sys/nact_sys1.cpp @@ -1,1277 +1,1277 @@ -/* - ALICE SOFT SYSTEM1 for Win32 - - D.P.S. - Dream Program System - Intruder -桜屋敷の探索- - Little Vampire - あぶないてんぐ伝説 - クレセントムーンがぁる - 婦警さん物語VX - - [ NACT - command ] -*/ - -#include "nact.h" -#include "ags.h" -#include "mako.h" -#include "msgskip.h" -#include "crc32.h" -#include "../fileio.h" -#include "encoding.h" -#include "texthook.h" - -// メニューの改ページ -#define MENU_MAX (crc32_a == CRC32_INTRUDER ? 6 : 11) - -#define WAIT(tm) \ -{ \ - Uint32 dwTime = SDL_GetTicks() + (tm); \ - for(;;) { \ - if(terminate) { \ - return; \ - } \ - if(dwTime <= SDL_GetTicks()) { \ - break; \ - } \ - sys_sleep(16); \ - } \ -} - -#define WAIT_KEYQUIT(tm) \ -{ \ - Uint32 dwTime = SDL_GetTicks() + (tm); \ - for(;;) { \ - if(terminate) { \ - return; \ - } \ - if(get_key()) { \ - for(;;) { \ - if(terminate) { \ - return; \ - } \ - if(!get_key()) { \ - break; \ - } \ - if(dwTime <= SDL_GetTicks()) { \ - break; \ - } \ - sys_sleep(16); \ - } \ - break; \ - } \ - if(dwTime <= SDL_GetTicks()) { \ - break; \ - } \ - sys_sleep(16); \ - } \ -} - -NACT_Sys1::NACT_Sys1(uint32 crc32_a, uint32 crc32_b, const Config& config) - : NACT(1, crc32_a, crc32_b, config) -{ - switch (crc32_a) { - case CRC32_DPS: - case CRC32_DPS_SG: - //case CRC32_DPS_SG2: - case CRC32_DPS_SG3: - text_refresh = false; - strcpy(tvar[0], strings.dps_custom.c_str()); - strcpy(tvar[1], strings.dps_linus.c_str()); - strcpy(tvar[2], strings.dps_katsumi.c_str()); - strcpy(tvar[3], strings.dps_yumiko.c_str()); - strcpy(tvar[4], strings.dps_itsumi.c_str()); - strcpy(tvar[5], strings.dps_hitomi.c_str()); - strcpy(tvar[6], strings.dps_mariko.c_str()); - break; - case CRC32_INTRUDER: - paint_x = paint_y = map_page = 0; - break; - } -} - -void NACT_Sys1::opening() -{ - switch (crc32_a) { - case CRC32_CRESCENT: - mako->play_music(2); - ags->load_cg(1, -1); - WAIT(3000); - ags->load_cg(81, -1); - break; - case CRC32_INTRUDER: - ags->load_cg(77, -1); - WAIT(1667); - ags->load_cg(74, -1); - break; - case CRC32_VAMPIRE: - case CRC32_VAMPIRE_ENG: - mako->play_music(4); - ags->load_cg(3, -1); - WAIT(2000); - ags->load_cg(38, -1); - cmd_a(); - ags->draw_box(0); - break; - } -} - -void NACT_Sys1::cmd_calc() -{ - int index = getd(); - if(0x80 <= index && index <= 0xbf) { - index &= 0x3f; - } else { - index = ((index & 0x3f) << 8) | getd(); - } - var[index] = cali(); - - output_console("\n!var[%d]:%d!", index, var[index]); -} - -void NACT_Sys1::cmd_branch() -{ - int condition = cali(); - int nest = 0; - bool set_menu = false; - - if(!condition) { - // 次の'}'命令までスキップする(ネストも考慮する) - for(;;) { - prev_addr = scenario_addr; - uint8 cmd = getd(); - - if(cmd == '!') { - int index = getd(); - if(!(0x80 <= index && index <= 0xbf)) { - getd(); - } - cali(); - } else if(cmd == '{') { - cali(); - nest++; - } else if(cmd == '}') { - if(nest) { - nest--; - } else { - break; - } - } else if(cmd == '@') { - getw(); - } else if(cmd == '\\') { - getw(); - } else if(cmd == '&') { - cali(); - } else if(cmd == '%') { - cali(); - } else if(cmd == '$') { - if(!set_menu) { - getw(); - set_menu = true; - } else { - set_menu = false; - } - } else if(cmd == '[') { - getd(); - getd(); - getw(); - } else if(cmd == ':') { - cali(); - getd(); - getd(); - getw(); - } else if(cmd == ']') { - - } else if(cmd == 'A') { - - } else if(cmd == 'F') { - - } else if(cmd == 'G') { - getd(); - } else if(cmd == 'L') { - getd(); - } else if(cmd == 'P') { - getd(); - } else if(cmd == 'Q') { - getd(); - } else if(cmd == 'R') { - - } else if(cmd == 'S') { - getd(); - } else if(cmd == 'U') { - getd(); - getd(); - } else if(cmd == 'X') { - getd(); - } else if(cmd == 'Y') { - cali(); - cali(); - } else if(cmd == 'Z') { - cali(); - cali(); - } else if (cmd == '\'' || cmd == '"') { // SysEng - skip_string(cmd); - } else if (is_message(cmd)) { - ungetd(); - scenario_addr += encoding->mblen(scenario_data + scenario_addr); - } else if (cmd >= 0x20 && cmd < 0x7f) { - fatal("Unknown Command: '%c' at page = %d, addr = %d", cmd, scenario_page, prev_addr); - } else { - fatal("Unknown Command: %02x at page = %d, addr = %d", cmd, scenario_page, prev_addr); - } - } - } - - output_console("\n{%d:", condition); -} - -void NACT_Sys1::cmd_label_jump() -{ - int next_addr = getw(); - scenario_addr = next_addr; - - output_console("\n@%x:", next_addr); -} - -void NACT_Sys1::cmd_label_call() -{ - int next_addr = getw(); - - output_console("\n\\%x:", next_addr); - - if(next_addr == 0) { - // リターン - if(label_depth == 0) { -// fatal_error = true; - return; - } - scenario_addr = label_stack[--label_depth]; - } else { - label_stack[label_depth++] = scenario_addr; - scenario_addr = next_addr; - } -} - -void NACT_Sys1::cmd_page_jump() -{ - int next_page = cali(); - load_scenario(next_page); - scenario_page = next_page; - scenario_addr = 2; - - output_console("\n&%d:", next_page); -} - -void NACT_Sys1::cmd_page_call() -{ - int next_page = cali(), next_addr; - - output_console("\n%%%d:", next_page); - - if(next_page == 0) { - // リターン - if(page_depth == 0) { -// fatal_error = true; - return; - } - next_page = page_stack[--page_depth]; - next_addr = addr_stack[page_depth]; - } else { - page_stack[page_depth] = scenario_page; - addr_stack[page_depth++] = scenario_addr; - next_addr = 2; - } - load_scenario(next_page); - scenario_page = next_page; - scenario_addr = next_addr; -} - -void NACT_Sys1::cmd_set_menu() -{ - if(ags->draw_menu) { - ags->menu_dest_x = 2; - ags->menu_dest_y += ags->menu_font_size + 2; - ags->draw_menu = false; - - output_console("$"); - } else { - if(!menu_index) { - ags->clear_menu_window(); - ags->menu_dest_y = 0; - } - menu_addr[menu_index++] = getw(); - ags->menu_dest_x = 2; - ags->menu_dest_y += 2; - ags->draw_menu = true; - - output_console("\n$%x,", menu_addr[menu_index - 1]); - } -} - -void NACT_Sys1::cmd_open_menu() -{ - output_console("\n]"); - - if(!menu_index) { - scenario_addr = scenario_data[0] | (scenario_data[1] << 8); - return; - } - - if(crc32_a == CRC32_DPS || crc32_a == CRC32_DPS_SG || crc32_a == CRC32_DPS_SG2 || crc32_a == CRC32_DPS_SG3) { - if(!text_refresh) { - cmd_a(); - } - } - - int selection = menu_select(menu_index); - if (terminate) - return; - - if (selection != -1) { - scenario_addr = menu_addr[selection]; - } - menu_index = 0; -} - -void NACT_Sys1::cmd_set_verbobj() -{ - int verb = getd(); - int obj = getd(); - int addr = getw(); - - menu_addr[menu_index] = addr; - menu_verb[menu_index] = verb; - menu_obj[menu_index++] = obj; - verb_obj = true; - - output_console("\n[%x,%s,%s:", addr, caption_verb[verb], caption_obj[obj]); -} - -void NACT_Sys1::cmd_set_verbobj2() -{ - int condition = cali(); - int verb = getd(); - int obj = getd(); - int addr = getw(); - - if(condition) { - menu_addr[menu_index] = addr; - menu_verb[menu_index] = verb; - menu_obj[menu_index++] = obj; - } - verb_obj = true; - - output_console("\n:%d,%x,%s,%s:", condition, addr, caption_verb[verb], caption_obj[obj]); -} - -void NACT_Sys1::cmd_open_verb() -{ - // 動詞メニューの表示 - output_console("\nopen verb-obj menu"); - verb_obj = false; - - // 表示する動詞のチェック - int chk[MAX_VERB], page = 0, cnt = 0; - - memset(chk, 0, sizeof(chk)); - for(int i = 0; i < menu_index; i++) { - chk[menu_verb[i]] = 1; - } - for(int i = 0; i < MAX_VERB; i++) { - if(chk[i]) { - cnt++; - } - } - -top: - // メニュー項目の準備 - int id[32], index = 0; - - ags->clear_menu_window(); - ags->menu_dest_y = 0; - ags->draw_menu = true; - - if(cnt <= MENU_MAX) { - // 1ページ内に全て表示できる - for(int i = 0; i < MAX_VERB; i++) { - if(chk[i]) { - ags->menu_dest_x = 2; - ags->menu_dest_y += 2; - ags->draw_text(caption_verb[i]); - id[index++] = i; - ags->menu_dest_y += ags->menu_font_size + 2; - } - } - } else { -top2: - for(int i = page; i < MAX_VERB; i++) { - if(chk[i]) { - ags->menu_dest_x = 2; - ags->menu_dest_y += 2; - ags->draw_text(caption_verb[i]); - id[index++] = i; - ags->menu_dest_y += ags->menu_font_size + 2; - } - page = i + 1; - if(index == MENU_MAX - 1) { - break; - } - } - if(index == 0) { - // 最初のページに戻る - page = 0; - goto top2; - } - // 次のページを追加 - ags->menu_dest_x = 2; - ags->menu_dest_y += 2; - ags->draw_text(strings.next_page.c_str()); - id[index++] = -1; - ags->menu_dest_y += ags->menu_font_size + 2; - } - ags->draw_menu = false; - - int selection = menu_select(index); - if (terminate) - return; - - if(selection == -1) { - scenario_addr = scenario_data[0] | (scenario_data[1] << 8); - } else if(id[selection] == -1) { - goto top; - } else { - cmd_open_obj(id[selection]); - } - menu_index = 0; -} - -void NACT_Sys1::cmd_open_obj(int verb) -{ - // 目的語メニューの表示 - verb_obj = false; - - // 表示する目的語のチェック - int chk[MAX_OBJ], addr[MAX_OBJ], page = 0, cnt = 0; - - memset(chk, 0, sizeof(chk)); - for(int i = 0; i < menu_index; i++) { - if(menu_verb[i] == verb) { - chk[menu_obj[i]] = 1; - addr[menu_obj[i]] = menu_addr[i]; - } - } - for(int i = 0; i < MAX_OBJ; i++) { - if(chk[i]) { - cnt++; - } - } - // 目的語がない場合 - if(chk[0] && cnt == 1) { - scenario_addr = addr[0]; - return; - } - // 以後、obj=0は戻るとして扱う - chk[0] = 0; - addr[0] = scenario_data[0] | (scenario_data[1] << 8); - -top: - // メニュー項目の準備 - int id[32], index = 0; - - ags->clear_menu_window(); - ags->menu_dest_y = 0; - ags->draw_menu = true; - - if(cnt <= MENU_MAX - 1) { - // 1ページ内に全て表示できる - for(int i = 0; i < MAX_OBJ; i++) { - if(chk[i]) { - ags->menu_dest_x = 2; - ags->menu_dest_y += 2; - ags->draw_text(caption_obj[i]); - id[index++] = i; - ags->menu_dest_y += ags->menu_font_size + 2; - } - } - // 戻るを追加 - ags->menu_dest_x = 2; - ags->menu_dest_y += 2; - ags->draw_text(strings.back.c_str()); - id[index++] = 0; - ags->menu_dest_y += ags->menu_font_size + 2; - } else { -top2: - for(int i = page; i < MAX_OBJ; i++) { - if(chk[i]) { - ags->menu_dest_x = 2; - ags->menu_dest_y += 2; - ags->draw_text(caption_obj[i]); - id[index++] = i; - ags->menu_dest_y += ags->menu_font_size + 2; - } - page = i + 1; - if(index == MENU_MAX - 2) { - break; - } - } - if(index == 0) { - // 最初のページに戻る - page = 0; - goto top2; - } - // 戻るを追加 - ags->menu_dest_x = 2; - ags->menu_dest_y += 2; - ags->draw_text(strings.back.c_str()); - id[index++] = 0; - ags->menu_dest_y += ags->menu_font_size + 2; - - // 次のページを追加 - ags->menu_dest_x = 2; - ags->menu_dest_y += 2; - ags->draw_text(strings.next_page.c_str()); - id[index++] = -1; - ags->menu_dest_y += ags->menu_font_size + 2; - } - ags->draw_menu = false; - - int selection = menu_select(index); - if (terminate) - return; - - if(selection == -1) { - scenario_addr = scenario_data[0] | (scenario_data[1] << 8); - } else if(id[selection] == -1) { - goto top; - } else { - scenario_addr = addr[id[selection]]; - } -} - -void NACT_Sys1::cmd_a() -{ - texthook_nextpage(); - - output_console("A\n"); - - if (msgskip->skipping()) { - if (msgskip->get_flags() & MSGSKIP_STOP_ON_CLICK && get_key()) - msgskip->activate(false); - } else if (show_push) { - ags->draw_push(text_window); - } - - // キーが押されて離されるまで待機 - while (!msgskip->skipping()) { - if(terminate) { - return; - } - if(get_key()) { - break; - } - sys_sleep(16); - } - sys_sleep(30); - while (!msgskip->skipping()) { - if(terminate) { - return; - } - if(!(get_key() & 0x18)) { - break; - } - sys_sleep(16); - } - - // ウィンドウ更新 - ags->clear_text_window(text_window, true); - - if(crc32_a == CRC32_DPS || crc32_a == CRC32_DPS_SG || crc32_a == CRC32_DPS_SG2 || crc32_a == CRC32_DPS_SG3) { - text_refresh = true; - } -} - -void NACT_Sys1::cmd_b() -{ - // 未使用 - fatal("Unknown Command: 'B' at page = %d, addr = %d", scenario_page, prev_addr); -} - -void NACT_Sys1::cmd_d() -{ - // 未使用 - fatal("Unknown Command: 'D' at page = %d, addr = %d", scenario_page, prev_addr); -} - -void NACT_Sys1::cmd_e() -{ - // 未使用 - fatal("Unknown Command: 'E' at page = %d, addr = %d", scenario_page, prev_addr); -} - -void NACT_Sys1::cmd_f() -{ - output_console("\nF"); - - scenario_addr = 2; -} - -void NACT_Sys1::cmd_g() -{ - int page = getd(); - - output_console("\nG %d:", page); - - if(crc32_a == CRC32_INTRUDER) { - page = (page == 97) ? 96 : (page == 98) ? 97 : page; - } - - ags->load_cg(page, -1); - - if(crc32_a == CRC32_INTRUDER) { - if(page == 94) { - WAIT(400); - } - if(page == 81 || page == 82) { - map_page = page; - } - } -} - -void NACT_Sys1::cmd_h() -{ - // 未使用 - fatal("Unknown Command: 'H' at page = %d, addr = %d", scenario_page, prev_addr); -} - -void NACT_Sys1::cmd_i() -{ - // 未使用 - fatal("Unknown Command: 'I' at page = %d, addr = %d", scenario_page, prev_addr); -} - -void NACT_Sys1::cmd_j() -{ - // 未使用 - fatal("Unknown Command: 'J' at page = %d, addr = %d", scenario_page, prev_addr); -} - -void NACT_Sys1::cmd_k() -{ - // 未使用 - fatal("Unknown Command: 'K' at page = %d, addr = %d", scenario_page, prev_addr); -} - -void NACT_Sys1::cmd_l() -{ - int index = getd(); - - output_console("\nL %d:", index); - - if(1 <= index && index <= 26) { - // ASLEEP_A.DAT - ASLEEP_Z.DAT - char file_name[_MAX_PATH]; - sprintf_s(file_name, _MAX_PATH, "ASLEEP_%c.DAT", 'A' + index - 1); - - FILEIO* fio = new FILEIO(); - if(fio->Fopen(file_name, FILEIO_READ_BINARY | FILEIO_SAVEDATA)) { - fio->Fseek(112, FILEIO_SEEK_SET); - - int next_page = fio->Fgetw() - 1; - fio->Fgetw(); - fio->Fgetw(); // cg no? - fio->Fgetw(); - int next_music = fio->Fgetw(); - fio->Fgetw(); - int next_addr = fio->Fgetw(); - fio->Fgetw(); - for(int i = 0; i < 512; i++) { - var[i] = fio->Fgetw(); - } - ags->menu_font_size = fio->Fgetw(); - ags->text_font_size = fio->Fgetw(); - ags->palette_bank = fio->Fgetw(); - if(!ags->palette_bank) { - ags->palette_bank = -1; - } - ags->text_font_color = fio->Fgetw(); - ags->menu_font_color = fio->Fgetw(); - ags->menu_frame_color = fio->Fgetw(); - ags->menu_back_color = fio->Fgetw(); - ags->text_frame_color = fio->Fgetw(); - ags->text_back_color = fio->Fgetw(); - for(int i = 0; i < 10; i++) { - ags->menu_w[i].sx = fio->Fgetw(); - ags->menu_w[i].sy = fio->Fgetw(); - ags->menu_w[i].ex = fio->Fgetw(); - ags->menu_w[i].ey = fio->Fgetw(); - ags->menu_w[i].push = fio->Fgetw() ? true : false; - ags->menu_w[i].frame = fio->Fgetw() ? true : false; - fio->Fgetw(); - fio->Fgetw(); - - if(ags->menu_w[i].screen) { - free(ags->menu_w[i].screen); - } - ags->menu_w[i].screen = NULL; - if(ags->menu_w[i].window) { - free(ags->menu_w[i].window); - } - ags->menu_w[i].window = NULL; - } - for(int i = 0; i < 10; i++) { - ags->text_w[i].sx = fio->Fgetw(); - ags->text_w[i].sy = fio->Fgetw(); - ags->text_w[i].ex = fio->Fgetw(); - ags->text_w[i].ey = fio->Fgetw(); - ags->text_w[i].push = fio->Fgetw() ? true : false; - ags->text_w[i].frame = fio->Fgetw() ? true : false; - fio->Fgetw(); - fio->Fgetw(); - - if(ags->text_w[i].screen) { - free(ags->text_w[i].screen); - } - ags->text_w[i].screen = NULL; - if(ags->text_w[i].window) { - free(ags->text_w[i].window); - } - ags->text_w[i].window = NULL; - } - for(int i = 0; i < 10; i++) { - fio->Fread(tvar[i], 22, 1); - } - for(int i = 0; i < 30; i++) { - for(int j = 0; j < 10; j++) { - fio->Fread(tvar_stack[i][j], 22, 1); - } - } - for(int i = 0; i < 30; i++) { - for(int j = 0; j < 20; j++) { - var_stack[i][j] = fio->Fgetw(); - } - } - fio->Fclose(); - - load_scenario(next_page); - scenario_page = next_page; - scenario_addr = next_addr; - - mako->play_music(next_music); - } - delete fio; - } -} - -void NACT_Sys1::cmd_m() -{ - // 未使用 - fatal("Unknown Command: 'M' at page = %d, addr = %d", scenario_page, prev_addr); -} - -void NACT_Sys1::cmd_n() -{ - // 未使用 - fatal("Unknown Command: 'N' at page = %d, addr = %d", scenario_page, prev_addr); -} - -void NACT_Sys1::cmd_o() -{ - // 未使用 - fatal("Unknown Command: 'O' at page = %d, addr = %d", scenario_page, prev_addr); -} - -void NACT_Sys1::cmd_p() -{ - int param = getd(); - - ags->text_font_color = (uint8)((param & 0x7) + 16); - - output_console("\nP %d:", param); -} - -#define FWRITE(data, size) { \ - memcpy(&buffer[p], data, size); \ - p += size; \ -} -#define FPUTW(data) { \ - uint16 tmp = (data); \ - buffer[p++] = tmp & 0xff; \ - buffer[p++] = (tmp >> 8) & 0xff; \ -} - -void NACT_Sys1::cmd_q() -{ - static char header[112] = { - 'T', 'h', 'i', 's', ' ', 'i', 's', ' ', 's', 'a', 'v', 'e', ' ', 'd', 'a', 't', - 'a', ' ', 'f', 'o', 'r', ' ', 'S', 'y', 's', 't', 'e', 'm', '1', ' ', ' ', 'U', - 'n', 'i', 'o', 'n', ' ', '[', 'W', 'i', 'n', '9', 'x', '/', 'N', 'T', '4', '0', - '/', '2', '0', '0', '0', '/', 'X', 'P', '/', 'C', 'E', ']', ' ', 'F', 'o', 'r', - ' ', 'N', 'A', 'C', 'T', '/', 'A', 'D', 'V', ' ', 's', 'y', 's', 't', 'e', 'm', - ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', '(', 'C', ')', '2', '0', '0', - '4', ' ', 'A', 'L', 'I', 'C', 'E', '-', 'S', 'O', 'F', 'T', ' ', ' ', ' ', ' ' - }; - - int index = getd(); - - output_console("\nQ %d:", index); - - if(1 <= index && index <= 26) { - // ASLEEP_A.DAT - ASLEEP_Z.DAT - char file_name[_MAX_PATH]; - sprintf_s(file_name, _MAX_PATH, "ASLEEP_%c.DAT", 'A' + index - 1); - - FILEIO* fio = new FILEIO(); - if(fio->Fopen(file_name, FILEIO_WRITE_BINARY | FILEIO_SAVEDATA)) { - uint8 buffer[9510]; - int p = 0; - - FWRITE(header, 112); - FPUTW(scenario_page + 1); - FPUTW(0); - FPUTW(0); // cg no? - FPUTW(0); - FPUTW(mako->current_music); - FPUTW(0); - FPUTW(scenario_addr); - FPUTW(0); - for(int i = 0; i < 512; i++) { - FPUTW(var[i]); - } - FPUTW(ags->menu_font_size); - FPUTW(ags->text_font_size); - FPUTW(ags->palette_bank == -1 ? 0 : ags->palette_bank); - FPUTW(ags->text_font_color); - FPUTW(ags->menu_font_color); - FPUTW(ags->menu_frame_color); - FPUTW(ags->menu_back_color); - FPUTW(ags->text_frame_color); - FPUTW(ags->text_back_color); - for(int i = 0; i < 10; i++) { - FPUTW(ags->menu_w[i].sx); - FPUTW(ags->menu_w[i].sy); - FPUTW(ags->menu_w[i].ex); - FPUTW(ags->menu_w[i].ey); - FPUTW(ags->menu_w[i].push ? 1 : 0); - FPUTW(ags->menu_w[i].frame ? 1 : 0); - FPUTW(0); - FPUTW(0); - } - for(int i = 0; i < 10; i++) { - FPUTW(ags->text_w[i].sx); - FPUTW(ags->text_w[i].sy); - FPUTW(ags->text_w[i].ex); - FPUTW(ags->text_w[i].ey); - FPUTW(ags->text_w[i].push ? 1 : 0); - FPUTW(ags->text_w[i].frame ? 1 : 0); - FPUTW(0); - FPUTW(0); - } - for(int i = 0; i < 10; i++) { - FWRITE(tvar[i], 22); - } - for(int i = 0; i < 30; i++) { - for(int j = 0; j < 10; j++) { - FWRITE(tvar_stack[i][j], 22); - } - } - for(int i = 0; i < 30; i++) { - for(int j = 0; j < 20; j++) { - FPUTW(var_stack[i][j]); - } - } - - fio->Fwrite(buffer, 9510, 1); - fio->Fclose(); - } - delete fio; - } -} - -void NACT_Sys1::cmd_r() -{ - texthook_newline(); - - output_console("R\n"); - - // ウィンドウの表示範囲外の場合は改ページ - if(ags->return_text_line(text_window)) { - cmd_a(); - } -} - -void NACT_Sys1::cmd_s() -{ - int page = getd(); - - output_console("\nS %d:", page); - - if(page) { - mako->play_music(page); - } else { - mako->stop_music(); - } -} - -void NACT_Sys1::cmd_t() -{ - // 未使用 - fatal("Unknown Command: 'T' at page = %d, addr = %d", scenario_page, prev_addr); -} - -void NACT_Sys1::cmd_u() -{ - int page = getd(); - int transparent = getd(); - - output_console("\nU %d,%d:", page, transparent); - - if(crc32_a == CRC32_INTRUDER) { - ags->load_cg(page, 11); - - if(page == 5) { - WAIT(400); - } - } else { - ags->load_cg(page, transparent); - } -} - -void NACT_Sys1::cmd_v() -{ - // 未使用 - fatal("Unknown Command: 'V' at page = %d, addr = %d", scenario_page, prev_addr); -} - -void NACT_Sys1::cmd_w() -{ - // 未使用 - fatal("Unknown Command: 'W' at page = %d, addr = %d", scenario_page, prev_addr); -} - -void NACT_Sys1::cmd_x() -{ - int index = getd(); - - output_console("\nX %d:", index); - - if(1 <= index && index <= 10) { - ags->draw_text(tvar[index - 1]); - } -} - -void NACT_Sys1::cmd_y() -{ - int cmd = cali(); - int param = cali(); - - output_console("\nY %d,%d:", cmd, param); - - if(crc32_a == CRC32_INTRUDER) { - switch(cmd) { - case 0: - ags->clear_text_window(text_window, true); - break; - case 1: - if(show_push) { - ags->draw_push(text_window); - } - for(;;) { - if(terminate) { - return; - } - if(get_key()) { - break; - } - sys_sleep(16); - } - sys_sleep(100); - for(;;) { - if(terminate) { - return; - } - if(!(get_key() & 0x18)) { - break; - } - sys_sleep(16); - } - ags->clear_text_window(text_window, true); - break; - case 2: - if(param == 0) { - post_quit = true; - fatal_error = true; - } else { - WAIT(100) - } - break; - case 3: - WAIT(param * 1000) - break; - case 255: - post_quit = true; - fatal_error = true; - break; - } - } else { - switch(cmd) { - case 0: - ags->clear_text_window(text_window, true); - break; - case 1: - { - char buf[16]; - buf[0] = '0' + (int)(param / 10000); - param %= 10000; - buf[1] = '0' + (int)(param / 1000); - param %= 1000; - buf[2] = '0' + (int)(param / 100); - param %= 100; - buf[3] = '0' + (int)(param / 10); - buf[4] = '0' + (param % 10); - buf[5] = '\0'; - - int p = 0; - for(;;) { - if(buf[p] != '0') { - break; - } - p++; - } - ags->draw_text(&buf[p < 4 ? p : 4]); - } - break; - case 2: - if(crc32_a == CRC32_CRESCENT) { - for(int i = 39; i <= 48; i++) { - var[i] = 0; - } - } else if(crc32_a == CRC32_DPS || crc32_a == CRC32_DPS_SG || crc32_a == CRC32_DPS_SG2 || crc32_a == CRC32_DPS_SG3) { - for(int i = 0; i <= 20; i++) { - var[i] = 0; - } - } else { - for(int i = 0; i <= 16; i++) { - var[i] = 0; - } - } - break; - case 3: - WAIT(param * 1000 / 60) - break; - case 4: - RND = (param == 0 || param == 1) ? 0 : random(param); - break; - case 7: - if(crc32_a == CRC32_DPS || crc32_a == CRC32_DPS_SG || crc32_a == CRC32_DPS_SG2 || crc32_a == CRC32_DPS_SG3) { - if(param == 1) { - ags->box_fill(0, 40, 8, 598, 270, 0); - } - } - break; - case 130: - if(crc32_a == CRC32_TENGU) { - WAIT(2000) - ags->load_cg(180, -1); - - WAIT(2000) - ags->draw_box(0); - ags->dest_screen = 1; - ags->load_cg(173, -1); - ags->dest_screen = 0; - ags->gcopy(0x1ecd, 0x3a2a, 8, 60, 3); - WAIT(667); - ags->gcopy(0x1b65, 0x262e, 8, 60, 3); - ags->gcopy(0x2e25, 0x38ee, 7, 9, 3); - WAIT(667); - ags->gcopy(0x1914, 0x1914, 8, 63, 3); - WAIT(667); - ags->gcopy(0x182c, 0x182c, 7, 50, 3); - WAIT(667); - ags->gcopy(0x0000, 0x1ecd, 32, 60, 1); - WAIT(667); - for(int i = 12; i <= 57; i++) { - ags->gcopy(i + 0x2306, i + 0x2306, 1, 165, 3); - } - WAIT_KEYQUIT(6000) - ags->draw_box(param); - } - break; - case 240: - ags->draw_hankaku = (param == 1) ? true : false; - break; - case 253: - post_quit = false; - fatal_error = true; - break; - case 254: - RND = 0; - break; - case 255: - if(crc32_a == CRC32_DPS || crc32_a == CRC32_DPS_SG || crc32_a == CRC32_DPS_SG2 || crc32_a == CRC32_DPS_SG3) { - post_quit = false; - } else { - post_quit = true; - } - fatal_error = true; - break; - } - } -} - -void NACT_Sys1::cmd_z() -{ - if (crc32_a == CRC32_CRESCENT) { - cmd_y(); - return; - } - int cmd = cali(); - int param = cali(); - - output_console("\nZ %d,%d:", cmd, param); - - switch (crc32_a) { - case CRC32_INTRUDER: - if(cmd == 1 && 1 <= param && param <= 4) { - const char* buf[4] = { - "\x81\x83", // "<" in SJIS - "\x81\xC8", // "∧" in SJIS - "\x81\x84", // ">" in SJIS - "\x81\xC9", // "∨" in SJIS - }; - - // 矢印を消去する - if(map_page) { - ags->load_cg(map_page, -1); - if(paint_x) { - ags->paint(paint_x, paint_y * 2, 2 + 16); - } - } - - // 矢印を表示する - int x = ags->text_dest_x; - int y = ags->text_dest_y; - int color = ags->text_font_color; - ags->text_font_size = 24; - ags->text_font_color = 16; - - ags->text_dest_x = 456; - ags->text_dest_y = 103; - ags->draw_text(buf[param - 1]); - - ags->text_dest_x = x; - ags->text_dest_y = y; - ags->text_font_size = 16; - ags->text_font_color = color; - } else if(cmd == 2) { - ags->load_cg(74, -1); - ags->load_cg(81, -1); - map_page = 81; - } else if(cmd == 3) { - RND = (param == 0 || param == 1) ? 0 : random(param); - } else if(460 <= cmd && cmd <= 625 && 20 <= param && param <= 55) { - if(paint_x) { - ags->paint(paint_x, paint_y * 2, 5 + 16); - } - ags->paint(cmd, param * 2, 2 + 16); - paint_x = cmd; - paint_y = param; - } else { - paint_x = 0; - } - break; - - case CRC32_TENGU: - if(cmd == 10) { - // nop - } else if(cmd == 20) { - if(param == 20) { - ags->gcopy(8, 8, 46, 144, 2); - } else if(param == 21) { - ags->gcopy(8, 8, 46, 144, 3); - } - } - break; - } -} - - -// 下位関数 - -uint16 NACT_Sys1::cali() -{ - uint32 cali[256]; - int p = 1; - bool ok = false; - - while(p > 0) { - uint8 dat = getd(); - - // 除算はサポートしない? - if(0x80 <= dat && dat <= 0xbf) { - cali[p++] = var[dat & 0x3f]; - } else if(0xc0 <= dat && dat <= 0xff) { - cali[p++] = var[((dat & 0x3f) << 8) | getd()]; - } else if(0x00 <= dat && dat <= 0x3f) { - cali[p++] = ((dat & 0x3f) << 8) | getd(); - } else if(0x40 <= dat && dat <= 0x77) { - cali[p++] = dat & 0x3f; - } else if(dat == 0x78) { - cali[p - 2] = cali[p - 2] * cali[p - 1]; - if (cali[p - 2] > 65535) { - cali[p - 2] = 65535; - } - p--; - } else if(dat == 0x79) { - cali[p - 2] = cali[p - 2] + cali[p - 1]; - if (cali[p - 2] > 65535) { - cali[p - 2] = 65535; - } - p--; - } else if(dat == 0x7a) { - if(cali[p - 2] > cali[p - 1]) { - cali[p - 2] = cali[p - 2] - cali[p - 1]; - } else { - cali[p - 2] = 0; - } - p--; - } else if(dat == 0x7b) { - cali[p - 2] = (cali[p - 2] == cali[p - 1]) ? 1 : 0; - p--; - } else if(dat == 0x7c) { - cali[p - 2] = (cali[p - 2] < cali[p - 1]) ? 1 : 0; - p--; - } else if(dat == 0x7d) { - cali[p - 2] = (cali[p - 2] > cali[p - 1]) ? 1 : 0; - p--; - } else if(dat == 0x7e) { - cali[p - 2] = (cali[p - 2] != cali[p - 1]) ? 1 : 0; - p--; - } else if(dat == 0x7f) { - if(p == 2) { - ok = true; - } - p = 0; - } - } - if (!ok) { - fatal("cali: invalid expression"); - } - return (uint16)(cali[1] & 0xffff); -} - -uint16 NACT_Sys1::cali2() -{ - uint16 val = 0; - uint16 dat = getd(); - - if(0x80 <= dat && dat <= 0xbf) { - val = dat & 0x3f; - } else if(0xc0 <= dat && dat <= 0xff) { - val = ((dat & 0x3f) << 8) | getd(); - } else { - fatal("cali2: invalid expression"); - } - if(getd() != 0x7f) { - fatal("cali2: invalid expression"); - } - return val; -} +/* + ALICE SOFT SYSTEM1 for Win32 + + D.P.S. - Dream Program System + Intruder -桜屋敷の探索- + Little Vampire + あぶないてんぐ伝説 + クレセントムーンがぁる + 婦警さん物語VX + + [ NACT - command ] +*/ + +#include "nact.h" +#include "ags.h" +#include "mako.h" +#include "msgskip.h" +#include "crc32.h" +#include "../fileio.h" +#include "encoding.h" +#include "texthook.h" + +// メニューの改ページ +#define MENU_MAX (crc32_a == CRC32_INTRUDER ? 6 : 11) + +#define WAIT(tm) \ +{ \ + Uint32 dwTime = SDL_GetTicks() + (tm); \ + for(;;) { \ + if(terminate) { \ + return; \ + } \ + if(dwTime <= SDL_GetTicks()) { \ + break; \ + } \ + sys_sleep(16); \ + } \ +} + +#define WAIT_KEYQUIT(tm) \ +{ \ + Uint32 dwTime = SDL_GetTicks() + (tm); \ + for(;;) { \ + if(terminate) { \ + return; \ + } \ + if(get_key()) { \ + for(;;) { \ + if(terminate) { \ + return; \ + } \ + if(!get_key()) { \ + break; \ + } \ + if(dwTime <= SDL_GetTicks()) { \ + break; \ + } \ + sys_sleep(16); \ + } \ + break; \ + } \ + if(dwTime <= SDL_GetTicks()) { \ + break; \ + } \ + sys_sleep(16); \ + } \ +} + +NACT_Sys1::NACT_Sys1(uint32 crc32_a, uint32 crc32_b, const Config& config) + : NACT(1, crc32_a, crc32_b, config) +{ + switch (crc32_a) { + case CRC32_DPS: + case CRC32_DPS_SG: + //case CRC32_DPS_SG2: + case CRC32_DPS_SG3: + text_refresh = false; + strcpy(tvar[0], strings.dps_custom.c_str()); + strcpy(tvar[1], strings.dps_linus.c_str()); + strcpy(tvar[2], strings.dps_katsumi.c_str()); + strcpy(tvar[3], strings.dps_yumiko.c_str()); + strcpy(tvar[4], strings.dps_itsumi.c_str()); + strcpy(tvar[5], strings.dps_hitomi.c_str()); + strcpy(tvar[6], strings.dps_mariko.c_str()); + break; + case CRC32_INTRUDER: + paint_x = paint_y = map_page = 0; + break; + } +} + +void NACT_Sys1::opening() +{ + switch (crc32_a) { + case CRC32_CRESCENT: + mako->play_music(2); + ags->load_cg(1, -1); + WAIT(3000); + ags->load_cg(81, -1); + break; + case CRC32_INTRUDER: + ags->load_cg(77, -1); + WAIT(1667); + ags->load_cg(74, -1); + break; + case CRC32_VAMPIRE: + case CRC32_VAMPIRE_ENG: + mako->play_music(4); + ags->load_cg(3, -1); + WAIT(2000); + ags->load_cg(38, -1); + cmd_a(); + ags->draw_box(0); + break; + } +} + +void NACT_Sys1::cmd_calc() +{ + int index = getd(); + if(0x80 <= index && index <= 0xbf) { + index &= 0x3f; + } else { + index = ((index & 0x3f) << 8) | getd(); + } + var[index] = cali(); + + output_console("\n!var[%d]:%d!", index, var[index]); +} + +void NACT_Sys1::cmd_branch() +{ + int condition = cali(); + int nest = 0; + bool set_menu = false; + + if(!condition) { + // 次の'}'命令までスキップする(ネストも考慮する) + for(;;) { + prev_addr = scenario_addr; + uint8 cmd = getd(); + + if(cmd == '!') { + int index = getd(); + if(!(0x80 <= index && index <= 0xbf)) { + getd(); + } + cali(); + } else if(cmd == '{') { + cali(); + nest++; + } else if(cmd == '}') { + if(nest) { + nest--; + } else { + break; + } + } else if(cmd == '@') { + getw(); + } else if(cmd == '\\') { + getw(); + } else if(cmd == '&') { + cali(); + } else if(cmd == '%') { + cali(); + } else if(cmd == '$') { + if(!set_menu) { + getw(); + set_menu = true; + } else { + set_menu = false; + } + } else if(cmd == '[') { + getd(); + getd(); + getw(); + } else if(cmd == ':') { + cali(); + getd(); + getd(); + getw(); + } else if(cmd == ']') { + + } else if(cmd == 'A') { + + } else if(cmd == 'F') { + + } else if(cmd == 'G') { + getd(); + } else if(cmd == 'L') { + getd(); + } else if(cmd == 'P') { + getd(); + } else if(cmd == 'Q') { + getd(); + } else if(cmd == 'R') { + + } else if(cmd == 'S') { + getd(); + } else if(cmd == 'U') { + getd(); + getd(); + } else if(cmd == 'X') { + getd(); + } else if(cmd == 'Y') { + cali(); + cali(); + } else if(cmd == 'Z') { + cali(); + cali(); + } else if (cmd == '\'' || cmd == '"') { // SysEng + skip_string(cmd); + } else if (is_message(cmd)) { + ungetd(); + scenario_addr += encoding->mblen(scenario_data + scenario_addr); + } else if (cmd >= 0x20 && cmd < 0x7f) { + fatal("Unknown Command: '%c' at page = %d, addr = %d", cmd, scenario_page, prev_addr); + } else { + fatal("Unknown Command: %02x at page = %d, addr = %d", cmd, scenario_page, prev_addr); + } + } + } + + output_console("\n{%d:", condition); +} + +void NACT_Sys1::cmd_label_jump() +{ + int next_addr = getw(); + scenario_addr = next_addr; + + output_console("\n@%x:", next_addr); +} + +void NACT_Sys1::cmd_label_call() +{ + int next_addr = getw(); + + output_console("\n\\%x:", next_addr); + + if(next_addr == 0) { + // リターン + if(label_depth == 0) { +// fatal_error = true; + return; + } + scenario_addr = label_stack[--label_depth]; + } else { + label_stack[label_depth++] = scenario_addr; + scenario_addr = next_addr; + } +} + +void NACT_Sys1::cmd_page_jump() +{ + int next_page = cali(); + load_scenario(next_page); + scenario_page = next_page; + scenario_addr = 2; + + output_console("\n&%d:", next_page); +} + +void NACT_Sys1::cmd_page_call() +{ + int next_page = cali(), next_addr; + + output_console("\n%%%d:", next_page); + + if(next_page == 0) { + // リターン + if(page_depth == 0) { +// fatal_error = true; + return; + } + next_page = page_stack[--page_depth]; + next_addr = addr_stack[page_depth]; + } else { + page_stack[page_depth] = scenario_page; + addr_stack[page_depth++] = scenario_addr; + next_addr = 2; + } + load_scenario(next_page); + scenario_page = next_page; + scenario_addr = next_addr; +} + +void NACT_Sys1::cmd_set_menu() +{ + if(ags->draw_menu) { + ags->menu_dest_x = 2; + ags->menu_dest_y += ags->menu_font_size + 2; + ags->draw_menu = false; + + output_console("$"); + } else { + if(!menu_index) { + ags->clear_menu_window(); + ags->menu_dest_y = 0; + } + menu_addr[menu_index++] = getw(); + ags->menu_dest_x = 2; + ags->menu_dest_y += 2; + ags->draw_menu = true; + + output_console("\n$%x,", menu_addr[menu_index - 1]); + } +} + +void NACT_Sys1::cmd_open_menu() +{ + output_console("\n]"); + + if(!menu_index) { + scenario_addr = scenario_data[0] | (scenario_data[1] << 8); + return; + } + + if(crc32_a == CRC32_DPS || crc32_a == CRC32_DPS_SG || crc32_a == CRC32_DPS_SG2 || crc32_a == CRC32_DPS_SG3) { + if(!text_refresh) { + cmd_a(); + } + } + + int selection = menu_select(menu_index); + if (terminate) + return; + + if (selection != -1) { + scenario_addr = menu_addr[selection]; + } + menu_index = 0; +} + +void NACT_Sys1::cmd_set_verbobj() +{ + int verb = getd(); + int obj = getd(); + int addr = getw(); + + menu_addr[menu_index] = addr; + menu_verb[menu_index] = verb; + menu_obj[menu_index++] = obj; + verb_obj = true; + + output_console("\n[%x,%s,%s:", addr, caption_verb[verb], caption_obj[obj]); +} + +void NACT_Sys1::cmd_set_verbobj2() +{ + int condition = cali(); + int verb = getd(); + int obj = getd(); + int addr = getw(); + + if(condition) { + menu_addr[menu_index] = addr; + menu_verb[menu_index] = verb; + menu_obj[menu_index++] = obj; + } + verb_obj = true; + + output_console("\n:%d,%x,%s,%s:", condition, addr, caption_verb[verb], caption_obj[obj]); +} + +void NACT_Sys1::cmd_open_verb() +{ + // 動詞メニューの表示 + output_console("\nopen verb-obj menu"); + verb_obj = false; + + // 表示する動詞のチェック + int chk[MAX_VERB], page = 0, cnt = 0; + + memset(chk, 0, sizeof(chk)); + for(int i = 0; i < menu_index; i++) { + chk[menu_verb[i]] = 1; + } + for(int i = 0; i < MAX_VERB; i++) { + if(chk[i]) { + cnt++; + } + } + +top: + // メニュー項目の準備 + int id[32], index = 0; + + ags->clear_menu_window(); + ags->menu_dest_y = 0; + ags->draw_menu = true; + + if(cnt <= MENU_MAX) { + // 1ページ内に全て表示できる + for(int i = 0; i < MAX_VERB; i++) { + if(chk[i]) { + ags->menu_dest_x = 2; + ags->menu_dest_y += 2; + ags->draw_text(caption_verb[i]); + id[index++] = i; + ags->menu_dest_y += ags->menu_font_size + 2; + } + } + } else { +top2: + for(int i = page; i < MAX_VERB; i++) { + if(chk[i]) { + ags->menu_dest_x = 2; + ags->menu_dest_y += 2; + ags->draw_text(caption_verb[i]); + id[index++] = i; + ags->menu_dest_y += ags->menu_font_size + 2; + } + page = i + 1; + if(index == MENU_MAX - 1) { + break; + } + } + if(index == 0) { + // 最初のページに戻る + page = 0; + goto top2; + } + // 次のページを追加 + ags->menu_dest_x = 2; + ags->menu_dest_y += 2; + ags->draw_text(strings.next_page.c_str()); + id[index++] = -1; + ags->menu_dest_y += ags->menu_font_size + 2; + } + ags->draw_menu = false; + + int selection = menu_select(index); + if (terminate) + return; + + if(selection == -1) { + scenario_addr = scenario_data[0] | (scenario_data[1] << 8); + } else if(id[selection] == -1) { + goto top; + } else { + cmd_open_obj(id[selection]); + } + menu_index = 0; +} + +void NACT_Sys1::cmd_open_obj(int verb) +{ + // 目的語メニューの表示 + verb_obj = false; + + // 表示する目的語のチェック + int chk[MAX_OBJ], addr[MAX_OBJ], page = 0, cnt = 0; + + memset(chk, 0, sizeof(chk)); + for(int i = 0; i < menu_index; i++) { + if(menu_verb[i] == verb) { + chk[menu_obj[i]] = 1; + addr[menu_obj[i]] = menu_addr[i]; + } + } + for(int i = 0; i < MAX_OBJ; i++) { + if(chk[i]) { + cnt++; + } + } + // 目的語がない場合 + if(chk[0] && cnt == 1) { + scenario_addr = addr[0]; + return; + } + // 以後、obj=0は戻るとして扱う + chk[0] = 0; + addr[0] = scenario_data[0] | (scenario_data[1] << 8); + +top: + // メニュー項目の準備 + int id[32], index = 0; + + ags->clear_menu_window(); + ags->menu_dest_y = 0; + ags->draw_menu = true; + + if(cnt <= MENU_MAX - 1) { + // 1ページ内に全て表示できる + for(int i = 0; i < MAX_OBJ; i++) { + if(chk[i]) { + ags->menu_dest_x = 2; + ags->menu_dest_y += 2; + ags->draw_text(caption_obj[i]); + id[index++] = i; + ags->menu_dest_y += ags->menu_font_size + 2; + } + } + // 戻るを追加 + ags->menu_dest_x = 2; + ags->menu_dest_y += 2; + ags->draw_text(strings.back.c_str()); + id[index++] = 0; + ags->menu_dest_y += ags->menu_font_size + 2; + } else { +top2: + for(int i = page; i < MAX_OBJ; i++) { + if(chk[i]) { + ags->menu_dest_x = 2; + ags->menu_dest_y += 2; + ags->draw_text(caption_obj[i]); + id[index++] = i; + ags->menu_dest_y += ags->menu_font_size + 2; + } + page = i + 1; + if(index == MENU_MAX - 2) { + break; + } + } + if(index == 0) { + // 最初のページに戻る + page = 0; + goto top2; + } + // 戻るを追加 + ags->menu_dest_x = 2; + ags->menu_dest_y += 2; + ags->draw_text(strings.back.c_str()); + id[index++] = 0; + ags->menu_dest_y += ags->menu_font_size + 2; + + // 次のページを追加 + ags->menu_dest_x = 2; + ags->menu_dest_y += 2; + ags->draw_text(strings.next_page.c_str()); + id[index++] = -1; + ags->menu_dest_y += ags->menu_font_size + 2; + } + ags->draw_menu = false; + + int selection = menu_select(index); + if (terminate) + return; + + if(selection == -1) { + scenario_addr = scenario_data[0] | (scenario_data[1] << 8); + } else if(id[selection] == -1) { + goto top; + } else { + scenario_addr = addr[id[selection]]; + } +} + +void NACT_Sys1::cmd_a() +{ + texthook_nextpage(); + + output_console("A\n"); + + if (msgskip->skipping()) { + if (msgskip->get_flags() & MSGSKIP_STOP_ON_CLICK && get_key()) + msgskip->activate(false); + } else if (show_push) { + ags->draw_push(text_window); + } + + // キーが押されて離されるまで待機 + while (!msgskip->skipping()) { + if(terminate) { + return; + } + if(get_key()) { + break; + } + sys_sleep(16); + } + sys_sleep(30); + while (!msgskip->skipping()) { + if(terminate) { + return; + } + if(!(get_key() & 0x18)) { + break; + } + sys_sleep(16); + } + + // ウィンドウ更新 + ags->clear_text_window(text_window, true); + + if(crc32_a == CRC32_DPS || crc32_a == CRC32_DPS_SG || crc32_a == CRC32_DPS_SG2 || crc32_a == CRC32_DPS_SG3) { + text_refresh = true; + } +} + +void NACT_Sys1::cmd_b() +{ + // 未使用 + fatal("Unknown Command: 'B' at page = %d, addr = %d", scenario_page, prev_addr); +} + +void NACT_Sys1::cmd_d() +{ + // 未使用 + fatal("Unknown Command: 'D' at page = %d, addr = %d", scenario_page, prev_addr); +} + +void NACT_Sys1::cmd_e() +{ + // 未使用 + fatal("Unknown Command: 'E' at page = %d, addr = %d", scenario_page, prev_addr); +} + +void NACT_Sys1::cmd_f() +{ + output_console("\nF"); + + scenario_addr = 2; +} + +void NACT_Sys1::cmd_g() +{ + int page = getd(); + + output_console("\nG %d:", page); + + if(crc32_a == CRC32_INTRUDER) { + page = (page == 97) ? 96 : (page == 98) ? 97 : page; + } + + ags->load_cg(page, -1); + + if(crc32_a == CRC32_INTRUDER) { + if(page == 94) { + WAIT(400); + } + if(page == 81 || page == 82) { + map_page = page; + } + } +} + +void NACT_Sys1::cmd_h() +{ + // 未使用 + fatal("Unknown Command: 'H' at page = %d, addr = %d", scenario_page, prev_addr); +} + +void NACT_Sys1::cmd_i() +{ + // 未使用 + fatal("Unknown Command: 'I' at page = %d, addr = %d", scenario_page, prev_addr); +} + +void NACT_Sys1::cmd_j() +{ + // 未使用 + fatal("Unknown Command: 'J' at page = %d, addr = %d", scenario_page, prev_addr); +} + +void NACT_Sys1::cmd_k() +{ + // 未使用 + fatal("Unknown Command: 'K' at page = %d, addr = %d", scenario_page, prev_addr); +} + +void NACT_Sys1::cmd_l() +{ + int index = getd(); + + output_console("\nL %d:", index); + + if(1 <= index && index <= 26) { + // ASLEEP_A.DAT - ASLEEP_Z.DAT + char file_name[_MAX_PATH]; + sprintf_s(file_name, _MAX_PATH, "ASLEEP_%c.DAT", 'A' + index - 1); + + FILEIO* fio = new FILEIO(); + if(fio->Fopen(file_name, FILEIO_READ_BINARY | FILEIO_SAVEDATA)) { + fio->Fseek(112, FILEIO_SEEK_SET); + + int next_page = fio->Fgetw() - 1; + fio->Fgetw(); + fio->Fgetw(); // cg no? + fio->Fgetw(); + int next_music = fio->Fgetw(); + fio->Fgetw(); + int next_addr = fio->Fgetw(); + fio->Fgetw(); + for(int i = 0; i < 512; i++) { + var[i] = fio->Fgetw(); + } + ags->menu_font_size = fio->Fgetw(); + ags->text_font_size = fio->Fgetw(); + ags->palette_bank = fio->Fgetw(); + if(!ags->palette_bank) { + ags->palette_bank = -1; + } + ags->text_font_color = fio->Fgetw(); + ags->menu_font_color = fio->Fgetw(); + ags->menu_frame_color = fio->Fgetw(); + ags->menu_back_color = fio->Fgetw(); + ags->text_frame_color = fio->Fgetw(); + ags->text_back_color = fio->Fgetw(); + for(int i = 0; i < 10; i++) { + ags->menu_w[i].sx = fio->Fgetw(); + ags->menu_w[i].sy = fio->Fgetw(); + ags->menu_w[i].ex = fio->Fgetw(); + ags->menu_w[i].ey = fio->Fgetw(); + ags->menu_w[i].push = fio->Fgetw() ? true : false; + ags->menu_w[i].frame = fio->Fgetw() ? true : false; + fio->Fgetw(); + fio->Fgetw(); + + if(ags->menu_w[i].screen) { + free(ags->menu_w[i].screen); + } + ags->menu_w[i].screen = NULL; + if(ags->menu_w[i].window) { + free(ags->menu_w[i].window); + } + ags->menu_w[i].window = NULL; + } + for(int i = 0; i < 10; i++) { + ags->text_w[i].sx = fio->Fgetw(); + ags->text_w[i].sy = fio->Fgetw(); + ags->text_w[i].ex = fio->Fgetw(); + ags->text_w[i].ey = fio->Fgetw(); + ags->text_w[i].push = fio->Fgetw() ? true : false; + ags->text_w[i].frame = fio->Fgetw() ? true : false; + fio->Fgetw(); + fio->Fgetw(); + + if(ags->text_w[i].screen) { + free(ags->text_w[i].screen); + } + ags->text_w[i].screen = NULL; + if(ags->text_w[i].window) { + free(ags->text_w[i].window); + } + ags->text_w[i].window = NULL; + } + for(int i = 0; i < 10; i++) { + fio->Fread(tvar[i], 22, 1); + } + for(int i = 0; i < 30; i++) { + for(int j = 0; j < 10; j++) { + fio->Fread(tvar_stack[i][j], 22, 1); + } + } + for(int i = 0; i < 30; i++) { + for(int j = 0; j < 20; j++) { + var_stack[i][j] = fio->Fgetw(); + } + } + fio->Fclose(); + + load_scenario(next_page); + scenario_page = next_page; + scenario_addr = next_addr; + + mako->play_music(next_music); + } + delete fio; + } +} + +void NACT_Sys1::cmd_m() +{ + // 未使用 + fatal("Unknown Command: 'M' at page = %d, addr = %d", scenario_page, prev_addr); +} + +void NACT_Sys1::cmd_n() +{ + // 未使用 + fatal("Unknown Command: 'N' at page = %d, addr = %d", scenario_page, prev_addr); +} + +void NACT_Sys1::cmd_o() +{ + // 未使用 + fatal("Unknown Command: 'O' at page = %d, addr = %d", scenario_page, prev_addr); +} + +void NACT_Sys1::cmd_p() +{ + int param = getd(); + + ags->text_font_color = (uint8)((param & 0x7) + 16); + + output_console("\nP %d:", param); +} + +#define FWRITE(data, size) { \ + memcpy(&buffer[p], data, size); \ + p += size; \ +} +#define FPUTW(data) { \ + uint16 tmp = (data); \ + buffer[p++] = tmp & 0xff; \ + buffer[p++] = (tmp >> 8) & 0xff; \ +} + +void NACT_Sys1::cmd_q() +{ + static char header[112] = { + 'T', 'h', 'i', 's', ' ', 'i', 's', ' ', 's', 'a', 'v', 'e', ' ', 'd', 'a', 't', + 'a', ' ', 'f', 'o', 'r', ' ', 'S', 'y', 's', 't', 'e', 'm', '1', ' ', ' ', 'U', + 'n', 'i', 'o', 'n', ' ', '[', 'W', 'i', 'n', '9', 'x', '/', 'N', 'T', '4', '0', + '/', '2', '0', '0', '0', '/', 'X', 'P', '/', 'C', 'E', ']', ' ', 'F', 'o', 'r', + ' ', 'N', 'A', 'C', 'T', '/', 'A', 'D', 'V', ' ', 's', 'y', 's', 't', 'e', 'm', + ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', '(', 'C', ')', '2', '0', '0', + '4', ' ', 'A', 'L', 'I', 'C', 'E', '-', 'S', 'O', 'F', 'T', ' ', ' ', ' ', ' ' + }; + + int index = getd(); + + output_console("\nQ %d:", index); + + if(1 <= index && index <= 26) { + // ASLEEP_A.DAT - ASLEEP_Z.DAT + char file_name[_MAX_PATH]; + sprintf_s(file_name, _MAX_PATH, "ASLEEP_%c.DAT", 'A' + index - 1); + + FILEIO* fio = new FILEIO(); + if(fio->Fopen(file_name, FILEIO_WRITE_BINARY | FILEIO_SAVEDATA)) { + uint8 buffer[9510]; + int p = 0; + + FWRITE(header, 112); + FPUTW(scenario_page + 1); + FPUTW(0); + FPUTW(0); // cg no? + FPUTW(0); + FPUTW(mako->current_music); + FPUTW(0); + FPUTW(scenario_addr); + FPUTW(0); + for(int i = 0; i < 512; i++) { + FPUTW(var[i]); + } + FPUTW(ags->menu_font_size); + FPUTW(ags->text_font_size); + FPUTW(ags->palette_bank == -1 ? 0 : ags->palette_bank); + FPUTW(ags->text_font_color); + FPUTW(ags->menu_font_color); + FPUTW(ags->menu_frame_color); + FPUTW(ags->menu_back_color); + FPUTW(ags->text_frame_color); + FPUTW(ags->text_back_color); + for(int i = 0; i < 10; i++) { + FPUTW(ags->menu_w[i].sx); + FPUTW(ags->menu_w[i].sy); + FPUTW(ags->menu_w[i].ex); + FPUTW(ags->menu_w[i].ey); + FPUTW(ags->menu_w[i].push ? 1 : 0); + FPUTW(ags->menu_w[i].frame ? 1 : 0); + FPUTW(0); + FPUTW(0); + } + for(int i = 0; i < 10; i++) { + FPUTW(ags->text_w[i].sx); + FPUTW(ags->text_w[i].sy); + FPUTW(ags->text_w[i].ex); + FPUTW(ags->text_w[i].ey); + FPUTW(ags->text_w[i].push ? 1 : 0); + FPUTW(ags->text_w[i].frame ? 1 : 0); + FPUTW(0); + FPUTW(0); + } + for(int i = 0; i < 10; i++) { + FWRITE(tvar[i], 22); + } + for(int i = 0; i < 30; i++) { + for(int j = 0; j < 10; j++) { + FWRITE(tvar_stack[i][j], 22); + } + } + for(int i = 0; i < 30; i++) { + for(int j = 0; j < 20; j++) { + FPUTW(var_stack[i][j]); + } + } + + fio->Fwrite(buffer, 9510, 1); + fio->Fclose(); + } + delete fio; + } +} + +void NACT_Sys1::cmd_r() +{ + texthook_newline(); + + output_console("R\n"); + + // ウィンドウの表示範囲外の場合は改ページ + if(ags->return_text_line(text_window)) { + cmd_a(); + } +} + +void NACT_Sys1::cmd_s() +{ + int page = getd(); + + output_console("\nS %d:", page); + + if(page) { + mako->play_music(page); + } else { + mako->stop_music(); + } +} + +void NACT_Sys1::cmd_t() +{ + // 未使用 + fatal("Unknown Command: 'T' at page = %d, addr = %d", scenario_page, prev_addr); +} + +void NACT_Sys1::cmd_u() +{ + int page = getd(); + int transparent = getd(); + + output_console("\nU %d,%d:", page, transparent); + + if(crc32_a == CRC32_INTRUDER) { + ags->load_cg(page, 11); + + if(page == 5) { + WAIT(400); + } + } else { + ags->load_cg(page, transparent); + } +} + +void NACT_Sys1::cmd_v() +{ + // 未使用 + fatal("Unknown Command: 'V' at page = %d, addr = %d", scenario_page, prev_addr); +} + +void NACT_Sys1::cmd_w() +{ + // 未使用 + fatal("Unknown Command: 'W' at page = %d, addr = %d", scenario_page, prev_addr); +} + +void NACT_Sys1::cmd_x() +{ + int index = getd(); + + output_console("\nX %d:", index); + + if(1 <= index && index <= 10) { + ags->draw_text(tvar[index - 1]); + } +} + +void NACT_Sys1::cmd_y() +{ + int cmd = cali(); + int param = cali(); + + output_console("\nY %d,%d:", cmd, param); + + if(crc32_a == CRC32_INTRUDER) { + switch(cmd) { + case 0: + ags->clear_text_window(text_window, true); + break; + case 1: + if(show_push) { + ags->draw_push(text_window); + } + for(;;) { + if(terminate) { + return; + } + if(get_key()) { + break; + } + sys_sleep(16); + } + sys_sleep(100); + for(;;) { + if(terminate) { + return; + } + if(!(get_key() & 0x18)) { + break; + } + sys_sleep(16); + } + ags->clear_text_window(text_window, true); + break; + case 2: + if(param == 0) { + post_quit = true; + fatal_error = true; + } else { + WAIT(100) + } + break; + case 3: + WAIT(param * 1000) + break; + case 255: + post_quit = true; + fatal_error = true; + break; + } + } else { + switch(cmd) { + case 0: + ags->clear_text_window(text_window, true); + break; + case 1: + { + char buf[16]; + buf[0] = '0' + (int)(param / 10000); + param %= 10000; + buf[1] = '0' + (int)(param / 1000); + param %= 1000; + buf[2] = '0' + (int)(param / 100); + param %= 100; + buf[3] = '0' + (int)(param / 10); + buf[4] = '0' + (param % 10); + buf[5] = '\0'; + + int p = 0; + for(;;) { + if(buf[p] != '0') { + break; + } + p++; + } + ags->draw_text(&buf[p < 4 ? p : 4]); + } + break; + case 2: + if(crc32_a == CRC32_CRESCENT) { + for(int i = 39; i <= 48; i++) { + var[i] = 0; + } + } else if(crc32_a == CRC32_DPS || crc32_a == CRC32_DPS_SG || crc32_a == CRC32_DPS_SG2 || crc32_a == CRC32_DPS_SG3) { + for(int i = 0; i <= 20; i++) { + var[i] = 0; + } + } else { + for(int i = 0; i <= 16; i++) { + var[i] = 0; + } + } + break; + case 3: + WAIT(param * 1000 / 60) + break; + case 4: + RND = (param == 0 || param == 1) ? 0 : random(param); + break; + case 7: + if(crc32_a == CRC32_DPS || crc32_a == CRC32_DPS_SG || crc32_a == CRC32_DPS_SG2 || crc32_a == CRC32_DPS_SG3) { + if(param == 1) { + ags->box_fill(0, 40, 8, 598, 270, 0); + } + } + break; + case 130: + if(crc32_a == CRC32_TENGU) { + WAIT(2000) + ags->load_cg(180, -1); + + WAIT(2000) + ags->draw_box(0); + ags->dest_screen = 1; + ags->load_cg(173, -1); + ags->dest_screen = 0; + ags->gcopy(0x1ecd, 0x3a2a, 8, 60, 3); + WAIT(667); + ags->gcopy(0x1b65, 0x262e, 8, 60, 3); + ags->gcopy(0x2e25, 0x38ee, 7, 9, 3); + WAIT(667); + ags->gcopy(0x1914, 0x1914, 8, 63, 3); + WAIT(667); + ags->gcopy(0x182c, 0x182c, 7, 50, 3); + WAIT(667); + ags->gcopy(0x0000, 0x1ecd, 32, 60, 1); + WAIT(667); + for(int i = 12; i <= 57; i++) { + ags->gcopy(i + 0x2306, i + 0x2306, 1, 165, 3); + } + WAIT_KEYQUIT(6000) + ags->draw_box(param); + } + break; + case 240: + ags->draw_hankaku = (param == 1) ? true : false; + break; + case 253: + post_quit = false; + fatal_error = true; + break; + case 254: + RND = 0; + break; + case 255: + if(crc32_a == CRC32_DPS || crc32_a == CRC32_DPS_SG || crc32_a == CRC32_DPS_SG2 || crc32_a == CRC32_DPS_SG3) { + post_quit = false; + } else { + post_quit = true; + } + fatal_error = true; + break; + } + } +} + +void NACT_Sys1::cmd_z() +{ + if (crc32_a == CRC32_CRESCENT) { + cmd_y(); + return; + } + int cmd = cali(); + int param = cali(); + + output_console("\nZ %d,%d:", cmd, param); + + switch (crc32_a) { + case CRC32_INTRUDER: + if(cmd == 1 && 1 <= param && param <= 4) { + const char* buf[4] = { + "\x81\x83", // "<" in SJIS + "\x81\xC8", // "∧" in SJIS + "\x81\x84", // ">" in SJIS + "\x81\xC9", // "∨" in SJIS + }; + + // 矢印を消去する + if(map_page) { + ags->load_cg(map_page, -1); + if(paint_x) { + ags->paint(paint_x, paint_y * 2, 2 + 16); + } + } + + // 矢印を表示する + int x = ags->text_dest_x; + int y = ags->text_dest_y; + int color = ags->text_font_color; + ags->text_font_size = 24; + ags->text_font_color = 16; + + ags->text_dest_x = 456; + ags->text_dest_y = 103; + ags->draw_text(buf[param - 1]); + + ags->text_dest_x = x; + ags->text_dest_y = y; + ags->text_font_size = 16; + ags->text_font_color = color; + } else if(cmd == 2) { + ags->load_cg(74, -1); + ags->load_cg(81, -1); + map_page = 81; + } else if(cmd == 3) { + RND = (param == 0 || param == 1) ? 0 : random(param); + } else if(460 <= cmd && cmd <= 625 && 20 <= param && param <= 55) { + if(paint_x) { + ags->paint(paint_x, paint_y * 2, 5 + 16); + } + ags->paint(cmd, param * 2, 2 + 16); + paint_x = cmd; + paint_y = param; + } else { + paint_x = 0; + } + break; + + case CRC32_TENGU: + if(cmd == 10) { + // nop + } else if(cmd == 20) { + if(param == 20) { + ags->gcopy(8, 8, 46, 144, 2); + } else if(param == 21) { + ags->gcopy(8, 8, 46, 144, 3); + } + } + break; + } +} + + +// 下位関数 + +uint16 NACT_Sys1::cali() +{ + uint32 cali[256]; + int p = 1; + bool ok = false; + + while(p > 0) { + uint8 dat = getd(); + + // 除算はサポートしない? + if(0x80 <= dat && dat <= 0xbf) { + cali[p++] = var[dat & 0x3f]; + } else if(0xc0 <= dat && dat <= 0xff) { + cali[p++] = var[((dat & 0x3f) << 8) | getd()]; + } else if(0x00 <= dat && dat <= 0x3f) { + cali[p++] = ((dat & 0x3f) << 8) | getd(); + } else if(0x40 <= dat && dat <= 0x77) { + cali[p++] = dat & 0x3f; + } else if(dat == 0x78) { + cali[p - 2] = cali[p - 2] * cali[p - 1]; + if (cali[p - 2] > 65535) { + cali[p - 2] = 65535; + } + p--; + } else if(dat == 0x79) { + cali[p - 2] = cali[p - 2] + cali[p - 1]; + if (cali[p - 2] > 65535) { + cali[p - 2] = 65535; + } + p--; + } else if(dat == 0x7a) { + if(cali[p - 2] > cali[p - 1]) { + cali[p - 2] = cali[p - 2] - cali[p - 1]; + } else { + cali[p - 2] = 0; + } + p--; + } else if(dat == 0x7b) { + cali[p - 2] = (cali[p - 2] == cali[p - 1]) ? 1 : 0; + p--; + } else if(dat == 0x7c) { + cali[p - 2] = (cali[p - 2] < cali[p - 1]) ? 1 : 0; + p--; + } else if(dat == 0x7d) { + cali[p - 2] = (cali[p - 2] > cali[p - 1]) ? 1 : 0; + p--; + } else if(dat == 0x7e) { + cali[p - 2] = (cali[p - 2] != cali[p - 1]) ? 1 : 0; + p--; + } else if(dat == 0x7f) { + if(p == 2) { + ok = true; + } + p = 0; + } + } + if (!ok) { + fatal("cali: invalid expression"); + } + return (uint16)(cali[1] & 0xffff); +} + +uint16 NACT_Sys1::cali2() +{ + uint16 val = 0; + uint16 dat = getd(); + + if(0x80 <= dat && dat <= 0xbf) { + val = dat & 0x3f; + } else if(0xc0 <= dat && dat <= 0xff) { + val = ((dat & 0x3f) << 8) | getd(); + } else { + fatal("cali2: invalid expression"); + } + if(getd() != 0x7f) { + fatal("cali2: invalid expression"); + } + return val; +} diff --git a/src/sys/nact_sys2.cpp b/src/sys/nact_sys2.cpp index f9aee42..649c6db 100644 --- a/src/sys/nact_sys2.cpp +++ b/src/sys/nact_sys2.cpp @@ -1,1367 +1,1367 @@ -/* - ALICE SOFT SYSTEM2 for Win32 - - Super D.P.S. - Dream Program System - - [ NACT - command ] -*/ - -#include "nact.h" -#include "ags.h" -#include "mako.h" -#include "msgskip.h" -#include "crc32.h" -#include "../fileio.h" -#include "encoding.h" -#include "texthook.h" - -#define WAIT(tm) \ -{ \ - Uint32 dwTime = SDL_GetTicks() + (tm); \ - for(;;) { \ - if(terminate) { \ - return; \ - } \ - if(dwTime <= SDL_GetTicks()) { \ - break; \ - } \ - sys_sleep(16); \ - } \ -} - -#define WAIT_KEYQUIT(tm) \ -{ \ - Uint32 dwTime = SDL_GetTicks() + (tm); \ - for(;;) { \ - if(terminate) { \ - return; \ - } \ - if(get_key()) { \ - for(;;) { \ - if(terminate) { \ - return; \ - } \ - if(!get_key()) { \ - break; \ - } \ - if(dwTime <= SDL_GetTicks()) { \ - break; \ - } \ - sys_sleep(16); \ - } \ - break; \ - } \ - if(dwTime <= SDL_GetTicks()) { \ - break; \ - } \ - sys_sleep(16); \ - } \ -} - -NACT_Sys2::NACT_Sys2(uint32 crc32_a, uint32 crc32_b, const Config& config) - : NACT(2, crc32_a, crc32_b, config) -{ -} - -void NACT_Sys2::cmd_calc() -{ - int index = getd(); - if(0x80 <= index && index <= 0xbf) { - index &= 0x3f; - } else { - index = ((index & 0x3f) << 8) | getd(); - } - var[index] = cali(); - - output_console("\n!var[%d]:%d!", index, var[index]); -} - -void NACT_Sys2::cmd_branch() -{ - int condition = cali(); - int nest = 0; - bool set_menu = false; - - if(!condition) { - // 次の'}'命令までスキップする(ネストも考慮する) - for(;;) { - prev_addr = scenario_addr; - uint8 cmd = getd(); - - if(cmd == '!') { - int index = getd(); - if(!(0x80 <= index && index <= 0xbf)) { - getd(); - } - cali(); - } else if(cmd == '{') { - cali(); - nest++; - } else if(cmd == '}') { - if(nest) { - nest--; - } else { - break; - } - } else if(cmd == '@') { - getw(); - } else if(cmd == '\\') { - getw(); - } else if(cmd == '&') { - cali(); - } else if(cmd == '%') { - cali(); - } else if(cmd == '$') { - if(!set_menu) { - getw(); - set_menu = true; - } else { - set_menu = false; - } - } else if(cmd == '[') { - getd(); - getd(); - getw(); - } else if(cmd == ':') { - cali(); - getd(); - getd(); - getw(); - } else if(cmd == ']') { - - } else if(cmd == 'A') { - - } else if(cmd == 'B') { - cali(); - cali(); - cali(); - cali(); - cali(); - cali(); - cali(); - } else if(cmd == 'D') { - cali(); - cali(); - cali(); - cali(); - cali(); - cali(); - cali(); - cali(); - } else if(cmd == 'E') { - cali(); - cali(); - cali(); - } else if(cmd == 'F') { - - } else if(cmd == 'G') { - cali(); - } else if(cmd == 'H') { - getd(); - cali(); - } else if(cmd == 'I') { - cali(); - cali(); -// getd(); - cali(); - } else if(cmd == 'J') { - cali(); - cali(); - } else if(cmd == 'K') { - - } else if(cmd == 'L') { - getd(); - } else if(cmd == 'M') { - uint8 val = getd(); - if (val == '\'' || val == '"') { // SysEng - skip_string(val); - } else { - while (val != ':') - val = getd(); - } - } else if(cmd == 'N') { - cali(); - cali(); - } else if(cmd == 'O') { - cali(); - cali(); - cali(); - } else if(cmd == 'P') { - getd(); - } else if(cmd == 'Q') { - getd(); - } else if(cmd == 'R') { - - } else if(cmd == 'S') { - getd(); - } else if(cmd == 'T') { - cali(); - cali(); - cali(); - } else if(cmd == 'U') { - if(crc32_a == CRC32_YAKATA2) { - cali(); - cali(); - } else { - getd(); - getd(); - } - } else if(cmd == 'V') { -#if 1 - cali(); - cali(); - cali(); - cali(); - cali(); - cali(); - cali(); - cali(); - cali(); - cali(); - cali(); - cali(); - cali(); - cali(); - cali(); - cali(); - cali(); - cali(); - cali(); - cali(); - cali(); - cali(); - cali(); - cali(); - cali(); - cali(); - cali(); - cali(); - cali(); -#else - cali(); - cali(); -#endif - } else if(cmd == 'W') { - cali(); - cali(); - cali(); - cali(); - } else if(cmd == 'X') { - getd(); - } else if(cmd == 'Y') { - cali(); - cali(); - } else if(cmd == 'Z') { - cali(); - cali(); - } else if (cmd == '\'' || cmd == '"') { // SysEng - skip_string(cmd); - } else if (is_message(cmd)) { - ungetd(); - scenario_addr += encoding->mblen(scenario_data + scenario_addr); - } else if (cmd >= 0x20 && cmd < 0x7f) { - fatal("Unknown Command: '%c' at page = %d, addr = %d", cmd, scenario_page, prev_addr); - } else { - fatal("Unknown Command: %02x at page = %d, addr = %d", cmd, scenario_page, prev_addr); - } - } - } - - output_console("\n{%d:", condition); -} - -void NACT_Sys2::cmd_label_jump() -{ - int next_addr = getw(); - scenario_addr = next_addr; - - output_console("\n@%x:", next_addr); -} - -void NACT_Sys2::cmd_label_call() -{ - int next_addr = getw(); - - output_console("\n\\%x:", next_addr); - - if(next_addr == 0) { - // リターン - if(label_depth == 0) { -// fatal_error = true; - return; - } - scenario_addr = label_stack[--label_depth]; - } else { - label_stack[label_depth++] = scenario_addr; - scenario_addr = next_addr; - } -} - -void NACT_Sys2::cmd_page_jump() -{ - int next_page = cali(); - load_scenario(next_page); - scenario_page = next_page; - scenario_addr = 2; - - output_console("\n&%d:", next_page); -} - -void NACT_Sys2::cmd_page_call() -{ - int next_page = cali(), next_addr; - - output_console("\n%%%d:", next_page); - - if(next_page == 0) { - // リターン - if(page_depth == 0) { -// fatal_error = true; - return; - } - next_page = page_stack[--page_depth]; - next_addr = addr_stack[page_depth]; - } else { - page_stack[page_depth] = scenario_page; - addr_stack[page_depth++] = scenario_addr; - next_addr = 2; - } - load_scenario(next_page); - scenario_page = next_page; - scenario_addr = next_addr; -} - -void NACT_Sys2::cmd_set_menu() -{ - if(ags->draw_menu) { - ags->menu_dest_x = 2; - ags->menu_dest_y += ags->menu_font_size + 2; - ags->draw_menu = false; - - output_console("$"); - } else { - if(!menu_index) { - ags->clear_menu_window(); - ags->menu_dest_y = 0; - } - menu_addr[menu_index++] = getw(); - ags->menu_dest_x = 2; - ags->menu_dest_y += 2; - ags->draw_menu = true; - - output_console("\n$%x,", menu_addr[menu_index - 1]); - } -} - -void NACT_Sys2::cmd_open_menu() -{ - output_console("\n]"); - - if(!menu_index) { - scenario_addr = scenario_data[0] | (scenario_data[1] << 8); - return; - } - - int selection = menu_select(menu_index); - if (terminate) - return; - - if (selection != -1) { - scenario_addr = menu_addr[selection]; - } - menu_index = 0; -} - -void NACT_Sys2::cmd_set_verbobj() -{ - int verb = getd(); - int obj = getd(); - int addr = getw(); - - menu_addr[menu_index] = addr; - menu_verb[menu_index] = verb; - menu_obj[menu_index++] = obj; - verb_obj = true; - - output_console("\n[%x,%s,%s:", addr, caption_verb[verb], caption_obj[obj]); -} - -void NACT_Sys2::cmd_set_verbobj2() -{ - int condition = cali(); - int verb = getd(); - int obj = getd(); - int addr = getw(); - - if(condition) { - menu_addr[menu_index] = addr; - menu_verb[menu_index] = verb; - menu_obj[menu_index++] = obj; - } - verb_obj = true; - - output_console("\n:%d,%x,%s,%s:", condition, addr, caption_verb[verb], caption_obj[obj]); -} - -void NACT_Sys2::cmd_open_verb() -{ - // 動詞メニューの表示 - output_console("\nopen verb-obj menu"); - verb_obj = false; - - // 表示する動詞のチェック - int chk[MAX_VERB], page = 0; - - memset(chk, 0, sizeof(chk)); - for(int i = 0; i < menu_index; i++) { - chk[menu_verb[i]] = 1; - } - - // メニュー項目の準備 - int id[32], index = 0; - - ags->clear_menu_window(); - ags->menu_dest_y = 0; - ags->draw_menu = true; - - for(int i = 0; i < MAX_VERB; i++) { - if(chk[i]) { - ags->menu_dest_x = 2; - ags->menu_dest_y += 2; - ags->draw_text(caption_verb[i]); - id[index++] = i; - ags->menu_dest_y += ags->menu_font_size + 2; - } - } - ags->draw_menu = false; - - int selection = menu_select(index); - if (terminate) - return; - - if(selection == -1) { - scenario_addr = scenario_data[0] | (scenario_data[1] << 8); - } else { - cmd_open_obj(id[selection]); - } - menu_index = 0; -} - -void NACT_Sys2::cmd_open_obj(int verb) -{ - // 目的語メニューの表示 - verb_obj = false; - - // 表示する目的語のチェック - int chk[MAX_OBJ], addr[MAX_OBJ], page = 0; - - memset(chk, 0, sizeof(chk)); - for(int i = 0; i < menu_index; i++) { - if(menu_verb[i] == verb) { - chk[menu_obj[i]] = 1; - addr[menu_obj[i]] = menu_addr[i]; - } - } - // 目的語がない場合 - if(chk[0]) { - scenario_addr = addr[0]; - return; - } - // 以後、obj=0は戻るとして扱う - chk[0] = 0; - addr[0] = scenario_data[0] | (scenario_data[1] << 8); - - // メニュー項目の準備 - int id[32], index = 0; - - ags->clear_menu_window(); - ags->menu_dest_y = 0; - ags->draw_menu = true; - - for(int i = 0; i < MAX_OBJ; i++) { - if(chk[i]) { - ags->menu_dest_x = 2; - ags->menu_dest_y += 2; - ags->draw_text(caption_obj[i]); - id[index++] = i; - ags->menu_dest_y += ags->menu_font_size + 2; - } - } - // 戻るを追加 - ags->menu_dest_x = 2; - ags->menu_dest_y += 2; - ags->draw_text(strings.back.c_str()); - id[index++] = 0; - ags->menu_dest_y += ags->menu_font_size + 2; - ags->draw_menu = false; - - int selection = menu_select(index); - if (terminate) - return; - - if(selection == -1) { - scenario_addr = scenario_data[0] | (scenario_data[1] << 8); - } else { - scenario_addr = addr[id[selection]]; - } -} - -void NACT_Sys2::cmd_a() -{ - texthook_nextpage(); - - output_console("A\n"); - - if (msgskip->skipping()) { - if (msgskip->get_flags() & MSGSKIP_STOP_ON_CLICK && get_key()) - msgskip->activate(false); - } else if (show_push) { - ags->draw_push(text_window); - } - - // キーが押されて離されるまで待機 - while (!msgskip->skipping()) { - if(terminate) { - return; - } - if(get_key()) { - break; - } - sys_sleep(16); - } - sys_sleep(30); - while (!msgskip->skipping()) { - if(terminate) { - return; - } - if(!(get_key() & 0x18)) { - break; - } - sys_sleep(16); - } - - // ウィンドウ更新 - ags->clear_text_window(text_window, true); -} - -void NACT_Sys2::cmd_b() -{ - int cmd = cali(); - int index = cali(); - int p1 = cali(); - int p2 = cali(); - int p3 = cali(); - int p4 = cali(); - int p5 = cali(); - - output_console("\nB %d,%d,%d,%d,%d,%d,%d:", cmd, index, p1, p2, p3, p4, p5); - - if(cmd == 1) { - if(crc32_a == CRC32_AYUMI_FD || crc32_a == CRC32_AYUMI_HINT || crc32_a == CRC32_DRSTOP) { - p5 = 1; - } - ags->menu_w[index - 1].sx = p1 * 8; - ags->menu_w[index - 1].sy = p2; - ags->menu_w[index - 1].ex = p3 * 8 - 1; - ags->menu_w[index - 1].ey = p4; - ags->menu_w[index - 1].push = p5 ? true : false; - - // 退避画面の破棄 - if(ags->menu_w[index - 1].screen) { - free(ags->menu_w[index - 1].screen); - ags->menu_w[index - 1].screen = NULL; - } - } else if(cmd == 2) { - if(crc32_a == CRC32_AYUMI_FD || crc32_a == CRC32_AYUMI_HINT || crc32_a == CRC32_DRSTOP) { - p1 = 1; - } -// if(crc32_a == CRC32_PROSTUDENTG_FD) { -// ags->menu_w[index - 1].frame = (index == 1 || index == 3) ? true : false; -// } else - ags->menu_w[index - 1].frame = p1 ? true : false; - menu_window = index; - } else if(cmd == 3) { - ags->text_w[index - 1].sx = p1 * 8; - ags->text_w[index - 1].sy = p2; - ags->text_w[index - 1].ex = p3 * 8 - 1; - ags->text_w[index - 1].ey = p4; - ags->text_w[index - 1].push = p5 ? true : false; - - // 退避画面の破棄 - if(ags->text_w[index - 1].screen) { - free(ags->text_w[index - 1].screen); - ags->text_w[index - 1].screen = NULL; - } - // 退避窓の破棄 - if(ags->text_w[index - 1].window) { - free(ags->text_w[index - 1].window); - ags->text_w[index - 1].window = NULL; - } - } else if(cmd == 4) { - if(crc32_a == CRC32_AYUMI_FD || crc32_a == CRC32_AYUMI_HINT) { - p1 = 1; - //p5 ? 0 : 1; // 逆? - p5 = 0; - } else if(crc32_a == CRC32_DRSTOP) { - p1 = 1; - } - if(p5 == 0) { - // ウィンドウ退避 -// if(crc32_a == CRC32_PROSTUDENTG_FD) { -// ags->text_w[index - 1].frame = (index == 1 || index == 3) ? true : false; -// } else - ags->text_w[index - 1].frame = p1 ? true : false; - ags->open_text_window(index, p4 ? false : true); - text_window = index; - } else { - // ウィンドウ復帰 - ags->close_text_window(index, text_window == index ? true : false); - } - } -} - -void NACT_Sys2::cmd_d() -{ - int p1 = cali(); - int p2 = cali(); - int p3 = cali(); - int p4 = cali(); - int p5 = cali(); - int p6 = cali(); - int p7 = cali(); - int p8 = cali(); - - output_console("\nD %d,%d,%d,%d,%d,%d,%d,%d:", p1, p2, p3, p4, p5, p6, p7, p8); -} - -void NACT_Sys2::cmd_e() -{ - int p1 = cali(); - int p2 = cali(); - int p3 = cali(); - - output_console("\nE %d,%d,%d:", p1, p2, p3); -} - -void NACT_Sys2::cmd_f() -{ - output_console("\nF"); - - scenario_addr = 2; -} - -void NACT_Sys2::cmd_g() -{ - int page = cali(); - - output_console("\nG %d:", page); - - if(crc32_a == CRC32_SDPS && (crc32_b == CRC32_SDPS_TONO || crc32_b == CRC32_SDPS_KAIZOKU)) { - if(20 <= page && page <= 100) { - page--; - } - } - ags->load_cg(page, -1); - - if(crc32_a == CRC32_DALK_HINT) { - if(page == 3) { - WAIT(2000) - } - } else if(crc32_a == CRC32_RANCE3_HINT) { - if(page == 25) { - WAIT(2000) - } - } -} - -void NACT_Sys2::cmd_h() -{ - int length = getd(); - int val = cali(); - - output_console("\nH %d,%d:", length, val); - - // 8桁の文字列を生成 - char tmp[8]; - tmp[0] = '0'; - tmp[1] = '0'; - tmp[2] = '0'; - for(int i = 3, ref = 10000; i < 8; i++) { - tmp[i] = '0' + (int)(val / ref); - val %= ref; - ref /= 10; - } - for(int i = 0; i < 7; i++) { - if(tmp[i] != '0') - break; - tmp[i] = ' '; - } - - // 指定した桁数だけ出力 - char string[9]; - int p = 0; - if(length == 0) { - for(int i = 0; i < 8; i++) { - if(tmp[i] != ' ') { - string[p++] = tmp[i]; - } - } - } else { - for(int i = 8 - length; i < 8; i++) { - string[p++] = tmp[i]; - } - } - string[p++] = '\0'; - ags->draw_text(string); -} - -void NACT_Sys2::cmd_i() -{ - int p1 = cali(); - int p2 = cali(); -// int p3 = getd(); - int p3 = cali(); - - output_console("\nI %d,%d,%d:", p1, p2, p3); -} - -void NACT_Sys2::cmd_j() -{ - int p1 = cali(); - int p2 = cali(); - - output_console("\nJ %d,%d:", p1, p2); -} - -void NACT_Sys2::cmd_k() -{ - // 未使用 - cmd_r(); -} - -void NACT_Sys2::cmd_l() -{ - int index = getd(); - - output_console("\nL %d:", index); - - if(1 <= index && index <= 26) { - // ASLEEP_A.DAT - ASLEEP_Z.DAT - char file_name[_MAX_PATH]; - sprintf_s(file_name, _MAX_PATH, "ASLEEP_%c.DAT", 'A' + index - 1); - - FILEIO* fio = new FILEIO(); - if(fio->Fopen(file_name, FILEIO_READ_BINARY | FILEIO_SAVEDATA)) { - fio->Fseek(112, FILEIO_SEEK_SET); - - int next_page = fio->Fgetw() - 1; - fio->Fgetw(); - fio->Fgetw(); // cg no? - fio->Fgetw(); - int next_music = fio->Fgetw(); - fio->Fgetw(); - int next_addr = fio->Fgetw(); - fio->Fgetw(); - for(int i = 0; i < 512; i++) { - var[i] = fio->Fgetw(); - } - ags->menu_font_size = fio->Fgetw(); - ags->text_font_size = fio->Fgetw(); - ags->palette_bank = fio->Fgetw(); - if(!ags->palette_bank) { - ags->palette_bank = -1; - } - ags->text_font_color = fio->Fgetw(); - ags->menu_font_color = fio->Fgetw(); - ags->menu_frame_color = fio->Fgetw(); - ags->menu_back_color = fio->Fgetw(); - ags->text_frame_color = fio->Fgetw(); - ags->text_back_color = fio->Fgetw(); - for(int i = 0; i < 10; i++) { - ags->menu_w[i].sx = fio->Fgetw(); - ags->menu_w[i].sy = fio->Fgetw(); - ags->menu_w[i].ex = fio->Fgetw(); - ags->menu_w[i].ey = fio->Fgetw(); - ags->menu_w[i].push = fio->Fgetw() ? true : false; - ags->menu_w[i].frame = fio->Fgetw() ? true : false; - fio->Fgetw(); - fio->Fgetw(); - - if(ags->menu_w[i].screen) { - free(ags->menu_w[i].screen); - } - ags->menu_w[i].screen = NULL; - if(ags->menu_w[i].window) { - free(ags->menu_w[i].window); - } - ags->menu_w[i].window = NULL; - } - for(int i = 0; i < 10; i++) { - ags->text_w[i].sx = fio->Fgetw(); - ags->text_w[i].sy = fio->Fgetw(); - ags->text_w[i].ex = fio->Fgetw(); - ags->text_w[i].ey = fio->Fgetw(); - ags->text_w[i].push = fio->Fgetw() ? true : false; - ags->text_w[i].frame = fio->Fgetw() ? true : false; - fio->Fgetw(); - fio->Fgetw(); - - if(ags->text_w[i].screen) { - free(ags->text_w[i].screen); - } - ags->text_w[i].screen = NULL; - if(ags->text_w[i].window) { - free(ags->text_w[i].window); - } - ags->text_w[i].window = NULL; - } - for(int i = 0; i < 10; i++) { - fio->Fread(tvar[i], 22, 1); - } - for(int i = 0; i < 30; i++) { - for(int j = 0; j < 10; j++) { - fio->Fread(tvar_stack[i][j], 22, 1); - } - } - for(int i = 0; i < 30; i++) { - for(int j = 0; j < 20; j++) { - var_stack[i][j] = fio->Fgetw(); - } - } - fio->Fclose(); - - load_scenario(next_page); - scenario_page = next_page; - scenario_addr = next_addr; - - mako->play_music(next_music); - } - delete fio; - } -} - -void NACT_Sys2::cmd_m() -{ - char string[33]; - - int d = getd(); - if (d == '\'' || d == '"') { // SysEng - get_string(string, sizeof(string), d); - } else { - int p = 0; - while(d != ':') { - string[p++] = d; - d = getd(); - } - string[p] = '\0'; - } - - output_console("\nM %s:", string); - - if(1 <= tvar_index && tvar_index <= 10) { - memcpy(tvar[tvar_index - 1], string, 33); - } -} - -void NACT_Sys2::cmd_n() -{ - int p1 = cali(); - int p2 = cali(); - - output_console("\nN %d,%d:", p1, p2); -} - -void NACT_Sys2::cmd_o() -{ - int st = cali(); - int width = cali(); - int height = cali(); - - output_console("\nO %d,%d,%d:", st, width, height); - -#if 0 - // white mesh - int sx = (st % 80) * 8; - int sy = (int)(st / 80); - ags->draw_mesh(sx, sy, width, height); -#endif -} - -void NACT_Sys2::cmd_p() -{ - int param = getd(); - - if(crc32_a != CRC32_YAKATA2 && crc32_a != CRC32_DALK_HINT && crc32_a != CRC32_RANCE3_HINT) { - ags->text_font_color = (uint8)((param & 0x7) + 16); - } - - output_console("\nP %d:", param); -} - -#define FWRITE(data, size) { \ - memcpy(&buffer[p], data, size); \ - p += size; \ -} -#define FPUTW(data) { \ - uint16 tmp = (data); \ - buffer[p++] = tmp & 0xff; \ - buffer[p++] = (tmp >> 8) & 0xff; \ -} - -void NACT_Sys2::cmd_q() -{ - static char header[112] = { - 'T', 'h', 'i', 's', ' ', 'i', 's', ' ', 's', 'a', 'v', 'e', ' ', 'd', 'a', 't', - 'a', ' ', 'f', 'o', 'r', ' ', 'S', 'y', 's', 't', 'e', 'm', '2', ' ', ' ', 'U', - 'n', 'i', 'o', 'n', ' ', '[', 'W', 'i', 'n', '9', 'x', '/', 'N', 'T', '4', '0', - '/', '2', '0', '0', '0', '/', 'X', 'P', '/', 'C', 'E', ']', ' ', 'F', 'o', 'r', - ' ', 'N', 'A', 'C', 'T', '/', 'A', 'D', 'V', ' ', 's', 'y', 's', 't', 'e', 'm', - ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', '(', 'C', ')', '2', '0', '0', - '4', ' ', 'A', 'L', 'I', 'C', 'E', '-', 'S', 'O', 'F', 'T', ' ', ' ', ' ', ' ' - }; - - int index = getd(); - - output_console("\nQ %d:", index); - - if(1 <= index && index <= 26) { - // ASLEEP_A.DAT - ASLEEP_Z.DAT - char file_name[_MAX_PATH]; - sprintf_s(file_name, _MAX_PATH, "ASLEEP_%c.DAT", 'A' + index - 1); - - FILEIO* fio = new FILEIO(); - if(fio->Fopen(file_name, FILEIO_WRITE_BINARY | FILEIO_SAVEDATA)) { - uint8 buffer[9510]; - int p = 0; - - FWRITE(header, 112); - FPUTW(scenario_page + 1); - FPUTW(0); - FPUTW(0); // cg no? - FPUTW(0); - FPUTW(mako->current_music); - FPUTW(0); - FPUTW(scenario_addr); - FPUTW(0); - for(int i = 0; i < 512; i++) { - FPUTW(var[i]); - } - FPUTW(ags->menu_font_size); - FPUTW(ags->text_font_size); - FPUTW(ags->palette_bank == -1 ? 0 : ags->palette_bank); - FPUTW(ags->text_font_color); - FPUTW(ags->menu_font_color); - FPUTW(ags->menu_frame_color); - FPUTW(ags->menu_back_color); - FPUTW(ags->text_frame_color); - FPUTW(ags->text_back_color); - for(int i = 0; i < 10; i++) { - FPUTW(ags->menu_w[i].sx); - FPUTW(ags->menu_w[i].sy); - FPUTW(ags->menu_w[i].ex); - FPUTW(ags->menu_w[i].ey); - FPUTW(ags->menu_w[i].push ? 1 : 0); - FPUTW(ags->menu_w[i].frame ? 1 : 0); - FPUTW(0); - FPUTW(0); - } - for(int i = 0; i < 10; i++) { - FPUTW(ags->text_w[i].sx); - FPUTW(ags->text_w[i].sy); - FPUTW(ags->text_w[i].ex); - FPUTW(ags->text_w[i].ey); - FPUTW(ags->text_w[i].push ? 1 : 0); - FPUTW(ags->text_w[i].frame ? 1 : 0); - FPUTW(0); - FPUTW(0); - } - for(int i = 0; i < 10; i++) { - FWRITE(tvar[i], 22); - } - for(int i = 0; i < 30; i++) { - for(int j = 0; j < 10; j++) { - FWRITE(tvar_stack[i][j], 22); - } - } - for(int i = 0; i < 30; i++) { - for(int j = 0; j < 20; j++) { - FPUTW(var_stack[i][j]); - } - } - - fio->Fwrite(buffer, 9510, 1); - fio->Fclose(); - } - delete fio; - } -} - -void NACT_Sys2::cmd_r() -{ - texthook_newline(); - - output_console("R\n"); - - // ウィンドウの表示範囲外の場合は改ページ - if(ags->return_text_line(text_window)) { - cmd_a(); - } -} - -void NACT_Sys2::cmd_s() -{ - int page = getd(); - - output_console("\nS %d:", page); - - if(page) { - mako->play_music(page); - } else { - mako->stop_music(); - } -} - -void NACT_Sys2::cmd_t() -{ - int p1 = cali(); - int p2 = cali(); - int p3 = cali(); - - output_console("\nT %d,%d,%d:", p1, p2, p3); -} - -void NACT_Sys2::cmd_u() -{ - int page, transparent; - - if(crc32_a == CRC32_YAKATA2) { - page = cali(); - transparent = cali(); - } else { - page = getd(); - transparent = getd(); - } - - output_console("\nU %d,%d:", page, transparent); - - ags->load_cg(page, transparent); -} - -void NACT_Sys2::cmd_v() -{ -#if 1 - int p01 = cali(); - int p02 = cali(); - int p03 = cali(); - int p04 = cali(); - int p05 = cali(); - int p06 = cali(); - int p07 = cali(); - int p08 = cali(); - int p09 = cali(); - int p10 = cali(); - int p11 = cali(); - int p12 = cali(); - int p13 = cali(); - int p14 = cali(); - int p15 = cali(); - int p16 = cali(); - int p17 = cali(); - int p18 = cali(); - int p19 = cali(); - int p20 = cali(); - int p21 = cali(); - int p22 = cali(); - int p23 = cali(); - int p24 = cali(); - int p25 = cali(); - int p26 = cali(); - int p27 = cali(); - int p28 = cali(); - int p29 = cali(); - - output_console("\nV %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d:", - p01, p02, p03, p04, p05, p06, p07, p08, p09, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20, p21, p22, p23, p24, p25, p26, p27, p28, p29); -#else - int p1 = cali(); - int p2 = cali(); - - output_console("\nV %d,%d:", p1, p2); -#endif -} - -void NACT_Sys2::cmd_w() -{ - int sx = cali(); - int sy = cali(); - int ex = cali(); - int ey = cali(); - - output_console("\nW %d,%d,%d,%d:", sx, sy, ex, ey); - - ags->draw_mesh(sx, sy, ex - sx, ey - sy); -} - -void NACT_Sys2::cmd_x() -{ - int index = getd(); - - output_console("\nX %d:", index); - - if(1 <= index && index <= 10) { - ags->draw_text(tvar[index - 1]); - } -} - -void NACT_Sys2::cmd_y() -{ - int cmd = cali(); - int param = cali(); - - output_console("\nY %d,%d:", cmd, param); - - switch(cmd) { - case 1: - ags->clear_text_window(text_window, (param == 0) ? true : false); - break; - case 2: - if(param == 0) { - for(int i = 1; i <= 20; i++) { - var[i] = 0; - } - } else if(param == 1) { - for(int i = 21; i <= 40; i++) { - var[i] = 0; - } - } else if(param == 2) { - for(int i = 41; i <= 56; i++) { - var[i] = 0; - } - } - break; - case 3: - { - Uint32 dwTime = SDL_GetTicks() + param * 1000 / 60; - for(;;) { - if(terminate) { - return; - } -// RND = get_key(); -// if(RND && wait_keydown) { -// break; -// } - if(dwTime <= SDL_GetTicks()) { - break; - } - sys_sleep(16); - } - } - break; - case 4: - RND = (param == 0 || param == 1) ? 0 : random(param); - break; - case 7: - if(!(crc32_a == CRC32_SDPS && crc32_b == CRC32_SDPS_MARIA)) { - ags->draw_box(param); - } - break; - case 8: - tvar_index = param; - break; - case 14: - RND = 1; - break; - case 25: - ags->menu_font_size = (param == 1) ? 16 : (param == 2) ? 24 : (param == 3) ? 32 : (param == 4) ? 48 : (param == 5) ? 64 : 16; - break; - case 26: - ags->text_font_size = (param == 1) ? 16 : (param == 2) ? 24 : (param == 3) ? 32 : (param == 4) ? 48 : (param == 5) ? 64 : 16; - break; - case 27: - { - int tmp = tvar_index; - tvar_index = param; - tvar_maxlen = 8;//param; - text_dialog(); - tvar_index = tmp; - } - break; - case 40: - case 42: - ags->fade_in(param * 16 * 1000 / 60); - break; - case 41: - case 43: - ags->fade_out(param * 16 * 1000 / 60, cmd == 43); - break; - case 221: - case 222: - case 223: - case 224: - case 225: - case 226: - case 227: - case 228: - case 229: - if(1 <= param && param <= 10) { - ags->draw_text(tvar[param - 1]); - int padlen = cmd - 220 - encoding->mbslen(tvar[param - 1]); - if (padlen > 0) { - char pad[10] = " "; - pad[padlen] = '\0'; - ags->draw_text(pad); - } - } - break; - case 252: - RND = 8; - break; - case 253: - // キーが押されて離されるまで待機 - for(;;) { - if(terminate) { - return; - } - if(get_key()) { - break; - } - sys_sleep(16); - } - sys_sleep(100); - for(;;) { - if(terminate) { - return; - } - if(!(get_key() & 0x18)) { - break; - } - sys_sleep(16); - } - break; - case 254: - RND = 0; - break; - case 255: - post_quit = (param == 1) ? true : false; - fatal_error = true; - break; - } -// Y1 -// Y2 -// Y3 -// Y7 -// Y8 -// Y11 -// Y23 -// Y25 -// Y26 -// Y27 -// Y40 -// Y50 -// Y252 -// Y254 -// Y255 -} - -void NACT_Sys2::cmd_z() -{ - int cmd = cali(); - int param = cali(); - - output_console("\nZ %d,%d:", cmd, param); - -// Z1 -// Z2 -// Z3 -// Z4 -// Z5 -} - - -// 下位関数 - -uint16 NACT_Sys2::cali() -{ - uint32 cali[256]; - int p = 1; - bool ok = false; - - while(p > 0) { - uint8 dat = getd(); - - if(0x80 <= dat && dat <= 0xbf) { - cali[p++] = var[dat & 0x3f]; - } else if(0xc0 <= dat && dat <= 0xff) { - cali[p++] = var[((dat & 0x3f) << 8) | getd()]; - } else if(0x00 <= dat && dat <= 0x3f) { - cali[p++] = ((dat & 0x3f) << 8) | getd(); - } else if(0x40 <= dat && dat <= 0x76) { - cali[p++] = dat & 0x3f; - } else if(dat == 0x77) { - cali[p - 2] = cali[p - 2] * cali[p - 1]; - if (cali[p - 2] > 65535) { - cali[p - 2] = 65535; - } - p--; - } else if(dat == 0x78) { - if(cali[p - 1]) { - cali[p - 2] = cali[p - 2] / cali[p - 1]; - } else { - cali[p - 2] = 0; - } - p--; - } else if(dat == 0x79) { - cali[p - 2] = cali[p - 2] + cali[p - 1]; - if (cali[p - 2] > 65535) { - cali[p - 2] = 65535; - } - p--; - } else if(dat == 0x7a) { - if(cali[p - 2] > cali[p - 1]) { - cali[p - 2] = cali[p - 2] - cali[p - 1]; - } else { - cali[p - 2] = 0; - } - p--; - } else if(dat == 0x7b) { - cali[p - 2] = (cali[p - 2] == cali[p - 1]) ? 1 : 0; - p--; - } else if(dat == 0x7c) { - cali[p - 2] = (cali[p - 2] < cali[p - 1]) ? 1 : 0; - p--; - }else if(dat == 0x7d) { - cali[p - 2] = (cali[p - 2] > cali[p - 1]) ? 1 : 0; - p--; - } else if(dat == 0x7e) { - cali[p - 2] = (cali[p - 2] != cali[p - 1]) ? 1 : 0; - p--; - } else if(dat == 0x7f) { - if(p == 2) { - ok = true; - } - p = 0; - } - } - if (!ok) { - fatal("cali: invalid expression"); - } - return (uint16)(cali[1] & 0xffff); -} - -uint16 NACT_Sys2::cali2() -{ - uint16 val = 0; - uint16 dat = getd(); - - if(0x80 <= dat && dat <= 0xbf) { - val = dat & 0x3f; - } else if(0xc0 <= dat && dat <= 0xff) { - val = ((dat & 0x3f) << 8) | getd(); - } else { - fatal("cali2: invalid expression"); - } - if(getd() != 0x7f) { - fatal("cali2: invalid expression"); - } - return val; -} +/* + ALICE SOFT SYSTEM2 for Win32 + + Super D.P.S. - Dream Program System + + [ NACT - command ] +*/ + +#include "nact.h" +#include "ags.h" +#include "mako.h" +#include "msgskip.h" +#include "crc32.h" +#include "../fileio.h" +#include "encoding.h" +#include "texthook.h" + +#define WAIT(tm) \ +{ \ + Uint32 dwTime = SDL_GetTicks() + (tm); \ + for(;;) { \ + if(terminate) { \ + return; \ + } \ + if(dwTime <= SDL_GetTicks()) { \ + break; \ + } \ + sys_sleep(16); \ + } \ +} + +#define WAIT_KEYQUIT(tm) \ +{ \ + Uint32 dwTime = SDL_GetTicks() + (tm); \ + for(;;) { \ + if(terminate) { \ + return; \ + } \ + if(get_key()) { \ + for(;;) { \ + if(terminate) { \ + return; \ + } \ + if(!get_key()) { \ + break; \ + } \ + if(dwTime <= SDL_GetTicks()) { \ + break; \ + } \ + sys_sleep(16); \ + } \ + break; \ + } \ + if(dwTime <= SDL_GetTicks()) { \ + break; \ + } \ + sys_sleep(16); \ + } \ +} + +NACT_Sys2::NACT_Sys2(uint32 crc32_a, uint32 crc32_b, const Config& config) + : NACT(2, crc32_a, crc32_b, config) +{ +} + +void NACT_Sys2::cmd_calc() +{ + int index = getd(); + if(0x80 <= index && index <= 0xbf) { + index &= 0x3f; + } else { + index = ((index & 0x3f) << 8) | getd(); + } + var[index] = cali(); + + output_console("\n!var[%d]:%d!", index, var[index]); +} + +void NACT_Sys2::cmd_branch() +{ + int condition = cali(); + int nest = 0; + bool set_menu = false; + + if(!condition) { + // 次の'}'命令までスキップする(ネストも考慮する) + for(;;) { + prev_addr = scenario_addr; + uint8 cmd = getd(); + + if(cmd == '!') { + int index = getd(); + if(!(0x80 <= index && index <= 0xbf)) { + getd(); + } + cali(); + } else if(cmd == '{') { + cali(); + nest++; + } else if(cmd == '}') { + if(nest) { + nest--; + } else { + break; + } + } else if(cmd == '@') { + getw(); + } else if(cmd == '\\') { + getw(); + } else if(cmd == '&') { + cali(); + } else if(cmd == '%') { + cali(); + } else if(cmd == '$') { + if(!set_menu) { + getw(); + set_menu = true; + } else { + set_menu = false; + } + } else if(cmd == '[') { + getd(); + getd(); + getw(); + } else if(cmd == ':') { + cali(); + getd(); + getd(); + getw(); + } else if(cmd == ']') { + + } else if(cmd == 'A') { + + } else if(cmd == 'B') { + cali(); + cali(); + cali(); + cali(); + cali(); + cali(); + cali(); + } else if(cmd == 'D') { + cali(); + cali(); + cali(); + cali(); + cali(); + cali(); + cali(); + cali(); + } else if(cmd == 'E') { + cali(); + cali(); + cali(); + } else if(cmd == 'F') { + + } else if(cmd == 'G') { + cali(); + } else if(cmd == 'H') { + getd(); + cali(); + } else if(cmd == 'I') { + cali(); + cali(); +// getd(); + cali(); + } else if(cmd == 'J') { + cali(); + cali(); + } else if(cmd == 'K') { + + } else if(cmd == 'L') { + getd(); + } else if(cmd == 'M') { + uint8 val = getd(); + if (val == '\'' || val == '"') { // SysEng + skip_string(val); + } else { + while (val != ':') + val = getd(); + } + } else if(cmd == 'N') { + cali(); + cali(); + } else if(cmd == 'O') { + cali(); + cali(); + cali(); + } else if(cmd == 'P') { + getd(); + } else if(cmd == 'Q') { + getd(); + } else if(cmd == 'R') { + + } else if(cmd == 'S') { + getd(); + } else if(cmd == 'T') { + cali(); + cali(); + cali(); + } else if(cmd == 'U') { + if(crc32_a == CRC32_YAKATA2) { + cali(); + cali(); + } else { + getd(); + getd(); + } + } else if(cmd == 'V') { +#if 1 + cali(); + cali(); + cali(); + cali(); + cali(); + cali(); + cali(); + cali(); + cali(); + cali(); + cali(); + cali(); + cali(); + cali(); + cali(); + cali(); + cali(); + cali(); + cali(); + cali(); + cali(); + cali(); + cali(); + cali(); + cali(); + cali(); + cali(); + cali(); + cali(); +#else + cali(); + cali(); +#endif + } else if(cmd == 'W') { + cali(); + cali(); + cali(); + cali(); + } else if(cmd == 'X') { + getd(); + } else if(cmd == 'Y') { + cali(); + cali(); + } else if(cmd == 'Z') { + cali(); + cali(); + } else if (cmd == '\'' || cmd == '"') { // SysEng + skip_string(cmd); + } else if (is_message(cmd)) { + ungetd(); + scenario_addr += encoding->mblen(scenario_data + scenario_addr); + } else if (cmd >= 0x20 && cmd < 0x7f) { + fatal("Unknown Command: '%c' at page = %d, addr = %d", cmd, scenario_page, prev_addr); + } else { + fatal("Unknown Command: %02x at page = %d, addr = %d", cmd, scenario_page, prev_addr); + } + } + } + + output_console("\n{%d:", condition); +} + +void NACT_Sys2::cmd_label_jump() +{ + int next_addr = getw(); + scenario_addr = next_addr; + + output_console("\n@%x:", next_addr); +} + +void NACT_Sys2::cmd_label_call() +{ + int next_addr = getw(); + + output_console("\n\\%x:", next_addr); + + if(next_addr == 0) { + // リターン + if(label_depth == 0) { +// fatal_error = true; + return; + } + scenario_addr = label_stack[--label_depth]; + } else { + label_stack[label_depth++] = scenario_addr; + scenario_addr = next_addr; + } +} + +void NACT_Sys2::cmd_page_jump() +{ + int next_page = cali(); + load_scenario(next_page); + scenario_page = next_page; + scenario_addr = 2; + + output_console("\n&%d:", next_page); +} + +void NACT_Sys2::cmd_page_call() +{ + int next_page = cali(), next_addr; + + output_console("\n%%%d:", next_page); + + if(next_page == 0) { + // リターン + if(page_depth == 0) { +// fatal_error = true; + return; + } + next_page = page_stack[--page_depth]; + next_addr = addr_stack[page_depth]; + } else { + page_stack[page_depth] = scenario_page; + addr_stack[page_depth++] = scenario_addr; + next_addr = 2; + } + load_scenario(next_page); + scenario_page = next_page; + scenario_addr = next_addr; +} + +void NACT_Sys2::cmd_set_menu() +{ + if(ags->draw_menu) { + ags->menu_dest_x = 2; + ags->menu_dest_y += ags->menu_font_size + 2; + ags->draw_menu = false; + + output_console("$"); + } else { + if(!menu_index) { + ags->clear_menu_window(); + ags->menu_dest_y = 0; + } + menu_addr[menu_index++] = getw(); + ags->menu_dest_x = 2; + ags->menu_dest_y += 2; + ags->draw_menu = true; + + output_console("\n$%x,", menu_addr[menu_index - 1]); + } +} + +void NACT_Sys2::cmd_open_menu() +{ + output_console("\n]"); + + if(!menu_index) { + scenario_addr = scenario_data[0] | (scenario_data[1] << 8); + return; + } + + int selection = menu_select(menu_index); + if (terminate) + return; + + if (selection != -1) { + scenario_addr = menu_addr[selection]; + } + menu_index = 0; +} + +void NACT_Sys2::cmd_set_verbobj() +{ + int verb = getd(); + int obj = getd(); + int addr = getw(); + + menu_addr[menu_index] = addr; + menu_verb[menu_index] = verb; + menu_obj[menu_index++] = obj; + verb_obj = true; + + output_console("\n[%x,%s,%s:", addr, caption_verb[verb], caption_obj[obj]); +} + +void NACT_Sys2::cmd_set_verbobj2() +{ + int condition = cali(); + int verb = getd(); + int obj = getd(); + int addr = getw(); + + if(condition) { + menu_addr[menu_index] = addr; + menu_verb[menu_index] = verb; + menu_obj[menu_index++] = obj; + } + verb_obj = true; + + output_console("\n:%d,%x,%s,%s:", condition, addr, caption_verb[verb], caption_obj[obj]); +} + +void NACT_Sys2::cmd_open_verb() +{ + // 動詞メニューの表示 + output_console("\nopen verb-obj menu"); + verb_obj = false; + + // 表示する動詞のチェック + int chk[MAX_VERB], page = 0; + + memset(chk, 0, sizeof(chk)); + for(int i = 0; i < menu_index; i++) { + chk[menu_verb[i]] = 1; + } + + // メニュー項目の準備 + int id[32], index = 0; + + ags->clear_menu_window(); + ags->menu_dest_y = 0; + ags->draw_menu = true; + + for(int i = 0; i < MAX_VERB; i++) { + if(chk[i]) { + ags->menu_dest_x = 2; + ags->menu_dest_y += 2; + ags->draw_text(caption_verb[i]); + id[index++] = i; + ags->menu_dest_y += ags->menu_font_size + 2; + } + } + ags->draw_menu = false; + + int selection = menu_select(index); + if (terminate) + return; + + if(selection == -1) { + scenario_addr = scenario_data[0] | (scenario_data[1] << 8); + } else { + cmd_open_obj(id[selection]); + } + menu_index = 0; +} + +void NACT_Sys2::cmd_open_obj(int verb) +{ + // 目的語メニューの表示 + verb_obj = false; + + // 表示する目的語のチェック + int chk[MAX_OBJ], addr[MAX_OBJ], page = 0; + + memset(chk, 0, sizeof(chk)); + for(int i = 0; i < menu_index; i++) { + if(menu_verb[i] == verb) { + chk[menu_obj[i]] = 1; + addr[menu_obj[i]] = menu_addr[i]; + } + } + // 目的語がない場合 + if(chk[0]) { + scenario_addr = addr[0]; + return; + } + // 以後、obj=0は戻るとして扱う + chk[0] = 0; + addr[0] = scenario_data[0] | (scenario_data[1] << 8); + + // メニュー項目の準備 + int id[32], index = 0; + + ags->clear_menu_window(); + ags->menu_dest_y = 0; + ags->draw_menu = true; + + for(int i = 0; i < MAX_OBJ; i++) { + if(chk[i]) { + ags->menu_dest_x = 2; + ags->menu_dest_y += 2; + ags->draw_text(caption_obj[i]); + id[index++] = i; + ags->menu_dest_y += ags->menu_font_size + 2; + } + } + // 戻るを追加 + ags->menu_dest_x = 2; + ags->menu_dest_y += 2; + ags->draw_text(strings.back.c_str()); + id[index++] = 0; + ags->menu_dest_y += ags->menu_font_size + 2; + ags->draw_menu = false; + + int selection = menu_select(index); + if (terminate) + return; + + if(selection == -1) { + scenario_addr = scenario_data[0] | (scenario_data[1] << 8); + } else { + scenario_addr = addr[id[selection]]; + } +} + +void NACT_Sys2::cmd_a() +{ + texthook_nextpage(); + + output_console("A\n"); + + if (msgskip->skipping()) { + if (msgskip->get_flags() & MSGSKIP_STOP_ON_CLICK && get_key()) + msgskip->activate(false); + } else if (show_push) { + ags->draw_push(text_window); + } + + // キーが押されて離されるまで待機 + while (!msgskip->skipping()) { + if(terminate) { + return; + } + if(get_key()) { + break; + } + sys_sleep(16); + } + sys_sleep(30); + while (!msgskip->skipping()) { + if(terminate) { + return; + } + if(!(get_key() & 0x18)) { + break; + } + sys_sleep(16); + } + + // ウィンドウ更新 + ags->clear_text_window(text_window, true); +} + +void NACT_Sys2::cmd_b() +{ + int cmd = cali(); + int index = cali(); + int p1 = cali(); + int p2 = cali(); + int p3 = cali(); + int p4 = cali(); + int p5 = cali(); + + output_console("\nB %d,%d,%d,%d,%d,%d,%d:", cmd, index, p1, p2, p3, p4, p5); + + if(cmd == 1) { + if(crc32_a == CRC32_AYUMI_FD || crc32_a == CRC32_AYUMI_HINT || crc32_a == CRC32_DRSTOP) { + p5 = 1; + } + ags->menu_w[index - 1].sx = p1 * 8; + ags->menu_w[index - 1].sy = p2; + ags->menu_w[index - 1].ex = p3 * 8 - 1; + ags->menu_w[index - 1].ey = p4; + ags->menu_w[index - 1].push = p5 ? true : false; + + // 退避画面の破棄 + if(ags->menu_w[index - 1].screen) { + free(ags->menu_w[index - 1].screen); + ags->menu_w[index - 1].screen = NULL; + } + } else if(cmd == 2) { + if(crc32_a == CRC32_AYUMI_FD || crc32_a == CRC32_AYUMI_HINT || crc32_a == CRC32_DRSTOP) { + p1 = 1; + } +// if(crc32_a == CRC32_PROSTUDENTG_FD) { +// ags->menu_w[index - 1].frame = (index == 1 || index == 3) ? true : false; +// } else + ags->menu_w[index - 1].frame = p1 ? true : false; + menu_window = index; + } else if(cmd == 3) { + ags->text_w[index - 1].sx = p1 * 8; + ags->text_w[index - 1].sy = p2; + ags->text_w[index - 1].ex = p3 * 8 - 1; + ags->text_w[index - 1].ey = p4; + ags->text_w[index - 1].push = p5 ? true : false; + + // 退避画面の破棄 + if(ags->text_w[index - 1].screen) { + free(ags->text_w[index - 1].screen); + ags->text_w[index - 1].screen = NULL; + } + // 退避窓の破棄 + if(ags->text_w[index - 1].window) { + free(ags->text_w[index - 1].window); + ags->text_w[index - 1].window = NULL; + } + } else if(cmd == 4) { + if(crc32_a == CRC32_AYUMI_FD || crc32_a == CRC32_AYUMI_HINT) { + p1 = 1; + //p5 ? 0 : 1; // 逆? + p5 = 0; + } else if(crc32_a == CRC32_DRSTOP) { + p1 = 1; + } + if(p5 == 0) { + // ウィンドウ退避 +// if(crc32_a == CRC32_PROSTUDENTG_FD) { +// ags->text_w[index - 1].frame = (index == 1 || index == 3) ? true : false; +// } else + ags->text_w[index - 1].frame = p1 ? true : false; + ags->open_text_window(index, p4 ? false : true); + text_window = index; + } else { + // ウィンドウ復帰 + ags->close_text_window(index, text_window == index ? true : false); + } + } +} + +void NACT_Sys2::cmd_d() +{ + int p1 = cali(); + int p2 = cali(); + int p3 = cali(); + int p4 = cali(); + int p5 = cali(); + int p6 = cali(); + int p7 = cali(); + int p8 = cali(); + + output_console("\nD %d,%d,%d,%d,%d,%d,%d,%d:", p1, p2, p3, p4, p5, p6, p7, p8); +} + +void NACT_Sys2::cmd_e() +{ + int p1 = cali(); + int p2 = cali(); + int p3 = cali(); + + output_console("\nE %d,%d,%d:", p1, p2, p3); +} + +void NACT_Sys2::cmd_f() +{ + output_console("\nF"); + + scenario_addr = 2; +} + +void NACT_Sys2::cmd_g() +{ + int page = cali(); + + output_console("\nG %d:", page); + + if(crc32_a == CRC32_SDPS && (crc32_b == CRC32_SDPS_TONO || crc32_b == CRC32_SDPS_KAIZOKU)) { + if(20 <= page && page <= 100) { + page--; + } + } + ags->load_cg(page, -1); + + if(crc32_a == CRC32_DALK_HINT) { + if(page == 3) { + WAIT(2000) + } + } else if(crc32_a == CRC32_RANCE3_HINT) { + if(page == 25) { + WAIT(2000) + } + } +} + +void NACT_Sys2::cmd_h() +{ + int length = getd(); + int val = cali(); + + output_console("\nH %d,%d:", length, val); + + // 8桁の文字列を生成 + char tmp[8]; + tmp[0] = '0'; + tmp[1] = '0'; + tmp[2] = '0'; + for(int i = 3, ref = 10000; i < 8; i++) { + tmp[i] = '0' + (int)(val / ref); + val %= ref; + ref /= 10; + } + for(int i = 0; i < 7; i++) { + if(tmp[i] != '0') + break; + tmp[i] = ' '; + } + + // 指定した桁数だけ出力 + char string[9]; + int p = 0; + if(length == 0) { + for(int i = 0; i < 8; i++) { + if(tmp[i] != ' ') { + string[p++] = tmp[i]; + } + } + } else { + for(int i = 8 - length; i < 8; i++) { + string[p++] = tmp[i]; + } + } + string[p++] = '\0'; + ags->draw_text(string); +} + +void NACT_Sys2::cmd_i() +{ + int p1 = cali(); + int p2 = cali(); +// int p3 = getd(); + int p3 = cali(); + + output_console("\nI %d,%d,%d:", p1, p2, p3); +} + +void NACT_Sys2::cmd_j() +{ + int p1 = cali(); + int p2 = cali(); + + output_console("\nJ %d,%d:", p1, p2); +} + +void NACT_Sys2::cmd_k() +{ + // 未使用 + cmd_r(); +} + +void NACT_Sys2::cmd_l() +{ + int index = getd(); + + output_console("\nL %d:", index); + + if(1 <= index && index <= 26) { + // ASLEEP_A.DAT - ASLEEP_Z.DAT + char file_name[_MAX_PATH]; + sprintf_s(file_name, _MAX_PATH, "ASLEEP_%c.DAT", 'A' + index - 1); + + FILEIO* fio = new FILEIO(); + if(fio->Fopen(file_name, FILEIO_READ_BINARY | FILEIO_SAVEDATA)) { + fio->Fseek(112, FILEIO_SEEK_SET); + + int next_page = fio->Fgetw() - 1; + fio->Fgetw(); + fio->Fgetw(); // cg no? + fio->Fgetw(); + int next_music = fio->Fgetw(); + fio->Fgetw(); + int next_addr = fio->Fgetw(); + fio->Fgetw(); + for(int i = 0; i < 512; i++) { + var[i] = fio->Fgetw(); + } + ags->menu_font_size = fio->Fgetw(); + ags->text_font_size = fio->Fgetw(); + ags->palette_bank = fio->Fgetw(); + if(!ags->palette_bank) { + ags->palette_bank = -1; + } + ags->text_font_color = fio->Fgetw(); + ags->menu_font_color = fio->Fgetw(); + ags->menu_frame_color = fio->Fgetw(); + ags->menu_back_color = fio->Fgetw(); + ags->text_frame_color = fio->Fgetw(); + ags->text_back_color = fio->Fgetw(); + for(int i = 0; i < 10; i++) { + ags->menu_w[i].sx = fio->Fgetw(); + ags->menu_w[i].sy = fio->Fgetw(); + ags->menu_w[i].ex = fio->Fgetw(); + ags->menu_w[i].ey = fio->Fgetw(); + ags->menu_w[i].push = fio->Fgetw() ? true : false; + ags->menu_w[i].frame = fio->Fgetw() ? true : false; + fio->Fgetw(); + fio->Fgetw(); + + if(ags->menu_w[i].screen) { + free(ags->menu_w[i].screen); + } + ags->menu_w[i].screen = NULL; + if(ags->menu_w[i].window) { + free(ags->menu_w[i].window); + } + ags->menu_w[i].window = NULL; + } + for(int i = 0; i < 10; i++) { + ags->text_w[i].sx = fio->Fgetw(); + ags->text_w[i].sy = fio->Fgetw(); + ags->text_w[i].ex = fio->Fgetw(); + ags->text_w[i].ey = fio->Fgetw(); + ags->text_w[i].push = fio->Fgetw() ? true : false; + ags->text_w[i].frame = fio->Fgetw() ? true : false; + fio->Fgetw(); + fio->Fgetw(); + + if(ags->text_w[i].screen) { + free(ags->text_w[i].screen); + } + ags->text_w[i].screen = NULL; + if(ags->text_w[i].window) { + free(ags->text_w[i].window); + } + ags->text_w[i].window = NULL; + } + for(int i = 0; i < 10; i++) { + fio->Fread(tvar[i], 22, 1); + } + for(int i = 0; i < 30; i++) { + for(int j = 0; j < 10; j++) { + fio->Fread(tvar_stack[i][j], 22, 1); + } + } + for(int i = 0; i < 30; i++) { + for(int j = 0; j < 20; j++) { + var_stack[i][j] = fio->Fgetw(); + } + } + fio->Fclose(); + + load_scenario(next_page); + scenario_page = next_page; + scenario_addr = next_addr; + + mako->play_music(next_music); + } + delete fio; + } +} + +void NACT_Sys2::cmd_m() +{ + char string[33]; + + int d = getd(); + if (d == '\'' || d == '"') { // SysEng + get_string(string, sizeof(string), d); + } else { + int p = 0; + while(d != ':') { + string[p++] = d; + d = getd(); + } + string[p] = '\0'; + } + + output_console("\nM %s:", string); + + if(1 <= tvar_index && tvar_index <= 10) { + memcpy(tvar[tvar_index - 1], string, 33); + } +} + +void NACT_Sys2::cmd_n() +{ + int p1 = cali(); + int p2 = cali(); + + output_console("\nN %d,%d:", p1, p2); +} + +void NACT_Sys2::cmd_o() +{ + int st = cali(); + int width = cali(); + int height = cali(); + + output_console("\nO %d,%d,%d:", st, width, height); + +#if 0 + // white mesh + int sx = (st % 80) * 8; + int sy = (int)(st / 80); + ags->draw_mesh(sx, sy, width, height); +#endif +} + +void NACT_Sys2::cmd_p() +{ + int param = getd(); + + if(crc32_a != CRC32_YAKATA2 && crc32_a != CRC32_DALK_HINT && crc32_a != CRC32_RANCE3_HINT) { + ags->text_font_color = (uint8)((param & 0x7) + 16); + } + + output_console("\nP %d:", param); +} + +#define FWRITE(data, size) { \ + memcpy(&buffer[p], data, size); \ + p += size; \ +} +#define FPUTW(data) { \ + uint16 tmp = (data); \ + buffer[p++] = tmp & 0xff; \ + buffer[p++] = (tmp >> 8) & 0xff; \ +} + +void NACT_Sys2::cmd_q() +{ + static char header[112] = { + 'T', 'h', 'i', 's', ' ', 'i', 's', ' ', 's', 'a', 'v', 'e', ' ', 'd', 'a', 't', + 'a', ' ', 'f', 'o', 'r', ' ', 'S', 'y', 's', 't', 'e', 'm', '2', ' ', ' ', 'U', + 'n', 'i', 'o', 'n', ' ', '[', 'W', 'i', 'n', '9', 'x', '/', 'N', 'T', '4', '0', + '/', '2', '0', '0', '0', '/', 'X', 'P', '/', 'C', 'E', ']', ' ', 'F', 'o', 'r', + ' ', 'N', 'A', 'C', 'T', '/', 'A', 'D', 'V', ' ', 's', 'y', 's', 't', 'e', 'm', + ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', '(', 'C', ')', '2', '0', '0', + '4', ' ', 'A', 'L', 'I', 'C', 'E', '-', 'S', 'O', 'F', 'T', ' ', ' ', ' ', ' ' + }; + + int index = getd(); + + output_console("\nQ %d:", index); + + if(1 <= index && index <= 26) { + // ASLEEP_A.DAT - ASLEEP_Z.DAT + char file_name[_MAX_PATH]; + sprintf_s(file_name, _MAX_PATH, "ASLEEP_%c.DAT", 'A' + index - 1); + + FILEIO* fio = new FILEIO(); + if(fio->Fopen(file_name, FILEIO_WRITE_BINARY | FILEIO_SAVEDATA)) { + uint8 buffer[9510]; + int p = 0; + + FWRITE(header, 112); + FPUTW(scenario_page + 1); + FPUTW(0); + FPUTW(0); // cg no? + FPUTW(0); + FPUTW(mako->current_music); + FPUTW(0); + FPUTW(scenario_addr); + FPUTW(0); + for(int i = 0; i < 512; i++) { + FPUTW(var[i]); + } + FPUTW(ags->menu_font_size); + FPUTW(ags->text_font_size); + FPUTW(ags->palette_bank == -1 ? 0 : ags->palette_bank); + FPUTW(ags->text_font_color); + FPUTW(ags->menu_font_color); + FPUTW(ags->menu_frame_color); + FPUTW(ags->menu_back_color); + FPUTW(ags->text_frame_color); + FPUTW(ags->text_back_color); + for(int i = 0; i < 10; i++) { + FPUTW(ags->menu_w[i].sx); + FPUTW(ags->menu_w[i].sy); + FPUTW(ags->menu_w[i].ex); + FPUTW(ags->menu_w[i].ey); + FPUTW(ags->menu_w[i].push ? 1 : 0); + FPUTW(ags->menu_w[i].frame ? 1 : 0); + FPUTW(0); + FPUTW(0); + } + for(int i = 0; i < 10; i++) { + FPUTW(ags->text_w[i].sx); + FPUTW(ags->text_w[i].sy); + FPUTW(ags->text_w[i].ex); + FPUTW(ags->text_w[i].ey); + FPUTW(ags->text_w[i].push ? 1 : 0); + FPUTW(ags->text_w[i].frame ? 1 : 0); + FPUTW(0); + FPUTW(0); + } + for(int i = 0; i < 10; i++) { + FWRITE(tvar[i], 22); + } + for(int i = 0; i < 30; i++) { + for(int j = 0; j < 10; j++) { + FWRITE(tvar_stack[i][j], 22); + } + } + for(int i = 0; i < 30; i++) { + for(int j = 0; j < 20; j++) { + FPUTW(var_stack[i][j]); + } + } + + fio->Fwrite(buffer, 9510, 1); + fio->Fclose(); + } + delete fio; + } +} + +void NACT_Sys2::cmd_r() +{ + texthook_newline(); + + output_console("R\n"); + + // ウィンドウの表示範囲外の場合は改ページ + if(ags->return_text_line(text_window)) { + cmd_a(); + } +} + +void NACT_Sys2::cmd_s() +{ + int page = getd(); + + output_console("\nS %d:", page); + + if(page) { + mako->play_music(page); + } else { + mako->stop_music(); + } +} + +void NACT_Sys2::cmd_t() +{ + int p1 = cali(); + int p2 = cali(); + int p3 = cali(); + + output_console("\nT %d,%d,%d:", p1, p2, p3); +} + +void NACT_Sys2::cmd_u() +{ + int page, transparent; + + if(crc32_a == CRC32_YAKATA2) { + page = cali(); + transparent = cali(); + } else { + page = getd(); + transparent = getd(); + } + + output_console("\nU %d,%d:", page, transparent); + + ags->load_cg(page, transparent); +} + +void NACT_Sys2::cmd_v() +{ +#if 1 + int p01 = cali(); + int p02 = cali(); + int p03 = cali(); + int p04 = cali(); + int p05 = cali(); + int p06 = cali(); + int p07 = cali(); + int p08 = cali(); + int p09 = cali(); + int p10 = cali(); + int p11 = cali(); + int p12 = cali(); + int p13 = cali(); + int p14 = cali(); + int p15 = cali(); + int p16 = cali(); + int p17 = cali(); + int p18 = cali(); + int p19 = cali(); + int p20 = cali(); + int p21 = cali(); + int p22 = cali(); + int p23 = cali(); + int p24 = cali(); + int p25 = cali(); + int p26 = cali(); + int p27 = cali(); + int p28 = cali(); + int p29 = cali(); + + output_console("\nV %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d:", + p01, p02, p03, p04, p05, p06, p07, p08, p09, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20, p21, p22, p23, p24, p25, p26, p27, p28, p29); +#else + int p1 = cali(); + int p2 = cali(); + + output_console("\nV %d,%d:", p1, p2); +#endif +} + +void NACT_Sys2::cmd_w() +{ + int sx = cali(); + int sy = cali(); + int ex = cali(); + int ey = cali(); + + output_console("\nW %d,%d,%d,%d:", sx, sy, ex, ey); + + ags->draw_mesh(sx, sy, ex - sx, ey - sy); +} + +void NACT_Sys2::cmd_x() +{ + int index = getd(); + + output_console("\nX %d:", index); + + if(1 <= index && index <= 10) { + ags->draw_text(tvar[index - 1]); + } +} + +void NACT_Sys2::cmd_y() +{ + int cmd = cali(); + int param = cali(); + + output_console("\nY %d,%d:", cmd, param); + + switch(cmd) { + case 1: + ags->clear_text_window(text_window, (param == 0) ? true : false); + break; + case 2: + if(param == 0) { + for(int i = 1; i <= 20; i++) { + var[i] = 0; + } + } else if(param == 1) { + for(int i = 21; i <= 40; i++) { + var[i] = 0; + } + } else if(param == 2) { + for(int i = 41; i <= 56; i++) { + var[i] = 0; + } + } + break; + case 3: + { + Uint32 dwTime = SDL_GetTicks() + param * 1000 / 60; + for(;;) { + if(terminate) { + return; + } +// RND = get_key(); +// if(RND && wait_keydown) { +// break; +// } + if(dwTime <= SDL_GetTicks()) { + break; + } + sys_sleep(16); + } + } + break; + case 4: + RND = (param == 0 || param == 1) ? 0 : random(param); + break; + case 7: + if(!(crc32_a == CRC32_SDPS && crc32_b == CRC32_SDPS_MARIA)) { + ags->draw_box(param); + } + break; + case 8: + tvar_index = param; + break; + case 14: + RND = 1; + break; + case 25: + ags->menu_font_size = (param == 1) ? 16 : (param == 2) ? 24 : (param == 3) ? 32 : (param == 4) ? 48 : (param == 5) ? 64 : 16; + break; + case 26: + ags->text_font_size = (param == 1) ? 16 : (param == 2) ? 24 : (param == 3) ? 32 : (param == 4) ? 48 : (param == 5) ? 64 : 16; + break; + case 27: + { + int tmp = tvar_index; + tvar_index = param; + tvar_maxlen = 8;//param; + text_dialog(); + tvar_index = tmp; + } + break; + case 40: + case 42: + ags->fade_in(param * 16 * 1000 / 60); + break; + case 41: + case 43: + ags->fade_out(param * 16 * 1000 / 60, cmd == 43); + break; + case 221: + case 222: + case 223: + case 224: + case 225: + case 226: + case 227: + case 228: + case 229: + if(1 <= param && param <= 10) { + ags->draw_text(tvar[param - 1]); + int padlen = cmd - 220 - encoding->mbslen(tvar[param - 1]); + if (padlen > 0) { + char pad[10] = " "; + pad[padlen] = '\0'; + ags->draw_text(pad); + } + } + break; + case 252: + RND = 8; + break; + case 253: + // キーが押されて離されるまで待機 + for(;;) { + if(terminate) { + return; + } + if(get_key()) { + break; + } + sys_sleep(16); + } + sys_sleep(100); + for(;;) { + if(terminate) { + return; + } + if(!(get_key() & 0x18)) { + break; + } + sys_sleep(16); + } + break; + case 254: + RND = 0; + break; + case 255: + post_quit = (param == 1) ? true : false; + fatal_error = true; + break; + } +// Y1 +// Y2 +// Y3 +// Y7 +// Y8 +// Y11 +// Y23 +// Y25 +// Y26 +// Y27 +// Y40 +// Y50 +// Y252 +// Y254 +// Y255 +} + +void NACT_Sys2::cmd_z() +{ + int cmd = cali(); + int param = cali(); + + output_console("\nZ %d,%d:", cmd, param); + +// Z1 +// Z2 +// Z3 +// Z4 +// Z5 +} + + +// 下位関数 + +uint16 NACT_Sys2::cali() +{ + uint32 cali[256]; + int p = 1; + bool ok = false; + + while(p > 0) { + uint8 dat = getd(); + + if(0x80 <= dat && dat <= 0xbf) { + cali[p++] = var[dat & 0x3f]; + } else if(0xc0 <= dat && dat <= 0xff) { + cali[p++] = var[((dat & 0x3f) << 8) | getd()]; + } else if(0x00 <= dat && dat <= 0x3f) { + cali[p++] = ((dat & 0x3f) << 8) | getd(); + } else if(0x40 <= dat && dat <= 0x76) { + cali[p++] = dat & 0x3f; + } else if(dat == 0x77) { + cali[p - 2] = cali[p - 2] * cali[p - 1]; + if (cali[p - 2] > 65535) { + cali[p - 2] = 65535; + } + p--; + } else if(dat == 0x78) { + if(cali[p - 1]) { + cali[p - 2] = cali[p - 2] / cali[p - 1]; + } else { + cali[p - 2] = 0; + } + p--; + } else if(dat == 0x79) { + cali[p - 2] = cali[p - 2] + cali[p - 1]; + if (cali[p - 2] > 65535) { + cali[p - 2] = 65535; + } + p--; + } else if(dat == 0x7a) { + if(cali[p - 2] > cali[p - 1]) { + cali[p - 2] = cali[p - 2] - cali[p - 1]; + } else { + cali[p - 2] = 0; + } + p--; + } else if(dat == 0x7b) { + cali[p - 2] = (cali[p - 2] == cali[p - 1]) ? 1 : 0; + p--; + } else if(dat == 0x7c) { + cali[p - 2] = (cali[p - 2] < cali[p - 1]) ? 1 : 0; + p--; + }else if(dat == 0x7d) { + cali[p - 2] = (cali[p - 2] > cali[p - 1]) ? 1 : 0; + p--; + } else if(dat == 0x7e) { + cali[p - 2] = (cali[p - 2] != cali[p - 1]) ? 1 : 0; + p--; + } else if(dat == 0x7f) { + if(p == 2) { + ok = true; + } + p = 0; + } + } + if (!ok) { + fatal("cali: invalid expression"); + } + return (uint16)(cali[1] & 0xffff); +} + +uint16 NACT_Sys2::cali2() +{ + uint16 val = 0; + uint16 dat = getd(); + + if(0x80 <= dat && dat <= 0xbf) { + val = dat & 0x3f; + } else if(0xc0 <= dat && dat <= 0xff) { + val = ((dat & 0x3f) << 8) | getd(); + } else { + fatal("cali2: invalid expression"); + } + if(getd() != 0x7f) { + fatal("cali2: invalid expression"); + } + return val; +} diff --git a/src/sys/nact_sys3.cpp b/src/sys/nact_sys3.cpp index e554f9a..58efcb0 100644 --- a/src/sys/nact_sys3.cpp +++ b/src/sys/nact_sys3.cpp @@ -1,1509 +1,1509 @@ -/* - ALICE SOFT SYSTEM 3 for Win32 - - [ NACT - command ] -*/ - -#include -#include -#include "nact.h" -#include "ags.h" -#include "mako.h" -#include "msgskip.h" -#include "crc32.h" -#include "../fileio.h" -#include "encoding.h" -#include "texthook.h" - -NACT_Sys3::NACT_Sys3(uint32 crc32_a, uint32 crc32_b, const Config& config) - : NACT(3, crc32_a, crc32_b, config) -{ -} - -void NACT_Sys3::cmd_calc() -{ - int index = getd(); - if(0x80 <= index && index <= 0xbf) { - index &= 0x3f; - } else { - index = ((index & 0x3f) << 8) | getd(); - } - var[index] = cali(); - - output_console("\n!var[%d]:%d!", index, var[index]); -} - -void NACT_Sys3::cmd_branch() -{ - int condition = cali(); - int t_addr = scenario_addr + 2; - int f_addr = getw(); - - // sigmarion3 最適化誤爆の対策 - scenario_addr = condition ? t_addr : f_addr; - - output_console("\n{%d: T:%4x, F:%4x", condition, t_addr, f_addr); -} - -void NACT_Sys3::cmd_label_jump() -{ - int next_addr = getw(); - scenario_addr = next_addr; - - output_console("\n@%x:", next_addr); -} - -void NACT_Sys3::cmd_label_call() -{ - int next_addr = getw(); - - output_console("\n\\%x:", next_addr); - - if(next_addr == 0) { - // リターン - if(label_depth == 0) { -// fatal_error = true; - return; - } - scenario_addr = label_stack[--label_depth]; - } else { - label_stack[label_depth++] = scenario_addr; - scenario_addr = next_addr; - } -} - -void NACT_Sys3::cmd_page_jump() -{ - int next_page = cali(); - load_scenario(next_page); - scenario_page = next_page; - scenario_addr = 2; - - output_console("\n&%d:", next_page); -} - -void NACT_Sys3::cmd_page_call() -{ - int next_page = cali(), next_addr; - - output_console("\n%%%d:", next_page); - - if(next_page == 0) { - // リターン - if(page_depth == 0) { -// fatal_error = true; - return; - } - next_page = page_stack[--page_depth]; - next_addr = addr_stack[page_depth]; - } else { - page_stack[page_depth] = scenario_page; - addr_stack[page_depth++] = scenario_addr; - next_addr = 2; - } - load_scenario(next_page); - scenario_page = next_page; - scenario_addr = next_addr; -} - -void NACT_Sys3::cmd_set_menu() -{ - if(ags->draw_menu) { - ags->menu_dest_x = 2; - ags->menu_dest_y += ags->menu_font_size + 2; - ags->draw_menu = false; - - output_console("$"); - } else { - if(!menu_index) { - ags->clear_menu_window(); - ags->menu_dest_y = 0; - } - menu_addr[menu_index++] = getw(); - ags->menu_dest_x = 2; - ags->menu_dest_y += 2; - ags->draw_menu = true; - - output_console("\n$%x,", menu_addr[menu_index - 1]); - } -} - -void NACT_Sys3::cmd_open_menu() -{ - output_console("\n]"); - - if(!menu_index) { - scenario_addr = scenario_data[0] | (scenario_data[1] << 8); - return; - } - - int index = menu_select(menu_index); - if (terminate) - return; - - if(index != -1) { - scenario_addr = menu_addr[index]; - } - menu_index = 0; -} - -void NACT_Sys3::cmd_set_verbobj() -{ - int verb = getd(); - int obj = getd(); - int addr = getw(); - - menu_addr[menu_index] = addr; - menu_verb[menu_index] = verb; - menu_obj[menu_index++] = obj; - verb_obj = true; - - output_console("\n[%x,%s,%s:", addr, caption_verb[verb], caption_obj[obj]); -} - -void NACT_Sys3::cmd_set_verbobj2() -{ - int condition = cali(); - int verb = getd(); - int obj = getd(); - int addr = getw(); - - if(condition) { - menu_addr[menu_index] = addr; - menu_verb[menu_index] = verb; - menu_obj[menu_index++] = obj; - } - verb_obj = true; - - output_console("\n:%d,%x,%s,%s:", condition, addr, caption_verb[verb], caption_obj[obj]); -} - -void NACT_Sys3::cmd_open_verb() -{ - // 動詞メニューの表示 - output_console("\nopen verb-obj menu"); - verb_obj = false; - - // 表示する動詞のチェック - int chk[MAX_VERB], page = 0; - - memset(chk, 0, sizeof(chk)); - for(int i = 0; i < menu_index; i++) { - chk[menu_verb[i]] = 1; - } - - // メニュー項目の準備 - int id[32], index = 0; - - ags->clear_menu_window(); - ags->menu_dest_y = 0; - ags->draw_menu = true; - - for(int i = 0; i < MAX_VERB; i++) { - if(chk[i]) { - ags->menu_dest_x = 2; - ags->menu_dest_y += 2; - ags->draw_text(caption_verb[i]); - id[index++] = i; - ags->menu_dest_y += ags->menu_font_size + 2; - } - } - ags->draw_menu = false; - - int selection = menu_select(index); - if (terminate) - return; - - if (selection == -1) { - scenario_addr = scenario_data[0] | (scenario_data[1] << 8); - } else { - cmd_open_obj(id[selection]); - } - menu_index = 0; -} - -void NACT_Sys3::cmd_open_obj(int verb) -{ - // 目的語メニューの表示 - verb_obj = false; - - // 表示する目的語のチェック - int chk[MAX_OBJ], addr[MAX_OBJ], page = 0; - - memset(chk, 0, sizeof(chk)); - for(int i = 0; i < menu_index; i++) { - if(menu_verb[i] == verb) { - chk[menu_obj[i]] = 1; - addr[menu_obj[i]] = menu_addr[i]; - } - } - // 目的語がない場合 - if(chk[0]) { - scenario_addr = addr[0]; - return; - } - // 以後、obj=0は戻るとして扱う - chk[0] = 0; - addr[0] = scenario_data[0] | (scenario_data[1] << 8); - - // メニュー項目の準備 - int id[32], index = 0; - - ags->clear_menu_window(); - ags->menu_dest_y = 0; - ags->draw_menu = true; - - for(int i = 0; i < MAX_OBJ; i++) { - if(chk[i]) { - ags->menu_dest_x = 2; - ags->menu_dest_y += 2; - ags->draw_text(caption_obj[i]); - id[index++] = i; - ags->menu_dest_y += ags->menu_font_size + 2; - } - } - // 戻るを追加 - ags->menu_dest_x = 2; - ags->menu_dest_y += 2; - ags->draw_text(strings.back.c_str()); - id[index++] = 0; - ags->menu_dest_y += ags->menu_font_size + 2; - ags->draw_menu = false; - - int selection = menu_select(index); - if (terminate) - return; - - if (selection == -1) { - scenario_addr = scenario_data[0] | (scenario_data[1] << 8); - } else { - scenario_addr = addr[id[selection]]; - } -} - -void NACT_Sys3::cmd_a() -{ - texthook_nextpage(); - - output_console("A\n"); - - if (msgskip->skipping()) { - if (msgskip->get_flags() & MSGSKIP_STOP_ON_CLICK && get_key()) - msgskip->activate(false); - } else if (show_push) { - ags->draw_push(text_window); - } - - // キーが押されて離されるまで待機 - while (!msgskip->skipping()) { - if(terminate) { - return; - } - if(get_key()) { - break; - } - sys_sleep(16); - } - sys_sleep(30); - while (!msgskip->skipping()) { - if(terminate) { - return; - } - if(!(get_key() & 0x18)) { - break; - } - sys_sleep(16); - } - - // ウィンドウ更新 - ags->clear_text_window(text_window, true); -} - -void NACT_Sys3::cmd_b() -{ - int cmd = getd(); - int index = cali(); - int p1 = cali(); - int p2 = cali(); - int p3 = cali(); - int p4 = cali(); - int p5 = cali(); - - output_console("\nB %d,%d,%d,%d,%d,%d,%d:", cmd, index, p1, p2, p3, p4, p5); - - if(cmd == 1) { - // あゆみちゃん物語 - if(crc32_a == CRC32_AYUMI_CD || crc32_a == CRC32_AYUMI_JISSHA_256 || crc32_a == CRC32_AYUMI_JISSHA_FULL) { - p5 = 1; - } - ags->menu_w[index - 1].sx = column ? p1 * 8 : p1 & 0xfff8; - ags->menu_w[index - 1].sy = p2; - ags->menu_w[index - 1].ex = column ? p3 * 8 - 1 : (p3 & 0xfff8) - 1; - ags->menu_w[index - 1].ey = p4; - ags->menu_w[index - 1].push = p5 ? true : false; - - // 退避画面の破棄 - if(ags->menu_w[index - 1].screen) { - free(ags->menu_w[index - 1].screen); - ags->menu_w[index - 1].screen = NULL; - } - } else if(cmd == 2) { - ags->menu_w[index - 1].frame = p1 ? true : false; - menu_window = index; - } else if(cmd == 3) { - ags->text_w[index - 1].sx = column ? p1 * 8 : p1 & 0xfff8; - ags->text_w[index - 1].sy = p2; - ags->text_w[index - 1].ex = column ? p3 * 8 - 1 : (p3 & 0xfff8) - 1; - ags->text_w[index - 1].ey = p4; - ags->text_w[index - 1].push = p5 ? true : false; - - // 退避画面の破棄 - if(ags->text_w[index - 1].screen) { - free(ags->text_w[index - 1].screen); - ags->text_w[index - 1].screen = NULL; - } - // 退避窓の破棄 - if(ags->text_w[index - 1].window) { - free(ags->text_w[index - 1].window); - ags->text_w[index - 1].window = NULL; - } - } else if(cmd == 4) { - if(p5 == 0) { - // ウィンドウ退避 - if(crc32_a == CRC32_PROSTUDENTG_CD && p4) { - // prostudent G オープニング画面化け対策 - if(ags->text_w[index - 1].window) { - free(ags->text_w[index - 1].window); - ags->text_w[index - 1].window = NULL; - } - } - ags->text_w[index - 1].frame = p1 ? true : false; - ags->open_text_window(index, p4 ? false : true); - text_window = index; - } else { - // ウィンドウ復帰 - ags->close_text_window(index, text_window == index ? true : false); - } - } -} - -void NACT_Sys3::cmd_d() -{ - // 未使用 - fatal("Unknown Command: 'D' at page = %d, addr = %d", scenario_page, prev_addr); -} - -void NACT_Sys3::cmd_e() -{ - int index = cali(); - uint8 color = (uint8)cali(); - int sx = cali(); - int sy = cali(); - int ex = cali(); - int ey = cali(); - - output_console("\nE %d,%d,%d,%d,%d,%d:", index, color, sx, sy, ex, ey); - - ags->box[index - 1].color = color; - ags->box[index - 1].sx = column ? sx * 8 : sx; - ags->box[index - 1].sy = sy; - ags->box[index - 1].ex = column ? ex * 8 - 1 : ex; // ? - ags->box[index - 1].ey = ey; -} - -void NACT_Sys3::cmd_f() -{ - output_console("\nF"); - - scenario_addr = 2; -} - -void NACT_Sys3::cmd_g() -{ - int page = cali(); - - output_console("\nG %d:", page); - - ags->load_cg(page, -1); -} - -void NACT_Sys3::cmd_h() -{ - int length = getd(); - int val = cali(); - - output_console("\nH %d,%d:", length, val); - - // 隠しコマンド? - if(length >= 9) { - return; - } - - // 8桁の文字列を生成 - char tmp[8]; - tmp[0] = '0'; - tmp[1] = '0'; - tmp[2] = '0'; - for(int i = 3, ref = 10000; i < 8; i++) { - tmp[i] = '0' + (int)(val / ref); - val %= ref; - ref /= 10; - } - for(int i = 0; i < 7; i++) { - if(tmp[i] != '0') { - break; - } - tmp[i] = ' '; - } - - // 指定した桁数だけ出力 - char string[9]; - int p = 0; - if(length == 0) { - for(int i = 0; i < 8; i++) { - if(tmp[i] != ' ') { - string[p++] = tmp[i]; - } - } - } else { - for(int i = 8 - length; i < 8; i++) { - string[p++] = tmp[i]; - } - } - string[p++] = '\0'; - ags->draw_text(string); -} - -void NACT_Sys3::cmd_i() -{ - int sx = cali(); - int sy = cali(); - int ex = cali(); - int ey = cali(); - int dx = cali(); - int dy = cali(); - - output_console("\nI %d,%d,%d,%d,%d,%d:", sx, sy, ex, ey, dx, dy); - - // X方向はカラム単位で切り捨て - sx = column ? sx * 8 : sx & 0xfff8; - ex = column ? ex * 8 - 1 : (crc32_a == CRC32_NINGYO) ? (ex & 0xfff8) + 7 : (ex & 0xfff8) - 1; - dx = column ? dx * 8 : dx & 0xfff8; - ags->copy(sx, sy, ex, ey, dx, dy); -} - -void NACT_Sys3::cmd_j() -{ - int x = cali(); - int y = cali(); - - output_console("\nJ %d,%d:", x, y); - - // x方向はカラム単位で切り捨て - ags->cg_dest_x = column ? x * 8 : x & 0xfff8; - ags->cg_dest_y = y; - ags->set_cg_dest = true; -} - -void NACT_Sys3::cmd_k() -{ - int cmd = getd(), val; - - output_console("\nK %d:", cmd); - - // K6の場合は、すぐに返る - if(cmd == 6) { - RND = get_key(); - return; - } - - // マウスの初期取得 - int mx, my; - get_cursor(&mx, &my); - - // キーが押されるまで待機 - for(;;) { - if(terminate) { - return; - } - if((val = get_key()) != 0) { - break; - } - if(1 <= cmd && cmd <= 3) { - // マウス対応 - int x, y, dx, dy; - get_cursor(&x, &y); - dx = (x < mx) ? mx - x : x - mx; - dy = (y < my) ? my - y : y - my; - if(dy > dx && my - y >= mouse_sence) { - val = 1; - } - if(dy > dx && y - my >= mouse_sence) { - val = 2; - } - if(dx > dy && mx - x >= mouse_sence) { - val = 4; - } - if(dx > dy && x - mx >= mouse_sence) { - val = 8; - } - if(val) { - RND = val; - return; - } - } - sys_sleep(16); - } - if(cmd != 0 && cmd != 4) { - RND = val; - } - - // キーが離されるまで待機 - if(cmd != 1) { - sys_sleep(100); - for(;;) { - if(terminate) { - return; - } - if(!(val = get_key())) { - break; - } - sys_sleep(16); - } - } - - // K0の場合は改行 - if(cmd == 0) { - cmd_r(); - } -} - -void NACT_Sys3::cmd_l() -{ - int index = cali(); - - output_console("\nL %d:", index); - - if(index == 0) { - // 特殊セーブ - FILEIO* fio = new FILEIO(); - if(fio->Fopen("ASLEEP.DAT", FILEIO_READ_BINARY | FILEIO_SAVEDATA)) { - // U01 - U20 - for(int i = 21; i <= 40; i++) { - var[i] = fio->Fgetw(); - } - // M1 - M10 - for(int i = 0; i < 10; i++) { - fio->Fread(tvar[i], 22, 1); - } - fio->Fclose(); - } - delete fio; - } else if(1 <= index && index <= 26) { - // ASLEEP_A.DAT - ASLEEP_Z.DAT - char file_name[_MAX_PATH]; - sprintf_s(file_name, _MAX_PATH, "ASLEEP_%c.DAT", 'A' + index - 1); - - FILEIO* fio = new FILEIO(); - if(fio->Fopen(file_name, FILEIO_READ_BINARY | FILEIO_SAVEDATA)) { - fio->Fseek(112, FILEIO_SEEK_SET); - - int next_page = fio->Fgetw() - 1; - fio->Fgetw(); - fio->Fgetw(); // cg no? - fio->Fgetw(); - int next_music = fio->Fgetw(); - fio->Fgetw(); - int next_addr = fio->Fgetw(); - fio->Fgetw(); - for(int i = 0; i < 512; i++) { - var[i] = fio->Fgetw(); - } - ags->menu_font_size = fio->Fgetw(); - ags->text_font_size = fio->Fgetw(); - ags->palette_bank = fio->Fgetw(); - if(!ags->palette_bank) { - ags->palette_bank = -1; - } - ags->text_font_color = fio->Fgetw(); - ags->menu_font_color = fio->Fgetw(); - ags->menu_frame_color = fio->Fgetw(); - ags->menu_back_color = fio->Fgetw(); - ags->text_frame_color = fio->Fgetw(); - ags->text_back_color = fio->Fgetw(); - for(int i = 0; i < 10; i++) { - ags->menu_w[i].sx = fio->Fgetw(); - ags->menu_w[i].sy = fio->Fgetw(); - ags->menu_w[i].ex = fio->Fgetw(); - ags->menu_w[i].ey = fio->Fgetw(); - ags->menu_w[i].push = fio->Fgetw() ? true : false; - ags->menu_w[i].frame = fio->Fgetw() ? true : false; - fio->Fgetw(); - fio->Fgetw(); - - if(ags->menu_w[i].screen) { - free(ags->menu_w[i].screen); - } - ags->menu_w[i].screen = NULL; - if(ags->menu_w[i].window) { - free(ags->menu_w[i].window); - } - ags->menu_w[i].window = NULL; - } - for(int i = 0; i < 10; i++) { - ags->text_w[i].sx = fio->Fgetw(); - ags->text_w[i].sy = fio->Fgetw(); - ags->text_w[i].ex = fio->Fgetw(); - ags->text_w[i].ey = fio->Fgetw(); - ags->text_w[i].push = fio->Fgetw() ? true : false; - ags->text_w[i].frame = fio->Fgetw() ? true : false; - fio->Fgetw(); - fio->Fgetw(); - - if(ags->text_w[i].screen) { - free(ags->text_w[i].screen); - } - ags->text_w[i].screen = NULL; - if(ags->text_w[i].window) { - free(ags->text_w[i].window); - } - ags->text_w[i].window = NULL; - } - for(int i = 0; i < 10; i++) { - fio->Fread(tvar[i], 22, 1); - } - for(int i = 0; i < 30; i++) { - for(int j = 0; j < 10; j++) { - fio->Fread(tvar_stack[i][j], 22, 1); - } - } - for(int i = 0; i < 30; i++) { - for(int j = 0; j < 20; j++) { - var_stack[i][j] = fio->Fgetw(); - } - } - fio->Fclose(); - - load_scenario(next_page); - scenario_page = next_page; - scenario_addr = next_addr; - - mako->play_music(next_music); - } - delete fio; - } else if(101 <= index && index <= 126) { - // ASLEEP_A.DAT - ASLEEP_Z.DAT - char file_name[_MAX_PATH]; - sprintf_s(file_name, _MAX_PATH, "ASLEEP_%c.DAT", 'A' + index - 101); - - FILEIO* fio = new FILEIO(); - if(fio->Fopen(file_name, FILEIO_READ_BINARY | FILEIO_SAVEDATA)) { - fio->Fseek(112 + 16, FILEIO_SEEK_SET); - var[0] = fio->Fgetw(); - fio->Fclose(); - } - delete fio; - } -} - -void NACT_Sys3::cmd_m() -{ - char string[22]; - - int d = getd(); - if (d == '\'' || d == '"') { // SysEng - get_string(string, sizeof(string), d); - } else { - int p = 0; - while(d != ':') { - string[p++] = d; - d = getd(); - } - string[p] = '\0'; - } - - output_console("\nM %s:", string); - - if(1 <= tvar_index && tvar_index <= 10) { - memcpy(tvar[tvar_index - 1], string, 22); - } else if(tvar_index == 31) { - strcpy_s(adisk, 16, string); - } else if(tvar_index == 32) { - strcpy_s(ags->acg, 16, string); - } else if(tvar_index == 33) { - strcpy_s(mako->amus, 16, string); - } else if(tvar_index == 34) { - strcpy_s(mako->amse, 16, string); - } -} - -void NACT_Sys3::cmd_n() -{ - int cmd = getd(); - int src = cali(); - int dest = cali(); - - output_console("\nN %d,%d,%d:", cmd, src, dest); -} - -void NACT_Sys3::cmd_o() -{ - int cmd = cali(); - if(cmd == 0) { - uint16 val = cali(); - B01 = (val & 0x0001) ? 1 : 0; - B02 = (val & 0x0002) ? 1 : 0; - B03 = (val & 0x0004) ? 1 : 0; - B04 = (val & 0x0008) ? 1 : 0; - B05 = (val & 0x0010) ? 1 : 0; - B06 = (val & 0x0020) ? 1 : 0; - B07 = (val & 0x0040) ? 1 : 0; - B08 = (val & 0x0080) ? 1 : 0; - B09 = (val & 0x0100) ? 1 : 0; - B10 = (val & 0x0200) ? 1 : 0; - B11 = (val & 0x0400) ? 1 : 0; - B12 = (val & 0x0800) ? 1 : 0; - B13 = (val & 0x1000) ? 1 : 0; - B14 = (val & 0x2000) ? 1 : 0; - B15 = (val & 0x4000) ? 1 : 0; - B16 = (val & 0x8000) ? 1 : 0; - - output_console("\nO %d,%d:", cmd, val); - } else { - uint16 val = 0; - val |= B01 ? 0x0001 : 0; - val |= B02 ? 0x0002 : 0; - val |= B03 ? 0x0004 : 0; - val |= B04 ? 0x0008 : 0; - val |= B05 ? 0x0010 : 0; - val |= B06 ? 0x0020 : 0; - val |= B07 ? 0x0040 : 0; - val |= B08 ? 0x0080 : 0; - val |= B09 ? 0x0100 : 0; - val |= B10 ? 0x0200 : 0; - val |= B11 ? 0x0400 : 0; - val |= B12 ? 0x0800 : 0; - val |= B13 ? 0x1000 : 0; - val |= B14 ? 0x2000 : 0; - val |= B15 ? 0x4000 : 0; - val |= B16 ? 0x8000 : 0; - int index = cali2(); - var[index] = val; - - output_console("\nO %d,var[%d]:", cmd, index); - } -} - -void NACT_Sys3::cmd_p() -{ - int index =cali(); - int r = cali(); - int g = cali(); - int b = cali(); - - output_console("\nP %d,%d,%d,%d:", index, r, g, b); - - ags->set_palette(index, r, g, b); - set_palette = true; -} - -#define FWRITE(data, size) { \ - memcpy(&buffer[p], data, size); \ - p += size; \ -} -#define FPUTW(data) { \ - uint16 tmp = (data); \ - buffer[p++] = tmp & 0xff; \ - buffer[p++] = (tmp >> 8) & 0xff; \ -} - -void NACT_Sys3::cmd_q() -{ - static char header[112] = { -#if 0 - // 夢幻泡影についてきたASLEEP_A.DATのヘッダ - 'T', 'h', 'i', 's', ' ', 'i', 's', ' ', 's', 'a', 'v', 'e', ' ', 'd', 'a', 't', - 'a', ' ', 'f', 'o', 'r', ' ', 'S', 'y', 's', 't', 'e', 'm', '3', ' ', ' ', 'U', - 'n', 'i', 'o', 'n', ' ', '[', 'P', 'C', '9', '8', '0', '1', ':', 'F', 'M', 'T', - 'O', 'W', 'N', 'S', ':', 'X', '6', '8', '0', '0', '0', ']', ' ', 'F', 'o', 'r', - ' ', 'N', 'A', 'C', 'T', '/', 'A', 'D', 'V', ' ', 's', 'y', 's', 't', 'e', 'm', - ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', '(', 'C', ')', '1', '9', '9', - '4', ' ', 'A', 'L', 'I', 'C', 'E', '-', 'S', 'O', 'F', 'T', ' ', ' ', ' ', ' ' -#else - // 偽ヘッダ - 'T', 'h', 'i', 's', ' ', 'i', 's', ' ', 's', 'a', 'v', 'e', ' ', 'd', 'a', 't', - 'a', ' ', 'f', 'o', 'r', ' ', 'S', 'y', 's', 't', 'e', 'm', '3', ' ', ' ', 'U', - 'n', 'i', 'o', 'n', ' ', '[', 'W', 'i', 'n', '9', 'x', '/', 'N', 'T', '4', '0', - '/', '2', '0', '0', '0', '/', 'X', 'P', '/', 'C', 'E', ']', ' ', 'F', 'o', 'r', - ' ', 'N', 'A', 'C', 'T', '/', 'A', 'D', 'V', ' ', 's', 'y', 's', 't', 'e', 'm', - ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', '(', 'C', ')', '2', '0', '0', - '4', ' ', 'A', 'L', 'I', 'C', 'E', '-', 'S', 'O', 'F', 'T', ' ', ' ', ' ', ' ' -#endif - }; - - int index = cali(); - - output_console("\nQ %d:", index); - - if(index == 0) { - // 特殊セーブ - FILEIO* fio = new FILEIO(); - if(fio->Fopen("ASLEEP.DAT", FILEIO_WRITE_BINARY | FILEIO_SAVEDATA)) { - // U01 - U20 - for(int i = 21; i <= 40; i++) { - fio->Fputw(var[i]); - } - // M1 - M10 - for(int i = 0; i < 10; i++) { - fio->Fwrite(tvar[i], 22, 1); - } - fio->Fclose(); - } - delete fio; - } else if(1 <= index && index <= 26) { - // ASLEEP_A.DAT - ASLEEP_Z.DAT - char file_name[_MAX_PATH]; - sprintf_s(file_name, _MAX_PATH, "ASLEEP_%c.DAT", 'A' + index - 1); - - FILEIO* fio = new FILEIO(); - if(fio->Fopen(file_name, FILEIO_WRITE_BINARY | FILEIO_SAVEDATA)) { - uint8 buffer[9510]; - int p = 0; - - FWRITE(header, 112); - FPUTW(scenario_page + 1); - FPUTW(0); - FPUTW(0); // cg no? - FPUTW(0); - FPUTW(mako->current_music); - FPUTW(0); - FPUTW(scenario_addr); - FPUTW(0); - for(int i = 0; i < 512; i++) { - FPUTW(var[i]); - } - FPUTW(ags->menu_font_size); - FPUTW(ags->text_font_size); - FPUTW(ags->palette_bank == -1 ? 0 : ags->palette_bank); - FPUTW(ags->text_font_color); - FPUTW(ags->menu_font_color); - FPUTW(ags->menu_frame_color); - FPUTW(ags->menu_back_color); - FPUTW(ags->text_frame_color); - FPUTW(ags->text_back_color); - for(int i = 0; i < 10; i++) { - FPUTW(ags->menu_w[i].sx); - FPUTW(ags->menu_w[i].sy); - FPUTW(ags->menu_w[i].ex); - FPUTW(ags->menu_w[i].ey); - FPUTW(ags->menu_w[i].push ? 1 : 0); - FPUTW(ags->menu_w[i].frame ? 1 : 0); - FPUTW(0); - FPUTW(0); - } - for(int i = 0; i < 10; i++) { - FPUTW(ags->text_w[i].sx); - FPUTW(ags->text_w[i].sy); - FPUTW(ags->text_w[i].ex); - FPUTW(ags->text_w[i].ey); - FPUTW(ags->text_w[i].push ? 1 : 0); - FPUTW(ags->text_w[i].frame ? 1 : 0); - FPUTW(0); - FPUTW(0); - } - for(int i = 0; i < 10; i++) { - FWRITE(tvar[i], 22); - } - for(int i = 0; i < 30; i++) { - for(int j = 0; j < 10; j++) { - FWRITE(tvar_stack[i][j], 22); - } - } - for(int i = 0; i < 30; i++) { - for(int j = 0; j < 20; j++) { - FPUTW(var_stack[i][j]); - } - } - - fio->Fwrite(buffer, 9510, 1); - fio->Fclose(); - } - delete fio; - } -} - -void NACT_Sys3::cmd_r() -{ - texthook_newline(); - - output_console("R\n"); - - // ウィンドウの表示範囲外の場合は改ページ - if(ags->return_text_line(text_window)) { - cmd_a(); - } -} - -void NACT_Sys3::cmd_s() -{ - int page = getd(); - - output_console("\nS %d:", page); - - if(page) { - mako->play_music(page); - } else { - mako->stop_music(); - } -} - -void NACT_Sys3::cmd_t() -{ - int x = cali(); - int y = cali(); - - output_console("\nT %d,%d:", x, y); - - // x方向はカラム単位で切り捨て - ags->text_dest_x = column ? x * 8 : x & 0xfff8; - ags->text_dest_y = y; -} - -void NACT_Sys3::cmd_u() -{ - int page = cali(); - int transparent = cali(); - - output_console("\nU %d,%d:", page, transparent); - - if(crc32_a == CRC32_RANCE41 || crc32_a == CRC32_RANCE41_ENG || - crc32_a == CRC32_RANCE42 || crc32_a == CRC32_RANCE42_ENG) { - transparent = (transparent == 28) ? 12 : transparent; - } - ags->load_cg(page, transparent); -} - -void NACT_Sys3::cmd_v() -{ - int cmd = cali(); - int index = cali(); - - output_console("\nV %d,%d:", cmd, index); - - if(cmd == 0) { - for(int i = 0; i < 20; i++) { - var[21 + i] = var_stack[index - 1][i]; - } - for(int i = 0; i < 10; i++) { - memcpy(tvar[i], tvar_stack[index - 1][i], 22); - } - } else { - for(int i = 0; i < 20; i++) { - var_stack[index - 1][i] = var[21 + i]; - } - for(int i = 0; i< 10; i++) { - memcpy(tvar_stack[index - 1][i], tvar[i], 22); - } - } -} - -void NACT_Sys3::cmd_w() -{ - int x = cali(); - int y = cali(); - uint8 color = (uint8)cali(); - - output_console("\nW %d,%d,%d", x, y, color); - - ags->paint(x, y, color); -} - -void NACT_Sys3::cmd_x() -{ - int index = getd(); - - output_console("\nX %d:", index); - - if(1 <= index && index <= 10) { - ags->draw_text(tvar[index - 1]); - } -} - -void NACT_Sys3::cmd_y() -{ - int cmd = cali(); - int param = cali(); - - output_console("\nY %d,%d:", cmd, param); - - switch(cmd) { - case 1: - ags->clear_text_window(text_window, (param == 0) ? true : false); - break; - case 2: - if(param == 0) { - for(int i = 1; i <= 20; i++) { - var[i] = 0; - } - } else if(param == 1) { - for(int i = 21; i <= 40; i++) { - var[i] = 0; - } - } else if(param == 2) { - for(int i = 41; i <= 56; i++) { - var[i] = 0; - } - } - break; - case 3: - if(param == 10000) { - wait_keydown = false; - } else if(param == 10001) { - wait_keydown = true; - } else { - Uint32 dwTime = SDL_GetTicks() + param * 1000 / 60; - for(;;) { - if(terminate) { - return; - } - RND = get_key(); - if(RND && wait_keydown) { - break; - } - if(dwTime <= SDL_GetTicks()) { - break; - } - sys_sleep(16); - } - } - break; - case 4: - RND = (param == 0 || param == 1) ? 0 : random(param); - break; - case 5: - break; - case 6: - break; - case 7: - ags->draw_box(param); - break; - case 8: - tvar_index = param; - break; - case 10: - ags->extract_palette_cg[param] = false; - break; - case 13: - if(param == 0 || param == 1) { - text_wait_time = 0; - } else { - text_wait_time = (param - 1) * 1000 / 60; - } - break; - case 14: - RND = 1; - break; - case 15: - break; - case 16: - mako->stop_music(); - break; - case 17: - if(param == 0) { - RND = mako->check_music() ? 1 : 0; - } else { - RND = 0; - } - break; - case 18: - { - int mark, loop; - mako->get_mark(&mark, &loop); - D01 = mark; - D02 = loop; - } - break; - case 19: - mako->next_loop = param; - break; - case 21: - break; - case 22: - break; - case 23: - break; - case 24: - break; - case 25: - ags->menu_font_size = (param == 1) ? 16 : (param == 2) ? 24 : (param == 3) ? 32 : (param == 4) ? 48 : (param == 5) ? 64 : 16; - break; - case 26: - ags->text_font_size = (param == 1) ? 16 : (param == 2) ? 24 : (param == 3) ? 32 : (param == 4) ? 48 : (param == 5) ? 64 : 16; - break; - case 27: - tvar_maxlen = param; - text_dialog(); - break; - case 28: - ags->text_space = (param == 0) ? 2 : 0; - break; - case 30: - ags->src_screen = param ? 1 : 0; - break; - case 31: - ags->dest_screen = param ? 1 : 0; - break; - case 32: - RND = (param <= 480) ? param : 480; - break; - case 33: - break; - case 40: - case 42: - ags->fade_in(param * 16 * 1000 / 60); - break; - case 41: - case 43: - ags->fade_out(param * 16 * 1000 / 60, cmd == 43); - break; - case 45: - ags->extract_palette = param ? true : false; - break; - case 46: - ags->get_palette = (param & 4) ? true : false; - ags->extract_palette = (param & 2) ? true : false; - ags->extract_cg = (param & 1) ? true : false; - break; - case 60: - ags->scroll = param; - ags->flush_screen(false); - break; - case 61: - if(param) { - ags->set_pixel(D03, D01, D02, (uint8)RND); - } else { - RND = ags->get_pixel(D03, D01, D02); - } - break; - case 70: - if(param == 2) { - int x, y; - get_cursor(&x, &y); - M_X = (x < 0) ? x : (x > 639) ? 639 : x; - M_Y = (y < 0) ? 0 : (y > 479) ? 479 : y; - if((RND = get_key())) { - // キー入力があった場合は、離すまで待機 - for(;;) { - if(terminate) { - return; - } - if(!get_key()) { - break; - } - sys_sleep(16); - } - } - } else if(param == 3) { - set_cursor(M_X, M_Y); - } - break; - case 71: - mouse_sence = param; - break; - case 72: - ags->load_cursor(param); - break; - case 73: - ags->cursor_index = param; - ags->select_cursor(); - break; - case 80: - if(param == 0) { - RND = label_depth; - } else if(param == 1) { - RND = page_depth; - } - break; - case 81: - if(param == 0) { - label_depth = label_depth ? label_depth - 1 : 0; - } else if(param == 1) { - page_depth = page_depth ? page_depth - 1 : 0; - } - break; - case 82: - if(param == 0) { - label_depth = 0; - } else if(param == 1) { - page_depth = 0; - } - break; - case 100: - RND = param; - break; - case 101: - pcm_index = param; - break; - case 102: - if(pcm_index < MAX_PCM) { - pcm[pcm_index] = param; - } - break; - case 103: - if(pcm_index < MAX_PCM) { - mako->play_pcm(pcm[pcm_index], param ? false : true); - } - break; - case 104: - mako->stop_pcm(); - break; - case 105: - RND = mako->check_pcm() ? 1 : 0; - break; - case 106: - // 乙女戦記で使用している謎のコマンド - // 多分PCM関連 - break; - case 221: - case 222: - case 223: - case 224: - case 225: - case 226: - case 227: - case 228: - case 229: - { - ags->draw_text(tvar[param - 1]); - int padlen = cmd - 220 - encoding->mbslen(tvar[param - 1]); - if (padlen > 0) { - char pad[10] = " "; - pad[padlen] = '\0'; - ags->draw_text(pad); - } - } - break; - case 230: - clear_text = param ? true : false; - break; - case 231: - D01 = 640; - D02 = (param == 1) ? ags->screen_height : 480; - D03 = (crc32_a == CRC32_YAKATA3_FD) ? 16 : 256; - break; - case 232: - if(ags->screen_height != (param ? 480 : 400)) { - // TODO: fix - // SendMessage(g_hwnd, WM_USER + 2, param ? 480 : 400, 0); - ags->screen_height = param ? 480 : 400; - } - break; - case 233: - break; - case 234: - ags->menu_fix = param ? true : false; - break; - case 235: - break; - case 236: - RND = 1024; - break; - case 237: - break; - case 238: - { - time_t timer; - time(&timer); - struct tm *t = localtime(&timer); - D01 = t->tm_year + 1900; - D02 = t->tm_mon + 1; - D03 = t->tm_mday; - D04 = t->tm_hour; - D05 = t->tm_min; - D06 = t->tm_sec; - D07 = t->tm_wday + 1; - } - break; - case 239: - if(1 <= param && param <= 26) { - char file_name[_MAX_PATH]; - sprintf_s(file_name, _MAX_PATH, "ASLEEP_%c.DAT", 'A' + param - 1); - - struct stat statbuf; - if (FILEIO::StatSavedata(file_name, &statbuf) != -1) { - struct tm *t = localtime(&statbuf.st_mtime); - D01 = t->tm_year + 1900; - D02 = t->tm_mon + 1; - D03 = t->tm_mday; - D04 = t->tm_hour; - D05 = t->tm_min; - D06 = t->tm_sec; - } else { - D01 = D02 = D03 = D04 = D05 = D06 = 0; - } - } else { - // 不正なファイル番号 - D01 = D02 = D03 = D04 = D05 = D06 = 0; - } - break; - case 240: - ags->draw_hankaku = (param == 1) ? true : false; - break; - case 241: - break; - case 250: -#if 0 - if(FILEIO::GetRootPath()[1] == ':') { - _TCHAR root_path[4]; - root_path[0] = FILEIO::GetRootPath()[0]; - root_path[1] = ':'; - root_path[2] = '\\'; - root_path[3] = '\0'; - - UINT t = GetDriveType(root_path); - // フロッピーから起動した場合は0が返る - //RND = (t == DRIVE_REMOVABLE) ? 0 : (t == DRIVE_CDROM) ? 2 : 1; - RND = (t == DRIVE_CDROM) ? 2 : 1; - } else { - // ネットワークドライブ? - RND = 1; - } -#else - RND = 1; -#endif - break; - case 251: - column = param ? false : true; - break; - case 252: - RND = (crc32_a == CRC32_YAKATA3_FD) ? 4 : 8; - break; - case 253: - show_push = (param == 0) ? true : false; - break; - case 254: - RND = (crc32_a == CRC32_YAKATA3_CD || crc32_a == CRC32_YAKATA3_FD || crc32_a == CRC32_NINGYO) ? 1 : 0; - break; - case 255: - post_quit = (param == 1) ? true : false; - fatal_error = true; - break; - } -} - -void NACT_Sys3::cmd_z() -{ - int cmd = cali(); - int param = cali(); - - output_console("\nZ %d,%d:", cmd, param); - - if(cmd == 0) { - ags->palette_bank = (uint8)(param & 0xff); - } else if(cmd == 1) { - ags->text_font_color = (uint8)(param & 0xff); - } else if(cmd == 2) { - ags->menu_font_color = (uint8)(param & 0xff); - } else if(cmd == 3) { - ags->menu_frame_color = (uint8)(param & 0xff); - } else if(cmd == 4) { - ags->menu_back_color = (uint8)(param & 0xff); - } else if(cmd == 5) { - ags->text_frame_color = (uint8)(param & 0xff); - } else if(cmd == 6) { - ags->text_back_color = (uint8)(param & 0xff); - } else if(cmd == 7) { - ags->cursor_color = (uint8)(param & 0xff); - } else if(101 <= cmd && cmd <= 199) { - mako->set_cd_track(cmd - 100, param); - } -} - - -// 下位関数 - -uint16 NACT_Sys3::cali() -{ - uint32 cali[256]; - int p = 1; - bool ok = false; - - while(p > 0) { - uint8 dat = getd(); - - if(0x80 <= dat && dat <= 0xbf) { - cali[p++] = var[dat & 0x3f]; - } else if(0xc0 <= dat && dat <= 0xff) { - cali[p++] = var[((dat & 0x3f) << 8) | getd()]; - } else if(0x00 <= dat && dat <= 0x3f) { - cali[p++] = ((dat & 0x3f) << 8) | getd(); - } else if(0x40 <= dat && dat <= 0x76) { - cali[p++] = dat & 0x3f; - } else if(dat == 0x77) { - cali[p - 2] = cali[p - 2] * cali[p - 1]; - if (cali[p - 2] > 65535) { - cali[p - 2] = 65535; - } - p--; - } else if(dat == 0x78) { - if(cali[p - 1]) { - cali[p - 2] = cali[p - 2] / cali[p - 1]; - } else { - cali[p - 2] = 0; - } - p--; - } else if(dat == 0x79) { - cali[p - 2] = cali[p - 2] + cali[p - 1]; - if (cali[p - 2] > 65535) { - cali[p - 2] = 65535; - } - p--; - } else if(dat == 0x7a) { - if(cali[p - 2] > cali[p - 1]) { - cali[p - 2] = cali[p - 2] - cali[p - 1]; - } else { - cali[p - 2] = 0; - } - p--; - } else if(dat == 0x7b) { - cali[p - 2] = (cali[p - 2] == cali[p - 1]) ? 1 : 0; - p--; - } else if(dat == 0x7c) { - cali[p - 2] = (cali[p - 2] < cali[p - 1]) ? 1 : 0; - p--; - } else if(dat == 0x7d) { - cali[p - 2] = (cali[p - 2] > cali[p - 1]) ? 1 : 0; - p--; - } else if(dat == 0x7e) { - cali[p - 2] = (cali[p - 2] != cali[p - 1]) ? 1 : 0; - p--; - } else if(dat == 0x7f) { - if(p == 2) { - ok = true; - } - p = 0; - } - } - if (!ok) { - fatal("cali: invalid expression"); - } - return (uint16)(cali[1] & 0xffff); -} - -uint16 NACT_Sys3::cali2() -{ - uint16 val = 0; - uint16 dat = getd(); - - if(0x80 <= dat && dat <= 0xbf) { - val = dat & 0x3f; - } else if(0xc0 <= dat && dat <= 0xff) { - val = ((dat & 0x3f) << 8) | getd(); - } else { - fatal("cali2: invalid expression"); - } - if(getd() != 0x7f) { - fatal("cali2: invalid expression"); - } - return val; -} +/* + ALICE SOFT SYSTEM 3 for Win32 + + [ NACT - command ] +*/ + +#include +#include +#include "nact.h" +#include "ags.h" +#include "mako.h" +#include "msgskip.h" +#include "crc32.h" +#include "../fileio.h" +#include "encoding.h" +#include "texthook.h" + +NACT_Sys3::NACT_Sys3(uint32 crc32_a, uint32 crc32_b, const Config& config) + : NACT(3, crc32_a, crc32_b, config) +{ +} + +void NACT_Sys3::cmd_calc() +{ + int index = getd(); + if(0x80 <= index && index <= 0xbf) { + index &= 0x3f; + } else { + index = ((index & 0x3f) << 8) | getd(); + } + var[index] = cali(); + + output_console("\n!var[%d]:%d!", index, var[index]); +} + +void NACT_Sys3::cmd_branch() +{ + int condition = cali(); + int t_addr = scenario_addr + 2; + int f_addr = getw(); + + // sigmarion3 最適化誤爆の対策 + scenario_addr = condition ? t_addr : f_addr; + + output_console("\n{%d: T:%4x, F:%4x", condition, t_addr, f_addr); +} + +void NACT_Sys3::cmd_label_jump() +{ + int next_addr = getw(); + scenario_addr = next_addr; + + output_console("\n@%x:", next_addr); +} + +void NACT_Sys3::cmd_label_call() +{ + int next_addr = getw(); + + output_console("\n\\%x:", next_addr); + + if(next_addr == 0) { + // リターン + if(label_depth == 0) { +// fatal_error = true; + return; + } + scenario_addr = label_stack[--label_depth]; + } else { + label_stack[label_depth++] = scenario_addr; + scenario_addr = next_addr; + } +} + +void NACT_Sys3::cmd_page_jump() +{ + int next_page = cali(); + load_scenario(next_page); + scenario_page = next_page; + scenario_addr = 2; + + output_console("\n&%d:", next_page); +} + +void NACT_Sys3::cmd_page_call() +{ + int next_page = cali(), next_addr; + + output_console("\n%%%d:", next_page); + + if(next_page == 0) { + // リターン + if(page_depth == 0) { +// fatal_error = true; + return; + } + next_page = page_stack[--page_depth]; + next_addr = addr_stack[page_depth]; + } else { + page_stack[page_depth] = scenario_page; + addr_stack[page_depth++] = scenario_addr; + next_addr = 2; + } + load_scenario(next_page); + scenario_page = next_page; + scenario_addr = next_addr; +} + +void NACT_Sys3::cmd_set_menu() +{ + if(ags->draw_menu) { + ags->menu_dest_x = 2; + ags->menu_dest_y += ags->menu_font_size + 2; + ags->draw_menu = false; + + output_console("$"); + } else { + if(!menu_index) { + ags->clear_menu_window(); + ags->menu_dest_y = 0; + } + menu_addr[menu_index++] = getw(); + ags->menu_dest_x = 2; + ags->menu_dest_y += 2; + ags->draw_menu = true; + + output_console("\n$%x,", menu_addr[menu_index - 1]); + } +} + +void NACT_Sys3::cmd_open_menu() +{ + output_console("\n]"); + + if(!menu_index) { + scenario_addr = scenario_data[0] | (scenario_data[1] << 8); + return; + } + + int index = menu_select(menu_index); + if (terminate) + return; + + if(index != -1) { + scenario_addr = menu_addr[index]; + } + menu_index = 0; +} + +void NACT_Sys3::cmd_set_verbobj() +{ + int verb = getd(); + int obj = getd(); + int addr = getw(); + + menu_addr[menu_index] = addr; + menu_verb[menu_index] = verb; + menu_obj[menu_index++] = obj; + verb_obj = true; + + output_console("\n[%x,%s,%s:", addr, caption_verb[verb], caption_obj[obj]); +} + +void NACT_Sys3::cmd_set_verbobj2() +{ + int condition = cali(); + int verb = getd(); + int obj = getd(); + int addr = getw(); + + if(condition) { + menu_addr[menu_index] = addr; + menu_verb[menu_index] = verb; + menu_obj[menu_index++] = obj; + } + verb_obj = true; + + output_console("\n:%d,%x,%s,%s:", condition, addr, caption_verb[verb], caption_obj[obj]); +} + +void NACT_Sys3::cmd_open_verb() +{ + // 動詞メニューの表示 + output_console("\nopen verb-obj menu"); + verb_obj = false; + + // 表示する動詞のチェック + int chk[MAX_VERB], page = 0; + + memset(chk, 0, sizeof(chk)); + for(int i = 0; i < menu_index; i++) { + chk[menu_verb[i]] = 1; + } + + // メニュー項目の準備 + int id[32], index = 0; + + ags->clear_menu_window(); + ags->menu_dest_y = 0; + ags->draw_menu = true; + + for(int i = 0; i < MAX_VERB; i++) { + if(chk[i]) { + ags->menu_dest_x = 2; + ags->menu_dest_y += 2; + ags->draw_text(caption_verb[i]); + id[index++] = i; + ags->menu_dest_y += ags->menu_font_size + 2; + } + } + ags->draw_menu = false; + + int selection = menu_select(index); + if (terminate) + return; + + if (selection == -1) { + scenario_addr = scenario_data[0] | (scenario_data[1] << 8); + } else { + cmd_open_obj(id[selection]); + } + menu_index = 0; +} + +void NACT_Sys3::cmd_open_obj(int verb) +{ + // 目的語メニューの表示 + verb_obj = false; + + // 表示する目的語のチェック + int chk[MAX_OBJ], addr[MAX_OBJ], page = 0; + + memset(chk, 0, sizeof(chk)); + for(int i = 0; i < menu_index; i++) { + if(menu_verb[i] == verb) { + chk[menu_obj[i]] = 1; + addr[menu_obj[i]] = menu_addr[i]; + } + } + // 目的語がない場合 + if(chk[0]) { + scenario_addr = addr[0]; + return; + } + // 以後、obj=0は戻るとして扱う + chk[0] = 0; + addr[0] = scenario_data[0] | (scenario_data[1] << 8); + + // メニュー項目の準備 + int id[32], index = 0; + + ags->clear_menu_window(); + ags->menu_dest_y = 0; + ags->draw_menu = true; + + for(int i = 0; i < MAX_OBJ; i++) { + if(chk[i]) { + ags->menu_dest_x = 2; + ags->menu_dest_y += 2; + ags->draw_text(caption_obj[i]); + id[index++] = i; + ags->menu_dest_y += ags->menu_font_size + 2; + } + } + // 戻るを追加 + ags->menu_dest_x = 2; + ags->menu_dest_y += 2; + ags->draw_text(strings.back.c_str()); + id[index++] = 0; + ags->menu_dest_y += ags->menu_font_size + 2; + ags->draw_menu = false; + + int selection = menu_select(index); + if (terminate) + return; + + if (selection == -1) { + scenario_addr = scenario_data[0] | (scenario_data[1] << 8); + } else { + scenario_addr = addr[id[selection]]; + } +} + +void NACT_Sys3::cmd_a() +{ + texthook_nextpage(); + + output_console("A\n"); + + if (msgskip->skipping()) { + if (msgskip->get_flags() & MSGSKIP_STOP_ON_CLICK && get_key()) + msgskip->activate(false); + } else if (show_push) { + ags->draw_push(text_window); + } + + // キーが押されて離されるまで待機 + while (!msgskip->skipping()) { + if(terminate) { + return; + } + if(get_key()) { + break; + } + sys_sleep(16); + } + sys_sleep(30); + while (!msgskip->skipping()) { + if(terminate) { + return; + } + if(!(get_key() & 0x18)) { + break; + } + sys_sleep(16); + } + + // ウィンドウ更新 + ags->clear_text_window(text_window, true); +} + +void NACT_Sys3::cmd_b() +{ + int cmd = getd(); + int index = cali(); + int p1 = cali(); + int p2 = cali(); + int p3 = cali(); + int p4 = cali(); + int p5 = cali(); + + output_console("\nB %d,%d,%d,%d,%d,%d,%d:", cmd, index, p1, p2, p3, p4, p5); + + if(cmd == 1) { + // あゆみちゃん物語 + if(crc32_a == CRC32_AYUMI_CD || crc32_a == CRC32_AYUMI_JISSHA_256 || crc32_a == CRC32_AYUMI_JISSHA_FULL) { + p5 = 1; + } + ags->menu_w[index - 1].sx = column ? p1 * 8 : p1 & 0xfff8; + ags->menu_w[index - 1].sy = p2; + ags->menu_w[index - 1].ex = column ? p3 * 8 - 1 : (p3 & 0xfff8) - 1; + ags->menu_w[index - 1].ey = p4; + ags->menu_w[index - 1].push = p5 ? true : false; + + // 退避画面の破棄 + if(ags->menu_w[index - 1].screen) { + free(ags->menu_w[index - 1].screen); + ags->menu_w[index - 1].screen = NULL; + } + } else if(cmd == 2) { + ags->menu_w[index - 1].frame = p1 ? true : false; + menu_window = index; + } else if(cmd == 3) { + ags->text_w[index - 1].sx = column ? p1 * 8 : p1 & 0xfff8; + ags->text_w[index - 1].sy = p2; + ags->text_w[index - 1].ex = column ? p3 * 8 - 1 : (p3 & 0xfff8) - 1; + ags->text_w[index - 1].ey = p4; + ags->text_w[index - 1].push = p5 ? true : false; + + // 退避画面の破棄 + if(ags->text_w[index - 1].screen) { + free(ags->text_w[index - 1].screen); + ags->text_w[index - 1].screen = NULL; + } + // 退避窓の破棄 + if(ags->text_w[index - 1].window) { + free(ags->text_w[index - 1].window); + ags->text_w[index - 1].window = NULL; + } + } else if(cmd == 4) { + if(p5 == 0) { + // ウィンドウ退避 + if(crc32_a == CRC32_PROSTUDENTG_CD && p4) { + // prostudent G オープニング画面化け対策 + if(ags->text_w[index - 1].window) { + free(ags->text_w[index - 1].window); + ags->text_w[index - 1].window = NULL; + } + } + ags->text_w[index - 1].frame = p1 ? true : false; + ags->open_text_window(index, p4 ? false : true); + text_window = index; + } else { + // ウィンドウ復帰 + ags->close_text_window(index, text_window == index ? true : false); + } + } +} + +void NACT_Sys3::cmd_d() +{ + // 未使用 + fatal("Unknown Command: 'D' at page = %d, addr = %d", scenario_page, prev_addr); +} + +void NACT_Sys3::cmd_e() +{ + int index = cali(); + uint8 color = (uint8)cali(); + int sx = cali(); + int sy = cali(); + int ex = cali(); + int ey = cali(); + + output_console("\nE %d,%d,%d,%d,%d,%d:", index, color, sx, sy, ex, ey); + + ags->box[index - 1].color = color; + ags->box[index - 1].sx = column ? sx * 8 : sx; + ags->box[index - 1].sy = sy; + ags->box[index - 1].ex = column ? ex * 8 - 1 : ex; // ? + ags->box[index - 1].ey = ey; +} + +void NACT_Sys3::cmd_f() +{ + output_console("\nF"); + + scenario_addr = 2; +} + +void NACT_Sys3::cmd_g() +{ + int page = cali(); + + output_console("\nG %d:", page); + + ags->load_cg(page, -1); +} + +void NACT_Sys3::cmd_h() +{ + int length = getd(); + int val = cali(); + + output_console("\nH %d,%d:", length, val); + + // 隠しコマンド? + if(length >= 9) { + return; + } + + // 8桁の文字列を生成 + char tmp[8]; + tmp[0] = '0'; + tmp[1] = '0'; + tmp[2] = '0'; + for(int i = 3, ref = 10000; i < 8; i++) { + tmp[i] = '0' + (int)(val / ref); + val %= ref; + ref /= 10; + } + for(int i = 0; i < 7; i++) { + if(tmp[i] != '0') { + break; + } + tmp[i] = ' '; + } + + // 指定した桁数だけ出力 + char string[9]; + int p = 0; + if(length == 0) { + for(int i = 0; i < 8; i++) { + if(tmp[i] != ' ') { + string[p++] = tmp[i]; + } + } + } else { + for(int i = 8 - length; i < 8; i++) { + string[p++] = tmp[i]; + } + } + string[p++] = '\0'; + ags->draw_text(string); +} + +void NACT_Sys3::cmd_i() +{ + int sx = cali(); + int sy = cali(); + int ex = cali(); + int ey = cali(); + int dx = cali(); + int dy = cali(); + + output_console("\nI %d,%d,%d,%d,%d,%d:", sx, sy, ex, ey, dx, dy); + + // X方向はカラム単位で切り捨て + sx = column ? sx * 8 : sx & 0xfff8; + ex = column ? ex * 8 - 1 : (crc32_a == CRC32_NINGYO) ? (ex & 0xfff8) + 7 : (ex & 0xfff8) - 1; + dx = column ? dx * 8 : dx & 0xfff8; + ags->copy(sx, sy, ex, ey, dx, dy); +} + +void NACT_Sys3::cmd_j() +{ + int x = cali(); + int y = cali(); + + output_console("\nJ %d,%d:", x, y); + + // x方向はカラム単位で切り捨て + ags->cg_dest_x = column ? x * 8 : x & 0xfff8; + ags->cg_dest_y = y; + ags->set_cg_dest = true; +} + +void NACT_Sys3::cmd_k() +{ + int cmd = getd(), val; + + output_console("\nK %d:", cmd); + + // K6の場合は、すぐに返る + if(cmd == 6) { + RND = get_key(); + return; + } + + // マウスの初期取得 + int mx, my; + get_cursor(&mx, &my); + + // キーが押されるまで待機 + for(;;) { + if(terminate) { + return; + } + if((val = get_key()) != 0) { + break; + } + if(1 <= cmd && cmd <= 3) { + // マウス対応 + int x, y, dx, dy; + get_cursor(&x, &y); + dx = (x < mx) ? mx - x : x - mx; + dy = (y < my) ? my - y : y - my; + if(dy > dx && my - y >= mouse_sence) { + val = 1; + } + if(dy > dx && y - my >= mouse_sence) { + val = 2; + } + if(dx > dy && mx - x >= mouse_sence) { + val = 4; + } + if(dx > dy && x - mx >= mouse_sence) { + val = 8; + } + if(val) { + RND = val; + return; + } + } + sys_sleep(16); + } + if(cmd != 0 && cmd != 4) { + RND = val; + } + + // キーが離されるまで待機 + if(cmd != 1) { + sys_sleep(100); + for(;;) { + if(terminate) { + return; + } + if(!(val = get_key())) { + break; + } + sys_sleep(16); + } + } + + // K0の場合は改行 + if(cmd == 0) { + cmd_r(); + } +} + +void NACT_Sys3::cmd_l() +{ + int index = cali(); + + output_console("\nL %d:", index); + + if(index == 0) { + // 特殊セーブ + FILEIO* fio = new FILEIO(); + if(fio->Fopen("ASLEEP.DAT", FILEIO_READ_BINARY | FILEIO_SAVEDATA)) { + // U01 - U20 + for(int i = 21; i <= 40; i++) { + var[i] = fio->Fgetw(); + } + // M1 - M10 + for(int i = 0; i < 10; i++) { + fio->Fread(tvar[i], 22, 1); + } + fio->Fclose(); + } + delete fio; + } else if(1 <= index && index <= 26) { + // ASLEEP_A.DAT - ASLEEP_Z.DAT + char file_name[_MAX_PATH]; + sprintf_s(file_name, _MAX_PATH, "ASLEEP_%c.DAT", 'A' + index - 1); + + FILEIO* fio = new FILEIO(); + if(fio->Fopen(file_name, FILEIO_READ_BINARY | FILEIO_SAVEDATA)) { + fio->Fseek(112, FILEIO_SEEK_SET); + + int next_page = fio->Fgetw() - 1; + fio->Fgetw(); + fio->Fgetw(); // cg no? + fio->Fgetw(); + int next_music = fio->Fgetw(); + fio->Fgetw(); + int next_addr = fio->Fgetw(); + fio->Fgetw(); + for(int i = 0; i < 512; i++) { + var[i] = fio->Fgetw(); + } + ags->menu_font_size = fio->Fgetw(); + ags->text_font_size = fio->Fgetw(); + ags->palette_bank = fio->Fgetw(); + if(!ags->palette_bank) { + ags->palette_bank = -1; + } + ags->text_font_color = fio->Fgetw(); + ags->menu_font_color = fio->Fgetw(); + ags->menu_frame_color = fio->Fgetw(); + ags->menu_back_color = fio->Fgetw(); + ags->text_frame_color = fio->Fgetw(); + ags->text_back_color = fio->Fgetw(); + for(int i = 0; i < 10; i++) { + ags->menu_w[i].sx = fio->Fgetw(); + ags->menu_w[i].sy = fio->Fgetw(); + ags->menu_w[i].ex = fio->Fgetw(); + ags->menu_w[i].ey = fio->Fgetw(); + ags->menu_w[i].push = fio->Fgetw() ? true : false; + ags->menu_w[i].frame = fio->Fgetw() ? true : false; + fio->Fgetw(); + fio->Fgetw(); + + if(ags->menu_w[i].screen) { + free(ags->menu_w[i].screen); + } + ags->menu_w[i].screen = NULL; + if(ags->menu_w[i].window) { + free(ags->menu_w[i].window); + } + ags->menu_w[i].window = NULL; + } + for(int i = 0; i < 10; i++) { + ags->text_w[i].sx = fio->Fgetw(); + ags->text_w[i].sy = fio->Fgetw(); + ags->text_w[i].ex = fio->Fgetw(); + ags->text_w[i].ey = fio->Fgetw(); + ags->text_w[i].push = fio->Fgetw() ? true : false; + ags->text_w[i].frame = fio->Fgetw() ? true : false; + fio->Fgetw(); + fio->Fgetw(); + + if(ags->text_w[i].screen) { + free(ags->text_w[i].screen); + } + ags->text_w[i].screen = NULL; + if(ags->text_w[i].window) { + free(ags->text_w[i].window); + } + ags->text_w[i].window = NULL; + } + for(int i = 0; i < 10; i++) { + fio->Fread(tvar[i], 22, 1); + } + for(int i = 0; i < 30; i++) { + for(int j = 0; j < 10; j++) { + fio->Fread(tvar_stack[i][j], 22, 1); + } + } + for(int i = 0; i < 30; i++) { + for(int j = 0; j < 20; j++) { + var_stack[i][j] = fio->Fgetw(); + } + } + fio->Fclose(); + + load_scenario(next_page); + scenario_page = next_page; + scenario_addr = next_addr; + + mako->play_music(next_music); + } + delete fio; + } else if(101 <= index && index <= 126) { + // ASLEEP_A.DAT - ASLEEP_Z.DAT + char file_name[_MAX_PATH]; + sprintf_s(file_name, _MAX_PATH, "ASLEEP_%c.DAT", 'A' + index - 101); + + FILEIO* fio = new FILEIO(); + if(fio->Fopen(file_name, FILEIO_READ_BINARY | FILEIO_SAVEDATA)) { + fio->Fseek(112 + 16, FILEIO_SEEK_SET); + var[0] = fio->Fgetw(); + fio->Fclose(); + } + delete fio; + } +} + +void NACT_Sys3::cmd_m() +{ + char string[22]; + + int d = getd(); + if (d == '\'' || d == '"') { // SysEng + get_string(string, sizeof(string), d); + } else { + int p = 0; + while(d != ':') { + string[p++] = d; + d = getd(); + } + string[p] = '\0'; + } + + output_console("\nM %s:", string); + + if(1 <= tvar_index && tvar_index <= 10) { + memcpy(tvar[tvar_index - 1], string, 22); + } else if(tvar_index == 31) { + strcpy_s(adisk, 16, string); + } else if(tvar_index == 32) { + strcpy_s(ags->acg, 16, string); + } else if(tvar_index == 33) { + strcpy_s(mako->amus, 16, string); + } else if(tvar_index == 34) { + strcpy_s(mako->amse, 16, string); + } +} + +void NACT_Sys3::cmd_n() +{ + int cmd = getd(); + int src = cali(); + int dest = cali(); + + output_console("\nN %d,%d,%d:", cmd, src, dest); +} + +void NACT_Sys3::cmd_o() +{ + int cmd = cali(); + if(cmd == 0) { + uint16 val = cali(); + B01 = (val & 0x0001) ? 1 : 0; + B02 = (val & 0x0002) ? 1 : 0; + B03 = (val & 0x0004) ? 1 : 0; + B04 = (val & 0x0008) ? 1 : 0; + B05 = (val & 0x0010) ? 1 : 0; + B06 = (val & 0x0020) ? 1 : 0; + B07 = (val & 0x0040) ? 1 : 0; + B08 = (val & 0x0080) ? 1 : 0; + B09 = (val & 0x0100) ? 1 : 0; + B10 = (val & 0x0200) ? 1 : 0; + B11 = (val & 0x0400) ? 1 : 0; + B12 = (val & 0x0800) ? 1 : 0; + B13 = (val & 0x1000) ? 1 : 0; + B14 = (val & 0x2000) ? 1 : 0; + B15 = (val & 0x4000) ? 1 : 0; + B16 = (val & 0x8000) ? 1 : 0; + + output_console("\nO %d,%d:", cmd, val); + } else { + uint16 val = 0; + val |= B01 ? 0x0001 : 0; + val |= B02 ? 0x0002 : 0; + val |= B03 ? 0x0004 : 0; + val |= B04 ? 0x0008 : 0; + val |= B05 ? 0x0010 : 0; + val |= B06 ? 0x0020 : 0; + val |= B07 ? 0x0040 : 0; + val |= B08 ? 0x0080 : 0; + val |= B09 ? 0x0100 : 0; + val |= B10 ? 0x0200 : 0; + val |= B11 ? 0x0400 : 0; + val |= B12 ? 0x0800 : 0; + val |= B13 ? 0x1000 : 0; + val |= B14 ? 0x2000 : 0; + val |= B15 ? 0x4000 : 0; + val |= B16 ? 0x8000 : 0; + int index = cali2(); + var[index] = val; + + output_console("\nO %d,var[%d]:", cmd, index); + } +} + +void NACT_Sys3::cmd_p() +{ + int index =cali(); + int r = cali(); + int g = cali(); + int b = cali(); + + output_console("\nP %d,%d,%d,%d:", index, r, g, b); + + ags->set_palette(index, r, g, b); + set_palette = true; +} + +#define FWRITE(data, size) { \ + memcpy(&buffer[p], data, size); \ + p += size; \ +} +#define FPUTW(data) { \ + uint16 tmp = (data); \ + buffer[p++] = tmp & 0xff; \ + buffer[p++] = (tmp >> 8) & 0xff; \ +} + +void NACT_Sys3::cmd_q() +{ + static char header[112] = { +#if 0 + // 夢幻泡影についてきたASLEEP_A.DATのヘッダ + 'T', 'h', 'i', 's', ' ', 'i', 's', ' ', 's', 'a', 'v', 'e', ' ', 'd', 'a', 't', + 'a', ' ', 'f', 'o', 'r', ' ', 'S', 'y', 's', 't', 'e', 'm', '3', ' ', ' ', 'U', + 'n', 'i', 'o', 'n', ' ', '[', 'P', 'C', '9', '8', '0', '1', ':', 'F', 'M', 'T', + 'O', 'W', 'N', 'S', ':', 'X', '6', '8', '0', '0', '0', ']', ' ', 'F', 'o', 'r', + ' ', 'N', 'A', 'C', 'T', '/', 'A', 'D', 'V', ' ', 's', 'y', 's', 't', 'e', 'm', + ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', '(', 'C', ')', '1', '9', '9', + '4', ' ', 'A', 'L', 'I', 'C', 'E', '-', 'S', 'O', 'F', 'T', ' ', ' ', ' ', ' ' +#else + // 偽ヘッダ + 'T', 'h', 'i', 's', ' ', 'i', 's', ' ', 's', 'a', 'v', 'e', ' ', 'd', 'a', 't', + 'a', ' ', 'f', 'o', 'r', ' ', 'S', 'y', 's', 't', 'e', 'm', '3', ' ', ' ', 'U', + 'n', 'i', 'o', 'n', ' ', '[', 'W', 'i', 'n', '9', 'x', '/', 'N', 'T', '4', '0', + '/', '2', '0', '0', '0', '/', 'X', 'P', '/', 'C', 'E', ']', ' ', 'F', 'o', 'r', + ' ', 'N', 'A', 'C', 'T', '/', 'A', 'D', 'V', ' ', 's', 'y', 's', 't', 'e', 'm', + ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', '(', 'C', ')', '2', '0', '0', + '4', ' ', 'A', 'L', 'I', 'C', 'E', '-', 'S', 'O', 'F', 'T', ' ', ' ', ' ', ' ' +#endif + }; + + int index = cali(); + + output_console("\nQ %d:", index); + + if(index == 0) { + // 特殊セーブ + FILEIO* fio = new FILEIO(); + if(fio->Fopen("ASLEEP.DAT", FILEIO_WRITE_BINARY | FILEIO_SAVEDATA)) { + // U01 - U20 + for(int i = 21; i <= 40; i++) { + fio->Fputw(var[i]); + } + // M1 - M10 + for(int i = 0; i < 10; i++) { + fio->Fwrite(tvar[i], 22, 1); + } + fio->Fclose(); + } + delete fio; + } else if(1 <= index && index <= 26) { + // ASLEEP_A.DAT - ASLEEP_Z.DAT + char file_name[_MAX_PATH]; + sprintf_s(file_name, _MAX_PATH, "ASLEEP_%c.DAT", 'A' + index - 1); + + FILEIO* fio = new FILEIO(); + if(fio->Fopen(file_name, FILEIO_WRITE_BINARY | FILEIO_SAVEDATA)) { + uint8 buffer[9510]; + int p = 0; + + FWRITE(header, 112); + FPUTW(scenario_page + 1); + FPUTW(0); + FPUTW(0); // cg no? + FPUTW(0); + FPUTW(mako->current_music); + FPUTW(0); + FPUTW(scenario_addr); + FPUTW(0); + for(int i = 0; i < 512; i++) { + FPUTW(var[i]); + } + FPUTW(ags->menu_font_size); + FPUTW(ags->text_font_size); + FPUTW(ags->palette_bank == -1 ? 0 : ags->palette_bank); + FPUTW(ags->text_font_color); + FPUTW(ags->menu_font_color); + FPUTW(ags->menu_frame_color); + FPUTW(ags->menu_back_color); + FPUTW(ags->text_frame_color); + FPUTW(ags->text_back_color); + for(int i = 0; i < 10; i++) { + FPUTW(ags->menu_w[i].sx); + FPUTW(ags->menu_w[i].sy); + FPUTW(ags->menu_w[i].ex); + FPUTW(ags->menu_w[i].ey); + FPUTW(ags->menu_w[i].push ? 1 : 0); + FPUTW(ags->menu_w[i].frame ? 1 : 0); + FPUTW(0); + FPUTW(0); + } + for(int i = 0; i < 10; i++) { + FPUTW(ags->text_w[i].sx); + FPUTW(ags->text_w[i].sy); + FPUTW(ags->text_w[i].ex); + FPUTW(ags->text_w[i].ey); + FPUTW(ags->text_w[i].push ? 1 : 0); + FPUTW(ags->text_w[i].frame ? 1 : 0); + FPUTW(0); + FPUTW(0); + } + for(int i = 0; i < 10; i++) { + FWRITE(tvar[i], 22); + } + for(int i = 0; i < 30; i++) { + for(int j = 0; j < 10; j++) { + FWRITE(tvar_stack[i][j], 22); + } + } + for(int i = 0; i < 30; i++) { + for(int j = 0; j < 20; j++) { + FPUTW(var_stack[i][j]); + } + } + + fio->Fwrite(buffer, 9510, 1); + fio->Fclose(); + } + delete fio; + } +} + +void NACT_Sys3::cmd_r() +{ + texthook_newline(); + + output_console("R\n"); + + // ウィンドウの表示範囲外の場合は改ページ + if(ags->return_text_line(text_window)) { + cmd_a(); + } +} + +void NACT_Sys3::cmd_s() +{ + int page = getd(); + + output_console("\nS %d:", page); + + if(page) { + mako->play_music(page); + } else { + mako->stop_music(); + } +} + +void NACT_Sys3::cmd_t() +{ + int x = cali(); + int y = cali(); + + output_console("\nT %d,%d:", x, y); + + // x方向はカラム単位で切り捨て + ags->text_dest_x = column ? x * 8 : x & 0xfff8; + ags->text_dest_y = y; +} + +void NACT_Sys3::cmd_u() +{ + int page = cali(); + int transparent = cali(); + + output_console("\nU %d,%d:", page, transparent); + + if(crc32_a == CRC32_RANCE41 || crc32_a == CRC32_RANCE41_ENG || + crc32_a == CRC32_RANCE42 || crc32_a == CRC32_RANCE42_ENG) { + transparent = (transparent == 28) ? 12 : transparent; + } + ags->load_cg(page, transparent); +} + +void NACT_Sys3::cmd_v() +{ + int cmd = cali(); + int index = cali(); + + output_console("\nV %d,%d:", cmd, index); + + if(cmd == 0) { + for(int i = 0; i < 20; i++) { + var[21 + i] = var_stack[index - 1][i]; + } + for(int i = 0; i < 10; i++) { + memcpy(tvar[i], tvar_stack[index - 1][i], 22); + } + } else { + for(int i = 0; i < 20; i++) { + var_stack[index - 1][i] = var[21 + i]; + } + for(int i = 0; i< 10; i++) { + memcpy(tvar_stack[index - 1][i], tvar[i], 22); + } + } +} + +void NACT_Sys3::cmd_w() +{ + int x = cali(); + int y = cali(); + uint8 color = (uint8)cali(); + + output_console("\nW %d,%d,%d", x, y, color); + + ags->paint(x, y, color); +} + +void NACT_Sys3::cmd_x() +{ + int index = getd(); + + output_console("\nX %d:", index); + + if(1 <= index && index <= 10) { + ags->draw_text(tvar[index - 1]); + } +} + +void NACT_Sys3::cmd_y() +{ + int cmd = cali(); + int param = cali(); + + output_console("\nY %d,%d:", cmd, param); + + switch(cmd) { + case 1: + ags->clear_text_window(text_window, (param == 0) ? true : false); + break; + case 2: + if(param == 0) { + for(int i = 1; i <= 20; i++) { + var[i] = 0; + } + } else if(param == 1) { + for(int i = 21; i <= 40; i++) { + var[i] = 0; + } + } else if(param == 2) { + for(int i = 41; i <= 56; i++) { + var[i] = 0; + } + } + break; + case 3: + if(param == 10000) { + wait_keydown = false; + } else if(param == 10001) { + wait_keydown = true; + } else { + Uint32 dwTime = SDL_GetTicks() + param * 1000 / 60; + for(;;) { + if(terminate) { + return; + } + RND = get_key(); + if(RND && wait_keydown) { + break; + } + if(dwTime <= SDL_GetTicks()) { + break; + } + sys_sleep(16); + } + } + break; + case 4: + RND = (param == 0 || param == 1) ? 0 : random(param); + break; + case 5: + break; + case 6: + break; + case 7: + ags->draw_box(param); + break; + case 8: + tvar_index = param; + break; + case 10: + ags->extract_palette_cg[param] = false; + break; + case 13: + if(param == 0 || param == 1) { + text_wait_time = 0; + } else { + text_wait_time = (param - 1) * 1000 / 60; + } + break; + case 14: + RND = 1; + break; + case 15: + break; + case 16: + mako->stop_music(); + break; + case 17: + if(param == 0) { + RND = mako->check_music() ? 1 : 0; + } else { + RND = 0; + } + break; + case 18: + { + int mark, loop; + mako->get_mark(&mark, &loop); + D01 = mark; + D02 = loop; + } + break; + case 19: + mako->next_loop = param; + break; + case 21: + break; + case 22: + break; + case 23: + break; + case 24: + break; + case 25: + ags->menu_font_size = (param == 1) ? 16 : (param == 2) ? 24 : (param == 3) ? 32 : (param == 4) ? 48 : (param == 5) ? 64 : 16; + break; + case 26: + ags->text_font_size = (param == 1) ? 16 : (param == 2) ? 24 : (param == 3) ? 32 : (param == 4) ? 48 : (param == 5) ? 64 : 16; + break; + case 27: + tvar_maxlen = param; + text_dialog(); + break; + case 28: + ags->text_space = (param == 0) ? 2 : 0; + break; + case 30: + ags->src_screen = param ? 1 : 0; + break; + case 31: + ags->dest_screen = param ? 1 : 0; + break; + case 32: + RND = (param <= 480) ? param : 480; + break; + case 33: + break; + case 40: + case 42: + ags->fade_in(param * 16 * 1000 / 60); + break; + case 41: + case 43: + ags->fade_out(param * 16 * 1000 / 60, cmd == 43); + break; + case 45: + ags->extract_palette = param ? true : false; + break; + case 46: + ags->get_palette = (param & 4) ? true : false; + ags->extract_palette = (param & 2) ? true : false; + ags->extract_cg = (param & 1) ? true : false; + break; + case 60: + ags->scroll = param; + ags->flush_screen(false); + break; + case 61: + if(param) { + ags->set_pixel(D03, D01, D02, (uint8)RND); + } else { + RND = ags->get_pixel(D03, D01, D02); + } + break; + case 70: + if(param == 2) { + int x, y; + get_cursor(&x, &y); + M_X = (x < 0) ? x : (x > 639) ? 639 : x; + M_Y = (y < 0) ? 0 : (y > 479) ? 479 : y; + if((RND = get_key())) { + // キー入力があった場合は、離すまで待機 + for(;;) { + if(terminate) { + return; + } + if(!get_key()) { + break; + } + sys_sleep(16); + } + } + } else if(param == 3) { + set_cursor(M_X, M_Y); + } + break; + case 71: + mouse_sence = param; + break; + case 72: + ags->load_cursor(param); + break; + case 73: + ags->cursor_index = param; + ags->select_cursor(); + break; + case 80: + if(param == 0) { + RND = label_depth; + } else if(param == 1) { + RND = page_depth; + } + break; + case 81: + if(param == 0) { + label_depth = label_depth ? label_depth - 1 : 0; + } else if(param == 1) { + page_depth = page_depth ? page_depth - 1 : 0; + } + break; + case 82: + if(param == 0) { + label_depth = 0; + } else if(param == 1) { + page_depth = 0; + } + break; + case 100: + RND = param; + break; + case 101: + pcm_index = param; + break; + case 102: + if(pcm_index < MAX_PCM) { + pcm[pcm_index] = param; + } + break; + case 103: + if(pcm_index < MAX_PCM) { + mako->play_pcm(pcm[pcm_index], param ? false : true); + } + break; + case 104: + mako->stop_pcm(); + break; + case 105: + RND = mako->check_pcm() ? 1 : 0; + break; + case 106: + // 乙女戦記で使用している謎のコマンド + // 多分PCM関連 + break; + case 221: + case 222: + case 223: + case 224: + case 225: + case 226: + case 227: + case 228: + case 229: + { + ags->draw_text(tvar[param - 1]); + int padlen = cmd - 220 - encoding->mbslen(tvar[param - 1]); + if (padlen > 0) { + char pad[10] = " "; + pad[padlen] = '\0'; + ags->draw_text(pad); + } + } + break; + case 230: + clear_text = param ? true : false; + break; + case 231: + D01 = 640; + D02 = (param == 1) ? ags->screen_height : 480; + D03 = (crc32_a == CRC32_YAKATA3_FD) ? 16 : 256; + break; + case 232: + if(ags->screen_height != (param ? 480 : 400)) { + // TODO: fix + // SendMessage(g_hwnd, WM_USER + 2, param ? 480 : 400, 0); + ags->screen_height = param ? 480 : 400; + } + break; + case 233: + break; + case 234: + ags->menu_fix = param ? true : false; + break; + case 235: + break; + case 236: + RND = 1024; + break; + case 237: + break; + case 238: + { + time_t timer; + time(&timer); + struct tm *t = localtime(&timer); + D01 = t->tm_year + 1900; + D02 = t->tm_mon + 1; + D03 = t->tm_mday; + D04 = t->tm_hour; + D05 = t->tm_min; + D06 = t->tm_sec; + D07 = t->tm_wday + 1; + } + break; + case 239: + if(1 <= param && param <= 26) { + char file_name[_MAX_PATH]; + sprintf_s(file_name, _MAX_PATH, "ASLEEP_%c.DAT", 'A' + param - 1); + + struct stat statbuf; + if (FILEIO::StatSavedata(file_name, &statbuf) != -1) { + struct tm *t = localtime(&statbuf.st_mtime); + D01 = t->tm_year + 1900; + D02 = t->tm_mon + 1; + D03 = t->tm_mday; + D04 = t->tm_hour; + D05 = t->tm_min; + D06 = t->tm_sec; + } else { + D01 = D02 = D03 = D04 = D05 = D06 = 0; + } + } else { + // 不正なファイル番号 + D01 = D02 = D03 = D04 = D05 = D06 = 0; + } + break; + case 240: + ags->draw_hankaku = (param == 1) ? true : false; + break; + case 241: + break; + case 250: +#if 0 + if(FILEIO::GetRootPath()[1] == ':') { + _TCHAR root_path[4]; + root_path[0] = FILEIO::GetRootPath()[0]; + root_path[1] = ':'; + root_path[2] = '\\'; + root_path[3] = '\0'; + + UINT t = GetDriveType(root_path); + // フロッピーから起動した場合は0が返る + //RND = (t == DRIVE_REMOVABLE) ? 0 : (t == DRIVE_CDROM) ? 2 : 1; + RND = (t == DRIVE_CDROM) ? 2 : 1; + } else { + // ネットワークドライブ? + RND = 1; + } +#else + RND = 1; +#endif + break; + case 251: + column = param ? false : true; + break; + case 252: + RND = (crc32_a == CRC32_YAKATA3_FD) ? 4 : 8; + break; + case 253: + show_push = (param == 0) ? true : false; + break; + case 254: + RND = (crc32_a == CRC32_YAKATA3_CD || crc32_a == CRC32_YAKATA3_FD || crc32_a == CRC32_NINGYO) ? 1 : 0; + break; + case 255: + post_quit = (param == 1) ? true : false; + fatal_error = true; + break; + } +} + +void NACT_Sys3::cmd_z() +{ + int cmd = cali(); + int param = cali(); + + output_console("\nZ %d,%d:", cmd, param); + + if(cmd == 0) { + ags->palette_bank = (uint8)(param & 0xff); + } else if(cmd == 1) { + ags->text_font_color = (uint8)(param & 0xff); + } else if(cmd == 2) { + ags->menu_font_color = (uint8)(param & 0xff); + } else if(cmd == 3) { + ags->menu_frame_color = (uint8)(param & 0xff); + } else if(cmd == 4) { + ags->menu_back_color = (uint8)(param & 0xff); + } else if(cmd == 5) { + ags->text_frame_color = (uint8)(param & 0xff); + } else if(cmd == 6) { + ags->text_back_color = (uint8)(param & 0xff); + } else if(cmd == 7) { + ags->cursor_color = (uint8)(param & 0xff); + } else if(101 <= cmd && cmd <= 199) { + mako->set_cd_track(cmd - 100, param); + } +} + + +// 下位関数 + +uint16 NACT_Sys3::cali() +{ + uint32 cali[256]; + int p = 1; + bool ok = false; + + while(p > 0) { + uint8 dat = getd(); + + if(0x80 <= dat && dat <= 0xbf) { + cali[p++] = var[dat & 0x3f]; + } else if(0xc0 <= dat && dat <= 0xff) { + cali[p++] = var[((dat & 0x3f) << 8) | getd()]; + } else if(0x00 <= dat && dat <= 0x3f) { + cali[p++] = ((dat & 0x3f) << 8) | getd(); + } else if(0x40 <= dat && dat <= 0x76) { + cali[p++] = dat & 0x3f; + } else if(dat == 0x77) { + cali[p - 2] = cali[p - 2] * cali[p - 1]; + if (cali[p - 2] > 65535) { + cali[p - 2] = 65535; + } + p--; + } else if(dat == 0x78) { + if(cali[p - 1]) { + cali[p - 2] = cali[p - 2] / cali[p - 1]; + } else { + cali[p - 2] = 0; + } + p--; + } else if(dat == 0x79) { + cali[p - 2] = cali[p - 2] + cali[p - 1]; + if (cali[p - 2] > 65535) { + cali[p - 2] = 65535; + } + p--; + } else if(dat == 0x7a) { + if(cali[p - 2] > cali[p - 1]) { + cali[p - 2] = cali[p - 2] - cali[p - 1]; + } else { + cali[p - 2] = 0; + } + p--; + } else if(dat == 0x7b) { + cali[p - 2] = (cali[p - 2] == cali[p - 1]) ? 1 : 0; + p--; + } else if(dat == 0x7c) { + cali[p - 2] = (cali[p - 2] < cali[p - 1]) ? 1 : 0; + p--; + } else if(dat == 0x7d) { + cali[p - 2] = (cali[p - 2] > cali[p - 1]) ? 1 : 0; + p--; + } else if(dat == 0x7e) { + cali[p - 2] = (cali[p - 2] != cali[p - 1]) ? 1 : 0; + p--; + } else if(dat == 0x7f) { + if(p == 2) { + ok = true; + } + p = 0; + } + } + if (!ok) { + fatal("cali: invalid expression"); + } + return (uint16)(cali[1] & 0xffff); +} + +uint16 NACT_Sys3::cali2() +{ + uint16 val = 0; + uint16 dat = getd(); + + if(0x80 <= dat && dat <= 0xbf) { + val = dat & 0x3f; + } else if(0xc0 <= dat && dat <= 0xff) { + val = ((dat & 0x3f) << 8) | getd(); + } else { + fatal("cali2: invalid expression"); + } + if(getd() != 0x7f) { + fatal("cali2: invalid expression"); + } + return val; +} diff --git a/src/win/mako.cpp b/src/win/mako.cpp index 8b89fcb..8d9ef39 100644 --- a/src/win/mako.cpp +++ b/src/win/mako.cpp @@ -1,498 +1,498 @@ -/* - ALICE SOFT SYSTEM 3 for Win32 - - [ MAKO ] -*/ - -#include -#undef ERROR -#include -#include -#include -#include -#include "mako.h" -#include "mako_midi.h" -#include "fm/mako_fmgen.h" -#include "../config.h" -#include "dri.h" -#include "crc32.h" - -extern SDL_Window* g_window; - -namespace { - -const int SAMPLE_RATE = 44100; - -// Per-game mapping from music numbers to CD tracks. This is necessary to -// forcibly change the sound device with a menu command. -// -// When the game uses "Z 100+x,y" command, the xth element of the array should -// be y. The array must be terminated with -1. -const int8 RANCE41_tracks[] = {2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,1,-1}; -const int8 RANCE42_tracks[] = {2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,1,-1}; -const int8 DPSALL_tracks[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,5,1,2,3,-1}; - -enum MakoThreadMessage { - MAKO_OPEN = WM_APP, - MAKO_PLAY, - MAKO_STOP, - MAKO_EXIT -}; - -enum MakoOpenFlags { - OPEN_CD = 0, - OPEN_MIDI = 1, -}; - -const char* mci_geterror(DWORD err) -{ - static char buf[128]; - mciGetErrorString(err, buf, sizeof(buf)); - return buf; -} - -class MCIThread { -public: - MCIThread(NACT* nact, HWND hwnd_notify) : hwnd_notify(hwnd_notify) { - if (!_beginthreadex(NULL, 0, &MCIThread::run, this, 0, &thread_id)) - nact->fatal("Cannot create thread: %s", strerror(errno)); - } - - bool post_message(UINT msg, WPARAM wparam, LPARAM lparam) { - return PostThreadMessage(thread_id, msg, wparam, lparam); - } - - MCIDEVICEID device_id() { return devid; } - -private: - static unsigned __stdcall run(void* param) - { - MCIThread* t = reinterpret_cast(param); - t->message_loop(); - delete t; - return 0; - } - - void message_loop() - { - MSG msg; - while (GetMessage(&msg, NULL, 0, 0)) { - switch (msg.message) { - case MAKO_OPEN: - close(); - open(reinterpret_cast(msg.wParam), - static_cast(msg.lParam)); - break; - - case MAKO_PLAY: - play(); - break; - - case MAKO_STOP: - close(); - break; - - case MAKO_EXIT: - close(); - return; - } - } - } - - void open(std::string* file, MakoOpenFlags open_flags) - { - file_playing = file; - is_midi = open_flags & OPEN_MIDI; - - MCI_OPEN_PARMS open; - open.lpstrElementName = file_playing->c_str(); - DWORD flags = MCI_OPEN_ELEMENT | MCI_WAIT; - if (is_midi) { - flags |= MCI_OPEN_TYPE | MCI_OPEN_TYPE_ID; - open.lpstrDeviceType = (LPCSTR)MCI_DEVTYPE_SEQUENCER; - } - MCIERROR err = mciSendCommand(0, MCI_OPEN, flags, (DWORD_PTR)&open); - if (err) { - WARNING("MCI_OPEN failed: %s: %s", - file_playing->c_str(), mci_geterror(err)); - return; - } - devid = open.wDeviceID; - } - - void play() - { - MCI_PLAY_PARMS play; - play.dwCallback = (DWORD_PTR)hwnd_notify; - play.dwFrom = 0; - DWORD flags = MCI_FROM | MCI_NOTIFY; - MCIERROR err = mciSendCommand(devid, MCI_PLAY, flags, (DWORD_PTR)&play); - if (err) - WARNING("MCI_PLAY failed: %s", mci_geterror(err)); - } - - void close() { - if (devid) { - mciSendCommand(devid, MCI_CLOSE, 0, 0); - devid = 0; - } - if (file_playing) { - if (is_midi) - DeleteFile(file_playing->c_str()); // remove temporary file - delete file_playing; - file_playing = nullptr; - } - } - - HWND hwnd_notify; - unsigned thread_id; - std::string* file_playing = nullptr; - bool is_midi; - MCIDEVICEID devid = 0; -}; - -MCIThread* mci_thread; - -class Music { -public: - Music(const char* fname, int loop) : loops(loop) { - std::string* fname_str = new std::string(fname); - mci_thread->post_message(MAKO_OPEN, (WPARAM)fname_str, OPEN_CD); - mci_thread->post_message(MAKO_PLAY, 0, 0); - playing = true; - } - - Music(std::unique_ptr midi, int loop) : loops(loop ? 1 : 0) { - std::vector smf = midi->generate_smf(loop); - char path[MAX_PATH + 1]; - if (!GetTempPath(sizeof(path), path)) { - WARNING("GetTempPath failed: 0x%x", GetLastError()); - return; - } - char fname[MAX_PATH + 1]; - if (!GetTempFileName(path, "mid", 0, fname)) { - WARNING("GetTempFileName failed: 0x%x", GetLastError()); - return; - } - FILE* fp = fopen(fname, "wb"); - if (!fp) { - WARNING("Cannot open %s: %s", fname, strerror(errno)); - return; - } - if (fwrite(smf.data(), smf.size(), 1, fp) != 1) { - WARNING("Cannot write to %s: %s", fname, strerror(errno)); - fclose(fp); - DeleteFile(fname); - return; - } - fclose(fp); - - std::string* fname_str = new std::string(fname); - mci_thread->post_message(MAKO_OPEN, (WPARAM)fname_str, OPEN_MIDI); - mci_thread->post_message(MAKO_PLAY, 0, 0); - playing = true; - } - - ~Music() { - close(); - } - - void close() { - mci_thread->post_message(MAKO_STOP, 0, 0); - playing = false; - } - - bool is_playing() { - return playing; - } - - bool on_mci_notify(const SDL_SysWMmsg* msg) { - if (msg->msg.win.lParam != mci_thread->device_id()) - return true; - switch (msg->msg.win.wParam) { - case MCI_NOTIFY_FAILURE: - close(); - return false; - case MCI_NOTIFY_SUCCESSFUL: - if (loops && --loops == 0) { - close(); - return false; - } - mci_thread->post_message(MAKO_PLAY, 0, 0); - return true; - } - return true; - } - -private: - int loops; // number of times to play, 0 for infinite loop - bool playing; -}; - -Music* music; -uint8* wav_buffer; -SDL_mutex* fm_mutex; -std::unique_ptr fm; - -void audio_callback(void*, Uint8* stream, int len) { - SDL_LockMutex(fm_mutex); - fm->Process(reinterpret_cast(stream), len/ 4); - SDL_UnlockMutex(fm_mutex); -} - -} // namespace - -MAKO::MAKO(NACT* parent, const Config& config) : - use_fm(config.use_fm), - current_music(0), - next_loop(0), - nact(parent) -{ - if (!config.playlist.empty()) - load_playlist(config.playlist.c_str()); - - strcpy_s(amus, 16, "AMUS.DAT"); - strcpy_s(amse, 16, "AMSE.DAT"); // 実際には使わない - - for(int i = 1; i <= 99; i++) { - cd_track[i] = 0; - } - - SDL_InitSubSystem(SDL_INIT_AUDIO); - SDL_AudioSpec fmt; - SDL_zero(fmt); - fmt.freq = SAMPLE_RATE; - fmt.format = AUDIO_S16; - fmt.channels = 2; - fmt.samples = 4096; - fmt.callback = &audio_callback; - if (SDL_OpenAudio(&fmt, NULL) < 0) { - WARNING("SDL_OpenAudio: %s", SDL_GetError()); - use_fm = false; - } - fm_mutex = SDL_CreateMutex(); - - SDL_SysWMinfo info; - SDL_VERSION(&info.version); - if (!SDL_GetWindowWMInfo(g_window, &info)) - parent->fatal("SDL_GetWindowWMInfo failed: %s", SDL_GetError()); - mci_thread = new MCIThread(parent, info.info.win.window); -} - -MAKO::~MAKO() -{ - stop_music(); - stop_pcm(); - mci_thread->post_message(MAKO_EXIT, 0, 0); - mci_thread = nullptr; // MCIThread self-destructs on the worker thread. - - SDL_LockMutex(fm_mutex); - SDL_CloseAudio(); - SDL_UnlockMutex(fm_mutex); - SDL_DestroyMutex(fm_mutex); - fm_mutex = nullptr; - SDL_QuitSubSystem(SDL_INIT_AUDIO); -} - -bool MAKO::load_playlist(const char* path) -{ - FILE* fp = fopen(path, "rt"); - if (!fp) { - WARNING("Cannot open %s", path); - return false; - } - char buf[256]; - while (fgets(buf, sizeof(buf) - 1, fp)) { - char *p = &buf[strlen(buf) - 1]; - if (*p == '\n') - *p = '\0'; - playlist.push_back(buf[0] ? strdup(buf) : NULL); - } - fclose(fp); - return true; -} - -void MAKO::play_music(int page) -{ - if (current_music == page) - return; - - stop_music(); - - size_t track = page < 100 ? cd_track[page] : 0; - if (track) { - if (track >= playlist.size() || !playlist[track]) - return; - music = new Music(playlist[track], next_loop); - } else if (use_fm) { - DRI dri; - int size; - uint8* data = dri.load(amus, page, &size); - if (!data) - return; - - SDL_LockMutex(fm_mutex); - fm = std::make_unique(SAMPLE_RATE, data, true); - SDL_UnlockMutex(fm_mutex); - SDL_PauseAudio(0); - } else { - auto midi = std::make_unique(nact, amus); - if (!midi->load_mml(page)) - return; - midi->load_mda(page); - music = new Music(std::move(midi), next_loop); - } - current_music = page; -} - -void MAKO::stop_music() -{ - if (music) { - delete music; - music = nullptr; - } - SDL_PauseAudio(1); - current_music = 0; -} - -bool MAKO::check_music() -{ - return music && music->is_playing(); -} - -void MAKO::select_sound(BGMDevice dev) -{ - // 強制的に音源を変更する - int page = current_music; - int old_dev = (1 <= page && page <= 99 && cd_track[page]) ? BGM_CD : - use_fm ? BGM_FM : BGM_MIDI; - - switch (dev) { - case BGM_FM: - case BGM_MIDI: - for (int i = 1; i <= 99; i++) - cd_track[i] = 0; - use_fm = dev == BGM_FM; - break; - - case BGM_CD: - const int8* tracks; - - switch (nact->crc32_a) { - case CRC32_RANCE41: - case CRC32_RANCE41_ENG: - tracks = RANCE41_tracks; - break; - case CRC32_RANCE42: - case CRC32_RANCE42_ENG: - tracks = RANCE42_tracks; - break; - case CRC32_DPSALL: - tracks = DPSALL_tracks; - break; - - // For the following games, the default mapping (cd_track[i] = i) works. - case CRC32_AYUMI_CD: - case CRC32_FUNNYBEE_CD: - case CRC32_ONLYYOU: - default: - tracks = nullptr; - } - - if (tracks) { - for (int i = 0; tracks[i] >= 0; i++) - cd_track[i + 1] = tracks[i]; - } else { - for (int i = 1; i <= 99; i++) - cd_track[i] = i; - } - break; - } - - // デバイスが変更された場合は再演奏する - if (dev != old_dev && page) { - stop_music(); - play_music(page); - } -} - -void MAKO::get_mark(int* mark, int* loop) -{ - SDL_LockMutex(fm_mutex); - if (fm) { - fm->get_mark(mark, loop); - } else { - *mark = 0; - *loop = 0; - } - SDL_UnlockMutex(fm_mutex); -} - -void MAKO::play_pcm(int page, bool loop) -{ - static char header[44] = { - 'R' , 'I' , 'F' , 'F' , 0x00, 0x00, 0x00, 0x00, 'W' , 'A' , 'V' , 'E' , 'f' , 'm' , 't' , ' ' , - 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x40, 0x1f, 0x00, 0x00, 0x40, 0x1f, 0x00, 0x00, - 0x01, 0x00, 0x08, 0x00, 'd' , 'a' , 't' , 'a' , 0x00, 0x00, 0x00, 0x00 - }; - - stop_pcm(); - - uint8* buffer = NULL; - int size; - DRI* dri = new DRI(); - - if ((buffer = dri->load("AWAV.DAT", page, &size)) != NULL) { - // WAV形式 (Only You) - wav_buffer = buffer; - } else if ((buffer = dri->load("AMSE.DAT", page, &size)) != NULL) { - // AMSE形式 (乙女戦記) - int total = (size - 12) * 2 + 0x24; - int samples = (size - 12) * 2; - - wav_buffer = (uint8*)malloc(total + 8); - memcpy(wav_buffer, header, 44); - wav_buffer[ 4] = (total >> 0) & 0xff; - wav_buffer[ 5] = (total >> 8) & 0xff; - wav_buffer[ 6] = (total >> 16) & 0xff; - wav_buffer[ 7] = (total >> 24) & 0xff; - wav_buffer[40] = (samples >> 0) & 0xff; - wav_buffer[41] = (samples >> 8) & 0xff; - wav_buffer[42] = (samples >> 16) & 0xff; - wav_buffer[43] = (samples >> 24) & 0xff; - for(int i = 12, p = 44; i < size; i++) { - wav_buffer[p++] = buffer[i] & 0xf0; - wav_buffer[p++] = (buffer[i] & 0x0f) << 4; - } - free(buffer); - } - PlaySound((LPCTSTR)wav_buffer, NULL, SND_ASYNC | SND_MEMORY | (loop ? SND_LOOP : 0)); -} - -void MAKO::stop_pcm() -{ - PlaySound(NULL, NULL, SND_PURGE); - if (wav_buffer) { - free(wav_buffer); - wav_buffer = nullptr; - } -} - -bool MAKO::check_pcm() -{ - // 再生中でtrue - static const char null_wav[45] = { - 'R' , 'I' , 'F' , 'F' , 0x25, 0x00, 0x00, 0x00, 'W' , 'A' , 'V' , 'E' , 'f' , 'm' , 't' , ' ' , - 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x40, 0x1f, 0x00, 0x00, 0x40, 0x1f, 0x00, 0x00, - 0x01, 0x00, 0x08, 0x00, 'd' , 'a' , 't' , 'a' , 0x01, 0x00, 0x00, 0x00, 0x00 - }; - return !PlaySound(null_wav, NULL, SND_ASYNC | SND_MEMORY | SND_NOSTOP); -} - -void MAKO::on_mci_notify(const SDL_SysWMmsg* msg) -{ - if (!music) - return; - if (!music->on_mci_notify(msg)) - current_music = 0; -} +/* + ALICE SOFT SYSTEM 3 for Win32 + + [ MAKO ] +*/ + +#include +#undef ERROR +#include +#include +#include +#include +#include "mako.h" +#include "mako_midi.h" +#include "fm/mako_fmgen.h" +#include "../config.h" +#include "dri.h" +#include "crc32.h" + +extern SDL_Window* g_window; + +namespace { + +const int SAMPLE_RATE = 44100; + +// Per-game mapping from music numbers to CD tracks. This is necessary to +// forcibly change the sound device with a menu command. +// +// When the game uses "Z 100+x,y" command, the xth element of the array should +// be y. The array must be terminated with -1. +const int8 RANCE41_tracks[] = {2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,1,-1}; +const int8 RANCE42_tracks[] = {2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,1,-1}; +const int8 DPSALL_tracks[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,5,1,2,3,-1}; + +enum MakoThreadMessage { + MAKO_OPEN = WM_APP, + MAKO_PLAY, + MAKO_STOP, + MAKO_EXIT +}; + +enum MakoOpenFlags { + OPEN_CD = 0, + OPEN_MIDI = 1, +}; + +const char* mci_geterror(DWORD err) +{ + static char buf[128]; + mciGetErrorString(err, buf, sizeof(buf)); + return buf; +} + +class MCIThread { +public: + MCIThread(NACT* nact, HWND hwnd_notify) : hwnd_notify(hwnd_notify) { + if (!_beginthreadex(NULL, 0, &MCIThread::run, this, 0, &thread_id)) + nact->fatal("Cannot create thread: %s", strerror(errno)); + } + + bool post_message(UINT msg, WPARAM wparam, LPARAM lparam) { + return PostThreadMessage(thread_id, msg, wparam, lparam); + } + + MCIDEVICEID device_id() { return devid; } + +private: + static unsigned __stdcall run(void* param) + { + MCIThread* t = reinterpret_cast(param); + t->message_loop(); + delete t; + return 0; + } + + void message_loop() + { + MSG msg; + while (GetMessage(&msg, NULL, 0, 0)) { + switch (msg.message) { + case MAKO_OPEN: + close(); + open(reinterpret_cast(msg.wParam), + static_cast(msg.lParam)); + break; + + case MAKO_PLAY: + play(); + break; + + case MAKO_STOP: + close(); + break; + + case MAKO_EXIT: + close(); + return; + } + } + } + + void open(std::string* file, MakoOpenFlags open_flags) + { + file_playing = file; + is_midi = open_flags & OPEN_MIDI; + + MCI_OPEN_PARMS open; + open.lpstrElementName = file_playing->c_str(); + DWORD flags = MCI_OPEN_ELEMENT | MCI_WAIT; + if (is_midi) { + flags |= MCI_OPEN_TYPE | MCI_OPEN_TYPE_ID; + open.lpstrDeviceType = (LPCSTR)MCI_DEVTYPE_SEQUENCER; + } + MCIERROR err = mciSendCommand(0, MCI_OPEN, flags, (DWORD_PTR)&open); + if (err) { + WARNING("MCI_OPEN failed: %s: %s", + file_playing->c_str(), mci_geterror(err)); + return; + } + devid = open.wDeviceID; + } + + void play() + { + MCI_PLAY_PARMS play; + play.dwCallback = (DWORD_PTR)hwnd_notify; + play.dwFrom = 0; + DWORD flags = MCI_FROM | MCI_NOTIFY; + MCIERROR err = mciSendCommand(devid, MCI_PLAY, flags, (DWORD_PTR)&play); + if (err) + WARNING("MCI_PLAY failed: %s", mci_geterror(err)); + } + + void close() { + if (devid) { + mciSendCommand(devid, MCI_CLOSE, 0, 0); + devid = 0; + } + if (file_playing) { + if (is_midi) + DeleteFile(file_playing->c_str()); // remove temporary file + delete file_playing; + file_playing = nullptr; + } + } + + HWND hwnd_notify; + unsigned thread_id; + std::string* file_playing = nullptr; + bool is_midi; + MCIDEVICEID devid = 0; +}; + +MCIThread* mci_thread; + +class Music { +public: + Music(const char* fname, int loop) : loops(loop) { + std::string* fname_str = new std::string(fname); + mci_thread->post_message(MAKO_OPEN, (WPARAM)fname_str, OPEN_CD); + mci_thread->post_message(MAKO_PLAY, 0, 0); + playing = true; + } + + Music(std::unique_ptr midi, int loop) : loops(loop ? 1 : 0) { + std::vector smf = midi->generate_smf(loop); + char path[MAX_PATH + 1]; + if (!GetTempPath(sizeof(path), path)) { + WARNING("GetTempPath failed: 0x%x", GetLastError()); + return; + } + char fname[MAX_PATH + 1]; + if (!GetTempFileName(path, "mid", 0, fname)) { + WARNING("GetTempFileName failed: 0x%x", GetLastError()); + return; + } + FILE* fp = fopen(fname, "wb"); + if (!fp) { + WARNING("Cannot open %s: %s", fname, strerror(errno)); + return; + } + if (fwrite(smf.data(), smf.size(), 1, fp) != 1) { + WARNING("Cannot write to %s: %s", fname, strerror(errno)); + fclose(fp); + DeleteFile(fname); + return; + } + fclose(fp); + + std::string* fname_str = new std::string(fname); + mci_thread->post_message(MAKO_OPEN, (WPARAM)fname_str, OPEN_MIDI); + mci_thread->post_message(MAKO_PLAY, 0, 0); + playing = true; + } + + ~Music() { + close(); + } + + void close() { + mci_thread->post_message(MAKO_STOP, 0, 0); + playing = false; + } + + bool is_playing() { + return playing; + } + + bool on_mci_notify(const SDL_SysWMmsg* msg) { + if (msg->msg.win.lParam != mci_thread->device_id()) + return true; + switch (msg->msg.win.wParam) { + case MCI_NOTIFY_FAILURE: + close(); + return false; + case MCI_NOTIFY_SUCCESSFUL: + if (loops && --loops == 0) { + close(); + return false; + } + mci_thread->post_message(MAKO_PLAY, 0, 0); + return true; + } + return true; + } + +private: + int loops; // number of times to play, 0 for infinite loop + bool playing; +}; + +Music* music; +uint8* wav_buffer; +SDL_mutex* fm_mutex; +std::unique_ptr fm; + +void audio_callback(void*, Uint8* stream, int len) { + SDL_LockMutex(fm_mutex); + fm->Process(reinterpret_cast(stream), len/ 4); + SDL_UnlockMutex(fm_mutex); +} + +} // namespace + +MAKO::MAKO(NACT* parent, const Config& config) : + use_fm(config.use_fm), + current_music(0), + next_loop(0), + nact(parent) +{ + if (!config.playlist.empty()) + load_playlist(config.playlist.c_str()); + + strcpy_s(amus, 16, "AMUS.DAT"); + strcpy_s(amse, 16, "AMSE.DAT"); // 実際には使わない + + for(int i = 1; i <= 99; i++) { + cd_track[i] = 0; + } + + SDL_InitSubSystem(SDL_INIT_AUDIO); + SDL_AudioSpec fmt; + SDL_zero(fmt); + fmt.freq = SAMPLE_RATE; + fmt.format = AUDIO_S16; + fmt.channels = 2; + fmt.samples = 4096; + fmt.callback = &audio_callback; + if (SDL_OpenAudio(&fmt, NULL) < 0) { + WARNING("SDL_OpenAudio: %s", SDL_GetError()); + use_fm = false; + } + fm_mutex = SDL_CreateMutex(); + + SDL_SysWMinfo info; + SDL_VERSION(&info.version); + if (!SDL_GetWindowWMInfo(g_window, &info)) + parent->fatal("SDL_GetWindowWMInfo failed: %s", SDL_GetError()); + mci_thread = new MCIThread(parent, info.info.win.window); +} + +MAKO::~MAKO() +{ + stop_music(); + stop_pcm(); + mci_thread->post_message(MAKO_EXIT, 0, 0); + mci_thread = nullptr; // MCIThread self-destructs on the worker thread. + + SDL_LockMutex(fm_mutex); + SDL_CloseAudio(); + SDL_UnlockMutex(fm_mutex); + SDL_DestroyMutex(fm_mutex); + fm_mutex = nullptr; + SDL_QuitSubSystem(SDL_INIT_AUDIO); +} + +bool MAKO::load_playlist(const char* path) +{ + FILE* fp = fopen(path, "rt"); + if (!fp) { + WARNING("Cannot open %s", path); + return false; + } + char buf[256]; + while (fgets(buf, sizeof(buf) - 1, fp)) { + char *p = &buf[strlen(buf) - 1]; + if (*p == '\n') + *p = '\0'; + playlist.push_back(buf[0] ? strdup(buf) : NULL); + } + fclose(fp); + return true; +} + +void MAKO::play_music(int page) +{ + if (current_music == page) + return; + + stop_music(); + + size_t track = page < 100 ? cd_track[page] : 0; + if (track) { + if (track >= playlist.size() || !playlist[track]) + return; + music = new Music(playlist[track], next_loop); + } else if (use_fm) { + DRI dri; + int size; + uint8* data = dri.load(amus, page, &size); + if (!data) + return; + + SDL_LockMutex(fm_mutex); + fm = std::make_unique(SAMPLE_RATE, data, true); + SDL_UnlockMutex(fm_mutex); + SDL_PauseAudio(0); + } else { + auto midi = std::make_unique(nact, amus); + if (!midi->load_mml(page)) + return; + midi->load_mda(page); + music = new Music(std::move(midi), next_loop); + } + current_music = page; +} + +void MAKO::stop_music() +{ + if (music) { + delete music; + music = nullptr; + } + SDL_PauseAudio(1); + current_music = 0; +} + +bool MAKO::check_music() +{ + return music && music->is_playing(); +} + +void MAKO::select_sound(BGMDevice dev) +{ + // 強制的に音源を変更する + int page = current_music; + int old_dev = (1 <= page && page <= 99 && cd_track[page]) ? BGM_CD : + use_fm ? BGM_FM : BGM_MIDI; + + switch (dev) { + case BGM_FM: + case BGM_MIDI: + for (int i = 1; i <= 99; i++) + cd_track[i] = 0; + use_fm = dev == BGM_FM; + break; + + case BGM_CD: + const int8* tracks; + + switch (nact->crc32_a) { + case CRC32_RANCE41: + case CRC32_RANCE41_ENG: + tracks = RANCE41_tracks; + break; + case CRC32_RANCE42: + case CRC32_RANCE42_ENG: + tracks = RANCE42_tracks; + break; + case CRC32_DPSALL: + tracks = DPSALL_tracks; + break; + + // For the following games, the default mapping (cd_track[i] = i) works. + case CRC32_AYUMI_CD: + case CRC32_FUNNYBEE_CD: + case CRC32_ONLYYOU: + default: + tracks = nullptr; + } + + if (tracks) { + for (int i = 0; tracks[i] >= 0; i++) + cd_track[i + 1] = tracks[i]; + } else { + for (int i = 1; i <= 99; i++) + cd_track[i] = i; + } + break; + } + + // デバイスが変更された場合は再演奏する + if (dev != old_dev && page) { + stop_music(); + play_music(page); + } +} + +void MAKO::get_mark(int* mark, int* loop) +{ + SDL_LockMutex(fm_mutex); + if (fm) { + fm->get_mark(mark, loop); + } else { + *mark = 0; + *loop = 0; + } + SDL_UnlockMutex(fm_mutex); +} + +void MAKO::play_pcm(int page, bool loop) +{ + static char header[44] = { + 'R' , 'I' , 'F' , 'F' , 0x00, 0x00, 0x00, 0x00, 'W' , 'A' , 'V' , 'E' , 'f' , 'm' , 't' , ' ' , + 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x40, 0x1f, 0x00, 0x00, 0x40, 0x1f, 0x00, 0x00, + 0x01, 0x00, 0x08, 0x00, 'd' , 'a' , 't' , 'a' , 0x00, 0x00, 0x00, 0x00 + }; + + stop_pcm(); + + uint8* buffer = NULL; + int size; + DRI* dri = new DRI(); + + if ((buffer = dri->load("AWAV.DAT", page, &size)) != NULL) { + // WAV形式 (Only You) + wav_buffer = buffer; + } else if ((buffer = dri->load("AMSE.DAT", page, &size)) != NULL) { + // AMSE形式 (乙女戦記) + int total = (size - 12) * 2 + 0x24; + int samples = (size - 12) * 2; + + wav_buffer = (uint8*)malloc(total + 8); + memcpy(wav_buffer, header, 44); + wav_buffer[ 4] = (total >> 0) & 0xff; + wav_buffer[ 5] = (total >> 8) & 0xff; + wav_buffer[ 6] = (total >> 16) & 0xff; + wav_buffer[ 7] = (total >> 24) & 0xff; + wav_buffer[40] = (samples >> 0) & 0xff; + wav_buffer[41] = (samples >> 8) & 0xff; + wav_buffer[42] = (samples >> 16) & 0xff; + wav_buffer[43] = (samples >> 24) & 0xff; + for(int i = 12, p = 44; i < size; i++) { + wav_buffer[p++] = buffer[i] & 0xf0; + wav_buffer[p++] = (buffer[i] & 0x0f) << 4; + } + free(buffer); + } + PlaySound((LPCTSTR)wav_buffer, NULL, SND_ASYNC | SND_MEMORY | (loop ? SND_LOOP : 0)); +} + +void MAKO::stop_pcm() +{ + PlaySound(NULL, NULL, SND_PURGE); + if (wav_buffer) { + free(wav_buffer); + wav_buffer = nullptr; + } +} + +bool MAKO::check_pcm() +{ + // 再生中でtrue + static const char null_wav[45] = { + 'R' , 'I' , 'F' , 'F' , 0x25, 0x00, 0x00, 0x00, 'W' , 'A' , 'V' , 'E' , 'f' , 'm' , 't' , ' ' , + 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x40, 0x1f, 0x00, 0x00, 0x40, 0x1f, 0x00, 0x00, + 0x01, 0x00, 0x08, 0x00, 'd' , 'a' , 't' , 'a' , 0x01, 0x00, 0x00, 0x00, 0x00 + }; + return !PlaySound(null_wav, NULL, SND_ASYNC | SND_MEMORY | SND_NOSTOP); +} + +void MAKO::on_mci_notify(const SDL_SysWMmsg* msg) +{ + if (!music) + return; + if (!music->on_mci_notify(msg)) + current_music = 0; +} diff --git a/src/win/resource.h b/src/win/resource.h index 46d83aa..21ba45e 100644 --- a/src/win/resource.h +++ b/src/win/resource.h @@ -1,33 +1,33 @@ -#ifndef _RESOURCE_H_ -#define _RESOURCE_H_ - -#define IDR_MENU1 101 -#define IDI_ICON1 102 -#define IDD_DIALOG1 103 -#define IDC_TEXT 104 -#define IDC_EDITBOX 105 -#define IDR_AL3 106 -#define IDR_ALL 107 -#define IDR_AMB 108 -#define IDR_AYM 109 -#define IDR_BEE 110 -#define IDR_MGN 111 -#define IDR_OTM 112 -#define IDR_OY 113 -#define IDR_PSG 114 -#define IDR_R41 115 -#define IDR_R42 116 -#define IDR_RG2 117 -#define IDR_T2 118 -#define ID_SCREENSHOT 40000 -#define ID_RESTART 40001 -#define ID_EXIT 40002 -#define ID_SCREEN_WINDOW 40003 -#define ID_SCREEN_FULL 40004 -#define ID_SOUND_FM 40005 -#define ID_SOUND_MIDI 40006 -#define ID_SOUND_CD 40007 -#define ID_TEXT_SKIP 40008 -#define ID_TEXT_WAIT 40009 - -#endif // _RESOURCE_H_ +#ifndef _RESOURCE_H_ +#define _RESOURCE_H_ + +#define IDR_MENU1 101 +#define IDI_ICON1 102 +#define IDD_DIALOG1 103 +#define IDC_TEXT 104 +#define IDC_EDITBOX 105 +#define IDR_AL3 106 +#define IDR_ALL 107 +#define IDR_AMB 108 +#define IDR_AYM 109 +#define IDR_BEE 110 +#define IDR_MGN 111 +#define IDR_OTM 112 +#define IDR_OY 113 +#define IDR_PSG 114 +#define IDR_R41 115 +#define IDR_R42 116 +#define IDR_RG2 117 +#define IDR_T2 118 +#define ID_SCREENSHOT 40000 +#define ID_RESTART 40001 +#define ID_EXIT 40002 +#define ID_SCREEN_WINDOW 40003 +#define ID_SCREEN_FULL 40004 +#define ID_SOUND_FM 40005 +#define ID_SOUND_MIDI 40006 +#define ID_SOUND_CD 40007 +#define ID_TEXT_SKIP 40008 +#define ID_TEXT_WAIT 40009 + +#endif // _RESOURCE_H_ diff --git a/src/win/resource.rc b/src/win/resource.rc index b90ac42..1a09213 100644 --- a/src/win/resource.rc +++ b/src/win/resource.rc @@ -1,235 +1,235 @@ -#pragma code_page(65001) - -#include "resource.h" -#include "winres.h" - -///////////////////////////////////////////////////////////////////////////// -// -// Icon -// - -// Icon with lowest ID value placed first to ensure application icon -// remains consistent on all systems. -IDI_ICON1 ICON DISCARDABLE "icon1.ico" - -///////////////////////////////////////////////////////////////////////////// -// -// FONTS -// - -// Note for game translators: -// Rather than replacing this, use a separate font file and the "fontfile" -// option in system3.ini. That will allow your translated version run on -// other platforms, such as Android and Web. -MTLc3m.ttf FONTS DISCARDABLE "../../resources/fonts/MTLc3m.ttf" - -///////////////////////////////////////////////////////////////////////////// -// -// MDA -// - -AMUS_AB.MDA MDA DISCARDABLE "../../resources/mda/AMUS_AB.MDA" -AMUS_AL1.MDA MDA DISCARDABLE "../../resources/mda/AMUS_AL1.MDA" -AMUS_AL2.MDA MDA DISCARDABLE "../../resources/mda/AMUS_AL2.MDA" -AMUS_AL3.MDA MDA DISCARDABLE "../../resources/mda/AMUS_AL3.MDA" -AMUS_ALL.MDA MDA DISCARDABLE "../../resources/mda/AMUS_ALL.MDA" -AMUS_AMB.MDA MDA DISCARDABLE "../../resources/mda/AMUS_AMB.MDA" -AMUS_AT.MDA MDA DISCARDABLE "../../resources/mda/AMUS_AT.MDA" -AMUS_AYM.MDA MDA DISCARDABLE "../../resources/mda/AMUS_AYM.MDA" -AMUS_BEE.MDA MDA DISCARDABLE "../../resources/mda/AMUS_BEE.MDA" -AMUS_CRS.MDA MDA DISCARDABLE "../../resources/mda/AMUS_CRS.MDA" -AMUS_DLK.MDA MDA DISCARDABLE "../../resources/mda/AMUS_DLK.MDA" -AMUS_DPS.MDA MDA DISCARDABLE "../../resources/mda/AMUS_DPS.MDA" -AMUS_DRS.MDA MDA DISCARDABLE "../../resources/mda/AMUS_DRS.MDA" -AMUS_INT.MDA MDA DISCARDABLE "../../resources/mda/AMUS_INT.MDA" -AMUS_KNG.MDA MDA DISCARDABLE "../../resources/mda/AMUS_KNG.MDA" -AMUS_LP2.MDA MDA DISCARDABLE "../../resources/mda/AMUS_LP2.MDA" -AMUS_MGN.MDA MDA DISCARDABLE "../../resources/mda/AMUS_MGN.MDA" -AMUS_OTM.MDA MDA DISCARDABLE "../../resources/mda/AMUS_OTM.MDA" -AMUS_OY.MDA MDA DISCARDABLE "../../resources/mda/AMUS_OY.MDA" -AMUS_PSG.MDA MDA DISCARDABLE "../../resources/mda/AMUS_PSG.MDA" -AMUS_R3H.MDA MDA DISCARDABLE "../../resources/mda/AMUS_R3H.MDA" -AMUS_R4.MDA MDA DISCARDABLE "../../resources/mda/AMUS_R4.MDA" -AMUS_R41.MDA MDA DISCARDABLE "../../resources/mda/AMUS_R41.MDA" -AMUS_R42.MDA MDA DISCARDABLE "../../resources/mda/AMUS_R42.MDA" -AMUS_RG2.MDA MDA DISCARDABLE "../../resources/mda/AMUS_RG2.MDA" -AMUS_SDP.MDA MDA DISCARDABLE "../../resources/mda/AMUS_SDP.MDA" -AMUS_SG.MDA MDA DISCARDABLE "../../resources/mda/AMUS_SG.MDA" -AMUS_T1.MDA MDA DISCARDABLE "../../resources/mda/AMUS_T1.MDA" -AMUS_T2.MDA MDA DISCARDABLE "../../resources/mda/AMUS_T2.MDA" -AMUS_VX.MDA MDA DISCARDABLE "../../resources/mda/AMUS_VX.MDA" -BMUS_AKA.MDA MDA DISCARDABLE "../../resources/mda/BMUS_AKA.MDA" -BMUS_ANT.MDA MDA DISCARDABLE "../../resources/mda/BMUS_ANT.MDA" -BMUS_FAH.MDA MDA DISCARDABLE "../../resources/mda/BMUS_FAH.MDA" -BMUS_KAM.MDA MDA DISCARDABLE "../../resources/mda/BMUS_KAM.MDA" -BMUS_KAT.MDA MDA DISCARDABLE "../../resources/mda/BMUS_KAT.MDA" -BMUS_MTK.MDA MDA DISCARDABLE "../../resources/mda/BMUS_MTK.MDA" -BMUS_NAI.MDA MDA DISCARDABLE "../../resources/mda/BMUS_NAI.MDA" -BMUS_NOB.MDA MDA DISCARDABLE "../../resources/mda/BMUS_NOB.MDA" -BMUS_RAB.MDA MDA DISCARDABLE "../../resources/mda/BMUS_RAB.MDA" -BMUS_SIN.MDA MDA DISCARDABLE "../../resources/mda/BMUS_SIN.MDA" -BMUS_SOT.MDA MDA DISCARDABLE "../../resources/mda/BMUS_SOT.MDA" -BMUS_TNM.MDA MDA DISCARDABLE "../../resources/mda/BMUS_TNM.MDA" -CMUS_T1.MDA MDA DISCARDABLE "../../resources/mda/CMUS_T1.MDA" - - -///////////////////////////////////////////////////////////////////////////// -// English resources - -LANGUAGE LANG_ENGLISH, SUBLANG_NEUTRAL - -///////////////////////////////////////////////////////////////////////////// -// -// Menu -// - -IDR_MENU1 MENU DISCARDABLE -BEGIN - POPUP "File" - BEGIN - MENUITEM "Save Screenshot", ID_SCREENSHOT - MENUITEM SEPARATOR - MENUITEM "Restart", ID_RESTART - MENUITEM SEPARATOR - MENUITEM "Exit", ID_EXIT - END - POPUP "Screen" - BEGIN - MENUITEM "Window", ID_SCREEN_WINDOW - MENUITEM "Fullscreen", ID_SCREEN_FULL - END - POPUP "Sound" - BEGIN - MENUITEM "FM Sound", ID_SOUND_FM - MENUITEM "MIDI Sound", ID_SOUND_MIDI - MENUITEM "CD Audio", ID_SOUND_CD - END - POPUP "Message" - BEGIN - MENUITEM "Skip", ID_TEXT_SKIP - MENUITEM "Wait", ID_TEXT_WAIT - END -END - -///////////////////////////////////////////////////////////////////////////// -// -// Dialog -// - -IDD_DIALOG1 DIALOG DISCARDABLE 0, 0, 122, 55 -STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU -CAPTION "Text input" -FONT 9, "MS Shell Dlg" -BEGIN - EDITTEXT IDC_EDITBOX,7,15,112,12 - LTEXT "Enter a string (up to 8 letters)",IDC_TEXT,7,3,112,8 - DEFPUSHBUTTON "OK",IDOK,35,36,50,14 -END - - -///////////////////////////////////////////////////////////////////////////// -// 日本語 resources - -LANGUAGE LANG_JAPANESE, SUBLANG_DEFAULT - -///////////////////////////////////////////////////////////////////////////// -// -// Menu -// - -IDR_MENU1 MENU DISCARDABLE -BEGIN - POPUP "ファイル" - BEGIN - MENUITEM "画面保存", ID_SCREENSHOT - MENUITEM SEPARATOR - MENUITEM "再起動", ID_RESTART - MENUITEM SEPARATOR - MENUITEM "閉じる", ID_EXIT - END - POPUP "画面" - BEGIN - MENUITEM "ウィンドウ", ID_SCREEN_WINDOW - MENUITEM "フルスクリーン", ID_SCREEN_FULL - END - POPUP "サウンド" - BEGIN - MENUITEM "FM音源", ID_SOUND_FM - MENUITEM "MIDI音源", ID_SOUND_MIDI - MENUITEM "CD音源", ID_SOUND_CD - END - POPUP "メッセージ" - BEGIN - MENUITEM "スキップ", ID_TEXT_SKIP - MENUITEM "ウェイトあり", ID_TEXT_WAIT - END -END - -///////////////////////////////////////////////////////////////////////////// -// -// Dialog -// - -IDD_DIALOG1 DIALOG DISCARDABLE 0, 0, 122, 55 -STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU -CAPTION "文字列の入力" -FONT 9, "MS Pゴシック" -BEGIN - EDITTEXT IDC_EDITBOX,7,15,112,12 - LTEXT "文字を入力してください(最大8文字)",IDC_TEXT,7,3,112,8 - DEFPUSHBUTTON "OK",IDOK,35,36,50,14 -END - - -///////////////////////////////////////////////////////////////////////////// -// 简体中文 resources - -LANGUAGE LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED - -///////////////////////////////////////////////////////////////////////////// -// -// Menu -// - -IDR_MENU1 MENU DISCARDABLE -BEGIN - POPUP "文件" - BEGIN - MENUITEM "截图", ID_SCREENSHOT - MENUITEM SEPARATOR - MENUITEM "重启", ID_RESTART - MENUITEM SEPARATOR - MENUITEM "退出", ID_EXIT - END - POPUP "窗口" - BEGIN - MENUITEM "窗口化", ID_SCREEN_WINDOW - MENUITEM "全屏化", ID_SCREEN_FULL - END - POPUP "音源" - BEGIN - MENUITEM "FM 音源", ID_SOUND_FM - MENUITEM "MIDI 音源", ID_SOUND_MIDI - MENUITEM "CD 音源", ID_SOUND_CD - END - POPUP "消息" - BEGIN - MENUITEM "跳过", ID_TEXT_SKIP - MENUITEM "等待", ID_TEXT_WAIT - END -END - -///////////////////////////////////////////////////////////////////////////// -// -// Dialog -// - -IDD_DIALOG1 DIALOG DISCARDABLE 0, 0, 122, 55 -STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU -CAPTION "字符串输入" -FONT 9, "微软雅黑" -BEGIN - EDITTEXT IDC_EDITBOX,7,15,112,12 - LTEXT "请输入字符串(最多8个字符)",IDC_TEXT,7,3,112,8 - DEFPUSHBUTTON "OK",IDOK,35,36,50,14 -END +#pragma code_page(65001) + +#include "resource.h" +#include "winres.h" + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. +IDI_ICON1 ICON DISCARDABLE "icon1.ico" + +///////////////////////////////////////////////////////////////////////////// +// +// FONTS +// + +// Note for game translators: +// Rather than replacing this, use a separate font file and the "fontfile" +// option in system3.ini. That will allow your translated version run on +// other platforms, such as Android and Web. +MTLc3m.ttf FONTS DISCARDABLE "../../resources/fonts/MTLc3m.ttf" + +///////////////////////////////////////////////////////////////////////////// +// +// MDA +// + +AMUS_AB.MDA MDA DISCARDABLE "../../resources/mda/AMUS_AB.MDA" +AMUS_AL1.MDA MDA DISCARDABLE "../../resources/mda/AMUS_AL1.MDA" +AMUS_AL2.MDA MDA DISCARDABLE "../../resources/mda/AMUS_AL2.MDA" +AMUS_AL3.MDA MDA DISCARDABLE "../../resources/mda/AMUS_AL3.MDA" +AMUS_ALL.MDA MDA DISCARDABLE "../../resources/mda/AMUS_ALL.MDA" +AMUS_AMB.MDA MDA DISCARDABLE "../../resources/mda/AMUS_AMB.MDA" +AMUS_AT.MDA MDA DISCARDABLE "../../resources/mda/AMUS_AT.MDA" +AMUS_AYM.MDA MDA DISCARDABLE "../../resources/mda/AMUS_AYM.MDA" +AMUS_BEE.MDA MDA DISCARDABLE "../../resources/mda/AMUS_BEE.MDA" +AMUS_CRS.MDA MDA DISCARDABLE "../../resources/mda/AMUS_CRS.MDA" +AMUS_DLK.MDA MDA DISCARDABLE "../../resources/mda/AMUS_DLK.MDA" +AMUS_DPS.MDA MDA DISCARDABLE "../../resources/mda/AMUS_DPS.MDA" +AMUS_DRS.MDA MDA DISCARDABLE "../../resources/mda/AMUS_DRS.MDA" +AMUS_INT.MDA MDA DISCARDABLE "../../resources/mda/AMUS_INT.MDA" +AMUS_KNG.MDA MDA DISCARDABLE "../../resources/mda/AMUS_KNG.MDA" +AMUS_LP2.MDA MDA DISCARDABLE "../../resources/mda/AMUS_LP2.MDA" +AMUS_MGN.MDA MDA DISCARDABLE "../../resources/mda/AMUS_MGN.MDA" +AMUS_OTM.MDA MDA DISCARDABLE "../../resources/mda/AMUS_OTM.MDA" +AMUS_OY.MDA MDA DISCARDABLE "../../resources/mda/AMUS_OY.MDA" +AMUS_PSG.MDA MDA DISCARDABLE "../../resources/mda/AMUS_PSG.MDA" +AMUS_R3H.MDA MDA DISCARDABLE "../../resources/mda/AMUS_R3H.MDA" +AMUS_R4.MDA MDA DISCARDABLE "../../resources/mda/AMUS_R4.MDA" +AMUS_R41.MDA MDA DISCARDABLE "../../resources/mda/AMUS_R41.MDA" +AMUS_R42.MDA MDA DISCARDABLE "../../resources/mda/AMUS_R42.MDA" +AMUS_RG2.MDA MDA DISCARDABLE "../../resources/mda/AMUS_RG2.MDA" +AMUS_SDP.MDA MDA DISCARDABLE "../../resources/mda/AMUS_SDP.MDA" +AMUS_SG.MDA MDA DISCARDABLE "../../resources/mda/AMUS_SG.MDA" +AMUS_T1.MDA MDA DISCARDABLE "../../resources/mda/AMUS_T1.MDA" +AMUS_T2.MDA MDA DISCARDABLE "../../resources/mda/AMUS_T2.MDA" +AMUS_VX.MDA MDA DISCARDABLE "../../resources/mda/AMUS_VX.MDA" +BMUS_AKA.MDA MDA DISCARDABLE "../../resources/mda/BMUS_AKA.MDA" +BMUS_ANT.MDA MDA DISCARDABLE "../../resources/mda/BMUS_ANT.MDA" +BMUS_FAH.MDA MDA DISCARDABLE "../../resources/mda/BMUS_FAH.MDA" +BMUS_KAM.MDA MDA DISCARDABLE "../../resources/mda/BMUS_KAM.MDA" +BMUS_KAT.MDA MDA DISCARDABLE "../../resources/mda/BMUS_KAT.MDA" +BMUS_MTK.MDA MDA DISCARDABLE "../../resources/mda/BMUS_MTK.MDA" +BMUS_NAI.MDA MDA DISCARDABLE "../../resources/mda/BMUS_NAI.MDA" +BMUS_NOB.MDA MDA DISCARDABLE "../../resources/mda/BMUS_NOB.MDA" +BMUS_RAB.MDA MDA DISCARDABLE "../../resources/mda/BMUS_RAB.MDA" +BMUS_SIN.MDA MDA DISCARDABLE "../../resources/mda/BMUS_SIN.MDA" +BMUS_SOT.MDA MDA DISCARDABLE "../../resources/mda/BMUS_SOT.MDA" +BMUS_TNM.MDA MDA DISCARDABLE "../../resources/mda/BMUS_TNM.MDA" +CMUS_T1.MDA MDA DISCARDABLE "../../resources/mda/CMUS_T1.MDA" + + +///////////////////////////////////////////////////////////////////////////// +// English resources + +LANGUAGE LANG_ENGLISH, SUBLANG_NEUTRAL + +///////////////////////////////////////////////////////////////////////////// +// +// Menu +// + +IDR_MENU1 MENU DISCARDABLE +BEGIN + POPUP "File" + BEGIN + MENUITEM "Save Screenshot", ID_SCREENSHOT + MENUITEM SEPARATOR + MENUITEM "Restart", ID_RESTART + MENUITEM SEPARATOR + MENUITEM "Exit", ID_EXIT + END + POPUP "Screen" + BEGIN + MENUITEM "Window", ID_SCREEN_WINDOW + MENUITEM "Fullscreen", ID_SCREEN_FULL + END + POPUP "Sound" + BEGIN + MENUITEM "FM Sound", ID_SOUND_FM + MENUITEM "MIDI Sound", ID_SOUND_MIDI + MENUITEM "CD Audio", ID_SOUND_CD + END + POPUP "Message" + BEGIN + MENUITEM "Skip", ID_TEXT_SKIP + MENUITEM "Wait", ID_TEXT_WAIT + END +END + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +IDD_DIALOG1 DIALOG DISCARDABLE 0, 0, 122, 55 +STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Text input" +FONT 9, "MS Shell Dlg" +BEGIN + EDITTEXT IDC_EDITBOX,7,15,112,12 + LTEXT "Enter a string (up to 8 letters)",IDC_TEXT,7,3,112,8 + DEFPUSHBUTTON "OK",IDOK,35,36,50,14 +END + + +///////////////////////////////////////////////////////////////////////////// +// 日本語 resources + +LANGUAGE LANG_JAPANESE, SUBLANG_DEFAULT + +///////////////////////////////////////////////////////////////////////////// +// +// Menu +// + +IDR_MENU1 MENU DISCARDABLE +BEGIN + POPUP "ファイル" + BEGIN + MENUITEM "画面保存", ID_SCREENSHOT + MENUITEM SEPARATOR + MENUITEM "再起動", ID_RESTART + MENUITEM SEPARATOR + MENUITEM "閉じる", ID_EXIT + END + POPUP "画面" + BEGIN + MENUITEM "ウィンドウ", ID_SCREEN_WINDOW + MENUITEM "フルスクリーン", ID_SCREEN_FULL + END + POPUP "サウンド" + BEGIN + MENUITEM "FM音源", ID_SOUND_FM + MENUITEM "MIDI音源", ID_SOUND_MIDI + MENUITEM "CD音源", ID_SOUND_CD + END + POPUP "メッセージ" + BEGIN + MENUITEM "スキップ", ID_TEXT_SKIP + MENUITEM "ウェイトあり", ID_TEXT_WAIT + END +END + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +IDD_DIALOG1 DIALOG DISCARDABLE 0, 0, 122, 55 +STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "文字列の入力" +FONT 9, "MS Pゴシック" +BEGIN + EDITTEXT IDC_EDITBOX,7,15,112,12 + LTEXT "文字を入力してください(最大8文字)",IDC_TEXT,7,3,112,8 + DEFPUSHBUTTON "OK",IDOK,35,36,50,14 +END + + +///////////////////////////////////////////////////////////////////////////// +// 简体中文 resources + +LANGUAGE LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED + +///////////////////////////////////////////////////////////////////////////// +// +// Menu +// + +IDR_MENU1 MENU DISCARDABLE +BEGIN + POPUP "文件" + BEGIN + MENUITEM "截图", ID_SCREENSHOT + MENUITEM SEPARATOR + MENUITEM "重启", ID_RESTART + MENUITEM SEPARATOR + MENUITEM "退出", ID_EXIT + END + POPUP "窗口" + BEGIN + MENUITEM "窗口化", ID_SCREEN_WINDOW + MENUITEM "全屏化", ID_SCREEN_FULL + END + POPUP "音源" + BEGIN + MENUITEM "FM 音源", ID_SOUND_FM + MENUITEM "MIDI 音源", ID_SOUND_MIDI + MENUITEM "CD 音源", ID_SOUND_CD + END + POPUP "消息" + BEGIN + MENUITEM "跳过", ID_TEXT_SKIP + MENUITEM "等待", ID_TEXT_WAIT + END +END + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +IDD_DIALOG1 DIALOG DISCARDABLE 0, 0, 122, 55 +STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "字符串输入" +FONT 9, "微软雅黑" +BEGIN + EDITTEXT IDC_EDITBOX,7,15,112,12 + LTEXT "请输入字符串(最多8个字符)",IDC_TEXT,7,3,112,8 + DEFPUSHBUTTON "OK",IDOK,35,36,50,14 +END