--- nono/vm/romemu_luna88k.cpp 2026/04/29 17:05:25 1.1.1.14 +++ nono/vm/romemu_luna88k.cpp 2026/04/29 17:05:43 1.1.1.16 @@ -9,34 +9,37 @@ // // IODevice -// | -// +-- ROMDevice (LoadROM()、ウェイト、マスク等を持つ) -// | | -// | +-- PROMDevice (LUNA* の PROM) -// | +-- IPLROM1Device (X680x0 の IPLROM 後半) -// | +-- IPLROM2Device (X680x0 の IPLROM 前半) -// | +-- CGROMDevice (X680x0 の CGROM) -// | +-- LunaPROMEmuDevice (LUNA PROM エミュレーションの共通部分) -// | | -// | +-- Luna1PROMEmuDevice (LUNA-I の PROM エミュレーション) -// | | -// | | +----------------------+ -// | +--| Luna88kPROMEmuDevice |(LUNA-88K の PROM エミュレーション) -// | +----------------------+ -// | -// +-- PROM0Device (LUNA* のブートページ切り替え用プロキシ) -// +-- IPLROM0Device (X680x0 のブートページ切り替え用プロキシ) +// | +// +- 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_luna88k.h" -#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 "sysclk.h" +#include "sysctlr.h" static bool luna88k_fline_callback(MPU88xx0Device *cpu, void *arg); @@ -166,15 +169,6 @@ Luna88kPROMEmuDevice::Luna88kPROMEmuDevi { machine_name = "LUNA-88K"; - // ROM の特定アドレスを読み出す人がいるかも知れないので、 - // サイズは実 ROM と同じにしておく。LUNA-I からの類推。 - uint devlen = 256 * 1024; - imagebuf.reset(new uint8 [devlen]); - memset(&imagebuf[0], 0, devlen); - mem = &imagebuf[0]; - - mask = devlen - 1; - // プロンプトを初期化。 prompt = default_prompt; } @@ -192,13 +186,19 @@ Luna88kPROMEmuDevice::Init() return false; } + // ROM の特定アドレスを読み出す人がいるかも知れないので、 + // サイズは実 ROM と同じにしておく。LUNA-I からの類推。 + if (AllocROM(256 * 1024, 0) == false) { + return false; + } + SysClkDevice *sysclk = GetSysClkDevice(); // DOS call エミュレーションのコールバックを登録 auto mpu88xx0 = GetMPU88xx0Device(mpu); mpu88xx0->SetFLineCallback(luna88k_fline_callback, this); - MemoryStreamBE ms(imagebuf.get()); + MemoryStreamBE roms(imagebuf.get()); // リセット時のブートページには ROM (これ) が見えている。 // ROMIO_INIT へのアクセスでブートページを RAM に切り替えて、同時に RAM の @@ -211,113 +211,113 @@ Luna88kPROMEmuDevice::Init() // _START: // ここは 0番地。ここから _ROM_START へジャンプ - ms.Write32(OP_or_u (r6, r0, 0x4100)); - ms.Write32(OP_or (r6, r6, 0x000c)); - ms.Write32(OP_jmp (r6)); + roms.Write4(OP_or_u (r6, r0, 0x4100)); + roms.Write4(OP_or (r6, r6, 0x000c)); + roms.Write4(OP_jmp (r6)); // _ROM_START: (ここは ROM) // RAM に切り替え - ms.Write32(OP_st (r0, r6, r0)); + roms.Write4(OP_st (r0, r6, r0)); // 元の PSR を r10 に保存し、r9 に割り込み許可の値を作る - ms.Write32(OP_ldcr (r10, psr)); - ms.Write32(OP_clr (r9, r10, 2, 0)); // clear IND,SFRZ - ms.Write32(OP_stcr (r9, psr)); - ms.Write32(OP_or (r11, r0, r0)); // r11 <- 0 + roms.Write4(OP_ldcr (r10, psr)); + roms.Write4(OP_clr (r9, r10, 2, 0)); // clear IND,SFRZ + roms.Write4(OP_stcr (r9, psr)); + roms.Write4(OP_or (r11, r0, r0)); // r11 <- 0 - ms.Write32(OP_or_u (r3, r0, ROMIO_BASE >> 16)); - ms.Write32(OP_or (r3, r3, ROMIO_BASE & 0xffff)); + roms.Write4(OP_or_u (r3, r0, ROMIO_BASE >> 16)); + roms.Write4(OP_or (r3, r3, ROMIO_BASE & 0xffff)); // ROMIO_INIT を実行 - ms.Write32(OP_ld (r0, r3, (ROMIO_INIT - ROMIO_BASE))); - ms.Write32(OP_ld (r0, r3, (ROMIO_LOAD - ROMIO_BASE))); - ms.Write32(OP_br (5)); // _entry + roms.Write4(OP_ld (r0, r3, (ROMIO_INIT - ROMIO_BASE))); + roms.Write4(OP_ld (r0, r3, (ROMIO_LOAD - ROMIO_BASE))); + roms.Write4(OP_br (5)); // _entry // _prompt: - uint32 prompt = ms.GetOffset(); - ms.Write32(OP_or_u (r11, r0, 0x4100)); - ms.Write32(OP_or (r11, r11, ms.GetOffset() + 8)); - ms.Write32(OP_br (0)); // STOP 相当 - ms.Write32(OP_or (r11, r0, r0)); + uint32 prompt = roms.GetOffset(); + roms.Write4(OP_or_u (r11, r0, 0x4100)); + roms.Write4(OP_or (r11, r11, roms.GetOffset() + 8)); + roms.Write4(OP_br (0)); // STOP 相当 + roms.Write4(OP_or (r11, r0, r0)); // _entry: - ms.Write32(OP_ld (r2, r3, (ROMIO_ENTRY - ROMIO_BASE))); - ms.Write32(OP_or_c (r5, r0, r0)); // r5 <- $ffffffff - ms.Write32(OP_cmp (r5, r2, r5)); - ms.Write32(OP_bb1 (CMP_EQ, r5, -7)); // 起動先なければループ + roms.Write4(OP_ld (r2, r3, (ROMIO_ENTRY - ROMIO_BASE))); + roms.Write4(OP_or_c (r5, r0, r0)); // r5 <- $ffffffff + roms.Write4(OP_cmp (r5, r2, r5)); + roms.Write4(OP_bb1 (CMP_EQ, r5, -7)); // 起動先なければループ // _go: // 起動先があれば後始末して - ms.Write32(OP_ld (r0, r3, (ROMIO_CLOSE - ROMIO_BASE))); + roms.Write4(OP_ld (r0, r3, (ROMIO_CLOSE - ROMIO_BASE))); // 割り込み禁止に戻して - ms.Write32(OP_stcr (r10, psr)); + roms.Write4(OP_stcr (r10, psr)); // 戻ってきたときのために r1 を用意して - ms.Write32(OP_or_u (r1, r0, 0x4100)); - ms.Write32(OP_or (r1, r1, ms.GetOffset() + 8)); + roms.Write4(OP_or_u (r1, r0, 0x4100)); + roms.Write4(OP_or (r1, r1, roms.GetOffset() + 8)); // ジャンプ - ms.Write32(OP_jmp (r2)); + roms.Write4(OP_jmp (r2)); // 戻ってきたら - ms.Write32(OP_br ((prompt - ms.GetOffset()) / 4)); + roms.Write4(OP_br ((prompt - roms.GetOffset()) / 4)); // 割り込みハンドラ。 // _intr: - ms.SetOffset(0x200); - ms.Write32(OP_or_u (r6, r0, 0x6500)); - ms.Write32(OP_ld (r6, r6, 0)); - ms.Write32(OP_extu (r6, r6, 3, 29)); - ms.Write32(OP_or (r7, r0, 6)); - ms.Write32(OP_cmp (r7, r6, r7)); - ms.Write32(OP_bb1 (CMP_EQ, r7, (0x240 - ms.GetOffset()) / 4)); + roms.SetOffset(0x200); + roms.Write4(OP_or_u (r6, r0, 0x6500)); + roms.Write4(OP_ld (r6, r6, 0)); + roms.Write4(OP_extu (r6, r6, 3, 29)); + roms.Write4(OP_or (r7, r0, 6)); + roms.Write4(OP_cmp (r7, r6, r7)); + roms.Write4(OP_bb1 (CMP_EQ, r7, (0x240 - roms.GetOffset()) / 4)); // key_intr: - ms.Write32(OP_ld (r0, r3, (ROMIO_KEYIN - ROMIO_BASE))); + roms.Write4(OP_ld (r0, r3, (ROMIO_KEYIN - ROMIO_BASE))); // _intr_ret: // r11 があればそこに戻る - uint32 intr_ret = ms.GetOffset(); - ms.Write32(OP_bcnd (eq0, r11, 5)); // beq @f - ms.Write32(OP_or (r6, r11, SxIP_VALID)); - ms.Write32(OP_stcr (r6, snip)); - ms.Write32(OP_addu (r6, r6, 0x0004)); - ms.Write32(OP_stcr (r6, sfip)); + uint32 intr_ret = roms.GetOffset(); + roms.Write4(OP_bcnd (eq0, r11, 5)); // beq @f + roms.Write4(OP_or (r6, r11, SxIP_VALID)); + roms.Write4(OP_stcr (r6, snip)); + roms.Write4(OP_addu (r6, r6, 0x0004)); + roms.Write4(OP_stcr (r6, sfip)); // @@: - ms.Write32(OP_rte ()); + roms.Write4(OP_rte ()); // Sysclk 割り込みハンドラ。 - ms.SetOffset(0x240); + roms.SetOffset(0x240); // ACK - ms.Write32(OP_or_u (r6, r0, 0x6300)); - ms.Write32(OP_st_b (r0, r6, r0)); + roms.Write4(OP_or_u (r6, r0, 0x6300)); + roms.Write4(OP_st_b (r0, r6, r0)); // inc - ms.Write32(OP_ld (r6, r3, (ROMIO_CLKCNT - ROMIO_BASE))); - ms.Write32(OP_addu (r6, r6, 1)); - ms.Write32(OP_st (r6, r3, (ROMIO_CLKCNT - ROMIO_BASE))); - ms.Write32(OP_br ((intr_ret - ms.GetOffset()) / 4)); + roms.Write4(OP_ld (r6, r3, (ROMIO_CLKCNT - ROMIO_BASE))); + roms.Write4(OP_addu (r6, r6, 1)); + roms.Write4(OP_st (r6, r3, (ROMIO_CLKCNT - ROMIO_BASE))); + roms.Write4(OP_br ((intr_ret - roms.GetOffset()) / 4)); // ROM GETC エミュレータ - ms.SetOffset(0x300); - ms.Write32(OP_doscall(r2, r0, DOS_GETCHAR)); - ms.Write32(OP_jmp (r1)); + roms.SetOffset(0x300); + roms.Write4(OP_doscall(r2, r0, DOS_GETCHAR)); + roms.Write4(OP_jmp (r1)); // ROM PUTC エミュレータ // 表示する文字は r2 に置かれている。 - ms.SetOffset(0x400); - ms.Write32(OP_doscall(r0, r2, DOS_PUTCHAR)); - ms.Write32(OP_jmp (r1)); + roms.SetOffset(0x400); + roms.Write4(OP_doscall(r0, r2, DOS_PUTCHAR)); + roms.Write4(OP_jmp (r1)); // サブルーチン - ms.SetOffset(0x900); - ms.Write32(OP_ld (r2, r3, (ROMIO_AP1 - ROMIO_BASE))); + roms.SetOffset(0x900); + roms.Write4(OP_ld (r2, r3, (ROMIO_AP1 - ROMIO_BASE))); //@@: - ms.Write32(OP_or_u (r11, r0, 0x4100)); - ms.Write32(OP_or (r11, r11, ms.GetOffset() + 8)); - ms.Write32(OP_br (0)); // STOP 相当 - ms.Write32(OP_or (r11, r0, r0)); - - ms.Write32(OP_ld (r2, r3, (ROMIO_CLKCNT - ROMIO_BASE))); - ms.Write32(OP_or (r5, r0, 0x01ff)); - ms.Write32(OP_and (r2, r2, r5)); // r2 &= 0x1ff; - int freq = sysclk->GetFreq(); - ms.Write32(OP_or (r5, r0, freq * 3)); // r5 = freq*3; - ms.Write32(OP_cmp (r5, r2, r5)); - ms.Write32(OP_bb1 (CMP_LT, r5, -9)); // blt @b - ms.Write32(OP_ld (r0, r3, (ROMIO_AP2 - ROMIO_BASE))); - ms.Write32(OP_jmp (r1)); + roms.Write4(OP_or_u (r11, r0, 0x4100)); + roms.Write4(OP_or (r11, r11, roms.GetOffset() + 8)); + roms.Write4(OP_br (0)); // STOP 相当 + roms.Write4(OP_or (r11, r0, r0)); + + roms.Write4(OP_ld (r2, r3, (ROMIO_CLKCNT - ROMIO_BASE))); + roms.Write4(OP_or (r5, r0, 0x01ff)); + roms.Write4(OP_and (r2, r2, r5)); // r2 &= 0x1ff; + uint freq = sysclk->GetFreq(); + roms.Write4(OP_or (r5, r0, freq * 3));// r5 = freq*3; + roms.Write4(OP_cmp (r5, r2, r5)); + roms.Write4(OP_bb1 (CMP_LT, r5, -9)); // blt @b + roms.Write4(OP_ld (r0, r3, (ROMIO_AP2 - ROMIO_BASE))); + roms.Write4(OP_jmp (r1)); // 変なインデントここまで @@ -328,27 +328,28 @@ Luna88kPROMEmuDevice::Init() void Luna88kPROMEmuDevice::ROM_InitMD() { - IODeviceStream rs(mainram); + IODeviceStream rams(mainram); // 割り込みマスクで Sysclk, SIO だけ許可 - auto *interrupt = GetInterruptDevice(); - interrupt->Write32(0x65000000, 0xc0000000); + // XXX とりあえず CPU#0 のみ + auto *sysctlr = dynamic_cast(GetInterruptDevice()); + sysctlr->WriteIntMask(0, 0xc0000000); - rs.SetAddr(0); + rams.SetAddr(0); // ベクタテーブルを rte で埋めておく for (int i = 0; i < 512 * 2; i++) { - rs.Write32(OP_rte()); + rams.Write4(OP_rte()); } // +$08: 割り込みベクタ - rs.Write32(8, OP_br(0x003fe)); // br $00001000 + rams.Write4(8, OP_br(0x003fe)); // br $00001000 // 割り込みトランポリン (0x1000) // ベクタテーブルは各2ワードしかないのに、0 番地付近にあるベクタテーブル // から2ワードでは ROM まで飛べない。一体どういう設計してんだ…。 - rs.SetAddr(0x1000); - rs.Write32(OP_or_u (r6, r0, 0x4100)); - rs.Write32(OP_or (r6, r6, 0x0200)); - rs.Write32(OP_jmp (r6)); + rams.SetAddr(0x1000); + rams.Write4(OP_or_u (r6, r0, 0x4100)); + rams.Write4(OP_or (r6, r6, 0x0200)); + rams.Write4(OP_jmp (r6)); // ROM の機能テーブル // 0x00001100 ? @@ -359,12 +360,12 @@ Luna88kPROMEmuDevice::ROM_InitMD() // 0x00001114 ビットマッププレーンの有効状態が入っている。 // bit0: plane0 有効 // bit1..7: plane1..7 有効 - rs.SetAddr(0x110c); - rs.Write32(0x41000300); - rs.Write32(0x41000400); - rs.Write32(0x00000001); + rams.SetAddr(0x110c); + rams.Write4(0x41000300); + rams.Write4(0x41000400); + rams.Write4(0x00000001); - uint32 ap = (nvram->Peek(0x7fd) << 8) | nvram->Peek(0x7fe); + uint32 ap = (nvram->PeekPort(0x7fd) << 8) | nvram->PeekPort(0x7fe); if (__predict_false(0||(ap & 0x3f1f) == 0x0104)) { auto *mpu88xx0 = GetMPU88xx0Device(mpu); mpu88xx0->reg.r[1] = mpu88xx0->reg.nip; @@ -454,7 +455,7 @@ Luna88kPROMEmuDevice::Command() std::vector arg; // 1ワードごとに分解 - strcpy(&buf[0], inputbuf.c_str()); + strlcpy(buf.data(), inputbuf.c_str(), buf.size()); char *p = &buf[0]; for (char *ap; (ap = strsep(&p, " ")) != NULL; ) { if (*ap != '\0') { @@ -463,7 +464,7 @@ Luna88kPROMEmuDevice::Command() } if (loglevel >= 1) { for (int i = 0; i < arg.size(); i++) { - putmsgn("arg[%d]=|%s|", i, arg[i].c_str()); + putmsgn("arg[%u]=|%s|", i, arg[i].c_str()); } } @@ -835,10 +836,10 @@ Luna88kPROMEmuDevice::GetNVRAM(bootinfo_ // dkpart (パーティション) は boot_partition (0..) // dkfile (ファイル名) は boot_filename // sd 以外のデバイスは未対応 - bootinfo.dkunit = nvram->Peek(0x0070) - '0'; - bootinfo.dkpart = nvram->Peek(0x0090) - '0'; + bootinfo.dkunit = nvram->PeekPort(0x0070) - '0'; + bootinfo.dkpart = nvram->PeekPort(0x0090) - '0'; bootinfo.dkfile = nvram->PeekString(0x00b0); - putmsg(1, "%s unit=%d", __func__, bootinfo.dkunit); + putmsg(1, "%s unit=%u", __func__, bootinfo.dkunit); putmsg(1, "%s part=%c", __func__, bootinfo.dkpart + 'a'); putmsg(1, "%s file=|%s|", __func__, bootinfo.dkfile.c_str()); } @@ -847,7 +848,7 @@ Luna88kPROMEmuDevice::GetNVRAM(bootinfo_ bool luna88k_fline_callback(MPU88xx0Device *cpu, void *arg) { - Luna88kPROMEmuDevice *dev = (Luna88kPROMEmuDevice *)arg; + auto *dev = reinterpret_cast(arg); return dev->FLineCallback(cpu); }