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

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: 
1.1.1.2 ! root       17: std::unique_ptr<TVRAMDevice> gTVRAM;
1.1       root       18: 
                     19: TVRAMDevice::TVRAMDevice()
                     20: {
                     21:        logname = "tvram";
                     22:        devname = "TVRAM";
                     23:        devaddr = baseaddr;
                     24:        devlen  = 512 * 1024;
                     25: 
1.1.1.2 ! root       26:        mem.reset(new uint8[devlen]);
1.1       root       27: }
                     28: 
                     29: TVRAMDevice::~TVRAMDevice()
                     30: {
                     31: }
                     32: 
                     33: void
                     34: TVRAMDevice::ResetHard()
                     35: {
                     36:        // XXX ここ?
                     37:        Invalidate();
                     38: }
                     39: 
1.1.1.2 ! root       40: inline uint64
        !            41: TVRAMDevice::Decoder(uint32 addr) const
        !            42: {
        !            43:        return addr - baseaddr;
        !            44: }
        !            45: 
1.1       root       46: uint64
                     47: TVRAMDevice::Read8(uint32 addr)
                     48: {
1.1.1.2 ! root       49:        uint32 offset = Decoder(addr);
1.1       root       50:        return mem[HB(offset)];
                     51: }
                     52: 
                     53: uint64
                     54: TVRAMDevice::Read16(uint32 addr)
                     55: {
1.1.1.2 ! root       56:        uint32 offset = Decoder(addr);
1.1       root       57:        return *(uint16 *)&mem[offset];
                     58: }
                     59: 
                     60: uint64
                     61: TVRAMDevice::Write8(uint32 addr, uint32 data)
                     62: {
1.1.1.2 ! root       63:        uint32 offset = Decoder(addr);
1.1       root       64: 
                     65:        // XXX とりあえずね
                     66:        putlog(3, "Write $%06x <- $%02x", addr, data);
                     67: 
                     68:        if (tvram.sa) {
                     69:                // 同時アクセス
                     70:                uint32 poffset = offset & 0x1ffff;
                     71:                for (int plane = 0; plane < 4; plane++) {
                     72:                        if (tvram.ap[plane]) {
                     73:                                mem[HB(0x20000 * plane + poffset)] = data;
                     74:                        }
                     75:                }
                     76:        } else {
                     77:                // 通常アクセス
                     78:                mem[HB(offset)] = data;
                     79:        }
                     80:        atomic_dirty[(offset % 0x20000) / 128] = 1;
                     81:        return 0;
                     82: }
                     83: 
                     84: uint64
                     85: TVRAMDevice::Write16(uint32 addr, uint32 data)
                     86: {
1.1.1.2 ! root       87:        uint32 offset = Decoder(addr);
1.1       root       88: 
                     89:        // XXX とりあえずね
                     90:        putlog(3, "Write $%06x <- $%04x", addr, data);
                     91: 
                     92:        if (tvram.sa) {
                     93:                // 同時アクセス
                     94:                uint32 poffset = offset & 0x1ffff;
                     95:                for (int plane = 0; plane < 4; plane++) {
                     96:                        if (tvram.ap[plane]) {
                     97:                                *(uint16 *)&mem[0x20000 * plane + poffset] = data;
                     98:                        }
                     99:                }
                    100:        } else {
                    101:                // 通常アクセス
                    102:                *(uint16 *)&mem[offset] = data;
                    103:        }
                    104:        atomic_dirty[(offset % 0x20000) / 128] = 1;
                    105:        return 0;
                    106: }
                    107: 
                    108: uint64
                    109: TVRAMDevice::Peek8(uint32 addr)
                    110: {
1.1.1.2 ! root      111:        uint32 offset = Decoder(addr);
        !           112:        return mem[HB(offset)];
1.1       root      113: }
                    114: 
                    115: // 全画面の更新フラグを立てる
                    116: void
                    117: TVRAMDevice::Invalidate()
                    118: {
                    119:        for (int i = 0; i < 1024; i++) {
                    120:                atomic_dirty[i] = 1;
                    121:        }
                    122: }
                    123: 
                    124: // CRTC R21 での同時アクセス設定を反映する
                    125: // CRTC から呼ばれる
                    126: void
                    127: TVRAMDevice::set_crtc_21(uint16 data)
                    128: {
                    129:        tvram.sa = (data & 0x100);
                    130:        tvram.ap[0] = (data & 0x10);
                    131:        tvram.ap[1] = (data & 0x20);
                    132:        tvram.ap[2] = (data & 0x40);
                    133:        tvram.ap[3] = (data & 0x80);
                    134: 
                    135:        if (0) {
                    136:                if (tvram.sa) {
                    137:                        putlog(2, "テキスト画面同時アクセス有効 %c%c%c%c",
                    138:                                tvram.ap[0] ? '0' : '-',
                    139:                                tvram.ap[1] ? '1' : '-',
                    140:                                tvram.ap[2] ? '2' : '-',
                    141:                                tvram.ap[3] ? '3' : '-');
                    142:                } else {
                    143:                        putlog(2, "テキスト画面同時アクセス無効");
                    144:                }
                    145:        }
                    146: }
                    147: 
                    148: // テキスト画面合成
                    149: bool
                    150: TVRAMDevice::Render(uint8 *imagebuf)
                    151: {
                    152:        const uint16 *palette_w;
                    153:        uint8 pal[16][3];
                    154:        const uint16 *plane0;
                    155:        const uint16 *plane1;
                    156:        const uint16 *plane2;
                    157:        const uint16 *plane3;
                    158:        uint8 *dst0;
                    159:        bool updated;
                    160: 
                    161:        dst0 = imagebuf;
                    162: 
                    163:        // パレット取得
                    164:        palette_w = gVicon->GetPalette();
                    165:        // パレット前半 256 ワードはグラフィックパレット、
                    166:        // テキストパレットは後半。
                    167:        palette_w += 0x100;
                    168: 
                    169:        // パレット情報から RGB24 色データを作成
                    170:        // XXX ちょっと輝度は置いとく
                    171:        for (int i = 0; i < 16; i++) {
                    172:                pal[i][0] = ((palette_w[i] >> 6) & 0x1f) << 3;  // R
                    173:                pal[i][1] = ((palette_w[i] >> 11)) << 3;                // G
                    174:                pal[i][2] = ((palette_w[i] >> 1) & 0x1f) << 3;  // B
                    175:        }
                    176: 
                    177:        updated = false;
                    178: 
                    179:        // dirty は VRAM への書き込みがあれば常に 1 にする。
                    180:        // レンダリング時に dirty が 1 なら 2 にしてレンダリング。
                    181:        // レンダリング終了時に dirty が 2 なら 0 に戻す。
                    182:        // これによりレンダリング中に VRAM への書き込みがあれば次回描画される。
                    183: 
                    184:        // sy はメモリ上の Y 座標
                    185:        // dy はレンダラ画面の Y 座標 (CRTC のXXX を考慮)
                    186:        // XXX スクロールは未実装
                    187: 
                    188:        // テキスト画面
1.1.1.2 ! root      189:        plane0 = (uint16 *)&mem[0x00000];
        !           190:        plane1 = (uint16 *)&mem[0x20000];
        !           191:        plane2 = (uint16 *)&mem[0x40000];
        !           192:        plane3 = (uint16 *)&mem[0x60000];
1.1       root      193:        int sy = 0;
                    194:        for (int dy = 0; dy < 512; dst0 += 768 * Renderer::BPP, dy++, sy++) {
                    195:                sy &= 0x3ff;
                    196: 
                    197:                if (atomic_cas_8(&atomic_dirty[sy], 1, 2) == 1) {
                    198:                        uint8 *dst = dst0;
                    199:                        // sx はメモリ上の X オフセット (ワード単位)
                    200:                        // dx はレンダラ画面の X オフセット (ワード単位)
                    201: 
                    202:                        int sx = sy * 1024 / 16;
                    203:                        for (int dx = 0; dx < 768 / 16; dx++, sx++) {
                    204:                                uint16 t0 = plane0[sx];
                    205:                                uint16 t1 = plane1[sx];
                    206:                                uint16 t2 = plane2[sx];
                    207:                                uint16 t3 = plane3[sx];
                    208: 
                    209:                                // 1ワードの 16bit が横 16dot に相当
                    210:                                for (int j = 0; j < 16; j++) {
                    211:                                        uint c = 0;
                    212:                                        // カラーコード(パレット番号)を作成
                    213:                                        if ((t0 & 0x8000)) c |= 1;
                    214:                                        if ((t1 & 0x8000)) c |= 2;
                    215:                                        if ((t2 & 0x8000)) c |= 4;
                    216:                                        if ((t3 & 0x8000)) c |= 8;
                    217:                                        t0 <<= 1;
                    218:                                        t1 <<= 1;
                    219:                                        t2 <<= 1;
                    220:                                        t3 <<= 1;
                    221: 
                    222:                                        *dst++ = pal[c][0];
                    223:                                        *dst++ = pal[c][1];
                    224:                                        *dst++ = pal[c][2];
                    225:                                }
                    226:                        }
                    227: 
                    228:                        // 2の時だけ0に戻す
                    229:                        atomic_cas_8(&atomic_dirty[sy], 2, 0);
                    230:                        updated = true;
                    231:                }
                    232:        }
                    233: 
                    234:        return updated;
                    235: }

unix.superglobalmegacorp.com

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