File:  [Isaki's NoNo m68k/m88k emulator] / nono / vm / videoctlr.h
Revision 1.1.1.14 (vendor branch): download - view: text, annotated - select for diffs
Wed Apr 29 17:05:59 2026 UTC (2 months, 3 weeks ago) by root
Branches: MAIN, Isaki
CVS tags: v027, HEAD
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);
}

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.