|
|
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()
{
}
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.