|
|
1.1 root 1: //
2: // nono
3: // Copyright (C) 2017 [email protected]
4: //
5:
6: #include "crtc.h"
7: #include "mfp.h"
8: #include "renderer.h"
9: #include "tvram.h"
10:
11: CRTCDevice::CRTCDevice()
12: {
13: logname = "crtc";
14: devname = "CRTC";
15: devaddr = 0xe80000;
16: devlen = 0x2000;
17:
18: vdisp_event.dev = this;
19: vdisp_event.func = (DeviceCallback_t)&CRTCDevice::VDispCallback;
20: vdisp_event.name = "CRTC V-DISP";
21: }
22:
23: CRTCDevice::~CRTCDevice()
24: {
25: }
26:
27: void
28: CRTCDevice::ResetHard()
29: {
30: // XXX 初期値適当
31: crtc.r[20] = 0x0016;
32:
33: // XXX 適当
34: // すぐに垂直帰線期間を開始する
35: vdisp_event.time = 0;
36: vdisp_event.code = 1;
37: gScheduler->AddEvent(&vdisp_event);
38: }
39:
40: uint64
41: CRTCDevice::Read8(uint32 addr)
42: {
43: uint32 an = (addr - devaddr) / 2;
44: uint16 data;
45:
46: switch (an) {
47: case CRTC::R00 ... CRTC::R23:
48: data = crtc.r[an];
49: if ((addr & 1) == 0) {
50: data >>= 8;
51: putlog(2, "R%02d(H) -> $%02x", an, data);
52: } else {
53: data &= 0xff;
54: putlog(2, "R%02d(L) -> $%02x", an, data);
55: }
56: break;
57:
58: case CRTC::REG_OP: // $E80480
59: data = crtc.op;
60: if ((addr & 1) == 0) {
61: data >>= 8;
62: putlog(2, "$E80480 -> $%02x", data);
63: } else {
64: data &= 0xff;
65: putlog(2, "$E80481 -> $%02x", data);
66: }
67: break;
68:
69: default:
70: putlog(1, "Read8 $%06x 未実装ポート読み込み", addr);
71: data = 0xff;
72: }
73:
74: return data;
75: }
76:
77: uint64
78: CRTCDevice::Read16(uint32 addr)
79: {
80: uint32 an = (addr - devaddr) / 2;
81: uint16 data;
82:
83: switch (an) {
84: case CRTC::R00 ... CRTC::R23:
85: data = crtc.r[an];
86: putlog(2, "R%02d -> $%04x", an, data);
87: return data;
88:
89: default:
90: putlog(1, "$%06x 未実装読み込み", addr);
91: return 0;
92: }
93: }
94:
95: uint64
96: CRTCDevice::Write8(uint32 addr, uint32 data)
97: {
98: uint32 an = (addr - devaddr) / 2;
99:
100: switch (an) {
101: case CRTC::R00 ... CRTC::R23:
102: // 16ビットにしてから書き込む
103: if((addr & 1) == 0) {
104: data = (data << 8) | (crtc.r[an] & 0x00ff);
105: putlog(2, "R%02d(H) = $%04x", an, data);
106: } else {
107: data = (data & 0xff) | (crtc.r[an] & 0xff00);
108: putlog(2, "R%02d(L) = $%04x", an, data);
109: }
110: WriteReg(an, data);
111: break;
112:
113: case CRTC::REG_OP:
114: // 下位8ビットのみ有効
115: if ((addr & 1) == 1) {
116: putlog(2, "$E80481 <- $%02x", data);
117: crtc.op = data & 0x0b;
118: }
119: break;
120:
121: default:
122: putlog(1, "Write8 $%06x <- $%02x 未実装書き込み", addr, data);
123: break;
124: }
125: return 0;
126: }
127:
128: uint64
129: CRTCDevice::Write16(uint32 addr, uint32 data)
130: {
131: uint32 an = (addr - devaddr) / 2;
132:
133: switch (an) {
134: case CRTC::R00 ... CRTC::R23:
135: putlog(2, "R%02d <- $%04x", an, data);
136: WriteReg(an, data);
137: break;
138:
139: case CRTC::REG_OP:
140: putlog(2, "$E80481 <- $%02x", data);
141: crtc.op = data & 0x0b;
142: break;
143:
144: default:
145: putlog(1, "$%06x <- $%04x 未実装書き込み", addr, data);
146: break;
147: }
148: return 0;
149: }
150:
151: // Write8/16 の下請け。内部アクセス用
152: // offset は CRTC::R00 .. CRTC::R23
153: void
154: CRTCDevice::WriteReg(uint32 reg, uint32 data)
155: {
156: crtc.r[reg] = data;
157:
158: switch (reg) {
159: case CRTC::R21:
160: gTVRAM->set_crtc_21(crtc.r[21]);
161: break;
162: }
163: }
164:
165: uint64
166: CRTCDevice::Peek8(uint32 addr)
167: {
168: uint32 an2 = addr - devaddr;
169:
170: switch (an2) {
171: case CRTC::R00 ... (CRTC::R23 * 2):
172: if ((an2 & 1) == 0) {
173: return crtc.r[an2 / 2] >> 8;
174: } else {
175: return crtc.r[an2 / 2] & 0xff;
176: }
177: break;
178:
179: case CRTC::REG_OP * 2 + 1:
180: return crtc.op;
181:
182: default:
183: return 0xff;
184: }
185: }
186:
187: // 垂直表示・帰線イベント
188: // arg == 1 なら表示期間開始、arg == 0 なら帰線期間開始。
189: void
190: CRTCDevice::VDispCallback(int arg)
191: {
192: // GPIP の状態を更新
193: gMFP->SetVDisp(arg);
194:
195: // 今はここで1画面まるごと作成
196: if (arg) {
197: // Render に作画指示
198: gRenderer->Render();
199: }
200:
201: // 次のタイミングを計算
202: // XXX まだ CRTC から計算していない
203: if (arg) {
204: // 垂直表示期間
205: vdisp_event.time = 16250_usec;
206: } else {
207: // 垂直帰線期間
208: vdisp_event.time = 1778_usec;
209: }
210: vdisp_event.code = 1 - arg;
211: gScheduler->AddEvent(&vdisp_event);
212: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.