--- nono/vm/msxdos.cpp 2026/04/29 17:05:33 1.1.1.5 +++ nono/vm/msxdos.cpp 2026/04/29 17:06:00 1.1.1.7 @@ -28,13 +28,6 @@ static void msxdos_callback(void *arg); MSXDOSDevice::MSXDOSDevice() : inherited() { - // 大きさは適当 - uint devlen = 128 * 1024; - imagebuf.reset(new uint8 [devlen]); - memset(&imagebuf[0], 0, devlen); - mem = &imagebuf[0]; - - mask = devlen - 1; } // デストラクタ @@ -50,6 +43,12 @@ MSXDOSDevice::Init() return false; } + // ROM 領域を用意。 + if (AllocROM(128 * 1024, 0) == false) { + // エラーメッセージは表示済み。 + return false; + } + cursor_x = 0; xp = GetMPU64180Device(); xpbus = GetXPbusDevice(); @@ -57,6 +56,20 @@ MSXDOSDevice::Init() // システムコール処理のコールバックを設定 xp->SetSYSCALLCallback(msxdos_callback, this); + // 実行ファイルオープン。 + // 失敗したらエラー終了したいので Init() で行うが、この時点ではまだ + // 書き込み先となる SubRAM の初期化が終わっていないので書き込めない。 + if (LoadBinary(gMainApp.exec_file) == false) { + return false; + } + + return true; +} + +// リセット +void +MSXDOSDevice::ResetHard(bool poweron) +{ // // ROM っぽいものを用意。 // @@ -95,7 +108,7 @@ MSXDOSDevice::Init() const uint16 _trap_handler = 0x7060; // リセットベクタ - xs.SetOffset(0x0000); + xs.SetAddr(0x0000); xs.Write1(0xc3); // 0000: JP _rominit xs.Write2LE(_rominit); xs.Write2(0x0000); // 0003: 00,00 @@ -104,7 +117,7 @@ MSXDOSDevice::Init() // RST エントリの初期化 for (int i = 1; i < 8; i++) { - xs.SetOffset(i * 8); + xs.SetAddr(i * 8); xs.Write1(0x0e); // +00: LD C,`RST xxH` xs.Write1(0xc7 | (i << 3)); xs.Write2(0xedff); // +02: SYSCALL @@ -115,7 +128,7 @@ MSXDOSDevice::Init() // SP として使っているらしいので、先頭に DOSCALL ハンドラを用意。 // DOSCALL ハンドラ。 - xs.SetOffset(_doscall); + xs.SetAddr(_doscall); xs.Write1(0x79); // 7000: LD A,C xs.Write1(0xb7); // 7001: OR A xs.Write1(0xca); // 7002: JP Z,_term + 2 @@ -124,7 +137,7 @@ MSXDOSDevice::Init() xs.Write1(0xc9); // 7007: RET // TERM - xs.SetOffset(_term); + xs.SetAddr(_term); xs.Write2(0x0e00); // 7010: LD C,00H xs.Write2(0xedff); // 7012: SYSCALL xs.Write1(0x76); // 7014: HALT @@ -133,7 +146,7 @@ MSXDOSDevice::Init() // XP 側の初期化ルーチン。 // 0000H 番地をトラップハンドラに向け変えて、 // 0100H にジャンプ。戻ってきたら終了。 - xs.SetOffset(_rominit); + xs.SetAddr(_rominit); xs.Write2(0x3e3c); // 7030: LD A,3CH xs.Write2(0xed39); // 7032: OUT0 (36H),A xs.Write1(0x36); @@ -147,13 +160,13 @@ MSXDOSDevice::Init() xs.Write2LE(_term); // msg_trap - xs.SetOffset(_msg_trap); + xs.SetAddr(_msg_trap); xs.WriteString("trap occured!\x0d\x0a$"); // トラップハンドラ。 // XXX: とりあえず未定義命令をスキップしたい。 // まだ LD IXH,n のようなオペランドを持つ命令をうまくスキップできない。 - xs.SetOffset(_trap_handler); + xs.SetAddr(_trap_handler); xs.Write1(0xe3); // +00: EX (SP),HL xs.Write1(0xf5); // +01: PUSH AF xs.Write1(0x23); // +02: INC HL @@ -171,29 +184,22 @@ MSXDOSDevice::Init() xs.Write1(0xe3); // +15: EX (SP),HL xs.Write1(0xc9); // +16: RET - // 実行ファイルオープン - std::vector src; - if (LoadBinary(gMainApp.exec_file, src) == false) { - return false; - } - - // コピー - xs.SetOffset(0x100); - for (auto s : src) { + // 読んでおいたファイルをここでコピー。 + xs.SetAddr(0x100); + for (auto s : filebuf) { xs.Write1(s); } - - return true; + filebuf.clear(); } -// filename で示されるファイルをロードする。 +// filename で示されるファイルを filebuf にロードする。 // 成功すれば data に格納して true を返す。 // 失敗すればエラーメッセージを表示し、false を返す。 // サポートしているのは // o z80-asm の出力する .z80 形式 // o MSX-DOS の .COM 形式 (生バイナリ) bool -MSXDOSDevice::LoadBinary(const char *filename, std::vector& dst) +MSXDOSDevice::LoadBinary(const char *filename) { struct stat st; size_t dlsize; @@ -241,8 +247,8 @@ MSXDOSDevice::LoadBinary(const char *fil return false; } - dst.resize(dlsize); - r = read(fd, dst.data(), dst.size()); + filebuf.resize(dlsize); + r = read(fd, filebuf.data(), filebuf.size()); if (r < 0) { warn("\%s\" read failed", filename); return false;