--- nono/vm/pio.cpp 2026/04/29 17:05:10 1.1.1.10 +++ nono/vm/pio.cpp 2026/04/29 17:05:14 1.1.1.11 @@ -74,7 +74,7 @@ i8255Device::WriteCtrl(uint32 data) // 最上位が立っていればモード設定 ctrl = data; putlog(1, - "モード設定 groupA=%d groupB=%d portA=%s portB=%s portC=%s/%s", + "Set mode: groupA=%d groupB=%d portA=%s portB=%s portC=%s/%s", GetGroupAMode(), GetGroupBMode(), PortADir() == DIR_IN ? "IN" : "OUT", PortBDir() == DIR_IN ? "IN" : "OUT", @@ -126,10 +126,11 @@ PPIDevice::Read(uint32 offset) case 1: return 0xff; case 2: - putlog(0, "$e9a005 PortC 未実装読み込み"); + putlog(0, "Read $e9a005 PortC (NOT IMPLEMENTED)"); return 0xff; case 3: - VMPANIC("PPI $e9a007 未サポート読み込み"); + putlog(0, "Read $e9a007 Ctrl (NOT IMPLEMENTED)"); + return 0xff; default: __unreachable(); } @@ -144,15 +145,14 @@ PPIDevice::Write(uint32 offset, uint32 d case 0: case 1: break; - case 2: - putlog(0, "$e9a005 未実装書き込み $%02X (無視)", data); + case 2: // PPI PortC + for (int i = 0; i < 8; i++) { + SetPC(i, data & 1); + data >>= 1; + } break; case 3: - if (data != 0x92) { - VMPANIC("PPI $e9a007 未実装書き込み $%02X", data); - } else { - putlog(0, "$e9a007 未実装書き込み $%02x (無視)", data); - } + WriteCtrl(data); break; default: __unreachable(); @@ -169,9 +169,31 @@ PPIDevice::Peek(uint32 offset) // PortC 書き込み void -PPIDevice::SetPC(int pc, int data) +PPIDevice::SetPC(int pc, int val) { - VMPANIC("not impl"); + switch (pc) { + case 0: // ADPCM PAN Left Off + pan_left = !val; + break; + case 1: // ADPCM PAN Right Off + pan_right = !val; + break; + case 2: // ADPCM サンプリングレート + adpcm_rate = (adpcm_rate & 2) | val; + break; + case 3: // ADPCM サンプリングレート + adpcm_rate = (val << 1) | (adpcm_rate & 1); + break; + + case 4: // ジョイスティック #1 コントロール + case 5: // ジョイスティック #2 コントロール + case 6: // ジョイスティック #1 ボタン A + case 7: // ジョイスティック #1 ボタン B + putlog(1, "SetPC(%d) <- %d (NOT IMPLEMENTED)", pc, val); + break; + default: + __unreachable(); + } } // @@ -262,11 +284,11 @@ PIO0Device::PIO0Device() // LUNA-1 と LUNA88K で使いやすいように初期値を変えておく。 switch (gMainApp.GetVMType()) { - case VMTYPE_LUNA1: + case VMType::LUNA1: gConfig->SetDefault("luna-dipsw1", "11110111"); msb_first = false; break; - case VMTYPE_LUNA88K: + case VMType::LUNA88K: gConfig->SetDefault("luna-dipsw1", "11111111"); msb_first = true; break; @@ -322,23 +344,25 @@ PIO0Device::Read(uint32 offset) switch (offset) { case 0: // PortA - putlog(1, "DIP-SW 1 読み込み"); - return GetPA(); + data = GetPA(); + putlog(1, "DIP-SW1 -> $%02x", data); + return data; case 1: // PortB - putlog(1, "DIP-SW 2 読み込み"); - return GetPB(); + data = GetPB(); + putlog(1, "DIP-SW2 -> $%02x", data); + return data; case 2: // PortC data = GetPC(); - putlog(1, "PC 読み込み -> $%02x", data); + putlog(1, "PortC -> $%02x", data); return data; case 3: data = ReadCtrl(); - putlog(1, "コントロール読み込み -> $%02x", data); + putlog(1, "Ctrl -> $%02x", data); return data; default: @@ -480,7 +504,7 @@ PIO0Device::SetPC(int pc, int val) case 0: if ((val ^ int1rq)) { int1rq = val; - putlog(0, "INT1割り込み要求 %d (未実装)", int1rq); + putlog(0, "INT1 Interrupt Request %d (NOT IMPLEMENTED)", int1rq); } return; case 1: @@ -489,19 +513,19 @@ PIO0Device::SetPC(int pc, int val) case 2: if ((val ^ int1en)) { int1en = val; - putlog(0, "INT1割り込み許可 %d (未実装)", int1en); + putlog(0, "INT1 Interrupt Enable %d (NOT IMPLEMENTED)", int1en); } return; case 3: if ((val ^ int5rq)) { int5rq = val; - putlog(0, "INT5割り込み要求 %d (未実装)", int5rq); + putlog(0, "INT5 Interrupt Request %d (NOT IMPLEMENTED)", int5rq); } return; case 4: if ((val ^ int5en)) { int5en = val; - putlog(0, "INT5割り込み許可 %d (未実装)", int5en); + putlog(0, "INT5 Interrupt Enable %d (NOT IMPLEMENTED)", int5en); } return; case 5: @@ -516,7 +540,7 @@ PIO0Device::SetPC(int pc, int val) // XP リセット if ((val ^ xp_reset)) { xp_reset = val; - putlog(0, "XPリセット %d (未実装)", xp_reset); + putlog(0, "XP Reset %d (NOT IMPLEMENTED)", xp_reset); } return; } @@ -537,9 +561,6 @@ PIO1Device::PIO1Device() devaddr = 0x4d000000; devlen = 4; - poffevent.func = ToEventCallback(&PIO1Device::PowerOffCallback); - poffevent.time = 1_msec; - poffevent.Regist("PIO1 Power Off"); } // デストラクタ @@ -554,7 +575,10 @@ PIO1Device::ResetHard(bool poweron) { inherited::ResetHard(poweron); - gScheduler->StopEvent(poffevent); + // デフォルトで PIO 出力は「1msec 後に電源オフ」という状態なので、 + // 電源オンから 1msec 以内にソフトウェアがこれをキャンセルしないと + // いけないらしい。どうしてこうなった…。 + gPower->SetSystemPowerOn(false); } uint64 @@ -577,12 +601,12 @@ PIO1Device::Read(uint32 offset) data |= xp_intreq ? 0 : 0x02; // 残りのビットは %1 だろうか? data |= 0x0d; - putlog(1, "PC 読み込み -> $%02x", data); + putlog(1, "PortC -> $%02x", data); return data; case 3: data = ReadCtrl(); - putlog(1, "コントロール読み込み -> $%02x", data); + putlog(1, "Ctrl -> $%02x", data); return data; default: @@ -662,12 +686,12 @@ PIO1Device::SetPC(int pc, int val) power = val; if (power) { // 電源オフ取り消し - putlog(1, "電源 OFF 取消"); - gScheduler->StopEvent(poffevent); + putlog(1, "Power-off canceled"); + gPower->SetSystemPowerOn(true); } else { // 1msec 後に電源オフ - putlog(1, "電源 OFF 指示"); - gScheduler->RestartEvent(poffevent); + putlog(1, "Power-off scheduled"); + gPower->SetSystemPowerOn(false); } return; case 5: @@ -685,11 +709,3 @@ PIO1Device::SetPC(int pc, int val) } VMPANIC("PC%d 未実装", pc); } - -// 電源オフイベントのコールバック -void -PIO1Device::PowerOffCallback(Event& ev) -{ - putlog(0, "電源 OFF"); - gPower->MakePowerOffExit(); -}