--- nono/vm/sram.cpp 2026/04/29 17:04:32 1.1.1.3 +++ nono/vm/sram.cpp 2026/04/29 17:04:50 1.1.1.5 @@ -1,13 +1,11 @@ // // nono -// Copyright (C) 2017 isaki@NetBSD.org +// Copyright (C) 2020 nono project +// Licensed under nono-license.txt // -#include "mainapp.h" #include "sram.h" -#include -#include -#include +#include "mainapp.h" // // SRAM @@ -23,62 +21,21 @@ SRAMDevice::SRAMDevice() 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() { - struct stat st; - filename = gMainApp.GetVMDir() + "SRAM030.DAT"; - memlen = 16 * 1024; - - fd = open(filename.c_str(), O_RDWR); - if (fd == -1) { - warn("SRAM \"%s\" open failed", filename.c_str()); - return false; - } - - // ファイルサイズをチェック。 - // ファイルが短くても mmap はしれっと成功してしまうようだ。 - if (fstat(fd, &st) == -1) { - warn("SRAM \"%s\" fstat failed", filename.c_str()); - close(fd); - return false; - } - if (st.st_size < memlen) { - warnx("SRAM \"%s\" is too short (filesize is expected %d but %d)", - filename.c_str(), memlen, (int)st.st_size); - close(fd); - return false; - } - if (st.st_size > memlen) { - // 大きすぎるほうはワーニングだけでいいか - warnx("SRAM \"%s\" is too large (ignore %d bytes)", - filename.c_str(), (int)st.st_size - memlen); - } - - mem = (uint8 *)mmap(NULL, memlen, PROT_READ | PROT_WRITE, - MAP_SHARED, fd, 0); - if (mem == MAP_FAILED) { - warn("SRAM \"%s\" mmap failed", filename.c_str()); - close(fd); + file.SetFilename(filename); + file.SetDispname(string_format("SRAM \"%s\"", filename.c_str())); + mem = file.OpenCreate(16 * 1024); + if (mem == NULL) { return false; } @@ -89,21 +46,51 @@ SRAMDevice::Init() inline uint64 SRAMDevice::Decoder(uint32 addr) const { - return addr - baseaddr; + uint32 offset = addr - baseaddr; + assertmsg(offset < file.GetMemSize(), + "offset=%x memlen=%x", offset, (int)file.GetMemSize()); + return offset; } uint64 SRAMDevice::Read8(uint32 addr) { uint32 offset = Decoder(addr); - return mem[offset]; + 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) { uint32 offset = Decoder(addr); - return be16toh(*(uint16 *)&mem[offset]); + 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 @@ -142,6 +129,20 @@ uint64 SRAMDevice::Peek8(uint32 addr) { 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]; } @@ -156,3 +157,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; +}