--- nono/vm/sysport.cpp 2026/04/29 17:04:42 1.1.1.4 +++ nono/vm/sysport.cpp 2026/04/29 17:05:17 1.1.1.10 @@ -4,37 +4,69 @@ // Licensed under nono-license.txt // +// +// システムポート +// + #include "sysport.h" -#include "mfp.h" -#include "ram.h" +#include "keyboard.h" +#include "mainram.h" +#include "mpu.h" +#include "nmi.h" +#include "power.h" #include "romimg_x68k.h" #include "sram.h" +#include +// コンストラクタ SysportDevice::SysportDevice() + : inherited(OBJ_SYSPORT) { - logname = "sysport"; - devname = "Sysport"; - devaddr = baseaddr; - devlen = 0x2000; + AddAlias("SysPort"); } +// デストラクタ SysportDevice::~SysportDevice() { } +// 初期化 +bool +SysportDevice::Init() +{ + if (inherited::Init() == false) { + return false; + } + + cgrom = GetCGROMDevice(); + iplrom1 = GetIPLROM1Device(); + iplrom2 = GetIPLROM2Device(); + keyboard = GetKeyboard(); + mainram = GetMainRAMDevice(); + nmi = GetNMIDevice(); + sram = GetSRAMDevice(); + + return true; +} + +// リセット 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; + GetPowerDevice()->SetSystemPowerOn(true); } uint64 -SysportDevice::Read(uint32 addr) +SysportDevice::Read(uint32 offset) { uint32 data; - switch (addr) { + switch (offset) { case SYSPORT::CONTRAST: data = 0xf0 | sysport.contrast; break; @@ -45,8 +77,11 @@ SysportDevice::Read(uint32 addr) data = 0xff; break; case SYSPORT::KEY: - // キーボードは接続されてることにする - data = 0x08; + // XXX bit3 以外は要実機確認 + data = 0xf7; + if (keyboard->IsConnected()) { + data |= 0x08; + } break; case SYSPORT::WAIT: data = 0xff; @@ -61,16 +96,17 @@ SysportDevice::Read(uint32 addr) data = 0xff; break; default: - __unreachable(); + VMPANIC("corrupted offset=%d", offset); + return 0xff; } - putlog(1, "$%06X -> $%02x", addr, data); + putlog(2, "$%06x -> $%02x", mpu->GetPaddr(), data); return data; } uint64 -SysportDevice::Write(uint32 addr, uint32 data) +SysportDevice::Write(uint32 offset, uint32 data) { - switch (addr) { + switch (offset) { case SYSPORT::CONTRAST: sysport.contrast = data & 15; break; @@ -81,12 +117,15 @@ SysportDevice::Write(uint32 addr, uint32 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)) { + nmi->NegateNMI(); } - // bit3 KEY CTRL は MFP で管理する - gMFP->SetKeyCtrl(data & 0x08); + sysport.key_ctrl = (data & 0x08); break; case SYSPORT::WAIT: @@ -96,14 +135,14 @@ SysportDevice::Write(uint32 addr, uint32 sysport.ram_wait = data; // ROM に指示。常に設定値 + 2 でよい - gIPLROM1->SetWait(sysport.rom_wait + 2); - gIPLROM2->SetWait(sysport.rom_wait + 2); - gCGROM->SetWait(sysport.rom_wait + 2); + iplrom1->SetWait(sysport.rom_wait + 2); + iplrom2->SetWait(sysport.rom_wait + 2); + cgrom->SetWait(sysport.rom_wait + 2); // RAM に指示。InsideOut p.124 int wait = sysport.ram_wait; if (wait > 0) wait += 2; - gRAM->SetWait(wait); + mainram->SetWait(wait); break; } @@ -112,28 +151,50 @@ SysportDevice::Write(uint32 addr, uint32 case SYSPORT::SRAMWP: if (data == 0x31) { - gSRAM->write_enable(true); + sram->WriteEnable(true); } else { - gSRAM->write_enable(false); + sram->WriteEnable(false); } break; case SYSPORT::POWEROFF: - putlog(0, "$E8E00F (POWEROFF) 未サポート書き込み %02x", data); + { + static const std::array sig { 0x00, 0x0f, 0x0f }; + + if (sysport.pwoff_count >= sig.size()) { + // すでにカウントオーバーしている場合何もしない? + putlog(2, "$e8e00f (POWEROFF) <- %02x", data); + break; + } + + 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"); + GetPowerDevice()->SetSystemPowerOn(false); + } break; + } default: - __unreachable(); + VMPANIC("corrupted offset=%d", offset); + break; } return 0; } uint64 -SysportDevice::Peek(uint32 addr) +SysportDevice::Peek(uint32 offset) { uint32 data; - switch (addr) { + switch (offset) { case SYSPORT::CONTRAST: data = 0xf0 | sysport.contrast; break; @@ -144,7 +205,11 @@ SysportDevice::Peek(uint32 addr) data = 0xff; break; case SYSPORT::KEY: - data = 0xff; + // XXX bit3 以外は要実機確認 + data = 0xf7; + if (keyboard->IsConnected()) { + data |= 0x08; + } break; case SYSPORT::WAIT: data = 0xff; @@ -159,7 +224,8 @@ SysportDevice::Peek(uint32 addr) data = 0xff; break; default: - __unreachable(); + data = 0xff; + break; } return data; }