--- nono/vm/sysport.cpp 2026/04/29 17:04:28 1.1 +++ nono/vm/sysport.cpp 2026/04/29 17:05:59 1.1.1.16 @@ -1,80 +1,85 @@ // // nono -// Copyright (C) 2017 isaki@NetBSD.org +// Copyright (C) 2020 nono project +// Licensed under nono-license.txt +// + +// +// システムポート // #include "sysport.h" +#include "keyboard.h" +#include "mainbus.h" +#include "mainram.h" +#include "monitor.h" +#include "nmi.h" +#include "power.h" +#include "romimg_x68k.h" #include "sram.h" +#include "videoctlr.h" +#include +// コンストラクタ SysportDevice::SysportDevice() + : inherited(OBJ_SYSPORT) { - logname = "sysport"; - devname = "Sysport"; - devaddr = baseaddr; - devlen = 0x2000; + monitor = gMonitorManager->Regist(ID_MONITOR_SYSPORT, this); + monitor->SetCallback(&SysportDevice::MonitorScreen); + monitor->SetSize(56, 8); } +// デストラクタ SysportDevice::~SysportDevice() { } -uint64 -SysportDevice::Read8(uint32 addr) +// 初期化 +bool +SysportDevice::Init() { - uint32 data; + cgrom = GetCGROMDevice(); + iplrom1 = GetIPLROM1Device(); + iplrom2 = GetIPLROM2Device(); + keyboard = GetKeyboard(); + mainram = GetMainRAMDevice(); + nmi = GetNMIDevice(); + sram = GetSRAMDevice(); + videoctlr = GetVideoCtlrDevice(); - if ((addr % 2) == 0) { - return 0xff; - } - - int n = (addr - baseaddr) / 2; - switch (n) { - case SYSPORT::CONTRAST: - data = 0xf0 | sysport.contrast; - break; - case SYSPORT::SCOPE3D: - data = 0xff; - break; - case SYSPORT::IMAGEUNIT: - data = 0xff; - break; - case SYSPORT::KEY: - // キーボードは接続されていない - data = 0x00; - break; - case SYSPORT::WAIT: - data = 0xff; - break; - case SYSPORT::MPU: - data = 0xdc; - break; - case SYSPORT::SRAMWP: - data = 0xff; - break; - default: - return (uint64)-1; - } - putlog(1, "$%06X -> $%02x", addr, data); - return data; + return true; } -uint64 -SysportDevice::Read16(uint32 addr) +// リセット +void +SysportDevice::ResetHard(bool poweron) { - return (0xff00 | Read8(addr + 1)); + sysport.ram_wait = 0; + sysport.rom_wait = 0; + sysport.key_ctrl = false; + sysport.pwoff_count = 0; + GetPowerDevice()->SetSystemPowerOn(true); } -uint64 -SysportDevice::Write8(uint32 addr, uint32 data) +busdata +SysportDevice::ReadPort(uint32 offset) { - if ((addr % 2) == 0) { - return (uint64)-1; - } + busdata data; + + data = PeekPort(offset); + putlog(2, "$%06x -> $%02x", GetMainbusDevice()->GetPaddr(), data.Data()); - int n = (addr - baseaddr) / 2; - switch (n) { + data |= BusData::Size1; + return data; +} + +busdata +SysportDevice::WritePort(uint32 offset, uint32 data) +{ + switch (offset) { case SYSPORT::CONTRAST: - sysport.contrast = data & 15; + putlog(1, "$e8e001 <- $%02x", data); + videoctlr->SetContrast(data & 15); break; case SYSPORT::SCOPE3D: @@ -82,55 +87,94 @@ SysportDevice::Write8(uint32 addr, uint3 break; case SYSPORT::KEY: - putlog(0, "$E8E007 未サポート書き込み %02x", data); + data &= 0x0e; + // bit1 + if ((data & 0x02)) { + putlog(0, "$e8e007 <- $%02x (HRL NOT IMPLEMENTED)", data); + } + // bit2: NMI リセット + if ((data & 0x04)) { + nmi->NegateNMI(); + } + sysport.key_ctrl = (data & 0x08); break; case SYSPORT::WAIT: - // 設定値で保持 - sysport.rom_wait = data >> 4; - sysport.ram_wait = data; + { + uint32 rom_wait = data >> 4; + uint32 ram_wait = data & 0xf; + + // InsideOut p.124 + rom_wait += 2; + if (ram_wait > 0) { + ram_wait += 2; + } + + // ROM/RAM に指示。 + iplrom1->SetWait(rom_wait); + iplrom2->SetWait(rom_wait); + cgrom->SetWait(rom_wait); + mainram->SetWait(ram_wait); + + // ROM/RAM への指定値で保持する。 + sysport.rom_wait = rom_wait; + sysport.ram_wait = ram_wait; break; + } case SYSPORT::MPU: break; 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=%u)", + data, sysport.pwoff_count); + if (sysport.pwoff_count == sig.size()) { + // pwoff_count はここではクリアせず、電源オン時に再初期化する。 + putlog(1, "$e8e00f (POWEROFF) Power Off"); + GetPowerDevice()->SetSystemPowerOn(false); + } break; + } default: - return (uint64)-1; + VMPANIC("corrupted offset=%u", offset); + break; } - return 0; -} -uint64 -SysportDevice::Write16(uint32 addr, uint32 data) -{ - return Write8(addr + 1, data & 0xff); + busdata r = BusData::Size1; + return r; } -uint64 -SysportDevice::Peek8(uint32 addr) +busdata +SysportDevice::PeekPort(uint32 offset) { uint32 data; - if ((addr % 2) == 0) { - return 0xff; - } - - int n = (addr - baseaddr) / 2; - switch (n) { + switch (offset) { case SYSPORT::CONTRAST: - data = 0xf0 | sysport.contrast; + data = 0xf0 | videoctlr->GetContrast(); break; case SYSPORT::SCOPE3D: data = 0xff; @@ -139,7 +183,11 @@ SysportDevice::Peek8(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; @@ -150,9 +198,75 @@ SysportDevice::Peek8(uint32 addr) case SYSPORT::SRAMWP: data = 0xff; break; + case SYSPORT::POWEROFF: + data = 0xff; + break; default: data = 0xff; break; } return data; } + +bool +SysportDevice::PokePort(uint32 offset, uint32 data) +{ + return false; +} + +void +SysportDevice::MonitorScreen(Monitor *, TextScreen& screen) +{ + screen.Clear(); + + static const char * const name[] = { + "Contrast", + "3D Scope", + "Image Unit", + "Keyboard Control", + "ROM/RAM Wait", + "MPU/FPU Type", + "SRAM Protect", + "PowerOff Sequence", + }; + + uint8 val[8]; + const uint32 disphex = 0x39; + for (int i = 0; i < 8; i++) { + char hex[4]; + if ((disphex & (1U << i)) != 0) { + val[i] = PeekPort(i); + snprintf(hex, sizeof(hex), "%02x", val[i]); + } else { + strlcpy(hex, "--", sizeof(hex)); + } + + screen.Print(0, i, "$%06x %s: #%u %-17s:", + baseaddr + 1 + i * 2, hex, i, name[i]); + } + + int x = 34; + // #0 Contrast + screen.Print(x, 0, "%2u", videoctlr->GetContrast()); + screen.Puts(x, 1, "(Not Supported)"); + screen.Puts(x, 2, "(Not Supported)"); + // #3 Keyboard + if ((val[SYSPORT::KEY] & 0x08) != 0) { + screen.Puts(x, 3, "Connected"); + } else { + screen.Puts(x, 3, "Not connected"); + } + // #4 ROM/RAM Wait + screen.Print(x, 4, "ROM %2u clk, RAM %2u clk", + sysport.rom_wait, sysport.ram_wait); + // #5 MPU/FPU Type + screen.Puts(x, 5, "MC68030 / 25MHz"); + // #6 SRAM + if (sram->IsWriteable()) { + screen.Puts(x, 6, "Writeable"); + } else { + screen.Puts(x, 6, "Protected"); + } + // #7 PowerOff + screen.Print(x, 7, "%u/3", sysport.pwoff_count); +}