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

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.5 ! root       55:        gMPU->AddCycle(9);      // InsideOut p.135
        !            56: 
1.1.1.4   root       57:        if (addr < 0x400 / 2) {         // CRTC レジスタ
                     58:                // 0x40 バイトでミラー
                     59:                addr &= (0x40 / 2) - 1;
                     60:                // R20, R21 のみ読み出し可能
                     61:                switch (addr) {
                     62:                 case 20:
                     63:                        data = crtc.r[addr];
                     64:                        putlog(2, "R%02d -> $%04x", addr, (uint32)data);
                     65:                        break;
                     66:                 case 21:
                     67:                        // R21 へのアクセスは多いのでログレベルを上げておく
                     68:                        data = crtc.r[addr];
                     69:                        putlog(3, "R%02d -> $%04x", addr, (uint32)data);
                     70:                        break;
                     71:                 default:
                     72:                        // それ以外は読み出し不可 ($00 が読める)
                     73:                        data = 0;
                     74:                        if (addr < countof(crtc.r)) {
                     75:                                putlog(3, "R%02d -> $%04x", addr, (uint32)data);
                     76:                        } else {
                     77:                                putlog(3, "$%06x -> $%04x", gMPU->GetPaddr(), (uint32)data);
                     78:                        }
                     79:                        break;
1.1       root       80:                }
                     81: 
1.1.1.4   root       82:        } else {                                        // 動作ポート
                     83:                if ((addr & (0x80 / 2)) == 0) { // +$00..+$7f
                     84:                        data = (uint64)-1;
                     85:                } else {                                                // +$80..+$ff
                     86:                        data = crtc.op;
1.1       root       87:                }
                     88:        }
                     89: 
                     90:        return data;
                     91: }
                     92: 
                     93: uint64
1.1.1.4   root       94: CRTCDevice::Write(uint32 addr, uint32 data)
1.1       root       95: {
1.1.1.5 ! root       96:        gMPU->AddCycle(9);      // InsideOut p.135
        !            97: 
1.1.1.4   root       98:        if (addr < 0x400 / 2) {         // CRTC レジスタ
                     99:                // 0x40 バイトでミラー
                    100:                addr &= (0x40 / 2) - 1;
                    101:                if (addr < countof(crtc.r)) {
                    102:                        SetReg(addr, data);
1.1       root      103:                } else {
1.1.1.4   root      104:                        // ここ何がいるんだ?
                    105:                        putlog(2, "$%06x <- $%04x", gMPU->GetPaddr(), data);
1.1       root      106:                }
                    107: 
1.1.1.4   root      108:        } else {                                        // 動作ポート
                    109:                if ((addr & (0x80 / 2)) == 0) { // +$00..+$7f
                    110:                        return (uint64)-1;
                    111:                } else {
1.1       root      112:                        crtc.op = data & 0x0b;
1.1.1.4   root      113:                        putlog(2, "$E80480.W <- $%04x", crtc.op);
1.1       root      114:                }
                    115:        }
1.1.1.4   root      116: 
1.1       root      117:        return 0;
                    118: }
                    119: 
                    120: uint64
1.1.1.4   root      121: CRTCDevice::Peek(uint32 addr)
1.1       root      122: {
1.1.1.4   root      123:        uint64 data;
1.1       root      124: 
1.1.1.4   root      125:        if (addr < 0x400 / 2) {         // CRTC レジスタ
                    126:                // 0x40 バイトでミラー
                    127:                addr &= (0x40 / 2) - 1;
                    128:                if (addr == 20 || addr == 21) {
                    129:                        // R20, R21 のみ読み出し可能
                    130:                        data = crtc.r[addr];
                    131:                } else {
                    132:                        data = 0;
                    133:                }
1.1       root      134: 
1.1.1.4   root      135:        } else {                                        // 動作ポート
                    136:                if ((addr & (0x80 / 2)) == 0) {
                    137:                        data = (uint64)-1;
                    138:                } else {
                    139:                        data = crtc.op;
                    140:                }
1.1       root      141:        }
1.1.1.4   root      142: 
                    143:        return data;
1.1       root      144: }
                    145: 
1.1.1.4   root      146: // CRTC レジスタへの書き込み。
                    147: // reg は CRTC::R00 .. CRTC::R23
1.1       root      148: void
1.1.1.4   root      149: CRTCDevice::SetReg(uint32 reg, uint32 data)
1.1       root      150: {
                    151:        crtc.r[reg] = data;
                    152: 
                    153:        switch (reg) {
1.1.1.4   root      154:         case CRTC::R10:
                    155:                putlog(2, "R%02d <- $%04x", reg, data);
                    156:                gTVRAM->SetScrollX(crtc.r[10]);
                    157:                break;
                    158:         case CRTC::R11:
                    159:                putlog(2, "R%02d <- $%04x", reg, data);
                    160:                gTVRAM->SetScrollY(crtc.r[11]);
                    161:                break;
1.1       root      162:         case CRTC::R21:
1.1.1.4   root      163:                // 頻度が高いのでログレベルを上げておく
                    164:                putlog(3, "R%02d <- $%04x", reg, data);
1.1       root      165:                gTVRAM->set_crtc_21(crtc.r[21]);
                    166:                break;
                    167:         default:
1.1.1.4   root      168:                putlog(2, "R%02d <- $%04x (未実装)", reg, data);
                    169:                break;
1.1       root      170:        }
                    171: }
                    172: 
                    173: // 垂直表示・帰線イベント
1.1.1.5 ! root      174: // ev.code が 1 なら表示期間開始(V-disp)、0 なら帰線期間開始(V-blank)。
1.1       root      175: void
1.1.1.5 ! root      176: CRTCDevice::VDispCallback(Event& ev)
1.1       root      177: {
1.1.1.5 ! root      178:        int& vdisp = ev.code;
        !           179: 
1.1       root      180:        // GPIP の状態を更新
1.1.1.5 ! root      181:        gMFP->SetVDisp(vdisp);
1.1       root      182: 
                    183:        // 今はここで1画面まるごと作成
1.1.1.5 ! root      184:        if (vdisp) {
1.1       root      185:                // Render に作画指示
                    186:                gRenderer->Render();
                    187:        }
                    188: 
                    189:        // 次のタイミングを計算
                    190:        // XXX まだ CRTC から計算していない
1.1.1.5 ! root      191:        if (vdisp) {
1.1       root      192:                // 垂直表示期間
1.1.1.5 ! root      193:                ev.time = 16250_usec;
        !           194:                ev.code = 0;
1.1       root      195:        } else {
                    196:                // 垂直帰線期間
1.1.1.5 ! root      197:                ev.time = 1778_usec;
        !           198:                ev.code = 1;
1.1       root      199:        }
1.1.1.5 ! root      200:        ev.Start();
1.1       root      201: }

unix.superglobalmegacorp.com

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