|
|
1.1 root 1: //
2: // nono
3: // Copyright (C) 2020 nono project
4: // Licensed under nono-license.txt
5: //
6:
7: #include "videoctlr.h"
1.1.1.3 root 8: #include "mpu.h"
1.1 root 9:
10: // e82000..e823ff パレット
11: // e82400..e824ff R0(e82400.w) のミラー
12: // e82500..e825ff R1(e82500.w) のミラー
13: // e82600..e826ff R2(e82600.w) のミラー
14: // e82700..e82fff $00 が読めるようだ
15: // 以上の 4KB をミラー。
16:
17: std::unique_ptr<VideoCtlrDevice> gVideoCtlr;
18:
19: VideoCtlrDevice::VideoCtlrDevice()
1.1.1.5 ! root 20: : inherited("VideoCtlr")
1.1 root 21: {
22: devaddr = baseaddr;
23: devlen = 0x2000;
24: }
25:
26: VideoCtlrDevice::~VideoCtlrDevice()
27: {
28: }
29:
1.1.1.3 root 30: void
31: VideoCtlrDevice::ResetHard()
32: {
33: // XXX not yet
34: }
35:
1.1.1.4 root 36: // offset は何ワード目のポートかという意味になるので
37: // $E82002 が offset=1 (番目のワード)。
1.1 root 38: uint64
1.1.1.4 root 39: VideoCtlrDevice::Read(uint32 offset)
1.1 root 40: {
41: uint32 data;
42:
1.1.1.3 root 43: gMPU->AddCycle(9); // InsideOut p.135
44:
1.1.1.4 root 45: if (offset < 0x400 / 2) { // パレット
46: data = palette.w[offset];
1.1 root 47:
1.1.1.4 root 48: } else if (offset < 0x500 / 2) { // $E82400 (R0)
1.1 root 49: data = videoctlr.r0;
50:
1.1.1.4 root 51: } else if (offset < 0x600 / 2) { // $E82500 (R1)
1.1 root 52: data = videoctlr.r1;
53:
1.1.1.4 root 54: } else if (offset < 0x700 / 2) { // $E82600 (R2)
1.1 root 55: data = videoctlr.r2;
56:
1.1.1.4 root 57: } else { // それ以降は $00 が読めるようだ
1.1 root 58: data = 0;
59: }
60:
61: return data;
62: }
63:
64: uint64
1.1.1.4 root 65: VideoCtlrDevice::Write(uint32 offset, uint32 data)
1.1 root 66: {
1.1.1.3 root 67: gMPU->AddCycle(11); // InsideOut p.135
68:
1.1.1.4 root 69: if (offset < 0x400 / 2) { // パレット
70: putlog(3, "パレット $%06x.W <- $%04x", baseaddr + offset * 2, data);
71: palette.w[offset] = data;
1.1.1.2 root 72: MakePalette();
1.1 root 73:
1.1.1.4 root 74: } else if (offset < 0x500 / 2) { // $E82400 (R0)
1.1 root 75: SetR0(data);
76:
1.1.1.4 root 77: } else if (offset < 0x600 / 2) { // $E82500 (R1)
1.1 root 78: SetR1(data);
79:
1.1.1.4 root 80: } else if (offset < 0x700 / 2) { // $E82600 (R2)
1.1 root 81: SetR2(data);
82:
1.1.1.4 root 83: } else { // それ以降はたぶん何も起きない?
1.1 root 84: }
85:
86: return 0;
87: }
88:
89: uint64
1.1.1.4 root 90: VideoCtlrDevice::Peek(uint32 offset)
1.1 root 91: {
92: uint32 data;
93:
1.1.1.4 root 94: if (offset < 0x400 / 2) { // パレット
95: data = palette.w[offset];
1.1 root 96:
1.1.1.4 root 97: } else if (offset < 0x500 / 2) { // $E82400 (R0)
1.1 root 98: data = videoctlr.r0;
99:
1.1.1.4 root 100: } else if (offset < 0x600 / 2) { // $E82500 (R1)
1.1 root 101: data = videoctlr.r1;
102:
1.1.1.4 root 103: } else if (offset < 0x700 / 2) { // $E82600 (R2)
1.1 root 104: data = videoctlr.r2;
105:
1.1.1.4 root 106: } else { // それ以降は $00 が読めるようだ
1.1 root 107: data = 0;
108: }
109:
110: return data;
111: }
112:
113: // R0 への書き込み
114: void
115: VideoCtlrDevice::SetR0(uint32 data)
116: {
117: putlog(0, "R0 <- $%04x 未実装書き込み", data);
118: videoctlr.r0 = data & 3;
119: }
120:
121: // R1 への書き込み
122: void
123: VideoCtlrDevice::SetR1(uint32 data)
124: {
125: putlog(0, "R1 <- $%04x 未実装書き込み", data);
126: videoctlr.r1 = data & 0x3fff;
127: }
128:
129: // R2 への書き込み
130: void
131: VideoCtlrDevice::SetR2(uint32 data)
132: {
133: putlog(0, "R2 <- $%04x 未実装書き込み", data);
134: videoctlr.r2 = (data & 0xff7f);
135: }
1.1.1.2 root 136:
137: //
138: void
139: VideoCtlrDevice::MakePalette()
140: {
141: const uint16 *p;
142:
143: // パレット前半 256 ワードはグラフィックパレット、
144: // テキストパレットは後半。
145: p = &palette.w[256];
146:
147: // パレット情報から xBGR32 形式の色データを作成
148: // X680x0 のパレットは %GGGGG'RRRRR'BBBBB'I で並んでいる。
149: for (int i = 0; i < 16; i++) {
150: int I = (p[i] & 1) << 2; // 輝度ビット
151: int R = (((p[i] >> 6) & 0x1f) << 3) + I;
152: int G = (((p[i] >> 11)) << 3) + I;
153: int B = (((p[i] >> 1) & 0x1f) << 3) + I;
154: cooked_palette[i] = R | (G << 8) | (B << 16);
155: }
156: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.