--- nono/vm/pio.h 2026/04/29 17:05:10 1.1.1.9 +++ nono/vm/pio.h 2026/04/29 17:05:17 1.1.1.11 @@ -10,8 +10,15 @@ #pragma once -#include "event.h" +#include "device.h" #include "monitor.h" +#include + +class InterruptDevice; +class LCDDevice; +class MPU64180Device; +class PIO1Device; +class PowerDevice; // Intel 82C55 の仕様書にはコントロールポートからの読み出しは明記してある。 // NEC uPD8255 の仕様書にはコントロールポートからの読み出しについての記載が @@ -21,7 +28,7 @@ class i8255Device : public IODevice using inherited = IODevice; public: - i8255Device(const std::string& objname_); + i8255Device(int objid_); virtual ~i8255Device() override; void ResetHard(bool poweron) override; @@ -34,6 +41,9 @@ class i8255Device : public IODevice // PortC への個別書き込み virtual void SetPC(int, int) = 0; + // 共通部分 + int MonitorUpdateCommon(TextScreen& screen, int y); + // 7 6 5 4 3 2 1 0 // 1 AM AM AD CHD BM BD CLD // | | | | | | +--- ポートC下位グループの方向。入力なら1 @@ -67,6 +77,9 @@ class PPIDevice : public i8255Device PPIDevice(); virtual ~PPIDevice() override; + // ADPCM のサンプリングレートの 2bit を取得する + uint8 GetADPCMRate() const { return adpcm_rate; } + protected: // BusIO インタフェース static const uint32 NPORT = 4; @@ -76,20 +89,33 @@ class PPIDevice : public i8255Device private: void SetPC(int, int) override; + + bool pan_left {}; + bool pan_right {}; + uint adpcm_rate {}; }; class PIO0Device : public i8255Device { using inherited = i8255Device; + + static const int INT_H = 0; + static const int INT_L = 1; + public: PIO0Device(); virtual ~PIO0Device() override; bool Init() override; + void ResetHard(bool poweron) override; // DIPSW #1-1 が Up なら true を返す (ROM エミュレーション用) bool IsDIPSW11Up() const { return dipsw1[0]; } + // XP からの割り込みは PIO0 が中継する + void InterruptXPHigh(); + void InterruptXPLow(); + protected: // BusIO インタフェース static const uint32 NPORT = 4; @@ -102,20 +128,22 @@ class PIO0Device : public i8255Device uint32 GetPB() const; uint32 GetPC() const; void SetPC(int, int) override; + void ChangeInterrupt(); DECLARE_MONITOR_CALLBACK(MonitorUpdate); bool dipsw1[8] {}; bool dipsw2[8] {}; - bool msb_first {}; // DIP-SW の1番が MSB なら true (LUNA88K) - bool int1rq {}; // $01 INT1 割り込み要求 - bool int1en {}; // $04 INT1 割り込み許可 - bool int5rq {}; // $08 INT5 割り込み要求 - bool int5en {}; // $10 INT5 割り込み許可 + bool msb_first {}; // DIP-SW の1番が MSB なら true (LUNA-88K) + std::array intreq {}; // XP 割り込み要求 + std::array inten {}; // XP 割り込み許可 bool parity {}; // $40 パリティ有効/無効 bool xp_reset {}; // $80 XP リセット Monitor monitor { this }; + + InterruptDevice *interrupt {}; + PIO1Device *pio1 {}; }; class PIO1Device : public i8255Device @@ -125,26 +153,42 @@ class PIO1Device : public i8255Device PIO1Device(); virtual ~PIO1Device() override; + bool Init() override; void ResetHard(bool poweron) override; + // BusIO インタフェース + // (内蔵 ROM からのアクセス用に特別に public にしてある) + uint64 Write(uint32 offset, uint32 data); + + // PIO0 の下請け + void MonitorUpdatePIO1(TextScreen& screen, int y); + protected: // BusIO インタフェース static const uint32 NPORT = 4; uint64 Read(uint32 offset); - uint64 Write(uint32 offset, uint32 data); uint64 Peek(uint32 offset); private: + uint32 GetPC() const; void SetPC(int, int) override; - void PowerOffCallback(Event& ev); + + DECLARE_MONITOR_CALLBACK(MonitorUpdate); bool power {}; // パワーダウン (false で電源オフ指示) bool xp_intreq {}; // XP 割り込み要求。あり(true)なら %0 - // 電源オフイベント - Event poffevent { this }; + LCDDevice *lcd {}; + MPU64180Device *mpu64180 {}; + PowerDevice *powerdev {}; }; -extern PPIDevice *gPPI; -extern PIO0Device *gPIO0; -extern PIO1Device *gPIO1; +static inline PPIDevice *GetPPIDevice() { + return Object::GetObject(OBJ_PPI); +} +static inline PIO0Device *GetPIO0Device() { + return Object::GetObject(OBJ_PIO0); +} +static inline PIO1Device *GetPIO1Device() { + return Object::GetObject(OBJ_PIO1); +}