MZ-2000というかEmuZ-2000 TF-Editionのメモ書き
気づいたことをメモ書きにしておきます。
プラグイン作成のメモ書き
独自で調べたもので、内容は無保証です。憶測の部分もあるのでかなり思い込みがあると思われます。DLLの作り方の基礎はオリジナル作者EmuZ-2000氏のExtBoardDLL拡張ボードDLL、<連載>拡張ボードDLLを作ろう!の記事が参考になるかも。この連載がもう少し続いていればうちの調査は不要だったかも?
- 記述する関数
- BoardInfomationService:プラグインの情報を戻す処理を行う。
最初に一度呼び出される。PEMUZ2000EBIH構造体の各内容を戻す処理を行う。これにより、プラグイン設定ダイアログに情報表示される。
- IntializeBoard:初期処理を行う。
InitializeBoardExから呼び出され、プラグインのロード時に呼び出される。
ボードで必要な外部ファイルのオープンとかメモリの初期化とか記述する。BoardInfomationServiceとIntializeBoard関数が存在しないとプラグインはパージされる。
- ReIntializeBoard:初期化の継続処理を行う。
全プラグインの初期化完了後に再度呼び出されるルーチン。おそらく、プラグイン同士の初期処理衝突回避用で別のプラグインの初期情報を参照したい場合に使うのかも?必要なければ関数内は何も記述しなくてもいい(returnのみ記述)。
- ReportCpuClock:現在のCPUクロック値が通知された時の処理を行う。
ReInitializeBoard後に一度呼び出される。引数に現在(呼び出し時)のCPUクロックが入ってくる。ボードで何らかのCPUクロックに合わせた処理が必要なら記述するのかも。
- FinalizeBoard:後始末を行う。
本体停止時に呼び出される。自分で使用してるファイルなどのクローズやメモリ解放を行う。
- InfomationDialog:ツール→プラグイン設定→カスタム設定を押したときのダイアログ処理を行う。
カスタム設定ダイアログが必要な場合に記述する。EMUZ2000EBIH構造体のフラグにUSE_INFODIALOGを指定する必要があり、指定しないとカスタム設定ボタンが押せない。
DialogBoxを呼び出す。コールバック関数名は次のInfomationDlgProcに合わせておくとよい。(実際は一致していれば何でもいけると思われます)
- InfomationDlgProc:ダイアログ処理のコールバック関数を記述する。
カスタム設定ダイアログが必要な場合に記述する。Windowsのコールバックルーチンと同じ構造。自分で設定したダイアログの処理を記述していく。
- StateSaveOutputDataEx:ステートセーブする情報をセット処理を行う。
- StateSaveInputDataEx:ステートセーブから復元する情報を処理する。
- InportFunction:プラグインから本体へ渡す処理を記述する。引数の値を調べて処理すべきポート番号なら処理を記述する。
- OutportFunction:本体からプラグインへデータを渡す処理を記述する。引数の値を調べて処理すべきポート番号なら処理を記述する。InportFunction、OutportFunctionの関数名はEMUZ2000EBIH構造体内(MAPIOSTRUCT構造体ioMapperのfInportFunc、fOutportFunc)に指定しておく。名前が一致すればなんでもOK
- EMUZ2000EBIH構造体
名前 | 型 | 意味 |
szGuidCode | TCHAR配列(配列長:MAX_GUID_LENGTH) | プロファイル内でプラグインを識別するのに使われるGUID |
szBoardName | TCHAR配列(配列長:MAX_BOARD_NAME_LENGTH) | プラグイン名※ |
szBoardInfo | TCHAR配列(配列長:MAX_BOARD_INFO_LENGTH) | プラグイン概要 |
szDllCopyright | TCHAR配列(配列長:MAX_DLL_COPYRIGHT_LENGTH) | 著作権情報※ |
szDllMakerUrl | TCHAR配列(配列長:MAX_DLL_MAKER_URL_LENGTH) | 作者ホームページ※ |
szDllMakerMail | TCHAR配列(配列長:MAX_DLL_MAKER_MAIL_LENGTH) | 作者メールアドレス※ |
dwIoMode | DWORD | 未使用? |
ioMapper | MAPIOSTRUCT構造体 | I/O情報の構造体。下記参照 |
flgs | EXTFLG共用体 | プラグインの機能指定。USE_INFODIALOGのみ効果あり。 |
※ツール→プラグイン設定で開いたダイアログに表示される情報。
- MAPIOSTRUCT構造体
名前 | 型 | 意味 |
fInportFunc | EMUZ2000INPORTFUNC関数 | INP処理関数名 |
fOutportFunc | EMUZ2000INPORTFUNC関数 | OUT処理関数名 |
ucStartPort | UCHAR | 使用ポート※ |
nCount | UCHAR | ポート数※ |
※ツール→プラグイン設定で開いたダイアログに表示される情報。
- 用意するソース
- メインプログラム、ヘッダファイル:1にある関数をすべて含むソースと自前のヘッダファイル。
分割してもまとめてもどちらでもいいと思われます。個人的には1本にまとめたい。
- ダイアログのリソース:ダイアログがある場合
リソーススクリプトやアイコン、ビットマップデータなど。
- モジュール定義ファイル:.defファイル。
DLL名、エクスポートする関数を記述したファイル。
- コンパイル方法
Visual Studio 2015でのコンパイル方法です。ファイル→新規作成→既存のコードからプロジェクトを作成を選択。
プロジェクトの種類は当然Visual C++、場所にソースを保存したフォルダを指定、プロジェクト名をボード名、プロジェクトの種類にダイナミックリンクライブラリを指定して完了。
*.c、*.h、*.rc、*.defが自動的に追加されます。プラグインソースのinterface内のplugin_ex.cとplugin_ex.hを追加(これはもしかしたら必要なら。うちは本体のメモリアドレスを得るのにこれに含まれる関数を使用しました)。
ビルド→ソリューションのビルドでコンパイルできます。str系関数でたくさんの警告が出ましたけど、unsafeとか言われても知ったことかって思って無視です。
環境設定が悪いのか、リソーススクリプトが参照してるDS_XXX関係が見つからない場合があったので、リソーススクリプトに#include <windows.h>を挿入したりしました。
また、構成プロパティ→リンカー→入力のモジュール定義ファイルに*.defを指定しないとエクスポートしてくれない(エミュレータのツール→プラグイン設定で作成したプラグインが認識されません)ので要注意。原因究明にテストプログラムを作ったり大変だった。
- プラグイン作成時のメモ
メインメモリを参照:interface/plugin_ex.cをプロジェクトに加える。emuz2000_getMainMemoryPointer()を呼び出すとメインメモリへのポインタが戻される。引数はBoardInfomationServiceの2番目の引数から得られるIDを指定する。
GRAMを参照:interface/plugin_ex.cをプロジェクトに加える。emuz2000_getGraphicRamPointers()を呼び出すと、2番目の引数にGRAM1、3番目の引数にGRAM2、4番目の引数にGRAM3へのポインタが戻される。1番目の引数は、上記と同様のIDを指定する。
MZ-1R13(漢字ROMボード)の利用
MZ-2Z021(漢字COLOR DISK BASIC)が無いと設定しても表示するすべがないと思われます。
漢字を表示させるのに必要なものは、DLL(emuz2000plugins_tf0_8d.zipに含まれてます)を本体のフォルダへ置き、EmuZ2000TF.iniをメモ帳などで開いてreadme.txtにあるように設定を記述します。
漢字ROM(アルゴの記憶にある漢字フォント作成プログラムで作成する)、
辞書ROM(sugaのジャンク部屋にあるオリジナル辞書作成ツールに含まれてます。手を加えた場合は作成します。)が必要です。
emuz2000plugins_tf0_8dで、漢字ROMと辞書ROMのファイル名の変更があり、元のDLLで使われていたファイル名ですと読み込まれなくなりました。
漢字ROMを「mz_1r13_kan.rom」、辞書ROMを「mz_1r13_dic.rom」とリネームしてください。
(2016-03-05追記:2016-02-26公開のemuz2000plugins_tf0_95_3のドキュメントChangeLog.txtにファイル名が記載されました)
コピー&ペースト機能
Version 0.94.1から表示画面をクリップボードへコピーする機能とクリップボード内のテキストをペーストする機能が追加されました。
コピーは表示イメージ通りにテキストがクリップボードへ転送され、ペーストはクリップボードから1文字づつ文字を打ち込まれた状態のように振る舞います。
一部のコードを除いてemuz2000_charcode.txtに対応するコードに置き換えられます。
- カナ文字の「シ」が正常に処理されない問題
Version 0.94.2現在、emuz2000_charcode.txt内のカナ「シ」が「セ」となってるので、コピーするとシはセになり、
ペーストではシは無視されてしまいます。内容を自分で直せば問題なく動きます。
Version 0.95.4で問題解消されました。TS-1000/2000でペースト時に複数改行される問題も解消
- クリップボード内のカナ文字を半角にしたい
emuz2000_charcode.txtのカナ文字を半角に置き換えればできます。全角(2バイト分)を半角1文字とスペース1バイトで置き換えれば問題なく処理されます。(要は英数字と同じようにするだけです。)
WindowsのテキストファイルでBASICソースをオリジナルに近い状態で格納できると思います。
- ペースト時に文字が欠落する
ペーストの設定をNormal、MZ-1Z001上でペーストした場合、タイミングによって文字が欠落するケースが発生してます。
ペーストする行が長い場合に発生するみたいで、次の行の先頭数バイトが欠落したりします。うちのWindows動作が重たいのかもしれませんけどね。
一画面分を送りこもうとせずに、長い行は1行づつ、あとは小分けして送り込めば問題ないのでゆっくりとやってます。
(2016-03-08追記:改行されてから内部処理で時間がかかる場合に欠落するケースがあるとか。モニターとは関係ないので、欠落する場合は貼り付け設定で待ち時間を変更して対応とのこと。)
EmuZ-2000用ステートセーブ(状態ファイル)の読み込み
EmuZ-2000 TF-Edition Ver0.92.0にはEmuZ-2000のステートセーブ(*.emuz)の読み込み機能があります。
読み込めるのは、EmuZ-2000のステートセーブVer1.0フォーマット(*.emuzをテキストエディタで開いて、ファイル先頭にある文字列が「EmuZ-2000 State Save 1.0」とあるもの)です。
EmuZ-2000の最新版は、ステートセーブVer1.1フォーマットとなっており、読み込みができません。1.0と1.1の違いは、ステートセーブのヘッダ部で、1.1の方が48バイト大きいだけだそうです。(この48バイト分の内容の違いは忘れてしまったので不明です、)
1.1フォーマットならヘッダと思われる部分の48バイトを削り、ファイル先頭の識別子を1.0にしてしまえば読める可能性が出てくるわけです。
- バイナリエディタ(うちはStirlingを使用)でステートセーブを開く。
- アドレスの100辺りから48バイトをカット。
- アドレス17の31を30へ書き換える。(ファイル先頭からEmuZ-2000 State Save 1.0となるはず)
- エミュレータのファイル→状態ファイルの読込で読ませる
挙動がおかしいと思われる場合は、BASIC上のプログラムならBREAKさせてRUNしてみるのも手です。また、リセットして動く場合もあります。
S-OS上のテキストファイルをWindowsのテキストファイルからインポートする
Windows上のテキストファイルとしてソースコードなどを入力し、それをS-OS上へ持っていく事ができます。
Windows上で改行コードがCR(0x0D)、終端コードNULL(0x00)のファイルを作成。うちのステートセーブ内のメモリ編集ツールでバイナリイメージとして埋め込み利用します。
- S-OSを動かした状態でステートセーブを行う。E-MATEとかSLANGなどをロードしておくといいかも。
- Windows上で目的のテキストファイルを作成。ASCIIコードのマップが違う点も考慮して作成(中括弧が■になるとか)
- S-OS用の最終調整。ファイル最後に終端コードNULLを1文字挿入、改行コードCRで保存(Sakura Editorがおすすめ)。
- ステートセーブ内のメモリ編集ツールでバイナリとして埋め込み保存。アドレスはE-MATEなり使うソフトのテキスト格納アドレスに合わせる。
- エミュレータのファイル→状態ファイルの読込で読ませる
- ソフトを立ち上げ、テキストを確認する。
細かいところはバイナリエディタで補正するといいかもです。