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

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

unix.superglobalmegacorp.com

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