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

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

//
// XP プロセッサの物理バス
//

// IODevice
//   +-- MainbusDevice (InitMainbus() と Read/Write に FC 版がある)
//   |    +-- Mainbus24Device
//   |    |    +-- LunaMainbus
//   |    |    |    +-- Luna1Mainbus
//   |    |    |    +-- Luna88kMainbus
//   |    |    +-- NewsMainbus
//   |    |    +-- Virt68kMainbus
//   |    +-- X68kMainbus
//   |    +-- X68kIODevice
//   |
//   |       +-------------+
//   +-------| XPbusDevice | (これはただの IODevice)
//           +-------------+

// 00000H +-------------------+
//        | 3Port RAM (128KB) |
// 20000H +-------------------+
//        | PROM   (32KB)     | ソケットが空のようだ
// 28000H +-------------------+
//        | 3Port RAM (32KB)  |
// 30000H +-------------------+
//        |                   |
// :        無効
//        |                   |
// FFE00H +-------------------+
//        | 内蔵 RAM (512B)   | (実際の位置は I/O で決まる)
// FFFFFH +-------------------+
//
// 3Port RAM (128KB) のほうは vm_luna で確保されている subram、
// 3Port RAM (32KB)  のほうはこちらで確保する subram2。
// 内蔵 RAM は XPBusDevice の internal_ram[]。

#include "xpbus.h"
#include "nop.h"
#include "subram.h"

// コンストラクタ
XPbusDevice::XPbusDevice()
	: inherited(OBJ_XPBUS)
{
	pSubRAM2.reset(new SubRAM2Device(32));
	pXPRAM.reset(new XPRAMDevice());
}

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

// 初期化
bool
XPbusDevice::Init()
{
	nopio = GetNopIODevice();
	subram = GetSubRAMDevice();
	return true;
}

void
XPbusDevice::ResetHard(bool poweron)
{
	// RMCR のリセットは XP 側からされるのでここでは何もしない
}

inline IODevice *
XPbusDevice::SearchDevice(uint32 addr) const
{
	// まず内蔵 512 バイトRAM (位置は設定で可変)
	if (__predict_true((addr & 0xffe00) == ram_addr)) {
		return pXPRAM.get();
	}

	if (__predict_true(addr < 0x20000)) {	// 00000H-20000H: 3Port RAM (128KB)
		return subram;
	}
	if (__predict_false(addr < 0x28000)) {	// 20000H-28000H: PROM 領域 (32KB)
		return nopio;
	}
	if (__predict_true(addr < 0x30000)) {	// 28000H-30000H: 非共有 RAM (32KB)
		return pSubRAM2.get();
	}
	// 30000H 以降は空き。
	// アクセス特性が NopIO かどうかは未調査。
	return nopio;
}

busdata
XPbusDevice::Read1(uint32 addr)
{
	addr &= 0x000fffff;
	IODevice *d = SearchDevice(addr);
	return d->Read1(addr);
}

busdata
XPbusDevice::Write1(uint32 addr, uint32 data)
{
	addr &= 0x000fffff;
	IODevice *d = SearchDevice(addr);
	return d->Write1(addr, data);
}

busdata
XPbusDevice::Peek1(uint32 addr)
{
	addr &= 0x000fffff;
	IODevice *d = SearchDevice(addr);
	return d->Peek1(addr);
}

bool
XPbusDevice::Poke1(uint32 addr, uint32 data)
{
	addr &= 0x000fffff;
	IODevice *d = SearchDevice(addr);
	return d->Poke1(addr, data);
}

// RMCR レジスタを取得する
uint32
XPbusDevice::GetRMCR() const
{
	return (ram_addr >> 12) & 0xff;
}

// RMCR レジスタを設定する
void
XPbusDevice::SetRMCR(uint32 data)
{
	ram_addr = ((data & 0xf0) << 12) | 0xfe00;
}


//
// XP 内蔵 512 バイト RAM
//
// IODevice にしておかないといけない関係で独立して用意する。
// ここは RAM 実体を持っているだけで、配置場所は XPbusDevice が担当している。
//

// コンストラクタ
XPRAMDevice::XPRAMDevice()
	: inherited(OBJ_XPRAM)
{
}

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

busdata
XPRAMDevice::Read1(uint32 addr)
{
	uint32 offset = addr & 0x1ff;
	busdata data = ram[offset];
	return data;
}

busdata
XPRAMDevice::Write1(uint32 addr, uint32 data)
{
	uint32 offset = addr & 0x1ff;
	ram[offset] = data;
	return 0;
}

busdata
XPRAMDevice::Peek1(uint32 addr)
{
	addr &= 0x1ff;
	return ram[addr];
}

bool
XPRAMDevice::Poke1(uint32 addr, uint32 data)
{
	if ((int32)data >= 0) {
		addr &= 0x1ff;
		ram[addr] = data;
	}
	return true;
}

unix.superglobalmegacorp.com

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