|
|
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.