1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

MSXPi対応openMSXをRaspberry pi用にビルドした話

Last updated at Posted at 2025-12-15

はじめに

MSXPiはRaspberry piを搭載したMSX用カートリッジで、MSXからRaspberry pi上のLinuxにアクセスしたり、さらには、Raspberry piを介してインターネット上のサービスを利用できるようになります。

実際にMSXPiを組み立てましたが、ファームウェアの書き込みなどの作業が終わっていません。

組み立てと並行して、エミュレーター上でMSXPiの動作を確認し、自分用のサービスを導入していきたいと計画しています。
この記事では、MSXPiの動作するopenMSXをビルドする方法を紹介します。

openMSX

openMSXはMSXのエミュレータで、本体のBIOSや周辺機器のファームウェアを指定することで、様々な周辺機器を搭載したMSXをエミュレートすることができます。

接続するデバイスの情報をopenMSXの含めてビルドすることで、デバイスの機能を利用することが可能です。
Raspberry pi OS上でパッケージ管理ソフトを使ってインストールしたopenMSXは、MSXPiを認識しませんので、ソースファイルからビルドする必要があります。

Linuxマシン上でのビルド

Raspberry pi 4上で利用するために、ソースファイルからビルドしました。
使用するソースファイルはMSXPi対応のものを使用します。

「openmsx-21.0-7-MSXPi」を使用しました。
始めに必要なライブラリをインストールします。

 sudo apt install libglew-dev libogg-dev libtheora-dev libvorbis-dev libsdl2-ttf-dev tcl-dev libpng-dev libsdl2-dev

openMSXのディレクトリで

./configure

とすると、環境構築ができているか確認できます。
例えば、以下のような表示です。

Using Python: python3
Probing target system...
Creating derived/aarch64-linux-opt/config/probed_defs.mk...
Up to date: derived/aarch64-linux-opt/config/systemfuncs.hh

Found libraries:
  ALSA:             version 1.2.8
  FreeType:         version
  GLEW:             version unknown
  libogg:           version unknown
  libpng:           version 1.6.39
  libtheora:        version unknown
  libvorbis:        version unknown
  OpenGL:           version 4.6
  SDL2:             version 2.26.5
  SDL2_ttf:         version 2.20.1
  Tcl:              version 8.6.13
  zlib:             version 1.2.13

Components overview:
  Emulation core:   yes
  GL renderer:      yes
  Laserdisc:        yes
  ALSA MIDI:        yes

Customisable options:
  Install to        /opt/openMSX
  (you can edit these in build/custom.mk)

All required and optional components can be built.

If the detected libraries differ from what you think is installed on this system, please check the log file: derived/aarch64-linux-opt/config/probe.log

##ソースファイルの修正
使用するgccのバージョンが9以上の場合、ソースファイルの修正が必要です。
修正箇所は、この記事下のパッチファイルを参照してください。
ソースファイルの修正後にビルドするしてインストールすることで、MSXPiをデバイスとして認識するopenMSXを起動できるようになります。

おわりに

MSXPiに対応したopenMSXのソースファイルを修正して、Raspberry piでの動作に成功しました。
MSXPiを動作させる場合、他の周辺機器と同様、ROMファイルの「msxpibios.ro」をopenMSXのshare->systemroms内に、設定ファイルの「MSXPi.xml」をopenMSXのshare->extensionsに保存します。
MSXの起動に成功したら、raspberry pi側で動作するサーバーの設定を行います。

付録

今回使用したパッチファイルです。
「static constexpr」を「static const」に修正します。

--- a/src/cassette/CassettePlayer.cc
+++ b/src/cassette/CassettePlayer.cc
@@ -215,16 +215,16 @@
 		// for instance)
 		"    after time 0.2 \"type [lindex $args 0]\"\n"
 
-		"    set next [lrange $args 1 end]\n" // Note: this is a list of lists
+		"    set next [lrange $args 1 end]\n"
 		"    if {[llength $next] == 0} return\n"
 
 		// H_READ is used by some firmwares; we need to hook the
 		// H_MAIN that happens immediately after H_READ.
 		"    set cmd \"openmsx::auto_run_cb $next\"\n"
 		"    set openmsx::auto_run_bp [debug set_bp ", H_MAIN, " 1 \"$cmd\"]\n"
-		"  }\n" // auto_run_cb
+		"  }\n"
 
 		"  if {[info exists auto_run_bp]} {debug remove_bp $auto_run_bp\n}\n"
 		"  set auto_run_bp [debug set_bp ", H_READ, " 1 {\n"
 		"    openmsx::auto_run_cb {{}} ", instr1, ' ', instr2, "\n"
--- a/src/config/HardwareConfig.cc
+++ b/src/config/HardwareConfig.cc
@@ -20,7 +20,7 @@
 #include <algorithm>
 #include <array>
 #include <cassert>
-//#include <iostream>
+#include <iostream>
 #include <memory>
 #include <version> // for _LIBCPP_VERSION
 
--- a/src/DebugDevice.cc
+++ b/src/DebugDevice.cc
@@ -12,7 +12,7 @@
 #include "strCat.hh"
 
 #include <iomanip>
-//#include <iostream>
+#include <iostream>
 
 namespace openmsx {
 
--- a/src/fdc/DriveMultiplexer.cc
+++ b/src/fdc/DriveMultiplexer.cc
@@ -131,7 +131,7 @@
 }
 
 
-static constexpr std::initializer_list<enum_string<DriveMultiplexer::Drive>> driveNumInfo = {
+static const std::initializer_list<enum_string<DriveMultiplexer::Drive>> driveNumInfo = {
 	{ "A",    DriveMultiplexer::Drive::A },
 	{ "B",    DriveMultiplexer::Drive::B },
 	{ "C",    DriveMultiplexer::Drive::C },
--- a/src/fdc/NowindHost.cc
+++ b/src/fdc/NowindHost.cc
@@ -16,7 +16,7 @@
 #include <cctype>
 #include <cstdarg>
 #include <cstdio>
-//#include <ctime>
+#include <ctime>
 #include <fstream>
 #include <memory>
 #include <ranges>
--- a/src/fdc/TC8566AF.cc
+++ b/src/fdc/TC8566AF.cc
@@ -480,7 +480,7 @@
 }
 
 
-static constexpr std::initializer_list<enum_string<TC8566AF::Command>> commandInfo = {
+static const std::initializer_list<enum_string<TC8566AF::Command>> commandInfo = {
 	{ "UNKNOWN",                TC8566AF::Command::UNKNOWN                },
 	{ "READ_DATA",              TC8566AF::Command::READ_DATA              },
 	{ "WRITE_DATA",             TC8566AF::Command::WRITE_DATA             },
@@ -499,7 +499,7 @@
 };
 SERIALIZE_ENUM(TC8566AF::Command, commandInfo);
 
-static constexpr std::initializer_list<enum_string<TC8566AF::Phase>> phaseInfo = {
+static const std::initializer_list<enum_string<TC8566AF::Phase>> phaseInfo = {
 	{ "IDLE",         TC8566AF::Phase::IDLE         },
 	{ "COMMAND",      TC8566AF::Phase::COMMAND      },
 	{ "DATATRANSFER", TC8566AF::Phase::DATA_TRANSFER },
@@ -507,7 +507,7 @@
 };
 SERIALIZE_ENUM(TC8566AF::Phase, phaseInfo);
 
-static constexpr std::initializer_list<enum_string<TC8566AF::Seek>> seekInfo = {
+static const std::initializer_list<enum_string<TC8566AF::Seek>> seekInfo = {
 	{ "IDLE",        TC8566AF::Seek::IDLE },
 	{ "SEEK",        TC8566AF::Seek::SEEK },
 	{ "RECALIBRATE", TC8566AF::Seek::RECALIBRATE }
--- a/src/fdc/WD2793.cc
+++ b/src/fdc/WD2793.cc
@@ -520,7 +520,7 @@
 }
 
 
-static constexpr std::initializer_list<enum_string<WD2793::FSM>> fsmStateInfo = {
+static const std::initializer_list<enum_string<WD2793::FSM>> fsmStateInfo = {
 	{ "NONE",              WD2793::FSM::NONE },
 	{ "SEEK",              WD2793::FSM::SEEK },
 	{ "TYPE2_LOADED",      WD2793::FSM::TYPE2_LOADED },
--- a/src/ide/MB89352.cc
+++ b/src/ide/MB89352.cc
@@ -601,7 +601,7 @@
 
 
 // TODO duplicated in WD33C93.cc
-static constexpr std::initializer_list<enum_string<SCSI::Phase>> phaseInfo = {
+static const std::initializer_list<enum_string<SCSI::Phase>> phaseInfo = {
 	{ "UNDEFINED",   SCSI::Phase::UNDEFINED   },
 	{ "BUS_FREE",    SCSI::Phase::BUS_FREE    },
 	{ "ARBITRATION", SCSI::Phase::ARBITRATION },
--- a/src/ide/WD33C93.cc
+++ b/src/ide/WD33C93.cc
@@ -401,7 +401,7 @@
 }
 
 
-static constexpr std::initializer_list<enum_string<SCSI::Phase>> phaseInfo = {
+static const std::initializer_list<enum_string<SCSI::Phase>> phaseInfo = {
 	{ "UNDEFINED",   SCSI::Phase::UNDEFINED   },
 	{ "BUS_FREE",    SCSI::Phase::BUS_FREE    },
 	{ "ARBITRATION", SCSI::Phase::ARBITRATION },
--- a/src/laserdisc/LaserdiscPlayer.cc
+++ b/src/laserdisc/LaserdiscPlayer.cc
@@ -22,7 +22,7 @@
 #include <cstdint>
 #include <cstdlib>
 #include <iostream>
-//#include <memory>
+#include <memory>
 
 namespace openmsx {
 
--- a/src/memory/AmdFlash.cc
+++ b/src/memory/AmdFlash.cc
@@ -770,7 +770,7 @@
 	}
 }
 
-static constexpr std::initializer_list<enum_string<AmdFlash::State>> stateInfo = {
+static const std::initializer_list<enum_string<AmdFlash::State>> stateInfo = {
 	{ "IDLE",         AmdFlash::State::READ },       // back compat with v3
 	{ "IDENT",        AmdFlash::State::AUTOSELECT }, // back compat with v3
 	{ "PRGERR",       AmdFlash::State::ERROR },      // back compat with v3
--- a/src/memory/EEPROM_93C46.cc
+++ b/src/memory/EEPROM_93C46.cc
@@ -208,7 +208,7 @@
 	}
 }
 
-static constexpr std::initializer_list<enum_string<EEPROM_93C46::State>> stateInfo = {
+static const std::initializer_list<enum_string<EEPROM_93C46::State>> stateInfo = {
 	{ "IN_RESET",           EEPROM_93C46::State::IN_RESET           },
 	{ "WAIT_FOR_START_BIT", EEPROM_93C46::State::WAIT_FOR_START_BIT },
 	{ "WAIT_FOR_COMMAND",   EEPROM_93C46::State::WAIT_FOR_COMMAND   },
--- a/src/memory/SdCard.cc
+++ b/src/memory/SdCard.cc
@@ -278,7 +278,7 @@
 	}
 }
 
-static const std::initializer_list<enum_string<SdCard::Mode>> modeInfo = {
+static const std::initializer_list<enum_string<SdCard::Mode>> modeInfo = {
 	{ "COMMAND",     SdCard::Mode::COMMAND  },
 	{ "READ",        SdCard::Mode::READ },
 	{ "MULTI_READ",  SdCard::Mode::MULTI_READ },
--- a/src/serial/I8251.cc
+++ b/src/serial/I8251.cc
@@ -241,7 +241,7 @@
 }
 
 
-static const std::initializer_list<enum_string<SerialDataInterface::DataBits>> dataBitsInfo = {
+static const std::initializer_list<enum_string<SerialDataInterface::DataBits>> dataBitsInfo = {
 		{ "5", SerialDataInterface::DataBits::D5 },
 		{ "6", SerialDataInterface::DataBits::D6 },
 		{ "7", SerialDataInterface::DataBits::D7 },
@@ -249,7 +249,7 @@
 };
 SERIALIZE_ENUM(SerialDataInterface::DataBits, dataBitsInfo);
 
-static const std::initializer_list<enum_string<SerialDataInterface::StopBits>> stopBitsInfo = {
+static const std::initializer_list<enum_string<SerialDataInterface::StopBits>> stopBitsInfo = {
 	{ "INVALID", SerialDataInterface::StopBits::INV },
 	{ "1",       SerialDataInterface::StopBits::S1   },
 	{ "1.5",     SerialDataInterface::StopBits::S1_5  },
@@ -257,14 +257,14 @@
 };
 SERIALIZE_ENUM(SerialDataInterface::StopBits, stopBitsInfo);
 
-static const std::initializer_list<enum_string<SerialDataInterface::Parity>> parityBitInfo = {
+static const std::initializer_list<enum_string<SerialDataInterface::Parity>> parityBitInfo = {
 	{ "EVEN", SerialDataInterface::Parity::EVEN },
 	{ "ODD",  SerialDataInterface::Parity::ODD  }
 };
 SERIALIZE_ENUM(SerialDataInterface::Parity, parityBitInfo);
 
-static const std::initializer_list<enum_string<I8251::CmdPhase>> cmdFazeInfo = {
+static const std::initializer_list<enum_string<I8251::CmdPhase>> cmdFazeInfo = {
 	{ "MODE",  I8251::CmdPhase::MODE  },
 	{ "SYNC1", I8251::CmdPhase::SYNC1 },
 	{ "SYNC2", I8251::CmdPhase::SYNC2 },
--- a/src/serial/I8254.cc
+++ b/src/serial/I8254.cc
@@ -311,7 +311,7 @@
 }
 
 
-static const std::initializer_list<enum_string<Counter::ByteOrder>> byteOrderInfo = {
+static const std::initializer_list<enum_string<Counter::ByteOrder>> byteOrderInfo = {
 	{ "LOW",  Counter::ByteOrder::LOW  },
 	{ "HIGH", Counter::ByteOrder::HIGH }
 };
--- a/src/sound/SCC.cc
+++ b/src/sound/SCC.cc
@@ -430,7 +430,7 @@
 }
 
 
-static const std::initializer_list<enum_string<SCC::Mode>> chipModeInfo = {
+static constexpr std::initializer_list<enum_string<SCC::Mode>> chipModeInfo = {
 	{ "Real",       SCC::Mode::Real       },
 	{ "Compatible", SCC::Mode::Compatible },
 	{ "Plus",       SCC::Mode::Plus   },
--- a/src/sound/VLM5030.cc
+++ b/src/sound/VLM5030.cc
@@ -510,7 +510,7 @@
 	unregisterSound();
 }
 
-static const std::initializer_list<enum_string<VLM5030::Phase>> phaseInfo = {
+static constexpr std::initializer_list<enum_string<VLM5030::Phase>> phaseInfo = {
 	{ "RESET", VLM5030::Phase::RESET },
 	{ "IDLE",  VLM5030::Phase::IDLE  },
 	{ "SETUP", VLM5030::Phase::SETUP },
--- a/src/sound/Y8950.cc
+++ b/src/sound/Y8950.cc
@@ -20,7 +20,7 @@
 #include <algorithm>
 #include <array>
 #include <cmath>
-//#include <iostream>
+#include <iostream>
 
 namespace openmsx {
 
--- a/src/sound/YM2413Burczynski.cc
+++ b/src/sound/YM2413Burczynski.cc
@@ -31,7 +31,7 @@
 #include <algorithm>
 #include <array>
 #include <cstdint>
-//#include <iostream>
+#include <iostream>
 #include <utility>
 
 namespace openmsx {
--- a/src/sound/YM2413NukeYKT.cc
+++ b/src/sound/YM2413NukeYKT.cc
@@ -34,7 +34,7 @@
 #include <algorithm>
 #include <array>
 #include <cstring>
-
+#include <iostream>
 namespace openmsx {
 namespace YM2413NukeYKT {
 
--- a/src/sound/YM2413Okazaki.cc
+++ b/src/sound/YM2413Okazaki.cc
@@ -19,7 +19,7 @@
 #include <algorithm>
 #include <array>
 #include <cassert>
-//#include <iostream>
+#include <iostream>
 
 namespace openmsx {
 namespace YM2413Okazaki {
--- a/src/sound/YMF262.cc
+++ b/src/sound/YMF262.cc
@@ -41,7 +41,7 @@
 #include <algorithm>
 #include <array>
 #include <cmath>
-//# <iostream>
+#include <iostream>
 
 namespace openmsx {
 
--- a/src/video/v9990/V9990.cc
+++ b/src/video/v9990/V9990.cc
@@ -520,7 +520,7 @@
 	scheduleHscan(time);
 }
 
-static const std::initializer_list<enum_string<V9990DisplayMode>> displayModeInfo = {
+static constexpr std::initializer_list<enum_string<V9990DisplayMode>> displayModeInfo = {
 	{ "P1", V9990DisplayMode::P1 }, { "P2", V9990DisplayMode::P2 },
 	{ "B0", V9990DisplayMode::B0 }, { "B1", V9990DisplayMode::B1 },
 	{ "B2", V9990DisplayMode::B2 }, { "B3", V9990DisplayMode::B3 },
1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?