Annotation of nono/vm/crtc.cpp, revision 1.1.1.4

1.1       root        1: //
                      2: // nono
1.1.1.4 ! root        3: // Copyright (C) 2020 nono project
        !             4: // Licensed under nono-license.txt
1.1       root        5: //
                      6: 
                      7: #include "crtc.h"
                      8: #include "mfp.h"
                      9: #include "renderer.h"
                     10: #include "tvram.h"
                     11: 
1.1.1.4 ! root       12: // e80000..e803ff 内は $40 バイトでミラー。
        !            13: // e80400..e807ff 内は 256 バイトでミラーになっており、このうち
        !            14: // +$00..+$7f はバスエラー、
        !            15: // +$80..+$ff は何かが読める。
        !            16: // 仕様は $e80480.w に1ポートあるので、これがワードで全域にミラーされている?
        !            17: // 全体としては この $800 バイトずつが繰り返して見える。
        !            18: 
        !            19: std::unique_ptr<CRTCDevice> gCRTC;
        !            20: 
1.1       root       21: CRTCDevice::CRTCDevice()
                     22: {
                     23:        logname = "crtc";
                     24:        devname = "CRTC";
                     25:        devaddr = 0xe80000;
                     26:        devlen  = 0x2000;
                     27: 
                     28:        vdisp_event.dev = this;
                     29:        vdisp_event.func = (DeviceCallback_t)&CRTCDevice::VDispCallback;
1.1.1.2   root       30:        vdisp_event.SetName("CRTC V-DISP");
1.1       root       31: }
                     32: 
                     33: CRTCDevice::~CRTCDevice()
                     34: {
                     35: }
                     36: 
                     37: void
                     38: CRTCDevice::ResetHard()
                     39: {
                     40:        // XXX 初期値適当
                     41:        crtc.r[20] = 0x0016;
                     42: 
                     43:        // XXX 適当
                     44:        // すぐに垂直帰線期間を開始する
                     45:        vdisp_event.time = 0;
                     46:        vdisp_event.code = 1;
1.1.1.3   root       47:        vdisp_event.Start();
1.1       root       48: }
                     49: 
                     50: uint64
1.1.1.4 ! root       51: CRTCDevice::Read(uint32 addr)
1.1       root       52: {
1.1.1.4 ! root       53:        uint64 data;
1.1       root       54: 
1.1.1.4 ! root       55:        if (addr < 0x400 / 2) {         // CRTC レジスタ
        !            56:                // 0x40 バイトでミラー
        !            57:                addr &= (0x40 / 2) - 1;
        !            58:                // R20, R21 のみ読み出し可能
        !            59:                switch (addr) {
        !            60:                 case 20:
        !            61:                        data = crtc.r[addr];
        !            62:                        putlog(2, "R%02d -> $%04x", addr, (uint32)data);
        !            63:                        break;
        !            64:                 case 21:
        !            65:                        // R21 へのアクセスは多いのでログレベルを上げておく
        !            66:                        data = crtc.r[addr];
        !            67:                        putlog(3, "R%02d -> $%04x", addr, (uint32)data);
        !            68:                        break;
        !            69:                 default:
        !            70:                        // それ以外は読み出し不可 ($00 が読める)
        !            71:                        data = 0;
        !            72:                        if (addr < countof(crtc.r)) {
        !            73:                                putlog(3, "R%02d -> $%04x", addr, (uint32)data);
        !            74:                        } else {
        !            75:                                putlog(3, "$%06x -> $%04x", gMPU->GetPaddr(), (uint32)data);
        !            76:                        }
        !            77:                        break;
1.1       root       78:                }
                     79: 
1.1.1.4 ! root       80:        } else {                                        // 動作ポート
        !            81:                if ((addr & (0x80 / 2)) == 0) { // +$00..+$7f
        !            82:                        data = (uint64)-1;
        !            83:                } else {                                                // +$80..+$ff
        !            84:                        data = crtc.op;
1.1       root       85:                }
                     86:        }
                     87: 
                     88:        return data;
                     89: }
                     90: 
                     91: uint64
1.1.1.4 ! root       92: CRTCDevice::Write(uint32 addr, uint32 data)
1.1       root       93: {
1.1.1.4 ! root       94:        if (addr < 0x400 / 2) {         // CRTC レジスタ
        !            95:                // 0x40 バイトでミラー
        !            96:                addr &= (0x40 / 2) - 1;
        !            97:                if (addr < countof(crtc.r)) {
        !            98:                        SetReg(addr, data);
1.1       root       99:                } else {
1.1.1.4 ! root      100:                        // ここ何がいるんだ?
        !           101:                        putlog(2, "$%06x <- $%04x", gMPU->GetPaddr(), data);
1.1       root      102:                }
                    103: 
1.1.1.4 ! root      104:        } else {                                        // 動作ポート
        !           105:                if ((addr & (0x80 / 2)) == 0) { // +$00..+$7f
        !           106:                        return (uint64)-1;
        !           107:                } else {
1.1       root      108:                        crtc.op = data & 0x0b;
1.1.1.4 ! root      109:                        putlog(2, "$E80480.W <- $%04x", crtc.op);
1.1       root      110:                }
                    111:        }
1.1.1.4 ! root      112: 
1.1       root      113:        return 0;
                    114: }
                    115: 
                    116: uint64
1.1.1.4 ! root      117: CRTCDevice::Peek(uint32 addr)
1.1       root      118: {
1.1.1.4 ! root      119:        uint64 data;
1.1       root      120: 
1.1.1.4 ! root      121:        if (addr < 0x400 / 2) {         // CRTC レジスタ
        !           122:                // 0x40 バイトでミラー
        !           123:                addr &= (0x40 / 2) - 1;
        !           124:                if (addr == 20 || addr == 21) {
        !           125:                        // R20, R21 のみ読み出し可能
        !           126:                        data = crtc.r[addr];
        !           127:                } else {
        !           128:                        data = 0;
        !           129:                }
1.1       root      130: 
1.1.1.4 ! root      131:        } else {                                        // 動作ポート
        !           132:                if ((addr & (0x80 / 2)) == 0) {
        !           133:                        data = (uint64)-1;
        !           134:                } else {
        !           135:                        data = crtc.op;
        !           136:                }
1.1       root      137:        }
1.1.1.4 ! root      138: 
        !           139:        return data;
1.1       root      140: }
                    141: 
1.1.1.4 ! root      142: // CRTC レジスタへの書き込み。
        !           143: // reg は CRTC::R00 .. CRTC::R23
1.1       root      144: void
1.1.1.4 ! root      145: CRTCDevice::SetReg(uint32 reg, uint32 data)
1.1       root      146: {
                    147:        crtc.r[reg] = data;
                    148: 
                    149:        switch (reg) {
1.1.1.4 ! root      150:         case CRTC::R10:
        !           151:                putlog(2, "R%02d <- $%04x", reg, data);
        !           152:                gTVRAM->SetScrollX(crtc.r[10]);
        !           153:                break;
        !           154:         case CRTC::R11:
        !           155:                putlog(2, "R%02d <- $%04x", reg, data);
        !           156:                gTVRAM->SetScrollY(crtc.r[11]);
        !           157:                break;
1.1       root      158:         case CRTC::R21:
1.1.1.4 ! root      159:                // 頻度が高いのでログレベルを上げておく
        !           160:                putlog(3, "R%02d <- $%04x", reg, data);
1.1       root      161:                gTVRAM->set_crtc_21(crtc.r[21]);
                    162:                break;
                    163:         default:
1.1.1.4 ! root      164:                putlog(2, "R%02d <- $%04x (未実装)", reg, data);
        !           165:                break;
1.1       root      166:        }
                    167: }
                    168: 
                    169: // 垂直表示・帰線イベント
                    170: // arg == 1 なら表示期間開始、arg == 0 なら帰線期間開始。
                    171: void
                    172: CRTCDevice::VDispCallback(int arg)
                    173: {
                    174:        // GPIP の状態を更新
                    175:        gMFP->SetVDisp(arg);
                    176: 
                    177:        // 今はここで1画面まるごと作成
                    178:        if (arg) {
                    179:                // Render に作画指示
                    180:                gRenderer->Render();
                    181:        }
                    182: 
                    183:        // 次のタイミングを計算
                    184:        // XXX まだ CRTC から計算していない
                    185:        if (arg) {
                    186:                // 垂直表示期間
                    187:                vdisp_event.time = 16250_usec;
                    188:        } else {
                    189:                // 垂直帰線期間
                    190:                vdisp_event.time = 1778_usec;
                    191:        }
                    192:        vdisp_event.code = 1 - arg;
1.1.1.3   root      193:        vdisp_event.Start();
1.1       root      194: }

unix.superglobalmegacorp.com

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