MSX
は MSX Licenses Corporation の登録商標のため、製品に商標を含める等(利用)に当たっては MSX Licensing Corporation からの許諾が必要
MSX
を用いる必要があるケースでは プロジェクトEGGクリエイターズ を使った方が良さそうです(私が知る限りではこれ以外に実機 BIOS と MSX の商標を合法的に利用する手段は無いと思われます)MSX2_ROM_TYPE_NORMAL
標準ROM (16KB, 32KB)MSX2_ROM_TYPE_ASC8
ASCII8 メガロムMSX2_ROM_TYPE_ASC8_SRAM2
ASCII8 + SRAM メガロムMSX2_ROM_TYPE_ASC16
ASCII16 メガロムMSX2_ROM_TYPE_ASC16_SRAM2
ASCII16 + SRAM メガロムMSX2_ROM_TYPE_KONAMI_SCC
KONAMI SCC メガロムMSX2_ROM_TYPE_KONAMI
KONAMI 標準メガロムDirectory | Platform | Core |
---|---|---|
msx1-osx | macOS+Cocoa | MSX1 |
msx2-osx | macOS+Cocoa | MSX2+ |
msx2-android | Android | MSX2+ |
msx2-ios | iOS | MSX2+ |
msx2-dotnet | .NET Core | MSX2+ |
msx1-m5stack | M5Stack CoreS3 | MSX1 |
msx1-m5stamps3 | M5StampS3 | MSX1 |
msx2-sdl2 | SDL2 (macOS and Linux) | MSX2+ |
msx1-rpizero | RaspberryPi Zero, Zero W, Zero WH (Bare Metal) | MSX1 |
msx2-rpizero | RaspberryPi Zero, Zero W, Zero WH (Bare Metal) | MSX2+ |
msx1-rpizero2 | RaspberryPi Zero 2W (Bare Metal) | MSX1 |
msx2-rpizero2 | RaspberryPi Zero 2W (Bare Metal) | MSX2+ |
Following platform support is now planning:
Directory | Platform | Core |
---|---|---|
msx1-rpi4b | RaspberryPi 4 model B (Bare Metal) | MSX1 |
msx2-rpi4b | RaspberryPi 4 model B (Bare Metal) | MSX2+ |
msx1-dotnet-wpf | Windows .NET Framework | MSX1 |
msx2-dotnet-wpf | Windows .NET Framework | MSX2+ |
msx1-uwp | Universal Windows Platform | MSX1 |
msx2-uwp | Universal Windows Platform | MSX2+ |
msx1-win32 | Windows native x86 (32bit) | MSX1 |
msx2-win32 | Windows native x86 (32bit) | MSX2+ |
msx1-win64 | Windows native x64 | MSX1 |
msx2-win64 | Windows native x64 | MSX2+ |
msx1-win64a | Windows native ARMv8 | MSX1 |
msx2-win64a | Windows native ARMv8 | MSX2+ |
幾つかの MSX2/MSX2+ の機能はまだ実装されていません。(※一部パフォーマンスを優先して意図的に省略している機能もありますが、それらを含めて将来的に実装する可能性があります)
#include "msx2.hpp"
コンストラクタ引数にディスプレイカラーモードを指定してインスタンスを生成します。
// ディスプレイのカラーモードを指定 (0: RGB555, 1: RGB565)
MSX2 msx2(0);
// ポート 7C,7D 直叩きで OPLL (YM2413) を使いたい場合、第2引数に true を指定すれば
// FMBIOS を用いなくても OPLL のインスタンスが生成されて利用可能になります
MSX2 msx2(0, true);
ディスプレイカラーモードの指定により msx2.getDisplay()
に格納される画面表示用データのピクセル形式が RGB555 (0) または RGB565 (1) の何れかになります。
// 拡張スロットの有効化設定
msx2.setupSecondaryExist(false, false, false, true);
// 必須 BIOS (main, logo, sub) を読み込む
msx2.setup(0, 0, 0, data.main, 0x8000, "MAIN");
msx2.setup(0, 0, 4, data.logo, 0x4000, "LOGO");
msx2.setup(3, 0, 0, data.ext, 0x4000, "SUB");
// RAM の割当 (3-3)
msx2.setupRAM(3, 3);
権利者から公式 BIOS の利用と再配布がライセンスされているケースや、ご自身で吸い出した実機 BIOS を用いてプログラムを配信せずに趣味の範囲で楽しみたい場合の例を示します。
以下、Panasonic FS-A1WSX の実機 BIOS を用いる手順を示します。
// 拡張スロットの有効化設定
msx2.setupSecondaryExist(false, false, false, true);
// 漢字フォントを読み込む (optional)
msx2.loadFont(knjfnt16, sizeof(knjfnt16));
// RAM の割当 (3-0)
msx2.setupRAM(3, 0);
// 必須 BIOS (MSX2P.ROM, MSX2PEXT.ROM) を読み込む
msx2.setup(0, 0, 0, msx2p, 0x8000, "MAIN");
msx2.setup(3, 1, 0, msx2pext, 0x4000, "SUB");
// 漢字BASIC BIOS を読み込む (optional)
msx2.setup(3, 1, 2, knjdrv, 0x8000, "KNJ");
// DISK BIOS を読み込む (optional)
// ※FDCはTOSHIBA TC8566AF のみ対応
static unsigned char empty[0x4000];
msx2.setup(3, 2, 0, empty, 0x4000, "DISK"); // ラベルは必ず "DISK" & 空バッファを指定
msx2.setup(3, 2, 2, disk, 0x4000, "DISK"); // ラベルは必ず "DISK" & BIOSを指定
msx2.setup(3, 2, 4, empty, 0x4000, "DISK"); // ラベルは必ず "DISK" & 空バッファを指定
msx2.setup(3, 2, 6, empty, 0x4000, "DISK"); // ラベルは必ず "DISK" & 空バッファを指定
// FM-PAC BIOS を読み込む (optional)
msx2.setup(3, 3, 2, data.fm, sizeof(data.fm), "FM");
機種によって拡張スロットの有効化範囲、各種 BIOS ROM の配置、RAMの配置が異なり、正しい配置にしなければ正常に動作しません。(正しい配置については、各機種付属のマニュアルに記載されている筈です)
setup
の引数には次のようにパラメタを指定します。
msx2.setup(基本スロット, 拡張スロット, 開始アドレス÷0x2000, サイズ, "ラベル");
ラベルは次のように指定します。
"MAIN"
... メインBIOS (MSX2P.ROM)"SUB"
... サブROM (MSX2PEXT.ROM)"KNJ"
... 漢字ドライバ (KNJDRV.ROM)"DISK"
... ディスクBIOS (DISK.ROM)"FM"
... FM-PAC (FMBIOS.ROM)上記以外の BIOS が含まれる機種の場合、上記以外の任意の文字列を設定してください。
micro MSX2+ は、1フレーム毎にジョイパッド入力(1P/2P各)と入力キー(ASCIIコード等)を指定し、ジョイパッドの入力は 1バイト で 1P/2P のそれぞれに入力キービットをセットして指定する仕様です。
#define MSX2_JOY_UP 0b00000001
#define MSX2_JOY_DW 0b00000010
#define MSX2_JOY_LE 0b00000100
#define MSX2_JOY_RI 0b00001000
#define MSX2_JOY_T1 0b00010000
#define MSX2_JOY_T2 0b00100000
#define MSX2_JOY_S1 0b01000000
#define MSX2_JOY_S2 0b10000000
例えば、1P側のジョイパッドの上ボタン(UP)、左ボタン(LE)、トリガ1(T1)を押している状態で1フレーム動かす場合、次のように指定します。
msx2.tick(MSX2_JOY_UP | MSX2_JOY_LE | MSX2_JOY_T1, 0, 0);
MSX のジョイパッドは通常、DPAD(上下左右)と2トリガーの6ボタンの仕様のため、上位2ビット(bit-7, bit-6)の指定は無視されますが、micro MSX2+ ではそれらのボタン(S1/S2)に任意のキーアサインを行うことができます。
例えば、1P側のS1ボタン(ファミコンのスタートボタン相当)に SPACE キー、S2ボタン(ファミコンのセレクトボタン相当)に ESC キーを割り当てる場合は、次のようにセットアップしてください。
msx2.setKeyAssign(0, MSX2_JOY_S1, ' '); // SPACE キーを S1 (START) ボタンに割り当てる
msx2.setKeyAssign(0, MSX2_JOY_S2, 0x1B); // ESC キーを S2 (SELECT) ボタンに割り当てる
大半のゲームデザインでは、ジョイパッド以外のキーアサインが2つあれば問題ないものと思われます。しかし、実用プログラムなどで3つ以上のキーを利用することが不可避なケースでは、tickの第3引数にキーコードを指定する方式での実装が必要になります。
キーコードは通常 ASCII コード('A'
など)で指定できますが、一部の制御コードには特殊な割り当てがされています。
(特殊キーコード)
'\t'
: TAB'\r'
: RETURN'\n'
: RETURN0x18
: CTRL + STOP0x1B
: ESC0x7F
: DEL0xC0
: up cursor0xC1
: down cursor0xC2
: left cursor0xC3
: right cursor0xF1
: f10xF2
: f20xF3
: f30xF4
: f40xF5
: f50xF6
: f6 (shift + f1)0xF7
: f7 (shift + f2)0xF8
: f8 (shift + f3)0xF9
: f9 (shift + f4)0xFA
: f10 (shift + f5)実用的なプログラムで、上記以外のキー(HOME, SELECTなど)やより細かなキー操作を行いたい場合 tickWithKeyCodeMap
でキーコードマップを指定することも可能です。
msx2.tickWithKeyCodeMap(pad1, pad2, keyCodeMap);
keyCodeMap
は、MSXのキーマトリクスと対応する 11 bytes の unsigned char 型配列で、各要素・各 bit でキーの押下状態を指定します。
要素番号 | bit-7 | bit-6 | bit-5 | bit-4 | bit-3 | bit-2 | bit-1 | bit-0 |
---|---|---|---|---|---|---|---|---|
0 | 7 |
6 |
5 |
4 |
3 |
2 |
1 |
0 |
1 | ; |
[ |
@ |
\ |
^ |
- |
9 |
8 |
2 | B |
A |
_ |
/ |
. |
, |
] |
: |
3 | J |
I |
H |
G |
F |
E |
D |
C |
4 | R |
Q |
P |
O |
N |
M |
L |
K |
5 | Z |
Y |
X |
W |
V |
U |
T |
S |
6 | F3 | F2 | F1 | かな | CAPS | GRAPH | CTRL | SHIFT |
7 | RETURN | SELECT | BS | STOP | TAB | ESC | F5 | F4 |
8 | → | ↓ | ↑ | ← | DEL | INS | HOME | SPACE |
9 (tenkey) | 4 |
3 |
2 |
1 |
0 |
option | option | option |
10 (tenkey) | , |
. |
- |
9 |
8 |
7 |
6 |
5 |
// 適切なメガロム種別の指定が必要:
// - MSX2_ROM_TYPE_NORMAL ....... 標準ROM(16KB or 32KB)
// - MSX2_ROM_TYPE_ASC8 ......... ASCII8 メガロム
// - MSX2_ROM_TYPE_ASC8_SRAM2 ... ASCII8 メガロム+SRAM
// - MSX2_ROM_TYPE_ASC16 ........ ASCII16 メガロム
// - MSX2_ROM_TYPE_ASC16_SRAM2 .. ASCII16 メガロム+SRAM
// - MSX2_ROM_TYPE_KONAMI_SCC ... KONAMI メガロム (SCC搭載)
// - MSX2_ROM_TYPE_KONAMI ....... KONAMI メガロム
msx2.loadRom(rom, romSize, megaRomType);
msx2.insertDisk(driveId, data, size, true); // write protect
msx2.insertDisk(driveId, data, size, false); // writable
msx2.ejectDisk(driveId);
FDのアクセスには時間が掛かるため、セクタ読み込みや書き込みのタイミングでアクセスランプの点灯やバイブレーション等の実装をすることが望ましいです。
msx2.fdc.setDiskReadListener(this, [](void* arg, int driveId, int sector) {
// ディスクが1セクタ読み込まれるタイミングでコールバック
});
msx2.fdc.setDiskWriteListener(this, [](void* arg, int driveId, int sector) {
// ディスクへ1セクタ書き込まれるタイミングでコールバック
});
// リセット
msx2.reset();
// 1フレーム実行 (キー入力は1フレームに1キーのみ送信で十分な場合)
msx2.tick(pad1, pad2, key);
// 1フレーム実行(キー入力にコードマップを用いる場合)
msx2.tickWithKeyCodeMap(pad1, pad2, keyCodeMap);
// 1フレーム実行後の音声データを取得 (44100Hz 16bit Stereo)
size_t soundSize;
void* sound = msx2.getSound(&soundSize);
// 1フレーム実行後の映像を取得
// - Size: 568(width) x 240(height) x 2(16bit-color)
// - Color: RGB555 or RGB565 (コンストラクタで指定したもの)
unsigned short* display = msx2.getDisplay();
int displayWidth = msx2.getDisplayWidth(); // 568
int displayHeight = msx2.getDisplayHeight(); // 240 (※将来的にインタレース対応時に480になる可能性がある)
// セーブ
size_t size;
const void* saveData = msx2.quickSave(&size);
// ロード
msx2.quickLoad(saveData, size);
フロッピーディスクの挿入状態は記憶されますが、挿入データの復元はされないため、復元のための追加実装が必要です。
まず、挿入されていたフロッピーディスクはCRC符号のみFDCコンテキストに記憶されています。
msx2.fdc.ctx.crc[driveId]
このコンテキスト情報を参照して、次のような手順でディスク挿入状態の復元を行ってください。
msx2.quickLoad
でクイックロードmsx2.fdc.calcDiskCrc
で上記CRC符号と一致するディスクを探索msx2.insertDisk
で挿入for (int driveId = 0; driveId < 2; driveId++) {
for (int i = 0; i < MY_DISK_NUM; i++) {
auto crc = msx2.fdc.calcDiskCrc(myDisks[i].data, myDisks[i].size);
if (crc == fdc.ctx.crc[driveId]) {
msx2.insertDisk(driveId, myDisks[i].data, myDisks[i].size, true);
break;
}
}
}
msx2.insertDisk
の第4引数 readOnly
を false
にすることで書き込み可能ディスクとして挿入できます。
msx2.insertDisk(driveId, myDisk.data, myDisk.size, false);
micro MSX2+ では、ディスクの書き込み状態は、ディスク(CRC)のセクタ番号(絶対セクタ番号)単位でジャーナル (JCT) に記憶します。
JCT は、クイックセーブ時に各セクタの最新情報のみが記憶され、クイックロード時にオンメモリで復元されます。
JCT が存在する場合 msx2.insertDisk
が行われた時に自動的にオンメモリのディスクキャッシュに反映されます。
つまり、何も考えずに quick save/load して
msx2.insertDisk
すればディスクの更新状態も自動的に復元されます。 しかし、ストレージ上のオリジナルのディスクファイル(.dsk)への変更内容の commit (.dskファイルの更新) は行われません。
セーブデータサイズは可変で、以下のデータを LZ4 で高速圧縮しています。(無風時の圧縮後サイズは5KBほど)
LZ4 解凍後のセーブデータは、
という形式になっていて、チャンク情報には以下の種類があります。
Chunk | Size in Byte | Optional | Describe |
---|---|---|---|
BRD |
260 | n | VMコンテキスト |
Z80 |
40 | n | CPUコンテキスト(レジスタ等) |
MMU |
48 | n | メモリ管理システム(スロット)のコンテキスト(レジスタ等) |
SCC |
204 | y | Sound Creative Chip(コナミ音源)のコンテキスト |
PSG |
108 | n | AY-3-8910(PSG音源)のコンテキスト |
RTC |
104 | n | クロックICのSRAM+コンテキスト |
KNJ |
12 | n | 漢字制御システムのコンテキスト |
VDP |
131,288 | n | V9958(Video Display Processor)のRAM+コンテキスト |
FDC |
544 | y | フロッピディスク制御装置 (TC8655AF) のコンテキスト |
JCT |
4 | y | フロッピの書き込みセクタジャーナル |
JDT |
520 x JCT | y | フロッピの書き込みデータ(セクタ単位) |
OPL |
4,280 | y | FM音源システム(YM2413)のコンテキスト |
SRM |
8,192 | y | メガROMカートリッジSRAM |
PAC |
8,192 | n | FM-PACのSRAM |
R:0 |
65,536 | n | マッパー0 RAM |
MSX2/2+ は古いパソコンの割に要求スペックが大きく、例えば IoT 機器などで使われている Arduino や ESP32 など、搭載メモリ容量が小さく CPU も遅い組み込み用マイクロプロセッサ向けのエミュレーションはとても困難です。
そこで、MSX2/2+ と比較して要求スペックがかなり低い MSX1 に絞ったコアモジュールも併せて提供しています。
詳しい使い方は M5Stack 版サンプルの app.cpp でご確認ください。
基本的な使い方は MSX2/2+ とほぼ同じですが、ROM カートリッジ以外の外部メディア、OPLL、SCC などは非サポートとしています。
micro MSX2+ には次のソフトウェアが含まれています。
利用に当たっては、著作権(財産権)及び著作者人格権は各作者に帰属する点の理解と、ライセンス条項の厳守をお願いいたします。
Copyright (c) 2011-2020, Yann Collet
Copyright (c) 2002-2005 BouKiCHi. All rights reserved.
Copyright (c) 2003 Reikan. All rights reserved.
Copyright (c) 2004-2006,2008-2010 Maarten ter Huurne. All rights reserved.
Copyright (c) 2004-2006,2008-2011 Albert Beevendorp. All rights reserved.
Copyright (c) 2004-2005 Patrick van Arkel. All rights reserved.
Copyright (c) 2004,2010-2011 Manuel Bilderbeek. All rights reserved.
Copyright (c) 2004-2006 Joost Yervante Damad. All rights reserved.
Copyright (c) 2004-2006 Jussi Pitkänen. All rights reserved.
Copyright (c) 2004-2007 Eric Boon. All rights reserved.
Copyright (c) 2001-2019 Mitsutaka Okazaki
Copyright (c) 2019 Yoji Suzuki.
Copyright (c) 2023 Yoji Suzuki.