実行速度が速く、ポータブルであることを目標に書きました。
C++のクラスになっており、複数のZ80CPUを持つマシンを簡単に実装できます。
ビッグエンディアン/リトルエンディアンどちらのホストでも使用できます。
https://github.com/kwhr0/Z80
version2.20の変更点
Execute()で、HALT命令実行時は0を返すように変更
オーバーフロー時、P/Vフラグが正しくないことがある不具合を修正
version2.10の変更点
スリープ機能を追加。具体的には、HALT命令実行時に割込みを受け付けた場合以外は実行ループを抜けるように変更
version2.00の変更点
Z80バイナリを実行中に別スレッドからINT/NMIをリクエストできるように変更
POP AFとEX AF,AF'でFレジスタの第3/第5ビット(X/Yフラグ)が常に0になる不具合を修正(これらのフラグに演算結果を反映しないのは仕様)
Rレジスタのインクリメントタイミングを修正
version1.10の変更点
64ビット環境のサポート。Xcode6.1.1で動作確認しています。
version1.04の変更点
OUTI/OUTD/OTIR/OTDR命令で、出力前にBレジスタをデクリメントするように修正
使い方
その他のメソッド
未定義命令および未定義のフラグ変化のサポート
昔話
1995年のこと。私は68kMac用にPC-8001エミュレータを作り始めました。
PC-8001は自分が触れた初めてのコンピュータで、当時の感覚を忘れたくないという一心でした。
ところが当時、68(LC)040で十分な速度を出せるZ80エミュレータのソースが手に入りませんでした。
# PowerMacintosh発売後だが家にあったのはLC630だった
遅い原因は、使われるかどうか分からないフラグ変化を命令ごとに全て計算することです。
これが、各命令のフラグ変化以外の処理に比べてかなり重いのです。
そこで、フラグの計算を実際に使用されるまで遅延する方法を思いつき、実装したのがこのZ80エミュレータの初版です。
これで、68kで実機より少し遅い程度、初代PowerMacintoshでは実機より速いエミュレーションができるようになりました。
公開版は、リトルエンディアンのホストにも対応するように改良したものです。
Intel / Apple Silicon Mac用PC8001エミュレータ
OS X Lion以降、Rosettaが無くなって下のMacintosh用PC8001エミュレータが走らなくなって悲しいので、
上記Z80エミュレータversion1.10を使ってCocoaで作り直しました。
アプリケーションと同じフォルダにpc8001.romファイルを置いて起動します。
cmtファイルを開けます。ただし、編集してもセーブできません。
新規で作成したドキュメントと拡張子が.8001の下記Mac8001と同じ独自フォーマットのとき、cmd+Sでセーブできます。
単にウィンドウを閉じるとダーティでもそのまま閉じてしまいます。
新機能として、キースキャンがないときのCPUクロックを通常時とは別に指定し、加速できるようにしました。
これにより、BASICで書かれた思考ルーチン等の処理時間を短縮できます。
ちなみに、BASICではSTOPキー、ESCキーを常時スキャンしているので、それらを含むポート9を除く、ポート0〜8がしばらく読まれないときに加速します。
Z80エミュレータのクロックカウント機能を使って、BEEP音も実装しました。
BEEP音でメロディーを奏でる場合、DMAのために音が濁っていましたが、これもなんとなく再現しています。
out 81,0で画面を消すと濁らなくなります。
Mac8001は画面描画を全てCPUでやっていましたが、Cocoa8001ではOpenGLを使っており、
CPU使用率はウィンドウ1枚、クロック4MHz設定で7%程度で済みます(MacMini2011/i7)。
(2016/10/30更新)
サウンド処理を軽量化
(2018/09/16更新)
インテルヘキサを開けるようになりました。この場合の動作は以下のようになります。
(1) ROMは読み込まず、インテルヘキサに含まれるバイナリだけを実行します。
(2) CVDisplayLinkにより、いわゆるVSync割込みを発生します。その際、データバスには0xffを乗せます。
(3) 開いているウィンドウがこれ一枚だけの場合、アプリケーションがアクティブになるときにリロードします。
(4) ファイル名に"_r."を含む場合、反時計回りに90度回転した縦画面になります。
初期設定にBeep Musicを追加しました。これをONにするとポート40hの第5ビットを2.4kHzでゲートせずにそのまま出力します。
これは80年代の雑誌に載っていた本体改造で、音楽演奏ソフトで綺麗な音を出すためのものです。
この場合はさらにDMAのために音が濁る処理を切り、画面が出ている状態でも綺麗な音で演奏できるようにしました。
ただし、通常のBEEPはクリックノイズのようになります。
その他の修正:
セーブ時にハングする不具合を修正
複数のウィンドウを整列する機能を追加
画面更新がないときの消費電力を低減
出力ポート90hにSN76489Aを実装
DMAコントローラを部分的に実装
プリンタ出力を標準出力に変更
(2018/10/07更新)
タイムプロファイラ機能を追加
Z80エミュレータのスリープ機能により、不必要な電力を削減
OS X 10.6で正常に実行できない不具合を修正
Cocoa8001(OS X 10.6以上)
このアプリケーションにより何らかの損害を受けた場合、作者はその責を負いません。
(2019/08/18更新)
GitHubに公開するためソースを整理し、64ビットのみになりました。
32ビットマシンでは上の旧版をご使用ください。
ゲームパッドに対応してみました。PS4のゲームパッドのみ確認しています。
上下左右と左スティックをテンキーの8246、○ボタンをxキー、×ボタンをzキーに割り当ててあります。
ソース&バイナリ
https://github.com/kwhr0/Cocoa8001/releases
Cocoa8001.appと同じフォルダにpc8001.romとpc8001.fonを入れて実行してください。
(2020/07/12更新)
対応OSを10.7以上に変更しました。
I/Oポート0f0hにlocalhost:10023を相手とする通信機能を実装しました。
描画にMetalを使用できるようになりました。
GitHubにアップしているものはOpenGL用で、以下のように変更するとMetal用になります。
(1) Cocoa8001-Prefix.pchの先頭でUSE_METALを定義する
(2) Shaders.metalのTarget Membershipで、Cocoa8001のチェックをONにする
(3) Deployment Targetを10.11にする
(4) フレームワークにMetal.frameworkとMetalKit.frameworkを追加する
(2021/05/16更新)
Apple Siliconに対応しました。
macOS 11 (Big Sur)でタイトルバーの高さが変わったことによる描画の不具合を修正しました。
Macintosh用PC8001エミュレータ
上記Z80クラスを使ったサンプルです。
無印PC8001から吸い出したROMイメージをpc8001.romという名前でアプリケーションと同じフォルダに置いて起動します。
ROMイメージを持っていない場合でも、雰囲気だけは楽しめるかも。
いろいろなマシンで試せるように、3種類用意しました。
Mac8001(68k) (version0.22)
Mac8001(PPC) (version0.22)
Mac8001(Carbon) (version0.22)
version0.22の変更点
Z80クラスversion1.03でビルド
j80用のcmtファイルを読めます。cmtファイルをMac8001のアイコンにドロップしてください。
上書きセーブすると、独自フォーマットに置き換えるのでご注意ください。
音に関しては実装していません。
スクリーンショット
ウィンドウを2枚開いて、別々のプログラムを走らせたところ。
Z80エミュレーションがクラスになっているので、複数のCPUのエミュレーションも簡単です。
エミュレーションスピード(version0.22)
下の表は、PC8001実機を4MHzとしたとき、何MHzに相当するかを表しています。
「N-BASIC入力待ち」は60fps出せる状態でも実際には画面の更新がない場合で、ほぼZ80クラスの性能を表します。
「走れ!スカイライン」(スクリーンショットの左上に映っているゲーム)は実際に60fps以上で画面更新をしている場合で、マシンの描画性能も含めた性能です。
機種 |
OS |
種別 |
画面モード |
N-BASIC入力待ち |
走れ!スカイライン |
Quadra800 |
7.5.3 |
68k |
16色 |
3.1MHz |
2.1MHz |
8500/180 |
8.1 |
PPC |
256色 |
44MHz |
23MHz |
G4/400(GBE) |
9.2.2 |
Carbon |
256色 |
130MHz |
120MHz |