Z80エミュレータライブラリは、コンパイル時に2つのモードのどちらかを選びます。
非テンプレートモードでは、一般的なオブジェクト指向形式のクラスライブラリが生成されます。
ライブラリ利用者は、中核となるCPUエミュレータクラスCZ80を派生させ、独自のインプリメントを施すことになります。
CZ80およびその派生クラスのオブジェクトは同時に複数存在させることができます。このため、マルチCPU環境のエミュレートも簡単に実装可能です。
非テンプレートモードは扱いは簡単ですが、速度はテンプレートモードに譲ります。
テンプレートモードでは、スピードアップのために最適化を施されたクラスライブラリが生成されます。
速度は非テンプレートモードより高速ですが、やや扱いが難しくなっています。
中核となるCPUエミュレータクラスはCZ80_1で、これを派生させて利用するのは非テンプレートモードとほぼ同様ですが、クラスのメンバ変数/関数がほぼ全てstaticと宣言されているのが最も大きく異なる点です。
また、メモリ及びI/Oアクセスのための関数の実装方法が、非テンプレートモードと違いブロック単位で指定可能です。Z80のようなアドレス空間が狭いスペックで多く利用されていたメモリバンク切り替えが、効率良く実装できます。
ただし、メンバ変数がstatic宣言されているため、非テンプレートモードはそのままでは複数のCPUオブジェクトを同時実行させることができません。2つ目のCPUを動作させたい場合、全く同等の機能を持つCZ80_2を利用することになります。
さらに多くのCPUを同時実行させる場合には、CZ80_3、CZ80_4…と新しいクラスを定義しなければいけません。新たなCPUクラス定義はごくわずかな作業で追加することができます。
なお、非テンプレートモードのマルチCPU環境では各CPUが異なる基本クラスを持つため、CPUオブジェクトを包括的に扱うことができません。このため、CZ80Adapterクラスが用意されています。
クラスライブラリをご利用の前に、以下の作業を行っておく必要があります。
Z80エミュレータライブラリが利用する標準Cライブラリのインクルード、およびいくつかの型定義を行うためのヘッダがStdHeader.hです。
(ライブラリにはZ80Sample1用に設定されたものが付属しますので、必要に応じて変更してください)
利用する標準Cライブラリは、VisualC++では以下のヘッダに含まれてますが、コンパイラによっては異なるヘッダをインクルードする必要があるかもしれません。
stdio.h : NULL, vsprintf
string.h : strcpy
stdarg.h : va_list, va_start, va_end
また、以下の符号あり/なし整数が必要です。
uint8_t : 8ビット幅符号なし整数
int8_t : 8ビット幅符号あり整数
uint16_t : 16ビット幅符号なし整数
int16_t : 16ビット幅符号あり整数
uint32_t : 32ビット幅符号なし整数
int32_t : 32ビット幅符号あり整数
stdint.hが存在する場合、インクルードすれば宣言の必要はありません。
VisualC++/BorlandC++等のWindows系コンパイラでは、以下のように宣言してください。
typedef unsigned char uint8_t;
typedef signed char int8_t;
typedef unsigned short uint16_t;
typedef short int16_t;
typedef unsigned int uint32_t;
typedef int int32_t;
ヘッダーファイルZ80Config.h内で、コンパイル時のオプションを指定するマクロが記述されています。作成するプログラムの種類によっては、これを変更する必要があります。
Z80CFG_LITTLE_ENDIAN / Z80CFG_BIG_ENDIAN
エミュレータを実行するCPUのエンディアンを指定します。
x86系はリトルエンディアン、68000/PowerPC系はビッグエンディアンになります。
Z80CFG_IOADDR_WIDTH_8 / Z80CFG_IOADDR_WIDTH_16
Z80のI/Oアドレス空間は本来8ビットなのですが、上位8ビットにも値が出力されることを利用して16ビットI/Oアドレス空間を使っていたマシンがあったようです(確かSMC-70だったような…)
このオプションはそういった機種のためのものですので、通常は8ビット幅で問題ありません。
# 8ビットしか試してないです(^^;)
Z80CFG_NOUSE_FLAGTBL / Z80CFG_USE_FLAGTBL
演算処理のフラグ変化を、その場で計算するか、事前に計算してテーブルに格納しておくかを指定します。
事前計算の方が効率的ですが、300KB弱のメモリを消費します。
また、CPUキャッシュが効きにくくなる可能性もあります。
コンパイルオプションを変更しても、利用方法は全く変わりません。
Z80CFG_NOUSE_TEMPLATE / Z80CFG_USE_TEMPLATE
ライブラリの非テンプレートモード/テンプレートモードを選択します。
(前項を参照)
テンプレートモードのCPUクラスCZ80_1/CZ80_2の実体は、特殊化されたクラステンプレートTZ80です。
これらを継承して利用する前に、テンプレートパラメータを設定する必要があります。
Z80Template.hには、通常以下のような2行があります。
#define CZ80_1 TZ80<1, 4096, 1>
#define CZ80_2 TZ80<2, 4096, 1>
最初の数字は、CPUの通し番号を示す数字です。これは変更しないでください。
2番目の数字は、メモリアドレスブロックのバイト数を指示します。例えば4096とした場合、アドレス0000Hから4KB毎が別ブロックとなり、64KBのアドレス空間が16ブロックに分かれます。各ブロックには別々のメモリアクセス関数を用意することができます。(実行中に動的に変更可)
3番目の数字は、I/Oアドレスブロックのバイト数を指示します。通常、I/Oポートは個別にアクセス関数を用意することになりますから、ブロックサイズは1になるでしょう。
また、3つ以上のCPUを同時実行させる場合には、CZ80_3等のクラスの追加が必要です。
この場合は、Z80Template.hにCZ80_3のエントリを追加したあと(通し番号はCZ80_3のときは必ず3とすること)、同時にZ80_2.cppをコピー/修正してZ80_3.cppを作成し、プロジェクトへ追加してください。
逆に、CPUを1つしか使用しない場合には、Z80Template.h内のCZ80_2エントリをコメントアウトするとコンパイル時間が短縮されます。