--- nono/vm/gvram.h 2026/04/29 17:05:24 1.1.1.8 +++ nono/vm/gvram.h 2026/04/29 17:05:59 1.1.1.12 @@ -11,21 +11,84 @@ #pragma once #include "device.h" +#include "bitmap.h" +#include +#include + +class VideoCtlrDevice; class GVRAMDevice : public IODevice { using inherited = IODevice; - static const uint baseaddr = 0xc0'0000; + + using bitset1024 = std::bitset<1024>; + + static const uint32 baseaddr = 0xc0'0000; + + // 更新情報。 + struct ModifyInfo + { + // 1ライン単位の更新フラグ。 + bitset1024 line {}; + + // パレットを更新した場合やスクロールした場合のように、 + // composite に変更がなくても bitmap を更新する必要がある場合は true。 + bool invalidate2 {}; + }; + public: GVRAMDevice(); ~GVRAMDevice() override; - busdata Read8(uint32 addr) override; - busdata Read16(uint32 addr) override; - busdata Write8(uint32 addr, uint32 data) override; - busdata Write16(uint32 addr, uint32 data) override; - busdata Peek8(uint32 addr) override; + bool Init() override; + void ResetHard(bool poweron) override; + + busdata Read(busaddr addr) override; + busdata Write(busaddr addr, uint32 data) override; + busdata Peek1(uint32 addr) override; + bool Poke1(uint32 addr, uint32 data) override; + + bool Snap(); + bool Render(BitmapRGBX& dst); + + // インデックスカラーのビットマップを取得する。(モニタ用) + const BitmapI8& GetComposite() const { return composite; } + + // グラフィック画面の座標位置の情報を出力 (GUI 用) + void UpdateInfo(TextScreen& screen, int x, int y) const; private: + inline uint32 Decoder(uint32 addr) const; + + void Invalidate(); + inline void SetDirty(uint32 offset); + + void Render1024ToComposite(const bitset1024& modified); + void RenderCompositeToRGBX(BitmapRGBX& dst, const ModifyInfo& modified); + + // メモリを確保する時のサイズ計算のため型を uint8 にしているが、 + // 運用はワードでホストバイトオーダー。 std::unique_ptr mem {}; + + // グラフィック画面(1024x1024, 16色)のビットマップ。 + BitmapI8 composite {}; + + // VM スレッド内での仮想画面の更新フラグ。 + ModifyInfo dirty {}; + + // レンダラスレッドで未処理の行。 + // VM スレッドからレンダラスレッドへの連絡用なので mtx で保護する。 + ModifyInfo pending {}; + std::mutex mtx {}; + + // ホストパレット + const Color *palette {}; + + VideoCtlrDevice *videoctlr {}; + + static const busdata wait; }; + +inline GVRAMDevice *GetGVRAMDevice() { + return Object::GetObject(OBJ_GVRAM); +}