--- nono/vm/romemu_news.cpp 2026/04/29 17:05:17 1.1 +++ nono/vm/romemu_news.cpp 2026/04/29 17:05:28 1.1.1.3 @@ -8,7 +8,31 @@ // NEWS の ROM エミュレーション (-X のみ対応) // +// IODevice +// | +// +- ROMDevice (LoadROM()、ウェイト、マスク等を持つ) +// | +- PROMDevice (LUNA* の PROM) +// | +- IPLROM1Device (X680x0 の IPLROM 後半) +// | +- IPLROM2Device (X680x0 の IPLROM 前半) +// | +- CGROMDevice (X680x0 の CGROM) +// | | +// | +- ROMEmuDevice +// | +- LunaPROMEmuDevice (LUNA PROM エミュレーションの共通部分) +// | | +- Luna1PROMEmuDevice (LUNA-I の PROM エミュレーション) +// | | +- Luna88kPROMEmuDevice (LUNA-88K の PROM エミュレーション) +// | | +// | | +------------------+ +// | +-| NewsROMEmuDevice | (NEWS の ROM エミュレーション) +// | | +------------------+ +// | | +// | +- ROM30EmuDevice (X68030 の ROM30 エミュレーション) +// | +- Virt68kROMEmuDevice (virt-m68k の IPLROM 相当の何か) +// | +// +- PROM0Device (LUNA* のブートページ切り替え用プロキシ) +// +- IPLROM0Device (X680x0 のブートページ切り替え用プロキシ) + #include "romemu_news.h" +#include "mainbus.h" #include "mainram.h" #include "memorystream.h" #include "mpu680x0.h" @@ -42,35 +66,46 @@ NewsROMEmuDevice::Init() mainram = GetMainRAMDevice(); - MemoryStreamBE ms(imagebuf.get()); - ms.Write32(0x00000400); // +00: リセットベクタ SP - ms.Write32(0xf8000400); // +04: リセットベクタ PC + MemoryStreamBE roms(imagebuf.get()); + roms.Write4(0x00000400); // +00: リセットベクタ SP + roms.Write4(0xf8000400); // +04: リセットベクタ PC // ベクタ for (int i = 2; i < 256; i++) { - ms.Write32(0); + roms.Write4(0); + } + roms.SetOffset(32 * 4); + roms.Write4(0xf8000500); // Trap#0 で ROM のサービスコール + // Trap#15 は ROM モニタらしい。今の所停止するだけ。 + // とりあえず Trap#1..#14 も全部ここへ向けておく。 + for (int i = 1; i < 16; i++) { + roms.Write4(0xf8000600); } - ms.SetOffset(32 * 4); - ms.Write32(0xf8000500); // Trap#0 で ROM のサービスコール // リセット時に実行する命令 - ms.SetOffset(0x400); - ms.Write16(0x2039); // move.l (ROMIO_INIT),d0 - ms.Write32(ROMIO_INIT); - ms.Write16(0x2040); // move.l d0,a0 ; ジャンプ先を a0 にセット - ms.Write16(0x4ed0); // jmp (a0) ; ジャンプ + roms.SetOffset(0x400); + roms.Write2(0x2039); // move.l (ROMIO_INIT),d0 + roms.Write4(ROMIO_INIT); + roms.Write2(0x2040); // move.l d0,a0 ; ジャンプ先を a0 にセット + roms.Write2(0x4ed0); // jmp (a0) ; ジャンプ // ROM サービスコール - ms.SetOffset(0x500); - ms.Write16(0x0c80); // cmpi.l #3,d0 - ms.Write32(0x00000003); // - ms.Write16(0x6708); // beq @f - ms.Write16(0x2039); // move.l (ROMIO_SYS),d0 - ms.Write32(ROMIO_SYS); // - ms.Write16(0x4e73); // rte + roms.SetOffset(0x500); + roms.Write2(0x0c80); // cmpi.l #3,d0 + roms.Write4(0x00000003); // + roms.Write2(0x6708); // beq @f + roms.Write2(0x2039); // move.l (ROMIO_SYS),d0 + roms.Write4(ROMIO_SYS); // + roms.Write2(0x4e73); // rte //@@: ; Read は対応してないので - ms.Write32(0x4e722500); // stop #0x2500 ; STOP しつつ - ms.Write16(0x60fa); // bra @b ; 無限ループ。 - ms.Write16(0x4e73); // rte + roms.Write4(0x4e722500); // stop #0x2500 ; STOP しつつ + roms.Write2(0x60fa); // bra @b ; 無限ループ。 + roms.Write2(0x4e73); // rte + + // ROM モニタの TRAP#n。はないのでここに来たらとりあえず停止する? + roms.SetOffset(0x600); + //@@: + roms.Write4(0x4e722700); // stop #0x2700 ; STOP しつつ + roms.Write2(0x60fa); // bra @b ; 無限ループ。 return true; } @@ -79,49 +114,46 @@ void NewsROMEmuDevice::ResetHard(bool poweron) { // 起動時に RAM にリセットベクタを書き込んでおく。(手抜き) - for (int i = 0; i < 8; i++) { - mainram->Write8(i, imagebuf[i]); - } + mainram->WriteMem(0, &imagebuf[0], 8); } +// ROMIO から読み出す。 +// ROMIO が応答すべきでなければ (uint64)-1 を返す。 uint64 -NewsROMEmuDevice::Read32(uint32 addr) +NewsROMEmuDevice::ReadROMIO(busaddr addr) { - switch (addr) { - case ROMIO_INIT: - return ROM_Init(); + if (addr.GetSize() == 4) { + switch (addr.Addr()) { + case ROMIO_INIT: + return ROM_Init(); - case ROMIO_SYS: - return ROM_Sys(); + case ROMIO_SYS: + return ROM_Sys(); - default: - break; + default: + break; + } } - return inherited::Read32(addr); + return (uint64)-1; } uint32 NewsROMEmuDevice::ROM_Init() { - LoadInfo info; + // -X file で指定されたホストファイルを読み込んでエントリポイント + // アドレスをこの Read アクセスの読み出し値として返す。 - // -X file - if (gMainApp.exec_file) { - // ホストのファイルを読み込んでエントリポイントアドレスを - // この Read アクセスの読み出し値として返す。 - // エラーがあればエラーメッセージは呼び出し先側で表示してある。 - info.path = gMainApp.exec_file; - if (mainram->LoadFromFile(&info) == false) { - // XXX どうすべ - PANIC("** Couldn't load specified host program.\n"); - return -1; - } - putmsg(1, "Host program loaded. Entry point = $%08x\n", info.entry); + LoadInfo info(gMainApp.exec_file); + if (mainram->LoadExec(&info) == false) { + // XXX どうすべ + PANIC("** Couldn't load specified host program"); + return -1; } + putmsg(1, "Host program loaded. Entry point = $%08x", info.entry); // ROMCONS のために VBR を設定 - m68kreg& reg = GetMPU680x0Device()->reg; + m68kreg& reg = GetMPU680x0Device(mpu)->reg; reg.vbr = 0xf8000000; // %d2 には MARK_END (たぶん最後の番地) @@ -148,22 +180,24 @@ NewsROMEmuDevice::ROM_Init() uint32 NewsROMEmuDevice::ROM_Sys() { - auto mpu680x0 = GetMPU680x0Device(); + auto mainbus = GetMainbusDevice(); + auto mpu680x0 = GetMPU680x0Device(mpu); m68kreg& reg = mpu680x0->reg; auto newsfb = GetNewsfbDevice(); if (reg.D[0] == SYS_write) { uint32 a6 = reg.A[6]; - uint32 fd = mpu680x0->Read32(a6 + 8); - uint32 buf = mpu680x0->Read32(a6 + 12); - uint32 len = mpu680x0->Read32(a6 + 16); + uint32 fd = mainbus->HVRead4(a6 + 8); + uint32 buf = mainbus->HVRead4(a6 + 12); + uint32 len = mainbus->HVRead4(a6 + 16); for (int i = 0; i < len; i++) { - uint64 ch = mpu680x0->Read8(buf++); - if ((int64)ch < 0) { + busdata bd = mainbus->HVRead1(buf++); + if (bd.IsBusErr()) { // XXX ? return 0; } + uint8 ch = bd.Data(); if (ch == '\r') { continue; }