--- nono/vm/spc.cpp 2026/04/29 17:04:32 1.1.1.3 +++ nono/vm/spc.cpp 2026/04/29 17:04:39 1.1.1.5 @@ -1,11 +1,13 @@ // // nono -// Copyright (C) 2017 isaki@NetBSD.org +// Copyright (C) 2020 nono project +// Licensed under nono-license.txt // #include "spc.h" #include "mainapp.h" -#include "mpu.h" +#include "mpu680x0.h" +#include "mpu88xx0.h" #include "mystring.h" #include "scheduler.h" #include "vm.h" @@ -35,7 +37,7 @@ SPCDevice::SPCDevice() SetConfigName("spc0"); myid = -1; - monitor.Init(70, 15); + monitor_size = nnSize(70, 15); // 汎用イベント // 名前とコールバック関数は都度セットする。 @@ -63,12 +65,11 @@ SPCDevice::Init() // 実行中に別インスタンスを頻繁に参照しないようにここで vmtype を覚えておく vmtype = gMainApp.GetVMType(); - if (vmtype == VMTYPE_LUNA) { - // おそらく 6.144MHz が入っていると思われる - t_CLF = 163; - } else { - t_CLF = 200; - } + // 入力クロックは機種によって異なる。 + // X68k は 5MHz が入っている。 + // LUNA-I はおそらく 6.144MHz だと思われる。LUNA88K は未確認。 + const ConfigItem& item = gConfig->Find("!spc-tCLF"); + t_CLF = item.AsInt(); return true; } @@ -79,7 +80,7 @@ void SPCDevice::ResetHard() { // LUNA は本体回路が分からないのでとりあえずこっち。 - if (vmtype == VMTYPE_LUNA) { + if (vmtype != VMTYPE_X68030) { Reset(); } } @@ -400,8 +401,8 @@ SPCDevice::Peek(uint32 addr) __unreachable(); } -bool -SPCDevice::MonitorUpdate() +void +SPCDevice::MonitorUpdate(TextScreen& monitor) { int x; int y; @@ -460,14 +461,14 @@ SPCDevice::MonitorUpdate() static const char * const sctl_bits[] = { "RST", "CTRL", "DIAG", "ARB", "PARI", "SEL", "RESL", "INTR" }; - MonitorReg(x, y, sctl, sctl_bits); + MonitorReg(monitor, x, y, sctl, sctl_bits); y++; // SCMD static const char * const scmd_bits[] = { "", "", "", "RST", "INTC", "PROG", "", "TERM" }; - MonitorReg(x, y, scmd, scmd_bits); + MonitorReg(monitor, x, y, scmd, scmd_bits); static const char * const scmd_cmd[] = { //12345678901234 "(Bus Release)", @@ -479,35 +480,35 @@ SPCDevice::MonitorUpdate() "(ResetACK/REQ)", "(Set ACK/REQ)", }; - monitor.Print(x, y, "%s", scmd_cmd[scmd >> 5]); + monitor.Puts(x, y, scmd_cmd[scmd >> 5]); y++; // INTS static const char * const ints_bits[] = { "Sel", "Resl", "Disc", "Cmpl", "SReq", "TOut", "HErr", "Rst" }; - MonitorReg(x, y, ints, ints_bits); + MonitorReg(monitor, x, y, ints, ints_bits); y++; // PSNS static const char * const psns_bits[] = { "REQ", "ACK", "ATN", "SEL", "BSY", "MSG", "C/D", "I/O" }; - MonitorReg(x, y, psns, psns_bits); + MonitorReg(monitor, x, y, psns, psns_bits); y++; // SDGC static const char * const sdgc_bits[] = { "", "", "XfEn", "", "", "", "", "" }; - MonitorReg(x, y, sdgc, sdgc_bits); + MonitorReg(monitor, x, y, sdgc, sdgc_bits); y++; // SSTS static const char * const ssts_bits[] = { "", "", "SBSY", "XInP", "RSTI", "TCZ", "Full", "Empt" }; - MonitorReg(x, y, ssts, ssts_bits); + MonitorReg(monitor, x, y, ssts, ssts_bits); static const char * const ssts_conn[] = { //12345678 "(NotConn)", @@ -515,21 +516,21 @@ SPCDevice::MonitorUpdate() "(As Init)", "(undef?)", }; - monitor.Print(x, y, "%s", ssts_conn[ssts >> 6]); + monitor.Puts(x, y, ssts_conn[ssts >> 6]); y++; // SERR static const char * const serr_bits[] = { "", "", "XOut", "", "PErr", "", "Shrt", "" }; - MonitorReg(x, y, serr, serr_bits); + MonitorReg(monitor, x, y, serr, serr_bits); y++; // PCTL static const char * const pctl_bits[] = { "BIE", "", "", "", "", "MSG", "C/D", "I/O" }; - MonitorReg(x, y, pctl, pctl_bits); + MonitorReg(monitor, x, y, pctl, pctl_bits); y++; // バス状態 @@ -560,23 +561,23 @@ SPCDevice::MonitorUpdate() data = GetData(); } monitor.Print(x, y++, "Phase: %s", SCSI::GetPhaseName(ph)); - monitor.Print(x, y++, (rst ? TA::On : TA::Off), "RST"); - monitor.Print(x, y++, (bsy ? TA::On : TA::Off), "BSY"); - monitor.Print(x, y++, (sel ? TA::On : TA::Off), "SEL"); - monitor.Print(x, y++, (msg ? TA::On : TA::Off), "MSG"); - monitor.Print(x, y++, (cd ? TA::On : TA::Off), "CD"); - monitor.Print(x, y++, (io ? TA::On : TA::Off), "IO"); - monitor.Print(x, y++, (atn ? TA::On : TA::Off), "ATN"); - monitor.Print(x, y++, (req ? TA::On : TA::Off), "REQ"); - monitor.Print(x, y++, (ack ? TA::On : TA::Off), "ACK"); + monitor.Puts(x, y++, TA::OnOff(rst), "RST"); + monitor.Puts(x, y++, TA::OnOff(bsy), "BSY"); + monitor.Puts(x, y++, TA::OnOff(sel), "SEL"); + monitor.Puts(x, y++, TA::OnOff(msg), "MSG"); + monitor.Puts(x, y++, TA::OnOff(cd), "CD"); + monitor.Puts(x, y++, TA::OnOff(io), "IO"); + monitor.Puts(x, y++, TA::OnOff(atn), "ATN"); + monitor.Puts(x, y++, TA::OnOff(req), "REQ"); + monitor.Puts(x, y++, TA::OnOff(ack), "ACK"); monitor.Print(x, y++, "DATA:$%02x", data); y = 2; - monitor.Print(x + 4, y++, "(________)"); - monitor.Print(x + 4, y++, "(________)"); - monitor.Print(x + 4, y++, "+"); - monitor.Print(x + 4, y++, "|"); - monitor.Print(x + 4, y++, "+"); + monitor.Puts(x + 4, y++, "(________)"); + monitor.Puts(x + 4, y++, "(________)"); + monitor.Puts(x + 4, y++, "+"); + monitor.Puts(x + 4, y++, "|"); + monitor.Puts(x + 4, y++, "+"); // BSY, SEL の内訳。"(76543210)" の順。 y = 2; @@ -599,7 +600,7 @@ SPCDevice::MonitorUpdate() // 転送フェーズ中なら現在の XferPhase y += 2; if (ph == SCSI::Phase::Transfer) { - monitor.Print(x + 5, y, "%s", SCSI::GetXferPhaseName(GetXfer())); + monitor.Puts(x + 5, y, SCSI::GetXferPhaseName(GetXfer())); } // ターゲット @@ -614,23 +615,21 @@ SPCDevice::MonitorUpdate() const char *cmdname = SCSI::GetCommandName(cmds[0]); monitor.Print(x, y, "Command: $%02x", cmds[0]); if (cmdname) { - monitor.Print(x + 14, y, "%s", cmdname); + monitor.Puts(x + 14, y, cmdname); } } } } - - return true; } // レジスタをビットごとに表示する。MonitorUpdate の下請け。 void -SPCDevice::MonitorReg(int x, int y, uint32 reg, const char * const *names) +SPCDevice::MonitorReg(TextScreen& monitor, + int x, int y, uint32 reg, const char * const *names) { for (int i = 0; i < 8; i++) { bool b = reg & (1 << (7 - i)); - uint attr = b ? TA::On : TA::Off; - monitor.Print(x + i * 5, y, attr, "%s", names[i]); + monitor.Puts(x + i * 5, y, TA::OnOff(b), names[i]); } } @@ -783,10 +782,10 @@ SPCDevice::SetINTS(uint32 data) if ((spc.sctl & SPC::SCTL_INTR_EN) || (spc.ints & SPC::INTS_RESET_COND)) { putlog(3, "割り込み ints=$%02x up=$%02x", spc.ints, up); if (vmtype != VMTYPE_X68030) { - gMPU->Interrupt(2); + gMPU->Interrupt(this, 2); } else { // とりあえず内蔵だけ - gMPU680x0->Interrupt(1, 0x6c); + gMPU680x0->Interrupt(this, 1, 0x6c); } } } @@ -832,7 +831,7 @@ SPCDevice::GetSSTS() const uint32 data; data = spc.ssts & 0xf0; - if (__predict_true(bus) && GetRST()) { // RST 信号 + if (__predict_true(bus != NULL) && GetRST()) { // RST 信号 data |= SPC::SSTS_RST_IN; } if (spc.tc == 0) { // TC がゼロか @@ -857,7 +856,7 @@ SPCDevice::GetPCTL() const uint32 data; data = 0; - if (__predict_true(bus)) { + if (__predict_true(bus != NULL)) { data |= (uint32)GetXfer(); } if (spc.busfree_intr_enable) {