Annotation of nono/vm/tvram.cpp, revision 1.1.1.1

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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.