commit 65221695d84c160ba5b199f582a8fd4454a1ef71 Author: kichikuou Date: Sun Mar 27 15:01:10 2016 +0900 Import system3 for win32 2016-01-16, downloaded from http://homepage3.nifty.com/takeda-toshiya/alice/index.html diff --git a/COPYING.txt b/COPYING.txt new file mode 100644 index 0000000..60549be --- /dev/null +++ b/COPYING.txt @@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) 19yy + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) 19yy name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/build8.bat b/build8.bat new file mode 100644 index 0000000..4ba473e --- /dev/null +++ b/build8.bat @@ -0,0 +1,21 @@ +echo off +if exist "%ProgramFiles(x86)%" goto is_x64 +set path="%ProgramFiles%\Microsoft Visual Studio 9.0\Common7\IDE";%PATH% +goto start +:is_x64 +set path="%ProgramFiles(x86)%\Microsoft Visual Studio 9.0\Common7\IDE";%PATH% +:start + +devenv.com crescent.vcproj /Rebuild Release +devenv.com dps.vcproj /Rebuild Release +devenv.com fukei.vcproj /Rebuild Release +devenv.com intruder.vcproj /Rebuild Release +devenv.com maria.vcproj /Rebuild Release +devenv.com prog_omake.vcproj /Rebuild Release +devenv.com sdps.vcproj /Rebuild Release +devenv.com system3.vcproj /Rebuild Release +devenv.com tengu.vcproj /Rebuild Release +devenv.com vampire.vcproj /Rebuild Release + +pause +echo on diff --git a/crescent.vcproj b/crescent.vcproj new file mode 100644 index 0000000..87e8ff7 --- /dev/null +++ b/crescent.vcproj @@ -0,0 +1,656 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/dps.vcproj b/dps.vcproj new file mode 100644 index 0000000..c3415b7 --- /dev/null +++ b/dps.vcproj @@ -0,0 +1,656 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/fukei.vcproj b/fukei.vcproj new file mode 100644 index 0000000..be5145b --- /dev/null +++ b/fukei.vcproj @@ -0,0 +1,656 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/history.txt b/history.txt new file mode 100644 index 0000000..0cc83e4 --- /dev/null +++ b/history.txt @@ -0,0 +1,122 @@ +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の乱数生成をxorhift32にしました。 + 512命令毎にSleep(10)を入れるようにしました。 + +2016.01.15 + + あゆみちゃん物語 フルカラー実写版をサポートしました。 + キーまたはボタンが離されるまで、メニューを表示しないようにしました。 diff --git a/intruder.vcproj b/intruder.vcproj new file mode 100644 index 0000000..357c44c --- /dev/null +++ b/intruder.vcproj @@ -0,0 +1,656 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/maria.vcproj b/maria.vcproj new file mode 100644 index 0000000..4768fc3 --- /dev/null +++ b/maria.vcproj @@ -0,0 +1,636 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/prog_omake.vcproj b/prog_omake.vcproj new file mode 100644 index 0000000..006d92d --- /dev/null +++ b/prog_omake.vcproj @@ -0,0 +1,669 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/readme.txt b/readme.txt new file mode 100644 index 0000000..8ca3ece --- /dev/null +++ b/readme.txt @@ -0,0 +1,26 @@ +GPL扱いで、適当に。 +このアーカイブについては一切サポート外です。 + +コンパイル環境は以下の通りです。 + + Visual C++ 2008 SP1 + +プロジェクトファイルは以下の通りです。 + + crescent.vcproj クレセントムーンがぁる + dsp.vcproj D.P.S. - Dream Program System + fukei.vcproj 婦警さん物語VX + intruder.vcproj Intruder -桜屋敷の探索- + maria.vcproj Super D.P.S. マリアとカンパン + prog_omake.vcproj prostudent G おまけ + sdps.vcproj Super D.P.S. + system3.vcproj SYSTEM3汎用 + tengu.vcproj あぶないてんぐ伝説 + vampire.vcproj Little Vampire + +実装上では、近間さんのxsystem35を参考にしています。 +旧作の実装については、Ryu1さんが移植されたDOS版や、 +unitbase内部でsystem35に移植されたものを参考にしています。 + +alsmidiは、Nastyさん、teruさんの作品です。 +REITHUSさんの作成されたMDAデータを内蔵しています。 diff --git a/sdps.vcproj b/sdps.vcproj new file mode 100644 index 0000000..3001c72 --- /dev/null +++ b/sdps.vcproj @@ -0,0 +1,636 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/common.h b/src/common.h new file mode 100644 index 0000000..dc52a6a --- /dev/null +++ b/src/common.h @@ -0,0 +1,52 @@ +/* + ALICE SOFT SYSTEM 3 for Win32 + + [ Common Header ] +*/ + +#ifndef _COMMON_H_ +#define _COMMON_H_ + +#include +#include + +#pragma comment(lib, "Gdiplus.lib") +using namespace Gdiplus; + +#ifdef _DEBUG + // detect memory leaks + #define _CRTDBG_MAP_ALLOC + #include + #define malloc(s) _malloc_dbg(s, _NORMAL_BLOCK, __FILE__, __LINE__) + #define new new(_NORMAL_BLOCK, __FILE__, __LINE__) +#endif + +#include + +#if defined(_MSC_VER) && _MSC_VER == 1200 + // variable scope of 'for' loop for Microsoft Visual C++ 6.0 + #define for if(0);else for +#endif + +// type definition +#ifndef uint8 +typedef unsigned char uint8; +#endif +#ifndef uint16 +typedef unsigned short uint16; +#endif +#ifndef uint32 +typedef unsigned long uint32; +#endif + +#ifndef int8 +typedef signed char int8; +#endif +#ifndef int16 +typedef signed short int16; +#endif +#ifndef int32 +typedef signed long int32; +#endif + +#endif diff --git a/src/fileio.cpp b/src/fileio.cpp new file mode 100644 index 0000000..cb61930 --- /dev/null +++ b/src/fileio.cpp @@ -0,0 +1,122 @@ +/* + ALICE SOFT SYSTEM 3 for Win32 + + [ File I/O ] +*/ + +#include "fileio.h" + +FILEIO::FILEIO() +{ + // 初期化 + fp = NULL; +} + +FILEIO::~FILEIO(void) +{ + // 後始末 + if(fp != NULL) { + Fclose(); + } +} + +bool FILEIO::Fopen(_TCHAR *filename, int mode) +{ + if(fp != NULL) { + Fclose(); + } + fp = NULL; + + if(mode == FILEIO_READ_BINARY) { + _tfopen_s(&fp, filename, _T("rb")); + } else if(mode == FILEIO_WRITE_BINARY) { + _tfopen_s(&fp, filename, _T("wb")); + } else if(mode == FILEIO_READ_WRITE_BINARY) { + _tfopen_s(&fp, filename, _T("r+b")); + } else if(mode == FILEIO_READ_ASCII) { + _tfopen_s(&fp, filename, __T("r")); + } else if(mode == FILEIO_WRITE_ASCII) { + _tfopen_s(&fp, filename, _T("w")); + } else if(mode == FILEIO_READ_WRITE_ASCII) { + _tfopen_s(&fp, filename, _T("r+w")); + } + return (fp != NULL); +} + +void FILEIO::Fclose() +{ + if(fp) { + fclose(fp); + } + fp = NULL; +} + +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); +} + +uint32 FILEIO::Fread(void* buffer, uint32 size, uint32 count) +{ + return fread(buffer, size, count, fp); +} + +uint32 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 p = 0; + + for(;;) { + int c = Fgetc(); + if(c == 0x0d || c == EOF) { + break; + } + if(c != 0x0a) { + dest[p++] = c; + if((0x81 <= c && c <= 0x9f) || 0xe0 <= c) { + dest[p++] = Fgetc(); + } + } + } + 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 new file mode 100644 index 0000000..37d994a --- /dev/null +++ b/src/fileio.h @@ -0,0 +1,45 @@ +/* + ALICE SOFT SYSTEM 3 for Win32 + + [ File I/O ] +*/ + +#ifndef _FILEIO_H_ +#define _FILEIO_H_ + +#include +#include "common.h" + +#define FILEIO_READ_BINARY 1 +#define FILEIO_WRITE_BINARY 2 +#define FILEIO_READ_WRITE_BINARY 3 +#define FILEIO_READ_ASCII 4 +#define FILEIO_WRITE_ASCII 5 +#define FILEIO_READ_WRITE_ASCII 6 + +#define FILEIO_SEEK_SET 0 +#define FILEIO_SEEK_CUR 1 +#define FILEIO_SEEK_END 2 + +class FILEIO +{ +private: + FILE* fp; +public: + FILEIO(); + ~FILEIO(); + + bool Fopen(_TCHAR *filename, int mode); + void Fclose(); + uint32 Fseek(long offset, int origin); + uint32 Ftell(); + uint32 Fread(void* buffer, uint32 size, uint32 count); + uint32 Fwrite(void* buffer, uint32 size, uint32 count); + int Fgetc(); + int Fgetw(); + void Fgets(char dest[]); + void Fputc(int c); + void Fputw(int w); +}; + +#endif diff --git a/src/res1/Script1.rc b/src/res1/Script1.rc new file mode 100644 index 0000000..ee8edde --- /dev/null +++ b/src/res1/Script1.rc @@ -0,0 +1,136 @@ +//Microsoft Developer Studio generated resource script. +// +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "afxres.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// 日本語 resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_JPN) +#ifdef _WIN32 +LANGUAGE LANG_JAPANESE, SUBLANG_DEFAULT +#pragma code_page(932) +#endif //_WIN32 + +///////////////////////////////////////////////////////////////////////////// +// +// Menu +// + +IDR_MENU1 MENU DISCARDABLE +BEGIN + POPUP "File" + BEGIN + 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 "CD Audio", ID_SOUND_CD + END + POPUP "Message" + BEGIN + MENUITEM "Skip", ID_TEXT_SKIP + MENUITEM "Wait", ID_TEXT_WAIT + END +END + + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE DISCARDABLE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE DISCARDABLE +BEGIN + "#include ""afxres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE DISCARDABLE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. +IDI_ICON1 ICON DISCARDABLE "icon1.ico" + +///////////////////////////////////////////////////////////////////////////// +// +// 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 + + +///////////////////////////////////////////////////////////////////////////// +// +// DESIGNINFO +// + +#ifdef APSTUDIO_INVOKED +GUIDELINES DESIGNINFO DISCARDABLE +BEGIN + IDD_DIALOG1, DIALOG + BEGIN + LEFTMARGIN, 7 + TOPMARGIN, 7 + END +END +#endif // APSTUDIO_INVOKED + +#endif // 日本語 resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/src/res1/icon1.ico b/src/res1/icon1.ico new file mode 100644 index 0000000..47c22f2 Binary files /dev/null and b/src/res1/icon1.ico differ diff --git a/src/res1/resource.h b/src/res1/resource.h new file mode 100644 index 0000000..a3c33a3 --- /dev/null +++ b/src/res1/resource.h @@ -0,0 +1,28 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Developer Studio generated include file. +// Used by Script1.rc +// +#define IDR_MENU1 101 +#define IDI_ICON1 102 +#define IDD_DIALOG1 103 +#define IDC_TEXT 104 +#define IDC_EDITBOX 105 +#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_CD 40006 +#define ID_TEXT_SKIP 40007 +#define ID_TEXT_WAIT 40008 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 118 +#define _APS_NEXT_COMMAND_VALUE 40009 +#define _APS_NEXT_CONTROL_VALUE 1000 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/src/res2/Script1.rc b/src/res2/Script1.rc new file mode 100644 index 0000000..ee8edde --- /dev/null +++ b/src/res2/Script1.rc @@ -0,0 +1,136 @@ +//Microsoft Developer Studio generated resource script. +// +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "afxres.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// 日本語 resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_JPN) +#ifdef _WIN32 +LANGUAGE LANG_JAPANESE, SUBLANG_DEFAULT +#pragma code_page(932) +#endif //_WIN32 + +///////////////////////////////////////////////////////////////////////////// +// +// Menu +// + +IDR_MENU1 MENU DISCARDABLE +BEGIN + POPUP "File" + BEGIN + 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 "CD Audio", ID_SOUND_CD + END + POPUP "Message" + BEGIN + MENUITEM "Skip", ID_TEXT_SKIP + MENUITEM "Wait", ID_TEXT_WAIT + END +END + + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE DISCARDABLE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE DISCARDABLE +BEGIN + "#include ""afxres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE DISCARDABLE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. +IDI_ICON1 ICON DISCARDABLE "icon1.ico" + +///////////////////////////////////////////////////////////////////////////// +// +// 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 + + +///////////////////////////////////////////////////////////////////////////// +// +// DESIGNINFO +// + +#ifdef APSTUDIO_INVOKED +GUIDELINES DESIGNINFO DISCARDABLE +BEGIN + IDD_DIALOG1, DIALOG + BEGIN + LEFTMARGIN, 7 + TOPMARGIN, 7 + END +END +#endif // APSTUDIO_INVOKED + +#endif // 日本語 resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/src/res2/icon1.ico b/src/res2/icon1.ico new file mode 100644 index 0000000..47c22f2 Binary files /dev/null and b/src/res2/icon1.ico differ diff --git a/src/res2/resource.h b/src/res2/resource.h new file mode 100644 index 0000000..a3c33a3 --- /dev/null +++ b/src/res2/resource.h @@ -0,0 +1,28 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Developer Studio generated include file. +// Used by Script1.rc +// +#define IDR_MENU1 101 +#define IDI_ICON1 102 +#define IDD_DIALOG1 103 +#define IDC_TEXT 104 +#define IDC_EDITBOX 105 +#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_CD 40006 +#define ID_TEXT_SKIP 40007 +#define ID_TEXT_WAIT 40008 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 118 +#define _APS_NEXT_COMMAND_VALUE 40009 +#define _APS_NEXT_CONTROL_VALUE 1000 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/src/res3/AMUS_AL3.MDA b/src/res3/AMUS_AL3.MDA new file mode 100644 index 0000000..c0ed11d Binary files /dev/null and b/src/res3/AMUS_AL3.MDA differ diff --git a/src/res3/AMUS_ALL.MDA b/src/res3/AMUS_ALL.MDA new file mode 100644 index 0000000..3b4d41f Binary files /dev/null and b/src/res3/AMUS_ALL.MDA differ diff --git a/src/res3/AMUS_AMB.MDA b/src/res3/AMUS_AMB.MDA new file mode 100644 index 0000000..006e8f4 Binary files /dev/null and b/src/res3/AMUS_AMB.MDA differ diff --git a/src/res3/AMUS_AYM.MDA b/src/res3/AMUS_AYM.MDA new file mode 100644 index 0000000..eb0ab3c Binary files /dev/null and b/src/res3/AMUS_AYM.MDA differ diff --git a/src/res3/AMUS_BEE.MDA b/src/res3/AMUS_BEE.MDA new file mode 100644 index 0000000..e43deae Binary files /dev/null and b/src/res3/AMUS_BEE.MDA differ diff --git a/src/res3/AMUS_MGN.MDA b/src/res3/AMUS_MGN.MDA new file mode 100644 index 0000000..af2cb4b Binary files /dev/null and b/src/res3/AMUS_MGN.MDA differ diff --git a/src/res3/AMUS_OTM.MDA b/src/res3/AMUS_OTM.MDA new file mode 100644 index 0000000..df1ec92 Binary files /dev/null and b/src/res3/AMUS_OTM.MDA differ diff --git a/src/res3/AMUS_OY.MDA b/src/res3/AMUS_OY.MDA new file mode 100644 index 0000000..259e9a8 Binary files /dev/null and b/src/res3/AMUS_OY.MDA differ diff --git a/src/res3/AMUS_PSG.MDA b/src/res3/AMUS_PSG.MDA new file mode 100644 index 0000000..aaece60 Binary files /dev/null and b/src/res3/AMUS_PSG.MDA differ diff --git a/src/res3/AMUS_R41.MDA b/src/res3/AMUS_R41.MDA new file mode 100644 index 0000000..152def9 Binary files /dev/null and b/src/res3/AMUS_R41.MDA differ diff --git a/src/res3/AMUS_R42.MDA b/src/res3/AMUS_R42.MDA new file mode 100644 index 0000000..f109115 Binary files /dev/null and b/src/res3/AMUS_R42.MDA differ diff --git a/src/res3/AMUS_RG2.MDA b/src/res3/AMUS_RG2.MDA new file mode 100644 index 0000000..1eb6b2f Binary files /dev/null and b/src/res3/AMUS_RG2.MDA differ diff --git a/src/res3/Script1.rc b/src/res3/Script1.rc new file mode 100644 index 0000000..bb3d9d0 --- /dev/null +++ b/src/res3/Script1.rc @@ -0,0 +1,154 @@ +//Microsoft Developer Studio generated resource script. +// +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "afxres.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// 日本語 resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_JPN) +#ifdef _WIN32 +LANGUAGE LANG_JAPANESE, SUBLANG_DEFAULT +#pragma code_page(932) +#endif //_WIN32 + +///////////////////////////////////////////////////////////////////////////// +// +// Menu +// + +IDR_MENU1 MENU DISCARDABLE +BEGIN + POPUP "File" + BEGIN + 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 "CD Audio", ID_SOUND_CD + END + POPUP "Message" + BEGIN + MENUITEM "Skip", ID_TEXT_SKIP + MENUITEM "Wait", ID_TEXT_WAIT + END +END + + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE DISCARDABLE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE DISCARDABLE +BEGIN + "#include ""afxres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE DISCARDABLE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. +IDI_ICON1 ICON DISCARDABLE "icon1.ico" + +///////////////////////////////////////////////////////////////////////////// +// +// MDA +// + +IDR_AL3 MDA DISCARDABLE "AMUS_AL3.MDA" +IDR_ALL MDA DISCARDABLE "AMUS_ALL.MDA" +IDR_AMB MDA DISCARDABLE "AMUS_AMB.MDA" +IDR_AYM MDA DISCARDABLE "AMUS_AYM.MDA" +IDR_BEE MDA DISCARDABLE "AMUS_BEE.MDA" +IDR_MGN MDA DISCARDABLE "AMUS_MGN.MDA" +IDR_OTM MDA DISCARDABLE "AMUS_OTM.MDA" +IDR_OY MDA DISCARDABLE "AMUS_OY.MDA" +IDR_PSG MDA DISCARDABLE "AMUS_PSG.MDA" +IDR_R41 MDA DISCARDABLE "AMUS_R41.MDA" +IDR_R42 MDA DISCARDABLE "AMUS_R42.MDA" +IDR_RG2 MDA DISCARDABLE "AMUS_RG2.MDA" + +///////////////////////////////////////////////////////////////////////////// +// +// 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 + + +///////////////////////////////////////////////////////////////////////////// +// +// DESIGNINFO +// + +#ifdef APSTUDIO_INVOKED +GUIDELINES DESIGNINFO DISCARDABLE +BEGIN + IDD_DIALOG1, DIALOG + BEGIN + LEFTMARGIN, 7 + TOPMARGIN, 7 + END +END +#endif // APSTUDIO_INVOKED + +#endif // 日本語 resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/src/res3/icon1.ico b/src/res3/icon1.ico new file mode 100644 index 0000000..47c22f2 Binary files /dev/null and b/src/res3/icon1.ico differ diff --git a/src/res3/resource.h b/src/res3/resource.h new file mode 100644 index 0000000..f5666c2 --- /dev/null +++ b/src/res3/resource.h @@ -0,0 +1,40 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Developer Studio generated include file. +// Used by Script1.rc +// +#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 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_CD 40006 +#define ID_TEXT_SKIP 40007 +#define ID_TEXT_WAIT 40008 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 118 +#define _APS_NEXT_COMMAND_VALUE 40009 +#define _APS_NEXT_CONTROL_VALUE 1000 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/src/rest2/AMUS_AL3.MDA b/src/rest2/AMUS_AL3.MDA new file mode 100644 index 0000000..c0ed11d Binary files /dev/null and b/src/rest2/AMUS_AL3.MDA differ diff --git a/src/rest2/AMUS_T2.MDA b/src/rest2/AMUS_T2.MDA new file mode 100644 index 0000000..51a36a4 Binary files /dev/null and b/src/rest2/AMUS_T2.MDA differ diff --git a/src/rest2/Script1.rc b/src/rest2/Script1.rc new file mode 100644 index 0000000..57d769a --- /dev/null +++ b/src/rest2/Script1.rc @@ -0,0 +1,144 @@ +//Microsoft Developer Studio generated resource script. +// +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "afxres.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// 日本語 resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_JPN) +#ifdef _WIN32 +LANGUAGE LANG_JAPANESE, SUBLANG_DEFAULT +#pragma code_page(932) +#endif //_WIN32 + +///////////////////////////////////////////////////////////////////////////// +// +// Menu +// + +IDR_MENU1 MENU DISCARDABLE +BEGIN + POPUP "File" + BEGIN + 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 "CD Audio", ID_SOUND_CD + END + POPUP "Message" + BEGIN + MENUITEM "Skip", ID_TEXT_SKIP + MENUITEM "Wait", ID_TEXT_WAIT + END +END + + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE DISCARDABLE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE DISCARDABLE +BEGIN + "#include ""afxres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE DISCARDABLE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. +IDI_ICON1 ICON DISCARDABLE "icon1.ico" + +///////////////////////////////////////////////////////////////////////////// +// +// MDA +// + +IDR_AL3 MDA DISCARDABLE "AMUS_AL3.MDA" +IDR_T2 MDA DISCARDABLE "AMUS_T2.MDA" + +///////////////////////////////////////////////////////////////////////////// +// +// 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 + + +///////////////////////////////////////////////////////////////////////////// +// +// DESIGNINFO +// + +#ifdef APSTUDIO_INVOKED +GUIDELINES DESIGNINFO DISCARDABLE +BEGIN + IDD_DIALOG1, DIALOG + BEGIN + LEFTMARGIN, 7 + TOPMARGIN, 7 + END +END +#endif // APSTUDIO_INVOKED + +#endif // 日本語 resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/src/rest2/icon1.ico b/src/rest2/icon1.ico new file mode 100644 index 0000000..47c22f2 Binary files /dev/null and b/src/rest2/icon1.ico differ diff --git a/src/rest2/resource.h b/src/rest2/resource.h new file mode 100644 index 0000000..f652de0 --- /dev/null +++ b/src/rest2/resource.h @@ -0,0 +1,30 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Developer Studio generated include file. +// Used by Script1.rc +// +#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_T2 107 +#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_CD 40006 +#define ID_TEXT_SKIP 40007 +#define ID_TEXT_WAIT 40008 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 118 +#define _APS_NEXT_COMMAND_VALUE 40009 +#define _APS_NEXT_CONTROL_VALUE 1000 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/src/sys/ags.cpp b/src/sys/ags.cpp new file mode 100644 index 0000000..1f25821 --- /dev/null +++ b/src/sys/ags.cpp @@ -0,0 +1,578 @@ +/* + ALICE SOFT SYSTEM 3 for Win32 + + [ AGS ] +*/ + +#include "ags.h" +#include "crc32.h" +#include "../fileio.h" + +extern _TCHAR g_root[_MAX_PATH]; +extern HWND g_hwnd; + +#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) : nact(parent) +{ + // GDI+初期化 + GdiplusStartup(&gdiToken, &gdiSI, NULL); + + HDC hdc = GetDC(g_hwnd); + + // DIBSection 8bpp * 3 (表, 裏, メニュー) + for(int i = 0; i < 3; i++) { + lpBufScreen[i] = (LPBYTE)GlobalAlloc(GPTR, sizeof(BITMAPINFO)); + lpDibScreen[i] = (LPBITMAPINFO)lpBufScreen[i]; + lpDibScreen[i]->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); + lpDibScreen[i]->bmiHeader.biWidth = 640; + lpDibScreen[i]->bmiHeader.biHeight = 480; + lpDibScreen[i]->bmiHeader.biPlanes = 1; + lpDibScreen[i]->bmiHeader.biBitCount = 32; + lpDibScreen[i]->bmiHeader.biCompression = BI_RGB; + lpDibScreen[i]->bmiHeader.biSizeImage = 0; + lpDibScreen[i]->bmiHeader.biXPelsPerMeter = 0; + lpDibScreen[i]->bmiHeader.biYPelsPerMeter = 0; + lpDibScreen[i]->bmiHeader.biClrUsed = 0; + lpDibScreen[i]->bmiHeader.biClrImportant = 0; + hBmpScreen[i] = CreateDIBSection(hdc, lpDibScreen[i], DIB_RGB_COLORS, (PVOID*)&lpBmpScreen[i], NULL, 0); + hdcDibScreen[i] = CreateCompatibleDC(hdc); + SelectObject(hdcDibScreen[i], hBmpScreen[i]); + memset(lpBmpScreen[i], 0, 640 * 480 * sizeof(DWORD)); + + // 仮想VRAMへのポインタ取得 + for(int j = 0; j < 480; j++) { + vram[i][j] = &lpBmpScreen[i][640 * (479 - j)]; + } + } + + // DIBSection 24bpp * 1 (最終出力先) + lpBufDest = (LPBYTE)GlobalAlloc(GPTR, sizeof(BITMAPINFO)); + lpDibDest = (LPBITMAPINFO)lpBufDest; + lpDibDest->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); + lpDibDest->bmiHeader.biWidth = 640; + lpDibDest->bmiHeader.biHeight = 480; + lpDibDest->bmiHeader.biPlanes = 1; + lpDibDest->bmiHeader.biBitCount = 32; + lpDibDest->bmiHeader.biCompression = BI_RGB; + lpDibDest->bmiHeader.biSizeImage = 0; + lpDibDest->bmiHeader.biXPelsPerMeter = 0; + lpDibDest->bmiHeader.biYPelsPerMeter = 0; + lpDibDest->bmiHeader.biClrUsed = 0; + lpDibDest->bmiHeader.biClrImportant = 0; + hBmpDest = CreateDIBSection(hdc, lpDibDest, DIB_RGB_COLORS, (PVOID*)&lpBmpDest, NULL, 0); + hdcDibDest = CreateCompatibleDC(hdc); + SelectObject(hdcDibDest, hBmpDest); + memset(lpBmpDest, 0, 640 * 480 * sizeof(DWORD)); + + // DIBSection 24bpp * 1 (テキスト描画) + lpBufText = (LPBYTE)GlobalAlloc(GPTR, sizeof(BITMAPINFO)); + lpDibText = (LPBITMAPINFO)lpBufText; + lpDibText->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); + lpDibText->bmiHeader.biWidth = 64; + lpDibText->bmiHeader.biHeight = 64; + lpDibText->bmiHeader.biPlanes = 1; + lpDibText->bmiHeader.biBitCount = 32; + lpDibText->bmiHeader.biCompression = BI_RGB; + lpDibText->bmiHeader.biSizeImage = 0; + lpDibText->bmiHeader.biXPelsPerMeter = 0; + lpDibText->bmiHeader.biYPelsPerMeter = 0; + lpDibText->bmiHeader.biClrUsed = 0; + lpDibText->bmiHeader.biClrImportant = 0; + hBmpText = CreateDIBSection(hdc, lpDibText, DIB_RGB_COLORS, (PVOID*)&lpBmpText, NULL, 0); + hdcDibText = CreateCompatibleDC(hdc); + SelectObject(hdcDibText, hBmpText); +// memset(lpBmpText, 0, 64 * 64 * sizeof(DWORD)); + + // DIBSection 24bpp * 1 (メニュー描画) + lpBufMenu = (LPBYTE)GlobalAlloc(GPTR, sizeof(BITMAPINFO)); + lpDibMenu = (LPBITMAPINFO)lpBufMenu; + lpDibMenu->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); + lpDibMenu->bmiHeader.biWidth = 64; + lpDibMenu->bmiHeader.biHeight = 64; + lpDibMenu->bmiHeader.biPlanes = 1; + lpDibMenu->bmiHeader.biBitCount = 32; + lpDibMenu->bmiHeader.biCompression = BI_RGB; + lpDibMenu->bmiHeader.biSizeImage = 0; + lpDibMenu->bmiHeader.biXPelsPerMeter = 0; + lpDibMenu->bmiHeader.biYPelsPerMeter = 0; + lpDibMenu->bmiHeader.biClrUsed = 0; + lpDibMenu->bmiHeader.biClrImportant = 0; + hBmpMenu = CreateDIBSection(hdc, lpDibMenu, DIB_RGB_COLORS, (PVOID*)&lpBmpMenu, NULL, 0); + hdcDibMenu = CreateCompatibleDC(hdc); + SelectObject(hdcDibMenu, hBmpMenu); +// memset(lpBmpMenu, 0, 64 * 64 * sizeof(DWORD)); + + ReleaseDC(g_hwnd, hdc); + + // フォント + LOGFONT logfont; + logfont.lfEscapement = 0; + logfont.lfOrientation = 0; + logfont.lfWeight = FW_NORMAL; + logfont.lfItalic = FALSE; + logfont.lfUnderline = FALSE; + logfont.lfStrikeOut = FALSE; + logfont.lfCharSet = SHIFTJIS_CHARSET; + logfont.lfOutPrecision = OUT_TT_PRECIS; + logfont.lfClipPrecision = CLIP_DEFAULT_PRECIS; + logfont.lfQuality = NONANTIALIASED_QUALITY; //DEFAULT_QUALITY; + logfont.lfPitchAndFamily = FIXED_PITCH | FF_DONTCARE; + _tcscpy_s(logfont.lfFaceName, LF_FACESIZE, _T("MS ゴシック")); + + logfont.lfHeight = 16; + logfont.lfWidth = 8; + hFont16 = CreateFontIndirect(&logfont); + logfont.lfHeight = 24; + logfont.lfWidth = 12; + hFont24 = CreateFontIndirect(&logfont); + logfont.lfHeight = 32; + logfont.lfWidth = 16; + hFont32 = CreateFontIndirect(&logfont); + logfont.lfHeight = 48; + logfont.lfWidth = 24; + hFont48 = CreateFontIndirect(&logfont); + logfont.lfHeight = 64; + logfont.lfWidth = 32; + hFont64 = CreateFontIndirect(&logfont); + + // カーソル初期化 + for(int i = 0; i < 10; i++) { + hCursor[i] = NULL; + } + hArrow = LoadCursor(NULL, IDC_ARROW); + + // GAIJI.DAT読み込み + memset(gaiji, 0, sizeof(gaiji)); + + FILEIO* fio = new FILEIO(); + _TCHAR file_path[_MAX_PATH]; + _stprintf_s(file_path, _MAX_PATH, _T("%sGAIJI.DAT"), g_root); + + if(fio->Fopen(file_path, 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 + _tcscpy_s(acg, 16, _T("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 defined(_SYSTEM1) + 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); +#endif + 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); + program_palette[0xff] = SETPALETTE16(0xf, 0xf, 0xf); + memcpy(screen_palette, program_palette, sizeof(program_palette)); + + // Bコマンド + for(int i = 0; i < 10; i++) { + // ウィンドウの初期位置はシステムによって異なる +#if defined(_BUNKASAI) + SET_TEXT(i, 24, 304, 616, 384, false); + SET_MENU(i, 440, 18, 620, 178, true); +#elif defined(_CRESCENT) + SET_TEXT(i, 24, 288, 616, 378, false); + // 本来は横メニュー + SET_MENU(i, 464, 50, 623, 240, true); +#elif defined(_DPS) + SET_TEXT(i, 48, 288, 594, 393, false); + //SET_MENU(i, 48, 288, 584, 393, false); + SET_MENU(i, 48, 288, 594, 393, false); +#elif defined(_FUKEI) + SET_TEXT(i, 44, 282, 593, 396, false); + SET_MENU(i, 460, 14, 635, 214, false); +#elif defined(_INTRUDER) + SET_TEXT(i, 8, 280, 629, 393, false); + SET_MENU(i, 448, 136, 623, 340, true); +#elif defined(_TENGU) + SET_TEXT(i, 44, 282, 593, 396, false); + SET_MENU(i, 452, 14, 627, 214, false); +#elif defined(_VAMPIRE) + SET_TEXT(i, 8, 255, 615, 383, false); + SET_MENU(i, 448, 11, 615, 224, false); +#else + SET_TEXT(i, 8, 311, 623, 391, true); + SET_MENU(i, 464, 80, 623, 240, true); +#endif + 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 defined(_SYSTEM2) + if(nact->crc32 == CRC32_SDPS_TONO || nact->crc32 == CRC32_SDPS_KAIZOKU) { + SET_BOX(0, 0, 40, 8, 598, 271); + } else if(nact->crc32 == 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); + } +#endif + + // 画面選択 + 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; + old_text_font_size = 0; +#if defined(_SYSTEM1) + 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; +#endif + + // メニュー表示 + menu_dest_x = 2; + menu_dest_y = 0; + menu_font_size = 16; + old_menu_font_size = 0; +#if defined(_SYSTEM1) + 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; +#endif + 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; + + // フェード状態 + fader = false; + memset(fader_screen, 0, sizeof(fader_screen)); +} + +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]) { + DestroyCursor(hCursor[i]); + } + } + + // フォント開放 + DeleteObject(hFont16); + DeleteObject(hFont24); + DeleteObject(hFont32); + DeleteObject(hFont48); + DeleteObject(hFont64); + + // DIBSection開放 + for(int i = 0; i < 3; i++) { + DeleteDC(hdcDibScreen[i]); + DeleteObject(hBmpScreen[i]); + GlobalFree(lpBufScreen[i]); + } + + DeleteDC(hdcDibDest); + DeleteObject(hBmpDest); + GlobalFree(lpBufDest); + + DeleteDC(hdcDibText); + DeleteObject(hBmpText); + GlobalFree(lpBufText); + + DeleteDC(hdcDibMenu); + DeleteObject(hBmpMenu); + GlobalFree(lpBufMenu); + + // GDI+開放 + GdiplusShutdown(gdiToken); +} + +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_start() +{ + memcpy(fader_screen, lpBmpDest, sizeof(fader_screen)); +} + +void AGS::fade_end() +{ + memcpy(lpBmpDest, fader_screen, sizeof(fader_screen)); +} + +void AGS::fade_out(int depth, bool white) +{ + // 通常画面 → 白黒画面 + int fx = fade_x[depth]; + int fy = fade_y[depth]; + fader = true; + + for(int y = 0; y < 480; y += 4) { + uint32* dest = &lpBmpDest[640 * (479 - y - fy) + fx]; + for(int x = 0; x < 640; x += 4) { + dest[x] = white ? 0xffffff : 0; + } + } + + // 画面更新 + invalidate_screen(0, 0, 640, screen_height); +} + +void AGS::fade_in(int depth) +{ + // 白黒画面 → 通常画面 + int fx = fade_x[depth]; + int fy = fade_y[depth]; + fader = (depth == 15) ? false : true; + + for(int y = 0; y < 480; y += 4) { + uint32* src = &fader_screen[640 * (479 - y - fy) + fx]; + uint32* dest = &lpBmpDest[640 * (479 - y - fy) + fx]; + for(int x = 0; x < 640; x += 4) { + dest[x] = src[x]; + } + } + + // 画面更新 + invalidate_screen(0, 0, 640, screen_height); +} + +void AGS::flush_screen(bool update) +{ + if(update) { + for(int y = 0; y < screen_height; y++) { + uint32* src = vram[0][y]; + uint32* dest = &lpBmpDest[640 * (479 - y)]; + for(int x = 0; x < 640; x++) { +#if defined(_SYSTEM3) + // あゆみちゃん物語 フルカラー実写版 + if(src[x] & 0x80000000) { + dest[x] = src[x] & 0xffffff; + } else +#endif + 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) +{ + if(fader) { + for(int y = sy; y < (sy + height) && y < 480; y++) { + uint32* src = vram[0][y]; + uint32* dest = &fader_screen[640 * (479 - y)]; + for(int x = sx; x < (sx + width) && x < 640; x++) { + uint32 a=src[x]; +#if defined(_SYSTEM3) + // あゆみちゃん物語 フルカラー実写版 + if(src[x] & 0x80000000) { + dest[x] = src[x] & 0xffffff; + } else +#endif + dest[x] = screen_palette[src[x] & 0xff]; + } + } + } else { + for(int y = sy; y < (sy + height) && y < 480; y++) { + uint32* src = vram[0][y]; + uint32* dest = &lpBmpDest[640 * (479 - y)]; + for(int x = sx; x < (sx + width) && x < 640; x++) { + uint32 a=src[x]; +#if defined(_SYSTEM3) + // あゆみちゃん物語 フルカラー実写版 + if(src[x] & 0x80000000) { + dest[x] = src[x] & 0xffffff; + } else +#endif + 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) +{ + RECT rect; + rect.left = sx; + rect.top = sy; + rect.right = sx + width; + rect.bottom = sy + height; + + InvalidateRect(g_hwnd, &rect, FALSE); + UpdateWindow(g_hwnd); +} + +void AGS::update_screen(HDC hdc, int sx, int sy, int width, int height) +{ + if(screen_height == 400) { + BitBlt(hdc, sx, sy, width, height, hdcDibDest, sx, sy + (scroll - 400), SRCCOPY); + } else { + BitBlt(hdc, sx, sy, width, height, hdcDibDest, sx, sy, SRCCOPY); + } +} + diff --git a/src/sys/ags.h b/src/sys/ags.h new file mode 100644 index 0000000..bea8167 --- /dev/null +++ b/src/sys/ags.h @@ -0,0 +1,244 @@ +/* + ALICE SOFT SYSTEM 3 for Win32 + + [ AGS ] +*/ + +#ifndef _AGS_H_ +#define _AGS_H_ + +#include +#include +#include +#include +#include "../common.h" +#include "nact.h" + +// フェード処理 +static const int fade_x[16] = {0, 2, 2, 0, 1, 3, 3, 1, 1, 3, 3, 1, 0, 2, 2, 0}; +static const int fade_y[16] = {0, 2, 0, 2, 1, 3, 1, 3, 0, 2, 0, 2, 1, 3, 1, 3}; + +#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); +} + +class AGS +{ +protected: + NACT* nact; +private: + // GDI+ + Gdiplus::GdiplusStartupInput gdiSI; + ULONG_PTR gdiToken; + + // DIBSection 8bpp * 3 (表, 裏, メニュー) + HDC hdcDibScreen[3]; + HBITMAP hBmpScreen[3]; + LPBYTE lpBufScreen[3]; + LPDWORD lpBmpScreen[3]; + LPBITMAPINFO lpDibScreen[3]; + + // DIBSection 24bpp (最終出力先) + HDC hdcDibDest; + HBITMAP hBmpDest; + LPBYTE lpBufDest; + LPDWORD lpBmpDest; + LPBITMAPINFO lpDibDest; + + // DIBSection 24bpp (テキスト描画) + HDC hdcDibText; + HBITMAP hBmpText; + LPBYTE lpBufText; + LPDWORD lpBmpText; + LPBITMAPINFO lpDibText; + + // DIBSection 24bpp (メニュー描画) + HDC hdcDibMenu; + HBITMAP hBmpMenu; + LPBYTE lpBufMenu; + LPDWORD lpBmpMenu; + LPBITMAPINFO lpDibMenu; + + // フォント + HFONT hFont16; + HFONT hFont24; + HFONT hFont32; + HFONT hFont48; + HFONT hFont64; + + // カーソル + HCURSOR hArrow; + HCURSOR hCursor[10]; + + // AGS +#if defined(_SYSTEM1) + void load_vsp2l(uint8* data, int page, int transparent); // Little Vampire + void load_gl3(uint8* data, int page, int transparent); // あぶない天狗伝説 + void load_gm3(uint8* data, int page, int transparent); // Intruder + void load_vsp(uint8* data, int page, int transparent); +#else + void load_gl3(uint8* data, int page, int transparent); // あぶない天狗伝説 + void load_vsp(uint8* data, int page, int transparent); + void load_pms(uint8* data, int page, int transparent); +#endif +#if defined(_SYSTEM3) + void load_bmp(const _TCHAR *file_path); +#endif + + void draw_char(int dest, int dest_x, int dest_y, uint16 code, int size, uint8 color); + void draw_gaiji(int dest, int dest_x, int dest_y, uint16 code, int size, uint8 color); + uint16 convert_zenkaku(uint16 code); + uint16 convert_hankaku(uint16 code); + + 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); + + uint32* vram[3][480]; // 仮想VRAMへのポインタ + + uint32 program_palette[256]; + uint32 screen_palette[256]; + uint8 gaiji[188][32]; + + bool fader; // フェードの状態 + uint32 fader_screen[640 * 480]; + +public: + AGS(NACT* parent); + ~AGS(); + + void update_screen(HDC hdc, int sx, int sy, int width, int height); + 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_start(); + void fade_end(); + void fade_out(int depth, bool white); + void fade_in(int depth); + bool now_fade() { return fader; } + + 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(char string[]); + + 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(); + + // ACG.DAT + _TCHAR 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; + int old_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; + int old_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; +}; + +#endif diff --git a/src/sys/ags_bmp.cpp b/src/sys/ags_bmp.cpp new file mode 100644 index 0000000..748da72 --- /dev/null +++ b/src/sys/ags_bmp.cpp @@ -0,0 +1,42 @@ +/* + ALICE SOFT SYSTEM 3 for Win32 + + [ AGS - bmp loader ] +*/ + +#include "ags.h" + +void AGS::load_bmp(const _TCHAR *file_path) +{ + // ヘッダ取得 + 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) { + // BMP読み込み + WCHAR wszFilePath[_MAX_PATH]; + MultiByteToWideChar(CP_ACP, 0, file_path, -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; + } +} diff --git a/src/sys/ags_cursor.cpp b/src/sys/ags_cursor.cpp new file mode 100644 index 0000000..967ca05 --- /dev/null +++ b/src/sys/ags_cursor.cpp @@ -0,0 +1,93 @@ +/* + ALICE SOFT SYSTEM 3 for Win32 + + [ AGS - draw ] +*/ + +#include "ags.h" + +extern HINSTANCE g_hinst; + +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]) { + DestroyCursor(hCursor[i]); + } + hCursor[i] = CreateCursor(g_hinst, 2, 2, 32, 32, amask, xmask); + } +} + +void AGS::select_cursor() +{ + if(cursor_index == 0) { + SetCursor(hArrow); + } else if(1 <= cursor_index && cursor_index <= 10 && hCursor[cursor_index - 1]) { + SetCursor(hCursor[cursor_index - 1]); + } +} + diff --git a/src/sys/ags_draw.cpp b/src/sys/ags_draw.cpp new file mode 100644 index 0000000..bd4aef6 --- /dev/null +++ b/src/sys/ags_draw.cpp @@ -0,0 +1,182 @@ +/* + ALICE SOFT SYSTEM 3 for Win32 + + [ AGS - draw ] +*/ + +#include "ags.h" +#include "dri.h" +#include "crc32.h" + +extern _TCHAR g_root[_MAX_PATH]; + +void AGS::load_cg(int page, int transparent) +{ +#if defined(_SYSTEM3) + // あゆみちゃん物語 フルカラー実写版 + if(strncmp(acg, "CGA000.BMP", 10) == 0) { + char file_path[_MAX_PATH]; + _stprintf_s(file_path, _MAX_PATH, _T("%sCGA%03d.BMP"), g_root, page); + load_bmp(file_path); + return; + } else if(strncmp(acg, "CGB000.BMP", 10) == 0) { + char file_path[_MAX_PATH]; + _stprintf_s(file_path, _MAX_PATH, _T("%sCGB%03d.BMP"), g_root, page); + load_bmp(file_path); + return; + } +#endif + DRI* dri = new DRI(); + int size; + uint8* data = dri->load(acg, page, &size); + if(data) { +#if defined(_SYSTEM1) +#if defined(_BUNKASAI) + load_vsp(data, page, transparent); +#elif defined(_INTRUDER) +// load_gm3(data, page, transparent); + load_vsp(data, page, transparent); // 暫定 +#elif defined(_VAMPIRE) + load_vsp2l(data, page, transparent); +#else + load_gl3(data, page, transparent); +#endif +#elif defined(_SYSTEM2) + if(nact->crc32 == CRC32_AYUMI_PROTO) { + // あゆみちゃん物語 PROTO + load_gl3(data, page, transparent); + } else if(nact->crc32 == CRC32_SDPS_MARIA || nact->crc32 == CRC32_SDPS_TONO || nact->crc32 == CRC32_SDPS_KAIZOKU) { + // 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); + } + } +#else + if(data[0x8] == 0) { + load_vsp(data, page, transparent); + } else { + load_pms(data, page, transparent); + } +#endif + 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 + BitBlt(hdcDibScreen[dest_screen], dx, dy, ex - sx + 1, ey - sy + 1, hdcDibScreen[src_screen], sx, sy, SRCCOPY); + 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; + + BitBlt(hdcDibScreen[dest], dx, dy, glx * 8, gly, hdcDibScreen[src], sx, sy, SRCCOPY); + if(dest == 0) { + draw_screen(dx, dy, glx * 8, gly); + } +} + +void AGS::paint(int x, int y, uint8 color) +{ + HBRUSH hBrush = CreateSolidBrush(RGB(color, color, color)); + SelectObject(hdcDibScreen[0], hBrush); + ExtFloodFill(hdcDibScreen[0], x, y, GetPixel(hdcDibScreen[0], x, y), FLOODFILLSURFACE); + draw_screen(0, 0, 640, screen_height); +} + +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 new file mode 100644 index 0000000..b3c80eb --- /dev/null +++ b/src/sys/ags_gl3.cpp @@ -0,0 +1,150 @@ +/* + ALICE SOFT SYSTEM 1 for Win32 + + [ AGS - gl3 loader ] +*/ + +#include "ags.h" + +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 new file mode 100644 index 0000000..9edfa7d --- /dev/null +++ b/src/sys/ags_gm3.cpp @@ -0,0 +1,152 @@ +/* + ALICE SOFT SYSTEM 1 for Win32 + + [ AGS - gm3 loader ] +*/ + +#include "ags.h" + +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 new file mode 100644 index 0000000..a8bb1c6 --- /dev/null +++ b/src/sys/ags_pms.cpp @@ -0,0 +1,181 @@ +/* + ALICE SOFT SYSTEM 3 for Win32 + + [ AGS - pms loader ] +*/ + +#include "ags.h" +#include "crc32.h" + +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 defined(_SYSTEM3) + if(nact->crc32 == CRC32_RANCE41 || nact->crc32 == CRC32_RANCE42 || nact->crc32 == 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 == 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 { +#endif + 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 defined(_SYSTEM3) + } +#endif + } + + // パレット展開 +#if defined(_SYSTEM3) + if((extract_palette && extract_palette_cg[page]) || nact->crc32 == CRC32_FUNNYBEE_CD) { + if(nact->crc32 == CRC32_RANCE41 || nact->crc32 == CRC32_RANCE42 || nact->crc32 == 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 == 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]; + } + } + } + } +#endif + + // 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 new file mode 100644 index 0000000..33335cf --- /dev/null +++ b/src/sys/ags_text.cpp @@ -0,0 +1,488 @@ +/* + ALICE SOFT SYSTEM 3 for Win32 + + [ AGS - text ] +*/ + +#include "ags.h" + +void AGS::draw_text(char string[]) +{ + // フォントサイズの変更後、一度だけ更新する + if(draw_menu) { + if(old_menu_font_size != menu_font_size) { + if(menu_font_size == 16) { + SelectObject(hdcDibMenu, hFont16); + } else if(menu_font_size == 24) { + SelectObject(hdcDibMenu, hFont24); + } else if(menu_font_size == 32) { + SelectObject(hdcDibMenu, hFont32); + } else if(menu_font_size == 48) { + SelectObject(hdcDibMenu, hFont48); + } else if(menu_font_size == 64) { + SelectObject(hdcDibMenu, hFont64); + } + SetBkMode(hdcDibMenu, TRANSPARENT); + SetTextColor(hdcDibMenu, RGB(255, 255, 255)); + old_menu_font_size = menu_font_size; + } + } else { + if(old_text_font_size != text_font_size) { + if(text_font_size == 16) { + SelectObject(hdcDibText, hFont16); + } else if(text_font_size == 24) { + SelectObject(hdcDibText, hFont24); + } else if(text_font_size == 32) { + SelectObject(hdcDibText, hFont32); + } else if(text_font_size == 48) { + SelectObject(hdcDibText, hFont48); + } else if(text_font_size == 64) { + SelectObject(hdcDibText, hFont64); + } + SetBkMode(hdcDibText, TRANSPARENT); + SetTextColor(hdcDibText, RGB(255, 255, 255)); + old_text_font_size = text_font_size; + } + } + + int p = 0; + + while(string[p] != '\0') { + // 文字コード取得 + uint16 code = (uint8)string[p++]; + if((0x81 <= code && code <= 0x9f) || 0xe0 <= code) { + code = (code << 8) | (uint8)string[p++]; + } + if(draw_hankaku) { + code = convert_hankaku(code); + } else { + code = convert_zenkaku(code); + } + + if(draw_menu) { + // 文字出力 + if((0xeb9f <= code && code <= 0xebfc) || (0xec40 <= code && code <= 0xec9e)) { + draw_gaiji(2, menu_dest_x, menu_dest_y, code, menu_font_size, menu_font_color); + } else { + draw_char(2, menu_dest_x, menu_dest_y, code, menu_font_size, menu_font_color); + } + // 出力位置の更新 + menu_dest_x += (code & 0xff00) ? menu_font_size : (menu_font_size >> 1); + } else { + // 文字出力 + if((0xeb9f <= code && code <= 0xebfc) || (0xec40 <= code && code <= 0xec9e)) { + draw_gaiji(dest_screen, text_dest_x, text_dest_y, code, text_font_size, text_font_color); + } else { + draw_char(dest_screen, text_dest_x, text_dest_y, code, text_font_size, text_font_color); + } + // 画面更新 + if(dest_screen == 0) { + draw_screen(text_dest_x, text_dest_y, (code & 0xff00) ? text_font_size : (text_font_size >> 1), text_font_size); + } + // 出力位置の更新 + text_dest_x += (code & 0xff00) ? text_font_size : (text_font_size >> 1); + if(text_font_maxsize < text_font_size) { + text_font_maxsize = text_font_size; + } + } + } +} + +void AGS::draw_char(int dest, int dest_x, int dest_y, uint16 code, int size, uint8 color) +{ + char string[3]; + int length; + + // パターン取得 + if(code > 0xff) { + string[0] = code >> 8; + string[1] = code & 0xff; + string[2] = '\0'; + length = 2; + } else { + string[0] = code & 0xff; + string[1] = '\0'; + length = 1; + } + memset(draw_menu ? lpBmpMenu : lpBmpText, 0, 64 * 64 * sizeof(DWORD)); + ExtTextOut(draw_menu ? hdcDibMenu : hdcDibText, 0, 0, NULL, NULL, string, length, NULL); + + // パターン出力 + for(int y = 0; y < size && y < 64 && dest_y + y < 480; y++) { + uint32 *pattern = draw_menu ? &lpBmpMenu[64 * (63 - y)] : &lpBmpText[64 * (63 - y)]; + for(int x = 0; x < size && x < 64 && dest_x + x < 640; x++) { + if(pattern[x] != 0) { + vram[dest][dest_y + y][dest_x + x] = color; + } + } + } +} + +void AGS::draw_gaiji(int dest, int dest_x, int dest_y, uint16 code, int size, uint8 color) +{ + int index = (0xeb9f <= code && code <= 0xebfc) ? code - 0xeb9f : (0xec40 <= code && code <= 0xec9e) ? code - 0xec40 + 94 : 0; + 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; + } + } + } +} + +uint16 AGS::convert_zenkaku(uint16 code) +{ + switch(code) { + case 0x20: return 0x8140; // ' ' + case 0x21: return 0x8149; // '!' + case 0x22: return 0x8168; // '”' + case 0x23: return 0x8194; // '#' + case 0x24: return 0x8190; // '$' + case 0x25: return 0x8193; // '%' + case 0x26: return 0x8195; // '&' + case 0x27: return 0x8166; // '’' + case 0x28: return 0x8169; // '(' + case 0x29: return 0x816a; // ')' + case 0x2a: return 0x8196; // '*' + case 0x2b: return 0x817b; // '+' + case 0x2c: return 0x8143; // ',' + case 0x2d: return 0x817c; // '−' + case 0x2e: return 0x8144; // '.' + case 0x2f: return 0x815e; // '/' + case 0x30: return 0x824f; // '0' + case 0x31: return 0x8250; // '1' + case 0x32: return 0x8251; // '2' + case 0x33: return 0x8252; // '3' + case 0x34: return 0x8253; // '4' + case 0x35: return 0x8254; // '5' + case 0x36: return 0x8255; // '6' + case 0x37: return 0x8256; // '7' + case 0x38: return 0x8257; // '8' + case 0x39: return 0x8258; // '9' + case 0x3a: return 0x8146; // ':' + case 0x3b: return 0x8147; // ';' + case 0x3c: return 0x8183; // '<' + case 0x3d: return 0x8181; // '=' + case 0x3e: return 0x8184; // '>' + case 0x3f: return 0x8148; // '?' + case 0x40: return 0x8197; // '@' + case 0x41: return 0x8260; // 'A' + case 0x42: return 0x8261; // 'B' + case 0x43: return 0x8262; // 'C' + case 0x44: return 0x8263; // 'D' + case 0x45: return 0x8264; // 'E' + case 0x46: return 0x8265; // 'F' + case 0x47: return 0x8266; // 'G' + case 0x48: return 0x8267; // 'H' + case 0x49: return 0x8268; // 'I' + case 0x4a: return 0x8269; // 'J' + case 0x4b: return 0x826a; // 'K' + case 0x4c: return 0x826b; // 'L' + case 0x4d: return 0x826c; // 'M' + case 0x4e: return 0x826d; // 'N' + case 0x4f: return 0x826e; // 'O' + case 0x50: return 0x826f; // 'P' + case 0x51: return 0x8270; // 'Q' + case 0x52: return 0x8271; // 'R' + case 0x53: return 0x8272; // 'S' + case 0x54: return 0x8273; // 'T' + case 0x55: return 0x8274; // 'U' + case 0x56: return 0x8275; // 'V' + case 0x57: return 0x8276; // 'W' + case 0x58: return 0x8277; // 'X' + case 0x59: return 0x8278; // 'Y' + case 0x5a: return 0x8279; // 'Z' + case 0x5b: return 0x816d; // '[' + case 0x5c: return 0x818f; // '¥' + case 0x5d: return 0x816e; // ']' + case 0x5e: return 0x814f; // '^' + case 0x5f: return 0x8151; // '_' + case 0x60: return 0x8165; // '‘' + case 0x61: return 0x8281; // 'a' + case 0x62: return 0x8282; // 'b' + case 0x63: return 0x8283; // 'c' + case 0x64: return 0x8284; // 'd' + case 0x65: return 0x8285; // 'e' + case 0x66: return 0x8286; // 'f' + case 0x67: return 0x8287; // 'g' + case 0x68: return 0x8288; // 'h' + case 0x69: return 0x8289; // 'i' + case 0x6a: return 0x828a; // 'j' + case 0x6b: return 0x828b; // 'k' + case 0x6c: return 0x828c; // 'l' + case 0x6d: return 0x828d; // 'm' + case 0x6e: return 0x828e; // 'n' + case 0x6f: return 0x828f; // 'o' + case 0x70: return 0x8290; // 'p' + case 0x71: return 0x8291; // 'q' + case 0x72: return 0x8292; // 'r' + case 0x73: return 0x8293; // 's' + case 0x74: return 0x8294; // 't' + case 0x75: return 0x8295; // 'u' + case 0x76: return 0x8296; // 'v' + case 0x77: return 0x8297; // 'w' + case 0x78: return 0x8298; // 'x' + case 0x79: return 0x8299; // 'y' + case 0x7a: return 0x829a; // 'z' + case 0x7b: return 0x816f; // '{' + case 0x7c: return 0x8162; // '|' + case 0x7d: return 0x8170; // '}' + case 0x7e: return 0x8160; // '〜' + case 0xa1: return 0x8142; // '。' + case 0xa2: return 0x8175; // '「' + case 0xa3: return 0x8176; // '」' + case 0xa4: return 0x8141; // '、' + case 0xa5: return 0x8145; // '・' + case 0xa6: return 0x82f0; // 'を' + case 0xa7: return 0x829f; // 'ぁ' + case 0xa8: return 0x82a1; // 'ぃ' + case 0xa9: return 0x82a3; // 'ぅ' + case 0xaa: return 0x82a5; // 'ぇ' + case 0xab: return 0x82a7; // 'ぉ' + case 0xac: return 0x82e1; // 'ゃ' + case 0xad: return 0x82e3; // 'ゅ' + case 0xae: return 0x82e5; // 'ょ' + case 0xaf: return 0x82c1; // 'っ' + case 0xb0: return 0x815b; // 'ー' + case 0xb1: return 0x82a0; // 'あ' + case 0xb2: return 0x82a2; // 'い' + case 0xb3: return 0x82a4; // 'う' + case 0xb4: return 0x82a6; // 'え' + case 0xb5: return 0x82a8; // 'お' + case 0xb6: return 0x82a9; // 'か' + case 0xb7: return 0x82ab; // 'き' + case 0xb8: return 0x82ad; // 'く' + case 0xb9: return 0x82af; // 'け' + case 0xba: return 0x82b1; // 'こ' + case 0xbb: return 0x82b3; // 'さ' + case 0xbc: return 0x82b5; // 'し' + case 0xbd: return 0x82b7; // 'す' + case 0xbe: return 0x82b9; // 'せ' + case 0xbf: return 0x82bb; // 'そ' + case 0xc0: return 0x82bd; // 'た' + case 0xc1: return 0x82bf; // 'ち' + case 0xc2: return 0x82c2; // 'つ' + case 0xc3: return 0x82c4; // 'て' + case 0xc4: return 0x82c6; // 'と' + case 0xc5: return 0x82c8; // 'な' + case 0xc6: return 0x82c9; // 'に' + case 0xc7: return 0x82ca; // 'ぬ' + case 0xc8: return 0x82cb; // 'ね' + case 0xc9: return 0x82cc; // 'の' + case 0xca: return 0x82cd; // 'は' + case 0xcb: return 0x82d0; // 'ひ' + case 0xcc: return 0x82d3; // 'ふ' + case 0xcd: return 0x82d6; // 'へ' + case 0xce: return 0x82d9; // 'ほ' + case 0xcf: return 0x82dc; // 'ま' + case 0xd0: return 0x82dd; // 'み' + case 0xd1: return 0x82de; // 'む' + case 0xd2: return 0x82df; // 'め' + case 0xd3: return 0x82e0; // 'も' + case 0xd4: return 0x82e2; // 'や' + case 0xd5: return 0x82e4; // 'ゆ' + case 0xd6: return 0x82e6; // 'よ' + case 0xd7: return 0x82e7; // 'ら' + case 0xd8: return 0x82e8; // 'り' + case 0xd9: return 0x82e9; // 'る' + case 0xda: return 0x82ea; // 'れ' + case 0xdb: return 0x82eb; // 'ろ' + case 0xdc: return 0x82ed; // 'わ' + case 0xdd: return 0x82f1; // 'ん' + case 0xde: return 0x814a; // '゛' + case 0xdf: return 0x814b; // '゜' + } + return code; +} + +uint16 AGS::convert_hankaku(uint16 code) +{ + switch(code) { + case 0x8140: return 0x20; // ' ' + case 0x8149: return 0x21; // '!' + case 0x8168: return 0x22; // '”' + case 0x8194: return 0x23; // '#' + case 0x8190: return 0x24; // '$' + case 0x8193: return 0x25; // '%' + case 0x8195: return 0x26; // '&' + case 0x8166: return 0x27; // '’' + case 0x8169: return 0x28; // '(' + case 0x816a: return 0x29; // ')' + case 0x8196: return 0x2a; // '*' + case 0x817b: return 0x2b; // '+' + case 0x8143: return 0x2c; // ',' + case 0x817c: return 0x2d; // '−' + case 0x8144: return 0x2e; // '.' + case 0x815e: return 0x2f; // '/' + case 0x824f: return 0x30; // '0' + case 0x8250: return 0x31; // '1' + case 0x8251: return 0x32; // '2' + case 0x8252: return 0x33; // '3' + case 0x8253: return 0x34; // '4' + case 0x8254: return 0x35; // '5' + case 0x8255: return 0x36; // '6' + case 0x8256: return 0x37; // '7' + case 0x8257: return 0x38; // '8' + case 0x8258: return 0x39; // '9' + case 0x8146: return 0x3a; // ':' + case 0x8147: return 0x3b; // ';' + case 0x8183: return 0x3c; // '<' + case 0x8181: return 0x3d; // '=' + case 0x8184: return 0x3e; // '>' + case 0x8148: return 0x3f; // '?' + case 0x8197: return 0x40; // '@' + case 0x8260: return 0x41; // 'A' + case 0x8261: return 0x42; // 'B' + case 0x8262: return 0x43; // 'C' + case 0x8263: return 0x44; // 'D' + case 0x8264: return 0x45; // 'E' + case 0x8265: return 0x46; // 'F' + case 0x8266: return 0x47; // 'G' + case 0x8267: return 0x48; // 'H' + case 0x8268: return 0x49; // 'I' + case 0x8269: return 0x4a; // 'J' + case 0x826a: return 0x4b; // 'K' + case 0x826b: return 0x4c; // 'L' + case 0x826c: return 0x4d; // 'M' + case 0x826d: return 0x4e; // 'N' + case 0x826e: return 0x4f; // 'O' + case 0x826f: return 0x50; // 'P' + case 0x8270: return 0x51; // 'Q' + case 0x8271: return 0x52; // 'R' + case 0x8272: return 0x53; // 'S' + case 0x8273: return 0x54; // 'T' + case 0x8274: return 0x55; // 'U' + case 0x8275: return 0x56; // 'V' + case 0x8276: return 0x57; // 'W' + case 0x8277: return 0x58; // 'X' + case 0x8278: return 0x59; // 'Y' + case 0x8279: return 0x5a; // 'Z' + case 0x816d: return 0x5b; // '[' + case 0x818f: return 0x5c; // '¥' + case 0x816e: return 0x5d; // ']' + case 0x814f: return 0x5e; // '^' + case 0x8151: return 0x5f; // '_' + case 0x8165: return 0x60; // '‘' + case 0x8281: return 0x61; // 'a' + case 0x8282: return 0x62; // 'b' + case 0x8283: return 0x63; // 'c' + case 0x8284: return 0x64; // 'd' + case 0x8285: return 0x65; // 'e' + case 0x8286: return 0x66; // 'f' + case 0x8287: return 0x67; // 'g' + case 0x8288: return 0x68; // 'h' + case 0x8289: return 0x69; // 'i' + case 0x828a: return 0x6a; // 'j' + case 0x828b: return 0x6b; // 'k' + case 0x828c: return 0x6c; // 'l' + case 0x828d: return 0x6d; // 'm' + case 0x828e: return 0x6e; // 'n' + case 0x828f: return 0x6f; // 'o' + case 0x8290: return 0x70; // 'p' + case 0x8291: return 0x71; // 'q' + case 0x8292: return 0x72; // 'r' + case 0x8293: return 0x73; // 's' + case 0x8294: return 0x74; // 't' + case 0x8295: return 0x75; // 'u' + case 0x8296: return 0x76; // 'v' + case 0x8297: return 0x77; // 'w' + case 0x8298: return 0x78; // 'x' + case 0x8299: return 0x79; // 'y' + case 0x829a: return 0x7a; // 'z' + case 0x816f: return 0x7b; // '{' + case 0x8162: return 0x7c; // '|' + case 0x8170: return 0x7d; // '}' + case 0x8160: return 0x7e; // '〜' + case 0x8142: return 0xa1; // '。' + case 0x8175: return 0xa2; // '「' + case 0x8176: return 0xa3; // '」' + case 0x8141: return 0xa4; // '、' + case 0x8145: return 0xa5; // '・' + case 0x82f0: return 0xa6; // 'を' + case 0x829f: return 0xa7; // 'ぁ' + case 0x82a1: return 0xa8; // 'ぃ' + case 0x82a3: return 0xa9; // 'ぅ' + case 0x82a5: return 0xaa; // 'ぇ' + case 0x82a7: return 0xab; // 'ぉ' + case 0x82e1: return 0xac; // 'ゃ' + case 0x82e3: return 0xad; // 'ゅ' + case 0x82e5: return 0xae; // 'ょ' + case 0x82c1: return 0xaf; // 'っ' + case 0x815b: return 0xb0; // 'ー' + case 0x82a0: return 0xb1; // 'あ' + case 0x82a2: return 0xb2; // 'い' + case 0x82a4: return 0xb3; // 'う' + case 0x82a6: return 0xb4; // 'え' + case 0x82a8: return 0xb5; // 'お' + case 0x82a9: return 0xb6; // 'か' + case 0x82ab: return 0xb7; // 'き' + case 0x82ad: return 0xb8; // 'く' + case 0x82af: return 0xb9; // 'け' + case 0x82b1: return 0xba; // 'こ' + case 0x82b3: return 0xbb; // 'さ' + case 0x82b5: return 0xbc; // 'し' + case 0x82b7: return 0xbd; // 'す' + case 0x82b9: return 0xbe; // 'せ' + case 0x82bb: return 0xbf; // 'そ' + case 0x82bd: return 0xc0; // 'た' + case 0x82bf: return 0xc1; // 'ち' + case 0x82c2: return 0xc2; // 'つ' + case 0x82c4: return 0xc3; // 'て' + case 0x82c6: return 0xc4; // 'と' + case 0x82c8: return 0xc5; // 'な' + case 0x82c9: return 0xc6; // 'に' + case 0x82ca: return 0xc7; // 'ぬ' + case 0x82cb: return 0xc8; // 'ね' + case 0x82cc: return 0xc9; // 'の' + case 0x82cd: return 0xca; // 'は' + case 0x82d0: return 0xcb; // 'ひ' + case 0x82d3: return 0xcc; // 'ふ' + case 0x82d6: return 0xcd; // 'へ' + case 0x82d9: return 0xce; // 'ほ' + case 0x82dc: return 0xcf; // 'ま' + case 0x82dd: return 0xd0; // 'み' + case 0x82de: return 0xd1; // 'む' + case 0x82df: return 0xd2; // 'め' + case 0x82e0: return 0xd3; // 'も' + case 0x82e2: return 0xd4; // 'や' + case 0x82e4: return 0xd5; // 'ゆ' + case 0x82e6: return 0xd6; // 'よ' + case 0x82e7: return 0xd7; // 'ら' + case 0x82e8: return 0xd8; // 'り' + case 0x82e9: return 0xd9; // 'る' + case 0x82ea: return 0xda; // 'れ' + case 0x82eb: return 0xdb; // 'ろ' + case 0x82ed: return 0xdc; // 'わ' + case 0x82f1: return 0xdd; // 'ん' + case 0x814a: return 0xde; // '゛' + case 0x814b: return 0xdf; // '゜' + } + return code; +} + diff --git a/src/sys/ags_vsp.cpp b/src/sys/ags_vsp.cpp new file mode 100644 index 0000000..c58626f --- /dev/null +++ b/src/sys/ags_vsp.cpp @@ -0,0 +1,172 @@ +/* + ALICE SOFT SYSTEM 3 for Win32 + + [ AGS - vsp loader ] +*/ + +#include "ags.h" +#include "crc32.h" + +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 defined(_SYSTEM3) + if(nact->crc32 == CRC32_AMBIVALENZ_FD || nact->crc32 == CRC32_AMBIVALENZ_CD) { + // Z 0,numを無視する + } else { +#endif + if(palette_bank != -1) { + base = (palette_bank & 0x0f) << 4; + } +#if defined(_SYSTEM3) + } +#endif + + // パレット取得 + if(get_palette) { + 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 defined(_SYSTEM3) + if(nact->crc32 == CRC32_FUNNYBEE_FD || nact->crc32 == CRC32_FUNNYBEE_CD || nact->crc32 == CRC32_FUNNYBEE_PATCH) { + if(extract_palette_cg[page]) { + for(int i = 0; i < 16; i++) { + screen_palette[base + i] = program_palette[base + i]; + } + } + } else { +#endif + if(extract_palette && extract_palette_cg[page]) { + for(int i = 0; i < 16; i++) { + screen_palette[base + i] = program_palette[base + i]; + } + } +#if defined(_SYSTEM3) + } +#endif + + // 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 new file mode 100644 index 0000000..59c1a19 --- /dev/null +++ b/src/sys/ags_vsp2l.cpp @@ -0,0 +1,143 @@ +/* + ALICE SOFT SYSTEM 1 for Win32 + + [ AGS - vsp2l loader ] +*/ + +#include "ags.h" + +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 new file mode 100644 index 0000000..7b96817 --- /dev/null +++ b/src/sys/ags_window.cpp @@ -0,0 +1,329 @@ +/* + ALICE SOFT SYSTEM 3 for Win32 + + [ AGS - window ] +*/ + +#include "ags.h" + +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 && fader) { + 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 = fader ? &fader_screen[640 * (479 - y - sy) + sx] : &lpBmpDest[640 * (479 - 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 = fader ? &fader_screen[640 * (479 - y - sy) + sx] : &lpBmpDest[640 * (479 - 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() +{ + memset(lpBmpScreen[2], menu_back_color, 640 * 480 * sizeof(DWORD)); +} + +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 = fader ? &fader_screen[640 * (479 - y - wsy) + wsx] : &lpBmpDest[640 * (479 - 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 new file mode 100644 index 0000000..d56ab26 --- /dev/null +++ b/src/sys/crc32.h @@ -0,0 +1,48 @@ +/* + ALICE SOFT SYSTEM 3 for Win32 + + [ crc32 database ] +*/ + +#ifndef _CRC32_H_ +#define _CRC32_H_ + +// ADISK.DATの先頭256bytes +#if defined(_SYSTEM1) + +#elif defined(_SYSTEM2) + +#define CRC32_AYUMI_PROTO 0x4e2f5678 // あゆみちゃん物語 PROTO +#define CRC32_SDPS 0xc7a20cdf // Super D.P.S +#define CRC32_SDPS_MARIA 0x80d4eaca // マリアとカンパン +#define CRC32_SDPS_TONO 0xbb1edff1 // 遠野の森 +#define CRC32_SDPS_KAIZOKU 0xf81829e3 // 海賊家業 +#define CRC32_PROSTUDENTG_FD 0x5ffbfee7 // Prostudent -G- (FD) + +#else + +#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_RANCE41 0xa43fb4b6 // Rance 4.1 +#define CRC32_RANCE42 0x04d24d1e // Rance 4.2 +#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_SP 0x2172c7b2 // 闘神都市2 〜そして、それから〜 +#define CRC32_OTOMESENKI 0x49a4db15 // 乙女戦記 +#define CRC32_NINGYO 0xd491e7ab // 人魚 -蘿子- +#define CRC32_MUGENHOUYOU 0xbb27d1ba // 夢幻泡影 + +#endif + +#endif diff --git a/src/sys/dri.cpp b/src/sys/dri.cpp new file mode 100644 index 0000000..b94187b --- /dev/null +++ b/src/sys/dri.cpp @@ -0,0 +1,180 @@ +/* + ALICE SOFT SYSTEM 3 for Win32 + + [ DRI ] +*/ + +#include "dri.h" +#include "crc32.h" +#include "../fileio.h" +#if defined(_SYSTEM1) +#include "../res1/resource.h" +#elif defined(_SYSTEM2) +#include "../res2/resource.h" +#else +#include "../res3/resource.h" +#endif + +extern _TCHAR g_root[_MAX_PATH]; + +uint8* DRI::load(_TCHAR path[], int page, int* size) +{ + _TCHAR base_path[_MAX_PATH], file_path[_MAX_PATH]; + _tcscpy_s(base_path, _MAX_PATH, path); + + FILEIO* fio = new FILEIO(); + + // ページの位置を取得 + base_path[0] = _T('A'); + _stprintf_s(file_path, _MAX_PATH, _T("%s%s"), g_root, base_path); + + if(!fio->Fopen(file_path, 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) { + base_path[0] = _T('A') + disk_index - 1; + _stprintf_s(file_path, _MAX_PATH, _T("%s%s"), g_root, base_path); + fio->Fclose(); + if(!fio->Fopen(file_path, 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; + + int buffer_size = (end_sector - start_sector) * 256; + uint8* buffer = (uint8*)malloc(buffer_size); + fio->Fseek((start_sector - 1) * 256, FILEIO_SEEK_SET); + fio->Fread(buffer, 256, end_sector - start_sector); + + fio->Fclose(); + delete fio; + + *size = buffer_size; + return buffer; +} + +uint8* DRI::load_mda(HINSTANCE hInst, uint32 crc32, int page, int* size) +{ +#if defined(_SYSTEM1) + return NULL; +#elif defined(_SYSTEM2) + return NULL; +#else + // データ取得 + HGLOBAL hGlobal = NULL; + + switch(crc32) { + case CRC32_AMBIVALENZ_FD: // AmbivalenZ (FD) + case CRC32_AMBIVALENZ_CD: // AmbivalenZ (CD) + hGlobal = LoadResource(hInst, FindResource(hInst, MAKEINTRESOURCE(IDR_AMB), _T("mda"))); + break; + case CRC32_DPSALL: // DPS全部 + hGlobal = LoadResource(hInst, FindResource(hInst, MAKEINTRESOURCE(IDR_ALL), _T("mda"))); + break; + case CRC32_FUNNYBEE_CD: // Funny Bee (CD) +// case CRC32_FUNNYBEE_PATCH: // Funny Bee (CD + Patch) + case CRC32_FUNNYBEE_FD: // Funny Bee (FD) + hGlobal = LoadResource(hInst, FindResource(hInst, MAKEINTRESOURCE(IDR_BEE), _T("mda"))); + break; + case CRC32_ONLYYOU: // Only You + case CRC32_ONLYYOU_DEMO: // Only You (DEMO) + hGlobal = LoadResource(hInst, FindResource(hInst, MAKEINTRESOURCE(IDR_OY), _T("mda"))); + break; + case CRC32_PROSTUDENTG_CD: // Prostudent -G- (CD) + hGlobal = LoadResource(hInst, FindResource(hInst, MAKEINTRESOURCE(IDR_PSG), _T("mda"))); + break; + case CRC32_RANCE41: // Rance 4.1 + hGlobal = LoadResource(hInst, FindResource(hInst, MAKEINTRESOURCE(IDR_R41), _T("mda"))); + break; + case CRC32_RANCE42: // Rance 4.2 + hGlobal = LoadResource(hInst, FindResource(hInst, MAKEINTRESOURCE(IDR_R42), _T("mda"))); + break; + case CRC32_AYUMI_CD: // あゆみちゃん物語 (CD) + case CRC32_AYUMI_JISSHA_256: // あゆみちゃん物語 実写版 + case CRC32_AYUMI_JISSHA_FULL: // あゆみちゃん物語 フルカラー実写版 + hGlobal = LoadResource(hInst, FindResource(hInst, MAKEINTRESOURCE(IDR_AYM), _T("mda"))); + break; + case CRC32_YAKATA3_CD: // アリスの館3 (CD) + case CRC32_YAKATA3_FD: // アリスの館3 (FD) + hGlobal = LoadResource(hInst, FindResource(hInst, MAKEINTRESOURCE(IDR_AL3), _T("mda"))); + break; + case CRC32_HASHIRIONNA2: // 走り女2 (Rance 4.x ヒントディスク) + hGlobal = LoadResource(hInst, FindResource(hInst, MAKEINTRESOURCE(IDR_RG2), _T("mda"))); + break; + case CRC32_OTOMESENKI: // 乙女戦記 + hGlobal = LoadResource(hInst, FindResource(hInst, MAKEINTRESOURCE(IDR_OTM), _T("mda"))); + break; + case CRC32_MUGENHOUYOU: // 夢幻泡影 + hGlobal = LoadResource(hInst, FindResource(hInst, MAKEINTRESOURCE(IDR_MGN), _T("mda"))); + break; + } + + if(hGlobal == NULL) { + return NULL; + } + + uint8* data = (uint8*)LockResource(hGlobal); + + // ページの位置を取得 + int link_sector = data[0] | (data[1] << 8); + int data_sector = data[2] | (data[3] << 8); + + if(page > (data_sector - link_sector) * 128 - 1) { + // ページ番号不正 + return NULL; + } + + int disk_index = data[(link_sector - 1) * 256 + (page - 1) * 2 + 0]; + int link_index = data[(link_sector - 1) * 256 + (page - 1) * 2 + 1]; + + if(disk_index == 0 || disk_index == 0x1a) { + // 欠番 + return NULL; + } + + // データ取得 + int start_sector = data[link_index * 2 + 0] | (data[link_index * 2 + 1] << 8); + int end_sector = data[link_index * 2 + 2] | (data[link_index * 2 + 3] << 8); + + int buffer_size = (end_sector - start_sector) * 256; + uint8* buffer = (uint8*)malloc(buffer_size); + memcpy(buffer, &data[(start_sector - 1) * 256], buffer_size); + + *size = buffer_size; + return buffer; +#endif +} + diff --git a/src/sys/dri.h b/src/sys/dri.h new file mode 100644 index 0000000..c7dd319 --- /dev/null +++ b/src/sys/dri.h @@ -0,0 +1,24 @@ +/* + ALICE SOFT SYSTEM 3 for Win32 + + [ DRI ] +*/ + +#ifndef _DRI_H_ +#define _DRI_H_ + +#include +#include +#include "../common.h" + +class DRI +{ +public: + DRI() {} + ~DRI() {} + + uint8* load(_TCHAR path[], int page, int* size); + uint8* load_mda(HINSTANCE hInst, uint32 crc32, int page, int* size); +}; + +#endif diff --git a/src/sys/mako.cpp b/src/sys/mako.cpp new file mode 100644 index 0000000..c97e36a --- /dev/null +++ b/src/sys/mako.cpp @@ -0,0 +1,251 @@ +/* + ALICE SOFT SYSTEM 3 for Win32 + + [ MAKO ] +*/ + +#include "mako.h" +#include "dri.h" + +extern HWND g_hwnd; + +MAKO::MAKO(NACT* parent) : nact(parent) +{ + // AMUS.DAT, AMSE.DAT + _tcscpy_s(amus, 16, _T("AMUS.DAT")); + _tcscpy_s(amse, 16, _T("AMSE.DAT")); // 実際には使わない + + // 再生状況 + current_music = current_mark = current_loop = 0; + current_max = next_loop = 0; + + // CD-DA + for(int i = 1; i <= 99; i++) { + cd_track[i] = 0; + } + cdda_play = false; + + // MIDI再生スレッド起動 + params.mako = this; + params.current_music = params.next_music = 0; + params.request_fill = params.terminate = false; + hThread = (HANDLE)_beginthread(thread, 0, ¶ms); + SetThreadPriority(hThread, THREAD_PRIORITY_HIGHEST); +} + +MAKO::~MAKO() +{ + // MIDI再生スレッド終了 + params.terminate = true; + if(hThread) { + WaitForSingleObject(hThread, INFINITE); + } + hThread = NULL; + + // PCM停止 +#if defined(_USE_PCM) + PlaySound(NULL, NULL, SND_PURGE); +#endif +} + +void MAKO::thread(PVOID pvoid) +{ + volatile PPARAMS pparams; + pparams = (PPARAMS)pvoid; + + // MIDI初期化 + pparams->mako->initialize_midi(); + + while(!pparams->terminate) { + int current_music = pparams->current_music; + int next_music = pparams->next_music; + int next_music_bak = next_music; + if(current_music != next_music) { + // 停止 + pparams->mako->stop_midi(); + current_music = 0; + + // 次の再生準備 + if(next_music) { + if(pparams->mako->load_mml(next_music)) { + pparams->mako->load_mda(next_music); + pparams->mako->start_midi(); + current_music = next_music; + Sleep(100); + } else { + next_music = 0; + } + } + } + if(current_music) { + pparams->mako->play_midi(); + } + + pparams->current_music = current_music; + if(pparams->next_music == next_music_bak) { + pparams->next_music = next_music; + } + Sleep(10); + } + + // MIDI開放 + pparams->mako->stop_midi(); + pparams->mako->release_midi(); + + _endthread(); +} + +void MAKO::play_music(int page) +{ + // 既に同じ曲を再生している + if(current_music == page) { + return; + } + + // 演奏するデバイスが変更される場合は停止する + if(current_music) { + bool next_cdda = (page < 100 && cd_track[page]) ? true : false; + if(cdda_play && !next_cdda) { + PostMessage(g_hwnd, WM_USER, 0, 0); + } else if(!cdda_play && next_cdda) { + params.next_music = 0; + } + } + + current_music = page; + current_max = next_loop; + current_mark = current_loop = next_loop = 0; + + if(page < 100 && cd_track[page]) { + // CD-DAで再生 + PostMessage(g_hwnd, WM_USER, cd_track[page] + 1, 0); + cdda_play = true; + } else { + // MIDIで再生 + params.next_music = page; + cdda_play = false; + } +} + +void MAKO::stop_music() +{ + // 現在再生中の場合は停止する + if(current_music) { + if(cdda_play) { + PostMessage(g_hwnd, WM_USER, 0, 0); + } else { + params.next_music = 0; + } + } + cdda_play = false; + current_music = current_mark = current_loop = 0; +} + +bool MAKO::check_music() +{ + // 再生中でtrue + return current_music ? true : false; +} + +void MAKO::get_mark(int* mark, int* loop) +{ + *mark = cdda_play ? 0 : current_mark; + *loop = cdda_play ? 0 : current_loop; +} + +void MAKO::notify_mci(int status) +{ + if(status == -1) { + // 再生に失敗 + current_music = current_mark = current_loop = 0; + return; + } + + if(cdda_play) { + current_loop++; + if(current_loop < current_max || current_max == 0) { + PostMessage(g_hwnd, WM_USER, cd_track[current_music] + 1, 0); + } else { + current_music = current_mark = current_loop = 0; + cdda_play = false; + } + } +} + +void MAKO::play_pcm(int page, bool loop) +{ +#if defined(_USE_PCM) + 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 + }; + + // 現在再生中のPCMを停止 + PlaySound(NULL, NULL, SND_PURGE); + + uint8* buffer = NULL; + int size; + DRI* dri = new DRI(); + + if((buffer = dri->load(_T("AWAV.DAT"), page, &size)) != NULL) { + // WAV形式 (Only You) + memcpy(wav, buffer, (size < MAX_SAMPLES) ? size : MAX_SAMPLES); + + if(loop) { + PlaySound(wav, NULL, SND_ASYNC | SND_MEMORY | SND_LOOP); + } else { + PlaySound(wav, NULL, SND_ASYNC | SND_MEMORY); + } + free(buffer); + } else if((buffer = dri->load(_T("AMSE.DAT"), page, &size)) != NULL) { + // AMSE形式 (乙女戦記) + int total = (size - 12) * 2 + 0x24; + int samples = (size - 12) * 2; + + 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 && p < MAX_SAMPLES - 2; i++) { + wav[p++] = buffer[i] & 0xf0; + wav[p++] = (buffer[i] & 0x0f) << 4; + } + + if(loop) { + PlaySound(wav, NULL, SND_ASYNC | SND_MEMORY | SND_LOOP); + } else { + PlaySound(wav, NULL, SND_ASYNC | SND_MEMORY); + } + free(buffer); + } +#endif +} + +void MAKO::stop_pcm() +{ +#if defined(_USE_PCM) + PlaySound(NULL, NULL, SND_PURGE); +#endif +} + +bool MAKO::check_pcm() +{ + // 再生中でtrue +#if defined(_USE_PCM) + static 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) ? false : true; +#else + return false; +#endif +} + diff --git a/src/sys/mako.h b/src/sys/mako.h new file mode 100644 index 0000000..ade93ee --- /dev/null +++ b/src/sys/mako.h @@ -0,0 +1,137 @@ +/* + ALICE SOFT SYSTEM 3 for Win32 + + [ MAKO ] +*/ + +#ifndef _MAKO_H_ +#define _MAKO_H_ + +#include +#include +#include +#include +#include +#include +#include +#include "../common.h" +#include "nact.h" + +#define MAX_SAMPLES (128 * 1024) +#define MAX_MMLS (128 * 1024) + +#define _USE_REAL_MIDI +#define _USE_PCM + +class MAKO +{ +protected: + NACT* nact; + +private: + // FM, CD-DA + bool cdda_play; + int current_mark; // Y18 + int current_loop; + int current_max; // Y19 + + // PCM + char wav[MAX_SAMPLES]; + + // MIDI再生スレッド + typedef struct { + MAKO* mako; + int current_music; + int next_music; + bool request_fill; + bool terminate; + } PARAMS, *PPARAMS; + PARAMS params; + + static void thread(PVOID pvoid); + HANDLE hThread; + + // MIDI音源 + union UNION_MIDI_DATA { + DWORD msg; + BYTE data[4]; + }; + UNION_MIDI_DATA midi; + HMIDIOUT hMidi; + + // MML + typedef struct { + uint8 data[MAX_MMLS]; + int addr; + } MML; + MML mml[9]; + + // MDA + typedef struct { + int bank_select; + int program_change; + int level; + int reverb; + int chorus; + int key_shift; + int pan; + } MDA; + MDA mda[259]; + int drum_map[8][128]; + int tempo, tempo_dif; + + // MIDI再生状態 + typedef struct { + 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; + } PLAY; + PLAY play[9]; + bool mute_flag; + float play_time; + DWORD prev_time; + +public: + MAKO(NACT* parent); + ~MAKO(); + + void play_music(int page); + void stop_music(); + bool check_music(); + void get_mark(int* mark, int* loop); + void notify_mci(int status); + + void play_pcm(int page, bool loop); + void stop_pcm(); + bool check_pcm(); + + void initialize_midi(); + void release_midi(); + void stop_midi(); + void start_midi(); + void play_midi(); + + bool load_mml(int page); + void load_mda(int page); + + // AMUS.DAT, AMSE.DAT + _TCHAR amus[16]; + _TCHAR amse[16]; + + int current_music; + int next_loop; // Y19 + int cd_track[100]; // Z +}; + +#endif diff --git a/src/sys/mako_midi.cpp b/src/sys/mako_midi.cpp new file mode 100644 index 0000000..170a521 --- /dev/null +++ b/src/sys/mako_midi.cpp @@ -0,0 +1,540 @@ +/* + ALICE SOFT SYSTEM 3 for Win32 + + [ MAKO - midi ] +*/ + +#include "mako.h" +#include "dri.h" + +extern HINSTANCE g_hinst; +extern HWND g_hwnd; + +#define next_mml(p) mml[p].data[mml[p].addr++] + +// MIDI音源 +#define send_2bytes(d1, d2) { midi.data[0] = (BYTE)d1; midi.data[1] = (BYTE)d2; midiOutShortMsg(hMidi,midi.msg); } +#define send_3bytes(d1, d2, d3) { midi.data[0] = (BYTE)d1; midi.data[1] = (BYTE)d2; midi.data[2] = (BYTE)d3 ;midiOutShortMsg(hMidi, midi.msg); } + +void MAKO::initialize_midi() +{ + // MIDI音源の初期化 + midiOutOpen(&hMidi, MIDI_MAPPER, NULL, NULL, CALLBACK_NULL); +} + +void MAKO::release_midi() +{ + // MIDI音源の開放 + midiOutClose(hMidi); +} + +void MAKO::stop_midi() +{ + for(int i = 0; i < 10; i++) { + send_3bytes(0xb0 + i, 0x78, 0x00); + } + for(int i = 0; i < 10; i++) { + send_3bytes(0xb0 + i, 0x79, 0x00); + } +} + +void MAKO::start_midi() +{ + for(int i = 0; i < 9; i++) { + play[i].loop_flag = true; + } + 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; + } + + // MIDI音源のGS-RESET + BYTE gs_reset[11] = {0xf0, 0x41, 0x20, 0x42, 0x12, 0x40, 0x00, 0x7f, 0x00, 0x41, 0xf7}; + MIDIHDR mhMidi; + ZeroMemory(&mhMidi, sizeof(mhMidi)); + mhMidi.lpData = (LPSTR)gs_reset; + mhMidi.dwBufferLength = 11; + mhMidi.dwBytesRecorded = 11; + + midiOutPrepareHeader(hMidi, &mhMidi, sizeof(mhMidi)); + midiOutLongMsg(hMidi, &mhMidi, sizeof(mhMidi)); + while(!(mhMidi.dwFlags & MHDR_DONE)) { + Sleep(10); + } + midiOutUnprepareHeader(hMidi, &mhMidi, sizeof(mhMidi)); + + // システムリセット、ボリュームリセット + for(int i = 0; i < 10; i++) { + send_3bytes(0xb0 + i, 0x79, 0x00); + } + for(int i = 0; i < 10; i++) { + send_3bytes(0xb0 + i, 0x07, 0x64); + } + + // SSG 1-3 の音色 + for(int i = 0; i < 3; i++) { + if(mda[i + 256].bank_select < 128) { + send_3bytes(0xb3 + i, 0x00, mda[i + 256].bank_select); + send_3bytes(0xb3 + i, 0x20, 0x00); + send_2bytes(0xc3 + i, mda[i + 256].program_change); + send_3bytes(0xb3 + i, 0x07, mda[i + 256].level); + send_3bytes(0xb3 + i, 0x5b, mda[i + 256].reverb); + send_3bytes(0xb3 + i, 0x5d, mda[i + 256].chorus); + send_3bytes(0xb3 + i, 0x0a, mda[i + 256].pan); + } else { + send_3bytes(0xb9, 0x07, mda[i + 256].level); + send_3bytes(0xb9, 0x5b, mda[i + 256].reverb); + send_3bytes(0xb9, 0x5d, mda[i + 256].chorus); + send_3bytes(0xb9, 0x0a, mda[i + 256].pan); + } + } + + // タイマーリセット + prev_time = timeGetTime(); + play_time = 0; +} + +void MAKO::play_midi() +{ + // 経過時間の取得 + DWORD current_time = timeGetTime(); + if(current_time > prev_time) { + play_time += (float)(current_time - prev_time); + prev_time = current_time; + } + + // 各パートの更新 + 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) { + // 全チャンネルが再生停止 (ループしない曲) + for(int j = 0; j < 10; j++) { + send_3bytes(0xb0 + j, 0x78, 0x00); + } + for(int j = 0; j < 10; j++) { + send_3bytes(0xb0 + j, 0x79, 0x00); + } + current_loop = 1; + current_music = 0; + params.current_music = params.next_music = 0; + return; + } + 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(current_loop >= current_max && current_max) { + // 指定回数だけ再生完了 + for(int j = 0; j < 10; j++) { + send_3bytes(0xb0 + j, 0x78, 0x00); + } + for(int j = 0; j < 10; j++) { + send_3bytes(0xb0 + j, 0x79, 0x00); + } + current_music = 0; + params.current_music = params.next_music = 0; + return; + } + } + } 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; + 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) { + 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); + send_3bytes(0xb0 + play[i].channel, 0x0a, play[i].pan); + } +#if !defined(_DPS) + else if(d0 == 0xec) { + mute_flag = true; + } +#endif + 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; + send_3bytes(0xb0 + play[i].channel, 0x00, mda[n].bank_select); + send_3bytes(0xb0 + play[i].channel, 0x20, 0x00); + 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) { + send_3bytes(0xb0 + play[i].channel, 0x07, mda[n].level); + } + if(play[i].reverb != mda[n].reverb) { + send_3bytes(0xb0 + play[i].channel, 0x5b, mda[n].reverb); + } + if(play[i].chorus != mda[n].chorus) { + send_3bytes(0xb0 + play[i].channel, 0x5d, mda[n].chorus); + } + if(play[i].pan != mda[n].pan) { + 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); + } + send_3bytes(0xb0 + play[i].channel, 0x65, 0x00); + send_3bytes(0xb0 + play[i].channel, 0x64, 0x01); + send_3bytes(0xb0 + play[i].channel, 0x06, d1); + } + } + } + } +} + +bool MAKO::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 MAKO::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データの読み込み + _TCHAR path[16]; + _tcscpy_s(path, 16, amus); + int p = _tcslen(path); + path[p - 3] = _T('M'); + path[p - 2] = _T('D'); + path[p - 1] = _T('A'); + + DRI* dri = new DRI(); + int size; + uint8* data = NULL; + if((data = dri->load(path, page, &size)) == NULL) { + data = dri->load_mda(g_hinst, nact->crc32, 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 new file mode 100644 index 0000000..a8022e5 --- /dev/null +++ b/src/sys/nact.cpp @@ -0,0 +1,575 @@ +/* + ALICE SOFT SYSTEM 3 for Win32 + + [ NACT ] +*/ + +#if defined(_SYSTEM1) +#include "../res1/resource.h" +#elif defined(_SYSTEM2) +#include "../res2/resource.h" +#else +#include "../res3/resource.h" +#endif + +#include +#include +#include "nact.h" +#include "ags.h" +#include "mako.h" +#include "dri.h" +#include "../fileio.h" + +extern _TCHAR g_root[_MAX_PATH]; +extern HWND g_hwnd; + +// 初期化 + +NACT::NACT() +{ + memset(key, 0, sizeof(key)); + mouse_x = mouse_y = 0; + + // デバッグコンソール起動 + initialize_console(); + + // SYSTEM3 初期化 + + crc32 = calc_crc32(); + fatal_error = post_quit = false; + + // AG00.DAT読み込み + FILEIO* fio = new FILEIO(); + _TCHAR file_path[_MAX_PATH]; + _stprintf_s(file_path, _MAX_PATH, _T("%sAG00.DAT"), g_root); + + if(fio->Fopen(file_path, FILEIO_READ_BINARY)) { + int d0, d1, d2, d3; + char string[MAX_CAPTION]; + fio->Fgets(string); + sscanf_s(string, "%d,%d,%d,%d", &d0, &d1, &d2, &d3); + for(int i = 0; i < d1; i++) { + // 動詞の読み込み + fio->Fgets(string); + memcpy(caption_verb[i], string, sizeof(string)); + } + for(int i = 0; i < d2; i++) { + // 目的語の読み込み + fio->Fgets(string); + memcpy(caption_obj[i], string, sizeof(string)); + } + fio->Fclose(); + } + delete fio; + + // ADISK.DAT +#if defined(_PROG_OMAKE) + _tcscpy_s(adisk, 16, _T("AGAME.DAT")); +#else + _tcscpy_s(adisk, 16, _T("ADISK.DAT")); +#endif + + // シナリオ管理 + 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 = timeGetTime(); // 乱数の種 + text_wait_time = 100; // メッセージ表示のウェイト + text_wait_enb = false; + text_skip_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)); + + // SYETEM1 初期化 +#if defined(_DPS) + text_refresh = false; + _tcscpy_s(tvar[0], 22, _T("カスタム")); + _tcscpy_s(tvar[1], 22, _T("リーナス")); + _tcscpy_s(tvar[2], 22, _T("かつみ")); + _tcscpy_s(tvar[3], 22, _T("由美子")); + _tcscpy_s(tvar[4], 22, _T("いつみ")); + _tcscpy_s(tvar[5], 22, _T("ひとみ")); + _tcscpy_s(tvar[6], 22, _T("真理子")); +#elif defined(_INTRUDER) + paint_x = paint_y = map_page = 0; +#endif + + // 各種クラス生成 + ags = new AGS(this); + mako = new MAKO(this); + + // 入力初期化 + joy_num = joyGetNumDevs(); + if(joy_num) { + joyGetDevCaps(JOYSTICKID1, &joycaps, sizeof(JOYCAPS)); + } + + // メインスレッド起動 + params.nact = this; + params.terminate = false; + hThread = (HANDLE)_beginthread(thread, 0, ¶ms); + SetThreadPriority(hThread, THREAD_PRIORITY_NORMAL); +} + +NACT::~NACT() +{ + // メインスレッド終了 + params.terminate = true; + if(hThread) { + WaitForSingleObject(hThread, INFINITE); + } + hThread = NULL; + + // 各種クラス開放 + if(ags) { + delete ags; + } + if(mako) { + delete mako; + } + + // シナリオ開放 + if(scenario_data) { + free(scenario_data); + } + + // デバッグコンソール開放 + release_console(); +} + +void NACT::thread(PVOID pvoid) +{ + volatile PPARAMS pparams; + pparams = (PPARAMS)pvoid; + int sleep_cnt = 0; + + while(!pparams->terminate) { + pparams->nact->execute(); + // 512コマンド実行毎にSleep(10) + if(!(sleep_cnt = (sleep_cnt + 1) & 0x1ff)) { + Sleep(10); + } else { + Sleep(0); + } + } + _endthread(); +} + +// コマンドパーサ + +void NACT::execute() +{ + // アドレスの確認 + if(scenario_addr < 2 || scenario_addr >= scenario_size) { + fatal_error = true; + } + + // 致命的なエラー発生 or 正常終了 + if(fatal_error) { + if(!post_quit) { + PostMessage(g_hwnd, WM_CLOSE, 0, 0); + } + post_quit = true; + return; + } + +#if defined(_SYSTEM1) + if(scenario_page == 0 && scenario_addr == 2) { + opening(); + } +#endif + + // 1コマンド実行 + 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; + default: + if(cmd == 0x20 || (0xa1 <= cmd && cmd <= 0xdd)) { + // message (1 byte) + char string[2]; + string[0] = cmd; + string[1] = '\0'; + ags->draw_text(string); +#if defined(_DPS) + if(!ags->draw_menu) { + text_refresh = false; + } +#endif + + if(!ags->draw_menu && text_wait_enb && cmd != 0x20) { + DWORD dwTime = timeGetTime() + text_wait_time; + for(;;) { + if(params.terminate) { + return; + } + RND = get_key(); + if(RND && wait_keydown) { + break; + } + if(dwTime <= timeGetTime()) { + break; + } + Sleep(10); + } + } + +#if defined(_DEBUG_CONSOLE) + output_console(string); +#endif + } else if((0x81 <= cmd && cmd <= 0x9f) || 0xe0 <= cmd) { + // message (2 bytes) + char string[3]; + string[0] = cmd; + string[1] = getd(); + string[2] = '\0'; + ags->draw_text(string); +#if defined(_DPS) + if(!ags->draw_menu) { + text_refresh = false; + } +#endif + + if(!ags->draw_menu && text_wait_enb) { + DWORD dwTime = timeGetTime() + text_wait_time; + for(;;) { + if(params.terminate) { + return; + } + RND = get_key(); + if(RND && wait_keydown) { + break; + } + if(dwTime <= timeGetTime()) { + break; + } + Sleep(10); + } + } + +#if defined(_DEBUG_CONSOLE) + output_console(string); +#endif + } else { + fatal_error = true; + +#if defined(_DEBUG_CONSOLE) + char log[128]; + memset(log, 0, sizeof(log)); + sprintf_s(log, 128, "\nFAILED: %2x, %d", cmd, scenario_addr); + output_console(log); +#endif + } + break; + } +} + +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_error = true; + } + delete dri; +} + +// 下位関数 + +uint16 NACT::random(uint16 range) +{ + // xorhift32 + seed = seed ^ (seed << 13); + seed = seed ^ (seed >> 17); + seed = seed ^ (seed << 15); + return (uint16)(((uint32)range * (seed & 0xffff)) >> 16) + 1; +} + +// WinMainとのインターフェース + +int NACT::get_screen_height() +{ + return ags->screen_height; +} + +void NACT::update_screen(HDC hdc, int sx, int sy, int width, int height) +{ + ags->update_screen(hdc, sx, sy, width, height); +} + +void NACT::notify_mci(int status) +{ + mako->notify_mci(status); +} + +void NACT::key_down(int val) +{ + key[val] = 1; +} + +void NACT::key_up(int val) +{ + if(val == -1) { + memset(key, 0, sizeof(key)); + } else { + key[val] = 0; + } +} + +void NACT::select_cursor() +{ + ags->select_cursor(); +} + +void NACT::select_sound(int dev) +{ + // 強制的に音源を変更する + int page = mako->current_music; + int old_dev = (1 <= page && page <= 99 && mako->cd_track[page]) ? 1 : 0; + + for(int i = 1; i <= 99; i++) { + mako->cd_track[i] = dev ? i : 0; + } + + // デバイスが変更された場合は再演奏する + if(dev != old_dev && page) { + mako->stop_music(); + mako->play_music(page); + } +} + +// デバッグコンソール + +void NACT::initialize_console() +{ +#if defined(_DEBUG_CONSOLE) + AllocConsole(); + hConsole = GetStdHandle(STD_OUTPUT_HANDLE); +#if defined(_SYSTEM1) + SetConsoleTitle("SYSTEM1 NACT Tracer"); +#elif defined(_SYSTEM2) + SetConsoleTitle("SYSTEM2 NACT Tracer"); +#else + SetConsoleTitle("SYSTEM3 NACT Tracer"); +#endif +#endif +} + +void NACT::release_console() +{ +#if defined(_DEBUG_CONSOLE) + FreeConsole(); +#endif +} + +void NACT::output_console(char log[]) +{ +#if defined(_DEBUG_CONSOLE) + DWORD dwWritten; + WriteConsole(hConsole, log, strlen(log), &dwWritten, NULL); +#endif +} + +BOOL CALLBACK NACT::TextDialogProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam) +{ + static NACT* nact; + char string[64]; + int pnt, cnt; + + switch(msg) { + case WM_CLOSE: + EndDialog(hDlg, IDCANCEL); + break; + case WM_INITDIALOG: + // get this pointer + nact = (NACT *)lParam; + // init dialog + sprintf_s(string, 64, "文字列を入力してください(最大%d文字)", nact->tvar_maxlen); + Edit_SetText(GetDlgItem(hDlg, IDC_TEXT), string); + Edit_SetText(GetDlgItem(hDlg, IDC_EDITBOX), nact->tvar[nact->tvar_index - 1]); + if(nact->tvar[nact->tvar_index - 1][0] == '\0') { + EnableWindow(GetDlgItem(hDlg, IDOK), FALSE); + } else { + EnableWindow(GetDlgItem(hDlg, IDOK), TRUE); + } + break; + + case WM_COMMAND: + switch(LOWORD(wParam)) { + case IDC_EDITBOX: + GetDlgItemText(hDlg, IDC_EDITBOX, string, 32); + pnt = cnt = 0; + while(string[pnt] != '\0') { + unsigned char dat = string[pnt]; + if((0x81 <= dat && dat <= 0x9f) || 0xe0 <= dat) { + pnt++; + } + pnt++; + cnt++; + } + if(cnt == 0 || cnt > nact->tvar_maxlen) { + EnableWindow(GetDlgItem(hDlg, IDOK), FALSE); + } else { + EnableWindow(GetDlgItem(hDlg, IDOK), TRUE); + } + break; + case IDOK: + GetDlgItemText(hDlg, IDC_EDITBOX, string, 32); + strcpy_s(nact->tvar[nact->tvar_index - 1], 22, string); + EndDialog(hDlg, IDOK); + break; + default: + return FALSE; + } + break; + + default: + return FALSE; + } + return TRUE; +} + diff --git a/src/sys/nact.h b/src/sys/nact.h new file mode 100644 index 0000000..c2be2c5 --- /dev/null +++ b/src/sys/nact.h @@ -0,0 +1,271 @@ +/* + ALICE SOFT SYSTEM 3 for Win32 + + [ NACT ] +*/ + +#ifndef _NACT_H_ +#define _NACT_H_ + +#include +#include +#if defined(_DEBUG_CONSOLE) +#include +#endif +#include +#include +#include +#include "../common.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 NACT +{ +protected: + AGS* ags; + MAKO* mako; + +private: + // コマンドパーサ + void execute(); + void load_scenario(int page); + + bool fatal_error; + bool post_quit; + + // ADISK.DAT, ASLEEP.DAT + _TCHAR adisk[16]; + + // シナリオデータ + uint8* scenario_data; + int scenario_size; + + // アドレス、ページ管理 + int scenario_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 cmd_calc(); + + void cmd_branch(); + void cmd_label_jump(); + void cmd_label_call(); + void cmd_page_jump(); + void cmd_page_call(); + + void cmd_set_menu(); + void cmd_open_menu(); + + void cmd_set_verbobj(); + void cmd_set_verbobj2(); + void cmd_open_verb(); + void cmd_open_obj(int verb); + + void cmd_a(); + void cmd_b(); + void cmd_d(); + void cmd_e(); + void cmd_f(); + void cmd_g(); + void cmd_h(); + void cmd_i(); + void cmd_j(); + void cmd_k(); + void cmd_l(); + void cmd_m(); + void cmd_n(); + void cmd_o(); + void cmd_p(); + void cmd_q(); + void cmd_r(); + void cmd_s(); + void cmd_t(); + void cmd_u(); + void cmd_v(); + void cmd_w(); + void cmd_x(); + void cmd_y(); + void cmd_z(); + +#if defined(_SYSTEM1) + void opening(); +#if defined(_DPS) + bool text_refresh; +#elif defined(_INTRUDER) + int paint_x; // Intruder Zコマンド + int paint_y; + int map_page; +#endif +#endif + + 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]; + + // 下位関数 + uint16 cali(); + uint16 cali2(); + uint8 getd(); + uint16 getw(); + + uint16 random(uint16 range); + uint32 seed; + + uint8 get_key(); + void get_cursor(int* x, int* y); + void set_cursor(int x, int y); + + int joy_num; + JOYCAPS joycaps; + uint8 key[256]; + int mouse_x, mouse_y; + + uint32 calc_crc32(); + + // Y27 ダイアログ + static BOOL CALLBACK TextDialogProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam); + + // メインスレッド + typedef struct { + NACT* nact; + bool terminate; + } PARAMS, *PPARAMS; + PARAMS params; + + static void thread(PVOID pvoid); + HANDLE hThread; + + // デバッグログ + void initialize_console(); + void release_console(); + HANDLE hConsole; + +public: + NACT(); + ~NACT(); + + int get_screen_height(); + void update_screen(HDC hdc, int sx, int sy, int width, int height); + void notify_mci(int status); + + void key_down(int val); + void key_up(int val); + void select_cursor(); + void select_sound(int dev); + + bool get_title(_TCHAR title[], int length); + + bool text_skip_enb; // メッセージスキップ + bool text_wait_enb; // テキスト表示のウェイト有効/無効 + uint32 crc32; + + // for Y27 + char tvar[10][22]; + int tvar_index, tvar_maxlen; + + // デバッグログ + void output_console(char log[]); +}; + +#endif + diff --git a/src/sys/nact_crc32.cpp b/src/sys/nact_crc32.cpp new file mode 100644 index 0000000..f446879 --- /dev/null +++ b/src/sys/nact_crc32.cpp @@ -0,0 +1,191 @@ +/* + ALICE SOFT SYSTEM 3 for Win32 + + [ NACT - crc32 ] +*/ + +#include "nact.h" +#include "crc32.h" +#include "../fileio.h" + +extern _TCHAR g_root[_MAX_PATH]; + +uint32 NACT::calc_crc32() +{ + uint32 crc = 0; + FILEIO* fio = new FILEIO(); + + _TCHAR file_path[_MAX_PATH]; + _stprintf_s(file_path, _MAX_PATH, _T("%sADISK.DAT"), g_root); + + if(fio->Fopen(file_path, 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(); + } +#if defined(_SYSTEM2) + if(crc == CRC32_SDPS) { + // Super D.P.Sの場合はBDISK.DATのCRCを取る + _stprintf_s(file_path, _MAX_PATH, _T("%sBDISK.DAT"), g_root); + + if(fio->Fopen(file_path, 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; + } + // BDISK.DATの先頭256bytes + crc = 0; + 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(); + } + } +#endif + delete fio; +#if 0 +FILE* fp = fopen("crc32.txt", "w"); +fprintf(fp, "%x\n", crc); +fclose(fp); +#endif + return crc; +} + +bool NACT::get_title(_TCHAR title[], int length) +{ +#if defined(_SYSTEM1) + +#if defined(_CRESCENT) + _tcscpy_s(title, length, _T("クレセントムーンがぁる")); + return true; +#elif defined(_DPS) + _tcscpy_s(title, length, _T("D.P.S - Dream Program System")); + return true; +#elif defined(_FUKEI) + _tcscpy_s(title, length, _T("婦警さんVX")); + return true; +#elif defined(_INTRUDER) + _tcscpy_s(title, length, _T("Intruder -桜屋敷の探索-")); + return true; +#elif defined(_TENGU) + _tcscpy_s(title, length, _T("あぶないてんぐ伝説")); + return true; +#elif defined(_VAMPIRE) + _tcscpy_s(title, length, _T("Little Vampire")); + return true; +#else + title[0] = _T('\0'); + return false; +#endif + +#elif defined(_SYSTEM2) + + switch(crc32) { + case CRC32_AYUMI_PROTO: + _tcscpy_s(title, length, _T("あゆみちゃん物語 PROTO")); + return true; + case CRC32_SDPS_MARIA: + case CRC32_SDPS_TONO: + case CRC32_SDPS_KAIZOKU: + _tcscpy_s(title, length, _T("Super D.P.S")); + return true; + case CRC32_PROSTUDENTG_FD: + _tcscpy_s(title, length, _T("prostudent G")); + return true; + } + title[0] = _T('\0'); + return false; + +#else + + switch(crc32) { + case CRC32_AMBIVALENZ_FD: + case CRC32_AMBIVALENZ_CD: + _tcscpy_s(title, length, _T("AmbivalenZ −二律背反−")); + return true; + case CRC32_DPSALL: + _tcscpy_s(title, length, _T("D.P.S. 全部")); + return true; + case CRC32_FUNNYBEE_CD: +// case CRC32_FUNNYBEE_PATCH: + case CRC32_FUNNYBEE_FD: + _tcscpy_s(title, length, _T("宇宙快盗ファニーBee")); + return true; + case CRC32_ONLYYOU: + _tcscpy_s(title, length, _T("Only You −世紀末のジュリエット達−")); + return true; + case CRC32_ONLYYOU_DEMO: + _tcscpy_s(title, length, _T("Only You −世紀末のジュリエット達− デモ版")); + return true; + case CRC32_PROSTUDENTG_CD: + _tcscpy_s(title, length, _T("prostudent G")); + return true; + case CRC32_RANCE41: + _tcscpy_s(title, length, _T("ランス 4.1 〜お薬工場を救え!〜")); + return true; + case CRC32_RANCE42: + _tcscpy_s(title, length, _T("ランス 4.2 〜エンジェル組〜")); + return true; + case CRC32_AYUMI_CD: + _tcscpy_s(title, length, _T("あゆみちゃん物語")); + return true; + case CRC32_AYUMI_JISSHA_256: + _tcscpy_s(title, length, _T("あゆみちゃん物語 実写版")); + return true; + case CRC32_AYUMI_JISSHA_FULL: + _tcscpy_s(title, length, _T("あゆみちゃん物語 フルカラー実写版")); + return true; + case CRC32_YAKATA3_CD: + case CRC32_YAKATA3_FD: + _tcscpy_s(title, length, _T("アリスの館3")); + return true; + case CRC32_HASHIRIONNA2: + _tcscpy_s(title, length, _T("走り女2")); + return true; + case CRC32_TOUSHIN2_SP: + _tcscpy_s(title, length, _T("闘神都市2 そして、それから…")); + return true; + case CRC32_OTOMESENKI: + _tcscpy_s(title, length, _T("乙女戦記")); + return true; + case CRC32_NINGYO: + _tcscpy_s(title, length, _T("人魚 -蘿子-")); + return true; + case CRC32_MUGENHOUYOU: + _tcscpy_s(title, length, _T("夢幻泡影")); + return true; + } + title[0] = _T('\0'); + return false; + +#endif +} + diff --git a/src/sys/nact_dialog.cpp b/src/sys/nact_dialog.cpp new file mode 100644 index 0000000..83c4fc8 --- /dev/null +++ b/src/sys/nact_dialog.cpp @@ -0,0 +1,67 @@ + +BOOL CALLBACK NACT::TextDialogProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam) +{ + _TCHAR string[64]; + char origin[22]; + + switch(msg) { + case WM_CLOSE: + EndDialog(hDlg, IDCANCEL); + break; + + case WM_INITDIALOG: + { + // ダイアログの初期化 + _TCHAR string[256]; + _stprintf_s(string, 258, _T("文字列を入力してください (最大%d文字)"), tvar_length); + Edit_SetText(GetDlgItem(hDlg, IDC_TEXT), string); + + char origin[22]; + memcpy(origin, tvar[tvar_index - 1], 22); + Edit_SetText(GetDlgItem(hDlg, IDC_EDITBOX), origin); + if(origin[0] == '\0') { + EnableWindow(GetDlgItem(hDlg, IDOK), FALSE); + } else { + EnableWindow(GetDlgItem(hDlg, IDOK), TRUE); + } + } + break; + + case WM_COMMAND: + switch(LOWORD(wParam)) { + case IDC_EDITBOX: + { + GetDlgItemText(hDlg, IDC_EDITBOX, string, 32); + int p = 0, cnt = 0; + while(string[p] != _T('\0')) { + int c = string[p]; + if((0x81 <= c && c <= 0x9f) || 0xe0 <= c) { + p++; + } + p++; + cnt++; + } + if(cnt == 0 || cnt > tvar_length) { + EnableWindow(GetDlgItem(hDlg, IDOK), FALSE); + } else { + EnableWindow(GetDlgItem(hDlg, IDOK), TRUE); + } + } + break; + + case IDOK: + GetDlgItemText(hDlg, IDC_EDITBOX, string, 32); + strcpy(tvar[tvar_index - 1], string); + EndDialog(hDlg, IDOK); + break; + default: + return FALSE; + } + break; + + default: + return FALSE; + } + return TRUE; +} + diff --git a/src/sys/nact_input.cpp b/src/sys/nact_input.cpp new file mode 100644 index 0000000..1dbeb4b --- /dev/null +++ b/src/sys/nact_input.cpp @@ -0,0 +1,62 @@ +/* + ALICE SOFT SYSTEM 3 for Win32 + + [ NACT - input ] +*/ + +#include "nact.h" + +extern HWND g_hwnd; + +uint8 NACT::get_key() +{ + uint8 val = 0; + + // キーボード&マウス + if(key[VK_UP ] || key[VK_NUMPAD8]) val |= 0x01; + if(key[VK_DOWN ] || key[VK_NUMPAD2]) val |= 0x02; + if(key[VK_LEFT ] || key[VK_NUMPAD4]) val |= 0x04; + if(key[VK_RIGHT ] || key[VK_NUMPAD6]) val |= 0x08; + if(key[VK_RETURN] || key[VK_LBUTTON]) val |= 0x10; + if(key[VK_SPACE ] || key[VK_RBUTTON]) val |= 0x20; + if(key[VK_ESCAPE] ) val |= 0x40; + if(key[VK_TAB ] ) val |= 0x80; + + // マウス移動で方向入力はサポートしない + + // ジョイスティック + 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; + } + } + + return val; +} + +void NACT::get_cursor(int* x, int* y) +{ + POINT pt; + GetCursorPos(&pt); + ScreenToClient(g_hwnd, &pt); + *x = pt.x; + *y = pt.y; +} + +void NACT::set_cursor(int x, int y) +{ + POINT pt; + pt.x = x; + pt.y = y; + ClientToScreen(g_hwnd, &pt); + SetCursorPos(pt.x, pt.y); +} + diff --git a/src/sys/nact_sys1.cpp b/src/sys/nact_sys1.cpp new file mode 100644 index 0000000..1e0e1bf --- /dev/null +++ b/src/sys/nact_sys1.cpp @@ -0,0 +1,1588 @@ +/* + 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 "crc32.h" +#include "../fileio.h" + +// メニューの改ページ +#if defined(_INTRUDER) +#define MENU_MAX 6 +#else +#define MENU_MAX 11 +#endif + +#define WAIT(tm) \ +{ \ + DWORD dwTime = timeGetTime() + (tm); \ + for(;;) { \ + if(params.terminate) { \ + return; \ + } \ + if(dwTime <= timeGetTime()) { \ + break; \ + } \ + Sleep(10); \ + } \ +} + +#define WAIT_KEYQUIT(tm) \ +{ \ + DWORD dwTime = timeGetTime() + (tm); \ + for(;;) { \ + if(params.terminate) { \ + return; \ + } \ + if(get_key()) { \ + for(;;) { \ + if(params.terminate) { \ + return; \ + } \ + if(!get_key()) { \ + break; \ + } \ + if(dwTime <= timeGetTime()) { \ + break; \ + } \ + Sleep(10); \ + } \ + break; \ + } \ + if(dwTime <= timeGetTime()) { \ + break; \ + } \ + Sleep(10); \ + } \ +} + +extern _TCHAR g_root[_MAX_PATH]; +extern HWND g_hwnd; + +void NACT::opening() +{ +#if defined(_CRESCENT) + mako->play_music(2); + ags->load_cg(1, -1); + WAIT(3000); + ags->load_cg(81, -1); +#elif defined(_INTRUDER) + ags->load_cg(77, -1); + WAIT(1667) + ags->load_cg(74, -1); +#elif defined(_VAMPIRE) + mako->play_music(4); + ags->load_cg(3, -1); + WAIT(2000) + ags->load_cg(38, -1); + cmd_a(); + ags->draw_box(0); +#endif +} + +void NACT::cmd_calc() +{ + int index = getd(); + if(0x80 <= index && index <= 0xbf) { + index &= 0x3f; + } else { + index = ((index & 0x3f) << 8) | getd(); + } + var[index] = cali(); + +#if defined(_DEBUG_CONSOLE) + char log[128]; + sprintf_s(log, 128, "\n!var[%d]:%d!", index, var[index]); + output_console(log); +#endif +} + +void NACT::cmd_branch() +{ + int condition = cali(); + int nest = 0; + bool set_menu = false; + + if(!condition) { + for(;;) { + 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 == '@') { + getd(); + getd(); + } else if(cmd == '\\') { + getd(); + getd(); + } else if(cmd == '&') { + cali(); + } else if(cmd == '%') { + cali(); + } else if(cmd == '$') { + if(!set_menu) { + getd(); + getd(); + set_menu = true; + } else { + set_menu = false; + } + } else if(cmd == '[') { + getd(); + getd(); + getd(); + getd(); + } else if(cmd == ':') { + cali(); + getd(); + getd(); + getd(); + getd(); + } 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 == 0x20 || (0xa1 <= cmd && cmd <= 0xdd)) { + // message (1 byte) + } else if((0x81 <= cmd && cmd <= 0x9f) || 0xe0 <= cmd) { + // message (2 bytes) + getd(); + } else { + fatal_error = true; + break; + } + } + } + +#if defined(_DEBUG_CONSOLE) + char log[128]; + sprintf_s(log, 128, "\n{%d:", condition); + output_console(log); +#endif +} + +void NACT::cmd_label_jump() +{ + int next_addr = getw(); + scenario_addr = next_addr; + +#if defined(_DEBUG_CONSOLE) + char log[128]; + sprintf_s(log, 128, "\n@%x:", next_addr); + output_console(log); +#endif +} + +void NACT::cmd_label_call() +{ + int next_addr = getw(); + +#if defined(_DEBUG_CONSOLE) + char log[128]; + sprintf_s(log, 128, "\n\\%x:", next_addr); + output_console(log); +#endif + + 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::cmd_page_jump() +{ + int next_page = cali(); + load_scenario(next_page); + scenario_page = next_page; + scenario_addr = 2; + +#if defined(_DEBUG_CONSOLE) + char log[128]; + sprintf_s(log, 128, "\n&%d:", next_page); + output_console(log); +#endif +} + +void NACT::cmd_page_call() +{ + int next_page = cali(), next_addr; + +#if defined(_DEBUG_CONSOLE) + char log[128]; + sprintf_s(log, 128, "\n%%%d:", next_page); + output_console(log); +#endif + + 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::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; + +#if defined(_DEBUG_CONSOLE) + char log[128]; + sprintf_s(log, 128, "$"); + output_console(log); +#endif + } 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; + +#if defined(_DEBUG_CONSOLE) + char log[128]; + sprintf_s(log, 128, "\n$%x,", menu_addr[menu_index - 1]); + output_console(log); +#endif + } +} + +void NACT::cmd_open_menu() +{ +#if defined(_DEBUG_CONSOLE) + char log[128]; + sprintf_s(log, 128, "\n]"); + output_console(log); +#endif + + if(!menu_index) { + scenario_addr = scenario_data[0] | (scenario_data[1] << 8); + return; + } + +#if defined(_DPS) + if(!text_refresh) { + cmd_a(); + } +#endif + + // クリック中の間は待機 + for(;;) { + if(params.terminate) { + return; + } +// if(get_key() != 32) { + if(!get_key()) { + break; + } + Sleep(10); + } + + // メニュー表示 + ags->open_menu_window(menu_window); + int current_index = 0; + + // マウス移動 + 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; + set_cursor(mx, my); + + // メニュー選択 + for(;;) { + // 入力待機 + int val = 0, current_mx = mx, current_my = my; + for(;;) { + if(params.terminate) { + return; + } + if(val = get_key()) { + Sleep(100); + break; + } + get_cursor(¤t_mx, ¤t_my); + if(abs(my - current_my) > 3) { + break; + } + Sleep(10); + } + if(val) { + for(;;) { + if(params.terminate) { + return; + } + if(!get_key()) { + break; + } + Sleep(10); + } + } + + if(val == 0) { + // マウス操作 + mx = current_mx; my = current_my; + int index = (my - sy) / height; + if(sx <= mx && mx <= ex && 0 <= index && index < menu_index) { + current_index = index; + ags->redraw_menu_window(menu_window, current_index); + } + } else if(val == 1 || val == 2 || val == 4 || val == 8) { + if(val == 1) { + current_index = current_index ? current_index - 1 : menu_index - 1; + } else if(val == 2) { + current_index = (current_index < menu_index - 1) ? current_index + 1 : 0; + } else if(val == 4) { + current_index = 0; + } else if(val == 8) { + current_index = menu_index - 1; + } + ags->redraw_menu_window(menu_window, current_index); + } else if(val == 16) { + 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); + } + + if(current_index != -1) { + scenario_addr = menu_addr[current_index]; + } + menu_index = 0; +} + +void NACT::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; + +#if defined(_DEBUG_CONSOLE) + char log[128]; + sprintf_s(log, 128, "\n[%x,%s,%s:", addr, caption_verb[verb], caption_obj[obj]); + output_console(log); +#endif +} + +void NACT::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; + +#if defined(_DEBUG_CONSOLE) + char log[128]; + sprintf_s(log, 128, "\n:%d,%x,%s,%s:", condition, addr, caption_verb[verb], caption_obj[obj]); + output_console(log); +#endif +} + +void NACT::cmd_open_verb() +{ + // 動詞メニューの表示 +#if defined(_DEBUG_CONSOLE) + char log[128]; + sprintf_s(log, 128, "\nopen verb-obj menu"); + output_console(log); +#endif + 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("次のページ"); + id[index++] = -1; + ags->menu_dest_y += ags->menu_font_size + 2; + } + ags->draw_menu = false; + + // クリック中の間は待機 + for(;;) { + if(params.terminate) { + return; + } +// if(get_key() != 32) { + if(!get_key()) { + break; + } + Sleep(10); + } + + // メニュー表示 + ags->open_menu_window(menu_window); + int current_index = 0; + + // マウス移動 + 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; + set_cursor(mx, my); + + // メニュー選択 + for(;;) { + // 入力待機 + int val = 0, current_mx = mx, current_my = my; + for(;;) { + if(params.terminate) { + return; + } + if(val = get_key()) { + Sleep(100); + break; + } + get_cursor(¤t_mx, ¤t_my); + if(abs(my - current_my) > 3) { + break; + } + Sleep(10); + } + if(val) { + for(;;) { + if(params.terminate) { + return; + } + if(!get_key()) { + break; + } + Sleep(10); + } + } + + if(val == 0) { + // マウス操作 + mx = current_mx; my = current_my; + int mindex = (my - sy) / height; + if(sx <= mx && mx <= ex && 0 <= mindex && mindex < index) { + current_index = mindex; + ags->redraw_menu_window(menu_window, current_index); + } + } else if(val == 1 || val == 2 || val == 4 || val == 8) { + if(val == 1) { + current_index = current_index ? current_index - 1 : index - 1; + } else if(val == 2) { + current_index = (current_index < index - 1) ? current_index + 1 : 0; + } else if(val == 4) { + current_index = 0; + } else if(val == 8) { + current_index = index - 1; + } + ags->redraw_menu_window(menu_window, current_index); + } else if(val == 16) { + 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); + } + + if(current_index == -1) { + scenario_addr = scenario_data[0] | (scenario_data[1] << 8); + } else if(id[current_index] == -1) { + goto top; + } else { + cmd_open_obj(id[current_index]); + } + menu_index = 0; +} + +void NACT::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("戻る"); + 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("戻る"); + 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("次のページ"); + id[index++] = -1; + ags->menu_dest_y += ags->menu_font_size + 2; + } + ags->draw_menu = false; + + // クリック中の間は待機 + for(;;) { + if(params.terminate) { + return; + } +// if(get_key() != 32) { + if(!get_key()) { + break; + } + Sleep(10); + } + + // メニュー表示 + ags->open_menu_window(menu_window); + int current_index = 0; + + // マウス移動 + 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; + set_cursor(mx, my); + + // メニュー選択 + for(;;) { + // 入力待機 + int val = 0, current_mx = mx, current_my = my; + for(;;) { + if(params.terminate) { + return; + } + if(val = get_key()) { + Sleep(100); + break; + } + get_cursor(¤t_mx, ¤t_my); + if(abs(my - current_my) > 3) { + break; + } + Sleep(10); + } + if(val) { + for(;;) { + if(params.terminate) { + return; + } + if(!get_key()) { + break; + } + Sleep(10); + } + } + + if(val == 0) { + // マウス操作 + mx = current_mx; my = current_my; + int mindex = (my - sy) / height; + if(sx <= mx && mx <= ex && 0 <= mindex && mindex < index) { + current_index = mindex; + ags->redraw_menu_window(menu_window, current_index); + } + } else if(val == 1 || val == 2 || val == 4 || val == 8) { + if(val == 1) { + current_index = current_index ? current_index - 1 : index - 1; + } else if(val == 2) { + current_index = (current_index < index - 1) ? current_index + 1 : 0; + } else if(val == 4) { + current_index = 0; + } else if(val == 8) { + current_index = index - 1; + } + ags->redraw_menu_window(menu_window, current_index); + } else if(val == 16) { + 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); + } + + if(current_index == -1) { + scenario_addr = scenario_data[0] | (scenario_data[1] << 8); + } else if(id[current_index] == -1) { + goto top; + } else { + scenario_addr = addr[id[current_index]]; + } +} + +void NACT::cmd_a() +{ +#if defined(_DEBUG_CONSOLE) + char log[128]; + sprintf_s(log, 128, "A\n"); + output_console(log); +#endif + + if(!text_skip_enb) { + // Pushマークの表示 + if(show_push) { + ags->draw_push(text_window); + } + + // キーが押されて離されるまで待機 + for(;;) { + if(params.terminate) { + return; + } + if(get_key()) { + break; + } + Sleep(10); + } + Sleep(100); + for(;;) { + if(params.terminate) { + return; + } + if(!(get_key() & 0x18)) { + break; + } + Sleep(10); + } + } + + // ウィンドウ更新 + ags->clear_text_window(text_window, true); + +#if defined(_DPS) + text_refresh = true; +#endif +} + +void NACT::cmd_b() +{ + // 未使用 +} + +void NACT::cmd_d() +{ + // 未使用 +} + +void NACT::cmd_e() +{ + // 未使用 +} + +void NACT::cmd_f() +{ +#if defined(_DEBUG_CONSOLE) + char log[128]; + sprintf_s(log, 128, "\nF"); + output_console(log); +#endif + + scenario_addr = 2; +} + +void NACT::cmd_g() +{ + int page = getd(); + +#if defined(_DEBUG_CONSOLE) + char log[128]; + sprintf_s(log, 128, "\nG %d:", page); + output_console(log); +#endif + +#if defined(_INTRUDER) + page = (page == 97) ? 96 : (page == 98) ? 97 : page; +#endif + + ags->load_cg(page, -1); + +#if defined(_INTRUDER) + if(page == 94) { + WAIT(400) + } + if(page == 81 || page == 82) { + map_page = page; + } +#endif +} + +void NACT::cmd_h() +{ + // 未使用 +} + +void NACT::cmd_i() +{ + // 未使用 +} + +void NACT::cmd_j() +{ + // 未使用 +} + +void NACT::cmd_k() +{ + // 未使用 +} + +void NACT::cmd_l() +{ + int index = getd(); + +#if defined(_DEBUG_CONSOLE) + char log[128]; + sprintf_s(log, 128, "\nL %d:", index); + output_console(log); +#endif + + if(1 <= index && index <= 26) { + // ASLEEP_A.DAT - ASLEEP_Z.DAT + _TCHAR path[_MAX_PATH], file_path[_MAX_PATH]; + _tcscpy_s(path, _MAX_PATH, _T("ASLEEP_A.DAT")); + path[7] = _T('A') + index - 1; + _stprintf_s(file_path, _MAX_PATH, _T("%s%s"), g_root, path); + + FILEIO* fio = new FILEIO(); + if(fio->Fopen(file_path, FILEIO_READ_BINARY)) { + 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; + +// ags->old_text_font_size = 0; +// ags->old__menu_font_fize = 0; + mako->play_music(next_music); + } + delete fio; + } +} + +void NACT::cmd_m() +{ + // 未使用 +} + +void NACT::cmd_n() +{ + // 未使用 +} + +void NACT::cmd_o() +{ + // 未使用 +} + +void NACT::cmd_p() +{ + int param = getd(); + + ags->text_font_color = (uint8)((param & 0x7) + 16); + +#if defined(_DEBUG_CONSOLE) + char log[128]; + sprintf_s(log, 128, "\nP %d:", param); + output_console(log); +#endif +} + +#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::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(); + +#if defined(_DEBUG_CONSOLE) + char log[128]; + sprintf_s(log, 128, "\nQ %d:", index); + output_console(log); +#endif + + if(1 <= index && index <= 26) { + // ASLEEP_A.DAT - ASLEEP_Z.DAT + _TCHAR path[_MAX_PATH], file_path[_MAX_PATH]; + _tcscpy_s(path, _MAX_PATH, _T("ASLEEP_A.DAT")); + path[7] = _T('A') + index - 1; + _stprintf_s(file_path, _MAX_PATH, _T("%s%s"), g_root, path); + + FILEIO* fio = new FILEIO(); + if(fio->Fopen(file_path, FILEIO_WRITE_BINARY)) { + 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::cmd_r() +{ +#if defined(_DEBUG_CONSOLE) + char log[128]; + sprintf_s(log, 128, "R\n"); + output_console(log); +#endif + + // ウィンドウの表示範囲外の場合は改ページ + if(ags->return_text_line(text_window)) { + cmd_a(); + } +} + +void NACT::cmd_s() +{ + int page = getd(); + +#if defined(_DEBUG_CONSOLE) + char log[128]; + sprintf_s(log, 128, "\nS %d:", page); + output_console(log); +#endif + + if(page) { + mako->play_music(page); + } else { + mako->stop_music(); + } +} + +void NACT::cmd_t() +{ + // 未使用 +} + +void NACT::cmd_u() +{ + int page = getd(); + int transparent = getd(); + +#if defined(_DEBUG_CONSOLE) + char log[128]; + sprintf_s(log, 128, "\nU %d,%d:", page, transparent); + output_console(log); +#endif + +#if defined(_INTRUDER) + ags->load_cg(page, 11); + + if(page == 5) { + WAIT(400) + } +#else + ags->load_cg(page, transparent); +#endif +} + +void NACT::cmd_v() +{ + // 未使用 +} + +void NACT::cmd_w() +{ + // 未使用 +} + +void NACT::cmd_x() +{ + int index = getd(); + +#if defined(_DEBUG_CONSOLE) + char log[128]; + sprintf_s(log, 128, "\nX %d:", index); + output_console(log); +#endif + + if(1 <= index && index <= 10) { + ags->draw_text(tvar[index - 1]); + } +} + +void NACT::cmd_y() +{ + int cmd = cali(); + int param = cali(); + +#if defined(_DEBUG_CONSOLE) + char log[128]; + sprintf_s(log, 128, "\nY %d,%d:", cmd, param); + output_console(log); +#endif + +#if defined(_BUNKASAI) || defined(_CRESCENT) || defined(_DPS) || defined(_FUKEI) || defined(_TENGU) + 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 defined(_CRESCENT) + for(int i = 39; i <= 48; i++) { +#elif defined(_DPS) + for(int i = 0; i <= 20; i++) { +#else + for(int i = 0; i <= 16; i++) { +#endif + var[i] = 0; + } + break; + case 3: + WAIT(param * 1000 / 60) + break; + case 4: + RND = (param == 0 || param == 1) ? 0 : random(param); + break; +#if defined(_DPS) + case 7: + if(param == 1) { + ags->box_fill(0, 40, 8, 598, 270, 0); + } + break; +#endif +#if defined(_TENGU) + case 130: + { + 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; +#endif + case 253: + post_quit = false; + fatal_error = true; + break; + case 254: + RND = 0; + break; + case 255: +#if defined(_DPS) + post_quit = false; +#else + post_quit = true; +#endif + fatal_error = true; + break; + } +#elif defined(_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(params.terminate) { + return; + } + if(get_key()) { + break; + } + Sleep(10); + } + Sleep(100); + for(;;) { + if(params.terminate) { + return; + } + if(!(get_key() & 0x18)) { + break; + } + Sleep(10); + } + 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; + } +#endif +} + +void NACT::cmd_z() +{ +#if defined(_CRESCENT) + cmd_y(); + return; +#endif + int cmd = cali(); + int param = cali(); + +#if defined(_DEBUG_CONSOLE) + char log[128]; + sprintf_s(log, 128, "\nZ %d,%d:", cmd, param); + output_console(log); +#endif + +#if defined(_INTRUDER) + if(cmd == 1 && 1 <= param && param <= 4) { + char* buf[4] = {"<", "∧", ">", "∨"}; + + // 矢印を消去する + 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; + } +#elif defined(_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); + } + } +#endif +} + + +// 下位関数 + +uint16 NACT::cali() +{ + uint32 cali[256]; + int p = 1; + fatal_error = true; + + 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) { + fatal_error = false; + } + p = 0; + } + } + return (uint16)(cali[1] & 0xffff); +} + +uint16 NACT::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_error = true; + } + if(getd() != 0x7f) { + fatal_error = true; + } + return val; +} + +uint8 NACT::getd() +{ + return scenario_data[scenario_addr++]; +} + +uint16 NACT::getw() +{ + uint16 val = scenario_data[scenario_addr] | (scenario_data[scenario_addr + 1] << 8); + scenario_addr += 2; + return val; +} + diff --git a/src/sys/nact_sys2.cpp b/src/sys/nact_sys2.cpp new file mode 100644 index 0000000..751c9d9 --- /dev/null +++ b/src/sys/nact_sys2.cpp @@ -0,0 +1,1681 @@ +/* + ALICE SOFT SYSTEM2 for Win32 + + Super D.P.S. - Dream Program System + + [ NACT - command ] +*/ + +#include "nact.h" +#include "ags.h" +#include "mako.h" +#include "crc32.h" +#include "../fileio.h" + +#define WAIT(tm) \ +{ \ + DWORD dwTime = timeGetTime() + (tm); \ + for(;;) { \ + if(params.terminate) { \ + return; \ + } \ + if(dwTime <= timeGetTime()) { \ + break; \ + } \ + Sleep(10); \ + } \ +} + +#define WAIT_KEYQUIT(tm) \ +{ \ + DWORD dwTime = timeGetTime() + (tm); \ + for(;;) { \ + if(params.terminate) { \ + return; \ + } \ + if(get_key()) { \ + for(;;) { \ + if(params.terminate) { \ + return; \ + } \ + if(!get_key()) { \ + break; \ + } \ + if(dwTime <= timeGetTime()) { \ + break; \ + } \ + Sleep(10); \ + } \ + break; \ + } \ + if(dwTime <= timeGetTime()) { \ + break; \ + } \ + Sleep(10); \ + } \ +} + +extern _TCHAR g_root[_MAX_PATH]; +extern HWND g_hwnd; + +void NACT::cmd_calc() +{ + int index = getd(); + if(0x80 <= index && index <= 0xbf) { + index &= 0x3f; + } else { + index = ((index & 0x3f) << 8) | getd(); + } + var[index] = cali(); + +#if defined(_DEBUG_CONSOLE) + char log[128]; + sprintf_s(log, 128, "\n!var[%d]:%d!", index, var[index]); + output_console(log); +#endif +} + +void NACT::cmd_branch() +{ + int condition = cali(); + int nest = 0; + bool set_menu = false; + + if(!condition) { + for(;;) { + 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 == '@') { + getd(); + getd(); + } else if(cmd == '\\') { + getd(); + getd(); + } else if(cmd == '&') { + cali(); + } else if(cmd == '%') { + cali(); + } else if(cmd == '$') { + if(!set_menu) { + getd(); + getd(); + set_menu = true; + } else { + set_menu = false; + } + } else if(cmd == '[') { + getd(); + getd(); + getd(); + getd(); + } else if(cmd == ':') { + cali(); + getd(); + getd(); + getd(); + getd(); + } 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(); + } else if(cmd == 'J') { + cali(); + cali(); + } else if(cmd == 'K') { + + } else if(cmd == 'L') { + getd(); + } else if(cmd == 'M') { + for(;;) { + uint8 val = getd(); + if(val == 0x20 || (0xa1 <= val && val <= 0xdd)) { + // message (1 byte) + } else if((0x81 <= val && val <= 0x9f) || 0xe0 <= val) { + // message (2 bytes) + getd(); + } else if(val == ':') { + break; + } + } + } 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') { + getd(); + getd(); + } else if(cmd == 'V') { + cali(); + cali(); + } 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 == 0x20 || (0xa1 <= cmd && cmd <= 0xdd)) { + // message (1 byte) + } else if((0x81 <= cmd && cmd <= 0x9f) || 0xe0 <= cmd) { + // message (2 bytes) + getd(); + } else { + fatal_error = true; + break; + } + } + } + +#if defined(_DEBUG_CONSOLE) + char log[128]; + sprintf_s(log, 128, "\n{%d:", condition); + output_console(log); +#endif +} + +void NACT::cmd_label_jump() +{ + int next_addr = getw(); + scenario_addr = next_addr; + +#if defined(_DEBUG_CONSOLE) + char log[128]; + sprintf_s(log, 128, "\n@%x:", next_addr); + output_console(log); +#endif +} + +void NACT::cmd_label_call() +{ + int next_addr = getw(); + +#if defined(_DEBUG_CONSOLE) + char log[128]; + sprintf_s(log, 128, "\n\\%x:", next_addr); + output_console(log); +#endif + + 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::cmd_page_jump() +{ + int next_page = cali(); + load_scenario(next_page); + scenario_page = next_page; + scenario_addr = 2; + +#if defined(_DEBUG_CONSOLE) + char log[128]; + sprintf_s(log, 128, "\n&%d:", next_page); + output_console(log); +#endif +} + +void NACT::cmd_page_call() +{ + int next_page = cali(), next_addr; + +#if defined(_DEBUG_CONSOLE) + char log[128]; + sprintf_s(log, 128, "\n%%%d:", next_page); + output_console(log); +#endif + + 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::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; + +#if defined(_DEBUG_CONSOLE) + char log[128]; + sprintf_s(log, 128, "$"); + output_console(log); +#endif + } 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; + +#if defined(_DEBUG_CONSOLE) + char log[128]; + sprintf_s(log, 128, "\n$%x,", menu_addr[menu_index - 1]); + output_console(log); +#endif + } +} + +void NACT::cmd_open_menu() +{ +#if defined(_DEBUG_CONSOLE) + char log[128]; + sprintf_s(log, 128, "\n]"); + output_console(log); +#endif + + if(!menu_index) { + scenario_addr = scenario_data[0] | (scenario_data[1] << 8); + return; + } + + // クリック中の間は待機 + for(;;) { + if(params.terminate) { + return; + } +// if(get_key() != 32) { + if(!get_key()) { + break; + } + Sleep(10); + } + + // メニュー表示 + ags->open_menu_window(menu_window); + int current_index = 0; + + // マウス移動 + 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; + set_cursor(mx, my); + + // メニュー選択 + for(;;) { + // 入力待機 + int val = 0, current_mx = mx, current_my = my; + for(;;) { + if(params.terminate) { + return; + } + if(val = get_key()) { + Sleep(100); + break; + } + get_cursor(¤t_mx, ¤t_my); + if(abs(my - current_my) > 3) { + break; + } + Sleep(10); + } + if(val) { + for(;;) { + if(params.terminate) { + return; + } + if(!get_key()) { + break; + } + Sleep(10); + } + } + + if(val == 0) { + // マウス操作 + mx = current_mx; my = current_my; + int index = (my - sy) / height; + if(sx <= mx && mx <= ex && 0 <= index && index < menu_index) { + current_index = index; + ags->redraw_menu_window(menu_window, current_index); + } + } else if(val == 1 || val == 2 || val == 4 || val == 8) { + if(val == 1) { + current_index = current_index ? current_index - 1 : menu_index - 1; + } else if(val == 2) { + current_index = (current_index < menu_index - 1) ? current_index + 1 : 0; + } else if(val == 4) { + current_index = 0; + } else if(val == 8) { + current_index = menu_index - 1; + } + ags->redraw_menu_window(menu_window, current_index); + } else if(val == 16) { + 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); + } + + if(current_index != -1) { + scenario_addr = menu_addr[current_index]; + } + menu_index = 0; +} + +void NACT::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; + +#if defined(_DEBUG_CONSOLE) + char log[128]; + sprintf_s(log, 128, "\n[%x,%s,%s:", addr, caption_verb[verb], caption_obj[obj]); + output_console(log); +#endif +} + +void NACT::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; + +#if defined(_DEBUG_CONSOLE) + char log[128]; + sprintf_s(log, 128, "\n:%d,%x,%s,%s:", condition, addr, caption_verb[verb], caption_obj[obj]); + output_console(log); +#endif +} + +void NACT::cmd_open_verb() +{ + // 動詞メニューの表示 +#if defined(_DEBUG_CONSOLE) + char log[128]; + sprintf_s(log, 128, "\nopen verb-obj menu"); + output_console(log); +#endif + 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; + + // クリック中の間は待機 + for(;;) { + if(params.terminate) { + return; + } +// if(get_key() != 32) { + if(!get_key()) { + break; + } + Sleep(10); + } + + // メニュー表示 + ags->open_menu_window(menu_window); + int current_index = 0; + + // マウス移動 + 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; + set_cursor(mx, my); + + // メニュー選択 + for(;;) { + // 入力待機 + int val = 0, current_mx = mx, current_my = my; + for(;;) { + if(params.terminate) { + return; + } + if(val = get_key()) { + Sleep(100); + break; + } + get_cursor(¤t_mx, ¤t_my); + if(abs(my - current_my) > 3) { + break; + } + Sleep(10); + } + if(val) { + for(;;) { + if(params.terminate) { + return; + } + if(!get_key()) { + break; + } + Sleep(10); + } + } + + if(val == 0) { + // マウス操作 + mx = current_mx; my = current_my; + int mindex = (my - sy) / height; + if(sx <= mx && mx <= ex && 0 <= mindex && mindex < index) { + current_index = mindex; + ags->redraw_menu_window(menu_window, current_index); + } + } else if(val == 1 || val == 2 || val == 4 || val == 8) { + if(val == 1) { + current_index = current_index ? current_index - 1 : index - 1; + } else if(val == 2) { + current_index = (current_index < index - 1) ? current_index + 1 : 0; + } else if(val == 4) { + current_index = 0; + } else if(val == 8) { + current_index = index - 1; + } + ags->redraw_menu_window(menu_window, current_index); + } else if(val == 16) { + 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); + } + + if(current_index == -1) { + scenario_addr = scenario_data[0] | (scenario_data[1] << 8); + } else { + cmd_open_obj(id[current_index]); + } + menu_index = 0; +} + +void NACT::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("戻る"); + id[index++] = 0; + ags->menu_dest_y += ags->menu_font_size + 2; + ags->draw_menu = false; + + // クリック中の間は待機 + for(;;) { + if(params.terminate) { + return; + } +// if(get_key() != 32) { + if(!get_key()) { + break; + } + Sleep(10); + } + + // メニュー表示 + ags->open_menu_window(menu_window); + int current_index = 0; + + // マウス移動 + 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; + set_cursor(mx, my); + + // メニュー選択 + for(;;) { + // 入力待機 + int val = 0, current_mx = mx, current_my = my; + for(;;) { + if(params.terminate) { + return; + } + if(val = get_key()) { + Sleep(100); + break; + } + get_cursor(¤t_mx, ¤t_my); + if(abs(my - current_my) > 3) { + break; + } + Sleep(10); + } + if(val) { + for(;;) { + if(params.terminate) { + return; + } + if(!get_key()) { + break; + } + Sleep(10); + } + } + + if(val == 0) { + // マウス操作 + mx = current_mx; my = current_my; + int mindex = (my - sy) / height; + if(sx <= mx && mx <= ex && 0 <= mindex && mindex < index) { + current_index = mindex; + ags->redraw_menu_window(menu_window, current_index); + } + } else if(val == 1 || val == 2 || val == 4 || val == 8) { + if(val == 1) { + current_index = current_index ? current_index - 1 : index - 1; + } else if(val == 2) { + current_index = (current_index < index - 1) ? current_index + 1 : 0; + } else if(val == 4) { + current_index = 0; + } else if(val == 8) { + current_index = index - 1; + } + ags->redraw_menu_window(menu_window, current_index); + } else if(val == 16) { + 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); + } + + if(current_index == -1) { + scenario_addr = scenario_data[0] | (scenario_data[1] << 8); + } else { + scenario_addr = addr[id[current_index]]; + } +} + +void NACT::cmd_a() +{ +#if defined(_DEBUG_CONSOLE) + char log[128]; + sprintf_s(log, 128, "A\n"); + output_console(log); +#endif + + if(!text_skip_enb) { + // Pushマークの表示 + if(show_push) { + ags->draw_push(text_window); + } + + // キーが押されて離されるまで待機 + for(;;) { + if(params.terminate) { + return; + } + if(get_key()) { + break; + } + Sleep(10); + } + Sleep(100); + for(;;) { + if(params.terminate) { + return; + } + if(!(get_key() & 0x18)) { + break; + } + Sleep(10); + } + } + + // ウィンドウ更新 + ags->clear_text_window(text_window, true); +} + +void NACT::cmd_b() +{ + int cmd = cali(); + int index = cali(); + int p1 = cali(); + int p2 = cali(); + int p3 = cali(); + int p4 = cali(); + int p5 = cali(); + +#if defined(_DEBUG_CONSOLE) + char log[128]; + sprintf_s(log, 128, "\nB %d,%d,%d,%d,%d,%d,%d:", cmd, index, p1, p2, p3, p4, p5); + output_console(log); +#endif + + if(cmd == 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 == 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(p5 == 0) { + // ウィンドウ退避 +// if(crc32 == 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::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(); + +#if defined(_DEBUG_CONSOLE) + char log[128]; + sprintf_s(log, 128, "\nD %d,%d,%d,%d,%d,%d,%d,%d:", p1, p2, p3, p4, p5, p6, p7, p8); + output_console(log); +#endif +} + +void NACT::cmd_e() +{ + int p1 = cali(); + int p2 = cali(); + int p3 = cali(); + +#if defined(_DEBUG_CONSOLE) + char log[128]; + sprintf_s(log, 128, "\nE %d,%d,%d:", p1, p2, p3); + output_console(log); +#endif +} + +void NACT::cmd_f() +{ +#if defined(_DEBUG_CONSOLE) + char log[128]; + sprintf_s(log, 128, "\nF"); + output_console(log); +#endif + + scenario_addr = 2; +} + +void NACT::cmd_g() +{ + int page = cali(); + +#if defined(_DEBUG_CONSOLE) + char log[128]; + sprintf_s(log, 128, "\nG %d:", page); + output_console(log); +#endif + + if(crc32 == CRC32_SDPS_TONO || crc32 == CRC32_SDPS_KAIZOKU) { + if(20 <= page && page <= 100) { + page--; + } + } + ags->load_cg(page, -1); +} + +void NACT::cmd_h() +{ + int length = getd(); + int val = cali(); + +#if defined(_DEBUG_CONSOLE) + char log[128]; + sprintf_s(log, 128, "\nH %d,%d:", length, val); + output_console(log); +#endif + + // 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::cmd_i() +{ + int p1 = cali(); + int p2 = cali(); + int p3 = getd(); + +#if defined(_DEBUG_CONSOLE) + char log[128]; + sprintf_s(log, 128, "\nI %d,%d,%d:", p1, p2, p3); + output_console(log); +#endif +} + +void NACT::cmd_j() +{ + int p1 = cali(); + int p2 = cali(); + +#if defined(_DEBUG_CONSOLE) + char log[128]; + sprintf_s(log, 128, "\nJ %d,%d:", p1, p2); + output_console(log); +#endif +} + +void NACT::cmd_k() +{ + // 未使用 + cmd_r(); +} + +void NACT::cmd_l() +{ + int index = getd(); + +#if defined(_DEBUG_CONSOLE) + char log[128]; + sprintf_s(log, 128, "\nL %d:", index); + output_console(log); +#endif + + if(1 <= index && index <= 26) { + // ASLEEP_A.DAT - ASLEEP_Z.DAT + _TCHAR path[_MAX_PATH], file_path[_MAX_PATH]; + _tcscpy_s(path, _MAX_PATH, _T("ASLEEP_A.DAT")); + path[7] = _T('A') + index - 1; + _stprintf_s(file_path, _MAX_PATH, _T("%s%s"), g_root, path); + + FILEIO* fio = new FILEIO(); + if(fio->Fopen(file_path, FILEIO_READ_BINARY)) { + 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; + +// ags->old_text_font_size = 0; +// ags->old__menu_font_fize = 0; + mako->play_music(next_music); + } + delete fio; + } +} + +void NACT::cmd_m() +{ + char string[22]; + int d, p = 0; + + while((d = getd()) != ':') { + if((0x81 <= d && d <= 0x9f) || 0xe0 <= d) { + // 2bytes + string[p++] = d; + string[p++] = getd(); + } else { + string[p++] = d; + } + } + string[p] = '\0'; + +#if defined(_DEBUG_CONSOLE) + char log[128]; + sprintf_s(log, 128, "\nM %s:", string); + output_console(log); +#endif + + if(1 <= tvar_index && tvar_index <= 10) { + memcpy(tvar[tvar_index - 1], string, 22); + } +} + +void NACT::cmd_n() +{ + int p1 = cali(); + int p2 = cali(); + +#if defined(_DEBUG_CONSOLE) + char log[128]; + sprintf_s(log, 128, "\nN %d,%d:", p1, p2); + output_console(log); +#endif +} + +void NACT::cmd_o() +{ + int st = cali(); + int width = cali(); + int height = cali(); + +#if defined(_DEBUG_CONSOLE) + char log[128]; + sprintf_s(log, 128, "\nO %d,%d,%d:", st, width, height); + output_console(log); +#endif + + // white mesh + int sx = (st % 80) * 8; + int sy = (int)(st / 80); + ags->draw_mesh(sx, sy, width, height); +} + +void NACT::cmd_p() +{ + int param = getd(); + + ags->text_font_color = (uint8)((param & 0x7) + 16); + +#if defined(_DEBUG_CONSOLE) + char log[128]; + sprintf_s(log, 128, "\nP %d:", param); + output_console(log); +#endif +} + +#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::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(); + +#if defined(_DEBUG_CONSOLE) + char log[128]; + sprintf_s(log, 128, "\nQ %d:", index); + output_console(log); +#endif + + if(1 <= index && index <= 26) { + // ASLEEP_A.DAT - ASLEEP_Z.DAT + _TCHAR path[_MAX_PATH], file_path[_MAX_PATH]; + _tcscpy_s(path, _MAX_PATH, _T("ASLEEP_A.DAT")); + path[7] = _T('A') + index - 1; + _stprintf_s(file_path, _MAX_PATH, _T("%s%s"), g_root, path); + + FILEIO* fio = new FILEIO(); + if(fio->Fopen(file_path, FILEIO_WRITE_BINARY)) { + 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::cmd_r() +{ +#if defined(_DEBUG_CONSOLE) + char log[128]; + sprintf_s(log, 128, "R\n"); + output_console(log); +#endif + + // ウィンドウの表示範囲外の場合は改ページ + if(ags->return_text_line(text_window)) { + cmd_a(); + } +} + +void NACT::cmd_s() +{ + int page = getd(); + +#if defined(_DEBUG_CONSOLE) + char log[128]; + sprintf_s(log, 128, "\nS %d:", page); + output_console(log); +#endif + + if(page) { + mako->play_music(page); + } else { + mako->stop_music(); + } +} + +void NACT::cmd_t() +{ + int p1 = cali(); + int p2 = cali(); + int p3 = cali(); + +#if defined(_DEBUG_CONSOLE) + char log[128]; + sprintf_s(log, 128, "\nT %d,%d,%d:", p1, p2, p3); + output_console(log); +#endif +} + +void NACT::cmd_u() +{ + int page = getd(); + int transparent = getd(); + +#if defined(_DEBUG_CONSOLE) + char log[128]; + sprintf_s(log, 128, "\nU %d,%d:", page, transparent); + output_console(log); +#endif + +#if defined(_INTRUDER) + ags->load_cg(page, 11); + + if(page == 5) { + WAIT(400) + } +#else + ags->load_cg(page, transparent); +#endif +} + +void NACT::cmd_v() +{ + int p1 = cali(); + int p2 = cali(); + +#if defined(_DEBUG_CONSOLE) + char log[128]; + sprintf_s(log, 128, "\nV %d,%d:", p1, p2); + output_console(log); +#endif +} + +void NACT::cmd_w() +{ + int p1 = cali(); + int p2 = cali(); + int p3 = cali(); + int p4 = cali(); + +#if defined(_DEBUG_CONSOLE) + char log[128]; + sprintf_s(log, 128, "\nW %d,%d,%d,%d:", p1, p2, p3, p4); + output_console(log); +#endif +} + +void NACT::cmd_x() +{ + int index = getd(); + +#if defined(_DEBUG_CONSOLE) + char log[128]; + sprintf_s(log, 128, "\nX %d:", index); + output_console(log); +#endif + + if(1 <= index && index <= 10) { + ags->draw_text(tvar[index - 1]); + } +} + +void NACT::cmd_y() +{ + int cmd = cali(); + int param = cali(); + +#if defined(_DEBUG_CONSOLE) + char log[128]; + sprintf_s(log, 128, "\nY %d,%d:", cmd, param); + output_console(log); +#endif + + 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: + { + DWORD dwTime = timeGetTime() + param * 1000 / 60; + for(;;) { + if(params.terminate) { + return; + } +// RND = get_key(); +// if(RND && wait_keydown) { +// break; +// } + if(dwTime <= timeGetTime()) { + break; + } + Sleep(10); + } + } + break; + case 4: + RND = (param == 0 || param == 1) ? 0 : random(param); + break; + case 7: + if(crc32 != 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 40: + case 42: + { + DWORD dwStart = timeGetTime(); + for(int i = 0; i < 16; i++) { + ags->fade_in(i); + DWORD dwTime = dwStart + param * 1000 / 60 * i; + for(;;) { + if(params.terminate) { + return; + } + if(dwTime <= timeGetTime()) { + break; + } + Sleep(0); + } + } + } + break; + case 41: + case 43: + { + DWORD dwStart = timeGetTime(); + for(int i = 0; i < 16; i++) { + ags->fade_out(i, (cmd == 41) ? false : true); + DWORD dwTime = dwStart + param * 1000 / 60 * i; + for(;;) { + if(params.terminate) { + return; + } + if(dwTime <= timeGetTime()) { + break; + } + Sleep(0); + } + } + } + break; + case 221: + case 222: + case 223: + case 224: + case 225: + case 226: + case 227: + case 228: + case 229: + if(1 <= param && param <= 10) { + char string[22]; + int len = cmd - 220, p = 0, q = 0; + uint8 d; + while((d = (uint8)tvar[param - 1][p]) != '\0') { + if((0x81 <= d && d <= 0x9f) || 0xe0 <= d) { + string[p++] = tvar[param - 1][p]; + } + string[p++] = tvar[param - 1][p]; + q++; + } + for(int i = q; i < len; i++) { + string[p++] = 0x20; + } + string[p] = '\0'; + ags->draw_text(string); + } + break; + case 252: + RND = 8; + 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::cmd_z() +{ + int cmd = cali(); + int param = cali(); + +#if defined(_DEBUG_CONSOLE) + char log[128]; + sprintf_s(log, 128, "\nZ %d,%d:", cmd, param); + output_console(log); +#endif + +// Z1 +// Z2 +// Z3 +// Z4 +// Z5 +} + + +// 下位関数 + +uint16 NACT::cali() +{ + uint32 cali[256]; + int p = 1; + fatal_error = true; + + 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) { + fatal_error = false; + } + p = 0; + } + } + return (uint16)(cali[1] & 0xffff); +} + +uint16 NACT::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_error = true; + } + if(getd() != 0x7f) { + fatal_error = true; + } + return val; +} + +uint8 NACT::getd() +{ + return scenario_data[scenario_addr++]; +} + +uint16 NACT::getw() +{ + uint16 val = scenario_data[scenario_addr] | (scenario_data[scenario_addr + 1] << 8); + scenario_addr += 2; + return val; +} + diff --git a/src/sys/nact_sys3.cpp b/src/sys/nact_sys3.cpp new file mode 100644 index 0000000..c5b39ee --- /dev/null +++ b/src/sys/nact_sys3.cpp @@ -0,0 +1,1965 @@ +/* + ALICE SOFT SYSTEM 3 for Win32 + + [ NACT - command ] +*/ + +#if defined(_SYSTEM1) +#include "../res1/resource.h" +#elif defined(_SYSTEM2) +#include "../res2/resource.h" +#else +#include "../res3/resource.h" +#endif + +#include "nact.h" +#include "ags.h" +#include "mako.h" +#include "crc32.h" +#include "../fileio.h" + +extern _TCHAR g_root[_MAX_PATH]; +extern HINSTANCE g_hinst; +extern HWND g_hwnd; + +void NACT::cmd_calc() +{ + int index = getd(); + if(0x80 <= index && index <= 0xbf) { + index &= 0x3f; + } else { + index = ((index & 0x3f) << 8) | getd(); + } + var[index] = cali(); + +#if defined(_DEBUG_CONSOLE) + char log[128]; + sprintf_s(log, 128, "\n!var[%d]:%d!", index, var[index]); + output_console(log); +#endif +} + +void NACT::cmd_branch() +{ + int condition = cali(); + int t_addr = scenario_addr + 2; + int f_addr = getw(); + + // sigmarion3 最適化誤爆の対策 + scenario_addr = condition ? t_addr : f_addr; + +#if defined(_DEBUG_CONSOLE) + char log[128]; + sprintf_s(log, 128, "\n{%d: T:%4x, F:%4x", condition, t_addr, f_addr); + output_console(log); +#endif +} + +void NACT::cmd_label_jump() +{ + int next_addr = getw(); + scenario_addr = next_addr; + +#if defined(_DEBUG_CONSOLE) + char log[128]; + sprintf_s(log, 128, "\n@%x:", next_addr); + output_console(log); +#endif +} + +void NACT::cmd_label_call() +{ + int next_addr = getw(); + +#if defined(_DEBUG_CONSOLE) + char log[128]; + sprintf_s(log, 128, "\n\\%x:", next_addr); + output_console(log); +#endif + + 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::cmd_page_jump() +{ + int next_page = cali(); + load_scenario(next_page); + scenario_page = next_page; + scenario_addr = 2; + +#if defined(_DEBUG_CONSOLE) + char log[128]; + sprintf_s(log, 128, "\n&%d:", next_page); + output_console(log); +#endif +} + +void NACT::cmd_page_call() +{ + int next_page = cali(), next_addr; + +#if defined(_DEBUG_CONSOLE) + char log[128]; + sprintf_s(log, 128, "\n%%%d:", next_page); + output_console(log); +#endif + + 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::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; + +#if defined(_DEBUG_CONSOLE) + char log[128]; + sprintf_s(log, 128, "$"); + output_console(log); +#endif + } 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; + +#if defined(_DEBUG_CONSOLE) + char log[128]; + sprintf_s(log, 128, "\n$%x,", menu_addr[menu_index - 1]); + output_console(log); +#endif + } +} + +void NACT::cmd_open_menu() +{ +#if defined(_DEBUG_CONSOLE) + char log[128]; + sprintf_s(log, 128, "\n]"); + output_console(log); +#endif + + if(!menu_index) { + scenario_addr = scenario_data[0] | (scenario_data[1] << 8); + return; + } + + // クリック中の間は待機 + for(;;) { + if(params.terminate) { + return; + } +// if(get_key() != 32) { + if(!get_key()) { + break; + } + Sleep(10); + } + + // メニュー表示 + ags->open_menu_window(menu_window); + int current_index = 0; + + // マウス移動 + 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; + set_cursor(mx, my); + + // メニュー選択 + for(;;) { + // 入力待機 + int val = 0, current_mx = mx, current_my = my; + for(;;) { + if(params.terminate) { + return; + } + if(val = get_key()) { + Sleep(100); + break; + } + get_cursor(¤t_mx, ¤t_my); + if(abs(my - current_my) > 3) { + break; + } + Sleep(10); + } + if(val) { + for(;;) { + if(params.terminate) { + return; + } + if(!get_key()) { + break; + } + Sleep(10); + } + } + + if(val == 0) { + // マウス操作 + mx = current_mx; my = current_my; + int index = (my - sy) / height; + if(sx <= mx && mx <= ex && 0 <= index && index < menu_index) { + current_index = index; + ags->redraw_menu_window(menu_window, current_index); + } + } else if(val == 1 || val == 2 || val == 4 || val == 8) { + if(val == 1) { + current_index = current_index ? current_index - 1 : menu_index - 1; + } else if(val == 2) { + current_index = (current_index < menu_index - 1) ? current_index + 1 : 0; + } else if(val == 4) { + current_index = 0; + } else if(val == 8) { + current_index = menu_index - 1; + } + ags->redraw_menu_window(menu_window, current_index); + } else if(val == 16) { + 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); + } + + if(current_index != -1) { + scenario_addr = menu_addr[current_index]; + } + menu_index = 0; +} + +void NACT::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; + +#if defined(_DEBUG_CONSOLE) + char log[128]; + sprintf_s(log, 128, "\n[%x,%s,%s:", addr, caption_verb[verb], caption_obj[obj]); + output_console(log); +#endif +} + +void NACT::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; + +#if defined(_DEBUG_CONSOLE) + char log[128]; + sprintf_s(log, 128, "\n:%d,%x,%s,%s:", condition, addr, caption_verb[verb], caption_obj[obj]); + output_console(log); +#endif +} + +void NACT::cmd_open_verb() +{ + // 動詞メニューの表示 +#if defined(_DEBUG_CONSOLE) + char log[128]; + sprintf_s(log, 128, "\nopen verb-obj menu"); + output_console(log); +#endif + 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; + + // クリック中の間は待機 + for(;;) { + if(params.terminate) { + return; + } +// if(get_key() != 32) { + if(!get_key()) { + break; + } + Sleep(10); + } + + // メニュー表示 + ags->open_menu_window(menu_window); + int current_index = 0; + + // マウス移動 + 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; + set_cursor(mx, my); + + // メニュー選択 + for(;;) { + // 入力待機 + int val = 0, current_mx = mx, current_my = my; + for(;;) { + if(params.terminate) { + return; + } + if(val = get_key()) { + Sleep(100); + break; + } + get_cursor(¤t_mx, ¤t_my); + if(abs(my - current_my) > 3) { + break; + } + Sleep(10); + } + if(val) { + for(;;) { + if(params.terminate) { + return; + } + if(!get_key()) { + break; + } + Sleep(10); + } + } + + if(val == 0) { + // マウス操作 + mx = current_mx; my = current_my; + int mindex = (my - sy) / height; + if(sx <= mx && mx <= ex && 0 <= mindex && mindex < index) { + current_index = mindex; + ags->redraw_menu_window(menu_window, current_index); + } + } else if(val == 1 || val == 2 || val == 4 || val == 8) { + if(val == 1) { + current_index = current_index ? current_index - 1 : index - 1; + } else if(val == 2) { + current_index = (current_index < index - 1) ? current_index + 1 : 0; + } else if(val == 4) { + current_index = 0; + } else if(val == 8) { + current_index = index - 1; + } + ags->redraw_menu_window(menu_window, current_index); + } else if(val == 16) { + 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); + } + + if(current_index == -1) { + scenario_addr = scenario_data[0] | (scenario_data[1] << 8); + } else { + cmd_open_obj(id[current_index]); + } + menu_index = 0; +} + +void NACT::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("戻る"); + id[index++] = 0; + ags->menu_dest_y += ags->menu_font_size + 2; + ags->draw_menu = false; + + // クリック中の間は待機 + for(;;) { + if(params.terminate) { + return; + } +// if(get_key() != 32) { + if(!get_key()) { + break; + } + Sleep(10); + } + + // メニュー表示 + ags->open_menu_window(menu_window); + int current_index = 0; + + // マウス移動 + 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; + set_cursor(mx, my); + + // メニュー選択 + for(;;) { + // 入力待機 + int val = 0, current_mx = mx, current_my = my; + for(;;) { + if(params.terminate) { + return; + } + if(val = get_key()) { + Sleep(100); + break; + } + get_cursor(¤t_mx, ¤t_my); + if(abs(my - current_my) > 3) { + break; + } + Sleep(10); + } + if(val) { + for(;;) { + if(params.terminate) { + return; + } + if(!get_key()) { + break; + } + Sleep(10); + } + } + + if(val == 0) { + // マウス操作 + mx = current_mx; my = current_my; + int mindex = (my - sy) / height; + if(sx <= mx && mx <= ex && 0 <= mindex && mindex < index) { + current_index = mindex; + ags->redraw_menu_window(menu_window, current_index); + } + } else if(val == 1 || val == 2 || val == 4 || val == 8) { + if(val == 1) { + current_index = current_index ? current_index - 1 : index - 1; + } else if(val == 2) { + current_index = (current_index < index - 1) ? current_index + 1 : 0; + } else if(val == 4) { + current_index = 0; + } else if(val == 8) { + current_index = index - 1; + } + ags->redraw_menu_window(menu_window, current_index); + } else if(val == 16) { + 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); + } + + if(current_index == -1) { + scenario_addr = scenario_data[0] | (scenario_data[1] << 8); + } else { + scenario_addr = addr[id[current_index]]; + } +} + +void NACT::cmd_a() +{ +#if defined(_DEBUG_CONSOLE) + char log[128]; + sprintf_s(log, 128, "A\n"); + output_console(log); +#endif + + if(!text_skip_enb) { + // Pushマークの表示 + if(show_push) { + ags->draw_push(text_window); + } + + // キーが押されて離されるまで待機 + for(;;) { + if(params.terminate) { + return; + } + if(get_key()) { + break; + } + Sleep(10); + } + Sleep(100); + for(;;) { + if(params.terminate) { + return; + } + if(!(get_key() & 0x18)) { + break; + } + Sleep(10); + } + } + + // ウィンドウ更新 + ags->clear_text_window(text_window, true); +} + +void NACT::cmd_b() +{ + int cmd = getd(); + int index = cali(); + int p1 = cali(); + int p2 = cali(); + int p3 = cali(); + int p4 = cali(); + int p5 = cali(); + +#if defined(_DEBUG_CONSOLE) + char log[128]; + sprintf_s(log, 128, "\nB %d,%d,%d,%d,%d,%d,%d:", cmd, index, p1, p2, p3, p4, p5); + output_console(log); +#endif + + if(cmd == 1) { + // あゆみちゃん物語 + if(crc32 == CRC32_AYUMI_CD || crc32 == CRC32_AYUMI_JISSHA_256 || crc32 == 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 == 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::cmd_d() +{ + // 未使用 +} + +void NACT::cmd_e() +{ + int index = cali(); + uint8 color = (uint8)cali(); + int sx = cali(); + int sy = cali(); + int ex = cali(); + int ey = cali(); + +#if defined(_DEBUG_CONSOLE) + char log[128]; + sprintf_s(log, 128, "\nE %d,%d,%d,%d,%d,%d:", index, color, sx, sy, ex, ey); + output_console(log); +#endif + + 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::cmd_f() +{ +#if defined(_DEBUG_CONSOLE) + char log[128]; + sprintf_s(log, 128, "\nF"); + output_console(log); +#endif + + scenario_addr = 2; +} + +void NACT::cmd_g() +{ + int page = cali(); + +#if defined(_DEBUG_CONSOLE) + char log[128]; + sprintf_s(log, 128, "\nG %d:", page); + output_console(log); +#endif + + ags->load_cg(page, -1); +} + +void NACT::cmd_h() +{ + int length = getd(); + int val = cali(); + +#if defined(_DEBUG_CONSOLE) + char log[128]; + sprintf_s(log, 128, "\nH %d,%d:", length, val); + output_console(log); +#endif + + // 隠しコマンド? + 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::cmd_i() +{ + int sx = cali(); + int sy = cali(); + int ex = cali(); + int ey = cali(); + int dx = cali(); + int dy = cali(); + +#if defined(_DEBUG_CONSOLE) + char log[128]; + sprintf_s(log, 128, "\nI %d,%d,%d,%d,%d,%d:", sx, sy, ex, ey, dx, dy); + output_console(log); +#endif + + // X方向はカラム単位で切り捨て + sx = column ? sx * 8 : sx & 0xfff8; + ex = column ? ex * 8 - 1 : (crc32 == CRC32_NINGYO) ? (ex & 0xfff8) + 7 : (ex & 0xfff8) - 1; + dx = column ? dx * 8 : dx & 0xfff8; + ags->copy(sx, sy, ex, ey, dx, dy); +} + +void NACT::cmd_j() +{ + int x = cali(); + int y = cali(); + +#if defined(_DEBUG_CONSOLE) + char log[128]; + sprintf_s(log, 128, "\nJ %d,%d:", x, y); + output_console(log); +#endif + + // x方向はカラム単位で切り捨て + ags->cg_dest_x = column ? x * 8 : x & 0xfff8; + ags->cg_dest_y = y; + ags->set_cg_dest = true; +} + +void NACT::cmd_k() +{ + int cmd = getd(), val; + +#if defined(_DEBUG_CONSOLE) + char log[128]; + sprintf_s(log, 128, "\nK %d:", cmd); + output_console(log); +#endif + + // K6の場合は、すぐに返る + if(cmd == 6) { + RND = get_key(); + return; + } + + // マウスの初期取得 + int mx, my; + get_cursor(&mx, &my); + + // キーが押されるまで待機 + for(;;) { + if(params.terminate) { + return; + } + if(val = get_key()) { + 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; + } + } + Sleep(10); + } + if(cmd != 0 && cmd != 4) { + RND = val; + } + + // キーが離されるまで待機 + if(cmd != 1) { + Sleep(100); + for(;;) { + if(params.terminate) { + return; + } + if(!(val = get_key())) { + break; + } + Sleep(10); + } + } + + // K0の場合は改行 + if(cmd == 0) { + cmd_r(); + } +} + +void NACT::cmd_l() +{ + int index = cali(); + +#if defined(_DEBUG_CONSOLE) + char log[128]; + sprintf_s(log, 128, "\nL %d:", index); + output_console(log); +#endif + + if(index == 0) { + // 特殊セーブ + _TCHAR file_path[_MAX_PATH]; + _stprintf_s(file_path, _MAX_PATH, _T("%sASLEEP.DAT"), g_root); + + FILEIO* fio = new FILEIO(); + if(fio->Fopen(file_path, FILEIO_READ_BINARY)) { + // 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 + _TCHAR path[_MAX_PATH], file_path[_MAX_PATH]; + _tcscpy_s(path, _MAX_PATH, _T("ASLEEP_A.DAT")); + path[7] = _T('A') + index - 1; + _stprintf_s(file_path, _MAX_PATH, _T("%s%s"), g_root, path); + + FILEIO* fio = new FILEIO(); + if(fio->Fopen(file_path, FILEIO_READ_BINARY)) { + 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; + +// ags->old_text_font_size = 0; +// ags->old_menu_font_size = 0; + mako->play_music(next_music); + } + delete fio; + } else if(101 <= index && index <= 126) { + // ASLEEP_A.DAT - ASLEEP_Z.DAT + _TCHAR path[_MAX_PATH], file_path[_MAX_PATH]; + _tcscpy_s(path, _MAX_PATH, _T("ASLEEP_A.DAT")); + path[7] = _T('A') + index - 101; + _stprintf_s(file_path, _MAX_PATH, _T("%s%s"), g_root, path); + + FILEIO* fio = new FILEIO(); + if(fio->Fopen(file_path, FILEIO_READ_BINARY)) { + fio->Fseek(112 + 16, FILEIO_SEEK_SET); + var[0] = fio->Fgetw(); + fio->Fclose(); + } + delete fio; + } +} + +void NACT::cmd_m() +{ + char string[22]; + int d, p = 0; + + while((d = getd()) != ':') { + if((0x81 <= d && d <= 0x9f) || 0xe0 <= d) { + // 2bytes + string[p++] = d; + string[p++] = getd(); + } else { + string[p++] = d; + } + } + string[p] = '\0'; + +#if defined(_DEBUG_CONSOLE) + char log[128]; + sprintf_s(log, 128, "\nM %s:", string); + output_console(log); +#endif + + if(1 <= tvar_index && tvar_index <= 10) { + memcpy(tvar[tvar_index - 1], string, 22); + } else if(tvar_index == 31) { + _tcscpy_s(adisk, 16, string); + } else if(tvar_index == 32) { + _tcscpy_s(ags->acg, 16, string); + } else if(tvar_index == 33) { + _tcscpy_s(mako->amus, 16, string); + } else if(tvar_index == 34) { + _tcscpy_s(mako->amse, 16, string); + } +} + +void NACT::cmd_n() +{ + int cmd = getd(); + int src = cali(); + int dest = cali(); + +#if defined(_DEBUG_CONSOLE) + char log[128]; + sprintf_s(log, 128, "\nN %d,%d,%d:", cmd, src, dest); + output_console(log); +#endif +} + +void NACT::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; + +#if defined(_DEBUG_CONSOLE) + char log[128]; + sprintf_s(log, 128, "\nO %d,%d:", cmd, val); + output_console(log); +#endif + } 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; + +#if defined(_DEBUG_CONSOLE) + char log[128]; + sprintf_s(log, 128, "\nO %d,var[%d]:", cmd, index); + output_console(log); +#endif + } +} + +void NACT::cmd_p() +{ + int index =cali(); + int r = cali(); + int g = cali(); + int b = cali(); + +#if defined(_DEBUG_CONSOLE) + char log[128]; + sprintf_s(log, 128, "\nP %d,%d,%d,%d:", index, r, g, b); + output_console(log); +#endif + + 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::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(); + +#if defined(_DEBUG_CONSOLE) + char log[128]; + sprintf_s(log, 128, "\nQ %d:", index); + output_console(log); +#endif + + if(index == 0) { + // 特殊セーブ + _TCHAR file_path[_MAX_PATH]; + _stprintf_s(file_path, _MAX_PATH, _T("%sASLEEP.DAT"), g_root); + + FILEIO* fio = new FILEIO(); + if(fio->Fopen(file_path, FILEIO_WRITE_BINARY)) { + // 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 + _TCHAR path[_MAX_PATH], file_path[_MAX_PATH]; + _tcscpy_s(path, _MAX_PATH, _T("ASLEEP_A.DAT")); + path[7] = _T('A') + index - 1; + _stprintf_s(file_path, _MAX_PATH, _T("%s%s"), g_root, path); + + FILEIO* fio = new FILEIO(); + if(fio->Fopen(file_path, FILEIO_WRITE_BINARY)) { + 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::cmd_r() +{ +#if defined(_DEBUG_CONSOLE) + char log[128]; + sprintf_s(log, 128, "R\n"); + output_console(log); +#endif + + // ウィンドウの表示範囲外の場合は改ページ + if(ags->return_text_line(text_window)) { + cmd_a(); + } +} + +void NACT::cmd_s() +{ + int page = getd(); + +#if defined(_DEBUG_CONSOLE) + char log[128]; + sprintf_s(log, 128, "\nS %d:", page); + output_console(log); +#endif + + if(page) { + mako->play_music(page); + } else { + mako->stop_music(); + } +} + +void NACT::cmd_t() +{ + int x = cali(); + int y = cali(); + +#if defined(_DEBUG_CONSOLE) + char log[128]; + sprintf_s(log, 128, "\nT %d,%d:", x, y); + output_console(log); +#endif + + // x方向はカラム単位で切り捨て + ags->text_dest_x = column ? x * 8 : x & 0xfff8; + ags->text_dest_y = y; +} + +void NACT::cmd_u() +{ + int page = cali(); + int transparent = cali(); + +#if defined(_DEBUG_CONSOLE) + char log[128]; + sprintf_s(log, 128, "\nU %d,%d:", page, transparent); + output_console(log); +#endif + + if(crc32 == CRC32_RANCE41 || crc32 == CRC32_RANCE42) { + transparent = (transparent == 28) ? 12 : transparent; + } + ags->load_cg(page, transparent); +} + +void NACT::cmd_v() +{ + int cmd = cali(); + int index = cali(); + +#if defined(_DEBUG_CONSOLE) + char log[128]; + sprintf_s(log, 128, "\nV %d,%d:", cmd, index); + output_console(log); +#endif + + 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::cmd_w() +{ + int x = cali(); + int y = cali(); + uint8 color = (uint8)cali(); + +#if defined(_DEBUG_CONSOLE) + char log[128]; + sprintf_s(log, 128, "\nW %d,%d,%d", x, y, color); + output_console(log); +#endif + + ags->paint(x, y, color); +} + +void NACT::cmd_x() +{ + int index = getd(); + +#if defined(_DEBUG_CONSOLE) + char log[128]; + sprintf_s(log, 128, "\nX %d:", index); + output_console(log); +#endif + + if(1 <= index && index <= 10) { + ags->draw_text(tvar[index - 1]); + } +} + +void NACT::cmd_y() +{ + int cmd = cali(); + int param = cali(); + +#if defined(_DEBUG_CONSOLE) + char log[128]; + sprintf_s(log, 128, "\nY %d,%d:", cmd, param); + output_console(log); +#endif + + 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 { + DWORD dwTime = timeGetTime() + param * 1000 / 60; + for(;;) { + if(params.terminate) { + return; + } + RND = get_key(); + if(RND && wait_keydown) { + break; + } + if(dwTime <= timeGetTime()) { + break; + } + Sleep(10); + } + } + 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; + DialogBoxParam(g_hinst, MAKEINTRESOURCE(IDD_DIALOG1), g_hwnd, TextDialogProc, (LPARAM)this); + 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: + if(ags->now_fade()) { + DWORD dwStart = timeGetTime(); + for(int i = 0; i < 16; i++) { + ags->fade_in(i); + DWORD dwTime = dwStart + param * 1000 / 60 * i; + for(;;) { + if(params.terminate) { + return; + } + if(dwTime <= timeGetTime()) { + break; + } + Sleep(0); + } + } + ags->fade_end(); + } + break; + case 41: + case 43: + if(!ags->now_fade()) { + ags->fade_start(); + DWORD dwStart = timeGetTime(); + for(int i = 0; i < 16; i++) { + ags->fade_out(i, (cmd == 41) ? false : true); + DWORD dwTime = dwStart + param * 1000 / 60 * i; + for(;;) { + if(params.terminate) { + return; + } + if(dwTime <= timeGetTime()) { + break; + } + Sleep(0); + } + } + } + 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(params.terminate) { + return; + } + if(!get_key()) { + break; + } + Sleep(0); + } + } + } 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: + { + char string[21]; + int s = 0, d = 0; + for(int i = 0; i < cmd - 220; i++) { + if(tvar[param - 1][s] == '\0') { + string[d++] = 0x20; + } else { + uint8 code = tvar[param - 1][s++]; + string[d++] = code; + if((0x81 <= code && code <= 0x9f) || 0xe0 <= code) { + string[d++] = tvar[param - 1][s++]; + } + } + } + string[d] = '\0'; + ags->draw_text(string); + } + break; + case 230: + clear_text = param ? true : false; + break; + case 231: + D01 = 640; + D02 = (param == 1) ? ags->screen_height : 480; + D03 = (crc32 == CRC32_YAKATA3_FD) ? 16 : 256; + break; + case 232: + if(ags->screen_height != param ? 480 : 400) { + 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: + { + SYSTEMTIME sTime; + GetLocalTime(&sTime); + D01 = sTime.wYear; + D02 = sTime.wMonth; + D03 = sTime.wDay; + D04 = sTime.wHour; + D05 = sTime.wMinute; + D06 = sTime.wSecond; + D07 = sTime.wDayOfWeek + 1; + } + break; + case 239: + { + _TCHAR path[_MAX_PATH], file_path[_MAX_PATH]; + _tcscpy_s(path, _MAX_PATH, _T("ASLEEP_A.DAT")); + path[7] = _T('A') + param - 1; + _stprintf_s(file_path, _MAX_PATH, _T("%s%s"), g_root, path); + + HANDLE hFile = CreateFile(file_path, GENERIC_READ, FILE_SHARE_WRITE, NULL, + OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + if(hFile != INVALID_HANDLE_VALUE) { + FILETIME fTime, fLocalTime; + SYSTEMTIME sTime; + GetFileTime(hFile, NULL, NULL, &fTime); + FileTimeToLocalFileTime(&fTime, &fLocalTime); + FileTimeToSystemTime(&fLocalTime, &sTime); + CloseHandle(hFile); + D01 = sTime.wYear; + D02 = sTime.wMonth; + D03 = sTime.wDay; + D04 = sTime.wHour; + D05 = sTime.wMinute; + D06 = sTime.wSecond; + } else { + D01 = D02 = D03 = D04 = D05 = D06 = 0; + } + } + break; + case 240: + ags->draw_hankaku = (param == 1) ? true : false; + break; + case 241: + break; + case 250: + { + _TCHAR path[4]; + path[0] = g_root[0]; + path[1] = _T(':'); + path[2] = _T('\\'); + path[3] = _T('\0'); + UINT t = GetDriveType(path); + // フロッピーから起動した場合は0が返る + //RND = (t == DRIVE_REMOVABLE) ? 0 : (t == DRIVE_CDROM) ? 2 : 1; + RND = (t == DRIVE_CDROM) ? 2 : 1; + } + break; + case 251: + column = param ? false : true; + break; + case 252: + RND = (crc32 == CRC32_YAKATA3_FD) ? 4 : 8; + break; + case 253: + show_push = (param == 0) ? true : false; + break; + case 254: + RND = (crc32 == CRC32_YAKATA3_CD || crc32 == CRC32_YAKATA3_FD || crc32 == CRC32_NINGYO) ? 1 : 0; + break; + case 255: + post_quit = (param == 1) ? true : false; + fatal_error = true; + break; + } +} + +void NACT::cmd_z() +{ + int cmd = cali(); + int param = cali(); + +#if defined(_DEBUG_CONSOLE) + char log[128]; + sprintf_s(log, 128, "\nZ %d,%d:", cmd, param); + output_console(log); +#endif + + 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->cd_track[cmd - 100] = param; + } +} + + +// 下位関数 + +uint16 NACT::cali() +{ + uint32 cali[256]; + int p = 1; + fatal_error = true; + + 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) { + fatal_error = false; + } + p = 0; + } + } + return (uint16)(cali[1] & 0xffff); +} + +uint16 NACT::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_error = true; + } + if(getd() != 0x7f) { + fatal_error = true; + } + return val; +} + +uint8 NACT::getd() +{ + return scenario_data[scenario_addr++]; +} + +uint16 NACT::getw() +{ + uint16 val = scenario_data[scenario_addr] | (scenario_data[scenario_addr + 1] << 8); + scenario_addr += 2; + return val; +} + diff --git a/src/winmain.cpp b/src/winmain.cpp new file mode 100644 index 0000000..972f5a9 --- /dev/null +++ b/src/winmain.cpp @@ -0,0 +1,453 @@ +/* + ALICE SOFT SYSTEM 3 for Win32 + + [ WinMain ] +*/ + +#include +#include +#include +#include +#include +#include +#include "common.h" +#if defined(_SYSTEM1) +#include "res1/resource.h" +#elif defined(_SYSTEM2) +#include "res2/resource.h" +#else +#include "res3/resource.h" +#endif +#include "sys/nact.h" + +int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR szCmdLine, int iCmdShow); +LRESULT CALLBACK WndProc(HWND hWnd, UINT iMsg, WPARAM wParam, LPARAM lParam); + +// フルスクリーン +void set_window(HWND hWnd, BOOL full); +void show_menu_bar(HWND hWnd); +void hide_menu_bar(HWND hWnd); + +BOOL fullscreen_now = FALSE; +BOOL menuloop_now = FALSE; + +// MCIデバイス +void initialize_mci(); +void release_mci(); +void play_mci(HWND hWnd, int index); +void stop_mci(); + +_TCHAR g_root[_MAX_PATH]; +HINSTANCE g_hinst; +HWND g_hwnd = NULL; +HMENU g_hmenu = NULL; + +NACT* nact; + +int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR szCmdLine, int iCmdShow) +{ + // モジュールパス取得 + GetModuleFileName(NULL, g_root, _MAX_PATH); + int p = _tcslen(g_root); + while(g_root[p] != _T('\\')) { + p--; + } + g_root[p + 1] = _T('\0'); + + g_hinst = hInstance; + + // ウィンドウの表示位置を取得する + RECT rect = {0, 0, 640, 400}; + AdjustWindowRect(&rect, WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX | WS_VISIBLE, TRUE); + + HDC hdc = CreateDC(_T("DISPLAY"), NULL, NULL, NULL); + int width = GetDeviceCaps(hdc, HORZRES); + int height = GetDeviceCaps(hdc, VERTRES); + int dest_x = (int)((width - (rect.right - rect.left)) / 2); + int dest_y = (int)((height - (rect.bottom - rect.top)) / 2); +// dest_x = (dest_x < 0) ? 0 : dest_x; + dest_y = (dest_y < 0) ? 0 : dest_y; + + // ウィンドウ生成 + WNDCLASS wndclass; + wndclass.style = CS_HREDRAW | CS_VREDRAW; + wndclass.lpfnWndProc = (WNDPROC)WndProc; + wndclass.cbClsExtra = 0; + wndclass.cbWndExtra = 0; + wndclass.hInstance = g_hinst; + wndclass.hIcon = LoadIcon(g_hinst, MAKEINTRESOURCE(IDI_ICON1)); + wndclass.hCursor = 0; + wndclass.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH); + wndclass.lpszMenuName = MAKEINTRESOURCE(IDR_MENU1); + wndclass.lpszClassName = _T("CWINDOW"); + RegisterClass(&wndclass); + + // ウィンドウ表示 + _TCHAR buf[128]; +#if defined(_SYSTEM1) + _tcscpy_s(buf, 128, _T("Scenario Decoder SYSTEM1")); +#elif defined(_SYSTEM2) + _tcscpy_s(buf, 128, _T("Scenario Decoder SYSTEM2")); +#else + _tcscpy_s(buf, 128, _T("Scenario Decoder SYSTEM3")); +#endif + + g_hwnd = CreateWindow(_T("CWINDOW"), buf, + WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX | WS_VISIBLE, + dest_x, dest_y, rect.right - rect.left, rect.bottom - rect.top, + NULL, NULL, g_hinst, NULL); + ShowWindow(g_hwnd, iCmdShow); + UpdateWindow(g_hwnd); + + // メニュー表示 + show_menu_bar(g_hwnd); + + // MCI 初期化 + initialize_mci(); + + // system3 初期化 + nact = new NACT(); + + _TCHAR title[128]; + if(nact->get_title(title, 128)) { +#if defined(_SYSTEM1) + _stprintf_s(buf, 128, _T("Scenario Decoder SYSTEM1 - %s"), title); +#elif defined(_SYSTEM2) + _stprintf_s(buf, 128, _T("Scenario Decoder SYSTEM2 - %s"), title); +#else + _stprintf_s(buf, 128, _T("Scenario Decoder SYSTEM3 - %s"), title); +#endif + SetWindowText(g_hwnd, buf); + } + + // メインループ + MSG msg; + while(GetMessage(&msg,NULL,0,0)) { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + + // system3 開放 + if(nact) { + delete nact; + } + + // MCI 開放 + release_mci(); + + // フルスクリーンから復帰 + if(fullscreen_now) { + ChangeDisplaySettings(NULL, 0); + } + +#ifdef _DEBUG + // メモリリーク検出 + _CrtDumpMemoryLeaks(); +#endif + + return msg.wParam; +} + +LRESULT CALLBACK WndProc(HWND hWnd, UINT iMsg, WPARAM wParam, LPARAM lParam) +{ + RECT rect; + HDC hdc; + PAINTSTRUCT ps; + + switch(iMsg) { + case WM_CLOSE: + if(g_hmenu != NULL && IsMenu(g_hmenu)) { + DestroyMenu(g_hmenu); + } + DestroyWindow(hWnd); + break; + + case WM_DESTROY: + PostQuitMessage(0); + break; + + case WM_PAINT: + if(GetUpdateRect(hWnd, &rect, TRUE)) { + hdc = BeginPaint(hWnd, &ps); + if(nact) { + nact->update_screen(hdc, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top); + } + EndPaint(hWnd, &ps); + } + return 0; + + case WM_ENTERMENULOOP: + menuloop_now = true; + break; + + case WM_EXITMENULOOP: + if(fullscreen_now && menuloop_now) { + hide_menu_bar(hWnd); + } + menuloop_now = false; + break; + + case WM_MOUSEMOVE: + if(fullscreen_now && !menuloop_now) { + POINTS p = MAKEPOINTS(lParam); + if(p.y == 0) { + show_menu_bar(hWnd); + } else if(p.y > 32) { + hide_menu_bar(hWnd); + } + } + break; + + case WM_LBUTTONDOWN: + if(nact) { + nact->key_down(VK_LBUTTON); + } + break; + + case WM_LBUTTONUP: + if(nact) { + nact->key_up(VK_LBUTTON); + } + break; + + case WM_RBUTTONDOWN: + if(nact) { + nact->key_down(VK_RBUTTON); + } + break; + + case WM_RBUTTONUP: + if(nact) { + nact->key_up(VK_RBUTTON); + } + break; + + case WM_KILLFOCUS: + if(nact) { + nact->key_up(-1); + } + break; + + case WM_KEYDOWN: + if(nact) { + uint8 code = LOBYTE(wParam); + nact->key_down(code); + } + break; + + case WM_KEYUP: + if(nact) { + uint8 code = LOBYTE(wParam); + nact->key_up(code); + } + break; + + case WM_SETCURSOR: + if(nact) { + nact->select_cursor(); + } + break; + + case MM_MCINOTIFY: + if(nact) { + if(wParam == MCI_NOTIFY_SUCCESSFUL) { + nact->notify_mci(0); + } else if(wParam == MCI_NOTIFY_FAILURE) { + nact->notify_mci(-1); + } + } + break; + + case WM_USER: + if(wParam) { + play_mci(hWnd, wParam); + } else { + stop_mci(); + } + break; + + case WM_USER + 2: +// if(fullscreen_now) { +// set_window(hWnd, FALSE); +// } + rect.left = rect.top = 0; + rect.right = 640; + rect.bottom = wParam; + AdjustWindowRectEx(&rect, WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_VISIBLE, TRUE, 0); + SetWindowPos(hWnd, NULL, 0, 0, rect.right - rect.left, rect.bottom - rect.top, SWP_NOMOVE | SWP_NOZORDER); + break; + + case WM_ACTIVATEAPP: + if(fullscreen_now) { + set_window(hWnd, FALSE); + } + break; + + case WM_INITMENUPOPUP: + if(LOWORD(lParam) == 1) { + EnableMenuItem((HMENU)wParam, ID_SCREEN_WINDOW, fullscreen_now ? MF_ENABLED : MF_GRAYED); + EnableMenuItem((HMENU)wParam, ID_SCREEN_FULL, fullscreen_now ? MF_GRAYED : MF_ENABLED); + } else if(LOWORD(lParam) == 3) { + if(nact) { + CheckMenuItem((HMENU)wParam, ID_TEXT_SKIP, nact->text_skip_enb ? MF_CHECKED : MF_UNCHECKED); + CheckMenuItem((HMENU)wParam, ID_TEXT_WAIT, nact->text_wait_enb ? MF_CHECKED : MF_UNCHECKED); + } + } + break; + + case WM_COMMAND: + switch(LOWORD(wParam)) { + case ID_RESTART: + // restart nact + if(nact) { + delete nact; + } + nact = new NACT(); + + // update screen + rect.left = rect.top = 0; + rect.right = 640; + rect.bottom = 480; + InvalidateRect(hWnd, &rect, FALSE); + UpdateWindow(g_hwnd); + break; + + case ID_EXIT: + SendMessage(hWnd, WM_CLOSE, 0, 0); + break; + + case ID_SCREEN_WINDOW: + if(fullscreen_now) { + set_window(hWnd, FALSE); + } + break; + + case ID_SCREEN_FULL: + if(!fullscreen_now) { + set_window(hWnd, TRUE); + } + break; + + case ID_SOUND_FM: + if(nact) { + nact->select_sound(0); + } + break; + + case ID_SOUND_CD: + if(nact) { + nact->select_sound(1); + } + break; + + case ID_TEXT_SKIP: + if(nact) { + nact->text_skip_enb = !nact->text_skip_enb; + } + break; + + case ID_TEXT_WAIT: + if(nact) { + nact->text_wait_enb = !nact->text_wait_enb; + } + break; + } + break; + } + return DefWindowProc(hWnd, iMsg, wParam, lParam) ; +} + +// フルスクリーン + +void set_window(HWND hWnd, BOOL full) +{ + static LONG style = WS_VISIBLE; + static int dest_x = 0, dest_y = 0; + WINDOWPLACEMENT place; + place.length = sizeof(WINDOWPLACEMENT); + + if(full && !fullscreen_now) { + // フルスクリーンに移行 + DEVMODE dev; + HDC hdc = GetDC(NULL); + ZeroMemory(&dev, sizeof(dev)); + dev.dmSize = sizeof(dev); + dev.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT; + dev.dmBitsPerPel = GetDeviceCaps(hdc, BITSPIXEL); + dev.dmPelsWidth = 640; + dev.dmPelsHeight = 480; + ReleaseDC(NULL, hdc); + + if(ChangeDisplaySettings(&dev, CDS_TEST) == DISP_CHANGE_SUCCESSFUL) { + GetWindowPlacement(hWnd, &place); + dest_x = place.rcNormalPosition.left; + dest_y = place.rcNormalPosition.top; + ChangeDisplaySettings(&dev, CDS_FULLSCREEN); + style = GetWindowLong(hWnd, GWL_STYLE); + SetWindowLong(hWnd, GWL_STYLE, WS_VISIBLE); + SetWindowPos(hWnd, HWND_TOP, 0, 0, 640, 480, SWP_SHOWWINDOW); + SetCursorPos(320, 200); + fullscreen_now = TRUE; + hide_menu_bar(hWnd); + } + } else if(!full && fullscreen_now) { + // フルスクリーンから復帰 + RECT rect = {0, 0, 640, nact ? nact->get_screen_height() : 400}; +// if(nact) { +// rect.bottom = nact->get_screen_height(); +// } + AdjustWindowRect(&rect, WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX | WS_VISIBLE, TRUE); + ChangeDisplaySettings(NULL, 0); + SetWindowLong(hWnd, GWL_STYLE, style); + SetWindowPos(hWnd, HWND_TOP, dest_x, dest_y, rect.right - rect.left, rect.bottom - rect.top, SWP_SHOWWINDOW); + fullscreen_now = FALSE; + show_menu_bar(g_hwnd); + } +} + +void show_menu_bar(HWND hWnd) +{ + if(!(g_hmenu != NULL && IsMenu(g_hmenu))) { + g_hmenu = LoadMenu((HINSTANCE)GetModuleHandle(0), MAKEINTRESOURCE(IDR_MENU1)); + SetMenu(hWnd, g_hmenu); + } +} + +void hide_menu_bar(HWND hWnd) +{ + if(g_hmenu != NULL && IsMenu(g_hmenu)) { + SetMenu(hWnd, NULL); + DestroyMenu(g_hmenu); + g_hmenu = NULL; + } +} + +// MCIデバイス + +void initialize_mci() +{ + mciSendString(_T("open cdaudio"), NULL, 0, NULL); + mciSendString(_T("set cdaudio time format tmsf"), NULL, 0, NULL); + mciSendString(_T("set cdaudio audio all on"), NULL, 0, NULL); + mciSendString(_T("stop cdaudio"), NULL, 0, NULL); +} + +void release_mci() +{ + mciSendString(_T("stop cdaudio"), NULL, 0, NULL); + mciSendString(_T("close cdaudio"), NULL, 0, NULL); +} + +void play_mci(HWND hWnd, int index) +{ + _TCHAR string[_MAX_PATH]; + + _stprintf_s(string, _MAX_PATH, _T("play cdaudio from %d to %d notify"), index, index + 1); + mciSendString(string, NULL, 0, hWnd); +} + +void stop_mci() +{ + mciSendString(_T("stop cdaudio"), NULL, 0, NULL); +} + diff --git a/system3.vcproj b/system3.vcproj new file mode 100644 index 0000000..de2a4e1 --- /dev/null +++ b/system3.vcproj @@ -0,0 +1,692 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tengu.vcproj b/tengu.vcproj new file mode 100644 index 0000000..8cd8cf9 --- /dev/null +++ b/tengu.vcproj @@ -0,0 +1,656 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/vampire.vcproj b/vampire.vcproj new file mode 100644 index 0000000..5fb9ae9 --- /dev/null +++ b/vampire.vcproj @@ -0,0 +1,656 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +