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

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: 
1.1.1.7 ! root       11: // TVRAM (PlaneVRAM) はロングワード単位でホストバイトオーダ配置なので、
        !            12: // バイトアクセス時は HLB()、ワードアクセス時は HLW() マクロを使用のこと。
        !            13: 
1.1       root       14: #include "tvram.h"
1.1.1.7 ! root       15: #include "mpu.h"
1.1.1.3   root       16: #include "videoctlr.h"
1.1       root       17: 
1.1.1.7 ! root       18: // コンストラクタ
1.1       root       19: TVRAMDevice::TVRAMDevice()
1.1.1.7 ! root       20:        : inherited("TVRAM", 1024, 1024)
1.1       root       21: {
                     22:        devaddr = baseaddr;
                     23:        devlen  = 512 * 1024;
                     24: 
1.1.1.7 ! root       25:        // プレーン数は4枚固定
        !            26:        nplane = NPLANE;
1.1.1.4   root       27: 
1.1.1.7 ! root       28:        modify_mask = 0xff00;
        !            29: 
        !            30:        mem.reset(new uint8[devlen]);
1.1       root       31: }
                     32: 
1.1.1.7 ! root       33: // デストラクタ
1.1       root       34: TVRAMDevice::~TVRAMDevice()
                     35: {
                     36: }
                     37: 
1.1.1.7 ! root       38: bool
        !            39: TVRAMDevice::Init()
        !            40: {
        !            41:        // 加工済みパレットを取得
        !            42:        palette = gVideoCtlr->GetHostPalette();
        !            43: 
        !            44:        return true;
        !            45: }
        !            46: 
        !            47: // リセット
1.1       root       48: void
1.1.1.7 ! root       49: TVRAMDevice::ResetHard(bool poweron)
1.1       root       50: {
                     51:        // XXX ここ?
                     52:        Invalidate();
                     53: }
                     54: 
1.1.1.2   root       55: inline uint64
                     56: TVRAMDevice::Decoder(uint32 addr) const
                     57: {
                     58:        return addr - baseaddr;
                     59: }
                     60: 
1.1       root       61: uint64
                     62: TVRAMDevice::Read8(uint32 addr)
                     63: {
1.1.1.5   root       64:        gMPU->AddCycle(9);      // Inside/Out p.135
1.1.1.2   root       65:        uint32 offset = Decoder(addr);
1.1.1.7 ! root       66:        return mem[HLB(offset)];
1.1       root       67: }
                     68: 
                     69: uint64
                     70: TVRAMDevice::Read16(uint32 addr)
                     71: {
1.1.1.5   root       72:        gMPU->AddCycle(9);      // Inside/Out p.135
1.1.1.2   root       73:        uint32 offset = Decoder(addr);
1.1.1.7 ! root       74:        return *(uint16 *)&mem[HLW(offset)];
1.1       root       75: }
                     76: 
                     77: uint64
                     78: TVRAMDevice::Write8(uint32 addr, uint32 data)
                     79: {
1.1.1.2   root       80:        uint32 offset = Decoder(addr);
1.1.1.7 ! root       81:        uint8 *ptr;
        !            82:        uint8 mask8;
1.1       root       83: 
1.1.1.5   root       84:        gMPU->AddCycle(9);      // Inside/Out p.135
                     85: 
1.1       root       86:        // XXX とりあえずね
                     87:        putlog(3, "Write $%06x <- $%02x", addr, data);
                     88: 
1.1.1.7 ! root       89:        if (tvram.men) {
        !            90:                if ((addr & 1) == 0) {
        !            91:                        mask8 = tvram.mask >> 8;
        !            92:                } else {
        !            93:                        mask8 = tvram.mask;
        !            94:                }
        !            95:        } else {
        !            96:                mask8 = 0;
        !            97:        }
        !            98: 
1.1       root       99:        if (tvram.sa) {
                    100:                // 同時アクセス
                    101:                uint32 poffset = offset & 0x1ffff;
                    102:                for (int plane = 0; plane < 4; plane++) {
                    103:                        if (tvram.ap[plane]) {
1.1.1.7 ! root      104:                                ptr = &mem[HLB(0x20000 * plane + poffset)];
        !           105:                                *ptr = (data & ~mask8) | (*ptr & mask8);
1.1       root      106:                        }
                    107:                }
                    108:        } else {
                    109:                // 通常アクセス
1.1.1.7 ! root      110:                ptr = &mem[HLB(offset)];
        !           111:                *ptr = (data & ~mask8) | (*ptr & mask8);
1.1       root      112:        }
1.1.1.7 ! root      113:        SetDirty(offset);
1.1       root      114:        return 0;
                    115: }
                    116: 
                    117: uint64
                    118: TVRAMDevice::Write16(uint32 addr, uint32 data)
                    119: {
1.1.1.2   root      120:        uint32 offset = Decoder(addr);
1.1.1.7 ! root      121:        uint16 *ptr;
        !           122:        uint16 mask16;
1.1       root      123: 
1.1.1.5   root      124:        gMPU->AddCycle(9);      // Inside/Out p.135
                    125: 
1.1       root      126:        // XXX とりあえずね
                    127:        putlog(3, "Write $%06x <- $%04x", addr, data);
                    128: 
1.1.1.7 ! root      129:        if (tvram.men) {
        !           130:                mask16 = tvram.mask;
        !           131:        } else {
        !           132:                mask16 = 0;
        !           133:        }
        !           134: 
1.1       root      135:        if (tvram.sa) {
                    136:                // 同時アクセス
                    137:                uint32 poffset = offset & 0x1ffff;
                    138:                for (int plane = 0; plane < 4; plane++) {
                    139:                        if (tvram.ap[plane]) {
1.1.1.7 ! root      140:                                ptr = (uint16 *)&mem[HLW(0x20000 * plane + poffset)];
        !           141:                                *ptr = (data & ~mask16) | (*ptr & mask16);
1.1       root      142:                        }
                    143:                }
                    144:        } else {
                    145:                // 通常アクセス
1.1.1.7 ! root      146:                ptr = (uint16 *)&mem[HLW(offset)];
        !           147:                *ptr = (data & ~mask16) | (*ptr & mask16);
1.1       root      148:        }
1.1.1.7 ! root      149:        SetDirty(offset);
1.1       root      150:        return 0;
                    151: }
                    152: 
                    153: uint64
                    154: TVRAMDevice::Peek8(uint32 addr)
                    155: {
1.1.1.2   root      156:        uint32 offset = Decoder(addr);
1.1.1.7 ! root      157:        return mem[HLB(offset)];
1.1       root      158: }
                    159: 
1.1.1.7 ! root      160: // offset の位置に対応する更新フラグを立てる。
        !           161: // offset は TVRAM 先頭からのバイトオフセット (プレーン先頭からではない)。
        !           162: inline void
        !           163: TVRAMDevice::SetDirty(uint32 offset)
        !           164: {
        !           165:        // VRAM は横 1024 ドット(128バイト) x 縦 1024 ドットで、これを
        !           166:        // 横 128 ドット(16バイト) x 縦 16 ドットずつのブロックに分割する。
        !           167:        // ブロック数は横 8個 x 縦 64個。
        !           168:        //
        !           169:        //              1                               0
        !           170:        //        3 2 1 0 f e d c b a 9 8 7 6 5 4 3 2 1 0
        !           171:        //       +-----------+-------+-----+-------+-----+
        !           172:        // VRAM  |  Y座標 (1024dot)  | X (128byte) : 8bit|
        !           173:        //       +-----------+-------+-----+-------+-----+
        !           174:        //       :           :       :     :             :
        !           175:        //       +-----------+-------+-----+-------------+
        !           176:        // Block | Y(64blks) | 16dot | X(8)|   128 dot   | *: X は 8 blocks
        !           177:        //       +-----------+-------+-----+-------------+
        !           178:        //        \          \     |     |
        !           179:        //          \          \   |     |
        !           180:        //            \          \ |     |
        !           181:        //               +-----------+-----+
        !           182:        // Dirty         | Y(64blks) | X(8)|
        !           183:        //               +-----------+-----+
        !           184:        //                8 7 6 5 4 3 2 1 0
        !           185: 
        !           186:        // x 座標(バイト単位 7 bit)の上位 3 bit
        !           187:        int x = (offset >> 4) & 0x07;
        !           188:        // y 座標(10bit) の上位 6 bit
        !           189:        int y = (offset >> 8) & 0x1f8;
        !           190: 
        !           191:        // からインデックスを求める
        !           192:        int b = x + y;
        !           193: 
        !           194:        dirty[b] = 1;
        !           195: 
        !           196: #if defined(PERF_HIT)
        !           197:        // どのロングワードが更新されたか
        !           198:        dirty_word[(offset & 0x1ffff) >> 2] = true;
        !           199: #endif
1.1       root      200: }
                    201: 
1.1.1.3   root      202: void
                    203: TVRAMDevice::SetScrollX(int x)
                    204: {
1.1.1.7 ! root      205:        xscroll = x;
1.1.1.3   root      206: }
                    207: 
                    208: void
                    209: TVRAMDevice::SetScrollY(int y)
                    210: {
1.1.1.7 ! root      211:        yscroll = y;
        !           212:        gRenderer->Invalidate2();
1.1.1.3   root      213: }
                    214: 
1.1.1.7 ! root      215: // CRTC R21 での同時アクセス設定を反映する。
        !           216: // CRTC から呼ばれる。
1.1       root      217: void
1.1.1.7 ! root      218: TVRAMDevice::SetAccessPlane(uint16 data)
1.1       root      219: {
1.1.1.7 ! root      220:        tvram.cp[0] = (data & 0x01);
        !           221:        tvram.cp[1] = (data & 0x02);
        !           222:        tvram.cp[2] = (data & 0x04);
        !           223:        tvram.cp[3] = (data & 0x08);
1.1       root      224:        tvram.ap[0] = (data & 0x10);
                    225:        tvram.ap[1] = (data & 0x20);
                    226:        tvram.ap[2] = (data & 0x40);
                    227:        tvram.ap[3] = (data & 0x80);
1.1.1.7 ! root      228:        tvram.sa = (data & 0x100);
        !           229:        tvram.men = (data & 0x200);
1.1       root      230: 
                    231:        if (0) {
                    232:                if (tvram.sa) {
                    233:                        putlog(2, "テキスト画面同時アクセス有効 %c%c%c%c",
                    234:                                tvram.ap[0] ? '0' : '-',
                    235:                                tvram.ap[1] ? '1' : '-',
                    236:                                tvram.ap[2] ? '2' : '-',
                    237:                                tvram.ap[3] ? '3' : '-');
                    238:                } else {
                    239:                        putlog(2, "テキスト画面同時アクセス無効");
                    240:                }
                    241:        }
                    242: }
                    243: 
1.1.1.7 ! root      244: // CRTC R23 でのアクセスマスク設定を反映する。
        !           245: // CRTC から呼ばれる。
        !           246: void
        !           247: TVRAMDevice::SetAccessMask(uint16 data)
1.1       root      248: {
1.1.1.7 ! root      249:        tvram.mask = data;
        !           250: }
1.1.1.4   root      251: 
1.1.1.7 ! root      252: // ラスターコピーを開始する。
        !           253: // XXX 今の所コピー中という期間は存在せず一瞬で終わる
        !           254: // src_ras, dst_ras はライン番号 (レジスタ設定値を4倍したもの)。
        !           255: void
        !           256: TVRAMDevice::RasterCopy(int src_ras, int dst_ras)
        !           257: {
        !           258:        for (int plane = 0; plane < 4; plane++) {
        !           259:                if (tvram.cp[plane]) {
        !           260:                        uint8 *src = &mem[HLW(0x20000 * plane + src_ras * 128)];
        !           261:                        uint8 *dst = &mem[HLW(0x20000 * plane + dst_ras * 128)];
        !           262:                        memcpy(dst, src, 128 * 4);
1.1       root      263:                }
                    264:        }
                    265: 
1.1.1.7 ! root      266:        // dst からの4ラインを全部 dirty にする
        !           267:        for (int i = 0; i < 4; i++) {
        !           268:                int y = dst_ras + i;
        !           269:                // PERF_HIT の更新もあるので律儀に全ロングバイト分ループする
        !           270:                for (int x = 0; x < 128 / sizeof(uint32); x++) {
        !           271:                        SetDirty(y * 128 + x * 4);
        !           272:                }
        !           273:        }
1.1       root      274: }

unix.superglobalmegacorp.com

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