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

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

unix.superglobalmegacorp.com

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