--- nono/vm/sram.cpp 2026/04/29 17:04:28 1.1 +++ nono/vm/sram.cpp 2026/04/29 17:05:24 1.1.1.12 @@ -1,122 +1,276 @@ // // nono -// Copyright (C) 2017 isaki@NetBSD.org +// Copyright (C) 2020 nono project +// Licensed under nono-license.txt // -#include "configfile.h" -#include "sram.h" -#include -#include - // // SRAM // + // SRAM はビッグエンディアンのままメモリに置かれるので、 // 必要ならアクセス時に都度変換すること。 -// -SRAMDevice *gSRAM; +#include "sram.h" +#include "config.h" +#include "mainapp.h" +#include "mainram.h" +#include +// コンストラクタ SRAMDevice::SRAMDevice() + : inherited(OBJ_SRAM) { - logname = "sram"; - devname = "SRAM"; - devaddr = baseaddr; - devlen = 0x10000; // 通常実際は16KBだが64KB分占有しておく - - fd = -1; } +// デストラクタ SRAMDevice::~SRAMDevice() { - if (mem) { - munmap(mem, memlen); - mem = NULL; - memlen = 0; - } - if (fd >= 0) { - close(fd); - fd = -1; - } } +// 初期化 bool SRAMDevice::Init() { - filename = gConfig->GetConfigDir() + "SRAM030.DAT"; - - fd = open(filename.c_str(), O_RDWR); - if (fd == -1) { - warn("%s: cannot open %s", devname, filename.c_str()); + if (inherited::Init() == false) { return false; } - memlen = 16 * 1024; - mem = (uint8 *)mmap(NULL, memlen, PROT_READ | PROT_WRITE, - MAP_SHARED, fd, 0); - if (mem == MAP_FAILED) { - warn("%s: cannot mmap %s", devname, filename.c_str()); - close(fd); + filename = gMainApp.GetVMDir() + "SRAM.DAT"; + file.SetFilename(filename); + file.SetDispname(string_format("SRAM \"%s\"", filename.c_str())); + mem = file.OpenCreate(16 * 1024); + if (mem == NULL) { return false; } + // SRAM の RAM 容量欄を設定値に同期させる。 + // この処理はアプリケーション起動時に一回行われるのみで、 + // その後の VM 内のリセット等では動作しない。 + bool sync = gConfig->Find("sram-sync-ramsize").AsInt(); + if (sync) { + SyncRAMSize(); + } + return true; } -uint64 +// リセット +void +SRAMDevice::ResetHard(bool poweron) +{ + // XXX 未調査 + writeable = false; +} + +// SRAM の RAM 容量欄を設定値に同期させる。 +void +SRAMDevice::SyncRAMSize() +{ + // SRAM の内容が無効なら何もしない。 + static const std::array magic { + 0x82, 0x77, '6', '8', '0', '0', '0' + }; + for (int i = 0; i < magic.size(); i++) { + if (mem[i] != magic[i]) { + return; + } + } + + uint32 ramsize = GetMainRAMDevice()->GetSize(); + + // 値が違う時だけ表示したいので一旦読み出して比較 + uint32 cursize; + cursize = mem[0x08] << 24; + cursize |= mem[0x09] << 16; + cursize |= mem[0x0a] << 8; + cursize |= mem[0x0b]; + if (cursize != ramsize) { + // ここは Init() なので putmsg() は使えない + warnx("SRAM: Update ramsize %dMB", ramsize / 1024 / 1024); + + mem[0x08] = ramsize >> 24; + mem[0x09] = ramsize >> 16; + mem[0x0a] = ramsize >> 8; + mem[0x0b] = ramsize; + } +} + +// アドレスデコーダ +inline uint32 +SRAMDevice::Decoder(uint32 addr) const +{ + uint32 offset = addr - baseaddr; + assertmsg(offset < file.GetMemSize(), + "offset=%x memlen=%x", offset, (int)file.GetMemSize()); + return offset; +} + +busdata SRAMDevice::Read8(uint32 addr) { - return mem[addr - baseaddr]; + uint32 offset = Decoder(addr); + uint32 data; + + data = Get8(offset); + putlog(2, "$%06x.B -> $%02x", addr, data); + + return data; } -uint64 +busdata SRAMDevice::Read16(uint32 addr) { - return be16toh(*(uint16 *)&mem[addr - baseaddr]); + uint32 offset = Decoder(addr); + uint32 data; + + data = Get16(offset); + putlog(2, "$%06x.W -> $%04x", addr, data); + + return data; } -uint64 +busdata SRAMDevice::Write8(uint32 addr, uint32 data) { + uint32 offset = Decoder(addr); + if (writeable) { - if (addr - baseaddr < 0x100) { - putlog(1, "更新 $%06x <- $%02x", addr, data); + if (offset < 0x100) { + putlog(1, "$%06x.B <- $%02x", addr, data); } - mem[addr - baseaddr] = data; + mem[offset] = data; } else { - putlog(1, "書き込み禁止 $%06x <- $%02x", addr, data); + putlog(1, "Write protected $%06x.B <- $%02x", addr, data); } return 0; } -uint64 +busdata SRAMDevice::Write16(uint32 addr, uint32 data) { + uint32 offset = Decoder(addr); + if (writeable) { - if (addr - baseaddr < 0x100) { - putlog(1, "更新 $%06x <- $%04x", addr, data); + if (offset < 0x100) { + putlog(1, "$%06x.W <- $%04x", addr, data); } - *(uint16 *)&mem[addr - baseaddr] = htobe16(data); + *(uint16 *)&mem[offset] = htobe16(data); } else { - putlog(1, "書き込み禁止 $%06x <- $%04x", addr, data); + putlog(1, "Write protected $%06x.W <- $%04x", addr, data); } return 0; } -uint64 +busdata SRAMDevice::Peek8(uint32 addr) { - return mem[addr - baseaddr]; + uint32 offset = Decoder(addr); + + return Get8(offset); +} + +bool +SRAMDevice::Poke8(uint32 addr, uint32 data) +{ + // WriteEnable() に関わらず変更する。 + // また Get8()、Get16() はこの変更の影響を受けないことに注意。 + + if ((int32)data >= 0) { + uint32 offset = Decoder(addr); + mem[offset] = data; + } + return true; } void -SRAMDevice::write_enable(bool value) +SRAMDevice::WriteEnable(bool value) { if (writeable == false && value == true) { - putlog(1, "書き込み許可"); + putlog(1, "Write Enable"); } else if (writeable == true && value == false) { - putlog(1, "書き込み禁止"); + putlog(1, "Write Disable"); } writeable = value; } + +// SRAM から副作用なく読み出す。 +// ただしホストファイル起動モードなら改変した値を返す。 +uint32 +SRAMDevice::Get8(uint32 offset) const +{ + if (gMainApp.exec_file) { + switch (offset) { + case 0x0c: // ROM 起動アドレス(.L) + return plutoaddr >> 24; + case 0x0d: + return (plutoaddr >> 16) & 0xff; + case 0x0e: + return (plutoaddr >> 8) & 0xff; + case 0x0f: + return plutoaddr & 0xff; + + case 0x18: // 起動デバイス(.W) を ROM($a000) にする + return 0xa0; + case 0x19: + return 0x00; + + default: + break; + } + } + + // 他は SRAM から + return mem[offset]; +} + +// SRAM から副作用なくワードで読み出す。 +// ただしホストファイル起動モードなら改変した値を返す。 +uint32 +SRAMDevice::Get16(uint32 offset) const +{ + uint32 data; + + data = Get8(offset) << 8; + data |= Get8(offset + 1); + + return data; +} + +// SRAM から副作用なくロングワードで読み出す。 +// ただしホストファイル起動モードなら改変した値を返す。 +uint32 +SRAMDevice::Get32(uint32 offset) const +{ + uint32 data; + + data = Get16(offset) << 16; + data |= Get16(offset + 2); + + return data; +} + +// IPLROM30 が初期化した SRAM の初期値。 +// +// 0000: 82 77 36 38 30 30 30 57 00 40 00 00 00 fc 00 00 |.w68000W.@......| +// 0010: 00 ed 01 00 ff ff ff ff 00 00 4e 07 00 10 00 00 |..........N.....| +// 0020: 00 00 ff ff 00 00 07 00 0e 00 0d 00 00 00 00 00 |................| +// 0030: f8 3e ff c0 ff fe de 6c 40 22 03 02 00 08 00 00 |.>.....l@"......| +// 0040: 00 00 00 00 00 00 00 00 00 ff f4 00 04 00 01 01 |................| +// 0050: 00 00 00 20 00 03 f9 01 00 00 00 00 00 00 00 00 |... ............| +/*static*/ std::array +SRAMDevice::InitialData { + 0x82, 0x77, 0x36, 0x38, 0x30, 0x30, 0x30, 0x57, + 0x00, 0x40, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x00, + 0x00, 0xed, 0x01, 0x00, 0xff, 0xff, 0xff, 0xff, + 0x00, 0x00, 0x4e, 0x07, 0x00, 0x10, 0x00, 0x00, + 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x07, 0x00, + 0x0e, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xf8, 0x3e, 0xff, 0xc0, 0xff, 0xfe, 0xde, 0x6c, + 0x40, 0x22, 0x03, 0x02, 0x00, 0x08, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xff, 0xf4, 0x00, 0x04, 0x00, 0x01, 0x01, + 0x00, 0x00, 0x00, 0x20, 0x00, 0x03, 0xf9, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +};