|
|
nono 1.7.0
//
// nono
// Copyright (C) 2020 nono project
// Licensed under nono-license.txt
//
//
// ビデオコントローラ
//
#pragma once
#include "device.h"
#include "bitmap.h"
#include <array>
#include <atomic>
class GVRAMDevice;
class PlaneVRAMDevice;
class VideoRenderer;
class UIMessage;
class VideoCtlr
{
public:
// f e d c b a 9 8 7 6 5 4 3 2 1 0
// +--------------------------------------+--+-----+
// R0 | |SZ| COL |
// +--------------------------------------+--+-----+
static constexpr uint32 R0_SIZ = 0x0004;
static constexpr uint32 R0_COL = 0x0003;
// f e d c b a 9 8 7 6 5 4 3 2 1 0
// +-----+-----+-----+-----+-----+-----+-----+-----+
// R1 | %00 | SP | TX | GR | GP3 | GP2 | GP1 | GP0 |
// +-----+-----+-----+-----+-----+-----+-----+-----+
static constexpr uint32 R1_SP = 0x3000; // スプライト優先度
static constexpr uint32 R1_TX = 0x0c00; // テキスト画面優先度
static constexpr uint32 R1_GR = 0x0300; // グラフィック画面優先度
static constexpr uint32 R1_G3 = 0x00c0; // GP3 優先度
static constexpr uint32 R1_G2 = 0x0030; // GP2 優先度
static constexpr uint32 R1_G1 = 0x000c; // GP1 優先度
static constexpr uint32 R1_G0 = 0x0003; // GP0 優先度
// f e d c b a 9 8 7 6 5 4 3 2 1 0
// +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
// R2 |YS|AH|VH|EX|HP|BP|GG|GT| |SO|TO|GO|G3|G2|G1|G0|
// +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
static constexpr uint32 R2_YS = 0x8000;
static constexpr uint32 R2_AH = 0x4000;
static constexpr uint32 R2_VH = 0x2000;
static constexpr uint32 R2_EX = 0x1000;
static constexpr uint32 R2_HP = 0x0800;
static constexpr uint32 R2_BP = 0x0400;
static constexpr uint32 R2_GG = 0x0200;
static constexpr uint32 R2_GT = 0x0100;
static constexpr uint32 R2_SP_ON = 0x0040; // スプライトオン
static constexpr uint32 R2_TX_ON = 0x0020; // テキスト画面オン
static constexpr uint32 R2_GR_ON = 0x0010; // グラフィック画面オン
static constexpr uint32 R2_G3_ON = 0x0008; // グラフィック(P3)オン
static constexpr uint32 R2_G2_ON = 0x0004; // グラフィック(P2)オン
static constexpr uint32 R2_G1_ON = 0x0002; // グラフィック(P1)オン
static constexpr uint32 R2_G0_ON = 0x0001; // グラフィック(P0)オン
};
class VideoCtlrDevice : public IODevice, public VideoCtlr
{
using inherited = IODevice;
static const uint32 baseaddr = 0xe82000;
// 描画順のための描画フラグ
static constexpr uint32 SORDER_NONE = 0x0;
static constexpr uint32 SORDER_SP = 0x1;
static constexpr uint32 SORDER_TX = 0x2;
static constexpr uint32 SORDER_GR = 0x3;
static constexpr uint32 SORDER_BG = 0x4;
static constexpr uint32 SORDER_BLACK = 0x5; // 仮想的な背景
public:
VideoCtlrDevice();
~VideoCtlrDevice() 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;
// コントラストを取得 (Peek() からも呼ぶので副作用を起こしてはいけない)
uint GetContrast() const { return target_contrast / 0x11; }
// コントラストを設定
void SetContrast(uint);
// 画面作成。
void VDisp();
// 画面合成
bool Render(BitmapRGBX& dst);
// モニタ更新(下請け)
int MonitorScreen(TextScreen&, int y, uint32 crtc_r20);
// グラフィック画面を取得。(モニタ用)
const BitmapRGBX& GetGraphicBitmap() const { return grbmp; }
// ホストパレットを取得。(レンダラとかからの参照用)
const std::vector<Color>& GetHostPalette() const { return hostcolor; }
// ホストパレットのアドレスを取得。
const Color *GetHostPalettePtr(int idx) const { return &hostcolor[idx]; }
// ゲストパレットを取得。(GUI 情報表示用)
const std::vector<uint16>& GetGuestPalette() const { return palette; }
// モニタ用。CRTC からも使う。
static const char * const siz_str[2];
static const char * const col_str[4];
private:
static inline uint32 Decoder(uint32 addr);
static inline uint Offset2Rn(uint32 offset);
uint32 Get16(uint32 offset) const;
void Set8(uint32 offset, uint32 data);
void Set16(uint32 offset, uint32 data);
void MakePalette();
void RenderContrast(BitmapRGBX& dst, const BitmapRGBX& src);
static void RenderContrast_gen(BitmapRGBX&, const BitmapRGBX&, uint32);
#if defined(HAVE_AVX2)
static void RenderContrast_avx2(BitmapRGBX&, const BitmapRGBX&, uint32);
bool enable_avx2 {};
#endif
#if defined(HAVE_NEON)
static void RenderContrast_neon(BitmapRGBX&, const BitmapRGBX&, uint32);
bool enable_neon {};
#endif
void ContrastCallback(Event *);
// ワードレジスタ R0, R1, R2
std::array<uint16, 3> reg {};
uint16 prev_reg1 {};
uint16 prev_reg2 {};
// 各画面
BitmapRGBX txbmp {};
BitmapRGBX grbmp {};
// 合成画面 (コントラスト適用前)
BitmapRGBX mixbmp {};
// パレット (ホストバイトオーダー)
std::vector<uint16> palette {};
// ホスト形式のテキストパレット (レンダラ用に加工したもの)
std::vector<Color> hostcolor {};
// 描画順 (SORDER_* を LSB 側から4ビットずつ並べる)
uint32 screen_order {};
// 設定したコントラスト値 (0-255)
uint32 target_contrast {};
// 現在の (遷移中かもしれない) コントラスト値 (0-255)
uint32 running_contrast {};
// 設定を変える時の初期値 (0-255)
uint32 initial_contrast {};
// 設定を変える時の起点
uint64 contrast_time0 {};
// VM スレッドからレンダラスレッドへの連絡用。(0-255)
std::atomic<uint32> pending_contrast {};
// レンダリングに使っているコントラスト値 (0-255)
uint32 rendering_contrast {};
Event *contrast_event {};
GVRAMDevice *gvram {};
PlaneVRAMDevice *planevram {};
UIMessage *uimessage {};
VideoRenderer *renderer {};
};
inline VideoCtlrDevice *GetVideoCtlrDevice() {
return Object::GetObject<VideoCtlrDevice>(OBJ_VIDEOCTLR);
}
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.