|
|
1.1 root 1: //
2: // nono
3: // Copyright (C) 2024 nono project
4: // Licensed under nono-license.txt
5: //
6:
7: //
8: // アクセス状況 (グラフィカル) ウィンドウ
9: //
10:
11: // パネルには WXTextScreen 同様に四辺に DefaultPadding を手動で入れてある。
12:
13: #include "wxaccstatmonitor.h"
14: #include "wxcolor.h"
15: #include "wxtextscreen.h"
16: #include "bankram.h"
17: #include "mainbus.h"
18:
19: //
20: // アクセス状況 (グラフィカル) パネル
21: //
22:
23: // コンストラクタ
24: WXAccStatPanel::WXAccStatPanel(wxWindow *parent, Monitor& monitor_)
25: : inherited(parent, monitor_)
26: {
27: // デバイスを取得
28: mainbus = GetMainbusDevice();
29:
30: // バンクメモリ描画のため
31: is_x68030 = gMainApp.IsX68030();
32: if (is_x68030) {
33: for (int n = 0; n < 2; n++) {
34: auto bankdev = gMainApp.FindObject<BankRAMDevice>(OBJ_BANKRAM(n));
35: bankram[n] = (bankdev != NULL);
36: }
37: }
38:
39: FontChanged();
40: }
41:
42: // デストラクタ
43: WXAccStatPanel::~WXAccStatPanel()
44: {
45: }
46:
47: void
48: WXAccStatPanel::FontChanged()
49: {
50: inherited::FontChanged();
51:
52: auto monsz = mainbus->monitor_accstat.GetSize();
53: wxSize size(
54: WXTextScreen::DefaultPadding * 2 + monsz.width * font_width,
55: WXTextScreen::DefaultPadding * 2 + monsz.height * font_height);
56:
57: SetClientSize(size);
58: SetMinClientSize(size);
59:
60: redraw_header = true;
61: }
62:
63: void
64: WXAccStatPanel::Draw()
65: {
66: const int padding = WXTextScreen::DefaultPadding;
67: const auto& accstat_rw = mainbus->accstat_rw;
68: const auto& accstat_avail = mainbus->accstat_avail;
69: int rows = accstat_rw.size() / 64;
70: uint fw = font_width;
71: uint fh = font_height;
72:
73: // 8文字分(16MB) ごとに 0.5 文字分ずつ空ける
74: int width8 = fw * 8 + (fw / 2);
75:
76: if (redraw_header) {
77: redraw_header = false;
78:
79: char buf[80];
80: static_assert(AccStat::SHIFT >= 20, "");
81: snprintf(buf, sizeof(buf),
82: "Show %ubit space. %uMB/piece. ' ':Read, ' ':Write(+Read)",
83: mainbus->accstat_bitlen, 1U << (AccStat::SHIFT - 20));
84: DrawStringSJIS(padding, padding, buf);
85:
86: bitmap.FillRect(UD_GREEN, padding + fw * 30, padding, fw - 1, fh - 1);
87: bitmap.FillRect(UD_RED, padding + fw * 40, padding, fw - 1, fh - 1);
88:
89: for (uint i = 0; i < 8; i++) {
90: snprintf(buf, sizeof(buf), "+$0%x", i);
91: DrawStringSJIS(padding + fw * 12 + width8 * i,
92: padding + fh * 1, buf);
93: }
94:
95: uint baseaddr;
96: if (accstat_rw.size() == mainbus->accstat_read.size()) {
97: baseaddr = 0;
98: } else {
99: baseaddr = 0xc0;
100: }
101:
102: for (int y = 0; y < rows; y++) {
103: snprintf(buf, sizeof(buf), "$%02x00'0000:",
104: (uint8)(baseaddr + y * 0x08));
105: DrawStringSJIS(padding, padding + fh * (y + 2), buf);
106: }
107:
108: if (is_x68030) {
109: for (int n = 0; n < 2; n++) {
110: snprintf(buf, sizeof(buf), "BankMem #%u:", n);
111: DrawStringSJIS(padding, padding + fh * (35 + n), buf);
112: }
113: }
114: }
115:
116: // UD_{RED,GREEN} から UD_LIGHT_GREY まで HSV の S,V を線形補間。
117: static const Color cols[8] = {
118: UD_RED, // HSV(18, 100, 100)
119: UD_GREEN, // HSV(162, 98, 69)
120: Color(242, 115, 60), // HSV(18, 75, 95)
121: Color(47, 183, 142), // HSV(162, 74, 72)
122: Color(229, 149, 114), // HSV(18, 50, 90)
123: Color(97, 191, 163), // HSV(162, 49, 75)
124: Color(216, 178, 162), // HSV(18, 25, 85)
125: Color(149, 196, 182), // HSV(162, 24, 77)
126: };
127: // UD_LIGHT_GREY // HSV(240, 1, 80)
128:
129: uint py = padding + fh * 2;
130: for (int y = 0; y < rows; y++) {
131: const uint8 *a = &mainbus->accstat_rw[y * 64];
132: uint8 avail = accstat_avail[y];
133: uint px = padding + fw * 12;
134:
135: for (int i = 0; i < 8; i++) {
136: if ((int8)avail < 0) {
137: // 何かしらデバイスがある 16MB (8文字相当) 分。
138: for (int j = 0; j < 8; j++, a++, px += fw) {
139: uint8 op = *a;
140: Color c;
141: if (__predict_true(op == 0)) {
142: c = UD_LIGHT_GREY;
143: } else {
144: c = cols[__builtin_ctz(op)];
145: }
146: bitmap.DrawLineH(c, px, py, px + fw - 1);
147: }
148: } else {
149: // この 16MB には何のデバイスもない。
150: a += 8;
151: // 事故がなければこれなくても動くはず
152: //bitmap.DrawLineH(BGPANEL, px, py, px + fw * 8 - 1);
153: px += fw * 8;
154: }
155: avail <<= 1;
156: px += fw / 2;
157: }
158:
159: // 1ラスターを縦1文字分に展開
160: CopyLine(12, py, 68);
161: py += fh;
162: }
163:
164: // バンクメモリ
165: if (is_x68030) {
166: for (int n = 0; n < 2; n++) {
167: if (bankram[n]) {
168: py = padding + fh * (35 + n);
169: const uint8 *a = &mainbus->accbank[n * AccStat::BANKLEN];
170: uint px = padding + fw * 12;
171:
172: for (int j = 0; j < 8; j++, a++, px += fw) {
173: uint8 op = *a;
174: Color c;
175: if (__predict_true(op == 0)) {
176: c = UD_LIGHT_GREY;
177: } else {
178: c = cols[__builtin_ctz(op)];
179: }
180: bitmap.DrawLineH(c, px, py, px + fw - 1);
181: }
182:
183: // 1ラスターを縦1文字分に展開
184: CopyLine(12, py, 8);
185: }
186: }
187: }
188: }
189:
190: // 1ラスターを縦1文字分に展開する。
191: // ただの共通下請けなので引数に汎用性はない。
192: // cx は文字単位の X 座標 (左端の1文字目が 0、次の文字が 1)。
193: // py はピクセル単位の Y 座標。
194: // clen はコピーする文字数。
195: // (cxをピクセルにした座標, py) から clen 文字分の長さを次ラスターから
196: // (font_height - 1) ラスターまでにコピーする。
197: void
198: WXAccStatPanel::CopyLine(int cx, int py, int clen)
199: {
200: const int padding = WXTextScreen::DefaultPadding;
201: int px = padding + font_width * cx;
202: Rect rect(px, py, clen * font_width, font_height - 1);
203:
204: bitmap.CopyFromTop(rect);
205: }
206:
207:
208: //
209: // アクセス状況 (グラフィカル) ウィンドウ
210: //
211:
212: // コンストラクタ
213: WXAccStatWindow::WXAccStatWindow(wxWindow *parent, Monitor& monitor_)
214: : inherited(parent, wxID_ANY, _("Access Status"))
215: {
216: new WXAccStatPanel(this, monitor_);
217: DoSize();
218: }
219:
220: // デストラクタ
221: WXAccStatWindow::~WXAccStatWindow()
222: {
223: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.