--- nono/vm/romemu_luna.cpp 2026/04/29 17:05:25 1.1.1.15 +++ nono/vm/romemu_luna.cpp 2026/04/29 17:05:51 1.1.1.19 @@ -9,27 +9,32 @@ // // IODevice -// | -// +-- ROMDevice (LoadROM()、ウェイト、マスク等を持つ) -// | | -// | +-- PROMDevice (LUNA* の PROM) -// | +-- IPLROM1Device (X680x0 の IPLROM 後半) -// | +-- IPLROM2Device (X680x0 の IPLROM 前半) -// | +-- CGROMDevice (X680x0 の CGROM) -// | | -// | | +-------------------+ -// | +--| LunaPROMEmuDevice | (LUNA PROM エミュレーションの共通部分) -// | +-------------------+ -// | | -// | +-- Luna1PROMEmuDevice (LUNA-I の PROM エミュレーション) -// | +-- Luna88kPROMEmuDevice (LUNA-88K の PROM エミュレーション) -// | -// +-- PROM0Device (LUNA* のブートページ切り替え用プロキシ) -// +-- IPLROM0Device (X680x0 のブートページ切り替え用プロキシ) +// | +// +- ROMDevice (LoadROM()、ウェイト、マスク等を持つ) +// | +- PROMDevice (LUNA* の PROM) +// | +- IPLROM1Device (X680x0 の IPLROM 後半) +// | +- IPLROM2Device (X680x0 の IPLROM 前半) +// | +- CGROMDevice (X680x0 の CGROM) +// | | +// | +- ROMEmuDevice +// | | +// | | +-------------------+ +// | +-| LunaPROMEmuDevice | (LUNA PROM エミュレーションの共通部分) +// | | +-------------------+ +// | | | +// | | +- Luna1PROMEmuDevice (LUNA-I の PROM エミュレーション) +// | | +- Luna88kPROMEmuDevice (LUNA-88K の PROM エミュレーション) +// | +- NewsROMEmuDevice (NEWS の ROM エミュレーション) +// | +- ROM30EmuDevice (X68030 の ROM30 エミュレーション) +// | +- Virt68kROMEmuDevice (virt-m68k の IPLROM 相当の何か) +// | +// +- PROM0Device (LUNA* のブートページ切り替え用プロキシ) +// +- IPLROM0Device (X680x0 のブートページ切り替え用プロキシ) #include "romemu_luna.h" #include "bt45x.h" #include "builtinrom.h" +#include "lance.h" #include "lunafb.h" #include "mainapp.h" #include "mainram.h" @@ -37,6 +42,9 @@ #include "mpu.h" #include "pio.h" #include "prom.h" +#include "rtc.h" +#include "scsidev.h" +#include "scsidomain.h" #include "sio.h" #include "spc.h" #include "ufs.h" @@ -58,11 +66,8 @@ LunaPROMEmuDevice::~LunaPROMEmuDevice() bool LunaPROMEmuDevice::Init() { - if (inherited::Init() == false) { - return false; - } - bt45x = GetBT45xDevice(); + lance = GetLanceDevice(); lunafb = GetLunafbDevice(); mainram = GetMainRAMDevice(); nvram = GetMK48T02Device(); @@ -72,22 +77,22 @@ LunaPROMEmuDevice::Init() return true; } -busdata -LunaPROMEmuDevice::Read32(uint32 addr) +// ROMIO から読み出す。 +// ROMIO が応答すべきでなければ (uint64)-1 を返す。 +uint64 +LunaPROMEmuDevice::ReadROMIO(busaddr addr) { // ROM からのロングワードアクセスでだけ謎の I/O 空間が見える。 - // addr をマスクする前に評価すること。 - if ((mpu->GetPaddr() & 0xff000000) == baseaddr) { - switch (addr) { + if ((mpu->GetPPC() & 0xff000000) == baseaddr && addr.GetSize() == 4) { + switch (addr.Addr()) { case ROMIO_INIT: - return ROM_Init(); + ROM_Init(); + return 0; case ROMIO_LOAD: - { entrypoint = ROM_Load(); putlog(2, "ROMIO_LOAD entrypoint=$%08x", entrypoint); return 0; - } case ROMIO_KEYIN: putlog(2, "ROMIO_KEYIN"); @@ -117,34 +122,43 @@ LunaPROMEmuDevice::Read32(uint32 addr) case ROMIO_CLKCNT: return clkcnt; + case ROMIO_QUITSTOP: + return quitstop; + default: break; } } - return inherited::Read32(addr); + return (uint64)-1; } -busdata -LunaPROMEmuDevice::Write32(uint32 addr, uint32 data) +// ROMIO に書き込む。 +// 反応すれば true を返す。そうでなければ false を返す。 +bool +LunaPROMEmuDevice::WriteROMIO(busaddr addr, uint32 data) { // ROM からのロングワードアクセスでだけ謎の I/O 空間が見える。 - // addr をマスクする前に評価すること。 - if ((mpu->GetPaddr() & 0xff000000) == baseaddr) { - switch (addr) { + if ((mpu->GetPPC() & 0xff000000) == baseaddr && addr.GetSize() == 4) { + switch (addr.Addr()) { case ROMIO_CLKCNT: clkcnt = data; - return 0; + return true; + + case ROMIO_QUITSTOP: + quitstop = data; + return true; + default: break; } } - return inherited::Write32(addr, data); + return false; } // ROM 処理の初期化。 -int +void LunaPROMEmuDevice::ROM_Init() { // 初期パレット @@ -152,22 +166,26 @@ LunaPROMEmuDevice::ROM_Init() // SCSI // BDID の書き込みによってホストデバイスがバスにアタッチされる構造なので。 - spc->Write(SPC::BDID, 7); + spc->WritePort(SPC::BDID, 7); + + // LANCE。 + lance->WritePort(0, 0x00); // RAP=CSR0 + lance->WritePort(1, AM7990::CSR0_STOP); // キーボード(chB)を初期化 - sio->Write(3, 0x01); // CR1 - sio->Write(3, 0x10); // RX Int(all char) - sio->Write(3, 0x04); // CR4 - sio->Write(3, 0x44); // Stop 1bit - sio->Write(3, 0x03); // CR3 - sio->Write(3, 0xc1); // RX Enable, 8bit - sio->Write(3, 0x05); // CR5 - sio->Write(3, 0x68); // TX Enable, 8bit + sio->WritePort(3, 0x01); // CR1 + sio->WritePort(3, 0x10); // RX Int(all char) + sio->WritePort(3, 0x04); // CR4 + sio->WritePort(3, 0x44); // Stop 1bit + sio->WritePort(3, 0x03); // CR3 + sio->WritePort(3, 0xc1); // RX Enable, 8bit + sio->WritePort(3, 0x05); // CR5 + sio->WritePort(3, 0x68); // TX Enable, 8bit // LED を(明示的に)オフ、マウスサンプリングをオフ - sio->Write(2, 0x00); - sio->Write(2, 0x01); - sio->Write(2, 0x20); + sio->WritePort(2, 0x00); + sio->WritePort(2, 0x01); + sio->WritePort(2, 0x20); // 電源オフをキャンセル。 // 実 PROM では、リセット後に PIO のモードセットを行っている。 @@ -175,15 +193,13 @@ LunaPROMEmuDevice::ROM_Init() // 即座にこれをキャンセルしている。 // ROMEmu ではモードセットを行っていないが、キャンセルだけ発行しておく。 auto pio1 = GetPIO1Device(); - pio1->Write(3, 0x09); + pio1->WritePort(3, 0x09); // 機種別の初期化 ROM_InitMD(); // スクリーンを初期化 InitScreen(); - - return 0; } // 起動時の実行ファイル読み込み処理を行う。 @@ -205,7 +221,10 @@ LunaPROMEmuDevice::ROM_Load() auto pio0 = GetPIO0Device(); if (pio0->IsDIPSW11Up()) { entry = LoadFile(""); - execute = true; + if (entry != -1) { + execute = true; + return entry; + } } } else { // LUNA-88K の PROM 1.20 は初期化するかどうか確認してくるけど、 @@ -215,13 +234,11 @@ LunaPROMEmuDevice::ROM_Load() // NVRAM をクリアしたら DIPSW によらずプロンプトに降りる } - if (entry == -1) { - PrintTitle(); - if (errmsg.empty() == false) { - Print("** %s\n\n", errmsg.c_str()); - } - ClearPrompt(); + PrintTitle(); + if (errmsg.empty() == false) { + Print("** %s\n\n", errmsg.c_str()); } + ClearPrompt(); return entry; } @@ -243,11 +260,11 @@ LunaPROMEmuDevice::InitPalette() { // 偶数番は白(R/G/B=15/15/15)、奇数番は黒(0/0/0)。 uint8 val = 0xff; - bt45x->Write(0, 0); // select palette + bt45x->WritePort(0, 0); // select palette for (int i = 0; i < 16; i++) { - bt45x->Write(1, val); // R - bt45x->Write(1, val); // G - bt45x->Write(1, val); // B + bt45x->WritePort(1, val); // R + bt45x->WritePort(1, val); // G + bt45x->WritePort(1, val); // B val ^= 0xff; } } @@ -285,7 +302,7 @@ LunaPROMEmuDevice::InitScreen() void LunaPROMEmuDevice::PrintTitle() { - Print("NONO %d.%d.%d Emulated ROM Monitor for %s\n\n", + Print("NONO %u.%u.%u Emulated ROM Monitor for %s\n\n", NONO_MAJOR_VER, NONO_MINOR_VER, NONO_PATCH_VER, machine_name); } @@ -310,12 +327,17 @@ LunaPROMEmuDevice::Putc(uint ch) bold = false; break; - case 0x10: + case 0x10: // カラーコード変更 + lunafb->SetBMSEL(0); + break; case 0x11: + lunafb->SetBMSEL(1); + break; case 0x12: + lunafb->SetBMSEL(3); + break; case 0x13: - // カラーコード変更 - lunafb->SetBMSEL(ch - 0x10); + lunafb->SetBMSEL(5); break; case CR: @@ -422,6 +444,8 @@ LunaPROMEmuDevice::ROM_Close() // その時のためにエントリポイント等も初期化しておく。 entrypoint = -1; execute = false; + clkcnt = 0; + quitstop = 0; } // ROM プロンプトのキー入力。 @@ -445,14 +469,14 @@ int LunaPROMEmuDevice::Getc() { // コントロールレジスタポインタを確実に 0 にするため読み捨てる - sio->Read(3); + sio->ReadPort(3); - uint8 sr0 = sio->Read(3); + uint8 sr0 = sio->ReadPort(3); if ((sr0 & MPSCC::SR0_RXAVAIL) == 0) { return -1; } - uint32 lunakey = sio->Read(2); + uint32 lunakey = sio->ReadPort(2); // マウス入力の 2, 3バイト目は無視 if (mousecnt > 0) { @@ -581,7 +605,7 @@ LunaPROMEmuDevice::CalcNVRAMCsum() const { uint8 eor = 0; for (uint32 addr = 0x20; addr < 0x560; addr++) { - eor ^= nvram->Peek(addr); + eor ^= nvram->PeekPort(addr); } return eor; } @@ -592,9 +616,9 @@ LunaPROMEmuDevice::WriteNVRAMCsum() { uint8 eor = CalcNVRAMCsum(); - nvram->Write(0x001c, eor); - nvram->Write(0x001d, eor); - nvram->Write(0x001e, eor); + nvram->WritePort(0x001c, eor); + nvram->WritePort(0x001d, eor); + nvram->WritePort(0x001e, eor); } // NVRAM のマジックとチェックサムを照合する @@ -607,7 +631,7 @@ LunaPROMEmuDevice::VerifyNVRAM() const uint8 eor = CalcNVRAMCsum(); for (uint32 addr = 0x1c; addr < 0x1f; addr++) { - if (nvram->Peek(addr) != eor) { + if (nvram->PeekPort(addr) != eor) { return false; } } @@ -643,7 +667,7 @@ LunaPROMEmuDevice::LoadHostFile() assert(gMainApp.exec_file); LoadInfo info(gMainApp.exec_file); - if (mainram->LoadExec(&info)) { + if (BootLoader::LoadExec(mainram, &info)) { return info.entry; } else { errmsg = "Couldn't load specified host program."; @@ -662,8 +686,8 @@ LunaPROMEmuDevice::LoadGuestFile(const b const std::string& dkfile = bootinfo.dkfile; // ユニット (今は SCSI ID=6 決め打ち) - int id = 6; - SCSITarget *target = spc->GetTarget(id); + uint id = 6; + SCSITarget *target = spc->GetDomain()->GetTarget(id); if (target == NULL) { errmsg = "No bootable disks"; putmsg(0, "%s", errmsg.c_str()); @@ -676,13 +700,13 @@ LunaPROMEmuDevice::LoadGuestFile(const b } SCSIDisk *hd = dynamic_cast(target); - putmsg(2, "%s SCSIHD[%d] found", __func__, id); + putmsg(2, "%s SCSIHD[%u] found", __func__, id); // +0 セクタ目(512byte)に Sun disklabel scd_dk_label dk; if (hd->Peek(&dk, 0, sizeof(dk)) == false) { - putmsg(0, "SCSIHD[%d] ReadSector failed", id); - errmsg = string_format("dk%d Read disklabel failed.", dkunit); + putmsg(0, "SCSIHD[%u] ReadSector failed", id); + errmsg = string_format("dk%u Read disklabel failed.", dkunit); return -1; } @@ -715,7 +739,7 @@ LunaPROMEmuDevice::LoadGuestFile(const b // ファイルシステムをオープン (マウントっぽいイメージ) Filesys fsys(this); if (fsys.Mount(hd, part_start, part_size) == false) { - errmsg = string_format("dk%d,%c Open ffs failed: %s", + errmsg = string_format("dk%u,%c Open ffs failed: %s", dkunit, dkpart + 'a', fsys.errstr.c_str()); putmsg(0, "%s: %s", __func__, errmsg.c_str()); return -1; @@ -724,7 +748,7 @@ LunaPROMEmuDevice::LoadGuestFile(const b // ファイルを探してオープンする inodefile f(this); if (fsys.OpenFile(f, dkfile) == false) { - errmsg = string_format("dk%d,%c,%s open failed: %s", + errmsg = string_format("dk%u,%c,%s open failed: %s", dkunit, dkpart + 'a', dkfile.c_str(), fsys.errstr.c_str()); putmsg(0, "%s: %s", __func__, errmsg.c_str()); return -1; @@ -734,18 +758,18 @@ LunaPROMEmuDevice::LoadGuestFile(const b fsys.ReadData(f); // ロード - std::string name = string_format("SCSIHD %d,%c:%s", + std::string name = string_format("SCSIHD %u,%c:%s", id, dkpart + 'a', dkfile.c_str()); LoadInfo info(name.c_str(), f.data.data(), f.data.size()); - if (mainram->LoadExec(&info) == false) { - errmsg = string_format("dk%d,%c,%s load failed", + if (BootLoader::LoadExec(mainram, &info) == false) { + errmsg = string_format("dk%u,%c,%s load failed", dkunit, dkpart + 'a', dkfile.c_str()); putmsg(0, "%s: %s", __func__, errmsg.c_str()); return -1; } if (info.entry == -1) { - errmsg = string_format("dk%d,%c,%s not executable", + errmsg = string_format("dk%u,%c,%s not executable", dkunit, dkpart + 'a', dkfile.c_str()); putmsg(0, "%s: %s", __func__, errmsg.c_str()); return -1; @@ -765,12 +789,20 @@ LunaPROMEmuDevice::ROM_AP1() static uint8 ap1pal[] = { 0x00, 0x00, 0x00, 0x00, 0xf8, 0xf8, + 0, 0, 0, 0xf8, 0xf8, 0x00, + 0, 0, 0, 0xf8, 0xf8, 0xf8, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0x00, 0x00, 0x00, + 0xf8, 0xf8, 0xf8 }; - bt45x->Write(0, 0); + bt45x->WritePort(0, 0); for (int i = 0; i < countof(ap1pal); i++) { - bt45x->Write(1, ap1pal[i]); + bt45x->WritePort(1, ap1pal[i]); } Print(std::string((const char *)test0)); @@ -782,12 +814,9 @@ LunaPROMEmuDevice::ROM_AP1() Print(std::string((const char *)test3)); n = strlcpy(buf, (const char *)&Builtin::IPLROM30[0x111e3], sizeof(buf)); - snprintf(buf + n, sizeof(buf) - n, "%d.%d.%d %s", - NONO_MAJOR_VER, NONO_MINOR_VER, NONO_PATCH_VER, NONO_DATE); - for (int i = 0; buf[i]; i++) { - if (buf[i] == '/') - buf[i] = '.'; - } + snprintf(buf + n, sizeof(buf) - n, "%d.%d.%d '%02d.%02d.%02d", + NONO_MAJOR_VER, NONO_MINOR_VER, NONO_PATCH_VER, + GetRTCDevice()->GetYear() % 100, 4, 1); Print("%s\n", buf); memcpy(buf, &Builtin::IPLROM30[0x111f5], 0x28); @@ -817,7 +846,7 @@ LunaPROMEmuDevice::ROM_AP1() strlcpy(buf, (const char *)&Builtin::IPLROM30[0x11280], sizeof(buf)); n = 0x1e; - n += snprintf(buf + n, sizeof(buf) - n, "%d", mainram->GetSizeMB()); + n += snprintf(buf + n, sizeof(buf) - n, "%u", mainram->GetSizeMB()); strlcpy(buf + n, (const char *)&Builtin::IPLROM30[0x1129f], sizeof(buf) - n); Print(std::string(buf));