Annotation of nono/vm/tvram.cpp, revision 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.