--- nono/vm/newsio.cpp 2026/04/29 17:05:18 1.1 +++ nono/vm/newsio.cpp 2026/04/29 17:05:25 1.1.1.2 @@ -34,6 +34,7 @@ #include "config.h" #include "kbc.h" #include "lance.h" +#include "mainbus.h" #include "mk48t02.h" #include "newsctlr.h" #include "scc.h" @@ -44,27 +45,23 @@ NewsIODevice::NewsIODevice() : inherited(OBJ_NEWSIO) { - // SIC を無視するオプション(暫定) - int ignore_sic = gConfig->Find("xxx-news-sic-ignore").AsInt(); - NEWDV(KBC, new KBCDevice()); NEWDV(RTC, new BusIO_B()); NEWDV(SCC, new BusIO_B()); NEWDV(Lance, new BusIO_W()); NEWDV(SubRAM, new SubRAMDevice(16)); - NEWDV(NopIO, new NopIODevice()); - // まずバスエラーで埋める。 - // XXX バスエラーが起きるかどうかは知らないが + // まず NopIO で埋める。 + // XXX 全域かどうかは分からないが + auto nopio = GetNopIODevice(); for (int i = 0; i < table.size(); i++) { - table[i] = GetBusErrDevice(); + table[i] = nopio; } // 少ないので手動で置いていく。 + newsctlr = GetNewsCtlrDevice(); auto kbc = pKBC.get(); auto lance = pLance.get(); - auto newsctlr = GetNewsCtlrDevice(); - auto nopio = pNopIO.get(); auto rtc = pRTC.get(); auto scc = pSCC.get(); auto subram = pSubRAM.get(); @@ -76,18 +73,20 @@ NewsIODevice::NewsIODevice() // NetBSD の locore.s がリセットのためにアクセスしに来るので // NewsCtlr でついでに対処してある。 table[A(0xe0c8)] = newsctlr; // FDC - if (ignore_sic) { - table[A(0xe0cc)] = nopio; // SIC - } table[A(0xe0d0)] = kbc; table[A(0xe0d4)] = scc; table[A(0xe0d8)] = rtc; table[A(0xe0dc)] = newsctlr; // LED table[A(0xe0e0)] = subram; - if (ignore_sic) { - table[A(0xe0e8)] = nopio; // DMAC - } table[A(0xe0f0)] = lance; + + src_screen.Init(75, 64, TextScreen::Ring); + + monitor.func = ToMonitorCallback(&NewsIODevice::MonitorUpdate); + monitor.SetSize(src_screen.GetCol(), 1 + 32); + monitor.SetMaxHeight(1 + 64); + monitor.Regist(ID_SUBWIN_NEWSIO); + } // デストラクタ @@ -106,26 +105,17 @@ NewsIODevice::Init() const ConfigItem& olditem = gConfig->Find("xxx-news-sci-ignore"); const ConfigItem& newitem = gConfig->Find("xxx-news-sic-ignore"); - // 古いオプションだけが指定されていればエラー - if (olditem.GetFrom() != ConfigItem::FromInitial && - newitem.GetFrom() == ConfigItem::FromInitial) - { - olditem.Err("The variable name was changed to \"xxx-news-sic-ignore\" " - "('sci' to 'sic'). It was a typo :-) " - "Please catch up your configuration."); - return false; + // 指定されていれば警告だけ出してスルーする。 + if (newitem.GetFrom() != ConfigItem::FromInitial) { + newitem.Err("obsoleted"); } - - // 両方指定されていて値が異なればエラー - if (olditem.GetFrom() != ConfigItem::FromInitial && - newitem.GetFrom() != ConfigItem::FromInitial && - olditem.AsString() != newitem.AsString()) - { - newitem.Err("Old \"xxx-news-sci-ignore\" is specified and " - "has a different value. Please remove old one."); - return false; + if (olditem.GetFrom() != ConfigItem::FromInitial) { + olditem.Err("obsoleted"); } + // モニタは実行中には変化しないので最初に作っておく。 + InitMonitor(); + return true; } @@ -140,58 +130,118 @@ NewsIODevice::SearchDevice(uint32 addr) return table[idx]; } -uint64 +busdata NewsIODevice::Read8(uint32 addr) { IODevice *d = SearchDevice(addr); return d->Read8(addr); } -uint64 +busdata NewsIODevice::Read16(uint32 addr) { IODevice *d = SearchDevice(addr); return d->Read16(addr); } -uint64 +busdata NewsIODevice::Read32(uint32 addr) { IODevice *d = SearchDevice(addr); return d->Read32(addr); } -uint64 +busdata NewsIODevice::Write8(uint32 addr, uint32 data) { IODevice *d = SearchDevice(addr); return d->Write8(addr, data); } -uint64 +busdata NewsIODevice::Write16(uint32 addr, uint32 data) { IODevice *d = SearchDevice(addr); return d->Write16(addr, data); } -uint64 +busdata NewsIODevice::Write32(uint32 addr, uint32 data) { IODevice *d = SearchDevice(addr); return d->Write32(addr, data); } -uint64 +busdata NewsIODevice::Peek8(uint32 addr) { IODevice *d = SearchDevice(addr); return d->Peek8(addr); } -// このアドレスを担当する次段の IODevice を返す (IOContainerDevice 用) -IODevice * -NewsIODevice::GetDevice(uint32 addr) const +bool +NewsIODevice::Poke8(uint32 addr, uint32 data) +{ + IODevice *d = SearchDevice(addr); + return d->Poke8(addr, data); +} + +// モニタを初期化。 +void +NewsIODevice::InitMonitor() +{ + TextScreen& screen = src_screen; + int y = 0; + + screen.Clear(); + + // 012345678901234567890 + // $0000'0000: 1234567 + + // table[] は $e0c0 以降なのでここには何もないが + // モニタ上の表をきりのいい範囲にするために埋めておく。 + auto nop = MainbusBaseDevice::FormatDevName(GetNopIODevice()); + for (uint32 addr = 0xe000; addr < 0xe0c0; ) { + screen.Print(0, y, "$%04x'0000:", addr); + for (int j = 0; j < 8; j++) { + const std::string& name = nop.first; + TA attr = nop.second; + screen.Puts(12 + j * 8, y, attr, name.c_str()); + addr++; + } + y++; + } + + int idx = 0; + for (int i = 0; i < table.size() / 8; i++) { + uint32 addr = 0xe0c0 + idx; + screen.Print(0, y, "$%04x'0000:", addr); + for (int j = 0; j < 8; j++) { + auto pair = MainbusBaseDevice::FormatDevName(table[idx]); + const std::string& name = pair.first; + TA attr = pair.second; + screen.Print(12 + j * 8, y, attr, "%s", name.c_str()); + idx++; + } + y++; + } + + // 下半分は NewsCtlr で処理。 + newsctlr->MonitorUpdateNewsCtlr(screen, y); +} + +void +NewsIODevice::MonitorUpdate(Monitor *, TextScreen& screen) { - return SearchDevice(addr); + // pos が表示開始位置(0-) + int pos = (int)screen.userdata; + + // ヘッダは常に描く + screen.Clear(); + for (int i = 0; i < 8; i++) { + screen.Print(12 + i * 8, 0, "+$%x'", i); + } + + // 裏バッファからコピーするだけ。 + screen.CopyRowsFrom(1, screen.GetRow() - 1, src_screen, pos); }