--- nono/vm/mk48t02.cpp 2026/04/29 17:04:29 1.1.1.2 +++ nono/vm/mk48t02.cpp 2026/04/29 17:04:32 1.1.1.3 @@ -4,7 +4,8 @@ // #include "mk48t02.h" -#include "configfile.h" +#include "mainapp.h" +#include "config.h" #include #include #include @@ -46,13 +47,33 @@ MK48T02Device::Init() struct stat st; // ファイルのロード - filename = gConfig->GetConfigDir() + "NVRAM.DAT"; + filename = gMainApp.GetVMDir() + "NVRAM.DAT"; memlen = 2040; fd = open(filename.c_str(), O_RDWR); if (fd == -1) { - warn("NVRAM \"%s\" open failed", filename.c_str()); - return false; + if (errno != ENOENT) { + warn("NVRAM \"%s\" open failed", filename.c_str()); + return false; + } else { + // オープンできない理由が ENOENT ならファイルを作ってみる + fd = open(filename.c_str(), O_RDWR | O_CREAT, 0644); + if (fd < 0) { + warn("NVRAM \"%s\" create failed", filename.c_str()); + return false; + } + + // ゼロで埋める (可変長配列は一様初期化できない(環境がある)ようだ) + char zerobuf[memlen]; + memset(zerobuf, 0, memlen); + if (write(fd, zerobuf, sizeof(zerobuf)) < 0) { + warn("NVRAM \"%s\" write failed", filename.c_str()); + close(fd); + return false; + } + warnx("NVRAM \"%s\" created", filename.c_str()); + // FALLTHROUGH + } } // ファイルサイズをチェック。 @@ -83,7 +104,7 @@ MK48T02Device::Init() } // レジスタ値固定オプション (パフォーマンス測定用) - force_fixed = gConfig->ReadInt("rtc_force_fixed"); + force_fixed = gConfig->Get(".rtc-force-fixed").AsInt(); if (force_fixed) { putmsg("force_fixed"); } @@ -115,10 +136,9 @@ MK48T02Device::BCD2num(uint8 bcd) } uint64 -MK48T02Device::Read8(uint32 addr) +MK48T02Device::Read(uint32 addr) { - // アドレスは 2KB 単位でミラーになっている。 - uint32 an = addr & 0x7ff; + uint32 an = addr; uint32 data; if (an < 2040) { @@ -158,9 +178,7 @@ MK48T02Device::Read8(uint32 addr) data = reg.year; break; default: - putlog(0, "未実装バイト読み込み $%08x", addr); - data = 0xff; - break; + __unreachable(); } if (force_fixed) { @@ -175,44 +193,9 @@ MK48T02Device::Read8(uint32 addr) } uint64 -MK48T02Device::Read16(uint32 addr) -{ - // アドレスは 2KB 単位でミラーになっている。 - uint32 an = addr & 0x7ff; - uint32 data; - - if (an < 2040) { - data = be16toh(*(uint16 *)&mem[an]); - putlog(3, "$%08x -> $%04x", addr, data); - } else { - putlog(0, "未実装ワード読み込み $%08x", addr); - data = 0xffff; - } - return data; -} - -uint64 -MK48T02Device::Read32(uint32 addr) -{ - // アドレスは 2KB 単位でミラーになっている。 - uint32 an = addr & 0x7ff; - uint32 data; - - if (an < 2040) { - data = be32toh(*(uint32 *)&mem[an]); - putlog(3, "$%08x -> $%08x", addr, data); - } else { - putlog(0, "未実装ロング読み込み $%08x", addr); - data = 0xffffffff; - } - return data; -} - -uint64 -MK48T02Device::Write8(uint32 addr, uint32 data) +MK48T02Device::Write(uint32 addr, uint32 data) { - // アドレスは 2KB 単位でミラーになっている。 - uint32 an = addr & 0x7ff; + uint32 an = addr; if (an < 2040) { putlog(3, "$%08x <- $%02x", addr, data); @@ -260,48 +243,16 @@ MK48T02Device::Write8(uint32 addr, uint3 } break; default: - putlog(0, "未実装バイト書き込み $%08x <- %02x", addr, data); - break; + __unreachable(); } } return 0; } uint64 -MK48T02Device::Write16(uint32 addr, uint32 data) +MK48T02Device::Peek(uint32 addr) { - // アドレスは 2KB 単位でミラーになっている。 - uint32 an = addr & 0x7ff; - - if (an < 2040) { - putlog(3, "$%08x <- $%04x", addr, data); - *(uint16 *)&mem[an] = htobe16(data); - } else { - putlog(0, "未実装ワード書き込み $%08x <- %04x", addr, data); - } - return 0; -} - -uint64 -MK48T02Device::Write32(uint32 addr, uint32 data) -{ - // アドレスは 2KB 単位でミラーになっている。 - uint32 an = addr & 0x7ff; - - if (an < 2040) { - putlog(3, "$%08x <- $%08x", addr, data); - *(uint32 *)&mem[an] = htobe32(data); - } else { - putlog(0, "未実装ロング書き込み $%08x <- %08x", addr, data); - } - return 0; -} - -uint64 -MK48T02Device::Peek8(uint32 addr) -{ - // アドレスは 2KB 単位でミラーになっている。 - uint32 an = addr & 0x7ff; + uint32 an = addr; uint8 data; if (an < 2040) { @@ -333,7 +284,7 @@ MK48T02Device::Peek8(uint32 addr) case 7: // 年 return reg.year; default: - return 0xff; + __unreachable(); } } } @@ -404,3 +355,41 @@ MK48T02Device::ClockIn() // 内部表現とデバイスから読み出せる値が同じなので、更新処理は不要。 CountUp(); } + +// 指定したアドレスからのゼロ終端文字列を返す +// (内蔵 ROM からのアクセス用) +std::string +MK48T02Device::PeekString(uint32 addr) const +{ + std::string rv = ""; + + uint32 an = addr & 0x7ff; + for (; mem[an]; an++) { + rv += mem[an]; + } + return rv; +} + +// 指定したアドレスに文字列を書き込み、 +// 16 バイトに満たないところはゼロでパディングする。 +// 書き込めれば true を、書き込めなければ false を返す。 +// (内蔵 ROM からの書き込み用) +bool +MK48T02Device::WriteString(uint32 addr, const std::string& data) +{ + int i = 0; + + // XXX ここの文字列はゼロ終端なのかどうか + if (data.length() == 0 || data.length() > 15) { + return false; + } + + addr &= 0x7ff; + for (; i < data.length(); i++) { + Write(addr + i, data[i]); + } + for (; i < 16; i++) { + Write(addr + i, 0); + } + return true; +}