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

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

unix.superglobalmegacorp.com

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