--- nono/vm/prom.cpp 2026/04/29 17:05:10 1.1.1.10 +++ nono/vm/prom.cpp 2026/04/29 17:05:20 1.1.1.13 @@ -5,7 +5,7 @@ // // -// PROM (LUNA-I, LUNA88K 共通) +// PROM (LUNA-I, LUNA-88K 共通) // // IODevice @@ -21,8 +21,8 @@ // | +-- CGROMDevice (X680x0 の CGROM) // | +-- LunaPROMEmuDevice (LUNA PROM エミュレーションの共通部分) // | | -// | +-- Luna1PROMEmuDevice (LUNA1 の PROM エミュレーション) -// | +-- Luna88kPROMEmuDevice (LUNA88K の PROM エミュレーション) +// | +-- Luna1PROMEmuDevice (LUNA-I の PROM エミュレーション) +// | +-- Luna88kPROMEmuDevice (LUNA-88K の PROM エミュレーション) // | // | +-------------+ // +-- | PROM0Device | (LUNA* のブートページ切り替え用プロキシ) @@ -34,10 +34,7 @@ #include "config.h" #include "ethernet.h" #include "mainapp.h" - -// グローバル参照用 -PROM0Device *gPROM0; -IODevice *gPROM; +#include "vm.h" // // PROM0 @@ -52,22 +49,27 @@ IODevice *gPROM; // コンストラクタ PROM0Device::PROM0Device() - : inherited("PROM(BOOT)") + : inherited(OBJ_PROM_BOOT) { + // 通常ここからログを出すことはない ClearAlias(); - AddAlias("PROMBOOT"); } // デストラクタ PROM0Device::~PROM0Device() { - gPROM0 = NULL; } +// 初期化 bool PROM0Device::Init() { - prom = gPROM; + if (inherited::Init() == false) { + return false; + } + + prom = GetPROMDevice(); + return true; } @@ -113,7 +115,7 @@ PROM0Device::Read32(uint32 addr) // LUNA では PROM へのライトアクセスでブートページを RAM に切り替えている。 // - LUNA-I では最初に $41000000.B への書き込みがあるが、 // それ以降も $41000000.L への書き込みが(複数回)あるようだ。 -// - LUNA88K では $4100000c.L への書き込みがある。 +// - LUNA-88K では $4100000c.L への書き込みがある。 // // よってアドレスを定めず PROM 全域への書き込みで最初の1回だけ発動する // ようにしておく。サイズも今の所ワード(16bit)アクセスは確認してないけど @@ -159,10 +161,8 @@ PROM0Device::Peek8(uint32 addr) // コンストラクタ PROMDevice::PROMDevice() - : inherited("PROM") + : inherited(OBJ_PROM) { - devaddr = 0x41000000; - // LUNA では ROM への書き込みは何も起きない write_op = 0; } @@ -170,23 +170,31 @@ PROMDevice::PROMDevice() // デストラクタ PROMDevice::~PROMDevice() { - gPROM = NULL; } +// 初期化 bool PROMDevice::Init() { - vmtype_t vmtype = gMainApp.GetVMType(); + if (inherited::Init() == false) { + return false; + } + + VMType vmtype = gMainApp.GetVMType(); switch (vmtype) { - case VMTYPE_LUNA1: - return InitLuna1(); + case VMType::LUNA1: + if (gMainApp.msxdos_mode) { + return true; + } else { + return InitLuna1(); + } - case VMTYPE_LUNA88K: + case VMType::LUNA88K: return InitLuna88k(); default: - PANIC("unknown vmtype %d", vmtype); + PANIC("unknown vmtype %d", (int)vmtype); } } @@ -194,7 +202,7 @@ PROMDevice::Init() bool PROMDevice::InitLuna1() { - devlen = 128 * 1024; + uint devlen = 128 * 1024; mask = devlen - 1; // ファイル名が存在してる時しかここに来ない @@ -217,8 +225,17 @@ PROMDevice::InitLuna1() //00d3a0 3a 34 32 20 31 39 38 39 00 00 00 00 4e 56 fd f8 |:42 1989....NV..| if (strcmp((const char *)&mem[0xd390], "Thu Jul 27 11:45:42 1989") == 0) { - // V4.22 - putmsg(1, "V4.22 detected"); + romver = 422; + } + + if (romver == 0) { + putmsg(0, "Unknown PROM version"); + } else { + putmsg(1, "v%d.%02d detected", romver / 100, romver % 100); + } + + if (romver == 422) { + // V4.22。他の ROM は何も分からないので何もしない。 // MAC アドレスは ROM に書き込まれているので、ここで上書き if (strcmp((const char *)&mem[0x1ffd8], "ENADDR") != 0) { @@ -228,25 +245,49 @@ PROMDevice::InitLuna1() // MAC アドレスは12桁の16進数文字列として書き込まれている。例えば // 前半の 00:00:0A 部分は 30 30 30 30 30 41 "00000A" という感じ。 - const macaddr_t macaddr = gEthernet->GetMacAddr(); - memcpy(&mem[0x1ffe0], macaddr.ToString().c_str(), 12); + macaddr_t macaddr {}; + if (EthernetDevice::GetConfigMacAddr(0, &macaddr, true) == false) { + // エラーメッセージは表示済み + return false; + } + + const char *msg; + if (macaddr.Empty()) { + // "rom" なら元イメージのままにする。 + msg = "ROM"; + } else { + // 指定されたら上書き。 + memcpy(&imagebuf[0x1ffe0], macaddr.ToString().c_str(), 12); + msg = "config"; + } + putmsg(1, "macaddr=%c%c:%c%c:%c%c:%c%c:%c%c:%c%c (from %s)", + std::tolower(imagebuf[0x1ffe0]), + std::tolower(imagebuf[0x1ffe1]), + std::tolower(imagebuf[0x1ffe2]), + std::tolower(imagebuf[0x1ffe3]), + std::tolower(imagebuf[0x1ffe4]), + std::tolower(imagebuf[0x1ffe5]), + std::tolower(imagebuf[0x1ffe6]), + std::tolower(imagebuf[0x1ffe7]), + std::tolower(imagebuf[0x1ffe8]), + std::tolower(imagebuf[0x1ffe9]), + std::tolower(imagebuf[0x1ffea]), + std::tolower(imagebuf[0x1ffeb]), + msg); // SCSI デバッグビット bool scsi_debug_bit = gConfig->Find(".prom-scsi-debug").AsInt(); - mem[0x4100981d - 0x41000000] = (scsi_debug_bit) ? 0x01 : 0; - } else { - // 他の ROM は何も分からないので何もしない。 - putmsg(0, "Unknown PROM Version"); + imagebuf[0x4100981d - 0x41000000] = (scsi_debug_bit) ? 0x01 : 0; } return true; } -// LUNA88K の場合 +// LUNA-88K の場合 bool PROMDevice::InitLuna88k() { - devlen = 256 * 1024; + uint devlen = 256 * 1024; mask = devlen - 1; // ファイル名が存在してる時しかここに来ない @@ -258,5 +299,38 @@ PROMDevice::InitLuna88k() // XXX アクセスウェイトは未調査。とりあえず RAM と同程度にしておく wait = 3; + // ROM バージョンを照合。どこかに日付が埋まってるっぽい。 + // + // 1.20: + //02c190 00 00 04 b0 28 0d 2f e1 28 0d 2f e1 54 68 75 20 |....(./.(./.Thu | + //02c1a0 41 70 72 20 31 38 20 31 34 3a 33 34 3a 32 35 20 |Apr 18 14:34:25 | + //02c1b0 31 39 39 31 00 00 00 00 41 02 c1 9c 00 00 00 00 |1991....A.......| + // + // 1.31: + //03c940 00 00 05 1e 2a 0f 28 78 2a 0f 28 78 54 75 65 20 |....*.(x*.(xTue | + //03c950 4d 61 79 20 31 32 20 31 31 3a 30 37 3a 35 32 20 |May 12 11:07:52 | + //03c960 31 39 39 32 00 00 00 00 41 03 c9 4c 00 00 00 00 |1992....A..L....| + // + // 1.37: + //03cf30 00 00 05 5a 2b 5a 4a 7d 2b 5a 4a 7d 4d 6f 6e 20 |...Z+ZJ}+ZJ}Mon | + //03cf40 4a 61 6e 20 31 38 20 31 35 3a 31 33 3a 31 37 20 |Jan 18 15:13:17 | + //03cf50 31 39 39 33 00 00 00 00 41 03 cf 3c 00 00 00 00 |1993....A..<....| + + if (strcmp((const char *)&mem[0x2c19c], "Thu Apr 18 14:34:25 1991") == 0) { + romver = 120; + } else + if (strcmp((const char *)&mem[0x3c94c], "Tue May 12 11:07:52 1992") == 0) { + romver = 131; + } else + if (strcmp((const char *)&mem[0x3cf3c], "Mon Jan 18 15:13:17 1993") == 0) { + romver = 137; + } + + if (romver == 0) { + putmsg(0, "Unknown PROM version"); + } else { + putmsg(1, "v%d.%02d detected", romver / 100, romver % 100); + } + return true; }