--- nono/vm/romemu_luna88k.cpp 2026/04/29 17:05:14 1.1.1.12 +++ nono/vm/romemu_luna88k.cpp 2026/04/29 17:05:18 1.1.1.13 @@ -5,7 +5,7 @@ // // -// LUNA88K の ROM エミュレーション +// LUNA-88K の ROM エミュレーション // // IODevice @@ -18,10 +18,10 @@ // | +-- CGROMDevice (X680x0 の CGROM) // | +-- LunaPROMEmuDevice (LUNA PROM エミュレーションの共通部分) // | | -// | +-- Luna1PROMEmuDevice (LUNA1 の PROM エミュレーション) +// | +-- Luna1PROMEmuDevice (LUNA-I の PROM エミュレーション) // | | // | | +----------------------+ -// | +--| Luna88kPROMEmuDevice | (LUNA88K の PROM エミュレーション) +// | +--| Luna88kPROMEmuDevice |(LUNA-88K の PROM エミュレーション) // | +----------------------+ // | // +-- PROM0Device (LUNA* のブートページ切り替え用プロキシ) @@ -31,13 +31,13 @@ #include "interrupt.h" #include "iodevstream.h" #include "mainapp.h" +#include "mainram.h" #include "memorystream.h" #include "mk48t02.h" #include "mpu88xx0.h" #include "pio.h" -#include "ram.h" -static bool luna88k_fline_callback(m88kcpu *cpu, void *arg); +static bool luna88k_fline_callback(MPU88xx0Device *cpu, void *arg); // m88k の命令コードを少し読みやすく書きたい。 // 必要なものは適宜足すこと。 @@ -60,6 +60,7 @@ enum class OPr { #define r10 OPr::r10 enum OPm5 { eq0 = 0x02, + ge0 = 0x03, ne0 = 0x0d, }; enum OPcr { @@ -128,11 +129,9 @@ USC uint32 OP_doscall(OPr rd, OPr rs1, u // コンストラクタ Luna88kPROMEmuDevice::Luna88kPROMEmuDevice() { - devaddr = baseaddr; - // ROM の特定アドレスを読み出す人がいるかも知れないので、 // サイズは実 ROM と同じにしておく。LUNA-I からの類推。 - devlen = 256 * 1024; + uint devlen = 256 * 1024; imagebuf.reset(new uint8 [devlen]); memset(&imagebuf[0], 0, devlen); mem = &imagebuf[0]; @@ -148,16 +147,19 @@ Luna88kPROMEmuDevice::~Luna88kPROMEmuDev { } +// 初期化 bool Luna88kPROMEmuDevice::Init() { - // 親クラス if (inherited::Init() == false) { return false; } + interrupt = GetInterruptDevice(); + // DOS call エミュレーションのコールバックを登録 - gMPU88xx0->SetFLineCallback(luna88k_fline_callback, this); + auto mpu88xx0 = GetMPU88xx0Device(); + mpu88xx0->SetFLineCallback(luna88k_fline_callback, this); MemoryStreamBE ms(imagebuf.get()); @@ -185,11 +187,11 @@ Luna88kPROMEmuDevice::Init() ms.Write32(OP_clr (r9, r10, 2, 0)); // clear IND,SFRZ ms.Write32(OP_or_u (r3, r0, ROMIO_BASE >> 16)); - ms.Write32(OP_or (r3, r3, ROMIO_BASE & 0xfff)); + ms.Write32(OP_or (r3, r3, ROMIO_BASE & 0xffff)); // ROMIO_INIT を読み出す ms.Write32(OP_ld (r2, r3, (ROMIO_INIT - ROMIO_BASE))); // 起動先があれば GO - ms.Write32(OP_bcnd (ne0, r2, 7)); // 7 = _go + ms.Write32(OP_bcnd (ge0, r2, 7)); // 7 = _go // _prompt: // 疑似 STOP でキー入力を待つ @@ -201,6 +203,7 @@ Luna88kPROMEmuDevice::Init() ms.Write32(OP_jmp (r1)); // _back: + uint32 back = baseaddr + ms.GetOffset(); // 割り込み禁止に戻す ms.Write32(OP_stcr (r10, psr)); @@ -219,7 +222,8 @@ Luna88kPROMEmuDevice::Init() ms.SetOffset(0x200); ms.Write32(OP_ld (r0, r3, (ROMIO_KEYIN - ROMIO_BASE))); // 戻ったところの jmp を抜ける - ms.Write32(OP_addu (r1, r1, 0x04)); + ms.Write32(OP_or_u (r1, r0, back >> 16)); + ms.Write32(OP_or (r1, r1, back & 0xffff)); ms.Write32(OP_rte ()); // ROM GETC エミュレータ @@ -228,9 +232,9 @@ Luna88kPROMEmuDevice::Init() ms.Write32(OP_jmp (r1)); // ROM PUTC エミュレータ - // 表示する文字は r3 に置かれている。 + // 表示する文字は r2 に置かれている。 ms.SetOffset(0x400); - ms.Write32(OP_doscall(r0, r3, DOS_PUTCHAR)); + ms.Write32(OP_doscall(r0, r2, DOS_PUTCHAR)); ms.Write32(OP_jmp (r1)); @@ -245,16 +249,18 @@ Luna88kPROMEmuDevice::Init() uint32 Luna88kPROMEmuDevice::ROM_Init() { - IODeviceStream rs(gRAM); + IODeviceStream rs(mainram); uint32 entry; - b_entrypoint = 0; + b_entrypoint = -1; // デバイスの初期化 (親クラス) InitDevice(); + auto pio0 = GetPIO0Device(); + // 割り込みマスクで SIO だけ許可 - gInterrupt->Write32(0x65000000, 0x40000000); + interrupt->Write32(0x65000000, 0x40000000); rs.SetAddr(0); // ベクタテーブルを rte で埋めておく @@ -289,7 +295,7 @@ Luna88kPROMEmuDevice::ROM_Init() // スクリーンを初期化 InitScreen(); - entry = 0; + entry = -1; // 表示環境が整ったところで NVRAM を照合 if (VerifyNVRAM() == false) { @@ -315,7 +321,7 @@ Luna88kPROMEmuDevice::ROM_Init() } else { // DIPSW#1-1 が UP なら自動起動、DOWN なら ROM モニタ起動なので、 // これを真似する。 - if (gPIO0->IsDIPSW11Up()) { + if (pio0->IsDIPSW11Up()) { // NVRAM の設定に従ってブート先を探す。 errmsg.clear(); @@ -326,7 +332,7 @@ Luna88kPROMEmuDevice::ROM_Init() } done: - if (entry == 0) { + if (entry == -1) { PrintTitle("LUNA88K"); if (errmsg.empty() == false) { Print("** %s\n\n", errmsg.c_str()); @@ -341,7 +347,7 @@ Luna88kPROMEmuDevice::ROM_Init() uint32 Luna88kPROMEmuDevice::ROM_Entry() { - if (b_entrypoint != 0) { + if (b_entrypoint != -1) { return b_entrypoint; } else { return 0; @@ -349,11 +355,11 @@ Luna88kPROMEmuDevice::ROM_Entry() } void -Luna88kPROMEmuDevice::GetChar(char asciicode) +Luna88kPROMEmuDevice::ProcessChar(char asciicode) { if (prompt_idx == 0) { // 行入力モード (画面更新もしてある) - inherited::GetChar(asciicode); + inherited::ProcessChar(asciicode); } else { // 0 以外ならノンブロッキングモード @@ -481,7 +487,7 @@ Luna88kPROMEmuDevice::CommandB(const std bootinfo_t bootinfo; GetNVRAM(bootinfo); b_entrypoint = LoadGuestFile(bootinfo); - if (b_entrypoint == 0) { + if (b_entrypoint == -1) { Print("** %s\n", errmsg.c_str()); } } @@ -549,7 +555,7 @@ Luna88kPROMEmuDevice::CommandNvram(const // // オフセット 0x540 から始まるエントリが最後で、これ以上追加しようとすると // "nvram set error: no area" (PROM 1.20) と言われる。 -// LUNA88K にはないが LUNA-I では 0x560 にぽつんと ENADDR があったので、 +// LUNA-88K にはないが LUNA-I では 0x560 にぽつんと ENADDR があったので、 // その辺りとの互換性だろうか。 // NVRAM 全項目表示 @@ -805,7 +811,7 @@ Luna88kPROMEmuDevice::GetNVRAM(bootinfo_ // コールバック関数 (C のグローバル関数) bool -luna88k_fline_callback(m88kcpu *cpu, void *arg) +luna88k_fline_callback(MPU88xx0Device *cpu, void *arg) { Luna88kPROMEmuDevice *dev = (Luna88kPROMEmuDevice *)arg; return dev->FLineCallback(cpu); @@ -813,7 +819,7 @@ luna88k_fline_callback(m88kcpu *cpu, voi // コールバック関数 (こっちが実体) bool -Luna88kPROMEmuDevice::FLineCallback(m88kcpu *cpu) +Luna88kPROMEmuDevice::FLineCallback(MPU88xx0Device *cpu) { // 111111_DDDDDSSSSS_000001_00nnnnnnnn // @@ -823,25 +829,25 @@ Luna88kPROMEmuDevice::FLineCallback(m88k // すべてこちらで責任持って処理すること。 // 戻り値がある DOS call では戻り値は rD に格納。 - uint32 D = (cpu->opX >> 21) & 0x1f; - uint32 S1 = (cpu->opX >> 16) & 0x1f; - uint32 num = cpu->opX & 0xff; + uint32 D = (cpu->reg.opX >> 21) & 0x1f; + uint32 S1 = (cpu->reg.opX >> 16) & 0x1f; + uint32 num = cpu->reg.opX & 0xff; switch (num) { case 0x00: // _EXIT break; case 0x01: // _GETCHAR - cpu->r[D] = getchar(); + cpu->reg.r[D] = Getc(); break; case 0x02: // _PUTCHAR - Putc(cpu->r[S1++] & 0xff); + Putc(cpu->reg.r[S1++] & 0xff); break; default: putlog(0, "DOS call #$%02x (NOT IMPLEMENTED)", num); - cpu->r[D] = 0xffffffff; + cpu->reg.r[D] = 0xffffffff; break; }