--- nono/vm/human68k.cpp 2026/04/29 17:05:33 1.1.1.14 +++ nono/vm/human68k.cpp 2026/04/29 17:05:55 1.1.1.18 @@ -22,6 +22,7 @@ #include "human68k.h" #include "autofd.h" +#include "event.h" #include "iodevstream.h" #include "mainapp.h" #include "mainbus.h" @@ -63,11 +64,7 @@ Human68kDevice::Init() uint32 psp_base; uint8 *file; uint32 last_addr; - int ram_size; - - if (inherited::Init() == false) { - return false; - } + uint32 ram_size; assert(gMainApp.exec_file); human68k_file = gMainApp.exec_file; @@ -149,7 +146,7 @@ Human68kDevice::Init() munmap(file, file_size); last_addr = load_addr + load_size + bss_size; - ram_size = mainram->GetSize(); + ram_size = (uint32)mainram->GetSize(); boot_addr = 0x200; ds.Write4(0, ram_size - 4); // 初期 SSP @@ -165,8 +162,26 @@ Human68kDevice::Init() // STOP による停止。終了時に CPU を止めておくため。 ds.Write4(0x1010, 0x4e722700); // stop #$2700 + // MFP Timer-C ベクタを書き込む。 + ds.Write4(0x0114, 0x1020); + // Timer-C で 10ミリ秒ごとに $9cc.w のワークを減算していく。 + // 0 になったら $9d6.l の稼働時間(分) をインクリメントして、 + // $9cc.w には $9ca.w の初期値 (6000 = 60秒 * 100) を再セット。 + ds.SetAddr(0x1020); + ds.Write2(0x5378); // subq.w #1,($9cc) + ds.Write2(0x9cc); + ds.Write2(0x660a); // bne @f + ds.Write2(0x31f8); // move.w ($9ca),($9cc) + ds.Write2(0x09ca); + ds.Write2(0x09cc); + ds.Write2(0x52b8); // addq.l #1,($9d6) + ds.Write2(0x09d6); + ds.Write2(0x4e73); //@@: rte + ds.Write2(0x9ca, 6000); // $9ca: 初期値 + ds.Write2(0x9cc, 6000); // いきなり初期化しておく。 + // コマンドライン文字列を書き込む。LASCII 形式 - ds.SetOffset(0xc001); + ds.SetAddr(0xc001); for (int i = 0; i < 255; i++) { uint8 c = human68k_arg[i]; ds.Write1(c); @@ -181,7 +196,7 @@ Human68kDevice::Init() // instructiontest.x はコマンドラインを指定するだけで動くようだ。 // PSP はロードアドレス-256 の位置でなければならないようだ。 psp_base = 0x1ff00; - ds.SetOffset(psp_base); + ds.SetAddr(psp_base); ds.Write4(-1); // 1つ前のメモリ管理ポインタ ds.Write4(-1); // このメモリを確保したプロセスのメモリ管理ポインタ @@ -190,7 +205,7 @@ Human68kDevice::Init() ds.Write4(psp_base + 0x20, 0xc000); // コマンドライン - ds.SetOffset(boot_addr); + ds.SetAddr(boot_addr); ds.Write2(0x2c4f); // move.l a7,a6 ds.Write2(0x2e7c); // move.l psp_base,a7 ds.Write4(psp_base); @@ -206,8 +221,8 @@ Human68kDevice::Init() ds.Write2(0x287c); // move.l exec_addr,a4 ds.Write4(exec_addr); ds.Write2(0x2c49); // move.l a1,a6 - ds.Write2(0x46fc); // move.w #$0700,sr - ds.Write2(0x0700); + ds.Write2(0x46fc); // move.w #$0500,sr + ds.Write2(0x0500); ds.Write2(0x4eb9); // jsr.l exec_addr ds.Write4(exec_addr); ds.Write2(0xff00); // DOS _EXIT @@ -347,7 +362,7 @@ bool Human68kDevice::LoadELF(const uint8 *file, uint size) { LoadInfo info(human68k_file, file, size); - if (mainram->LoadExec(&info) == false) { + if (BootLoader::LoadExec(mainram, &info) == false) { return false; } @@ -421,6 +436,25 @@ Human68kDevice::FLineOp() IOCS(); break; + case 0xfe11: // FPACK __LTOS + { + putlog(1, "FPACK __LTOS"); + uint32 data = RegD(0); + uint32 dst = RegA(0); + char buf[16]; + snprintf(buf, sizeof(buf), "%d", data); + for (char *p = buf; ; p++, dst++) { + uint8 c = *p; + mainbus->HVWrite1(dst, c); + if (c == 0) { + break; + } + } + // '\0' の位置を A0 に返す。 + RegA(0) = dst; + break; + } + case 0xff00: // _EXIT putlog(1, "DOS _EXIT"); // XXX CPU の実行を止める。方式自体を I/O 方式に見直したときには @@ -770,6 +804,21 @@ Human68kDevice::IOCS() RegD(1) = t / 86400_sec; break; } + case 0x80: // _B_INTVCS + { + uint32 num = RegD(1); + uint32 newaddr = RegA(1); + uint32 oldaddr; + if (num < 0x100) { + oldaddr = mainbus->HVRead4(num * 4); + mainbus->HVWrite4(num * 4, newaddr); + RegD(0) = oldaddr; + } else { + printf("IOCS _B_INTVCS(#%04x) (NOT IMPLEMENTED)", num); + RequestExit(1); + } + break; + } case 0x82: // _B_BPEEK { uint32 data = mainbus->HVRead1(RegA(1));