File:  [Isaki's NoNo m68k/m88k emulator] / nono / vm / subram.cpp
Revision 1.1.1.5 (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) 2020 nono project
// Licensed under nono-license.txt
//

//
// サブメモリ
//

// SubRAM はバイト配置とする。

#include "subram.h"
#include "mainapp.h"

//
// 共通クラス
//

// コンストラクタ
SubRAMBaseDevice::SubRAMBaseDevice(uint objid_, uint ramsize_kb)
	: inherited(objid_)
{
	uint ramsize = ramsize_kb * 1024;
	assert((ramsize & (ramsize - 1)) == 0);

	mask = ramsize - 1;
}

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

// 初期化
bool
SubRAMBaseDevice::Init()
{
	uint ramsize = GetSize();
	ram.reset(new(std::nothrow) uint8[ramsize]);
	if ((bool)ram == false) {
		warnx("Could not allocate %u bytes at %s", ramsize, __method__);
		return false;
	}
	memset(&ram[0], 0, ramsize);

	return true;
}

// リセット
void
SubRAMBaseDevice::ResetHard(bool poweron)
{
	if (poweron) {
		// 実際にはゼロ初期化ではなくゴミだと思うがとりあえず。
		memset(&ram[0], 0, GetSize());
	}
}

// アドレスデコーダ
inline uint32
SubRAMBaseDevice::Decoder(uint32 addr) const
{
	// たぶんサイズ分で折り返しイメージが見えるはず。要確認。
	return addr & mask;
}

// MPU からのアクセス
busdata
SubRAMBaseDevice::Read(busaddr addr)
{
	uint32 offset = Decoder(addr.Addr());
	busdata data;

	// MPU からはおそらくロングワードデバイス。
	data  = be32toh(*(uint32 *)&ram[offset & ~3U]);
	data |= BusData::Size4;
	putlog(4, "$%08x -> $%08x", addr.Addr(), data.Data());
	return data;
}

// MPU からのアクセス
busdata
SubRAMBaseDevice::Write(busaddr addr, uint32 data)
{
	uint32 offset = Decoder(addr.Addr());
	uint32 reqsize = addr.GetSize();
	uint32 datasize = std::min(4 - (offset & 3U), reqsize);

	// MPU からはおそらくロングワードデバイス。
	if (datasize == 4) {
		putlog(3, "$%08x <- $%08x", addr.Addr(), data);
		*(uint32 *)&ram[offset] = htobe32(data);
	} else if (datasize == 1) {
		data >>= (reqsize - datasize) * 8;
		putlog(3, "$%08x <- $%02x", addr.Addr(), data);
		ram[offset] = data;
	} else {
		data >>= (reqsize - datasize) * 8;
		putlog(3, "$%08x <- $%0*x", addr.Addr(), datasize * 2, data);
		for (int i = datasize - 1; i >= 0; i--) {
			ram[offset + i] = data;
			data >>= 8;
		}
	}

	busdata r = BusData::Size4;
	return r;
}

busdata
SubRAMBaseDevice::Peek1(uint32 addr)
{
	uint32 offset = Decoder(addr);
	return ram[offset];
}

bool
SubRAMBaseDevice::Poke1(uint32 addr, uint32 data)
{
	if ((int32)data >= 0) {
		uint32 offset = Decoder(addr);
		ram[offset] = data;
	}
	return true;
}

// XP からのバイト読み込み。
// (サイズは自明なので返さない)
busdata
SubRAMBaseDevice::Read1(uint32 addr)
{
	uint32 offset = Decoder(addr);
	busdata data = ram[offset];
	putlog(4, "XP $%05x -> $%02x", offset, data.Data());
	return data;
}

// XP からのバイト書き込み。
// (サイズは自明なので返さない)
busdata
SubRAMBaseDevice::Write1(uint32 addr, uint32 data)
{
	uint32 offset = Decoder(addr);
	putlog(3, "XP $%05x <- $%02x", offset, data);
	ram[offset] = data;
	return 0;
}

// Lance からのワード読み込み。addr は偶数であること。
// (サイズは自明なので返さない)
busdata
SubRAMBaseDevice::Read2(uint32 addr)
{
	busdata data = Peek2(addr);
	putlog(4, "LE $%05x -> $%04x", Decoder(addr), data.Data());
	return data;
}

// Lance からのワード書き込み。addr は偶数であること。
// (サイズは自明なので返さない)
busdata
SubRAMBaseDevice::Write2(uint32 addr, uint32 data)
{
	uint32 offset = Decoder(addr);
	putlog(3, "LE $%05x <- $%04x", offset, data);
	*(uint16 *)&ram[offset] = htobe16(data);
	return 0;
}

// Lance からのピーク。addr は偶数であること。
busdata
SubRAMBaseDevice::Peek2(uint32 addr) const
{
	uint32 offset = Decoder(addr);
	busdata data = be16toh(*(uint16 *)&ram[offset]);
	return data;
}


//
// サブメモリ 1 (XP/Lance との共有 RAM)
//

// コンストラクタ
SubRAMDevice::SubRAMDevice(uint ramsize_kb)
	: inherited(OBJ_SUBRAM, ramsize_kb)
{
}

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

// リセット
void
SubRAMDevice::ResetHard(bool poweron)
{
	// 通常モードなら電源オンで初期化。
	// MSXDOS モードなら MSXDOSDevice::Init() がすでにここに
	// 書き込んでいるため、消してはいけない。
	if (gMainApp.msxdos_mode == false) {
		inherited::ResetHard(poweron);
	}
}


//
// サブメモリ 2 (XP の非共有部)
//

// コンストラクタ
SubRAM2Device::SubRAM2Device(uint ramsize_kb)
	: inherited(OBJ_SUBRAM2, ramsize_kb)
{
}

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

unix.superglobalmegacorp.com

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