--- nono/vm/pio.cpp 2026/04/29 17:05:25 1.1.1.13 +++ nono/vm/pio.cpp 2026/04/29 17:05:33 1.1.1.15 @@ -32,7 +32,7 @@ #include "interrupt.h" #include "lcd.h" #include "mainapp.h" -#include "mpu.h" +#include "monitor.h" #include "mpu64180.h" #include "power.h" #include "scheduler.h" @@ -42,7 +42,7 @@ // // コンストラクタ -i8255Device::i8255Device(int objid_) +i8255Device::i8255Device(uint objid_) : inherited(objid_) { } @@ -72,7 +72,7 @@ i8255Device::WriteCtrl(uint32 data) ctrl = data; if (__predict_false(loglevel >= 1)) { if (loglevel >= 2) { - putlogn("Ctrl <- $%02x: GrA/Bmode=%d/%d PA=%s PB=%s PC=%s:%s", + putlogn("Ctrl <- $%02x: GrA/Bmode=%u/%u PA=%s PB=%s PC=%s:%s", data, GetGroupAMode(), GetGroupBMode(), PortADir() == DIR_IN ? "IN" : "OUT", @@ -95,13 +95,19 @@ i8255Device::WriteCtrl(uint32 data) // | | | +-- 書き込むビットデータ // +--+--+----- 書き込むビット位置 - int pc = (data >> 1) & 7; - int val = data & 1; - putlog(2, "Ctrl <- $%02x: SetPC%d=%d", data, pc, val); + uint pc = (data >> 1) & 7; + uint val = data & 1; + putlog(2, "Ctrl <- $%02x: SetPC%u=%u", data, pc, val); SetPC(pc, val); } } +bool +i8255Device::PokePort(uint32 offset, uint32 data) +{ + return false; +} + // 共通部分を表示。 // 戻り値は表示を終えた次の行。 int @@ -120,10 +126,10 @@ i8255Device::MonitorUpdateCommon(TextScr "BiDirection", }; const int x = 16; - screen.Print(x, y++, "GroupA (PortA,PortCH) Mode: %d(%s)", + screen.Print(x, y++, "GroupA (PortA,PortCH) Mode: %u(%s)", GetGroupAMode(), modestr[GetGroupAMode()]); - screen.Print(x, y++, "GroupB (PortB,PortCL) Mode: %d(%s)", + screen.Print(x, y++, "GroupB (PortB,PortCL) Mode: %u(%s)", GetGroupBMode(), modestr[GetGroupBMode()]); static const char *inoutstr[] = { @@ -158,7 +164,7 @@ PPIDevice::~PPIDevice() } busdata -PPIDevice::Read(uint32 offset) +PPIDevice::ReadPort(uint32 offset) { busdata data; @@ -176,15 +182,16 @@ PPIDevice::Read(uint32 offset) data = 0xff; break; default: - VMPANIC("corrupted offset=%d", offset); + VMPANIC("corrupted offset=%u", offset); } data |= ppi_wait; + data |= BusData::Size1; return data; } busdata -PPIDevice::Write(uint32 offset, uint32 data) +PPIDevice::WritePort(uint32 offset, uint32 data) { switch (offset) { case 0: @@ -200,13 +207,15 @@ PPIDevice::Write(uint32 offset, uint32 d WriteCtrl(data); break; default: - VMPANIC("corrupted offset=%d", offset); + VMPANIC("corrupted offset=%u", offset); } - return ppi_wait; + busdata r = ppi_wait; + r |= BusData::Size1; + return r; } busdata -PPIDevice::Peek(uint32 offset) +PPIDevice::PeekPort(uint32 offset) { // XXX return 0xff; @@ -214,30 +223,30 @@ PPIDevice::Peek(uint32 offset) // PortC 書き込み void -PPIDevice::SetPC(int pc, int val) +PPIDevice::SetPC(uint pc, uint val) { switch (pc) { case 0: // ADPCM PAN Left Off pan_left = !val; - break; + return; case 1: // ADPCM PAN Right Off pan_right = !val; - break; + return; case 2: // ADPCM サンプリングレート adpcm_rate = (adpcm_rate & 2) | val; - break; + return; case 3: // ADPCM サンプリングレート adpcm_rate = (val << 1) | (adpcm_rate & 1); - break; + return; case 4: // ジョイスティック #1 コントロール case 5: // ジョイスティック #2 コントロール case 6: // ジョイスティック #1 ボタン A case 7: // ジョイスティック #1 ボタン B - putlog(1, "SetPC(%d) <- %d (NOT IMPLEMENTED)", pc, val); - break; + putlog(1, "SetPC(%u) <- %u (NOT IMPLEMENTED)", pc, val); + return; default: - VMPANIC("corrupted pc=%d", pc); + VMPANIC("corrupted pc=%u", pc); } } @@ -322,9 +331,9 @@ PIO0Device::PIO0Device() } // PIO0/PIO1 - monitor.func = ToMonitorCallback(&PIO0Device::MonitorUpdate); - monitor.SetSize(76, 15); - monitor.Regist(ID_MONITOR_PIO); + monitor = gMonitorManager->Regist(ID_MONITOR_PIO, this); + monitor->func = ToMonitorCallback(&PIO0Device::MonitorUpdate); + monitor->SetSize(76, 15); } // デストラクタ @@ -367,9 +376,9 @@ PIO0Device::ResetHard(bool poweron) } busdata -PIO0Device::Read(uint32 offset) +PIO0Device::ReadPort(uint32 offset) { - uint32 data; + busdata data; switch (offset) { case 0: @@ -380,7 +389,7 @@ PIO0Device::Read(uint32 offset) intreq[INT_H] = false; ChangeInterrupt(); - putlog(1, "DIP-SW1 -> $%02x", data); + putlog(1, "DIP-SW1 -> $%02x", data.Data()); break; case 1: @@ -391,30 +400,31 @@ PIO0Device::Read(uint32 offset) intreq[INT_L] = false; ChangeInterrupt(); - putlog(1, "DIP-SW2 -> $%02x", data); + putlog(1, "DIP-SW2 -> $%02x", data.Data()); break; case 2: // PortC data = GetPC(); - putlog(1, "PortC -> $%02x", data); + putlog(1, "PortC -> $%02x", data.Data()); break; case 3: data = ReadCtrl(); - putlog(1, "Ctrl -> $%02x", data); + putlog(1, "Ctrl -> $%02x", data.Data()); break; default: - VMPANIC("corrupted offset=%d", offset); + VMPANIC("corrupted offset=%u", offset); } // XXX wait? + data |= BusData::Size1; return data; } busdata -PIO0Device::Write(uint32 offset, uint32 data) +PIO0Device::WritePort(uint32 offset, uint32 data) { switch (offset) { case 0: // PIO0 PortA: DIPSW1 (入力のみ) @@ -433,15 +443,16 @@ PIO0Device::Write(uint32 offset, uint32 break; default: - VMPANIC("corrupted offset=%d", offset); + VMPANIC("corrupted offset=%u", offset); } // XXX wait? - return 0; + busdata r = BusData::Size1; + return r; } busdata -PIO0Device::Peek(uint32 offset) +PIO0Device::PeekPort(uint32 offset) { switch (offset) { case 0: @@ -487,8 +498,8 @@ PIO0Device::MonitorUpdate(Monitor *, Tex bool d1 = (pa & (1U << bitpos)); bool d2 = (pb & (1U << bitpos)); - screen.Print(21 + i * 7, y, TA::OnOff(d1), "DIP1-%d", label); - screen.Print(21 + i * 7, y + 1, TA::OnOff(d2), "DIP2-%d", label); + screen.Print(21 + i * 7, y, TA::OnOff(d1), "DIP1-%u", label); + screen.Print(21 + i * 7, y + 1, TA::OnOff(d2), "DIP2-%u", label); } y += 2; @@ -554,7 +565,7 @@ PIO0Device::GetPC() const // PortC 書き込み void -PIO0Device::SetPC(int pc, int val) +PIO0Device::SetPC(uint pc, uint val) { switch (pc) { case 0: @@ -586,13 +597,14 @@ PIO0Device::SetPC(int pc, int val) // XP リセット if ((val ^ xp_reset)) { xp_reset = val; - putlog(1, "XP Reset %d", xp_reset); + putlog(1, "XP Reset %u", xp_reset); auto mpu64180 = GetMPU64180Device(); mpu64180->ChangeRESET(xp_reset); } return; + default: + VMPANIC("corrupted pc=%u", pc); } - VMPANIC("invalid pc=%d", pc); } // とりあえず、XP からここまではエッジトリガーで、 @@ -670,17 +682,21 @@ PIO1Device::ResetHard(bool poweron) { inherited::ResetHard(poweron); - // デフォルトで PIO 出力は「1msec 後に電源オフ」という状態なので、 - // 電源オンから 1msec 以内にソフトウェアがこれをキャンセルしないと - // いけないらしい。どうしてこうなった…。 - power = false; - powerdev->SetSystemPowerOn(false); + // 電源ユニットは POWF* 信号が 'L' になると 1msec 後に電源オフになる。 + // 正確には「1msec 以内に 'H' にすれば回避できる」なので、実際に電源が + // オフになるのはそれよりもっと十分長いとは思われる。 + // 8255 リセット時、ポート C の各ピンは入力モードになっているので、 + // ハイインピーダンス。たぶん電源的にも 'H' になってると想像する。 + // なので電源オンで POWF* がハイインピーダンスなだけでは電源オフ + // タイマーは動作しないんじゃないかな。 + power = true; + powerdev->SetSystemPowerOn(power); } busdata -PIO1Device::Read(uint32 offset) +PIO1Device::ReadPort(uint32 offset) { - uint32 data; + busdata data; switch (offset) { case 0: @@ -699,24 +715,25 @@ PIO1Device::Read(uint32 offset) data |= xp_intreq ? 0 : 0x02; // 残りのビットは %1 だろうか? data |= 0x0d; - putlog(1, "PortC -> $%02x", data); + putlog(1, "PortC -> $%02x", data.Data()); break; case 3: data = ReadCtrl(); - putlog(1, "Ctrl -> $%02x", data); + putlog(1, "Ctrl -> $%02x", data.Data()); break; default: - VMPANIC("corrupted offset=%d", offset); + VMPANIC("corrupted offset=%u", offset); } // XXX wait? + data |= BusData::Size1; return data; } busdata -PIO1Device::Write(uint32 offset, uint32 data) +PIO1Device::WritePort(uint32 offset, uint32 data) { switch (offset) { case 0: // PIO1 PortA: LCD データ @@ -741,15 +758,16 @@ PIO1Device::Write(uint32 offset, uint32 break; default: - VMPANIC("corrupted offset=%d", offset); + VMPANIC("corrupted offset=%u", offset); } // XXX wait? - return 0; + busdata r = BusData::Size1; + return r; } busdata -PIO1Device::Peek(uint32 offset) +PIO1Device::PeekPort(uint32 offset) { switch (offset) { case 0: // PIO1 PortA LCD データ @@ -807,7 +825,7 @@ PIO1Device::GetPC() const } void -PIO1Device::SetPC(int pc, int val) +PIO1Device::SetPC(uint pc, uint val) { switch (pc) { case 0: @@ -819,6 +837,10 @@ PIO1Device::SetPC(int pc, int val) return; case 4: + // 8255 はモード変更 (WriteCtrl) をするとポート C を 'L' にするが、 + // PC4 (POWF*) が 'L' だと電源オフ指示なので、1msec 以内に + // ソフトウェアでこれをキャンセルしないといけない。 + // どうしてこうなった…。 power = val; if (power) { // 電源オフ取り消し @@ -841,7 +863,6 @@ PIO1Device::SetPC(int pc, int val) return; default: - break; + VMPANIC("corrupted pc=%u", pc); } - VMPANIC("PC%d 未実装", pc); }