﻿------------------------------------------------------------------------------

  FM-7 EMULATOR XM7 (V2.8L31a / V3.3L31a)

  ソースコード
  Copyright (C) 1999-2003 ＰＩ．(ytanaka@ipc-tokai.or.jp)
  Copyright (C) 2001-2003 Ryu Takegami
  ROMEO support code by usalin

------------------------------------------------------------------------------

□ソース公開にあたって

  このアーカイブはFM-7エミュレータXM7(V2.8L31a/V3.3L31a)の全ソースコードです。

  私は元々、ソースコード公開に余り積極的ではありません。ただ本ソフトについては
  その性質上、実機・資料の入手が難しい過去の機種の、詳細なドキュメント・仕様書
  となり得ますので、電子保存の意味でも公開すべきだと考えます。

  またXM7の開発の過程で、M88をはじめとする多くのソフトウェアのソースを参考に
  させて頂きました。そのお礼という意味もあります。


□使用規定

  アーカイブに含まれるファイル群は、一部の例外(後述)を除きＰＩ．が著作権を保有
  しています。

  ソースファイルの一部、もしくは全部を再利用する場合は、次の規則に基づくもの
  とします。
  ・VMディレクトリ下のファイルを再利用する場合は、ドキュメントにオリジナルの
    著作権表示を明記してください。また商用利用は禁止します。
  ・それ以外の部分の再利用は自由です。ただし前項同様、商用利用は禁止します。

  このアーカイブの再配布はできません。無断転載を禁じます。


□例外、その他

  以下に示すファイルはM88の作者であるcisc氏の許可を得て、改変の上組み込んで
  いるものです。この部分については前述の規定は適用されません。

  vm\fmtimer.cpp
  vm\fmtimer.h
  vm\fmgen.cpp
  vm\fmgen.h
  vm\fmgeninl.h
  vm\fmgenx86.h
  vm\opna.cpp
  vm\opna.h
  vm\psg.cpp
  vm\psg.h


  以下に示すファイルはうさ氏の許可を得て、改変の上組み込んでいるものです。
  この部分については前述の規定は適用されません。

  win32\juliet.cpp
  win32\juliet.h
  win32\romeo.h


  以下に示すファイルは「たけがみ  りう」氏より提供を受けたコードが含まれて
  います。管理はＰＩ．が行っています。

  vm\vm_sub.asm
  vm\aluline.c
  vm\aluline.h
  vm\display.c
  vm\display.h
  vm\dmac.c
  vm\dmac.h
  vm\fdc.c
  vm\fdc.h
  vm\jcard.c
  vm\jcard.h
  vm\mmr.c
  vm\mmr.h
  vm\mouse.c
  vm\mouse.h
  vm\subctrl.c
  vm\subctrl.h
  vm\tools.c
  vm\tools.h
  win32\ddrend16.asm
  win32\ddrend24.asm
  win32\ddrend32.asm
  win32\gdi_rend.asm
  win32\w32_sub.asm
  win32\w32_gdi.c
  win32\w32_gdi.h
  win32\w32_dd.cpp
  win32\w32_dd.h
  win32\w32_kbd.cpp
  win32\w32_kbd.h
  win32\w32_snd.cpp
  win32\w32_snd.h
  win32\w32_wxp.h


□ディレクトリ

  以下のようなディレクトリ構成になっています。これは便宜的なものです。

  VM          仮想FM-7
  Win32       I/O部(Win32)
  Borland     Borlandコンパイラ向けプロジェクトファイル
  Tool        補助ツール


□定義済みシンボル

  以下のシンボルを全体で使っています。

  _DEBUG     デバッグビルドします。assertによる自己診断を行います。
  NDEBUG     リリースビルドします。通常はこちらを定義します。
  _WIN32     Win32を宣言します。(コンパイラにより自動定義されます)
  XM7_VER    バージョンを定義します。バージョンに応じ、2または3を定義します。
  MOUSE      マウスエミュレーション機能を有効にします。
  MR2        MR2のI/O型RAMディスク機能を有効にします(XM7_VER=3時のみ有効)。
  ROMEO      ROMEOサポート機能を有効にします。

  以下のシンボルはxm7.h内で宣言されています。

  FALSE      0
  TRUE       (!FALSE)
  NULL       ((void)0)
  ASSERT     _DEBUG定義時に、assertを有効にします。
  FASTCALL   Borland系のコンパイラで、レジスタ関数呼び出し規約を使います。


□ビルドの前に

  XM7本体のビルドをする場合は、VMディレクトリとWIN32ディレクトリの内容を作業
  ディレクトリにまとめてコピーしてください。次のようなツリーになります。

  ------- 本体(VM及びWIN32の内容を1つにまとめたもの)
      |
      ------- resource (アイコンリソース)

  またアセンブラとしてNASM(Netwide Assembler)が必要です。無償配布されています
  ので別途入手してください。バージョンは0.98を推奨します。


□ビルド(Borland C++ 5.5.1)

  XM7はBorlandから無償配布されているBorland C++でビルドできます。Borland C++の
  Version 5.5.1をセットアップし、さらに次の2点を設定しておきます。

  (1)nasmwにパスを通しておく
  (2)リンカのライブラリパスにlib\psdkを含める

  次にBorlandディレクトリからmakefileをコピーします。ターゲットバージョンは
  makefileの先頭で定義されていますので必要があれば変更しておきます。

  準備が出来たら、作業ディレクトリでmakeするとXM7.exeが生成されます。


□ビルド(C++ Builder 5)

  あらかじめBorlandディレクトリからXM7.bpr,XM7.bpfをコピーしておきます。

  まずNASMを使ってcpu_x86.obj, ddrend16.obj, ddrend24.obj, ddrend32.obj,
  gdi_rend.obj, w32_sub.obj, vm_sub.obj を作っておきます。
  次のコマンドラインでアセンブルし、.objが出来ていることを確認します。

  (V2をビルドする場合)
   nasmw -d _OMF -d XM7_VER=2 -f obj cpu_x86.asm
   nasmw -d _OMF -d XM7_VER=2 -f obj ddrend16.asm
   nasmw -d _OMF -d XM7_VER=2 -f obj ddrend24.asm
   nasmw -d _OMF -d XM7_VER=2 -f obj ddrend32.asm
   nasmw -d _OMF -d XM7_VER=2 -f obj gdi_rend.asm
   nasmw -d _OMF -d XM7_VER=2 -f obj vm_sub.asm
   nasmw -d _OMF -d XM7_VER=2 -f obj w32_sub.asm

  (V3をビルドする場合)
   nasmw -d _OMF -d XM7_VER=3 -f obj cpu_x86.asm
   nasmw -d _OMF -d XM7_VER=3 -f obj ddrend16.asm
   nasmw -d _OMF -d XM7_VER=3 -f obj ddrend24.asm
   nasmw -d _OMF -d XM7_VER=3 -f obj ddrend32.asm
   nasmw -d _OMF -d XM7_VER=3 -f obj gdi_rend.asm
   nasmw -d _OMF -d XM7_VER=3 -f obj vm_sub.asm
   nasmw -d _OMF -d XM7_VER=3 -f obj w32_sub.asm

  次にBorland C++ Builderを起動し、プロジェクトファイルXM7.bprをロードします。
  プロジェクト(P)→オプション(O)→ディレクトリ/条件タブでXM7_VERが正しく定義さ
  れていることを確認してください。okならプロジェクト(P)→メイク(M)でXM7.exeが
  生成されます。

  コンパイラの警告レベルを最大にしているためいくつかWarningが出ますが、いずれ
  も無視できるものです。通常の警告レベルでは、FM音源ユニットのごく一部を除き
  Warningはありません。

  ただし、微妙なコンパイルオプションやライブラリ順序の違いにより、無償配布版の
  Borland C++ 5.5.1 と全く同じオブジェクトが出力されるわけではありません。動作
  としては同じです。


□ビルド(Visual C++)

  まずNASMでアセンブルします。Borland系とはコマンドラインが異なりますので注意
  してください。

  (V2をビルドする場合)
  nasmw -d _WIN32 -d XM7_VER=2 -f win32 cpu_x86.asm
  nasmw -d _WIN32 -d XM7_VER=2 -f win32 ddrend16.asm
  nasmw -d _WIN32 -d XM7_VER=2 -f win32 ddrend24.asm
  nasmw -d _WIN32 -d XM7_VER=2 -f win32 ddrend32.asm
  nasmw -d _WIN32 -d XM7_VER=2 -f win32 gdi_rend.asm
  nasmw -d _WIN32 -d XM7_VER=2 -f win32 vm_sub.asm
  nasmw -d _WIN32 -d XM7_VER=2 -f win32 w32_sub.asm

  (V3をビルドする場合)
  nasmw -d _WIN32 -d XM7_VER=3 -f win32 cpu_x86.asm
  nasmw -d _WIN32 -d XM7_VER=3 -f win32 ddrend16.asm
  nasmw -d _WIN32 -d XM7_VER=3 -f win32 ddrend24.asm
  nasmw -d _WIN32 -d XM7_VER=3 -f win32 ddrend32.asm
  nasmw -d _WIN32 -d XM7_VER=3 -f win32 gdi_rend.asm
  nasmw -d _WIN32 -d XM7_VER=3 -f win32 vm_sub.asm
  nasmw -d _WIN32 -d XM7_VER=3 -f win32 w32_sub.asm

  次にVisual C++のIDEを起動、アプリケーションウィザードで"Win32 Application"
  初期設定は"空のプロジェクト"を選んでXM7のプロジェクトを作成します。

  プロジェクト作成後、ワークディレクトリの.c、.cpp、.rcをすべてプロジェクトに
  追加します。またnasmにより生成されたcpu_x86.obj, ddrend16.obj, ddrend24.obj,
  ddrend32.obj, gdi_rend.obj, vm_sub.obj, w32_sub.obj も追加します。

  あとはシンボルXM7_VERを定義し、ビルドすればokです。ライブラリは次のものをリ
  ンクする必要があると思われます。

  kernel32.lib user32.lib gdi32.lib comctl32.lib comdlg32.lib shell32.lib
  winmm.lib imm32.lib ddraw.lib dinput.lib dsound.lib dxguid.lib


□補助ツール

  ROM作成ツールSAVEROM(2)は、FM77AV上で動作する部分(6809アセンブラで記述)と、
  起動ディスクを作成する部分(8086アセンブラで記述)に分かれています。

  6809アセンブラ部は次のツールで作成します。
      HD63C09/6809 クロスアセンブラ AS63.EXE Version 1.20T
  8086アセンブラ部は次のツールで作成します。
      Netwide Assembler 0.98

  メイクはBorland C++に付属のmake.exeを使うと良いでしょう。正常にメイクされ
  ると、SAVEROM.COM/SAVEROM.BIN(XM7 V2・FM77AVシリーズ全機種用 2D版),SAVEROM
  2.COM/SAVEROM2.BIN(XM7 V3・FM77AV20/40/EX/SX用 2DD版),SAVEROM7.COM/SAVEROM
  7.BIN(XM7 V1・FM-7シリーズ全機種用 2D版)が生成されます。

  AS63のオプティマイズ機能を使い、6809のブランチはロングブランチ主体で記述
  しています。アセンブル時にショートで届くものはショートに変換されます。


□ソースコード ガイド

  XM7のアーキテクチャ、プログラム構造を簡単に説明します。

  XM7はVMと呼ぶ仮想FM-7部と、実際のI/Oエミュレーションを担当するWin32部の2つ
  に分離されています。仮想FM-7の部分は移植性、汎用性を高める方向で作ってあり
  ますので、他のCPU、OSへの移植は比較的容易です。ただし6809CPUコアについては
  性能向上のためx86アセンブラで記述していますので、他のCPUに移植する場合はCPU
  コアを別途準備する必要があります。

  基本的なVMの使い方は次の通りです。
  (1)初期化
     ワークエリアを初期化し、ROMファイルをロードします。失敗するとFALSEを返し
     ます。
     #include "xm7.h"
     ....
     if (!system_init()) {
       (エラー処理)
     }
  (2)リセット
     VMの初期化が終わったら、リセットします。これは実機でのパワーオンリセット
     に相当する処理です。
     #include "xm7.h"
     ....
     system_reset();
  (3)実行
     VMはus単位の仮想時間を持っており、この時間に基づいてCPUやデバイスが動い
     ていきます。つまりこの時間を進めるという操作が、実行にあたります。
     実行するとメモリ、レジスタ等のワークエリアが変化し、後述するnotify系の関
     数が必要に応じて呼び出されます。
     #include "xm7.h"
     ....
     /* 1ms、VMを実行する例 */
     DWORD us = 1000;
     while (us > 0) {
       us -= schedule_exec(us);
     }
  (4)終了
     メモリの解放など、後片付けを行います。
     #include "xm7.h"
     ....
     system_cleanup();

  VMはROMファイル、ディスクイメージ(D77ファイル等)、XM7ファイル等のファイルI/O
　が必要になると、device.hで宣言されているfile_系の関数を呼び出し、ファイルア
　クセスを要求します。

  またVRAM変更、パレット変更、OPNへのレジスタ出力が発生すると、同じくdevice.h
  に宣言されているxxxxx_notify系の関数を呼び出します。プラットフォーム側では
  notifyを受け、適宜処理を行います。

  キーボード、ジョイスティックおよびマウスについては、VMに通知またはVMからの
　データ要求に対してデータを引き渡す形になります。キーボードについてはkeyboa
　rd_make、keyboard_breakの2つの関数でキーのMake/Breakを通知します。ジョイス
　ティックはjoy_requestが、マウスはmospos_request/mosbtn_requestがVMから呼び
　出されますので、プラットフォーム側でデータを作成、返します。

  実際のエミュレータの実装では、リアルタイム処理を実現するためプラットフォーム
  側の時間を計時し、それに見合った時間だけVMを駆動することになります。駆動の
  合間でnotifyの処理、キーボードデータの通知などを行うことになります。このため
  別にスケジューラが必要となり、時間処理は2層構造となります。


  Win32側ではw32_main.cで上に述べた初期化、リセット、終了処理を行っています。

  スケジューラはw32_sch.cにあり、timeGetTime APIを用いて時間計測を行うととも
  に、時間オーバーの場合の処理や、描画・入力・波形合成などのサブモジュールの呼
  び出しも行っています。

  描画はw32_draw.cにあり、実際の処理はw32_gdi.cまたはw32_dd.cppに振り分けてい
  ます。VRAMからビットイメージ、カラーを作る部分(レンダリング)はgdi_rend.asmと
  dd_rend.asmにありますが、同様のアルゴリズムを実装したものがVMのtool.cにBMP
  セーブ機能としてありますので、こちらも参考にしてください。

  入力処理はw32_kbd.cppです。DirectInputを用いてキーボード・ゲームコントローラ・
　マウスの取得を行い、上に述べたAPIを使ってVMと通信しています。

  波形合成はw32_snd.cppにあり、DirectSoundを使った音声出力を行っています。スト
  リーミングは典型的なダブルバッファ処理を行い、標準設定では75msごとにバッファ
  の半充填を行う仕様としています。


□連絡先

  ホームページ
  http://www.ipc-tokai.or.jp/~ytanaka/ (本家)
  http://retropc.net/ryu/xm7/ (誰も見ないXM7改のぺーじ)

  公式掲示板
  http://cgi.ipc-tokai.or.jp/~ytanaka/cgi-bin/xm7/hyperbbs.cgi

  メールアドレス
  ＰＩ．氏 : ytanaka@ipc-tokai.or.jp
  たけがみ : ryu.takegami@mbg.nifty.com
