--- nono/vm/rom.cpp 2026/04/29 17:05:06 1.1.1.8 +++ nono/vm/rom.cpp 2026/04/29 17:06:00 1.1.1.15 @@ -4,8 +4,10 @@ // Licensed under nono-license.txt // -// ROM の共通部分 // +// ROM の基本クラス +// + // IODevice // | // | +-----------+ @@ -18,8 +20,8 @@ // | +-- CGROMDevice (X680x0 の CGROM) // | +-- LunaPROMEmuDevice (LUNA PROM エミュレーションの共通部分) // | | -// | +-- Luna1PROMEmuDevice (LUNA1 の PROM エミュレーション) -// | +-- Luna88kPROMEmuDevice (LUNA88K の PROM エミュレーション) +// | +-- Luna1PROMEmuDevice (LUNA-I の PROM エミュレーション) +// | +-- Luna88kPROMEmuDevice (LUNA-88K の PROM エミュレーション) // | // +-- PROM0Device (LUNA* のブートページ切り替え用プロキシ) // +-- IPLROM0Device (X680x0 のブートページ切り替え用プロキシ) @@ -36,8 +38,8 @@ // ROM 共通部 // -ROMDevice::ROMDevice(const std::string& objname_) - : inherited(objname_) +ROMDevice::ROMDevice(uint objid_) + : inherited(objid_) { mask = 0xffffffff; } @@ -46,15 +48,32 @@ ROMDevice::~ROMDevice() { } +// ROM 用の領域を用意する。 +// 失敗した場合は warn 系でエラーメッセージを表示して false を返す。 +bool +ROMDevice::AllocROM(uint len, uint8 fill) +{ + imagebuf.reset(new(std::nothrow) uint8 [len]); + if ((bool)imagebuf == false) { + warnx("Could not allocate %u bytes at %s", len, __method__); + return false; + } + memset(&imagebuf[0], fill, len); + mem = &imagebuf[0]; + mask = len - 1; + + return true; +} + // name の ROM を探してロードする。 // name はパスを含まないファイル名のみ。パスはこちらで探す。 -// 失敗した場合はエラーメッセージを表示して false を返す。 +// 失敗した場合は warn 系でエラーメッセージを表示して false を返す。 bool -ROMDevice::LoadROM(const char *name, int size) +ROMDevice::LoadROM(const char *name, uint size) { struct stat st; - assert(size > 0); + assert(size != 0); // ファイル名 filename = gMainApp.SearchFile(name); @@ -64,9 +83,9 @@ ROMDevice::LoadROM(const char *name, int } // メモリを確保 - imagebuf.reset(new uint8 [size]); + imagebuf.reset(new(std::nothrow) uint8 [size]); if ((bool)imagebuf == false) { - warnx("ROM \"%s\": Cannot allocate memory (%d bytes)", + warnx("ROM \"%s\": Could not allocate %u bytes", filename.c_str(), size); return false; } @@ -85,15 +104,14 @@ ROMDevice::LoadROM(const char *name, int } if (st.st_size < size) { - warnx("ROM \"%s\" is too short (filesize is expected %d but %jd)", + warnx("ROM \"%s\" is too short (filesize is expected %u but %jd)", filename.c_str(), size, (intmax_t)st.st_size); return false; } if (st.st_size > size) { // 大きすぎるほうはワーニングだけでいいか - warnx("%s is too large (ignore %zd bytes)", - filename.c_str(), (ssize_t)st.st_size - size); - return false; + warnx("%s is too large (ignore %zu bytes)", + filename.c_str(), (size_t)st.st_size - size); } // 読み込む @@ -113,62 +131,50 @@ ROMDevice::LoadROM(const char *name, int return true; } -uint64 -ROMDevice::Read8(uint32 addr) -{ - gMPU->AddCycle(wait); - uint32 data; - data = mem[addr & mask]; - putlog(4, "$%08x.B -> $%02x", addr, data); - return data; -} - -uint64 -ROMDevice::Read16(uint32 addr) +busdata +ROMDevice::Read(busaddr addr) { - gMPU->AddCycle(wait); - uint16 data; - data = be16toh(*(uint16 *)&mem[addr & mask]); - putlog(4, "$%08x.W -> $%04x", addr, data); - return data; -} + busdata data; -uint64 -ROMDevice::Read32(uint32 addr) -{ - gMPU->AddCycle(wait); - uint32 data; - data = be32toh(*(uint32 *)&mem[addr & mask]); - putlog(4, "$%08x.L -> $%08x", addr, data); + uint32 paddr = addr.Addr() & ~3U; + data = be32toh(*(const uint32 *)&mem[paddr & mask]); + data |= wait; + data |= BusData::Size4; + putlog(4, "$%08x -> $%08x", paddr, data.Data()); return data; } -uint64 -ROMDevice::Write8(uint32 addr, uint32 data) +busdata +ROMDevice::Write(busaddr addr, uint32 data) { - gMPU->AddCycle(wait); // ? - putlog(4, "$%08x.B <- $%02x", addr, data); - return write_op; + busdata r = write_op; + putlog(4, "$%08x.%u <- $%0*x", addr.Addr(), addr.GetSize(), + addr.GetSize() * 2, data); + r |= wait; + r |= BusData::Size4; + return r; } -uint64 -ROMDevice::Write16(uint32 addr, uint32 data) +busdata +ROMDevice::Peek1(uint32 addr) { - gMPU->AddCycle(wait); // ? - putlog(4, "$%08x.W <- $%04x", addr, data); - return write_op; + return mem[addr & mask]; } -uint64 -ROMDevice::Write32(uint32 addr, uint32 data) +// アクセスウェイト [clock] を設定。 +void +ROMDevice::SetWait(uint32 wait_) { - gMPU->AddCycle(wait); // ? - putlog(4, "$%08x.L <- $%08x", addr, data); - return write_op; + wait = busdata::Wait(wait_ * mpu->GetClock_tsec()); } -uint64 -ROMDevice::Peek8(uint32 addr) +// ファイル名を返す。なければ NULL を返す。 +const char * +ROMDevice::GetFilename() const { - return mem[addr & mask]; + if (filename.empty()) { + return NULL; + } else { + return filename.c_str(); + } }