|
|
1.1 root 1: //
2: // nono
3: // Copyright (C) 2022 nono project
4: // Licensed under nono-license.txt
5: //
6:
7: //
8: // パレットモニターウィンドウ
9: //
10:
11: #include "wxpalettemonitor.h"
12: #include "wxcolor.h"
13: #include "wxtextscreen.h"
14: #include "wxuimessage.h"
15: #include "bt45x.h"
1.1.1.3 root 16: #include "mainapp.h"
1.1 root 17: #include "videoctlr.h"
18:
19: //
20: // パレットビットマップ
21: //
22: //
23: // 情報欄は WXTextScreen 同様に上下と左に DefaultPadding を手動で入れてある。
24: //
25: //
26: // +------------ DefaultPadding (情報欄の左側)
27: // |
28: // +-|------
29: // | v <- DefaultPadding (情報欄の上側)
30: // | "Text"
31: // | <- DefaultPadding (情報欄の下側、パレット欄の区切り)
32: // | "+0 +1 …"
33: // |-------- <- pal_y0 (ここから以下がパレット領域)
34: // | □‥
35: // : :
36: // | □‥
37: // | <- DefaultPadding (パレットの下側)
38: // +-^-------^
39: // | |
40: // +-------+---- DefaultPadding (パレットの左右)
41: //
42: // パレット欄は1マスが横 font_height (= font_width * 2)、縦 font_height [px]
43: // で、マスの右端と左端の1ピクセルを BGPANEL 色にして罫線にする。
44:
1.1.1.5 ! root 45: // Bt454 は 16 色なので 16色 x 1行。
! 46: // Bt458 は 256 色なので 16色 x 16行。
! 47: // X68030 は 512 色なので 16色 x 16行 x 2列組。
! 48:
1.1 root 49: // イベントテーブル
50: wxBEGIN_EVENT_TABLE(WXPalettePanel, inherited)
51: EVT_MOUSE_EVENTS(WXPalettePanel::OnMouse)
52: wxEND_EVENT_TABLE()
53:
54: // コンストラクタ
55: WXPalettePanel::WXPalettePanel(wxWindow *parent)
56: : inherited(parent)
57: {
1.1.1.4 root 58: SetName("PalettePanel");
59:
1.1 root 60: // デバイスを取得
61: bt45x = gMainApp.FindObject<BT45xDevice>(OBJ_BT45x);
62: videoctlr = gMainApp.FindObject<VideoCtlrDevice>(OBJ_VIDEOCTLR);
63:
64: cursor = -1;
65:
66: // パレットは1行に16個で、行数 (1 or 16) が可変。
67: // ここではサイズだけ確定させる。
1.1.1.2 root 68: const std::vector<Color> *hpal;
1.1 root 69: if (videoctlr) {
70: hpal = &videoctlr->GetHostPalette();
1.1.1.5 ! root 71: rows = 16;
! 72: idxlen = 3;
1.1 root 73: } else {
74: hpal = &bt45x->GetHostPalette();
1.1.1.5 ! root 75: rows = hpal->size() / 16;
! 76: idxlen = (rows == 1) ? 1 : 2;
1.1 root 77: }
78:
79: FontChanged();
80: PaletteChanged();
81:
82: // VM からの通知を受け取る
83: WXUIMessage::Connect(UIMessage::PALETTE, this,
84: wxCommandEventHandler(WXPalettePanel::OnPaletteChanged));
85: }
86:
87: // デストラクタ
88: WXPalettePanel::~WXPalettePanel()
89: {
90: WXUIMessage::Disconnect(UIMessage::PALETTE, this,
91: wxCommandEventHandler(WXPalettePanel::OnPaletteChanged));
92: }
93:
94: void
95: WXPalettePanel::FontChanged()
96: {
97: inherited::FontChanged();
98:
99: pal0x = WXTextScreen::DefaultPadding; // 左余白
100: pal0x += font_width * 4; // "$00:"
101:
102: pal0y = WXTextScreen::DefaultPadding; // 上余白
103: pal0y += font_height * 2; // テキスト
104: pal0y += WXTextScreen::DefaultPadding; // テキストとパレットの境界余白
105: pal0y += font_height; // ヘッダ("+0+1"…)
106:
1.1.1.5 ! root 107: if (videoctlr) {
! 108: pal1x = pal0x + 17 * font_height;
! 109: pal0y += font_height; // Text/Graphic の表示
! 110: }
! 111:
1.1 root 112: wxSize size;
113: size.x = pal0x; // パレットより左全部
114: size.x += 16 * font_height; // パレット部
1.1.1.5 ! root 115: if (videoctlr) {
! 116: size.x += 17 * font_height; // X68030 なら2列組。
! 117: }
1.1 root 118: size.x += WXTextScreen::DefaultPadding; // 右余白
119:
120: size.y = pal0y; // パレットより上全部
121: size.y += rows * font_height; // パレット部
122: size.y += WXTextScreen::DefaultPadding; // 下余白
123:
1.1.1.4 root 124: // バックバッファのサイズを固定。
125: SetMinBitmapSize(size);
126:
127: SetSize(size);
128: SetMinSize(size);
1.1 root 129: }
130:
131: // VM からのパレット変更通知
132: void
133: WXPalettePanel::OnPaletteChanged(wxCommandEvent& event)
134: {
135: PaletteChanged();
136: }
137:
138: void
139: WXPalettePanel::PaletteChanged()
140: {
1.1.1.5 ! root 141: // ホスト/ゲストパレットをここでコピー。
1.1 root 142: if (videoctlr) {
143: pal = videoctlr->GetHostPalette();
1.1.1.5 ! root 144: vcpal = videoctlr->GetGuestPalette();
1.1 root 145: } else {
146: pal = bt45x->GetHostPalette();
1.1.1.5 ! root 147: btpal = bt45x->GetGuestPalette();
1.1 root 148: }
149: Refresh();
150: }
151:
152: void
153: WXPalettePanel::Draw()
154: {
155: bitmap.Fill(BGPANEL);
156:
1.1.1.5 ! root 157: // Bt454 (2 or 16色)
! 158: // 01234567
! 159: // [$0] Guest
! 160: // Host
! 161: //
! 162: // Bt458 (256色)
! 163: // 01234567
! 164: // [$00] Guest
! 165: // Host
! 166: //
! 167: // X68030 (512色)
! 168: // 01234567
! 169: // [$000] Guest
! 170: // Host
! 171:
1.1 root 172: // テキスト (2行)
173: // XXX snprintf が色々うるさくてアレ…
174: char text1[36 + 1 + 40];
175: char text2[36 + 1];
176: if (cursor < 0) {
1.1.1.5 ! root 177: strlcpy(text1, "[ Guest", sizeof(text1));
! 178: text1[idxlen + 2] = ']';
1.1 root 179: strlcpy(text2, "Host R: G: B:", sizeof(text2));
180: } else {
181: // この位置のパレット情報を取得
182: if (videoctlr) {
1.1.1.5 ! root 183: // X68030 のパレットは %GGGGG'RRRRR'BBBBB'I の16ビット。
! 184: assert(cursor <= 0x1ff);
! 185: uint c = vcpal[cursor];
! 186: uint r = (c >> 6) & 0x1f;
! 187: uint g = (c >> 11) & 0x1f;
! 188: uint b = (c >> 1) & 0x1f;
! 189: uint i = c & 1;
! 190: snprintf(text1, sizeof(text1),
! 191: "[$%03x] Guest $%04x R:%02x G:%02x B:%02x I:%u",
! 192: cursor, c, r, g, b, i);
1.1 root 193: } else {
194: if (rows == 1) {
1.1.1.5 ! root 195: // Bt454 のパレットは $RR, $GG, $BB の3バイト。
! 196: // ただし上位4ビットと下位4ビットは同じにしてある。
! 197: assert(cursor <= 0xf);
! 198: const uint8 *c = &btpal[cursor * 3];
! 199: uint r = c[0] >> 4;
! 200: uint g = c[1] >> 4;
! 201: uint b = c[2] >> 4;
! 202: snprintf(text1, sizeof(text1),
! 203: "[$%x] Guest R:%x G:%x B:%x", cursor, r, g, b);
1.1 root 204: } else {
1.1.1.5 ! root 205: // Bt458 のパレットは $RR, $GG, $BB の3バイトで各8ビット。
! 206: assert(cursor <= 0xff);
! 207: const uint8 *c = &btpal[cursor * 3];
! 208: uint r = c[0];
! 209: uint g = c[1];
! 210: uint b = c[2];
! 211: snprintf(text1, sizeof(text1),
! 212: "[$%02x] Guest R:%02x G:%02x B:%02x", cursor, r, g, b);
1.1 root 213: }
214: }
215: snprintf(text2, sizeof(text2), "Host R:%02x G:%02x B:%02x",
216: pal[cursor].r,
217: pal[cursor].g,
218: pal[cursor].b);
219: }
220: const int padding = WXTextScreen::DefaultPadding;
221: DrawStringSJIS(padding, padding, text1);
1.1.1.5 ! root 222: DrawStringSJIS(padding + font_width * 7, padding + font_height, text2);
1.1 root 223:
224: // ヘッダ
1.1.1.5 ! root 225: static const char xlabel[] = "+0+1+2+3+4+5+6+7+8+9+a+b+c+d+e+f";
! 226: DrawStringSJIS(pal0x, pal0y - font_height, xlabel);
1.1 root 227: for (int y = 0; y < rows; y++) {
228: char buf[8];
229: __assume(y < 16); // XXX snprintf 対策。うーん
230: snprintf(buf, sizeof(buf), "$%02x:", y * 16);
231: DrawStringSJIS(padding, pal0y + y * font_height, buf);
232: }
233:
234: // パレット
235: Rect rect(0, 0, font_height - 1, font_height - 1);
236: for (int y = 0; y < rows; y++) {
237: for (int x = 0; x < 16; x++) {
238: int cc = y * 16 + x;
239: rect.x = pal0x + x * font_height;
240: rect.y = pal0y + y * font_height;
1.1.1.2 root 241: bitmap.FillRect(pal[cc], rect);
1.1 root 242: }
243: }
1.1.1.5 ! root 244: if (videoctlr) {
! 245: DrawStringSJIS(pal0x, pal0y - font_height * 2, "Graphic Palette");
! 246: DrawStringSJIS(pal1x, pal0y - font_height * 2,
! 247: "Text/Sprite/BG Palette");
! 248: DrawStringSJIS(pal1x, pal0y - font_height, xlabel);
! 249: uint cc = 256;
! 250: rect.y = pal0y;
! 251: for (uint y = 0; y < rows; y++) {
! 252: rect.x = pal1x;
! 253: for (uint x = 0; x < 16; x++) {
! 254: bitmap.FillRect(pal[cc++], rect);
! 255: rect.x += font_height;
! 256: }
! 257: rect.y += font_height;
! 258: }
! 259: }
1.1 root 260: }
261:
262: void
263: WXPalettePanel::OnMouse(wxMouseEvent& event)
264: {
265: wxPoint pt = event.GetPosition();
266: int new_cursor = -1;
267:
268: // pt がパネル内の座標なのに Leaving() になることがある。
269: // pt がパネル外の座標なのに Leaving() にならないことがある。
270: if (event.Leaving() == false && GetClientRect().Contains(pt)) {
271: // マウスカーソルがパネル上にある
272:
273: int y = pt.y - pal0y;
1.1.1.5 ! root 274: if (y < 0) {
1.1 root 275: goto next;
276: }
277: y /= font_height;
1.1.1.5 ! root 278: if (y >= rows) {
! 279: goto next;
! 280: }
! 281:
! 282: int x;
! 283: if (pal0x <= pt.x && pt.x < pal0x + font_height * 16) {
! 284: x = (pt.x - pal0x) / font_height;
! 285: } else if (pal1x != 0) {
! 286: // X68030 の右段
! 287: if (pal1x <= pt.x && pt.x < pal1x + font_height * 16) {
! 288: x = (pt.x - pal1x) / font_height;
! 289: y += 16;
! 290: } else {
! 291: goto next;
! 292: }
! 293: } else {
1.1 root 294: goto next;
295: }
296:
297: new_cursor = y * 16 + x;
298: }
299:
300: next:
301: if (new_cursor != cursor) {
302: cursor = new_cursor;
303: Refresh();
304: }
305: }
306:
307:
308: //
309: // パレットウィンドウ
310: //
311:
312: // コンストラクタ
313: WXPaletteWindow::WXPaletteWindow(wxWindow *parent, const wxString& name)
314: : inherited(parent, wxID_ANY, name)
315: {
316: new WXPalettePanel(this);
1.1.1.4 root 317: Fit();
1.1 root 318: }
319:
320: // デストラクタ
321: WXPaletteWindow::~WXPaletteWindow()
322: {
323: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.