2016年12月18日日曜日

ゲーム機エミュレータの技術的な話

割と古めのエミュレータのソースコードを眺めてみて、プラットフォーム依存(主にWindows依存)の実装がモリモリと入っているものが多いなと。

エミュレータのコア部分は、必ずしもプラットフォームに依存する必要はなくて、Cの標準ライブラリやC++のSTLだけで実装できるものです。

何処までがプラットフォーム非依存(PIL)で、何処からがプラットフォーム依存(PDL)か。
その線引は、以下のようになります。

【プラットフォーム非依存】(PIL)
・CPUなどのエミュレーション全般
・プラットフォーム依存(PDL)間のブリッジ

【プラットフォーム依存】(PDL)
・映像出力
・音声出力
・入力機器からの入力

コードで書いた方が分かり易いので、LaiNESというファミコンエミュレータの実装をベースに見てみると分かり易いです。

オリジナルのLaiNESは、PIL と PDL が若干入り乱れているので、純粋な PIL だけを切り離した LaiNES を私の方で作ってみました。
https://github.com/suzukiplan/LaiNES

上記のSUZUKI PLANカスタム版LaiNESは純粋なPILのみ実装している キレイなエミュレータ なので、ターミナル上でファミコンを動かすこともできてしまいます。上記リポジトリのtest.cppが実際にターミナル上でファミコンを動かすプログラムの例です。
// this is a dummy code for checking the linkage
#include <stdio.h>
#include "cartridge.hpp"
#include "apu.hpp"
#include "cpu.hpp"
#include "hal.hpp"
int main(int argc, char* argv[]) {
if (argc < 2) {
puts("usage: a.out rom_file");
return 1;
}
// note: need initialize APU before load rom
APU::init();
// load rom file
puts("loading");
FILE* f = fopen(argv[1], "rb");
if (!f) {
puts("file not found");
return 2;
}
fseek(f, 0, SEEK_END);
int size = ftell(f);
fseek(f, 0, SEEK_SET);
u8* rom = new u8[size];
fread(rom, size, 1, f);
fclose(f);
Cartridge::load(rom, size);
if (!Cartridge::loaded()) {
puts("load error");
return 2;
}
// execute 60 frame
for (int i = 0; i < 60; i++) {
puts("execute 1 frame");
CPU::run_frame();
}
return 0;
}
// these function will callbacked by CPU (CPU::run_frame function)
namespace HAL {
u8 get_joypad_state(int n) {
printf("get_joypad_state: %d\n", n);
return 0; // return joypad state
}
void new_frame(u16* pixels) {
// set pixels to graphic-module
printf("new_frame: %p\n", pixels);
}
void new_samples(const blip_sample_t* samples, size_t count) {
// set samples to sound-module
printf("new_samples: %p, %ld\n", samples, count);
}
}
view raw test.cpp hosted with ❤ by GitHub

ファミコンを動かすといっても、ターミナル上でPDL(の全て)を再現するのは厳しいので、PDL部分(namespace HALの部分の実装)はダミーですが。

それだとあんまりなので、このSUZUKI PLANカスタム版LaiNESを用いてAndroidでPDLを実装してみた例も作ってみました。
https://github.com/suzukiplan/nes-view-android

なお、動作についてはPublic DomainのROMで確認してます。

0 件のコメント:

コメントを投稿

注: コメントを投稿できるのは、このブログのメンバーだけです。

合理的ではないものを作りたい

ここ最近、実機版の東方VGSの開発が忙しくて、東方VGSの曲追加が滞っています。 東方VGS(実機版)のデザインを作りながら検討中。基本レトロUIベースですがシークバーはモダンに倣おうかな…とか pic.twitter.com/YOYprlDsYD — SUZUKI PLAN (...