|
|
1.1 root 1: //
2: // nono
3: // Copyright (C) 2017 [email protected]
4: //
5: // TVRAM
6: //
7:
8: #include "renderer.h"
9: #include "tvram.h"
10: #include "vicon.h"
11:
12: //
13: // TVRAM はワード単位でホストバイトオーダ配置なので、
14: // バイトアクセス時は HB() マクロを使用のこと。
15: //
16:
17: TVRAMDevice *gTVRAM;
18:
19: TVRAMDevice::TVRAMDevice()
20: {
21: logname = "tvram";
22: devname = "TVRAM";
23: devaddr = baseaddr;
24: devlen = 512 * 1024;
25:
26: mem = new uint8[devlen]();
27: }
28:
29: TVRAMDevice::~TVRAMDevice()
30: {
31: if (mem) {
32: delete[] mem;
33: }
34: }
35:
36: void
37: TVRAMDevice::ResetHard()
38: {
39: // XXX ここ?
40: Invalidate();
41: }
42:
43: uint64
44: TVRAMDevice::Read8(uint32 addr)
45: {
46: uint32 offset = addr - baseaddr;
47: return mem[HB(offset)];
48: }
49:
50: uint64
51: TVRAMDevice::Read16(uint32 addr)
52: {
53: uint32 offset = addr - baseaddr;
54: return *(uint16 *)&mem[offset];
55: }
56:
57: uint64
58: TVRAMDevice::Write8(uint32 addr, uint32 data)
59: {
60: uint32 offset = addr - baseaddr;
61:
62: // XXX とりあえずね
63: putlog(3, "Write $%06x <- $%02x", addr, data);
64:
65: if (tvram.sa) {
66: // 同時アクセス
67: uint32 poffset = offset & 0x1ffff;
68: for (int plane = 0; plane < 4; plane++) {
69: if (tvram.ap[plane]) {
70: mem[HB(0x20000 * plane + poffset)] = data;
71: }
72: }
73: } else {
74: // 通常アクセス
75: mem[HB(offset)] = data;
76: }
77: atomic_dirty[(offset % 0x20000) / 128] = 1;
78: return 0;
79: }
80:
81: uint64
82: TVRAMDevice::Write16(uint32 addr, uint32 data)
83: {
84: uint32 offset = addr - baseaddr;
85:
86: // XXX とりあえずね
87: putlog(3, "Write $%06x <- $%04x", addr, data);
88:
89: if (tvram.sa) {
90: // 同時アクセス
91: uint32 poffset = offset & 0x1ffff;
92: for (int plane = 0; plane < 4; plane++) {
93: if (tvram.ap[plane]) {
94: *(uint16 *)&mem[0x20000 * plane + poffset] = data;
95: }
96: }
97: } else {
98: // 通常アクセス
99: *(uint16 *)&mem[offset] = data;
100: }
101: atomic_dirty[(offset % 0x20000) / 128] = 1;
102: return 0;
103: }
104:
105: uint64
106: TVRAMDevice::Peek8(uint32 addr)
107: {
108: return mem[HB(addr - baseaddr)];
109: }
110:
111: // 全画面の更新フラグを立てる
112: void
113: TVRAMDevice::Invalidate()
114: {
115: for (int i = 0; i < 1024; i++) {
116: atomic_dirty[i] = 1;
117: }
118: }
119:
120: // CRTC R21 での同時アクセス設定を反映する
121: // CRTC から呼ばれる
122: void
123: TVRAMDevice::set_crtc_21(uint16 data)
124: {
125: tvram.sa = (data & 0x100);
126: tvram.ap[0] = (data & 0x10);
127: tvram.ap[1] = (data & 0x20);
128: tvram.ap[2] = (data & 0x40);
129: tvram.ap[3] = (data & 0x80);
130:
131: if (0) {
132: if (tvram.sa) {
133: putlog(2, "テキスト画面同時アクセス有効 %c%c%c%c",
134: tvram.ap[0] ? '0' : '-',
135: tvram.ap[1] ? '1' : '-',
136: tvram.ap[2] ? '2' : '-',
137: tvram.ap[3] ? '3' : '-');
138: } else {
139: putlog(2, "テキスト画面同時アクセス無効");
140: }
141: }
142: }
143:
144: // テキスト画面合成
145: bool
146: TVRAMDevice::Render(uint8 *imagebuf)
147: {
148: const uint16 *palette_w;
149: uint8 pal[16][3];
150: const uint16 *plane0;
151: const uint16 *plane1;
152: const uint16 *plane2;
153: const uint16 *plane3;
154: uint8 *dst0;
155: bool updated;
156:
157: dst0 = imagebuf;
158:
159: // パレット取得
160: palette_w = gVicon->GetPalette();
161: // パレット前半 256 ワードはグラフィックパレット、
162: // テキストパレットは後半。
163: palette_w += 0x100;
164:
165: // パレット情報から RGB24 色データを作成
166: // XXX ちょっと輝度は置いとく
167: for (int i = 0; i < 16; i++) {
168: pal[i][0] = ((palette_w[i] >> 6) & 0x1f) << 3; // R
169: pal[i][1] = ((palette_w[i] >> 11)) << 3; // G
170: pal[i][2] = ((palette_w[i] >> 1) & 0x1f) << 3; // B
171: }
172:
173: updated = false;
174:
175: // dirty は VRAM への書き込みがあれば常に 1 にする。
176: // レンダリング時に dirty が 1 なら 2 にしてレンダリング。
177: // レンダリング終了時に dirty が 2 なら 0 に戻す。
178: // これによりレンダリング中に VRAM への書き込みがあれば次回描画される。
179:
180: // sy はメモリ上の Y 座標
181: // dy はレンダラ画面の Y 座標 (CRTC のXXX を考慮)
182: // XXX スクロールは未実装
183:
184: // テキスト画面
185: plane0 = (uint16 *)mem;
186: plane1 = (uint16 *)(mem + 0x20000);
187: plane2 = (uint16 *)(mem + 0x40000);
188: plane3 = (uint16 *)(mem + 0x60000);
189: int sy = 0;
190: for (int dy = 0; dy < 512; dst0 += 768 * Renderer::BPP, dy++, sy++) {
191: sy &= 0x3ff;
192:
193: if (atomic_cas_8(&atomic_dirty[sy], 1, 2) == 1) {
194: uint8 *dst = dst0;
195: // sx はメモリ上の X オフセット (ワード単位)
196: // dx はレンダラ画面の X オフセット (ワード単位)
197:
198: int sx = sy * 1024 / 16;
199: for (int dx = 0; dx < 768 / 16; dx++, sx++) {
200: uint16 t0 = plane0[sx];
201: uint16 t1 = plane1[sx];
202: uint16 t2 = plane2[sx];
203: uint16 t3 = plane3[sx];
204:
205: // 1ワードの 16bit が横 16dot に相当
206: for (int j = 0; j < 16; j++) {
207: uint c = 0;
208: // カラーコード(パレット番号)を作成
209: if ((t0 & 0x8000)) c |= 1;
210: if ((t1 & 0x8000)) c |= 2;
211: if ((t2 & 0x8000)) c |= 4;
212: if ((t3 & 0x8000)) c |= 8;
213: t0 <<= 1;
214: t1 <<= 1;
215: t2 <<= 1;
216: t3 <<= 1;
217:
218: *dst++ = pal[c][0];
219: *dst++ = pal[c][1];
220: *dst++ = pal[c][2];
221: }
222: }
223:
224: // 2の時だけ0に戻す
225: atomic_cas_8(&atomic_dirty[sy], 2, 0);
226: updated = true;
227: }
228: }
229:
230: return updated;
231: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.