--- nono/vm/sram.cpp 2026/04/29 17:04:28 1.1.1.1 +++ nono/vm/sram.cpp 2026/04/29 17:04:56 1.1.1.7 @@ -1,12 +1,11 @@ // // 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 +#include "mainapp.h" // // SRAM @@ -15,74 +14,101 @@ // 必要ならアクセス時に都度変換すること。 // -SRAMDevice *gSRAM; +std::unique_ptr gSRAM; SRAMDevice::SRAMDevice() + : inherited("SRAM") { - logname = "sram"; - devname = "SRAM"; devaddr = baseaddr; - devlen = 0x10000; // 通常実際は16KBだが64KB分占有しておく - - fd = -1; + devlen = 0x4000; } 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()); - 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() + "SRAM030.DAT"; + file.SetFilename(filename); + file.SetDispname(string_format("SRAM \"%s\"", filename.c_str())); + mem = file.OpenCreate(16 * 1024); + if (mem == NULL) { return false; } return true; } +void +SRAMDevice::ResetHard() +{ + // XXX 未調査 + writeable = false; +} + +// アドレスデコーダ +inline uint64 +SRAMDevice::Decoder(uint32 addr) const +{ + uint32 offset = addr - baseaddr; + assertmsg(offset < file.GetMemSize(), + "offset=%x memlen=%x", offset, (int)file.GetMemSize()); + return offset; +} + uint64 SRAMDevice::Read8(uint32 addr) { - return mem[addr - baseaddr]; + uint32 offset = Decoder(addr); + uint32 data; + + // ホストファイル起動モードなら起動アドレスとして Pluto-X を見せる。 + if (gMainApp.host_file) { + data = PeekHostBoot(offset); + if ((int32)data >= 0) { + if ((offset & 1) == 0) { + data = data >> 8; + } else { + data = data & 0xff; + } + return data; + } + } + + data = mem[offset]; + return data; } uint64 SRAMDevice::Read16(uint32 addr) { - return be16toh(*(uint16 *)&mem[addr - baseaddr]); + uint32 offset = Decoder(addr); + uint32 data; + + // ホストファイル起動モードなら起動アドレスとして Pluto-X を見せる。 + if (gMainApp.host_file) { + data = PeekHostBoot(offset); + if ((int32)data >= 0) { + return data; + } + } + + data = be16toh(*(uint16 *)&mem[offset]); + return data; } uint64 SRAMDevice::Write8(uint32 addr, uint32 data) { + uint32 offset = Decoder(addr); + if (writeable) { - if (addr - baseaddr < 0x100) { + if (offset < 0x100) { putlog(1, "更新 $%06x <- $%02x", addr, data); } - mem[addr - baseaddr] = data; + mem[offset] = data; } else { putlog(1, "書き込み禁止 $%06x <- $%02x", addr, data); } @@ -92,11 +118,13 @@ SRAMDevice::Write8(uint32 addr, uint32 d uint64 SRAMDevice::Write16(uint32 addr, uint32 data) { + uint32 offset = Decoder(addr); + if (writeable) { - if (addr - baseaddr < 0x100) { + if (offset < 0x100) { putlog(1, "更新 $%06x <- $%04x", addr, data); } - *(uint16 *)&mem[addr - baseaddr] = htobe16(data); + *(uint16 *)&mem[offset] = htobe16(data); } else { putlog(1, "書き込み禁止 $%06x <- $%04x", addr, data); } @@ -106,7 +134,22 @@ SRAMDevice::Write16(uint32 addr, uint32 uint64 SRAMDevice::Peek8(uint32 addr) { - return mem[addr - baseaddr]; + uint32 offset = Decoder(addr); + + // ホストファイル起動モードなら起動アドレスとして Pluto-X を見せる。 + if (gMainApp.host_file) { + uint32 data = PeekHostBoot(offset); + if ((int32)data >= 0) { + if ((offset & 1) == 0) { + data = data >> 8; + } else { + data = data & 0xff; + } + return data; + } + } + + return mem[offset]; } void @@ -120,3 +163,25 @@ SRAMDevice::write_enable(bool value) writeable = value; } + +// ホストファイル起動用の読み出し値を返す。 +// offset はワード境界であること。戻り値はホストバイトオーダのワード値。 +// 本来の SRAM の値を読み出してよいところについては (uint32)-1 を返す。 +// +// mem[] は SRAM.DAT を直接 mmap(2) しており書き換えておくことは出来ないため、 +// ホストファイル起動モードなら読み出し時に動的に値を返す。 +uint32 +SRAMDevice::PeekHostBoot(uint32 offset) const +{ + switch (offset) { + case 0x0c: // ROM 起動アドレス(H) + return (plutoaddr >> 16); + case 0x0e: // ROM 起動アドレス(L) + return (plutoaddr & 0xffff); + case 0x18: // 起動デバイスを ROM にする + return 0xa000; + default: + break; + } + return (uint32)-1; +}