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

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.12  root       15: #include "textscreen.h"
1.1.1.3   root       16: #include "videoctlr.h"
1.1       root       17: 
1.1.1.10  root       18: // InsideOut p.135
                     19: static const busdata wait = busdata::Wait(9 * 40_nsec);
                     20: 
1.1.1.7   root       21: // コンストラクタ
1.1       root       22: TVRAMDevice::TVRAMDevice()
1.1.1.9   root       23:        : inherited(1024, 1024)
1.1       root       24: {
1.1.1.9   root       25:        SetName("TVRAM");
                     26:        ClearAlias();
                     27:        AddAlias("TVRAM");
                     28: 
                     29:        uint devlen = 512 * 1024;
1.1       root       30: 
1.1.1.7   root       31:        // プレーン数は4枚固定
                     32:        nplane = NPLANE;
1.1.1.4   root       33: 
1.1.1.7   root       34:        mem.reset(new uint8[devlen]);
1.1       root       35: }
                     36: 
1.1.1.7   root       37: // デストラクタ
1.1       root       38: TVRAMDevice::~TVRAMDevice()
                     39: {
                     40: }
                     41: 
1.1.1.9   root       42: // 初期化
1.1.1.7   root       43: bool
                     44: TVRAMDevice::Init()
                     45: {
1.1.1.12  root       46:        videoctlr = GetVideoCtlrDevice();
1.1.1.9   root       47: 
1.1.1.7   root       48:        // 加工済みパレットを取得
1.1.1.9   root       49:        palette = &(videoctlr->GetHostPalette())[0];
1.1.1.7   root       50: 
                     51:        return true;
                     52: }
                     53: 
1.1.1.10  root       54: inline uint32
1.1.1.2   root       55: TVRAMDevice::Decoder(uint32 addr) const
                     56: {
                     57:        return addr - baseaddr;
                     58: }
                     59: 
1.1.1.10  root       60: busdata
1.1.1.11  root       61: TVRAMDevice::Read(busaddr addr)
1.1       root       62: {
1.1.1.10  root       63:        busdata data;
1.1.1.11  root       64:        uint32 offset = Decoder(addr.Addr());
                     65:        data = *(uint32 *)&mem[offset & ~3U];
1.1.1.10  root       66:        data |= wait;
1.1.1.11  root       67:        data |= BusData::Size4;
1.1.1.10  root       68:        return data;
1.1       root       69: }
                     70: 
1.1.1.10  root       71: busdata
1.1.1.11  root       72: TVRAMDevice::Write(busaddr addr, uint32 data)
1.1       root       73: {
1.1.1.11  root       74:        uint32 offset = Decoder(addr.Addr());
                     75:        uint32 reqsize = addr.GetSize();
                     76:        uint32 datasize = std::min(2 - (offset & 1U), reqsize);
                     77:        data >>= (reqsize - datasize) * 8;
1.1       root       78: 
1.1.1.11  root       79:        uint32 mask;
1.1.1.7   root       80:        if (tvram.men) {
1.1.1.11  root       81:                if (datasize == 1) {
                     82:                        if ((offset & 1U) == 0) {
                     83:                                mask = tvram.mask >> 8;
                     84:                        } else {
                     85:                                mask = tvram.mask & 0xff;
                     86:                        }
1.1.1.7   root       87:                } else {
1.1.1.11  root       88:                        mask = tvram.mask;
1.1.1.7   root       89:                }
                     90:        } else {
1.1.1.11  root       91:                mask = 0;
1.1.1.7   root       92:        }
                     93: 
1.1.1.9   root       94:        uint32 poffset = offset & 0x1ffff;
1.1.1.11  root       95:        if (datasize == 1) {
                     96:                Set8(offset, poffset, data, mask);
1.1       root       97:        } else {
1.1.1.11  root       98:                Set16(offset, poffset, data, mask);
1.1       root       99:        }
1.1.1.9   root      100:        SetDirty(poffset);
1.1.1.11  root      101: 
                    102:        busdata r = wait;
                    103:        r |= busdata::Size(datasize);
                    104:        return r;
1.1       root      105: }
                    106: 
1.1.1.10  root      107: busdata
1.1.1.11  root      108: TVRAMDevice::Peek1(uint32 addr)
1.1       root      109: {
1.1.1.2   root      110:        uint32 offset = Decoder(addr);
1.1.1.11  root      111:        return mem[HLB(offset)];
                    112: }
1.1       root      113: 
1.1.1.11  root      114: bool
                    115: TVRAMDevice::Poke1(uint32 addr, uint32 data)
                    116: {
                    117:        if ((int32)data >= 0) {
                    118:                uint32 offset = Decoder(addr);
                    119:                uint32 poffset = offset & 0x1ffff;
                    120:                mem[HLB(offset)] = data;
                    121:                // この場合も画面を更新する
                    122:                SetDirty(poffset);
1.1.1.7   root      123:        }
1.1.1.11  root      124:        return true;
                    125: }
1.1.1.7   root      126: 
1.1.1.11  root      127: // マスクと同時アクセスを含むバイト書き込み。
                    128: void
                    129: TVRAMDevice::Set8(uint32 offset, uint32 poffset, uint32 data, uint32 mask)
                    130: {
1.1       root      131:        if (tvram.sa) {
                    132:                // 同時アクセス
                    133:                for (int plane = 0; plane < 4; plane++) {
                    134:                        if (tvram.ap[plane]) {
1.1.1.11  root      135:                                uint8 *p = &mem[HLB(0x20000 * plane + poffset)];
                    136:                                *p = (data & ~mask) | (*p & mask);
1.1       root      137:                        }
                    138:                }
                    139:        } else {
                    140:                // 通常アクセス
1.1.1.11  root      141:                uint8 *p = &mem[HLB(offset)];
                    142:                *p = (data & ~mask) | (*p & mask);
1.1       root      143:        }
                    144: }
                    145: 
1.1.1.11  root      146: // マスクと同時アクセスを含むワード書き込み。
                    147: void
                    148: TVRAMDevice::Set16(uint32 offset, uint32 poffset, uint32 data, uint32 mask)
1.1.1.9   root      149: {
1.1.1.11  root      150:        if (tvram.sa) {
                    151:                // 同時アクセス
                    152:                for (int plane = 0; plane < 4; plane++) {
                    153:                        if (tvram.ap[plane]) {
                    154:                                uint16 *p = (uint16 *)&mem[HLW(0x20000 * plane + poffset)];
                    155:                                *p = (data & ~mask) | (*p & mask);
                    156:                        }
                    157:                }
                    158:        } else {
                    159:                // 通常アクセス
                    160:                uint16 *p = (uint16 *)&mem[HLW(offset)];
                    161:                *p = (data & ~mask) | (*p & mask);
1.1.1.9   root      162:        }
                    163: }
                    164: 
1.1.1.7   root      165: // offset の位置に対応する更新フラグを立てる。
1.1.1.9   root      166: // offset はプレーン先頭からのバイトオフセット。
1.1.1.7   root      167: inline void
                    168: TVRAMDevice::SetDirty(uint32 offset)
                    169: {
1.1.1.9   root      170:        // VRAM は横 1024 ドット(128バイト) x 縦 1024 ドット。
1.1.1.7   root      171:        //
                    172:        //              1                               0
                    173:        //        3 2 1 0 f e d c b a 9 8 7 6 5 4 3 2 1 0
                    174:        //       +-----------+-------+-----+-------+-----+
                    175:        // VRAM  |  Y座標 (1024dot)  | X (128byte) : 8bit|
                    176:        //       +-----------+-------+-----+-------+-----+
1.1.1.9   root      177:        //       :                   :
                    178:        //       +-------------------+
                    179:        // Dirty |                   |
                    180:        //       +-------------------+
                    181:        //        9 8 7 6 5 4 3 2 1 0
                    182: 
                    183:        // 更新フラグはラスタ単位
1.1.1.11  root      184:        uint y = offset >> 7;
1.1.1.12  root      185:        dirty.line[y] = true;
1.1.1.9   root      186: }
                    187: 
                    188: // X 方向にはみ出したときに対応する仮想画面の Y 座標を返す。
                    189: int
                    190: TVRAMDevice::GetWrapY(int y) const
                    191: {
                    192:        // はみ出すと次のラスタの先頭から表示するが、
                    193:        // TVRAM は 4 ラスタがひとかたまりで構成されていて、
                    194:        // 末尾 2bit が 3 のラスタの次は、末尾だけ 0 のラスタに戻る。ようだ。
                    195:        return (y & ~3) + ((y + 1) & 3);
1.1       root      196: }
                    197: 
1.1.1.3   root      198: void
                    199: TVRAMDevice::SetScrollX(int x)
                    200: {
1.1.1.7   root      201:        xscroll = x;
1.1.1.3   root      202: }
                    203: 
                    204: void
                    205: TVRAMDevice::SetScrollY(int y)
                    206: {
1.1.1.7   root      207:        yscroll = y;
1.1.1.12  root      208:        Invalidate2();
1.1.1.3   root      209: }
                    210: 
1.1.1.7   root      211: // CRTC R21 での同時アクセス設定を反映する。
                    212: // CRTC から呼ばれる。
1.1       root      213: void
1.1.1.7   root      214: TVRAMDevice::SetAccessPlane(uint16 data)
1.1       root      215: {
1.1.1.7   root      216:        tvram.cp[0] = (data & 0x01);
                    217:        tvram.cp[1] = (data & 0x02);
                    218:        tvram.cp[2] = (data & 0x04);
                    219:        tvram.cp[3] = (data & 0x08);
1.1       root      220:        tvram.ap[0] = (data & 0x10);
                    221:        tvram.ap[1] = (data & 0x20);
                    222:        tvram.ap[2] = (data & 0x40);
                    223:        tvram.ap[3] = (data & 0x80);
1.1.1.7   root      224:        tvram.sa = (data & 0x100);
                    225:        tvram.men = (data & 0x200);
1.1       root      226: 
                    227:        if (0) {
                    228:                if (tvram.sa) {
                    229:                        putlog(2, "テキスト画面同時アクセス有効 %c%c%c%c",
                    230:                                tvram.ap[0] ? '0' : '-',
                    231:                                tvram.ap[1] ? '1' : '-',
                    232:                                tvram.ap[2] ? '2' : '-',
                    233:                                tvram.ap[3] ? '3' : '-');
                    234:                } else {
                    235:                        putlog(2, "テキスト画面同時アクセス無効");
                    236:                }
                    237:        }
                    238: }
                    239: 
1.1.1.7   root      240: // CRTC R23 でのアクセスマスク設定を反映する。
                    241: // CRTC から呼ばれる。
                    242: void
                    243: TVRAMDevice::SetAccessMask(uint16 data)
1.1       root      244: {
1.1.1.7   root      245:        tvram.mask = data;
                    246: }
1.1.1.4   root      247: 
1.1.1.7   root      248: // ラスターコピーを開始する。
                    249: // src_ras, dst_ras はライン番号 (レジスタ設定値を4倍したもの)。
                    250: void
1.1.1.11  root      251: TVRAMDevice::RasterCopy(uint src_ras, uint dst_ras)
1.1.1.7   root      252: {
                    253:        for (int plane = 0; plane < 4; plane++) {
                    254:                if (tvram.cp[plane]) {
1.1.1.8   root      255:                        uint8 *src = &mem[0x20000 * plane + src_ras * 128];
                    256:                        uint8 *dst = &mem[0x20000 * plane + dst_ras * 128];
1.1.1.7   root      257:                        memcpy(dst, src, 128 * 4);
1.1       root      258:                }
                    259:        }
                    260: 
1.1.1.8   root      261:        // dst からの4ラインを全部 dirty にする。
1.1.1.9   root      262:        for (int y = 0; y < 4; y++) {
                    263:                SetDirty((dst_ras + y) * 128);
1.1.1.8   root      264:        }
1.1.1.9   root      265: }
                    266: 
                    267: // (x, y) 位置のピクセル情報を screen に描画。(ビットマップモニタの情報欄)
                    268: void
                    269: TVRAMDevice::UpdateInfo(TextScreen& screen, int x, int y) const
                    270: {
                    271:        screen.Clear();
                    272: 
                    273:        //0         1         2         3         4         5         6
                    274:        //012345678901234567890123456789012345678901234567890123456789012345
                    275:        //X=1024 Y=2024: (P0) $e01234: $00 (%00000000) ColorCode=$d
                    276: 
                    277:        screen.Puts(0, 0, "X=     Y=");
                    278:        for (int i = 0; i < nplane; i++) {
1.1.1.11  root      279:                screen.Print(15, i, "(P%u)", i);
1.1.1.9   root      280:        }
                    281: 
                    282:        // カーソルが範囲外ならここまで。
                    283:        if (x < 0) {
                    284:                return;
                    285:        }
                    286: 
                    287:        screen.Print(2, 0, "%4d Y=%4d", x, y);
                    288: 
                    289:        // 1プレーン内のバイトオフセット
                    290:        uint32 planeoffset = ((uint)y * 128) + ((uint)x / 8);
                    291: 
                    292:        uint cc = 0;
                    293:        for (int i = 0; i < nplane; i++) {
                    294:                // プレーン0先頭からのバイトオフセット
                    295:                uint32 totaloffset = 0x20000 * i + planeoffset;
                    296: 
                    297:                uint8 data = mem[HLB(totaloffset)];
1.1.1.11  root      298:                screen.Print(15, i, "(P%u) $%06x: $%02x (%%",
1.1.1.9   root      299:                        i, baseaddr + totaloffset, data);
                    300: 
                    301:                // ビットパターン
                    302:                for (int m = 0x80; m != 0; m >>= 1) {
                    303:                        screen.Putc((data & m) ? '1' : '0');
                    304:                }
                    305:                screen.Putc(')');
                    306: 
                    307:                // カーソル位置をハイライト
                    308:                screen.Locate(35 + (x % 8), i);
                    309:                screen.SetAttr(TA::Em);
                    310: 
                    311:                // カラーコードを計算
                    312:                if ((data & (0x80U >> (x % 8))) != 0) {
                    313:                        cc |= (1U << i);
1.1.1.7   root      314:                }
                    315:        }
1.1.1.9   root      316: 
                    317:        screen.Print(45, 0, "ColorCode=$%x", cc);
1.1       root      318: }

unix.superglobalmegacorp.com

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