File:  [Isaki's NoNo m68k/m88k emulator] / nono / vm / newsio.cpp
Revision 1.1.1.7 (vendor branch): download - view: text, annotated - select for diffs
Wed Apr 29 17:06:01 2026 UTC (2 months, 3 weeks ago) by root
Branches: MAIN, Isaki
CVS tags: v027, HEAD
nono 1.7.0

//
// nono
// Copyright (C) 2022 nono project
// Licensed under nono-license.txt
//

//
// NEWS の I/O 空間担当
//

// NWS-1750
//            +0 +1 +2 +3 +4 +5 +6 +7  +8 +9 +A +B +C +D +E +F'0000
// e000'0000 |
// e010'0000 |
// e020'0000 |
// e030'0000 |
// e040'0000 |
// e050'0000 |
// e060'0000 |
// e070'0000 |
// e080'0000 |
// e090'0000 |
// e0a0'0000 |
// e0b0'0000 |
// e0c0'0000 |            PAR?         FDC         SIC
// e0d0'0000 |KBC         SCC          RTC         LED
// e0e0'0000 |MEM                      DMAC
// e0f0'0000 |ETH
//
// MEM: Lance のメモリ

#include "newsio.h"
#include "busio.h"
#include "config.h"
#include "kbc.h"
#include "lance.h"
#include "mainbus.h"
#include "mk48t02.h"
#include "monitor.h"
#include "newsctlr.h"
#include "nop.h"
#include "scc.h"
#include "subram.h"
#include "vm.h"

// コンストラクタ
NewsIODevice::NewsIODevice()
	: inherited(OBJ_NEWSIO)
{
	NEWDV(KBC, new BusIO_B<KBCDevice>());
	NEWDV(RTC, new BusIO_B<MK48T02Device>());
	NEWDV(SCC, new BusIO_B<SCCDevice>());
	NEWDV(Lance, new BusIO_W<LanceDevice>());
	NEWDV(SubRAM, new SubRAMDevice(16));

	// まず NopIO で埋める。
	// XXX 全域かどうかは分からないが
	auto nopio = GetNopIODevice();
	for (int i = 0; i < table.size(); i++) {
		table[i] = nopio;
	}

	// 少ないので手動で置いていく。
	newsctlr = GetNewsCtlrDevice();
	auto kbc = pKBC.get();
	auto lance = pLance.get();
	auto rtc = pRTC.get();
	auto scc = pSCC.get();
	auto subram = pSubRAM.get();

	// table[] は $e0c0'0000 以降を 0x10000 (64KB) 単位にしたもの。
#define A(addr)	(addr - 0xe0c0)

	// FDC は現状サポートしていないが (それに機種が違うっぽい?)、
	// NetBSD の locore.s がリセットのためにアクセスしに来るので
	// NewsCtlr でついでに対処してある。
	table[A(0xe0c8)] = newsctlr;	// FDC
	table[A(0xe0d0)] = kbc;
	table[A(0xe0d4)] = scc;
	table[A(0xe0d8)] = rtc;
	table[A(0xe0dc)] = newsctlr;	// LED
	table[A(0xe0e0)] = subram;
	table[A(0xe0f0)] = lance;

	src_screen.Init(75, 64, TextScreen::Ring);

	monitor = gMonitorManager->Regist(ID_SUBWIN_NEWSIO, this);
	monitor->SetCallback(&NewsIODevice::MonitorScreen);
	monitor->SetSize(src_screen.GetCol(), 1 + 32);
	monitor->SetMaxHeight(1 + 64);
}

// デストラクタ
NewsIODevice::~NewsIODevice()
{
}

// 初期化
bool
NewsIODevice::Init()
{
	const ConfigItem& olditem = gConfig->Find("xxx-news-sci-ignore");
	const ConfigItem& newitem = gConfig->Find("xxx-news-sic-ignore");

	// 指定されていれば警告だけ出してスルーする。
	if (newitem.GetFrom() != ConfigItem::FromInitial) {
		newitem.Err("obsoleted");
	}
	if (olditem.GetFrom() != ConfigItem::FromInitial) {
		olditem.Err("obsoleted");
	}

	// モニタは実行中には変化しないので最初に作っておく。
	InitMonitor();

	return true;
}

// アドレスから該当するデバイスを返す
inline IODevice *
NewsIODevice::SearchDevice(uint32 addr) const
{
	// アドレスを table のインデックスに変換。ここに来た時点で
	// $e0'000000 (かそのミラー) の 16MB 内にいることは分かっている。
	addr &= 0x00ff'ffff;
	uint idx = (addr - 0x00c0'0000) >> 16;
	return table[idx];
}

busdata
NewsIODevice::Read(busaddr addr)
{
	IODevice *d = SearchDevice(addr.Addr());
	return d->Read(addr);
}

busdata
NewsIODevice::Write(busaddr addr, uint32 data)
{
	IODevice *d = SearchDevice(addr.Addr());
	return d->Write(addr, data);
}

busdata
NewsIODevice::Peek1(uint32 addr)
{
	IODevice *d = SearchDevice(addr);
	return d->Peek1(addr);
}

bool
NewsIODevice::Poke1(uint32 addr, uint32 data)
{
	IODevice *d = SearchDevice(addr);
	return d->Poke1(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->MonitorScreenNewsCtlr(screen, y);
}

void
NewsIODevice::MonitorScreen(Monitor *, TextScreen& screen)
{
	// 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);
}

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.