File:  [Isaki's NoNo m68k/m88k emulator] / nono / wx / wxlcdwindow.cpp
Revision 1.1.1.11 (vendor branch): download - view: text, annotated - select for diffs
Wed Apr 29 17:05:58 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
//

//
// LUNA LCD パネル、モニタ
//

#include "wxlcdwindow.h"
#include "wxuimessage.h"
#include "lcd.h"
#include "monitor.h"

//
// LUNA 前面 LCD パネル
//

// BitmapPanel の継承で十分だが FontChanged() に連動させるため、
// TextPanel からの継承としている。
//
// 全体図。横16文字 x 縦2行
// □ は1キャラクタ分。5x8ピクセル。
// _  は1ピクセル分のアキ。
//
//     +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +a +b +c +d +e +f
// 横 _□_□_□_□_□_□_□_□_□_□_□_□_□_□_□_□_
//    _□_□_□_□_□_□_□_□_□_□_□_□_□_□_□_□_
//
//      1  2
// 縦 _□_□_

// コンストラクタ
WXLCDPanel::WXLCDPanel(wxWindow *parent)
	: inherited(parent)
{
	SetName("LCDPanel");

	u_width  = 5 * 16 + 17;
	u_height = 8 * 2 + 3;

	lcd = GetLCDDevice();
	ddram = lcd->GetDDRAM();

	// VM からの通知を受け取る
	WXUIMessage::Connect(UIMessage::LCD, this,
		wxCommandEventHandler(WXLCDPanel::OnLCDChanged));

	FontChanged();
	SetBitmapBGColor(UD_CREAM);
	Fill();
}

// デストラクタ
WXLCDPanel::~WXLCDPanel()
{
	WXUIMessage::Disconnect(UIMessage::LCD, this,
		wxCommandEventHandler(WXLCDPanel::OnLCDChanged));
}

// フォントサイズ変更通知
void
WXLCDPanel::FontChanged()
{
	inherited::FontChanged();

	// このパネル内の描画の基本単位。
	// 12, 16, 24 を 2, 3, 4 にする。
	unit = (font_height + 5) / 6;
	wxSize size(u_width * unit, u_height * unit);

	// バックバッファのサイズを固定。
	SetMinBitmapSize(size);

	// コントロールの大きさを変更。
	SetSize(size);
	SetMinSize(size);
}

// LCD 状態変更イベント (UIMessage)
void
WXLCDPanel::OnLCDChanged(wxCommandEvent& event)
{
	Refresh();
}

// バックグラウンドバッファに描画
void
WXLCDPanel::Draw()
{
	for (int y = 0; y < 2; y++) {
		for (int x = 0; x < 16; x++) {
			uint8 ch = ddram[0x40 * y + x];
			DrawChar(x, y, ch);
		}
	}
}

// 1文字描画
void
WXLCDPanel::DrawChar(int x, int y, uint8 ch)
{
	const Color pal[2] = { UD_YELLOW_GREEN, UD_BROWN };
	const uint8 *font;

	font = lcd->GetFont(ch);
	BitmapI1 src(font, 5, 8);

	int dx = (1 + x * 6) * unit;
	int dy = (1 + y * 9) * unit;
	bitmap.DrawBitmapI1Scale(dx, dy, src, pal, unit);
}


//
// LUNA 前面 LCD ウィンドウ
//

// コンストラクタ
WXLCDWindow::WXLCDWindow(wxWindow *parent)
	: inherited(parent, wxID_ANY, _("Front LCD"))
{
	new WXLCDPanel(this);
	Fit();
}

// デストラクタ
WXLCDWindow::~WXLCDWindow()
{
}


//
// モニタの LCD キャラクタ部パネル
//

// BitmapPanel の継承で十分だが FontChanged() に連動させるため、
// TextPanel からの継承としている。
//
// 全体図。横16文字 + 横16文字の2段組。
// □ は1キャラクタ分。5x8ピクセル。
// _  は1ピクセル分のアキ。
//
//                                                   余白
//     +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +a +b +c +d +e +f  +0 +1    +f
// 横 _□_□_□_□_□_□_□_□_□_□_□_□_□_□_□_□□□_□ … □_
//
//     00 10 20 30 40 50 60 70
// 縦 _□_□_□_□_□_□_□_□_

// コンストラクタ
WXLCDCharPanel::WXLCDCharPanel(wxWindow *parent)
	: inherited(parent)
{
	SetName("LCDCharPanel");

	lcd = GetLCDDevice();

	u_width  = 5 * 33 + 32;	// 横 5px * (32+1)文字、余白が計 32
	u_height = 8 * 8 + 9;	// 縦 8px * 8行、余白が計 9

	FontChanged();
}

// デストラクタ
WXLCDCharPanel::~WXLCDCharPanel()
{
}

// フォントサイズ変更通知
void
WXLCDCharPanel::FontChanged()
{
	inherited::FontChanged();

	// このパネル内の描画の基本単位。
	// 12, 16, 24 を 2, 3, 4 にする。
	unit = (font_height + 5) / 6;
	wxSize size(u_width * unit, u_height * unit);

	// バックバッファのサイズを固定。
	SetMinBitmapSize(size);

	// コントロールの大きさを変更。
	SetSize(size);
	SetMinSize(size);
}

// バックグラウンドバッファに描画
void
WXLCDCharPanel::Draw()
{
	const Color pal[2] = { UD_WHITE, UD_BLACK };

	// フォントは 5x8 (最下行はカーソル用に空けてあるので実際は 5x7)。
	// 実際には 0xe0 以降には 5x10 フォントが混在しているのだが、その
	// モードはサポートしていないので今の所全部 5x8 としてある。

	// cx, cy はこの文字の左上座標 (スケール前)
	int cx = 1;
	int cy = 1;
	for (int ch = 0; ch < 256; ch++) {
		const uint8 *font = lcd->GetFont(ch);
		BitmapI1 src(font, 5, 8);
		bitmap.DrawBitmapI1Scale(cx * unit, cy * unit, src, pal, unit);

		cx += 6;
		if (ch % 16 == 15) {
			if (ch == 127) {
				// 0x80 以降は右側に作る。
				// 余白も含めた 6px ずつ加算してきたが中間のアキは計 5px
				// なので、過剰分の 1 引く必要がある。
				cx += 5 - 1;
				cy = 1;
			} else {
				// 行折り返し
				cx -= 6 * 16;
				cy += 9;
			}
		}
	}
}


//
// LCD モニタウィンドウ
//

// コンストラクタ
WXLCDMonitor::WXLCDMonitor(wxWindow *parent)
	: inherited(parent, wxID_ANY, "LCD (HD44780)")
{
	// +------------+
	// | TextScreen |
	// +------------+
	// | CharPanel  |
	// +------------+

	// 上段、テキストスクリーン
	monpanel = new WXMonitorPanel(this, gMonitorManager->Get(ID_MONITOR_LCD));
	// 下辺は CharPanel の上余白が隣接しているため、自分のほうは付けない。
	monpanel->SetPadding(-1, -1, -1, 0);

	// 下段、キャラクタパネル
	chrpanel = new WXLCDCharPanel(this);

	// 空き地用。
	space = new WXBitmapPanel(this);

	SetAutoLayout(true);
	FontChanged();
}

// デストラクタ
WXLCDMonitor::~WXLCDMonitor()
{
}

void
WXLCDMonitor::FontChanged()
{
	monpanel->FontChanged();
	chrpanel->FontChanged();

	const wxSize& monsize = monpanel->GetSize();
	const wxSize& chrsize = chrpanel->GetSize();
	wxSize size(std::max(monsize.x, chrsize.x), monsize.y + chrsize.y);
	SetClientSize(size);
}

bool
WXLCDMonitor::Layout()
{
	// inherited::Layout() は(実質何もしないので)、呼ばずに自力で行う。

	wxSize client = GetClientSize();
	const wxSize& monsize = monpanel->GetSize();
	const wxSize& chrsize = chrpanel->GetSize();

	// コントロールを配置。
	monpanel->SetSize(0, 0, monsize.x, monsize.y);
	chrpanel->SetSize(0, monsize.y, chrsize.x, chrsize.y);

	// monpanel と chrpanel はフォントサイズによる拡大倍率が違うため
	// フォントサイズを変更した時に相似にならず、現状では必ずどちらかが
	// 大きい (がどちらかは固定されない) という状態になる。
	// そこで小さい方のコントロールの右に空き地が出来てしまう。そのままだと
	// GTK3 のウィンドウ下地色が見えてしまうため、BGPANEL 色のパネルを敷く。

	if (monsize.x < chrsize.x) {
		// 上が小さいので、右上に空き地を置く。
		space->SetSize(monsize.x, 0, client.x - monsize.x, monsize.y);
	} else {
		// 下が小さいので、左下に空き地を置く。
		space->SetSize(chrsize.x, monsize.y, client.x - chrsize.x, chrsize.y);
	}

	return true;
}

unix.superglobalmegacorp.com

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