|
|
1.1 root 1: //
2: // nono
3: // Copyright (C) 2020 nono project
4: // Licensed under nono-license.txt
5: //
6:
1.1.1.6 root 7: //
8: // ビデオコントローラ
9: //
1.1 root 10:
11: // e82000..e823ff パレット
12: // e82400..e824ff R0(e82400.w) のミラー
13: // e82500..e825ff R1(e82500.w) のミラー
14: // e82600..e826ff R2(e82600.w) のミラー
15: // e82700..e82fff $00 が読めるようだ
16: // 以上の 4KB をミラー。
17:
1.1.1.6 root 18: #include "videoctlr.h"
19: #include "mpu.h"
1.1.1.7 root 20: #include "renderer.h"
21: #include "uimessage.h"
1.1 root 22:
1.1.1.6 root 23: // コンストラクタ
1.1 root 24: VideoCtlrDevice::VideoCtlrDevice()
1.1.1.8 ! root 25: : inherited(OBJ_VIDEOCTLR)
1.1 root 26: {
1.1.1.8 ! root 27: hostcolor.resize(16);
1.1 root 28: }
29:
1.1.1.6 root 30: // デストラクタ
1.1 root 31: VideoCtlrDevice::~VideoCtlrDevice()
32: {
1.1.1.8 ! root 33: }
! 34:
! 35: // 初期化
! 36: bool
! 37: VideoCtlrDevice::Init()
! 38: {
! 39: if (inherited::Init() == false) {
! 40: return false;
! 41: }
! 42:
! 43: renderer = GetRenderer();
! 44:
! 45: return true;
1.1 root 46: }
47:
1.1.1.6 root 48: // リセット
1.1.1.3 root 49: void
1.1.1.6 root 50: VideoCtlrDevice::ResetHard(bool poweron)
1.1.1.3 root 51: {
52: // XXX not yet
53: }
54:
1.1.1.8 ! root 55: inline uint32
! 56: VideoCtlrDevice::Decoder(uint32 addr) const
! 57: {
! 58: return addr & 0xfff;
! 59: }
! 60:
1.1 root 61: uint64
1.1.1.8 ! root 62: VideoCtlrDevice::Read8(uint32 addr)
1.1 root 63: {
64: uint32 data;
65:
1.1.1.8 ! root 66: mpu->AddCycle(9); // InsideOut p.135
1.1.1.3 root 67:
1.1.1.8 ! root 68: uint32 offset = Decoder(addr);
! 69: if (offset < 0x400) { // パレット
! 70: data = palette[HB(offset)];
! 71: putlog(3, "Palette $%06x.B -> $%02x", addr, data);
! 72:
! 73: } else if (offset < 0x700) { // R0,R1,R2
! 74: uint nr = Offset2NR(offset);
! 75: data = GetNR(nr);
! 76: putlog(3, "R%d.%c -> $%02x",
! 77: (nr / 2),
! 78: (nr % 2) == 0 ? 'H' : 'L',
! 79: data);
1.1 root 80:
1.1.1.8 ! root 81: } else {
! 82: data = 0;
! 83: }
1.1 root 84:
1.1.1.8 ! root 85: return data;
! 86: }
! 87:
! 88: uint64
! 89: VideoCtlrDevice::Read16(uint32 addr)
! 90: {
! 91: uint32 data;
1.1 root 92:
1.1.1.8 ! root 93: mpu->AddCycle(9); // InsideOut p.135
1.1 root 94:
1.1.1.8 ! root 95: uint32 offset = Decoder(addr);
! 96: if (offset < 0x400) { // パレット
! 97: data = *(uint16 *)&palette[offset];
! 98: putlog(3, "Palette $%06x.W -> $%04x", addr, data);
! 99:
! 100: } else if (offset < 0x700) { // R0,R1,R2
! 101: uint nr = Offset2NR(offset);
! 102: data = GetNR(nr) << 8;
! 103: data |= GetNR(nr + 1);
! 104: putlog(3, "R%d -> $%04x", (nr / 2), data);
! 105:
! 106: } else {
1.1 root 107: data = 0;
108: }
109:
110: return data;
111: }
112:
113: uint64
1.1.1.8 ! root 114: VideoCtlrDevice::Write8(uint32 addr, uint32 data)
1.1 root 115: {
1.1.1.8 ! root 116: mpu->AddCycle(11); // InsideOut p.135
1.1.1.3 root 117:
1.1.1.8 ! root 118: uint32 offset = Decoder(addr);
! 119: if (offset < 0x400) { // パレット
! 120: putlog(2, "Palette $%06x.B <- $%02x", addr, data);
! 121: palette[HB(offset)] = data;
1.1.1.2 root 122: MakePalette();
1.1 root 123:
1.1.1.8 ! root 124: } else if (offset < 0x700) { // R0,R1,R2
! 125: uint nr = Offset2NR(offset);
! 126: putlog(2, "R%d.%c <- $%02x (NOT IMPLEMENTED)",
! 127: (nr / 2),
! 128: (nr % 2) == 0 ? 'H' : 'L',
! 129: data);
! 130: SetNR(nr, data);
1.1 root 131:
1.1.1.8 ! root 132: } else {
! 133: // たぶん何も起きない?
1.1 root 134: }
135:
136: return 0;
137: }
138:
139: uint64
1.1.1.8 ! root 140: VideoCtlrDevice::Write16(uint32 addr, uint32 data)
1.1 root 141: {
1.1.1.8 ! root 142: mpu->AddCycle(11); // InsideOut p.135
! 143:
! 144: uint32 offset = Decoder(addr);
! 145: if (offset < 0x400) { // パレット
! 146: putlog(2, "Palette $%06x.W <- $%04x", addr, data);
! 147: *(uint16 *)&palette[offset] = data;
! 148: MakePalette();
1.1 root 149:
1.1.1.8 ! root 150: } else if (offset < 0x700) { // R0,R1,R2
! 151: uint nr = Offset2NR(offset);
! 152: putlog(3, "R%d <- $%04x (NOT IMPLEMENTED)", (nr / 2), data);
! 153: SetNR(nr, data >> 8);
! 154: SetNR(nr + 1, data & 0xff);
1.1 root 155:
1.1.1.8 ! root 156: } else {
! 157: // たぶん何も起きない?
! 158: }
1.1 root 159:
1.1.1.8 ! root 160: return 0;
! 161: }
1.1 root 162:
1.1.1.8 ! root 163: uint64
! 164: VideoCtlrDevice::Peek8(uint32 addr)
! 165: {
! 166: uint32 offset = Decoder(addr);
! 167: if (offset < 0x400) { // パレット
! 168: return palette[HB(offset)];
! 169:
! 170: } else if (offset < 0x700) { // R0,R1,R2
! 171: uint nr = Offset2NR(offset);
! 172: return GetNR(nr);
1.1 root 173:
1.1.1.8 ! root 174: } else {
! 175: return 0x00;
1.1 root 176: }
1.1.1.8 ! root 177: }
1.1 root 178:
1.1.1.8 ! root 179: uint64
! 180: VideoCtlrDevice::Poke8(uint32 addr, uint32 data)
! 181: {
! 182: uint32 offset = Decoder(addr);
! 183: if (offset < 0x400) {
! 184: if ((int32)data >= 0) {
! 185: palette[HB(offset)] = data;
! 186: // Poke による編集でもパレットに反映させる
! 187: MakePalette();
! 188: }
! 189: return 0;
! 190: }
! 191:
! 192: return -1;
1.1 root 193: }
194:
1.1.1.8 ! root 195: // R0, R1, R2 のオフセットから内部仮想レジスタ番号 NR0-NR5 に変換する。
! 196: // offset は R0, R1, R2 の領域を指していること。
! 197: inline uint
! 198: VideoCtlrDevice::Offset2NR(uint32 offset) const
1.1 root 199: {
1.1.1.8 ! root 200: assert(0x400 <= offset && offset < 0x700);
! 201: return ((offset / 0x100) - 4) * 2 + (offset & 1);
1.1 root 202: }
203:
1.1.1.8 ! root 204: // 内部仮想レジスタ NR0-NR5 を読み出す。
! 205: uint32
! 206: VideoCtlrDevice::GetNR(uint reg) const
1.1 root 207: {
1.1.1.8 ! root 208: return nreg[reg];
1.1 root 209: }
210:
1.1.1.8 ! root 211: // 内部仮想レジスタ NR0-NR5 にバイトデータを書き込む。
1.1 root 212: void
1.1.1.8 ! root 213: VideoCtlrDevice::SetNR(uint reg, uint32 data)
1.1 root 214: {
1.1.1.8 ! root 215: // XXX まだ値を保存する以外何もしていない
! 216: assert(reg < 6);
! 217: switch (reg) {
! 218: case 0: // R0.H
! 219: nreg[reg] = 0;
! 220: break;
! 221: case 1: // R0.L
! 222: nreg[reg] = data & 0x03;
! 223: break;
! 224:
! 225: case 2: // R1.H
! 226: nreg[reg] = data & 0x3f;
! 227: break;
! 228: case 3: // R1.L
! 229: nreg[reg] = data & 0xff;
! 230: break;
! 231:
! 232: case 4: // R2.H
! 233: nreg[reg] = data & 0xff;
! 234: break;
! 235: case 5: // R2.L
! 236: nreg[reg] = data & 0x7f;
! 237: break;
! 238:
! 239: default:
! 240: __unreachable();
! 241: }
1.1 root 242: }
1.1.1.2 root 243:
244: //
245: void
246: VideoCtlrDevice::MakePalette()
247: {
248: const uint16 *p;
249:
250: // パレット前半 256 ワードはグラフィックパレット、
251: // テキストパレットは後半。
1.1.1.8 ! root 252: p = (uint16 *)&palette[512];
1.1.1.2 root 253:
1.1.1.6 root 254: // パレット情報から Color 形式の色データを作成
1.1.1.2 root 255: // X680x0 のパレットは %GGGGG'RRRRR'BBBBB'I で並んでいる。
256: for (int i = 0; i < 16; i++) {
257: int I = (p[i] & 1) << 2; // 輝度ビット
258: int R = (((p[i] >> 6) & 0x1f) << 3) + I;
259: int G = (((p[i] >> 11)) << 3) + I;
260: int B = (((p[i] >> 1) & 0x1f) << 3) + I;
1.1.1.8 ! root 261: hostcolor[i].r = R;
! 262: hostcolor[i].g = G;
! 263: hostcolor[i].b = B;
1.1.1.2 root 264: }
1.1.1.6 root 265:
1.1.1.7 root 266: // パレット変更が起きたことをレンダラに通知
1.1.1.8 ! root 267: renderer->Invalidate2();
1.1.1.7 root 268:
269: // UI にも通知
270: UIMessage::Post(UIMessage::PALETTE);
1.1.1.2 root 271: }
1.1.1.8 ! root 272:
! 273: // ゲストパレットを uint32 形式にしたものの一覧を返す。(GUI 用)
! 274: // XXX 今の所テキスト16色しか考えてない
! 275: const std::vector<uint32>
! 276: VideoCtlrDevice::GetIntPalette() const
! 277: {
! 278: std::vector<uint32> ipal;
! 279: const uint16 *p = (const uint16 *)&palette[0];
! 280:
! 281: for (int i = 0; i < 16; i++) {
! 282: ipal.push_back(p[256 + i]);
! 283: }
! 284: return ipal;
! 285: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.