--- nono/vm/romemu_news.cpp 2026/04/29 17:05:24 1.1.1.2 +++ nono/vm/romemu_news.cpp 2026/04/29 17:05:59 1.1.1.7 @@ -8,24 +8,42 @@ // 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 "mainapp.h" #include "mainbus.h" #include "mainram.h" #include "memorystream.h" #include "mpu680x0.h" #include "newsfb.h" +#include "power.h" // コンストラクタ NewsROMEmuDevice::NewsROMEmuDevice() : inherited(OBJ_PROM) { - // 適当 - uint devlen = 4096; - imagebuf.reset(new uint8 [devlen]); - memset(&imagebuf[0], 0, devlen); - mem = &imagebuf[0]; - - mask = devlen - 1; } // デストラクタ @@ -37,52 +55,53 @@ NewsROMEmuDevice::~NewsROMEmuDevice() bool NewsROMEmuDevice::Init() { - if (inherited::Init() == false) { + // ROM 領域を用意。サイズは適当。 + if (AllocROM(2048, 0) == false) { return false; } 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); } - ms.SetOffset(32 * 4); - ms.Write32(0xf8000500); // Trap#0 で ROM のサービスコール + roms.SetOffset(32 * 4); + roms.Write4(0xf8000500); // Trap#0 で ROM のサービスコール // Trap#15 は ROM モニタらしい。今の所停止するだけ。 // とりあえず Trap#1..#14 も全部ここへ向けておく。 for (int i = 1; i < 16; i++) { - ms.Write32(0xf8000600); + roms.Write4(0xf8000600); } // リセット時に実行する命令 - 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。はないのでここに来たらとりあえず停止する? - ms.SetOffset(0x600); + roms.SetOffset(0x600); //@@: - ms.Write32(0x4e722700); // stop #0x2700 ; STOP しつつ - ms.Write16(0x60fa); // bra @b ; 無限ループ。 + roms.Write4(0x4e722700); // stop #0x2700 ; STOP しつつ + roms.Write2(0x60fa); // bra @b ; 無限ループ。 return true; } @@ -91,26 +110,28 @@ void NewsROMEmuDevice::ResetHard(bool poweron) { // 起動時に RAM にリセットベクタを書き込んでおく。(手抜き) - for (int i = 0; i < 8; i++) { - mainram->Write8(i, imagebuf[i]); - } + mainram->WriteMem(0, &imagebuf[0], 8); } -busdata -NewsROMEmuDevice::Read32(uint32 addr) +// ROMIO から読み出す。 +// ROMIO が応答すべきでなければ (uint64)-1 を返す。 +uint64 +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 @@ -120,9 +141,10 @@ NewsROMEmuDevice::ROM_Init() // アドレスをこの Read アクセスの読み出し値として返す。 LoadInfo info(gMainApp.exec_file); - if (mainram->LoadExec(&info) == false) { - // XXX どうすべ - PANIC("** Couldn't load specified host program"); + if (BootLoader::LoadExec(mainram, &info) == false) { + // エラーメッセージは表示済み。 + auto power = GetPowerDevice(); + power->PushPowerButton(); return -1; } putmsg(1, "Host program loaded. Entry point = $%08x", info.entry); @@ -145,7 +167,7 @@ NewsROMEmuDevice::ROM_Init() // 下位28ビット(7桁) は ROM から渡されるようだ。 // %d7 は boothowto。 reg.D[2] = info.sym; - reg.D[4] = mainram->GetSize(); + reg.D[4] = (uint32)mainram->GetSize(); reg.D[6] = 0x50000000; reg.D[7] = 0; @@ -162,12 +184,12 @@ NewsROMEmuDevice::ROM_Sys() if (reg.D[0] == SYS_write) { uint32 a6 = reg.A[6]; - uint32 fd = mainbus->HVRead32(a6 + 8); - uint32 buf = mainbus->HVRead32(a6 + 12); - uint32 len = mainbus->HVRead32(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++) { - busdata bd = mainbus->HVRead8(buf++); + busdata bd = mainbus->HVRead1(buf++); if (bd.IsBusErr()) { // XXX ? return 0;