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