--- nono/vm/sysport.cpp 2026/04/29 17:04:56 1.1.1.7 +++ nono/vm/sysport.cpp 2026/04/29 17:05:13 1.1.1.9 @@ -4,14 +4,24 @@ // Licensed under nono-license.txt // +// +// システムポート +// + #include "sysport.h" -#include "mfp.h" +#include "keyboard.h" +#include "mpu.h" +#include "nmi.h" +#include "power.h" #include "ram.h" #include "romimg_x68k.h" #include "sram.h" +#include -std::unique_ptr gSysport; +// グローバル参照用 +SysportDevice *gSysport; +// コンストラクタ SysportDevice::SysportDevice() : inherited("SystemPort") { @@ -21,17 +31,22 @@ SysportDevice::SysportDevice() devlen = 0x2000; } +// デストラクタ SysportDevice::~SysportDevice() { + gSysport = NULL; } +// リセット void -SysportDevice::ResetHard() +SysportDevice::ResetHard(bool poweron) { sysport.contrast = 0; // XXX 未調査 sysport.ram_wait = 0; sysport.rom_wait = 0; sysport.key_ctrl = false; + sysport.pwoff_count = 0; + gPower->SetSystemPowerOn(true); } uint64 @@ -50,8 +65,11 @@ SysportDevice::Read(uint32 offset) data = 0xff; break; case SYSPORT::KEY: - // キーボードは接続されてることにする - data = 0x08; + // XXX bit3 以外は要実機確認 + data = 0xf7; + if (gKeyboard->IsConnected()) { + data |= 0x08; + } break; case SYSPORT::WAIT: data = 0xff; @@ -68,7 +86,7 @@ SysportDevice::Read(uint32 offset) default: __unreachable(); } - putlog(1, "$%06X -> $%02x", gMPU->GetPaddr(), data); + putlog(2, "$%06x -> $%02x", gMPU->GetPaddr(), data); return data; } @@ -86,9 +104,13 @@ SysportDevice::Write(uint32 offset, uint case SYSPORT::KEY: data &= 0x0e; - // bit1,2 - if ((data & 0x06)) { - putlog(0, "$E8E007 未サポート書き込み $%02x", data); + // bit1 + if ((data & 0x02)) { + putlog(0, "$e8e007 <- $%02x (HRL NOT IMPLEMENTED)", data); + } + // bit2: NMI リセット + if ((data & 0x04)) { + gNMI->NegateNMI(); } sysport.key_ctrl = (data & 0x08); break; @@ -123,8 +145,25 @@ SysportDevice::Write(uint32 offset, uint break; case SYSPORT::POWEROFF: - putlog(0, "$e8e00f (POWEROFF) 未サポート書き込み %02x", data); + { + static const std::array sig { 0x00, 0x0f, 0x0f }; + + assertmsg(sysport.pwoff_count < sig.size(), + "sysport.pwoff_count=%d", sysport.pwoff_count); + if (data == sig[sysport.pwoff_count]) { + sysport.pwoff_count++; + } else { + sysport.pwoff_count = 0; + } + putlog(2, "$e8e00f (POWEROFF) <- %02x (count=%d)", + data, sysport.pwoff_count); + if (sysport.pwoff_count == sig.size()) { + // pwoff_count はここではクリアせず、電源オン時に再初期化する。 + putlog(1, "$e8e00f (POWEROFF) Power Off"); + gPower->SetSystemPowerOn(false); + } break; + } default: __unreachable(); @@ -148,7 +187,11 @@ SysportDevice::Peek(uint32 offset) data = 0xff; break; case SYSPORT::KEY: - data = 0xff; + // XXX bit3 以外は要実機確認 + data = 0xf7; + if (gKeyboard->IsConnected()) { + data |= 0x08; + } break; case SYSPORT::WAIT: data = 0xff;